2 * Copyright (C) 2005-2008 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, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 #include "FLACcodec.h"
23 #include "music/tags/FlacTag.h"
24 #include "utils/log.h"
26 using namespace MUSIC_INFO;
28 FLACCodec::FLACCodec()
33 m_DataFormat = AE_FMT_INVALID;
46 FLACCodec::~FLACCodec()
51 bool FLACCodec::Init(const CStdString &strFile, unsigned int filecache)
56 if (!m_file.Open(strFile, READ_CACHED))
59 m_pFlacDecoder=m_dll.FLAC__stream_decoder_new();
63 CLog::Log(LOGERROR, "FLACCodec: Error creating decoder");
67 if (m_dll.FLAC__stream_decoder_init_stream(m_pFlacDecoder, DecoderReadCallback,
70 DecoderLengthCallback,
73 DecoderMetadataCallback,
75 this) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
77 CLog::Log(LOGERROR, "FLACCodec: Error initializing decoder");
82 // Process metadata like number of channels...
83 if (!m_dll.FLAC__stream_decoder_process_until_end_of_metadata(m_pFlacDecoder))
85 CLog::Log(LOGERROR, "FLACCodec: Error while processing metadata");
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)
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);
98 // Extract ReplayGain info
100 if (tag.Read(strFile))
101 m_replayGain=tag.GetReplayGain();
103 m_Bitrate = (int)(((float)m_file.GetLength() * 8) / ((float)m_TotalTime / 1000));
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];
117 void FLACCodec::DeInit()
129 int64_t FLACCodec::Seek(int64_t iSeekTime)
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).
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");
139 if(m_dll.FLAC__stream_decoder_get_state(m_pFlacDecoder)==FLAC__STREAM_DECODER_SEEK_ERROR)
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");
149 int FLACCodec::ReadPCM(BYTE *pBuffer, int size, int *actualsize)
154 if (m_dll.FLAC__stream_decoder_get_state(m_pFlacDecoder)==FLAC__STREAM_DECODER_END_OF_STREAM)
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)
163 if (!m_dll.FLAC__stream_decoder_process_single(m_pFlacDecoder))
165 CLog::Log(LOGERROR, "FLACCodec: Error decoding single block");
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);
180 memcpy(pBuffer, m_pBuffer, m_BufferSize);
181 *actualsize=m_BufferSize;
185 if (eof && m_BufferSize==0)
191 bool FLACCodec::CanInit()
193 return m_dll.CanLoad();
196 void FLACCodec::FreeDecoder()
200 m_dll.FLAC__stream_decoder_finish(m_pFlacDecoder);
201 m_dll.FLAC__stream_decoder_delete(m_pFlacDecoder);
206 FLAC__StreamDecoderReadStatus FLACCodec::DecoderReadCallback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
208 FLACCodec* pThis=(FLACCodec*)client_data;
210 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
212 *bytes=pThis->m_file.Read(buffer, *bytes);
214 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
217 FLAC__StreamDecoderSeekStatus FLACCodec::DecoderSeekCallback(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
219 FLACCodec* pThis=(FLACCodec*)client_data;
221 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
223 if (pThis->m_file.Seek(absolute_byte_offset, SEEK_SET)<0)
224 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
227 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
230 FLAC__StreamDecoderTellStatus FLACCodec::DecoderTellCallback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
232 FLACCodec* pThis=(FLACCodec*)client_data;
234 return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
236 *absolute_byte_offset=pThis->m_file.GetPosition();
238 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
241 FLAC__StreamDecoderLengthStatus FLACCodec::DecoderLengthCallback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
243 FLACCodec* pThis=(FLACCodec*)client_data;
245 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
247 *stream_length=pThis->m_file.GetLength();
249 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
252 FLAC__bool FLACCodec::DecoderEofCallback(const FLAC__StreamDecoder *decoder, void *client_data)
254 FLACCodec* pThis=(FLACCodec*)client_data;
258 return (pThis->m_file.GetLength()==pThis->m_file.GetPosition());
261 FLAC__StreamDecoderWriteStatus FLACCodec::DecoderWriteCallback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
263 FLACCodec* pThis=(FLACCodec*)client_data;
265 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
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;
272 unsigned int current_sample = 0;
273 for(current_sample = 0; current_sample < frame->header.blocksize; current_sample++)
275 for(unsigned int channel = 0; channel < frame->header.channels; channel++)
277 switch(bytes_per_sample)
280 outptr16[current_sample*frame->header.channels + channel] = (FLAC__int16) buffer[channel][current_sample];
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;
289 outptr32[current_sample*frame->header.channels + channel] = buffer[channel][current_sample];
295 if (bytes_per_sample == 1)
297 for(unsigned int i=0;i<current_sample;i++)
299 BYTE* outptr=pThis->m_pBuffer+pThis->m_BufferSize;
304 pThis->m_BufferSize += current_sample*bytes_per_sample*frame->header.channels;
306 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
309 void FLACCodec::DecoderMetadataCallback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
311 FLACCodec* pThis=(FLACCodec*)client_data;
315 if (metadata->type==FLAC__METADATA_TYPE_STREAMINFO)
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}
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);
330 pThis->m_ChannelInfo = CAEChannelInfo(map[metadata->data.stream_info.channels - 1]);
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)
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;
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;
347 void FLACCodec::DecoderErrorCallback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
349 CLog::Log(LOGERROR, "FLACCodec: Read error %i", status);