@@ -27,6 +27,7 @@
#include "libavutil/avassert.h"
#include "libavutil/imgutils.h"
+#include "libavutil/film_grain_params.h"
#include "internal.h"
#include "cabac.h"
#include "cabac_functions.h"
@@ -212,6 +213,8 @@ void ff_h264_set_erpic(ERPicture *dst, H264Picture *src)
int ff_h264_field_end(H264Context *h, H264SliceContext *sl, int in_setup)
{
AVCodecContext *const avctx = h->avctx;
+ H264Picture *cur = h->cur_pic_ptr;
+ AVFrameSideData *sd;
int err = 0;
h->mb_y = 0;
@@ -225,6 +228,9 @@ int ff_h264_field_end(H264Context *h, H264SliceContext *sl, int in_setup)
h->poc.prev_frame_num = h->poc.frame_num;
}
+ if (!h->picture_idr && h->picture_intra_only)
+ h->poc_offset = 0;
+
if (avctx->hwaccel) {
err = avctx->hwaccel->end_frame(avctx);
if (err < 0)
@@ -232,8 +238,13 @@ int ff_h264_field_end(H264Context *h, H264SliceContext *sl, int in_setup)
"hardware accelerator failed to decode picture\n");
}
+ if ((sd = av_frame_get_side_data(cur->f, AV_FRAME_DATA_FILM_GRAIN_PARAMS))) {
+ AVFilmGrainParams *fgp = (AVFilmGrainParams *) sd->data;
+ fgp->seed = cur->poc + (h->poc_offset << 5);
+ }
+
if (!in_setup && !h->droppable)
- ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
+ ff_thread_report_progress(&cur->tf, INT_MAX,
h->picture_structure == PICT_BOTTOM_FIELD);
emms_c();
@@ -406,6 +406,7 @@ int ff_h264_update_thread_context(AVCodecContext *dst,
h->next_output_pic = h1->next_output_pic;
h->next_outputed_poc = h1->next_outputed_poc;
+ h->poc_offset = h1->poc_offset;
memcpy(h->mmco, h1->mmco, sizeof(h->mmco));
h->nb_mmco = h1->nb_mmco;
@@ -510,6 +511,7 @@ static int h264_frame_start(H264Context *h)
pic->sei_recovery_frame_cnt = h->sei.recovery_point.recovery_frame_cnt;
pic->f->pict_type = h->slice_ctx[0].slice_type;
+ h->picture_intra_only = 1; // set to 0 by h264_slice_init
pic->f->crop_left = h->crop_left;
pic->f->crop_right = h->crop_right;
@@ -1335,6 +1337,7 @@ static int h264_export_frame_props(H264Context *h)
return AVERROR(ENOMEM);
fgp->type = AV_FILM_GRAIN_PARAMS_H274;
+ /* fgp->seed is set by ff_h264_field_end */
fgp->codec.h274.model_id = fgc->model_id;
if (fgc->separate_colour_description_present_flag) {
@@ -1543,6 +1546,9 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl,
h->poc.delta_poc[0] = sl->delta_poc[0];
h->poc.delta_poc[1] = sl->delta_poc[1];
+ if (nal->type == H264_NAL_IDR_SLICE)
+ h->poc_offset = sl->idr_pic_id;
+
/* Shorten frame num gaps so we don't have to allocate reference
* frames just to throw them away */
if (h->poc.frame_num != h->poc.prev_frame_num) {
@@ -1891,7 +1897,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
}
if (nal->type == H264_NAL_IDR_SLICE)
- get_ue_golomb_long(&sl->gb); /* idr_pic_id */
+ sl->idr_pic_id = get_ue_golomb_long(&sl->gb);
sl->poc_lsb = 0;
sl->delta_poc_bottom = 0;
@@ -2024,6 +2030,9 @@ static int h264_slice_init(H264Context *h, H264SliceContext *sl,
return AVERROR_INVALIDDATA;
}
+ if (sl->slice_type_nos != AV_PICTURE_TYPE_I)
+ h->picture_intra_only = 0;
+
av_assert1(h->mb_num == h->mb_width * h->mb_height);
if (sl->first_mb_addr << FIELD_OR_MBAFF_PICTURE(h) >= h->mb_num ||
sl->first_mb_addr >= h->mb_num) {
@@ -331,6 +331,7 @@ typedef struct H264SliceContext {
int explicit_ref_marking;
int frame_num;
+ int idr_pic_id;
int poc_lsb;
int delta_poc_bottom;
int delta_poc[2];
@@ -384,6 +385,11 @@ typedef struct H264Context {
*/
int picture_idr;
+ /*
+ * Set to 1 when the current picture contains only I slices, 0 otherwise.
+ */
+ int picture_intra_only;
+
int crop_left;
int crop_right;
int crop_top;
@@ -473,6 +479,7 @@ typedef struct H264Context {
int last_pocs[MAX_DELAYED_PIC_COUNT];
H264Picture *next_output_pic;
int next_outputed_poc;
+ int poc_offset; ///< PicOrderCnt_offset from SMPTE RDD-2006
/**
* memory management control operations buffer.
@@ -221,6 +221,9 @@ typedef struct AVFilmGrainParams {
/**
* Seed to use for the synthesis process, if the codec allows for it.
+ *
+ * @note For H.264, this refers to `pic_offset` as defined in
+ * SMPTE RDD 5-2006.
*/
uint64_t seed;