Re: [FFmpeg-devel] [PATCH] avutil/timestamp: avoid using INFINITY for log10 result in av_ts_make_time_string2
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
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
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
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}
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
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
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
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
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
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
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/*
--- 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
--- 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
--- 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
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
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
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
--- 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
--- 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
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
--- 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
--- 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
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
--- 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
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
--- 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
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
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
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
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
--- 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
--- 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
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
--- 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
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
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
--- 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
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
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
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
--- 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
--- 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
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
--- 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
--- 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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".