[FFmpeg-devel] [PATCH] vp9: split segmentation map / mvpair references.
This prevents a memcpy if segmentation.update_map == false. --- libavcodec/vp9.c | 72 ++-- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index aff86d0..6f129f0 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -74,6 +74,7 @@ typedef struct VP9Frame { AVBufferRef *extradata; uint8_t *segmentation_map; struct VP9mvrefPair *mv; +int uses_2pass; } VP9Frame; struct VP9Filter { @@ -100,7 +101,7 @@ typedef struct VP9Context { VP56RangeCoder *c_b; unsigned c_b_size; VP9Block *b_base, *b; -int pass, uses_2pass, last_uses_2pass; +int pass; int row, row7, col, col7; uint8_t *dst[3]; ptrdiff_t y_stride, uv_stride; @@ -128,8 +129,9 @@ typedef struct VP9Context { uint8_t varcompref[2]; ThreadFrame refs[8], next_refs[8]; #define CUR_FRAME 0 -#define LAST_FRAME 1 -VP9Frame frames[2]; +#define REF_FRAME_MVPAIR 1 +#define REF_FRAME_SEGMAP 2 +VP9Frame frames[3]; struct { uint8_t level; @@ -277,13 +279,6 @@ static int vp9_alloc_frame(AVCodecContext *ctx, VP9Frame *f) f-segmentation_map = f-extradata-data; f-mv = (struct VP9mvrefPair *) (f-extradata-data + sz); -// retain segmentation map if it doesn't update -if (s-segmentation.enabled !s-segmentation.update_map -!s-intraonly !s-keyframe !s-errorres -ctx-active_thread_type != FF_THREAD_FRAME) { -memcpy(f-segmentation_map, s-frames[LAST_FRAME].segmentation_map, sz); -} - return 0; } @@ -362,12 +357,12 @@ static int update_block_buffers(AVCodecContext *ctx) { VP9Context *s = ctx-priv_data; -if (s-b_base s-block_base s-block_alloc_using_2pass == s-uses_2pass) +if (s-b_base s-block_base s-block_alloc_using_2pass == s-frames[CUR_FRAME].uses_2pass) return 0; av_free(s-b_base); av_free(s-block_base); -if (s-uses_2pass) { +if (s-frames[CUR_FRAME].uses_2pass) { int sbs = s-sb_cols * s-sb_rows; s-b_base = av_malloc_array(s-cols * s-rows, sizeof(VP9Block)); @@ -390,7 +385,7 @@ static int update_block_buffers(AVCodecContext *ctx) s-uveob_base[0] = s-eob_base + 256; s-uveob_base[1] = s-uveob_base[0] + 64; } -s-block_alloc_using_2pass = s-uses_2pass; +s-block_alloc_using_2pass = s-frames[CUR_FRAME].uses_2pass; return 0; } @@ -491,7 +486,6 @@ static int decode_frame_header(AVCodecContext *ctx, *ref = get_bits(s-gb, 3); return 0; } -s-last_uses_2pass = s-uses_2pass; s-last_keyframe = s-keyframe; s-keyframe = !get_bits1(s-gb); last_invisible= s-invisible; @@ -1082,10 +1076,10 @@ static void find_ref_mvs(VP9Context *s, // MV at this position in previous frame, using same reference frame if (s-use_last_frame_mvs) { -struct VP9mvrefPair *mv = s-frames[LAST_FRAME].mv[row * s-sb_cols * 8 + col]; +struct VP9mvrefPair *mv = s-frames[REF_FRAME_MVPAIR].mv[row * s-sb_cols * 8 + col]; -if (!s-last_uses_2pass) -ff_thread_await_progress(s-frames[LAST_FRAME].tf, row 3, 0); +if (!s-frames[REF_FRAME_MVPAIR].uses_2pass) +ff_thread_await_progress(s-frames[REF_FRAME_MVPAIR].tf, row 3, 0); if (mv-ref[0] == ref) { RETURN_MV(mv-mv[0]); } else if (mv-ref[1] == ref) { @@ -1124,7 +1118,7 @@ static void find_ref_mvs(VP9Context *s, // MV at this position in previous frame, using different reference frame if (s-use_last_frame_mvs) { -struct VP9mvrefPair *mv = s-frames[LAST_FRAME].mv[row * s-sb_cols * 8 + col]; +struct VP9mvrefPair *mv = s-frames[REF_FRAME_MVPAIR].mv[row * s-sb_cols * 8 + col]; // no need to await_progress, because we already did that above if (mv-ref[0] != ref mv-ref[0] = 0) { @@ -1348,21 +1342,14 @@ static void decode_mode(AVCodecContext *ctx) s-left_segpred_ctx[row7]]))) { if (!s-errorres) { int pred = 8, x; -uint8_t *refsegmap = s-frames[LAST_FRAME].segmentation_map; +uint8_t *refsegmap = s-frames[REF_FRAME_SEGMAP].segmentation_map; -if (!s-last_uses_2pass) -ff_thread_await_progress(s-frames[LAST_FRAME].tf, row 3, 0); +if (!s-frames[REF_FRAME_SEGMAP].uses_2pass) +ff_thread_await_progress(s-frames[REF_FRAME_SEGMAP].tf, row 3, 0); for (y = 0; y h4; y++) { int idx_base = (y + row) * 8 * s-sb_cols + col; for (x = 0; x w4; x++) pred = FFMIN(pred, refsegmap[idx_base + x]); -if (!s-segmentation.update_map ctx-active_thread_type == FF_THREAD_FRAME) { -// FIXME maybe retain reference to previous frame as -// segmap reference instead of copying the whole map -
[FFmpeg-devel] [PATCH] vp9: split segmentation map / mvpair references.
This prevents a memcpy if segmentation.update_map == false. --- libavcodec/vp9.c | 68 ++-- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index aff86d0..6ac2935 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -74,6 +74,7 @@ typedef struct VP9Frame { AVBufferRef *extradata; uint8_t *segmentation_map; struct VP9mvrefPair *mv; +int uses_2pass; } VP9Frame; struct VP9Filter { @@ -100,7 +101,7 @@ typedef struct VP9Context { VP56RangeCoder *c_b; unsigned c_b_size; VP9Block *b_base, *b; -int pass, uses_2pass, last_uses_2pass; +int pass; int row, row7, col, col7; uint8_t *dst[3]; ptrdiff_t y_stride, uv_stride; @@ -128,8 +129,9 @@ typedef struct VP9Context { uint8_t varcompref[2]; ThreadFrame refs[8], next_refs[8]; #define CUR_FRAME 0 -#define LAST_FRAME 1 -VP9Frame frames[2]; +#define REF_FRAME_MVPAIR 1 +#define REF_FRAME_SEGMAP 2 +VP9Frame frames[3]; struct { uint8_t level; @@ -277,13 +279,6 @@ static int vp9_alloc_frame(AVCodecContext *ctx, VP9Frame *f) f-segmentation_map = f-extradata-data; f-mv = (struct VP9mvrefPair *) (f-extradata-data + sz); -// retain segmentation map if it doesn't update -if (s-segmentation.enabled !s-segmentation.update_map -!s-intraonly !s-keyframe !s-errorres -ctx-active_thread_type != FF_THREAD_FRAME) { -memcpy(f-segmentation_map, s-frames[LAST_FRAME].segmentation_map, sz); -} - return 0; } @@ -362,12 +357,12 @@ static int update_block_buffers(AVCodecContext *ctx) { VP9Context *s = ctx-priv_data; -if (s-b_base s-block_base s-block_alloc_using_2pass == s-uses_2pass) +if (s-b_base s-block_base s-block_alloc_using_2pass == s-frames[CUR_FRAME].uses_2pass) return 0; av_free(s-b_base); av_free(s-block_base); -if (s-uses_2pass) { +if (s-frames[CUR_FRAME].uses_2pass) { int sbs = s-sb_cols * s-sb_rows; s-b_base = av_malloc_array(s-cols * s-rows, sizeof(VP9Block)); @@ -390,7 +385,7 @@ static int update_block_buffers(AVCodecContext *ctx) s-uveob_base[0] = s-eob_base + 256; s-uveob_base[1] = s-uveob_base[0] + 64; } -s-block_alloc_using_2pass = s-uses_2pass; +s-block_alloc_using_2pass = s-frames[CUR_FRAME].uses_2pass; return 0; } @@ -491,7 +486,6 @@ static int decode_frame_header(AVCodecContext *ctx, *ref = get_bits(s-gb, 3); return 0; } -s-last_uses_2pass = s-uses_2pass; s-last_keyframe = s-keyframe; s-keyframe = !get_bits1(s-gb); last_invisible= s-invisible; @@ -1082,10 +1076,10 @@ static void find_ref_mvs(VP9Context *s, // MV at this position in previous frame, using same reference frame if (s-use_last_frame_mvs) { -struct VP9mvrefPair *mv = s-frames[LAST_FRAME].mv[row * s-sb_cols * 8 + col]; +struct VP9mvrefPair *mv = s-frames[REF_FRAME_MVPAIR].mv[row * s-sb_cols * 8 + col]; -if (!s-last_uses_2pass) -ff_thread_await_progress(s-frames[LAST_FRAME].tf, row 3, 0); +if (!s-frames[REF_FRAME_MVPAIR].uses_2pass) +ff_thread_await_progress(s-frames[REF_FRAME_MVPAIR].tf, row 3, 0); if (mv-ref[0] == ref) { RETURN_MV(mv-mv[0]); } else if (mv-ref[1] == ref) { @@ -1124,7 +1118,7 @@ static void find_ref_mvs(VP9Context *s, // MV at this position in previous frame, using different reference frame if (s-use_last_frame_mvs) { -struct VP9mvrefPair *mv = s-frames[LAST_FRAME].mv[row * s-sb_cols * 8 + col]; +struct VP9mvrefPair *mv = s-frames[REF_FRAME_MVPAIR].mv[row * s-sb_cols * 8 + col]; // no need to await_progress, because we already did that above if (mv-ref[0] != ref mv-ref[0] = 0) { @@ -1348,21 +1342,14 @@ static void decode_mode(AVCodecContext *ctx) s-left_segpred_ctx[row7]]))) { if (!s-errorres) { int pred = 8, x; -uint8_t *refsegmap = s-frames[LAST_FRAME].segmentation_map; +uint8_t *refsegmap = s-frames[REF_FRAME_SEGMAP].segmentation_map; -if (!s-last_uses_2pass) -ff_thread_await_progress(s-frames[LAST_FRAME].tf, row 3, 0); +if (!s-frames[REF_FRAME_SEGMAP].uses_2pass) +ff_thread_await_progress(s-frames[REF_FRAME_SEGMAP].tf, row 3, 0); for (y = 0; y h4; y++) { int idx_base = (y + row) * 8 * s-sb_cols + col; for (x = 0; x w4; x++) pred = FFMIN(pred, refsegmap[idx_base + x]); -if (!s-segmentation.update_map ctx-active_thread_type == FF_THREAD_FRAME) { -// FIXME maybe retain reference to previous frame as -// segmap reference instead of copying the whole map -