1 // Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
2 // Copyright (c) 2017-2020, The rav1e contributors. All rights reserved
3 //
4 // This source code is subject to the terms of the BSD 2 Clause License and
5 // the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 // was not distributed with this source code in the LICENSE file, you can
7 // obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 // Media Patent License 1.0 was not distributed with this source code in the
9 // PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10
11 //! # C API for rav1e
12 //!
13 //! [rav1e](https://github.com/xiph/rav1e/) is an [AV1](https://aomediacodec.github.io/av1-spec/)
14 //! encoder written in [Rust](https://rust-lang.org)
15 //!
16 //! This is the C-compatible API
17 #![deny(missing_docs)]
18
19 use std::slice;
20 use std::sync::Arc;
21
22 use std::ffi::CStr;
23 use std::ffi::CString;
24 use std::os::raw::c_char;
25 use std::os::raw::c_int;
26 use std::os::raw::c_void;
27
28 use libc::ptrdiff_t;
29 use libc::size_t;
30
31 use num_derive::*;
32 use num_traits::cast::FromPrimitive;
33
34 use crate::prelude as rav1e;
35
36 type PixelRange = rav1e::PixelRange;
37 type ChromaSamplePosition = rav1e::ChromaSamplePosition;
38 type ChromaSampling = rav1e::ChromaSampling;
39 type MatrixCoefficients = rav1e::MatrixCoefficients;
40 type ColorPrimaries = rav1e::ColorPrimaries;
41 type TransferCharacteristics = rav1e::TransferCharacteristics;
42 type Rational = rav1e::Rational;
43 type FrameTypeOverride = rav1e::FrameTypeOverride;
44 type FrameOpaqueCb = Option<extern fn(*mut c_void)>;
45
46 #[derive(Clone)]
47 enum FrameInternal {
48 U8(Arc<rav1e::Frame<u8>>),
49 U16(Arc<rav1e::Frame<u16>>),
50 }
51
52 impl From<rav1e::Frame<u8>> for FrameInternal {
from(f: rav1e::Frame<u8>) -> FrameInternal53 fn from(f: rav1e::Frame<u8>) -> FrameInternal {
54 FrameInternal::U8(Arc::new(f))
55 }
56 }
57
58 impl From<rav1e::Frame<u16>> for FrameInternal {
from(f: rav1e::Frame<u16>) -> FrameInternal59 fn from(f: rav1e::Frame<u16>) -> FrameInternal {
60 FrameInternal::U16(Arc::new(f))
61 }
62 }
63
64 struct FrameOpaque {
65 opaque: *mut c_void,
66 cb: FrameOpaqueCb,
67 }
68
69 unsafe impl Send for FrameOpaque {}
70
71 impl Default for FrameOpaque {
default() -> Self72 fn default() -> Self {
73 FrameOpaque { opaque: std::ptr::null_mut(), cb: None }
74 }
75 }
76
77 impl Drop for FrameOpaque {
drop(&mut self)78 fn drop(&mut self) {
79 let FrameOpaque { opaque, cb } = self;
80 if let Some(cb) = cb {
81 cb(*opaque);
82 }
83 }
84 }
85
86 /// Raw video Frame
87 ///
88 /// It can be allocated through rav1e_frame_new(), populated using rav1e_frame_fill_plane()
89 /// and freed using rav1e_frame_unref().
90 pub struct Frame {
91 fi: FrameInternal,
92 frame_type: FrameTypeOverride,
93 opaque: Option<FrameOpaque>,
94 }
95
96 /// Status that can be returned by encoder functions.
97 #[repr(C)]
98 #[derive(Copy, Clone, Debug, FromPrimitive, PartialEq)]
99 pub enum EncoderStatus {
100 /// Normal operation.
101 Success = 0,
102 /// The encoder needs more data to produce an output packet.
103 ///
104 /// May be emitted by `rav1e_receive_packet` when frame reordering is
105 /// enabled.
106 NeedMoreData,
107 /// There are enough frames in the queue.
108 ///
109 /// May be emitted by `rav1e_send_frame` when trying to send a frame after
110 /// the encoder has been flushed or the internal queue is full.
111 EnoughData,
112 /// The encoder has already produced the number of frames requested.
113 ///
114 /// May be emitted by `rav1e_receive_packet` after a flush request had been
115 /// processed or the frame limit had been reached.
116 LimitReached,
117 /// A Frame had been encoded but not emitted yet.
118 Encoded,
119 /// Generic fatal error.
120 Failure = -1,
121 /// A frame was encoded in the first pass of a 2-pass encode, but its stats
122 /// data was not retrieved with `rav1e_twopass_out`, or not enough stats data
123 /// was provided in the second pass of a 2-pass encode to encode the next
124 /// frame.
125 NotReady = -2,
126 }
127
128 impl EncoderStatus {
to_c(&self) -> *const u8129 fn to_c(&self) -> *const u8 {
130 use self::EncoderStatus::*;
131 match self {
132 Success => "Normal operation\0".as_ptr(),
133 NeedMoreData => "The encoder needs more data to produce an output packet\0".as_ptr(),
134 EnoughData => "There are enough frames in the queue\0".as_ptr(),
135 LimitReached => "The encoder has already produced the number of frames requested\0".as_ptr(),
136 Encoded => "A Frame had been encoded but not emitted yet\0".as_ptr(),
137 Failure => "Generic fatal error\0".as_ptr(),
138 NotReady => "First-pass stats data not retrieved or not enough second-pass data provided\0".as_ptr(),
139 }
140 }
141 }
142
143 impl From<Option<rav1e::EncoderStatus>> for EncoderStatus {
from(status: Option<rav1e::EncoderStatus>) -> Self144 fn from(status: Option<rav1e::EncoderStatus>) -> Self {
145 match status {
146 None => EncoderStatus::Success,
147 Some(s) => match s {
148 rav1e::EncoderStatus::NeedMoreData => EncoderStatus::NeedMoreData,
149 rav1e::EncoderStatus::EnoughData => EncoderStatus::EnoughData,
150 rav1e::EncoderStatus::LimitReached => EncoderStatus::LimitReached,
151 rav1e::EncoderStatus::Encoded => EncoderStatus::Encoded,
152 rav1e::EncoderStatus::Failure => EncoderStatus::Failure,
153 rav1e::EncoderStatus::NotReady => EncoderStatus::NotReady,
154 },
155 }
156 }
157 }
158
159 /// Encoder configuration
160 ///
161 /// Instantiate it using rav1e_config_default() and fine-tune it using
162 /// rav1e_config_parse().
163 ///
164 /// Use rav1e_config_unref() to free its memory.
165 pub struct Config {
166 cfg: rav1e::Config,
167 }
168
169 enum EncContext {
170 U8(rav1e::Context<u8>),
171 U16(rav1e::Context<u16>),
172 }
173
174 impl EncContext {
new_frame(&self) -> FrameInternal175 fn new_frame(&self) -> FrameInternal {
176 match self {
177 EncContext::U8(ctx) => ctx.new_frame().into(),
178 EncContext::U16(ctx) => ctx.new_frame().into(),
179 }
180 }
send_frame( &mut self, frame: Option<FrameInternal>, frame_type: FrameTypeOverride, opaque: Option<Box<dyn std::any::Any + Send>>, ) -> Result<(), rav1e::EncoderStatus>181 fn send_frame(
182 &mut self, frame: Option<FrameInternal>, frame_type: FrameTypeOverride,
183 opaque: Option<Box<dyn std::any::Any + Send>>,
184 ) -> Result<(), rav1e::EncoderStatus> {
185 let info =
186 rav1e::FrameParameters { frame_type_override: frame_type, opaque };
187 if let Some(frame) = frame {
188 match (self, frame) {
189 (EncContext::U8(ctx), FrameInternal::U8(ref f)) => {
190 ctx.send_frame((f.clone(), info))
191 }
192 (EncContext::U16(ctx), FrameInternal::U16(ref f)) => {
193 ctx.send_frame((f.clone(), info))
194 }
195 _ => Err(rav1e::EncoderStatus::Failure),
196 }
197 } else {
198 match self {
199 EncContext::U8(ctx) => ctx.send_frame(None),
200 EncContext::U16(ctx) => ctx.send_frame(None),
201 }
202 }
203 }
204
receive_packet(&mut self) -> Result<Packet, rav1e::EncoderStatus>205 fn receive_packet(&mut self) -> Result<Packet, rav1e::EncoderStatus> {
206 fn receive_packet<T: rav1e::Pixel>(
207 ctx: &mut rav1e::Context<T>,
208 ) -> Result<Packet, rav1e::EncoderStatus> {
209 ctx.receive_packet().map(|p| {
210 let mut p = std::mem::ManuallyDrop::new(p);
211 let opaque = p.opaque.take().map_or_else(
212 || std::ptr::null_mut(),
213 |o| {
214 let mut opaque = o.downcast::<FrameOpaque>().unwrap();
215 opaque.cb = None;
216 opaque.opaque
217 },
218 );
219 let p = std::mem::ManuallyDrop::into_inner(p);
220 let rav1e::Packet { data, input_frameno, frame_type, .. } = p;
221 let len = data.len();
222 let data = Box::into_raw(data.into_boxed_slice()) as *const u8;
223 Packet { data, len, input_frameno, frame_type, opaque }
224 })
225 }
226 match self {
227 EncContext::U8(ctx) => receive_packet(ctx),
228 EncContext::U16(ctx) => receive_packet(ctx),
229 }
230 }
231
container_sequence_header(&self) -> Vec<u8>232 fn container_sequence_header(&self) -> Vec<u8> {
233 match self {
234 EncContext::U8(ctx) => ctx.container_sequence_header(),
235 EncContext::U16(ctx) => ctx.container_sequence_header(),
236 }
237 }
238
twopass_bytes_needed(&mut self) -> usize239 fn twopass_bytes_needed(&mut self) -> usize {
240 match self {
241 EncContext::U8(ctx) => ctx.twopass_bytes_needed(),
242 EncContext::U16(ctx) => ctx.twopass_bytes_needed(),
243 }
244 }
245
twopass_in(&mut self, buf: &[u8]) -> Result<usize, rav1e::EncoderStatus>246 fn twopass_in(&mut self, buf: &[u8]) -> Result<usize, rav1e::EncoderStatus> {
247 match self {
248 EncContext::U8(ctx) => ctx.twopass_in(buf),
249 EncContext::U16(ctx) => ctx.twopass_in(buf),
250 }
251 }
252
twopass_out(&mut self) -> Option<&[u8]>253 fn twopass_out(&mut self) -> Option<&[u8]> {
254 match self {
255 EncContext::U8(ctx) => ctx.twopass_out(),
256 EncContext::U16(ctx) => ctx.twopass_out(),
257 }
258 }
259
rc_summary_size(&self) -> usize260 fn rc_summary_size(&self) -> usize {
261 match self {
262 EncContext::U8(ctx) => ctx.rc_summary_size(),
263 EncContext::U16(ctx) => ctx.rc_summary_size(),
264 }
265 }
266
rc_receive_pass_data(&mut self) -> Option<rav1e::RcData>267 fn rc_receive_pass_data(&mut self) -> Option<rav1e::RcData> {
268 match self {
269 EncContext::U8(ctx) => ctx.rc_receive_pass_data(),
270 EncContext::U16(ctx) => ctx.rc_receive_pass_data(),
271 }
272 }
273
rc_second_pass_data_required(&self) -> usize274 fn rc_second_pass_data_required(&self) -> usize {
275 match self {
276 EncContext::U8(ctx) => ctx.rc_second_pass_data_required(),
277 EncContext::U16(ctx) => ctx.rc_second_pass_data_required(),
278 }
279 }
280
rc_send_pass_data( &mut self, data: &[u8], ) -> Result<(), rav1e::EncoderStatus>281 fn rc_send_pass_data(
282 &mut self, data: &[u8],
283 ) -> Result<(), rav1e::EncoderStatus> {
284 match self {
285 EncContext::U8(ctx) => ctx.rc_send_pass_data(data),
286 EncContext::U16(ctx) => ctx.rc_send_pass_data(data),
287 }
288 }
289 }
290
291 /// Encoder context
292 ///
293 /// Contains the encoding state, it is created by rav1e_context_new() using an
294 /// Encoder configuration.
295 ///
296 /// Use rav1e_context_unref() to free its memory.
297 pub struct Context {
298 ctx: EncContext,
299 last_err: Option<rav1e::EncoderStatus>,
300 }
301
302 type FrameType = rav1e::FrameType;
303
304 /// Encoded Packet
305 ///
306 /// The encoded packets are retrieved using rav1e_receive_packet().
307 ///
308 /// Use rav1e_packet_unref() to free its memory.
309 #[repr(C)]
310 pub struct Packet {
311 /// Encoded data buffer
312 pub data: *const u8,
313 /// Encoded data buffer size
314 pub len: size_t,
315 /// Frame sequence number
316 pub input_frameno: u64,
317 /// Frame type
318 pub frame_type: FrameType,
319 /// User provided opaque data
320 pub opaque: *mut c_void,
321 }
322
323 /// Version information as presented in `[package]` `version`.
324 ///
325 /// e.g. `0.1.0``
326 ///
327 /// Can be parsed by [semver](https://crates.io/crates/semver).
328 /// This returns the version of the loaded library, regardless
329 /// of which version the library user was built against.
330 #[no_mangle]
rav1e_version_short() -> *const c_char331 pub unsafe extern fn rav1e_version_short() -> *const c_char {
332 concat!(env!("CARGO_PKG_VERSION"), "\0").as_ptr() as *const c_char
333 }
334
335 /// Version information with the information
336 /// provided by `git describe --tags`.
337 ///
338 /// e.g. `0.1.0 (v0.1.0-1-g743d464)`
339 ///
340 /// This returns the version of the loaded library, regardless
341 /// of which version the library user was built against.
342 #[no_mangle]
rav1e_version_full() -> *const c_char343 pub unsafe extern fn rav1e_version_full() -> *const c_char {
344 concat!(
345 env!("CARGO_PKG_VERSION"),
346 " (",
347 env!("VERGEN_SEMVER_LIGHTWEIGHT"),
348 ")\0"
349 )
350 .as_ptr() as *const c_char
351 }
352
353 /// Simple Data
354 ///
355 ///
356 ///
357 /// Use rav1e_data_unref() to free its memory.
358 #[repr(C)]
359 pub struct Data {
360 /// Pointer to the data buffer
361 pub data: *const u8,
362 /// Data buffer size
363 pub len: size_t,
364 }
365
366 /// Free a RaData buffer
367 #[no_mangle]
rav1e_data_unref(data: *mut Data)368 pub unsafe extern fn rav1e_data_unref(data: *mut Data) {
369 if !data.is_null() {
370 let data = Box::from_raw(data);
371 let _ = Vec::from_raw_parts(
372 data.data as *mut u8,
373 data.len as usize,
374 data.len as usize,
375 );
376 }
377 }
378
379 /// Create a RaConfig filled with default parameters.
380 #[no_mangle]
rav1e_config_default() -> *mut Config381 pub unsafe extern fn rav1e_config_default() -> *mut Config {
382 let cfg = rav1e::Config::default();
383
384 let c = Box::new(Config { cfg });
385
386 Box::into_raw(c)
387 }
388
decode_slice<'a>( data: *mut *const u8, len: *mut size_t, ) -> (c_int, Option<&'a [u8]>)389 unsafe fn decode_slice<'a>(
390 data: *mut *const u8, len: *mut size_t,
391 ) -> (c_int, Option<&'a [u8]>) {
392 use std::convert::TryInto;
393
394 if *len < 8 {
395 return (8, None);
396 }
397
398 let buf = slice::from_raw_parts(*data, *len as usize);
399 let (len_bytes, rest) = buf.split_at(std::mem::size_of::<u64>());
400 let buf_len = u64::from_be_bytes(len_bytes.try_into().unwrap()) as usize;
401 let full_len = buf_len + 8;
402 if buf_len > rest.len() {
403 return (full_len as c_int, None);
404 }
405
406 *len -= full_len;
407 *data = (*data).offset(full_len.try_into().unwrap());
408
409 (0, Some(&rest[..buf_len]))
410 }
411
412 /// Setup a second pass rate control using the provided summary
413 ///
414 /// Passing NULL data resets the rate control settings.
415 ///
416 /// If additional data is required, pointer and len stay unchanged, otherwise
417 /// they are updated.
418 ///
419 /// Return:
420 /// 0 on success
421 /// > 0 if the buffer has to be larger
422 /// < 0 on failure
423 #[no_mangle]
rav1e_config_set_rc_summary( cfg: *mut Config, data: *mut *const u8, len: *mut size_t, ) -> c_int424 pub unsafe extern fn rav1e_config_set_rc_summary(
425 cfg: *mut Config, data: *mut *const u8, len: *mut size_t,
426 ) -> c_int {
427 if data.is_null() {
428 (*cfg).cfg.rate_control.summary = None;
429
430 return 0;
431 }
432
433 let (needed, maybe_buf) = decode_slice(data, len);
434
435 if maybe_buf.is_none() {
436 return needed;
437 }
438
439 let summary = rav1e::RateControlSummary::from_slice(maybe_buf.unwrap()).ok();
440 if summary.is_none() {
441 -1
442 } else {
443 (*cfg).cfg.rate_control.summary = summary;
444
445 0
446 }
447 }
448
449 /// Request to emit pass data
450 ///
451 /// Set emit to 0 to not emit pass data, non-zero to emit pass data.
452 ///
453 #[no_mangle]
rav1e_config_set_emit_data( cfg: *mut Config, emit: c_int, )454 pub unsafe extern fn rav1e_config_set_emit_data(
455 cfg: *mut Config, emit: c_int,
456 ) {
457 (*cfg).cfg.rate_control.emit_pass_data = emit != 0;
458 }
459
460 /// Set the display aspect ratio of the stream
461 ///
462 /// Needed for anamorphic video.
463 #[no_mangle]
rav1e_config_set_sample_aspect_ratio( cfg: *mut Config, sample_aspect_ratio: Rational, )464 pub unsafe extern fn rav1e_config_set_sample_aspect_ratio(
465 cfg: *mut Config, sample_aspect_ratio: Rational,
466 ) {
467 (*cfg).cfg.enc.sample_aspect_ratio = sample_aspect_ratio
468 }
469
470 /// Set the time base of the stream
471 ///
472 /// Needed for rate control.
473 #[no_mangle]
rav1e_config_set_time_base( cfg: *mut Config, time_base: Rational, )474 pub unsafe extern fn rav1e_config_set_time_base(
475 cfg: *mut Config, time_base: Rational,
476 ) {
477 (*cfg).cfg.enc.time_base = time_base
478 }
479
480 /// Set pixel format of the stream.
481 ///
482 /// Supported values for subsampling and chromapos are defined by the
483 /// enum types RaChromaSampling and RaChromaSamplePosition respectively.
484 /// Valid values for fullrange are 0 and 1.
485 ///
486 /// Returns a negative value on error or 0.
487 #[no_mangle]
rav1e_config_set_pixel_format( cfg: *mut Config, bit_depth: u8, subsampling: ChromaSampling, chroma_pos: ChromaSamplePosition, pixel_range: PixelRange, ) -> c_int488 pub unsafe extern fn rav1e_config_set_pixel_format(
489 cfg: *mut Config, bit_depth: u8, subsampling: ChromaSampling,
490 chroma_pos: ChromaSamplePosition, pixel_range: PixelRange,
491 ) -> c_int {
492 if bit_depth != 8 && bit_depth != 10 && bit_depth != 12 {
493 return -1;
494 }
495 (*cfg).cfg.enc.bit_depth = bit_depth as usize;
496
497 let subsampling_val =
498 std::mem::transmute::<ChromaSampling, i32>(subsampling);
499 if ChromaSampling::from_i32(subsampling_val).is_none() {
500 return -1;
501 }
502 (*cfg).cfg.enc.chroma_sampling = subsampling;
503
504 let chroma_pos_val =
505 std::mem::transmute::<ChromaSamplePosition, i32>(chroma_pos);
506 if ChromaSamplePosition::from_i32(chroma_pos_val).is_none() {
507 return -1;
508 }
509 (*cfg).cfg.enc.chroma_sample_position = chroma_pos;
510
511 let pixel_range_val = std::mem::transmute::<PixelRange, i32>(pixel_range);
512 if PixelRange::from_i32(pixel_range_val).is_none() {
513 return -1;
514 }
515 (*cfg).cfg.enc.pixel_range = pixel_range;
516
517 0
518 }
519
520 /// Set color properties of the stream.
521 ///
522 /// Supported values are defined by the enum types
523 /// RaMatrixCoefficients, RaColorPrimaries, and RaTransferCharacteristics
524 /// respectively.
525 ///
526 /// Return a negative value on error or 0.
527 #[no_mangle]
rav1e_config_set_color_description( cfg: *mut Config, matrix: MatrixCoefficients, primaries: ColorPrimaries, transfer: TransferCharacteristics, ) -> c_int528 pub unsafe extern fn rav1e_config_set_color_description(
529 cfg: *mut Config, matrix: MatrixCoefficients, primaries: ColorPrimaries,
530 transfer: TransferCharacteristics,
531 ) -> c_int {
532 (*cfg).cfg.enc.color_description = Some(rav1e::ColorDescription {
533 matrix_coefficients: matrix,
534 color_primaries: primaries,
535 transfer_characteristics: transfer,
536 });
537
538 if (*cfg).cfg.enc.color_description.is_some() {
539 0
540 } else {
541 -1
542 }
543 }
544
545 /// Set the content light level information for HDR10 streams.
546 ///
547 /// Return a negative value on error or 0.
548 #[no_mangle]
rav1e_config_set_content_light( cfg: *mut Config, max_content_light_level: u16, max_frame_average_light_level: u16, ) -> c_int549 pub unsafe extern fn rav1e_config_set_content_light(
550 cfg: *mut Config, max_content_light_level: u16,
551 max_frame_average_light_level: u16,
552 ) -> c_int {
553 (*cfg).cfg.enc.content_light = Some(rav1e::ContentLight {
554 max_content_light_level,
555 max_frame_average_light_level,
556 });
557
558 if (*cfg).cfg.enc.content_light.is_some() {
559 0
560 } else {
561 -1
562 }
563 }
564
565 /// Set the mastering display information for HDR10 streams.
566 ///
567 /// primaries and white_point arguments are RaChromaticityPoint, containing 0.16 fixed point
568 /// values.
569 /// max_luminance is a 24.8 fixed point value.
570 /// min_luminance is a 18.14 fixed point value.
571 ///
572 /// Returns a negative value on error or 0.
573 /// cbindgen:ptrs-as-arrays=[[primaries;3]]
574 #[no_mangle]
rav1e_config_set_mastering_display( cfg: *mut Config, primaries: *const rav1e::ChromaticityPoint, white_point: rav1e::ChromaticityPoint, max_luminance: u32, min_luminance: u32, ) -> c_int575 pub unsafe extern fn rav1e_config_set_mastering_display(
576 cfg: *mut Config, primaries: *const rav1e::ChromaticityPoint,
577 white_point: rav1e::ChromaticityPoint, max_luminance: u32,
578 min_luminance: u32,
579 ) -> c_int {
580 let primaries = *(primaries as *const [rav1e::ChromaticityPoint; 3]);
581
582 (*cfg).cfg.enc.mastering_display = Some(rav1e::MasteringDisplay {
583 primaries,
584 white_point,
585 max_luminance,
586 min_luminance,
587 });
588
589 if (*cfg).cfg.enc.mastering_display.is_some() {
590 0
591 } else {
592 -1
593 }
594 }
595
596 /// Free the RaConfig.
597 #[no_mangle]
rav1e_config_unref(cfg: *mut Config)598 pub unsafe extern fn rav1e_config_unref(cfg: *mut Config) {
599 if !cfg.is_null() {
600 let _ = Box::from_raw(cfg);
601 }
602 }
603
tile_log2(blk_size: usize, target: usize) -> usize604 fn tile_log2(blk_size: usize, target: usize) -> usize {
605 let mut k = 0;
606 while (blk_size << k) < target {
607 k += 1;
608 }
609 k
610 }
611
check_tile_log2(n: Result<usize, ()>) -> Result<usize, ()>612 fn check_tile_log2(n: Result<usize, ()>) -> Result<usize, ()> {
613 match n {
614 Ok(n) => {
615 if ((1 << tile_log2(1, n)) - n) == 0 || n == 0 {
616 Ok(n)
617 } else {
618 Err(())
619 }
620 }
621 Err(e) => Err(e),
622 }
623 }
624
check_frame_size(n: Result<usize, ()>) -> Result<usize, ()>625 fn check_frame_size(n: Result<usize, ()>) -> Result<usize, ()> {
626 match n {
627 Ok(n) => {
628 if n >= 16 && n < u16::max_value().into() {
629 Ok(n)
630 } else {
631 Err(())
632 }
633 }
634 Err(e) => Err(e),
635 }
636 }
637
option_match( cfg: *mut Config, key: *const c_char, value: *const c_char, ) -> Result<(), ()>638 unsafe fn option_match(
639 cfg: *mut Config, key: *const c_char, value: *const c_char,
640 ) -> Result<(), ()> {
641 let key = CStr::from_ptr(key).to_str().map_err(|_| ())?;
642 let value = CStr::from_ptr(value).to_str().map_err(|_| ())?;
643 let enc = &mut (*cfg).cfg.enc;
644
645 match key {
646 "width" => enc.width = check_frame_size(value.parse().map_err(|_| ()))?,
647 "height" => enc.height = check_frame_size(value.parse().map_err(|_| ()))?,
648 "speed" => {
649 enc.speed_settings =
650 rav1e::SpeedSettings::from_preset(value.parse().map_err(|_| ())?)
651 }
652
653 "threads" => (*cfg).cfg.threads = value.parse().map_err(|_| ())?,
654
655 "tiles" => enc.tiles = value.parse().map_err(|_| ())?,
656 "tile_rows" => {
657 enc.tile_rows = check_tile_log2(value.parse().map_err(|_| ()))?
658 }
659 "tile_cols" => {
660 enc.tile_cols = check_tile_log2(value.parse().map_err(|_| ()))?
661 }
662
663 "tune" => enc.tune = value.parse().map_err(|_| ())?,
664 "quantizer" => enc.quantizer = value.parse().map_err(|_| ())?,
665 "min_quantizer" => enc.min_quantizer = value.parse().map_err(|_| ())?,
666 "bitrate" => enc.bitrate = value.parse().map_err(|_| ())?,
667
668 "key_frame_interval" => {
669 enc.set_key_frame_interval(
670 enc.min_key_frame_interval,
671 value.parse().map_err(|_| ())?,
672 );
673 }
674 "min_key_frame_interval" => {
675 enc.set_key_frame_interval(
676 value.parse().map_err(|_| ())?,
677 enc.max_key_frame_interval,
678 );
679 }
680 "switch_frame_interval" => {
681 enc.switch_frame_interval = value.parse().map_err(|_| ())?
682 }
683 "reservoir_frame_delay" => {
684 enc.reservoir_frame_delay = Some(value.parse().map_err(|_| ())?)
685 }
686 "rdo_lookahead_frames" => {
687 enc.rdo_lookahead_frames = value.parse().map_err(|_| ())?
688 }
689 "low_latency" => enc.low_latency = value.parse().map_err(|_| ())?,
690 "enable_timing_info" => {
691 enc.enable_timing_info = value.parse().map_err(|_| ())?
692 }
693 "still_picture" => enc.still_picture = value.parse().map_err(|_| ())?,
694
695 _ => return Err(()),
696 }
697
698 Ok(())
699 }
700
701 /// Set a configuration parameter using its key and value as string.
702 ///
703 /// Available keys and values
704 /// - "width": width of the frame, default 640
705 /// - "height": height of the frame, default 480
706 /// - "speed": 0-10, default 6
707 /// - "threads": maximum number of threads to be used
708 /// - "tune": "psnr"-"psychovisual", default "psychovisual"
709 /// - "quantizer": 0-255, default 100
710 /// - "tiles": total number of tiles desired (0 denotes auto), default 0
711 /// - "tile_rows": number of tiles horizontally (must be a power of two, overridden by tiles if present), default 0
712 /// - "tile_cols": number of tiles vertically (must be a power of two, overridden by tiles if present), default 0
713 /// - "min_quantizer": minimum allowed base quantizer to use in bitrate mode, default 0
714 /// - "bitrate": target bitrate for the bitrate mode (required for two pass mode), default 0
715 /// - "key_frame_interval": maximum interval between two keyframes, default 240
716 /// - "min_key_frame_interval": minimum interval between two keyframes, default 12
717 /// - "switch_frame_interval": interval between switch frames, default 0
718 /// - "reservoir_frame_delay": number of temporal units over which to distribute the reservoir usage, default None
719 /// - "rdo_lookahead_frames": number of frames to read ahead for the RDO lookahead computation, default 40
720 /// - "low_latency": flag to enable low latency mode, default false
721 /// - "enable_timing_info": flag to enable signaling timing info in the bitstream, default false
722 /// - "still_picture": flag for still picture mode, default false
723 ///
724 /// Return a negative value on error or 0.
725 #[no_mangle]
rav1e_config_parse( cfg: *mut Config, key: *const c_char, value: *const c_char, ) -> c_int726 pub unsafe extern fn rav1e_config_parse(
727 cfg: *mut Config, key: *const c_char, value: *const c_char,
728 ) -> c_int {
729 if option_match(cfg, key, value) == Ok(()) {
730 0
731 } else {
732 -1
733 }
734 }
735
736 /// Set a configuration parameter using its key and value as integer.
737 ///
738 /// Available keys and values are the same as rav1e_config_parse()
739 ///
740 /// Return a negative value on error or 0.
741 #[no_mangle]
rav1e_config_parse_int( cfg: *mut Config, key: *const c_char, value: c_int, ) -> c_int742 pub unsafe extern fn rav1e_config_parse_int(
743 cfg: *mut Config, key: *const c_char, value: c_int,
744 ) -> c_int {
745 let val = CString::new(value.to_string()).unwrap();
746 if option_match(cfg, key, val.as_ptr()) == Ok(()) {
747 0
748 } else {
749 -1
750 }
751 }
752
753 /// Generate a new encoding context from a populated encoder configuration
754 ///
755 /// Multiple contexts can be generated through it.
756 /// Returns Null if context creation failed, e.g. by passing
757 /// an invalid Config.
758 #[no_mangle]
rav1e_context_new(cfg: *const Config) -> *mut Context759 pub unsafe extern fn rav1e_context_new(cfg: *const Config) -> *mut Context {
760 let cfg = &(*cfg).cfg;
761 let enc = &cfg.enc;
762
763 let ctx = match enc.bit_depth {
764 8 => cfg.new_context().map(EncContext::U8),
765 _ => cfg.new_context().map(EncContext::U16),
766 };
767
768 if let Ok(ctx) = ctx {
769 Box::into_raw(Box::new(Context { ctx, last_err: None }))
770 } else {
771 std::ptr::null_mut()
772 }
773 }
774
775 /// Free the RaContext.
776 #[no_mangle]
rav1e_context_unref(ctx: *mut Context)777 pub unsafe extern fn rav1e_context_unref(ctx: *mut Context) {
778 if !ctx.is_null() {
779 let _ = Box::from_raw(ctx);
780 }
781 }
782
783 /// Produce a new frame from the encoding context
784 ///
785 /// It must be populated using rav1e_frame_fill_plane().
786 ///
787 /// The frame is reference counted and must be released passing it to rav1e_frame_unref(),
788 /// see rav1e_send_frame().
789 #[no_mangle]
rav1e_frame_new(ctx: *const Context) -> *mut Frame790 pub unsafe extern fn rav1e_frame_new(ctx: *const Context) -> *mut Frame {
791 let fi = (*ctx).ctx.new_frame();
792 let frame_type = rav1e::FrameTypeOverride::No;
793 let f = Frame { fi, frame_type, opaque: None };
794 let frame = Box::new(f.into());
795
796 Box::into_raw(frame)
797 }
798
799 /// Free the RaFrame.
800 #[no_mangle]
rav1e_frame_unref(frame: *mut Frame)801 pub unsafe extern fn rav1e_frame_unref(frame: *mut Frame) {
802 if !frame.is_null() {
803 let _ = Box::from_raw(frame);
804 }
805 }
806
807 /// Overrides the encoders frame type decision for a frame
808 ///
809 /// Must be called before rav1e_send_frame() if used.
810 #[no_mangle]
rav1e_frame_set_type( frame: *mut Frame, frame_type: FrameTypeOverride, ) -> c_int811 pub unsafe extern fn rav1e_frame_set_type(
812 frame: *mut Frame, frame_type: FrameTypeOverride,
813 ) -> c_int {
814 let frame_type_val =
815 std::mem::transmute::<FrameTypeOverride, i32>(frame_type);
816 if FrameTypeOverride::from_i32(frame_type_val).is_none() {
817 return -1;
818 }
819 (*frame).frame_type = frame_type;
820
821 0
822 }
823
824 /// Register an opaque data and a destructor to the frame
825 ///
826 /// It takes the ownership of its memory:
827 /// - it will relinquish the ownership to the context if
828 /// rav1e_send_frame is called.
829 /// - it will call the destructor if rav1e_frame_unref is called
830 /// otherwise.
831 #[no_mangle]
rav1e_frame_set_opaque( frame: *mut Frame, opaque: *mut c_void, cb: FrameOpaqueCb, )832 pub unsafe extern fn rav1e_frame_set_opaque(
833 frame: *mut Frame, opaque: *mut c_void, cb: FrameOpaqueCb,
834 ) {
835 if opaque.is_null() {
836 (*frame).opaque = None;
837 } else {
838 (*frame).opaque = Some(FrameOpaque { opaque, cb });
839 }
840 }
841
842 /// Retrieve the first-pass data of a two-pass encode for the frame that was
843 /// just encoded. This should be called BEFORE every call to rav1e_receive_packet()
844 /// (including the very first one), even if no packet was produced by the
845 /// last call to rav1e_receive_packet, if any (i.e., RA_ENCODER_STATUS_ENCODED
846 /// was returned). It needs to be called once more after
847 /// RA_ENCODER_STATUS_LIMIT_REACHED is returned, to retrieve the header that
848 /// should be written to the front of the stats file (overwriting the
849 /// placeholder header that was emitted at the start of encoding).
850 ///
851 /// It is still safe to call this function when rav1e_receive_packet() returns any
852 /// other error. It will return NULL instead of returning a duplicate copy
853 /// of the previous frame's data.
854 ///
855 /// Must be freed with rav1e_data_unref().
856 #[no_mangle]
rav1e_twopass_out(ctx: *mut Context) -> *mut Data857 pub unsafe extern fn rav1e_twopass_out(ctx: *mut Context) -> *mut Data {
858 let buf = (*ctx).ctx.twopass_out();
859
860 if buf.is_none() {
861 return std::ptr::null_mut();
862 }
863
864 let v = buf.unwrap().to_vec();
865 Box::into_raw(Box::new(Data {
866 len: v.len(),
867 data: Box::into_raw(v.into_boxed_slice()) as *mut u8,
868 }))
869 }
870
871 /// Rate Control Data
872 #[derive(Debug, PartialEq)]
873 #[repr(C)]
874 pub enum RcDataKind {
875 /// A Rate Control Summary Packet
876 ///
877 /// It is emitted once, after the encoder is flushed.
878 ///
879 /// It contains a summary of the rate control information for the
880 /// encoding process that just terminated.
881 Summary,
882 /// A Rate Control Frame-specific Packet
883 ///
884 /// It is emitted every time a frame is processed.
885 ///
886 /// The information contained is required to encode its matching
887 /// frame in a second pass encoding.
888 Frame,
889 /// There is no pass data available for now
890 ///
891 /// This is emitted if rav1e_rc_receive_pass_data is called more
892 /// often than it should.
893 Empty,
894 }
895
896 /// Return the Rate Control Summary Packet size
897 ///
898 /// It is useful mainly to preserve space when saving
899 /// both Rate Control Summary and Frame Packets in a single file
900 #[no_mangle]
rav1e_rc_summary_size(ctx: *const Context) -> size_t901 pub unsafe extern fn rav1e_rc_summary_size(ctx: *const Context) -> size_t {
902 (*ctx).ctx.rc_summary_size() as size_t + 8
903 }
904
905 /// Return the first pass data
906 ///
907 /// Call it after rav1e_receive_packet() returns a normal condition status:
908 /// EncoderStatus::Encoded,
909 /// EncoderStatus::Success,
910 /// EncoderStatus::LimitReached.
911 ///
912 /// use rav1e_data_unref() to free the data.
913 ///
914 /// It will return a `RcDataKind::Summary` once the encoder is flushed.
915 #[no_mangle]
rav1e_rc_receive_pass_data( ctx: *mut Context, data: *mut *mut Data, ) -> RcDataKind916 pub unsafe extern fn rav1e_rc_receive_pass_data(
917 ctx: *mut Context, data: *mut *mut Data,
918 ) -> RcDataKind {
919 use crate::api::RcData::*;
920 let (buf, kind) = match (*ctx).ctx.rc_receive_pass_data() {
921 Some(Summary(data)) => (data, RcDataKind::Summary),
922 Some(Frame(data)) => (data, RcDataKind::Frame),
923 None => return RcDataKind::Empty,
924 };
925
926 let mut full_buf = Vec::with_capacity(buf.len() + 8);
927
928 full_buf.extend_from_slice(&(buf.len() as u64).to_be_bytes());
929 full_buf.extend_from_slice(&buf);
930
931 let full_buf = full_buf.into_boxed_slice();
932
933 *data = Box::into_raw(Box::new(Data {
934 len: full_buf.len(),
935 data: Box::into_raw(full_buf) as *mut u8,
936 }));
937
938 kind
939 }
940
941 /// Number of pass data packets required to progress the encoding process.
942 ///
943 /// At least that number of packets must be passed before the encoder can
944 /// progress.
945 ///
946 /// Stop feeding-in pass data packets once the function returns 0.
947 ///
948 /// ``` c
949 /// while (rav1e_rc_second_pass_data_required(ctx) > 0) {
950 /// int more = rav1e_rc_send_pass_data(ctx, &data, &len);
951 /// if (more > 0) {
952 /// refill(&data, &len);
953 /// } else if (more < 0) {
954 /// goto fail;
955 /// }
956 /// }
957 /// ```
958 ///
959 #[no_mangle]
rav1e_rc_second_pass_data_required( ctx: *const Context, ) -> i32960 pub unsafe extern fn rav1e_rc_second_pass_data_required(
961 ctx: *const Context,
962 ) -> i32 {
963 (*ctx).ctx.rc_second_pass_data_required() as i32
964 }
965
966 /// Feed the first pass Rate Control data to the encoder,
967 /// Frame-specific Packets only.
968 ///
969 /// Call it before receive_packet()
970 ///
971 /// If additional data is required, pointer and len stay unchanged, otherwise
972 /// they are updated.
973 ///
974 /// Returns:
975 /// - `0` on success,
976 /// - `> 0` the amount of bytes needed
977 /// - `< 0` on unrecoverable failure
978 #[no_mangle]
rav1e_rc_send_pass_data( ctx: *mut Context, data: *mut *const u8, len: *mut size_t, ) -> c_int979 pub unsafe extern fn rav1e_rc_send_pass_data(
980 ctx: *mut Context, data: *mut *const u8, len: *mut size_t,
981 ) -> c_int {
982 let (need, maybe_buf) = decode_slice(data, len);
983
984 if maybe_buf.is_none() {
985 return need;
986 }
987
988 let ret = (*ctx)
989 .ctx
990 .rc_send_pass_data(maybe_buf.unwrap())
991 .map(|_v| None)
992 .unwrap_or_else(|e| Some(e));
993
994 (*ctx).last_err = ret;
995
996 if ret.is_some() {
997 -1
998 } else {
999 0
1000 }
1001 }
1002
1003 /// Ask how many bytes of the stats file are needed before the next frame
1004 /// of the second pass in a two-pass encode can be encoded. This is a lower
1005 /// bound (more might be required), but if 0 is returned, then encoding can
1006 /// proceed. This is just a hint to the application, and does not need to
1007 /// be called for encoding the second pass to work, so long as the
1008 /// application continues to provide more data to rav1e_twopass_in() in a loop
1009 /// until rav1e_twopass_in() returns 0.
1010 #[no_mangle]
rav1e_twopass_bytes_needed(ctx: *mut Context) -> size_t1011 pub unsafe extern fn rav1e_twopass_bytes_needed(ctx: *mut Context) -> size_t {
1012 (*ctx).ctx.twopass_bytes_needed() as size_t
1013 }
1014
1015 /// Provide stats data produced in the first pass of a two-pass encode to the
1016 /// second pass. On success this returns the number of bytes of that data
1017 /// which were consumed. When encoding the second pass of a two-pass encode,
1018 /// this should be called repeatedly in a loop before every call to
1019 /// rav1e_receive_packet() (including the very first one) until no bytes are
1020 /// consumed, or until twopass_bytes_needed() returns 0. Returns -1 on failure.
1021 #[no_mangle]
rav1e_twopass_in( ctx: *mut Context, buf: *mut u8, buf_size: size_t, ) -> c_int1022 pub unsafe extern fn rav1e_twopass_in(
1023 ctx: *mut Context, buf: *mut u8, buf_size: size_t,
1024 ) -> c_int {
1025 let buf_slice = slice::from_raw_parts(buf, buf_size as usize);
1026 let r = (*ctx).ctx.twopass_in(buf_slice);
1027 match r {
1028 Ok(v) => v as c_int,
1029 Err(v) => {
1030 (*ctx).last_err = Some(v);
1031 -1
1032 }
1033 }
1034 }
1035
1036 /// Send the frame for encoding
1037 ///
1038 /// The function increases the frame internal reference count and it can be passed multiple
1039 /// times to different rav1e_send_frame() with a caveat:
1040 ///
1041 /// The opaque data, if present, will be moved from the Frame to the context
1042 /// and returned by rav1e_receive_packet in the Packet opaque field or
1043 /// the destructor will be called on rav1e_context_unref if the frame is
1044 /// still pending in the encoder.
1045 ///
1046 /// Returns:
1047 /// - `0` on success,
1048 /// - `> 0` if the input queue is full
1049 /// - `< 0` on unrecoverable failure
1050 #[no_mangle]
rav1e_send_frame( ctx: *mut Context, frame: *mut Frame, ) -> EncoderStatus1051 pub unsafe extern fn rav1e_send_frame(
1052 ctx: *mut Context, frame: *mut Frame,
1053 ) -> EncoderStatus {
1054 let frame_internal =
1055 if frame.is_null() { None } else { Some((*frame).fi.clone()) };
1056 let frame_type = if frame.is_null() {
1057 rav1e::FrameTypeOverride::No
1058 } else {
1059 (*frame).frame_type
1060 };
1061
1062 let maybe_opaque = if frame.is_null() {
1063 None
1064 } else {
1065 (*frame)
1066 .opaque
1067 .take()
1068 .map(|o| Box::new(o) as Box<dyn std::any::Any + Send>)
1069 };
1070
1071 let ret = (*ctx)
1072 .ctx
1073 .send_frame(frame_internal, frame_type, maybe_opaque)
1074 .map(|_v| None)
1075 .unwrap_or_else(|e| Some(e));
1076
1077 (*ctx).last_err = ret;
1078
1079 ret.into()
1080 }
1081
1082 /// Return the last encoder status
1083 #[no_mangle]
rav1e_last_status(ctx: *const Context) -> EncoderStatus1084 pub unsafe extern fn rav1e_last_status(ctx: *const Context) -> EncoderStatus {
1085 (*ctx).last_err.into()
1086 }
1087
1088 /// Return a static string matching the EncoderStatus variant.
1089 ///
1090 #[no_mangle]
rav1e_status_to_str( status: EncoderStatus, ) -> *const c_char1091 pub unsafe extern fn rav1e_status_to_str(
1092 status: EncoderStatus,
1093 ) -> *const c_char {
1094 if EncoderStatus::from_i32(std::mem::transmute(status)).is_none() {
1095 return std::ptr::null();
1096 }
1097
1098 status.to_c() as *const c_char
1099 }
1100
1101 /// Receive encoded data
1102 ///
1103 /// Returns:
1104 /// - `0` on success
1105 /// - `> 0` if additional frame data is required
1106 /// - `< 0` on unrecoverable failure
1107 #[no_mangle]
rav1e_receive_packet( ctx: *mut Context, pkt: *mut *mut Packet, ) -> EncoderStatus1108 pub unsafe extern fn rav1e_receive_packet(
1109 ctx: *mut Context, pkt: *mut *mut Packet,
1110 ) -> EncoderStatus {
1111 let ret = (*ctx)
1112 .ctx
1113 .receive_packet()
1114 .map(|packet| {
1115 *pkt = Box::into_raw(Box::new(packet));
1116 None
1117 })
1118 .unwrap_or_else(|e| Some(e));
1119
1120 (*ctx).last_err = ret;
1121
1122 ret.into()
1123 }
1124
1125 /// Free the RaPacket.
1126 #[no_mangle]
rav1e_packet_unref(pkt: *mut Packet)1127 pub unsafe extern fn rav1e_packet_unref(pkt: *mut Packet) {
1128 if !pkt.is_null() {
1129 let pkt = Box::from_raw(pkt);
1130 let _ = Vec::from_raw_parts(
1131 pkt.data as *mut u8,
1132 pkt.len as usize,
1133 pkt.len as usize,
1134 );
1135 }
1136 }
1137
1138 /// Produce a sequence header matching the current encoding context
1139 ///
1140 /// Its format is compatible with the AV1 Matroska and ISOBMFF specification.
1141 ///
1142 /// Use rav1e_data_unref() to free it.
1143 #[no_mangle]
rav1e_container_sequence_header( ctx: *const Context, ) -> *mut Data1144 pub unsafe extern fn rav1e_container_sequence_header(
1145 ctx: *const Context,
1146 ) -> *mut Data {
1147 let buf = (*ctx).ctx.container_sequence_header();
1148
1149 Box::into_raw(Box::new(Data {
1150 len: buf.len(),
1151 data: Box::into_raw(buf.into_boxed_slice()) as *mut u8,
1152 }))
1153 }
1154
rav1e_frame_fill_plane_internal<T: rav1e::Pixel>( f: &mut Arc<rav1e::Frame<T>>, plane: c_int, data_slice: &[u8], stride: ptrdiff_t, bytewidth: c_int, )1155 fn rav1e_frame_fill_plane_internal<T: rav1e::Pixel>(
1156 f: &mut Arc<rav1e::Frame<T>>, plane: c_int, data_slice: &[u8],
1157 stride: ptrdiff_t, bytewidth: c_int,
1158 ) {
1159 let input = Arc::make_mut(f);
1160 input.planes[plane as usize].copy_from_raw_u8(
1161 data_slice,
1162 stride as usize,
1163 bytewidth as usize,
1164 );
1165 }
1166
1167 /// Fill a frame plane
1168 ///
1169 /// Currently the frame contains 3 planes, the first is luminance followed by
1170 /// chrominance.
1171 ///
1172 /// The data is copied and this function has to be called for each plane.
1173 ///
1174 /// frame: A frame provided by rav1e_frame_new()
1175 /// plane: The index of the plane starting from 0
1176 /// data: The data to be copied
1177 /// data_len: Length of the buffer
1178 /// stride: Plane line in bytes, including padding
1179 /// bytewidth: Number of bytes per component, either 1 or 2
1180 #[no_mangle]
rav1e_frame_fill_plane( frame: *mut Frame, plane: c_int, data: *const u8, data_len: size_t, stride: ptrdiff_t, bytewidth: c_int, )1181 pub unsafe extern fn rav1e_frame_fill_plane(
1182 frame: *mut Frame, plane: c_int, data: *const u8, data_len: size_t,
1183 stride: ptrdiff_t, bytewidth: c_int,
1184 ) {
1185 let data_slice = slice::from_raw_parts(data, data_len as usize);
1186
1187 match (*frame).fi {
1188 FrameInternal::U8(ref mut f) => {
1189 rav1e_frame_fill_plane_internal(f, plane, data_slice, stride, bytewidth)
1190 }
1191 FrameInternal::U16(ref mut f) => {
1192 rav1e_frame_fill_plane_internal(f, plane, data_slice, stride, bytewidth)
1193 }
1194 }
1195 }
1196
1197 #[cfg(test)]
1198 mod test {
1199 use super::*;
1200
1201 use std::ffi::CString;
1202
1203 #[test]
forward_opaque()1204 fn forward_opaque() {
1205 unsafe {
1206 let rac = rav1e_config_default();
1207 let w = CString::new("width").unwrap();
1208 rav1e_config_parse_int(rac, w.as_ptr(), 64);
1209 let h = CString::new("height").unwrap();
1210 rav1e_config_parse_int(rac, h.as_ptr(), 64);
1211 let s = CString::new("speed").unwrap();
1212 rav1e_config_parse_int(rac, s.as_ptr(), 10);
1213
1214 let rax = rav1e_context_new(rac);
1215
1216 let f = rav1e_frame_new(rax);
1217
1218 for i in 0..30 {
1219 let v = Box::new(i as u8);
1220 extern fn cb(o: *mut c_void) {
1221 let v = unsafe { Box::from_raw(o as *mut u8) };
1222 eprintln!("Would free {}", v);
1223 }
1224 rav1e_frame_set_opaque(f, Box::into_raw(v) as *mut c_void, Some(cb));
1225 rav1e_send_frame(rax, f);
1226 }
1227
1228 rav1e_send_frame(rax, std::ptr::null_mut());
1229
1230 for _ in 0..15 {
1231 let mut p: *mut Packet = std::ptr::null_mut();
1232 let ret = rav1e_receive_packet(rax, &mut p);
1233
1234 if ret == EncoderStatus::Success {
1235 let v = Box::from_raw((*p).opaque as *mut u8);
1236 eprintln!("Opaque {}", v);
1237 }
1238
1239 if ret == EncoderStatus::LimitReached {
1240 break;
1241 }
1242 }
1243
1244 let v = Box::new(42u64);
1245 extern fn cb(o: *mut c_void) {
1246 let v = unsafe { Box::from_raw(o as *mut u64) };
1247 eprintln!("Would free {}", v);
1248 }
1249 rav1e_frame_set_opaque(f, Box::into_raw(v) as *mut c_void, Some(cb));
1250
1251 // 42 would be freed after this
1252 rav1e_frame_unref(f);
1253 // 15 - reorder delay .. 29 would be freed after this
1254 rav1e_context_unref(rax);
1255 rav1e_config_unref(rac);
1256 }
1257 }
1258
1259 #[test]
two_pass_encoding()1260 fn two_pass_encoding() {
1261 unsafe {
1262 let rac = rav1e_config_default();
1263 let w = CString::new("width").unwrap();
1264 rav1e_config_parse_int(rac, w.as_ptr(), 64);
1265 let h = CString::new("height").unwrap();
1266 rav1e_config_parse_int(rac, h.as_ptr(), 64);
1267 let s = CString::new("speed").unwrap();
1268 rav1e_config_parse_int(rac, s.as_ptr(), 10);
1269 let s = CString::new("bitrate").unwrap();
1270 rav1e_config_parse_int(rac, s.as_ptr(), 1000);
1271 rav1e_config_set_emit_data(rac, 1);
1272
1273 let rax = rav1e_context_new(rac);
1274 let f = rav1e_frame_new(rax);
1275
1276 for _ in 0..10 {
1277 rav1e_send_frame(rax, f);
1278 }
1279
1280 rav1e_send_frame(rax, std::ptr::null_mut());
1281
1282 let mut frame_data = std::collections::VecDeque::new();
1283 let mut summary: *mut Data = std::ptr::null_mut();
1284
1285 loop {
1286 let mut p: *mut Packet = std::ptr::null_mut();
1287 let ret = rav1e_receive_packet(rax, &mut p);
1288 rav1e_packet_unref(p);
1289 if ret == EncoderStatus::LimitReached {
1290 let kind = rav1e_rc_receive_pass_data(rax, &mut summary);
1291 assert_eq!(kind, RcDataKind::Summary);
1292 eprintln!("Got rc summary {} bytes", (*summary).len);
1293 break;
1294 } else if ret == EncoderStatus::Encoded
1295 || ret == EncoderStatus::Success
1296 {
1297 let mut p: *mut Data = std::ptr::null_mut();
1298 let kind = rav1e_rc_receive_pass_data(rax, &mut p);
1299 assert_eq!(kind, RcDataKind::Frame);
1300 eprintln!("Got rc frame data {} bytes", (*p).len);
1301 frame_data.push_back(p);
1302 }
1303 }
1304
1305 rav1e_config_set_emit_data(rac, 0);
1306 let mut data = (*summary).data;
1307 let mut len = (*summary).len;
1308 let ret = rav1e_config_set_rc_summary(rac, &mut data, &mut len);
1309 assert_eq!(ret, 0);
1310
1311 rav1e_data_unref(summary);
1312
1313 for _ in 0..10 {
1314 rav1e_send_frame(rax, f);
1315 }
1316
1317 rav1e_send_frame(rax, std::ptr::null_mut());
1318
1319 loop {
1320 let mut p: *mut Packet = std::ptr::null_mut();
1321 while rav1e_rc_second_pass_data_required(rax) > 0 {
1322 let d = frame_data.pop_front().unwrap();
1323 let mut data = (*d).data;
1324 let mut len = (*d).len;
1325 rav1e_rc_send_pass_data(rax, &mut data, &mut len);
1326 rav1e_data_unref(d);
1327 }
1328
1329 let ret = rav1e_receive_packet(rax, &mut p);
1330 rav1e_packet_unref(p);
1331 if ret == EncoderStatus::LimitReached {
1332 break;
1333 }
1334 }
1335
1336 rav1e_frame_unref(f);
1337 rav1e_context_unref(rax);
1338 rav1e_config_unref(rac);
1339 }
1340 }
1341 }
1342