Go to the documentation of this file.
23 #include <stdatomic.h>
115 memset(t, 0,
sizeof(*t));
120 t->
rs = ry *
fc->ft->ctu_width + rx;
149 if (ry !=
pps->ctb_to_row_bd[ry]) {
151 return fc->tab.slice_idx[rs] !=
fc->tab.slice_idx[rs - ft->
ctu_width];
159 static const uint8_t target_score[] =
174 target = 2 + wpp - 1;
183 return score == target + 1;
261 if (
sps->r->sps_entropy_coding_sync_enabled_flag) {
262 if (t->
rx ==
fc->ps.pps->ctb_to_col_bd[t->
rx]) {
275 const int next_rx = next_rs % ft->
ctu_width;
276 const int next_ry = next_rs / ft->
ctu_width;
286 CTU *ctu =
fc->tab.ctus + rs;
287 for (
int lx = 0; lx < 2; lx++) {
289 const int y = ctu->
max_y[lx][
i];
302 const int slice_idx =
fc->tab.slice_idx[rs];
316 #define ADD(dx, dy, stage) frame_thread_add_score(s, ft, t->rx + (dx), t->ry + (dy), stage)
366 #define CHECK(a, b) \
377 CHECK(
a->fc->decode_order,
b->fc->decode_order);
382 return a->rx <
b->rx;
385 CHECK(
a->rx +
a->ry +
a->stage,
b->rx +
b->ry +
b->stage);
387 return a->ry <
b->ry;
404 const int progress = y == ft->
ctu_height ? INT_MAX : y * ctu_size;
416 const int rs = t->
rs;
417 const CTU *ctu =
fc->tab.ctus + rs;
437 const CTU *ctu =
fc->tab.ctus + rs;
438 const int slice_idx =
fc->tab.slice_idx[rs];
440 if (slice_idx != -1) {
441 lc->
sc =
fc->slices[slice_idx];
454 const int rs = t->
rs;
455 const int slice_idx =
fc->tab.slice_idx[rs];
457 if (slice_idx != -1) {
458 lc->
sc =
fc->slices[slice_idx];
470 const int x0 = t->
rx * ctu_size;
471 const int y0 = t->
ry * ctu_size;
473 const int slice_idx =
fc->tab.slice_idx[rs];
475 if (slice_idx != -1) {
476 lc->
sc =
fc->slices[slice_idx];
489 const int x0 = t->
rx * ctb_size;
490 const int y0 = t->
ry * ctb_size;
491 const int slice_idx =
fc->tab.slice_idx[rs];
493 if (slice_idx != -1) {
494 lc->
sc =
fc->slices[slice_idx];
510 const int x0 = t->
rx * ctb_size;
511 const int y0 = t->
ry * ctb_size;
512 const int slice_idx =
fc->tab.slice_idx[rs];
514 if (slice_idx != -1) {
515 lc->
sc =
fc->slices[slice_idx];
520 if (
fc->ps.sps->r->sps_sao_enabled_flag)
531 const int rs = t->
ry *
fc->ps.pps->ctb_width + t->
rx;
533 const int x0 = t->
rx * ctb_size;
534 const int y0 = t->
ry * ctb_size;
536 if (
fc->ps.sps->r->sps_sao_enabled_flag) {
541 if (
fc->ps.sps->r->sps_alf_enabled_flag)
552 const int x0 = t->
rx * ctu_size;
553 const int y0 = t->
ry * ctu_size;
555 if (
fc->ps.sps->r->sps_alf_enabled_flag) {
556 const int slice_idx =
CTB(
fc->tab.slice_idx, t->
rx, t->
ry);
557 if (slice_idx != -1) {
558 lc->
sc =
fc->slices[slice_idx];
568 #define VVC_THREAD_DEBUG
569 #ifdef VVC_THREAD_DEBUG
601 #ifdef VVC_THREAD_DEBUG
606 if ((
ret =
run[stage](
s, lc, t)) < 0) {
607 #ifdef COMPAT_ATOMICS_WIN32_STDATOMIC_H
614 "frame %5d, %s(%3d, %3d) failed with %d\r\n",
746 for (
int rs = 0; rs < ft->
ctu_count; rs++) {
771 if (
fc->ps.ph.r->ph_temporal_mvp_enabled_flag ||
fc->ps.sps->r->sps_sbtmvp_enabled_flag) {
773 const int first_col = t->
rx ==
fc->ps.pps->ctb_to_col_bd[t->
rx];
774 if (col && first_col) {
776 const int y = (t->
ry <<
fc->ps.sps->ctb_log2_size_y);
796 for (
int i = 0;
i <
fc->nb_slices;
i++) {
798 for (
int j = 0; j < sc->
nb_eps; j++) {
800 for (
int k = ep->
ctu_start; k < ep->ctu_end; k++) {
824 #ifdef VVC_THREAD_DEBUG
static uint8_t task_get_score(VVCTask *t, const VVCTaskStage stage)
void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y)
sao filter for the CTU
static void add_task(VVCContext *s, VVCTask *t)
static int ff_mutex_init(AVMutex *mutex, const void *attr)
#define atomic_store(object, desired)
void ff_vvc_lmcs_filter(const VVCLocalContext *lc, const int x, const int y)
lmcs filter for the CTU
static void listener_init(ProgressListener *l, VVCTask *t, VVCContext *s, const VVCProgress vp, const int y)
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
static void task_init_parse(VVCTask *t, SliceContext *sc, EntryPoint *ep, const int ctu_idx)
void ff_vvc_report_frame_finished(VVCFrame *frame)
const static char * task_name[]
void ff_vvc_alf_filter(VVCLocalContext *lc, const int x0, const int y0)
alf filter for the CTU
static int run_parse(VVCContext *s, VVCLocalContext *lc, VVCTask *t)
int ff_vvc_predict_inter(VVCLocalContext *lc, const int rs)
Loop entire CTU to predict all inter coding blocks.
static const OMX_CALLBACKTYPE callbacks
static int task_is_stage_ready(VVCTask *t, int add)
const H266RawSliceHeader * r
RefStruct reference.
static void schedule_next_parse(VVCContext *s, VVCFrameContext *fc, const SliceContext *sc, const VVCTask *t)
#define fc(width, name, range_min, range_max)
static int run_recon(VVCContext *s, VVCLocalContext *lc, VVCTask *t)
static int ff_mutex_unlock(AVMutex *mutex)
static void schedule_inter(VVCContext *s, VVCFrameContext *fc, const SliceContext *sc, VVCTask *t, const int rs)
static int task_ready(const AVTask *_t, void *user_data)
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
#define atomic_fetch_sub(object, operand)
@ VVC_TASK_STAGE_DEBLOCK_V
AVExecutor * av_executor_alloc(const AVTaskCallbacks *cb, int thread_count)
Alloc executor.
void ff_vvc_report_progress(VVCFrame *frame, const VVCProgress vp, const int y)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define FF_ARRAY_ELEMS(a)
atomic_int nb_scheduled_tasks
static void frame_thread_init_score(VVCFrameContext *fc)
static void parse_task_done(VVCContext *s, VVCFrameContext *fc, const int rx, const int ry)
static void progress_done(VVCProgressListener *_l, const int type)
VVCCabacState cabac_state[VVC_CONTEXTS]
static int ff_cond_wait(AVCond *cond, AVMutex *mutex)
#define av_assert0(cond)
assert() equivalent, that is always enabled.
int ff_vvc_coding_tree_unit(VVCLocalContext *lc, const int ctu_idx, const int rs, const int rx, const int ry)
parse a CTU
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
struct VVCFrameThread * ft
static void pixel_done(VVCProgressListener *l)
struct HEVCFrame * ref[HEVC_MAX_REFS]
atomic_int col_progress[VVC_PROGRESS_LAST]
int ff_vvc_frame_wait(VVCContext *s, VVCFrameContext *fc)
#define atomic_load(object)
static int run_lmcs(VVCContext *s, VVCLocalContext *lc, VVCTask *t)
static void add_progress_listener(VVCFrame *ref, ProgressListener *l, VVCTask *t, VVCContext *s, const VVCProgress vp, const int y)
static void frame_thread_add_score(VVCContext *s, VVCFrameThread *ft, const int rx, const int ry, const VVCTaskStage stage)
static void mv_done(VVCProgressListener *l)
static void task_init(VVCTask *t, VVCTaskStage stage, VVCFrameContext *fc, const int rx, const int ry)
static void submit_entry_point(VVCContext *s, VVCFrameThread *ft, SliceContext *sc, EntryPoint *ep)
void ff_vvc_frame_thread_free(VVCFrameContext *fc)
void ff_vvc_sao_copy_ctb_to_hv(VVCLocalContext *lc, const int rx, const int ry, const int last_row)
atomic_int nb_scheduled_listeners
static int ff_mutex_destroy(AVMutex *mutex)
#define atomic_compare_exchange_strong(object, expected, desired)
ProgressListener col_listener
ProgressListener listener[2][VVC_MAX_REF_ENTRIES]
static int run_deblock_v(VVCContext *s, VVCLocalContext *lc, VVCTask *t)
static int FUNC() pps(CodedBitstreamContext *ctx, RWContext *rw, H264RawPPS *current)
void ff_vvc_deblock_vertical(const VVCLocalContext *lc, int x0, int y0)
vertical deblock filter for the CTU
static void report_frame_progress(VVCFrameContext *fc, const int ry, const VVCProgress idx)
void ff_vvc_alf_copy_ctu_to_hv(VVCLocalContext *lc, const int x0, const int y0)
static int FUNC() user_data(CodedBitstreamContext *ctx, RWContext *rw, MPEG2RawUserData *current)
static int run_alf(VVCContext *s, VVCLocalContext *lc, VVCTask *t)
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
static uint8_t task_add_score(VVCTask *t, const VVCTaskStage stage)
int(* run_func)(VVCContext *s, VVCLocalContext *lc, VVCTask *t)
const uint32_t * ctb_addr_in_curr_slice
CtbAddrInCurrSlice.
static int ff_mutex_lock(AVMutex *mutex)
static int is_first_row(const VVCFrameContext *fc, const int rx, const int ry)
void ff_vvc_ep_init_stat_coeff(EntryPoint *ep, const int bit_depth, const int persistent_rice_adaptation_enabled_flag)
void ff_vvc_decode_neighbour(VVCLocalContext *lc, const int x_ctb, const int y_ctb, const int rx, const int ry, const int rs)
int max_y[2][VVC_MAX_REF_ENTRIES]
static int task_priority_higher(const AVTask *_a, const AVTask *_b)
#define i(width, name, range_min, range_max)
static int run_sao(VVCContext *s, VVCLocalContext *lc, VVCTask *t)
int ff_vvc_frame_thread_init(VVCFrameContext *fc)
void * av_calloc(size_t nmemb, size_t size)
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
void ff_vvc_executor_free(AVExecutor **e)
void av_executor_free(AVExecutor **executor)
Free executor.
int row_progress[VVC_PROGRESS_LAST]
static int task_run(AVTask *_t, void *local_context, void *user_data)
void ff_vvc_frame_submit(VVCContext *s, VVCFrameContext *fc)
void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, int x0, int y0)
horizontal deblock filter for the CTU
void av_executor_execute(AVExecutor *e, AVTask *t)
Add task to executor.
#define atomic_fetch_add(object, operand)
int ff_vvc_reconstruct(VVCLocalContext *lc, const int rs, const int rx, const int ry)
reconstruct a CTU
static int ref[MAX_W *MAX_W]
static int ff_cond_signal(AVCond *cond)
uint8_t sps_entropy_coding_sync_enabled_flag
atomic_uchar score[VVC_TASK_STAGE_LAST]
atomic_uchar target_inter_score
static int run_inter(VVCContext *s, VVCLocalContext *lc, VVCTask *t)
@ VVC_TASK_STAGE_DEBLOCK_H
static void task_run_stage(VVCTask *t, VVCContext *s, VVCLocalContext *lc)
static void check_colocation(VVCContext *s, VVCTask *t)
static void task_stage_done(const VVCTask *t, VVCContext *s)
static void sheduled_done(VVCFrameThread *ft, atomic_int *scheduled)
static int ff_cond_destroy(AVCond *cond)
#define ADD(dx, dy, stage)
progress_done_fn progress_done
static int run_deblock_h(VVCContext *s, VVCLocalContext *lc, VVCTask *t)
static int ff_cond_init(AVCond *cond, const void *attr)
AVExecutor * ff_vvc_executor_alloc(VVCContext *s, const int thread_count)
void ff_vvc_add_progress_listener(VVCFrame *frame, VVCProgressListener *l)
static int task_has_target_score(VVCTask *t, const VVCTaskStage stage, const uint8_t score)