strip added smb:// shares of their user/pass when adding, and instead store that...
[vuplus_xbmc] / xbmc / cores / paplayer / FLACcodec.cpp
1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://www.xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include "FLACcodec.h"
23 #include "music/tags/FlacTag.h"
24 #include "utils/log.h"
25
26 using namespace MUSIC_INFO;
27
28 FLACCodec::FLACCodec()
29 {
30   m_SampleRate = 0;
31   m_Channels = 0;
32   m_BitsPerSample = 0;
33   m_DataFormat = AE_FMT_INVALID;
34   m_TotalTime=0;
35   m_Bitrate = 0;
36   m_CodecName = "FLAC";
37
38   m_pFlacDecoder=NULL;
39
40   m_pBuffer=NULL;
41   m_BufferSize=0;
42   m_MaxFrameSize=0;
43
44 }
45
46 FLACCodec::~FLACCodec()
47 {
48   DeInit();
49 }
50
51 bool FLACCodec::Init(const CStdString &strFile, unsigned int filecache)
52 {
53   if (!m_dll.Load())
54     return false;
55
56   if (!m_file.Open(strFile, READ_CACHED))
57     return false;
58
59   m_pFlacDecoder=m_dll.FLAC__stream_decoder_new();
60
61   if (!m_pFlacDecoder)
62   {
63     CLog::Log(LOGERROR, "FLACCodec: Error creating decoder");
64     return false;
65   }
66
67   if (m_dll.FLAC__stream_decoder_init_stream(m_pFlacDecoder, DecoderReadCallback,
68                                                              DecoderSeekCallback,
69                                                              DecoderTellCallback,
70                                                              DecoderLengthCallback,
71                                                              DecoderEofCallback,
72                                                              DecoderWriteCallback,
73                                                              DecoderMetadataCallback,
74                                                              DecoderErrorCallback,
75                                                              this) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
76   {
77     CLog::Log(LOGERROR, "FLACCodec: Error initializing decoder");
78     FreeDecoder();
79     return false;
80   }
81
82   //  Process metadata like number of channels...
83   if (!m_dll.FLAC__stream_decoder_process_until_end_of_metadata(m_pFlacDecoder))
84   {
85     CLog::Log(LOGERROR, "FLACCodec: Error while processing metadata");
86     FreeDecoder();
87     return false;
88   }
89
90   //  These are filled by the metadata callback
91   if (m_SampleRate==0 || m_Channels==0 || m_BitsPerSample==0 || m_TotalTime==0 || m_MaxFrameSize==0 || m_DataFormat == AE_FMT_INVALID)
92   {
93     CLog::Log(LOGERROR, "FLACCodec: Can't get stream info, SampleRate=%i, Channels=%i, BitsPerSample=%i, TotalTime=%"PRIu64", MaxFrameSize=%i", m_SampleRate, m_Channels, m_BitsPerSample, m_TotalTime, m_MaxFrameSize);
94     FreeDecoder();
95     return false;
96   }
97
98   //  Extract ReplayGain info
99   CFlacTag tag;
100   if (tag.Read(strFile))
101     m_replayGain=tag.GetReplayGain();
102
103   m_Bitrate = (int)(((float)m_file.GetLength() * 8) / ((float)m_TotalTime / 1000));
104
105   if (m_pBuffer)
106   {
107     delete[] m_pBuffer;
108     m_pBuffer=NULL;
109   }
110   //  allocate the buffer to hold the audio data,
111   //  it is 5 times bigger then a single decoded frame
112   m_pBuffer=new BYTE[m_MaxFrameSize*5];
113
114   return true;
115 }
116
117 void FLACCodec::DeInit()
118 {
119   FreeDecoder();
120   m_file.Close();
121
122   if (m_pBuffer)
123   {
124     delete[] m_pBuffer;
125     m_pBuffer=NULL;
126   }
127 }
128
129 int64_t FLACCodec::Seek(int64_t iSeekTime)
130 {
131   //  Seek to the nearest sample
132   // set the buffer size to 0 first, as this invokes a WriteCallback which
133   // may be called when the buffer is almost full (resulting in a buffer
134   // overrun unless we reset m_BufferSize first).
135   m_BufferSize=0;
136   if(!m_dll.FLAC__stream_decoder_seek_absolute(m_pFlacDecoder, (int64_t)(iSeekTime*m_SampleRate)/1000))
137     CLog::Log(LOGERROR, "FLACCodec::Seek - failed to seek");
138
139   if(m_dll.FLAC__stream_decoder_get_state(m_pFlacDecoder)==FLAC__STREAM_DECODER_SEEK_ERROR)
140   {
141     CLog::Log(LOGINFO, "FLACCodec::Seek - must reset decoder after seek");
142     if(!m_dll.FLAC__stream_decoder_flush(m_pFlacDecoder))
143       CLog::Log(LOGERROR, "FLACCodec::Seek - flush failed");
144   }
145
146   return iSeekTime;
147 }
148
149 int FLACCodec::ReadPCM(BYTE *pBuffer, int size, int *actualsize)
150 {
151   *actualsize=0;
152
153   bool eof=false;
154   if (m_dll.FLAC__stream_decoder_get_state(m_pFlacDecoder)==FLAC__STREAM_DECODER_END_OF_STREAM)
155     eof=true;
156
157   if (!eof)
158   {
159     //  fill our buffer 4 decoded frame (the buffer could hold 5)
160     while(m_BufferSize < m_MaxFrameSize*4 &&
161           m_dll.FLAC__stream_decoder_get_state(m_pFlacDecoder)!=FLAC__STREAM_DECODER_END_OF_STREAM)
162     {
163       if (!m_dll.FLAC__stream_decoder_process_single(m_pFlacDecoder))
164       {
165         CLog::Log(LOGERROR, "FLACCodec: Error decoding single block");
166         return READ_ERROR;
167       }
168     }
169   }
170
171   if (size<m_BufferSize)
172   { //  do we need less audio data then in our buffer
173     memcpy(pBuffer, m_pBuffer, size);
174     memmove(m_pBuffer, m_pBuffer+size, m_BufferSize-size);
175     m_BufferSize-=size;
176     *actualsize=size;
177   }
178   else
179   {
180     memcpy(pBuffer, m_pBuffer, m_BufferSize);
181     *actualsize=m_BufferSize;
182     m_BufferSize=0;
183   }
184
185   if (eof && m_BufferSize==0)
186     return READ_EOF;
187
188   return READ_SUCCESS;
189 }
190
191 bool FLACCodec::CanInit()
192 {
193   return m_dll.CanLoad();
194 }
195
196 void FLACCodec::FreeDecoder()
197 {
198   if (m_pFlacDecoder)
199   {
200     m_dll.FLAC__stream_decoder_finish(m_pFlacDecoder);
201     m_dll.FLAC__stream_decoder_delete(m_pFlacDecoder);
202     m_pFlacDecoder=NULL;
203   }
204 }
205
206 FLAC__StreamDecoderReadStatus FLACCodec::DecoderReadCallback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
207 {
208   FLACCodec* pThis=(FLACCodec*)client_data;
209   if (!pThis)
210     return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
211
212   *bytes=pThis->m_file.Read(buffer, *bytes);
213
214   return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
215 }
216
217 FLAC__StreamDecoderSeekStatus FLACCodec::DecoderSeekCallback(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
218 {
219   FLACCodec* pThis=(FLACCodec*)client_data;
220   if (!pThis)
221     return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
222
223   if (pThis->m_file.Seek(absolute_byte_offset, SEEK_SET)<0)
224     return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
225
226
227   return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
228 }
229
230 FLAC__StreamDecoderTellStatus FLACCodec::DecoderTellCallback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
231 {
232   FLACCodec* pThis=(FLACCodec*)client_data;
233   if (!pThis)
234     return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
235
236   *absolute_byte_offset=pThis->m_file.GetPosition();
237
238   return FLAC__STREAM_DECODER_TELL_STATUS_OK;
239 }
240
241 FLAC__StreamDecoderLengthStatus FLACCodec::DecoderLengthCallback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
242 {
243   FLACCodec* pThis=(FLACCodec*)client_data;
244   if (!pThis)
245     return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
246
247   *stream_length=pThis->m_file.GetLength();
248
249   return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
250 }
251
252 FLAC__bool FLACCodec::DecoderEofCallback(const FLAC__StreamDecoder *decoder, void *client_data)
253 {
254   FLACCodec* pThis=(FLACCodec*)client_data;
255   if (!pThis)
256     return true;
257
258   return (pThis->m_file.GetLength()==pThis->m_file.GetPosition());
259 }
260
261 FLAC__StreamDecoderWriteStatus FLACCodec::DecoderWriteCallback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
262 {
263   FLACCodec* pThis=(FLACCodec*)client_data;
264   if (!pThis)
265     return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
266
267   const int bytes_per_sample = frame->header.bits_per_sample/8;
268   BYTE* outptr = pThis->m_pBuffer+pThis->m_BufferSize;
269   FLAC__int16* outptr16 = (FLAC__int16 *) outptr;
270   FLAC__int32* outptr32 = (FLAC__int32 *) outptr;
271
272   unsigned int current_sample = 0;
273   for(current_sample = 0; current_sample < frame->header.blocksize; current_sample++)
274   {
275     for(unsigned int channel = 0; channel < frame->header.channels; channel++)
276     {
277       switch(bytes_per_sample)
278       {
279         case 2:
280           outptr16[current_sample*frame->header.channels + channel] = (FLAC__int16) buffer[channel][current_sample];
281           break;
282         case 3:
283           outptr[2] = (buffer[channel][current_sample] >> 16) & 0xff;
284           outptr[1] = (buffer[channel][current_sample] >> 8 ) & 0xff;
285           outptr[0] = (buffer[channel][current_sample] >> 0 ) & 0xff;
286           outptr += bytes_per_sample;
287           break;
288         default:
289           outptr32[current_sample*frame->header.channels + channel] = buffer[channel][current_sample];
290           break;
291       }
292     }
293   }
294
295   if (bytes_per_sample == 1)
296   {
297     for(unsigned int i=0;i<current_sample;i++)
298     {
299       BYTE* outptr=pThis->m_pBuffer+pThis->m_BufferSize;
300       outptr[i]^=0x80;
301     }
302   }
303
304   pThis->m_BufferSize += current_sample*bytes_per_sample*frame->header.channels;
305
306   return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
307 }
308
309 void FLACCodec::DecoderMetadataCallback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
310 {
311   FLACCodec* pThis=(FLACCodec*)client_data;
312   if (!pThis)
313     return;
314
315   if (metadata->type==FLAC__METADATA_TYPE_STREAMINFO)
316   {
317     static enum AEChannel map[6][7] = {
318       {AE_CH_FC, AE_CH_NULL},
319       {AE_CH_FL, AE_CH_FR, AE_CH_NULL},
320       {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_NULL},
321       {AE_CH_FL, AE_CH_FR, AE_CH_BL, AE_CH_BR, AE_CH_NULL},
322       {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_BL, AE_CH_BR, AE_CH_NULL},
323       {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_LFE, AE_CH_BL, AE_CH_BR, AE_CH_NULL}
324     };
325
326     /* channel counts greater then 6 are undefined */
327     if (metadata->data.stream_info.channels > 6)
328       pThis->m_ChannelInfo = CAEUtil::GuessChLayout(metadata->data.stream_info.channels);
329     else
330       pThis->m_ChannelInfo = CAEChannelInfo(map[metadata->data.stream_info.channels - 1]);
331
332     pThis->m_SampleRate    = metadata->data.stream_info.sample_rate;
333     pThis->m_Channels      = metadata->data.stream_info.channels;
334     pThis->m_BitsPerSample = metadata->data.stream_info.bits_per_sample;
335     switch(pThis->m_BitsPerSample)
336     {
337       case  8: pThis->m_DataFormat = AE_FMT_U8;     break;
338       case 16: pThis->m_DataFormat = AE_FMT_S16NE;  break;
339       case 24: pThis->m_DataFormat = AE_FMT_S24NE3; break;
340       case 32: pThis->m_DataFormat = AE_FMT_FLOAT;  break;
341     }
342     pThis->m_TotalTime     = (int64_t)metadata->data.stream_info.total_samples * 1000 / metadata->data.stream_info.sample_rate;
343     pThis->m_MaxFrameSize  = metadata->data.stream_info.max_blocksize*(pThis->m_BitsPerSample/8)*pThis->m_Channels;
344   }
345 }
346
347 void FLACCodec::DecoderErrorCallback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
348 {
349   CLog::Log(LOGERROR, "FLACCodec: Read error %i", status);
350 }