Commit 6f1c2f7c authored by Andrey Norkin's avatar Andrey Norkin

Film grain synthesis algorithm

Change-Id: I7758fc79c1b6709c630f5641705dfd07fc4478e8
parent fdaad4dc
......@@ -689,6 +689,13 @@ enum aome_enc_control_id {
* EQUAL
*/
AV1E_SET_TIMING_INFO,
/*!\brief Codec control function to add film grain parameters (one of several
* preset types) info in the bitstream.
* \note Valid ranges: 0..11, default is "0". 0 = UNKNOWN,
* 1..16 = different test vectors for grain
*/
AV1E_SET_FILM_GRAIN_TEST_VECTOR,
};
/*!\brief aom 1-D scaling mode
......@@ -945,6 +952,9 @@ AOM_CTRL_USE_TYPE(AV1E_SET_SINGLE_TILE_DECODING, unsigned int)
AOM_CTRL_USE_TYPE(AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST, unsigned int)
#define AOM_CTRL_AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST
AOM_CTRL_USE_TYPE(AV1E_SET_FILM_GRAIN_TEST_VECTOR, unsigned int)
#define AOM_CTRL_AV1E_SET_FILM_GRAIN_TEST_VECTOR
/*!\endcond */
/*! @} - end defgroup aom_encoder */
#ifdef __cplusplus
......
......@@ -293,6 +293,12 @@ if (CONFIG_AV1_DECODER)
"${AOM_ROOT}/aom_dsp/daalaboolreader.h"
"${AOM_ROOT}/aom_dsp/entdec.c"
"${AOM_ROOT}/aom_dsp/entdec.h")
set(AOM_DSP_DECODER_SOURCES
${AOM_DSP_DECODER_SOURCES}
"${AOM_ROOT}/aom_dsp/grain_synthesis.c"
"${AOM_ROOT}/aom_dsp/grain_synthesis.h")
endif ()
if (CONFIG_AV1_ENCODER)
......
This diff is collapsed.
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
/*!\file
* \brief Describes film grain parameters and film grain synthesis
*
*/
#ifndef AOM_AOM_GRAIN_SYNTHESIS_H_
#define AOM_AOM_GRAIN_SYNTHESIS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "aom_dsp/aom_dsp_common.h"
#include "aom/aom_image.h"
/*!\brief Structure containing film grain synthesis parameters for a frame
*
* This structure contains input parameters for film grain synthesis
*/
typedef struct {
int apply_grain;
int update_parameters;
// 8 bit values
int scaling_points_y[14][2];
int num_y_points; // value: 0..14
// 8 bit values
int scaling_points_cb[10][2];
int num_cb_points; // value: 0..10
// 8 bit values
int scaling_points_cr[10][2];
int num_cr_points; // value: 0..10
int scaling_shift; // values : 8..11
int ar_coeff_lag; // values: 0..3
// 8 bit values
int ar_coeffs_y[24];
int ar_coeffs_cb[25];
int ar_coeffs_cr[25];
// Shift value: AR coeffs range
// 6: [-2, 2)
// 7: [-1, 1)
// 8: [-0.5, 0.5)
// 9: [-0.25, 0.25)
int ar_coeff_shift; // values : 6..9
int cb_mult; // 8 bits
int cb_luma_mult; // 8 bits
int cb_offset; // 9 bits
int cr_mult; // 8 bits
int cr_luma_mult; // 8 bits
int cr_offset; // 9 bits
int overlap_flag;
int clip_to_restricted_range;
int bit_depth; // video bit depth
int chroma_scaling_from_luma;
uint16_t random_seed;
} aom_film_grain_t;
/*!\brief Add film grain
*
* Add film grain to an image
*
* \param[in] grain_params Grain parameters
* \param[in] luma luma plane
* \param[in] cb cb plane
* \param[in] cr cr plane
* \param[in] height luma plane height
* \param[in] width luma plane width
* \param[in] luma_stride luma plane stride
* \param[in] chroma_stride chroma plane stride
*/
void av1_add_film_grain_run(aom_film_grain_t *grain_params, uint8_t *luma,
uint8_t *cb, uint8_t *cr, int height, int width,
int luma_stride, int chroma_stride,
int use_high_bit_depth);
/*!\brief Add film grain
*
* Add film grain to an image
*
* \param[in] grain_params Grain parameters
* \param[in] src Source image
* \param[in] dst Resulting image with grain
*/
void av1_add_film_grain(aom_film_grain_t *grain_params, aom_image_t *src,
aom_image_t *dst);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // AOM_AOM_GRAIN_SYNTHESIS_H_
......@@ -480,6 +480,12 @@ static const arg_def_t timing_info =
ARG_DEF_ENUM(NULL, "timing-info", 1,
"Signal timing info in the bitstream:", timing_info_enum);
#endif
#if CONFIG_FILM_GRAIN
static const arg_def_t film_grain_test =
ARG_DEF(NULL, "film-grain-test", 1,
"Film grain test vectors (0: none (default), 1: test-1 2: test-2, "
"... 16: test-16)");
#endif
#if CONFIG_TEMPMV_SIGNALING
static const arg_def_t disable_tempmv = ARG_DEF(
NULL, "disable-tempmv", 1, "Disable temporal mv prediction (default is 0)");
......@@ -712,6 +718,9 @@ static const arg_def_t *av1_args[] = { &cpu_used_av1,
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
&timing_info,
#endif
#if CONFIG_FILM_GRAIN
&film_grain_test,
#endif
#if CONFIG_TEMPMV_SIGNALING
&disable_tempmv,
#endif
......@@ -783,6 +792,9 @@ static const int av1_arg_ctrl_map[] = { AOME_SET_CPUUSED,
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
AV1E_SET_TIMING_INFO,
#endif
#if CONFIG_FILM_GRAIN
AV1E_SET_FILM_GRAIN_TEST_VECTOR,
#endif
#if CONFIG_TEMPMV_SIGNALING
AV1E_SET_DISABLE_TEMPMV,
#endif
......
......@@ -126,6 +126,7 @@ set(AOM_AV1_ENCODER_SOURCES
"${AOM_ROOT}/av1/encoder/extend.h"
"${AOM_ROOT}/av1/encoder/firstpass.c"
"${AOM_ROOT}/av1/encoder/firstpass.h"
"${AOM_ROOT}/av1/encoder/grain_test_vectors.h"
"${AOM_ROOT}/av1/encoder/hash.c"
"${AOM_ROOT}/av1/encoder/hash.h"
"${AOM_ROOT}/av1/encoder/hybrid_fwd_txfm.c"
......
......@@ -102,6 +102,9 @@ struct av1_extracfg {
unsigned int single_tile_decoding;
#endif // CONFIG_EXT_TILE
#if CONFIG_FILM_GRAIN
int film_grain_test_vector;
#endif
unsigned int motion_vector_unit_test;
};
......@@ -178,6 +181,9 @@ static struct av1_extracfg default_extra_cfg = {
0, // Single tile decoding is off by default.
#endif // CONFIG_EXT_TILE
#if CONFIG_FILM_GRAIN
0,
#endif
0, // motion_vector_unit_test
};
......@@ -434,6 +440,10 @@ static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx,
RANGE_CHECK(extra_cfg, timing_info, AOM_TIMING_UNSPECIFIED, AOM_TIMING_EQUAL);
#endif
#if CONFIG_FILM_GRAIN
RANGE_CHECK(extra_cfg, film_grain_test_vector, 0, 16);
#endif
if (extra_cfg->lossless) {
if (extra_cfg->aq_mode != 0)
ERROR("Only --aq_mode=0 can be used with --lossless=1.");
......@@ -671,6 +681,9 @@ static aom_codec_err_t set_encoder_config(
oxcf->superblock_size = extra_cfg->superblock_size;
#endif // CONFIG_EXT_PARTITION
#if CONFIG_FILM_GRAIN
oxcf->film_grain_test_vector = extra_cfg->film_grain_test_vector;
#endif
#if CONFIG_EXT_TILE
oxcf->large_scale_tile = cfg->large_scale_tile;
oxcf->single_tile_decoding =
......@@ -1049,6 +1062,16 @@ static aom_codec_err_t ctrl_set_aq_mode(aom_codec_alg_priv_t *ctx,
return update_extra_cfg(ctx, &extra_cfg);
}
#if CONFIG_FILM_GRAIN
static aom_codec_err_t ctrl_set_film_grain_test_vector(
aom_codec_alg_priv_t *ctx, va_list args) {
struct av1_extracfg extra_cfg = ctx->extra_cfg;
extra_cfg.film_grain_test_vector =
CAST(AV1E_SET_FILM_GRAIN_TEST_VECTOR, args);
return update_extra_cfg(ctx, &extra_cfg);
}
#endif
#if CONFIG_EXT_DELTA_Q
static aom_codec_err_t ctrl_set_deltaq_mode(aom_codec_alg_priv_t *ctx,
va_list args) {
......@@ -1755,6 +1778,10 @@ static aom_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
#if CONFIG_EXT_TILE
{ AV1E_SET_SINGLE_TILE_DECODING, ctrl_set_single_tile_decoding },
#endif // CONFIG_EXT_TILE
#if CONFIG_FILM_GRAIN
{ AV1E_SET_FILM_GRAIN_TEST_VECTOR, ctrl_set_film_grain_test_vector },
#endif // CONFIG_FILM_GRAIN
{ AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST, ctrl_enable_motion_vector_unit_test },
// Getters
......
......@@ -38,6 +38,9 @@
typedef struct cache_frame {
int fb_idx;
aom_image_t img;
#if CONFIG_FILM_GRAIN
aom_film_grain_t film_grain_params;
#endif
} cache_frame;
struct aom_codec_alg_priv {
......@@ -66,6 +69,9 @@ struct aom_codec_alg_priv {
int next_output_worker_id;
int available_threads;
cache_frame frame_cache[FRAME_CACHE_SIZE];
#if CONFIG_FILM_GRAIN
aom_image_t *image_with_grain;
#endif
int frame_cache_write;
int frame_cache_read;
int num_cache_frames;
......@@ -111,6 +117,9 @@ static aom_codec_err_t decoder_init(aom_codec_ctx_t *ctx,
priv->cfg = *ctx->config.dec;
ctx->config.dec = &priv->cfg;
}
#if CONFIG_FILM_GRAIN
priv->image_with_grain = NULL;
#endif
}
return AOM_CODEC_OK;
......@@ -152,6 +161,9 @@ static aom_codec_err_t decoder_destroy(aom_codec_alg_priv_t *ctx) {
aom_free(ctx->frame_workers);
aom_free(ctx->buffer_pool);
#if CONFIG_FILM_GRAIN
if (ctx->image_with_grain) aom_img_free(ctx->image_with_grain);
#endif
aom_free(ctx);
return AOM_CODEC_OK;
}
......@@ -723,6 +735,10 @@ static void wait_worker_and_cache_frame(aom_codec_alg_priv_t *ctx) {
frame_worker_data->user_priv);
ctx->frame_cache[ctx->frame_cache_write].img.fb_priv =
frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv;
#if CONFIG_FILM_GRAIN
memcpy(&ctx->frame_cache[ctx->frame_cache_write].film_grain_params,
&cm->film_grain_params, sizeof(aom_film_grain_t));
#endif
ctx->frame_cache_write = (ctx->frame_cache_write + 1) % FRAME_CACHE_SIZE;
++ctx->num_cache_frames;
}
......@@ -856,6 +872,28 @@ static void release_last_output_frame(aom_codec_alg_priv_t *ctx) {
}
}
#if CONFIG_FILM_GRAIN
aom_image_t *add_grain_if_needed(aom_image_t *img, aom_image_t *grain_img_buf,
aom_film_grain_t *grain_params) {
if (!grain_params->apply_grain) return img;
if (grain_img_buf &&
(img->d_w != grain_img_buf->d_w || img->d_h != grain_img_buf->d_h ||
img->fmt != grain_img_buf->fmt)) {
aom_img_free(grain_img_buf);
grain_img_buf = NULL;
}
if (!grain_img_buf) {
grain_img_buf = aom_img_alloc(NULL, img->fmt, img->d_w, img->d_h, 16);
grain_img_buf->bit_depth = img->bit_depth;
}
av1_add_film_grain(grain_params, img, grain_img_buf);
return grain_img_buf;
}
#endif
static aom_image_t *decoder_get_frame(aom_codec_alg_priv_t *ctx,
aom_codec_iter_t *iter) {
aom_image_t *img = NULL;
......@@ -875,7 +913,13 @@ static aom_image_t *decoder_get_frame(aom_codec_alg_priv_t *ctx,
img = &ctx->frame_cache[ctx->frame_cache_read].img;
ctx->frame_cache_read = (ctx->frame_cache_read + 1) % FRAME_CACHE_SIZE;
--ctx->num_cache_frames;
#if CONFIG_FILM_GRAIN
return add_grain_if_needed(
img, ctx->image_with_grain,
&ctx->frame_cache[ctx->frame_cache_read].film_grain_params);
#else
return img;
#endif
}
// iter acts as a flip flop, so an image is only returned on the first
......@@ -945,7 +989,13 @@ static aom_image_t *decoder_get_frame(aom_codec_alg_priv_t *ctx,
ctx->img.fb_priv = frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv;
img = &ctx->img;
#if CONFIG_FILM_GRAIN
return add_grain_if_needed(
img, ctx->image_with_grain,
&frame_worker_data->pbi->common.film_grain_params);
#else
return img;
#endif
}
} else {
// Decoding failed. Release the worker thread.
......
......@@ -33,6 +33,9 @@
// TODO(youzhou@microsoft.com): Encoder only. Move it out of common
#include "av1/encoder/hash_motion.h"
#endif
#if CONFIG_FILM_GRAIN
#include "aom_dsp/grain_synthesis.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
......@@ -156,6 +159,9 @@ typedef struct {
int width;
int height;
WarpedMotionParams global_motion[TOTAL_REFS_PER_FRAME];
#if CONFIG_FILM_GRAIN
aom_film_grain_t film_grain_params;
#endif
aom_codec_frame_buffer_t raw_frame_buffer;
YV12_BUFFER_CONFIG buf;
#if CONFIG_HASH_ME
......@@ -547,6 +553,10 @@ typedef struct AV1Common {
TXFM_CONTEXT left_txfm_context[MAX_MB_PLANE][2 * MAX_MIB_SIZE];
int above_context_alloc_cols;
WarpedMotionParams global_motion[TOTAL_REFS_PER_FRAME];
#if CONFIG_FILM_GRAIN
int film_grain_params_present;
aom_film_grain_t film_grain_params;
#endif
BLOCK_SIZE sb_size; // Size of the superblock used for this frame
int mib_size; // Size of the superblock in units of MI blocks
int mib_size_log2; // Log 2 of above.
......
......@@ -2175,6 +2175,98 @@ void av1_read_bitdepth(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
return;
}
#if CONFIG_FILM_GRAIN
void av1_read_film_grain_params(AV1_COMMON *cm,
struct aom_read_bit_buffer *rb) {
aom_film_grain_t *pars = &cm->film_grain_params;
pars->apply_grain = aom_rb_read_bit(rb);
if (!pars->apply_grain) return;
pars->random_seed = aom_rb_read_literal(rb, 16);
pars->update_parameters = aom_rb_read_bit(rb);
if (!pars->update_parameters) return;
// Scaling functions parameters
pars->num_y_points = aom_rb_read_literal(rb, 4); // max 14
for (int i = 0; i < pars->num_y_points; i++) {
pars->scaling_points_y[i][0] = aom_rb_read_literal(rb, 8);
pars->scaling_points_y[i][1] = aom_rb_read_literal(rb, 8);
}
pars->chroma_scaling_from_luma = aom_rb_read_bit(rb);
if (!pars->chroma_scaling_from_luma) {
pars->num_cb_points = aom_rb_read_literal(rb, 4); // max 10
for (int i = 0; i < pars->num_cb_points; i++) {
pars->scaling_points_cb[i][0] = aom_rb_read_literal(rb, 8);
pars->scaling_points_cb[i][1] = aom_rb_read_literal(rb, 8);
}
pars->num_cr_points = aom_rb_read_literal(rb, 4); // max 10
for (int i = 0; i < pars->num_cr_points; i++) {
pars->scaling_points_cr[i][0] = aom_rb_read_literal(rb, 8);
pars->scaling_points_cr[i][1] = aom_rb_read_literal(rb, 8);
}
}
pars->scaling_shift = aom_rb_read_literal(rb, 2) + 8; // 8 + value
// AR coefficients
// Only sent if the corresponsing scaling function has
// more than 0 points
pars->ar_coeff_lag = aom_rb_read_literal(rb, 2);
int num_pos_luma = 2 * pars->ar_coeff_lag * (pars->ar_coeff_lag + 1);
int num_pos_chroma = num_pos_luma + 1;
if (pars->num_y_points)
for (int i = 0; i < num_pos_luma; i++)
pars->ar_coeffs_y[i] = aom_rb_read_literal(rb, 8) - 128;
if (pars->num_cb_points || pars->chroma_scaling_from_luma)
for (int i = 0; i < num_pos_chroma; i++)
pars->ar_coeffs_cb[i] = aom_rb_read_literal(rb, 8) - 128;
if (pars->num_cr_points || pars->chroma_scaling_from_luma)
for (int i = 0; i < num_pos_chroma; i++)
pars->ar_coeffs_cr[i] = aom_rb_read_literal(rb, 8) - 128;
pars->ar_coeff_shift = aom_rb_read_literal(rb, 2) + 6; // 6 + value
if (pars->num_cb_points) {
pars->cb_mult = aom_rb_read_literal(rb, 8);
pars->cb_luma_mult = aom_rb_read_literal(rb, 8);
pars->cb_offset = aom_rb_read_literal(rb, 9);
}
if (pars->num_cr_points) {
pars->cr_mult = aom_rb_read_literal(rb, 8);
pars->cr_luma_mult = aom_rb_read_literal(rb, 8);
pars->cr_offset = aom_rb_read_literal(rb, 9);
}
pars->overlap_flag = aom_rb_read_bit(rb);
pars->clip_to_restricted_range = aom_rb_read_bit(rb);
}
static void av1_read_film_grain(AV1_COMMON *cm,
struct aom_read_bit_buffer *rb) {
if (cm->film_grain_params_present) {
av1_read_film_grain_params(cm, rb);
} else {
memset(&cm->film_grain_params, 0, sizeof(cm->film_grain_params));
}
cm->film_grain_params.bit_depth = cm->bit_depth;
memcpy(&cm->cur_frame->film_grain_params, &cm->film_grain_params,
sizeof(aom_film_grain_t));
}
#endif
void av1_read_bitdepth_colorspace_sampling(AV1_COMMON *cm,
struct aom_read_bit_buffer *rb,
int allow_lowbitdepth) {
......@@ -2594,6 +2686,10 @@ static int read_uncompressed_header(AV1Decoder *pbi,
#endif
cm->show_frame = 1;
#if CONFIG_FILM_GRAIN
av1_read_film_grain(cm, rb);
#endif
#if CONFIG_FWD_KF
cm->reset_decoder_state = aom_rb_read_bit(rb);
if (cm->reset_decoder_state) {
......@@ -2688,7 +2784,10 @@ static int read_uncompressed_header(AV1Decoder *pbi,
#if !CONFIG_OBU
av1_read_bitdepth_colorspace_sampling(cm, rb, pbi->allow_lowbitdepth);
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
av1_read_time_info_header(cm, rb);
av1_read_timing_info_header(cm, rb);
#endif
#if CONFIG_FILM_GRAIN
cm->film_grain_params_present = aom_rb_read_bit(rb);
#endif
#endif
pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1;
......@@ -2760,6 +2859,9 @@ static int read_uncompressed_header(AV1Decoder *pbi,
#if CONFIG_TIMING_INFO_IN_SEQ_HEADERS
av1_read_timing_info_header(cm, rb);
#endif
#if CONFIG_FILM_GRAIN
cm->film_grain_params_present = aom_rb_read_bit(rb);
#endif
#endif
pbi->refresh_frame_flags = aom_rb_read_literal(rb, REF_FRAMES);
......@@ -3181,6 +3283,12 @@ static int read_uncompressed_header(AV1Decoder *pbi,
if (!frame_is_intra_only(cm)) read_global_motion(cm, rb);
#if CONFIG_FILM_GRAIN
if (cm->show_frame) {
av1_read_film_grain(cm, rb);
}
#endif
#if !CONFIG_TILE_INFO_FIRST
read_tile_info(pbi, rb);
#endif
......
......@@ -60,6 +60,10 @@ static uint32_t read_sequence_header_obu(AV1Decoder *pbi,
av1_read_timing_info_header(cm, rb);
#endif
#if CONFIG_FILM_GRAIN
cm->film_grain_params_present = aom_rb_read_bit(rb);
#endif
return ((rb->bit_offset - saved_bit_offset + 7) >> 3);
}
......
......@@ -3311,6 +3311,90 @@ static void write_timing_info_header(AV1_COMMON *const cm,
}
#endif // CONFIG_TIMING_INFO_IN_SEQ_HEADERS
#if CONFIG_FILM_GRAIN
static void write_film_grain_params(AV1_COMMON *const cm,
struct aom_write_bit_buffer *wb) {
aom_film_grain_t *pars = &cm->film_grain_params;
aom_wb_write_bit(wb, pars->apply_grain);
if (!pars->apply_grain) return;
aom_wb_write_literal(wb, pars->random_seed, 16);
pars->random_seed += 3245; // For film grain test vectors purposes
if (!pars->random_seed) // Random seed should not be zero
pars->random_seed += 1735;
aom_wb_write_bit(wb, pars->update_parameters);
if (!pars->update_parameters) return;
// Scaling functions parameters
aom_wb_write_literal(wb, pars->num_y_points, 4); // max 14
for (int i = 0; i < pars->num_y_points; i++) {
aom_wb_write_literal(wb, pars->scaling_points_y[i][0], 8);
aom_wb_write_literal(wb, pars->scaling_points_y[i][1], 8);
}
aom_wb_write_bit(wb, pars->chroma_scaling_from_luma);
if (!pars->chroma_scaling_from_luma) {
aom_wb_write_literal(wb, pars->num_cb_points, 4); // max 10
for (int i = 0; i < pars->num_cb_points; i++) {
aom_wb_write_literal(wb, pars->scaling_points_cb[i][0], 8);
aom_wb_write_literal(wb, pars->scaling_points_cb[i][1], 8);
}
aom_wb_write_literal(wb, pars->num_cr_points, 4); // max 10
for (int i = 0; i < pars->num_cr_points; i++) {
aom_wb_write_literal(wb, pars->scaling_points_cr[i][0], 8);
aom_wb_write_literal(wb, pars->scaling_points_cr[i][1], 8);
}
}
aom_wb_write_literal(wb, pars->scaling_shift - 8, 2); // 8 + value
// AR coefficients
// Only sent if the corresponsing scaling function has
// more than 0 points
aom_wb_write_literal(wb, pars->ar_coeff_lag, 2);
int num_pos_luma = 2 * pars->ar_coeff_lag * (pars->ar_coeff_lag + 1);
int num_pos_chroma = num_pos_luma + 1;
if (pars->num_y_points)
for (int i = 0; i < num_pos_luma; i++)
aom_wb_write_literal(wb, pars->ar_coeffs_y[i] + 128, 8);
if (pars->num_cb_points || pars->chroma_scaling_from_luma)
for (int i = 0; i < num_pos_chroma; i++)
aom_wb_write_literal(wb, pars->ar_coeffs_cb[i] + 128, 8);
if (pars->num_cr_points || pars->chroma_scaling_from_luma)
for (int i = 0; i < num_pos_chroma; i++)
aom_wb_write_literal(wb, pars->ar_coeffs_cr[i] + 128, 8);
aom_wb_write_literal(wb, pars->ar_coeff_shift - 6, 2); // 8 + value
if (pars->num_cb_points) {
aom_wb_write_literal(wb, pars->cb_mult, 8);
aom_wb_write_literal(wb, pars->cb_luma_mult, 8);
aom_wb_write_literal(wb, pars->cb_offset, 9);
}
if (pars->num_cr_points) {
aom_wb_write_literal(wb, pars->cr_mult, 8);
aom_wb_write_literal(wb, pars->cr_luma_mult, 8);
aom_wb_write_literal(wb, pars->cr_offset, 9);
}
aom_wb_write_bit(wb, pars->overlap_flag);
aom_wb_write_bit(wb, pars->clip_to_restricted_range);
}
#endif // CONFIG_FILM_GRAIN
#if CONFIG_REFERENCE_BUFFER || CONFIG_OBU
void write_sequence_header(AV1_COMP *cpi, struct aom_write_bit_buffer *wb) {
AV1_COMMON *const cm = &cpi->common;
......@@ -3515,6 +3599,10 @@ static void write_uncompressed_header_frame(AV1_COMP *cpi,
}
#endif // CONFIG_REFERENCE_BUFFER
#if CONFIG_FILM_GRAIN
if (cm->film_grain_params_present) write_film_grain_params(cm, wb);
#endif
#if CONFIG_FWD_KF
if (cm->reset_decoder_state && !frame_bufs[frame_to_show].intra_only) {
aom_internal_error(
......@@ -3573,6 +3661,9 @@ static void write_uncompressed_header_frame(AV1_COMP *cpi,
// timing_info
write_timing_info_header(cm, wb);
#endif
#if CONFIG_FILM_GRAIN
aom_wb_write_bit(wb, cm->film_grain_params_present);
#endif
#if CONFIG_FRAME_SIZE
write_frame_size(cm, frame_size_override_flag, wb);
#else
......@@ -3617,6 +3708,9 @@ static void write_uncompressed_header_frame(AV1_COMP *cpi,
write_timing_info_header(cm, wb);
#endif
#if CONFIG_FILM_GRAIN
aom_wb_write_bit(wb, cm->film_grain_params_present);
#endif
aom_wb_write_literal(wb, cpi->refresh_frame_mask, REF_FRAMES);
#if CONFIG_FRAME_SIZE
write_frame_size(cm, frame_size_override_flag, wb);
......@@ -3805,6 +3899,11 @@ static void write_uncompressed_header_frame(AV1_COMP *cpi,
if (!frame_is_intra_only(cm)) write_global_motion(cpi, wb);
#if CONFIG_FILM_GRAIN
if (cm->film_grain_params_present && cm->show_frame)
write_film_grain_params(cm, wb);
#endif
#if !CONFIG_TILE_INFO_FIRST
write_tile_info(cm, wb);
#endif
......@@ -3849,6 +3948,21 @@ static void write_uncompressed_header_obu(AV1_COMP *cpi,
}
#endif // CONFIG_REFERENCE_BUFFER
#if CONFIG_FILM_GRAIN
if (cm->film_grain_params_present && cm->show_frame) {
int flip_back_update_parameters_flag = 0;
if (cm->frame_type == KEY_FRAME &&
cm->film_grain_params.update_parameters == 0) {
cm->film_grain_params.update_parameters = 1;
flip_back_update_parameters_flag = 1;
}
write_film_grain_params(cm, wb);
if (flip_back_update_parameters_flag)
cm->film_grain_params.update_parameters = 0;
}
#endif
#if CONFIG_FWD_KF
if (cm->reset_decoder_state && !frame_bufs[frame_to_show].intra_only) {
aom_internal_error(
......@@ -4186,6 +4300,21 @@ static void write_uncompressed_header_obu(AV1_COMP *cpi,
if (!frame_is_intra_only(cm)) write_global_motion(cpi, wb);
#if CONFIG_FILM_GRAIN
if (cm->film_grain_params_present && cm->show_frame) {
int flip_back_update_parameters_flag = 0;
if (cm->frame_type == KEY_FRAME &&
cm->film_grain_params.update_parameters == 0) {
cm->film_grain_params.update_parameters = 1;
flip_back_update_parameters_flag = 1;
}
write_film_grain_params(cm, wb);
if (flip_back_update_parameters_flag)
cm->film_grain_params.update_parameters = 0;
}
#endif
#if !CONFIG_TILE_INFO_FIRST
write_tile_info(cm, wb);
......@@ -4402,6 +4531,10 @@ static uint32_t write_sequence_header_obu(AV1_COMP *cpi, uint8_t *const dst) {
write_timing_info_header(cm, &wb);
#endif
#if CONFIG_FILM_GRAIN
aom_wb_write_bit(&wb, cm->film_grain_params_present);
#endif
size = aom_wb_bytes_written(&wb);
return size;
}
......