1 /* Copyright (c) MediaArea.net SARL. All Rights Reserved.
2 *
3 * Use of this source code is governed by a BSD-style license that can
4 * be found in the License.html file in the root of the source tree.
5 */
6
7 //---------------------------------------------------------------------------
8 // Pre-compilation
9 #include "MediaInfo/PreComp.h"
10 #ifdef __BORLANDC__
11 #pragma hdrstop
12 #endif
13 //---------------------------------------------------------------------------
14
15 //---------------------------------------------------------------------------
16 #include "MediaInfo/Setup.h"
17 //---------------------------------------------------------------------------
18
19 //---------------------------------------------------------------------------
20 #if defined(MEDIAINFO_PRORES_YES)
21 //---------------------------------------------------------------------------
22
23 //---------------------------------------------------------------------------
24 #include "MediaInfo/Video/File_ProRes.h"
25 //---------------------------------------------------------------------------
26
27 namespace MediaInfoLib
28 {
29
30 //***************************************************************************
31 // Infos
32 //***************************************************************************
33
34 //---------------------------------------------------------------------------
35 const char* Mpegv_colour_primaries(int8u colour_primaries);
36 const char* Mpegv_transfer_characteristics(int8u transfer_characteristics);
37 const char* Mpegv_matrix_coefficients(int8u matrix_coefficients);
38 const char* Mpegv_matrix_coefficients_ColorSpace(int8u matrix_coefficients);
39
40 //---------------------------------------------------------------------------
ProRes_chrominance_factor(int8u chrominance_factor)41 static const char* ProRes_chrominance_factor(int8u chrominance_factor)
42 {
43 switch (chrominance_factor)
44 {
45 case 0x02 : return "4:2:2";
46 case 0x03 : return "4:4:4";
47 default : return "";
48 }
49 }
50
51 //---------------------------------------------------------------------------
ProRes_frame_type_ScanType(int8u frame_type)52 static const char* ProRes_frame_type_ScanType(int8u frame_type)
53 {
54 switch (frame_type)
55 {
56 case 0x00 : return "Progressive";
57 case 0x01 :
58 case 0x02 : return "Interlaced";
59 default : return "";
60 }
61 }
62
63 //---------------------------------------------------------------------------
ProRes_frame_type_ScanOrder(int8u frame_type)64 static const char* ProRes_frame_type_ScanOrder(int8u frame_type)
65 {
66 switch (frame_type)
67 {
68 case 0x01 : return "TFF";
69 case 0x02 : return "BFF";
70 default : return "";
71 }
72 }
73
74 //---------------------------------------------------------------------------
ProRes_creatorID(int32u creatorID)75 static Ztring ProRes_creatorID(int32u creatorID)
76 {
77 switch (creatorID)
78 {
79 case 0x61706C30 : return __T("Apple"); //apl0
80 case 0x61727269 : return __T("Arnold & Richter Cine Technik"); //arri
81 case 0x616A6130 : return __T("AJA Kona Hardware"); //aja0
82 default : return Ztring().From_CC4(creatorID);
83 }
84 }
85
86 //***************************************************************************
87 // Constructor/Destructor
88 //***************************************************************************
89
90 //---------------------------------------------------------------------------
File_ProRes()91 File_ProRes::File_ProRes()
92 :File__Analyze()
93 {
94 //Configuration
95 ParserName="ProRes";
96 StreamSource=IsStream;
97 }
98
99 //***************************************************************************
100 // Streams management
101 //***************************************************************************
102
103 //---------------------------------------------------------------------------
Streams_Fill()104 void File_ProRes::Streams_Fill()
105 {
106 Stream_Prepare(Stream_Video);
107 Fill(Stream_Video, 0, Video_Format, "ProRes");
108 }
109
110 //***************************************************************************
111 // Buffer - Global
112 //***************************************************************************
113
114 //---------------------------------------------------------------------------
Read_Buffer_Continue()115 void File_ProRes::Read_Buffer_Continue()
116 {
117 //Parsing
118 int32u Name, creatorID;
119 int16u hdrSize, version, frameWidth, frameHeight;
120 int8u chrominance_factor, frame_type, primaries, transf_func, colorMatrix, alpha_info;
121 bool IsOk=true, luma, chroma;
122 Element_Begin1("Header");
123 Skip_B4( "Size");
124 Get_C4 (Name, "Name");
125 Element_End();
126 Element_Begin1("Frame header");
127 Get_B2 (hdrSize, "hdrSize");
128 Get_B2 (version, "version");
129 Get_C4 (creatorID, "creatorID");
130 Get_B2 (frameWidth, "frameWidth");
131 Get_B2 (frameHeight, "frameHeight");
132 if (Name==0x69637066) // icpf
133 {
134 BS_Begin();
135 Get_S1 (2, chrominance_factor, "chrominance factor"); Param_Info1(ProRes_chrominance_factor(chrominance_factor));
136 Skip_S1(2, "reserved");
137 Get_S1 (2, frame_type, "frame type"); Param_Info1(ProRes_frame_type_ScanType(frame_type)); Param_Info1(ProRes_frame_type_ScanOrder(frame_type));
138 Skip_S1(2, "reserved");
139 BS_End();
140 Skip_B1( "reserved");
141 Get_B1 (primaries, "primaries"); Param_Info1(Mpegv_colour_primaries(primaries));
142 Get_B1 (transf_func, "transf_func"); Param_Info1(Mpegv_transfer_characteristics(transf_func));
143 Get_B1 (colorMatrix, "colorMatrix"); Param_Info1(Mpegv_matrix_coefficients(colorMatrix));
144 BS_Begin();
145 Skip_S1(4, "src_pix_fmt");
146 Get_S1 (4, alpha_info, "alpha_info");
147 BS_End();
148 Skip_B1( "reserved");
149 BS_Begin();
150 Skip_S1(6, "reserved");
151 Get_SB (luma, "custom luma quant matrix present");
152 Get_SB (chroma, "custom chroma quant matrix present");
153 BS_End();
154 if (luma)
155 Skip_XX(64, "QMatLuma");
156 if (chroma)
157 Skip_XX(64, "QMatChroma");
158 }
159 else
160 {
161 if (hdrSize>20)
162 Skip_XX(hdrSize-20, "Unknown");
163 }
164 Element_End();
165 if (Name==0x69637066 && Element_Offset!=8+(int32u)hdrSize) // Coherency test icpf
166 IsOk=false;
167 if (Name==0x69637066) // icpf
168 {
169 for (int8u PictureNumber=0; PictureNumber<(frame_type?2:1); PictureNumber++)
170 {
171 Element_Begin1("Picture layout");
172 int16u total_slices;
173 vector<int16u> slices_size;
174 Element_Begin1("Picture header");
175 int64u pic_hdr_End, pic_data_End;
176 int32u pic_data_size;
177 int8u pic_hdr_size;
178 Get_B1 (pic_hdr_size, "pic_hdr_size");
179 if (pic_hdr_size<64)
180 {
181 Trusted_IsNot("pic_hdr_size");
182 Element_End();
183 Element_End();
184 return;
185 }
186 pic_hdr_End=Element_Offset+pic_hdr_size/8-((pic_hdr_size%8)?0:1);
187 Get_B4 (pic_data_size, "pic_data_size");
188 if (pic_data_size<8)
189 {
190 Trusted_IsNot("pic_data_size");
191 Element_End();
192 Element_End();
193 return;
194 }
195 pic_data_End=Element_Offset+pic_data_size-5;
196 Get_B2 (total_slices, "total_slices");
197 BS_Begin();
198 Skip_S1(4, "slice_width_factor");
199 Skip_S1(4, "slice_height_factor");
200 BS_End();
201 if (Element_Offset<pic_hdr_End)
202 Skip_XX(pic_hdr_End-Element_Offset, "Unknown");
203 Element_End();
204 Element_Begin1("Slice index table");
205 for (int16u Pos=0; Pos<total_slices; Pos++)
206 {
207 int16u slice_size;
208 Get_B2 (slice_size, "slice_size");
209 slices_size.push_back(slice_size);
210 }
211 Element_End();
212 for (int16u Pos=0; Pos<slices_size.size(); Pos++)
213 {
214 Skip_XX(slices_size[Pos], "slice data");
215 }
216 if (Element_Offset<pic_data_End)
217 Skip_XX(pic_data_End-Element_Offset, "Unknown");
218 Element_End();
219 }
220 }
221 bool IsZeroes=true;
222 for (size_t Pos=(size_t)Element_Offset; Pos<(size_t)Element_Size; Pos++)
223 if (Buffer[Buffer_Offset+Pos])
224 {
225 IsZeroes=false;
226 break;
227 }
228 Skip_XX(Element_Size-Element_Offset, IsZeroes?"Zeroes":"Unknown");
229
230 FILLING_BEGIN();
231 if (IsOk && (Name==0x69637066 || Name==0x70727266) && !Status[IsAccepted]) //icpf (all but RAW) & prrf (RAW)
232 {
233 Accept();
234 Fill();
235
236 Fill(Stream_Video, 0, Video_Format_Version, __T("Version ")+Ztring::ToZtring(version));
237 Fill(Stream_Video, 0, Video_Width, frameWidth);
238 Fill(Stream_Video, 0, Video_Height, frameHeight);
239 Fill(Stream_Video, 0, Video_Encoded_Library, ProRes_creatorID(creatorID));
240 Fill(Stream_Video, 0, Video_ChromaSubsampling, ProRes_chrominance_factor(chrominance_factor));
241 Fill(Stream_Video, 0, Video_ScanType, ProRes_frame_type_ScanType(frame_type));
242 Fill(Stream_Video, 0, Video_ScanOrder, ProRes_frame_type_ScanOrder(frame_type));
243 Fill(Stream_Video, 0, Video_colour_description_present, "Yes");
244 if (primaries || transf_func || colorMatrix) //Some streams have all 0 when it means unknwon, instead of assigned 2 for unknown
245 {
246 Fill(Stream_Video, 0, Video_colour_primaries, Mpegv_colour_primaries(primaries));
247 Fill(Stream_Video, 0, Video_transfer_characteristics, Mpegv_transfer_characteristics(transf_func));
248 Fill(Stream_Video, 0, Video_matrix_coefficients, Mpegv_matrix_coefficients(colorMatrix));
249 if (colorMatrix!=2)
250 Fill(Stream_Video, 0, Video_ColorSpace, Ztring().From_UTF8(Mpegv_matrix_coefficients_ColorSpace(colorMatrix))+(alpha_info?__T("A"):__T("")), true);
251 }
252 else if (chrominance_factor==2)
253 Fill(Stream_Video, 0, Video_ColorSpace, alpha_info?"YUVA":"YUV", Unlimited, true, true); //We are sure it is YUV as there is subsampling
254
255 Finish();
256 }
257 FILLING_ELSE();
258 if (!Status[IsAccepted])
259 Reject();
260 FILLING_END();
261 }
262
263 //***************************************************************************
264 // C++
265 //***************************************************************************
266
267 } //NameSpace
268
269 #endif //MEDIAINFO_PRORES_YES
270