codec_bitstream/
h264.rs

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/*
150      Unspecified                                                    non-VCL
161      Coded slice of a non-IDR picture                               VCL
172      Coded slice data partition A                                   VCL
183      Coded slice data partition B                                   VCL
194      Coded slice data partition C                                   VCL
205      Coded slice of an IDR picture                                  VCL
216      Supplemental enhancement information (SEI)                     non-VCL
227      Sequence parameter set                                         non-VCL
238      Picture parameter set                                          non-VCL
249      Access unit delimiter                                          non-VCL
2510     End of sequence                                                non-VCL
2611     End of stream                                                  non-VCL
2712     Filler data                                                    non-VCL
2813     Sequence parameter set extension                               non-VCL
2914     Prefix NAL unit                                                non-VCL
3015     Subset sequence parameter set                                  non-VCL
3116     Depth parameter set                                            non-VCL
3217..18 Reserved                                                       non-VCL
3319     Coded slice of an auxiliary coded picture without partitioning non-VCL
3420     Coded slice extension                                          non-VCL
3521     Coded slice extension for depth view components                non-VCL
3622..23 Reserved                                                       non-VCL
3724..31 Unspecified                                                    non-VCL
38 */
39#[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/// As defined in "Table E-3 – Colour primaries interpretation using colour_primaries syntax element" of the H.264 specification.
94#[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    // TODO complete colour primaries
105}
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/// As defined in "Table E-4 – Transfer characteristics interpretation using transfer_characteristics syntax element" of the H.264 specification.
115#[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    // TODO complete transfer characteristic
126}
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/// As defined in "Table E-5 – Matrix coefficients interpretation using matrix_coefficients syntax element" of the H.264 specification.
136#[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    // TODO complete matrix coefficients
147}
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/// Get NAL units with SPS and PPS from the avc decoder configuration record.
157#[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(); // Reserved
165    let nal_size: u8 = reader.read::<u8>(2).unwrap() + 1;
166    reader.read::<u8>(3).unwrap(); // Reserved
167    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        // Read a variable number of bytes in big endian format
210        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// pub struct NalReader<R: Read> {
266//     r: R,
267//     buf: VecDeque<u8>,
268//     pop: Option<usize>,
269// }
270//
271// impl<R: Read> NalReader<R> {
272//     pub fn new(r: R) -> Self {
273//         Self {
274//             r,
275//             buf: VecDeque::from(vec![0; 8 * 1024]),
276//             pop: None,
277//         }
278//     }
279//
280//     pub fn read_nalu(&mut self) -> Result<&[u8], ()> {
281//         const READ_AMOUNT: usize = 2048;
282//         if let Some(idx) = self.pop {
283//             self.buf.drain(..idx);
284//         }
285//         loop {
286//             let buf = self.buf.make_contiguous();
287//             for (i, w) in buf.windows(4).enumerate() {
288//                 if i == 0 {
289//                     assert_eq!(w, NALU_HEADER);
290//                     continue;
291//                 }
292//                 if w == NALU_HEADER {
293//                     self.pop = Some(i);
294//                     return Ok(&buf[..i]);
295//                 }
296//             }
297//             let old_len = self.buf.len();
298//             self.buf.extend(repeat(0).take(READ_AMOUNT));
299//             let buf = self.buf.make_contiguous();
300//             let len = self.r.read(&mut buf[old_len..]).unwrap();
301//             assert!(len > 0);
302//             self.buf.drain(old_len + len..);
303//         }
304//
305//         Err(())
306//     }
307// }
308
309#[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        // dbg!(bitstream);
329
330        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        // dbg!(extradata2);
336
337        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 pkt = Vec::new();
367        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        // matroska.next_frame(&mut frame).unwrap();
375        // packet_to_annexb(&mut pkt, &frame.data, nal_length_size);
376
377        // dbg!(apkt.len());
378        // dbg!(pkt.len());
379        // assert_eq!(&pkt, &apkt);
380    }
381}