You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

333 lines
10 KiB
Rust

use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use std::fmt::{Debug, Error, Formatter};
use std::io::{Cursor, Seek, SeekFrom};
#[derive(Debug)]
pub struct AvcDecoderConfigurationRecord {
pub profile_idc: u8,
pub constraint_set_flag: u8,
pub level_idc: u8,
pub sequence_parameter_set: Vec<u8>,
pub picture_parameter_set: Vec<u8>,
}
impl AvcDecoderConfigurationRecord {
pub fn from_parameter_sets(
sequence_parameter_set: Vec<u8>,
picture_parameter_set: Vec<u8>,
) -> AvcDecoderConfigurationRecord {
AvcDecoderConfigurationRecord {
profile_idc: sequence_parameter_set[1],
constraint_set_flag: sequence_parameter_set[2],
level_idc: sequence_parameter_set[3],
sequence_parameter_set,
picture_parameter_set,
}
}
pub fn to_bytes(&self) -> Result<Vec<u8>, String> {
let mut buffer = vec![];
// configuration_version
buffer.push(1);
buffer.push(self.profile_idc);
buffer.push(self.constraint_set_flag);
buffer.push(self.level_idc);
// reserved and length_size_minus_one
buffer.push(0b1111_1100 | 0b0000_0011);
// reserved and num_of_sequence_parameter_set_ext
buffer.push(0b1110_0000 | 0b0000_0001);
buffer
.write_u16::<BigEndian>(self.sequence_parameter_set.len() as u16)
.map_err(|x| format!("Failed to write u16 to vec ({})", x))?;
buffer.append(&mut self.sequence_parameter_set.clone());
// num_of_picture_parameter_set_ext
buffer.push(0b0000_0001);
buffer
.write_u16::<BigEndian>(self.picture_parameter_set.len() as u16)
.map_err(|x| format!("Failed to write u16 to vec ({})", x))?;
buffer.append(&mut self.picture_parameter_set.clone());
Ok(buffer)
}
}
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
#[repr(u8)]
pub enum NalUnitType {
CodedSliceOfANonIdrPicture = 1,
CodedSliceDataPartitionA = 2,
CodedSliceDataPartitionB = 3,
CodedSliceDataPartitionC = 4,
CodedSliceOfAnIdrPicture = 5,
SupplementalEnhancementInformation = 6,
SequenceParameterSet = 7,
PictureParameterSet = 8,
AccessUnitDelimiter = 9,
EndOfSequence = 10,
EndOfStream = 11,
FilterData = 12,
SequenceParameterSetExtension = 13,
PrefixNalUnit = 14,
SubsetSequenceParameterSet = 15,
CodedSliceOfAnAuxiliaryCodedPictureWithoutPartitioning = 19,
CodedSliceExtension = 20,
}
impl NalUnitType {
fn from_u8(n: u8) -> Result<Self, String> {
Ok(match n {
1 => NalUnitType::CodedSliceOfANonIdrPicture,
2 => NalUnitType::CodedSliceDataPartitionA,
3 => NalUnitType::CodedSliceDataPartitionB,
4 => NalUnitType::CodedSliceDataPartitionC,
5 => NalUnitType::CodedSliceOfAnIdrPicture,
6 => NalUnitType::SupplementalEnhancementInformation,
7 => NalUnitType::SequenceParameterSet,
8 => NalUnitType::PictureParameterSet,
9 => NalUnitType::AccessUnitDelimiter,
10 => NalUnitType::EndOfSequence,
11 => NalUnitType::EndOfStream,
12 => NalUnitType::FilterData,
13 => NalUnitType::SequenceParameterSetExtension,
14 => NalUnitType::PrefixNalUnit,
15 => NalUnitType::SubsetSequenceParameterSet,
19 => NalUnitType::CodedSliceOfAnAuxiliaryCodedPictureWithoutPartitioning,
20 => NalUnitType::CodedSliceExtension,
_ => return Err(format!("Couldn't find NalUnitType for {:?}", n)),
})
}
}
#[derive(Debug, Copy, Clone)]
pub struct NalUnit {
pub nal_ref_idc: u8,
pub nal_unit_type: NalUnitType,
}
impl NalUnit {
fn from_byte(byte: u8) -> Result<Self, String> {
let nal_ref_idc = (byte >> 5) & 0b11;
let nal_unit_type = NalUnitType::from_u8(byte & 0b1_1111)?;
Ok(NalUnit {
nal_ref_idc,
nal_unit_type,
})
}
fn to_byte(&self) -> u8 {
let nal_ref_idc = self.nal_ref_idc << 5;
let nal_unit_type = self.nal_unit_type as u8;
return nal_unit_type | nal_ref_idc;
}
}
#[derive(Clone)]
pub struct NalBuffer {
pub nal_unit: NalUnit,
pub buffer: Vec<u8>,
}
struct StringyBoi(String);
impl Debug for StringyBoi {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
f.write_str(&self.0)
}
}
impl Debug for NalBuffer {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
if f.alternate() {
f.debug_tuple("NalBuffer")
.field(&self.nal_unit)
.field(&self.buffer)
.finish()
} else {
f.debug_tuple("NalBuffer")
.field(&self.nal_unit)
.field(&StringyBoi(format!("len={}", self.buffer.len())))
.finish()
}
}
}
fn find_mdat(data: &Vec<u8>) -> Option<usize> {
for i in 0..=data.len() - 3 {
if data[i] == 'm' as u8
&& data.get(i + 3).copied() == Some('t' as u8)
&& &data[i..i + 4] == b"mdat"
{
return Some(i + 4);
}
}
None
}
#[cfg(debug_assertions)]
pub fn verify_data(data: Vec<u8>) {
let index = find_mdat(&data).expect("no mdat found") as u64;
let mut cursor = Cursor::new(&data);
cursor.set_position(index - 8);
let size = cursor.read_u32::<BigEndian>().expect(":O") as u64;
cursor.set_position(index);
while cursor.position() < (size + index - 8) {
let skip = cursor.read_u32::<BigEndian>().expect(":C") as i64;
cursor
.seek(SeekFrom::Current(skip))
.expect("Failed to seek");
}
assert_eq!(cursor.position() - index, size - 8);
}
pub fn annex_b_to_avc(mut data: Vec<u8>, nal_length: u8) -> Result<Vec<u8>, String> {
let nal_length = nal_length as usize;
let mut result: Vec<u8> = vec![];
let index = find_mdat(&data).ok_or("No mdat found".to_string())?;
let end = {
let mut cursor = Cursor::new(&data);
cursor.set_position((index - 8) as u64);
index + (cursor.read_u32::<BigEndian>().expect(":O") as usize) - 8
};
result.extend_from_slice(&data[0..index]);
let matcher = vec![0u8; nal_length - 1 as usize];
let mut last_position = index + nal_length - 1;
for i in (index + matcher.len() + nal_length)..end {
if data[i] == 1 && &data[1 + i - nal_length..i] == &matcher[..] {
let block_length = (i - last_position - 4) as u32;
let mut header = &mut data[last_position - 3..last_position + 1];
header
.write_u32::<BigEndian>(block_length)
.map_err(|x| format!("Failed writing to buffer: {}", x))?;
last_position = i;
}
}
let data_len = data.len();
let mut header = &mut data[last_position - 3..=last_position];
header
.write_u32::<BigEndian>(((data_len - 1) - last_position) as u32)
.map_err(|x| format!("Failed writing to buffer: {}", x))?;
#[cfg(debug_assertions)]
verify_data(data.clone());
Ok(data)
}
impl NalBuffer {
pub fn to_vec(&self) -> Vec<u8> {
let mut bytes = vec![0; 1 + self.buffer.len()];
{
let (left, right) = bytes.split_at_mut(1);
left[0] = self.nal_unit.to_byte();
right.copy_from_slice(&self.buffer);
}
bytes
}
pub fn from_stream(stream: Vec<u8>) -> Result<Vec<NalBuffer>, String> {
let mut i = 0;
let mut buffers = vec![];
let mut byte_buffer = vec![];
let mut current: Option<NalBuffer> = None;
while i < stream.len() {
if stream.len() > i + 3
&& stream[i] == 0
&& stream[i + 1] == 0
&& (stream[i + 2] == 1
|| (stream.len() > i + 4 && stream[i + 2] == 0 && stream[i + 3] == 1))
{
if let Some(mut buffer) = current.take() {
buffer.buffer = byte_buffer;
byte_buffer = vec![];
buffers.push(buffer);
}
i += if stream[i + 2] == 1 { 3 } else { 4 };
if i >= stream.len() {
break;
}
current = Some(NalBuffer {
nal_unit: NalUnit::from_byte(stream[i])?,
buffer: vec![],
});
i += 1;
if i >= stream.len() {
break;
}
}
if stream.len() > i + 4
&& stream[i] == 0
&& stream[i + 1] == 0
&& stream[i + 2] == 0
&& stream[i + 3] == 3
{
byte_buffer.append(&mut (&stream[i..i + 2]).to_vec());
i += 4;
if i >= stream.len() {
break;
}
}
byte_buffer.push(stream[i]);
i += 1;
}
if let Some(mut buffer) = current.take() {
buffer.buffer = byte_buffer;
buffers.push(buffer);
}
Ok(buffers)
}
}
#[cfg(test)]
mod test {
use crate::av::mov_avc::{annex_b_to_avc, verify_data};
use std::fs::File;
use std::io::Read;
#[test]
fn test_annex_b_to_avc() {
let mdat = b"mdat".to_vec();
let mut insert: Vec<u8> = vec![
0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 1, 1, 2, 3, 4, 5, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8,
9,
];
let mut buffer: Vec<u8> = vec![0, 0, 0, insert.len() as u8 + 8];
let mut result: Vec<u8> = vec![0, 0, 0, insert.len() as u8 + 8];
buffer.extend_from_slice(&mdat);
buffer.append(&mut insert);
result.extend(mdat);
result.append(&mut vec![
0, 0, 0, 4, 1, 2, 3, 4, 0, 0, 0, 5, 1, 2, 3, 4, 5, 0, 0, 0, 9, 1, 2, 3, 4, 5, 6, 7, 8,
9,
]);
assert_eq!(annex_b_to_avc(buffer, 4), Ok(result.clone()));
verify_data(result);
}
#[test]
fn bs() {
let mut x = File::open("/home/eater/shit/dash-exmp/chunk-stream0-00001.m4s").expect("ok");
let mut xxx = vec![];
x.read_to_end(&mut xxx).unwrap();
verify_data(xxx);
let mut x = File::open("/tmp/transotf/segment-00000.m4s").expect("ok");
let mut xxx = vec![];
x.read_to_end(&mut xxx).unwrap();
verify_data(xxx);
}
}