diff options
-rw-r--r-- | libavcodec/hevc_refs.c | 10 | ||||
-rw-r--r-- | libavcodec/hevcdec.c | 54 | ||||
-rw-r--r-- | libavcodec/hevcdec.h | 5 |
3 files changed, 66 insertions, 3 deletions
diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c index 4f6d985ae6..06e42d9c53 100644 --- a/libavcodec/hevc_refs.c +++ b/libavcodec/hevc_refs.c @@ -38,6 +38,8 @@ void ff_hevc_unref_frame(HEVCContext *s, HEVCFrame *frame, int flags) frame->flags &= ~flags; if (!frame->flags) { ff_thread_release_buffer(s->avctx, &frame->tf); + ff_thread_release_buffer(s->avctx, &frame->tf_grain); + frame->needs_fg = 0; av_buffer_unref(&frame->tab_mvf_buf); frame->tab_mvf = NULL; @@ -208,7 +210,7 @@ int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush) if (nb_output) { HEVCFrame *frame = &s->DPB[min_idx]; - ret = av_frame_ref(out, frame->frame); + ret = av_frame_ref(out, frame->needs_fg ? frame->frame_grain : frame->frame); if (frame->flags & HEVC_FRAME_FLAG_BUMPING) ff_hevc_unref_frame(s, frame, HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_BUMPING); else @@ -216,6 +218,12 @@ int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush) if (ret < 0) return ret; + if (frame->needs_fg && (ret = av_frame_copy_props(out, frame->frame)) < 0) + return ret; + + if (!(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN)) + av_frame_remove_side_data(out, AV_FRAME_DATA_FILM_GRAIN_PARAMS); + av_log(s->avctx, AV_LOG_DEBUG, "Output frame with POC %d.\n", frame->poc); return 1; diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index b4edb3b3cc..246ffd7d80 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2884,14 +2884,14 @@ static int set_side_data(HEVCContext *s) s->sei.timecode.num_clock_ts = 0; } - if (s->sei.film_grain_characteristics.present && - (s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN)) { + if (s->sei.film_grain_characteristics.present) { HEVCSEIFilmGrainCharacteristics *fgc = &s->sei.film_grain_characteristics; AVFilmGrainParams *fgp = av_film_grain_params_create_side_data(out); if (!fgp) return AVERROR(ENOMEM); fgp->type = AV_FILM_GRAIN_PARAMS_H274; + fgp->seed = s->ref->poc; /* no poc_offset in HEVC */ fgp->codec.h274.model_id = fgc->model_id; if (fgc->separate_colour_description_present_flag) { @@ -2986,6 +2986,18 @@ static int hevc_frame_start(HEVCContext *s) s->ref->frame->key_frame = IS_IRAP(s); + s->ref->needs_fg = s->sei.film_grain_characteristics.present && + !(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) && + !s->avctx->hwaccel; + + if (s->ref->needs_fg) { + s->ref->frame_grain->format = s->ref->frame->format; + s->ref->frame_grain->width = s->ref->frame->width; + s->ref->frame_grain->height = s->ref->frame->height; + if ((ret = ff_thread_get_buffer(s->avctx, &s->ref->tf_grain, 0)) < 0) + goto fail; + } + ret = set_side_data(s); if (ret < 0) goto fail; @@ -3012,6 +3024,28 @@ fail: return ret; } +static int hevc_frame_end(HEVCContext *s) +{ + HEVCFrame *out = s->ref; + const AVFrameSideData *sd; + int ret; + + if (out->needs_fg) { + sd = av_frame_get_side_data(out->frame, AV_FRAME_DATA_FILM_GRAIN_PARAMS); + av_assert0(out->frame_grain->buf[0] && sd); + ret = ff_h274_apply_film_grain(out->frame_grain, out->frame, &s->h274db, + (AVFilmGrainParams *) sd->data); + + if (ret < 0) { + av_log(s->avctx, AV_LOG_WARNING, "Failed synthesizing film " + "grain, ignoring: %s\n", av_err2str(ret)); + out->needs_fg = 0; + } + } + + return 0; +} + static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) { HEVCLocalContext *lc = s->HEVClc; @@ -3170,6 +3204,9 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) else ctb_addr_ts = hls_slice_data(s); if (ctb_addr_ts >= (s->ps.sps->ctb_width * s->ps.sps->ctb_height)) { + ret = hevc_frame_end(s); + if (ret < 0) + goto fail; s->is_decoded = 1; } @@ -3429,6 +3466,13 @@ static int hevc_ref_frame(HEVCContext *s, HEVCFrame *dst, HEVCFrame *src) if (ret < 0) return ret; + if (src->needs_fg) { + ret = ff_thread_ref_frame(&dst->tf_grain, &src->tf_grain); + if (ret < 0) + return ret; + dst->needs_fg = 1; + } + dst->tab_mvf_buf = av_buffer_ref(src->tab_mvf_buf); if (!dst->tab_mvf_buf) goto fail; @@ -3481,6 +3525,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ff_hevc_unref_frame(s, &s->DPB[i], ~0); av_frame_free(&s->DPB[i].frame); + av_frame_free(&s->DPB[i].frame_grain); } ff_hevc_ps_uninit(&s->ps); @@ -3534,6 +3579,11 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) if (!s->DPB[i].frame) goto fail; s->DPB[i].tf.f = s->DPB[i].frame; + + s->DPB[i].frame_grain = av_frame_alloc(); + if (!s->DPB[i].frame_grain) + goto fail; + s->DPB[i].tf_grain.f = s->DPB[i].frame_grain; } s->max_ra = INT_MAX; diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index 482638a8e5..8963aa83ae 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -39,6 +39,7 @@ #include "hevc_ps.h" #include "hevc_sei.h" #include "hevcdsp.h" +#include "h274.h" #include "internal.h" #include "thread.h" #include "videodsp.h" @@ -395,7 +396,10 @@ typedef struct DBParams { typedef struct HEVCFrame { AVFrame *frame; + AVFrame *frame_grain; ThreadFrame tf; + ThreadFrame tf_grain; + int needs_fg; /* 1 if grain needs to be applied by the decoder */ MvField *tab_mvf; RefPicList *refPicList; RefPicListTab **rpl_tab; @@ -525,6 +529,7 @@ typedef struct HEVCContext { HEVCDSPContext hevcdsp; VideoDSPContext vdsp; BswapDSPContext bdsp; + H274FilmGrainDatabase h274db; int8_t *qp_y_tab; uint8_t *horizontal_bs; uint8_t *vertical_bs; |