1use std::collections::VecDeque;
2use std::io::{Cursor, ErrorKind, Read};
3use std::iter::repeat;
4use std::{io, mem};
5
6use bitstream_io::{BigEndian, BitRead, BitReader};
7use h264_reader::annexb::AnnexBReader;
8use h264_reader::avcc::AvccError;
9use h264_reader::nal::{Nal, RefNal};
10use h264_reader::push::{AccumulatedNalHandler, NalAccumulator, NalInterest};
11
12pub const NALU_DELIMITER: [u8; 4] = [0, 0, 0, 1];
13
14#[derive(Debug)]
40#[repr(u8)]
41pub enum NaluType {
42 Unspecified = 0,
43 Slice = 1,
44 SliceA = 2,
45 SliceB = 3,
46 SliceC = 4,
47 SliceIDR = 5,
48 SEI = 6,
49 SPS = 7,
50 PPS = 8,
51 AUD = 9,
52 EOSeq = 10,
53 EOStream = 11,
54}
55
56impl NaluType {
57 pub fn from_nalu_header(header: u8) -> Self {
58 let value = header & 0b00011111;
59 assert!(value <= NaluType::EOStream as u8);
60 unsafe { mem::transmute::<u8, _>(value) }
61 }
62}
63
64#[derive(Debug, Copy, Clone)]
65pub struct ColorCharacteristics {
66 pub cp: ColourPrimaries,
67 pub mc: MatrixCoefficients,
68 pub tc: TransferCharacteristic,
69}
70
71impl ColorCharacteristics {
72 pub fn or(self, other: Self) -> Self {
73 Self {
74 cp: if matches!(self.cp, ColourPrimaries::Unspecified) {
75 other.cp
76 } else {
77 self.cp
78 },
79 mc: if matches!(self.mc, MatrixCoefficients::Unspecified) {
80 other.mc
81 } else {
82 self.mc
83 },
84 tc: if matches!(self.tc, TransferCharacteristic::Unspecified) {
85 other.tc
86 } else {
87 self.tc
88 },
89 }
90 }
91}
92
93#[derive(Debug, Copy, Clone)]
95#[repr(u8)]
96pub enum ColourPrimaries {
97 Reserved = 0,
98 BT709 = 1,
99 Unspecified = 2,
100 Reserved2 = 3,
101 FCC = 4,
102 BT601_625 = 5,
103 BT601_525 = 6,
104 }
106
107impl ColourPrimaries {
108 pub fn from_byte(byte: u8) -> Self {
109 assert!(byte <= ColourPrimaries::BT601_525 as u8);
110 unsafe { mem::transmute::<u8, _>(byte) }
111 }
112}
113
114#[derive(Debug, Copy, Clone)]
116#[repr(u8)]
117pub enum TransferCharacteristic {
118 Reserved = 0,
119 BT709 = 1,
120 Unspecified = 2,
121 Reserved2 = 3,
122 Gamma22 = 4,
123 Gamma28 = 5,
124 BT601 = 6,
125 }
127
128impl TransferCharacteristic {
129 pub fn from_byte(byte: u8) -> Self {
130 assert!(byte <= TransferCharacteristic::BT601 as u8);
131 unsafe { mem::transmute::<u8, _>(byte) }
132 }
133}
134
135#[derive(Debug, Copy, Clone)]
137#[repr(u8)]
138pub enum MatrixCoefficients {
139 Identity = 0,
140 BT709 = 1,
141 Unspecified = 2,
142 Reserved = 3,
143 FCC = 4,
144 BT601_625 = 5,
145 BT601_525 = 6,
146 }
148
149impl MatrixCoefficients {
150 pub fn from_byte(byte: u8) -> Self {
151 assert!(byte <= MatrixCoefficients::BT601_525 as u8);
152 unsafe { mem::transmute::<u8, _>(byte) }
153 }
154}
155
156#[allow(unused_variables)]
158pub fn avcc_extradata_to_annexb(codec_private: &[u8]) -> (usize, Vec<u8>) {
159 let mut reader = BitReader::endian(Cursor::new(codec_private), BigEndian);
160 let version: u8 = reader.read(8).unwrap();
161 let profile: u8 = reader.read(8).unwrap();
162 let profile_compat: u8 = reader.read(8).unwrap();
163 let level: u8 = reader.read(8).unwrap();
164 reader.read::<u8>(6).unwrap(); let nal_size: u8 = reader.read::<u8>(2).unwrap() + 1;
166 reader.read::<u8>(3).unwrap(); let num_sps: u8 = reader.read(5).unwrap();
168
169 let mut nalus = Vec::new();
170 for _ in 0..num_sps {
171 let len = reader.read::<u16>(16).unwrap() as usize;
172 nalus.extend_from_slice(&NALU_DELIMITER);
173 let start = nalus.len();
174 nalus.extend(repeat(0).take(len));
175 reader.read_bytes(&mut nalus[start..]).unwrap();
176 }
177 let num_pps: u8 = reader.read(8).unwrap();
178 for _ in 0..num_pps {
179 let len = reader.read::<u16>(16).unwrap() as usize;
180 nalus.extend_from_slice(&NALU_DELIMITER);
181 let start = nalus.len();
182 nalus.extend(repeat(0).take(len));
183 reader.read_bytes(&mut nalus[start..]).unwrap();
184 }
185
186 (nal_size as usize, nalus)
187}
188
189pub fn extract_sps_pps_clean(codec_private: &[u8]) -> Result<Vec<u8>, AvccError> {
190 let dcr = h264_reader::avcc::AvcDecoderConfigurationRecord::try_from(codec_private)?;
191 let mut nalus = Vec::new();
192 for sps in dcr.sequence_parameter_sets() {
193 let sps = sps.map_err(AvccError::ParamSet)?;
194 nalus.extend_from_slice(&[0, 0, 0, 1]);
195 nalus.extend_from_slice(sps);
196 }
197 for pps in dcr.picture_parameter_sets() {
198 let pps = pps.map_err(AvccError::ParamSet)?;
199 nalus.extend_from_slice(&[0, 0, 0, 1]);
200 nalus.extend_from_slice(pps);
201 }
202 Ok(nalus)
203}
204
205pub fn packet_to_annexb(buffer: &mut Vec<u8>, mut packet: &[u8], nal_length_size: usize) {
206 buffer.clear();
207 while packet.len() > nal_length_size {
208 let mut len = 0usize;
209 for &byte in packet.iter().take(nal_length_size) {
211 len = (len << 8) | byte as usize;
212 }
213 packet = &packet[nal_length_size..];
214 buffer.extend_from_slice(&NALU_DELIMITER);
215 buffer.extend_from_slice(&packet[..len]);
216 packet = &packet[len..];
217 }
218 assert!(packet.is_empty());
219}
220
221pub struct NalReader<R: Read> {
222 annexb: AnnexBReader<NalAccumulator<Handler<R>>>,
223}
224
225struct Handler<R: Read> {
226 r: R,
227 packets: VecDeque<Vec<u8>>,
228}
229
230impl<R: Read> AccumulatedNalHandler for Handler<R> {
231 fn nal(&mut self, nal: RefNal<'_>) -> NalInterest {
232 if nal.is_complete() {
233 let mut reader = nal.reader();
234 let mut pkt = NALU_DELIMITER.to_vec();
235 reader.read_to_end(&mut pkt).unwrap();
236 self.packets.push_back(pkt);
237 }
238 NalInterest::Buffer
239 }
240}
241
242impl<R: Read> NalReader<R> {
243 pub fn new(r: R) -> Self {
244 Self {
245 annexb: AnnexBReader::accumulate(Handler {
246 r,
247 packets: VecDeque::new(),
248 }),
249 }
250 }
251
252 pub fn read_nalu(&mut self) -> io::Result<Vec<u8>> {
253 while self.annexb.nal_handler_ref().packets.is_empty() {
254 let mut buf = [0; 2048];
255 let len = self.annexb.nal_handler_mut().r.read(&mut buf)?;
256 if len == 0 {
257 return Err(io::Error::from(ErrorKind::UnexpectedEof));
258 }
259 self.annexb.push(&buf[..len]);
260 }
261 Ok(self.annexb.nal_handler_mut().packets.pop_front().unwrap())
262 }
263}
264
265#[cfg(test)]
310mod tests {
311 use matroska_demuxer::{Frame, MatroskaFile};
312 use std::fs::File;
313 use std::io::BufReader;
314
315 use crate::h264::{avcc_extradata_to_annexb, extract_sps_pps_clean, NalReader, NaluType};
316
317 const RAW_H264: &'static str = "../../data/raw.h264";
318 const RAW_H264_SOURCE: &'static str = "../../data/dummy_encode.mkv";
319 const TEST_MKV: &'static str = "../../data/chainsaw_man_s01e01_v.mkv";
320
321 #[test]
322 fn sps_pps_extraction() {
323 let mut matroska =
324 MatroskaFile::open(BufReader::new(File::open(TEST_MKV).unwrap())).unwrap();
325
326 let (_, bitstream) =
327 avcc_extradata_to_annexb(matroska.tracks()[0].codec_private().unwrap());
328 let mut matroska =
331 MatroskaFile::open(BufReader::new(File::open(TEST_MKV).unwrap())).unwrap();
332
333 let extradata2 =
334 extract_sps_pps_clean(matroska.tracks()[0].codec_private().unwrap()).unwrap();
335 assert_eq!(bitstream, extradata2);
338 }
339
340 #[test]
341 fn test_nalus() {
342 let mut r = NalReader::new(File::open(RAW_H264).unwrap());
343 let mut i = 0;
344 while let Ok(pkt) = r.read_nalu() {
345 println!(
346 "{i:>3}: {:?} ({} bytes)",
347 NaluType::from_nalu_header(pkt[4]),
348 pkt.len()
349 );
350 i += 1;
351 }
352 }
353
354 #[test]
355 fn test_nal_reader() {
356 let mut r = NalReader::new(File::open(RAW_H264).unwrap());
357 while let Ok(pkt) = r.read_nalu() {
358 dbg!(pkt.len());
359 }
360
361 let mut matroska =
362 MatroskaFile::open(BufReader::new(File::open(RAW_H264_SOURCE).unwrap())).unwrap();
363 let (nal_length_size, sps_pps) =
364 avcc_extradata_to_annexb(matroska.tracks()[0].codec_private().unwrap());
365 dbg!(sps_pps.len());
366 let mut frame = Frame::default();
368 while let Ok(remaining) = matroska.next_frame(&mut frame) {
369 if !remaining {
370 break;
371 }
372 dbg!(frame.data.len());
373 }
374 }
381}