/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ravif-0.13.0/src/av1encoder.rs
Line | Count | Source |
1 | | #![allow(deprecated)] |
2 | | use std::borrow::Cow; |
3 | | use crate::dirtyalpha::blurred_dirty_alpha; |
4 | | use crate::error::Error; |
5 | | #[cfg(not(feature = "threading"))] |
6 | | use crate::rayoff as rayon; |
7 | | use imgref::{Img, ImgVec}; |
8 | | use rav1e::prelude::*; |
9 | | use rgb::{RGB8, RGBA8}; |
10 | | |
11 | | /// For [`Encoder::with_internal_color_model`] |
12 | | #[derive(Debug, Copy, Clone, Eq, PartialEq)] |
13 | | pub enum ColorModel { |
14 | | /// Standard color model for photographic content. Usually the best choice. |
15 | | /// This library always uses full-resolution color (4:4:4). |
16 | | /// This library will automatically choose between BT.601 or BT.709. |
17 | | YCbCr, |
18 | | /// RGB channels are encoded without color space transformation. |
19 | | /// Usually results in larger file sizes, and is less compatible than `YCbCr`. |
20 | | /// Use only if the content really makes use of RGB, e.g. anaglyph images or RGB subpixel anti-aliasing. |
21 | | RGB, |
22 | | } |
23 | | |
24 | | /// Handling of color channels in transparent images. For [`Encoder::with_alpha_color_mode`] |
25 | | #[derive(Debug, Copy, Clone, Eq, PartialEq)] |
26 | | pub enum AlphaColorMode { |
27 | | /// Use unassociated alpha channel and leave color channels unchanged, even if there's redundant color data in transparent areas. |
28 | | UnassociatedDirty, |
29 | | /// Use unassociated alpha channel, but set color channels of transparent areas to a solid color to eliminate invisible data and improve compression. |
30 | | UnassociatedClean, |
31 | | /// Store color channels of transparent images in premultiplied form. |
32 | | /// This requires support for premultiplied alpha in AVIF decoders. |
33 | | /// |
34 | | /// It may reduce file sizes due to clearing of fully-transparent pixels, but |
35 | | /// may also increase file sizes due to creation of new edges in the color channels. |
36 | | /// |
37 | | /// Note that this is only internal detail for the AVIF file. |
38 | | /// It does not change meaning of `RGBA` in this library — it's always unassociated. |
39 | | Premultiplied, |
40 | | } |
41 | | |
42 | | #[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] |
43 | | pub enum BitDepth { |
44 | | Eight, |
45 | | Ten, |
46 | | /// Same as `Ten` |
47 | | #[default] |
48 | | Auto, |
49 | | } |
50 | | |
51 | | /// The newly-created image file + extra info FYI |
52 | | #[non_exhaustive] |
53 | | #[derive(Clone)] |
54 | | pub struct EncodedImage { |
55 | | /// AVIF (HEIF+AV1) encoded image data |
56 | | pub avif_file: Vec<u8>, |
57 | | /// FYI: number of bytes of AV1 payload used for the color |
58 | | pub color_byte_size: usize, |
59 | | /// FYI: number of bytes of AV1 payload used for the alpha channel |
60 | | pub alpha_byte_size: usize, |
61 | | } |
62 | | |
63 | | /// Encoder config builder |
64 | | /// |
65 | | /// The lifetime is relevant only for [`Encoder::with_exif()`]. Use `Encoder<'static>` if Rust complains. |
66 | | #[derive(Debug, Clone)] |
67 | | pub struct Encoder<'exif_slice> { |
68 | | /// 0-255 scale |
69 | | quantizer: u8, |
70 | | /// 0-255 scale |
71 | | alpha_quantizer: u8, |
72 | | /// rav1e preset 1 (slow) 10 (fast but crappy) |
73 | | speed: u8, |
74 | | /// True if RGBA input has already been premultiplied. It inserts appropriate metadata. |
75 | | premultiplied_alpha: bool, |
76 | | /// Which pixel format to use in AVIF file. RGB tends to give larger files. |
77 | | color_model: ColorModel, |
78 | | /// How many threads should be used (0 = match core count), None - use global rayon thread pool |
79 | | threads: Option<usize>, |
80 | | /// [`AlphaColorMode`] |
81 | | alpha_color_mode: AlphaColorMode, |
82 | | /// 8 or 10 |
83 | | output_depth: BitDepth, |
84 | | /// Dropped into MPEG infe BOX |
85 | | exif: Option<Cow<'exif_slice, [u8]>>, |
86 | | } |
87 | | |
88 | | /// Builder methods |
89 | | impl<'exif_slice> Encoder<'exif_slice> { |
90 | | /// Start here |
91 | | #[must_use] |
92 | 0 | pub fn new() -> Self { |
93 | 0 | Self { |
94 | 0 | quantizer: quality_to_quantizer(80.), |
95 | 0 | alpha_quantizer: quality_to_quantizer(80.), |
96 | 0 | speed: 5, |
97 | 0 | output_depth: BitDepth::default(), |
98 | 0 | premultiplied_alpha: false, |
99 | 0 | color_model: ColorModel::YCbCr, |
100 | 0 | threads: None, |
101 | 0 | exif: None, |
102 | 0 | alpha_color_mode: AlphaColorMode::UnassociatedClean, |
103 | 0 | } |
104 | 0 | } |
105 | | |
106 | | /// Quality `1..=100`. Panics if out of range. |
107 | | #[inline(always)] |
108 | | #[track_caller] |
109 | | #[must_use] |
110 | 0 | pub fn with_quality(mut self, quality: f32) -> Self { |
111 | 0 | assert!(quality >= 1. && quality <= 100.); |
112 | 0 | self.quantizer = quality_to_quantizer(quality); |
113 | 0 | self |
114 | 0 | } |
115 | | |
116 | | #[doc(hidden)] |
117 | | #[deprecated(note = "Renamed to with_bit_depth")] |
118 | | #[must_use] |
119 | 0 | pub fn with_depth(self, depth: Option<u8>) -> Self { |
120 | 0 | self.with_bit_depth(depth.map(|d| if d >= 10 { BitDepth::Ten } else { BitDepth::Eight }).unwrap_or(BitDepth::Auto)) |
121 | 0 | } |
122 | | |
123 | | /// Internal precision to use in the encoded AV1 data, for both color and alpha. 10-bit depth works best, even for 8-bit inputs/outputs. |
124 | | /// |
125 | | /// Use 8-bit depth only as a workaround for decoders that need it. |
126 | | /// |
127 | | /// This setting does not affect pixel inputs for this library. |
128 | | #[inline(always)] |
129 | | #[must_use] |
130 | 0 | pub fn with_bit_depth(mut self, depth: BitDepth) -> Self { |
131 | 0 | self.output_depth = depth; |
132 | 0 | self |
133 | 0 | } |
134 | | |
135 | | /// Quality for the alpha channel only. `1..=100`. Panics if out of range. |
136 | | #[inline(always)] |
137 | | #[track_caller] |
138 | | #[must_use] |
139 | 0 | pub fn with_alpha_quality(mut self, quality: f32) -> Self { |
140 | 0 | assert!(quality >= 1. && quality <= 100.); |
141 | 0 | self.alpha_quantizer = quality_to_quantizer(quality); |
142 | 0 | self |
143 | 0 | } |
144 | | |
145 | | /// * 1 = very very slow, but max compression. |
146 | | /// * 10 = quick, but larger file sizes and lower quality. |
147 | | /// |
148 | | /// Panics if outside `1..=10`. |
149 | | #[inline(always)] |
150 | | #[track_caller] |
151 | | #[must_use] |
152 | 0 | pub fn with_speed(mut self, speed: u8) -> Self { |
153 | 0 | assert!(speed >= 1 && speed <= 10); |
154 | 0 | self.speed = speed; |
155 | 0 | self |
156 | 0 | } |
157 | | |
158 | | /// Changes how color channels are stored in the image. The default is YCbCr. |
159 | | /// |
160 | | /// Note that this is only internal detail for the AVIF file, and doesn't |
161 | | /// change color model of inputs to encode functions. |
162 | | #[inline(always)] |
163 | | #[must_use] |
164 | 0 | pub fn with_internal_color_model(mut self, color_model: ColorModel) -> Self { |
165 | 0 | self.color_model = color_model; |
166 | 0 | self |
167 | 0 | } |
168 | | |
169 | | #[doc(hidden)] |
170 | | #[deprecated = "Renamed to `with_internal_color_model()`"] |
171 | | #[must_use] |
172 | 0 | pub fn with_internal_color_space(self, color_model: ColorModel) -> Self { |
173 | 0 | self.with_internal_color_model(color_model) |
174 | 0 | } |
175 | | |
176 | | /// Configures `rayon` thread pool size. |
177 | | /// The default `None` is to use all threads in the default `rayon` thread pool. |
178 | | #[inline(always)] |
179 | | #[track_caller] |
180 | | #[must_use] |
181 | 0 | pub fn with_num_threads(mut self, num_threads: Option<usize>) -> Self { |
182 | 0 | assert!(num_threads.is_none_or(|n| n > 0)); |
183 | 0 | self.threads = num_threads; |
184 | 0 | self |
185 | 0 | } |
186 | | |
187 | | /// Configure handling of color channels in transparent images |
188 | | /// |
189 | | /// Note that this doesn't affect input format for this library, |
190 | | /// which for RGBA is always uncorrelated alpha. |
191 | | #[inline(always)] |
192 | | #[must_use] |
193 | 0 | pub fn with_alpha_color_mode(mut self, mode: AlphaColorMode) -> Self { |
194 | 0 | self.alpha_color_mode = mode; |
195 | 0 | self.premultiplied_alpha = mode == AlphaColorMode::Premultiplied; |
196 | 0 | self |
197 | 0 | } |
198 | | |
199 | | /// Embedded into AVIF file as-is |
200 | | /// |
201 | | /// The data can be `Vec<u8>`, or `&[u8]` if the encoder instance doesn't leave its scope. |
202 | 0 | pub fn with_exif(mut self, exif_data: impl Into<Cow<'exif_slice, [u8]>>) -> Self { |
203 | 0 | self.exif = Some(exif_data.into()); |
204 | 0 | self |
205 | 0 | } Unexecuted instantiation: <ravif::av1encoder::Encoder>::with_exif::<_> Unexecuted instantiation: <ravif::av1encoder::Encoder>::with_exif::<alloc::vec::Vec<u8>> |
206 | | } |
207 | | |
208 | | /// Once done with config, call one of the `encode_*` functions |
209 | | impl Encoder<'_> { |
210 | | /// Make a new AVIF image from RGBA pixels (non-premultiplied, alpha last) |
211 | | /// |
212 | | /// Make the `Img` for the `buffer` like this: |
213 | | /// |
214 | | /// ```rust,ignore |
215 | | /// Img::new(&pixels_rgba[..], width, height) |
216 | | /// ``` |
217 | | /// |
218 | | /// If you have pixels as `u8` slice, then use the `rgb` crate, and do: |
219 | | /// |
220 | | /// ```rust,ignore |
221 | | /// use rgb::ComponentSlice; |
222 | | /// let pixels_rgba = pixels_u8.as_rgba(); |
223 | | /// ``` |
224 | | /// |
225 | | /// If all pixels are opaque, the alpha channel will be left out automatically. |
226 | | /// |
227 | | /// This function takes 8-bit inputs, but will generate an AVIF file using 10-bit depth. |
228 | | /// |
229 | | /// returns AVIF file with info about sizes about AV1 payload. |
230 | 0 | pub fn encode_rgba(&self, in_buffer: Img<&[rgb::RGBA<u8>]>) -> Result<EncodedImage, Error> { |
231 | 0 | let new_alpha = self.convert_alpha_8bit(in_buffer); |
232 | 0 | let buffer = new_alpha.as_ref().map(|b| b.as_ref()).unwrap_or(in_buffer); |
233 | 0 | let use_alpha = buffer.pixels().any(|px| px.a != 255); |
234 | 0 | if !use_alpha { |
235 | 0 | return self.encode_rgb_internal_from_8bit(buffer.width(), buffer.height(), buffer.pixels().map(|px| px.rgb())); |
236 | 0 | } |
237 | | |
238 | 0 | let width = buffer.width(); |
239 | 0 | let height = buffer.height(); |
240 | 0 | let matrix_coefficients = match self.color_model { |
241 | 0 | ColorModel::YCbCr => MatrixCoefficients::BT601, |
242 | 0 | ColorModel::RGB => MatrixCoefficients::Identity, |
243 | | }; |
244 | 0 | match self.output_depth { |
245 | | BitDepth::Eight => { |
246 | 0 | let planes = buffer.pixels().map(|px| match self.color_model { |
247 | 0 | ColorModel::YCbCr => rgb_to_8_bit_ycbcr(px.rgb(), BT601).into(), |
248 | 0 | ColorModel::RGB => rgb_to_8_bit_gbr(px.rgb()).into(), |
249 | 0 | }); |
250 | 0 | let alpha = buffer.pixels().map(|px| px.a); |
251 | 0 | self.encode_raw_planes_8_bit(width, height, planes, Some(alpha), PixelRange::Full, matrix_coefficients) |
252 | | }, |
253 | | BitDepth::Ten | BitDepth::Auto => { |
254 | 0 | let planes = buffer.pixels().map(|px| match self.color_model { |
255 | 0 | ColorModel::YCbCr => rgb_to_10_bit_ycbcr(px.rgb(), BT601).into(), |
256 | 0 | ColorModel::RGB => rgb_to_10_bit_gbr(px.rgb()).into(), |
257 | 0 | }); |
258 | 0 | let alpha = buffer.pixels().map(|px| to_ten(px.a)); |
259 | 0 | self.encode_raw_planes_10_bit(width, height, planes, Some(alpha), PixelRange::Full, matrix_coefficients) |
260 | | }, |
261 | | } |
262 | 0 | } |
263 | | |
264 | 0 | fn convert_alpha_8bit(&self, in_buffer: Img<&[RGBA8]>) -> Option<ImgVec<RGBA8>> { |
265 | 0 | match self.alpha_color_mode { |
266 | 0 | AlphaColorMode::UnassociatedDirty => None, |
267 | 0 | AlphaColorMode::UnassociatedClean => blurred_dirty_alpha(in_buffer), |
268 | | AlphaColorMode::Premultiplied => { |
269 | 0 | let prem = in_buffer.pixels() |
270 | 0 | .map(|px| { |
271 | 0 | if px.a == 0 || px.a == 255 { |
272 | 0 | RGBA8::default() |
273 | | } else { |
274 | 0 | RGBA8::new( |
275 | 0 | (u16::from(px.r) * 255 / u16::from(px.a)) as u8, |
276 | 0 | (u16::from(px.g) * 255 / u16::from(px.a)) as u8, |
277 | 0 | (u16::from(px.b) * 255 / u16::from(px.a)) as u8, |
278 | 0 | px.a, |
279 | | ) |
280 | | } |
281 | 0 | }) |
282 | 0 | .collect(); |
283 | 0 | Some(ImgVec::new(prem, in_buffer.width(), in_buffer.height())) |
284 | | }, |
285 | | } |
286 | 0 | } |
287 | | |
288 | | /// Make a new AVIF image from RGB pixels |
289 | | /// |
290 | | /// Make the `Img` for the `buffer` like this: |
291 | | /// |
292 | | /// ```rust,ignore |
293 | | /// Img::new(&pixels_rgb[..], width, height) |
294 | | /// ``` |
295 | | /// |
296 | | /// If you have pixels as `u8` slice, then first do: |
297 | | /// |
298 | | /// ```rust,ignore |
299 | | /// use rgb::ComponentSlice; |
300 | | /// let pixels_rgb = pixels_u8.as_rgb(); |
301 | | /// ``` |
302 | | /// |
303 | | /// returns AVIF file, size of color metadata |
304 | | #[inline] |
305 | 0 | pub fn encode_rgb(&self, buffer: Img<&[RGB8]>) -> Result<EncodedImage, Error> { |
306 | 0 | self.encode_rgb_internal_from_8bit(buffer.width(), buffer.height(), buffer.pixels()) |
307 | 0 | } Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_rgb Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_rgb |
308 | | |
309 | 0 | fn encode_rgb_internal_from_8bit(&self, width: usize, height: usize, pixels: impl Iterator<Item = RGB8> + Send + Sync) -> Result<EncodedImage, Error> { |
310 | 0 | let matrix_coefficients = match self.color_model { |
311 | 0 | ColorModel::YCbCr => MatrixCoefficients::BT601, |
312 | 0 | ColorModel::RGB => MatrixCoefficients::Identity, |
313 | | }; |
314 | | |
315 | 0 | match self.output_depth { |
316 | | BitDepth::Eight => { |
317 | 0 | let planes = pixels.map(|px| { |
318 | 0 | let (y, u, v) = match self.color_model { |
319 | 0 | ColorModel::YCbCr => rgb_to_8_bit_ycbcr(px, BT601), |
320 | 0 | ColorModel::RGB => rgb_to_8_bit_gbr(px), |
321 | | }; |
322 | 0 | [y, u, v] |
323 | 0 | }); Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit::<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit::<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#0} |
324 | 0 | self.encode_raw_planes_8_bit(width, height, planes, None::<[_; 0]>, PixelRange::Full, matrix_coefficients) |
325 | | }, |
326 | | BitDepth::Ten | BitDepth::Auto => { |
327 | 0 | let planes = pixels.map(|px| { |
328 | 0 | let (y, u, v) = match self.color_model { |
329 | 0 | ColorModel::YCbCr => rgb_to_10_bit_ycbcr(px, BT601), |
330 | 0 | ColorModel::RGB => rgb_to_10_bit_gbr(px), |
331 | | }; |
332 | 0 | [y, u, v] |
333 | 0 | }); Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit::<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#1}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit::<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#1} |
334 | 0 | self.encode_raw_planes_10_bit(width, height, planes, None::<[_; 0]>, PixelRange::Full, matrix_coefficients) |
335 | | }, |
336 | | } |
337 | 0 | } Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit::<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit::<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>> |
338 | | |
339 | | /// Encodes AVIF from 3 planar channels that are in the color space described by `matrix_coefficients`, |
340 | | /// with sRGB transfer characteristics and color primaries. |
341 | | /// |
342 | | /// Alpha always uses full range. Chroma subsampling is not supported, and it's a bad idea for AVIF anyway. |
343 | | /// If there's no alpha, use `None::<[_; 0]>`. |
344 | | /// |
345 | | /// `color_pixel_range` should be `PixelRange::Full` to avoid worsening already small 8-bit dynamic range. |
346 | | /// Support for limited range may be removed in the future. |
347 | | /// |
348 | | /// If `AlphaColorMode::Premultiplied` has been set, the alpha pixels must be premultiplied. |
349 | | /// `AlphaColorMode::UnassociatedClean` has no effect in this function, and is equivalent to `AlphaColorMode::UnassociatedDirty`. |
350 | | /// |
351 | | /// returns AVIF file, size of color metadata, size of alpha metadata overhead |
352 | | #[inline] |
353 | 0 | pub fn encode_raw_planes_8_bit( |
354 | 0 | &self, width: usize, height: usize, |
355 | 0 | planes: impl IntoIterator<Item = [u8; 3]> + Send, |
356 | 0 | alpha: Option<impl IntoIterator<Item = u8> + Send>, |
357 | 0 | color_pixel_range: PixelRange, matrix_coefficients: MatrixCoefficients, |
358 | 0 | ) -> Result<EncodedImage, Error> { |
359 | 0 | self.encode_raw_planes_internal(width, height, planes, alpha, color_pixel_range, matrix_coefficients, 8) |
360 | 0 | } Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_8_bit::<core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#0}>, [u8; 0]>Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_8_bit::<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#3}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#4}>>Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_8_bit::<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#0}>, [u8; 0]> |
361 | | |
362 | | /// Encodes AVIF from 3 planar channels that are in the color space described by `matrix_coefficients`, |
363 | | /// with sRGB transfer characteristics and color primaries. |
364 | | /// |
365 | | /// The pixels are 10-bit (values `0.=1023`) in host's native endian. |
366 | | /// |
367 | | /// Alpha always uses full range. Chroma subsampling is not supported, and it's a bad idea for AVIF anyway. |
368 | | /// If there's no alpha, use `None::<[_; 0]>`. |
369 | | /// |
370 | | /// `color_pixel_range` should be `PixelRange::Full`. Support for limited range may be removed in the future. |
371 | | /// |
372 | | /// If `AlphaColorMode::Premultiplied` has been set, the alpha pixels must be premultiplied. |
373 | | /// `AlphaColorMode::UnassociatedClean` has no effect in this function, and is equivalent to `AlphaColorMode::UnassociatedDirty`. |
374 | | /// |
375 | | /// returns AVIF file, size of color metadata, size of alpha metadata overhead |
376 | | #[inline] |
377 | 0 | pub fn encode_raw_planes_10_bit( |
378 | 0 | &self, width: usize, height: usize, |
379 | 0 | planes: impl IntoIterator<Item = [u16; 3]> + Send, |
380 | 0 | alpha: Option<impl IntoIterator<Item = u16> + Send>, |
381 | 0 | color_pixel_range: PixelRange, matrix_coefficients: MatrixCoefficients, |
382 | 0 | ) -> Result<EncodedImage, Error> { |
383 | 0 | self.encode_raw_planes_internal(width, height, planes, alpha, color_pixel_range, matrix_coefficients, 10) |
384 | 0 | } Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_10_bit::<core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#1}>, [u16; 0]>Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_10_bit::<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#5}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#6}>>Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_10_bit::<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#1}>, [u16; 0]> |
385 | | |
386 | | #[inline(never)] |
387 | 0 | fn encode_raw_planes_internal<P: rav1e::Pixel + Default>( |
388 | 0 | &self, width: usize, height: usize, |
389 | 0 | planes: impl IntoIterator<Item = [P; 3]> + Send, |
390 | 0 | alpha: Option<impl IntoIterator<Item = P> + Send>, |
391 | 0 | color_pixel_range: PixelRange, matrix_coefficients: MatrixCoefficients, |
392 | 0 | input_pixels_bit_depth: u8, |
393 | 0 | ) -> Result<EncodedImage, Error> { |
394 | 0 | let color_description = Some(ColorDescription { |
395 | 0 | transfer_characteristics: TransferCharacteristics::SRGB, |
396 | 0 | color_primaries: ColorPrimaries::BT709, // sRGB-compatible |
397 | 0 | matrix_coefficients, |
398 | 0 | }); |
399 | | |
400 | 0 | let threads = self.threads.map(|threads| { |
401 | 0 | if threads > 0 { threads } else { rayon::current_num_threads() } |
402 | 0 | }); Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#0}>, [u8; 0]>::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#3}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#4}>>::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#1}>, [u16; 0]>::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#5}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#6}>>::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#0}>, [u8; 0]>::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#1}>, [u16; 0]>::{closure#0} |
403 | | |
404 | 0 | let encode_color = move || { |
405 | 0 | encode_to_av1::<P>( |
406 | 0 | &Av1EncodeConfig { |
407 | 0 | width, |
408 | 0 | height, |
409 | 0 | bit_depth: input_pixels_bit_depth.into(), |
410 | 0 | quantizer: self.quantizer.into(), |
411 | 0 | speed: SpeedTweaks::from_my_preset(self.speed, self.quantizer), |
412 | 0 | threads, |
413 | 0 | pixel_range: color_pixel_range, |
414 | 0 | chroma_sampling: ChromaSampling::Cs444, |
415 | 0 | color_description, |
416 | 0 | }, |
417 | 0 | move |frame| init_frame_3(width, height, planes, frame), Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#0}>, [u8; 0]>::{closure#1}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#3}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#4}>>::{closure#1}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#1}>, [u16; 0]>::{closure#1}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#5}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#6}>>::{closure#1}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#0}>, [u8; 0]>::{closure#1}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#1}>, [u16; 0]>::{closure#1}::{closure#0} |
418 | | ) |
419 | 0 | }; Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#0}>, [u8; 0]>::{closure#1}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#3}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#4}>>::{closure#1}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#1}>, [u16; 0]>::{closure#1}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#5}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#6}>>::{closure#1}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#0}>, [u8; 0]>::{closure#1}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#1}>, [u16; 0]>::{closure#1} |
420 | 0 | let encode_alpha = move || { |
421 | 0 | alpha.map(|alpha| { |
422 | 0 | encode_to_av1::<P>( |
423 | 0 | &Av1EncodeConfig { |
424 | 0 | width, |
425 | 0 | height, |
426 | 0 | bit_depth: input_pixels_bit_depth.into(), |
427 | 0 | quantizer: self.alpha_quantizer.into(), |
428 | 0 | speed: SpeedTweaks::from_my_preset(self.speed, self.alpha_quantizer), |
429 | 0 | threads, |
430 | 0 | pixel_range: PixelRange::Full, |
431 | 0 | chroma_sampling: ChromaSampling::Cs400, |
432 | 0 | color_description: None, |
433 | 0 | }, |
434 | 0 | |frame| init_frame_1(width, height, alpha, frame), Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#0}>, [u8; 0]>::{closure#2}::{closure#0}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#3}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#4}>>::{closure#2}::{closure#0}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#1}>, [u16; 0]>::{closure#2}::{closure#0}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#5}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#6}>>::{closure#2}::{closure#0}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#0}>, [u8; 0]>::{closure#2}::{closure#0}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#1}>, [u16; 0]>::{closure#2}::{closure#0}::{closure#0} |
435 | | ) |
436 | 0 | }) Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#0}>, [u8; 0]>::{closure#2}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#3}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#4}>>::{closure#2}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#1}>, [u16; 0]>::{closure#2}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#5}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#6}>>::{closure#2}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#0}>, [u8; 0]>::{closure#2}::{closure#0}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#1}>, [u16; 0]>::{closure#2}::{closure#0} |
437 | 0 | }; Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#0}>, [u8; 0]>::{closure#2}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#3}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#4}>>::{closure#2}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#1}>, [u16; 0]>::{closure#2}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#5}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#6}>>::{closure#2}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#0}>, [u8; 0]>::{closure#2}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#1}>, [u16; 0]>::{closure#2} |
438 | | #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] |
439 | | let (color, alpha) = (encode_color(), encode_alpha()); |
440 | | #[cfg(not(all(target_arch = "wasm32", not(target_feature = "atomics"))))] |
441 | 0 | let (color, alpha) = rayon::join(encode_color, encode_alpha); |
442 | 0 | let (color, alpha) = (color?, alpha.transpose()?); |
443 | | |
444 | 0 | let mut serializer_config = avif_serialize::Aviffy::new(); |
445 | 0 | serializer_config |
446 | 0 | .matrix_coefficients(match matrix_coefficients { |
447 | 0 | MatrixCoefficients::Identity => avif_serialize::constants::MatrixCoefficients::Rgb, |
448 | 0 | MatrixCoefficients::BT709 => avif_serialize::constants::MatrixCoefficients::Bt709, |
449 | 0 | MatrixCoefficients::Unspecified => avif_serialize::constants::MatrixCoefficients::Unspecified, |
450 | 0 | MatrixCoefficients::BT601 => avif_serialize::constants::MatrixCoefficients::Bt601, |
451 | 0 | MatrixCoefficients::YCgCo => avif_serialize::constants::MatrixCoefficients::Ycgco, |
452 | 0 | MatrixCoefficients::BT2020NCL => avif_serialize::constants::MatrixCoefficients::Bt2020Ncl, |
453 | 0 | MatrixCoefficients::BT2020CL => avif_serialize::constants::MatrixCoefficients::Bt2020Cl, |
454 | 0 | _ => return Err(Error::Unsupported("matrix coefficients")), |
455 | | }) |
456 | 0 | .premultiplied_alpha(self.premultiplied_alpha); |
457 | 0 | if let Some(exif) = &self.exif { |
458 | 0 | serializer_config.set_exif(exif.to_vec()); |
459 | 0 | } |
460 | 0 | let avif_file = serializer_config.to_vec(&color, alpha.as_deref(), width as u32, height as u32, input_pixels_bit_depth); |
461 | 0 | let color_byte_size = color.len(); |
462 | 0 | let alpha_byte_size = alpha.as_ref().map_or(0, |a| a.len()); Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#0}>, [u8; 0]>::{closure#3}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#3}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#4}>>::{closure#3}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#1}>, [u16; 0]>::{closure#3}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#5}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#6}>>::{closure#3}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#0}>, [u8; 0]>::{closure#3}Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#1}>, [u16; 0]>::{closure#3} |
463 | | |
464 | 0 | Ok(EncodedImage { |
465 | 0 | avif_file, color_byte_size, alpha_byte_size, |
466 | 0 | }) |
467 | 0 | } Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#0}>, [u8; 0]>Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#3}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#4}>>Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#1}>, [u16; 0]>Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#5}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#6}>>Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#0}>, [u8; 0]>Unexecuted instantiation: <ravif::av1encoder::Encoder>::encode_raw_planes_internal::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#1}>, [u16; 0]> |
468 | | } |
469 | | |
470 | | /// Native endian |
471 | | #[inline(always)] |
472 | 0 | fn to_ten(x: u8) -> u16 { |
473 | 0 | (u16::from(x) << 2) | (u16::from(x) >> 6) |
474 | 0 | } |
475 | | |
476 | | /// Native endian |
477 | | #[inline(always)] |
478 | 0 | fn rgb_to_10_bit_gbr(px: rgb::RGB<u8>) -> (u16, u16, u16) { |
479 | 0 | (to_ten(px.g), to_ten(px.b), to_ten(px.r)) |
480 | 0 | } |
481 | | |
482 | | #[inline(always)] |
483 | 0 | fn rgb_to_8_bit_gbr(px: rgb::RGB<u8>) -> (u8, u8, u8) { |
484 | 0 | (px.g, px.b, px.r) |
485 | 0 | } |
486 | | |
487 | | // const REC709: [f32; 3] = [0.2126, 0.7152, 0.0722]; |
488 | | const BT601: [f32; 3] = [0.2990, 0.5870, 0.1140]; |
489 | | |
490 | | #[inline(always)] |
491 | 0 | fn rgb_to_ycbcr(px: rgb::RGB<u8>, depth: u8, matrix: [f32; 3]) -> (f32, f32, f32) { |
492 | 0 | let max_value = ((1 << depth) - 1) as f32; |
493 | 0 | let scale = max_value / 255.; |
494 | 0 | let shift = (max_value * 0.5).round(); |
495 | 0 | let y = (scale * matrix[2]).mul_add(f32::from(px.b), (scale * matrix[0]).mul_add(f32::from(px.r), scale * matrix[1] * f32::from(px.g))); |
496 | 0 | let cb = f32::from(px.b).mul_add(scale, -y).mul_add(0.5 / (1. - matrix[2]), shift); |
497 | 0 | let cr = f32::from(px.r).mul_add(scale, -y).mul_add(0.5 / (1. - matrix[0]), shift); |
498 | 0 | (y.round(), cb.round(), cr.round()) |
499 | 0 | } |
500 | | |
501 | | #[inline(always)] |
502 | 0 | fn rgb_to_10_bit_ycbcr(px: rgb::RGB<u8>, matrix: [f32; 3]) -> (u16, u16, u16) { |
503 | 0 | let (y, u, v) = rgb_to_ycbcr(px, 10, matrix); |
504 | 0 | (y as u16, u as u16, v as u16) |
505 | 0 | } |
506 | | |
507 | | #[inline(always)] |
508 | 0 | fn rgb_to_8_bit_ycbcr(px: rgb::RGB<u8>, matrix: [f32; 3]) -> (u8, u8, u8) { |
509 | 0 | let (y, u, v) = rgb_to_ycbcr(px, 8, matrix); |
510 | 0 | (y as u8, u as u8, v as u8) |
511 | 0 | } |
512 | | |
513 | 0 | fn quality_to_quantizer(quality: f32) -> u8 { |
514 | 0 | let q = quality / 100.; |
515 | 0 | let x = if q >= 0.82 { (1. - q) * 2.6 } else if q > 0.25 { q.mul_add(-0.5, 1. - 0.125) } else { 1. - q }; |
516 | 0 | (x * 255.).round() as u8 |
517 | 0 | } |
518 | | |
519 | | #[derive(Debug, Copy, Clone)] |
520 | | struct SpeedTweaks { |
521 | | pub speed_preset: u8, |
522 | | |
523 | | pub fast_deblock: Option<bool>, |
524 | | pub reduced_tx_set: Option<bool>, |
525 | | pub tx_domain_distortion: Option<bool>, |
526 | | pub tx_domain_rate: Option<bool>, |
527 | | pub encode_bottomup: Option<bool>, |
528 | | pub rdo_tx_decision: Option<bool>, |
529 | | pub cdef: Option<bool>, |
530 | | /// loop restoration filter |
531 | | pub lrf: Option<bool>, |
532 | | pub sgr_complexity_full: Option<bool>, |
533 | | pub use_satd_subpel: Option<bool>, |
534 | | pub inter_tx_split: Option<bool>, |
535 | | pub fine_directional_intra: Option<bool>, |
536 | | pub complex_prediction_modes: Option<bool>, |
537 | | pub partition_range: Option<(u8, u8)>, |
538 | | pub min_tile_size: u16, |
539 | | } |
540 | | |
541 | | impl SpeedTweaks { |
542 | 0 | pub fn from_my_preset(speed: u8, quantizer: u8) -> Self { |
543 | 0 | let low_quality = quantizer < quality_to_quantizer(55.); |
544 | 0 | let high_quality = quantizer > quality_to_quantizer(80.); |
545 | 0 | let max_block_size = if high_quality { 16 } else { 64 }; |
546 | | |
547 | | Self { |
548 | 0 | speed_preset: speed, |
549 | | |
550 | 0 | partition_range: Some(match speed { |
551 | 0 | 0 => (4, 64.min(max_block_size)), |
552 | 0 | 1 if low_quality => (4, 64.min(max_block_size)), |
553 | 0 | 2 if low_quality => (4, 32.min(max_block_size)), |
554 | 0 | 1..=4 => (4, 16), |
555 | 0 | 5..=8 => (8, 16), |
556 | 0 | _ => (16, 16), |
557 | | }), |
558 | | |
559 | 0 | complex_prediction_modes: Some(speed <= 1), // 2x-3x slower, 2% better |
560 | 0 | sgr_complexity_full: Some(speed <= 2), // 15% slower, barely improves anything -/+1% |
561 | | |
562 | 0 | encode_bottomup: Some(speed <= 2), // may be costly (+60%), may even backfire |
563 | | |
564 | | // big blocks disabled at 3 |
565 | | |
566 | | // these two are together? |
567 | 0 | rdo_tx_decision: Some(speed <= 4 && !high_quality), // it tends to blur subtle textures |
568 | 0 | reduced_tx_set: Some(speed == 4 || speed >= 9), // It interacts with tx_domain_distortion too? |
569 | | |
570 | | // 4px blocks disabled at 5 |
571 | | |
572 | 0 | fine_directional_intra: Some(speed <= 6), |
573 | 0 | fast_deblock: Some(speed >= 7 && !high_quality), // mixed bag? |
574 | | |
575 | | // 8px blocks disabled at 8 |
576 | 0 | lrf: Some(low_quality && speed <= 8), // hardly any help for hi-q images. recovers some q at low quality |
577 | 0 | cdef: Some(low_quality && speed <= 9), // hardly any help for hi-q images. recovers some q at low quality |
578 | | |
579 | 0 | inter_tx_split: Some(speed >= 9), // mixed bag even when it works, and it backfires if not used together with reduced_tx_set |
580 | 0 | tx_domain_rate: Some(speed >= 10), // 20% faster, but also 10% larger files! |
581 | | |
582 | 0 | tx_domain_distortion: None, // very mixed bag, sometimes helps speed sometimes it doesn't |
583 | 0 | use_satd_subpel: Some(false), // doesn't make sense |
584 | 0 | min_tile_size: match speed { |
585 | 0 | 0 => 4096, |
586 | 0 | 1 => 2048, |
587 | 0 | 2 => 1024, |
588 | 0 | 3 => 512, |
589 | 0 | 4 => 256, |
590 | 0 | _ => 128, |
591 | 0 | } * if high_quality { 2 } else { 1 }, |
592 | | } |
593 | 0 | } |
594 | | |
595 | 0 | pub(crate) fn speed_settings(&self) -> SpeedSettings { |
596 | 0 | let mut speed_settings = SpeedSettings::from_preset(self.speed_preset); |
597 | | |
598 | 0 | speed_settings.multiref = false; |
599 | 0 | speed_settings.rdo_lookahead_frames = 1; |
600 | 0 | speed_settings.scene_detection_mode = SceneDetectionSpeed::None; |
601 | 0 | speed_settings.motion.include_near_mvs = false; |
602 | | |
603 | 0 | if let Some(v) = self.fast_deblock { speed_settings.fast_deblock = v; } |
604 | 0 | if let Some(v) = self.reduced_tx_set { speed_settings.transform.reduced_tx_set = v; } |
605 | 0 | if let Some(v) = self.tx_domain_distortion { speed_settings.transform.tx_domain_distortion = v; } |
606 | 0 | if let Some(v) = self.tx_domain_rate { speed_settings.transform.tx_domain_rate = v; } |
607 | 0 | if let Some(v) = self.encode_bottomup { speed_settings.partition.encode_bottomup = v; } |
608 | 0 | if let Some(v) = self.rdo_tx_decision { speed_settings.transform.rdo_tx_decision = v; } |
609 | 0 | if let Some(v) = self.cdef { speed_settings.cdef = v; } |
610 | 0 | if let Some(v) = self.lrf { speed_settings.lrf = v; } |
611 | 0 | if let Some(v) = self.inter_tx_split { speed_settings.transform.enable_inter_tx_split = v; } |
612 | 0 | if let Some(v) = self.sgr_complexity_full { speed_settings.sgr_complexity = if v { SGRComplexityLevel::Full } else { SGRComplexityLevel::Reduced } } |
613 | 0 | if let Some(v) = self.use_satd_subpel { speed_settings.motion.use_satd_subpel = v; } |
614 | 0 | if let Some(v) = self.fine_directional_intra { speed_settings.prediction.fine_directional_intra = v; } |
615 | 0 | if let Some(v) = self.complex_prediction_modes { speed_settings.prediction.prediction_modes = if v { PredictionModesSetting::ComplexAll } else { PredictionModesSetting::Simple} } |
616 | 0 | if let Some((min, max)) = self.partition_range { |
617 | 0 | debug_assert!(min <= max); |
618 | 0 | fn sz(s: u8) -> BlockSize { |
619 | 0 | match s { |
620 | 0 | 4 => BlockSize::BLOCK_4X4, |
621 | 0 | 8 => BlockSize::BLOCK_8X8, |
622 | 0 | 16 => BlockSize::BLOCK_16X16, |
623 | 0 | 32 => BlockSize::BLOCK_32X32, |
624 | 0 | 64 => BlockSize::BLOCK_64X64, |
625 | 0 | 128 => BlockSize::BLOCK_128X128, |
626 | 0 | _ => panic!("bad size {s}"), |
627 | | } |
628 | 0 | } |
629 | 0 | speed_settings.partition.partition_range = PartitionRange::new(sz(min), sz(max)); |
630 | 0 | } |
631 | | |
632 | 0 | speed_settings |
633 | 0 | } |
634 | | } |
635 | | |
636 | | struct Av1EncodeConfig { |
637 | | pub width: usize, |
638 | | pub height: usize, |
639 | | pub bit_depth: usize, |
640 | | pub quantizer: usize, |
641 | | pub speed: SpeedTweaks, |
642 | | /// 0 means num_cpus |
643 | | pub threads: Option<usize>, |
644 | | pub pixel_range: PixelRange, |
645 | | pub chroma_sampling: ChromaSampling, |
646 | | pub color_description: Option<ColorDescription>, |
647 | | } |
648 | | |
649 | 0 | fn rav1e_config(p: &Av1EncodeConfig) -> Config { |
650 | | // AV1 needs all the CPU power you can give it, |
651 | | // except when it'd create inefficiently tiny tiles |
652 | 0 | let tiles = { |
653 | 0 | let threads = p.threads.unwrap_or_else(rayon::current_num_threads); |
654 | 0 | threads.min((p.width * p.height) / (p.speed.min_tile_size as usize).pow(2)) |
655 | | }; |
656 | 0 | let speed_settings = p.speed.speed_settings(); |
657 | 0 | let cfg = Config::new() |
658 | 0 | .with_encoder_config(EncoderConfig { |
659 | 0 | width: p.width, |
660 | 0 | height: p.height, |
661 | 0 | time_base: Rational::new(1, 1), |
662 | 0 | sample_aspect_ratio: Rational::new(1, 1), |
663 | 0 | bit_depth: p.bit_depth, |
664 | 0 | chroma_sampling: p.chroma_sampling, |
665 | 0 | chroma_sample_position: ChromaSamplePosition::Unknown, |
666 | 0 | pixel_range: p.pixel_range, |
667 | 0 | color_description: p.color_description, |
668 | 0 | mastering_display: None, |
669 | 0 | content_light: None, |
670 | 0 | enable_timing_info: false, |
671 | 0 | still_picture: true, |
672 | 0 | error_resilient: false, |
673 | 0 | switch_frame_interval: 0, |
674 | 0 | min_key_frame_interval: 0, |
675 | 0 | max_key_frame_interval: 0, |
676 | 0 | reservoir_frame_delay: None, |
677 | 0 | low_latency: false, |
678 | 0 | quantizer: p.quantizer, |
679 | 0 | min_quantizer: p.quantizer as _, |
680 | 0 | bitrate: 0, |
681 | 0 | tune: Tune::Psychovisual, |
682 | 0 | tile_cols: 0, |
683 | 0 | tile_rows: 0, |
684 | 0 | tiles, |
685 | 0 | film_grain_params: None, |
686 | 0 | level_idx: None, |
687 | 0 | speed_settings, |
688 | 0 | }); |
689 | | |
690 | 0 | if let Some(threads) = p.threads { |
691 | 0 | cfg.with_threads(threads) |
692 | | } else { |
693 | 0 | cfg |
694 | | } |
695 | 0 | } |
696 | | |
697 | 0 | fn init_frame_3<P: rav1e::Pixel + Default>( |
698 | 0 | width: usize, height: usize, planes: impl IntoIterator<Item = [P; 3]> + Send, frame: &mut Frame<P>, |
699 | 0 | ) -> Result<(), Error> { |
700 | 0 | let mut f = frame.planes.iter_mut(); |
701 | 0 | let mut planes = planes.into_iter(); |
702 | | |
703 | | // it doesn't seem to be necessary to fill padding area |
704 | 0 | let mut y = f.next().unwrap().mut_slice(Default::default()); |
705 | 0 | let mut u = f.next().unwrap().mut_slice(Default::default()); |
706 | 0 | let mut v = f.next().unwrap().mut_slice(Default::default()); |
707 | | |
708 | 0 | for ((y, u), v) in y.rows_iter_mut().zip(u.rows_iter_mut()).zip(v.rows_iter_mut()).take(height) { |
709 | 0 | let y = &mut y[..width]; |
710 | 0 | let u = &mut u[..width]; |
711 | 0 | let v = &mut v[..width]; |
712 | 0 | for ((y, u), v) in y.iter_mut().zip(u).zip(v) { |
713 | 0 | let px = planes.next().ok_or(Error::TooFewPixels)?; |
714 | 0 | *y = px[0]; |
715 | 0 | *u = px[1]; |
716 | 0 | *v = px[2]; |
717 | | } |
718 | | } |
719 | 0 | Ok(()) |
720 | 0 | } Unexecuted instantiation: ravif::av1encoder::init_frame_3::<u8, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#0}>>Unexecuted instantiation: ravif::av1encoder::init_frame_3::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#3}>>Unexecuted instantiation: ravif::av1encoder::init_frame_3::<u16, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#1}>>Unexecuted instantiation: ravif::av1encoder::init_frame_3::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#5}>>Unexecuted instantiation: ravif::av1encoder::init_frame_3::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#0}>>Unexecuted instantiation: ravif::av1encoder::init_frame_3::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#1}>> |
721 | | |
722 | 0 | fn init_frame_1<P: rav1e::Pixel + Default>(width: usize, height: usize, planes: impl IntoIterator<Item = P> + Send, frame: &mut Frame<P>) -> Result<(), Error> { |
723 | 0 | let mut y = frame.planes[0].mut_slice(Default::default()); |
724 | 0 | let mut planes = planes.into_iter(); |
725 | | |
726 | 0 | for y in y.rows_iter_mut().take(height) { |
727 | 0 | let y = &mut y[..width]; |
728 | 0 | for y in y.iter_mut() { |
729 | 0 | *y = planes.next().ok_or(Error::TooFewPixels)?; |
730 | | } |
731 | | } |
732 | 0 | Ok(()) |
733 | 0 | } Unexecuted instantiation: ravif::av1encoder::init_frame_1::<u8, [u8; 0]> Unexecuted instantiation: ravif::av1encoder::init_frame_1::<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#4}>>Unexecuted instantiation: ravif::av1encoder::init_frame_1::<u16, [u16; 0]> Unexecuted instantiation: ravif::av1encoder::init_frame_1::<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#6}>> |
734 | | |
735 | | #[inline(never)] |
736 | 0 | fn encode_to_av1<P: rav1e::Pixel>(p: &Av1EncodeConfig, init: impl FnOnce(&mut Frame<P>) -> Result<(), Error>) -> Result<Vec<u8>, Error> { |
737 | 0 | let mut ctx: Context<P> = rav1e_config(p).new_context()?; |
738 | 0 | let mut frame = ctx.new_frame(); |
739 | | |
740 | 0 | init(&mut frame)?; |
741 | 0 | ctx.send_frame(frame)?; |
742 | 0 | ctx.flush(); |
743 | | |
744 | 0 | let mut out = Vec::new(); |
745 | | loop { |
746 | 0 | match ctx.receive_packet() { |
747 | 0 | Ok(mut packet) => match packet.frame_type { |
748 | 0 | FrameType::KEY => { |
749 | 0 | out.append(&mut packet.data); |
750 | 0 | }, |
751 | 0 | _ => continue, |
752 | | }, |
753 | 0 | Err(EncoderStatus::Encoded | EncoderStatus::LimitReached) => break, |
754 | 0 | Err(err) => Err(err)?, |
755 | | } |
756 | | } |
757 | 0 | Ok(out) |
758 | 0 | } Unexecuted instantiation: ravif::av1encoder::encode_to_av1::<u8, <ravif::av1encoder::Encoder>::encode_raw_planes_internal<u8, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#0}>, [u8; 0]>::{closure#1}::{closure#0}>Unexecuted instantiation: ravif::av1encoder::encode_to_av1::<u8, <ravif::av1encoder::Encoder>::encode_raw_planes_internal<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#3}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#4}>>::{closure#1}::{closure#0}>Unexecuted instantiation: ravif::av1encoder::encode_to_av1::<u8, <ravif::av1encoder::Encoder>::encode_raw_planes_internal<u8, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#0}>, [u8; 0]>::{closure#2}::{closure#0}::{closure#0}>Unexecuted instantiation: ravif::av1encoder::encode_to_av1::<u8, <ravif::av1encoder::Encoder>::encode_raw_planes_internal<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#3}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#4}>>::{closure#2}::{closure#0}::{closure#0}>Unexecuted instantiation: ravif::av1encoder::encode_to_av1::<u16, <ravif::av1encoder::Encoder>::encode_raw_planes_internal<u16, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#1}>, [u16; 0]>::{closure#1}::{closure#0}>Unexecuted instantiation: ravif::av1encoder::encode_to_av1::<u16, <ravif::av1encoder::Encoder>::encode_raw_planes_internal<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#5}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#6}>>::{closure#1}::{closure#0}>Unexecuted instantiation: ravif::av1encoder::encode_to_av1::<u16, <ravif::av1encoder::Encoder>::encode_raw_planes_internal<u16, core::iter::adapters::map::Map<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#2}>>::{closure#1}>, [u16; 0]>::{closure#2}::{closure#0}::{closure#0}>Unexecuted instantiation: ravif::av1encoder::encode_to_av1::<u16, <ravif::av1encoder::Encoder>::encode_raw_planes_internal<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#5}>, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgba::Rgba<u8>>, <ravif::av1encoder::Encoder>::encode_rgba::{closure#6}>>::{closure#2}::{closure#0}::{closure#0}>Unexecuted instantiation: ravif::av1encoder::encode_to_av1::<u8, <ravif::av1encoder::Encoder>::encode_raw_planes_internal<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#0}>, [u8; 0]>::{closure#1}::{closure#0}>Unexecuted instantiation: ravif::av1encoder::encode_to_av1::<u8, <ravif::av1encoder::Encoder>::encode_raw_planes_internal<u8, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#0}>, [u8; 0]>::{closure#2}::{closure#0}::{closure#0}>Unexecuted instantiation: ravif::av1encoder::encode_to_av1::<u16, <ravif::av1encoder::Encoder>::encode_raw_planes_internal<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#1}>, [u16; 0]>::{closure#1}::{closure#0}>Unexecuted instantiation: ravif::av1encoder::encode_to_av1::<u16, <ravif::av1encoder::Encoder>::encode_raw_planes_internal<u16, core::iter::adapters::map::Map<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>, <ravif::av1encoder::Encoder>::encode_rgb_internal_from_8bit<imgref::iter::PixelsIter<rgb::formats::rgb::Rgb<u8>>>::{closure#1}>, [u16; 0]>::{closure#2}::{closure#0}::{closure#0}> |