blob: 307dbb2032f8f987540a1f4542df6c49f373616d [file] [log] [blame]
#ifndef LIBGAV1_SRC_DSP_FILM_GRAIN_H_
#define LIBGAV1_SRC_DSP_FILM_GRAIN_H_
#include <cstddef>
#include <cstdint>
#include <memory>
#include <type_traits>
#include "src/dsp/common.h"
#include "src/utils/array_2d.h"
#include "src/utils/constants.h"
namespace libgav1 {
namespace dsp {
// Initialize Dsp::film_grain_synthesis. This function is not thread-safe.
void FilmGrainInit_C();
// Section 7.18.3.5. Add noise synthesis process.
template <int bitdepth>
class FilmGrain {
public:
// bitdepth grain_min_ grain_max_
// --------------------------------
// 8 -128 127
// 10 -512 511
// 12 -2048 2047
//
// So int8_t is big enough for bitdepth 8, whereas bitdepths 10 and 12 need
// int16_t.
using GrainType =
typename std::conditional<bitdepth == 8, int8_t, int16_t>::type;
FilmGrain(const FilmGrainParams& params, bool is_monochrome,
bool color_matrix_is_identity, int subsampling_x, int subsampling_y,
int width, int height);
// Note: These static methods are declared public so that the unit tests can
// call them.
static int GetRandomNumber(int bits, uint16_t* seed);
static void GenerateLumaGrain(const FilmGrainParams& params,
GrainType* luma_grain);
// Applies an auto-regressive filter to the white noise in luma_grain.
static void ApplyAutoRegressiveFilterToLumaGrain(
const FilmGrainParams& params, int grain_min, int grain_max,
GrainType* luma_grain);
// Generates white noise arrays u_grain and v_grain chroma_width samples wide
// and chroma_height samples high.
static void GenerateChromaGrains(const FilmGrainParams& params,
int chroma_width, int chroma_height,
GrainType* u_grain, GrainType* v_grain);
static void ApplyAutoRegressiveFilterToChromaGrains(
const FilmGrainParams& params, int grain_min, int grain_max,
const GrainType* luma_grain, int subsampling_x, int subsampling_y,
int chroma_width, int chroma_height, GrainType* u_grain,
GrainType* v_grain);
static void InitializeScalingLookupTable(int num_points,
const uint8_t point_value[],
const uint8_t point_scaling[],
uint8_t scaling_lut[256]);
// Combines the film grain with the image data.
bool AddNoise(const void* source_plane_y, ptrdiff_t source_stride_y,
const void* source_plane_u, ptrdiff_t source_stride_u,
const void* source_plane_v, ptrdiff_t source_stride_v,
void* dest_plane_y, ptrdiff_t dest_stride_y, void* dest_plane_u,
ptrdiff_t dest_stride_u, void* dest_plane_v,
ptrdiff_t dest_stride_v);
private:
using Pixel =
typename std::conditional<bitdepth == 8, uint8_t, uint16_t>::type;
// Allocates noise_stripe_, which points to memory owned by noise_buffer_.
bool AllocateNoiseStripes();
void ConstructNoiseStripes();
bool AllocateNoiseImage();
// Blends the noise stripes together to form a noise image.
void ConstructNoiseImage();
// Blends the noise with the original image data.
void BlendNoiseWithImage(
const void* source_plane_y, ptrdiff_t source_stride_y,
const void* source_plane_u, ptrdiff_t source_stride_u,
const void* source_plane_v, ptrdiff_t source_stride_v, void* dest_plane_y,
ptrdiff_t dest_stride_y, void* dest_plane_u, ptrdiff_t dest_stride_u,
void* dest_plane_v, ptrdiff_t dest_stride_v) const;
// The width of the luma noise array.
static constexpr int kLumaWidth = 82;
// The height of the luma noise array.
static constexpr int kLumaHeight = 73;
// The two possible widths of the chroma noise array
static constexpr int kMinChromaWidth = 44;
static constexpr int kMaxChromaWidth = 82;
// The two possible heights of the chroma noise array.
static constexpr int kMinChromaHeight = 38;
static constexpr int kMaxChromaHeight = 73;
const FilmGrainParams& params_;
const bool is_monochrome_;
const bool color_matrix_is_identity_;
const int subsampling_x_;
const int subsampling_y_;
const int width_;
const int height_;
int grain_min_;
int grain_max_;
const int chroma_width_;
const int chroma_height_;
// The luma_grain array contains white noise generated for luma.
// The array size is fixed but subject to further optimization for SIMD.
GrainType luma_grain_[kLumaHeight * kLumaWidth];
// The maximum size of the u_grain and v_grain arrays is
// kMaxChromaHeight * kMaxChromaWidth. The actual size is
// chroma_height_ * chroma_width_.
GrainType u_grain_[kMaxChromaHeight * kMaxChromaWidth];
GrainType v_grain_[kMaxChromaHeight * kMaxChromaWidth];
// Scaling lookup tables.
uint8_t scaling_lut_y_[256];
uint8_t scaling_lut_u_[256];
uint8_t scaling_lut_v_[256];
// A two-dimensional array of noise data. Generated for each 32 luma sample
// high stripe of the image. The first dimension is called luma_num. The
// second dimension is the plane.
//
// Each element of the noise_stripe_ array points to a conceptually
// two-dimensional array of int's. The two-dimensional array of int's is
// flattened into a one-dimensional buffer in this implementation.
//
// noise_stripe_[luma_num][kPlaneY] points to an array that has 34 rows and
// |width_| columns and contains noise for the luma component.
//
// noise_stripe_[luma_num][kPlaneU] or noise_stripe_[luma_num][kPlaneV]
// points to an array that has (34 >> subsampling_y_) rows and
// RightShiftWithRounding(width_, subsampling_x_) columns and contains noise
// for the chroma components.
Array2D<GrainType*> noise_stripe_;
// Owns the memory pointed to by the elements of noise_stripe_.
std::unique_ptr<GrainType[]> noise_buffer_;
Array2D<GrainType> noise_image_[kMaxPlanes];
};
} // namespace dsp
} // namespace libgav1
#endif // LIBGAV1_SRC_DSP_FILM_GRAIN_H_