Re: [FFmpeg-devel] [PATCH] avutil/timestamp: avoid using INFINITY for log10 result in av_ts_make_time_string2

2024-08-27 Thread Marton Balint



On Tue, 27 Aug 2024, Rémi Denis-Courmont wrote:




Le 27 août 2024 03:03:37 GMT+03:00, Marton Balint  a écrit :

Using INFINITY can cause issues with -ffast-math, and since we only use this
value to decide the formatting, we can just as easily use 0 for log10 of zero.


FFmpeg does not enable fast-math and last I tried it won't work at all anyway: 
FATE commits seppuku by OoM.

The statement above is completely false if applied to the whole code 
base rather than just this function. Notably FFMAX and FFMIN behave 
differently under -fno-infinite-math (which is implied by -ffast-math).


I meant the statement to the code in question, not generically.



I suspect that *this* code is just the tip of the iceberg. It's not hard 
to imagine that ignoring infinities will break stuff, for one: reading 
raw binary content as float can lead to infinities and other NaNs.


Agreed.



So IMO this patch is wrong. Either we've audited the whole code base, 
and then we should enable -ffast-math, or at least -fno-infinite-math by 
default, or we haven't and then we should not be papering over the issue 
like this.




IMHO the patch itself is harmless (simple, easy to follow), and if it 
helps somebody (no matter how unupported its use-case is), then why the 
hell not. But I can understand your point of view, that we should not 
bother with it, if it is unsupported in the first place, so I will just 
drop this, did not feel strongly about it anyway.


Regards,
Marton




Signed-off-by: Marton Balint 
---
libavutil/timestamp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavutil/timestamp.c b/libavutil/timestamp.c
index 6c231a517d..be4540d4c8 100644
--- a/libavutil/timestamp.c
+++ b/libavutil/timestamp.c
@@ -24,7 +24,7 @@ char *av_ts_make_time_string2(char *buf, int64_t ts, 
AVRational tb)
snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS");
} else {
double val = av_q2d(tb) * ts;
-double log = (fpclassify(val) == FP_ZERO ? -INFINITY : 
floor(log10(fabs(val;
+double log = (fpclassify(val) == FP_ZERO ? 0 : 
floor(log10(fabs(val;
int precision = (isfinite(log) && log < 0) ? -log + 5 : 6;
int last = snprintf(buf, AV_TS_MAX_STRING_SIZE, "%.*f", precision, val);
last = FFMIN(last, AV_TS_MAX_STRING_SIZE - 1) - 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 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] avutil/timestamp: avoid using INFINITY for log10 result in av_ts_make_time_string2

2024-08-27 Thread Rémi Denis-Courmont


Le 27 août 2024 10:00:08 GMT+03:00, Marton Balint  a écrit :

>IMHO the patch itself is harmless (simple, easy to follow), and if it helps 
>somebody (no matter how unupported its use-case is), then why the hell not. 
>But I can understand your point of view, that we should not bother with it, if 
>it is unsupported in the first place, so I will just drop this, did not feel 
>strongly about it anyway.

Can't we just fail configure or compilation hard if __FINITE_MATH_ONLY__ is 
true?

If MPV or whichever downstream wants to get this flag working, it's on them to 
do the hard work (and it's a lot harder than this patch).
___
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] avcodec/cbs_h265: fix valid range for {left, right}_view_id

2024-08-27 Thread James Almer
view_id_len in VPS is 4 bits, so view_id values can be up to 15 bits long.

Signed-off-by: James Almer 
---
 libavcodec/cbs_h265.h | 4 ++--
 libavcodec/cbs_h265_syntax_template.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/libavcodec/cbs_h265.h b/libavcodec/cbs_h265.h
index 892a35bd22..eec4bf0825 100644
--- a/libavcodec/cbs_h265.h
+++ b/libavcodec/cbs_h265.h
@@ -725,8 +725,8 @@ typedef struct H265RawSEI3DReferenceDisplaysInfo {
 uint8_t ref_viewing_distance_flag;
 uint8_t prec_ref_viewing_dist;
 uint8_t num_ref_displays_minus1;
-uint8_t left_view_id[31];
-uint8_t right_view_id[31];
+uint16_t left_view_id[31];
+uint16_t right_view_id[31];
 uint8_t exponent_ref_display_width[31];
 uint8_t mantissa_ref_display_width[31];
 uint8_t exponent_ref_viewing_distance[31];
diff --git a/libavcodec/cbs_h265_syntax_template.c 
b/libavcodec/cbs_h265_syntax_template.c
index 9f0281b8e8..e2805c7ff1 100644
--- a/libavcodec/cbs_h265_syntax_template.c
+++ b/libavcodec/cbs_h265_syntax_template.c
@@ -2299,8 +2299,8 @@ SEI_FUNC(sei_3d_reference_displays_info, 
(CodedBitstreamContext *ctx, RWContext
 ue(prec_ref_viewing_dist, 0, 31);
 ue(num_ref_displays_minus1, 0, 31);
 for (i = 0; i <= current->num_ref_displays_minus1; i++) {
-ues(left_view_id[i], 0, UINT8_MAX, 1, i);
-ues(right_view_id[i], 0, UINT8_MAX, 1, i);
+ues(left_view_id[i], 0, MAX_UINT_BITS(15), 1, i);
+ues(right_view_id[i], 0, MAX_UINT_BITS(15), 1, i);
 us(6, exponent_ref_display_width[i], 0, 62, 1, i);
 if (!current->exponent_ref_display_width[i])
 length = FFMAX(0, (int)current->prec_ref_display_width - 30);
-- 
2.46.0

___
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 v2 3/4] checkasm: improve print format

2024-08-27 Thread J. Dekker
On Mon, Aug 26, 2024, at 12:41, Ramiro Polla wrote:
> On Sun, Aug 25, 2024 at 7:52 PM J. Dekker  wrote:
>> On Thu, Aug 22, 2024, at 16:57, Ramiro Polla wrote:
>> > On Wed, Aug 21, 2024 at 1:26 PM J. Dekker  wrote:
>> >>
>> >> Port dav1d's checkasm output format to FFmpeg's checkasm, includes
>> >> relative speedups and aligns results.
>> >>
>> >> Signed-off-by: J. Dekker 
>> >> ---
>> >>  tests/checkasm/checkasm.c | 53 +++
>> >>  1 file changed, 48 insertions(+), 5 deletions(-)
>> >>
>> >> diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c
>> >> index c5c1eeb07a..f43c1c50f0 100644
>> >> --- a/tests/checkasm/checkasm.c
>> >> +++ b/tests/checkasm/checkasm.c
>> >> @@ -18,6 +18,31 @@
>> >>   * 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.
>> >> + *
>> >> + * Copyright © 2018, VideoLAN and dav1d authors
>> >> + * Copyright © 2018, Two Orioles, LLC
>> >> + * All rights reserved.
>> >> + *
>> >> + * 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.
>> >> + *
>> >> + * 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 OWNER 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.
>> >>   */
>> >
>> > Do we need this double licensing?
>> >
>> >>
>> >>  #include "config.h"
>> >> @@ -575,6 +600,16 @@ static int measure_nop_time(void)
>> >>  return nop_sum / 500;
>> >>  }
>> >>
>> >> +static inline double avg_cycles_per_call(const CheckasmPerf *const p)
>> >> +{
>> >> +if (p->iterations) {
>> >> +const double cycles = (double)(10 * p->cycles) / p->iterations - 
>> >> state.nop_time;
>> >> +if (cycles > 0.0)
>> >> +return cycles / 4.0; /* 4 calls per iteration */
>> >> +}
>> >> +return 0.0;
>> >> +}
>> >> +
>> >>  /* Print benchmark results */
>> >>  static void print_benchs(CheckasmFunc *f)
>> >>  {
>> >> @@ -584,17 +619,25 @@ static void print_benchs(CheckasmFunc *f)
>> >>  /* Only print functions with at least one assembly version */
>> >>  if (f->versions.cpu || f->versions.next) {
>> >>  CheckasmFuncVersion *v = &f->versions;
>> >> +const CheckasmPerf *p = &v->perf;
>> >> +const double baseline = avg_cycles_per_call(p);
>> >> +double decicycles;
>> >>  do {
>> >> -CheckasmPerf *p = &v->perf;
>> >>  if (p->iterations) {
>> >> -int decicycles = (10*p->cycles/p->iterations - 
>> >> state.nop_time) / 4;
>> >> +p = &v->perf;
>> >> +decicycles = avg_cycles_per_call(p);
>> >>  if (state.csv || state.tsv) {
>> >>  const char sep = state.csv ? ',' : '\t';
>> >> -printf("%s%c%s%c%d.%d\n", f->name, sep,
>> >> +printf("%s%c%s%c%.1f\n", f->name, sep,
>> >> cpu_suffix(v->cpu), sep,
>> >> -   decicycles / 10, decicycles % 10);
>> >> +   decicycles / 10.0);
>> >>  } else {
>> >> -printf("%s_%s: %d.%d\n", f->name, 
>> >> cpu_suffix(v->cpu), decicycles/10, decicycles%10);
>> >> +const int pad_length = 10 + 50 -
>> >> +printf("%s_%s:", f->name, 
>> >> cpu_suffix(v->cpu));
>> >> +const double ratio = decicycles ?
>> >> +baseline / decicycles : 0.0;
>> >> +

Re: [FFmpeg-devel] [PATCH] lavc/vvc: Fix assertion bound on qPy_{a, b}

2024-08-27 Thread Nuo Mi
On Sun, Aug 25, 2024 at 10:37 PM Nicolas George  wrote:

> Nuo Mi (12024-08-25):
> > Yes, I mean the v1. sorry for misleading you.
>
> Ah, ok. Then… maybe.
>
> Maybe v1 is the proper fix. Maybe the proper fix is to find where qPy_a
> or qPy_b are set to 63 if they can only be <63 and fix that part of the
> code. Only somebody who knows the codec can say which is the proper fix,
> but it is highly unlikely any other change is.
>
Hi Nicolas,
From the spec
QpY = ( ( qPY_PRED + CuQpDeltaVal + 64 + 2 * QpBdOffset ) % ( 64 +
QpBdOffset ) ) - QpBdOffset
So qPY_A and qPY_B <= 63. Not < 63.
Frank's patch will fix the assert.

qPY_A and qPY_B calculations have no obvious issues.
We read  qPY_A and qPY_B  from a table. We add an assertion here to ensure
the table hasn't been polluted.

Thank you


> Regards,
>
> --
>   Nicolas George
> ___
> 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 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] avutil/timestamp: avoid using INFINITY for log10 result in av_ts_make_time_string2

2024-08-27 Thread Michael Niedermayer
On Tue, Aug 27, 2024 at 02:03:37AM +0200, Marton Balint wrote:
> Using INFINITY can cause issues with -ffast-math, and since we only use this
> value to decide the formatting, we can just as easily use 0 for log10 of zero.
> 
> Signed-off-by: Marton Balint 
> ---
>  libavutil/timestamp.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/libavutil/timestamp.c b/libavutil/timestamp.c
> index 6c231a517d..be4540d4c8 100644
> --- a/libavutil/timestamp.c
> +++ b/libavutil/timestamp.c
> @@ -24,7 +24,7 @@ char *av_ts_make_time_string2(char *buf, int64_t ts, 
> AVRational tb)
>  snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS");
>  } else {
>  double val = av_q2d(tb) * ts;
> -double log = (fpclassify(val) == FP_ZERO ? -INFINITY : 
> floor(log10(fabs(val;
> +double log = (fpclassify(val) == FP_ZERO ? 0 : 
> floor(log10(fabs(val;
>  int precision = (isfinite(log) && log < 0) ? -log + 5 : 6;

please add a comment as log(0) = 0 is not correct (in the general case)
otherwise LGTM

thx

[...]
-- 
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

No human being will ever know the Truth, for even if they happen to say it
by chance, they would not even known they had done so. -- Xenophanes


signature.asc
Description: PGP signature
___
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 7/7] avcodec/riscv: add h264 qpel

2024-08-27 Thread Niklas Haas
On Mon, 19 Aug 2024 21:27:38 +0300 Rémi Denis-Courmont  wrote:
> Le tiistaina 13. elokuuta 2024, 17.03.36 EEST J. Dekker a écrit :
> > +#include "libavutil/riscv/asm.S"
> > +
> > +.macro vnclipsu.wi  shifti, lmul, lmul2, vregs:vararg
> > +vsetvli zero, zero, e16, \lmul2, ta, ma
> 
> We don't typically do that for a very good reason. The vsetvli is most often 
> redundant and nonobviously so. (Also in some cases, there are better ways to 
> do signed-to-unsigned clip.)

I could rename the macro to discourage its use outside of this function, then.

> 
> > +.irp x, \vregs
> > +vmax.vx \x, \x, zero
> > +.endr
> > +vsetvli zero, zero, e8, \lmul, ta, ma
> > +.irp x, \vregs
> > +vnclipu.wi  \x, \x, \shifti
> > +.endr
> > +.endm
> > +
> > +.macro lowpass_init  lmul, sizei, size, w0, w1, backup
> 
> This is needlessly convoluted. In fact, backup is not even used, which kind 
> of 
> highlights the point.

That parameter was simply left over from a previous version of the code. Are
you suggesting we simply duplicate the contents of this macro into all of the
functions that use it?

> 
> > +vsetivli zero, \sizei, e8, \lmul, ta, ma
> > +csrwivxrm, 0
> > +li   \size, \sizei
> > +.ifnb \w0
> > +li   \w0, 20
> > +li   \w1, -5
> > +.endif
> > +.endm
> > +
> > +/* output is unclipped; clobbers v26-v31 plus \tmp and \tmp2 */
> > +.macro lowpass_h vdst, src, w0, w1, tmp=t3, tmp2=t4
> > +addi \tmp, \src, 3
> > +lbu  \tmp2, 2(\src)
> > +vle8.v   v31, (\tmp)
> > +lbu  \tmp, 1(\src)
> > +vslide1up.vx v30, v31, \tmp2
> > +lbu  \tmp2, 0(\src)
> > +vslide1up.vx v29, v30, \tmp
> > +lbu  \tmp, -1(\src)
> > +vslide1up.vx v28, v29, \tmp2
> > +lbu  \tmp2, -2(\src)
> > +vslide1up.vx v27, v28, \tmp
> > +vslide1up.vx v26, v27, \tmp2
> 
> That's a lot of sequentially dependent vector instructions to save zero-
> extending v31 before the MACs. Are you sure it's faster that way?

I'm not sure what you mean. How would your alternative implementation look?
It's certainly possible to make these instructions less sequential by emitting
multiple `lbu` instructions instead of sliding up.

> 
> > +vwaddu.vv\vdst, v26, v31
> > +vwmaccu.vx   \vdst, \w0, v28
> > +vwmaccu.vx   \vdst, \w0, v29
> > +vwmaccsu.vx  \vdst, \w1, v27
> > +vwmaccsu.vx  \vdst, \w1, v30
> > +.endm
> > +
> > +/* output is unclipped */
> > +.macro lowpass_v w0, w1, vdst, vsrc0, vsrc1, vsrc2, vsrc3, vsrc4,
> > vsrc5, signed=0
> > +.if \signed
> > +vwadd.vv \vdst, \vsrc0, \vsrc5
> > +vwmacc.vx\vdst, \w0, \vsrc2
> > +vwmacc.vx\vdst, \w0, \vsrc3
> > +vwmacc.vx\vdst, \w1, \vsrc1
> > +vwmacc.vx\vdst, \w1, \vsrc4
> > +.else
> > +vwaddu.vv\vdst, \vsrc0, \vsrc5
> > +vwmaccu.vx   \vdst, \w0, \vsrc2
> > +vwmaccu.vx   \vdst, \w0, \vsrc3
> > +vwmaccsu.vx  \vdst, \w1, \vsrc1
> > +vwmaccsu.vx  \vdst, \w1, \vsrc4
> > +.endif
> > +.endm
> > +
> > +.macro qpel_mc00 op, dst, src, stride, size
> > +func ff_\op\()_h264_qpel_pixels, zve32x
> > +1:
> > +add  t0, \stride, \src
> > +add  t1, \stride, t0
> > +add  t2, \stride, t1
> > +vle8.v   v0, (\src)
> > +vle8.v   v1, (t0)
> > +vle8.v   v2, (t1)
> > +vle8.v   v3, (t2)
> > +addi \size, \size, -4
> > +add  \src, \stride, t2
> > +add  t0, \stride, \dst
> > +add  t1, \stride, t0
> > +add  t2, \stride, t1
> > +.ifc \op, avg
> > +vle8.v   v4, (\dst)
> > +vle8.v   v5, (t0)
> > +vle8.v   v6, (t1)
> > +vle8.v   v7, (t2)
> > +vaaddu.vvv0, v0, v4
> > +vaaddu.vvv1, v1, v5
> > +vaaddu.vvv2, v2, v6
> > +vaaddu.vvv3, v3, v7
> > +.endif
> > +vse8.v   v0, (\dst)
> > +vse8.v   v1, (t0)
> > +vse8.v   v2, (t1)
> > +vse8.v   v3, (t2)
> > +add  \dst, \stride, t2
> > +bnez \size, 1b
> > +ret
> > +endfunc
> > +.endm
> > +
> > +qpel_mc00put, a0, a1, a2, a4
> > +qpel_mc00avg, a0, a1, a2, a4
> 
> Please don't add constant macro parameters.

Why? It makes the code much easier to modify, and arguably also to understand.
This design was certainly invaluable

Re: [FFmpeg-devel] [PATCH 1/3] lavu/opt: document underlying C types for enum AVOptionType

2024-08-27 Thread Anton Khirnov
Quoting Michael Niedermayer (2024-08-23 21:30:06)
> On Thu, Aug 22, 2024 at 02:39:10PM +0200, Anton Khirnov wrote:
> > Quoting Michael Niedermayer (2024-08-20 22:57:37)
> > > Hi
> > > 
> > > On Sun, Aug 18, 2024 at 01:26:53PM +0200, Anton Khirnov wrote:
> > > > ---
> > > >  libavutil/opt.h | 78 +++--
> > > >  1 file changed, 75 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/libavutil/opt.h b/libavutil/opt.h
> > > > index 07e27a9208..23bc495158 100644
> > > > --- a/libavutil/opt.h
> > > > +++ b/libavutil/opt.h
> > > > @@ -240,26 +240,98 @@
> > > >   * before the file is actually opened.
> > > >   */
> > > >  
> > > > +/**
> > > > + * An option type determines:
> > > > + * - for native access, the underlying C type of the field that an 
> > > > AVOption
> > > > + *   refers to;
> > > > + * - for foreign access, the semantics of accessing the option through 
> > > > this API,
> > > > + *   e.g. which av_opt_get_*() and av_opt_set_*() functions can be 
> > > > called, or
> > > > + *   what format will av_opt_get()/av_opt_set() expect/produce.
> > > 
> > > "foreign access" ? is this a standard/ common term ?
> > > if not, maybe somone has a more descriptive more common term/idea
> > 
> > The term is defined higher up in the file, cf. fc706276c05
> 
> if it sounds fine to you, then no objection.
> I wonder if direct vs access through accessor functions are clearer
> terms though

That's not what the difference is.

-- 
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 01/42] lavu/opt: add API for setting array-type option values

2024-08-27 Thread Anton Khirnov
Previously one could only replace the entire array with a new one
deserialized from a string. The new API allows inserting, replacing, and
removing arbitrary element ranges.
---
 doc/APIchanges  |   3 +
 libavutil/opt.c | 186 
 libavutil/opt.h |  56 +
 libavutil/version.h |   2 +-
 4 files changed, 246 insertions(+), 1 deletion(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index 226c6f8b10..9c3ee5 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07
 
 API changes, most recent first:
 
+2024-09-xx - x - lavu 59.36.100 - opt.h
+  Add av_opt_set_array() and AV_OPT_ARRAY_REPLACE.
+
 2024-08-xx - x - lavu 59.35.100 - opt.h
   Add av_opt_get_array_size() and av_opt_get_array().
 
diff --git a/libavutil/opt.c b/libavutil/opt.c
index d515e20e97..e07ec8ce0f 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -2244,6 +2244,192 @@ fail:
 return ret;
 }
 
+int av_opt_set_array(void *obj, const char *name, int search_flags,
+ unsigned int start_elem, unsigned int nb_elems,
+ enum AVOptionType val_type, const void *val)
+{
+const size_t elem_size_val = opt_elem_size[TYPE_BASE(val_type)];
+
+const AVOption *o;
+const AVOptionArrayDef *arr;
+void *target_obj;
+
+void *parray;
+void *new_elems;
+unsigned *array_size, new_size;
+size_t elem_size;
+
+int ret;
+
+o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+if (!o || !target_obj)
+return AVERROR_OPTION_NOT_FOUND;
+if (!(o->type & AV_OPT_TYPE_FLAG_ARRAY) ||
+(val_type & AV_OPT_TYPE_FLAG_ARRAY))
+return AVERROR(EINVAL);
+
+arr= o->default_val.arr;
+parray = (uint8_t *)target_obj + o->offset;
+array_size = opt_array_pcount(parray);
+elem_size  = opt_elem_size[TYPE_BASE(o->type)];
+
+if (start_elem > *array_size)
+return AVERROR(EINVAL);
+
+// compute new array size
+if (!val) {
+if (*array_size - start_elem < nb_elems)
+return AVERROR(EINVAL);
+
+new_size = *array_size - nb_elems;
+} else if (search_flags & AV_OPT_ARRAY_REPLACE) {
+if (start_elem >= UINT_MAX - nb_elems)
+return AVERROR(EINVAL);
+
+new_size = FFMAX(*array_size, start_elem + nb_elems);
+} else {
+if (nb_elems >= UINT_MAX - *array_size)
+return AVERROR(EINVAL);
+
+new_size = *array_size + nb_elems;
+}
+
+if (arr &&
+((arr->size_max && new_size > arr->size_max) ||
+ (arr->size_min && new_size < arr->size_min)))
+return AVERROR(EINVAL);
+
+// desired operation is shrinking the array
+if (!val) {
+void *array = *(void**)parray;
+
+for (unsigned i = 0; i < nb_elems; i++) {
+opt_free_elem(o->type,
+  opt_array_pelem(o, array, start_elem + i));
+}
+
+if (new_size > 0) {
+memmove(opt_array_pelem(o, array, start_elem),
+opt_array_pelem(o, array, start_elem + nb_elems),
+elem_size * (*array_size - start_elem - nb_elems));
+
+array = av_realloc_array(array, new_size, elem_size);
+if (!array)
+return AVERROR(ENOMEM);
+
+*(void**)parray = array;
+} else
+av_freep(parray);
+
+*array_size = new_size;
+
+return 0;
+}
+
+// otherwise, desired operation is insert/replace;
+// first, store new elements in a separate array to simplify
+// rollback on failure
+new_elems = av_calloc(nb_elems, elem_size);
+if (!new_elems)
+return AVERROR(ENOMEM);
+
+// convert/validate each new element
+for (unsigned i = 0; i < nb_elems; i++) {
+void   *dst = opt_array_pelem(o, new_elems, i);
+const void *src = (uint8_t*)val + i * elem_size_val;
+
+double num = 1.0;
+intden = 1;
+int64_t intnum = 1;
+
+if (val_type == TYPE_BASE(o->type)) {
+ret = opt_copy_elem(obj, val_type, dst, src);
+if (ret < 0)
+goto fail;
+
+// validate the range for numeric options
+ret = read_number(o, dst, &num, &den, &intnum);
+if (ret >= 0 && TYPE_BASE(o->type) != AV_OPT_TYPE_FLAGS &&
+(!den || o->max * den < num * intnum || o->min * den > num * 
intnum)) {
+num = den ? num * intnum / den : (num && intnum ? INFINITY : 
NAN);
+av_log(obj, AV_LOG_ERROR, "Cannot set array element %u for "
+   "parameter '%s': value %f out of range [%g - %g]\n",
+   start_elem + i, o->name, num, o->min, o->max);
+ret = AVERROR(ERANGE);
+goto fail;
+}
+} else if (val_type == AV_OPT_TYPE_STRING) {
+ 

[FFmpeg-devel] [PATCH 02/42] lavu/opt: handle UINT options as the POD they are

2024-08-27 Thread Anton Khirnov
Fixes operations on array UINT options.
---
 libavutil/opt.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libavutil/opt.c b/libavutil/opt.c
index e07ec8ce0f..d2af76478c 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -98,6 +98,7 @@ static int opt_is_pod(enum AVOptionType type)
 case AV_OPT_TYPE_DURATION:
 case AV_OPT_TYPE_COLOR:
 case AV_OPT_TYPE_BOOL:
+case AV_OPT_TYPE_UINT:
 return 1;
 }
 return 0;
-- 
2.43.0

___
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] [RFC/PATCH] MV-HEVC decoding

2024-08-27 Thread Anton Khirnov
Hi,
this patchset adds support for decoding MV-HEVC (multiview, typically
used for stereoscopic 3D video). The code currently supports at most two
views, with the second depending on the first (i.e. using it for inter
prediction). Both views have to be of the same size; the spec allows
them not to be, but I'm not supporting that, or a lot of other insanity
in there.

The frames for both views are interleaved in the output, with side data
indicating which one has which view ID. If the relevant SEI is present,
we also add side data indicating which view is left or right.

Since the API caller needs to request the views it wants, and all the
multilayer configuration is potentially per-sequence, there needs to be
a negotiation process where the decoder exports available views and the
caller picks from them. I'm implementing this by adding several
decoder-private AVOptions, meant to be accessed from get_format(). Some
of them are read-only and the caller reads available view IDs (and
positions, if known) from them. The others are writable, and are used to
receive the caller's choice.

One potential point of discussion is that the caller may want to know
the view ID in its get_buffer2() callback (this is actually used in the
ffmpeg CLI code). One potential option is attaching the view ID side
data before calling get_buffer2(), but that is quite unusual and would
require changes to the progress frame API. For now, I'm using another
read-only decoder-private AVOption for that. Opinions welcome.

I'm also adding nontrivial support for this to ffmpeg CLI, which mainly
means extending stream specifiers to allow specifying individual views,
e.g. "-map 0:v:0:vpos:left" selects the left view (see TFM for more
details).

The set should be mostly functional, I'm tagging it as RFC because
there's a little polishing left to do, and a few tests left to add.
Testing and review welcome. You can fetch the set from
git://git.khirnov.net/libav, branch 'mv-hevc'.

Cheers,
-- 
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 03/42] MAINTAINERS: add myself for hevc/*

2024-08-27 Thread Anton Khirnov
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 1f758f401c..d79920d9d6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -174,6 +174,7 @@ Codecs:
   h263* Michael Niedermayer
   h264* Loren Merritt, Michael Niedermayer
   hap*  Tom Butterworth
+  hevc/*Anton Khirnov
   huffyuv*  Michael Niedermayer
   idcinvideo.c  Mike Melanson
   interplayvideo.c  Mike Melanson
-- 
2.43.0

___
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 15/42] lavc/hevcdec: move HEVCContext.tab_ipm to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
---
 libavcodec/hevc/hevcdec.c | 32 ++--
 libavcodec/hevc/hevcdec.h |  2 +-
 2 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 1887a44e3e..0a3b5ba4c4 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -74,7 +74,7 @@ static void pic_arrays_free(HEVCContext *s, HEVCLayerContext 
*l)
 av_freep(&l->skip_flag);
 av_freep(&l->tab_ct_depth);
 
-av_freep(&s->tab_ipm);
+av_freep(&l->tab_ipm);
 av_freep(&l->cbf_luma);
 av_freep(&s->is_pcm);
 
@@ -114,9 +114,9 @@ static int pic_arrays_init(HEVCContext *s, HEVCLayerContext 
*l, const HEVCSPS *s
 goto fail;
 
 l->cbf_luma = av_malloc_array(sps->min_tb_width, sps->min_tb_height);
-s->tab_ipm  = av_mallocz(min_pu_size);
+l->tab_ipm  = av_mallocz(min_pu_size);
 s->is_pcm   = av_malloc_array(sps->min_pu_width + 1, sps->min_pu_height + 
1);
-if (!s->tab_ipm || !l->cbf_luma || !s->is_pcm)
+if (!l->tab_ipm || !l->cbf_luma || !s->is_pcm)
 goto fail;
 
 s->filter_slice_edges = av_mallocz(ctb_count);
@@ -2010,7 +2010,8 @@ static void hls_prediction_unit(HEVCLocalContext *lc,
 /**
  * 8.4.1
  */
-static int luma_intra_pred_mode(HEVCLocalContext *lc, const HEVCSPS *sps,
+static int luma_intra_pred_mode(HEVCLocalContext *lc, const HEVCLayerContext 
*l,
+const HEVCSPS *sps,
 int x0, int y0, int pu_size,
 int prev_intra_luma_pred_flag)
 {
@@ -2023,9 +2024,9 @@ static int luma_intra_pred_mode(HEVCLocalContext *lc, 
const HEVCSPS *sps,
 int y0b  = av_zero_extend(y0, sps->log2_ctb_size);
 
 int cand_up   = (lc->ctb_up_flag || y0b) ?
-s->tab_ipm[(y_pu - 1) * min_pu_width + x_pu] : INTRA_DC;
+l->tab_ipm[(y_pu - 1) * min_pu_width + x_pu] : INTRA_DC;
 int cand_left = (lc->ctb_left_flag || x0b) ?
-s->tab_ipm[y_pu * min_pu_width + x_pu - 1]   : INTRA_DC;
+l->tab_ipm[y_pu * min_pu_width + x_pu - 1]   : INTRA_DC;
 
 int y_ctb = (y0 >> (sps->log2_ctb_size)) << (sps->log2_ctb_size);
 
@@ -2080,7 +2081,7 @@ static int luma_intra_pred_mode(HEVCLocalContext *lc, 
const HEVCSPS *sps,
 if (!size_in_pus)
 size_in_pus = 1;
 for (i = 0; i < size_in_pus; i++) {
-memset(&s->tab_ipm[(y_pu + i) * min_pu_width + x_pu],
+memset(&l->tab_ipm[(y_pu + i) * min_pu_width + x_pu],
intra_pred_mode, size_in_pus);
 
 for (j = 0; j < size_in_pus; j++) {
@@ -2109,7 +2110,8 @@ static const uint8_t tab_mode_idx[] = {
  0,  1,  2,  2,  2,  2,  3,  5,  7,  8, 10, 12, 13, 15, 17, 18, 19, 20,
 21, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 28, 29, 29, 30, 31};
 
-static void intra_prediction_unit(HEVCLocalContext *lc, const HEVCSPS *sps,
+static void intra_prediction_unit(HEVCLocalContext *lc,
+  const HEVCLayerContext *l, const HEVCSPS 
*sps,
   int x0, int y0,
   int log2_cb_size)
 {
@@ -2133,7 +2135,8 @@ static void intra_prediction_unit(HEVCLocalContext *lc, 
const HEVCSPS *sps,
 lc->pu.rem_intra_luma_pred_mode = 
ff_hevc_rem_intra_luma_pred_mode_decode(lc);
 
 lc->pu.intra_pred_mode[2 * i + j] =
-luma_intra_pred_mode(lc, sps, x0 + pb_size * j, y0 + pb_size * 
i, pb_size,
+luma_intra_pred_mode(lc, l, sps,
+ x0 + pb_size * j, y0 + pb_size * i, 
pb_size,
  prev_intra_luma_pred_flag[2 * i + j]);
 }
 }
@@ -2178,6 +2181,7 @@ static void intra_prediction_unit(HEVCLocalContext *lc, 
const HEVCSPS *sps,
 }
 
 static void intra_prediction_unit_default_value(HEVCLocalContext *lc,
+const HEVCLayerContext *l,
 const HEVCSPS *sps,
 int x0, int y0,
 int log2_cb_size)
@@ -2194,7 +2198,7 @@ static void 
intra_prediction_unit_default_value(HEVCLocalContext *lc,
 if (size_in_pus == 0)
 size_in_pus = 1;
 for (j = 0; j < size_in_pus; j++)
-memset(&s->tab_ipm[(y_pu + j) * min_pu_width + x_pu], INTRA_DC, 
size_in_pus);
+memset(&l->tab_ipm[(y_pu + j) * min_pu_width + x_pu], INTRA_DC, 
size_in_pus);
 if (lc->cu.pred_mode == MODE_INTRA)
 for (j = 0; j < size_in_pus; j++)
 for (k = 0; k < size_in_pus; k++)
@@ -2256,7 +2260,7 @@ static int hls_coding_unit(HEVCLocalContext *lc, const 
HEVCContext *s,
 if (SAMPLE_CTB(l->skip_flag, x_cb, y_cb)) {
 hls_prediction_unit(lc, l, pps, sps,
 x0, y0, cb_size, cb_size, log2_cb_size, 0, idx);
-intra_prediction_unit_default_value(lc, 

[FFmpeg-devel] [PATCH 04/42] lavu/frame: add side data storing view ID for multi-view video

2024-08-27 Thread Anton Khirnov
---
 doc/APIchanges| 3 +++
 fftools/ffprobe.c | 2 ++
 libavfilter/vf_showinfo.c | 2 ++
 libavutil/frame.c | 1 +
 libavutil/frame.h | 9 +
 libavutil/version.h   | 2 +-
 6 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index 9c3ee5..a8f84ca45f 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07
 
 API changes, most recent first:
 
+2024-xx-xx - xxx - lavu 59.37.100 - frame.h
+  Add AV_FRAME_DATA_VIEW_ID.
+
 2024-09-xx - x - lavu 59.36.100 - opt.h
   Add av_opt_set_array() and AV_OPT_ARRAY_REPLACE.
 
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index bf5ebe3ce0..14b98d22a1 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -2920,6 +2920,8 @@ static void print_frame_side_data(WriterContext *w,
 } else if (sd->type == AV_FRAME_DATA_FILM_GRAIN_PARAMS) {
 AVFilmGrainParams *fgp = (AVFilmGrainParams *)sd->data;
 print_film_grain_params(w, fgp);
+} else if (sd->type == AV_FRAME_DATA_VIEW_ID) {
+print_int("view_id", *(int*)sd->data);
 }
 writer_print_section_footer(w);
 }
diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c
index f81df9d1bf..77082505f5 100644
--- a/libavfilter/vf_showinfo.c
+++ b/libavfilter/vf_showinfo.c
@@ -857,6 +857,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame 
*frame)
 case AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT:
 dump_ambient_viewing_environment(ctx, sd);
 break;
+case AV_FRAME_DATA_VIEW_ID:
+av_log(ctx, AV_LOG_INFO, "view id: %d\n", *(int*)sd->data);
 default:
 if (name)
 av_log(ctx, AV_LOG_INFO,
diff --git a/libavutil/frame.c b/libavutil/frame.c
index 5cbfc6a48b..891909fc2a 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -46,6 +46,7 @@ static const AVSideDataDescriptor sd_props[] = {
 [AV_FRAME_DATA_DETECTION_BBOXES]= { "Bounding boxes for object 
detection and classification" },
 [AV_FRAME_DATA_DOVI_RPU_BUFFER] = { "Dolby Vision RPU Data" },
 [AV_FRAME_DATA_DOVI_METADATA]   = { "Dolby Vision Metadata" },
+[AV_FRAME_DATA_VIEW_ID] = { "View ID" },
 [AV_FRAME_DATA_STEREO3D]= { "Stereo 3D",   
 AV_SIDE_DATA_PROP_GLOBAL },
 [AV_FRAME_DATA_REPLAYGAIN]  = { "AVReplayGain",
 AV_SIDE_DATA_PROP_GLOBAL },
 [AV_FRAME_DATA_DISPLAYMATRIX]   = { "3x3 displaymatrix",   
 AV_SIDE_DATA_PROP_GLOBAL },
diff --git a/libavutil/frame.h b/libavutil/frame.h
index 60bb966f8b..cea1c68df5 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -228,6 +228,15 @@ enum AVFrameSideDataType {
  * encoding.
  */
 AV_FRAME_DATA_VIDEO_HINT,
+
+/**
+ * This side data must be associated with a video frame.
+ * The presence of this side data indicates that the video stream is
+ * composed of multiple views (e.g. stereoscopic 3D content,
+ * cf. H.264 Annex H or H.265 Annex G).
+ * The data is an int storing the view ID.
+ */
+AV_FRAME_DATA_VIEW_ID,
 };
 
 enum AVActiveFormatDescription {
diff --git a/libavutil/version.h b/libavutil/version.h
index 25a6f5531b..7900379c12 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
  */
 
 #define LIBAVUTIL_VERSION_MAJOR  59
-#define LIBAVUTIL_VERSION_MINOR  36
+#define LIBAVUTIL_VERSION_MINOR  37
 #define LIBAVUTIL_VERSION_MICRO 100
 
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
-- 
2.43.0

___
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 24/42] lavc/hevcdec: move active SPS from HEVCParamSets to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
Currently active SPS is a per-layer property.
---
 libavcodec/hevc/hevcdec.c | 29 -
 libavcodec/hevc/hevcdec.h |  2 ++
 libavcodec/hevc/ps.c  |  6 --
 libavcodec/hevc/ps.h  |  3 ---
 libavcodec/hevc/refs.c| 24 
 libavcodec/vaapi_hevc.c   |  4 ++--
 libavcodec/vdpau_hevc.c   |  2 +-
 7 files changed, 33 insertions(+), 37 deletions(-)

diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index eb41f9a5d6..6b596f1573 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -555,7 +555,7 @@ static int set_sps(HEVCContext *s, HEVCLayerContext *l, 
const HEVCSPS *sps)
 int ret;
 
 pic_arrays_free(l);
-s->ps.sps = NULL;
+ff_refstruct_unref(&l->sps);
 ff_refstruct_unref(&s->vps);
 
 if (!sps)
@@ -569,14 +569,14 @@ static int set_sps(HEVCContext *s, HEVCLayerContext *l, 
const HEVCSPS *sps)
 ff_hevc_dsp_init (&s->hevcdsp, sps->bit_depth);
 ff_videodsp_init (&s->vdsp,sps->bit_depth);
 
-s->ps.sps = sps;
+l->sps= ff_refstruct_ref_c(sps);
 s->vps= ff_refstruct_ref_c(sps->vps);
 
 return 0;
 
 fail:
 pic_arrays_free(l);
-s->ps.sps = NULL;
+ff_refstruct_unref(&l->sps);
 return ret;
 }
 
@@ -2831,6 +2831,7 @@ static int decode_slice_data(HEVCContext *s, const 
HEVCLayerContext *l,
 
 static int set_side_data(HEVCContext *s)
 {
+const HEVCSPS *sps = s->cur_frame->pps->sps;
 AVFrame *out = s->cur_frame->f;
 int ret;
 
@@ -2846,8 +2847,8 @@ static int set_side_data(HEVCContext *s)
 }
 
 ret = ff_h2645_sei_to_frame(out, &s->sei.common, AV_CODEC_ID_HEVC, 
s->avctx,
-&s->ps.sps->vui.common,
-s->ps.sps->bit_depth, 
s->ps.sps->bit_depth_chroma,
+&sps->vui.common,
+sps->bit_depth, sps->bit_depth_chroma,
 s->cur_frame->poc /* no poc_offset in HEVC */);
 if (ret < 0)
 return ret;
@@ -2932,7 +2933,7 @@ static int hevc_frame_start(HEVCContext *s, 
HEVCLayerContext *l)
 }
 
 ff_refstruct_replace(&s->pps, pps);
-if (s->ps.sps != sps) {
+if (l->sps != sps) {
 enum AVPixelFormat pix_fmt;
 
 ff_hevc_clear_refs(l);
@@ -3523,8 +3524,10 @@ static av_cold int hevc_decode_free(AVCodecContext 
*avctx)
 {
 HEVCContext   *s = avctx->priv_data;
 
-for (int i = 0; i < FF_ARRAY_ELEMS(s->layers); i++)
+for (int i = 0; i < FF_ARRAY_ELEMS(s->layers); i++) {
 pic_arrays_free(&s->layers[i]);
+ff_refstruct_unref(&s->layers[i].sps);
+}
 
 ff_refstruct_unref(&s->vps);
 ff_refstruct_unref(&s->pps);
@@ -3620,10 +3623,14 @@ static int hevc_update_thread_context(AVCodecContext 
*dst,
 return ret;
 }
 }
+
+if (l->sps != l0->sps) {
+ret = set_sps(s, l, l0->sps);
+if (ret < 0)
+return ret;
+}
 }
 
-if (s->ps.sps != s0->ps.sps)
-s->ps.sps = NULL;
 for (int i = 0; i < FF_ARRAY_ELEMS(s->ps.vps_list); i++)
 ff_refstruct_replace(&s->ps.vps_list[i], s0->ps.vps_list[i]);
 
@@ -3636,10 +3643,6 @@ static int hevc_update_thread_context(AVCodecContext 
*dst,
 // PPS do not persist between frames
 ff_refstruct_unref(&s->pps);
 
-if (s->ps.sps != s0->ps.sps)
-if ((ret = set_sps(s, &s->layers[0], s0->ps.sps)) < 0)
-return ret;
-
 s->poc_tid0   = s0->poc_tid0;
 s->eos= s0->eos;
 s->no_rasl_output_flag = s0->no_rasl_output_flag;
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index a534aee60f..e43f2d0201 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -442,6 +442,8 @@ typedef struct HEVCLocalContext {
 typedef struct HEVCLayerContext {
 HEVCFrame   DPB[32];
 
+const HEVCSPS  *sps; // RefStruct reference
+
 int bs_width;
 int bs_height;
 
diff --git a/libavcodec/hevc/ps.c b/libavcodec/hevc/ps.c
index 99382876af..5fa470cea3 100644
--- a/libavcodec/hevc/ps.c
+++ b/libavcodec/hevc/ps.c
@@ -66,15 +66,11 @@ static void remove_sps(HEVCParamSets *s, int id)
 {
 int i;
 if (s->sps_list[id]) {
-if (s->sps == s->sps_list[id])
-s->sps = NULL;
-
 /* drop all PPS that depend on this SPS */
 for (i = 0; i < FF_ARRAY_ELEMS(s->pps_list); i++)
 if (s->pps_list[i] && s->pps_list[i]->sps_id == id)
 ff_refstruct_unref(&s->pps_list[i]);
 
-av_assert0(!(s->sps_list[id] && s->sps == s->sps_list[id]));
 ff_refstruct_unref(&s->sps_list[id]);
 }
 }
@@ -2042,8 +2038,6 @@ void ff_hevc_ps_uninit(HEVCParamSets *ps)
 ff_refstruct_unref(&ps->sps_list[i]);
 for (i = 0; i < FF_ARRAY_ELEMS(ps->pps_list); i++)
 ff_refstruct_unref(&ps->pps_list[i]);
-
-ps->sps = NULL;
 }
 
 int

[FFmpeg-devel] [PATCH 28/42] lavc/hevc/ps: implement SPS parsing for nuh_layer_id>0

2024-08-27 Thread Anton Khirnov
Cf. F.7.3.2.2 "Sequence parameter set RBSP syntax", which extends normal
SPS parsing with special clauses depending on MultiLayerExtSpsFlag.
---
 libavcodec/hevc/hevcdec.c |  2 +-
 libavcodec/hevc/parse.c   |  3 +-
 libavcodec/hevc/parser.c  |  2 +-
 libavcodec/hevc/ps.c  | 62 +++
 libavcodec/hevc/ps.h  |  7 +++--
 libavcodec/qsvenc_hevc.c  |  2 +-
 6 files changed, 65 insertions(+), 13 deletions(-)

diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 6b596f1573..260b9abef0 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -3256,7 +3256,7 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL 
*nal)
 break;
 case HEVC_NAL_SPS:
 ret = ff_hevc_decode_nal_sps(&gb, s->avctx, &s->ps,
- s->apply_defdispwin);
+ nal->nuh_layer_id, s->apply_defdispwin);
 if (ret < 0)
 goto fail;
 break;
diff --git a/libavcodec/hevc/parse.c b/libavcodec/hevc/parse.c
index ec8d1aeacf..ad84b7b152 100644
--- a/libavcodec/hevc/parse.c
+++ b/libavcodec/hevc/parse.c
@@ -49,7 +49,8 @@ static int hevc_decode_nal_units(const uint8_t *buf, int 
buf_size, HEVCParamSets
 goto done;
 break;
 case HEVC_NAL_SPS:
-ret = ff_hevc_decode_nal_sps(&nal->gb, logctx, ps, 
apply_defdispwin);
+ret = ff_hevc_decode_nal_sps(&nal->gb, logctx, ps,
+ nal->nuh_layer_id, apply_defdispwin);
 if (ret < 0)
 goto done;
 break;
diff --git a/libavcodec/hevc/parser.c b/libavcodec/hevc/parser.c
index 8db56e259e..a10f38941b 100644
--- a/libavcodec/hevc/parser.c
+++ b/libavcodec/hevc/parser.c
@@ -209,7 +209,7 @@ static int parse_nal_units(AVCodecParserContext *s, const 
uint8_t *buf,
 ff_hevc_decode_nal_vps(gb, avctx, ps);
 break;
 case HEVC_NAL_SPS:
-ff_hevc_decode_nal_sps(gb, avctx, ps, 1);
+ff_hevc_decode_nal_sps(gb, avctx, ps, nal->nuh_layer_id, 1);
 break;
 case HEVC_NAL_PPS:
 ff_hevc_decode_nal_pps(gb, avctx, ps);
diff --git a/libavcodec/hevc/ps.c b/libavcodec/hevc/ps.c
index 0e084958be..0b34dd10a8 100644
--- a/libavcodec/hevc/ps.c
+++ b/libavcodec/hevc/ps.c
@@ -1145,12 +1145,12 @@ static int map_pixel_format(AVCodecContext *avctx, 
HEVCSPS *sps)
 }
 
 int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id,
-  int apply_defdispwin, const HEVCVPS * const *vps_list,
-  AVCodecContext *avctx)
+  unsigned nuh_layer_id, int apply_defdispwin,
+  const HEVCVPS * const *vps_list, AVCodecContext *avctx)
 {
 HEVCWindow *ow;
 int ret = 0;
-int bit_depth_chroma, start, num_comps;
+int bit_depth_chroma, num_comps, multi_layer_ext;
 int i;
 
 // Coded parameters
@@ -1167,16 +1167,26 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, 
unsigned int *sps_id,
 }
 
 sps->max_sub_layers = get_bits(gb, 3) + 1;
+multi_layer_ext = nuh_layer_id > 0 &&
+  sps->max_sub_layers == HEVC_MAX_SUB_LAYERS + 1;
+if (multi_layer_ext) {
+if (!sps->vps)
+return AVERROR(EINVAL);
+
+sps->max_sub_layers = sps->vps->vps_max_sub_layers;
+}
 if (sps->max_sub_layers > HEVC_MAX_SUB_LAYERS) {
 av_log(avctx, AV_LOG_ERROR, "sps_max_sub_layers out of range: %d\n",
sps->max_sub_layers);
 return AVERROR_INVALIDDATA;
 }
 
+if (!multi_layer_ext) {
 sps->temporal_id_nesting = get_bits(gb, 1);
 
 if ((ret = parse_ptl(gb, avctx, 1, &sps->ptl, sps->max_sub_layers)) < 0)
 return ret;
+}
 
 *sps_id = get_ue_golomb_long(gb);
 if (*sps_id >= HEVC_MAX_SPS_COUNT) {
@@ -1184,6 +1194,28 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, 
unsigned int *sps_id,
 return AVERROR_INVALIDDATA;
 }
 
+if (multi_layer_ext) {
+const RepFormat *rf = &sps->vps->rep_format;
+
+if (get_bits1(gb) &&// update_rep_format_flag
+get_bits(gb, 8)) {  // sps_rep_format_idx
+av_log(avctx, AV_LOG_ERROR, "sps_rep_format_idx!=0\n");
+return AVERROR_PATCHWELCOME;
+}
+
+sps->separate_colour_plane = rf->separate_colour_plane_flag;
+sps->chroma_format_idc = sps->separate_colour_plane ? 0 :
+ rf->chroma_format_idc;
+sps->bit_depth = rf->bit_depth_luma;
+sps->width = rf->pic_width_in_luma_samples;
+sps->height= rf->pic_height_in_luma_samples;
+
+sps->pic_conf_win.left_offset   = rf->conf_win_left_offset;
+sps->pic_conf_win.right_offset  = rf->conf_win_right_offset;
+sps->pic_conf_win.top_offset= rf->conf_win_top_offset;
+  

[FFmpeg-devel] [PATCH 21/42] lavc/hevcdec: move HEVCContext.{tab_mvf, rpl_tab}_pool to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
pic_arrays_{init,free}() no longer access HEVCContext
---
 libavcodec/hevc/hevcdec.c | 24 
 libavcodec/hevc/hevcdec.h |  6 +++---
 libavcodec/hevc/refs.c|  4 ++--
 3 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 2e31928e99..c4e3debae1 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -66,7 +66,7 @@ static const uint8_t hevc_pel_weight[65] = { [2] = 0, [4] = 
1, [6] = 2, [8] = 3,
  */
 
 /* free everything allocated  by pic_arrays_init() */
-static void pic_arrays_free(HEVCContext *s, HEVCLayerContext *l)
+static void pic_arrays_free(HEVCLayerContext *l)
 {
 av_freep(&l->sao);
 av_freep(&l->deblock);
@@ -85,12 +85,12 @@ static void pic_arrays_free(HEVCContext *s, 
HEVCLayerContext *l)
 av_freep(&l->horizontal_bs);
 av_freep(&l->vertical_bs);
 
-ff_refstruct_pool_uninit(&s->tab_mvf_pool);
-ff_refstruct_pool_uninit(&s->rpl_tab_pool);
+ff_refstruct_pool_uninit(&l->tab_mvf_pool);
+ff_refstruct_pool_uninit(&l->rpl_tab_pool);
 }
 
 /* allocate arrays that depend on frame dimensions */
-static int pic_arrays_init(HEVCContext *s, HEVCLayerContext *l, const HEVCSPS 
*sps)
+static int pic_arrays_init(HEVCLayerContext *l, const HEVCSPS *sps)
 {
 int log2_min_cb_size = sps->log2_min_cb_size;
 int width= sps->width;
@@ -132,15 +132,15 @@ static int pic_arrays_init(HEVCContext *s, 
HEVCLayerContext *l, const HEVCSPS *s
 if (!l->horizontal_bs || !l->vertical_bs)
 goto fail;
 
-s->tab_mvf_pool = ff_refstruct_pool_alloc(min_pu_size * sizeof(MvField), 
0);
-s->rpl_tab_pool = ff_refstruct_pool_alloc(ctb_count * 
sizeof(RefPicListTab), 0);
-if (!s->tab_mvf_pool || !s->rpl_tab_pool)
+l->tab_mvf_pool = ff_refstruct_pool_alloc(min_pu_size * sizeof(MvField), 
0);
+l->rpl_tab_pool = ff_refstruct_pool_alloc(ctb_count   * 
sizeof(RefPicListTab), 0);
+if (!l->tab_mvf_pool || !l->rpl_tab_pool)
 goto fail;
 
 return 0;
 
 fail:
-pic_arrays_free(s, l);
+pic_arrays_free(l);
 return AVERROR(ENOMEM);
 }
 
@@ -531,14 +531,14 @@ static int set_sps(HEVCContext *s, HEVCLayerContext *l, 
const HEVCSPS *sps)
 {
 int ret, i;
 
-pic_arrays_free(s, l);
+pic_arrays_free(l);
 s->ps.sps = NULL;
 ff_refstruct_unref(&s->vps);
 
 if (!sps)
 return 0;
 
-ret = pic_arrays_init(s, l, sps);
+ret = pic_arrays_init(l, sps);
 if (ret < 0)
 goto fail;
 
@@ -576,7 +576,7 @@ static int set_sps(HEVCContext *s, HEVCLayerContext *l, 
const HEVCSPS *sps)
 return 0;
 
 fail:
-pic_arrays_free(s, l);
+pic_arrays_free(l);
 for (i = 0; i < 3; i++) {
 av_freep(&s->sao_pixel_buffer_h[i]);
 av_freep(&s->sao_pixel_buffer_v[i]);
@@ -3529,7 +3529,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx)
 int i;
 
 for (int i = 0; i < FF_ARRAY_ELEMS(s->layers); i++)
-pic_arrays_free(s, &s->layers[i]);
+pic_arrays_free(&s->layers[i]);
 
 ff_refstruct_unref(&s->vps);
 ff_refstruct_unref(&s->pps);
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index 426b7968b0..1a43c3662c 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -465,6 +465,9 @@ typedef struct HEVCLayerContext {
 
 uint8_t*horizontal_bs;
 uint8_t*vertical_bs;
+
+struct FFRefStructPool *tab_mvf_pool;
+struct FFRefStructPool *rpl_tab_pool;
 } HEVCLayerContext;
 
 typedef struct HEVCContext {
@@ -489,9 +492,6 @@ typedef struct HEVCContext {
 HEVCSEI sei;
 struct AVMD5 *md5_ctx;
 
-struct FFRefStructPool *tab_mvf_pool;
-struct FFRefStructPool *rpl_tab_pool;
-
 ///< candidate references for the current frame
 RefPicList rps[5];
 
diff --git a/libavcodec/hevc/refs.c b/libavcodec/hevc/refs.c
index 4d123d6d8d..7b8dff4f55 100644
--- a/libavcodec/hevc/refs.c
+++ b/libavcodec/hevc/refs.c
@@ -95,11 +95,11 @@ static HEVCFrame *alloc_frame(HEVCContext *s, 
HEVCLayerContext *l)
 goto fail;
 frame->nb_rpl_elems = s->pkt.nb_nals;
 
-frame->tab_mvf = ff_refstruct_pool_get(s->tab_mvf_pool);
+frame->tab_mvf = ff_refstruct_pool_get(l->tab_mvf_pool);
 if (!frame->tab_mvf)
 goto fail;
 
-frame->rpl_tab = ff_refstruct_pool_get(s->rpl_tab_pool);
+frame->rpl_tab = ff_refstruct_pool_get(l->rpl_tab_pool);
 if (!frame->rpl_tab)
 goto fail;
 frame->ctb_count = s->ps.sps->ctb_width * s->ps.sps->ctb_height;
-- 
2.43.0

___
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 09/42] lavc/hevcdec: move HEVCContext.bs_{width, height} to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
---
 libavcodec/hevc/filter.c  | 43 ---
 libavcodec/hevc/hevcdec.c | 73 ++-
 libavcodec/hevc/hevcdec.h | 14 +---
 3 files changed, 73 insertions(+), 57 deletions(-)

diff --git a/libavcodec/hevc/filter.c b/libavcodec/hevc/filter.c
index 56e354b486..18c73dc2fa 100644
--- a/libavcodec/hevc/filter.c
+++ b/libavcodec/hevc/filter.c
@@ -495,7 +495,7 @@ static int get_pcm(const HEVCSPS *sps, const uint8_t 
*is_pcm, int x, int y)
 (tc_offset & -2),   \
 0, MAX_QP + DEFAULT_INTRA_TC_OFFSET)]
 
-static void deblocking_filter_CTB(const HEVCContext *s,
+static void deblocking_filter_CTB(const HEVCContext *s, const HEVCLayerContext 
*l,
   const HEVCPPS *pps, const HEVCSPS *sps,
   int x0, int y0)
 {
@@ -546,8 +546,8 @@ static void deblocking_filter_CTB(const HEVCContext *s,
 for (y = y0; y < y_end; y += 8) {
 // vertical filtering luma
 for (x = x0 ? x0 : 8; x < x_end; x += 8) {
-const int bs0 = s->vertical_bs[(x +  y  * s->bs_width) >> 2];
-const int bs1 = s->vertical_bs[(x + (y + 4) * s->bs_width) >> 2];
+const int bs0 = s->vertical_bs[(x +  y  * l->bs_width) >> 2];
+const int bs1 = s->vertical_bs[(x + (y + 4) * l->bs_width) >> 2];
 if (bs0 || bs1) {
 const int qp = (get_qPy(sps, s->qp_y_tab, x - 1, y) +
 get_qPy(sps, s->qp_y_tab, x, y) + 1) >> 1;
@@ -575,8 +575,8 @@ static void deblocking_filter_CTB(const HEVCContext *s,
 
 // horizontal filtering luma
 for (x = x0 ? x0 - 8 : 0; x < x_end2; x += 8) {
-const int bs0 = s->horizontal_bs[( x  + y * s->bs_width) >> 2];
-const int bs1 = s->horizontal_bs[((x + 4) + y * s->bs_width) >> 2];
+const int bs0 = s->horizontal_bs[( x  + y * l->bs_width) >> 2];
+const int bs1 = s->horizontal_bs[((x + 4) + y * l->bs_width) >> 2];
 if (bs0 || bs1) {
 const int qp = (get_qPy(sps, s->qp_y_tab, x, y - 1) +
 get_qPy(sps, s->qp_y_tab, x, y) + 1) >> 1;
@@ -610,8 +610,8 @@ static void deblocking_filter_CTB(const HEVCContext *s,
 // vertical filtering chroma
 for (y = y0; y < y_end; y += (8 * v)) {
 for (x = x0 ? x0 : 8 * h; x < x_end; x += (8 * h)) {
-const int bs0 = s->vertical_bs[(x +  y* 
s->bs_width) >> 2];
-const int bs1 = s->vertical_bs[(x + (y + (4 * v)) * 
s->bs_width) >> 2];
+const int bs0 = s->vertical_bs[(x +  y* 
l->bs_width) >> 2];
+const int bs1 = s->vertical_bs[(x + (y + (4 * v)) * 
l->bs_width) >> 2];
 
 if ((bs0 == 2) || (bs1 == 2)) {
 const int qp0 = (get_qPy(sps, s->qp_y_tab, x - 1, y) +
@@ -644,8 +644,8 @@ static void deblocking_filter_CTB(const HEVCContext *s,
 if (x_end != sps->width)
 x_end2 = x_end - 8 * h;
 for (x = x0 ? x0 - 8 * h : 0; x < x_end2; x += (8 * h)) {
-const int bs0 = s->horizontal_bs[( x  + y * 
s->bs_width) >> 2];
-const int bs1 = s->horizontal_bs[((x + 4 * h) + y * 
s->bs_width) >> 2];
+const int bs0 = s->horizontal_bs[( x  + y * 
l->bs_width) >> 2];
+const int bs1 = s->horizontal_bs[((x + 4 * h) + y * 
l->bs_width) >> 2];
 if ((bs0 == 2) || (bs1 == 2)) {
 const int qp0 = bs0 == 2 ? (get_qPy(sps, s->qp_y_tab, 
x,   y - 1) +
 get_qPy(sps, s->qp_y_tab, 
x,   y) + 1) >> 1 : 0;
@@ -736,7 +736,8 @@ static int boundary_strength(const HEVCContext *s, const 
MvField *curr, const Mv
 return 1;
 }
 
-void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext *lc, const HEVCPPS 
*pps,
+void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext *lc, const 
HEVCLayerContext *l,
+   const HEVCPPS *pps,
int x0, int y0, int log2_trafo_size)
 {
 const HEVCSPS *const sps = pps->sps;
@@ -784,7 +785,7 @@ void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext 
*lc, const HEVCPPS *
 bs = 1;
 else
 bs = boundary_strength(s, curr, top, rpl_top);
-s->horizontal_bs[((x0 + i) + y0 * s->bs_width) >> 2] = bs;
+s->horizontal_bs[((x0 + i) + y0 * l->bs_width) >> 2] = bs;
 }
 }
 
@@ -822,7 +823,7 @@ void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext 
*lc, const HEVCPPS *
 bs = 1;
 else
 bs = boundary_strength(s, 

[FFmpeg-devel] [PATCH 13/42] lavc/hevcdec: move HEVCContext.tab_ct_depth to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
---
 libavcodec/hevc/cabac.c   |  8 
 libavcodec/hevc/hevcdec.c | 11 ++-
 libavcodec/hevc/hevcdec.h |  6 +++---
 3 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/libavcodec/hevc/cabac.c b/libavcodec/hevc/cabac.c
index 12d477b2bd..892dd1c215 100644
--- a/libavcodec/hevc/cabac.c
+++ b/libavcodec/hevc/cabac.c
@@ -636,10 +636,10 @@ int ff_hevc_pred_mode_decode(HEVCLocalContext *lc)
 return GET_CABAC(PRED_MODE_FLAG_OFFSET);
 }
 
-int ff_hevc_split_coding_unit_flag_decode(HEVCLocalContext *lc, const HEVCSPS 
*sps,
+int ff_hevc_split_coding_unit_flag_decode(HEVCLocalContext *lc, uint8_t 
*tab_ct_depth,
+  const HEVCSPS *sps,
   int ct_depth, int x0, int y0)
 {
-const HEVCContext *const s = lc->parent;
 int inc = 0, depth_left = 0, depth_top = 0;
 int x0b  = av_zero_extend(x0, sps->log2_ctb_size);
 int y0b  = av_zero_extend(y0, sps->log2_ctb_size);
@@ -647,9 +647,9 @@ int ff_hevc_split_coding_unit_flag_decode(HEVCLocalContext 
*lc, const HEVCSPS *s
 int y_cb = y0 >> sps->log2_min_cb_size;
 
 if (lc->ctb_left_flag || x0b)
-depth_left = s->tab_ct_depth[(y_cb) * sps->min_cb_width + x_cb - 
1];
+depth_left = tab_ct_depth[(y_cb) * sps->min_cb_width + x_cb - 1];
 if (lc->ctb_up_flag || y0b)
-depth_top  = s->tab_ct_depth[(y_cb - 1) * sps->min_cb_width + x_cb];
+depth_top  = tab_ct_depth[(y_cb - 1) * sps->min_cb_width + x_cb];
 
 inc += (depth_left > ct_depth);
 inc += (depth_top  > ct_depth);
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 2e620d8c4a..8f0f761ee5 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -72,7 +72,7 @@ static void pic_arrays_free(HEVCContext *s, HEVCLayerContext 
*l)
 av_freep(&l->deblock);
 
 av_freep(&l->skip_flag);
-av_freep(&s->tab_ct_depth);
+av_freep(&l->tab_ct_depth);
 
 av_freep(&s->tab_ipm);
 av_freep(&s->cbf_luma);
@@ -109,8 +109,8 @@ static int pic_arrays_init(HEVCContext *s, HEVCLayerContext 
*l, const HEVCSPS *s
 goto fail;
 
 l->skip_flag= av_malloc_array(sps->min_cb_height, sps->min_cb_width);
-s->tab_ct_depth = av_malloc_array(sps->min_cb_height, sps->min_cb_width);
-if (!l->skip_flag || !s->tab_ct_depth)
+l->tab_ct_depth = av_malloc_array(sps->min_cb_height, sps->min_cb_width);
+if (!l->skip_flag || !l->tab_ct_depth)
 goto fail;
 
 s->cbf_luma = av_malloc_array(sps->min_tb_width, sps->min_tb_height);
@@ -2383,7 +2383,7 @@ static int hls_coding_unit(HEVCLocalContext *lc, const 
HEVCContext *s,
 lc->qPy_pred = lc->qp_y;
 }
 
-set_ct_depth(sps, s->tab_ct_depth, x0, y0, log2_cb_size, lc->ct_depth);
+set_ct_depth(sps, l->tab_ct_depth, x0, y0, log2_cb_size, lc->ct_depth);
 
 return 0;
 }
@@ -2403,7 +2403,8 @@ static int hls_coding_quadtree(HEVCLocalContext *lc,
 if (x0 + cb_size <= sps->width  &&
 y0 + cb_size <= sps->height &&
 log2_cb_size > sps->log2_min_cb_size) {
-split_cu = ff_hevc_split_coding_unit_flag_decode(lc, sps, cb_depth, 
x0, y0);
+split_cu = ff_hevc_split_coding_unit_flag_decode(lc, l->tab_ct_depth,
+ sps, cb_depth, x0, 
y0);
 } else {
 split_cu = (log2_cb_size > sps->log2_min_cb_size);
 }
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index 1d8b6daf8b..59c8587787 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -449,6 +449,7 @@ typedef struct HEVCLayerContext {
 
 //  CU
 uint8_t*skip_flag;
+uint8_t*tab_ct_depth;
 } HEVCLayerContext;
 
 typedef struct HEVCContext {
@@ -506,8 +507,6 @@ typedef struct HEVCContext {
 
 int32_t *tab_slice_address;
 
-//  CU
-uint8_t *tab_ct_depth;
 // PU
 uint8_t *tab_ipm;
 
@@ -584,7 +583,8 @@ int 
ff_hevc_cu_transquant_bypass_flag_decode(HEVCLocalContext *lc);
 int ff_hevc_skip_flag_decode(HEVCLocalContext *lc, uint8_t *skip_flag,
  int x0, int y0, int x_cb, int y_cb, int 
min_cb_width);
 int ff_hevc_pred_mode_decode(HEVCLocalContext *lc);
-int ff_hevc_split_coding_unit_flag_decode(HEVCLocalContext *lc, const HEVCSPS 
*sps,
+int ff_hevc_split_coding_unit_flag_decode(HEVCLocalContext *lc, uint8_t 
*tab_ct_depth,
+  const HEVCSPS *sps,
   int ct_depth, int x0, int y0);
 int ff_hevc_part_mode_decode(HEVCLocalContext *lc, const HEVCSPS *sps, int 
log2_cb_size);
 int ff_hevc_pcm_flag_decode(HEVCLocalContext *lc);
-- 
2.43.0

___
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 25/42] avcodec/hevc/sei: add support for 3D Reference Displays Information SEI

2024-08-27 Thread Anton Khirnov
From: James Almer 

Signed-off-by: James Almer 
---
 libavcodec/hevc/sei.c | 55 +++
 libavcodec/hevc/sei.h | 17 +
 2 files changed, 72 insertions(+)

diff --git a/libavcodec/hevc/sei.c b/libavcodec/hevc/sei.c
index e39ac0c38a..6c2b55b43c 100644
--- a/libavcodec/hevc/sei.c
+++ b/libavcodec/hevc/sei.c
@@ -150,6 +150,59 @@ static int decode_nal_sei_timecode(HEVCSEITimeCode *s, 
GetBitContext *gb)
 return 0;
 }
 
+static int decode_nal_sei_3d_reference_displays_info(HEVCSEITDRDI *s, 
GetBitContext *gb)
+{
+s->prec_ref_display_width = get_ue_golomb(gb);
+if (s->prec_ref_display_width > 31)
+return AVERROR_INVALIDDATA;
+s->ref_viewing_distance_flag = get_bits1(gb);
+if (s->ref_viewing_distance_flag) {
+s->prec_ref_viewing_dist = get_ue_golomb(gb);
+if (s->prec_ref_viewing_dist > 31)
+return AVERROR_INVALIDDATA;
+}
+s->num_ref_displays = get_ue_golomb(gb);
+if (s->num_ref_displays > 31)
+return AVERROR_INVALIDDATA;
+s->num_ref_displays += 1;
+
+for (int i = 0; i < s->num_ref_displays; i++) {
+int length;
+s->left_view_id[i] = get_ue_golomb(gb);
+s->right_view_id[i] = get_ue_golomb(gb);
+s->exponent_ref_display_width[i] = get_bits(gb, 6);
+if (s->exponent_ref_display_width[i] > 62)
+return AVERROR_INVALIDDATA;
+else if (!s->exponent_ref_display_width[i])
+length = FFMAX(0, (int)s->prec_ref_display_width - 30);
+else
+length = FFMAX(0, (int)s->exponent_ref_display_width[i] +
+  (int)s->prec_ref_display_width - 31);
+s->mantissa_ref_display_width[i] = get_bits_long(gb, length);
+if (s->ref_viewing_distance_flag) {
+s->exponent_ref_viewing_distance[i] = get_bits(gb, 6);
+if (s->exponent_ref_viewing_distance[i] > 62)
+return AVERROR_INVALIDDATA;
+else if (!s->exponent_ref_viewing_distance[i])
+length = FFMAX(0, (int)s->prec_ref_viewing_dist - 30);
+else
+length = FFMAX(0, (int)s->exponent_ref_viewing_distance[i] +
+  (int)s->prec_ref_viewing_dist - 31);
+s->mantissa_ref_viewing_distance[i] = get_bits_long(gb, length);
+}
+s->additional_shift_present_flag[i] = get_bits1(gb);
+if (s->additional_shift_present_flag[i]) {
+s->num_sample_shift[i] = get_bits(gb, 10);
+if (s->num_sample_shift[i] > 1023)
+return AVERROR_INVALIDDATA;
+s->num_sample_shift[i] -= 512;
+}
+}
+s->three_dimensional_reference_displays_extension_flag = get_bits1(gb);
+
+return 0;
+}
+
 static int decode_nal_sei_prefix(GetBitContext *gb, GetByteContext *gbyte,
  void *logctx, HEVCSEI *s,
  const HEVCParamSets *ps, int type)
@@ -163,6 +216,8 @@ static int decode_nal_sei_prefix(GetBitContext *gb, 
GetByteContext *gbyte,
 return decode_nal_sei_active_parameter_sets(s, gb, logctx);
 case SEI_TYPE_TIME_CODE:
 return decode_nal_sei_timecode(&s->timecode, gb);
+case SEI_TYPE_THREE_DIMENSIONAL_REFERENCE_DISPLAYS_INFO:
+return decode_nal_sei_3d_reference_displays_info(&s->tdrdi, gb);
 default: {
 int ret = ff_h2645_sei_message_decode(&s->common, type, 
AV_CODEC_ID_HEVC,
   gb, gbyte, logctx);
diff --git a/libavcodec/hevc/sei.h b/libavcodec/hevc/sei.h
index c97d22d423..a233d432cc 100644
--- a/libavcodec/hevc/sei.h
+++ b/libavcodec/hevc/sei.h
@@ -79,12 +79,29 @@ typedef struct HEVCSEITimeCode {
 int32_t  time_offset_value[3];
 } HEVCSEITimeCode;
 
+typedef struct HEVCSEITDRDI {
+uint8_t prec_ref_display_width;
+uint8_t ref_viewing_distance_flag;
+uint8_t prec_ref_viewing_dist;
+uint8_t num_ref_displays;
+uint8_t left_view_id[31];
+uint8_t right_view_id[31];
+uint8_t exponent_ref_display_width[31];
+uint8_t mantissa_ref_display_width[31];
+uint8_t exponent_ref_viewing_distance[31];
+uint8_t mantissa_ref_viewing_distance[31];
+uint8_t additional_shift_present_flag[31];
+int16_t num_sample_shift[31];
+uint8_t three_dimensional_reference_displays_extension_flag;
+} HEVCSEITDRDI;
+
 typedef struct HEVCSEI {
 H2645SEI common;
 HEVCSEIPictureHash picture_hash;
 HEVCSEIPictureTiming picture_timing;
 int active_seq_parameter_set_id;
 HEVCSEITimeCode timecode;
+HEVCSEITDRDI tdrdi;
 } HEVCSEI;
 
 struct HEVCParamSets;
-- 
2.43.0

___
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 06/42] lavc: add HEVC Multiview Main profile

2024-08-27 Thread Anton Khirnov
---
 doc/APIchanges|  3 +++
 libavcodec/defs.h |  1 +
 libavcodec/hevc/ps.c  | 21 +
 libavcodec/profiles.c |  1 +
 libavcodec/version.h  |  2 +-
 5 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index a8f84ca45f..a4cf1bf69f 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07
 
 API changes, most recent first:
 
+2024-xx-xx - xxx - lavc 61.12.100 - defs.h
+  Add AV_PROFILE_HEVC_MULTIVIEW_MAIN
+
 2024-xx-xx - xxx - lavu 59.37.100 - frame.h
   Add AV_FRAME_DATA_VIEW_ID.
 
diff --git a/libavcodec/defs.h b/libavcodec/defs.h
index 7ddfdcad0b..24250f8af5 100644
--- a/libavcodec/defs.h
+++ b/libavcodec/defs.h
@@ -160,6 +160,7 @@
 #define AV_PROFILE_HEVC_MAIN_10 2
 #define AV_PROFILE_HEVC_MAIN_STILL_PICTURE  3
 #define AV_PROFILE_HEVC_REXT4
+#define AV_PROFILE_HEVC_MULTIVIEW_MAIN  6
 #define AV_PROFILE_HEVC_SCC 9
 
 #define AV_PROFILE_VVC_MAIN_10  1
diff --git a/libavcodec/hevc/ps.c b/libavcodec/hevc/ps.c
index 22042d3e62..dbdfc16cfa 100644
--- a/libavcodec/hevc/ps.c
+++ b/libavcodec/hevc/ps.c
@@ -29,6 +29,7 @@
 #include "h2645_vui.h"
 #include "data.h"
 #include "ps.h"
+#include "profiles.h"
 #include "refstruct.h"
 
 static const uint8_t default_scaling_list_intra[] = {
@@ -244,6 +245,7 @@ int ff_hevc_decode_short_term_rps(GetBitContext *gb, 
AVCodecContext *avctx,
 static int decode_profile_tier_level(GetBitContext *gb, AVCodecContext *avctx,
   PTLCommon *ptl)
 {
+const char *profile_name = NULL;
 int i;
 
 if (get_bits_left(gb) < 2+1+5 + 32 + 4 + 43 + 1)
@@ -252,18 +254,13 @@ static int decode_profile_tier_level(GetBitContext *gb, 
AVCodecContext *avctx,
 ptl->profile_space = get_bits(gb, 2);
 ptl->tier_flag = get_bits1(gb);
 ptl->profile_idc   = get_bits(gb, 5);
-if (ptl->profile_idc == AV_PROFILE_HEVC_MAIN)
-av_log(avctx, AV_LOG_DEBUG, "Main profile bitstream\n");
-else if (ptl->profile_idc == AV_PROFILE_HEVC_MAIN_10)
-av_log(avctx, AV_LOG_DEBUG, "Main 10 profile bitstream\n");
-else if (ptl->profile_idc == AV_PROFILE_HEVC_MAIN_STILL_PICTURE)
-av_log(avctx, AV_LOG_DEBUG, "Main Still Picture profile bitstream\n");
-else if (ptl->profile_idc == AV_PROFILE_HEVC_REXT)
-av_log(avctx, AV_LOG_DEBUG, "Range Extension profile bitstream\n");
-else if (ptl->profile_idc == AV_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);
+for (int i = 0; ff_hevc_profiles[i].profile != AV_PROFILE_UNKNOWN; i++)
+if (ff_hevc_profiles[i].profile == ptl->profile_idc) {
+profile_name = ff_hevc_profiles[i].name;
+break;
+}
+av_log(avctx, profile_name ? AV_LOG_DEBUG : AV_LOG_WARNING,
+   "%s profile bitstream\n", profile_name ? profile_name : "Unknown");
 
 for (i = 0; i < 32; i++) {
 ptl->profile_compatibility_flag[i] = get_bits1(gb);
diff --git a/libavcodec/profiles.c b/libavcodec/profiles.c
index 44bdf6f85b..3cef82be3b 100644
--- a/libavcodec/profiles.c
+++ b/libavcodec/profiles.c
@@ -99,6 +99,7 @@ const AVProfile ff_hevc_profiles[] = {
 { AV_PROFILE_HEVC_MAIN_10,  "Main 10" },
 { AV_PROFILE_HEVC_MAIN_STILL_PICTURE,   "Main Still Picture"  },
 { AV_PROFILE_HEVC_REXT, "Rext"},
+{ AV_PROFILE_HEVC_MULTIVIEW_MAIN,   "Multiview Main"  },
 { AV_PROFILE_HEVC_SCC,  "Scc" },
 { AV_PROFILE_UNKNOWN },
 };
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 8b53586be1..da2264a097 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, \
-- 
2.43.0

___
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 12/42] lavc/hevcdec: move HEVCContext.skip_flag to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
---
 libavcodec/hevc/cabac.c   |  9 +++
 libavcodec/hevc/hevcdec.c | 56 ---
 libavcodec/hevc/hevcdec.h |  8 +++---
 3 files changed, 38 insertions(+), 35 deletions(-)

diff --git a/libavcodec/hevc/cabac.c b/libavcodec/hevc/cabac.c
index 33f8241bb3..12d477b2bd 100644
--- a/libavcodec/hevc/cabac.c
+++ b/libavcodec/hevc/cabac.c
@@ -570,16 +570,15 @@ int 
ff_hevc_cu_transquant_bypass_flag_decode(HEVCLocalContext *lc)
 return GET_CABAC(CU_TRANSQUANT_BYPASS_FLAG_OFFSET);
 }
 
-int ff_hevc_skip_flag_decode(HEVCLocalContext *lc, int x0, int y0,
- int x_cb, int y_cb, int min_cb_width)
+int ff_hevc_skip_flag_decode(HEVCLocalContext *lc, uint8_t *skip_flag,
+ int x0, int y0, int x_cb, int y_cb, int 
min_cb_width)
 {
-const HEVCContext *const s = lc->parent;
 int inc = 0;
 
 if (lc->ctb_left_flag || x0)
-inc = !!SAMPLE_CTB(s->skip_flag, x_cb - 1, y_cb);
+inc = !!SAMPLE_CTB(skip_flag, x_cb - 1, y_cb);
 if (lc->ctb_up_flag || y0)
-inc += !!SAMPLE_CTB(s->skip_flag, x_cb, y_cb - 1);
+inc += !!SAMPLE_CTB(skip_flag, x_cb, y_cb - 1);
 
 return GET_CABAC(SKIP_FLAG_OFFSET + inc);
 }
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index a20e559353..2e620d8c4a 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -71,7 +71,7 @@ static void pic_arrays_free(HEVCContext *s, HEVCLayerContext 
*l)
 av_freep(&l->sao);
 av_freep(&l->deblock);
 
-av_freep(&s->skip_flag);
+av_freep(&l->skip_flag);
 av_freep(&s->tab_ct_depth);
 
 av_freep(&s->tab_ipm);
@@ -108,9 +108,9 @@ static int pic_arrays_init(HEVCContext *s, HEVCLayerContext 
*l, const HEVCSPS *s
 if (!l->sao || !l->deblock)
 goto fail;
 
-s->skip_flag= av_malloc_array(sps->min_cb_height, sps->min_cb_width);
+l->skip_flag= av_malloc_array(sps->min_cb_height, sps->min_cb_width);
 s->tab_ct_depth = av_malloc_array(sps->min_cb_height, sps->min_cb_width);
-if (!s->skip_flag || !s->tab_ct_depth)
+if (!l->skip_flag || !s->tab_ct_depth)
 goto fail;
 
 s->cbf_luma = av_malloc_array(sps->min_tb_width, sps->min_tb_height);
@@ -1882,6 +1882,7 @@ static void hevc_luma_mv_mvp_mode(HEVCLocalContext *lc,
 }
 
 static void hls_prediction_unit(HEVCLocalContext *lc,
+const HEVCLayerContext *l,
 const HEVCPPS *pps, const HEVCSPS *sps,
 int x0, int y0, int nPbW, int nPbH,
 int log2_cb_size, int partIdx, int idx)
@@ -1909,7 +1910,7 @@ static void hls_prediction_unit(HEVCLocalContext *lc,
 int x_pu, y_pu;
 int i, j;
 
-int skip_flag = SAMPLE_CTB(s->skip_flag, x_cb, y_cb);
+int skip_flag = SAMPLE_CTB(l->skip_flag, x_cb, y_cb);
 
 if (!skip_flag)
 lc->pu.merge_flag = ff_hevc_merge_flag_decode(lc);
@@ -2221,7 +,7 @@ static int hls_coding_unit(HEVCLocalContext *lc, const 
HEVCContext *s,
 lc->cu.part_mode= PART_2Nx2N;
 lc->cu.intra_split_flag = 0;
 
-SAMPLE_CTB(s->skip_flag, x_cb, y_cb) = 0;
+SAMPLE_CTB(l->skip_flag, x_cb, y_cb) = 0;
 for (x = 0; x < 4; x++)
 lc->pu.intra_pred_mode[x] = 1;
 if (pps->transquant_bypass_enable_flag) {
@@ -2234,25 +2235,26 @@ static int hls_coding_unit(HEVCLocalContext *lc, const 
HEVCContext *s,
 if (s->sh.slice_type != HEVC_SLICE_I) {
 const int x0b = av_zero_extend(x0, sps->log2_ctb_size);
 const int y0b = av_zero_extend(y0, sps->log2_ctb_size);
-uint8_t skip_flag = ff_hevc_skip_flag_decode(lc, x0b, y0b, x_cb, y_cb,
+uint8_t skip_flag = ff_hevc_skip_flag_decode(lc, l->skip_flag,
+ x0b, y0b, x_cb, y_cb,
  min_cb_width);
 
 x = y_cb * min_cb_width + x_cb;
 for (y = 0; y < length; y++) {
-memset(&s->skip_flag[x], skip_flag, length);
+memset(&l->skip_flag[x], skip_flag, length);
 x += min_cb_width;
 }
 lc->cu.pred_mode = skip_flag ? MODE_SKIP : MODE_INTER;
 } else {
 x = y_cb * min_cb_width + x_cb;
 for (y = 0; y < length; y++) {
-memset(&s->skip_flag[x], 0, length);
+memset(&l->skip_flag[x], 0, length);
 x += min_cb_width;
 }
 }
 
-if (SAMPLE_CTB(s->skip_flag, x_cb, y_cb)) {
-hls_prediction_unit(lc, pps, sps,
+if (SAMPLE_CTB(l->skip_flag, x_cb, y_cb)) {
+hls_prediction_unit(lc, l, pps, sps,
 x0, y0, cb_size, cb_size, log2_cb_size, 0, idx);
 intra_prediction_unit_default_value(lc, sps, x0, y0, log2_cb_size);
 
@@ -2291,53 +2293,53 @@ static int hls_coding_unit(HEVCLocalContext *lc, const 
HEVCContext *s,
 intra_prediction_unit_default_value(lc, sps, x0, y0, log2_cb_size);

[FFmpeg-devel] [PATCH 30/42] lavc/hevcdec/parse: process NALUs with nuh_layer_id>0

2024-08-27 Thread Anton Khirnov
Otherwise parameter sets from extradata with nuh_layer_id>0 would be
ignored. Needed for upcoming MV-HEVC support.
---
 libavcodec/hevc/parse.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/libavcodec/hevc/parse.c b/libavcodec/hevc/parse.c
index ad84b7b152..29f21a5966 100644
--- a/libavcodec/hevc/parse.c
+++ b/libavcodec/hevc/parse.c
@@ -38,9 +38,6 @@ static int hevc_decode_nal_units(const uint8_t *buf, int 
buf_size, HEVCParamSets
 
 for (i = 0; i < pkt.nb_nals; i++) {
 H2645NAL *nal = &pkt.nals[i];
-if (nal->nuh_layer_id > 0)
-continue;
-
 /* ignore everything except parameter sets and VCL NALUs */
 switch (nal->type) {
 case HEVC_NAL_VPS:
-- 
2.43.0

___
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 42/42] tests/fate/hevc: add a test for switching between single and multi-view

2024-08-27 Thread Anton Khirnov
---
 tests/fate/hevc.mak   |  10 ++
 tests/ref/fate/hevc-mv-switch | 172 ++
 2 files changed, 182 insertions(+)
 create mode 100644 tests/ref/fate/hevc-mv-switch

diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak
index e75fbd3c16..5631ded860 100644
--- a/tests/fate/hevc.mak
+++ b/tests/fate/hevc.mak
@@ -273,6 +273,16 @@ FATE_HEVC-$(call FRAMECRC, HEVC, HEVC, HEVC_PARSER 
SCALE_FILTER) += fate-hevc-sm
 fate-hevc-mv-nuh-layer-id: CMD = framecrc -i 
$(TARGET_SAMPLES)/hevc/mv_nuh_layer_id.bit -map 0:view:all
 FATE_HEVC-$(call FRAMECRC, HEVC, HEVC) += fate-hevc-mv-nuh-layer-id
 
+# NB: $\ at the end of line joins lines without adding whitespace;
+# this trick is recommended by GNU make manual
+fate-hevc-mv-switch: INPUT = \
+$(TARGET_SAMPLES)/hevc-conformance/LS_A_Orange_2.bit|$\
+$(TARGET_SAMPLES)/hevc/mv_nuh_layer_id.bit|$\
+$(TARGET_SAMPLES)/hevc-conformance/NoOutPrior_B_Qualcomm_1.bit|$\
+$(TARGET_SAMPLES)/hevc-conformance/MVHEVCS_A.bit
+fate-hevc-mv-switch: CMD = framecrc -i "concat:$(INPUT)" -fps_mode passthrough 
-map 0:vidx:0 -map 0:vidx:1
+FATE_HEVC-$(call FRAMECRC, HEVC, HEVC, CONCAT_PROTOCOL) += fate-hevc-mv-switch
+
 FATE_SAMPLES_AVCONV += $(FATE_HEVC-yes)
 FATE_SAMPLES_FFPROBE += $(FATE_HEVC_FFPROBE-yes)
 
diff --git a/tests/ref/fate/hevc-mv-switch b/tests/ref/fate/hevc-mv-switch
new file mode 100644
index 00..0fc3630637
--- /dev/null
+++ b/tests/ref/fate/hevc-mv-switch
@@ -0,0 +1,172 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
+#tb 1: 1/25
+#media_type 1: video
+#codec_id 1: rawvideo
+#dimensions 1: 128x128
+#sar 1: 0/1
+0,  0,  0,1,   149760, 0x94a51701
+0,  1,  1,1,   149760, 0x67c71885
+0,  2,  2,1,   149760, 0x218f1751
+0,  3,  3,1,   149760, 0x56951bef
+0,  4,  4,1,   149760, 0x76aec81e
+0,  5,  5,1,   149760, 0x20df61ac
+0,  6,  6,1,   149760, 0x2eacf616
+0,  7,  7,1,   149760, 0x06322ce2
+0,  8,  8,1,   149760, 0xf14aa104
+0,  9,  9,1,   149760, 0xc948dcba
+1, 10, 10,1,24576, 0xf8f638da
+0, 11, 11,1,   149760, 0x674e34b1
+1, 12, 12,1,24576, 0xd22675a4
+0, 13, 13,1,   149760, 0x41d3acd6
+1, 14, 14,1,24576, 0x60da42e6
+0, 15, 15,1,   149760, 0x55a5b835
+1, 16, 16,1,24576, 0xe0577f6e
+0, 17, 17,1,   149760, 0xc6958049
+1, 18, 18,1,24576, 0x8d9944bd
+0, 19, 19,1,   149760, 0x94b37050
+0, 20, 20,1,   149760, 0xed72a560
+0, 21, 21,1,   149760, 0xd0ccac61
+0, 22, 22,1,   149760, 0x6cc2d7fa
+0, 23, 23,1,   149760, 0x3a02b5ba
+0, 24, 24,1,   149760, 0xce7ef09c
+0, 25, 25,1,   149760, 0xa518fc05
+0, 26, 26,1,   149760, 0x01d238fe
+0, 27, 27,1,   149760, 0x5f5012fa
+0, 28, 28,1,   149760, 0x5b8e7405
+0, 29, 29,1,   149760, 0xcc2e5b33
+0, 30, 30,1,   149760, 0x590a6890
+0, 31, 31,1,   149760, 0x9c7b189f
+0, 32, 32,1,   149760, 0xd0752ef4
+0, 33, 33,1,   149760, 0x367513ce
+0, 34, 34,1,   149760, 0xb64c209d
+0, 35, 35,1,   149760, 0x6e50994c
+0, 36, 36,1,   149760, 0x8276cce4
+0, 37, 37,1,   149760, 0xb292ac8f
+0, 38, 38,1,   149760, 0x57de9d2c
+0, 39, 39,1,   149760, 0xe8533f38
+0, 40, 40,1,   149760, 0xde9b536d
+0, 41, 41,1,   149760, 0x83173b1d
+0, 42, 42,1,   149760, 0x853a83a4
+0, 43, 43,1,   149760, 0x481af1bf
+0, 44, 44,1,   149760, 0x27221abb
+0, 45, 45,1,   149760, 0x094eac00
+0, 46, 46,1,   149760, 0x3f3a27c8
+0, 47, 47,1,   149760, 0x8f19b2af
+0, 48, 48,1,   149760, 0x93e7e591
+0, 49, 49,1,   149760, 0x0c531ab8
+0, 50, 50,1,   149760, 0x3456ef8a
+0, 51, 51,1,   149760, 0xfee2ec1e
+0, 52, 52,1,   149760, 0x76b4b750
+0, 53, 53,1,   149760, 0xa48bb670
+0, 54, 54,1,   149760, 0x3dee7cac
+0, 55, 55,1,   149760, 0x2b20561d
+0, 56, 56,  

[FFmpeg-devel] [PATCH 36/42] fftools/cmdutils: tighten condition for media type stream specifiers

2024-08-27 Thread Anton Khirnov
Require the character indicating media type to be followed by a
non-alphanumeric character (or end of string).

Needed by future syntax extensions.
---
 fftools/cmdutils.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c
index f725c31c12..8909572ea3 100644
--- a/fftools/cmdutils.c
+++ b/fftools/cmdutils.c
@@ -988,6 +988,12 @@ FILE *get_preset_file(char *filename, size_t filename_size,
 return f;
 }
 
+static int cmdutils_isalnum(char c)
+{
+return (c >= '0' && c <= '9') ||
+   (c >= 'A' && c <= 'Z') ||
+   (c >= 'a' && c <= 'z');
+}
 
 void stream_specifier_uninit(StreamSpecifier *ss)
 {
@@ -1024,8 +1030,9 @@ int stream_specifier_parse(StreamSpecifier *ss, const 
char *spec,
 
 // this terminates the specifier
 break;
-} else if (*spec == 'v' || *spec == 'a' || *spec == 's' || *spec == 
'd' ||
-   *spec == 't' || *spec == 'V') { /* opt:[vasdtV] */
+} else if ((*spec == 'v' || *spec == 'a' || *spec == 's' ||
+*spec == 'd' || *spec == 't' || *spec == 'V') &&
+   !cmdutils_isalnum(*(spec + 1))) { /* opt:[vasdtV] */
 if (ss->media_type != AVMEDIA_TYPE_UNKNOWN) {
 av_log(logctx, AV_LOG_ERROR, "Stream type specified multiple 
times\n");
 ret = AVERROR(EINVAL);
-- 
2.43.0

___
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 29/42] lavc/hevc/ps: reindent

2024-08-27 Thread Anton Khirnov
---
 libavcodec/hevc/ps.c | 178 +--
 1 file changed, 89 insertions(+), 89 deletions(-)

diff --git a/libavcodec/hevc/ps.c b/libavcodec/hevc/ps.c
index 0b34dd10a8..5aebd66ba7 100644
--- a/libavcodec/hevc/ps.c
+++ b/libavcodec/hevc/ps.c
@@ -1182,10 +1182,10 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, 
unsigned int *sps_id,
 }
 
 if (!multi_layer_ext) {
-sps->temporal_id_nesting = get_bits(gb, 1);
+sps->temporal_id_nesting = get_bits(gb, 1);
 
-if ((ret = parse_ptl(gb, avctx, 1, &sps->ptl, sps->max_sub_layers)) < 0)
-return ret;
+if ((ret = parse_ptl(gb, avctx, 1, &sps->ptl, sps->max_sub_layers)) < 
0)
+return ret;
 }
 
 *sps_id = get_ue_golomb_long(gb);
@@ -1216,69 +1216,69 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, 
unsigned int *sps_id,
 sps->pic_conf_win.bottom_offset = rf->conf_win_bottom_offset;
 
 } else {
-sps->chroma_format_idc = get_ue_golomb_long(gb);
-if (sps->chroma_format_idc > 3U) {
-av_log(avctx, AV_LOG_ERROR, "chroma_format_idc %d is invalid\n", 
sps->chroma_format_idc);
-return AVERROR_INVALIDDATA;
-}
-
-if (sps->chroma_format_idc == 3)
-sps->separate_colour_plane = get_bits1(gb);
-
-if (sps->separate_colour_plane)
-sps->chroma_format_idc = 0;
-
-sps->width  = get_ue_golomb_long(gb);
-sps->height = get_ue_golomb_long(gb);
-if ((ret = av_image_check_size(sps->width,
-   sps->height, 0, avctx)) < 0)
-return ret;
-
-sps->conformance_window = get_bits1(gb);
-if (sps->conformance_window) {
-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;
-sps->pic_conf_win.right_offset  = get_ue_golomb_long(gb) * horiz_mult;
-sps->pic_conf_win.top_offset= get_ue_golomb_long(gb) *  vert_mult;
-sps->pic_conf_win.bottom_offset = get_ue_golomb_long(gb) *  vert_mult;
-
-if (avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) {
-av_log(avctx, AV_LOG_DEBUG,
-   "discarding sps conformance window, "
-   "original values are l:%u r:%u t:%u b:%u\n",
-   sps->pic_conf_win.left_offset,
-   sps->pic_conf_win.right_offset,
-   sps->pic_conf_win.top_offset,
-   sps->pic_conf_win.bottom_offset);
-
-sps->pic_conf_win.left_offset   =
-sps->pic_conf_win.right_offset  =
-sps->pic_conf_win.top_offset=
-sps->pic_conf_win.bottom_offset = 0;
+sps->chroma_format_idc = get_ue_golomb_long(gb);
+if (sps->chroma_format_idc > 3U) {
+av_log(avctx, AV_LOG_ERROR, "chroma_format_idc %d is invalid\n", 
sps->chroma_format_idc);
+return AVERROR_INVALIDDATA;
 }
-}
 
-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), "
-   "this is unsupported.\n",
-   sps->bit_depth, bit_depth_chroma);
-return AVERROR_INVALIDDATA;
-}
-sps->bit_depth_chroma = bit_depth_chroma;
+if (sps->chroma_format_idc == 3)
+sps->separate_colour_plane = get_bits1(gb);
+
+if (sps->separate_colour_plane)
+sps->chroma_format_idc = 0;
+
+sps->width  = get_ue_golomb_long(gb);
+sps->height = get_ue_golomb_long(gb);
+if ((ret = av_image_check_size(sps->width,
+   sps->height, 0, avctx)) < 0)
+return ret;
+
+sps->conformance_window = get_bits1(gb);
+if (sps->conformance_window) {
+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;
+sps->pic_conf_win.right_offset  = get_ue_golomb_long(gb) * 
horiz_mult;
+sps->pic_conf_win.top_offset= get_ue_golomb_long(gb) *  
vert_mult;
+sps->pic_conf_win.bottom_offset = get_ue_golomb_long(gb) *  
vert_mult;
+
+if (avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) {
+av_log(avctx, AV_LOG_DEBUG,
+ 

[FFmpeg-devel] [PATCH 40/42] tests/fate/hevc: add MV-HEVC conformance sample tests

2024-08-27 Thread Anton Khirnov
Only those that can be decoded with our implementation, so excluding
* C and D - independent layers
* G, H, I - more than 2 layers

Frame hashes verified against the reference implementation from
https://hevc.hhi.fraunhofer.de/svn/svn_3DVCSoftware/
---
 tests/fate/hevc.mak   |  13 +-
 tests/ref/fate/hevc-conformance-MVHEVCS_A | 106 +
 tests/ref/fate/hevc-conformance-MVHEVCS_B | 138 ++
 tests/ref/fate/hevc-conformance-MVHEVCS_E | 106 +
 tests/ref/fate/hevc-conformance-MVHEVCS_F | 106 +
 5 files changed, 468 insertions(+), 1 deletion(-)
 create mode 100644 tests/ref/fate/hevc-conformance-MVHEVCS_A
 create mode 100644 tests/ref/fate/hevc-conformance-MVHEVCS_B
 create mode 100644 tests/ref/fate/hevc-conformance-MVHEVCS_E
 create mode 100644 tests/ref/fate/hevc-conformance-MVHEVCS_F

diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak
index 720603c112..e7dad6c898 100644
--- a/tests/fate/hevc.mak
+++ b/tests/fate/hevc.mak
@@ -178,7 +178,14 @@ HEVC_SAMPLES_444_12BIT =\
 PERSIST_RPARAM_A_RExt_Sony_3\
 $(if $(CONFIG_LARGE_TESTS), $(HEVC_SAMPLES_444_12BIT_LARGE))
 
-FATE_HEVC_VARS := 8BIT 10BIT 422_10BIT 422_10BIN 444_8BIT 444_12BIT
+HEVC_SAMPLES_MULTIVIEW =\
+MVHEVCS_A   \
+MVHEVCS_B   \
+MVHEVCS_E   \
+MVHEVCS_F   \
+
+
+FATE_HEVC_VARS := 8BIT 10BIT 422_10BIT 422_10BIN 444_8BIT 444_12BIT MULTIVIEW
 $(foreach VAR,$(FATE_HEVC_VARS), $(eval HEVC_TESTS_$(VAR) := $(addprefix 
fate-hevc-conformance-, $(HEVC_SAMPLES_$(VAR)
 
 # equivalent bitstreams
@@ -202,6 +209,8 @@ $(HEVC_TESTS_422_10BIT) $(HEVC_TESTS_422_10BIN): SCALE_OPTS 
:= -pix_fmt yuv422p1
 $(HEVC_TESTS_444_12BIT): SCALE_OPTS := -pix_fmt yuv444p12le -vf scale
 fate-hevc-conformance-%: CMD = framecrc -i 
$(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bit 
$(SCALE_OPTS)
 $(HEVC_TESTS_422_10BIN): CMD = framecrc -i 
$(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bin 
$(SCALE_OPTS)
+$(HEVC_TESTS_MULTIVIEW): CMD = framecrc -i 
$(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bit \
+   -pix_fmt yuv420p -map "0:view:0" -map "0:view:1" -vf setpts=N
 
 FATE_HEVC-$(call FRAMECRC, HEVC, HEVC, HEVC_PARSER) += $(HEVC_TESTS_8BIT) 
$(HEVC_TESTS_444_8BIT)
 FATE_HEVC-$(call FRAMECRC, HEVC, HEVC, HEVC_PARSER SCALE_FILTER) += \
@@ -210,6 +219,8 @@ FATE_HEVC-$(call FRAMECRC, HEVC, HEVC, HEVC_PARSER 
SCALE_FILTER) += \
 $(HEVC_TESTS_422_10BIN) \
 $(HEVC_TESTS_444_12BIT) \
 
+FATE_HEVC-$(call FRAMECRC, HEVC, HEVC, HEVC_PARSER SCALE_FILTER) += 
$(HEVC_TESTS_MULTIVIEW)
+
 fate-hevc-paramchange-yuv420p-yuv420p10: CMD = framecrc -i 
$(TARGET_SAMPLES)/hevc/paramchange_yuv420p_yuv420p10.hevc -fps_mode passthrough 
-sws_flags area+accurate_rnd+bitexact
 FATE_HEVC-$(call FRAMECRC, HEVC, HEVC, HEVC_PARSER SCALE_FILTER LARGE_TESTS) 
+= fate-hevc-paramchange-yuv420p-yuv420p10
 
diff --git a/tests/ref/fate/hevc-conformance-MVHEVCS_A 
b/tests/ref/fate/hevc-conformance-MVHEVCS_A
new file mode 100644
index 00..c919889207
--- /dev/null
+++ b/tests/ref/fate/hevc-conformance-MVHEVCS_A
@@ -0,0 +1,106 @@
+#tb 0: 1/120
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1024x768
+#sar 0: 0/1
+#tb 1: 1/120
+#media_type 1: video
+#codec_id 1: rawvideo
+#dimensions 1: 1024x768
+#sar 1: 0/1
+0,  0,  0,0,  1179648, 0x4a15620e
+1,  0,  0,0,  1179648, 0x5b752453
+0,  1,  1,0,  1179648, 0xb33277fe
+1,  1,  1,0,  1179648, 0xacf4376d
+0,  2,  2,0,  1179648, 0x97b969bd
+1,  2,  2,0,  1179648, 0xa9d6e75d
+0,  3,  3,0,  1179648, 0x3c6b7b81
+1,  3,  3,0,  1179648, 0x2142cc59
+0,  4,  4,0,  1179648, 0xdf83fe63
+1,  4,  4,0,  1179648, 0x838d4f0a
+0,  5,  5,0,  1179648, 0x93fc3bdf
+1,  5,  5,0,  1179648, 0x29bc71c2
+0,  6,  6,0,  1179648, 0x18f90aa3
+1,  6,  6,0,  1179648, 0x3b25ee18
+0,  7,  7,0,  1179648, 0x84c730c5
+1,  7,  7,0,  1179648, 0x60ecae5b
+0,  8,  8,0,  1179648, 0x7b49f2b1
+1,  8,  8,0,  1179648, 0x8c3c635e
+0,  9,  9,0,  1179648, 0x71f1b862
+1,  9,  9,0,  1179648, 0x16c2a6fc
+0, 10, 10,0,  1179648, 0x92be991a
+1, 10, 10,0,  1179648, 0x092d6378
+0, 11, 11,0,  1179648, 0xa948322d
+1, 11, 11,0,  1179648, 0x5d977eec
+0, 12, 12,  

[FFmpeg-devel] [PATCH 26/42] lavc/hevc_ps: parse VPS extension

2024-08-27 Thread Anton Khirnov
From: Niklas Haas 

Only implementing what's needed for MV-HEVC with two views.

Signed-off-by: Anton Khirnov 
---
 libavcodec/hevc/hevc.h |   9 +-
 libavcodec/hevc/ps.c   | 307 +++--
 libavcodec/hevc/ps.h   |  62 +
 3 files changed, 364 insertions(+), 14 deletions(-)

diff --git a/libavcodec/hevc/hevc.h b/libavcodec/hevc/hevc.h
index 9fdbc0a224..8bd59142db 100644
--- a/libavcodec/hevc/hevc.h
+++ b/libavcodec/hevc/hevc.h
@@ -100,11 +100,14 @@ enum HEVCSliceType {
 
 enum {
 // 7.4.3.1: vps_max_layers_minus1 is in [0, 62].
-HEVC_MAX_LAYERS = 63,
+HEVC_MAX_LAYERS = 63,
 // 7.4.3.1: vps_max_sub_layers_minus1 is in [0, 6].
-HEVC_MAX_SUB_LAYERS = 7,
+HEVC_MAX_SUB_LAYERS = 7,
 // 7.4.3.1: vps_num_layer_sets_minus1 is in [0, 1023].
-HEVC_MAX_LAYER_SETS = 1024,
+HEVC_MAX_LAYER_SETS = 1024,
+// 7.4.3.1: vps_max_layer_id is in [0, 63].
+HEVC_MAX_LAYER_ID   = 63,
+HEVC_MAX_NUH_LAYER_ID   = 62,
 
 // 7.4.2.1: vps_video_parameter_set_id is u(4).
 HEVC_MAX_VPS_COUNT = 16,
diff --git a/libavcodec/hevc/ps.c b/libavcodec/hevc/ps.c
index 5fa470cea3..0f4ae92588 100644
--- a/libavcodec/hevc/ps.c
+++ b/libavcodec/hevc/ps.c
@@ -308,11 +308,17 @@ static int decode_profile_tier_level(GetBitContext *gb, 
AVCodecContext *avctx,
 }
 
 static int parse_ptl(GetBitContext *gb, AVCodecContext *avctx,
-  PTL *ptl, int max_num_sub_layers)
+ int profile_present, PTL *ptl, int max_num_sub_layers)
 {
-int i;
-if (decode_profile_tier_level(gb, avctx, &ptl->general_ptl) < 0 ||
-get_bits_left(gb) < 8 + (8*2 * (max_num_sub_layers - 1 > 0))) {
+int i, status = 0;
+
+if (profile_present) {
+status = decode_profile_tier_level(gb, avctx, &ptl->general_ptl);
+} else {
+memset(&ptl->general_ptl, 0, sizeof(ptl->general_ptl));
+}
+
+if (status < 0 || get_bits_left(gb) < 8 + (8*2 * (max_num_sub_layers - 1 > 
0))) {
 av_log(avctx, AV_LOG_ERROR, "PTL information too short\n");
 return -1;
 }
@@ -441,13 +447,273 @@ static void hevc_vps_free(FFRefStructOpaque opaque, void 
*obj)
 av_freep(&vps->data);
 }
 
+enum ScalabilityMask {
+HEVC_SCALABILITY_DEPTH  = 0,
+HEVC_SCALABILITY_MULTIVIEW  = 1,
+HEVC_SCALABILITY_SPATIAL= 2,
+HEVC_SCALABILITY_AUXILIARY  = 3,
+HEVC_SCALABILITY_MASK_MAX   = 15,
+};
+
+enum DependencyType {
+HEVC_DEP_TYPE_SAMPLE = 0,
+HEVC_DEP_TYPE_MV = 1,
+HEVC_DEP_TYPE_BOTH   = 2,
+};
+
+static int decode_vps_ext(GetBitContext *gb, AVCodecContext *avctx, HEVCVPS 
*vps,
+  uint64_t layer1_id_included)
+{
+PTL ptl_dummy;
+uint8_t max_sub_layers[HEVC_MAX_LAYERS];
+
+int splitting_flag, dimension_id_len, view_id_len, num_add_olss,
+default_output_layer_idc, direct_dep_type_len, direct_dep_type,
+sub_layers_max_present, sub_layer_flag_info_present_flag, nb_ptl;
+unsigned non_vui_extension_length;
+
+if (vps->vps_max_layers == 1 || vps->vps_num_layer_sets == 1) {
+av_log(avctx, AV_LOG_VERBOSE, "Ignoring VPS extensions with a single 
layer\n");
+return 0;
+}
+
+if (vps->vps_max_layers > 2) {
+av_log(avctx, AV_LOG_ERROR,
+   "VPS has %d layers, only 2 layers are supported\n",
+   vps->vps_max_layers);
+return AVERROR_PATCHWELCOME;
+}
+if (vps->vps_num_layer_sets > 2) {
+av_log(avctx, AV_LOG_ERROR,
+   "VPS has %d layer sets, only 2 layer sets are supported\n",
+   vps->vps_num_layer_sets);
+return AVERROR_PATCHWELCOME;
+}
+
+align_get_bits(gb);
+
+/**
+ * For stereoscopic MV-HEVC, the following simplifying assumptions are 
made:
+ *
+ * - vps_max_layers = 2 (one base layer, one multiview layer)
+ * - vps_num_layer_sets = 2 (one output layer set for each view)
+ * - NumScalabilityTypes = 1 (only HEVC_SCALABILITY_MULTIVIEW)
+ * - direct_dependency_flag[1][0] = 1 (second layer depends on first)
+ * - num_add_olss = 0 (no extra output layer sets)
+ * - default_output_layer_idc = 0 (1:1 mapping between OLSs and layers)
+ * - layer_id_included_flag[1] = {1, 1} (consequence of layer dependencies)
+ * - vps_num_rep_formats_minus1 = 0 (all layers have the same size)
+ *
+ * Which results in the following derived variables:
+ * - ViewOrderIdx = {0, 1}
+ * - NumViews = 2
+ * - DependencyFlag[1][0] = 1
+ * - NumDirectRefLayers = {0, 1}
+ * - NumRefLayers = {0, 1}
+ * - NumPredictedLayers = {1, 0}
+ * - NumIndependentLayers = 1
+ * - NumLayersInTreePartition = {2}
+ * - NumLayerSets = 2
+ * - NumOutputLayerSets = 2
+ * - OlsIdxToLsIdx = {0, 1}
+ * - LayerIdxInVps = {0, 1}
+ * - NumLayersInIdList = {1, 2}
+ * - NumNecessaryLayers = {1, 2}
+ * - NecessaryLayerFlag = {{1, 0}, {1, 1}}
+ * - NumOutputL

[FFmpeg-devel] [PATCH 34/42] lavc/hevcdec: implement decoding MV-HEVC

2024-08-27 Thread Anton Khirnov
At most two layers are supported.
---
 doc/decoders.texi |  68 +++
 libavcodec/hevc/hevcdec.c | 375 ++
 libavcodec/hevc/hevcdec.h |  41 -
 libavcodec/hevc/refs.c|  64 +--
 libavcodec/version.h  |   2 +-
 5 files changed, 493 insertions(+), 57 deletions(-)

diff --git a/doc/decoders.texi b/doc/decoders.texi
index 2fcc761d2f..6fc585477c 100644
--- a/doc/decoders.texi
+++ b/doc/decoders.texi
@@ -38,6 +38,74 @@ Select an operating point of a scalable AV1 bitstream (0 - 
31). Default is 0.
 
 @end table
 
+@section hevc
+HEVC (AKA ITU-T H.265 or ISO/IEC 23008-2) decoder.
+
+The decoder supports MV-HEVC multiview streams with at most two views. Views to
+be output may be selected either as the index of an output layer set defined in
+the VPS (the @option{output_layer_set} option), or as a list of view IDs (the
+@option{view_ids} option). These options are mutually exclusive - only one may
+be specified at a time. These option may be set either statically before 
decoder
+init, or from the @code{get_format()} callback - useful for the case when the
+view count or IDs change dynamically during decoding.
+
+Only the base layer is decoded by default.
+
+Note that if you are using the @code{ffmpeg} CLI tool, you should be using view
+specifiers as documented in its manual, rather than the options documented 
here.
+
+@subsection Options
+
+@table @option
+
+@item output_layer_set (MV-HEVC)
+Select the index of the output layer set that should be output. Available layer
+sets may be read by the user from the @option{output_layer_set_available}
+option.
+
+@item output_layer_set_available (MV-HEVC)
+This option may be read by the caller to retrieve an array of output layer sets
+available in the active VPS. The array is empty for single-layer video.
+
+Each array element is a bitmask defining layers present in the set. I.e. when
+i-th bit is equal to 1, the layer with view ID @option{view_ids[i]} is present
+in the set.
+
+The value of this option is guaranteed to be accurate when read from the
+@code{get_format()} callback. It may also be set at other times (e.g. after
+opening the decoder), but the value is informational only and may be incorrect
+(e.g. when the stream contains multiple distinct VPS NALUs).
+
+@item view_ids (MV-HEVC)
+Specify a list of view IDs that should be output. This option can also be set 
to
+a single '-1', which will cause all views defined in the VPS to be decoded and
+output.
+
+@item view_ids_available (MV-HEVC)
+This option may be read by the caller to retrieve an array of view IDs 
available
+in the active VPS. The array is empty for single-layer video.
+
+Same validity restrictions as for @option{output_layer_set_available} apply to
+this option.
+
+@item view_pos_available (MV-HEVC)
+This option may be read by the caller to retrieve an array of view positions
+(left, right, or unspecified) available in the active VPS, as AVStereo3DView
+values. When the array is available, its elements describe view IDs from
+@option{view_ids_available}.
+
+Same validity restrictions as for @option{output_layer_set_available} apply to
+this option.
+
+@item view_id_cur (MV-HEVC)
+This option may be read from within the @code{get_buffer2()} callback to obtain
+the view ID of the frame for which the callback is being called.
+
+It should not be accessed at other times and its contents are then not
+specified.
+
+@end table
+
 @section rawvideo
 
 Raw video decoder.
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 9a549bb0d2..f0e284bdf6 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -34,6 +34,7 @@
 #include "libavutil/mem.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
+#include "libavutil/stereo3d.h"
 #include "libavutil/timecode.h"
 
 #include "aom_film_grain.h"
@@ -54,6 +55,8 @@
 #include "refstruct.h"
 #include "thread.h"
 
+#define HEVC_OLS_AUTO INT_MAX
+
 static const uint8_t hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 
3, [12] = 4, [16] = 5, [24] = 6, [32] = 7, [48] = 8, [64] = 9 };
 
 /**
@@ -417,6 +420,137 @@ static int export_stream_params_from_sei(HEVCContext *s)
 return 0;
 }
 
+static int export_multilayer(HEVCContext *s, const HEVCVPS *vps)
+{
+const HEVCSEITDRDI *tdrdi = &s->sei.tdrdi;
+
+av_freep(&s->view_ids_available);
+s->nb_view_ids_available = 0;
+av_freep(&s->view_pos_available);
+s->nb_view_pos_available = 0;
+av_freep(&s->output_layer_set_available);
+s->nb_output_layer_set_available = 0;
+
+// don't export anything in the trivial case (1 layer, view id=0)
+if (vps->nb_layers < 2 && !vps->view_id[0])
+return 0;
+
+s->view_ids_available = av_calloc(vps->nb_layers, 
sizeof(*s->view_ids_available));
+if (!s->view_ids_available)
+return AVERROR(ENOMEM);
+
+if (tdrdi->num_ref_displays) {
+s->view_pos_available = av_calloc(vps->nb_layers, 
sizeof(*s->view_pos_available));

[FFmpeg-devel] [PATCH 23/42] lavc/hevcdec: make a HEVCFrame hold a reference to its PPS

2024-08-27 Thread Anton Khirnov
ff_hevc_get_ref_list() needs the PPS of a previously decoded frame,
which may be different from the currently active one.
---
 libavcodec/hevc/filter.c  |  4 ++--
 libavcodec/hevc/hevcdec.c |  1 +
 libavcodec/hevc/hevcdec.h |  4 ++--
 libavcodec/hevc/mvs.c |  2 +-
 libavcodec/hevc/refs.c| 15 +--
 5 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/libavcodec/hevc/filter.c b/libavcodec/hevc/filter.c
index 298f1792b2..68ae0e9ef6 100644
--- a/libavcodec/hevc/filter.c
+++ b/libavcodec/hevc/filter.c
@@ -767,7 +767,7 @@ void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext 
*lc, const HEVCLayer
 
 if (boundary_upper) {
 const RefPicList *rpl_top = (lc->boundary_flags & 
BOUNDARY_UPPER_SLICE) ?
-ff_hevc_get_ref_list(s, s->cur_frame, x0, 
y0 - 1) :
+ff_hevc_get_ref_list(s->cur_frame, x0, y0 
- 1) :
 s->cur_frame->refPicList;
 int yp_pu = (y0 - 1) >> log2_min_pu_size;
 int yq_pu =  y0  >> log2_min_pu_size;
@@ -805,7 +805,7 @@ void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext 
*lc, const HEVCLayer
 
 if (boundary_left) {
 const RefPicList *rpl_left = (lc->boundary_flags & 
BOUNDARY_LEFT_SLICE) ?
- ff_hevc_get_ref_list(s, s->cur_frame, x0 
- 1, y0) :
+ ff_hevc_get_ref_list(s->cur_frame, x0 - 
1, y0) :
  s->cur_frame->refPicList;
 int xp_pu = (x0 - 1) >> log2_min_pu_size;
 int xq_pu =  x0  >> log2_min_pu_size;
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index e02d5bba72..eb41f9a5d6 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -3503,6 +3503,7 @@ static int hevc_ref_frame(HEVCFrame *dst, const HEVCFrame 
*src)
 dst->needs_fg = 1;
 }
 
+dst->pps = ff_refstruct_ref_c(src->pps);
 dst->tab_mvf = ff_refstruct_ref(src->tab_mvf);
 dst->rpl_tab = ff_refstruct_ref(src->rpl_tab);
 dst->rpl = ff_refstruct_ref(src->rpl);
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index 0b5d87b18f..a534aee60f 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -366,6 +366,7 @@ typedef struct HEVCFrame {
 int ctb_count;
 int poc;
 
+const HEVCPPS *pps;///< RefStruct reference
 RefPicListTab *rpl;///< RefStruct reference
 int nb_rpl_elems;
 
@@ -556,8 +557,7 @@ void ff_hevc_clear_refs(HEVCLayerContext *l);
  */
 void ff_hevc_flush_dpb(HEVCContext *s);
 
-const RefPicList *ff_hevc_get_ref_list(const HEVCContext *s, const HEVCFrame 
*frame,
-   int x0, int y0);
+const RefPicList *ff_hevc_get_ref_list(const HEVCFrame *frame, int x0, int y0);
 
 /**
  * Construct the reference picture sets for the current frame.
diff --git a/libavcodec/hevc/mvs.c b/libavcodec/hevc/mvs.c
index 96d8d58f39..55f115ad0c 100644
--- a/libavcodec/hevc/mvs.c
+++ b/libavcodec/hevc/mvs.c
@@ -211,7 +211,7 @@ static int derive_temporal_colocated_mvs(const HEVCContext 
*s, MvField temp_col,
 #define DERIVE_TEMPORAL_COLOCATED_MVS   \
 derive_temporal_colocated_mvs(s, temp_col,  \
   refIdxLx, mvLXCol, X, colPic, \
-  ff_hevc_get_ref_list(s, ref, x, y))
+  ff_hevc_get_ref_list(ref, x, y))
 
 /*
  * 8.5.3.1.7  temporal luma motion vector prediction
diff --git a/libavcodec/hevc/refs.c b/libavcodec/hevc/refs.c
index 7b8dff4f55..58edc15a6f 100644
--- a/libavcodec/hevc/refs.c
+++ b/libavcodec/hevc/refs.c
@@ -38,6 +38,7 @@ void ff_hevc_unref_frame(HEVCFrame *frame, int flags)
 av_frame_unref(frame->frame_grain);
 frame->needs_fg = 0;
 
+ff_refstruct_unref(&frame->pps);
 ff_refstruct_unref(&frame->tab_mvf);
 
 ff_refstruct_unref(&frame->rpl);
@@ -49,13 +50,13 @@ void ff_hevc_unref_frame(HEVCFrame *frame, int flags)
 }
 }
 
-const RefPicList *ff_hevc_get_ref_list(const HEVCContext *s,
-   const HEVCFrame *ref, int x0, int y0)
+const RefPicList *ff_hevc_get_ref_list(const HEVCFrame *ref, int x0, int y0)
 {
-int x_cb = x0 >> s->ps.sps->log2_ctb_size;
-int y_cb = y0 >> s->ps.sps->log2_ctb_size;
-int pic_width_cb = s->ps.sps->ctb_width;
-int ctb_addr_ts  = s->pps->ctb_addr_rs_to_ts[y_cb * pic_width_cb + x_cb];
+const HEVCSPS *sps = ref->pps->sps;
+int x_cb = x0 >> sps->log2_ctb_size;
+int y_cb = y0 >> sps->log2_ctb_size;
+int pic_width_cb = sps->ctb_width;
+int ctb_addr_ts  = ref->pps->ctb_addr_rs_to_ts[y_cb * pic_width_cb + x_cb];
 return &ref->rpl_tab[ctb_addr_ts]->refPicList[0];
 }
 
@@ -116,6 +117,8 @@ static HEVCFrame *alloc_frame(HEVCContext *s, 
HEVCLaye

[FFmpeg-devel] [PATCH 19/42] lavc/hevcdec: move HEVCContext.qp_y_tab to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
---
 libavcodec/hevc/filter.c  | 34 ++
 libavcodec/hevc/hevcdec.c | 17 +
 libavcodec/hevc/hevcdec.h |  6 --
 3 files changed, 31 insertions(+), 26 deletions(-)

diff --git a/libavcodec/hevc/filter.c b/libavcodec/hevc/filter.c
index 14afb147b9..ad655a2b36 100644
--- a/libavcodec/hevc/filter.c
+++ b/libavcodec/hevc/filter.c
@@ -75,6 +75,7 @@ static int chroma_tc(const HEVCPPS *pps, const HEVCSPS *sps,
 }
 
 static int get_qPy_pred(HEVCLocalContext *lc, const HEVCContext *s,
+const HEVCLayerContext *l,
 const HEVCPPS *pps, const HEVCSPS *sps,
 int xBase, int yBase, int log2_cb_size)
 {
@@ -104,13 +105,13 @@ static int get_qPy_pred(HEVCLocalContext *lc, const 
HEVCContext *s,
 if (availableA == 0)
 qPy_a = qPy_pred;
 else
-qPy_a = s->qp_y_tab[(x_cb - 1) + y_cb * min_cb_width];
+qPy_a = l->qp_y_tab[(x_cb - 1) + y_cb * min_cb_width];
 
 // qPy_b
 if (availableB == 0)
 qPy_b = qPy_pred;
 else
-qPy_b = s->qp_y_tab[x_cb + (y_cb - 1) * min_cb_width];
+qPy_b = l->qp_y_tab[x_cb + (y_cb - 1) * min_cb_width];
 
 av_assert2(qPy_a >= -sps->qp_bd_offset && qPy_a < 52);
 av_assert2(qPy_b >= -sps->qp_bd_offset && qPy_b < 52);
@@ -118,12 +119,13 @@ static int get_qPy_pred(HEVCLocalContext *lc, const 
HEVCContext *s,
 return (qPy_a + qPy_b + 1) >> 1;
 }
 
-void ff_hevc_set_qPy(HEVCLocalContext *lc, const HEVCPPS *pps,
+void ff_hevc_set_qPy(HEVCLocalContext *lc,
+ const HEVCLayerContext *l, const HEVCPPS *pps,
  int xBase, int yBase, int log2_cb_size)
 {
 const HEVCSPS   *const sps = pps->sps;
 const HEVCContext *const s = lc->parent;
-int qp_y = get_qPy_pred(lc, s, pps, sps, xBase, yBase, log2_cb_size);
+int qp_y = get_qPy_pred(lc, s, l, pps, sps, xBase, yBase, log2_cb_size);
 
 if (lc->tu.cu_qp_delta != 0) {
 int off = sps->qp_bd_offset;
@@ -550,8 +552,8 @@ static void deblocking_filter_CTB(const HEVCContext *s, 
const HEVCLayerContext *
 const int bs0 = s->vertical_bs[(x +  y  * l->bs_width) >> 2];
 const int bs1 = s->vertical_bs[(x + (y + 4) * l->bs_width) >> 2];
 if (bs0 || bs1) {
-const int qp = (get_qPy(sps, s->qp_y_tab, x - 1, y) +
-get_qPy(sps, s->qp_y_tab, x, y) + 1) >> 1;
+const int qp = (get_qPy(sps, l->qp_y_tab, x - 1, y) +
+get_qPy(sps, l->qp_y_tab, x, y) + 1) >> 1;
 
 beta = betatable[av_clip(qp + beta_offset, 0, MAX_QP)];
 
@@ -579,8 +581,8 @@ static void deblocking_filter_CTB(const HEVCContext *s, 
const HEVCLayerContext *
 const int bs0 = s->horizontal_bs[( x  + y * l->bs_width) >> 2];
 const int bs1 = s->horizontal_bs[((x + 4) + y * l->bs_width) >> 2];
 if (bs0 || bs1) {
-const int qp = (get_qPy(sps, s->qp_y_tab, x, y - 1) +
-get_qPy(sps, s->qp_y_tab, x, y) + 1) >> 1;
+const int qp = (get_qPy(sps, l->qp_y_tab, x, y - 1) +
+get_qPy(sps, l->qp_y_tab, x, y) + 1) >> 1;
 
 tc_offset   = x >= x0 ? cur_tc_offset : left_tc_offset;
 beta_offset = x >= x0 ? cur_beta_offset : left_beta_offset;
@@ -615,10 +617,10 @@ static void deblocking_filter_CTB(const HEVCContext *s, 
const HEVCLayerContext *
 const int bs1 = s->vertical_bs[(x + (y + (4 * v)) * 
l->bs_width) >> 2];
 
 if ((bs0 == 2) || (bs1 == 2)) {
-const int qp0 = (get_qPy(sps, s->qp_y_tab, x - 1, y) +
- get_qPy(sps, s->qp_y_tab, x, y) + 
1) >> 1;
-const int qp1 = (get_qPy(sps, s->qp_y_tab, x - 1, y + 
(4 * v)) +
- get_qPy(sps, s->qp_y_tab, x, y + 
(4 * v)) + 1) >> 1;
+const int qp0 = (get_qPy(sps, l->qp_y_tab, x - 1, y) +
+ get_qPy(sps, l->qp_y_tab, x, y) + 
1) >> 1;
+const int qp1 = (get_qPy(sps, l->qp_y_tab, x - 1, y + 
(4 * v)) +
+ get_qPy(sps, l->qp_y_tab, x, y + 
(4 * v)) + 1) >> 1;
 
 c_tc[0] = (bs0 == 2) ? chroma_tc(pps, sps, qp0, 
chroma, tc_offset) : 0;
 c_tc[1] = (bs1 == 2) ? chroma_tc(pps, sps, qp1, 
chroma, tc_offset) : 0;
@@ -648,10 +650,10 @@ static void deblocking_filter_CTB(const HEVCContext *s, 
const HEVCLayerContext *
 const int bs0 = s->horizontal_bs[( x  + y * 
l->bs_width) >> 2];
 const int bs1 = s->horizontal_bs[((x + 4 * h) + y * 
l->bs_width) >> 2];
 if ((bs0 == 2) || (bs1 == 2)) {
-const int qp0 = b

[FFmpeg-devel] [PATCH 17/42] lavc/hevcdec: move HEVCContext.filter_slice_edges to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
---
 libavcodec/hevc/filter.c  | 2 +-
 libavcodec/hevc/hevcdec.c | 8 
 libavcodec/hevc/hevcdec.h | 6 +++---
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/libavcodec/hevc/filter.c b/libavcodec/hevc/filter.c
index f5224151b6..12a57eb223 100644
--- a/libavcodec/hevc/filter.c
+++ b/libavcodec/hevc/filter.c
@@ -281,7 +281,7 @@ static void sao_filter_CTB(HEVCLocalContext *lc, const 
HEVCLayerContext *l,
 uint8_t vert_edge[]  = { 0, 0 };
 uint8_t horiz_edge[] = { 0, 0 };
 uint8_t diag_edge[]  = { 0, 0, 0, 0 };
-uint8_t lfase= CTB(s->filter_slice_edges, x_ctb, y_ctb);
+uint8_t lfase= CTB(l->filter_slice_edges, x_ctb, y_ctb);
 uint8_t no_tile_filter   = pps->tiles_enabled_flag &&
!pps->loop_filter_across_tiles_enabled_flag;
 uint8_t restore  = no_tile_filter || !lfase;
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 02571f0607..4174743eb6 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -80,7 +80,7 @@ static void pic_arrays_free(HEVCContext *s, HEVCLayerContext 
*l)
 
 av_freep(&s->qp_y_tab);
 av_freep(&s->tab_slice_address);
-av_freep(&s->filter_slice_edges);
+av_freep(&l->filter_slice_edges);
 
 av_freep(&s->horizontal_bs);
 av_freep(&s->vertical_bs);
@@ -119,12 +119,12 @@ static int pic_arrays_init(HEVCContext *s, 
HEVCLayerContext *l, const HEVCSPS *s
 if (!l->tab_ipm || !l->cbf_luma || !l->is_pcm)
 goto fail;
 
-s->filter_slice_edges = av_mallocz(ctb_count);
+l->filter_slice_edges = av_mallocz(ctb_count);
 s->tab_slice_address  = av_malloc_array(pic_size_in_ctb,
   sizeof(*s->tab_slice_address));
 s->qp_y_tab   = av_malloc_array(pic_size_in_ctb,
   sizeof(*s->qp_y_tab));
-if (!s->qp_y_tab || !s->filter_slice_edges || !s->tab_slice_address)
+if (!s->qp_y_tab || !l->filter_slice_edges || !s->tab_slice_address)
 goto fail;
 
 s->horizontal_bs = av_calloc(l->bs_width, l->bs_height);
@@ -2568,7 +2568,7 @@ static int hls_decode_entry(HEVCContext *s, GetBitContext 
*gb)
 
 l->deblock[ctb_addr_rs].beta_offset = s->sh.beta_offset;
 l->deblock[ctb_addr_rs].tc_offset   = s->sh.tc_offset;
-s->filter_slice_edges[ctb_addr_rs]  = 
s->sh.slice_loop_filter_across_slices_enabled_flag;
+l->filter_slice_edges[ctb_addr_rs]  = 
s->sh.slice_loop_filter_across_slices_enabled_flag;
 
 more_data = hls_coding_quadtree(lc, l, pps, sps, x_ctb, y_ctb, 
sps->log2_ctb_size, 0);
 if (more_data < 0) {
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index dde87be5be..afaf4c1954 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -455,6 +455,9 @@ typedef struct HEVCLayerContext {
 uint8_t*cbf_luma; // cbf_luma of colocated TU
 uint8_t*tab_ipm;
 uint8_t*is_pcm;
+
+// CTB-level flags affecting loop filter operation
+uint8_t*filter_slice_edges;
 } HEVCLayerContext;
 
 typedef struct HEVCContext {
@@ -512,9 +515,6 @@ typedef struct HEVCContext {
 
 int32_t *tab_slice_address;
 
-// CTB-level flags affecting loop filter operation
-uint8_t *filter_slice_edges;
-
 /** used on BE to byteswap the lines for checksumming */
 uint8_t *checksum_buf;
 int  checksum_buf_size;
-- 
2.43.0

___
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 39/42] fftools/ffmpeg_mux_init: cosmetics

2024-08-27 Thread Anton Khirnov
Restore vertical alignment to OutputFilterOptions initializer.

The flags field is kept as-is, since the corresponding lines are already
long, aligning them would make them even longer, and breaking them would
look worse.
---
 fftools/ffmpeg_mux_init.c | 31 ---
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index c874ccb113..c054765be7 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1388,23 +1388,24 @@ static int ost_add(Muxer *mux, const OptionsContext *o, 
enum AVMediaType type,
 (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
 char name[16];
 OutputFilterOptions opts = {
-.enc = enc,
-.name= name,
-.format  = (type == AVMEDIA_TYPE_VIDEO) ?
-   ost->enc_ctx->pix_fmt : ost->enc_ctx->sample_fmt,
-.width   = ost->enc_ctx->width,
-.height  = ost->enc_ctx->height,
-.vsync_method = vsync_method,
-.sample_rate = ost->enc_ctx->sample_rate,
-.ch_layout   = ost->enc_ctx->ch_layout,
-.sws_opts= o->g->sws_dict,
-.swr_opts= o->g->swr_opts,
-.vs  = vs,
-.output_tb = enc_tb,
+.enc  = enc,
+.name = name,
+.format   = (type == AVMEDIA_TYPE_VIDEO) ?
+ost->enc_ctx->pix_fmt : 
ost->enc_ctx->sample_fmt,
+.width= ost->enc_ctx->width,
+.height   = ost->enc_ctx->height,
+.vsync_method = vsync_method,
+.sample_rate  = ost->enc_ctx->sample_rate,
+.ch_layout= ost->enc_ctx->ch_layout,
+.sws_opts = o->g->sws_dict,
+.swr_opts = o->g->swr_opts,
+.vs   = vs,
+.output_tb= enc_tb,
 .trim_start_us= mux->of.start_time,
 .trim_duration_us = mux->of.recording_time,
-.ts_offset = mux->of.start_time == AV_NOPTS_VALUE ?
- 0 : mux->of.start_time,
+.ts_offset= mux->of.start_time == AV_NOPTS_VALUE ?
+0 : mux->of.start_time,
+
 .flags = OFILTER_FLAG_DISABLE_CONVERT * !!keep_pix_fmt |
  OFILTER_FLAG_AUTOSCALE   * !!autoscale|
  OFILTER_FLAG_AUDIO_24BIT * 
!!(av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24),
-- 
2.43.0

___
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 11/42] lavc/hevcdec: move HEVCContext.deblock to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
---
 libavcodec/hevc/filter.c  |  8 
 libavcodec/hevc/hevcdec.c | 10 +-
 libavcodec/hevc/hevcdec.h |  2 +-
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/libavcodec/hevc/filter.c b/libavcodec/hevc/filter.c
index 78f408f170..4d5ef631d7 100644
--- a/libavcodec/hevc/filter.c
+++ b/libavcodec/hevc/filter.c
@@ -515,8 +515,8 @@ static void deblocking_filter_CTB(const HEVCContext *s, 
const HEVCLayerContext *
 int ctb_size= 1 << log2_ctb_size;
 int ctb = (x0 >> log2_ctb_size) +
   (y0 >> log2_ctb_size) * sps->ctb_width;
-int cur_tc_offset   = s->deblock[ctb].tc_offset;
-int cur_beta_offset = s->deblock[ctb].beta_offset;
+int cur_tc_offset   = l->deblock[ctb].tc_offset;
+int cur_beta_offset = l->deblock[ctb].beta_offset;
 int left_tc_offset, left_beta_offset;
 int tc_offset, beta_offset;
 int pcmf = (sps->pcm_enabled &&
@@ -524,8 +524,8 @@ static void deblocking_filter_CTB(const HEVCContext *s, 
const HEVCLayerContext *
pps->transquant_bypass_enable_flag;
 
 if (x0) {
-left_tc_offset   = s->deblock[ctb - 1].tc_offset;
-left_beta_offset = s->deblock[ctb - 1].beta_offset;
+left_tc_offset   = l->deblock[ctb - 1].tc_offset;
+left_beta_offset = l->deblock[ctb - 1].beta_offset;
 } else {
 left_tc_offset   = 0;
 left_beta_offset = 0;
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 0bb4d43ed4..a20e559353 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -69,7 +69,7 @@ static const uint8_t hevc_pel_weight[65] = { [2] = 0, [4] = 
1, [6] = 2, [8] = 3,
 static void pic_arrays_free(HEVCContext *s, HEVCLayerContext *l)
 {
 av_freep(&l->sao);
-av_freep(&s->deblock);
+av_freep(&l->deblock);
 
 av_freep(&s->skip_flag);
 av_freep(&s->tab_ct_depth);
@@ -104,8 +104,8 @@ static int pic_arrays_init(HEVCContext *s, HEVCLayerContext 
*l, const HEVCSPS *s
 l->bs_height = (height >> 2) + 1;
 
 l->sao   = av_calloc(ctb_count, sizeof(*l->sao));
-s->deblock   = av_calloc(ctb_count, sizeof(*s->deblock));
-if (!l->sao || !s->deblock)
+l->deblock   = av_calloc(ctb_count, sizeof(*l->deblock));
+if (!l->sao || !l->deblock)
 goto fail;
 
 s->skip_flag= av_malloc_array(sps->min_cb_height, sps->min_cb_width);
@@ -2559,8 +2559,8 @@ static int hls_decode_entry(HEVCContext *s, GetBitContext 
*gb)
 hls_sao_param(lc, l, pps, sps,
   x_ctb >> sps->log2_ctb_size, y_ctb >> 
sps->log2_ctb_size);
 
-s->deblock[ctb_addr_rs].beta_offset = s->sh.beta_offset;
-s->deblock[ctb_addr_rs].tc_offset   = s->sh.tc_offset;
+l->deblock[ctb_addr_rs].beta_offset = s->sh.beta_offset;
+l->deblock[ctb_addr_rs].tc_offset   = s->sh.tc_offset;
 s->filter_slice_edges[ctb_addr_rs]  = 
s->sh.slice_loop_filter_across_slices_enabled_flag;
 
 more_data = hls_coding_quadtree(lc, l, pps, sps, x_ctb, y_ctb, 
sps->log2_ctb_size, 0);
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index e0b026eef6..22b34924d5 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -445,6 +445,7 @@ typedef struct HEVCLayerContext {
 int bs_height;
 
 SAOParams  *sao;
+DBParams   *deblock;
 } HEVCLayerContext;
 
 typedef struct HEVCContext {
@@ -478,7 +479,6 @@ typedef struct HEVCContext {
 const HEVCVPS *vps; ///< RefStruct reference
 const HEVCPPS *pps; ///< RefStruct reference
 SliceHeader sh;
-DBParams *deblock;
 enum HEVCNALUnitType nal_unit_type;
 int temporal_id;  ///< temporal_id_plus1 - 1
 HEVCFrame *cur_frame;
-- 
2.43.0

___
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 27/42] lavc/hevc/ps: drop a warning for sps_multilayer_extension_flag

2024-08-27 Thread Anton Khirnov
SPS multilayer extension contains a single flag that we are free to
ignore, no reason to print a warning.
---
 libavcodec/hevc/ps.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/libavcodec/hevc/ps.c b/libavcodec/hevc/ps.c
index 0f4ae92588..0e084958be 100644
--- a/libavcodec/hevc/ps.c
+++ b/libavcodec/hevc/ps.c
@@ -1422,8 +1422,6 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, 
unsigned int *sps_id,
 
 if (sps->multilayer_extension) {
 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) {
-- 
2.43.0

___
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 38/42] fftools/ffmpeg: add support for multiview video

2024-08-27 Thread Anton Khirnov
This extends the syntax for specifying input streams in -map and complex
filtergraph labels, to allow selecting a view by view ID, index, or
position. The corresponding decoder is then set up to decode the
appropriate view and send frames for that view to the correct
filtergraph input(s).
---
 doc/ffmpeg.texi   |  30 +++-
 fftools/cmdutils.c|   2 +-
 fftools/cmdutils.h|   2 +
 fftools/ffmpeg.h  |  45 -
 fftools/ffmpeg_dec.c  | 355 +-
 fftools/ffmpeg_demux.c|  24 ++-
 fftools/ffmpeg_filter.c   |  71 +---
 fftools/ffmpeg_mux_init.c |  29 +++-
 fftools/ffmpeg_opt.c  |  70 +++-
 9 files changed, 575 insertions(+), 53 deletions(-)

diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index 842e92ad1a..34007f7ea2 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -1799,7 +1799,7 @@ Set the size of the canvas used to render subtitles.
 @section Advanced options
 
 @table @option
-@item -map [-]@var{input_file_id}[:@var{stream_specifier}][?] | 
@var{[linklabel]} (@emph{output})
+@item -map 
[-]@var{input_file_id}[:@var{stream_specifier}][:@var{view_specifier}][?] | 
@var{[linklabel]} (@emph{output})
 
 Create one or more streams in the output file. This option has two forms for
 specifying the data source(s): the first selects one or more streams from some
@@ -1814,6 +1814,26 @@ only those streams that match the specifier are used 
(see the
 A @code{-} character before the stream identifier creates a "negative" mapping.
 It disables matching streams from already created mappings.
 
+An optional @var{view_specifier} may be given after the stream specifier, which
+for multiview video specifies the view to be used. The view specifier may have
+one of the following formats:
+@table @option
+@item view:@var{view_id}
+select a view by its ID; @var{view_id} may be set to 'all' to use all the views
+interleaved into one stream;
+
+@item vidx:@var{view_idx}
+select a view by its index; i.e. 0 is the base view, 1 is the first non-base
+view, etc.
+
+@item vpos:@var{position}
+select a view by its display position; @var{position} may be @code{left} or
+@code{right}
+@end table
+The default for transcoding is to only use the base view, i.e. the equivalent 
of
+@code{vidx:0}. For streamcopy, view specifiers are not supported and all views
+are always copied.
+
 A trailing @code{?} after the stream index will allow the map to be
 optional: if the map matches no streams the map will be ignored instead
 of failing. Note the map will still fail if an invalid input file index
@@ -2206,11 +2226,15 @@ distinguished by the format of the corresponding link 
label:
 @item
 To connect an input stream, use @code{[file_index:stream_specifier]} (i.e. the
 same syntax as @option{-map}). If @var{stream_specifier} matches multiple
-streams, the first one will be used.
+streams, the first one will be used. For multiview video, the stream specifier
+may be followed by the view specifier, see documentation for the @option{-map}
+option for its syntax.
 
 @item
 To connect a loopback decoder use [dec:@var{dec_idx}], where @var{dec_idx} is
-the index of the loopback decoder to be connected to given input.
+the index of the loopback decoder to be connected to given input. For multiview
+video, the decoder index may be followed by the view specifier, see
+documentation for the @option{-map} option for its syntax.
 
 @item
 To connect an output from another complex filtergraph, use its link label. E.g
diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c
index 8909572ea3..d7a78ede12 100644
--- a/fftools/cmdutils.c
+++ b/fftools/cmdutils.c
@@ -988,7 +988,7 @@ FILE *get_preset_file(char *filename, size_t filename_size,
 return f;
 }
 
-static int cmdutils_isalnum(char c)
+int cmdutils_isalnum(char c)
 {
 return (c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h
index 9609c6c739..722ec05b0c 100644
--- a/fftools/cmdutils.h
+++ b/fftools/cmdutils.h
@@ -554,4 +554,6 @@ void remove_avoptions(AVDictionary **a, AVDictionary *b);
 /* Check if any keys exist in dictionary m */
 int check_avoptions(AVDictionary *m);
 
+int cmdutils_isalnum(char c);
+
 #endif /* FFTOOLS_CMDUTILS_H */
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 3c5d933e17..ddb4cf47ef 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -112,12 +112,32 @@ typedef struct HWDevice {
 AVBufferRef *device_ref;
 } HWDevice;
 
+enum ViewSpecifierType {
+// no specifier given
+VIEW_SPECIFIER_TYPE_NONE = 0,
+// val is view index
+VIEW_SPECIFIER_TYPE_IDX,
+// val is view ID
+VIEW_SPECIFIER_TYPE_ID,
+// specify view by its position, val is AV_STEREO3D_VIEW_LEFT/RIGHT
+VIEW_SPECIFIER_TYPE_POS,
+// use all views, val is ignored
+VIEW_SPECIFIER_TYPE_ALL,
+};
+
+typedef struct ViewSpecifier {
+enum ViewSpecifierType type;
+unsigned   val;
+} ViewSpecifier;
+
 /* select an input

[FFmpeg-devel] [PATCH 16/42] lavc/hevcdec: move HEVCContext.is_pcm to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
---
 libavcodec/hevc/filter.c  | 40 +++
 libavcodec/hevc/hevcdec.c | 18 +-
 libavcodec/hevc/hevcdec.h |  5 +
 3 files changed, 30 insertions(+), 33 deletions(-)

diff --git a/libavcodec/hevc/filter.c b/libavcodec/hevc/filter.c
index 379c488d78..f5224151b6 100644
--- a/libavcodec/hevc/filter.c
+++ b/libavcodec/hevc/filter.c
@@ -223,7 +223,7 @@ static void copy_CTB_to_hv(const HEVCContext *s, const 
HEVCSPS *sps,
 copy_vert(s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 1) * h + y) << 
sh), src + ((width - 1) << sh), sh, height, 1 << sh, stride_src);
 }
 
-static void restore_tqb_pixels(const HEVCContext *s,
+static void restore_tqb_pixels(const HEVCLayerContext *l,
const HEVCPPS *pps, const HEVCSPS *sps,
uint8_t *src1, const uint8_t *dst1,
ptrdiff_t stride_src, ptrdiff_t stride_dst,
@@ -242,7 +242,7 @@ static void restore_tqb_pixels(const HEVCContext *s,
 int len  = (min_pu_size >> hshift) << sps->pixel_shift;
 for (y = y_min; y < y_max; y++) {
 for (x = x_min; x < x_max; x++) {
-if (s->is_pcm[y * sps->min_pu_width + x]) {
+if (l->is_pcm[y * sps->min_pu_width + x]) {
 int n;
 uint8_t *src = src1 +
  (((y << sps->log2_min_pu_size) - y0) >> vshift) * 
stride_src +
@@ -351,7 +351,7 @@ static void sao_filter_CTB(HEVCLocalContext *lc, const 
HEVCLayerContext *l,
 s->hevcdsp.sao_band_filter[tab](src, dst, stride_src, 
stride_dst,
 sao->offset_val[c_idx], 
sao->band_position[c_idx],
 width, height);
-restore_tqb_pixels(s, pps, sps, src, dst, stride_src, 
stride_dst,
+restore_tqb_pixels(l, pps, sps, src, dst, stride_src, 
stride_dst,
x, y, width, height, c_idx);
 } else {
 s->hevcdsp.sao_band_filter[tab](src, src, stride_src, 
stride_src,
@@ -466,7 +466,7 @@ static void sao_filter_CTB(HEVCLocalContext *lc, const 
HEVCLayerContext *l,
 vert_edge,
 horiz_edge,
 diag_edge);
-restore_tqb_pixels(s, pps, sps, src, dst, stride_src, stride_dst,
+restore_tqb_pixels(l, pps, sps, src, dst, stride_src, stride_dst,
x, y, width, height, c_idx);
 sao->type_idx[c_idx] = SAO_APPLIED;
 break;
@@ -559,10 +559,10 @@ static void deblocking_filter_CTB(const HEVCContext *s, 
const HEVCLayerContext *
 tc[1]   = bs1 ? TC_CALC(qp, bs1) : 0;
 src = &data[LUMA][y * linesize[LUMA] + (x << 
sps->pixel_shift)];
 if (pcmf) {
-no_p[0] = get_pcm(sps, s->is_pcm, x - 1, y);
-no_p[1] = get_pcm(sps, s->is_pcm, x - 1, y + 4);
-no_q[0] = get_pcm(sps, s->is_pcm, x, y);
-no_q[1] = get_pcm(sps, s->is_pcm, x, y + 4);
+no_p[0] = get_pcm(sps, l->is_pcm, x - 1, y);
+no_p[1] = get_pcm(sps, l->is_pcm, x - 1, y + 4);
+no_q[0] = get_pcm(sps, l->is_pcm, x, y);
+no_q[1] = get_pcm(sps, l->is_pcm, x, y + 4);
 s->hevcdsp.hevc_v_loop_filter_luma_c(src, linesize[LUMA],
  beta, tc, no_p, no_q);
 } else
@@ -590,10 +590,10 @@ static void deblocking_filter_CTB(const HEVCContext *s, 
const HEVCLayerContext *
 tc[1]   = bs1 ? TC_CALC(qp, bs1) : 0;
 src = &data[LUMA][y * linesize[LUMA] + (x << 
sps->pixel_shift)];
 if (pcmf) {
-no_p[0] = get_pcm(sps, s->is_pcm, x, y - 1);
-no_p[1] = get_pcm(sps, s->is_pcm, x + 4, y - 1);
-no_q[0] = get_pcm(sps, s->is_pcm, x, y);
-no_q[1] = get_pcm(sps, s->is_pcm, x + 4, y);
+no_p[0] = get_pcm(sps, l->is_pcm, x, y - 1);
+no_p[1] = get_pcm(sps, l->is_pcm, x + 4, y - 1);
+no_q[0] = get_pcm(sps, l->is_pcm, x, y);
+no_q[1] = get_pcm(sps, l->is_pcm, x + 4, y);
 s->hevcdsp.hevc_h_loop_filter_luma_c(src, linesize[LUMA],
  beta, tc, no_p, no_q);
 } else
@@ -624,10 +624,10 @@ static void deblocking_filter_CTB(const HEVCContext *s, 
const HEVCLayerContext *
 c_tc[1] = (bs1 == 2) ? chroma_tc(pps, sps, qp1, 
chroma, tc_offset) : 0;
 src   = &data[chroma][(y >> sps->vshift[chroma]) * 
linesize[chroma] + ((x

[FFmpeg-devel] [PATCH 22/42] lavc/hevcdec: move HEVCContext.sao_pixel_buffer_[vh] to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
Handle them together with other sps-dependent arrays.

Note that current code only allocates these arrays when hwaccel is not
set, but this is wrong as the relevant code runs BEFORE get_format() is
called and hence before we know whether hwaccel is in use.
---
 libavcodec/hevc/filter.c  | 22 +++
 libavcodec/hevc/hevcdec.c | 59 ---
 libavcodec/hevc/hevcdec.h |  5 ++--
 3 files changed, 38 insertions(+), 48 deletions(-)

diff --git a/libavcodec/hevc/filter.c b/libavcodec/hevc/filter.c
index db82f2319f..298f1792b2 100644
--- a/libavcodec/hevc/filter.c
+++ b/libavcodec/hevc/filter.c
@@ -204,7 +204,7 @@ static void copy_vert(uint8_t *dst, const uint8_t *src,
 }
 }
 
-static void copy_CTB_to_hv(const HEVCContext *s, const HEVCSPS *sps,
+static void copy_CTB_to_hv(const HEVCLayerContext *l, const HEVCSPS *sps,
const uint8_t *src,
ptrdiff_t stride_src, int x, int y, int width, int 
height,
int c_idx, int x_ctb, int y_ctb)
@@ -214,15 +214,15 @@ static void copy_CTB_to_hv(const HEVCContext *s, const 
HEVCSPS *sps,
 int h = sps->height >> sps->vshift[c_idx];
 
 /* copy horizontal edges */
-memcpy(s->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb) * w + x) << sh),
+memcpy(l->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb) * w + x) << sh),
 src, width << sh);
-memcpy(s->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb + 1) * w + x) << sh),
+memcpy(l->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb + 1) * w + x) << sh),
 src + stride_src * (height - 1), width << sh);
 
 /* copy vertical edges */
-copy_vert(s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb) * h + y) << sh), 
src, sh, height, 1 << sh, stride_src);
+copy_vert(l->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb) * h + y) << sh), 
src, sh, height, 1 << sh, stride_src);
 
-copy_vert(s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 1) * h + y) << 
sh), src + ((width - 1) << sh), sh, height, 1 << sh, stride_src);
+copy_vert(l->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 1) * h + y) << 
sh), src + ((width - 1) << sh), sh, height, 1 << sh, stride_src);
 }
 
 static void restore_tqb_pixels(const HEVCLayerContext *l,
@@ -343,7 +343,7 @@ static void sao_filter_CTB(HEVCLocalContext *lc, const 
HEVCLayerContext *l,
 
 switch (sao->type_idx[c_idx]) {
 case SAO_BAND:
-copy_CTB_to_hv(s, sps, src, stride_src, x0, y0, width, height, 
c_idx,
+copy_CTB_to_hv(l, sps, src, stride_src, x0, y0, width, height, 
c_idx,
x_ctb, y_ctb);
 if (pps->transquant_bypass_enable_flag ||
 (sps->pcm_loop_filter_disabled && sps->pcm_enabled)) {
@@ -385,7 +385,7 @@ static void sao_filter_CTB(HEVCLocalContext *lc, const 
HEVCLayerContext *l,
 
 dst1 = dst - stride_dst - (left << sh);
 src1[0] = src - stride_src - (left << sh);
-src1[1] = s->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb - 1) * w 
+ x0 - left) << sh);
+src1[1] = l->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb - 1) * w 
+ x0 - left) << sh);
 pos = 0;
 if (left) {
 src_idx = (CTB(l->sao, x_ctb-1, y_ctb-1).type_idx[c_idx] ==
@@ -412,7 +412,7 @@ static void sao_filter_CTB(HEVCLocalContext *lc, const 
HEVCLayerContext *l,
 
 dst1 = dst + height * stride_dst - (left << sh);
 src1[0] = src + height * stride_src - (left << sh);
-src1[1] = s->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb + 2) * w 
+ x0 - left) << sh);
+src1[1] = l->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb + 2) * w 
+ x0 - left) << sh);
 pos = 0;
 if (left) {
 src_idx = (CTB(l->sao, x_ctb-1, y_ctb+1).type_idx[c_idx] ==
@@ -434,7 +434,7 @@ static void sao_filter_CTB(HEVCLocalContext *lc, const 
HEVCLayerContext *l,
 if (!left_edge) {
 if (CTB(l->sao, x_ctb-1, y_ctb).type_idx[c_idx] == 
SAO_APPLIED) {
 copy_vert(dst - (1 << sh),
-  s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb - 1) 
* h + y0) << sh),
+  l->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb - 1) 
* h + y0) << sh),
   sh, height, stride_dst, 1 << sh);
 } else {
 left_pixels = 1;
@@ -444,7 +444,7 @@ static void sao_filter_CTB(HEVCLocalContext *lc, const 
HEVCLayerContext *l,
 if (!right_edge) {
 if (CTB(l->sao, x_ctb+1, y_ctb).type_idx[c_idx] == 
SAO_APPLIED) {
 copy_vert(dst + (width << sh),
-  s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 2) 
* h + y0) << sh),
+  l->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 2) 
* h + y0) << sh),
   sh, height, stride_dst, 1 << sh);
  

[FFmpeg-devel] [PATCH 05/42] lavfi/f_select: allow selection based on view ID

2024-08-27 Thread Anton Khirnov
Can be used together with the split filter to decompose multiview video
into individual views.
---
 doc/filters.texi   | 3 +++
 libavfilter/f_select.c | 9 +
 2 files changed, 12 insertions(+)

diff --git a/doc/filters.texi b/doc/filters.texi
index 2eb4a380fb..3d524e5d96 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -31043,6 +31043,9 @@ Represents the width of the input video frame.
 @item ih @emph{(video only)}
 Represents the height of the input video frame.
 
+@item view @emph{(video only)}
+View ID for multi-view video.
+
 @end table
 
 The default value of the select expression is "1".
diff --git a/libavfilter/f_select.c b/libavfilter/f_select.c
index 6ba96bd7c5..ba0ae31f1b 100644
--- a/libavfilter/f_select.c
+++ b/libavfilter/f_select.c
@@ -93,6 +93,8 @@ static const char *const var_names[] = {
 "ih",///< ih: Represents the height of the input video 
frame.
 "iw",///< iw: Represents the width of the input video 
frame.
 
+"view",
+
 NULL
 };
 
@@ -150,6 +152,8 @@ enum var_name {
 VAR_IH,
 VAR_IW,
 
+VAR_VIEW,
+
 VAR_VARS_NB
 };
 
@@ -343,6 +347,7 @@ static void select_frame(AVFilterContext *ctx, AVFrame 
*frame)
 SelectContext *select = ctx->priv;
 AVFilterLink *inlink = ctx->inputs[0];
 FilterLink  *inl = ff_filter_link(inlink);
+const AVFrameSideData *sd;
 double res;
 
 if (isnan(select->var_values[VAR_START_PTS]))
@@ -381,6 +386,10 @@ FF_ENABLE_DEPRECATION_WARNINGS
 snprintf(buf, sizeof(buf), "%f", select->var_values[VAR_SCENE]);
 av_dict_set(&frame->metadata, "lavfi.scene_score", buf, 0);
 }
+
+sd = av_frame_side_data_get(frame->side_data, frame->nb_side_data,
+AV_FRAME_DATA_VIEW_ID);
+select->var_values[VAR_VIEW] = sd ? *(int*)sd->data : NAN;
 break;
 }
 
-- 
2.43.0

___
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 07/42] lavc/hevcdec: add a per-layer context

2024-08-27 Thread Anton Khirnov
Start by moving the DPB to it.

Only one context exists for now, so decoder behaviour should not change
with this commit, but that will change in the future.
---
 libavcodec/dxva2_hevc.c   |  7 ++--
 libavcodec/hevc/hevcdec.c | 63 +-
 libavcodec/hevc/hevcdec.h | 19 +++---
 libavcodec/hevc/refs.c| 80 +--
 libavcodec/nvdec_hevc.c   |  5 ++-
 libavcodec/vaapi_hevc.c   | 14 ---
 libavcodec/vdpau_hevc.c   |  5 ++-
 libavcodec/vulkan_hevc.c  | 17 +
 8 files changed, 120 insertions(+), 90 deletions(-)

diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c
index 97e51d15de..d01d1e76e8 100644
--- a/libavcodec/dxva2_hevc.c
+++ b/libavcodec/dxva2_hevc.c
@@ -61,6 +61,7 @@ void ff_dxva2_hevc_fill_picture_parameters(const 
AVCodecContext *avctx, AVDXVACo
 DXVA_PicParams_HEVC *pp)
 {
 const HEVCContext *h = avctx->priv_data;
+const HEVCLayerContext *l = &h->layers[h->cur_layer];
 const HEVCFrame *current_picture = h->cur_frame;
 const HEVCPPS *pps = h->pps;
 const HEVCSPS *sps = pps->sps;
@@ -163,9 +164,9 @@ void ff_dxva2_hevc_fill_picture_parameters(const 
AVCodecContext *avctx, AVDXVACo
 // fill RefPicList from the DPB
 for (i = 0, j = 0; i < FF_ARRAY_ELEMS(pp->RefPicList); i++) {
 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)))
-frame = &h->DPB[j];
+while (!frame && j < FF_ARRAY_ELEMS(l->DPB)) {
+if (&l->DPB[j] != current_picture && (l->DPB[j].flags & 
(HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF)))
+frame = &l->DPB[j];
 j++;
 }
 
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 4077ed3ac5..669c8f550b 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -2902,7 +2902,7 @@ static int set_side_data(HEVCContext *s)
 return 0;
 }
 
-static int hevc_frame_start(HEVCContext *s)
+static int hevc_frame_start(HEVCContext *s, HEVCLayerContext *l)
 {
 const HEVCPPS *const pps = s->ps.pps_list[s->sh.pps_id];
 const HEVCSPS *const sps = pps->sps;
@@ -2915,7 +2915,7 @@ static int hevc_frame_start(HEVCContext *s)
 if (s->ps.sps != sps) {
 enum AVPixelFormat pix_fmt;
 
-ff_hevc_clear_refs(s);
+ff_hevc_clear_refs(l);
 
 ret = set_sps(s, sps);
 if (ret < 0)
@@ -2938,7 +2938,7 @@ static int hevc_frame_start(HEVCContext *s)
 memset(s->tab_slice_address, -1, pic_size_in_ctb * 
sizeof(*s->tab_slice_address));
 
 if (IS_IDR(s))
-ff_hevc_clear_refs(s);
+ff_hevc_clear_refs(l);
 
 s->slice_idx = 0;
 s->first_nal_type= s->nal_unit_type;
@@ -2963,7 +2963,7 @@ static int hevc_frame_start(HEVCContext *s)
 s->local_ctx[0].end_of_tiles_x = pps->column_width[0] << 
sps->log2_ctb_size;
 
 if (new_sequence) {
-ret = ff_hevc_output_frames(s, 0, 0, 
s->sh.no_output_of_prior_pics_flag);
+ret = ff_hevc_output_frames(s, l, 0, 0, 
s->sh.no_output_of_prior_pics_flag);
 if (ret < 0)
 return ret;
 }
@@ -2972,11 +2972,11 @@ static int hevc_frame_start(HEVCContext *s)
 if (ret < 0)
 return ret;
 
-ret = ff_hevc_set_new_ref(s, s->poc);
+ret = ff_hevc_set_new_ref(s, l, s->poc);
 if (ret < 0)
 goto fail;
 
-ret = ff_hevc_frame_rps(s);
+ret = ff_hevc_frame_rps(s, l);
 if (ret < 0) {
 av_log(s->avctx, AV_LOG_ERROR, "Error constructing the frame RPS.\n");
 goto fail;
@@ -3020,7 +3020,7 @@ static int hevc_frame_start(HEVCContext *s)
 
 s->cur_frame->f->pict_type = 3 - s->sh.slice_type;
 
-ret = ff_hevc_output_frames(s, sps->temporal_layer[sps->max_sub_layers - 
1].num_reorder_pics,
+ret = ff_hevc_output_frames(s, l, sps->temporal_layer[sps->max_sub_layers 
- 1].num_reorder_pics,
 sps->temporal_layer[sps->max_sub_layers - 
1].max_dec_pic_buffering, 0);
 if (ret < 0)
 goto fail;
@@ -3158,7 +3158,8 @@ static int hevc_frame_end(HEVCContext *s)
 return 0;
 }
 
-static int decode_slice(HEVCContext *s, const H2645NAL *nal, GetBitContext *gb)
+static int decode_slice(HEVCContext *s, HEVCLayerContext *l,
+const H2645NAL *nal, GetBitContext *gb)
 {
 int ret;
 
@@ -3183,7 +3184,7 @@ static int decode_slice(HEVCContext *s, const H2645NAL 
*nal, GetBitContext *gb)
 return AVERROR_INVALIDDATA;
 }
 
-ret = hevc_frame_start(s);
+ret = hevc_frame_start(s, l);
 if (ret < 0)
 return ret;
 } else if (!s->cur_frame) {
@@ -3207,6 +3208,7 @@ static int decode_slice(HEVCContext *s, const H2645NAL 
*nal, GetBitContext *gb)
 
 static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal)
 {
+

[FFmpeg-devel] [PATCH 10/42] lavc/hevcdec: move HEVCContext.sao to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
---
 libavcodec/hevc/filter.c  | 29 +++--
 libavcodec/hevc/hevcdec.c | 29 +++--
 libavcodec/hevc/hevcdec.h |  3 ++-
 3 files changed, 32 insertions(+), 29 deletions(-)

diff --git a/libavcodec/hevc/filter.c b/libavcodec/hevc/filter.c
index 18c73dc2fa..78f408f170 100644
--- a/libavcodec/hevc/filter.c
+++ b/libavcodec/hevc/filter.c
@@ -264,7 +264,8 @@ static void restore_tqb_pixels(const HEVCContext *s,
 
 #define CTB(tab, x, y) ((tab)[(y) * sps->ctb_width + (x)])
 
-static void sao_filter_CTB(HEVCLocalContext *lc, const HEVCContext *s,
+static void sao_filter_CTB(HEVCLocalContext *lc, const HEVCLayerContext *l,
+   const HEVCContext *s,
const HEVCPPS *pps, const HEVCSPS *sps,
int x, int y)
 {
@@ -275,7 +276,7 @@ static void sao_filter_CTB(HEVCLocalContext *lc, const 
HEVCContext *s,
 int y_ctb= y >> sps->log2_ctb_size;
 int ctb_addr_rs  = y_ctb * sps->ctb_width + x_ctb;
 int ctb_addr_ts  = pps->ctb_addr_rs_to_ts[ctb_addr_rs];
-SAOParams *sao   = &CTB(s->sao, x_ctb, y_ctb);
+SAOParams *sao   = &CTB(l->sao, x_ctb, y_ctb);
 // flags indicating unfilterable edges
 uint8_t vert_edge[]  = { 0, 0 };
 uint8_t horiz_edge[] = { 0, 0 };
@@ -385,17 +386,17 @@ static void sao_filter_CTB(HEVCLocalContext *lc, const 
HEVCContext *s,
 src1[1] = s->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb - 1) * w 
+ x0 - left) << sh);
 pos = 0;
 if (left) {
-src_idx = (CTB(s->sao, x_ctb-1, y_ctb-1).type_idx[c_idx] ==
+src_idx = (CTB(l->sao, x_ctb-1, y_ctb-1).type_idx[c_idx] ==
SAO_APPLIED);
 copy_pixel(dst1, src1[src_idx], sh);
 pos += (1 << sh);
 }
-src_idx = (CTB(s->sao, x_ctb, y_ctb-1).type_idx[c_idx] ==
+src_idx = (CTB(l->sao, x_ctb, y_ctb-1).type_idx[c_idx] ==
SAO_APPLIED);
 memcpy(dst1 + pos, src1[src_idx] + pos, width << sh);
 if (right) {
 pos += width << sh;
-src_idx = (CTB(s->sao, x_ctb+1, y_ctb-1).type_idx[c_idx] ==
+src_idx = (CTB(l->sao, x_ctb+1, y_ctb-1).type_idx[c_idx] ==
SAO_APPLIED);
 copy_pixel(dst1 + pos, src1[src_idx] + pos, sh);
 }
@@ -412,24 +413,24 @@ static void sao_filter_CTB(HEVCLocalContext *lc, const 
HEVCContext *s,
 src1[1] = s->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb + 2) * w 
+ x0 - left) << sh);
 pos = 0;
 if (left) {
-src_idx = (CTB(s->sao, x_ctb-1, y_ctb+1).type_idx[c_idx] ==
+src_idx = (CTB(l->sao, x_ctb-1, y_ctb+1).type_idx[c_idx] ==
SAO_APPLIED);
 copy_pixel(dst1, src1[src_idx], sh);
 pos += (1 << sh);
 }
-src_idx = (CTB(s->sao, x_ctb, y_ctb+1).type_idx[c_idx] ==
+src_idx = (CTB(l->sao, x_ctb, y_ctb+1).type_idx[c_idx] ==
SAO_APPLIED);
 memcpy(dst1 + pos, src1[src_idx] + pos, width << sh);
 if (right) {
 pos += width << sh;
-src_idx = (CTB(s->sao, x_ctb+1, y_ctb+1).type_idx[c_idx] ==
+src_idx = (CTB(l->sao, x_ctb+1, y_ctb+1).type_idx[c_idx] ==
SAO_APPLIED);
 copy_pixel(dst1 + pos, src1[src_idx] + pos, sh);
 }
 }
 left_pixels = 0;
 if (!left_edge) {
-if (CTB(s->sao, x_ctb-1, y_ctb).type_idx[c_idx] == 
SAO_APPLIED) {
+if (CTB(l->sao, x_ctb-1, y_ctb).type_idx[c_idx] == 
SAO_APPLIED) {
 copy_vert(dst - (1 << sh),
   s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb - 1) 
* h + y0) << sh),
   sh, height, stride_dst, 1 << sh);
@@ -439,7 +440,7 @@ static void sao_filter_CTB(HEVCLocalContext *lc, const 
HEVCContext *s,
 }
 right_pixels = 0;
 if (!right_edge) {
-if (CTB(s->sao, x_ctb+1, y_ctb).type_idx[c_idx] == 
SAO_APPLIED) {
+if (CTB(l->sao, x_ctb+1, y_ctb).type_idx[c_idx] == 
SAO_APPLIED) {
 copy_vert(dst + (width << sh),
   s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 2) 
* h + y0) << sh),
   sh, height, stride_dst, 1 << sh);
@@ -889,16 +890,16 @@ void ff_hevc_hls_filter(HEVCLocalContext *lc, const 
HEVCLayerContext *l,
 if (sps->sao_enabled && !skip) {
 int y_end = y >= sps->height - ctb_size;
 if (y && x)
-

[FFmpeg-devel] [PATCH 14/42] lavc/hevcdec: move HEVCContext.cbf_luma to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
---
 libavcodec/hevc/filter.c  |  8 
 libavcodec/hevc/hevcdec.c | 10 +-
 libavcodec/hevc/hevcdec.h |  4 +++-
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/libavcodec/hevc/filter.c b/libavcodec/hevc/filter.c
index 4d5ef631d7..379c488d78 100644
--- a/libavcodec/hevc/filter.c
+++ b/libavcodec/hevc/filter.c
@@ -777,8 +777,8 @@ void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext 
*lc, const HEVCLayer
 int x_tu = (x0 + i) >> log2_min_tu_size;
 const MvField *top  = &tab_mvf[yp_pu * min_pu_width + x_pu];
 const MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu];
-uint8_t top_cbf_luma  = s->cbf_luma[yp_tu * min_tu_width + 
x_tu];
-uint8_t curr_cbf_luma = s->cbf_luma[yq_tu * min_tu_width + 
x_tu];
+uint8_t top_cbf_luma  = l->cbf_luma[yp_tu * min_tu_width + 
x_tu];
+uint8_t curr_cbf_luma = l->cbf_luma[yq_tu * min_tu_width + 
x_tu];
 
 if (curr->pred_flag == PF_INTRA || top->pred_flag == PF_INTRA)
 bs = 2;
@@ -815,8 +815,8 @@ void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext 
*lc, const HEVCLayer
 int y_tu  = (y0 + i) >> log2_min_tu_size;
 const MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu];
 const MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu];
-uint8_t left_cbf_luma = s->cbf_luma[y_tu * min_tu_width + 
xp_tu];
-uint8_t curr_cbf_luma = s->cbf_luma[y_tu * min_tu_width + 
xq_tu];
+uint8_t left_cbf_luma = l->cbf_luma[y_tu * min_tu_width + 
xp_tu];
+uint8_t curr_cbf_luma = l->cbf_luma[y_tu * min_tu_width + 
xq_tu];
 
 if (curr->pred_flag == PF_INTRA || left->pred_flag == PF_INTRA)
 bs = 2;
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 8f0f761ee5..1887a44e3e 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -75,7 +75,7 @@ static void pic_arrays_free(HEVCContext *s, HEVCLayerContext 
*l)
 av_freep(&l->tab_ct_depth);
 
 av_freep(&s->tab_ipm);
-av_freep(&s->cbf_luma);
+av_freep(&l->cbf_luma);
 av_freep(&s->is_pcm);
 
 av_freep(&s->qp_y_tab);
@@ -113,10 +113,10 @@ static int pic_arrays_init(HEVCContext *s, 
HEVCLayerContext *l, const HEVCSPS *s
 if (!l->skip_flag || !l->tab_ct_depth)
 goto fail;
 
-s->cbf_luma = av_malloc_array(sps->min_tb_width, sps->min_tb_height);
+l->cbf_luma = av_malloc_array(sps->min_tb_width, sps->min_tb_height);
 s->tab_ipm  = av_mallocz(min_pu_size);
 s->is_pcm   = av_malloc_array(sps->min_pu_width + 1, sps->min_pu_height + 
1);
-if (!s->tab_ipm || !s->cbf_luma || !s->is_pcm)
+if (!s->tab_ipm || !l->cbf_luma || !s->is_pcm)
 goto fail;
 
 s->filter_slice_edges = av_mallocz(ctb_count);
@@ -1431,7 +1431,7 @@ do {
 for (j = 0; j < (1 << log2_trafo_size); j += min_tu_size) {
 int x_tu = (x0 + j) >> log2_min_tu_size;
 int y_tu = (y0 + i) >> log2_min_tu_size;
-s->cbf_luma[y_tu * min_tu_width + x_tu] = 1;
+l->cbf_luma[y_tu * min_tu_width + x_tu] = 1;
 }
 }
 if (!s->sh.disable_deblocking_filter_flag) {
@@ -2951,7 +2951,7 @@ static int hevc_frame_start(HEVCContext *s, 
HEVCLayerContext *l)
 
 memset(s->horizontal_bs, 0, l->bs_width * l->bs_height);
 memset(s->vertical_bs,   0, l->bs_width * l->bs_height);
-memset(s->cbf_luma,  0, sps->min_tb_width * sps->min_tb_height);
+memset(l->cbf_luma,  0, sps->min_tb_width * sps->min_tb_height);
 memset(s->is_pcm,0, (sps->min_pu_width + 1) * (sps->min_pu_height 
+ 1));
 memset(s->tab_slice_address, -1, pic_size_in_ctb * 
sizeof(*s->tab_slice_address));
 
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index 59c8587787..ccea7a46e1 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -450,6 +450,9 @@ typedef struct HEVCLayerContext {
 //  CU
 uint8_t*skip_flag;
 uint8_t*tab_ct_depth;
+
+// PU
+uint8_t*cbf_luma; // cbf_luma of colocated TU
 } HEVCLayerContext;
 
 typedef struct HEVCContext {
@@ -510,7 +513,6 @@ typedef struct HEVCContext {
 // PU
 uint8_t *tab_ipm;
 
-uint8_t *cbf_luma; // cbf_luma of colocated TU
 uint8_t *is_pcm;
 
 // CTB-level flags affecting loop filter operation
-- 
2.43.0

___
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 08/42] lavc/hevcdec: move active VPS from HEVCParamSets to HEVCContext

2024-08-27 Thread Anton Khirnov
Active VPS is a property of the decoding process, not of the list of
parameter sets.

Check that the VPS can only change in a base layer - while this can
never happen currently (as no other layers can exist in the decoder), it
will become useful when multilayer decoding is supported.
---
 libavcodec/hevc/hevcdec.c | 11 +--
 libavcodec/hevc/hevcdec.h |  1 +
 libavcodec/hevc/ps.c  |  4 
 libavcodec/hevc/ps.h  |  1 -
 4 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 669c8f550b..b44bc93507 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -533,7 +533,7 @@ static int set_sps(HEVCContext *s, const HEVCSPS *sps)
 
 pic_arrays_free(s);
 s->ps.sps = NULL;
-s->ps.vps = NULL;
+ff_refstruct_unref(&s->vps);
 
 if (!sps)
 return 0;
@@ -571,7 +571,7 @@ static int set_sps(HEVCContext *s, const HEVCSPS *sps)
 }
 
 s->ps.sps = sps;
-s->ps.vps = sps->vps;
+s->vps= ff_refstruct_ref_c(sps->vps);
 
 return 0;
 
@@ -2911,6 +2911,12 @@ static int hevc_frame_start(HEVCContext *s, 
HEVCLayerContext *l)
 int new_sequence = IS_IDR(s) || IS_BLA(s) || s->last_eos;
 int ret;
 
+if (sps->vps != s->vps && l != &s->layers[0]) {
+av_log(s->avctx, AV_LOG_ERROR, "VPS changed in a non-base layer\n");
+set_sps(s, NULL, AV_PIX_FMT_NONE);
+return AVERROR_INVALIDDATA;
+}
+
 ff_refstruct_replace(&s->pps, pps);
 if (s->ps.sps != sps) {
 enum AVPixelFormat pix_fmt;
@@ -3505,6 +3511,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx)
 
 pic_arrays_free(s);
 
+ff_refstruct_unref(&s->vps);
 ff_refstruct_unref(&s->pps);
 
 ff_dovi_ctx_unref(&s->dovi_ctx);
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index aab09bfd94..be5d76c183 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -470,6 +470,7 @@ typedef struct HEVCContext {
 ///< candidate references for the current frame
 RefPicList rps[5];
 
+const HEVCVPS *vps; ///< RefStruct reference
 const HEVCPPS *pps; ///< RefStruct reference
 SliceHeader sh;
 SAOParams *sao;
diff --git a/libavcodec/hevc/ps.c b/libavcodec/hevc/ps.c
index dbdfc16cfa..99382876af 100644
--- a/libavcodec/hevc/ps.c
+++ b/libavcodec/hevc/ps.c
@@ -83,9 +83,6 @@ static void remove_vps(HEVCParamSets *s, int id)
 {
 int i;
 if (s->vps_list[id]) {
-if (s->vps == s->vps_list[id])
-s->vps = NULL;
-
 for (i = 0; i < FF_ARRAY_ELEMS(s->sps_list); i++)
 if (s->sps_list[i] && s->sps_list[i]->vps_id == id)
 remove_sps(s, i);
@@ -2047,7 +2044,6 @@ void ff_hevc_ps_uninit(HEVCParamSets *ps)
 ff_refstruct_unref(&ps->pps_list[i]);
 
 ps->sps = NULL;
-ps->vps = NULL;
 }
 
 int ff_hevc_compute_poc(const HEVCSPS *sps, int pocTid0, int poc_lsb, int 
nal_unit_type)
diff --git a/libavcodec/hevc/ps.h b/libavcodec/hevc/ps.h
index 17395c5510..554c86a656 100644
--- a/libavcodec/hevc/ps.h
+++ b/libavcodec/hevc/ps.h
@@ -449,7 +449,6 @@ typedef struct HEVCParamSets {
 const HEVCPPS *pps_list[HEVC_MAX_PPS_COUNT]; ///< RefStruct references
 
 /* currently active parameter sets */
-const HEVCVPS *vps;
 const HEVCSPS *sps;
 } HEVCParamSets;
 
-- 
2.43.0

___
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 18/42] lavc/hevcdec: move HEVCContext.tab_slice_address to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
---
 libavcodec/hevc/filter.c  | 16 
 libavcodec/hevc/hevcdec.c | 34 ++
 libavcodec/hevc/hevcdec.h |  4 ++--
 3 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/libavcodec/hevc/filter.c b/libavcodec/hevc/filter.c
index 12a57eb223..14afb147b9 100644
--- a/libavcodec/hevc/filter.c
+++ b/libavcodec/hevc/filter.c
@@ -298,31 +298,31 @@ static void sao_filter_CTB(HEVCLocalContext *lc, const 
HEVCLayerContext *l,
 if (restore) {
 if (!edges[0]) {
 left_tile_edge  = no_tile_filter && pps->tile_id[ctb_addr_ts] != 
pps->tile_id[pps->ctb_addr_rs_to_ts[ctb_addr_rs-1]];
-vert_edge[0]= (!lfase && CTB(s->tab_slice_address, x_ctb, 
y_ctb) != CTB(s->tab_slice_address, x_ctb - 1, y_ctb)) || left_tile_edge;
+vert_edge[0]= (!lfase && CTB(l->tab_slice_address, x_ctb, 
y_ctb) != CTB(l->tab_slice_address, x_ctb - 1, y_ctb)) || left_tile_edge;
 }
 if (!edges[2]) {
 right_tile_edge = no_tile_filter && pps->tile_id[ctb_addr_ts] != 
pps->tile_id[pps->ctb_addr_rs_to_ts[ctb_addr_rs+1]];
-vert_edge[1]= (!lfase && CTB(s->tab_slice_address, x_ctb, 
y_ctb) != CTB(s->tab_slice_address, x_ctb + 1, y_ctb)) || right_tile_edge;
+vert_edge[1]= (!lfase && CTB(l->tab_slice_address, x_ctb, 
y_ctb) != CTB(l->tab_slice_address, x_ctb + 1, y_ctb)) || right_tile_edge;
 }
 if (!edges[1]) {
 up_tile_edge = no_tile_filter && pps->tile_id[ctb_addr_ts] != 
pps->tile_id[pps->ctb_addr_rs_to_ts[ctb_addr_rs - sps->ctb_width]];
-horiz_edge[0]= (!lfase && CTB(s->tab_slice_address, x_ctb, 
y_ctb) != CTB(s->tab_slice_address, x_ctb, y_ctb - 1)) || up_tile_edge;
+horiz_edge[0]= (!lfase && CTB(l->tab_slice_address, x_ctb, 
y_ctb) != CTB(l->tab_slice_address, x_ctb, y_ctb - 1)) || up_tile_edge;
 }
 if (!edges[3]) {
 bottom_tile_edge = no_tile_filter && pps->tile_id[ctb_addr_ts] != 
pps->tile_id[pps->ctb_addr_rs_to_ts[ctb_addr_rs + sps->ctb_width]];
-horiz_edge[1]= (!lfase && CTB(s->tab_slice_address, x_ctb, 
y_ctb) != CTB(s->tab_slice_address, x_ctb, y_ctb + 1)) || bottom_tile_edge;
+horiz_edge[1]= (!lfase && CTB(l->tab_slice_address, x_ctb, 
y_ctb) != CTB(l->tab_slice_address, x_ctb, y_ctb + 1)) || bottom_tile_edge;
 }
 if (!edges[0] && !edges[1]) {
-diag_edge[0] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) 
!= CTB(s->tab_slice_address, x_ctb - 1, y_ctb - 1)) || left_tile_edge || 
up_tile_edge;
+diag_edge[0] = (!lfase && CTB(l->tab_slice_address, x_ctb, y_ctb) 
!= CTB(l->tab_slice_address, x_ctb - 1, y_ctb - 1)) || left_tile_edge || 
up_tile_edge;
 }
 if (!edges[1] && !edges[2]) {
-diag_edge[1] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) 
!= CTB(s->tab_slice_address, x_ctb + 1, y_ctb - 1)) || right_tile_edge || 
up_tile_edge;
+diag_edge[1] = (!lfase && CTB(l->tab_slice_address, x_ctb, y_ctb) 
!= CTB(l->tab_slice_address, x_ctb + 1, y_ctb - 1)) || right_tile_edge || 
up_tile_edge;
 }
 if (!edges[2] && !edges[3]) {
-diag_edge[2] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) 
!= CTB(s->tab_slice_address, x_ctb + 1, y_ctb + 1)) || right_tile_edge || 
bottom_tile_edge;
+diag_edge[2] = (!lfase && CTB(l->tab_slice_address, x_ctb, y_ctb) 
!= CTB(l->tab_slice_address, x_ctb + 1, y_ctb + 1)) || right_tile_edge || 
bottom_tile_edge;
 }
 if (!edges[0] && !edges[3]) {
-diag_edge[3] = (!lfase && CTB(s->tab_slice_address, x_ctb, y_ctb) 
!= CTB(s->tab_slice_address, x_ctb - 1, y_ctb + 1)) || left_tile_edge || 
bottom_tile_edge;
+diag_edge[3] = (!lfase && CTB(l->tab_slice_address, x_ctb, y_ctb) 
!= CTB(l->tab_slice_address, x_ctb - 1, y_ctb + 1)) || left_tile_edge || 
bottom_tile_edge;
 }
 }
 
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 4174743eb6..3561a3a3ad 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -79,7 +79,7 @@ static void pic_arrays_free(HEVCContext *s, HEVCLayerContext 
*l)
 av_freep(&l->is_pcm);
 
 av_freep(&s->qp_y_tab);
-av_freep(&s->tab_slice_address);
+av_freep(&l->tab_slice_address);
 av_freep(&l->filter_slice_edges);
 
 av_freep(&s->horizontal_bs);
@@ -120,11 +120,11 @@ static int pic_arrays_init(HEVCContext *s, 
HEVCLayerContext *l, const HEVCSPS *s
 goto fail;
 
 l->filter_slice_edges = av_mallocz(ctb_count);
-s->tab_slice_address  = av_malloc_array(pic_size_in_ctb,
-  sizeof(*s->tab_slice_address));
+l->tab_slice_address  = av_malloc_array(pic_size_in_ctb,
+  sizeof(*l->tab_slice_address));
 s->qp_y_tab   = av_malloc_array(pic_size_in_ctb,
   sizeof(*s->qp_y

[FFmpeg-devel] [PATCH 20/42] lavc/hevcdec: move HEVCContext.{horizontal, vertical}_bs to HEVCLayerContext

2024-08-27 Thread Anton Khirnov
---
 libavcodec/hevc/filter.c  | 24 
 libavcodec/hevc/hevcdec.c | 14 +++---
 libavcodec/hevc/hevcdec.h |  5 +++--
 3 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/libavcodec/hevc/filter.c b/libavcodec/hevc/filter.c
index ad655a2b36..db82f2319f 100644
--- a/libavcodec/hevc/filter.c
+++ b/libavcodec/hevc/filter.c
@@ -549,8 +549,8 @@ static void deblocking_filter_CTB(const HEVCContext *s, 
const HEVCLayerContext *
 for (y = y0; y < y_end; y += 8) {
 // vertical filtering luma
 for (x = x0 ? x0 : 8; x < x_end; x += 8) {
-const int bs0 = s->vertical_bs[(x +  y  * l->bs_width) >> 2];
-const int bs1 = s->vertical_bs[(x + (y + 4) * l->bs_width) >> 2];
+const int bs0 = l->vertical_bs[(x +  y  * l->bs_width) >> 2];
+const int bs1 = l->vertical_bs[(x + (y + 4) * l->bs_width) >> 2];
 if (bs0 || bs1) {
 const int qp = (get_qPy(sps, l->qp_y_tab, x - 1, y) +
 get_qPy(sps, l->qp_y_tab, x, y) + 1) >> 1;
@@ -578,8 +578,8 @@ static void deblocking_filter_CTB(const HEVCContext *s, 
const HEVCLayerContext *
 
 // horizontal filtering luma
 for (x = x0 ? x0 - 8 : 0; x < x_end2; x += 8) {
-const int bs0 = s->horizontal_bs[( x  + y * l->bs_width) >> 2];
-const int bs1 = s->horizontal_bs[((x + 4) + y * l->bs_width) >> 2];
+const int bs0 = l->horizontal_bs[( x  + y * l->bs_width) >> 2];
+const int bs1 = l->horizontal_bs[((x + 4) + y * l->bs_width) >> 2];
 if (bs0 || bs1) {
 const int qp = (get_qPy(sps, l->qp_y_tab, x, y - 1) +
 get_qPy(sps, l->qp_y_tab, x, y) + 1) >> 1;
@@ -613,8 +613,8 @@ static void deblocking_filter_CTB(const HEVCContext *s, 
const HEVCLayerContext *
 // vertical filtering chroma
 for (y = y0; y < y_end; y += (8 * v)) {
 for (x = x0 ? x0 : 8 * h; x < x_end; x += (8 * h)) {
-const int bs0 = s->vertical_bs[(x +  y* 
l->bs_width) >> 2];
-const int bs1 = s->vertical_bs[(x + (y + (4 * v)) * 
l->bs_width) >> 2];
+const int bs0 = l->vertical_bs[(x +  y* 
l->bs_width) >> 2];
+const int bs1 = l->vertical_bs[(x + (y + (4 * v)) * 
l->bs_width) >> 2];
 
 if ((bs0 == 2) || (bs1 == 2)) {
 const int qp0 = (get_qPy(sps, l->qp_y_tab, x - 1, y) +
@@ -647,8 +647,8 @@ static void deblocking_filter_CTB(const HEVCContext *s, 
const HEVCLayerContext *
 if (x_end != sps->width)
 x_end2 = x_end - 8 * h;
 for (x = x0 ? x0 - 8 * h : 0; x < x_end2; x += (8 * h)) {
-const int bs0 = s->horizontal_bs[( x  + y * 
l->bs_width) >> 2];
-const int bs1 = s->horizontal_bs[((x + 4 * h) + y * 
l->bs_width) >> 2];
+const int bs0 = l->horizontal_bs[( x  + y * 
l->bs_width) >> 2];
+const int bs1 = l->horizontal_bs[((x + 4 * h) + y * 
l->bs_width) >> 2];
 if ((bs0 == 2) || (bs1 == 2)) {
 const int qp0 = bs0 == 2 ? (get_qPy(sps, l->qp_y_tab, 
x,   y - 1) +
 get_qPy(sps, l->qp_y_tab, 
x,   y) + 1) >> 1 : 0;
@@ -788,7 +788,7 @@ void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext 
*lc, const HEVCLayer
 bs = 1;
 else
 bs = boundary_strength(s, curr, top, rpl_top);
-s->horizontal_bs[((x0 + i) + y0 * l->bs_width) >> 2] = bs;
+l->horizontal_bs[((x0 + i) + y0 * l->bs_width) >> 2] = bs;
 }
 }
 
@@ -826,7 +826,7 @@ void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext 
*lc, const HEVCLayer
 bs = 1;
 else
 bs = boundary_strength(s, curr, left, rpl_left);
-s->vertical_bs[(x0 + (y0 + i) * l->bs_width) >> 2] = bs;
+l->vertical_bs[(x0 + (y0 + i) * l->bs_width) >> 2] = bs;
 }
 }
 
@@ -844,7 +844,7 @@ void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext 
*lc, const HEVCLayer
 const MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu];
 
 bs = boundary_strength(s, curr, top, rpl);
-s->horizontal_bs[((x0 + i) + (y0 + j) * l->bs_width) >> 2] = 
bs;
+l->horizontal_bs[((x0 + i) + (y0 + j) * l->bs_width) >> 2] = 
bs;
 }
 }
 
@@ -859,7 +859,7 @@ void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext 
*lc, const HEVCLayer
 const MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu];
 
 bs = boundary_strength(s, curr, left, rpl);
-s->vertical_bs[((x0 + i) + (y

[FFmpeg-devel] [PATCH 33/42] lavc/hevc/hevcdec: implement MV-HEVC inter-layer prediction

2024-08-27 Thread Anton Khirnov
The per-frame reference picture set contains two more lists -
INTER_LAYER[01]. Assuming at most two layers, INTER_LAYER1 is always
empty, but is added anyway for completeness.

When inter-layer prediction is enabled, INTER_LAYER0 for the
second-layer frame will contain the base-layer frame from the same
access unit, if it exists.

The new lists are then used in per-slice reference picture set
construction as per F.8.3.4 "Decoding process for reference picture
lists construction".
---
 libavcodec/hevc/hevcdec.c |  7 -
 libavcodec/hevc/hevcdec.h |  8 --
 libavcodec/hevc/refs.c| 58 ++-
 libavcodec/nvdec_hevc.c   |  2 +-
 libavcodec/vdpau_hevc.c   |  2 +-
 5 files changed, 59 insertions(+), 18 deletions(-)

diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index d9a12279cd..9a549bb0d2 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -784,7 +784,7 @@ static int hls_slice_header(SliceHeader *sh, const 
HEVCContext *s, GetBitContext
 
 sh->rpl_modification_flag[0] = 0;
 sh->rpl_modification_flag[1] = 0;
-nb_refs = ff_hevc_frame_nb_refs(sh, pps);
+nb_refs = ff_hevc_frame_nb_refs(sh, pps, layer_idx);
 if (!nb_refs) {
 av_log(s->avctx, AV_LOG_ERROR, "Zero refs for a frame with P 
or B slices.\n");
 return AVERROR_INVALIDDATA;
@@ -3352,6 +3352,11 @@ static int decode_nal_units(HEVCContext *s, const 
uint8_t *buf, int length)
 s->eos = 0;
 s->slice_initialized = 0;
 
+for (int i = 0; i < FF_ARRAY_ELEMS(s->layers); i++) {
+HEVCLayerContext *l = &s->layers[i];
+l->cur_frame = NULL;
+}
+
 /* split the input packet into NAL units, so we know the upper bound on the
  * number of slices in the frame */
 ret = ff_h2645_packet_split(&s->pkt, buf, length, s->avctx,
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index 7072eee077..eba7cca1a6 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -84,6 +84,8 @@ enum RPSType {
 ST_FOLL,
 LT_CURR,
 LT_FOLL,
+INTER_LAYER0,
+INTER_LAYER1,
 NB_RPS_TYPE,
 };
 
@@ -442,6 +444,7 @@ typedef struct HEVCLocalContext {
 
 typedef struct HEVCLayerContext {
 HEVCFrame   DPB[32];
+HEVCFrame  *cur_frame;
 
 const HEVCSPS  *sps; // RefStruct reference
 
@@ -498,7 +501,7 @@ typedef struct HEVCContext {
 struct AVMD5 *md5_ctx;
 
 ///< candidate references for the current frame
-RefPicList rps[5];
+RefPicList rps[NB_RPS_TYPE];
 
 const HEVCVPS *vps; ///< RefStruct reference
 const HEVCPPS *pps; ///< RefStruct reference
@@ -612,7 +615,8 @@ int ff_hevc_res_scale_sign_flag(HEVCLocalContext *lc, int 
idx);
 /**
  * Get the number of candidate references for the current frame.
  */
-int ff_hevc_frame_nb_refs(const SliceHeader *sh, const HEVCPPS *pps);
+int ff_hevc_frame_nb_refs(const SliceHeader *sh, const HEVCPPS *pps,
+  unsigned layer_idx);
 
 int ff_hevc_set_new_ref(HEVCContext *s, HEVCLayerContext *l, int poc);
 
diff --git a/libavcodec/hevc/refs.c b/libavcodec/hevc/refs.c
index 09d759f936..f93c5893c6 100644
--- a/libavcodec/hevc/refs.c
+++ b/libavcodec/hevc/refs.c
@@ -149,6 +149,7 @@ int ff_hevc_set_new_ref(HEVCContext *s, HEVCLayerContext 
*l, int poc)
 return AVERROR(ENOMEM);
 
 s->cur_frame = ref;
+l->cur_frame = ref;
 s->collocated_ref = NULL;
 
 if (s->sh.pic_output_flag)
@@ -246,7 +247,9 @@ 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->pps->pps_curr_pic_ref_enabled_flag) {
+  s->rps[LT_CURR].nb_refs +
+  s->rps[INTER_LAYER0].nb_refs + s->rps[INTER_LAYER1].nb_refs) &&
+!s->pps->pps_curr_pic_ref_enabled_flag) {
 av_log(s->avctx, AV_LOG_ERROR, "Zero refs in the frame RPS.\n");
 return AVERROR_INVALIDDATA;
 }
@@ -256,11 +259,14 @@ int ff_hevc_slice_rpl(HEVCContext *s)
 RefPicList *rpl = &s->cur_frame->refPicList[list_idx];
 
 /* The order of the elements is
- * ST_CURR_BEF - ST_CURR_AFT - LT_CURR for the L0 and
- * ST_CURR_AFT - ST_CURR_BEF - LT_CURR for the L1 */
-int cand_lists[3] = { list_idx ? ST_CURR_AFT : ST_CURR_BEF,
-  list_idx ? ST_CURR_BEF : ST_CURR_AFT,
-  LT_CURR };
+ * ST_CURR_BEF - INTER_LAYER0 - ST_CURR_AFT - LT_CURR - INTER_LAYER1 
for the L0 and
+ * ST_CURR_AFT - INTER_LAYER1 - ST_CURR_BEF - LT_CURR - INTER_LAYER0 
for the L1 */
+int cand_lists[] = { list_idx ? ST_CURR_AFT : ST_CURR_BEF,
+ list_idx ? INTER_LAYER1 : INTER_LAYER0,
+ list_idx ? ST_CURR_BEF : ST_CURR_AFT,
+ LT_CURR,
+ 

[FFmpeg-devel] [PATCH 37/42] fftools/ffmpeg_sched: allow decoders to have multiple outputs

2024-08-27 Thread Anton Khirnov
Will be useful for multilayer video.
---
 fftools/ffmpeg_dec.c  |  10 ++--
 fftools/ffmpeg_demux.c|   2 +-
 fftools/ffmpeg_filter.c   |   4 +-
 fftools/ffmpeg_mux_init.c |   2 +-
 fftools/ffmpeg_sched.c| 102 --
 fftools/ffmpeg_sched.h|  21 ++--
 6 files changed, 100 insertions(+), 41 deletions(-)

diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c
index c2bcf784b0..54f7223f0f 100644
--- a/fftools/ffmpeg_dec.c
+++ b/fftools/ffmpeg_dec.c
@@ -578,7 +578,7 @@ static int process_subtitle(DecoderPriv *dp, AVFrame *frame)
 if (!subtitle)
 return 0;
 
-ret = sch_dec_send(dp->sch, dp->sch_idx, frame);
+ret = sch_dec_send(dp->sch, dp->sch_idx, 0, frame);
 if (ret < 0)
 av_frame_unref(frame);
 
@@ -620,7 +620,7 @@ static int transcode_subtitles(DecoderPriv *dp, const 
AVPacket *pkt,
 frame->time_base = pkt->time_base;
 frame->opaque= (void*)(intptr_t)FRAME_OPAQUE_SUB_HEARTBEAT;
 
-ret = sch_dec_send(dp->sch, dp->sch_idx, frame);
+ret = sch_dec_send(dp->sch, dp->sch_idx, 0, frame);
 return ret == AVERROR_EOF ? AVERROR_EXIT : ret;
 } else if (pkt && (intptr_t)pkt->opaque == PKT_OPAQUE_FIX_SUB_DURATION) {
 return fix_sub_duration_heartbeat(dp, av_rescale_q(pkt->pts, 
pkt->time_base,
@@ -773,7 +773,7 @@ static int packet_decode(DecoderPriv *dp, AVPacket *pkt, 
AVFrame *frame)
 
 dp->dec.frames_decoded++;
 
-ret = sch_dec_send(dp->sch, dp->sch_idx, frame);
+ret = sch_dec_send(dp->sch, dp->sch_idx, 0, frame);
 if (ret < 0) {
 av_frame_unref(frame);
 return ret == AVERROR_EOF ? AVERROR_EXIT : ret;
@@ -951,7 +951,7 @@ static int decoder_thread(void *arg)
   dp->last_frame_pts + dp->last_frame_duration_est;
 dt.frame->time_base = dp->last_frame_tb;
 
-ret = sch_dec_send(dp->sch, dp->sch_idx, dt.frame);
+ret = sch_dec_send(dp->sch, dp->sch_idx, 0, dt.frame);
 if (ret < 0 && ret != AVERROR_EOF) {
 av_log(dp, AV_LOG_FATAL,
"Error signalling EOF timestamp: %s\n", av_err2str(ret));
@@ -1355,7 +1355,7 @@ int dec_create(const OptionsContext *o, const char *arg, 
Scheduler *sch)
 return ret;
 enc_idx = ret;
 
-ret = sch_connect(sch, SCH_ENC(enc_idx), SCH_DEC(dp->sch_idx));
+ret = sch_connect(sch, SCH_ENC(enc_idx), SCH_DEC_IN(dp->sch_idx));
 if (ret < 0)
 return ret;
 
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 039ee0c785..476efff127 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -954,7 +954,7 @@ static int ist_use(InputStream *ist, int decoding_needed)
 ds->sch_idx_dec = ret;
 
 ret = sch_connect(d->sch, SCH_DSTREAM(d->f.index, ds->sch_idx_stream),
-  SCH_DEC(ds->sch_idx_dec));
+  SCH_DEC_IN(ds->sch_idx_dec));
 if (ret < 0)
 return ret;
 
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index b562e8417c..fb2b1a5b32 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -703,7 +703,7 @@ static int ifilter_bind_ist(InputFilter *ifilter, 
InputStream *ist)
 if (dec_idx < 0)
 return dec_idx;
 
-ret = sch_connect(fgp->sch, SCH_DEC(dec_idx),
+ret = sch_connect(fgp->sch, SCH_DEC_OUT(dec_idx, 0),
 SCH_FILTER_IN(fgp->sch_idx, ifp->index));
 if (ret < 0)
 return ret;
@@ -749,7 +749,7 @@ static int ifilter_bind_dec(InputFilterPriv *ifp, Decoder 
*dec)
 if (dec_idx < 0)
 return dec_idx;
 
-ret = sch_connect(fgp->sch, SCH_DEC(dec_idx),
+ret = sch_connect(fgp->sch, SCH_DEC_OUT(dec_idx, 0),
 SCH_FILTER_IN(fgp->sch_idx, ifp->index));
 if (ret < 0)
 return ret;
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index e84fa9719f..5ee2a9685b 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1458,7 +1458,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, 
enum AVMediaType type,
 ms->sch_idx_src = sched_idx;
 
 if (ost->enc) {
-ret = sch_connect(mux->sch, SCH_DEC(sched_idx),
+ret = sch_connect(mux->sch, SCH_DEC_OUT(sched_idx, 0),
 SCH_ENC(ms->sch_idx_enc));
 if (ret < 0)
 goto fail;
diff --git a/fftools/ffmpeg_sched.c b/fftools/ffmpeg_sched.c
index cff824340b..ef0b6e2897 100644
--- a/fftools/ffmpeg_sched.c
+++ b/fftools/ffmpeg_sched.c
@@ -71,13 +71,19 @@ typedef struct SchTask {
 int thread_running;
 } SchTask;
 
+typedef struct SchDecOutput {
+SchedulerNode  *dst;
+uint8_t*dst_finished;
+unsigned nb_dst;
+} SchDecOutput;
+
 typedef struct SchDec {
 const AVClass  *class;
 
 SchedulerNode   src;
-Schedul

[FFmpeg-devel] [PATCH 31/42] lavc/hevc/parser: only split packets on NALUs with nuh_layer_id=0

2024-08-27 Thread Anton Khirnov
A packet should contain a full access unit, which for multilayer video
should contain all the layers.
---
 libavcodec/hevc/parser.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/libavcodec/hevc/parser.c b/libavcodec/hevc/parser.c
index a10f38941b..05b92b21ee 100644
--- a/libavcodec/hevc/parser.c
+++ b/libavcodec/hevc/parser.c
@@ -262,7 +262,7 @@ static int hevc_find_frame_end(AVCodecParserContext *s, 
const uint8_t *buf,
 int i;
 
 for (i = 0; i < buf_size; i++) {
-int nut;
+int nut, layer_id;
 
 pc->state64 = (pc->state64 << 8) | buf[i];
 
@@ -270,6 +270,11 @@ static int hevc_find_frame_end(AVCodecParserContext *s, 
const uint8_t *buf,
 continue;
 
 nut = (pc->state64 >> 2 * 8 + 1) & 0x3F;
+
+layer_id = (pc->state64 >> 11) & 0x3F;
+if (layer_id > 0)
+continue;
+
 // Beginning of access unit
 if ((nut >= HEVC_NAL_VPS && nut <= HEVC_NAL_EOB_NUT) || nut == 
HEVC_NAL_SEI_PREFIX ||
 (nut >= 41 && nut <= 44) || (nut >= 48 && nut <= 55)) {
-- 
2.43.0

___
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 32/42] lavc/hevcdec: implement slice header parsing for nuh_layer_id>0

2024-08-27 Thread Anton Khirnov
Cf. F.7.3.6.1 "General slice segment header syntax"
---
 libavcodec/hevc/hevcdec.c | 36 
 libavcodec/hevc/hevcdec.h |  1 +
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 260b9abef0..d9a12279cd 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -584,7 +584,8 @@ static int hls_slice_header(SliceHeader *sh, const 
HEVCContext *s, GetBitContext
 {
 const HEVCPPS *pps;
 const HEVCSPS *sps;
-unsigned pps_id;
+const HEVCVPS *vps;
+unsigned pps_id, layer_idx;
 int i, ret;
 
 // Coded parameters
@@ -607,6 +608,8 @@ static int hls_slice_header(SliceHeader *sh, const 
HEVCContext *s, GetBitContext
 
 pps = s->ps.pps_list[pps_id];
 sps = pps->sps;
+vps = sps->vps;
+layer_idx = vps->layer_idx[s->nuh_layer_id];
 
 if (s->nal_unit_type == HEVC_NAL_CRA_NUT && s->last_eos == 1)
 sh->no_output_of_prior_pics_flag = 1;
@@ -652,7 +655,8 @@ static int hls_slice_header(SliceHeader *sh, const 
HEVCContext *s, GetBitContext
 return AVERROR_INVALIDDATA;
 }
 if (IS_IRAP(s) && sh->slice_type != HEVC_SLICE_I &&
-!pps->pps_curr_pic_ref_enabled_flag) {
+!pps->pps_curr_pic_ref_enabled_flag &&
+s->nuh_layer_id == 0) {
 av_log(s->avctx, AV_LOG_ERROR, "Inter slices in an IRAP frame.\n");
 return AVERROR_INVALIDDATA;
 }
@@ -665,8 +669,10 @@ static int hls_slice_header(SliceHeader *sh, const 
HEVCContext *s, GetBitContext
 if (sps->separate_colour_plane)
 sh->colour_plane_id = get_bits(gb, 2);
 
-if (!IS_IDR(s)) {
-int poc, pos;
+if (!IS_IDR(s) ||
+(s->nuh_layer_id > 0 &&
+ !(vps->poc_lsb_not_present & (1 << layer_idx {
+int poc;
 
 sh->pic_order_cnt_lsb = get_bits(gb, sps->log2_max_poc_lsb);
 poc = ff_hevc_compute_poc(sps, s->poc_tid0, sh->pic_order_cnt_lsb, 
s->nal_unit_type);
@@ -678,6 +684,10 @@ static int hls_slice_header(SliceHeader *sh, const 
HEVCContext *s, GetBitContext
 poc = sh->poc;
 }
 sh->poc = poc;
+}
+
+if (!IS_IDR(s)) {
+int pos;
 
 sh->short_term_ref_pic_set_sps_flag = get_bits1(gb);
 pos = get_bits_left(gb);
@@ -724,6 +734,23 @@ static int hls_slice_header(SliceHeader *sh, const 
HEVCContext *s, GetBitContext
 sh->slice_temporal_mvp_enabled_flag = 0;
 }
 
+sh->inter_layer_pred = 0;
+if (s->nuh_layer_id > 0) {
+int num_direct_ref_layers = vps->num_direct_ref_layers[layer_idx];
+
+if (vps->default_ref_layers_active)
+sh->inter_layer_pred = !!num_direct_ref_layers;
+else if (num_direct_ref_layers) {
+sh->inter_layer_pred = get_bits1(gb);
+
+if (sh->inter_layer_pred && num_direct_ref_layers > 1) {
+av_log(s->avctx, AV_LOG_ERROR,
+   "NumDirectRefLayers>1 not supported\n");
+return AVERROR_PATCHWELCOME;
+}
+}
+}
+
 if (sps->sao_enabled) {
 sh->slice_sample_adaptive_offset_flag[0] = get_bits1(gb);
 if (sps->chroma_format_idc) {
@@ -3234,6 +3261,7 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL 
*nal)
 int ret;
 
 s->nal_unit_type = nal->type;
+s->nuh_layer_id  = nal->nuh_layer_id;
 s->temporal_id   = nal->temporal_id;
 
 if (FF_HW_HAS_CB(s->avctx, decode_params) &&
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index e43f2d0201..7072eee077 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -215,6 +215,7 @@ typedef struct SliceHeader {
 uint8_t dependent_slice_segment_flag;
 uint8_t pic_output_flag;
 uint8_t colour_plane_id;
+uint8_t inter_layer_pred;
 
 ///< RPS coded in the slice header itself is stored here
 int short_term_ref_pic_set_sps_flag;
-- 
2.43.0

___
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 41/42] tests/fate/hevc: add a test for nontrivial values of nuh_layer_id

2024-08-27 Thread Anton Khirnov
Typical files use 0 for the base layer and 1 for the secondary one, but
any value for the secondary layer should be supported.
---
 tests/fate/hevc.mak |  4 
 tests/ref/fate/hevc-mv-nuh-layer-id | 15 +++
 2 files changed, 19 insertions(+)
 create mode 100644 tests/ref/fate/hevc-mv-nuh-layer-id

diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak
index e7dad6c898..e75fbd3c16 100644
--- a/tests/fate/hevc.mak
+++ b/tests/fate/hevc.mak
@@ -269,6 +269,10 @@ FATE_HEVC-$(call FRAMECRC, HEVC, HEVC) += 
fate-hevc-cabac-tudepth
 fate-hevc-small422chroma: CMD = framecrc -i $(TARGET_SAMPLES)/hevc/food.hevc 
-pix_fmt yuv422p10le -vf scale
 FATE_HEVC-$(call FRAMECRC, HEVC, HEVC, HEVC_PARSER SCALE_FILTER) += 
fate-hevc-small422chroma
 
+# multiview stream, where the secondary layer has a nontrivial nuh_layer_id=6
+fate-hevc-mv-nuh-layer-id: CMD = framecrc -i 
$(TARGET_SAMPLES)/hevc/mv_nuh_layer_id.bit -map 0:view:all
+FATE_HEVC-$(call FRAMECRC, HEVC, HEVC) += fate-hevc-mv-nuh-layer-id
+
 FATE_SAMPLES_AVCONV += $(FATE_HEVC-yes)
 FATE_SAMPLES_FFPROBE += $(FATE_HEVC_FFPROBE-yes)
 
diff --git a/tests/ref/fate/hevc-mv-nuh-layer-id 
b/tests/ref/fate/hevc-mv-nuh-layer-id
new file mode 100644
index 00..3cbefe17f6
--- /dev/null
+++ b/tests/ref/fate/hevc-mv-nuh-layer-id
@@ -0,0 +1,15 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 0/1
+0,  0,  0,1,24576, 0xdfd350a6
+0,  1,  1,1,24576, 0xf8f638da
+0,  2,  2,1,24576, 0x8ac574d5
+0,  3,  3,1,24576, 0xd22675a4
+0,  4,  4,1,24576, 0xdd0f4704
+0,  5,  5,1,24576, 0x60da42e6
+0,  6,  6,1,24576, 0x8bf28fdd
+0,  7,  7,1,24576, 0xe0577f6e
+0,  8,  8,1,24576, 0x8b3e3c29
+0,  9,  9,1,24576, 0x8d9944bd
-- 
2.43.0

___
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 35/42] avcodec/hevc/refs: export Stereo 3D side data

2024-08-27 Thread Anton Khirnov
From: James Almer 

Use the 3D Reference Displays Info SEI message to link a view_id with
an eye.

Signed-off-by: James Almer 
---
 libavcodec/hevc/hevcdec.c |  1 +
 libavcodec/hevc/refs.c| 19 +++
 2 files changed, 20 insertions(+)

diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index f0e284bdf6..0b3c56b526 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -3991,6 +3991,7 @@ static int hevc_update_thread_context(AVCodecContext *dst,
 s->sei.common.mastering_display= s0->sei.common.mastering_display;
 s->sei.common.content_light= s0->sei.common.content_light;
 s->sei.common.aom_film_grain   = s0->sei.common.aom_film_grain;
+s->sei.tdrdi   = s0->sei.tdrdi;
 
 return 0;
 }
diff --git a/libavcodec/hevc/refs.c b/libavcodec/hevc/refs.c
index dbedd69aa1..a6a7d7b06c 100644
--- a/libavcodec/hevc/refs.c
+++ b/libavcodec/hevc/refs.c
@@ -22,6 +22,7 @@
  */
 
 #include "libavutil/mem.h"
+#include "libavutil/stereo3d.h"
 
 #include "container_fifo.h"
 #include "decode.h"
@@ -172,12 +173,30 @@ int ff_hevc_set_new_ref(HEVCContext *s, HEVCLayerContext 
*l, int poc)
 
 // add view ID side data if it's nontrivial
 if (vps->nb_layers > 1 || view_id) {
+HEVCSEITDRDI *tdrdi = &s->sei.tdrdi;
 AVFrameSideData *sd = av_frame_side_data_new(&ref->f->side_data, 
&ref->f->nb_side_data,
  AV_FRAME_DATA_VIEW_ID, 
sizeof(int),
  
AV_FRAME_SIDE_DATA_FLAG_REPLACE);
 if (!sd)
 return AVERROR(ENOMEM);
 *(int*)sd->data = view_id;
+
+if (tdrdi->num_ref_displays) {
+AVStereo3D *stereo_3d;
+
+av_frame_remove_side_data(ref->f, AV_FRAME_DATA_STEREO3D);
+stereo_3d = av_stereo3d_create_side_data(ref->f);
+if (!stereo_3d)
+return AVERROR(ENOMEM);
+
+stereo_3d->type = AV_STEREO3D_FRAMESEQUENCE;
+if (tdrdi->left_view_id[0] == view_id)
+stereo_3d->view = AV_STEREO3D_VIEW_LEFT;
+else if (tdrdi->right_view_id[0] == view_id)
+stereo_3d->view = AV_STEREO3D_VIEW_RIGHT;
+else
+stereo_3d->view = AV_STEREO3D_VIEW_UNSPEC;
+}
 }
 
 if (!(s->layers_active_output & (1 << s->cur_layer)))
-- 
2.43.0

___
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 7/7] avcodec/riscv: add h264 qpel

2024-08-27 Thread Rémi Denis-Courmont
Le 27 août 2024 17:12:03 GMT+03:00, Niklas Haas  a écrit :
>> > +.irp x, \vregs
>> > +vmax.vx \x, \x, zero
>> > +.endr
>> > +vsetvli zero, zero, e8, \lmul, ta, ma
>> > +.irp x, \vregs
>> > +vnclipu.wi  \x, \x, \shifti
>> > +.endr
>> > +.endm
>> > +
>> > +.macro lowpass_init  lmul, sizei, size, w0, w1, backup
>> 
>> This is needlessly convoluted. In fact, backup is not even used, which kind 
>> of highlights the point.
>
>That parameter was simply left over from a previous version of the code.

That would not have happened if this was not a macro.

>Are you suggesting we simply duplicate the contents of this macro into all of
>thefunctions that use it?

What are you implying here? Can you point to any other .S file from Arm, 
Aarch64, LoongArch or RV that does this?

This macro can only realistically be used once per function - at the 
beginning. Do you typically make macros for declaring and initialising local 
variables in other languages? Because I don't and I don't know anybody else 
that does.

And to make things worse, it has a conditional. TBH, this patch is 
unreviewable to me. It's simply too hard to read because of excess macro usage 
and excess macro parameter on top.

>> > +vsetivli zero, \sizei, e8, \lmul, ta, ma
>> > +csrwivxrm, 0
>> > +li   \size, \sizei
>> > +.ifnb \w0
>> > +li   \w0, 20
>> > +li   \w1, -5
>> > +.endif
>> > +.endm
>> > +
>> > +/* output is unclipped; clobbers v26-v31 plus \tmp and \tmp2 */
>> > +.macro lowpass_h vdst, src, w0, w1, tmp=t3, tmp2=t4
>> > +addi \tmp, \src, 3
>> > +lbu  \tmp2, 2(\src)
>> > +vle8.v   v31, (\tmp)
>> > +lbu  \tmp, 1(\src)
>> > +vslide1up.vx v30, v31, \tmp2
>> > +lbu  \tmp2, 0(\src)
>> > +vslide1up.vx v29, v30, \tmp
>> > +lbu  \tmp, -1(\src)
>> > +vslide1up.vx v28, v29, \tmp2
>> > +lbu  \tmp2, -2(\src)
>> > +vslide1up.vx v27, v28, \tmp
>> > +vslide1up.vx v26, v27, \tmp2
>> 
>> That's a lot of sequentially dependent vector instructions to save zero-
>> extending v31 before the MACs. Are you sure it's faster that way?
>
>I'm not sure what you mean. How would your alternative implementation look?
>It's certainly possible to make these instructions less sequential by
>emitting multiple `lbu` instructions instead of sliding up.

Slides are actually quite slow, but they're unavoidable here. The point is 
that you wouldn't need v26 up-front if you zero-extended v31 first. And then 
you would be able to interleave non-dependent instructions.

That doesn't affect the number of slides and scalar loads.

>> 
>> > +vwaddu.vv\vdst, v26, v31
>> > +vwmaccu.vx   \vdst, \w0, v28
>> > +vwmaccu.vx   \vdst, \w0, v29
>> > +vwmaccsu.vx  \vdst, \w1, v27
>> > +vwmaccsu.vx  \vdst, \w1, v30
>> > +.endm
>> > +
>> > +/* output is unclipped */
>> > +.macro lowpass_v w0, w1, vdst, vsrc0, vsrc1, vsrc2, vsrc3, 
vsrc4,
>> > vsrc5, signed=0
>> > +.if \signed
>> > +vwadd.vv \vdst, \vsrc0, \vsrc5
>> > +vwmacc.vx\vdst, \w0, \vsrc2
>> > +vwmacc.vx\vdst, \w0, \vsrc3
>> > +vwmacc.vx\vdst, \w1, \vsrc1
>> > +vwmacc.vx\vdst, \w1, \vsrc4
>> > +.else
>> > +vwaddu.vv\vdst, \vsrc0, \vsrc5
>> > +vwmaccu.vx   \vdst, \w0, \vsrc2
>> > +vwmaccu.vx   \vdst, \w0, \vsrc3
>> > +vwmaccsu.vx  \vdst, \w1, \vsrc1
>> > +vwmaccsu.vx  \vdst, \w1, \vsrc4
>> > +.endif
>> > +.endm
>> > +
>> > +.macro qpel_mc00 op, dst, src, stride, size
>> > +func ff_\op\()_h264_qpel_pixels, zve32x
>> > +1:
>> > +add  t0, \stride, \src
>> > +add  t1, \stride, t0
>> > +add  t2, \stride, t1
>> > +vle8.v   v0, (\src)
>> > +vle8.v   v1, (t0)
>> > +vle8.v   v2, (t1)
>> > +vle8.v   v3, (t2)
>> > +addi \size, \size, -4
>> > +add  \src, \stride, t2
>> > +add  t0, \stride, \dst
>> > +add  t1, \stride, t0
>> > +add  t2, \stride, t1
>> > +.ifc \op, avg
>> > +vle8.v   v4, (\dst)
>> > +vle8.v   v5, (t0)
>> > +vle8.v   v6, (t1)
>> > +vle8.v   v7, (t2)
>> > +vaaddu.vvv0, v0, v4
>> > +vaaddu.vvv1, v1, v5
>> > +vaaddu.vvv2, v2, v6
>> > +vaaddu.vvv3, v3, v7
>> > +.endif
>> > +vse8.v   v0, (\dst)
>> > +vse8.v   v1, (t0)
>> > +vse8.v   v2,

Re: [FFmpeg-devel] [PATCH 1/2] lavc/vp9dsp: R-V V mc tap h v

2024-08-27 Thread Rémi Denis-Courmont
Le sunnuntaina 25. elokuuta 2024, 14.41.22 EEST flow gg a écrit :
> > Does not assemble with binutils 2.43.1 and default flags.
> 
> Fixed through zve32x -> zve32x, zba

Are the Bitmanip runtime support checks missing or did I miss them?

-- 
Rémi Denis-Courmont
http://www.remlab.net/



___
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] lavc/vvc_mc: R-V V avg w_avg

2024-08-27 Thread Rémi Denis-Courmont
Le sunnuntaina 18. elokuuta 2024, 13.19.33 EEST flow gg a écrit :
> Based on the test results for 49 different resolutions, most of them were
> significantly slower.

OK, thanks for checking. The heights are probably not large enough for this to 
work. I don't have any objection on the RISC-V side of this patchset (reviewed 
only, not tested).

-- 
Rémi Denis-Courmont
http://www.remlab.net/



___
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] lavc/qsvenc: Remove duplicate include header file

2024-08-27 Thread Xiang, Haihao
On Ma, 2024-08-26 at 09:41 +0800, fei.w.wang-at-intel@ffmpeg.org wrote:
> From: Fei Wang 
> 
> Signed-off-by: Fei Wang 
> ---
>  libavcodec/qsvenc.h | 2 --
>  libavcodec/qsvenc_av1.c | 2 --
>  2 files changed, 4 deletions(-)
> 
> diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
> index e3eb083746..4bc77f2f7c 100644
> --- a/libavcodec/qsvenc.h
> +++ b/libavcodec/qsvenc.h
> @@ -26,8 +26,6 @@
>  #include 
>  #include 
>  
> -#include 
> -
>  #include "libavutil/common.h"
>  #include "libavutil/hwcontext.h"
>  #include "libavutil/hwcontext_qsv.h"
> diff --git a/libavcodec/qsvenc_av1.c b/libavcodec/qsvenc_av1.c
> index 56002746b9..f7505a69f8 100644
> --- a/libavcodec/qsvenc_av1.c
> +++ b/libavcodec/qsvenc_av1.c
> @@ -22,8 +22,6 @@
>  #include 
>  #include 
>  
> -#include 
> -
>  #include "libavutil/common.h"
>  #include "libavutil/mastering_display_metadata.h"
>  #include "libavutil/mem.h"

Will apply

Thanks
Haihao




___
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] doc/av1_qsv: Fix typo

2024-08-27 Thread Xiang, Haihao
On Ma, 2024-08-26 at 09:40 +0800, fei.w.wang-at-intel@ffmpeg.org wrote:
> From: Fei Wang 
> 
> Signed-off-by: Fei Wang 
> ---
>  doc/encoders.texi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/doc/encoders.texi b/doc/encoders.texi
> index 496852faeb..1035be0052 100644
> --- a/doc/encoders.texi
> +++ b/doc/encoders.texi
> @@ -4105,7 +4105,7 @@ Setting this flag turns on or off LowDelayBRC feautre in
> qsv plugin, which provi
>  more accurate bitrate control to minimize the variance of bitstream size
> frame
>  by frame. Value: -1-default 0-off 1-on
>  
> -@item max_frame_size
> +@item @var{max_frame_size}
>  Set the allowed max size in bytes for each frame. If the frame size exceeds
>  the limitation, encoder will adjust the QP value to control the frame size.
>  Invalid in CQP rate control mode.

Patchset LGTM, will apply,

Thanks
Haihao

___
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] lavu/opt: Fix return of uninitialised value

2024-08-27 Thread Marvin Scholz
In one of the failure paths of av_opt_get_array, the ret variable
was accidentally declared again, shadowing the outer one and once when
jumping to the fail label would return the still uninitialised outer
one.

To fix this simply remove the local declaration of ret that shadowed
the outer one.

Introduced in d89930f8666c563a96f1dc1835b450522b4cd6da

Fixes: CID1618663 Uninitialized scalar variable
---
 libavutil/opt.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libavutil/opt.c b/libavutil/opt.c
index d515e20e97..3788a9df75 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -2213,7 +2213,6 @@ int av_opt_get_array(void *obj, const char *name, int 
search_flags,
 double num = 1.0;
 intden = 1;
 int64_t intnum = 1;
-int ret;
 
 ret = read_number(o, src, &num, &den, &intnum);
 if (ret < 0)

base-commit: d89930f8666c563a96f1dc1835b450522b4cd6da
-- 
2.39.3 (Apple Git-146)
___
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] avutil/timestamp: avoid using INFINITY for log10 result in av_ts_make_time_string2

2024-08-27 Thread Kacper Michajlow
On Tue, 27 Aug 2024 at 09:51, Rémi Denis-Courmont  wrote:
>
>
>
> Le 27 août 2024 10:00:08 GMT+03:00, Marton Balint  a écrit :
>
> >IMHO the patch itself is harmless (simple, easy to follow), and if it helps 
> >somebody (no matter how unupported its use-case is), then why the hell not. 
> >But I can understand your point of view, that we should not bother with it, 
> >if it is unsupported in the first place, so I will just drop this, did not 
> >feel strongly about it anyway.
>
> Can't we just fail configure or compilation hard if __FINITE_MATH_ONLY__ is 
> true?
>
> If MPV or whichever downstream wants to get this flag working, it's on them 
> to do the hard work (and it's a lot harder than this patch).

Whoa, don't call out mpv like that. There are no plans to do any of
that. -ffast-math should be considered harmful unless proven otherwise
for given codebase. mpv itself depends on infinites.
___
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] avutil/timestamp: avoid using INFINITY for log10 result in av_ts_make_time_string2

2024-08-27 Thread Rémi Denis-Courmont


Le 28 août 2024 06:29:30 GMT+03:00, Kacper Michajlow  a 
écrit :
>On Tue, 27 Aug 2024 at 09:51, Rémi Denis-Courmont  wrote:
>>
>>
>>
>> Le 27 août 2024 10:00:08 GMT+03:00, Marton Balint  a écrit :
>>
>> >IMHO the patch itself is harmless (simple, easy to follow), and if it helps 
>> >somebody (no matter how unupported its use-case is), then why the hell not. 
>> >But I can understand your point of view, that we should not bother with it, 
>> >if it is unsupported in the first place, so I will just drop this, did not 
>> >feel strongly about it anyway.
>>
>> Can't we just fail configure or compilation hard if __FINITE_MATH_ONLY__ is 
>> true?
>>
>> If MPV or whichever downstream wants to get this flag working, it's on them 
>> to do the hard work (and it's a lot harder than this patch).
>
>Whoa, don't call out mpv like that. There are no plans to do any of
>that.

Don't publicly accuse me of something I did not do. I don't remember who blamed 
this code for breaking mpv but it certainly wasn't me. And why the heck do you 
make it a problem now rather than then?
___
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] lavc/vvc_mc: R-V V avg w_avg

2024-08-27 Thread uk7b
From: sunyuechi 

 C908   X60
avg_8_2x2_c:1.21.0
avg_8_2x2_rvv_i32  :0.70.7
avg_8_2x4_c:2.02.2
avg_8_2x4_rvv_i32  :1.21.2
avg_8_2x8_c:3.74.0
avg_8_2x8_rvv_i32  :1.71.5
avg_8_2x16_c   :7.27.7
avg_8_2x16_rvv_i32 :3.02.7
avg_8_2x32_c   :   14.2   15.2
avg_8_2x32_rvv_i32 :5.55.0
avg_8_2x64_c   :   51.0   43.7
avg_8_2x64_rvv_i32 :   39.2   29.7
avg_8_2x128_c  :  100.5   79.2
avg_8_2x128_rvv_i32:   79.7   68.2
avg_8_4x2_c:1.72.0
avg_8_4x2_rvv_i32  :1.00.7
avg_8_4x4_c:3.53.7
avg_8_4x4_rvv_i32  :1.21.2
avg_8_4x8_c:6.77.0
avg_8_4x8_rvv_i32  :1.71.5
avg_8_4x16_c   :   13.5   14.0
avg_8_4x16_rvv_i32 :3.02.7
avg_8_4x32_c   :   26.2   27.7
avg_8_4x32_rvv_i32 :5.54.7
avg_8_4x64_c   :   73.0   73.7
avg_8_4x64_rvv_i32 :   39.0   32.5
avg_8_4x128_c  :  143.0  137.2
avg_8_4x128_rvv_i32:   72.7   68.0
avg_8_8x2_c:3.53.5
avg_8_8x2_rvv_i32  :1.00.7
avg_8_8x4_c:6.26.5
avg_8_8x4_rvv_i32  :1.51.0
avg_8_8x8_c:   12.7   13.2
avg_8_8x8_rvv_i32  :2.01.5
avg_8_8x16_c   :   25.0   26.5
avg_8_8x16_rvv_i32 :3.22.7
avg_8_8x32_c   :   50.0   52.7
avg_8_8x32_rvv_i32 :6.25.0
avg_8_8x64_c   :  118.7  122.5
avg_8_8x64_rvv_i32 :   40.2   31.5
avg_8_8x128_c  :  236.7  220.2
avg_8_8x128_rvv_i32:   85.2   67.7
avg_8_16x2_c   :6.26.7
avg_8_16x2_rvv_i32 :1.20.7
avg_8_16x4_c   :   12.5   13.0
avg_8_16x4_rvv_i32 :1.71.0
avg_8_16x8_c   :   24.5   26.0
avg_8_16x8_rvv_i32 :3.01.7
avg_8_16x16_c  :   49.0   51.5
avg_8_16x16_rvv_i32:5.53.0
avg_8_16x32_c  :   97.5  102.5
avg_8_16x32_rvv_i32:   10.55.5
avg_8_16x64_c  :  213.7  222.0
avg_8_16x64_rvv_i32:   48.5   34.2
avg_8_16x128_c :  434.7  420.0
avg_8_16x128_rvv_i32   :   97.7   74.0
avg_8_32x2_c   :   12.2   12.7
avg_8_32x2_rvv_i32 :1.51.0
avg_8_32x4_c   :   24.5   25.5
avg_8_32x4_rvv_i32 :3.01.7
avg_8_32x8_c   :   48.5   50.7
avg_8_32x8_rvv_i32 :5.22.7
avg_8_32x16_c  :   96.7  101.2
avg_8_32x16_rvv_i32:   10.25.0
avg_8_32x32_c  :  192.7  202.2
avg_8_32x32_rvv_i32:   19.79.5
avg_8_32x64_c  :  427.5  426.5
avg_8_32x64_rvv_i32:   64.2   18.2
avg_8_32x128_c :  816.5  821.0
avg_8_32x128_rvv_i32   :  135.2   75.5
avg_8_64x2_c   :   24.0   25.2
avg_8_64x2_rvv_i32 :2.71.5
avg_8_64x4_c   :   48.2   50.5
avg_8_64x4_rvv_i32

Re: [FFmpeg-devel] [PATCH] lavc/vvc_mc: R-V V avg w_avg

2024-08-27 Thread flow gg
Updated: zve32x -> zve32x, zbb, zba

 于2024年8月28日周三 14:37写道:

> From: sunyuechi 
>
>  C908   X60
> avg_8_2x2_c:1.21.0
> avg_8_2x2_rvv_i32  :0.70.7
> avg_8_2x4_c:2.02.2
> avg_8_2x4_rvv_i32  :1.21.2
> avg_8_2x8_c:3.74.0
> avg_8_2x8_rvv_i32  :1.71.5
> avg_8_2x16_c   :7.27.7
> avg_8_2x16_rvv_i32 :3.02.7
> avg_8_2x32_c   :   14.2   15.2
> avg_8_2x32_rvv_i32 :5.55.0
> avg_8_2x64_c   :   51.0   43.7
> avg_8_2x64_rvv_i32 :   39.2   29.7
> avg_8_2x128_c  :  100.5   79.2
> avg_8_2x128_rvv_i32:   79.7   68.2
> avg_8_4x2_c:1.72.0
> avg_8_4x2_rvv_i32  :1.00.7
> avg_8_4x4_c:3.53.7
> avg_8_4x4_rvv_i32  :1.21.2
> avg_8_4x8_c:6.77.0
> avg_8_4x8_rvv_i32  :1.71.5
> avg_8_4x16_c   :   13.5   14.0
> avg_8_4x16_rvv_i32 :3.02.7
> avg_8_4x32_c   :   26.2   27.7
> avg_8_4x32_rvv_i32 :5.54.7
> avg_8_4x64_c   :   73.0   73.7
> avg_8_4x64_rvv_i32 :   39.0   32.5
> avg_8_4x128_c  :  143.0  137.2
> avg_8_4x128_rvv_i32:   72.7   68.0
> avg_8_8x2_c:3.53.5
> avg_8_8x2_rvv_i32  :1.00.7
> avg_8_8x4_c:6.26.5
> avg_8_8x4_rvv_i32  :1.51.0
> avg_8_8x8_c:   12.7   13.2
> avg_8_8x8_rvv_i32  :2.01.5
> avg_8_8x16_c   :   25.0   26.5
> avg_8_8x16_rvv_i32 :3.22.7
> avg_8_8x32_c   :   50.0   52.7
> avg_8_8x32_rvv_i32 :6.25.0
> avg_8_8x64_c   :  118.7  122.5
> avg_8_8x64_rvv_i32 :   40.2   31.5
> avg_8_8x128_c  :  236.7  220.2
> avg_8_8x128_rvv_i32:   85.2   67.7
> avg_8_16x2_c   :6.26.7
> avg_8_16x2_rvv_i32 :1.20.7
> avg_8_16x4_c   :   12.5   13.0
> avg_8_16x4_rvv_i32 :1.71.0
> avg_8_16x8_c   :   24.5   26.0
> avg_8_16x8_rvv_i32 :3.01.7
> avg_8_16x16_c  :   49.0   51.5
> avg_8_16x16_rvv_i32:5.53.0
> avg_8_16x32_c  :   97.5  102.5
> avg_8_16x32_rvv_i32:   10.55.5
> avg_8_16x64_c  :  213.7  222.0
> avg_8_16x64_rvv_i32:   48.5   34.2
> avg_8_16x128_c :  434.7  420.0
> avg_8_16x128_rvv_i32   :   97.7   74.0
> avg_8_32x2_c   :   12.2   12.7
> avg_8_32x2_rvv_i32 :1.51.0
> avg_8_32x4_c   :   24.5   25.5
> avg_8_32x4_rvv_i32 :3.01.7
> avg_8_32x8_c   :   48.5   50.7
> avg_8_32x8_rvv_i32 :5.22.7
> avg_8_32x16_c  :   96.7  101.2
> avg_8_32x16_rvv_i32:   10.25.0
> avg_8_32x32_c  :  192.7  202.2
> avg_8_32x32_rvv_i32:   19.79.5
> avg_8_32x64_c  :  427.5  426.5
> avg_8_32x64_rvv_i32:   64.2   18.2
> avg_8_32x128_c :  816.5  821.0
> avg_8_32x128_rvv_i32   :  135.2   75.5
> avg_8_64x2_c  

Re: [FFmpeg-devel] [PATCH 1/2] lavc/vp9dsp: R-V V mc tap h v

2024-08-27 Thread flow gg
It seems that the previous patch have partially lacked if RVB, but now it
has if (flags & AV_CPU_FLAG_RVB).

Rémi Denis-Courmont  于2024年8月28日周三 03:00写道:

> Le sunnuntaina 25. elokuuta 2024, 14.41.22 EEST flow gg a écrit :
> > > Does not assemble with binutils 2.43.1 and default flags.
> >
> > Fixed through zve32x -> zve32x, zba
>
> Are the Bitmanip runtime support checks missing or did I miss them?
>
> --
> Rémi Denis-Courmont
> http://www.remlab.net/
>
>
>
> ___
> 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 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".