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 // Information about OpenMG (OMA) files
10 //
11 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 
13 //---------------------------------------------------------------------------
14 // Pre-compilation
15 #include "MediaInfo/PreComp.h"
16 #ifdef __BORLANDC__
17     #pragma hdrstop
18 #endif
19 //---------------------------------------------------------------------------
20 
21 //---------------------------------------------------------------------------
22 #include "MediaInfo/Setup.h"
23 //---------------------------------------------------------------------------
24 
25 //---------------------------------------------------------------------------
26 #if defined(MEDIAINFO_OPENMG_YES)
27 //---------------------------------------------------------------------------
28 
29 //---------------------------------------------------------------------------
30 #include "MediaInfo/Audio/File_OpenMG.h"
31 //---------------------------------------------------------------------------
32 
33 namespace MediaInfoLib
34 {
35 
36 //***************************************************************************
37 // Info
38 //***************************************************************************
39 
40 //---------------------------------------------------------------------------
OpenMG_CodecID_Format(int8u CodecID)41 static const char* OpenMG_CodecID_Format (int8u CodecID)
42 {
43     switch (CodecID)
44     {
45         case  0 :
46         case  1 :
47                     return "Atrac3";
48         case  3 :   return "MPEG Audio";
49         case  4 :   return "PCM";
50         case  5 :   return "WMA";
51         default :   return "";
52     }
53 }
54 
55 //---------------------------------------------------------------------------
OpenMG_CodecID_Encryption(int8u CodecID)56 static const char* OpenMG_CodecID_Encryption (int8u CodecID)
57 {
58     switch (CodecID)
59     {
60         case  1 :   return "SDMI";
61         default :   return "";
62     }
63 }
64 
65 //---------------------------------------------------------------------------
OpenMG_SamplingRate(int8u SamplingRate_Code)66 static int32u OpenMG_SamplingRate (int8u SamplingRate_Code)
67 {
68     switch (SamplingRate_Code)
69     {
70         case   0 : return 32000;
71         case   1 : return 44100;
72         case   2 : return 44800;
73         case   3 : return 88200;
74         case   4 : return 96000;
75         default  : return 0;
76     }
77 }
78 
79 //---------------------------------------------------------------------------
OpenMG_Channels(int8u Channels_Code)80 static int8u OpenMG_Channels (int8u Channels_Code)
81 {
82     if (Channels_Code<=4)
83         return Channels_Code;
84     else
85         return Channels_Code+1; //+LFE
86 }
87 
88 //---------------------------------------------------------------------------
OpenMG_ChannelPositions(int8u Channels_Code)89 static const char* OpenMG_ChannelPositions (int8u Channels_Code)
90 {
91     switch (Channels_Code)
92     {
93         case  1 :   return "Front: C";
94         case  2 :   return "Front: L R";
95         case  3 :   return "Front: L R, Side: C";
96         case  4 :   return "Front: L R, Back: L R";
97         case  5 :   return "Front: L C R, Side: L R, LFE";
98         case  6 :   return "Front: L C R, Side: L R, Back: C, LFE";
99         case  7 :   return "Front: L C R, Side: L R, Back: L R, LFE";
100         default :   return "";
101     }
102 }
103 
104 //---------------------------------------------------------------------------
OpenMG_ChannelLayout(int8u Channels_Code)105 static const char* OpenMG_ChannelLayout (int8u Channels_Code)
106 {
107     switch (Channels_Code)
108     {
109         case  1 :   return "C";
110         case  2 :   return "L R";
111         case  3 :   return "L R S";
112         case  4 :   return "L R BL BR";
113         case  5 :   return "L R C SL SR LFE";
114         case  6 :   return "L R C SL SR BC LFE";
115         case  7 :   return "L R C SL SR BL BR LFE";
116         default :   return "";
117     }
118 }
119 
120 //***************************************************************************
121 // Constructor/Destructor
122 //***************************************************************************
123 
124 //---------------------------------------------------------------------------
File_OpenMG()125 File_OpenMG::File_OpenMG()
126 {
127     //File__Tags_Helper
128     Base=this;
129 
130     //Config
131     #if MEDIAINFO_TRACE
132         Trace_Layers_Update(8); //Stream
133     #endif //MEDIAINFO_TRACE
134     StreamSource=IsStream;
135 }
136 
137 //***************************************************************************
138 // Streams management
139 //***************************************************************************
140 
141 //---------------------------------------------------------------------------
Streams_Fill()142 void File_OpenMG::Streams_Fill()
143 {
144     Fill(Stream_General, 0, General_Format, "OpenMG");
145 
146     File__Tags_Helper::Stream_Prepare(Stream_Audio);
147 
148     File__Tags_Helper::Streams_Fill();
149 }
150 
151 //***************************************************************************
152 // Buffer - File header
153 //***************************************************************************
154 
155 //---------------------------------------------------------------------------
FileHeader_Begin()156 bool File_OpenMG::FileHeader_Begin()
157 {
158     if (!File__Tags_Helper::FileHeader_Begin())
159         return false;
160 
161     //Synchro
162     if (Buffer_Offset+3>Buffer_Size)
163         return false;
164 
165     // Testing
166     if (Buffer[Buffer_Offset  ]!=0x45 // "EA3"
167      || Buffer[Buffer_Offset+1]!=0x41
168      || Buffer[Buffer_Offset+2]!=0x33)
169     {
170         File__Tags_Helper::Reject();
171         return false;
172     }
173 
174     return true;
175 }
176 
177 //---------------------------------------------------------------------------
FileHeader_Parse()178 void File_OpenMG::FileHeader_Parse()
179 {
180     //Parsing
181     int16u Size, FrameSize=0;
182     int8u  Flags, CodecID, SamplingRate_Code=0, Channels_Code=0;
183     bool  JointStereo=false;
184     Skip_C3(                                                    "Code");
185     Get_B1 (Flags,                                              "Flags");
186     Get_B2 (Size,                                               "Size");
187     Skip_XX(26,                                                 "Unknown");
188     Get_B1 (CodecID,                                            "Coded ID"); Param_Info1(OpenMG_CodecID_Format(CodecID));
189     if (CodecID<=1) //Atrac3
190     {
191         BS_Begin();
192         Skip_S1(7,                                              "Unknown");
193         Get_SB (   JointStereo,                                 "Joint Stereo");
194         Get_S1 (3, SamplingRate_Code,                           "Sampling Rate"); Param_Info2(OpenMG_SamplingRate(SamplingRate_Code), " Hz");
195         Get_S1 (3, Channels_Code,                               "Channels"); Param_Info2(OpenMG_Channels(Channels_Code), " channel(s)");
196         Get_S2 (10, FrameSize,                                  "Frame size");
197         BS_End();
198     }
199     Skip_XX(Size-Element_Offset,                                "Unknown");
200 
201     FILLING_BEGIN();
202         if (!Status[IsAccepted])
203         {
204             File__Tags_Helper::Accept();
205 
206             Fill(Stream_Audio, 0, Audio_Format, OpenMG_CodecID_Format(CodecID));
207             Fill(Stream_Audio, 0, Audio_Encryption, OpenMG_CodecID_Encryption(CodecID));
208             int64u StreamSize=(int64u)-1;
209             if (File_Size!=(int64u)-1)
210             {
211                 StreamSize=File_Size-(Buffer_Offset+Element_Size);
212                 Fill(Stream_Audio, 0, Audio_StreamSize, StreamSize);
213             }
214             if (CodecID<=1) // Atrac3
215             {
216                 Fill(Stream_Audio, 0, Audio_Channel_s_, OpenMG_Channels(Channels_Code));
217                 Fill(Stream_Audio, 0, Audio_ChannelPositions, OpenMG_ChannelPositions(Channels_Code));
218                 Fill(Stream_Audio, 0, Audio_ChannelLayout, OpenMG_ChannelLayout(Channels_Code));
219                 if (Channels_Code==1 && JointStereo)
220                     Fill(Stream_Audio, 0, Audio_Format_Settings_Mode, "Joint Stereo");
221                 Fill(Stream_Audio, 0, Audio_SamplingRate, OpenMG_SamplingRate(SamplingRate_Code));
222 
223                 if (CodecID==1) //Protected
224                     FrameSize++; //Not sure
225                 FrameSize<<=3; //8-byte  blocks
226                 int64u BitRate=OpenMG_SamplingRate(SamplingRate_Code)*FrameSize/256;
227                 Fill(Stream_Audio, 0, Audio_BitRate, BitRate);
228                 if (StreamSize!=(int64u)-1 && BitRate)
229                     Fill(Stream_Audio, 0, Audio_Duration, StreamSize*8*1000/BitRate);
230             }
231         }
232     FILLING_END();
233 }
234 
235 //***************************************************************************
236 // Buffer - Global
237 //***************************************************************************
238 
239 //---------------------------------------------------------------------------
Read_Buffer_Continue()240 void File_OpenMG::Read_Buffer_Continue()
241 {
242     //Parsing
243     Skip_XX(File_Size-Buffer_Offset,                            "Data");
244 
245     File__Analyze::Finish();
246 }
247 
248 } //NameSpace
249 
250 #endif
251