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