Re: [FFmpeg-devel] [PATCH 24/35] fftools/ffmpeg: use the sync queues to handle -frames
Anton Khirnov: > Quoting Andreas Rheinhardt (2022-06-16 22:33:46) >> Anton Khirnov: >>> Same issues apply to it as to -shortest. >>> >>> Changes the results of the following tests: >>> - matroska-flac-extradata-update >>> The test reencodes two input FLAC streams into three output FLAC >>> streams. The last output stream is limited to 8 frames. The current >>> code results in the first two output streams having 12 frames, after >>> this commit all three streams have 8 frames and are the same length. >>> This new result is better, since it is predictable. >> >> The point of the test was that only one stream is limited so that one >> can see the extradata update directly in the test result: The unlimited >> streams have a different extradata than the limited stream (because said >> extradata contains an md5 of the decoded data). So it is expected that >> the extradata hashes of the first two streams coincide and differ from >> the hash of the last stream. > > Right, but my point is that the amount of data that ends up in those > unlimited streams is largely an accident of how the code happens to > work currently and is not guaranteed by anything. > The documentation of frames reads: "-frames[:stream_specifier] framecount (output,per-stream) Stop writing to the stream after framecount frames." It does not say that the other streams end after one stream has reached its framecount. So it is guaranteed by the documentation that the other streams don't end prematurely. (Why do you think that this is an accident?) > Are you suggesting any specific changes to the test or the patch? E.g. > the atrim filter could be used to replicate previous behaviour if you'd > like to keep it. > >> (The current test results btw show an imperfection: The extradata of the >> last stream is not updated, as the encoder is not flushed (or the flush >> packet does not arrive at the muxer). Fixing this (as seems to be the >> case) is good.) > > Correct - frame-limiting is now done before sending frames to the > encoder, so all packets, including the one from flushing the encoder, > get to the muxer. > ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 1/2] checkasm: updated tests for sw_scale
On Tue, 21 Jun 2022, Martin Storsjö wrote: On Mon, 13 Jun 2022, Swinney, Jonathan wrote: - added a test for yuv2plane1 (currently disabled for x86_64) What's the reason for having it disabled for x86 - is it another case where the current implementations there aren't bitexact? Could we avoid that by setting the bitexact flag for the new yuv2yuv1 test? - fixed test for yuv2planeX for aarch64 which was previously not working at all Could we make the test fuzzy and allow minor differences from the reference, when the bitexact flag isn't set, and separately test with the bitexact flag and require exact matches? @@ -95,7 +210,7 @@ static void check_yuv2yuvX(void) ff_sws_init_scale(ctx); for(isi = 0; isi < INPUT_SIZES; ++isi){ dstW = input_sizes[isi]; -for(osi = 0; osi < 64; osi += 16){ +for(osi = 0; osi < 1; osi += 16){ This looks like a stray leftover change? I had a look at this, trying to fix things up. This now passes tests on x86_32, x86_64 and aarch64. See the attached patch, which goes on top of yours. It's not intended as a final version of how things should be necessarily, but as a more concrete pointer about how it could be done - it needs at least reindenting after adding the outer for loop. I also had to skip the filter sizes 1 and 3 in check_yuv2yuvX, because ff_yuv2planeX_8_sse2 couldn't handle those. I presume that means that in practice, those aren't ever used? // Martin From e6d33cc199a879060e8e954e6eaea8aebe96b433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 22 Jun 2022 12:16:15 +0300 Subject: [PATCH] checkasm: sw_scale: Fixups Changes: - Omit x86 yuv2plane1 if SWS_ACCURATE_RND is set - Remove yuv2plane1_8_ref from the testcase; this function can be tested with the usual call_ref pattern - Add testing with and without SWS_ACCURATE_RND in both check_yuv2yuvX and check_yuv2yuv1 - Remove the x86 specific reference function in checkasm; use the generic reference function which matches swscale's C code, and compare with a tolerance of 2 unless SWS_ACCURATE_RND is set - Reinstate testing of offsets in check_yuv2yuvX - Make all tests arch independent - Clarify why we can't use call_ref in check_yuv2yuvX The code isn't properly indented (I added an outer for loop, without reindenting the loop body, for patch clarity). --- libswscale/x86/swscale.c | 11 ++-- tests/checkasm/sw_scale.c | 113 +++--- 2 files changed, 50 insertions(+), 74 deletions(-) diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c index 73869355b8..1c57b3a700 100644 --- a/libswscale/x86/swscale.c +++ b/libswscale/x86/swscale.c @@ -550,7 +550,8 @@ switch(c->dstBpc){ \ if (EXTERNAL_MMX(cpu_flags)) { ASSIGN_MMX_SCALE_FUNC(c->hyScale, c->hLumFilterSize, mmx, mmx); ASSIGN_MMX_SCALE_FUNC(c->hcScale, c->hChrFilterSize, mmx, mmx); -ASSIGN_VSCALE_FUNC(c->yuv2plane1, mmx, mmxext, cpu_flags & AV_CPU_FLAG_MMXEXT); +if (!(c->flags & SWS_ACCURATE_RND)) +ASSIGN_VSCALE_FUNC(c->yuv2plane1, mmx, mmxext, cpu_flags & AV_CPU_FLAG_MMXEXT); switch (c->srcFormat) { case AV_PIX_FMT_YA8: @@ -599,7 +600,8 @@ switch(c->dstBpc){ \ ASSIGN_SSE_SCALE_FUNC(c->hcScale, c->hChrFilterSize, sse2, sse2); ASSIGN_VSCALEX_FUNC(c->yuv2planeX, sse2, , HAVE_ALIGNED_STACK || ARCH_X86_64); -ASSIGN_VSCALE_FUNC(c->yuv2plane1, sse2, sse2, 1); +if (!(c->flags & SWS_ACCURATE_RND)) +ASSIGN_VSCALE_FUNC(c->yuv2plane1, sse2, sse2, 1); switch (c->srcFormat) { case AV_PIX_FMT_YA8: @@ -648,14 +650,15 @@ switch(c->dstBpc){ \ ASSIGN_VSCALEX_FUNC(c->yuv2planeX, sse4, if (!isBE(c->dstFormat)) c->yuv2planeX = ff_yuv2planeX_16_sse4, HAVE_ALIGNED_STACK || ARCH_X86_64); -if (c->dstBpc == 16 && !isBE(c->dstFormat)) +if (c->dstBpc == 16 && !isBE(c->dstFormat) && !(c->flags & SWS_ACCURATE_RND)) c->yuv2plane1 = ff_yuv2plane1_16_sse4; } if (EXTERNAL_AVX(cpu_flags)) { ASSIGN_VSCALEX_FUNC(c->yuv2planeX, avx, , HAVE_ALIGNED_STACK || ARCH_X86_64); -ASSIGN_VSCALE_FUNC(c->yuv2plane1, avx, avx, 1); +if (!(c->flags & SWS_ACCURATE_RND)) +ASSIGN_VSCALE_FUNC(c->yuv2plane1, avx, avx, 1); switch (c->srcFormat) { case AV_PIX_FMT_YUYV422: diff --git a/tests/checkasm/sw_scale.c b/tests/checkasm/sw_scale.c index edce3cbe4e..0c19974034 100644 --- a/tests/checkasm/sw_scale.c +++ b/tests/checkasm/sw_scale.c @@ -39,45 +39,25 @@ static void yuv2planeX_8_ref(const int16_t *filter, int filterSize, const int16_t **src, uint8_t *dest, int dstW, const uint8_t *dither, int offset) { -#if ARCH_X86_64 -// This reference function is the same approximate algorithm
[FFmpeg-devel] [PATCH] avcodec/h2645_parse: Only trim RBSP trailing padding if it exists
It does not exist for NALUs for which the SODB is empty; it also does not exist for NALUs for which not even the complete header is present. The former category contains end of sequence and end of bitstream units. The latter category consists of one-byte HEVC units (the ordinary H.264 header is only one byte long). This commit therefore stops stripping RBSP trailing padding from the former type of unit and discards the latter type of unit altogether. This also fixes an assertion failure: Before this commit, a one-byte HEVC NALU from an ISOBMFF packet could pass all the checks in hevc_parse_nal_header() (because the first byte of the size field of the next unit is mistaken as containing the temporal_id); yet because the trailing padding bits were stripped, its actually had a size of less than eight bits; because h2645_parse.c uses the checked bitstream reader, the get_bits_count() of the GetBitContext is not 16 in this case; it is not even a multiple of eight and this can trigger an assert in ff_hevc_decode_nal_sei(). Fixes: Assertion failure Fixes: 46662/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_HEVC_fuzzer-4947860854013952 Signed-off-by: Andreas Rheinhardt --- libavcodec/h2645_parse.c | 26 -- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c index 03780680c6..dca91b24f3 100644 --- a/libavcodec/h2645_parse.c +++ b/libavcodec/h2645_parse.c @@ -259,10 +259,10 @@ static const char *h264_nal_unit_name(int nal_type) return h264_nal_type_name[nal_type]; } -static int get_bit_length(H2645NAL *nal, int skip_trailing_zeros) +static int get_bit_length(H2645NAL *nal, int min_size, int skip_trailing_zeros) { int size = nal->size; -int v; +int trailing_padding = 0; while (skip_trailing_zeros && size > 0 && nal->data[size - 1] == 0) size--; @@ -270,18 +270,23 @@ static int get_bit_length(H2645NAL *nal, int skip_trailing_zeros) if (!size) return 0; -v = nal->data[size - 1]; +if (size <= min_size) { +if (nal->size < min_size) +return AVERROR_INVALIDDATA; +size = min_size; +} else { +int v = nal->data[size - 1]; +/* remove the stop bit and following trailing zeros, +* or nothing for damaged bitstreams */ +if (v) +trailing_padding = ff_ctz(v) + 1; +} if (size > INT_MAX / 8) return AVERROR(ERANGE); size *= 8; -/* remove the stop bit and following trailing zeros, - * or nothing for damaged bitstreams */ -if (v) -size -= ff_ctz(v) + 1; - -return size; +return size - trailing_padding; } /** @@ -491,7 +496,8 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, bytestream2_peek_be32(&bc) == 0x01E0) skip_trailing_zeros = 0; -nal->size_bits = get_bit_length(nal, skip_trailing_zeros); +nal->size_bits = get_bit_length(nal, 1 + (codec_id == AV_CODEC_ID_HEVC), +skip_trailing_zeros); if (nal->size <= 0 || nal->size_bits <= 0) continue; -- 2.34.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 2/2] avcodec/h2645_parse: Check HEVC NAL size
Andreas Rheinhardt: > Michael Niedermayer: >> Fixes: Assertion failure >> Fixes: >> 46662/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_HEVC_fuzzer-4947860854013952 >> >> This also results in more frames to be decoded from fate samples >> >> Found-by: continuous fuzzing process >> https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg >> Signed-off-by: Michael Niedermayer >> --- >> libavcodec/h2645_parse.c | 2 +- >> .../ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 | 10 ++ >> tests/ref/fate/hevc-conformance-RAP_B_Bossen_1 | 3 +++ >> 3 files changed, 14 insertions(+), 1 deletion(-) >> >> diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c >> index 03780680c6..78ab22b76e 100644 >> --- a/libavcodec/h2645_parse.c >> +++ b/libavcodec/h2645_parse.c >> @@ -292,7 +292,7 @@ static int hevc_parse_nal_header(H2645NAL *nal, void >> *logctx) >> { >> GetBitContext *gb = &nal->gb; >> >> -if (get_bits1(gb) != 0) >> +if (get_bits_left(gb) < 16 || get_bits1(gb) != 0) >> return AVERROR_INVALIDDATA; >> >> nal->type = get_bits(gb, 6); >> diff --git a/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 >> b/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 >> index 0c930f6556..3283925e38 100644 >> --- a/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 >> +++ b/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 >> @@ -25,6 +25,16 @@ >> 0, 19, 19,1, 599040, 0x4227009b >> 0, 20, 20,1, 599040, 0x1bda8be4 >> 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, 29, 29,1, 599040, 0x812ce986 >> +0, 30, 30,1, 599040, 0xf07c212c >> +0, 31, 31,1, 599040, 0xb5476890 >> 0, 32, 32,1, 599040, 0x00a0249f >> 0, 33, 33,1, 599040, 0x7263f7cf >> 0, 34, 34,1, 599040, 0x47054be4 >> diff --git a/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1 >> b/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1 >> index e661ff245e..776267b59c 100644 >> --- a/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1 >> +++ b/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1 >> @@ -70,6 +70,9 @@ >> 0, 64, 64,1, 149760, 0x3362678b >> 0, 65, 65,1, 149760, 0x6e7fc851 >> 0, 66, 66,1, 149760, 0x33f96449 >> +0, 67, 67,1, 149760, 0xd9d05007 >> +0, 75, 75,1, 149760, 0x477f2cf2 >> +0, 76, 76,1, 149760, 0xe1f9ccd0 >> 0, 77, 77,1, 149760, 0xb3ba8cfb >> 0, 78, 78,1, 149760, 0x64787995 >> 0, 79, 79,1, 149760, 0xc10de4c4 > > get_bit_length currently presumes every NALU to contain > rbsp_trailing_bits. Yet this is not true for the End of > Sequence/Bitstream units which are just headers without RBSP. For these > units, get_bit_length might truncate them -- it does so for end of > sequence units in H.264. It would not be a serious issue for H.265, as > the semantics of nuh_temporal_id_plus1 require nuh_temporal_id_plus1 to > be 1 for End of Sequence/Bitstream units. Nevertheless I think this > should be coupled with a patch that does not truncate the NAL unit if it > is just a header. > 1. I just sent a patch implementing the above: https://ffmpeg.org/pipermail/ffmpeg-devel/2022-June/297923.html Please confirm that it actually fixes the testcase its commit message claims to fix. 2. The RAP_B_Bossen_1 and NoOutPrior_A_Qualcomm_1 (where the testcases change due to your patch) contain completely fine end of sequence NALUs. Because they are valid, stripping them (as your patch does) is not ok (e.g. these units would even be discarded when using hevc_metadata). There are two bugs with these units: a) Our parser puts them at the beginning of their NALUs, yet they should be at the end of the (preceding) NALU. b) When remuxing the samples to Matroska with mkvmerge (which puts these units at the end of their packets), the output is the same as with raw input, i.e. decoder still misses some frames. So somehow these units confuse the decoder. - Andreas ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "
[FFmpeg-devel] [PATCH] avcodec/hevc_sei: Fix check for SEI end
The intention behind the current check seems to be to check for the rbsp_trailing_bits() syntax structure which is always 0x80 for valid SEI messages. Yet this is wrong: These trailing bits are not part of the GetBitContext -- they have already been stripped in ff_h2645_packet_split(). And it is harmful, as 0x80 is a legal SEI message payload type (namely for Structure of pictures information SEI messages). We ignore this type of SEI, but because of this bug we also ignored every SEI message in the same NALU following it. Signed-off-by: Andreas Rheinhardt --- libavcodec/hevc_sei.c | 8 +--- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index a5c7df34b0..953633f4bd 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -549,12 +549,6 @@ static int decode_nal_sei_message(GetByteContext *gb, void *logctx, HEVCSEI *s, } } -static int more_rbsp_data(GetByteContext *gb) -{ -return bytestream2_get_bytes_left(gb) > 0 && - bytestream2_peek_byteu(gb) != 0x80; -} - int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s, const HEVCParamSets *ps, int type) { @@ -569,7 +563,7 @@ int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s, ret = decode_nal_sei_message(&gbyte, logctx, s, ps, type); if (ret < 0) return ret; -} while (more_rbsp_data(&gbyte)); +} while (bytestream2_get_bytes_left(&gbyte) > 0); return 1; } -- 2.34.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] ffmpeg: add option -isync
This is a per-file input option that adjusts an input's timestamps with reference to another input, so that emitted packet timestamps account for the difference between the start times of the two inputs. Typical use case is to sync two or more live inputs such as capture devices. Both the target and reference input source timestamps should be based on the same clock source. If not all inputs have timestamps, the wallclock times at the time of reception of inputs shall be used. --- In its current form, the patch depends on first_pts_wallclock being available but that's not integral, just a fallback for crude sync. If f_p_w is not available, then an error log will be inserted in that code path. The f_p_w patch is at https://ffmpeg.org/pipermail/ffmpeg-devel/.html2022-June/297609 The patch has been used to successfully stream a synced audio mix of a karaoke performance and the original audio. It can similarly be used to sync webcam+mic feeds in different inputs or various media feeds received on a LAN. doc/ffmpeg.texi | 16 ++ fftools/ffmpeg.h | 2 ++ fftools/ffmpeg_opt.c | 52 3 files changed, 70 insertions(+) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index d943f4d6f5..92dd584c89 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -518,6 +518,22 @@ see @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) Like the @code{-ss} option but relative to the "end of file". That is negative values are earlier in the file, 0 is at EOF. +@item -isync @var{input_index} (@emph{input}) +Assign an input as a sync source. + +This will take the difference between the start times of the target and referenced inputs and +offset the timestamps of the target file by that difference. The source timestamps of the two +inputs should derive from the same clock source for expected results. If @code{copyts} is set +then @code{start_at_zero} must also be set. If at least one of the inputs has no starting +timestamp then the wallclock time at time of reception of the inputs is used as a best-effort +sync basis. + +Acceptable values are those that refer to a valid ffmpeg input index. If the sync reference is +the target index itself or @var{-1}, then no adjustment is made to target timestamps. A sync +reference may not itself be synced to any other input. + +Default value is var{-1}. + @item -itsoffset @var{offset} (@emph{input}) Set the input time offset. diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 69a368b8d1..dc74de6684 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -118,6 +118,7 @@ typedef struct OptionsContext { float readrate; int accurate_seek; int thread_queue_size; +int input_sync_ref; SpecifierOpt *ts_scale; intnb_ts_scale; @@ -410,6 +411,7 @@ typedef struct InputFile { at the moment when looping happens */ AVRational time_base; /* time base of the duration */ int64_t input_ts_offset; +int input_sync_ref; int64_t ts_offset; int64_t last_ts; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index e08455478f..eda0717380 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -235,6 +235,7 @@ static void init_options(OptionsContext *o) o->chapters_input_file = INT_MAX; o->accurate_seek = 1; o->thread_queue_size = -1; +o->input_sync_ref = -1; } static int show_hwaccels(void *optctx, const char *opt, const char *arg) @@ -287,6 +288,51 @@ static int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, in return 0; } +static int apply_sync_offsets(void) +{ +for (int i = 0; i < nb_input_files; i++) { +InputFile *ref, *self = input_files[i]; +int64_t adjustment; +int64_t self_start_time, ref_start_time, self_seek_start, ref_seek_start; + +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); +} + +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); +} + +ref = input_files[self->input_sync_ref]; +if (ref->input_sync_ref != -1 && ref->input_sync_ref != self->input_sync_ref) { +av_log(NULL, AV_LOG_ERROR, "-isync for input %d references a resynced input %d. Sync not set.\n", i, self->input_sync_ref); +continue; +} + +if (self->ctx->start_time == AV_NOPTS_VALUE || ref->ctx->start_time == AV_NOPTS_VALUE) { +self_start_time = self->ctx->first_pts_wallclock; +ref_start_time = ref->ctx->first_pts_wallclock; +} else { +
Re: [FFmpeg-devel] [PATCH v8 0/2] libjxl Colorspace Fixes
On 6/15/22 10:31, Leo Izen wrote: On 6/9/22 07:31, Leo Izen wrote: On 6/1/22 22:14, Leo Izen wrote: Changes in v8: - Use avutil/csp for both encoding and decoding - Handle the non-XYB case with an attached ICC Profile on decoding - clean up some code and segment it out to static functions Leo Izen (2): avcodec/libjxldec: properly tag output colorspace avcodec/libjxlenc: properly read input colorspace libavcodec/libjxldec.c | 142 +++--- libavcodec/libjxlenc.c | 153 + 2 files changed, 256 insertions(+), 39 deletions(-) I believe this should make it into 5.1 as it fixes a known bug and improves existing behavior. - Leo Izen (thebombzen) Bumping again for review. - Leo Izen (thebombzen) Could someone please review this? Thanks. - Leo Izen (thebombzen) ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 24/35] fftools/ffmpeg: use the sync queues to handle -frames
Quoting Andreas Rheinhardt (2022-06-22 10:27:30) > Anton Khirnov: > > Quoting Andreas Rheinhardt (2022-06-16 22:33:46) > >> Anton Khirnov: > >>> Same issues apply to it as to -shortest. > >>> > >>> Changes the results of the following tests: > >>> - matroska-flac-extradata-update > >>> The test reencodes two input FLAC streams into three output FLAC > >>> streams. The last output stream is limited to 8 frames. The current > >>> code results in the first two output streams having 12 frames, after > >>> this commit all three streams have 8 frames and are the same length. > >>> This new result is better, since it is predictable. > >> > >> The point of the test was that only one stream is limited so that one > >> can see the extradata update directly in the test result: The unlimited > >> streams have a different extradata than the limited stream (because said > >> extradata contains an md5 of the decoded data). So it is expected that > >> the extradata hashes of the first two streams coincide and differ from > >> the hash of the last stream. > > > > Right, but my point is that the amount of data that ends up in those > > unlimited streams is largely an accident of how the code happens to > > work currently and is not guaranteed by anything. > > > > The documentation of frames reads: > "-frames[:stream_specifier] framecount (output,per-stream) > Stop writing to the stream after framecount frames." > It does not say that the other streams end after one stream has reached > its framecount. So it is guaranteed by the documentation that the other > streams don't end prematurely. > (Why do you think that this is an accident?) 1) Documentation not saying what happens to the other streams does not imply any guarantees IMO, it implies a lack of any guarantees. 2) Documentation for ffmpeg has always been less than fully descriptive (to put it extremely mildly), so I would not rely on it as the ultimate source of truth. 3) The original commit adding this option in 2004 would terminate ALL output to the file on reaching the specified frame limit, not just the affected stream. This was broken by me in 2f51ec2b9438e211f5b8abb2fcf5d8be678e7e8c, because need_output() terminates early and does not check max_frames for further streams if an earlier stream still allows output. I would consider this a bug, because it makes no sense to treat the option differently based on stream ordering. Presumably nobody noticed because nobody relies on this option producing consistent output with multiple streams. This is also the reason the test outputs all frames for the first two streams. If you changed "-frames:a:2 8" to "-frames:a:0 8", you would get: Output stream #0:0 (audio): 8 frames encoded (36864 samples); 8 packets muxed (208 bytes); Output stream #0:1 (audio): 7 frames encoded (32256 samples); 8 packets muxed (182 bytes); Output stream #0:2 (audio): 8 frames encoded (36864 samples); 9 packets muxed (208 bytes); -- Anton Khirnov ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v3] libavcodec/qsvenc: Enable fixed QP configure in qsv CQP runtime
From: Yue Heng Enable dynamic QP configuration in runtime on qsv encoder. Through AVFrame->metadata, we can set key "qsv_config_qp" to change QP configuration when we encode video in CQP mode. Signed-off-by: Yue Heng Signed-off-by: Wenbin Chen --- doc/encoders.texi | 10 + libavcodec/qsvenc.c | 89 + 2 files changed, 99 insertions(+) diff --git a/doc/encoders.texi b/doc/encoders.texi index 1850c99fe9..02a91ffe96 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -,6 +,16 @@ Forcing I frames as IDR frames. For encoders set this flag to ON to reduce power consumption and GPU usage. @end table +@subsection Runtime Options +Following options can be used durning qsv encoding. + +@table @option +@item @var{qsv_config_qp} +Supported in h264_qsv and hevc_qsv. +This option can be set in per-frame metadata. QP parameter can be dynamically +changed when encoding in CQP mode. +@end table + @subsection H264 options These options are used by h264_qsv diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 902bada55b..2382c2f5f7 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -146,6 +146,14 @@ static const struct { { MFX_RATECONTROL_QVBR,"QVBR" }, }; +#define UPDATE_PARAM(a, b) \ +do {\ +if ((a) != (b)) { \ +a = b; \ +updated = 1;\ +} \ +} while (0) \ + static const char *print_ratecontrol(mfxU16 rc_mode) { int i; @@ -1613,6 +1621,83 @@ static int set_roi_encode_ctrl(AVCodecContext *avctx, const AVFrame *frame, return 0; } +static int update_qp(AVCodecContext *avctx, QSVEncContext *q, + const AVFrame *frame) +{ +int updated = 0, qp = 0, new_qp; +char *tail; +AVDictionaryEntry *entry = NULL; + +if (avctx->codec_id != AV_CODEC_ID_H264 && avctx->codec_id != AV_CODEC_ID_HEVC) +return 0; + +entry = av_dict_get(frame->metadata, "qsv_config_qp", NULL, 0); +if (entry && q->param.mfx.RateControlMethod == MFX_RATECONTROL_CQP) { +qp = strtol(entry->value, &tail, 10); +if (*tail) { +av_log(avctx, AV_LOG_WARNING, "Invalid qsv_config_qp string. Ignore this metadata\n"); +return 0; +} +if (qp < 0 || qp > 51) { +av_log(avctx, AV_LOG_WARNING, "Invalid qp, clip to 0 ~ 51\n"); +qp = av_clip(qp, 0, 51); +} +av_log(avctx, AV_LOG_DEBUG, "Configure qp: %d\n",qp); +UPDATE_PARAM(q->param.mfx.QPP, qp); +new_qp = av_clip(qp * fabs(avctx->i_quant_factor) + +avctx->i_quant_offset, 0, 51); +UPDATE_PARAM(q->param.mfx.QPI, new_qp); +new_qp = av_clip(qp * fabs(avctx->b_quant_factor) + +avctx->b_quant_offset, 0, 51); +UPDATE_PARAM(q->param.mfx.QPB, new_qp); +av_log(avctx, AV_LOG_DEBUG, +"using fixed qp = %d/%d/%d for idr/p/b frames\n", +q->param.mfx.QPI, q->param.mfx.QPP, q->param.mfx.QPB); +} +return updated; +} + +static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, + const AVFrame *frame) +{ +int needReset = 0, ret = 0; + +if (!frame) +return 0; + +needReset = update_qp(avctx, q, frame); +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) { @@ -1731,6 +1816,10 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q, { int ret; +ret = update_parameters(avctx, q, frame); +if (ret < 0) +return ret; + ret = encode_frame(avctx, q, frame); if (ret < 0) return ret; -- 2.32.0 ___ ffmpeg-devel mailin