Square prediction units are the most common.
About 0.7% faster on 4k videos.
---
libavcodec/hevc.c | 64 +++++++++++++++++++++++++++++++++----------
libavcodec/hevcdsp.c | 6 ++++
libavcodec/hevcdsp.h | 2 ++
libavcodec/hevcdsp_template.c | 16 +++++++++++
4 files changed, 73 insertions(+), 15 deletions(-)
diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c
index 1634185..7d15ed3 100644
--- a/libavcodec/hevc.c
+++ b/libavcodec/hevc.c
@@ -27,6 +27,7 @@
#include "libavutil/common.h"
#include "libavutil/display.h"
#include "libavutil/internal.h"
+#include "libavutil/intmath.h"
#include "libavutil/md5.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
@@ -1652,9 +1653,27 @@ static void hevc_await_progress(HEVCContext *s,
HEVCFrame *ref,
ff_thread_await_progress(&ref->tf, y, 0);
}
-static void hls_prediction_unit(HEVCContext *s, int x0, int y0,
- int nPbW, int nPbH,
- int log2_cb_size, int partIdx)
+av_always_inline
+static void put_unweighted_pred(HEVCContext *s,
+ uint8_t *dst, ptrdiff_t dststride,
+ int16_t *src, ptrdiff_t srcstride,
+ int width, int height, int square)
+{
+ if (!square) {
+ s->hevcdsp.put_unweighted_pred(dst, dststride,
+ src, srcstride, width, height);
+ } else {
+ const int square = av_log2_16bit(width) - 2;
+ s->hevcdsp.put_unweighted_pred_square[square](dst, dststride,
+ src, srcstride);
+ }
+}
+
+av_always_inline
+static void hls_prediction_unit_internal(HEVCContext *s, int x0, int y0,
+ int nPbW, int nPbH,
+ int log2_cb_size, int partIdx,
+ int square)
{
#define POS(c_idx, x, y)
\
&s->frame->data[c_idx][((y) >> s->sps->vshift[c_idx]) *
s->frame->linesize[c_idx] + \
@@ -1796,7 +1815,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0,
int y0,
dst0, s->frame->linesize[0], tmp,
tmpstride, nPbW, nPbH);
} else {
- s->hevcdsp.put_unweighted_pred(dst0, s->frame->linesize[0], tmp,
tmpstride, nPbW, nPbH);
+ put_unweighted_pred(s, dst0, s->frame->linesize[0], tmp,
tmpstride, nPbW, nPbH, square);
}
chroma_mc(s, tmp, tmp2, tmpstride, ref0->frame,
¤t_mv.mv[0], x0 / 2, y0 / 2, nPbW / 2, nPbH / 2);
@@ -1814,8 +1833,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0,
int y0,
dst2, s->frame->linesize[2], tmp2,
tmpstride,
nPbW / 2, nPbH / 2);
} else {
- s->hevcdsp.put_unweighted_pred(dst1, s->frame->linesize[1], tmp,
tmpstride, nPbW/2, nPbH/2);
- s->hevcdsp.put_unweighted_pred(dst2, s->frame->linesize[2], tmp2,
tmpstride, nPbW/2, nPbH/2);
+ put_unweighted_pred(s, dst1, s->frame->linesize[1], tmp,
tmpstride, nPbW / 2, nPbH / 2, square);
+ put_unweighted_pred(s, dst2, s->frame->linesize[2], tmp2,
tmpstride, nPbW / 2, nPbH / 2, square);
}
} else if (!current_mv.pred_flag[0] && current_mv.pred_flag[1]) {
DECLARE_ALIGNED(16, int16_t, tmp [MAX_PB_SIZE * MAX_PB_SIZE]);
@@ -1835,7 +1854,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0,
int y0,
dst0, s->frame->linesize[0], tmp,
tmpstride,
nPbW, nPbH);
} else {
- s->hevcdsp.put_unweighted_pred(dst0, s->frame->linesize[0], tmp,
tmpstride, nPbW, nPbH);
+ put_unweighted_pred(s, dst0, s->frame->linesize[0], tmp,
tmpstride, nPbW, nPbH, square);
}
chroma_mc(s, tmp, tmp2, tmpstride, ref1->frame,
@@ -1852,8 +1871,8 @@ static void hls_prediction_unit(HEVCContext *s, int x0,
int y0,
s->sh.chroma_offset_l1[current_mv.ref_idx[1]][1],
dst2, s->frame->linesize[2], tmp2,
tmpstride, nPbW/2, nPbH/2);
} else {
- s->hevcdsp.put_unweighted_pred(dst1, s->frame->linesize[1], tmp,
tmpstride, nPbW/2, nPbH/2);
- s->hevcdsp.put_unweighted_pred(dst2, s->frame->linesize[2], tmp2,
tmpstride, nPbW/2, nPbH/2);
+ put_unweighted_pred(s, dst1, s->frame->linesize[1], tmp,
tmpstride, nPbW / 2, nPbH / 2, square);
+ put_unweighted_pred(s, dst2, s->frame->linesize[2], tmp2,
tmpstride, nPbW / 2, nPbH / 2, square);
}
} else if (current_mv.pred_flag[0] && current_mv.pred_flag[1]) {
DECLARE_ALIGNED(16, int16_t, tmp [MAX_PB_SIZE * MAX_PB_SIZE]);
@@ -1913,6 +1932,21 @@ static void hls_prediction_unit(HEVCContext *s, int x0,
int y0,
}
}
+
+static void hls_prediction_unit_square(HEVCContext *s, int x0, int y0,
+ int cb_size, int log2_cb_size,
+ int partIdx)
+{
+ hls_prediction_unit_internal(s, x0, y0, cb_size, cb_size, log2_cb_size,
partIdx, 1);
+}
+
+static void hls_prediction_unit(HEVCContext *s, int x0, int y0,
+ int nPbW, int nPbH,
+ int log2_cb_size, int partIdx)
+{
+ hls_prediction_unit_internal(s, x0, y0, nPbW, nPbH, log2_cb_size, partIdx,
0);
+}
+
/**
* 8.4.1
*/
@@ -2121,7 +2155,7 @@ static int hls_coding_unit(HEVCContext *s, int x0, int
y0, int log2_cb_size)
}
if (SAMPLE_CTB(s->skip_flag, x_cb, y_cb)) {
- hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0);
+ hls_prediction_unit_square(s, x0, y0, cb_size, log2_cb_size, 0);
intra_prediction_unit_default_value(s, x0, y0, log2_cb_size);
if (!s->sh.disable_deblocking_filter_flag)
@@ -2159,7 +2193,7 @@ static int hls_coding_unit(HEVCContext *s, int x0, int
y0, int log2_cb_size)
intra_prediction_unit_default_value(s, x0, y0, log2_cb_size);
switch (lc->cu.part_mode) {
case PART_2Nx2N:
- hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size,
0);
+ hls_prediction_unit_square(s, x0, y0, cb_size, log2_cb_size,
0);
break;
case PART_2NxN:
hls_prediction_unit(s, x0, y0, cb_size, cb_size
/ 2, log2_cb_size, 0);
@@ -2186,10 +2220,10 @@ static int hls_coding_unit(HEVCContext *s, int x0, int
y0, int log2_cb_size)
hls_prediction_unit(s, x0 + cb_size * 3 / 4, y0, cb_size /
4, cb_size, log2_cb_size, 1);
break;
case PART_NxN:
- hls_prediction_unit(s, x0, y0,
cb_size / 2, cb_size / 2, log2_cb_size, 0);
- hls_prediction_unit(s, x0 + cb_size / 2, y0,
cb_size / 2, cb_size / 2, log2_cb_size, 1);
- hls_prediction_unit(s, x0, y0 + cb_size / 2,
cb_size / 2, cb_size / 2, log2_cb_size, 2);
- hls_prediction_unit(s, x0 + cb_size / 2, y0 + cb_size / 2,
cb_size / 2, cb_size / 2, log2_cb_size, 3);
+ hls_prediction_unit_square(s, x0, y0,
cb_size / 2, log2_cb_size, 0);
+ hls_prediction_unit_square(s, x0 + cb_size / 2, y0,
cb_size / 2, log2_cb_size, 1);
+ hls_prediction_unit_square(s, x0, y0 + cb_size /
2, cb_size / 2, log2_cb_size, 2);
+ hls_prediction_unit_square(s, x0 + cb_size / 2, y0 + cb_size /
2, cb_size / 2, log2_cb_size, 3);
break;
}
}
diff --git a/libavcodec/hevcdsp.c b/libavcodec/hevcdsp.c
index 969c11c..883503b 100644
--- a/libavcodec/hevcdsp.c
+++ b/libavcodec/hevcdsp.c
@@ -166,6 +166,12 @@ void ff_hevc_dsp_init(HEVCDSPContext *hevcdsp, int
bit_depth)
hevcdsp->put_hevc_epel[1][1] = FUNC(put_hevc_epel_hv, depth); \
\
hevcdsp->put_unweighted_pred = FUNC(put_unweighted_pred, depth); \
+ hevcdsp->put_unweighted_pred_square[0] = FUNC(put_unweighted_pred_4,
depth); \
+ hevcdsp->put_unweighted_pred_square[1] = FUNC(put_unweighted_pred_8,
depth); \
+ hevcdsp->put_unweighted_pred_square[2] = FUNC(put_unweighted_pred_16,
depth); \
+ hevcdsp->put_unweighted_pred_square[3] = FUNC(put_unweighted_pred_32,
depth); \
+ hevcdsp->put_unweighted_pred_square[4] = FUNC(put_unweighted_pred_64,
depth); \
+
\
hevcdsp->put_weighted_pred_avg = FUNC(put_weighted_pred_avg, depth); \
\
hevcdsp->weighted_pred = FUNC(weighted_pred, depth); \
diff --git a/libavcodec/hevcdsp.h b/libavcodec/hevcdsp.h
index 1665ad6..139f48d 100644
--- a/libavcodec/hevcdsp.h
+++ b/libavcodec/hevcdsp.h
@@ -68,6 +68,8 @@ typedef struct HEVCDSPContext {
void (*put_unweighted_pred)(uint8_t *dst, ptrdiff_t dststride, int16_t
*src,
ptrdiff_t srcstride, int width, int height);
+ void (*put_unweighted_pred_square[5])(uint8_t *dst, ptrdiff_t dststride,
int16_t *src,
+ ptrdiff_t srcstride);
void (*put_weighted_pred_avg)(uint8_t *dst, ptrdiff_t dststride,
int16_t *src1, int16_t *src2,
ptrdiff_t srcstride, int width, int height);
diff --git a/libavcodec/hevcdsp_template.c b/libavcodec/hevcdsp_template.c
index 72e50b5..429ec20 100644
--- a/libavcodec/hevcdsp_template.c
+++ b/libavcodec/hevcdsp_template.c
@@ -1031,6 +1031,7 @@ static void FUNC(put_hevc_epel_hv)(int16_t *dst,
ptrdiff_t dststride,
}
}
+av_always_inline
static void FUNC(put_unweighted_pred)(uint8_t *_dst, ptrdiff_t _dststride,
int16_t *src, ptrdiff_t srcstride,
int width, int height)
@@ -1053,6 +1054,21 @@ static void FUNC(put_unweighted_pred)(uint8_t *_dst,
ptrdiff_t _dststride,
}
}
+#define UNWEIGHTED_PRED_SQUARE(size) \
+static void FUNC(put_unweighted_pred_ ## size) (uint8_t * _dst, \
+ ptrdiff_t _dststride, \
+ int16_t * src, \
+ ptrdiff_t srcstride) \
+{ \
+ FUNC(put_unweighted_pred)(_dst, _dststride, src, srcstride, size, size); \
+}
+
+UNWEIGHTED_PRED_SQUARE(4)
+UNWEIGHTED_PRED_SQUARE(8)
+UNWEIGHTED_PRED_SQUARE(16)
+UNWEIGHTED_PRED_SQUARE(32)
+UNWEIGHTED_PRED_SQUARE(64)
+
static void FUNC(put_weighted_pred_avg)(uint8_t *_dst, ptrdiff_t _dststride,
int16_t *src1, int16_t *src2,
ptrdiff_t srcstride,
--
1.9.0
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel