@@ -157,7 +157,8 @@ static av_always_inline void generate(int8_t *out, int out_stride,
const uint8_t *in, int in_stride,
H274FilmGrainDatabase *database,
const AVFilmGrainH274Params *h274,
- int c, int invert, int deblock,
+ int c, uint8_t xs, uint8_t ys,
+ int invert, int deblock,
int y_offset, int x_offset)
{
const uint8_t shift = h274->log2_scale_factor + 6;
@@ -200,8 +201,8 @@ static av_always_inline void generate(int8_t *out, int out_stride,
h = num_values > 1 ? h274->comp_model_value[c][s][1] : 8;
v = num_values > 2 ? h274->comp_model_value[c][s][2] : h;
- h = av_clip(h << (c > 0 ? 1 : 0), 2, 14) - 2;
- v = av_clip(v << (c > 0 ? 1 : 0), 2, 14) - 2;
+ h = av_clip(h << xs, 2, 14) - 2;
+ v = av_clip(v << ys, 2, 14) - 2;
init_slice(database, h, v);
synth_grain_8x8_c(out, out_stride, scale, shift,
@@ -224,19 +225,34 @@ int ff_h274_apply_film_grain(AVFrame *out_frame, const AVFrame *in_frame,
const AVFilmGrainParams *params)
{
const AVFilmGrainH274Params *h274 = ¶ms->codec.h274;
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(out_frame->format);
av_assert1(params->type == AV_FILM_GRAIN_PARAMS_H274);
if (h274->model_id != 0)
return AVERROR_PATCHWELCOME;
av_assert1(out_frame->format == in_frame->format);
- if (in_frame->format != AV_PIX_FMT_YUV420P)
+ switch (out_frame->format) {
+ case AV_PIX_FMT_YUV444P:
+ case AV_PIX_FMT_YUV440P:
+ case AV_PIX_FMT_YUV422P:
+ case AV_PIX_FMT_YUV420P:
+ case AV_PIX_FMT_YUV411P:
+ case AV_PIX_FMT_YUV410P:
+ // 8-bit YCbCr formats with varying subsampling
+ break;
+
+ default:
+ // TODO: support higher bit depth formats!
return AVERROR_PATCHWELCOME;
+ }
for (int c = 0; c < 3; c++) {
static const uint8_t color_offset[3] = { 0, 85, 170 };
uint32_t seed = Seed_LUT[(params->seed + color_offset[c]) % 256];
- const int width = c > 0 ? AV_CEIL_RSHIFT(out_frame->width, 1) : out_frame->width;
- const int height = c > 0 ? AV_CEIL_RSHIFT(out_frame->height, 1) : out_frame->height;
+ const uint8_t xs = c > 0 ? desc->log2_chroma_w : 0;
+ const uint8_t ys = c > 0 ? desc->log2_chroma_h : 0;
+ const int width = AV_CEIL_RSHIFT(out_frame->width, xs);
+ const int height = AV_CEIL_RSHIFT(out_frame->height, ys);
uint8_t * const out = out_frame->data[c];
const int out_stride = out_frame->linesize[c];
@@ -266,7 +282,7 @@ int ff_h274_apply_film_grain(AVFrame *out_frame, const AVFrame *in_frame,
for (int xx = 0; xx < 16 && x+xx < width; xx += 8) {
generate(grain + (y+yy) * grain_stride + (x+xx), grain_stride,
in + (y+yy) * in_stride + (x+xx), in_stride,
- database, h274, c, invert, (x+xx) > 0,
+ database, h274, c, xs, ys, invert, (x+xx) > 0,
y_offset + yy, x_offset + xx);
}
}