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