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_CDXA_YES)
21 //---------------------------------------------------------------------------
22 
23 //---------------------------------------------------------------------------
24 #include "MediaInfo/Multiple/File_Cdxa.h"
25 #include "ZenLib/Utils.h"
26 #include "MediaInfo/MediaInfo_Internal.h"
27 #if MEDIAINFO_EVENTS
28     #include "MediaInfo/MediaInfo_Events.h"
29 #endif //MEDIAINFO_EVENTS
30 using namespace ZenLib;
31 //---------------------------------------------------------------------------
32 
33 namespace MediaInfoLib
34 {
35 
36 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
37 // Format
38 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
39 //
40 // CDXA = RIFF header + Raw sectors
41 // Riff header size = 44
42 // Raw sector size = 2352
43 //
44 // Raw sector :
45 // Sync             12 bytes (00 FF .. FF 00)
46 // Header           4 bytes
47 // SubHeader        8 bytes
48 // Datas            2324 bytes
49 // EDC (CRC)        4 bytes
50 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
51 
52 //***************************************************************************
53 // Constructor/Destructor
54 //***************************************************************************
55 
56 //---------------------------------------------------------------------------
File_Cdxa()57 File_Cdxa::File_Cdxa()
58 :File__Analyze()
59 {
60     //Configuration
61     ParserName="CDXA";
62     #if MEDIAINFO_EVENTS
63         ParserIDs[0]=MediaInfo_Parser_Cdxa;
64         StreamIDs_Width[0]=0;
65     #endif //MEDIAINFO_EVENTS
66     MustSynchronize=true;
67 
68     //Temp
69     MI=NULL;
70 }
71 
72 //---------------------------------------------------------------------------
~File_Cdxa()73 File_Cdxa::~File_Cdxa()
74 {
75     delete MI; //MI=NULL;
76 }
77 
78 //***************************************************************************
79 // Buffer - File header
80 //***************************************************************************
81 // RIFF Header, 44 bytes
82 // RIFF header                      4 bytes, Pos=0
83 // RIFF data size                   4 bytes, Pos=4
84 // Format (CDXA)                    4 bytes, Pos=8
85 // Format Header                    4 bytes, Pos=12
86 // Format Size                      4 bytes, Pos=16
87 // Format user_id                   2 bytes, Pos=20
88 // Format group_id                  2 bytes, Pos=22
89 // Format attributes                2 bytes, Pos=24
90 // Format xa_signature              2 bytes, Pos=26 ("XA")
91 // Format xa_track_number           4 bytes, Pos=28
92 // Format Reserved                  4 bytes, Pos=32
93 // Data Header                      4 bytes, Pos=36
94 // Data Size                        4 bytes, Pos=40
95 //
96 // Attributes (big endian):
97 // 15 Directory
98 // 14 CDDA
99 // 13 Interleaved
100 // 12 Mode2Form2 --> 2324 bytes/block
101 // 11 Mode2Form1 --> 2048 bytes/block
102 // 10 Exec_Other
103 // 09 Reserved
104 // 08 Read_Other
105 // 07 Reserved
106 // 06 Exec_Group
107 // 05 Reserved
108 // 04 Read_Group
109 // 03 Reserved
110 // 02 Exec_User
111 // 01 Reserved
112 // 00 Read_User
113 
114 //---------------------------------------------------------------------------
FileHeader_Begin()115 bool File_Cdxa::FileHeader_Begin()
116 {
117     //Element_Size
118     if (Buffer_Size<0x28)
119         return false; //Must wait for more data
120 
121     if (                CC4(Buffer+0x00)!=0x52494646  //"RIFF"
122      || LittleEndian2int32u(Buffer+0x04)!=LittleEndian2int32u(Buffer+0x28)+0x24 //Sizes of chunks
123      ||                 CC4(Buffer+0x08)!=0x43445841  //"CDXA"
124      ||                 CC4(Buffer+0x0C)!=0x666D7420  //"fmt "
125      || LittleEndian2int32u(Buffer+0x10)!=0x10
126      ||                 CC2(Buffer+0x1A)!=0x5841      //"XA"
127      ||                 CC4(Buffer+0x24)!=0x64617461) //"data"
128     {
129         Reject("CDXA");
130         return false;
131     }
132 
133     //All should be OK...
134     return true;
135 }
136 
137 //---------------------------------------------------------------------------
FileHeader_Parse()138 void File_Cdxa::FileHeader_Parse()
139 {
140     //Parsing
141     Skip_C4(                                                    "RIFF header");
142     Skip_L4(                                                    "RIFF data size");
143     Skip_C4(                                                    "CDXA");
144     Skip_C4(                                                    "fmt header");
145     Skip_L4(                                                    "fmt size");
146     Skip_L2(                                                    "user_id");
147     Skip_L2(                                                    "group_id");
148     Skip_L2(                                                    "attributes");
149     Skip_C2(                                                    "xa_signature");
150     Skip_L4(                                                    "xa_track_number");
151     Skip_L4(                                                    "reserved");
152     Skip_C4(                                                    "data header");
153     Skip_L4(                                                    "data size");
154 
155     FILLING_BEGIN();
156         Accept("CDXA");
157         MI=new MediaInfo_Internal;
158         MI->Option(__T("FormatDetection_MaximumOffset"), __T("1048576"));
159         MI->Option(__T("File_IsReferenced"), __T("1"));
160         //MI->Option(__T("File_IsSub"), __T("1"));
161         MI->Open_Buffer_Init(File_Size, File_Offset+Buffer_Offset);
162     FILLING_END();
163 }
164 
165 //***************************************************************************
166 // Buffer - Synchro
167 //***************************************************************************
168 
169 //---------------------------------------------------------------------------
Synchronize()170 bool File_Cdxa::Synchronize()
171 {
172     //Synchronizing
173     while (           Buffer_Offset+2352*3+12<=Buffer_Size
174       && !(CC8(Buffer+Buffer_Offset+2352*0)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+2352*0+8)==0xFFFFFF00
175         && CC8(Buffer+Buffer_Offset+2352*1)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+2352*1+8)==0xFFFFFF00
176         && CC8(Buffer+Buffer_Offset+2352*2)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+2352*2+8)==0xFFFFFF00
177         && CC8(Buffer+Buffer_Offset+2352*3)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+2352*3+8)==0xFFFFFF00))
178         Buffer_Offset++;
179     if (Buffer_Offset+2352*3+12>Buffer_Size)
180         return false;
181 
182     //Synched is OK
183     return true;
184 }
185 
186 //---------------------------------------------------------------------------
Synched_Test()187 bool File_Cdxa::Synched_Test()
188 {
189     //Must have enough buffer for having header
190     if (Buffer_Offset+12>Buffer_Size)
191         return false;
192 
193     //Quick test of synchro
194     if (!(CC8(Buffer+Buffer_Offset)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+8)==0xFFFFFF00))
195         Synched=false;
196 
197     //We continue
198     return true;
199 }
200 
201 //***************************************************************************
202 // Streams management
203 //***************************************************************************
204 
205 //---------------------------------------------------------------------------
Streams_Finish()206 void File_Cdxa::Streams_Finish ()
207 {
208     if (!MI)
209         return;
210 
211     //If nothing
212     if (MI->Info==NULL || !MI->Info->Status[IsAccepted])
213     {
214         Fill(Stream_General, 0, General_Format, "CDXA");
215     }
216     else
217     {
218 
219         //General
220         MI->Info->Open_Buffer_Finalize();
221         Merge(*(MI->Info));
222         Merge(*(MI->Info), Stream_General, 0, 0);
223         const Ztring &Format=Retrieve(Stream_General, 0, General_Format);
224         Fill(Stream_General, 0, General_Format, (Ztring(__T("CDXA/"))+Format).c_str(), Unlimited, true);
225         Clear(Stream_General, 0, General_Duration);
226         Clear(Stream_Video, 0, Video_Duration);
227     }
228 
229     //Purge what is not needed anymore
230     if (!File_Name.empty()) //Only if this is not a buffer, with buffer we can have more data
231     {
232         delete MI; MI=NULL;
233     }
234 }
235 
236 //***************************************************************************
237 // Buffer - Per element
238 //***************************************************************************
239 
240 //---------------------------------------------------------------------------
Header_Parse()241 void File_Cdxa::Header_Parse()
242 {
243     //Parsing
244     Skip_B4(                                                    "Sync1");
245     Skip_B4(                                                    "Sync2");
246     Skip_B4(                                                    "Sync3");
247     Skip_B4(                                                    "Header");
248     Skip_B8(                                                    "SubHeader");
249 
250     //Filling
251     Header_Fill_Size(2352);
252     Header_Fill_Code(0, "Chunk");
253 }
254 
255 //---------------------------------------------------------------------------
Data_Parse()256 void File_Cdxa::Data_Parse()
257 {
258     if (MI==NULL)
259     {
260         //Where is the header? --> Problem
261         Reject("CDXA");
262         return;
263     }
264 
265     //CRC or not?
266     int64u CRC_Size=4;
267     if (Element_Size!=2328)
268         CRC_Size=0;
269 
270     //Parsing
271     Skip_XX(Element_Size-CRC_Size,                              "Data");
272     if (CRC_Size>0)
273         Skip_B4(                                                "CRC");
274 
275     //Preparing to fill MediaInfo with a buffer
276     MI->Open_Buffer_Position_Set(File_Offset+Buffer_Offset);
277 
278     //Sending the buffer to MediaInfo
279     MI->Open_Buffer_Continue(Buffer+Buffer_Offset, (size_t)(Element_Size-CRC_Size));
280 
281     //Testing if filled
282     if (MI->Info->Status[IsFilled]) {
283 
284     }
285 
286     //Testing if MediaInfo always need data
287     File_GoTo=MI->Open_Buffer_Continue_GoTo_Get();
288     if (File_GoTo==(int64u)-1 && MI->Info->Status[IsFilled] && File_Size!=(int64u)-1 && File_Offset+Buffer_Size<File_Size/2)
289         GoToFromEnd(File_Offset+Buffer_Size);
290     if (File_GoTo!=(int64u)-1)
291         Info("CDXA, Jumping to end of file");
292 
293     //Details
294     #if MEDIAINFO_TRACE
295     if (Config_Trace_Level)
296     {
297         if (!MI->Inform().empty())
298             Element_Show_Add(MI->Info);
299     }
300     #endif //MEDIAINFO_TRACE
301 
302     //Demux
303     Demux(Buffer+Buffer_Offset, (size_t)(Element_Size-CRC_Size), ContentType_MainStream);
304 }
305 
306 } //NameSpace
307 
308 #endif //MEDIAINFO_CDXA_YES
309 
310