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