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 //
9 // Links:
10 //
11 // http://www.fileformat.info/format/jpeg/
12 // http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html
13 // http://www.w3.org/Graphics/JPEG/jfif3.pdf
14 // http://www.sentex.net/~mwandel/jhead/
15 //
16 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17 
18 //---------------------------------------------------------------------------
19 // Pre-compilation
20 #include "MediaInfo/PreComp.h"
21 #ifdef __BORLANDC__
22     #pragma hdrstop
23 #endif
24 //---------------------------------------------------------------------------
25 
26 //---------------------------------------------------------------------------
27 #include "MediaInfo/Setup.h"
28 //---------------------------------------------------------------------------
29 
30 //---------------------------------------------------------------------------
31 #if defined(MEDIAINFO_JPEG_YES)
32 //---------------------------------------------------------------------------
33 
34 //---------------------------------------------------------------------------
35 #include "MediaInfo/Image/File_Jpeg.h"
36 #include "MediaInfo/MediaInfo_Config_MediaInfo.h"
37 #include "ZenLib/Utils.h"
38 #include <vector>
39 using namespace ZenLib;
40 using namespace std;
41 //---------------------------------------------------------------------------
42 
43 namespace MediaInfoLib
44 {
45 
46 //***************************************************************************
47 // Constants
48 //***************************************************************************
49 
50 //---------------------------------------------------------------------------
51 namespace Elements
52 {
53     const int16u TEM =0xFF01;
54     const int16u SOC =0xFF4F; //JPEG 2000
55     const int16u SIZ =0xFF51; //JPEG 2000
56     const int16u COD =0xFF52; //JPEG 2000
57     const int16u COC =0xFF53; //JPEG 2000
58     const int16u TLM =0xFF55; //JPEG 2000
59     const int16u PLM =0xFF57; //JPEG 2000
60     const int16u PLT =0xFF58; //JPEG 2000
61     const int16u QCD =0xFF5C; //JPEG 2000
62     const int16u QCC =0xFF5D; //JPEG 2000
63     const int16u RGN =0xFF5E; //JPEG 2000
64     const int16u POC =0xFF5F; //JPEG 2000
65     const int16u PPM =0xFF60; //JPEG 2000
66     const int16u PPT =0xFF61; //JPEG 2000
67     const int16u CME =0xFF64; //JPEG 2000
68     const int16u SOT =0xFF90; //JPEG 2000
69     const int16u SOP =0xFF91; //JPEG 2000
70     const int16u EPH =0xFF92; //JPEG 2000
71     const int16u SOD =0xFF93; //JPEG 2000
72     const int16u SOF0=0xFFC0;
73     const int16u SOF1=0xFFC1;
74     const int16u SOF2=0xFFC2;
75     const int16u SOF3=0xFFC3;
76     const int16u DHT =0xFFC4;
77     const int16u SOF5=0xFFC5;
78     const int16u SOF6=0xFFC6;
79     const int16u SOF7=0xFFC7;
80     const int16u JPG =0xFFC8;
81     const int16u SOF9=0xFFC9;
82     const int16u SOFA=0xFFCA;
83     const int16u SOFB=0xFFCB;
84     const int16u DAC =0xFFCC;
85     const int16u SOFD=0xFFCD;
86     const int16u SOFE=0xFFCE;
87     const int16u SOFF=0xFFCF;
88     const int16u RST0=0xFFD0;
89     const int16u RST1=0xFFD1;
90     const int16u RST2=0xFFD2;
91     const int16u RST3=0xFFD3;
92     const int16u RST4=0xFFD4;
93     const int16u RST5=0xFFD5;
94     const int16u RST6=0xFFD6;
95     const int16u RST7=0xFFD7;
96     const int16u SOI =0xFFD8;
97     const int16u EOI =0xFFD9; //EOC in JPEG 2000
98     const int16u SOS =0xFFDA;
99     const int16u DQT =0xFFDB;
100     const int16u DNL =0xFFDC;
101     const int16u DRI =0xFFDD;
102     const int16u DHP =0xFFDE;
103     const int16u EXP =0xFFDF;
104     const int16u APP0=0xFFE0;
105     const int16u APP1=0xFFE1;
106     const int16u APP2=0xFFE2;
107     const int16u APP3=0xFFE3;
108     const int16u APP4=0xFFE4;
109     const int16u APP5=0xFFE5;
110     const int16u APP6=0xFFE6;
111     const int16u APP7=0xFFE7;
112     const int16u APP8=0xFFE8;
113     const int16u APP9=0xFFE9;
114     const int16u APPA=0xFFEA;
115     const int16u APPB=0xFFEB;
116     const int16u APPC=0xFFEC;
117     const int16u APPD=0xFFED;
118     const int16u APPE=0xFFEE;
119     const int16u APPF=0xFFEF;
120     const int16u JPG0=0xFFF0;
121     const int16u JPG1=0xFFF1;
122     const int16u JPG2=0xFFF2;
123     const int16u JPG3=0xFFF3;
124     const int16u JPG4=0xFFF4;
125     const int16u JPG5=0xFFF5;
126     const int16u JPG6=0xFFF6;
127     const int16u JPG7=0xFFF7;
128     const int16u JPG8=0xFFF8;
129     const int16u JPG9=0xFFF9;
130     const int16u JPGA=0xFFFA;
131     const int16u JPGB=0xFFFB;
132     const int16u JPGC=0xFFFC;
133     const int16u JPGD=0xFFFD;
134     const int16u COM =0xFFFE;
135 }
136 
137 //---------------------------------------------------------------------------
138 // Borland C++ does not accept local template
139 struct Jpeg_samplingfactor
140 {
141     int8u Ci;
142     int8u Hi;
143     int8u Vi;
144 };
145 
146 //---------------------------------------------------------------------------
Jpeg_AddDec(string & Current,int8u Value)147 void Jpeg_AddDec(string& Current, int8u Value)
148 {
149     if (Value < 10)
150         Current += '0' + Value;
151     else
152     {
153         Current += '1';
154         Current += '0' - 10 + Value;
155     }
156 }
157 
158 //---------------------------------------------------------------------------
Jpeg_WithLevel(string Profile,int8u Level,bool HasSubLevel=false)159 string Jpeg_WithLevel(string Profile, int8u Level, bool HasSubLevel=false)
160 {
161     Profile += '@';
162     if (HasSubLevel)
163         Profile += 'M'; // Has Mainlevel
164     Profile += 'L';
165     Jpeg_AddDec(Profile, Level & 0xF);
166     if (HasSubLevel)
167     {
168         Profile += 'S'; // Has Sublevel
169         Profile += 'L';
170         Jpeg_AddDec(Profile, Level >> 4);
171     }
172     return Profile;
173 }
174 
Jpeg2000_Rsiz(int16u Rsiz)175 string Jpeg2000_Rsiz(int16u Rsiz)
176 {
177     switch (Rsiz)
178     {
179         case 0x0000: return "No restrictions";
180         case 0x0001: return "Profile-0";
181         case 0x0002: return "Profile-1";
182         case 0x0003: return "D-Cinema 2k";
183         case 0x0004: return "D-Cinema 4k";
184         case 0x0005: return "D-Cinema 2k Scalable";
185         case 0x0006: return "D-Cinema 4k Scalable";
186         case 0x0007: return "Long-term storage";
187         case 0x0306: return "BCMR@L6"; //Broadcast Contribution Multi-tile Reversible
188         case 0x0307: return "BCMR@L7"; //Broadcast Contribution Multi-tile Reversible
189         default:
190             switch ((Rsiz & 0xFFF0))
191             {
192                 case 0x0100: return Jpeg_WithLevel("BCS", (int8u)Rsiz); //Broadcast Contribution Single-tile
193                 case 0x0200: return Jpeg_WithLevel("BCM", (int8u)Rsiz); //Broadcast Contribution Multi-tile
194                 default:;
195             }
196             switch ((Rsiz & 0xFF00))
197             {
198                 case 0x0400: return Jpeg_WithLevel("IMFS2k", (int8u)Rsiz, true); // IMF Single-tile 2k
199                 case 0x0500: return Jpeg_WithLevel("IMFS4k", (int8u)Rsiz, true); // IMF Single-tile 4k
200                 case 0x0600: return Jpeg_WithLevel("IMFS8k", (int8u)Rsiz, true); // IMF Single-tile 8k
201                 case 0x0700: return Jpeg_WithLevel("IMFMR2k", (int8u)Rsiz, true); // IMF Single/Multi-tile 2k
202                 case 0x0800: return Jpeg_WithLevel("IMFMR4k", (int8u)Rsiz, true); // IMF Single/Multi-tile 4k
203                 case 0x0900: return Jpeg_WithLevel("IMFMR8k", (int8u)Rsiz, true); // IMF Single/Multi-tile 8k
204                 default:;
205             }
206             return Ztring::ToZtring(Rsiz, 16).To_UTF8();
207     }
208 }
209 
ICC_Tag(int32u Signature)210 string ICC_Tag(int32u Signature)
211 {
212     switch (Signature)
213     {
214         case 0x63707274: return "Copyright";
215         case 0x64657363: return "Profile description";
216         case 0x77747074: return "White point";
217         case 0x626B7074: return "Black point";
218         case 0x72545243: return "Reproduction curve, red";
219         case 0x67545243: return "Reproduction curve, green";
220         case 0x62545243: return "Reproduction curve, blue";
221         case 0x7258595A: return "Matrix, red";
222         case 0x6758595A: return "Matrix, green";
223         case 0x6258595A: return "Matrix, blue";
224         default        : return Ztring().From_CC4(Signature).To_UTF8();
225     }
226 }
227 
ICC_ColorSpace(int32u ColorSpace)228 string ICC_ColorSpace(int32u ColorSpace)
229 {
230     switch (ColorSpace)
231     {
232         case 0x434D5920: return "CMY";
233         case 0x434D594B: return "CMYK";
234         case 0x47524159: return "Y";
235         case 0x484C5320: return "HLS";
236         case 0x48535620: return "HSV";
237         case 0x4C616220: return "Lab";
238         case 0x4C757620: return "Luv";
239         case 0x52474220: return "RGB";
240         case 0x58595A20: return "XYZ";
241         case 0x59436272: return "YCbCr";
242         case 0x59787920: return "xyY";
243         default        : return Ztring().From_CC4(ColorSpace).To_UTF8();
244     }
245 }
246 
247 //***************************************************************************
248 // Constructor/Destructor
249 //***************************************************************************
250 
251 //---------------------------------------------------------------------------
File_Jpeg()252 File_Jpeg::File_Jpeg()
253 {
254     //Config
255     #if MEDIAINFO_EVENTS
256         ParserIDs[0]=MediaInfo_Parser_Jpeg;
257         StreamIDs_Width[0]=0;
258     #endif //MEDIAINFO_EVENTS
259     #if MEDIAINFO_TRACE
260         Trace_Layers_Update(8); //Stream
261     #endif //MEDIAINFO_TRACE
262     MustSynchronize=true;
263     StreamSource=IsStream;
264 
265     //In
266     StreamKind=Stream_Image;
267     Interlaced=false;
268     #if MEDIAINFO_DEMUX
269     FrameRate=0;
270     #endif //MEDIAINFO_DEMUX
271 }
272 
273 //***************************************************************************
274 // Streams management
275 //***************************************************************************
276 
277 //---------------------------------------------------------------------------
Streams_Accept()278 void File_Jpeg::Streams_Accept()
279 {
280     if (!IsSub)
281     {
282         TestContinuousFileNames();
283 
284         Stream_Prepare(Config->File_Names.size()>1?Stream_Video:StreamKind);
285         if (File_Size!=(int64u)-1)
286             Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_StreamSize), File_Size);
287         if (StreamKind_Last==Stream_Video)
288             Fill(Stream_Video, StreamPos_Last, Video_FrameCount, Config->File_Names.size());
289     }
290     else
291         Stream_Prepare(StreamKind);
292 
293     //Configuration
294     Buffer_MaximumSize=64*1024*1024; //Some big frames are possible (e.g YUV 4:2:2 10 bits 1080p)
295 }
296 
297 //---------------------------------------------------------------------------
Streams_Finish()298 void File_Jpeg::Streams_Finish()
299 {
300     if (StreamKind_Last==Stream_Video && Config->ParseSpeed>=1.0)
301         Fill (Stream_Video, 0, Video_StreamSize, Buffer_TotalBytes, 10, true);
302 }
303 
304 //***************************************************************************
305 // Static stuff
306 //***************************************************************************
307 
308 //---------------------------------------------------------------------------
FileHeader_Begin()309 bool File_Jpeg::FileHeader_Begin()
310 {
311     //Element_Size
312     if (Buffer_Size<3)
313         return false; //Must wait for more data
314 
315     if (Buffer[2]!=0xFF
316      || (CC2(Buffer)!=Elements::SOI
317       && CC2(Buffer)!=Elements::SOC))
318     {
319         Reject("JPEG");
320         return false;
321     }
322 
323     //All should be OK...
324     return true;
325 }
326 
327 //***************************************************************************
328 // Buffer - Synchro
329 //***************************************************************************
330 
331 //---------------------------------------------------------------------------
Synchronize()332 bool File_Jpeg::Synchronize()
333 {
334     //Synchronizing
335     while(Buffer_Offset+2<=Buffer_Size && (Buffer[Buffer_Offset  ]!=0xFF
336                                         || Buffer[Buffer_Offset+1]==0x00))
337         Buffer_Offset++;
338 
339     if (Buffer_Offset+1==Buffer_Size &&  Buffer[Buffer_Offset  ]!=0xFF)
340         Buffer_Offset++;
341 
342     if (Buffer_Offset+2>Buffer_Size)
343         return false;
344 
345     //Synched is OK
346     Synched=true;
347     return true;
348 }
349 
350 //---------------------------------------------------------------------------
Synched_Test()351 bool File_Jpeg::Synched_Test()
352 {
353     if (SOS_SOD_Parsed)
354         return true; ///No sync after SOD
355 
356     //Must have enough buffer for having header
357     if (Buffer_Offset+2>Buffer_Size)
358         return false;
359 
360     //Quick test of synchro
361     if (Buffer[Buffer_Offset]!=0xFF)
362     {
363         Synched=false;
364         return true;
365     }
366 
367     //We continue
368     return true;
369 }
370 
371 //---------------------------------------------------------------------------
Synched_Init()372 void File_Jpeg::Synched_Init()
373 {
374     APP0_JFIF_Parsed=false;
375     SOS_SOD_Parsed=false;
376     APPE_Adobe0_transform=(int8u)-1;
377 }
378 
379 //***************************************************************************
380 // Buffer - Demux
381 //***************************************************************************
382 
383 //---------------------------------------------------------------------------
384 #if MEDIAINFO_DEMUX
Demux_UnpacketizeContainer_Test()385 bool File_Jpeg::Demux_UnpacketizeContainer_Test()
386 {
387     if (!IsSub)
388     {
389         if (!Status[IsAccepted])
390         {
391             Accept();
392             if (Config->Demux_EventWasSent)
393                 return false;
394         }
395         if (Config->File_Names.size()>1)
396             return Demux_UnpacketizeContainer_Test_OneFramePerFile();
397     }
398 
399     if (Interlaced && Buffer_Offset==0)
400     {
401         bool StartIsFound=false;
402         while (Demux_Offset+2<=Buffer_Size)
403         {
404             int16u code=BigEndian2int16u(Buffer+Demux_Offset);
405             Demux_Offset+=2;
406             switch (code)
407             {
408                 case Elements::SOD  :   //JPEG-2000 start
409                                         StartIsFound=true;
410                 case Elements::TEM  :
411                 case Elements::RST0 :
412                 case Elements::RST1 :
413                 case Elements::RST2 :
414                 case Elements::RST3 :
415                 case Elements::RST4 :
416                 case Elements::RST5 :
417                 case Elements::RST6 :
418                 case Elements::RST7 :
419                 case Elements::SOC  :
420                 case Elements::SOI  :
421                 case Elements::EOI  :
422                              break;
423                 default   :
424                             if (Demux_Offset+2>Buffer_Size)
425                                 break;
426                             {
427                             int16u size=BigEndian2int16u(Buffer+Demux_Offset);
428                             if (Demux_Offset+2+size>Buffer_Size)
429                                 break;
430                             Demux_Offset+=size;
431                             if (code==Elements::SOS) //JPEG start
432                                 StartIsFound=true;
433                             }
434             }
435             if (StartIsFound)
436                 break;
437         }
438 
439         while (Demux_Offset+2<=Buffer_Size)
440         {
441             while (Demux_Offset<Buffer_Size && Buffer[Demux_Offset]!=0xFF)
442                 Demux_Offset++;
443             if (Demux_Offset+2<=Buffer_Size && Buffer[Demux_Offset+1]==0xD9) //EOI (JPEG 2000)
444                 break;
445             Demux_Offset++;
446         }
447         if (Demux_Offset+2<=Buffer_Size)
448             Demux_Offset+=2;
449     }
450     else
451         Demux_Offset=Buffer_Size;
452 
453     if (Interlaced)
454     {
455         if (Field_Count==0 && FrameRate && Demux_Offset!=Buffer_Size)
456             FrameRate*=2; //Now field rate
457         if (FrameRate)
458             FrameInfo.DUR=float64_int64s(1000000000/FrameRate); //Actually, field or frame rate
459     }
460 
461     Demux_UnpacketizeContainer_Demux();
462 
463     if (Interlaced)
464     {
465         if (FrameInfo.DTS!=(int64u)-1 && FrameInfo.DUR!=(int64u)-1)
466             FrameInfo.DTS+=FrameInfo.DUR;
467     }
468 
469     return true;
470 }
471 #endif //MEDIAINFO_DEMUX
472 
473 //***************************************************************************
474 // Buffer - Global
475 //***************************************************************************
476 
477 //---------------------------------------------------------------------------
Read_Buffer_Unsynched()478 void File_Jpeg::Read_Buffer_Unsynched()
479 {
480     SOS_SOD_Parsed=false;
481 
482     Read_Buffer_Unsynched_OneFramePerFile();
483 }
484 
485 //---------------------------------------------------------------------------
Read_Buffer_Continue()486 void File_Jpeg::Read_Buffer_Continue()
487 {
488     if (Config->ParseSpeed>=1.0 && IsSub && Status[IsFilled])
489     {
490         #if MEDIAINFO_DEMUX
491             if (Buffer_TotalBytes<Demux_TotalBytes)
492             {
493                 Skip_XX(Demux_TotalBytes-Buffer_TotalBytes,     "Data"); //We currently don't want to parse data during demux
494                 Param_Info1(Frame_Count);
495                 if (Interlaced)
496                 {
497                     Field_Count++;
498                     Field_Count_InThisBlock++;
499                 }
500                 if (!Interlaced || Field_Count%2==0)
501                 {
502                     Frame_Count++;
503                     if (Frame_Count_NotParsedIncluded!=(int64u)-1)
504                         Frame_Count_NotParsedIncluded++;
505                 }
506                 return;
507             }
508         #endif //MEDIAINFO_DEMUX
509 
510         #if MEDIAINFO_DEMUX
511         if (!Demux_UnpacketizeContainer)
512         #endif //MEDIAINFO_DEMUX
513         {
514             Skip_XX(Buffer_Size,                                    "Data"); //We currently don't want to parse data during demux
515             Param_Info1(Frame_Count);
516             if (Interlaced)
517                 Field_Count+=2;
518             Frame_Count++;
519             if (Frame_Count_NotParsedIncluded!=(int64u)-1)
520                 Frame_Count_NotParsedIncluded++;
521         }
522     }
523 }
524 
525 //***************************************************************************
526 // Buffer - Per element
527 //***************************************************************************
528 
529 //---------------------------------------------------------------------------
Header_Parse()530 void File_Jpeg::Header_Parse()
531 {
532     if (SOS_SOD_Parsed)
533     {
534         Header_Fill_Code(0, "Data");
535         if (!Header_Parser_Fill_Size())
536         {
537             Element_WaitForMoreData();
538             return;
539         }
540         return;
541     }
542 
543     //Parsing
544     int16u code, size;
545     Get_B2 (code,                                               "Marker");
546     switch (code)
547     {
548         case Elements::TEM :
549         case Elements::RST0 :
550         case Elements::RST1 :
551         case Elements::RST2 :
552         case Elements::RST3 :
553         case Elements::RST4 :
554         case Elements::RST5 :
555         case Elements::RST6 :
556         case Elements::RST7 :
557         case Elements::SOC  :
558         case Elements::SOD  :
559         case Elements::SOI  :
560         case Elements::EOI  :
561                     size=0; break;
562         default   : Get_B2 (size,                               "Fl - Frame header length");
563     }
564 
565     //Filling
566     Header_Fill_Code(code, Ztring().From_CC2(code));
567     Header_Fill_Size(2+size);
568 }
569 
570 //---------------------------------------------------------------------------
Header_Parser_Fill_Size()571 bool File_Jpeg::Header_Parser_Fill_Size()
572 {
573     //Look for next Sync word
574     if (Buffer_Offset_Temp==0) //Buffer_Offset_Temp is not 0 if Header_Parse_Fill_Size() has already parsed first frames
575         Buffer_Offset_Temp=Buffer_Offset;
576 
577     #if MEDIAINFO_DEMUX
578         if (Buffer_TotalBytes+2<Demux_TotalBytes)
579             Buffer_Offset_Temp=(size_t)(Demux_TotalBytes-(Buffer_TotalBytes+2));
580     #endif //MEDIAINFO_DEMUX
581 
582     while (Buffer_Offset_Temp+2<=Buffer_Size)
583     {
584         while (Buffer_Offset_Temp<Buffer_Size && Buffer[Buffer_Offset_Temp]!=0xFF)
585             Buffer_Offset_Temp++;
586         if (Buffer_Offset_Temp+2<=Buffer_Size && Buffer[Buffer_Offset_Temp+1]==0xD9) //EOI
587             break;
588         Buffer_Offset_Temp++;
589     }
590 
591     //Must wait more data?
592     if (Buffer_Offset_Temp+2>Buffer_Size)
593     {
594         if (/*FrameIsAlwaysComplete ||*/ File_Offset+Buffer_Size>=File_Size)
595             Buffer_Offset_Temp=Buffer_Size; //We are sure that the next bytes are a start
596         else
597             return false;
598     }
599 
600     //OK, we continue
601     Header_Fill_Size(Buffer_Offset_Temp-Buffer_Offset);
602     Buffer_Offset_Temp=0;
603     return true;
604 }
605 
606 //---------------------------------------------------------------------------
Data_Parse()607 void File_Jpeg::Data_Parse()
608 {
609     #define CASE_INFO(_NAME, _DETAIL) \
610         case Elements::_NAME : Element_Info1(#_NAME); Element_Info1(_DETAIL); _NAME(); break;
611 
612     //Parsing
613     if (SOS_SOD_Parsed)
614     {
615         Skip_XX(Element_Size,                                   "Data");
616         SOS_SOD_Parsed=false;
617         return;
618     }
619     switch (Element_Code)
620     {
621         CASE_INFO(TEM ,                                         "TEM");
622         CASE_INFO(SOC ,                                         "Start of codestream"); //JPEG 2000
623         CASE_INFO(SIZ ,                                         "Image and tile size"); //JPEG 2000
624         CASE_INFO(COD ,                                         "Coding style default"); //JPEG 2000
625         CASE_INFO(COC ,                                         "Coding style component"); //JPEG 2000
626         CASE_INFO(TLM ,                                         "Tile-part lengths, main header"); //JPEG 2000
627         CASE_INFO(PLM ,                                         "Packet length, main header"); //JPEG 2000
628         CASE_INFO(PLT ,                                         "Packet length, tile-part header"); //JPEG 2000
629         CASE_INFO(QCD ,                                         "Quantization default"); //JPEG 2000
630         CASE_INFO(QCC ,                                         "Quantization component "); //JPEG 2000
631         CASE_INFO(RGN ,                                         "Region-of-interest"); //JPEG 2000
632         CASE_INFO(POC ,                                         "Progression order change"); //JPEG 2000
633         CASE_INFO(PPM ,                                         "Packed packet headers, main header"); //JPEG 2000
634         CASE_INFO(PPT ,                                         "Packed packet headers, tile-part header"); //JPEG 2000
635         CASE_INFO(CME ,                                         "Comment and extension"); //JPEG 2000
636         CASE_INFO(SOT ,                                         "Start of tile-part"); //JPEG 2000
637         CASE_INFO(SOP ,                                         "Start of packet"); //JPEG 2000
638         CASE_INFO(EPH ,                                         "End of packet header"); //JPEG 2000
639         CASE_INFO(SOD ,                                         "Start of data"); //JPEG 2000
640         CASE_INFO(SOF0,                                         "Baseline DCT (Huffman)");
641         CASE_INFO(SOF1,                                         "Extended sequential DCT (Huffman)");
642         CASE_INFO(SOF2,                                         "Progressive DCT (Huffman)");
643         CASE_INFO(SOF3,                                         "Lossless (sequential) (Huffman)");
644         CASE_INFO(DHT ,                                         "Define Huffman Tables");
645         CASE_INFO(SOF5,                                         "Differential sequential DCT (Huffman)");
646         CASE_INFO(SOF6,                                         "Differential progressive DCT (Huffman)");
647         CASE_INFO(SOF7,                                         "Differential lossless (sequential) (Huffman)");
648         CASE_INFO(JPG ,                                         "Reserved for JPEG extensions");
649         CASE_INFO(SOF9,                                         "Extended sequential DCT (Arithmetic)");
650         CASE_INFO(SOFA,                                         "Progressive DCT (Arithmetic)");
651         CASE_INFO(SOFB,                                         "Lossless (sequential) (Arithmetic)");
652         CASE_INFO(DAC ,                                         "Define Arithmetic Coding");
653         CASE_INFO(SOFD,                                         "Differential sequential DCT (Arithmetic)");
654         CASE_INFO(SOFE,                                         "Differential progressive DCT (Arithmetic)");
655         CASE_INFO(SOFF,                                         "Differential lossless (sequential) (Arithmetic)");
656         CASE_INFO(RST0,                                         "Restart Interval Termination 0");
657         CASE_INFO(RST1,                                         "Restart Interval Termination 1");
658         CASE_INFO(RST2,                                         "Restart Interval Termination 2");
659         CASE_INFO(RST3,                                         "Restart Interval Termination 3");
660         CASE_INFO(RST4,                                         "Restart Interval Termination 4");
661         CASE_INFO(RST5,                                         "Restart Interval Termination 5");
662         CASE_INFO(RST6,                                         "Restart Interval Termination 6");
663         CASE_INFO(RST7,                                         "Restart Interval Termination 7");
664         CASE_INFO(SOI ,                                         "Start Of Image");
665         CASE_INFO(EOI ,                                         "End Of Image"); //Is EOC (End of codestream) in JPEG 2000
666         CASE_INFO(SOS ,                                         "Start Of Scan");
667         CASE_INFO(DQT ,                                         "Define Quantization Tables");
668         CASE_INFO(DNL ,                                         "Define Number of Lines");
669         CASE_INFO(DRI ,                                         "Define Restart Interval");
670         CASE_INFO(DHP ,                                         "Define Hierarchical Progression");
671         CASE_INFO(EXP ,                                         "Expand Reference Components");
672         CASE_INFO(APP0,                                         "Application-specific marker 0");
673         CASE_INFO(APP1,                                         "Application-specific marker 1");
674         CASE_INFO(APP2,                                         "Application-specific marker 2");
675         CASE_INFO(APP3,                                         "Application-specific marker 3");
676         CASE_INFO(APP4,                                         "Application-specific marker 4");
677         CASE_INFO(APP5,                                         "Application-specific marker 5");
678         CASE_INFO(APP6,                                         "Application-specific marker 6");
679         CASE_INFO(APP7,                                         "Application-specific marker 7");
680         CASE_INFO(APP8,                                         "Application-specific marker 8");
681         CASE_INFO(APP9,                                         "Application-specific marker 9");
682         CASE_INFO(APPA,                                         "Application-specific marker 10");
683         CASE_INFO(APPB,                                         "Application-specific marker 11");
684         CASE_INFO(APPC,                                         "Application-specific marker 12");
685         CASE_INFO(APPD,                                         "Application-specific marker 13");
686         CASE_INFO(APPE,                                         "Application-specific marker 14");
687         CASE_INFO(APPF,                                         "Application-specific marker 15");
688         CASE_INFO(JPG0,                                         "JPG");
689         CASE_INFO(JPG1,                                         "JPG");
690         CASE_INFO(JPG2,                                         "JPG");
691         CASE_INFO(JPG3,                                         "JPG");
692         CASE_INFO(JPG4,                                         "JPG");
693         CASE_INFO(JPG5,                                         "JPG");
694         CASE_INFO(JPG6,                                         "JPG");
695         CASE_INFO(JPG7,                                         "JPG");
696         CASE_INFO(JPG8,                                         "JPG");
697         CASE_INFO(JPG9,                                         "JPG");
698         CASE_INFO(JPGA,                                         "JPG");
699         CASE_INFO(JPGB,                                         "JPG");
700         CASE_INFO(JPGC,                                         "JPG");
701         CASE_INFO(JPGD,                                         "JPG");
702         CASE_INFO(COM ,                                         "Comment");
703         default : Element_Info1("Reserved");
704                   Skip_XX(Element_Size,                         "Data");
705     }
706 }
707 
708 //***************************************************************************
709 // Elements
710 //***************************************************************************
711 
712 //---------------------------------------------------------------------------
SIZ()713 void File_Jpeg::SIZ()
714 {
715     //Parsing
716     vector<float> SamplingFactors;
717     vector<int8u> BitDepths;
718     int8u SamplingFactors_Max=0;
719     int32u Xsiz, Ysiz;
720     int16u Rsiz, Count;
721     Get_B2 (Rsiz,                                               "Rsiz - Capability of the codestream");
722     Get_B4 (Xsiz,                                               "Xsiz - Image size X");
723     Get_B4 (Ysiz,                                               "Ysiz - Image size Y");
724     Skip_B4(                                                    "XOsiz - Image offset X");
725     Skip_B4(                                                    "YOsiz - Image offset Y");
726     Skip_B4(                                                    "tileW - Size of tile W");
727     Skip_B4(                                                    "tileH - Size of tile H");
728     Skip_B4(                                                    "XTOsiz - Upper-left tile offset X");
729     Skip_B4(                                                    "YTOsiz - Upper-left tile offset Y");
730     Get_B2 (Count,                                              "Components and initialize related arrays");
731     for (int16u Pos=0; Pos<Count; Pos++)
732     {
733         Element_Begin1("Initialize related array");
734         int8u BitDepth, compSubsX, compSubsY;
735         BS_Begin();
736         Skip_SB(                                                "Signed");
737         Get_S1 (7, BitDepth,                                    "BitDepth"); Param_Info1(1+BitDepth); Element_Info1(1+BitDepth);
738         BS_End();
739         Get_B1 (   compSubsX,                                   "compSubsX"); Element_Info1(compSubsX);
740         Get_B1 (   compSubsY,                                   "compSubsY"); Element_Info1(compSubsY);
741         Element_End0();
742 
743         //Filling list of HiVi
744         if (compSubsX)
745         {
746             SamplingFactors.push_back(((float)compSubsY)/compSubsX);
747             if (((float)compSubsY)/compSubsX>SamplingFactors_Max)
748                 SamplingFactors_Max=(int8u)((float)compSubsY)/compSubsX;
749         }
750 
751         if (BitDepths.empty() || BitDepth!=BitDepths[0])
752             BitDepths.push_back(BitDepth);
753     }
754 
755     FILLING_BEGIN_PRECISE();
756         if (Frame_Count==0 && Field_Count==0)
757         {
758             Accept("JPEG 2000");
759             Fill("JPEG 2000");
760 
761             if (Count_Get(StreamKind_Last)==0)
762                 Stream_Prepare(StreamKind_Last);
763             Fill(StreamKind_Last, 0, Fill_Parameter(StreamKind_Last, Generic_Format), "JPEG 2000");
764             Fill(StreamKind_Last, 0, Fill_Parameter(StreamKind_Last, Generic_Codec), "JPEG 2000");
765             Fill(StreamKind_Last, 0, "Format_Profile", Jpeg2000_Rsiz(Rsiz));
766             if (StreamKind_Last==Stream_Image)
767                 Fill(Stream_Image, 0, Image_Codec_String, "JPEG 2000", Unlimited, true, true); //To Avoid automatic filling
768             Fill(StreamKind_Last, 0, StreamKind_Last==Stream_Image?(size_t)Image_Width:(size_t)Video_Width, Xsiz);
769             Fill(StreamKind_Last, 0, StreamKind_Last==Stream_Image?(size_t)Image_Height:(size_t)Video_Height, Ysiz*(Interlaced?2:1)); //If image is from interlaced content, must multiply height by 2
770 
771             if (BitDepths.size()==1)
772                 Fill(StreamKind_Last, 0, Fill_Parameter(StreamKind_Last, Generic_BitDepth), 1+BitDepths[0]);
773 
774             //Chroma subsampling
775             if (SamplingFactors_Max)
776                 while (SamplingFactors_Max<4)
777                 {
778                     for (size_t Pos=0; Pos<SamplingFactors.size(); Pos++)
779                         SamplingFactors[Pos]*=2;
780                     SamplingFactors_Max*=2;
781                 }
782             while (SamplingFactors.size()<3)
783                 SamplingFactors.push_back(0);
784             Ztring ChromaSubsampling;
785             for (size_t Pos=0; Pos<SamplingFactors.size(); Pos++)
786                 ChromaSubsampling+=Ztring::ToZtring(SamplingFactors[Pos], 0)+__T(':');
787             if (!ChromaSubsampling.empty())
788             {
789                 ChromaSubsampling.resize(ChromaSubsampling.size()-1);
790                 Fill(StreamKind_Last, 0, "ChromaSubsampling", ChromaSubsampling);
791 
792                 //Not for sure
793                 if (ChromaSubsampling==__T("4:4:4") && (Retrieve(StreamKind_Last, 0, "Format_Profile")==__T("D-Cinema 2k") || Retrieve(StreamKind_Last, 0, "Format_Profile")==__T("D-Cinema 4k")))
794                     Fill(StreamKind_Last, 0, "ColorSpace", "XYZ");
795                 else if (!IsSub)
796                 {
797                     if (ChromaSubsampling==__T("4:2:0") || ChromaSubsampling==__T("4:2:2"))
798                         Fill(StreamKind_Last, 0, "ColorSpace", "YUV");
799                     else if (ChromaSubsampling==__T("4:4:4"))
800                         Fill(StreamKind_Last, 0, "ColorSpace", "RGB");
801                 }
802             }
803         }
804     FILLING_END();
805 }
806 
807 //---------------------------------------------------------------------------
COD()808 void File_Jpeg::COD()
809 {
810     //Parsing
811     int8u Style, Style2, Levels, MultipleComponentTransform;
812     bool PrecinctUsed;
813     Get_B1 (Style,                                              "Scod - Style");
814         Get_Flags (Style, 0, PrecinctUsed,                      "Precinct used");
815         Skip_Flags(Style, 1,                                    "Use SOP (start of packet)");
816         Skip_Flags(Style, 2,                                    "Use EPH (end of packet header)");
817     Get_B1 (Levels,                                             "Number of decomposition levels");
818     Skip_B1(                                                    "Progression order");
819     Skip_B2(                                                    "Number of layers");
820     Info_B1(DimX,                                               "Code-blocks dimensions X (2^(n+2))"); Param_Info2(1<<(DimX+2), " pixels");
821     Info_B1(DimY,                                               "Code-blocks dimensions Y (2^(n+2))"); Param_Info2(1<<(DimY+2), " pixels");
822     Get_B1 (Style2,                                             "Style of the code-block coding passes");
823         Skip_Flags(Style2, 0,                                   "Selective arithmetic coding bypass");
824         Skip_Flags(Style2, 1,                                   "MQ states for all contexts");
825         Skip_Flags(Style2, 2,                                   "Regular termination");
826         Skip_Flags(Style2, 3,                                   "Vertically stripe-causal context formation");
827         Skip_Flags(Style2, 4,                                   "Error resilience info is embedded on MQ termination");
828         Skip_Flags(Style2, 5,                                   "Segmentation marker is to be inserted at the end of each normalization coding pass");
829     Skip_B1(                                                    "Transform");
830     Get_B1(MultipleComponentTransform,                          "Multiple component transform");
831     if (PrecinctUsed)
832     {
833         BS_Begin();
834         Skip_S1(4,                                              "LL sub-band width");
835         Skip_S1(4,                                              "LL sub-band height");
836         BS_End();
837         for (int16u Pos=0; Pos<Levels; Pos++)
838         {
839             Element_Begin1("Decomposition level");
840             BS_Begin();
841             Skip_S1(4,                                          "decomposition level width");
842             Skip_S1(4,                                          "decomposition level height");
843             BS_End();
844             Element_End0();
845         }
846     }
847 
848     FILLING_BEGIN();
849         if (Frame_Count==0 && Field_Count==0)
850         {
851             switch (MultipleComponentTransform)
852             {
853                 case 0x01 : Fill(StreamKind_Last, 0, "Compression_Mode", "Lossless"); break;
854                 case 0x02 : Fill(StreamKind_Last, 0, "Compression_Mode", "Lossy"); break;
855                 default   : ;
856             }
857         }
858     FILLING_END();
859 }
860 
861 //---------------------------------------------------------------------------
QCD()862 void File_Jpeg::QCD()
863 {
864     //Parsing
865     Skip_B1(                                                    "Sqcd - Style");
866     Skip_XX(Element_Size-Element_Offset,                        "QCD data");
867 }
868 
869 //---------------------------------------------------------------------------
SOD()870 void File_Jpeg::SOD()
871 {
872     SOS_SOD_Parsed=true;
873     if (Interlaced)
874     {
875         Field_Count++;
876         Field_Count_InThisBlock++;
877     }
878     if (!Interlaced || Field_Count%2==0)
879     {
880         Frame_Count++;
881         Frame_Count_InThisBlock++;
882         if (Frame_Count_NotParsedIncluded!=(int64u)-1)
883             Frame_Count_NotParsedIncluded++;
884         if (Status[IsFilled])
885             Fill();
886         if (Config->ParseSpeed<1.0)
887             Finish("JPEG 2000"); //No need of more
888     }
889 }
890 
891 //---------------------------------------------------------------------------
SOF_()892 void File_Jpeg::SOF_()
893 {
894     //Parsing
895     vector<Jpeg_samplingfactor> SamplingFactors;
896     int16u Height, Width;
897     int8u  Resolution, Count;
898     Get_B1 (Resolution,                                         "P - Sample precision");
899     Get_B2 (Height,                                             "Y - Number of lines");
900     Get_B2 (Width,                                              "X - Number of samples per line");
901     Get_B1 (Count,                                              "Nf - Number of image components in frame");
902     for (int8u Pos=0; Pos<Count; Pos++)
903     {
904         Jpeg_samplingfactor SamplingFactor;
905         Element_Begin1("Component");
906         Get_B1 (   SamplingFactor.Ci,                           "Ci - Component identifier"); if (SamplingFactor.Ci>Count) Element_Info1(Ztring().append(1, (Char)SamplingFactor.Ci)); else Element_Info1(SamplingFactor.Ci);
907         BS_Begin();
908         Get_S1 (4, SamplingFactor.Hi,                           "Hi - Horizontal sampling factor"); Element_Info1(SamplingFactor.Hi);
909         Get_S1 (4, SamplingFactor.Vi,                           "Vi - Vertical sampling factor"); Element_Info1(SamplingFactor.Vi);
910         BS_End();
911         Skip_B1(                                                "Tqi - Quantization table destination selector");
912         Element_End0();
913 
914         //Filling list of HiVi
915         SamplingFactors.push_back(SamplingFactor);
916     }
917 
918     FILLING_BEGIN_PRECISE();
919         if (Frame_Count==0 && Field_Count==0)
920         {
921             Accept("JPEG");
922             Fill("JPEG");
923 
924             if (Count_Get(StreamKind_Last)==0)
925                 Stream_Prepare(StreamKind_Last);
926             Fill(StreamKind_Last, 0, Fill_Parameter(StreamKind_Last, Generic_Format), "JPEG");
927             Fill(StreamKind_Last, 0, Fill_Parameter(StreamKind_Last, Generic_Codec), "JPEG");
928             if (StreamKind_Last==Stream_Image)
929                 Fill(Stream_Image, 0, Image_Codec_String, "JPEG", Unlimited, true, true); //To Avoid automatic filling
930             if (StreamKind_Last==Stream_Video)
931                 Fill(Stream_Video, 0, Video_InternetMediaType, "video/JPEG", Unlimited, true, true);
932             Fill(StreamKind_Last, 0, Fill_Parameter(StreamKind_Last, Generic_BitDepth), Resolution);
933             Fill(StreamKind_Last, 0, "Height", Height*(Interlaced?2:1));
934             Fill(StreamKind_Last, 0, "Width", Width);
935 
936             //ColorSpace from http://docs.oracle.com/javase/1.4.2/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html
937             //TODO: if APPE_Adobe0_transform is present, indicate that K is inverted, see http://halicery.com/Image/jpeg/JPEGCMYK.html
938             switch (APPE_Adobe0_transform)
939             {
940                 case 0x01 :
941                             if (Count==3)
942                                 Fill(StreamKind_Last, 0, "ColorSpace", "YUV");
943                             break;
944                 case 0x02 :
945                             if (Count==4)
946                                 Fill(StreamKind_Last, 0, "ColorSpace", "YUVK");
947                             break;
948                 default   :
949                             {
950                             int8u Ci[256];
951                             memset(Ci, 0, 256);
952                             for (int8u Pos=0; Pos<Count; Pos++)
953                                 Ci[SamplingFactors[Pos].Ci]++;
954 
955                             switch (Count)
956                             {
957                                 case 1 :    Fill(StreamKind_Last, 0, "ColorSpace", "Y"); break;
958                                 case 2 :    Fill(StreamKind_Last, 0, "ColorSpace", "YA"); break;
959                                 case 3 :
960                                                  if (!APP0_JFIF_Parsed && Ci['R']==1 && Ci['G']==1 && Ci['B']==1)                                                       //RGB
961                                                 Fill(StreamKind_Last, 0, "ColorSpace", "RGB");
962                                             else if ((Ci['Y']==1 && ((Ci['C']==1 && Ci['c']==1)                                                                         //YCc
963                                                                   || Ci['C']==2))                                                                                       //YCC
964                                                   || APP0_JFIF_Parsed                                                                                                   //APP0 JFIF header present so YCC
965                                                   || APPE_Adobe0_transform==0                                                                                           //transform set to YCC
966                                                   || (SamplingFactors[0].Ci==0 && SamplingFactors[1].Ci==1 && SamplingFactors[2].Ci==2)                                 //012
967                                                   || (SamplingFactors[0].Ci==1 && SamplingFactors[1].Ci==2 && SamplingFactors[2].Ci==3))                                //123
968                                                 Fill(StreamKind_Last, 0, "ColorSpace", "YUV");
969                                             else if (APPE_Adobe0_transform==0 || APPE_Adobe0_transform==(int8u)-1)                                                      //transform set to RGB (it is a guess)
970                                                 Fill(StreamKind_Last, 0, "ColorSpace", "RGB");
971                                             break;
972                                 case 4 :
973                                                  if (!APP0_JFIF_Parsed && Ci['R']==1 && Ci['G']==1 && Ci['B']==1 && Ci['A']==1)                                         //RGBA
974                                                 Fill(StreamKind_Last, 0, "ColorSpace", "RGBA");
975                                             else if ((Ci['Y']==1 && Ci['A']==1 && ((Ci['C']==1 && Ci['c']==1)                                                           //YCcA
976                                                                                 || Ci['C']==2))                                                                         //YCCA
977                                                   || APP0_JFIF_Parsed                                                                                                   //APP0 JFIF header present so YCCA
978                                                   || (SamplingFactors[0].Ci==0 && SamplingFactors[1].Ci==1 && SamplingFactors[2].Ci==2 && SamplingFactors[3].Ci==3)     //0123
979                                                   || (SamplingFactors[0].Ci==1 && SamplingFactors[1].Ci==2 && SamplingFactors[2].Ci==3 && SamplingFactors[3].Ci==4))    //1234
980                                                 Fill(StreamKind_Last, 0, "ColorSpace", "YUVA");
981                                             else if (Ci['C']==1 && Ci['M']==1 && Ci['Y']==1 && Ci['K']==1)                                                              //CMYK
982                                                 Fill(StreamKind_Last, 0, "ColorSpace", "CMYK");
983                                             else if (APPE_Adobe0_transform==0 || APPE_Adobe0_transform==(int8u)-1)                                                      //transform set to CMYK (it is a guess)
984                                                 Fill(StreamKind_Last, 0, "ColorSpace", "CMYK");
985                                             break;
986                                 default:    ;
987                             }
988                             }
989             }
990 
991             //Chroma subsampling
992             if ((SamplingFactors.size()==3 || SamplingFactors.size()==4) && SamplingFactors[1].Hi==1 && SamplingFactors[2].Hi==1 && SamplingFactors[1].Vi==1 && SamplingFactors[2].Vi==1)
993             {
994                 string ChromaSubsampling;
995                 switch (SamplingFactors[0].Hi)
996                 {
997                     case 1 :
998                             switch (SamplingFactors[0].Vi)
999                             {
1000                                 case 1 : if (Retrieve(StreamKind_Last, 0, "ColorSpace").find(__T("YUV"))==0) ChromaSubsampling="4:4:4"; break;
1001                                 default: ;
1002                             }
1003                             break;
1004                     case 2 :
1005                             switch (SamplingFactors[0].Vi)
1006                             {
1007                                 case 1 : ChromaSubsampling="4:2:2"; break;
1008                                 case 2 : ChromaSubsampling="4:2:0"; break;
1009                                 default: ;
1010                             }
1011                             break;
1012                     case 4 :
1013                             switch (SamplingFactors[0].Vi)
1014                             {
1015                                 case 1 : ChromaSubsampling="4:1:1"; break;
1016                                 case 2 : ChromaSubsampling="4:1:0"; break;
1017                                 default: ;
1018                             }
1019                             break;
1020                     default: ;
1021                 }
1022                 if (!ChromaSubsampling.empty())
1023                 {
1024                     if (SamplingFactors.size()>3 && (SamplingFactors[3].Hi!=SamplingFactors[0].Hi || SamplingFactors[3].Vi!=SamplingFactors[0].Vi))
1025                         ChromaSubsampling+=":?";
1026                     Fill(StreamKind_Last, 0, "ChromaSubsampling", ChromaSubsampling);
1027                 }
1028             }
1029         }
1030     FILLING_END();
1031 }
1032 
1033 //---------------------------------------------------------------------------
SOS()1034 void File_Jpeg::SOS()
1035 {
1036     //Parsing
1037     int8u Count;
1038     Get_B1 (Count,                                              "Number of image components in scan");
1039     for (int8u Pos=0; Pos<Count; Pos++)
1040     {
1041         Skip_B1(                                                "Scan component selector");
1042         Skip_B1(                                                "Entropy coding table destination selector");
1043     }
1044     Skip_B1(                                                    "Start of spectral or predictor selection");
1045     Skip_B1(                                                    "End of spectral selection");
1046     Skip_B1(                                                    "Successive approximation bit position");
1047 
1048     FILLING_BEGIN_PRECISE();
1049     SOS_SOD_Parsed=true;
1050     if (Interlaced)
1051     {
1052         Field_Count++;
1053         Field_Count_InThisBlock++;
1054     }
1055     if (!Interlaced || Field_Count%2==0)
1056     {
1057         Frame_Count++;
1058         Frame_Count_InThisBlock++;
1059         if (Frame_Count_NotParsedIncluded!=(int64u)-1)
1060             Frame_Count_NotParsedIncluded++;
1061     }
1062     if (Status[IsFilled])
1063         Fill();
1064     if (Config->ParseSpeed<1.0)
1065         Finish("JPEG"); //No need of more
1066     FILLING_END();
1067 }
1068 
1069 //---------------------------------------------------------------------------
APP0()1070 void File_Jpeg::APP0()
1071 {
1072     //Parsing
1073     int32u Name;
1074     Get_C4(Name,                                                "Name");
1075     switch (Name)
1076     {
1077         case 0x41564931 : APP0_AVI1(); break; //"AVI1"
1078         case 0x4A464946 : APP0_JFIF(); break; //"JFIF"
1079         case 0x4A464646 : APP0_JFFF(); break; //"JFFF"
1080         default         : Skip_XX(Element_Size-Element_Offset,  "Unknown");
1081     }
1082 }
1083 
1084 //---------------------------------------------------------------------------
1085 // From OpenDML AVI File Format Extensions
APP0_AVI1()1086 void File_Jpeg::APP0_AVI1()
1087 {
1088     Element_Info1("AVI1");
1089 
1090     //Parsing
1091     bool UnknownInterlacement_IsDetected=false;
1092     int8u  FieldOrder=(int8u)-1;
1093     Get_B1 (FieldOrder,                                         "Polarity");
1094     if (Element_Size>=14)
1095     {
1096         int32u FieldSize, FieldSizeLessPadding;
1097         Skip_B1(                                                "Reserved");
1098         Get_B4 (FieldSize,                                      "FieldSize");
1099         Get_B4 (FieldSizeLessPadding,                           "FieldSizeLessPadding");
1100 
1101         //Coherency
1102         if (FieldOrder==0 && IsSub && FieldSize && FieldSize!=Buffer_Size)
1103         {
1104             if (FieldSizeLessPadding>1 && FieldSizeLessPadding<=Buffer_Size && Buffer[FieldSizeLessPadding-2]==0xFF && Buffer[FieldSizeLessPadding-1]==0xD9  //EOI
1105              &&                           FieldSize+1         < Buffer_Size && Buffer[FieldSize]             ==0xFF && Buffer[FieldSize+1]           ==0xD8) //SOI
1106                 UnknownInterlacement_IsDetected=true;
1107         }
1108     }
1109     Skip_XX(Element_Size-Element_Offset,                        "Unknown");
1110 
1111     FILLING_BEGIN();
1112         if (Frame_Count==0 && Field_Count==0)
1113         {
1114             Accept();
1115 
1116             if (UnknownInterlacement_IsDetected)
1117             {
1118                 Fill(Stream_Video, 0, Video_ScanType, "Interlaced");
1119                 Interlaced=true;
1120             }
1121             else
1122             {
1123             switch (FieldOrder)
1124             {
1125                 case 0x00 : Fill(Stream_Video, 0, Video_Interlacement, "PPF"); Fill(Stream_Video, 0, Video_ScanType, "Progressive"); break;
1126                 case 0x01 : Fill(Stream_Video, 0, Video_Interlacement, "TFF"); Fill(Stream_Video, 0, Video_ScanType, "Interlaced"); Fill(Stream_Video, 0, Video_ScanOrder, "TFF"); Interlaced=true; break;
1127                 case 0x02 : Fill(Stream_Video, 0, Video_Interlacement, "BFF"); Fill(Stream_Video, 0, Video_ScanType, "Interlaced"); Fill(Stream_Video, 0, Video_ScanOrder, "BFF"); Interlaced=true; break;
1128                 default   : ;
1129             }
1130             }
1131         }
1132     FILLING_END();
1133 }
1134 
1135 //---------------------------------------------------------------------------
APP0_JFIF()1136 void File_Jpeg::APP0_JFIF()
1137 {
1138     Element_Info1("JFIF");
1139 
1140     //Parsing
1141     Skip_B1(                                                    "Zero");
1142     int16u Width, Height;
1143     int8u  Unit, ThumbailX, ThumbailY;
1144     Skip_B2(                                                    "Version");
1145     Get_B1 (Unit,                                               "Unit"); //0=Pixels, 1=dpi, 2=dpcm
1146     Get_B2 (Width,                                              "Xdensity");
1147     Get_B2 (Height,                                             "Ydensity");
1148     Get_B1 (ThumbailX,                                          "Xthumbail");
1149     Get_B1 (ThumbailY,                                          "Ythumbail");
1150     Skip_XX(3*ThumbailX*ThumbailY,                              "RGB Thumbail");
1151 
1152     APP0_JFIF_Parsed=true;
1153 }
1154 
1155 //---------------------------------------------------------------------------
APP0_JFFF()1156 void File_Jpeg::APP0_JFFF()
1157 {
1158     Element_Info1("JFFF");
1159 
1160     Skip_B1(                                                    "Zero");
1161     Skip_B1(                                                    "extension_code"); //0x10 Thumbnail coded using JPEG, 0x11 Thumbnail stored using 1 byte/pixel, 0x13 Thumbnail stored using 3 bytes/pixel
1162     if (Element_Size>Element_Offset)
1163         Skip_XX(Element_Size-Element_Offset,                    "extension_data");
1164 }
1165 
1166 //---------------------------------------------------------------------------
APP0_JFFF_JPEG()1167 void File_Jpeg::APP0_JFFF_JPEG()
1168 {
1169     //Parsing
1170     Element_Begin1("Thumbail JPEG");
1171         if (Element_Size>Element_Offset)
1172             Skip_XX(Element_Size-Element_Offset,                "Data");
1173     Element_End0();
1174 }
1175 
1176 //---------------------------------------------------------------------------
APP0_JFFF_1B()1177 void File_Jpeg::APP0_JFFF_1B()
1178 {
1179     //Parsing
1180     Element_Begin1("Thumbail 1 byte per pixel");
1181         int8u  ThumbailX, ThumbailY;
1182         Get_B1 (ThumbailX,                                      "Xthumbail");
1183         Get_B1 (ThumbailY,                                      "Ythumbail");
1184         Skip_XX(768,                                            "Palette");
1185         Skip_XX(ThumbailX*ThumbailY,                            "Thumbail");
1186     Element_End0();
1187 }
1188 
1189 //---------------------------------------------------------------------------
APP0_JFFF_3B()1190 void File_Jpeg::APP0_JFFF_3B()
1191 {
1192     //Parsing
1193     Element_Begin1("Thumbail 3 bytes per pixel");
1194         int8u  ThumbailX, ThumbailY;
1195         Get_B1 (ThumbailX,                                      "Xthumbail");
1196         Get_B1 (ThumbailY,                                      "Ythumbail");
1197         Skip_XX(3*ThumbailX*ThumbailY,                          "RGB Thumbail");
1198     Element_End0();
1199 }
1200 
1201 //---------------------------------------------------------------------------
APP1()1202 void File_Jpeg::APP1()
1203 {
1204     //Parsing
1205     int64u Name;
1206     Get_C6(Name,                                                "Name");
1207 
1208     switch (Name)
1209     {
1210         case 0x457869660000LL : APP1_EXIF(); break; //"Exif\0\0"
1211         default               : Skip_XX(Element_Size-Element_Offset, "Data");
1212     }
1213 }
1214 
1215 //---------------------------------------------------------------------------
APP1_EXIF()1216 void File_Jpeg::APP1_EXIF()
1217 {
1218     Element_Info1("Exif");
1219 
1220     //Parsing
1221     int32u Alignment;
1222     Get_C4(Alignment,                                           "Alignment");
1223     if (Alignment==0x49492A00)
1224         Skip_B4(                                                "First_IFD");
1225     if (Alignment==0x4D4D2A00)
1226         Skip_L4(                                                "First_IFD");
1227 }
1228 
1229 //---------------------------------------------------------------------------
APP2()1230 void File_Jpeg::APP2()
1231 {
1232     //Parsing
1233     if (Element_Size>=12 && Buffer[Buffer_Offset+11]==0 && string((const char*)Buffer+Buffer_Offset)=="ICC_PROFILE")
1234     {
1235         Element_Info1("ICC profile");
1236         int8u Pos;
1237         Skip_Local(12,                                          "Signature");
1238         Get_B1 (Pos,                                            "Chunk position?"); //1-based?
1239         Skip_B1(                                                "Chunk Max?"); //1-based?
1240         if (Pos<=1) //Multi-chunk ICC is not supported so we test it is order to skip the extra ICC blocks
1241             APP2_ICC_PROFILE();
1242         else
1243             Skip_XX(Element_Size-Element_Offset,                "(Multi-chunk ICC is not supported)");
1244     }
1245     else
1246         Skip_XX(Element_Size,                                   "Data");
1247 }
1248 
1249 //---------------------------------------------------------------------------
1250 struct icctagtable
1251 {
1252     int32u Signature;
1253     int32u Offset;
1254     int32u Size;
1255 };
APP2_ICC_PROFILE()1256 void File_Jpeg::APP2_ICC_PROFILE()
1257 {
1258     Element_Begin1("ICC profile");
1259 
1260     //Parsing
1261     int64u Element_Start=Element_Offset; // Needed for tags position
1262     int32u ColorSpace;
1263     Element_Begin1("Profile header");
1264         Skip_B4(                                                "Profile size");
1265         Skip_C4(                                                "Preferred CMM type");
1266         Element_Begin1("Profile version number");
1267             int8u M;
1268             Get_B1(M,                                           "Major");
1269             if (M>4)
1270             {
1271                 Element_End0();
1272                 Element_End0();
1273                 Element_End0();
1274                 return;
1275             }
1276             BS_Begin();
1277             Info_S1(4, m,                                       "Minor");
1278             Info_S1(4, f,                                       "Fix");
1279             BS_End();
1280             Skip_B2(                                            "Reserved");
1281             Element_Info1(Ztring().From_Number(M)+__T('.')+Ztring().From_Number(m)+__T('.')+Ztring().From_Number(f));
1282         Element_End0();
1283         Skip_C4(                                                "Profile/Device class");
1284         Get_C4 (ColorSpace,                                     "Colour space of data");
1285         Skip_C4(                                                "PCS");
1286         Element_Begin1("Date/Time");
1287             Info_B2(YY,                                         "Year");
1288             Info_B2(MM,                                         "Month");
1289             Info_B2(DD,                                         "Day");
1290             Info_B2(hh,                                         "Hour");
1291             Info_B2(mm,                                         "Minute");
1292             Info_B2(ss,                                         "Second");
1293             #if MEDIAINFO_TRACE
1294                 string DateTime;
1295                 DateTime+='0'+YY/1000;
1296                 DateTime+='0'+(YY%1000)/100;
1297                 DateTime+='0'+(YY%100)/10;
1298                 DateTime+='0'+(YY%1000);
1299                 DateTime+='-';
1300                 DateTime+='0'+MM/10;
1301                 DateTime+='0'+(MM%10);
1302                 DateTime+='-';
1303                 DateTime+='0'+DD/10;
1304                 DateTime+='0'+(DD%10);
1305                 DateTime+=' ';
1306                 DateTime+='0'+hh/10;
1307                 DateTime+='0'+(hh%10);
1308                 DateTime+=':';
1309                 DateTime+='0'+mm/10;
1310                 DateTime+='0'+(mm%10);
1311                 DateTime+=':';
1312                 DateTime+='0'+ss/10;
1313                 DateTime+='0'+(ss%10);
1314                 Element_Info1(DateTime.c_str());
1315             #endif //MEDIAINFO_TRACE
1316         Element_End0();
1317         Skip_C4(                                                "'acsp' profile file signature ");
1318         Skip_C4(                                                "Primary platform signature");
1319         Skip_B4(                                                "Profile flags");
1320         Skip_C4(                                                "Device manufacturer");
1321         Skip_B4(                                                "Device model");
1322         Skip_B4(                                                "Device attributes TODO 1");
1323         Skip_B4(                                                "Device attributes TODO 2");
1324         Skip_B4(                                                "Rendering Intent");
1325         Element_Begin1("Illuminant of the PCS");
1326             APP2_ICC_PROFILE_XYZNumber();
1327         Element_End0();
1328         Skip_C4(                                                "Profile creator signature");
1329         Skip_XX(16,                                             "Profile ID");
1330         Skip_XX(28,                                             "Reserved");
1331     Element_End0();
1332 
1333     int32u Count;
1334     vector<icctagtable> TagTables;
1335     Element_Begin1("Tag table");
1336         Get_B4(Count,                                           "Count");
1337         if (Count*12>Element_Size-Element_Offset)
1338             Count=(Element_Size-Element_Offset)/12;
1339         for (int32u i=0; i<Count; i++)
1340         {
1341             icctagtable TagTable;
1342             Get_C4(TagTable.Signature,                          "Signature"); Param_Info1(ICC_Tag(TagTable.Signature).c_str());
1343             Get_B4(TagTable.Offset,                             "Offset");
1344             Get_B4(TagTable.Size,                               "Size");
1345             if (((int64u)TagTable.Offset)+TagTable.Size<=Element_Size-Element_Start)
1346                 TagTables.push_back(TagTable);
1347         }
1348     Element_End0();
1349 
1350     Element_Begin1("Tagged element data");
1351         Count=(int32u)TagTables.size();
1352         for (int32u i=0; i<Count; i++)
1353         {
1354             icctagtable& TagTable=TagTables[i];
1355             Ztring Name;
1356 
1357             Element_Begin1(ICC_Tag(TagTable.Signature).c_str());
1358             Element_Offset=Element_Start+TagTable.Offset;
1359             int32u Type;
1360             Get_C4(Type,                                        "Type");
1361             switch (Type)
1362             {
1363                 case 0x63757276: //curv
1364                                 if (TagTable.Size<12)
1365                                     Skip_XX(TagTable.Size-4,    "Unknown");
1366                                 else
1367                                 {
1368                                     int32u Count;
1369                                     Skip_B4(                    "Reserved");
1370                                     Get_B4(Count,               "Count");
1371                                     if (12+4*((Count+1)/2)!=TagTable.Size)
1372                                         Skip_XX(TagTable.Size-12, "Unknown");
1373                                     else
1374                                     {
1375                                         for (int32u i=0; i<Count; i++)
1376                                             Skip_B2(            "Value");
1377                                         if (Count%2)
1378                                             Skip_B2(            "Padding");
1379                                     }
1380                                 }
1381                                 break;
1382                 case 0x64657363: //desc
1383                                 if (TagTable.Size<12)
1384                                     Skip_XX(TagTable.Size-4,    "Unknown");
1385                                 else
1386                                 {
1387                                     Skip_B7(                    "?");
1388                                     Skip_B1(                    "String size");
1389                                     Skip_Local(TagTable.Size-12, "Value"); //TODO: beter handling of this complex type
1390                                 }
1391                                 break;
1392                 case 0x74657874: //text
1393                                 if (TagTable.Size<8)
1394                                     Skip_XX(TagTable.Size-4,    "Unknown");
1395                                 else
1396                                 {
1397                                     Skip_B4(                    "Reserved");
1398                                     Skip_Local(TagTable.Size-8, "Value");
1399                                 }
1400                                 break;
1401                 case 0x58595A20: //XYZ
1402                                 if (TagTable.Size!=20)
1403                                     Skip_XX(TagTable.Size-4,    "Unknown");
1404                                 else
1405                                 {
1406                                     Skip_B4(                    "Reserved");
1407                                     APP2_ICC_PROFILE_XYZNumber();
1408                                 }
1409                                 break;
1410                 default:        Skip_XX(TagTable.Size-4,        "Unknown");
1411             }
1412             Element_End0();
1413         }
1414     Element_End0();
1415     Element_End0();
1416 
1417     FILLING_BEGIN()
1418         Fill(StreamKind, 0, "ColorSpace_ICC", ICC_ColorSpace(ColorSpace));
1419     FILLING_END()
1420 }
1421 
APP2_ICC_PROFILE_XYZNumber()1422 void File_Jpeg::APP2_ICC_PROFILE_XYZNumber()
1423 {
1424     #if MEDIAINFO_TRACE
1425         APP2_ICC_PROFILE_s15Fixed16Number("X");
1426         APP2_ICC_PROFILE_s15Fixed16Number("Y");
1427         APP2_ICC_PROFILE_s15Fixed16Number("Z");
1428     #else //MEDIAINFO_TRACE
1429         Element_Offset+=12;
1430     #endif //MEDIAINFO_TRACE
1431 }
1432 
APP2_ICC_PROFILE_s15Fixed16Number(const char * Name)1433 void File_Jpeg::APP2_ICC_PROFILE_s15Fixed16Number(const char* Name)
1434 {
1435     Info_B4(Value,                                              Name); Param_Info1(Ztring().From_Number(((float64)Value)/0x10000, 6));
1436 }
1437 
1438 //---------------------------------------------------------------------------
APPE()1439 void File_Jpeg::APPE()
1440 {
1441     //Parsing
1442     int64u Name;
1443     Get_C6(Name,                                                "Name");
1444     switch (Name)
1445     {
1446         case 0x41646F626500LL : APPE_Adobe0(); break; //"AVI1"
1447         default               : Skip_XX(Element_Size-Element_Offset, "Unknown");
1448     }
1449 }
1450 
1451 //---------------------------------------------------------------------------
APPE_Adobe0()1452 void File_Jpeg::APPE_Adobe0()
1453 {
1454     Element_Info1("Adobe");
1455 
1456     //Parsing
1457     int8u Version;
1458     Get_B1(Version,                                             "Version");
1459     if (Version==100)
1460     {
1461         int8u transform;
1462         Skip_B2(                                                "flags0");
1463         Skip_B2(                                                "flags1");
1464         Get_B1 (transform,                                      "transform");
1465 
1466         FILLING_BEGIN();
1467             APPE_Adobe0_transform=transform;
1468         FILLING_END();
1469     }
1470     else
1471         Skip_XX(Element_Size-Element_Offset,                    "unknown");
1472 }
1473 
1474 } //NameSpace
1475 
1476 #endif
1477