-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[WIP] Add support for AV1 Dolby Vision metadata payloads
Parsing and writing RPUs less than 256 bytes
- Loading branch information
Showing
12 changed files
with
248 additions
and
18 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
use anyhow::{bail, ensure, Result}; | ||
|
||
use crate::rpu::dovi_rpu::DoviRpu; | ||
|
||
pub const ITU_T35_DOVI_RPU_PAYLOAD_HEADER: &[u8] = | ||
&[0x00, 0x3B, 0x00, 0x00, 0x08, 0x00, 0x37, 0xCD, 0x08]; | ||
|
||
fn validated_trimmed_data(data: &[u8]) -> Result<&[u8]> { | ||
if data.len() < 34 { | ||
bail!("Invalid RPU length: {}", data.len()); | ||
} | ||
|
||
let data = if data[0] == 0xB5 { | ||
// itu_t_t35_country_code - United States | ||
// Remove from buffer | ||
&data[1..] | ||
} else { | ||
data | ||
}; | ||
|
||
let trimmed_data = match &data[..9] { | ||
ITU_T35_DOVI_RPU_PAYLOAD_HEADER => data, | ||
_ => bail!("Invalid RPU data start_bytes\n{:?}", &data[..9]), | ||
}; | ||
|
||
Ok(trimmed_data) | ||
} | ||
|
||
/// Internal function, use `parse_itu_t35_dovi_metadata_obu` | ||
/// | ||
/// Expects the payload to have `ITU_T35_DOVI_RPU_PAYLOAD_HEADER` discarded | ||
pub fn convert_av1_rpu_payload_to_regular(data: &[u8]) -> Result<Vec<u8>> { | ||
let mut converted_buf = vec![0x19]; | ||
|
||
// 256+ bytes size | ||
if data[1] & 0x10 > 0 { | ||
if data[2] & 0x08 > 0 { | ||
bail!("RPU exceeds 512 bytes"); | ||
} | ||
|
||
let mut rpu_size: usize = 0x100; | ||
rpu_size |= (data[1] as usize & 0x0F) << 4; | ||
rpu_size |= (data[2] as usize >> 4) & 0x0F; | ||
|
||
converted_buf.reserve(rpu_size); | ||
|
||
for i in 0..rpu_size { | ||
let mut converted_byte = (data[2 + i] & 0x07) << 5; | ||
converted_byte |= (data[3 + i] >> 3) & 0x1F; | ||
converted_buf.push(converted_byte); | ||
} | ||
} else { | ||
let mut rpu_size: usize = (data[0] as usize & 0x1F) << 3; | ||
rpu_size |= (data[1] as usize >> 5) & 0x07; | ||
|
||
converted_buf.reserve(rpu_size); | ||
|
||
for i in 0..rpu_size { | ||
let mut converted_byte = (data[1 + i] & 0x0F) << 4; | ||
converted_byte |= (data[2 + i] >> 4) & 0x0F; | ||
converted_buf.push(converted_byte); | ||
} | ||
} | ||
|
||
Ok(converted_buf) | ||
} | ||
|
||
/// Buffer must start with 0x19 prefix | ||
/// Returns payload for AV1 ITU T-T.35 metadata OBU | ||
pub fn convert_regular_rpu_to_av1_payload(data: &[u8]) -> Result<Vec<u8>> { | ||
ensure!(data[0] == 0x19); | ||
|
||
// Exclude 0x19 prefix | ||
let rpu_size = data.len() - 1; | ||
let mut out_buf = | ||
Vec::<u8>::with_capacity(ITU_T35_DOVI_RPU_PAYLOAD_HEADER.len() + data.len() - 1); | ||
out_buf.extend(ITU_T35_DOVI_RPU_PAYLOAD_HEADER); | ||
|
||
// 256+ bytes size | ||
if rpu_size > 0xFF { | ||
// FIXME: Figure out size and final bytes to work | ||
out_buf.extend(&[0xFF, (rpu_size >> 4) as u8, ((rpu_size & 0x0F) as u8) << 4]); | ||
|
||
for i in 1..rpu_size { | ||
let mut byte = (data[i] & 0x1F) << 3; | ||
byte |= (data[1 + i] >> 5) & 0x07; | ||
|
||
out_buf.push(byte); | ||
} | ||
|
||
// Last byte | ||
out_buf.push((data[rpu_size] & 0x1F) << 3); | ||
} else { | ||
// Unknown additional diff for first size byte | ||
let size_byte1_diff = 32; // 2^5 | ||
|
||
out_buf.extend(&[ | ||
(rpu_size >> 3) as u8 + size_byte1_diff, | ||
((rpu_size & 0x07) as u8) << 5, | ||
]); | ||
|
||
for i in 1..rpu_size { | ||
let mut byte = (data[i] & 0x0F) << 4; | ||
byte |= (data[1 + i] >> 4) & 0x0F; | ||
|
||
out_buf.push(byte); | ||
} | ||
|
||
// Last byte | ||
out_buf.push((data[rpu_size] & 0x0F) << 4); | ||
|
||
// Unknown necessary bytes | ||
out_buf.extend(&[size_byte1_diff, 0]); | ||
} | ||
|
||
Ok(out_buf) | ||
} | ||
|
||
/// Parse AV1 RPU metadata payload starting with `ITU_T35_DOVI_RPU_PAYLOAD_HEADER` | ||
pub fn parse_itu_t35_dovi_metadata_obu(data: &[u8]) -> Result<DoviRpu> { | ||
let data = validated_trimmed_data(data)?; | ||
|
||
if !(data[0] == 0x00 | ||
&& data[1] == 0x3B // itu_t_t35_terminal_provider_code - Dolby 0x003B | ||
&& data[2] == 0x00 | ||
&& data[3] == 0x00 // itu_t_t35_terminal_provider_oriented_code - 0x0000 | ||
&& data[4] == 0x08 | ||
&& data[5] == 0x00 | ||
&& data[6] == 0x37 | ||
&& data[7] == 0xCD | ||
&& data[8] == 0x08) | ||
{ | ||
bail!("Invalid AV1 RPU header: {:?}", &data[..9]); | ||
} | ||
|
||
let converted_buf = convert_av1_rpu_payload_to_regular(&data[9..])?; | ||
|
||
DoviRpu::parse_rpu(&converted_buf) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.