Go to the documentation of this file.
27 #define POS(x, y) src[(x) + stride * (y)]
30 const int w,
const int h,
const pixel* pdsy,
const int *
a,
const int *
b,
const int *k)
34 const int c_idx =
i + 1;
35 const int x = x0 >>
sps->hshift[c_idx];
36 const int y = y0 >>
sps->vshift[c_idx];
37 const ptrdiff_t
stride =
fc->frame->linesize[c_idx] /
sizeof(
pixel);
39 for (
int y = 0; y <
h; y++) {
40 for (
int x = 0; x <
w; x++) {
41 const int dsy = pdsy[y *
w + x];
42 const int pred = ((dsy *
a[
i]) >> k[
i]) +
b[
i];
49 #define MAX_PICK_POS 4
55 for (
int i = 0;
i < 2;
i++) {
62 const int x,
const int y,
const int w,
const int h,
const int avail_t,
const int avail_l,
70 num_samp[
TOP] = avail_t ?
w : 0;
71 num_samp[
LEFT] = avail_l ?
h : 0;
76 if (!num_samp[
TOP] && !num_samp[
LEFT]) {
80 const int start = num_samp[
i] >> (2 + num_is4);
81 const int step =
FFMAX(1, num_samp[
i] >> (1 + num_is4)) ;
82 cnt[
i] =
FFMIN(num_samp[
i], (1 + num_is4) << 1);
83 for (
int c = 0;
c < cnt[
i];
c++)
92 for (
int i = 0;
i < cnt;
i++)
97 const int x0,
const int y0,
const int avail_t,
const int avail_l,
const int cnt[2],
const int pos[2][
MAX_PICK_POS],
103 const int hs =
sps->hshift[1];
104 const int vs =
sps->vshift[1];
105 const ptrdiff_t
stride =
fc->frame->linesize[0] /
sizeof(
pixel);
113 if (vs && !b_ctu_boundary) {
115 for (
int i = 0;
i < cnt[
TOP];
i++) {
116 const int x =
pos[
TOP][
i] << hs;
118 const int has_left = x || avail_l;
120 if (
sps->r->sps_chroma_vertical_collocated_flag) {
121 sel_luma[
i] = (
POS(0, -1) + l + 4 *
POS(0, 0) +
POS(1, 0) +
POS(0, 1) + 4) >> 3;
123 const pixel l1 = has_left ?
POS(-1, 1) :
POS(0, 1);
124 sel_luma[
i] = (l + l1 + 2 * (
POS(0, 0) +
POS(0, 1)) +
POS(1, 0) +
POS(1, 1) + 4) >> 3;
129 for (
int i = 0;
i < cnt[
TOP];
i++) {
130 const int x =
pos[
TOP][
i] << hs;
132 const int has_left = x || avail_l;
134 sel_luma[
i] = (l + 2 *
POS(0, 0) +
POS(1, 0) + 2) >> 2;
144 for (
int i = 0;
i < cnt[
LEFT];
i++) {
151 pred = (*l + 2 *
POS(0, 0) +
POS(1, 0) + 2) >> 2;
153 if (
sps->r->sps_chroma_vertical_collocated_flag) {
154 const int has_top = y || avail_t;
156 pred = (*l + t + 4 *
POS(0, 0) +
POS(1, 0) +
POS(0, 1) + 4) >> 3;
168 const int x,
const int y,
const int cnt[2],
const int pos[2][
MAX_PICK_POS],
172 const ptrdiff_t
stride =
fc->frame->linesize[c_idx] /
sizeof(
pixel);
176 for (
int i = 0;
i < cnt[
TOP];
i++) {
189 const int x0,
const int y0,
const int w,
const int h,
const int avail_t,
const int avail_l,
194 const int x = x0 >>
sps->hshift[1];
195 const int y = y0 >>
sps->vshift[1];
204 if (cnt[
TOP] + cnt[
LEFT] == 2) {
206 sel[c_idx][3] = sel[c_idx][0];
207 sel[c_idx][2] = sel[c_idx][1];
208 sel[c_idx][0] = sel[c_idx][1];
209 sel[c_idx][1] = sel[c_idx][3];
218 int min_grp_idx[] = { 0, 2 };
219 int max_grp_idx[] = { 1, 3 };
221 if (sel[
LUMA][min_grp_idx[0]] > sel[
LUMA][min_grp_idx[1]])
222 FFSWAP(
int, min_grp_idx[0], min_grp_idx[1]);
223 if (sel[
LUMA][max_grp_idx[0]] > sel[
LUMA][max_grp_idx[1]])
224 FFSWAP(
int, max_grp_idx[0], max_grp_idx[1]);
225 if (sel[
LUMA][min_grp_idx[0]] > sel[
LUMA][max_grp_idx[1]]) {
226 FFSWAP(
int, min_grp_idx[0], max_grp_idx[0]);
227 FFSWAP(
int, min_grp_idx[1], max_grp_idx[1]);
229 if (sel[
LUMA][min_grp_idx[1]] > sel[
LUMA][max_grp_idx[0]])
230 FFSWAP(
int, min_grp_idx[1], max_grp_idx[0]);
232 max[c_idx] = (sel[c_idx][max_grp_idx[0]] + sel[c_idx][max_grp_idx[1]] + 1) >> 1;
233 min[c_idx] = (sel[c_idx][min_grp_idx[0]] + sel[c_idx][min_grp_idx[1]] + 1) >> 1;
238 const int x0,
const int y0,
const int w,
const int h,
const int avail_t,
const int avail_l,
239 int *
a,
int *
b,
int *k)
254 for (
int i = 0;
i < 2;
i++) {
260 for (
int i = 0;
i < 2;
i++) {
261 const static int div_sig_table[] = {0, 7, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 0};
262 const int diffc =
max[
i + 1] -
min[
i + 1];
265 const int norm_diff = ((diff << 4) >> x) & 15;
266 x += (norm_diff) ? 1 : 0;
268 v = div_sig_table[norm_diff] | 8;
270 a[
i] = (diffc * v + add) >> y;
271 k[
i] =
FFMAX(1, 3 + x -y);
272 sign =
a[
i] < 0 ? -1 : (
a[
i] > 0);
273 a[
i] = ((3 + x - y) < 1) ? sign * 15 :
a[
i];
283 const int x0,
const int y0,
const int w,
const int h,
const int avail_t,
const int avail_l,
286 const int hs =
fc->ps.sps->hshift[1];
287 const int vs =
fc->ps.sps->vshift[1];
288 const ptrdiff_t
stride =
fc->frame->linesize[0] /
sizeof(
pixel);
295 for (
int i = 0;
i <
h;
i++)
299 for (
int i = 0;
i <
h;
i++) {
302 const pixel *t = top;
304 for (
int j = 0; j <
w; j++) {
312 if (
sps->r->sps_chroma_vertical_collocated_flag) {
313 for (
int j = 0; j <
w; j++) {
321 for (
int j = 0; j <
w; j++) {
337 const int x,
const int y,
const int w,
const int h,
const int avail_t,
const int avail_l)
340 const ptrdiff_t
stride =
fc->frame->linesize[c_idx] /
sizeof(
pixel);
343 for (
int j = 0; j <
w; j++) {
359 const int hs =
sps->hshift[1];
360 const int vs =
sps->vshift[1];
361 const int x = x0 >> hs;
362 const int y = y0 >> vs;
363 const int w =
width >> hs;
365 int a[2],
b[2], k[2];
368 if (!avail_t && !avail_l) {
379 const int size =
FFMIN(avail, target_size);
381 for (
int i = 0;
i <
size;
i++) {
385 sum += *(start -
stride) * (target_size -
size);
394 const int size_y =
FFMIN(
fc->ps.sps->ctb_size_y, 64);
396 const int x = x0 & ~(size_y - 1);
397 const int y = y0 & ~(size_y - 1);
398 if (lc->lmcs.x_vpdu != x || lc->lmcs.y_vpdu != y) {
399 int cnt = 0, luma = 0,
i;
413 luma = (luma + (cnt >> 1)) >>
av_log2(cnt);
418 if (luma < lmcs->pivot[
i + 1])
427 return lc->lmcs.chroma_scale;
432 const int width,
const int height,
const int x0_cu,
const int y0_cu)
436 for (
int y = 0; y <
height; y++) {
437 for (
int x = 0; x <
width; x++) {
441 *
dst = (
c * chroma_scale + (1 << 10)) >> 11;
443 *
dst = -((-
c * chroma_scale + (1 << 10)) >> 11);
451 pixel *filtered_left,
pixel *filtered_top,
const int left_size,
const int top_size,
452 const int unfilter_last_one)
454 filtered_left[-1] = filtered_top[-1] = (
left[0] + 2 *
left[-1] + top[0] + 2 ) >> 2;
455 for (
int i = 0;
i < left_size - unfilter_last_one;
i++) {
458 for (
int i = 0;
i < top_size - unfilter_last_one;
i++) {
459 filtered_top[
i] = (top[
i-1] + 2 * top[
i] + top[
i + 1] + 2) >> 2;
461 if (unfilter_last_one) {
462 filtered_top[top_size - 1] = top[top_size - 1];
463 filtered_left[left_size - 1] =
left[left_size - 1];
469 const int x,
int y,
int w,
int h,
int c_idx,
const int is_intra_mip,
470 const int mode,
const int ref_idx,
const int need_pdpc)
472 #define EXTEND(ptr, val, len) \
474 for (i = 0; i < (len); i++) \
479 const int filter_flag = !ref_idx &&
w *
h > 32 && !c_idx &&
481 int cand_up_left = lc->na.cand_up_left;
486 const int ref_line = ref_idx == 3 ? -4 : (-1 - ref_idx);
487 int left_size, top_size, unfilter_left_size, unfilter_top_size;
488 int left_available, top_available;
490 int intra_pred_angle, inv_angle;
496 unfilter_left_size = left_size + filter_flag;
497 unfilter_top_size = top_size + filter_flag;
499 unfilter_left_size = left_size =
h;
500 unfilter_top_size = top_size =
w;
503 unfilter_left_size = left_size = need_pdpc ?
h : 1;
504 unfilter_top_size = top_size =
w;
506 unfilter_left_size = left_size =
h;
508 unfilter_top_size = top_size = need_pdpc ?
w : 1;
519 unfilter_top_size = top_size = refw;
520 unfilter_left_size = left_size = refh;
524 for (
i = 0;
i < left_available;
i++)
528 memcpy(top,
src + ref_line *
stride, top_available *
sizeof(
pixel));
530 for (
int i = -1;
i >= ref_line;
i--) {
533 top[
i] =
POS(
i, ref_line);
534 }
else if (left_available) {
536 }
else if (top_available) {
537 left[
i] = top[
i] = top[0];
543 EXTEND(top + top_available, top[top_available-1], unfilter_top_size - top_available);
544 EXTEND(
left + left_available,
left[left_available-1], unfilter_left_size - left_available);
546 if (ref_filter_flag) {
548 const int unfilter_last_one = left_size == unfilter_left_size;
549 FUNC(
ref_filter)(
left, top, filtered_left, filtered_top, unfilter_left_size, unfilter_top_size, unfilter_last_one);
550 left = filtered_left;
556 edge->filter_flag = 0;
559 const int intra_hor_ver_dist_thres[] = {24, 14, 2, 0, 0};
561 edge->filter_flag = min_dist_ver_hor > intra_hor_ver_dist_thres[ntbs - 2];
566 if (intra_pred_angle < 0) {
567 pixel *p = top - (ref_idx + 1);
568 for (
int x = -
h; x < 0; x++) {
569 const int idx = -1 - ref_idx +
FFMIN((x*inv_angle + 256) >> 9,
h);
573 for (
int i = refw;
i <= refw +
FFMAX(1,
w/
h) * ref_idx + 1;
i++)
574 top[
i] = top[refw - 1];
577 if (intra_pred_angle < 0) {
579 for (
int x = -
w; x < 0; x++) {
580 const int idx = -1 - ref_idx +
FFMIN((x*inv_angle + 256) >> 9,
w);
584 for (
int i = refh;
i <= refh +
FFMAX(1,
h/
w) * ref_idx + 1;
i++)
590 edge->left = (uint8_t*)
left;
591 edge->top = (uint8_t*)top;
602 const int log2_min_cb_size =
sps->min_cb_log2_size_y;
603 const int min_cb_width =
pps->min_cb_width;
604 const int x_cb = x0 >> log2_min_cb_size;
605 const int y_cb = y0 >> log2_min_cb_size;
607 const int hshift =
fc->ps.sps->hshift[c_idx];
608 const int vshift =
fc->ps.sps->vshift[c_idx];
609 const int x = x0 >> hshift;
610 const int y = y0 >>
vshift;
611 const int w =
width >> hshift;
613 const ptrdiff_t
stride =
fc->frame->linesize[c_idx] /
sizeof(
pixel);
618 const int intra_mip_flag =
SAMPLE_CTB(
fc->tab.imf, x_cb, y_cb);
627 FUNC(
prepare_intra_edge_params)(lc, &edge,
src,
stride, x, y,
w,
h, c_idx, is_intra_mip,
mode, ref_idx, need_pdpc);
630 int intra_mip_transposed_flag;
632 unpack_mip_info(&intra_mip_transposed_flag, &intra_mip_mode, intra_mip_flag);
634 fc->vvcdsp.intra.pred_mip((uint8_t *)
src, edge.top, edge.left,
635 w,
h,
stride, intra_mip_mode, intra_mip_transposed_flag);
637 fc->vvcdsp.intra.pred_planar((uint8_t *)
src, edge.top, edge.left,
w,
h,
stride);
639 fc->vvcdsp.intra.pred_dc((uint8_t *)
src, edge.top, edge.left,
w,
h,
stride);
641 fc->vvcdsp.intra.pred_v((uint8_t *)
src, edge.top,
w,
h,
stride);
643 fc->vvcdsp.intra.pred_h((uint8_t *)
src, edge.left,
w,
h,
stride);
646 fc->vvcdsp.intra.pred_angular_v((uint8_t *)
src, edge.top, edge.left,
648 edge.filter_flag, need_pdpc);
650 fc->vvcdsp.intra.pred_angular_h((uint8_t *)
src, edge.top, edge.left,
652 edge.filter_flag, need_pdpc);
662 for (
int y = 0; y <
h; y++) {
663 for (
int x = 0; x <
w; x++) {
664 int l, t, wl, wt,
pred;
673 t = top[x] - top[-1] +
POS(x,y);
688 const uint8_t *_left,
const int w,
const int h,
const ptrdiff_t
stride)
697 const int shift = (logw + logh + 1);
698 for (y = 0; y <
h; y++) {
699 for (x = 0; x <
w; x++) {
700 const int pred_v = ((
h - 1 - y) * top[x] + (y + 1) *
left[
h]) << logw;
701 const int pred_h = ((
w - 1 - x) *
left[y] + (x + 1) * top[
w]) << logh;
712 const int b_dwn = n_tb_s / boundary_size;
715 if (boundary_size == n_tb_s) {
716 for (
int i = 0;
i < n_tb_s;
i++)
720 for (
int i = 0;
i < boundary_size;
i++) {
723 for (
int j = 1; j < b_dwn; j++)
730 const int up_hor,
const int up_ver,
const int pred_size,
const int *reduced,
const int reduced_size,
731 const int ow,
const int temp0,
const uint8_t *
matrix,
int is_transposed)
733 src = &
POS(up_hor - 1, up_ver - 1);
734 for (
int y = 0; y < pred_size; y++) {
735 for (
int x = 0; x < pred_size; x++) {
737 for (
int i = 0;
i < reduced_size;
i++)
743 POS(y * up_hor, x * up_ver) =
pred;
745 POS(x * up_hor, y * up_ver) =
pred;
751 const pixel *boundary,
const int boundary_step,
const int pred_size)
754 for (
int i = 0;
i < dst_height;
i++) {
755 const pixel *before = boundary;
756 const pixel *after =
dst - dst_step;
758 for (
int j = 0; j < pred_size; j++) {
759 after += dst_step *
factor;
760 for (
int k = 1; k <
factor; k++) {
761 int mid = (
factor - k) * (*before) + k * (*after);
768 boundary += boundary_step;
775 const uint8_t *_left,
const int w,
const int h,
const ptrdiff_t
stride,
776 int mode_id,
int is_transposed)
783 static const int boundary_sizes[] = {2, 4, 4};
784 static const int pred_sizes[] = {4, 4, 8};
785 const int boundary_size = boundary_sizes[size_id];
786 const int pred_size = pred_sizes[size_id];
787 const int in_size = 2 * boundary_size - ((size_id == 2) ? 1 : 0);
789 const int up_hor =
w / pred_size;
790 const int up_ver =
h / pred_size;
793 int *red_t = reduced;
794 int *red_l = reduced + boundary_size;
799 FFSWAP(
int*, red_t, red_l);
809 ow = reduced[1] - temp0;
812 for (
int i = 1;
i < in_size;
i++) {
813 reduced[
i] = reduced[
i + off] - temp0;
818 FUNC(
mip_reduced_pred)(
src,
stride, up_hor, up_ver, pred_size, reduced, in_size, ow, temp0,
matrix, is_transposed);
819 if (up_hor > 1 || up_ver > 1) {
828 const int w,
const int h)
836 for (
int i = 0;
i <
w;
i++)
840 for (
int i = 0;
i <
h;
i++)
849 const uint8_t *_left,
const int w,
const int h,
const ptrdiff_t
stride)
857 for (y = 0; y <
h; y++) {
859 for (x = 0; x <
w; x += 4) {
868 const int w,
const int h,
const ptrdiff_t
stride)
872 for (
int y = 0; y <
h; y++) {
883 for (
int y = 0; y <
h; y++) {
885 for (
int x = 0; x <
w; x += 4) {
891 #define INTRA_LUMA_FILTER(p) CLIP((p[0] * f[0] + p[1] * f[1] + p[2] * f[2] + p[3] * f[3] + 32) >> 6)
892 #define INTRA_CHROMA_FILTER(p) (((32 - fact) * p[1] + fact * p[2] + 16) >> 5)
896 const int w,
const int h,
const ptrdiff_t
stride,
const int c_idx,
const int mode,
897 const int ref_idx,
const int filter_flag,
const int need_pdpc)
901 const pixel *top = (
const pixel *)_top - (1 + ref_idx);
903 int pos = (1 + ref_idx) * intra_pred_angle;
904 const int dp = intra_pred_angle;
905 const int is_luma = !c_idx;
906 int nscale, inv_angle;
913 for (
int y = 0; y <
h; y++) {
914 const int idx = (
pos >> 5) + ref_idx;
916 if (!
fact && (!is_luma || !filter_flag)) {
917 for (
int x = 0; x <
w; x++) {
918 const pixel *p = top + x + idx + 1;
924 for (
int x = 0; x <
w; x++) {
925 const pixel *p = top + x + idx;
929 for (
int x = 0; x <
w; x++) {
930 const pixel *p = top + x + idx;
936 int inv_angle_sum = 256 + inv_angle;
937 for (
int x = 0; x <
FFMIN(
w, 3 << nscale); x++) {
938 const pixel l =
left[y + (inv_angle_sum >> 9)];
940 const int wl = 32 >> ((x << 1) >> nscale);
941 const int pred =
val + (((l -
val) * wl + 32) >> 6);
943 inv_angle_sum += inv_angle;
952 const int w,
const int h,
const ptrdiff_t
stride,
const int c_idx,
const int mode,
953 const int ref_idx,
const int filter_flag,
const int need_pdpc)
958 const int is_luma = !c_idx;
960 const int dp = intra_pred_angle;
961 int nscale = 0, inv_angle, inv_angle_sum;
965 inv_angle_sum = 256 + inv_angle;
969 for (
int y = 0; y <
h; y++) {
970 int pos = (1 + ref_idx) * intra_pred_angle;
973 wt = (32 >>
FFMIN(31, (y * 2) >> nscale));
975 for (
int x = 0; x <
w; x++) {
976 const int idx = (
pos >> 5) + ref_idx;
980 if (!
fact && (!is_luma || !filter_flag)) {
991 if (y < (3 << nscale)) {
992 const pixel t = top[x + (inv_angle_sum >> 9)];
1000 inv_angle_sum += inv_angle;
static av_always_inline void FUNC() pred_planar(uint8_t *_src, const uint8_t *_top, const uint8_t *_left, const int w, const int h, const ptrdiff_t stride)
static av_always_inline void FUNC() cclm_get_min_max(const pixel sel[][MAX_PICK_POS *2], int *min, int *max)
static av_always_inline void FUNC() mip_upsampling_1d(pixel *dst, const int dst_step, const int dst_stride, const int dst_height, const int factor, const pixel *boundary, const int boundary_step, const int pred_size)
static int FUNC() lmcs_derive_chroma_scale(VVCLocalContext *lc, const int x0, const int y0)
int ff_vvc_ref_filter_flag_derive(int mode)
int bdpcm_flag[VVC_MAX_SAMPLE_ARRAYS]
BdpcmFlag.
#define LMCS_MAX_BIN_SIZE
static void FUNC() ff_vvc_intra_dsp_init(VVCIntraDSPContext *const intra)
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
#define fc(width, name, range_min, range_max)
uint8_t ptrdiff_t const uint8_t * _src
uint16_t chroma_scale_coeff[LMCS_MAX_BIN_SIZE]
int ff_vvc_intra_pred_angle_derive(int pred_mode)
int ff_vvc_get_mip_size_id(int w, int h)
static double val(void *priv, double ch)
static void FUNC() intra_cclm_pred(const VVCLocalContext *lc, const int x0, const int y0, const int width, const int height)
int ff_vvc_get_top_available(const VVCLocalContext *lc, int x0, int y0, int target_size, int c_idx)
static av_always_inline void FUNC() cclm_get_luma_rec_pixels(const VVCFrameContext *fc, const int x0, const int y0, const int w, const int h, const int avail_t, const int avail_l, pixel *pdsy)
const int8_t ff_vvc_intra_luma_filter[VVC_INTRA_LUMA_TYPES][VVC_INTRA_LUMA_FACTS][VVC_INTRA_LUMA_TAPS]
static av_always_inline void FUNC() cclm_linear_pred(VVCFrameContext *fc, const int x0, const int y0, const int w, const int h, const pixel *pdsy, const int *a, const int *b, const int *k)
static av_always_inline void FUNC() cclm_select_luma(const VVCFrameContext *fc, const int x0, const int y0, const int avail_t, const int avail_l, const int cnt[2], const int pos[2][MAX_PICK_POS], pixel *sel_luma)
#define PIXEL_SPLAT_X4(x)
static av_always_inline void FUNC() cclm_get_params(const VVCLocalContext *lc, const int x0, const int y0, const int w, const int h, const int avail_t, const int avail_l, int *a, int *b, int *k)
int ff_vvc_intra_inv_angle_derive(int pred_mode)
static void FUNC() pred_h(uint8_t *_src, const uint8_t *_left, const int w, const int h, const ptrdiff_t stride)
uint8_t intra_luma_ref_idx
IntraLumaRefLineIdx[][].
#define INTRA_CHROMA_FILTER(p)
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
#define SAMPLE_CTB(tab, x, y)
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 source
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled top and top right vectors is used as motion vector prediction the used motion vector is the sum of the predictor and(mvx_diff, mvy_diff) *mv_scale Intra DC Prediction block[y][x] dc[1]
static av_always_inline void FUNC() cclm_select_luma_444(const pixel *src, const int step, const int cnt, const int pos[MAX_PICK_POS], pixel *sel_luma)
IntraPredMode intra_pred_mode_y
IntraPredModeY.
static int shift(int a, int b)
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
static av_always_inline void FUNC() prepare_intra_edge_params(const VVCLocalContext *lc, IntraEdgeParams *edge, const pixel *src, const ptrdiff_t stride, const int x, int y, int w, int h, int c_idx, const int is_intra_mip, const int mode, const int ref_idx, const int need_pdpc)
static void FUNC() pred_angular_h(uint8_t *_src, const uint8_t *_top, const uint8_t *_left, const int w, const int h, const ptrdiff_t stride, const int c_idx, const int mode, const int ref_idx, const int filter_flag, const int need_pdpc)
static av_always_inline void FUNC() mip_reduced_pred(pixel *src, const ptrdiff_t stride, const int up_hor, const int up_ver, const int pred_size, const int *reduced, const int reduced_size, const int ow, const int temp0, const uint8_t *matrix, int is_transposed)
static av_always_inline void unpack_mip_info(int *intra_mip_transposed_flag, int *intra_mip_mode, const uint8_t mip_info)
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
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
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 offset
static av_always_inline void FUNC() mip_downsampling(int *reduced, const int boundary_size, const pixel *ref, const int n_tb_s)
static double fact(double i)
IntraPredMode intra_pred_mode_c
IntraPredModeC.
static av_always_inline void FUNC() pred_mip(uint8_t *_src, const uint8_t *_top, const uint8_t *_left, const int w, const int h, const ptrdiff_t stride, int mode_id, int is_transposed)
#define i(width, name, range_min, range_max)
static av_always_inline int FUNC() cclm_select_samples(const VVCLocalContext *lc, const int x0, const int y0, const int w, const int h, const int avail_t, const int avail_l, pixel sel[][MAX_PICK_POS *2])
static av_always_inline void FUNC() pred_dc(uint8_t *_src, const uint8_t *_top, const uint8_t *_left, const int w, const int h, const ptrdiff_t stride)
int ff_vvc_get_left_available(const VVCLocalContext *lc, int x0, int y0, int target_size, int c_idx)
static av_always_inline void FUNC() cclm_pred_default(VVCFrameContext *fc, const int x, const int y, const int w, const int h, const int avail_t, const int avail_l)
static av_always_inline void FUNC() pred_v(uint8_t *_src, const uint8_t *_top, const int w, const int h, const ptrdiff_t stride)
static av_always_inline void FUNC() cclm_get_params_default(int *a, int *b, int *k)
#define INTRA_LUMA_FILTER(p)
#define EXTEND(ptr, val, len)
int ff_vvc_wide_angle_mode_mapping(const CodingUnit *cu, int tb_width, int tb_height, int c_idx, int pred_mode_intra)
static int vshift(enum AVPixelFormat fmt, int plane)
static av_always_inline int FUNC() cclm_get_select_pos(const VVCLocalContext *lc, const int x, const int y, const int w, const int h, const int avail_t, const int avail_l, int cnt[2], int pos[2][MAX_PICK_POS])
static av_always_inline pixel FUNC() pred_dc_val(const pixel *top, const pixel *left, const int w, const int h)
static const float pred[4]
#define FFSWAP(type, a, b)
static void FUNC() lmcs_scale_chroma(VVCLocalContext *lc, int *dst, const int *coeff, const int width, const int height, const int x0_cu, const int y0_cu)
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
static void FUNC() pred_angular_v(uint8_t *_src, const uint8_t *_top, const uint8_t *_left, const int w, const int h, const ptrdiff_t stride, const int c_idx, const int mode, const int ref_idx, const int filter_flag, const int need_pdpc)
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
static int FUNC() lmcs_sum_samples(const pixel *start, ptrdiff_t stride, const int avail, const int target_size)
static av_always_inline void FUNC() ref_filter(const pixel *left, const pixel *top, pixel *filtered_left, pixel *filtered_top, const int left_size, const int top_size, const int unfilter_last_one)
static int ref[MAX_W *MAX_W]
static const int factor[16]
static void FUNC() intra_pred(const VVCLocalContext *lc, int x0, int y0, const int width, const int height, int c_idx)
const uint8_t * ff_vvc_get_mip_matrix(const int size_id, const int mode_id)
static void scale(int *out, const int *in, const int w, const int h, const int shift)
int ff_vvc_nscale_derive(int w, int h, int mode)
enum IspType isp_split_type
IntraSubPartitionsSplitType.
static av_always_inline void FUNC() cclm_select_chroma(const VVCFrameContext *fc, const int x, const int y, const int cnt[2], const int pos[2][MAX_PICK_POS], pixel sel[][MAX_PICK_POS *2])
int mip_chroma_direct_flag
MipChromaDirectFlag.
static const double coeff[2][5]
int ff_vvc_need_pdpc(int w, int h, uint8_t bdpcm_flag, int mode, int ref_idx)