Go to the documentation of this file.
23 #include <stdatomic.h>
116 memset(t, 0,
sizeof(*t));
121 t->
rs = ry *
fc->ft->ctu_width + rx;
150 if (ry !=
pps->ctb_to_row_bd[ry]) {
152 return fc->tab.slice_idx[rs] !=
fc->tab.slice_idx[rs - ft->
ctu_width];
160 static const uint8_t target_score[] =
175 target = 2 + wpp - 1;
184 return score == target + 1;
262 if (
sps->r->sps_entropy_coding_sync_enabled_flag) {
263 if (t->
rx ==
fc->ps.pps->ctb_to_col_bd[t->
rx]) {
276 const int next_rx = next_rs % ft->
ctu_width;
277 const int next_ry = next_rs / ft->
ctu_width;
287 CTU *ctu =
fc->tab.ctus + rs;
288 for (
int lx = 0; lx < 2; lx++) {
290 const int y = ctu->
max_y[lx][
i];
303 const int slice_idx =
fc->tab.slice_idx[rs];
317 #define ADD(dx, dy, stage) frame_thread_add_score(s, ft, t->rx + (dx), t->ry + (dy), stage)
367 #define CHECK(a, b) \
378 CHECK(
a->fc->decode_order,
b->fc->decode_order);
383 return a->rx <
b->rx;
386 CHECK(
a->rx +
a->ry +
a->stage,
b->rx +
b->ry +
b->stage);
388 return a->ry <
b->ry;
405 const int progress = y == ft->
ctu_height ? INT_MAX : y * ctu_size;
417 const int rs = t->
rs;
418 const CTU *ctu =
fc->tab.ctus + rs;
435 const CTU *ctu =
fc->tab.ctus + t->
rs;
457 const int x0 = t->
rx * ctu_size;
458 const int y0 = t->
ry * ctu_size;
470 const int x0 = t->
rx * ctb_size;
471 const int y0 = t->
ry * ctb_size;
486 const int x0 = t->
rx * ctb_size;
487 const int y0 = t->
ry * ctb_size;
493 if (
fc->ps.sps->r->sps_sao_enabled_flag)
504 const int x0 = t->
rx * ctb_size;
505 const int y0 = t->
ry * ctb_size;
507 if (
fc->ps.sps->r->sps_sao_enabled_flag) {
512 if (
fc->ps.sps->r->sps_alf_enabled_flag)
523 const int x0 = t->
rx * ctu_size;
524 const int y0 = t->
ry * ctu_size;
526 if (
fc->ps.sps->r->sps_alf_enabled_flag) {
535 #define VVC_THREAD_DEBUG
536 #ifdef VVC_THREAD_DEBUG
568 #ifdef VVC_THREAD_DEBUG
575 if ((
ret =
run[stage](
s, lc, t)) < 0) {
576 #ifdef COMPAT_ATOMICS_WIN32_STDATOMIC_H
583 "frame %5d, %s(%3d, %3d) failed with %d\r\n",
715 for (
int rs = 0; rs < ft->
ctu_count; rs++) {
740 if (
fc->ps.ph.r->ph_temporal_mvp_enabled_flag ||
fc->ps.sps->r->sps_sbtmvp_enabled_flag) {
742 const int first_col = t->
rx ==
fc->ps.pps->ctb_to_col_bd[t->
rx];
743 if (col && first_col) {
745 const int y = (t->
ry <<
fc->ps.sps->ctb_log2_size_y);
765 for (
int i = 0;
i <
fc->nb_slices;
i++) {
767 for (
int j = 0; j < sc->
nb_eps; j++) {
769 for (
int k = ep->
ctu_start; k < ep->ctu_end; k++) {
793 #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)
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]
void ff_vvc_deblock_vertical(const VVCLocalContext *lc, const int x0, const int y0, const int rs)
vertical deblock filter for the CTU
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)
void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, const int x0, const int y0, const int rs)
horizontal deblock filter for the CTU
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 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)