Skip to content

Commit

Permalink
hevc: fix decoding of one PU wide files
Browse files Browse the repository at this point in the history
For those the block size may be larger than the source linesize (if the
edges are not allocated).

Signed-off-by: Anton Khirnov <anton@khirnov.net>
  • Loading branch information
smarter authored and elenril committed Jan 9, 2014
1 parent a246af8 commit e588615
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 17 deletions.
33 changes: 18 additions & 15 deletions libavcodec/hevc.c
Expand Up @@ -1497,15 +1497,19 @@ static void luma_mc(HEVCContext *s, int16_t *dst, ptrdiff_t dststride,
if (x_off < extra_left || y_off < extra_top ||
x_off >= pic_width - block_w - ff_hevc_qpel_extra_after[mx] ||
y_off >= pic_height - block_h - ff_hevc_qpel_extra_after[my]) {
const int edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->sps->pixel_shift;
int offset = extra_top * srcstride + (extra_left << s->sps->pixel_shift);
int buf_offset = extra_top *
edge_emu_stride + (extra_left << s->sps->pixel_shift);

s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src - offset,
srcstride, srcstride,
edge_emu_stride, srcstride,
block_w + ff_hevc_qpel_extra[mx],
block_h + ff_hevc_qpel_extra[my],
x_off - extra_left, y_off - extra_top,
pic_width, pic_height);
src = lc->edge_emu_buffer + offset;
src = lc->edge_emu_buffer + buf_offset;
srcstride = edge_emu_stride;
}
s->hevcdsp.put_hevc_qpel[my][mx](dst, dststride, src, srcstride, block_w,
block_h, lc->mc_buffer);
Expand Down Expand Up @@ -1548,27 +1552,35 @@ static void chroma_mc(HEVCContext *s, int16_t *dst1, int16_t *dst2,
if (x_off < EPEL_EXTRA_BEFORE || y_off < EPEL_EXTRA_AFTER ||
x_off >= pic_width - block_w - EPEL_EXTRA_AFTER ||
y_off >= pic_height - block_h - EPEL_EXTRA_AFTER) {
const int edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->sps->pixel_shift;
int offset1 = EPEL_EXTRA_BEFORE * (src1stride + (1 << s->sps->pixel_shift));
int buf_offset1 = EPEL_EXTRA_BEFORE *
(edge_emu_stride + (1 << s->sps->pixel_shift));
int offset2 = EPEL_EXTRA_BEFORE * (src2stride + (1 << s->sps->pixel_shift));
int buf_offset2 = EPEL_EXTRA_BEFORE *
(edge_emu_stride + (1 << s->sps->pixel_shift));

s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src1 - offset1,
src1stride, src1stride,
edge_emu_stride, src1stride,
block_w + EPEL_EXTRA, block_h + EPEL_EXTRA,
x_off - EPEL_EXTRA_BEFORE,
y_off - EPEL_EXTRA_BEFORE,
pic_width, pic_height);

src1 = lc->edge_emu_buffer + offset1;
src1 = lc->edge_emu_buffer + buf_offset1;
src1stride = edge_emu_stride;
s->hevcdsp.put_hevc_epel[!!my][!!mx](dst1, dststride, src1, src1stride,
block_w, block_h, mx, my, lc->mc_buffer);

s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src2 - offset2,
src2stride, src2stride,
edge_emu_stride, src2stride,
block_w + EPEL_EXTRA, block_h + EPEL_EXTRA,
x_off - EPEL_EXTRA_BEFORE,
y_off - EPEL_EXTRA_BEFORE,
pic_width, pic_height);
src2 = lc->edge_emu_buffer + offset2;
src2 = lc->edge_emu_buffer + buf_offset2;
src2stride = edge_emu_stride;

s->hevcdsp.put_hevc_epel[!!my][!!mx](dst2, dststride, src2, src2stride,
block_w, block_h, mx, my,
lc->mc_buffer);
Expand Down Expand Up @@ -2421,13 +2433,6 @@ static int hevc_frame_start(HEVCContext *s)
if (ret < 0)
goto fail;

av_fast_malloc(&lc->edge_emu_buffer, &lc->edge_emu_buffer_size,
(MAX_PB_SIZE + 7) * s->ref->frame->linesize[0]);
if (!lc->edge_emu_buffer) {
ret = AVERROR(ENOMEM);
goto fail;
}

ret = ff_hevc_frame_rps(s);
if (ret < 0) {
av_log(s->avctx, AV_LOG_ERROR, "Error constructing the frame RPS.\n");
Expand Down Expand Up @@ -2924,12 +2929,10 @@ static int hevc_ref_frame(HEVCContext *s, HEVCFrame *dst, HEVCFrame *src)
static av_cold int hevc_decode_free(AVCodecContext *avctx)
{
HEVCContext *s = avctx->priv_data;
HEVCLocalContext *lc = &s->HEVClc;
int i;

pic_arrays_free(s);

av_freep(&lc->edge_emu_buffer);
av_freep(&s->md5_ctx);

av_frame_free(&s->tmp_frame);
Expand Down
6 changes: 4 additions & 2 deletions libavcodec/hevc.h
Expand Up @@ -71,6 +71,8 @@
#define EPEL_EXTRA_AFTER 2
#define EPEL_EXTRA 3

#define EDGE_EMU_BUFFER_STRIDE 80

/**
* Value of the luma sample at position (x, y) in the 2D array tab.
*/
Expand Down Expand Up @@ -741,8 +743,8 @@ typedef struct HEVCLocalContext {
int start_of_tiles_x;
int end_of_tiles_x;
int end_of_tiles_y;
uint8_t *edge_emu_buffer;
int edge_emu_buffer_size;
/* +7 is for subpixel interpolation, *2 for high bit depths */
DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[(MAX_PB_SIZE + 7) * EDGE_EMU_BUFFER_STRIDE * 2];
CodingTree ct;
CodingUnit cu;
PredictionUnit pu;
Expand Down

0 comments on commit e588615

Please sign in to comment.