2 * Copyright (C) 2005-2013 Team XBMC
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)
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.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "FLACcodec.h"
22 #include "utils/log.h"
23 #include "cores/AudioEngine/Utils/AEUtil.h"
24 #include "music/tags/TagLoaderTagLib.h"
26 FLACCodec::FLACCodec()
31 m_DataFormat = AE_FMT_INVALID;
44 FLACCodec::~FLACCodec()
49 bool FLACCodec::Init(const CStdString &strFile, unsigned int filecache)
54 if (!m_file.Open(strFile, READ_CACHED))
57 // Extract ReplayGain info
58 CTagLoaderTagLib tagLoaderTagLib;
59 tagLoaderTagLib.Load(strFile, m_tag, "flac");
61 m_pFlacDecoder=m_dll.FLAC__stream_decoder_new();
65 CLog::Log(LOGERROR, "FLACCodec: Error creating decoder");
69 if (m_dll.FLAC__stream_decoder_init_stream(m_pFlacDecoder, DecoderReadCallback,
72 DecoderLengthCallback,
75 DecoderMetadataCallback,
77 this) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
79 CLog::Log(LOGERROR, "FLACCodec: Error initializing decoder");
84 // Process metadata like number of channels...
85 if (!m_dll.FLAC__stream_decoder_process_until_end_of_metadata(m_pFlacDecoder))
87 CLog::Log(LOGERROR, "FLACCodec: Error while processing metadata");
92 // These are filled by the metadata callback
93 if (m_SampleRate==0 || m_Channels==0 || m_BitsPerSample==0 || m_TotalTime==0 || m_MaxFrameSize==0 || m_DataFormat == AE_FMT_INVALID)
95 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);
100 m_Bitrate = (int)(((float)m_file.GetLength() * 8) / ((float)m_TotalTime / 1000));
107 // allocate the buffer to hold the audio data,
108 // it is 5 times bigger then a single decoded frame
109 m_pBuffer=new BYTE[m_MaxFrameSize*5];
114 void FLACCodec::DeInit()
126 int64_t FLACCodec::Seek(int64_t iSeekTime)
128 // Seek to the nearest sample
129 // set the buffer size to 0 first, as this invokes a WriteCallback which
130 // may be called when the buffer is almost full (resulting in a buffer
131 // overrun unless we reset m_BufferSize first).
133 if(!m_dll.FLAC__stream_decoder_seek_absolute(m_pFlacDecoder, (int64_t)(iSeekTime*m_SampleRate)/1000))
134 CLog::Log(LOGERROR, "FLACCodec::Seek - failed to seek");
136 if(m_dll.FLAC__stream_decoder_get_state(m_pFlacDecoder)==FLAC__STREAM_DECODER_SEEK_ERROR)
138 CLog::Log(LOGINFO, "FLACCodec::Seek - must reset decoder after seek");
139 if(!m_dll.FLAC__stream_decoder_flush(m_pFlacDecoder))
140 CLog::Log(LOGERROR, "FLACCodec::Seek - flush failed");
146 int FLACCodec::ReadPCM(BYTE *pBuffer, int size, int *actualsize)
151 if (m_dll.FLAC__stream_decoder_get_state(m_pFlacDecoder)==FLAC__STREAM_DECODER_END_OF_STREAM)
156 // fill our buffer 4 decoded frame (the buffer could hold 5)
157 while(m_BufferSize < m_MaxFrameSize*4 &&
158 m_dll.FLAC__stream_decoder_get_state(m_pFlacDecoder)!=FLAC__STREAM_DECODER_END_OF_STREAM)
160 if (!m_dll.FLAC__stream_decoder_process_single(m_pFlacDecoder))
162 CLog::Log(LOGERROR, "FLACCodec: Error decoding single block");
168 if (size<m_BufferSize)
169 { // do we need less audio data then in our buffer
170 memcpy(pBuffer, m_pBuffer, size);
171 memmove(m_pBuffer, m_pBuffer+size, m_BufferSize-size);
177 memcpy(pBuffer, m_pBuffer, m_BufferSize);
178 *actualsize=m_BufferSize;
182 if (eof && m_BufferSize==0)
188 bool FLACCodec::CanInit()
190 return m_dll.CanLoad();
193 void FLACCodec::FreeDecoder()
197 m_dll.FLAC__stream_decoder_finish(m_pFlacDecoder);
198 m_dll.FLAC__stream_decoder_delete(m_pFlacDecoder);
203 FLAC__StreamDecoderReadStatus FLACCodec::DecoderReadCallback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
205 FLACCodec* pThis=(FLACCodec*)client_data;
207 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
209 *bytes=pThis->m_file.Read(buffer, *bytes);
211 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
214 FLAC__StreamDecoderSeekStatus FLACCodec::DecoderSeekCallback(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
216 FLACCodec* pThis=(FLACCodec*)client_data;
218 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
220 if (pThis->m_file.Seek(absolute_byte_offset, SEEK_SET)<0)
221 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
224 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
227 FLAC__StreamDecoderTellStatus FLACCodec::DecoderTellCallback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
229 FLACCodec* pThis=(FLACCodec*)client_data;
231 return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
233 *absolute_byte_offset=pThis->m_file.GetPosition();
235 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
238 FLAC__StreamDecoderLengthStatus FLACCodec::DecoderLengthCallback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
240 FLACCodec* pThis=(FLACCodec*)client_data;
242 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
244 *stream_length=pThis->m_file.GetLength();
246 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
249 FLAC__bool FLACCodec::DecoderEofCallback(const FLAC__StreamDecoder *decoder, void *client_data)
251 FLACCodec* pThis=(FLACCodec*)client_data;
255 return (pThis->m_file.GetLength()==pThis->m_file.GetPosition());
258 FLAC__StreamDecoderWriteStatus FLACCodec::DecoderWriteCallback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
260 FLACCodec* pThis=(FLACCodec*)client_data;
262 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
264 const int bytes_per_sample = frame->header.bits_per_sample/8;
265 BYTE* outptr = pThis->m_pBuffer+pThis->m_BufferSize;
266 FLAC__int16* outptr16 = (FLAC__int16 *) outptr;
267 FLAC__int32* outptr32 = (FLAC__int32 *) outptr;
269 unsigned int current_sample = 0;
270 for(current_sample = 0; current_sample < frame->header.blocksize; current_sample++)
272 for(unsigned int channel = 0; channel < frame->header.channels; channel++)
274 switch(bytes_per_sample)
277 outptr16[current_sample*frame->header.channels + channel] = (FLAC__int16) buffer[channel][current_sample];
280 outptr[2] = (buffer[channel][current_sample] >> 16) & 0xff;
281 outptr[1] = (buffer[channel][current_sample] >> 8 ) & 0xff;
282 outptr[0] = (buffer[channel][current_sample] >> 0 ) & 0xff;
283 outptr += bytes_per_sample;
286 outptr32[current_sample*frame->header.channels + channel] = buffer[channel][current_sample];
292 if (bytes_per_sample == 1)
294 for(unsigned int i=0;i<current_sample;i++)
296 BYTE* outptr=pThis->m_pBuffer+pThis->m_BufferSize;
301 pThis->m_BufferSize += current_sample*bytes_per_sample*frame->header.channels;
303 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
306 void FLACCodec::DecoderMetadataCallback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
308 FLACCodec* pThis=(FLACCodec*)client_data;
312 if (metadata->type==FLAC__METADATA_TYPE_STREAMINFO)
314 static enum AEChannel map[8][9] = {
315 {AE_CH_FC, AE_CH_NULL},
316 {AE_CH_FL, AE_CH_FR, AE_CH_NULL},
317 {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_NULL},
318 {AE_CH_FL, AE_CH_FR, AE_CH_BL, AE_CH_BR, AE_CH_NULL},
319 {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_BL, AE_CH_BR, AE_CH_NULL},
320 {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_LFE, AE_CH_BL, AE_CH_BR, AE_CH_NULL}, // 6 channels
321 {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_LFE, AE_CH_BC, AE_CH_BL, AE_CH_BR, AE_CH_NULL}, // 7 channels
322 {AE_CH_FL, AE_CH_FR, AE_CH_FC, AE_CH_LFE, AE_CH_BL, AE_CH_BR, AE_CH_SL, AE_CH_SR, AE_CH_NULL} // 8 channels
325 /* channel counts greater then 6 are undefined */
326 if (metadata->data.stream_info.channels > 8)
327 pThis->m_ChannelInfo = CAEUtil::GuessChLayout(metadata->data.stream_info.channels);
329 pThis->m_ChannelInfo = CAEChannelInfo(map[metadata->data.stream_info.channels - 1]);
331 pThis->m_SampleRate = metadata->data.stream_info.sample_rate;
332 pThis->m_Channels = metadata->data.stream_info.channels;
333 pThis->m_BitsPerSample = metadata->data.stream_info.bits_per_sample;
334 switch(pThis->m_BitsPerSample)
336 case 8: pThis->m_DataFormat = AE_FMT_U8; break;
337 case 16: pThis->m_DataFormat = AE_FMT_S16NE; break;
338 case 24: pThis->m_DataFormat = AE_FMT_S24NE3; break;
339 case 32: pThis->m_DataFormat = AE_FMT_FLOAT; break;
341 pThis->m_TotalTime = (int64_t)metadata->data.stream_info.total_samples * 1000 / metadata->data.stream_info.sample_rate;
342 pThis->m_MaxFrameSize = metadata->data.stream_info.max_blocksize*(pThis->m_BitsPerSample/8)*pThis->m_Channels;
346 void FLACCodec::DecoderErrorCallback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
348 CLog::Log(LOGERROR, "FLACCodec: Read error %i", status);