#![deny(missing_docs)]
use anyhow::anyhow;
use libc::{c_char, size_t};
use std::{
ffi::{CStr, CString},
path::PathBuf,
ptr::{null, null_mut},
};
use crate::{
metadata::{Hdr10PlusMetadata, Hdr10PlusMetadataEncOpts},
metadata_json::MetadataJsonRoot,
};
use super::c_structs::*;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn hdr10plus_rs_parse_json(path: *const c_char) -> *mut JsonOpaque {
if path.is_null() {
return null_mut();
}
let mut opaque = JsonOpaque {
metadata_root: None,
error: None,
};
let mut error = None;
if let Ok(str) = unsafe { CStr::from_ptr(path) }.to_str() {
let path = PathBuf::from(str);
match MetadataJsonRoot::from_file(path) {
Ok(metadata) => opaque.metadata_root = Some(metadata),
Err(e) => {
error = Some(format!(
"hdr10plus_rs_parse_json: Errored while parsing: {e}"
));
}
};
} else {
error =
Some("hdr10plus_rs_parse_json: Failed parsing the input path as a string".to_string());
}
if let Some(err) = error {
opaque.error = CString::new(err).ok();
}
Box::into_raw(Box::new(opaque))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn hdr10plus_rs_json_get_error(ptr: *const JsonOpaque) -> *const c_char {
if ptr.is_null() {
return null();
}
let opaque = unsafe { &*ptr };
match &opaque.error {
Some(s) => s.as_ptr(),
None => null(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn hdr10plus_rs_json_free(ptr: *mut JsonOpaque) {
if !ptr.is_null() {
drop(unsafe { Box::from_raw(ptr) });
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn hdr10plus_rs_write_av1_metadata_obu_t35_complete(
ptr: *mut JsonOpaque,
frame_number: size_t,
) -> *const Data {
if ptr.is_null() {
return null();
}
let opaque = unsafe { &mut *ptr };
let frame_metadata = opaque
.metadata_root
.as_ref()
.and_then(|root| root.scene_info.get(frame_number))
.ok_or(anyhow!("No metadata for frame {frame_number}"))
.and_then(|jm| {
let enc_opts = Hdr10PlusMetadataEncOpts {
with_country_code: true,
..Default::default()
};
Hdr10PlusMetadata::try_from(jm)
.and_then(|metadata| metadata.encode_with_opts(&enc_opts))
});
match frame_metadata {
Ok(buf) => Box::into_raw(Box::new(Data::from(buf))),
Err(e) => {
opaque
.error
.replace(CString::new(format!("Failed writing byte buffer: {e}")).unwrap());
null()
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn hdr10plus_rs_data_free(data: *const Data) {
if !data.is_null() {
unsafe {
let data = Box::from_raw(data as *mut Data);
data.free();
}
}
}