Go to the documentation of this file.
23 #include <stdatomic.h>
32 #define VVC_FRAME_FLAG_OUTPUT (1 << 0)
33 #define VVC_FRAME_FLAG_SHORT_REF (1 << 1)
34 #define VVC_FRAME_FLAG_LONG_REF (1 << 2)
35 #define VVC_FRAME_FLAG_BUMPING (1 << 3)
60 frame->nb_rpl_elems = 0;
69 const int x_cb = x0 >>
fc->ps.sps->ctb_log2_size_y;
70 const int y_cb = y0 >>
fc->ps.sps->ctb_log2_size_y;
71 const int pic_width_cb =
fc->ps.pps->ctb_width;
72 const int ctb_addr_rs = y_cb * pic_width_cb + x_cb;
119 if (
frame->frame->buf[0])
129 frame->nb_rpl_elems =
s->current_frame.nb_units;
132 if (!
frame->tab_dmvr_mvf)
138 frame->ctb_count =
pps->ctb_width *
pps->ctb_height;
139 for (
int j = 0; j <
frame->ctb_count; j++)
143 if (!
frame->progress)
158 const int poc =
ph->poc;
165 if (
frame->frame->buf[0] &&
frame->sequence ==
s->seq_decode &&
181 else if (
ph->r->ph_pic_output_flag)
184 if (!
ph->r->ph_non_ref_pic_flag)
188 ref->sequence =
s->seq_decode;
189 ref->frame->crop_left =
fc->ps.pps->r->pps_conf_win_left_offset <<
fc->ps.sps->hshift[
CHROMA];
190 ref->frame->crop_right =
fc->ps.pps->r->pps_conf_win_right_offset <<
fc->ps.sps->hshift[
CHROMA];
191 ref->frame->crop_top =
fc->ps.pps->r->pps_conf_win_top_offset <<
fc->ps.sps->vshift[
CHROMA];
192 ref->frame->crop_bottom =
fc->ps.pps->r->pps_conf_win_bottom_offset <<
fc->ps.sps->vshift[
CHROMA];
202 int min_poc = INT_MAX;
205 if (no_output_of_prior_pics_flag) {
209 frame->sequence ==
s->seq_output) {
218 frame->sequence ==
s->seq_output) {
220 if (
frame->poc < min_poc || nb_output == 1) {
221 min_poc =
frame->poc;
228 if (!
flush &&
s->seq_output ==
s->seq_decode &&
sps &&
229 nb_output <= sps->
r->sps_dpb_params.dpb_max_dec_pic_buffering_minus1[
sps->r->sps_max_sublayers_minus1] + 1)
244 "Output frame with POC %d.\n",
frame->poc);
248 if (
s->seq_output !=
s->seq_decode)
249 s->seq_output = (
s->seq_output + 1) & 0xff;
259 const int poc =
fc->ps.ph.poc;
261 int min_poc = INT_MAX;
265 if ((
frame->flags) &&
266 frame->sequence ==
s->seq_output &&
272 if (
sps && dpb >=
sps->r->sps_dpb_params.dpb_max_dec_pic_buffering_minus1[
sps->r->sps_max_sublayers_minus1] + 1) {
275 if ((
frame->flags) &&
276 frame->sequence ==
s->seq_output &&
279 min_poc =
frame->poc;
287 frame->sequence ==
s->seq_output &&
288 frame->poc <= min_poc) {
299 const int mask = use_msb ? ~0 :
fc->ps.sps->max_pic_order_cnt_lsb - 1;
303 if (
ref->frame->buf[0] &&
ref->sequence ==
s->seq_decode) {
327 if (!
s->avctx->hwaccel) {
328 if (!
sps->pixel_shift) {
329 for (
int i = 0;
frame->frame->buf[
i];
i++)
330 memset(
frame->frame->buf[
i]->data, 1 << (
sps->bit_depth - 1),
331 frame->frame->buf[
i]->size);
333 for (
int i = 0;
frame->frame->data[
i];
i++)
334 for (
int y = 0; y < (
pps->height >>
sps->vshift[
i]); y++) {
335 uint8_t *dst =
frame->frame->data[
i] + y *
frame->frame->linesize[
i];
343 frame->sequence =
s->seq_decode;
353 int poc,
int ref_flag, uint8_t use_msb)
397 if (!((
sps->r->sps_weighted_pred_flag ||
398 sps->r->sps_weighted_bipred_flag) &&
i != 0))
404 const int lx,
const int j,
const int max_poc_lsb)
411 lt_poc += poc -
delta * max_poc_lsb - (poc & (max_poc_lsb - 1));
412 *prev_delta_poc_msb =
delta;
423 const int max_poc_lsb =
sps->max_pic_order_cnt_lsb;
432 for (
int lx =
L0; lx <=
L1; lx++) {
435 int poc_base =
ph->poc;
436 int prev_delta_poc_msb = 0;
450 poc =
poc_lt(&prev_delta_poc_msb,
ph->poc, ref_lists, lx, j, max_poc_lsb);
529 prev = &(*prev)->
next;
F H1 F F H1 F F F F H1<-F-------F-------F v v v H2 H3 H2 ^ ^ ^ F-------F-------F-> H1<-F-------F-------F|||||||||F H1 F|||||||||F H1 Funavailable fullpel samples(outside the picture for example) shall be equalto the closest available fullpel sampleSmaller pel interpolation:--------------------------if diag_mc is set then points which lie on a line between 2 vertically, horizontally or diagonally adjacent halfpel points shall be interpolatedlinearly with rounding to nearest and halfway values rounded up.points which lie on 2 diagonals at the same time should only use the onediagonal not containing the fullpel point F--> O q O<--h1-> O q O<--F v \/v \/v O O O O O O O|/|\|q q q q q|/|\|O O O O O O O ^/\ ^/\ ^ h2--> O q O<--h3-> O q O<--h2 v \/v \/v O O O O O O O|\|/|q q q q q|\|/|O O O O O O O ^/\ ^/\ ^ F--> O q O<--h1-> O q O<--Fthe remaining points shall be bilinearly interpolated from theup to 4 surrounding halfpel and fullpel points, again rounding should be tonearest and halfway values rounded upcompliant Snow decoders MUST support 1-1/8 pel luma and 1/2-1/16 pel chromainterpolation at leastOverlapped block motion compensation:-------------------------------------FIXMELL band prediction:===================Each sample in the LL0 subband is predicted by the median of the left, top andleft+top-topleft samples, samples outside the subband shall be considered tobe 0. To reverse this prediction in the decoder apply the following.for(y=0;y< height;y++){ for(x=0;x< width;x++){ sample[y][x]+=median(sample[y-1][x], sample[y][x-1], sample[y-1][x]+sample[y][x-1]-sample[y-1][x-1]);}}sample[-1][ *]=sample[ *][-1]=0;width, height here are the width and height of the LL0 subband not of the finalvideoDequantization:===============FIXMEWavelet Transform:==================Snow supports 2 wavelet transforms, the symmetric biorthogonal 5/3 integertransform and an integer approximation of the symmetric biorthogonal 9/7daubechies wavelet.2D IDWT(inverse discrete wavelet transform) --------------------------------------------The 2D IDWT applies a 2D filter recursively, each time combining the4 lowest frequency subbands into a single subband until only 1 subbandremains.The 2D filter is done by first applying a 1D filter in the vertical directionand then applying it in the horizontal one. --------------- --------------- --------------- ---------------|LL0|HL0|||||||||||||---+---|HL1||L0|H0|HL1||LL1|HL1|||||LH0|HH0|||||||||||||-------+-------|-> L1 H1 LH1 HH1 LH1 HH1 LH1 HH1 L1
static int add_candidate_ref(VVCContext *s, VVCFrameContext *fc, RefPicList *list, int poc, int ref_flag, uint8_t use_msb)
uint16_t poc_lsb_lt[2][VVC_MAX_REF_ENTRIES]
uint32_t num_ctus_in_curr_slice
NumCtusInCurrSlice.
static int ff_mutex_init(AVMutex *mutex, const void *attr)
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
void ff_vvc_report_frame_finished(VVCFrame *frame)
static void * ff_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque, void(*free_cb)(FFRefStructOpaque opaque, void *obj))
A wrapper around ff_refstruct_alloc_ext_c() for the common case of a non-const qualified opaque.
static int FUNC() ph(CodedBitstreamContext *ctx, RWContext *rw, H266RawPH *current)
This structure describes decoded (raw) audio or video data.
static int is_progress_done(const FrameProgress *p, const VVCProgressListener *l)
const H266RawSliceHeader * r
RefStruct reference.
uint8_t st_ref_pic_flag[VVC_MAX_REF_ENTRIES]
int ff_vvc_slice_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc)
#define fc(width, name, range_min, range_max)
uint8_t ltrp_in_header_flag
RefStruct is an API for creating reference-counted objects with minimal overhead.
static void free_progress(FFRefStructOpaque unused, void *obj)
the pkt_dts and pkt_pts fields in AVFrame will work as usual Restrictions on codec whose streams don t reset across will not work because their bitstreams cannot be decoded in parallel *The contents of buffers must not be read before as well as code calling up to before the decode process starts Call have so the codec calls ff_thread_report set FF_CODEC_CAP_ALLOCATE_PROGRESS in FFCodec caps_internal and use ff_thread_get_buffer() to allocate frames. Otherwise decode directly into the user-supplied frames. Call ff_thread_report_progress() after some part of the current picture has decoded. A good place to put this is where draw_horiz_band() is called - add this if it isn 't called anywhere
static int ff_mutex_unlock(AVMutex *mutex)
uint8_t inter_layer_ref_pic_flag[VVC_MAX_REF_ENTRIES]
H266RefPicListStruct rpl_ref_list[2]
VVCProgressListener * listener[VVC_PROGRESS_LAST]
uint8_t delta_poc_msb_cycle_present_flag[2][VVC_MAX_REF_ENTRIES]
void ff_vvc_report_progress(VVCFrame *frame, const VVCProgress vp, const int y)
void ff_vvc_unref_frame(VVCFrameContext *fc, VVCFrame *frame, int flags)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define FF_ARRAY_ELEMS(a)
#define VVC_FRAME_FLAG_LONG_REF
static const uint16_t mask[17]
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
#define AV_GET_BUFFER_FLAG_REF
The decoder will keep a reference to the frame and may reuse it later.
#define av_assert0(cond)
assert() equivalent, that is always enabled.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
static VVCFrame * generate_missing_ref(VVCContext *s, VVCFrameContext *fc, int poc)
static int delta_poc_st(const H266RefPicListStruct *rpls, const int lx, const int i, const VVCSPS *sps)
struct HEVCFrame * ref[HEVC_MAX_REFS]
void ff_vvc_clear_refs(VVCFrameContext *fc)
static void add_listener(VVCProgressListener **prev, VVCProgressListener *l)
uint8_t abs_delta_poc_st[VVC_MAX_REF_ENTRIES]
void ff_vvc_flush_dpb(VVCFrameContext *fc)
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
uint8_t strp_entry_sign_flag[VVC_MAX_REF_ENTRIES]
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining list
void(* flush)(AVBSFContext *ctx)
static int init_slice_rpl(const VVCFrameContext *fc, SliceContext *sc)
static void * ff_refstruct_allocz(size_t size)
Equivalent to ff_refstruct_alloc_ext(size, 0, NULL, NULL)
uint8_t rpls_poc_lsb_lt[VVC_MAX_REF_ENTRIES]
static VVCFrame * find_ref_idx(VVCContext *s, VVCFrameContext *fc, int poc, uint8_t use_msb)
int ff_vvc_output_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *out, const int no_output_of_prior_pics_flag, int flush)
static int ff_mutex_destroy(AVMutex *mutex)
static int poc_lt(int *prev_delta_poc_msb, const int poc, const H266RefPicLists *ref_lists, const int lx, const int j, const int max_poc_lsb)
static int FUNC() pps(CodedBitstreamContext *ctx, RWContext *rw, H264RawPPS *current)
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
static void mark_ref(VVCFrame *frame, int flag)
static FrameProgress * alloc_progress(void)
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
const uint32_t * ctb_addr_in_curr_slice
CtbAddrInCurrSlice.
static int ff_mutex_lock(AVMutex *mutex)
#define i(width, name, range_min, range_max)
atomic_int progress[VVC_PROGRESS_LAST]
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
#define VVC_FRAME_FLAG_OUTPUT
#define GDR_IS_RECOVERED(s)
VVCProgressListener * next
uint16_t delta_poc_msb_cycle_lt[2][VVC_MAX_REF_ENTRIES]
static VVCProgressListener * get_done_listener(FrameProgress *p, const VVCProgress vp)
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
static VVCProgressListener * remove_listener(VVCProgressListener **prev, VVCProgressListener *l)
static int ref[MAX_W *MAX_W]
static int ff_cond_signal(AVCond *cond)
int ff_vvc_frame_rpl(VVCContext *s, VVCFrameContext *fc, SliceContext *sc)
#define VVC_FRAME_FLAG_BUMPING
static VVCFrame * alloc_frame(VVCContext *s, VVCFrameContext *fc)
#define VVC_FRAME_FLAG_SHORT_REF
const RefPicList * ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0)
static int ff_cond_destroy(AVCond *cond)
progress_done_fn progress_done
#define flags(name, subs,...)
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
static int ff_cond_init(AVCond *cond, const void *attr)
int ff_vvc_set_new_ref(VVCContext *s, VVCFrameContext *fc, AVFrame **frame)
void ff_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
void * ff_refstruct_pool_get(FFRefStructPool *pool)
Get an object from the pool, reusing an old one from the pool when available.
void ff_vvc_add_progress_listener(VVCFrame *frame, VVCProgressListener *l)
void ff_vvc_bump_frame(VVCContext *s, VVCFrameContext *fc)