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_FLAC_YES)
21 //---------------------------------------------------------------------------
22
23 //---------------------------------------------------------------------------
24 #include "MediaInfo/Audio/File_Flac.h"
25 #include "MediaInfo/Tag/File_VorbisCom.h"
26 #include "ThirdParty/base64/base64.h"
27 //---------------------------------------------------------------------------
28
29 namespace MediaInfoLib
30 {
31
32 //***************************************************************************
33 // Infos
34 //***************************************************************************
35
36 //---------------------------------------------------------------------------
37 extern const char* Id3v2_PictureType(int8u Type); //In Tag/File_Id3v2.cpp
38 extern std::string ExtensibleWave_ChannelMask (int32u ChannelMask); //In Multiple/File_Riff_Elements.cpp
39 extern std::string ExtensibleWave_ChannelMask2 (int32u ChannelMask); //In Multiple/File_Riff_Elements.cpp
40 extern std::string ExtensibleWave_ChannelMask_ChannelLayout(int32u ChannelMask); //In Multiple/File_Riff_Elements.cpp
41
42 //***************************************************************************
43 // Constructor/Destructor
44 //***************************************************************************
45
46 //---------------------------------------------------------------------------
File_Flac()47 File_Flac::File_Flac()
48 :File__Analyze(), File__Tags_Helper()
49 {
50 //File__Tags_Helper
51 Base=this;
52
53 //In
54 VorbisHeader=false;
55
56 //Temp
57 Last_metadata_block=false;
58 }
59
60 //***************************************************************************
61 // Buffer - File header
62 //***************************************************************************
63
64 //---------------------------------------------------------------------------
FileHeader_Begin()65 bool File_Flac::FileHeader_Begin()
66 {
67 if (!File__Tags_Helper::FileHeader_Begin())
68 return false;
69
70 //Element_Size
71 if (Buffer_Size<Buffer_Offset+4+(VorbisHeader?9:0))
72 return false; //Must wait for more data
73
74 if (CC4(Buffer+Buffer_Offset+(VorbisHeader?9:0))!=0x664C6143) //"fLaC"
75 {
76 File__Tags_Helper::Finish("Flac");
77 return false;
78 }
79
80 //All should be OK...
81 return true;
82 }
83
84 //---------------------------------------------------------------------------
FileHeader_Parse()85 void File_Flac::FileHeader_Parse()
86 {
87 //Parsing
88 if (VorbisHeader)
89 {
90 Skip_B1( "Signature");
91 Skip_Local(4, "Signature");
92 Skip_B1( "Major version");
93 Skip_B1( "Minor version");
94 Skip_B2( "Number of header");
95 }
96 Skip_C4( "Signature");
97 }
98
99 //***************************************************************************
100 // Buffer - Per element
101 //***************************************************************************
102
103 //---------------------------------------------------------------------------
Header_Parse()104 void File_Flac::Header_Parse()
105 {
106 //Parsing
107 int32u Length;
108 int8u BLOCK_TYPE;
109 BS_Begin();
110 Get_SB ( Last_metadata_block, "Last-metadata-block");
111 Get_S1 (7, BLOCK_TYPE, "BLOCK_TYPE");
112 BS_End();
113 Get_B3 (Length, "Length");
114
115 //Filling
116 Header_Fill_Code(BLOCK_TYPE, Ztring().From_CC1(BLOCK_TYPE));
117 Header_Fill_Size(Element_Offset+Length);
118 }
119
120 //---------------------------------------------------------------------------
Data_Parse()121 void File_Flac::Data_Parse()
122 {
123 #define CASE_INFO(_NAME) \
124 case Flac::_NAME : Element_Info1(#_NAME); _NAME(); break;
125
126 //Parsing
127 switch ((int16u)Element_Code)
128 {
129 CASE_INFO(STREAMINFO);
130 CASE_INFO(PADDING);
131 CASE_INFO(APPLICATION);
132 CASE_INFO(SEEKTABLE);
133 CASE_INFO(VORBIS_COMMENT);
134 CASE_INFO(CUESHEET);
135 CASE_INFO(PICTURE);
136 default : Skip_XX(Element_Size, "Data");
137 }
138
139 if (Last_metadata_block)
140 {
141 if (!IsSub)
142 Fill(Stream_Audio, 0, Audio_StreamSize, File_Size-(File_Offset+Buffer_Offset+Element_Size));
143
144 if (Retrieve(Stream_Audio, 0, Audio_ChannelPositions).empty() && Retrieve(Stream_Audio, 0, Audio_ChannelPositions_String2).empty())
145 {
146 int32u t = 0;
147 int32s c = Retrieve(Stream_Audio, 0, Audio_Channel_s_).To_int32s();
148 if (c==1) t=4;
149 else if (c==2) t=3;
150 else if (c==3) t=7;
151 else if (c==4) t=1539;
152 else if (c==5) t=1543;
153 else if (c==6) t=1551;
154 else if (c==7) t=1807;
155 else if (c==8) t=1599;
156 if (t) {
157 Fill(Stream_Audio, 0, Audio_ChannelPositions, ExtensibleWave_ChannelMask(t));
158 Fill(Stream_Audio, 0, Audio_ChannelPositions_String2, ExtensibleWave_ChannelMask2(t));
159 Fill(Stream_Audio, 0, Audio_ChannelLayout, ExtensibleWave_ChannelMask_ChannelLayout(t));
160 }
161 }
162
163 //No more need data
164 File__Tags_Helper::Finish("Flac");
165 }
166 }
167
168 //***************************************************************************
169 // Elements
170 //***************************************************************************
171
172 //---------------------------------------------------------------------------
STREAMINFO()173 void File_Flac::STREAMINFO()
174 {
175 //Parsing
176 int64u Samples;
177 int32u FrameSize_Min, FrameSize_Max, SampleRate;
178 int8u Channels, BitPerSample;
179 Skip_B2( "BlockSize_Min"); //The minimum block size (in samples) used in the stream.
180 Skip_B2( "BlockSize_Max"); //The maximum block size (in samples) used in the stream. (Minimum blocksize == maximum blocksize) implies a fixed-blocksize stream.
181 Get_B3 ( FrameSize_Min, "FrameSize_Min"); //The minimum frame size (in bytes) used in the stream. May be 0 to imply the value is not known.
182 Get_B3 ( FrameSize_Max, "FrameSize_Max"); //The maximum frame size (in bytes) used in the stream. May be 0 to imply the value is not known.
183 BS_Begin();
184 Get_S3 (20, SampleRate, "SampleRate"); //Sample rate in Hz. Though 20 bits are available, the maximum sample rate is limited by the structure of frame headers to 1048570Hz. Also, a value of 0 is invalid.
185 Get_S1 ( 3, Channels, "Channels"); Param_Info2(Channels+1, " channels"); //(number of channels)-1. FLAC supports from 1 to 8 channels
186 Get_S1 ( 5, BitPerSample, "BitPerSample"); Param_Info2(BitPerSample+1, " bits"); //(bits per sample)-1. FLAC supports from 4 to 32 bits per sample. Currently the reference encoder and decoders only support up to 24 bits per sample.
187 Get_S5 (36, Samples, "Samples");
188 BS_End();
189 Skip_B16( "MD5 signature of the unencoded audio data");
190
191 FILLING_BEGIN();
192 if (SampleRate==0)
193 return;
194 File__Tags_Helper::Accept("FLAC");
195
196 File__Tags_Helper::Streams_Fill();
197
198 File__Tags_Helper::Stream_Prepare(Stream_Audio);
199 Fill(Stream_Audio, 0, Audio_Format, "FLAC");
200 Fill(Stream_Audio, 0, Audio_Codec, "FLAC");
201 if (FrameSize_Min==FrameSize_Max && FrameSize_Min!=0 ) // 0 means it is unknown
202 Fill(Stream_Audio, 0, Audio_BitRate_Mode, "CBR");
203 else
204 Fill(Stream_Audio, 0, Audio_BitRate_Mode, "VBR");
205 Fill(Stream_Audio, 0, Audio_SamplingRate, SampleRate);
206 Fill(Stream_Audio, 0, Audio_Channel_s_, Channels+1);
207 Fill(Stream_Audio, 0, Audio_BitDepth, BitPerSample+1);
208 if (!IsSub)
209 Fill(Stream_Audio, 0, Audio_Duration, Samples*1000/SampleRate);
210 FILLING_END();
211 }
212
213 //---------------------------------------------------------------------------
APPLICATION()214 void File_Flac::APPLICATION()
215 {
216 //Parsing
217 Skip_C4( "Application");
218 if (Element_Size>4)
219 Skip_XX(Element_Size-4, "(Application specific)");
220 }
221
222 //---------------------------------------------------------------------------
VORBIS_COMMENT()223 void File_Flac::VORBIS_COMMENT()
224 {
225 //Parsing
226 #if defined(MEDIAINFO_VORBISCOM_YES)
227 File_VorbisCom VorbisCom;
228 VorbisCom.StreamKind_Specific=Stream_Audio;
229 Open_Buffer_Init(&VorbisCom);
230 Open_Buffer_Continue(&VorbisCom);
231 File__Analyze::Finish(&VorbisCom);
232
233 //Specific case: bit depth
234 if (!VorbisCom.Retrieve(Stream_Audio, 0, Audio_BitDepth).empty() && VorbisCom.Retrieve(Stream_Audio, 0, Audio_BitDepth).To_int64u()<Retrieve(Stream_Audio, 0, Audio_BitDepth).To_int64u())
235 {
236 //Bit depth information from tags is the real value, the one from Flac is the count of bits stored
237 Fill(Stream_Audio, 0, Audio_BitDepth_Stored, Retrieve(Stream_Audio, 0, Audio_BitDepth));
238 Fill(Stream_Audio, 0, Audio_BitDepth, VorbisCom.Retrieve(Stream_Audio, 0, Audio_BitDepth), true);
239 VorbisCom.Clear(Stream_Audio, 0, Audio_BitDepth);
240 }
241
242 Merge(VorbisCom, Stream_General, 0, 0);
243 Merge(VorbisCom, Stream_Audio, 0, 0);
244 Merge(VorbisCom, Stream_Menu, 0, 0);
245 #else
246 Skip_XX(Element_Offset, "Data");
247 #endif
248 }
249
250 //---------------------------------------------------------------------------
PICTURE()251 void File_Flac::PICTURE()
252 {
253 //Parsing
254 int32u PictureType, MimeType_Size, Description_Size, Data_Size;
255 Ztring MimeType, Description;
256 Get_B4 (PictureType, "Picture type"); Element_Info1(Id3v2_PictureType((int8u)PictureType));
257 Get_B4 (MimeType_Size, "MIME type size");
258 Get_UTF8(MimeType_Size, MimeType, "MIME type");
259 Get_B4 (Description_Size, "Description size");
260 Get_UTF8(Description_Size, Description, "Description");
261 Skip_B4( "Width");
262 Skip_B4( "Height");
263 Skip_B4( "Color depth");
264 Skip_B4( "Number of colors used");
265 Get_B4 (Data_Size, "Data size");
266 if (Element_Offset+Data_Size>Element_Size)
267 return; //There is a problem
268
269 //Filling
270 Fill(Stream_General, 0, General_Cover, "Yes");
271 Fill(Stream_General, 0, General_Cover_Description, Description);
272 Fill(Stream_General, 0, General_Cover_Type, Id3v2_PictureType((int8u)PictureType));
273 Fill(Stream_General, 0, General_Cover_Mime, MimeType);
274 #if MEDIAINFO_ADVANCED
275 if (MediaInfoLib::Config.Flags1_Get(Flags_Cover_Data_base64))
276 {
277 std::string Data_Raw((const char*)(Buffer+(size_t)(Buffer_Offset+Element_Offset)), Data_Size);
278 std::string Data_Base64(Base64::encode(Data_Raw));
279 Fill(Stream_General, 0, General_Cover_Data, Data_Base64);
280 }
281 #endif //MEDIAINFO_ADVANCED
282
283 Skip_XX(Data_Size, "Data");
284 if (Element_Offset<Element_Size)
285 Skip_XX(Element_Size-Element_Offset, "?");
286 }
287
288 } //NameSpace
289
290 #endif //MEDIAINFO_FLAC_YES
291
292
293