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

Reply via email to