Hi, 2015-02-05 7:29 GMT+01:00 Christophe Gisquet <christophe.gisq...@gmail.com>: > We were previously reference-counting the sao-buffer. Should we do > that for sao_pixel_buffer_[hv], then?
Something like the attached patch. Note: I'm probably overallocating compared to previously, but that doesn't look to be a big deal. On the other hand, those are buffers sized 2*block_height*image_width and 2*block_width*image_height. The storing is maybe overzealous, as I don't see why just more than 1 or 2 lines/columns need to be stored. -- Christophe
From 8ac4c9e5db63de26523e4677f397019c5eb6bd89 Mon Sep 17 00:00:00 2001 From: Christophe Gisquet <christophe.gisq...@gmail.com> Date: Thu, 5 Feb 2015 08:11:28 +0100 Subject: [PATCH] hevc/sao: referenced line/column buffers Otherwise, a change in parameters may cause the buffers to be lost, causing memory leak. --- libavcodec/hevc.c | 50 ++++++++++++++++++++++++++++++++---------------- libavcodec/hevc.h | 4 ++-- libavcodec/hevc_filter.c | 18 +++++++++-------- 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index 0624cb0..9a6df3c 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -280,6 +280,23 @@ static int decode_lt_rps(HEVCContext *s, LongTermRPS *rps, GetBitContext *gb) return 0; } +static int get_buffer_sao(HEVCContext *s, const HEVCSPS *sps) +{ + int ret; + AVFrame *frame = s->tmp_frame[0]; + frame->width = FFALIGN(4 * sps->width, FF_INPUT_BUFFER_PADDING_SIZE); + frame->height = sps->ctb_height; + if ((ret = ff_get_buffer(s->avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + frame = s->tmp_frame[1]; + frame->width = FFALIGN(4 * sps->height, FF_INPUT_BUFFER_PADDING_SIZE); + frame->height = sps->ctb_width; + if ((ret = ff_get_buffer(s->avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + return 0; +} + static int set_sps(HEVCContext *s, const HEVCSPS *sps) { #define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL) @@ -335,19 +352,14 @@ static int set_sps(HEVCContext *s, const HEVCSPS *sps) ff_videodsp_init (&s->vdsp, sps->bit_depth); if (sps->sao_enabled && !s->avctx->hwaccel) { - int c_count = (sps->chroma_format_idc != 0) ? 3 : 1; - int c_idx; - - for(c_idx = 0; c_idx < c_count; c_idx++) { - int w = sps->width >> sps->hshift[c_idx]; - int h = sps->height >> sps->vshift[c_idx]; - s->sao_pixel_buffer_h[c_idx] = - av_malloc((w * 2 * sps->ctb_height) << - sps->pixel_shift); - s->sao_pixel_buffer_v[c_idx] = - av_malloc((h * 2 * sps->ctb_width) << - sps->pixel_shift); - } + av_frame_unref(s->tmp_frame[0]); + av_frame_unref(s->tmp_frame[1]); + s->sao_frame[0] = NULL; + s->sao_frame[1] = NULL; + if ( (ret = get_buffer_sao(s, sps)) < 0 ) + goto fail; + s->sao_frame[0] = s->tmp_frame[0]; + s->sao_frame[1] = s->tmp_frame[1]; } s->sps = sps; @@ -3178,10 +3190,8 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) av_freep(&s->cabac_state); - for (i = 0; i < 3; i++) { - av_freep(&s->sao_pixel_buffer_h[i]); - av_freep(&s->sao_pixel_buffer_v[i]); - } + av_frame_free(&s->tmp_frame[0]); + av_frame_free(&s->tmp_frame[1]); av_frame_free(&s->output_frame); for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { @@ -3241,6 +3251,12 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) if (!s->cabac_state) goto fail; + for (i = 0; i < 2; i++) { + s->tmp_frame[i] = av_frame_alloc(); + if (!s->tmp_frame[i]) + goto fail; + } + s->output_frame = av_frame_alloc(); if (!s->output_frame) goto fail; diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h index ae9a32a..5ec7a23 100644 --- a/libavcodec/hevc.h +++ b/libavcodec/hevc.h @@ -809,8 +809,8 @@ typedef struct HEVCContext { AVFrame *frame; AVFrame *output_frame; - uint8_t *sao_pixel_buffer_h[3]; - uint8_t *sao_pixel_buffer_v[3]; + AVFrame *tmp_frame[2]; + AVFrame *sao_frame[2]; const HEVCVPS *vps; const HEVCSPS *sps; diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c index 1172282..63d83c1 100644 --- a/libavcodec/hevc_filter.c +++ b/libavcodec/hevc_filter.c @@ -196,17 +196,19 @@ static void copy_CTB_to_hv(HEVCContext *s, const uint8_t *src, int sh = s->sps->pixel_shift; int w = s->sps->width >> s->sps->hshift[c_idx]; int h = s->sps->height >> s->sps->vshift[c_idx]; + uint8_t *buffer_h = s->sao_frame[0]->data[c_idx]; + uint8_t *buffer_v = s->sao_frame[1]->data[c_idx]; /* copy horizontal edges */ - memcpy(s->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb) * w + x) << sh), + memcpy(buffer_h + (((2 * y_ctb) * w + x) << sh), src, width << sh); - memcpy(s->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb + 1) * w + x) << sh), + memcpy(buffer_h + (((2 * y_ctb + 1) * w + x) << sh), src + stride_src * (height - 1), width << sh); /* copy vertical edges */ - copy_vert(s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb) * h + y) << sh), src, sh, height, 1 << sh, stride_src); + copy_vert(buffer_v + (((2 * x_ctb) * h + y) << sh), src, sh, height, 1 << sh, stride_src); - copy_vert(s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 1) * h + y) << sh), src + ((width - 1) << sh), sh, height, 1 << sh, stride_src); + copy_vert(buffer_v + (((2 * x_ctb + 1) * h + y) << sh), src + ((width - 1) << sh), sh, height, 1 << sh, stride_src); } static void restore_tqb_pixels(HEVCContext *s, @@ -361,7 +363,7 @@ static void sao_filter_CTB(HEVCContext *s, int x, int y) dst1 = dst - stride_dst - (left << sh); src1[0] = src - stride_src - (left << sh); - src1[1] = s->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb - 1) * w + x0 - left) << sh); + src1[1] = s->sao_frame[0]->data[c_idx] + (((2 * y_ctb - 1) * w + x0 - left) << sh); pos = 0; if (left) { src_idx = (CTB(s->sao, x_ctb-1, y_ctb-1).type_idx[c_idx] == @@ -388,7 +390,7 @@ static void sao_filter_CTB(HEVCContext *s, int x, int y) dst1 = dst + height * stride_dst - (left << sh); src1[0] = src + height * stride_src - (left << sh); - src1[1] = s->sao_pixel_buffer_h[c_idx] + (((2 * y_ctb + 2) * w + x0 - left) << sh); + src1[1] = s->sao_frame[0]->data[c_idx] + (((2 * y_ctb + 2) * w + x0 - left) << sh); pos = 0; if (left) { src_idx = (CTB(s->sao, x_ctb-1, y_ctb+1).type_idx[c_idx] == @@ -410,7 +412,7 @@ static void sao_filter_CTB(HEVCContext *s, int x, int y) if (!left_edge) { if (CTB(s->sao, x_ctb-1, y_ctb).type_idx[c_idx] == SAO_APPLIED) { copy_vert(dst - (1 << sh), - s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb - 1) * h + y0) << sh), + s->sao_frame[1]->data[c_idx] + (((2 * x_ctb - 1) * h + y0) << sh), sh, height, stride_dst, 1 << sh); } else { left_pixels = 1; @@ -420,7 +422,7 @@ static void sao_filter_CTB(HEVCContext *s, int x, int y) if (!right_edge) { if (CTB(s->sao, x_ctb+1, y_ctb).type_idx[c_idx] == SAO_APPLIED) { copy_vert(dst + (width << sh), - s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 2) * h + y0) << sh), + s->sao_frame[1]->data[c_idx] + (((2 * x_ctb + 2) * h + y0) << sh), sh, height, stride_dst, 1 << sh); } else { right_pixels = 1; -- 1.9.2.msysgit.0
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel