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_DTVCCTRANSPORT_YES)
21 //---------------------------------------------------------------------------
22
23 //---------------------------------------------------------------------------
24 #include "MediaInfo/Text/File_DtvccTransport.h"
25 #if defined(MEDIAINFO_EIA608_YES)
26 #include "MediaInfo/Text/File_Eia608.h"
27 #endif
28 #if defined(MEDIAINFO_EIA708_YES)
29 #include "MediaInfo/Text/File_Eia708.h"
30 #endif
31 #if MEDIAINFO_ADVANCED || defined(MEDIAINFO_EIA608_YES) || defined(MEDIAINFO_EIA708_YES)
32 #include "MediaInfo/MediaInfo_Config_MediaInfo.h"
33 #endif
34 #if MEDIAINFO_EVENTS
35 #include "MediaInfo/MediaInfo_Events.h"
36 #endif //MEDIAINFO_EVENTS
37 //---------------------------------------------------------------------------
38
39 //---------------------------------------------------------------------------
40 namespace MediaInfoLib
41 {
42 //---------------------------------------------------------------------------
43
44 //***************************************************************************
45 // Infos
46 //***************************************************************************
47
48 //---------------------------------------------------------------------------
DtvccTransport_cc_type(int8u cc_type)49 static const char* DtvccTransport_cc_type (int8u cc_type)
50 {
51 switch (cc_type)
52 {
53 case 0 : return "CEA-608 line 21 field 1 closed captions"; //closed caption 3 if this is second field
54 case 1 : return "CEA-608 line 21 field 2 closed captions"; //closed caption 4 if this is second field
55 case 2 : return "DTVCC Channel Packet Data";
56 case 3 : return "DTVCC Channel Packet Start";
57 default : return "";
58 }
59 }
60
61 //***************************************************************************
62 // Constructor/Destructor
63 //***************************************************************************
64
65 //---------------------------------------------------------------------------
File_DtvccTransport()66 File_DtvccTransport::File_DtvccTransport()
67 :File__Analyze()
68 {
69 //Configuration
70 ParserName="DTVCC Transport";
71 #if MEDIAINFO_EVENTS
72 ParserIDs[0]=MediaInfo_Parser_DtvccTransport;
73 StreamIDs_Width[0]=1;
74 #endif //MEDIAINFO_EVENTS
75 PTS_DTS_Needed=true;
76
77 //In
78 Format=Format_Unknown;
79 AspectRatio=0;
80
81 //Temp
82 Streams.resize(3); //CEA-608 Field 1, CEA-608 Field 2, CEA-708 Channel
83 }
84
85 //---------------------------------------------------------------------------
~File_DtvccTransport()86 File_DtvccTransport::~File_DtvccTransport()
87 {
88 for (size_t Pos=0; Pos<Streams.size(); Pos++)
89 delete Streams[Pos]; //Streams[Pos]=NULL
90 }
91
92 //***************************************************************************
93 // Streams management
94 //***************************************************************************
95
96 //---------------------------------------------------------------------------
Streams_Update()97 void File_DtvccTransport::Streams_Update()
98 {
99 Clear(Stream_Text);
100
101 //Per stream
102 for (size_t Pos=0; Pos<Streams.size(); Pos++)
103 if (Streams[Pos] && Streams[Pos]->Parser && Streams[Pos]->Parser->Status[IsFilled] /*&& Streams[Pos]->Parser->Status[IsUpdated]*/ && Streams[Pos]->Parser->Count_Get(Stream_Text))
104 Streams_Update_PerStream(Pos);
105 }
106
107 //---------------------------------------------------------------------------
Streams_Update_PerStream(size_t Pos)108 void File_DtvccTransport::Streams_Update_PerStream(size_t Pos)
109 {
110 if (Streams[Pos]==NULL)
111 return;
112
113 Update(Streams[Pos]->Parser);
114
115 if (Streams[Pos]->Parser)
116 {
117 for (size_t Pos2=0; Pos2<Streams[Pos]->Parser->Count_Get(Stream_Text); Pos2++)
118 {
119 Stream_Prepare(Stream_Text);
120 Merge(*Streams[Pos]->Parser, Stream_Text, Pos2, StreamPos_Last);
121 Fill(Stream_Text, StreamPos_Last, "MuxingMode", Format==Format_DVD?__T("DVD-Video"):__T("DTVCC Transport"));
122 Fill(Stream_Text, StreamPos_Last, Text_ID, Streams[Pos]->Parser->Retrieve(Stream_Text, Pos2, Text_ID), true);
123 }
124
125 Ztring LawRating=Streams[Pos]->Parser->Retrieve(Stream_General, 0, General_LawRating);
126 if (!LawRating.empty())
127 Fill(Stream_General, 0, General_LawRating, LawRating, true);
128 Ztring Title=Streams[Pos]->Parser->Retrieve(Stream_General, 0, General_Title);
129 if (!Title.empty() && Retrieve(Stream_General, 0, General_Title).empty())
130 Fill(Stream_General, 0, General_Title, Title);
131 }
132 }
133
134 //---------------------------------------------------------------------------
Streams_Finish()135 void File_DtvccTransport::Streams_Finish()
136 {
137 Clear(Stream_Text);
138
139 if (ServiceDescriptors)
140 {
141 if (ServiceDescriptors->ServiceDescriptors608.find(0)!=ServiceDescriptors->ServiceDescriptors608.end())
142 CreateStream(0);
143 if (ServiceDescriptors->ServiceDescriptors608.find(1)!=ServiceDescriptors->ServiceDescriptors608.end())
144 CreateStream(1);
145 if (!ServiceDescriptors->ServiceDescriptors708.empty())
146 CreateStream(2);
147 }
148
149 //Per stream
150 for (size_t Pos=0; Pos<Streams.size(); Pos++)
151 if (Streams[Pos] && Streams[Pos]->Parser && Streams[Pos]->Parser->Status[IsAccepted] /*&& Streams[Pos]->Parser->Status[IsUpdated]*/)
152 {
153 Finish(Streams[Pos]->Parser);
154 Streams_Update_PerStream(Pos);
155 }
156 }
157
158 //***************************************************************************
159 // Buffer - Synchro
160 //***************************************************************************
161
162 //---------------------------------------------------------------------------
Read_Buffer_Init()163 void File_DtvccTransport::Read_Buffer_Init()
164 {
165 //Global information
166 #if defined(MEDIAINFO_EIA608_YES) || defined(MEDIAINFO_EIA708_YES)
167 Config->File_DtvccTransport_Stream_IsPresent=true;
168 #endif //defined(MEDIAINFO_EIA608_YES) || defined(MEDIAINFO_EIA708_YES)
169 }
170
171 //---------------------------------------------------------------------------
Read_Buffer_Unsynched()172 void File_DtvccTransport::Read_Buffer_Unsynched()
173 {
174 //Parsing
175 for (size_t Pos=0; Pos<Streams.size(); Pos++)
176 if (Streams[Pos] && Streams[Pos]->Parser)
177 Streams[Pos]->Parser->Open_Buffer_Unsynch();
178 }
179
180 //***************************************************************************
181 // Buffer - Global
182 //***************************************************************************
183
184 //---------------------------------------------------------------------------
Read_Buffer_Continue()185 void File_DtvccTransport::Read_Buffer_Continue()
186 {
187 //Parsing
188 Element_Begin1(Format==Format_DVD?"DVD Captions":"DTVCC Transport");
189 int8u cc_count;
190 bool process_cc_data_flag, additional_data_flag;
191 BS_Begin();
192 if (Format==Format_DVD)
193 {
194 //Modified DTVCC Transport from DVD
195 Skip_SB( "field 1 then field 2");
196 Get_S1 (7, cc_count, "cc_count");
197 process_cc_data_flag=true;
198 additional_data_flag=false;
199 }
200 else
201 {
202 //Normal DTVCC Transport
203 bool process_em_data_flag;
204 Get_SB (process_em_data_flag, "process_em_data_flag");
205 Get_SB (process_cc_data_flag, "process_cc_data_flag");
206 Get_SB (additional_data_flag, "additional_data_flag");
207 Get_S1 (5, cc_count, "cc_count");
208 Skip_S1(8, process_em_data_flag?"em_data":"reserved"); //Emergency message
209 }
210 BS_End();
211 if (process_cc_data_flag)
212 {
213 for (int8u Pos=0; Pos<cc_count; Pos++)
214 {
215 if (Element_Offset+3>Element_Size)
216 break; //Found one stream with bad cc_count, we discard cc_count without flagging the stream as untrusted for the moment
217
218 Element_Begin1("cc");
219 int8u cc_type;
220 bool cc_valid;
221 BS_Begin();
222 Mark_1();
223 Mark_1_NoTrustError();
224 Mark_1_NoTrustError();
225 Mark_1_NoTrustError();
226 Mark_1_NoTrustError();
227 if (Format==Format_DVD)
228 {
229 //Modified DTVCC Transport from DVD
230 Mark_1();
231 Mark_1();
232 Get_S1 (1, cc_type, "cc_type"); Param_Info1(DtvccTransport_cc_type(cc_type));
233 cc_valid=true;
234 }
235 else
236 {
237 //Normal DTVCC Transport
238 Get_SB ( cc_valid, "cc_valid");
239 Get_S1 (2, cc_type, "cc_type"); Param_Info1(DtvccTransport_cc_type(cc_type));
240 }
241 BS_End();
242
243 #if MEDIAINFO_ADVANCED
244 if (cc_type>=2 && !Streams[2] && Config->File_Eia708_DisplayEmptyStream_Get())
245 CreateStream(2);
246 #endif //MEDIAINFO_ADVANCED
247
248 if (cc_valid)
249 {
250 Element_Begin1("cc_data");
251 //Calculating the parser position
252 int8u Parser_Pos=cc_type==3?2:cc_type; //cc_type 2 and 3 are for the same text
253
254 //Stream creation
255 if (Streams[Parser_Pos]==NULL)
256 CreateStream(Parser_Pos);
257
258 //Parsing
259 #if MEDIAINFO_DEMUX
260 Element_Code=Parser_Pos;
261 /* //Used for debugging (CRC bit is removed of the demuxed stream)
262 int8u A[2];
263 A[0] = Buffer[Buffer_Offset+Element_Offset] & 0x7F;
264 A[1] = Buffer[Buffer_Offset + Element_Offset + 1] & 0x7F;
265 Demux(A, 2, ContentType_MainStream);
266 //*/
267 Demux(Buffer+(size_t)(Buffer_Offset+Element_Offset), 2, ContentType_MainStream);
268 #endif //MEDIAINFO_DEMUX
269 if (!Streams[Parser_Pos]->Parser->Status[IsFinished])
270 {
271 //Parsing
272 if (Streams[Parser_Pos]->Parser->PTS_DTS_Needed)
273 {
274 Streams[Parser_Pos]->Parser->FrameInfo.PCR=FrameInfo.PCR;
275 Streams[Parser_Pos]->Parser->FrameInfo.PTS=FrameInfo.PTS;
276 Streams[Parser_Pos]->Parser->FrameInfo.DTS=FrameInfo.DTS;
277 }
278 if (Parser_Pos==2)
279 {
280 #if defined(MEDIAINFO_EIA708_YES)
281 ((File_Eia708*)Streams[2]->Parser)->cc_type=cc_type;
282 if (AspectRatio)
283 ((File_Eia708*)Streams[2]->Parser)->AspectRatio=AspectRatio;
284 #endif
285 if (cc_type==3)
286 {
287 ((File_Eia708*)Streams[2]->Parser)->cc_type=4; //Magic value saying that the buffer must be kept (this is only a point of synchro from the undelying layer)
288 Open_Buffer_Continue(Streams[Parser_Pos]->Parser, Buffer+(size_t)(Buffer_Offset+Element_Offset), 0);
289 ((File_Eia708*)Streams[2]->Parser)->cc_type=3;
290 }
291 }
292 else
293 {
294 }
295 #if defined(MEDIAINFO_EIA608_YES) || defined(MEDIAINFO_EIA708_YES)
296 Streams[Parser_Pos]->Parser->ServiceDescriptors=ServiceDescriptors;
297 #endif
298 Open_Buffer_Continue(Streams[Parser_Pos]->Parser, Buffer+(size_t)(Buffer_Offset+Element_Offset), 2);
299 Element_Show();
300 Element_Offset+=2;
301 }
302 else
303 Skip_XX(2, "Data");
304 Element_End0();
305 }
306 else
307 Skip_XX(2, "Junk");
308 Element_End0();
309 }
310
311 FILLING_BEGIN();
312 if (!Status[IsAccepted])
313 Accept("DTVCC Transport");
314 FILLING_END();
315 }
316 else
317 Skip_XX(cc_count*2, "Junk");
318
319 if (Format==Format_A53_4_GA94_03)
320 {
321 //Normal DTVCC Transport
322 BS_Begin();
323 Mark_1_NoTrustError();
324 Mark_1_NoTrustError();
325 Mark_1_NoTrustError();
326 Mark_1_NoTrustError();
327 Mark_1_NoTrustError();
328 Mark_1_NoTrustError();
329 Mark_1_NoTrustError();
330 Mark_1_NoTrustError();
331 BS_End();
332
333 if (additional_data_flag)
334 {
335 Skip_XX(Element_Size-Element_Offset, "additional_user_data");
336 }
337
338 while (Element_Offset<Element_Size)
339 {
340 Skip_B1( "Zero"); //TODO: test Zero
341 }
342 }
343
344 Element_End0();
345 }
346
347 //***************************************************************************
348 // Helpers
349 //***************************************************************************
350
351 //---------------------------------------------------------------------------
CreateStream(int8u Parser_Pos)352 void File_DtvccTransport::CreateStream(int8u Parser_Pos)
353 {
354 if (Streams[Parser_Pos])
355 return; //Already done
356
357 //Parsing
358 #if MEDIAINFO_DEMUX
359 Element_Code=Parser_Pos;
360 #endif //MEDIAINFO_DEMUX
361
362 //Creation of the parser
363 Streams[Parser_Pos]=new stream;
364 #if defined(MEDIAINFO_EIA608_YES) || defined(MEDIAINFO_EIA708_YES)
365 if (Parser_Pos<2)
366 {
367 #if defined(MEDIAINFO_EIA608_YES)
368 Streams[Parser_Pos]->Parser=new File_Eia608();
369 ((File_Eia608*)Streams[Parser_Pos]->Parser)->cc_type=Parser_Pos;
370 #else //defined(MEDIAINFO_EIA608_YES)
371 Streams[Parser_Pos]->Parser=new File__Analyze();
372 #endif //defined(MEDIAINFO_EIA608_YES)
373 }
374 else
375 {
376 #if defined(MEDIAINFO_EIA708_YES)
377 Streams[Parser_Pos]->Parser=new File_Eia708();
378 #else //defined(MEDIAINFO_EIA708_YES)
379 Streams[Parser_Pos]->Parser=new File__Analyze();
380 #endif //defined(MEDIAINFO_EIA708_YES)
381 }
382 #else //defined(MEDIAINFO_EIA608_YES) || defined(MEDIAINFO_EIA708_YES)
383 Streams[Parser_Pos]->Parser=new File__Analyze();
384 #endif //defined(MEDIAINFO_EIA608_YES) || defined(MEDIAINFO_EIA708_YES)
385
386 //Init
387 Streams[Parser_Pos]->Parser->ServiceDescriptors=ServiceDescriptors;
388 Open_Buffer_Init(Streams[Parser_Pos]->Parser);
389 Streams[Parser_Pos]->Parser->Accept();
390 }
391
392 //***************************************************************************
393 // C++
394 //***************************************************************************
395
396 } //NameSpace
397
398 #endif //MEDIAINFO_DTVCCTRANSPORT_YES
399
400