summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavcodec/hevc_refs.c10
-rw-r--r--libavcodec/hevcdec.c54
-rw-r--r--libavcodec/hevcdec.h5
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;