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