1 //! Module for parsing Canon CR3 files that are ISO Base Media Format
2 //!  aka video/mp4 streams.
3 
4 // This Source Code Form is subject to the terms of the Mozilla Public
5 // License, v. 2.0. If a copy of the MPL was not distributed with this
6 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
7 
8 use super::{
9     be_u16, be_u32, be_u64, read_buf, skip, skip_box_content, skip_box_remain, BMFFBox, Error,
10 };
11 use boxes::BoxType;
12 use std::io::Read;
13 
14 pub const HEADER_UUID: [u8; 16] = [
15     0x85, 0xc0, 0xb6, 0x87, 0x82, 0x0f, 0x11, 0xe0, 0x81, 0x11, 0xf4, 0xce, 0x46, 0x2b, 0x6a, 0x48,
16 ];
17 
18 #[allow(dead_code)]
19 pub const XPACKET_UUID: [u8; 16] = [
20     0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8, 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac,
21 ];
22 
23 #[allow(dead_code)]
24 pub const PREVIEW_UUID: [u8; 16] = [
25     0xea, 0xf4, 0x2b, 0x5e, 0x1c, 0x98, 0x4b, 0x88, 0xb9, 0xfb, 0xb7, 0xdc, 0x40, 0x6e, 0x4d, 0x16,
26 ];
27 
28 /// Canon Thumbnail
29 #[derive(Debug, Default)]
30 pub struct CanonThumbnail {
31     pub width: u16,
32     pub height: u16,
33     pub data: Vec<u8>,
34 }
35 
36 /// Canon CRAW data ('crx ' brand files)
37 #[derive(Debug, Default)]
38 pub struct CrawHeader {
39     pub cncv: Vec<u8>,
40     pub offsets: Vec<(u64, u64)>,
41     pub meta1: Option<Vec<u8>>,
42     pub meta2: Option<Vec<u8>>,
43     pub meta3: Option<Vec<u8>>,
44     pub meta4: Option<Vec<u8>>,
45     pub thumbnail: CanonThumbnail,
46 }
47 
48 #[derive(Debug, Clone)]
49 pub struct CanonCRAWEntry {
50     data_reference_index: u16,
51     pub width: u16,
52     pub height: u16,
53     pub is_jpeg: bool,
54 }
55 
56 /// Parse the CRAW entry inside the video sample entry.
read_craw_entry<T: Read>( src: &mut BMFFBox<T>, width: u16, height: u16, data_reference_index: u16, ) -> super::Result<super::SampleEntry>57 pub fn read_craw_entry<T: Read>(
58     src: &mut BMFFBox<T>,
59     width: u16,
60     height: u16,
61     data_reference_index: u16,
62 ) -> super::Result<super::SampleEntry> {
63     skip(src, 54)?;
64     let mut is_jpeg = false;
65     {
66         let mut iter = src.box_iter();
67         while let Some(mut b) = iter.next_box()? {
68             debug!("Box size {}", b.head.size);
69             match b.head.name {
70                 BoxType::QTJPEGAtom => {
71                     is_jpeg = true;
72                 }
73                 BoxType::CanonCMP1 => {}
74                 _ => {
75                     debug!("Unsupported box '{:?}' in CRAW", b.head.name);
76                 }
77             }
78             skip_box_remain(&mut b)?;
79         }
80     }
81     skip_box_remain(src)?;
82     check_parser_state!(src.content);
83 
84     Ok(super::SampleEntry::CanonCRAW(CanonCRAWEntry {
85         data_reference_index: data_reference_index,
86         width: width,
87         height: height,
88         is_jpeg: is_jpeg,
89     }))
90 }
91 
parse_craw_header<T: Read>(f: &mut BMFFBox<T>) -> super::Result<CrawHeader>92 pub fn parse_craw_header<T: Read>(f: &mut BMFFBox<T>) -> super::Result<CrawHeader> {
93     let mut header = CrawHeader::default();
94     let mut iter = f.box_iter();
95     while let Some(mut b) = iter.next_box()? {
96         match b.head.name {
97             BoxType::CanonCompressorVersion => {
98                 let size = b.head.size - b.head.offset;
99                 let data = read_buf(&mut b, size)?;
100                 header.cncv = data.to_vec();
101                 skip_box_remain(&mut b)?;
102             }
103             BoxType::CanonTableOffset => {
104                 let count = be_u32(&mut b)?;
105                 for _i in 0..count {
106                     skip(&mut b, 4)?; // index. We do not care.
107                     let offset = be_u64(&mut b)?;
108                     let size = be_u64(&mut b)?;
109                     if offset == 0 || size == 0 {
110                         break;
111                     }
112                     header.offsets.push((offset, size));
113                 }
114                 skip_box_remain(&mut b)?;
115             }
116             BoxType::CanonMeta1
117             | BoxType::CanonMeta2
118             | BoxType::CanonMeta3
119             | BoxType::CanonMeta4 => {
120                 let len = b.head.size - b.head.offset;
121                 let data = read_buf(&mut b, len)?;
122                 let data = data.to_vec();
123                 match b.head.name {
124                     BoxType::CanonMeta1 => header.meta1 = Some(data),
125                     BoxType::CanonMeta2 => header.meta2 = Some(data),
126                     BoxType::CanonMeta3 => header.meta3 = Some(data),
127                     BoxType::CanonMeta4 => header.meta4 = Some(data),
128                     _ => unreachable!(),
129                 }
130             }
131             BoxType::CanonThumbnail => {
132                 skip(&mut b, 4)?;
133                 let width = be_u16(&mut b)?;
134                 let height = be_u16(&mut b)?;
135                 let jpeg_size = be_u32(&mut b)?;
136                 skip(&mut b, 4)?;
137                 if (jpeg_size as u64) + b.head.offset + 16u64 > b.head.size {
138                     return Err(Error::InvalidData("short box size for JPEG data"));
139                 }
140                 let data = read_buf(&mut b, jpeg_size as u64)?;
141                 header.thumbnail = CanonThumbnail {
142                     width: width,
143                     height: height,
144                     data: data.to_vec(),
145                 };
146                 skip_box_remain(&mut b)?;
147             }
148             _ => skip_box_content(&mut b)?,
149         }
150     }
151 
152     debug!("{:?}", header);
153     Ok(header)
154 }
155