From 902a55f7161ffea10e13c1e7df14022e2ed90514 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Thu, 28 May 2015 18:25:37 +0200 Subject: dxva2_hevc: re-write reference frame handling The old logic required an explicit clearing of the lists first and was prone to overflow the DXVA2 struct in some circumstances. Signed-off-by: Luca Barbato --- libavcodec/dxva2_hevc.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'libavcodec/dxva2_hevc.c') diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c index a2abb97d19..5112bd2a51 100644 --- a/libavcodec/dxva2_hevc.c +++ b/libavcodec/dxva2_hevc.c @@ -57,7 +57,7 @@ static void fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext * DXVA_PicParams_HEVC *pp) { const HEVCFrame *current_picture = h->ref; - int i, j, k; + int i, j; memset(pp, 0, sizeof(*pp)); @@ -155,30 +155,34 @@ static void fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext * pp->log2_parallel_merge_level_minus2 = h->pps->log2_parallel_merge_level - 2; pp->CurrPicOrderCntVal = h->poc; - // empty the lists - memset(&pp->RefPicList, 0xff, sizeof(pp->RefPicList)); - memset(&pp->RefPicSetStCurrBefore, 0xff, sizeof(pp->RefPicSetStCurrBefore)); - memset(&pp->RefPicSetStCurrAfter, 0xff, sizeof(pp->RefPicSetStCurrAfter)); - memset(&pp->RefPicSetLtCurr, 0xff, sizeof(pp->RefPicSetLtCurr)); - // fill RefPicList from the DPB - for (i = 0, j = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) { - const HEVCFrame *frame = &h->DPB[i]; - if (frame != current_picture && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) { - fill_picture_entry(&pp->RefPicList[j], ff_dxva2_get_surface_index(avctx, ctx, frame->frame), !!(frame->flags & HEVC_FRAME_FLAG_LONG_REF)); - pp->PicOrderCntValList[j] = frame->poc; + for (i = 0, j = 0; i < FF_ARRAY_ELEMS(pp->RefPicList); i++) { + const HEVCFrame *frame = NULL; + while (!frame && j < FF_ARRAY_ELEMS(h->DPB)) { + if (&h->DPB[j] != current_picture && (h->DPB[j].flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) + frame = &h->DPB[j]; j++; } + + if (frame) { + fill_picture_entry(&pp->RefPicList[i], ff_dxva2_get_surface_index(avctx, ctx, frame->frame), !!(frame->flags & HEVC_FRAME_FLAG_LONG_REF)); + pp->PicOrderCntValList[i] = frame->poc; + } else { + pp->RefPicList[i].bPicEntry = 0xff; + pp->PicOrderCntValList[i] = 0; + } } #define DO_REF_LIST(ref_idx, ref_list) { \ const RefPicList *rpl = &h->rps[ref_idx]; \ - av_assert0(rpl->nb_refs <= FF_ARRAY_ELEMS(pp->ref_list)); \ - for (j = 0, k = 0; j < rpl->nb_refs; j++) { \ - if (rpl->ref[j]) { \ - pp->ref_list[k] = get_refpic_index(pp, ff_dxva2_get_surface_index(avctx, ctx, rpl->ref[j]->frame)); \ - k++; \ - } \ + for (i = 0, j = 0; i < FF_ARRAY_ELEMS(pp->ref_list); i++) { \ + const HEVCFrame *frame = NULL; \ + while (!frame && j < rpl->nb_refs) \ + frame = rpl->ref[j++]; \ + if (frame) \ + pp->ref_list[i] = get_refpic_index(pp, ff_dxva2_get_surface_index(avctx, ctx, frame->frame)); \ + else \ + pp->ref_list[i] = 0xff; \ } \ } -- cgit v1.2.3