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_MPEG7_YES)
21 //---------------------------------------------------------------------------
22 
23 //---------------------------------------------------------------------------
24 #include "MediaInfo/Export/Export_Mpeg7.h"
25 #include "MediaInfo/File__Analyse_Automatic.h"
26 #include "MediaInfo/OutputHelpers.h"
27 #include <ctime>
28 using namespace std;
29 //---------------------------------------------------------------------------
30 
31 namespace MediaInfoLib
32 {
33 
34 //---------------------------------------------------------------------------
35 extern MediaInfo_Config Config;
36 //---------------------------------------------------------------------------
37 
38 //***************************************************************************
39 // Infos
40 //***************************************************************************
41 
42 //---------------------------------------------------------------------------
Mpeg7_TimeToISO(Ztring Value)43 static Ztring Mpeg7_TimeToISO(Ztring Value)
44 {
45     if (Value.size()>=3 && Value[0]==__T('U') && Value[1]==__T('T') && Value[2]==__T('C') && Value[3]==__T(' '))
46     {
47         Value.erase(0, 4);
48         Value+=__T("+00:00");
49     }
50     if (Value.size()>11 && Value[10]==__T(' '))
51         Value[10]=__T('T');
52     if (Value.size() > 19 && Value[19] == __T('.')) //Milliseconds are valid ISO but MPEG-7 XSD does not like them
53         Value.erase(19, Value.find_first_not_of(__T("0123456789"), 20)-19);
54     return Value;
55 }
56 
57 //---------------------------------------------------------------------------
Mpeg7_TimeToISO_Isvalid(Ztring & TimePoint)58 static bool Mpeg7_TimeToISO_Isvalid(Ztring& TimePoint)
59 {
60     if (TimePoint.size()<=3)
61        return false;
62     else if (!(TimePoint[0]>=__T('0') && TimePoint[0]<=__T('9')
63             && TimePoint[1]>=__T('0') && TimePoint[1]<=__T('9')
64             && TimePoint[2]>=__T('0') && TimePoint[2]<=__T('9')
65             && TimePoint[3]>=__T('0') && TimePoint[3]<=__T('9')))
66        return false;
67     else if (TimePoint.size()>4)
68     {
69         if (TimePoint.size()<=6)
70            return false;
71         else if (!(TimePoint[4]==__T('-')
72                 && TimePoint[5]>=__T('0') && TimePoint[5]<=__T('9')
73                 && TimePoint[6]>=__T('0') && TimePoint[6]<=__T('9')))
74            return false;
75         else if (TimePoint.size()>7)
76         {
77             if (TimePoint.size()<=9)
78                return false;
79             else if (!(TimePoint[7]==__T('-')
80                     && TimePoint[8]>=__T('0') && TimePoint[8]<=__T('9')
81                     && TimePoint[9]>=__T('0') && TimePoint[9]<=__T('9')))
82                return false;
83             else if (TimePoint.size()>10)
84             {
85                 if (TimePoint.size()<=12)
86                    return false;
87                 else if (!(TimePoint[10]==__T('T')
88                         && TimePoint[11]>=__T('0') && TimePoint[11]<=__T('9')
89                         && TimePoint[12]>=__T('0') && TimePoint[12]<=__T('9')))
90                    return false;
91                 else if (TimePoint.size()>13)
92                 {
93                     if (TimePoint.size()<=15)
94                        return false;
95                     else if (!(TimePoint[13]==__T(':')
96                             && TimePoint[14]>=__T('0') && TimePoint[14]<=__T('9')
97                             && TimePoint[15]>=__T('0') && TimePoint[15]<=__T('9')))
98                        return false;
99                     else if (TimePoint.size()>16)
100                     {
101                         if (TimePoint.size()<=18)
102                            return false;
103                         else if (!(TimePoint[16]==__T(':')
104                                 && TimePoint[17]>=__T('0') && TimePoint[17]<=__T('9')
105                                 && TimePoint[18]>=__T('0') && TimePoint[18]<=__T('9')))
106                            return false;
107                         else if (TimePoint.size()>19)
108                         {
109                             if (TimePoint.size()==20 && TimePoint[19]==__T('Z'))
110                             {
111                                 TimePoint[19]=__T('+');
112                                 TimePoint+=__T("00:00");
113                             }
114                             else if (TimePoint.size()<=24)
115                                return false;
116                             else if (!((TimePoint[19]==__T('+') || TimePoint[19]==__T('-'))
117                                     && TimePoint[20]>=__T('0') && TimePoint[20]<=__T('9')
118                                     && TimePoint[21]>=__T('0') && TimePoint[21]<=__T('9')
119                                     && TimePoint[22]>=__T(':')
120                                     && TimePoint[23]>=__T('0') && TimePoint[23]<=__T('9')
121                                     && TimePoint[24]>=__T('0') && TimePoint[24]<=__T('9')))
122                                return false;
123                         }
124                     }
125                 }
126             }
127         }
128     }
129     return true;
130 }
131 
132 //---------------------------------------------------------------------------
Mpeg7_Type(MediaInfo_Internal & MI)133 const Char* Mpeg7_Type(MediaInfo_Internal &MI) //TO ADAPT
134 {
135     if (MI.Count_Get(Stream_Image))
136     {
137         if (MI.Count_Get(Stream_Video) || MI.Count_Get(Stream_Audio))
138             return __T("Multimedia");
139         else
140             return __T("Image");
141     }
142     else if (MI.Count_Get(Stream_Video))
143     {
144         if (MI.Count_Get(Stream_Audio))
145             return __T("AudioVisual");
146         else
147             return __T("Video");
148     }
149     else if (MI.Count_Get(Stream_Audio))
150         return __T("Audio");
151 
152     //Not known
153     const Ztring &Format=MI.Get(Stream_General, 0, General_Format);
154     if (Format==__T("AVI") || Format==__T("DV") || Format==__T("MPEG-4") || Format==__T("MPEG-PS") || Format==__T("MPEG-TS") || Format==__T("QuickTime") || Format==__T("Windows Media"))
155         return __T("Video");
156     if (Format==__T("MPEG Audio") || Format==__T("Wave"))
157         return __T("Audio");
158     if (Format==__T("BMP") || Format==__T("GIF") || Format==__T("JPEG") || Format==__T("JPEG 2000") || Format==__T("PNG") || Format==__T("TIFF"))
159         return __T("Image");
160     return __T("Multimedia");
161 }
162 
163 //---------------------------------------------------------------------------
Mpeg7_ContentCS_termID(MediaInfo_Internal & MI,size_t)164 int32u Mpeg7_ContentCS_termID(MediaInfo_Internal &MI, size_t)
165 {
166     if (MI.Count_Get(Stream_Image))
167     {
168         if (MI.Count_Get(Stream_Video) || MI.Count_Get(Stream_Audio))
169             return 20000;
170         else
171             return 40100;
172     }
173     else if (MI.Count_Get(Stream_Video))
174     {
175         if (MI.Count_Get(Stream_Audio))
176             return 20000;
177         else
178             return 40200;
179     }
180     else if (MI.Count_Get(Stream_Audio))
181         return 10000;
182 
183     //Not known
184     const Ztring &Format=MI.Get(Stream_General, 0, General_Format);
185     if (Format==__T("AVI") || Format==__T("DV") || Format==__T("MPEG-4") || Format==__T("MPEG-PS") || Format==__T("MPEG-TS") || Format==__T("QuickTime") || Format==__T("Windows Media"))
186         return 40200;
187     if (Format==__T("MPEG Audio") || Format==__T("Wave"))
188         return 10000;
189     if (Format==__T("BMP") || Format==__T("GIF") || Format==__T("JPEG") || Format==__T("JPEG 2000") || Format==__T("PNG") || Format==__T("TIFF"))
190         return 40100;
191     return 0;
192 }
193 
Mpeg7_ContentCS_Name(int32u termID,MediaInfo_Internal & MI,size_t)194 Ztring Mpeg7_ContentCS_Name(int32u termID, MediaInfo_Internal &MI, size_t) //xxyyzz: xx=main number, yy=sub-number, zz=sub-sub-number
195 {
196     switch (termID/10000)
197     {
198         case  1 : return __T("Audio");
199         case  2 : return __T("Audiovisual");
200         case  3 : return __T("Scene");
201         case  4 :   switch ((termID%10000)/100)
202                     {
203                         case 1 : return __T("Image");
204                         case 2 : return __T("Video");
205                         case 3 : return __T("Graphics");
206                     }
207         default : return MI.Get(Stream_General, 0, General_FileExtension);
208     }
209 }
210 
211 //---------------------------------------------------------------------------
Mpeg7_FileFormatCS_termID_MediaInfo(MediaInfo_Internal & MI)212 int32u Mpeg7_FileFormatCS_termID_MediaInfo(MediaInfo_Internal &MI)
213 {
214     const Ztring &Format=MI.Get(Stream_General, 0, General_Format);
215 
216     if (Format==__T("MPEG Audio"))
217     {
218         if (MI.Get(Stream_Audio, 0, Audio_Format_Profile).find(__T('2'))!=string::npos)
219             return 500000; //mp2
220         if (MI.Get(Stream_Audio, 0, Audio_Format_Profile).find(__T('1'))!=string::npos)
221             return 510000; //mp1
222         return 0;
223     }
224     if (Format==__T("Wave"))
225     {
226         if (MI.Get(Stream_General, 0, General_Format_Profile)==__T("RF64"))
227         {
228             if (!MI.Get(Stream_General, 0, __T("bext_Present")).empty())
229                 return 520100; // Wav (RF64) with bext
230             return 520000; //Wav (RF64)
231         }
232         else if (!MI.Get(Stream_General, 0, __T("bext_Present")).empty())
233             return 90100;
234     }
235     if (Format==__T("Wave64"))
236         return 530000;
237     if (Format==__T("DSF"))
238         return 540000;
239     if (Format==__T("DSDIFF"))
240         return 550000;
241     if (Format==__T("FLAC"))
242         return 560000;
243     if (Format==__T("AIFF"))
244         return 570000;
245     return 0;
246 }
247 
248 //---------------------------------------------------------------------------
Mpeg7_FileFormatCS_termID(MediaInfo_Internal & MI,size_t)249 int32u Mpeg7_FileFormatCS_termID(MediaInfo_Internal &MI, size_t)
250 {
251     const Ztring &Format=MI.Get(Stream_General, 0, General_Format);
252 
253     if (Format==__T("AVI"))
254         return 70000;
255     if (Format==__T("BMP"))
256         return 110000;
257     if (Format==__T("GIF"))
258         return 120000;
259     if (Format==__T("DV"))
260         return 60000;
261     if (Format==__T("JPEG"))
262         return 10000;
263     if (Format==__T("JPEG 2000"))
264         return 20000;
265     if (Format==__T("MPEG Audio"))
266         return (MI.Get(Stream_Audio, 0, Audio_Format_Profile).find(__T('3'))!=string::npos)?40000:0;
267     if (Format==__T("MPEG-4"))
268         return 50000;
269     if (Format==__T("MPEG-PS"))
270         return 30100;
271     if (Format==__T("MPEG-TS"))
272         return 30200;
273     if (Format==__T("PNG"))
274         return 150000;
275     if (Format==__T("QuickTime"))
276         return 160000;
277     if (Format==__T("TIFF"))
278         return 180000;
279     if (Format==__T("Wave"))
280     {
281         if (!MI.Get(Stream_General, 0, General_Format_Profile).empty() || !MI.Get(Stream_General, 0, __T("bext_Present")).empty())
282             return Mpeg7_FileFormatCS_termID_MediaInfo(MI); //Out of specs
283         else
284             return 90000;
285     }
286     if (Format==__T("Windows Media"))
287         return 190000;
288     if (Format==__T("ZIP"))
289         return 100000;
290 
291     //Out of specs
292     return Mpeg7_FileFormatCS_termID_MediaInfo(MI);
293 }
294 
Mpeg7_FileFormatCS_Name(int32u termID,MediaInfo_Internal & MI,size_t)295 Ztring Mpeg7_FileFormatCS_Name(int32u termID, MediaInfo_Internal &MI, size_t) //xxyyzz: xx=main number, yy=sub-number, zz=sub-sub-number
296 {
297     switch (termID/10000)
298     {
299         case  1 : return __T("jpeg");
300         case  2 : return __T("JPEG 2000");
301         case  3 :   switch ((termID%10000)/100)
302                     {
303                         case 1 : return __T("mpeg-ps");
304                         case 2 : return __T("mpeg-ts");
305                         default: return __T("mpeg");
306                     }
307         case  4 : return __T("mp3");
308         case  5 : return __T("mp4");
309         case  6 : return __T("dv");
310         case  7 : return __T("avi");
311         case  8 : return __T("bdf");
312         case  9 :   switch ((termID%10000)/100)
313                     {
314                         case 1 : return __T("bwf");
315                         default: return __T("wav");
316                     }
317         case 10 : return __T("zip");
318         case 11 : return __T("bmp");
319         case 12 : return __T("gif");
320         case 13 : return __T("photocd");
321         case 14 : return __T("ppm");
322         case 15 : return __T("png");
323         case 16 : return __T("quicktime");
324         case 17 : return __T("spiff");
325         case 18 : return __T("tiff");
326         case 19 : return __T("asf");
327         case 20 : return __T("iff");
328         case 21 : return __T("miff");
329         case 22 : return __T("pcx");
330         //Out of specs --> MediaInfo CS
331         case 50 : return __T("mp1");
332         case 51 : return __T("mp2");
333         case 52:   switch ((termID%10000)/100)
334                     {
335                         case 1 : return __T("mbwf");
336                         default: return __T("wav-rf64");
337                     }
338         case 53 : return __T("wave64");
339         case 54 : return __T("dsf");
340         case 55 : return __T("dsdiff");
341         case 56 : return __T("flac");
342         case 57 : return __T("aiff");
343         default : return MI.Get(Stream_General, 0, General_Format);
344     }
345 }
346 
347 //---------------------------------------------------------------------------
Mpeg7_VisualCodingFormatCS_termID_MediaInfo(MediaInfo_Internal & MI,size_t StreamPos)348 int32u Mpeg7_VisualCodingFormatCS_termID_MediaInfo(MediaInfo_Internal &MI, size_t StreamPos)
349 {
350     const Ztring &Format=MI.Get(Stream_Video, StreamPos, Video_Format);
351 
352     if (Format==__T("AVC"))
353         return 500000;
354     if (Format==__T("HEVC"))
355         return 510000;
356     if (Format==__T("WMV"))
357         return 520000;
358     if (Format==__T("WMV2"))
359         return 530000;
360     if (Format==__T("ProRes"))
361         return 540000;
362     return 0;
363 }
364 
365 //---------------------------------------------------------------------------
Mpeg7_VisualCodingFormatCS_termID(MediaInfo_Internal & MI,size_t StreamPos)366 int32u Mpeg7_VisualCodingFormatCS_termID(MediaInfo_Internal &MI, size_t StreamPos)
367 {
368     const Ztring &Format=MI.Get(Stream_Video, StreamPos, Video_Format);
369     const Ztring &Version=MI.Get(Stream_Video, StreamPos, Video_Format_Version);
370     const Ztring &Profile=MI.Get(Stream_Video, StreamPos, Video_Format_Profile);
371 
372     if (Format==__T("MPEG Video"))
373     {
374         if (Version.find(__T('1'))!=string::npos)
375             return 10000;
376         if (Version.find(__T('2'))!=string::npos)
377         {
378             if (Profile.find(__T("Simple@"))!=string::npos)
379             {
380                 if (Profile.find(__T("Main"))!=string::npos)
381                     return 20101;
382                 return 20100;
383             }
384             if (Profile.find(__T("Main@"))!=string::npos)
385             {
386                 if (Profile.find(__T("Low"))!=string::npos)
387                     return 20201;
388                 if (Profile.find(__T("@Main"))!=string::npos)
389                     return 20202;
390                 if (Profile.find(__T("High 1440"))!=string::npos)
391                     return 20203;
392                 if (Profile.find(__T("High"))!=string::npos)
393                     return 20204;
394                 return 20200;
395             }
396             if (Profile.find(__T("SNR Scalable@"))!=string::npos)
397             {
398                 if (Profile.find(__T("Low"))!=string::npos)
399                     return 20301;
400                 if (Profile.find(__T("Main"))!=string::npos)
401                     return 20302;
402                 return 20300;
403             }
404             if (Profile.find(__T("Spatial Sclable@"))!=string::npos)
405             {
406                 if (Profile.find(__T("Main"))!=string::npos)
407                     return 20401;
408                 if (Profile.find(__T("High 1440"))!=string::npos)
409                     return 20402;
410                 if (Profile.find(__T("High"))!=string::npos)
411                     return 20403;
412                 return 20400;
413             }
414             if (Profile.find(__T("High@"))!=string::npos)
415             {
416                 if (Profile.find(__T("Main"))!=string::npos)
417                     return 20501;
418                 if (Profile.find(__T("High 1440"))!=string::npos)
419                     return 20502;
420                 if (Profile.find(__T("High"))!=string::npos)
421                     return 20503;
422                 return 20500;
423             }
424             if (Profile.find(__T("Multi-view@"))!=string::npos)
425             {
426                 if (Profile.find(__T("Main"))!=string::npos)
427                     return 20601;
428                 return 20600;
429             }
430             if (Profile.find(__T("4:2:2@"))!=string::npos)
431             {
432                 if (Profile.find(__T("Main"))!=string::npos)
433                     return 20701;
434                 return 20700;
435             }
436             return 20000;
437         }
438     }
439     if (Format==__T("MPEG-4 Visual"))
440     {
441         if (Profile.find(__T("Simple@"))==0)
442         {
443             if (Profile.find(__T("L0"))!=string::npos)
444                 return 30101;
445             if (Profile.find(__T("L1"))!=string::npos)
446                 return 30102;
447             if (Profile.find(__T("L2"))!=string::npos)
448                 return 30103;
449             if (Profile.find(__T("L3"))!=string::npos)
450                 return 30104;
451             if (Profile.find(__T("L4"))!=string::npos)
452                 return 30105;
453             if (Profile.find(__T("L5"))!=string::npos)
454                 return 30106;
455             return 30100;
456         }
457         if (Profile.find(__T("Simple Scalable@"))==0)
458         {
459             if (Profile.find(__T("L1"))!=string::npos)
460                 return 30201;
461             if (Profile.find(__T("L2"))!=string::npos)
462                 return 30202;
463             if (Profile.find(__T("L3"))!=string::npos)
464                 return 30203;
465             return 30200;
466         }
467         if (Profile.find(__T("Advanced Simple@"))==0)
468         {
469             if (Profile.find(__T("L0"))!=string::npos)
470                 return 30301;
471             if (Profile.find(__T("L1"))!=string::npos)
472                 return 30302;
473             if (Profile.find(__T("L2"))!=string::npos)
474                 return 30303;
475             if (Profile.find(__T("L3"))!=string::npos)
476                 return 30304;
477             if (Profile.find(__T("L4"))!=string::npos)
478                 return 30305;
479             if (Profile.find(__T("L5"))!=string::npos)
480                 return 30306;
481             return 30100;
482         }
483         if (Profile.find(__T("Core@"))==0)
484         {
485             if (Profile.find(__T("L1"))!=string::npos)
486                 return 30401;
487             if (Profile.find(__T("L2"))!=string::npos)
488                 return 30402;
489             return 30400;
490         }
491         if (Profile.find(__T("Core Scalable@"))==0)
492         {
493             if (Profile.find(__T("L1"))!=string::npos)
494                 return 30501;
495             if (Profile.find(__T("L2"))!=string::npos)
496                 return 30502;
497             if (Profile.find(__T("L3"))!=string::npos)
498                 return 30503;
499             return 30500;
500         }
501         if (Profile.find(__T("Advanced Core@"))==0)
502         {
503             if (Profile.find(__T("L1"))!=string::npos)
504                 return 30601;
505             if (Profile.find(__T("L2"))!=string::npos)
506                 return 30602;
507             return 30600;
508         }
509         if (Profile.find(__T("Main@"))==0)
510         {
511             if (Profile.find(__T("L2"))!=string::npos)
512                 return 30701;
513             if (Profile.find(__T("L3"))!=string::npos)
514                 return 30702;
515             if (Profile.find(__T("L4"))!=string::npos)
516                 return 30703;
517             return 30700;
518         }
519         if (Profile.find(__T("N-bit@"))==0)
520         {
521             if (Profile.find(__T("L2"))!=string::npos)
522                 return 30801;
523             return 30800;
524         }
525         if (Profile.find(__T("Advanced Real Time Simple@"))==0)
526         {
527             if (Profile.find(__T("L1"))!=string::npos)
528                 return 30901;
529             if (Profile.find(__T("L2"))!=string::npos)
530                 return 30902;
531             if (Profile.find(__T("L3"))!=string::npos)
532                 return 30903;
533             if (Profile.find(__T("L4"))!=string::npos)
534                 return 30904;
535             return 30900;
536         }
537         if (Profile.find(__T("Advanced Coding Efficiency@"))==0)
538         {
539             if (Profile.find(__T("L1"))!=string::npos)
540                 return 31001;
541             if (Profile.find(__T("L2"))!=string::npos)
542                 return 31002;
543             if (Profile.find(__T("L3"))!=string::npos)
544                 return 31003;
545             if (Profile.find(__T("L4"))!=string::npos)
546                 return 31004;
547             return 31000;
548         }
549         if (Profile.find(__T("Simple Studio@"))==0)
550         {
551             if (Profile.find(__T("L1"))!=string::npos)
552                 return 31101;
553             if (Profile.find(__T("L2"))!=string::npos)
554                 return 31102;
555             if (Profile.find(__T("L3"))!=string::npos)
556                 return 31103;
557             if (Profile.find(__T("L4"))!=string::npos)
558                 return 31104;
559             return 31100;
560         }
561         if (Profile.find(__T("Core Studio@"))==0)
562         {
563             if (Profile.find(__T("L1"))!=string::npos)
564                 return 31201;
565             if (Profile.find(__T("L2"))!=string::npos)
566                 return 31202;
567             if (Profile.find(__T("L3"))!=string::npos)
568                 return 31203;
569             if (Profile.find(__T("L4"))!=string::npos)
570                 return 31204;
571             return 31200;
572         }
573         if (Profile.find(__T("Fine Granularity Scalable@"))==0)
574         {
575             if (Profile.find(__T("L0"))!=string::npos)
576                 return 31301;
577             if (Profile.find(__T("L1"))!=string::npos)
578                 return 31302;
579             if (Profile.find(__T("L2"))!=string::npos)
580                 return 31303;
581             if (Profile.find(__T("L3"))!=string::npos)
582                 return 31304;
583             if (Profile.find(__T("L4"))!=string::npos)
584                 return 31305;
585             if (Profile.find(__T("L5"))!=string::npos)
586                 return 31306;
587             return 31300;
588         }
589         if (Profile.find(__T("Simple Face Animation@"))==0)
590         {
591             if (Profile.find(__T("L1"))!=string::npos)
592                 return 31401;
593             if (Profile.find(__T("L2"))!=string::npos)
594                 return 31402;
595             return 31400;
596         }
597         if (Profile.find(__T("Simple FBA@"))==0)
598         {
599             if (Profile.find(__T("L1"))!=string::npos)
600                 return 31501;
601             if (Profile.find(__T("L2"))!=string::npos)
602                 return 31502;
603             return 31500;
604         }
605         if (Profile.find(__T("Basic Animated Texture@"))==0)
606         {
607             if (Profile.find(__T("L1"))!=string::npos)
608                 return 31601;
609             if (Profile.find(__T("L2"))!=string::npos)
610                 return 31602;
611             return 31600;
612         }
613         if (Profile.find(__T("Scalable Texture@"))==0)
614         {
615             if (Profile.find(__T("L1"))!=string::npos)
616                 return 31701;
617             return 31700;
618         }
619         if (Profile.find(__T("Advanced Scalable Texture@"))==0)
620         {
621             if (Profile.find(__T("L1"))!=string::npos)
622                 return 31801;
623             if (Profile.find(__T("L2"))!=string::npos)
624                 return 31802;
625             if (Profile.find(__T("L3"))!=string::npos)
626                 return 31803;
627             return 31800;
628         }
629         if (Profile.find(__T("Hybrid@"))==0)
630         {
631             if (Profile.find(__T("L1"))!=string::npos)
632                 return 31901;
633             if (Profile.find(__T("L2"))!=string::npos)
634                 return 31902;
635             return 31900;
636         }
637         return 30000;
638     }
639     if (Format==__T("JPEG"))
640         return 50000;
641     if (Format==__T("JPEG 2000"))
642     {
643         const Ztring &CodecID=MI.Get(Stream_Video, StreamPos, Video_CodecID);
644         if (CodecID==__T("mjp2"))
645             return 60100;
646         if (CodecID==__T("mjs2"))
647             return 60200;
648         return 60000;
649     }
650     if (Format==__T("H.261"))
651         return 70000;
652     if (Format==__T("H.263"))
653         return 80000;
654 
655     //Out of specs
656     return Mpeg7_VisualCodingFormatCS_termID_MediaInfo(MI, StreamPos);
657 }
658 
659 //---------------------------------------------------------------------------
Mpeg7_Visual_colorDomain(MediaInfo_Internal & MI,size_t StreamPos)660 Ztring Mpeg7_Visual_colorDomain(MediaInfo_Internal &MI, size_t StreamPos)
661 {
662     const Ztring &ChromaSubsampling=MI.Get(Stream_Video, StreamPos, Video_ChromaSubsampling);
663     if (ChromaSubsampling.find(__T("4:"))!=string::npos)
664         return __T("color");
665     if (ChromaSubsampling==__T("Gray"))
666         return __T("graylevel");
667     return __T("");
668 }
669 
670 //---------------------------------------------------------------------------
Mpeg7_SystemCS_termID(MediaInfo_Internal & MI,size_t StreamPos)671 int32u Mpeg7_SystemCS_termID(MediaInfo_Internal &MI, size_t StreamPos)
672 {
673     if (MI.Get(Stream_Video, StreamPos, Video_Standard)==__T("PAL"))
674         return 10000;
675     if (MI.Get(Stream_Video, StreamPos, Video_Standard)==__T("SECAM"))
676         return 20000;
677     if (MI.Get(Stream_Video, StreamPos, Video_Standard)==__T("NTSC"))
678         return 30000;
679     return 0;
680 }
681 
Mpeg7_SystemCS_Name(int32u termID,MediaInfo_Internal & MI,size_t)682 Ztring Mpeg7_SystemCS_Name(int32u termID, MediaInfo_Internal &MI, size_t) //xxyyzz: xx=main number, yy=sub-number, zz=sub-sub-number
683 {
684     switch (termID/10000)
685     {
686         case  1 : return __T("PAL");
687         case  2 : return __T("SECAM");
688         case  3 : return __T("NTSC");
689         default : return MI.Get(Stream_Video, 0, Video_Standard);
690     }
691 }
692 
693 //---------------------------------------------------------------------------
Mpeg7_AudioCodingFormatCS_termID_MediaInfo(MediaInfo_Internal & MI,size_t StreamPos)694 int32u Mpeg7_AudioCodingFormatCS_termID_MediaInfo(MediaInfo_Internal &MI, size_t StreamPos)
695 {
696     const Ztring &Format=MI.Get(Stream_Audio, StreamPos, Audio_Format);
697 
698     if (Format==__T("DSD"))
699         return 500000;
700     if (Format==__T("DST"))
701         return 510000;
702     if (Format==__T("FLAC"))
703         return 520000;
704     if (Format.find(__T("AAC"))==0)
705         return 530000;
706     if (Format==__T("WMA"))
707         return 540000;
708     return 0;
709 }
710 
711 //---------------------------------------------------------------------------
Mpeg7_AudioCodingFormatCS_termID(MediaInfo_Internal & MI,size_t StreamPos)712 int32u Mpeg7_AudioCodingFormatCS_termID(MediaInfo_Internal &MI, size_t StreamPos)
713 {
714     const Ztring &Format=MI.Get(Stream_Audio, StreamPos, Audio_Format);
715     const Ztring &Version=MI.Get(Stream_Audio, StreamPos, Audio_Format_Version);
716     const Ztring &Profile=MI.Get(Stream_Audio, StreamPos, Audio_Format_Profile);
717 
718     if (Format==__T("AC-3"))
719         return 10000;
720     if (Format==__T("DTS"))
721         return 20000;
722     if (Format==__T("MPEG Audio"))
723     {
724         if (Version.find(__T('1'))!=string::npos)
725         {
726             if (Profile.find(__T('1'))!=string::npos)
727                 return 30100;
728             if (Profile.find(__T('2'))!=string::npos)
729                 return 30200;
730             if (Profile.find(__T('3'))!=string::npos)
731                 return 30300;
732             return 30000;
733         }
734         if (Version.find(__T('2'))!=string::npos)
735         {
736             if (Profile.find(__T('1'))!=string::npos)
737                 return 40100;
738             if (Profile.find(__T('2'))!=string::npos)
739                 return 40200;
740             if (Profile.find(__T('3'))!=string::npos)
741                 return 40300;
742             return 40000;
743         }
744         return 0;
745     }
746     if (Format==__T("PCM"))
747         return 80000;
748 
749     //Out of specs
750     return Mpeg7_AudioCodingFormatCS_termID_MediaInfo(MI, StreamPos);
751 }
752 
Mpeg7_AudioCodingFormatCS_Name(int32u termID,MediaInfo_Internal & MI,size_t StreamPos)753 Ztring Mpeg7_AudioCodingFormatCS_Name(int32u termID, MediaInfo_Internal &MI, size_t StreamPos) //xxyyzz: xx=main number, yy=sub-number, zz=sub-sub-number
754 {
755     switch (termID/10000)
756     {
757         case 1 : return __T("AC3");
758         case 2 : return __T("DTS");
759         case 3 :    switch ((termID%10000)/100)
760                     {
761                         case 1 : return __T("MPEG-1 Audio Layer I");
762                         case 2 : return __T("MPEG-1 Audio Layer II");
763                         case 3 : return __T("MPEG-1 Audio Layer III");
764                         default: return __T("MPEG-1 Audio");
765                     }
766         case 4 :    switch ((termID%10000)/100)
767                     {
768                         case 1 :    switch (termID%100)
769                                     {
770                                         case 1 : return __T("MPEG-2 Audio Low Sampling Rate Layer I");
771                                         case 2 : return __T("MPEG-2 Audio Low Sampling Rate Layer II");
772                                         case 3 : return __T("MPEG-2 Audio Low Sampling Rate Layer III");
773                                         default: return __T("MPEG-2 Audio Low Sampling Rate");
774                                     }
775                         case 2 :    switch (termID%100)
776                                     {
777                                         case 1 : return __T("MPEG-2 Backward Compatible Multi-Channel Layer I");
778                                         case 2 : return __T("MPEG-2 Backward Compatible Multi-Channel Layer II");
779                                         case 3 : return __T("MPEG-2 Backward Compatible Multi-Channel Layer III");
780                                         default: return __T("MPEG-2 Backward Compatible Multi-Channel");
781                                     }
782                         default: return __T("MPEG-2 Audio");
783                     }
784         case 8 : return __T("Linear PCM");
785         //Out of specs --> MediaInfo CS
786         case 50 : return __T("DSD");
787         case 51 : return __T("DST");
788         case 52 : return __T("FLAC");
789         case 53 : return __T("AAC");
790         case 54 : return __T("WMA");
791         default: return MI.Get(Stream_Audio, StreamPos, Audio_Format);
792     }
793 }
794 
795 //---------------------------------------------------------------------------
Mpeg7_AudioPresentationCS_termID(MediaInfo_Internal & MI,size_t StreamPos)796 int32u Mpeg7_AudioPresentationCS_termID(MediaInfo_Internal &MI, size_t StreamPos)
797 {
798     const Ztring &Channels=MI.Get(Stream_Audio, StreamPos, Audio_Channel_s_);
799     const Ztring &ChannelPositions2=MI.Get(Stream_Audio, StreamPos, Audio_ChannelPositions_String2);
800     if (Channels==__T("6") && ChannelPositions2==__T("3/2.1"))
801         return 50000;
802     if (Channels==__T("8") && ChannelPositions2==__T("3/2/2.1"))
803         return 60000;
804     if (Channels==__T("2"))
805         return 30000;
806     if (Channels==__T("1"))
807         return 20000;
808     return 0;
809 }
810 
Mpeg7_AudioPresentationCS_Name(int32u termID,MediaInfo_Internal & MI,size_t StreamPos)811 Ztring Mpeg7_AudioPresentationCS_Name(int32u termID, MediaInfo_Internal &MI, size_t StreamPos)
812 {
813     switch (termID/10000)
814     {
815         case 2 : return __T("mono");
816         case 3 : return __T("stereo");
817         case 5 : return __T("Home theater 5.1");
818         case 6 : return __T("Movie theater");
819         default: return MI.Get(Stream_Audio, StreamPos, Audio_ChannelLayout);
820     }
821 }
822 
823 //---------------------------------------------------------------------------
Mpeg7_AudioEmphasis(MediaInfo_Internal & MI,size_t StreamPos)824 Ztring Mpeg7_AudioEmphasis(MediaInfo_Internal &MI, size_t StreamPos)
825 {
826     const Ztring &Emphasis=MI.Get(Stream_Audio, StreamPos, Audio_Format_Settings_Emphasis);
827     if (Emphasis==__T("50/15ms"))
828         return __T("50over15Microseconds");
829     if (Emphasis==__T("CCITT"))
830         return __T("ccittJ17");
831     if (Emphasis==__T("Reserved"))
832         return __T("reserved");
833     return __T("none");
834 }
835 
836 //---------------------------------------------------------------------------
Mpeg7_MediaTimePoint(MediaInfo_Internal & MI)837 Ztring Mpeg7_MediaTimePoint(MediaInfo_Internal &MI)
838 {
839     if (MI.Count_Get(Stream_Video)==1 && MI.Get(Stream_General, 0, General_Format)==__T("MPEG-PS"))
840     {
841         int64u Delay=(int64u)(MI.Get(Stream_Video, 0, Video_Delay).To_float64()*90);
842         int64u Rate=90000;
843         int64u DD=Delay/(24*60*60*Rate);
844         Delay=Delay%(24*60*60*Rate);
845         int64u HH=Delay/(60*60*Rate);
846         Delay=Delay%(60*60*Rate);
847         int64u MM=Delay/(60*Rate);
848         Delay=Delay%(60*Rate);
849         int64u Sec=Delay/Rate;
850         Delay=Delay%Rate;
851         Ztring ToReturn;
852         if (DD)
853             ToReturn+=Ztring::ToZtring(DD);
854         ToReturn+=__T('T');
855         ToReturn+=(HH<10?__T("0"):__T(""))+Ztring::ToZtring(HH)+__T(':');
856         ToReturn+=(MM<10?__T("0"):__T(""))+Ztring::ToZtring(MM)+__T(':');
857         ToReturn+=(Sec<10?__T("0"):__T(""))+Ztring::ToZtring(Sec)+__T(':');
858         ToReturn+=Ztring::ToZtring(Delay)+__T('F');
859         ToReturn+=Ztring::ToZtring(Rate);
860         return ToReturn;
861     }
862 
863     if (MI.Count_Get(Stream_Audio)==1 && MI.Get(Stream_General, 0, General_Format)==__T("Wave"))
864     {
865         int64u Rate=MI.Get(Stream_Audio, 0, Audio_SamplingRate).To_int64u();
866         if (!Rate)
867             return Ztring();
868         int64u Delay=(int64u)float64_int64s(MI.Get(Stream_Audio, 0, Audio_Delay).To_float64()*Rate/1000);
869         int64u DD=Delay/(24*60*60*Rate);
870         Delay=Delay%(24*60*60*Rate);
871         int64u HH=Delay/(60*60*Rate);
872         Delay=Delay%(60*60*Rate);
873         int64u MM=Delay/(60*Rate);
874         Delay=Delay%(60*Rate);
875         int64u Sec=Delay/Rate;
876         Delay=Delay%Rate;
877         Ztring ToReturn;
878         if (DD)
879             ToReturn+=Ztring::ToZtring(DD);
880         ToReturn+=__T('T');
881         ToReturn+=(HH<10?__T("0"):__T(""))+Ztring::ToZtring(HH)+__T(':');
882         ToReturn+=(MM<10?__T("0"):__T(""))+Ztring::ToZtring(MM)+__T(':');
883         ToReturn+=(Sec<10?__T("0"):__T(""))+Ztring::ToZtring(Sec)+__T(':');
884         ToReturn+=Ztring::ToZtring(Delay)+__T('F');
885         ToReturn+=Ztring::ToZtring(Rate);
886         return ToReturn;
887     }
888 
889     //Default: In milliseconds
890     int64u Milliseconds=MI.Get(Stream_Video, 0, Video_Delay).To_int64u();
891     int64u DD=Milliseconds/(24*60*60*1000);
892     Milliseconds=Milliseconds%(24*60*60*1000);
893     int64u HH=Milliseconds/(60*60*1000);
894     Milliseconds=Milliseconds%(60*60*1000);
895     int64u MM=Milliseconds/(60*1000);
896     Milliseconds=Milliseconds%(60*1000);
897     int64u Sec=Milliseconds/1000;
898     int64u NN=Milliseconds%1000;
899     int64u FF=1000;
900     Ztring ToReturn;
901     if (DD)
902         ToReturn+=Ztring::ToZtring(DD);
903     ToReturn+=__T('T');
904     ToReturn+=(HH<10?__T("0"):__T(""))+Ztring::ToZtring(HH)+__T(':');
905     ToReturn+=(MM<10?__T("0"):__T(""))+Ztring::ToZtring(MM)+__T(':');
906     ToReturn+=(Sec<10?__T("0"):__T(""))+Ztring::ToZtring(Sec)+__T(':');
907     ToReturn+=Ztring::ToZtring(NN)+__T('F');
908     ToReturn+=Ztring::ToZtring(FF);
909     return ToReturn;
910 }
911 
912 //---------------------------------------------------------------------------
Mpeg7_MediaDuration(MediaInfo_Internal & MI)913 Ztring Mpeg7_MediaDuration(MediaInfo_Internal &MI)
914 {
915     if (MI.Count_Get(Stream_Video)==1)
916     {
917         int64u FrameCount=MI.Get(Stream_Video, 0, Video_FrameCount).To_int64u();
918         int64u FrameRate=MI.Get(Stream_Video, 0, Video_FrameRate).To_int64u();
919         if (FrameRate==0)
920             return Ztring();
921         int64u DD=FrameCount/(24*60*60*FrameRate);
922         FrameCount=FrameCount%(24*60*60*FrameRate);
923         int64u HH=FrameCount/(60*60*FrameRate);
924         FrameCount=FrameCount%(60*60*FrameRate);
925         int64u MM=FrameCount/(60*FrameRate);
926         FrameCount=FrameCount%(60*FrameRate);
927         int64u Sec=FrameCount/FrameRate;
928         FrameCount=FrameCount%FrameRate;
929         Ztring ToReturn;
930         ToReturn+=__T('P');
931         if (DD)
932             ToReturn+=Ztring::ToZtring(DD)+__T('D');
933         ToReturn+=__T('T');
934         ToReturn+=Ztring::ToZtring(HH)+__T('H');
935         ToReturn+=Ztring::ToZtring(MM)+__T('M');
936         ToReturn+=Ztring::ToZtring(Sec)+__T('S');
937         ToReturn+=Ztring::ToZtring(FrameCount)+__T('N');
938         ToReturn+=Ztring::ToZtring(FrameRate)+__T('F');
939         return ToReturn;
940     }
941 
942     if (MI.Count_Get(Stream_Audio)==1)
943     {
944         int64u SamplingCount=MI.Get(Stream_Audio, 0, Audio_SamplingCount).To_int64u();
945         int64u SamplingRate=MI.Get(Stream_Audio, 0, Audio_SamplingRate).To_int64u();
946         if (SamplingRate==0)
947             return Ztring();
948         int64u DD=SamplingCount/(24*60*60*SamplingRate);
949         SamplingCount=SamplingCount%(24*60*60*SamplingRate);
950         int64u HH=SamplingCount/(60*60*SamplingRate);
951         SamplingCount=SamplingCount%(60*60*SamplingRate);
952         int64u MM=SamplingCount/(60*SamplingRate);
953         SamplingCount=SamplingCount%(60*SamplingRate);
954         int64u Sec=SamplingCount/SamplingRate;
955         SamplingCount=SamplingCount%SamplingRate;
956         Ztring ToReturn;
957         ToReturn+=__T('P');
958         if (DD)
959             ToReturn+=Ztring::ToZtring(DD)+__T('D');
960         ToReturn+=__T('T');
961         ToReturn+=Ztring::ToZtring(HH)+__T('H');
962         ToReturn+=Ztring::ToZtring(MM)+__T('M');
963         ToReturn+=Ztring::ToZtring(Sec)+__T('S');
964         ToReturn+=Ztring::ToZtring(SamplingCount)+__T('N');
965         ToReturn+=Ztring::ToZtring(SamplingRate)+__T('F');
966         return ToReturn;
967     }
968 
969     //Default: In milliseconds
970     int64u Milliseconds=MI.Get(Stream_General, 0, General_Duration).To_int64u();
971     int64u DD=Milliseconds/(24*60*60*1000);
972     Milliseconds=Milliseconds%(24*60*60*1000);
973     int64u HH=Milliseconds/(60*60*1000);
974     Milliseconds=Milliseconds%(60*60*1000);
975     int64u MM=Milliseconds/(60*1000);
976     Milliseconds=Milliseconds%(60*1000);
977     int64u Sec=Milliseconds/1000;
978     int64u NN=Milliseconds%1000;
979     int64u FF=1000;
980     Ztring ToReturn;
981     ToReturn+=__T('P');
982     if (DD)
983         ToReturn+=Ztring::ToZtring(DD)+__T('D');
984     ToReturn+=__T('T');
985     ToReturn+=Ztring::ToZtring(HH)+__T('H');
986     ToReturn+=Ztring::ToZtring(MM)+__T('M');
987     ToReturn+=Ztring::ToZtring(Sec)+__T('S');
988     ToReturn+=Ztring::ToZtring(NN)+__T('N');
989     ToReturn+=Ztring::ToZtring(FF)+__T('F');
990     return ToReturn;
991 }
992 
993 //---------------------------------------------------------------------------
Mpeg7_StripExtraValues(Ztring Value)994 Ztring Mpeg7_StripExtraValues(Ztring Value)
995 {
996     if (Value.empty())
997         return Value;
998 
999     size_t SlashPos=Value.find(__T(" / "));
1000     if (SlashPos!=string::npos)
1001         Value.erase(SlashPos);
1002 
1003     return Value;
1004 }
1005 
1006 //---------------------------------------------------------------------------
Mpeg7_termID2String(int32u termID,const char * CS)1007 static Ztring Mpeg7_termID2String(int32u termID, const char* CS)
1008 {
1009     Ztring ToReturn;
1010 
1011     //Unknown
1012     if (!termID)
1013     {
1014         ToReturn="urn:x-mpeg7-mediainfo:cs:";
1015         ToReturn+=Ztring(CS);
1016         ToReturn+=Ztring(":2009:unknown");
1017         return ToReturn;
1018     }
1019 
1020     //URN prefix
1021     bool OutOfSpec=(termID>=500000);
1022     if (OutOfSpec)
1023         ToReturn="urn:x-mpeg7-mediainfo:cs:";
1024     else
1025         ToReturn="urn:mpeg:mpeg7:cs:";
1026     ToReturn+=Ztring(CS);
1027     if (OutOfSpec)
1028         ToReturn+=Ztring(":2009:");
1029     else
1030         ToReturn+=Ztring(":2001:");
1031 
1032     //URN value
1033     ToReturn+=Ztring::ToZtring(termID/10000);
1034     if (termID%10000)
1035     {
1036         ToReturn+=__T('.');
1037         ToReturn+=Ztring::ToZtring((termID%10000)/100);
1038         if (termID%100)
1039         {
1040             ToReturn+=__T('.');
1041             ToReturn+=Ztring::ToZtring(termID%100);
1042         }
1043     }
1044 
1045     return ToReturn;
1046 }
1047 
1048 //---------------------------------------------------------------------------
1049 typedef int32u(*Mpeg7_termID) (MediaInfo_Internal &MI, size_t StreamPos);
1050 typedef Ztring(*Mpeg7_Name) (int32u termID, MediaInfo_Internal &MI, size_t StreamPos);
Mpeg7_CS(Node * Node_MediaFormat,const char * MainName,const char * CS,const Mpeg7_termID & termIDFunction,const Mpeg7_Name & NameFunction,MediaInfo_Internal & MI,size_t StreamPos,bool Mandatory=false,bool FullDigits=false)1051 static Node* Mpeg7_CS(Node* Node_MediaFormat, const char* MainName, const char* CS, const Mpeg7_termID& termIDFunction, const Mpeg7_Name& NameFunction, MediaInfo_Internal &MI, size_t StreamPos, bool Mandatory=false, bool FullDigits=false)
1052 {
1053     int32u termID=termIDFunction(MI, StreamPos);
1054     Ztring Value=NameFunction(FullDigits?termID:((termID/10000)*10000), MI, StreamPos);
1055     if (!Mandatory && Value.empty())
1056         return NULL;
1057 
1058     Node* Node_Main=Node_MediaFormat->Add_Child(MainName);
1059     Node_Main->Add_Attribute("href", Mpeg7_termID2String(FullDigits?termID:((termID/10000)*10000), CS));
1060 
1061     Node_Main->Add_Child("mpeg7:Name", Value, "xml:lang", "en");
1062     if (!FullDigits && termID%10000)
1063     {
1064         Node* Node_Term=Node_Main->Add_Child("mpeg7:Term");
1065         Node_Term->Add_Attribute("termID", Ztring::ToZtring(termID/10000)+__T(".")+
1066                                             Ztring::ToZtring((termID%10000)/100));
1067 
1068         Value=NameFunction((termID/100)*100, MI, StreamPos);
1069         Node_Term->Add_Child("mpeg7:Name", Value, "xml:lang", "en");
1070         if (termID%100)
1071         {
1072             Node_Term=Node_Term->Add_Child("mpeg7:Term");
1073             Node_Term->Add_Attribute("termID", Ztring::ToZtring(termID/10000)+__T(".")+
1074                                                 Ztring::ToZtring((termID%10000)/100)+__T(".")+
1075                                                 Ztring::ToZtring(termID%100));
1076 
1077             Value=NameFunction(termID, MI, StreamPos);
1078             if (!Value.empty())
1079                 Node_Term->Add_Child("mpeg7:Name", Value, "xml:lang", "en");
1080         }
1081     }
1082 
1083     return Node_Main;
1084 }
1085 
1086 //***************************************************************************
1087 // Constructor/Destructor
1088 //***************************************************************************
1089 
1090 //---------------------------------------------------------------------------
Export_Mpeg7()1091 Export_Mpeg7::Export_Mpeg7 ()
1092 {
1093 }
1094 
1095 //---------------------------------------------------------------------------
~Export_Mpeg7()1096 Export_Mpeg7::~Export_Mpeg7 ()
1097 {
1098 }
1099 
1100 //***************************************************************************
1101 // Input
1102 //***************************************************************************
1103 
1104 //---------------------------------------------------------------------------
Mpeg7_Transform_Visual(Node * Parent,MediaInfo_Internal & MI,size_t StreamPos)1105 void Mpeg7_Transform_Visual(Node* Parent, MediaInfo_Internal &MI, size_t StreamPos)
1106 {
1107     Node* Node_VisualCoding=Parent->Add_Child("mpeg7:VisualCoding");
1108 
1109     //Format
1110     Node* Node_Format=Mpeg7_CS(Node_VisualCoding, "mpeg7:Format", "VisualCodingFormatCS", Mpeg7_VisualCodingFormatCS_termID, VideoCompressionCodeCS_Name, MI, StreamPos);
1111     if (Node_Format)
1112     {
1113     Ztring Value=Mpeg7_Visual_colorDomain(MI, StreamPos); //Algo puts empty string if not known
1114     if (!Value.empty())
1115         Node_Format->Add_Attribute("colorDomain", Value);
1116     }
1117 
1118     //Pixel
1119     if (!MI.Get(Stream_Video, 0, Video_PixelAspectRatio).empty()
1120      || !MI.Get(Stream_Video, 0, Video_BitDepth).empty())
1121     {
1122         Node* Node_Pixel=Node_VisualCoding->Add_Child("mpeg7:Pixel");
1123         Node_Pixel->Add_Attribute_IfNotEmpty(MI, Stream_Video, 0, Video_PixelAspectRatio, "aspectRatio");
1124         Ztring bitsPer=Mpeg7_StripExtraValues(MI.Get(Stream_Video, 0, Video_BitDepth));
1125         if (!bitsPer.empty())
1126             Node_Pixel->Add_Attribute("bitsPer", bitsPer);
1127     }
1128 
1129     //Frame
1130     if (!MI.Get(Stream_Video, 0, Video_DisplayAspectRatio).empty()
1131      || !MI.Get(Stream_Video, 0, Video_Height).empty()
1132      || !MI.Get(Stream_Video, 0, Video_Width).empty()
1133      || !MI.Get(Stream_Video, 0, Video_FrameRate).empty()
1134      || !MI.Get(Stream_Video, 0, Video_ScanType).empty())
1135     {
1136         Node* Node_Frame=Node_VisualCoding->Add_Child("mpeg7:Frame");
1137         Node_Frame->Add_Attribute_IfNotEmpty(MI, Stream_Video, 0, Video_DisplayAspectRatio, "aspectRatio");
1138 
1139         Ztring Height=Mpeg7_StripExtraValues(MI.Get(Stream_Video, 0, Video_Height));
1140         if (!Height.empty())
1141             Node_Frame->Add_Attribute("height", Height);
1142 
1143         Ztring Width=Mpeg7_StripExtraValues(MI.Get(Stream_Video, 0, Video_Width));
1144         if (!Width.empty())
1145             Node_Frame->Add_Attribute("width", Width);
1146 
1147         Node_Frame->Add_Attribute_IfNotEmpty(MI, Stream_Video, 0, Video_FrameRate, "rate");
1148 
1149         Ztring Value=MI.Get(Stream_Video, 0, Video_ScanType).MakeLowerCase();
1150         if (!Value.empty())
1151         {
1152             if (Value==__T("mbaff") || Value==__T("interlaced"))
1153                 Node_Frame->Add_Attribute("structure", "interlaced");
1154             else if (Value==__T("progressive"))
1155                 Node_Frame->Add_Attribute("structure", "progressive");
1156         }
1157     }
1158 
1159     //ChromaSubsampling
1160     if (MI.Get(Stream_Video, StreamPos, Video_ChromaSubsampling).find(__T("4:2:0"))!=string::npos)
1161     {
1162         Node* Node_ColorSampling=Node_VisualCoding->Add_Child("mpeg7:ColorSampling");
1163         Node_ColorSampling->XmlComment="YUV 4:2:0 Interlaced";
1164         Node* Node_Lattice=Node_ColorSampling->Add_Child("mpeg7:Lattice");
1165         Node_Lattice->Add_Attribute("height", "720");
1166         Node_Lattice->Add_Attribute("width", "486");
1167 
1168         {
1169             Node* Node_Field=Node_ColorSampling->Add_Child("mpeg7:Field");
1170             Node_Field->Add_Attribute("temporalOrder", "0");
1171             Node_Field->Add_Attribute("positionalOrder", "0");
1172 
1173             {
1174                 Node* Node_Component=Node_Field->Add_Child("mpeg7:Component");
1175                 Node_Component->Add_Child("mpeg7:Name", std::string("Luminance"));
1176                 Node* Node_Offset=Node_Component->Add_Child("mpeg7:Offset");
1177                 Node_Offset->Add_Attribute("horizontal", "0.0");
1178                 Node_Offset->Add_Attribute("vertical", "0.0");
1179                 Node* Node_Period=Node_Component->Add_Child("mpeg7:Period");
1180                 Node_Period->Add_Attribute("horizontal", "1.0");
1181                 Node_Period->Add_Attribute("vertical", "2.0");
1182             }
1183 
1184             {
1185                 Node* Node_Component=Node_Field->Add_Child("mpeg7:Component");
1186                 Node_Component->Add_Child("mpeg7:Name", std::string("ChrominanceBlueDifference"));
1187                 Node* Node_Offset=Node_Component->Add_Child("mpeg7:Offset");
1188                 Node_Offset->Add_Attribute("horizontal", "0.0");
1189                 Node_Offset->Add_Attribute("vertical", "0.5");
1190                 Node* Node_Period=Node_Component->Add_Child("mpeg7:Period");
1191                 Node_Period->Add_Attribute("horizontal", "2.0");
1192                 Node_Period->Add_Attribute("vertical", "4.0");
1193             }
1194 
1195             {
1196                 Node* Node_Component=Node_Field->Add_Child("mpeg7:Component");
1197                 Node_Component->Add_Child("mpeg7:Name", std::string("ChrominanceRedDifference"));
1198                 Node* Node_Offset=Node_Component->Add_Child("mpeg7:Offset");
1199                 Node_Offset->Add_Attribute("horizontal", "0.0");
1200                 Node_Offset->Add_Attribute("vertical", "0.5");
1201                 Node* Node_Period=Node_Component->Add_Child("mpeg7:Period");
1202                 Node_Period->Add_Attribute("horizontal", "2.0");
1203                 Node_Period->Add_Attribute("vertical", "4.0");
1204             }
1205         }
1206 
1207         {
1208             Node* Node_Field=Node_ColorSampling->Add_Child("mpeg7:Field");
1209             Node_Field->Add_Attribute("temporalOrder", "1");
1210             Node_Field->Add_Attribute("positionalOrder", "1");
1211 
1212             {
1213                 Node* Node_Component=Node_Field->Add_Child("mpeg7:Component");
1214                 Node_Component->Add_Child("mpeg7:Name", std::string("Luminance"));
1215                 Node* Node_Offset=Node_Component->Add_Child("mpeg7:Offset");
1216                 Node_Offset->Add_Attribute("horizontal", "0.0");
1217                 Node_Offset->Add_Attribute("vertical", "1.0");
1218                 Node* Node_Period=Node_Component->Add_Child("mpeg7:Period");
1219                 Node_Period->Add_Attribute("horizontal", "1.0");
1220                 Node_Period->Add_Attribute("vertical", "2.0");
1221             }
1222 
1223             {
1224                 Node* Node_Component=Node_Field->Add_Child("mpeg7:Component");
1225                 Node_Component->Add_Child("mpeg7:Name", std::string("ChrominanceBlueDifference"));
1226                 Node* Node_Offset=Node_Component->Add_Child("mpeg7:Offset");
1227                 Node_Offset->Add_Attribute("horizontal", "0.0");
1228                 Node_Offset->Add_Attribute("vertical", "2.5");
1229                 Node* Node_Period=Node_Component->Add_Child("mpeg7:Period");
1230                 Node_Period->Add_Attribute("horizontal", "2.0");
1231                 Node_Period->Add_Attribute("vertical", "4.0");
1232             }
1233 
1234             {
1235                 Node* Node_Component=Node_Field->Add_Child("mpeg7:Component");
1236                 Node_Component->Add_Child("mpeg7:Name", std::string("ChrominanceRedDifference"));
1237                 Node* Node_Offset=Node_Component->Add_Child("mpeg7:Offset");
1238                 Node_Offset->Add_Attribute("horizontal", "0.0");
1239                 Node_Offset->Add_Attribute("vertical", "2.5");
1240                 Node* Node_Period=Node_Component->Add_Child("mpeg7:Period");
1241                 Node_Period->Add_Attribute("horizontal", "4.0");
1242                 Node_Period->Add_Attribute("vertical", "2.0");
1243             }
1244         }
1245     }
1246 }
1247 
1248 //---------------------------------------------------------------------------
Mpeg7_Transform_Audio(Node * Parent,MediaInfo_Internal & MI,size_t StreamPos)1249 void Mpeg7_Transform_Audio(Node* Parent, MediaInfo_Internal &MI, size_t StreamPos)
1250 {
1251     Node* Node_AudioCoding=Parent->Add_Child("mpeg7:AudioCoding");
1252 
1253     //Format
1254     Mpeg7_CS(Node_AudioCoding, "mpeg7:Format", "AudioCodingFormatCS", Mpeg7_AudioCodingFormatCS_termID, Mpeg7_AudioCodingFormatCS_Name, MI, StreamPos);
1255 
1256     //AudioChannels
1257     Ztring Channels=Mpeg7_StripExtraValues(MI.Get(Stream_Audio, StreamPos, Audio_Channel_s_));
1258     if (!Channels.empty() && Channels.To_int32s())
1259         Node_AudioCoding->Add_Child("mpeg7:AudioChannels", Channels);
1260 
1261     //Sample
1262     Node* Node_Sample=Node_AudioCoding->Add_Child("mpeg7:Sample");
1263 
1264     Ztring Rate=Mpeg7_StripExtraValues(MI.Get(Stream_Audio, StreamPos, Audio_SamplingRate));
1265     if (!Rate.empty())
1266         Node_Sample->Add_Attribute("rate", Rate);
1267 
1268     Ztring bitsPer=Mpeg7_StripExtraValues(MI.Get(Stream_Audio, StreamPos, Audio_BitDepth));
1269     if (!bitsPer.empty())
1270         Node_Sample->Add_Attribute("bitsPer", bitsPer);
1271 
1272     //Emphasis
1273     if (MI.Get(Stream_Audio, StreamPos, Audio_Format)==__T("MPEG Audio"))
1274         Node_AudioCoding->Add_Child("mpeg7:Emphasis", Mpeg7_AudioEmphasis(MI, StreamPos));
1275 
1276     //Presentation
1277     Mpeg7_CS(Node_AudioCoding, "mpeg7:Presentation", "AudioPresentationCS", Mpeg7_AudioPresentationCS_termID, Mpeg7_AudioPresentationCS_Name, MI, StreamPos);
1278 }
1279 
1280 //---------------------------------------------------------------------------
Transform(MediaInfo_Internal & MI)1281 Ztring Export_Mpeg7::Transform(MediaInfo_Internal &MI)
1282 {
1283     Ztring Value;
1284 
1285     //ebuCoreMain
1286     Node* Node_Mpeg7 = new Node("mpeg7:Mpeg7");
1287     Node_Mpeg7->Add_Attribute("xmlns", "urn:mpeg:mpeg7:schema:2004");
1288     Node_Mpeg7->Add_Attribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
1289     Node_Mpeg7->Add_Attribute("xmlns:mpeg7", "urn:mpeg:mpeg7:schema:2004");
1290     Node_Mpeg7->Add_Attribute("xsi:schemaLocation", "urn:mpeg:mpeg7:schema:2004 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-7_schema_files/mpeg7-v2.xsd");
1291 
1292     //Description - DescriptionMetadata
1293     Node* Node_DescriptionMetadata=Node_Mpeg7->Add_Child("mpeg7:DescriptionMetadata");
1294 
1295     Node_DescriptionMetadata->Add_Child_IfNotEmpty(MI, Stream_General, 0, General_ISRC, "mpeg7:PublicIdentifier", "type", std::string("ISRC"));
1296 
1297     Ztring FileName=MI.Get(Stream_General, 0, General_FileName);
1298     Ztring Extension=MI.Get(Stream_General, 0, General_FileExtension);
1299     if (!Extension.empty())
1300         FileName+=__T('.')+Extension;
1301     if (!FileName.empty())
1302        Node_DescriptionMetadata->Add_Child("mpeg7:PrivateIdentifier", FileName);
1303 
1304     //Current date/time is ISO format
1305     time_t Time=time(NULL);
1306     Ztring TimeS; TimeS.Date_From_Seconds_1970((int32u)Time);
1307     TimeS.FindAndReplace(__T("UTC "), __T(""));
1308     TimeS.FindAndReplace(__T(" "), __T("T"));
1309     TimeS+=__T("+00:00");
1310     Node_DescriptionMetadata->Add_Child("mpeg7:CreationTime", TimeS);
1311 
1312     Node* Node_Instrument=Node_DescriptionMetadata->Add_Child("mpeg7:Instrument");
1313     Node_Instrument->Add_Child("mpeg7:Tool")->Add_Child("mpeg7:Name", MediaInfoLib::Config.Info_Version_Get());
1314 
1315     //Description - CreationDescription
1316     Node* Node_Description=Node_Mpeg7->Add_Child("mpeg7:Description", "", "xsi:type", "ContentEntityType");
1317 
1318     //MultimediaContent
1319     Node* Node_MultimediaContent=Node_Description->Add_Child("mpeg7:MultimediaContent", std::string(""), "xsi:type", Ztring(Ztring(Mpeg7_Type(MI))+__T("Type")).To_UTF8());
1320 
1321     //(Type)
1322     Node* Node_Type=Node_MultimediaContent->Add_Child(Ztring(Ztring(__T("mpeg7:"))+Ztring(Mpeg7_Type(MI))).To_UTF8());
1323 
1324     //MediaFormat header
1325     Node* Node_MediaInformation=Node_Type->Add_Child("mpeg7:MediaInformation");
1326     Node* Node_MediaProfile=Node_MediaInformation->Add_Child("mpeg7:MediaProfile");
1327 
1328     Node* Node_MediaFormat=Node_MediaProfile->Add_Child("mpeg7:MediaFormat");
1329 
1330     //Content
1331     Mpeg7_CS(Node_MediaFormat, "mpeg7:Content", "ContentCS", Mpeg7_ContentCS_termID, Mpeg7_ContentCS_Name, MI, 0, true, true);
1332 
1333     //FileFormat
1334     Mpeg7_CS(Node_MediaFormat, "mpeg7:FileFormat", "FileFormatCS", Mpeg7_FileFormatCS_termID, Mpeg7_FileFormatCS_Name, MI, 0);
1335 
1336     //FileSize
1337     Node* FileSize=Node_MediaFormat->Add_Child_IfNotEmpty(MI, Stream_General, 0, General_FileSize, "mpeg7:FileSize");
1338     if (FileSize && !MI.Get(Stream_General, 0, __T("IsTruncated")).empty())
1339         FileSize->XmlComment="Malformed file: truncated";
1340 
1341     //System
1342     Mpeg7_CS(Node_MediaFormat, "mpeg7:System", "SystemCS", Mpeg7_SystemCS_termID, Mpeg7_SystemCS_Name, MI, 0);
1343 
1344     //BitRate
1345     Ztring BitRate=Mpeg7_StripExtraValues(MI.Get(Stream_General, 0, General_OverallBitRate));
1346     if (!BitRate.empty())
1347     {
1348         Node* Node_BitRate=Node_MediaFormat->Add_Child("mpeg7:BitRate", BitRate);
1349         bool IsCBR=true;
1350         bool IsVBR=true;
1351         for (size_t StreamKind=Stream_Video; StreamKind<=Stream_Audio; StreamKind++)
1352             for (size_t StreamPos=0; StreamPos<MI.Count_Get((stream_t)StreamKind); StreamPos++)
1353             {
1354                 if (IsCBR && MI.Get((stream_t)StreamKind, StreamPos, __T("BitRate_Mode"))==__T("VBR"))
1355                     IsCBR=false;
1356                 if (IsVBR && MI.Get((stream_t)StreamKind, StreamPos, __T("BitRate_Mode"))==__T("CBR"))
1357                     IsVBR=false;
1358             }
1359         if (IsCBR && IsVBR)
1360         {
1361             IsCBR=false;
1362             IsVBR=false;
1363         }
1364         if (IsCBR)
1365             Node_BitRate->Add_Attribute("variable", "false");
1366         if (IsVBR)
1367             Node_BitRate->Add_Attribute("variable", "true");
1368     }
1369 
1370     //xxxCoding
1371     for (size_t Pos=0; Pos<MI.Count_Get(Stream_Video); Pos++)
1372         Mpeg7_Transform_Visual(Node_MediaFormat, MI, Pos);
1373     for (size_t Pos=0; Pos<MI.Count_Get(Stream_Audio); Pos++)
1374         Mpeg7_Transform_Audio(Node_MediaFormat, MI, Pos);
1375 
1376     //MediaTranscodingHints, intraFrameDistance and anchorFrameDistance
1377     if (!MI.Get(Stream_Video, 0, Video_Format_Settings_GOP).empty())
1378     {
1379         Ztring M=MI.Get(Stream_Video, 0, Video_Format_Settings_GOP).SubString(__T("M="), __T(","));
1380         Ztring N=MI.Get(Stream_Video, 0, Video_Format_Settings_GOP).SubString(__T("N="), __T(""));
1381 
1382         Node* Node_CodingHints=Node_MediaProfile->Add_Child("mpeg7:MediaTranscodingHints")->Add_Child("mpeg7:CodingHints");
1383         if (!N.empty())
1384             Node_CodingHints->Add_Attribute("intraFrameDistance", N);
1385         if (!M.empty())
1386             Node_CodingHints->Add_Attribute("anchorFrameDistance", M);
1387     }
1388 
1389     if (!MI.Get(Stream_General, 0, General_Movie).empty()
1390      || !MI.Get(Stream_General, 0, General_Part).empty()
1391      || !MI.Get(Stream_General, 0, General_Part_Position).empty()
1392      || !MI.Get(Stream_General, 0, General_Track).empty()
1393      || !MI.Get(Stream_General, 0, General_Track_Position).empty()
1394      || !MI.Get(Stream_General, 0, General_Album).empty()
1395      || !MI.Get(Stream_General, 0, General_Recorded_Date).empty()
1396      || !MI.Get(Stream_General, 0, General_Encoded_Date).empty()
1397      || !MI.Get(Stream_General, 0, General_Encoded_Application).empty()
1398      || !MI.Get(Stream_General, 0, General_Encoded_Library).empty()
1399      || !MI.Get(Stream_General, 0, General_Producer).empty()
1400      || !MI.Get(Stream_General, 0, General_Performer).empty())
1401     {
1402         Node* Node_Creation=Node_Type->Add_Child("mpeg7:CreationInformation")->Add_Child("mpeg7:Creation");
1403 
1404         if (!MI.Get(Stream_General, 0, General_Movie).empty()
1405          || !MI.Get(Stream_General, 0, General_Track).empty()
1406          || !MI.Get(Stream_General, 0, General_Track_Position).empty()
1407          || !MI.Get(Stream_General, 0, General_Part).empty()
1408          || !MI.Get(Stream_General, 0, General_Part_Position).empty()
1409          || !MI.Get(Stream_General, 0, General_Album).empty())
1410         {
1411             Node_Creation->Add_Child_IfNotEmpty(MI, Stream_General, 0, General_Movie, "mpeg7:Title", "type", std::string("songTitle"));
1412             Node_Creation->Add_Child_IfNotEmpty(MI, Stream_General, 0, General_Track, "mpeg7:Title", "type", std::string("songTitle"));
1413             if (!MI.Get(Stream_General, 0, General_Part_Position).empty())
1414             {
1415                 Ztring Total=MI.Get(Stream_General, 0, General_Part_Position_Total);
1416                 Value=MI.Get(Stream_General, 0, General_Part_Position)+(Total.empty()?Ztring():(__T("/")+Total));
1417 
1418                 Node_Creation->Add_Child("mpeg7:Title", Value, "type", std::string("urn:x-mpeg7-mediainfo:cs:TitleTypeCS:2009:PART"));
1419             }
1420             if (!MI.Get(Stream_General, 0, General_Track_Position).empty())
1421             {
1422                  Ztring Total=MI.Get(Stream_General, 0, General_Track_Position_Total);
1423                  Value=MI.Get(Stream_General, 0, General_Track_Position)+(Total.empty()?Ztring():(__T("/")+Total));
1424 
1425                  Node_Creation->Add_Child("mpeg7:Title", Value, "type", std::string("urn:x-mpeg7-mediainfo:cs:TitleTypeCS:2009:TRACK"));
1426             }
1427             Node_Creation->Add_Child_IfNotEmpty(MI, Stream_General, 0, General_Album, "mpeg7:Title", "type", std::string("albumTitle"));
1428         }
1429         else
1430         {
1431               Node_Creation->Add_Child("mpeg7:Title", FileName);
1432         }
1433 
1434         if (!MI.Get(Stream_General, 0, General_WrittenBy).empty())
1435         {
1436             Node* Node_Creator=Node_Creation->Add_Child("mpeg7:Creator");
1437             Node_Creator->Add_Child("mpeg7:Role", "", "href", "urn:mpeg:mpeg7:cs:RoleCS:2001:AUTHOR");
1438             Node* Node_Agent=Node_Creator->Add_Child("mpeg7:Agent", "", "xsi:type", "PersonGroupType");
1439             Node_Agent->Add_Child("mpeg7:Name", MI.Get(Stream_General, 0, General_WrittenBy));
1440         }
1441 
1442         if (!MI.Get(Stream_General, 0, General_Performer).empty())
1443         {
1444             Node* Node_Creator=Node_Creation->Add_Child("mpeg7:Creator");
1445             Node_Creator->Add_Child("mpeg7:Role", "", "href", "urn:mpeg:mpeg7:cs:RoleCS:2001:PERFORMER");
1446             Node* Node_Agent=Node_Creator->Add_Child("mpeg7:Agent", "", "xsi:type", "PersonGroupType");
1447             Node_Agent->Add_Child("mpeg7:Name", MI.Get(Stream_General, 0, General_Performer));
1448         }
1449         if (!MI.Get(Stream_General, 0, General_ExecutiveProducer).empty())
1450         {
1451             Node* Node_Creator=Node_Creation->Add_Child("mpeg7:Creator");
1452             Node_Creator->Add_Child("mpeg7:Role", "", "href", "urn:mpeg:mpeg7:cs:RoleCS:2001:EXECUTIVE-PRODUCER");
1453             Node* Node_Agent=Node_Creator->Add_Child("mpeg7:Agent", "", "xsi:type", "PersonGroupType");
1454             Node_Agent->Add_Child("mpeg7:Name", MI.Get(Stream_General, 0, General_ExecutiveProducer));
1455         }
1456         if (!MI.Get(Stream_General, 0, General_Producer).empty())
1457         {
1458             Node* Node_Creator=Node_Creation->Add_Child("mpeg7:Creator");
1459             Node_Creator->Add_Child("mpeg7:Role", "", "href", "urn:mpeg:mpeg7:cs:RoleCS:2001:PRODUCER");
1460             Node* Node_Agent=Node_Creator->Add_Child("mpeg7:Agent", "", "xsi:type", "PersonGroupType");
1461             Node_Agent->Add_Child("mpeg7:Name", MI.Get(Stream_General, 0, General_Producer));
1462         }
1463         if (!MI.Get(Stream_General, 0, General_Director).empty())
1464         {
1465             Node* Node_Creator=Node_Creation->Add_Child("mpeg7:Creator");
1466             Node_Creator->Add_Child("mpeg7:Role", "", "href", "urn:mpeg:mpeg7:cs:RoleCS:2001:PRODUCER");
1467             Node* Node_Agent=Node_Creator->Add_Child("mpeg7:Agent", "", "xsi:type", "PersonGroupType");
1468             Node_Agent->Add_Child("mpeg7:Name", MI.Get(Stream_General, 0, General_Director));
1469         }
1470         if (!MI.Get(Stream_General, 0, General_Composer).empty())
1471         {
1472             Node* Node_Creator=Node_Creation->Add_Child("mpeg7:Creator");
1473             Node_Creator->Add_Child("mpeg7:Role", "", "href", "urn:mpeg:mpeg7:cs:RoleCS:2001:COMPOSER");
1474             Node* Node_Agent=Node_Creator->Add_Child("mpeg7:Agent", "", "xsi:type", "PersonGroupType");
1475             Node_Agent->Add_Child("mpeg7:Name", MI.Get(Stream_General, 0, General_Composer));
1476         }
1477         if (!MI.Get(Stream_General, 0, General_CostumeDesigner).empty())
1478         {
1479             Node* Node_Creator=Node_Creation->Add_Child("mpeg7:Creator");
1480             Node_Creator->Add_Child("mpeg7:Role", "", "href", "urn:mpeg:mpeg7:cs:RoleCS:2001:COSTUME-SUPERVISOR");
1481             Node* Node_Agent=Node_Creator->Add_Child("mpeg7:Agent", "", "xsi:type", "PersonGroupType");
1482             Node_Agent->Add_Child("mpeg7:Name", MI.Get(Stream_General, 0, General_CostumeDesigner));
1483         }
1484         if (!MI.Get(Stream_General, 0, General_ProductionDesigner).empty())
1485         {
1486             Node* Node_Creator=Node_Creation->Add_Child("mpeg7:Creator");
1487             Node_Creator->Add_Child("mpeg7:Role", "", "href", "urn:mpeg:mpeg7:cs:RoleCS:2001:PRODUCTION-DESIGNER");
1488             Node* Node_Agent=Node_Creator->Add_Child("mpeg7:Agent", "", "xsi:type", "PersonGroupType");
1489             Node_Agent->Add_Child("mpeg7:Name", MI.Get(Stream_General, 0, General_ProductionDesigner));
1490         }
1491         if (!MI.Get(Stream_General, 0, General_Publisher).empty())
1492         {
1493             Node* Node_Creator=Node_Creation->Add_Child("mpeg7:Creator");
1494             Node_Creator->Add_Child("mpeg7:Role", "", "href", "urn:mpeg:mpeg7:cs:RoleCS:2001:PUBLISHER");
1495             Node* Node_Agent=Node_Creator->Add_Child("mpeg7:Agent", "", "xsi:type", "PersonGroupType");
1496             Node_Agent->Add_Child("mpeg7:Name", MI.Get(Stream_General, 0, General_Publisher));
1497         }
1498         if (!MI.Get(Stream_General, 0, General_DistributedBy).empty())
1499         {
1500             Node* Node_Creator=Node_Creation->Add_Child("mpeg7:Creator");
1501             Node_Creator->Add_Child("mpeg7:Role", "", "href", "urn:mpeg:mpeg7:cs:RoleCS:2001:DISTRIBUTOR");
1502             Node* Node_Agent=Node_Creator->Add_Child("mpeg7:Agent", "", "xsi:type", "PersonGroupType");
1503             Node_Agent->Add_Child("mpeg7:Name", MI.Get(Stream_General, 0, General_DistributedBy));
1504         }
1505         if (!MI.Get(Stream_General, 0, General_Label).empty())
1506         {
1507             Node* Node_Creator=Node_Creation->Add_Child("mpeg7:Creator");
1508             Node_Creator->Add_Child("mpeg7:Role", "", "href", "urn:x-mpeg7-mediainfo:cs:RoleCS:2009:RECORD-LABEL");
1509             Node* Node_Agent=Node_Creator->Add_Child("mpeg7:Agent", "", "xsi:type", "OrganizationType");
1510             Node_Agent->Add_Child("mpeg7:Name", MI.Get(Stream_General, 0, General_Label));
1511         }
1512         if (!MI.Get(Stream_General, 0, General_Recorded_Date).empty())
1513         {
1514             Node* Node_Date=Node_Creation->Add_Child("mpeg7:CreationCoordinates")->Add_Child("mpeg7:Date");
1515             Node_Date->Add_Child("")->XmlCommentOut="Recorded date";
1516             Node_Date->Add_Child("mpeg7:TimePoint", Mpeg7_TimeToISO(MI.Get(Stream_General, 0, General_Recorded_Date)));
1517         }
1518         if (!MI.Get(Stream_General, 0, General_Encoded_Date).empty())
1519         {
1520             Node* Node_Date=Node_Creation->Add_Child("mpeg7:CreationCoordinates")->Add_Child("mpeg7:Date");
1521             Ztring TimePoint=Mpeg7_TimeToISO(MI.Get(Stream_General, 0, General_Encoded_Date));
1522             bool TimePoint_Isvalid=Mpeg7_TimeToISO_Isvalid(TimePoint);
1523             if (TimePoint_Isvalid)
1524                 Node_Date->Add_Child("")->XmlCommentOut="Encoded date";
1525             Node_Date->Add_Child("mpeg7:TimePoint", TimePoint);
1526             if (!TimePoint_Isvalid)
1527                 Node_Date->XmlCommentOut="Encoded date, invalid input";
1528         }
1529         if (!MI.Get(Stream_General, 0, General_Producer).empty())
1530         {
1531             Node* Node_Tool=Node_Creation->Add_Child("mpeg7:CreationTool")->Add_Child("mpeg7:Tool");
1532             Node_Tool->Add_Child("")->XmlCommentOut="Producer";
1533             Node_Tool->Add_Child("mpeg7:Name", MI.Get(Stream_General, 0, General_Producer));
1534         }
1535         if (!MI.Get(Stream_General, 0, General_Encoded_Application).empty())
1536         {
1537             Node* Node_Tool=Node_Creation->Add_Child("mpeg7:CreationTool")->Add_Child("mpeg7:Tool");
1538             Node_Tool->Add_Child("")->XmlCommentOut="Writing application";
1539             Node_Tool->Add_Child("mpeg7:Name", MI.Get(Stream_General, 0, General_Encoded_Application));
1540         }
1541         else if (!MI.Get(Stream_General, 0, General_Encoded_Library).empty())
1542         {
1543             Node* Node_Tool=Node_Creation->Add_Child("mpeg7:CreationTool")->Add_Child("mpeg7:Tool");
1544             Node_Tool->Add_Child("")->XmlCommentOut="Writing library";
1545             Node_Tool->Add_Child("mpeg7:Name", MI.Get(Stream_General, 0, General_Encoded_Library));
1546         }
1547     }
1548 
1549     if (MI.Count_Get(Stream_Video)==1 || MI.Count_Get(Stream_Audio)==1)
1550     {
1551         Node* Node_MediaTime=Node_Type->Add_Child("mpeg7:MediaTime");
1552         //MediaTimePoint
1553         Value=Mpeg7_MediaTimePoint(MI);
1554         if (!Value.empty())
1555             Node_MediaTime->Add_Child("mpeg7:MediaTimePoint", Value);
1556         //MediaDuration
1557         Value=Mpeg7_MediaDuration(MI);
1558         if (!Value.empty())
1559             Node_MediaTime->Add_Child("mpeg7:MediaDuration", Value);
1560     }
1561 
1562     Ztring ToReturn=Ztring().From_UTF8(To_XML(*Node_Mpeg7, 0, true, true).c_str());
1563 
1564     //Find and replace
1565     ZtringListList ToReplace=MediaInfoLib::Config.Inform_Replace_Get_All();
1566     for (size_t Pos=0; Pos<ToReplace.size(); Pos++)
1567         ToReturn.FindAndReplace(ToReplace[Pos][0], ToReplace[Pos][1], 0, Ztring_Recursive);
1568 
1569     //Carriage return
1570     if (MediaInfoLib::Config.LineSeparator_Get()!=__T("\n"))
1571         ToReturn.FindAndReplace(__T("\n"), MediaInfoLib::Config.LineSeparator_Get(), 0, Ztring_Recursive);
1572 
1573     return ToReturn;
1574 }
1575 
1576 //***************************************************************************
1577 //
1578 //***************************************************************************
1579 
1580 } //NameSpace
1581 
1582 #endif
1583