diff options
author | Mickaƫl Raulet <mraulet@insa-rennes.fr> | 2014-07-17 01:15:32 +0400 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-07-19 00:46:50 +0400 |
commit | d249e6828e8a84758010ec020a84dfcd156b585e (patch) | |
tree | 14a2103e8c7bd59d1082915c3c7e277e1b974108 /libavcodec/hevc_filter.c | |
parent | 2897447ddf805edc0a7935ab633c28e29a89b7b3 (diff) |
hevc/sao: optimze sao implementation
- adding one extra pixel all around the frame
- do not copy when SAO is not applied
5% improvement
cherry picked from commit 10fc29fc19a12c4d8168fbe1a954b76386db12d0
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/hevc_filter.c')
-rw-r--r-- | libavcodec/hevc_filter.c | 66 |
1 files changed, 47 insertions, 19 deletions
diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c index 0d3e238d69..b0b197cc66 100644 --- a/libavcodec/hevc_filter.c +++ b/libavcodec/hevc_filter.c @@ -142,14 +142,14 @@ static int get_qPy(HEVCContext *s, int xC, int yC) } static void copy_CTB(uint8_t *dst, uint8_t *src, - int width, int height, int stride) + int width, int height, int stride_dst, int stride_src) { int i; for (i = 0; i < height; i++) { memcpy(dst, src, width); - dst += stride; - src += stride; + dst += stride_dst; + src += stride_src; } } @@ -174,7 +174,7 @@ static void restore_tqb_pixels(HEVCContext *s, int x0, int y0, int width, int he uint8_t *src = &s->frame->data[c_idx][ ((y << s->sps->log2_min_pu_size) >> vshift) * stride + (((x << s->sps->log2_min_pu_size) >> hshift) << s->sps->pixel_shift)]; uint8_t *dst = &s->sao_frame->data[c_idx][((y << s->sps->log2_min_pu_size) >> vshift) * stride + (((x << s->sps->log2_min_pu_size) >> hshift) << s->sps->pixel_shift)]; for (n = 0; n < (min_pu_size >> vshift); n++) { - memcpy(dst, src, len); + memcpy(src, dst, len); src += stride; dst += stride; } @@ -247,29 +247,58 @@ static void sao_filter_CTB(HEVCContext *s, int x, int y) for (c_idx = 0; c_idx < 3; c_idx++) { int x0 = x >> s->sps->hshift[c_idx]; int y0 = y >> s->sps->vshift[c_idx]; - int stride = s->frame->linesize[c_idx]; + int stride_src = s->frame->linesize[c_idx]; + int stride_dst = s->sao_frame->linesize[c_idx]; int ctb_size_h = (1 << (s->sps->log2_ctb_size)) >> s->sps->hshift[c_idx]; int ctb_size_v = (1 << (s->sps->log2_ctb_size)) >> s->sps->vshift[c_idx]; - int width = FFMIN(ctb_size_h, - (s->sps->width >> s->sps->hshift[c_idx]) - x0); - int height = FFMIN(ctb_size_v, - (s->sps->height >> s->sps->vshift[c_idx]) - y0); - - uint8_t *src = &s->frame->data[c_idx][y0 * stride + (x0 << s->sps->pixel_shift)]; - uint8_t *dst = &s->sao_frame->data[c_idx][y0 * stride + (x0 << s->sps->pixel_shift)]; + int width = FFMIN(ctb_size_h, (s->sps->width >> s->sps->hshift[c_idx]) - x0); + int height = FFMIN(ctb_size_v, (s->sps->height >> s->sps->vshift[c_idx]) - y0); + uint8_t *src = &s->frame->data[c_idx][y0 * stride_src + (x0 << s->sps->pixel_shift)]; + uint8_t *dst = &s->sao_frame->data[c_idx][y0 * stride_dst + (x0 << s->sps->pixel_shift)]; switch (sao->type_idx[c_idx]) { case SAO_BAND: - s->hevcdsp.sao_band_filter(dst, src, - stride, + copy_CTB(dst, src, width << s->sps->pixel_shift, height, stride_dst, stride_src); + s->hevcdsp.sao_band_filter(src, dst, + stride_src, stride_dst, sao, edges, width, height, c_idx); restore_tqb_pixels(s, x, y, width, height, c_idx); + sao->type_idx[c_idx] = SAO_APPLIED; break; case SAO_EDGE: - s->hevcdsp.sao_edge_filter[restore](dst, src, - stride, + { + uint8_t left_pixels = !edges[0] && (CTB(s->sao, x_ctb-1, y_ctb).type_idx[c_idx] != SAO_APPLIED); + if (!edges[1]) { + uint8_t top_left = !edges[0] && (CTB(s->sao, x_ctb-1, y_ctb-1).type_idx[c_idx] != SAO_APPLIED); + uint8_t top_right = !edges[2] && (CTB(s->sao, x_ctb+1, y_ctb-1).type_idx[c_idx] != SAO_APPLIED); + if (CTB(s->sao, x_ctb , y_ctb-1).type_idx[c_idx] == 0) + memcpy( dst - stride_dst - (top_left << s->sps->pixel_shift), + src - stride_src - (top_left << s->sps->pixel_shift), + (top_left + width + top_right) << s->sps->pixel_shift); + else { + if (top_left) + memcpy( dst - stride_dst - (1 << s->sps->pixel_shift), + src - stride_src - (1 << s->sps->pixel_shift), + 1 << s->sps->pixel_shift); + if(top_right) + memcpy( dst - stride_dst + (width << s->sps->pixel_shift), + src - stride_src + (width << s->sps->pixel_shift), + 1 << s->sps->pixel_shift); + } + } + if (!edges[3]) { // bottom and bottom right + uint8_t bottom_left = !edges[0] && (CTB(s->sao, x_ctb-1, y_ctb+1).type_idx[c_idx] != SAO_APPLIED); + memcpy( dst + height * stride_dst - (bottom_left << s->sps->pixel_shift), + src + height * stride_src - (bottom_left << s->sps->pixel_shift), + (width + 1 + bottom_left) << s->sps->pixel_shift); + } + copy_CTB(dst - (left_pixels << s->sps->pixel_shift), + src - (left_pixels << s->sps->pixel_shift), + (width + 1 + left_pixels) << s->sps->pixel_shift, height, stride_dst, stride_src); + s->hevcdsp.sao_edge_filter[restore](src, dst, + stride_src, stride_dst, sao, edges, width, height, c_idx, @@ -277,10 +306,9 @@ static void sao_filter_CTB(HEVCContext *s, int x, int y) horiz_edge, diag_edge); restore_tqb_pixels(s, x, y, width, height, c_idx); + sao->type_idx[c_idx] = SAO_APPLIED; break; - default : - copy_CTB(dst, src, width << s->sps->pixel_shift, height, stride); - break; + } } } } |