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 "DVDAudioCodecFFmpeg.h"
23 #include "XMemUtils.h"
25 #include "../../DVDStreamInfo.h"
26 #include "utils/log.h"
28 #if defined(TARGET_DARWIN)
29 #include "settings/Settings.h"
30 #include "cores/AudioEngine/Utils/AEUtil.h"
33 CDVDAudioCodecFFmpeg::CDVDAudioCodecFFmpeg() : CDVDAudioCodec()
37 m_iBufferTotalSize2 = 0;
41 m_pCodecContext = NULL;
43 m_bOpenedCodec = false;
49 m_iSampleFormat = AV_SAMPLE_FMT_NONE;
52 CDVDAudioCodecFFmpeg::~CDVDAudioCodecFFmpeg()
57 bool CDVDAudioCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
60 m_bOpenedCodec = false;
62 if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllSwResample.Load())
65 m_dllAvCodec.avcodec_register_all();
67 pCodec = m_dllAvCodec.avcodec_find_decoder(hints.codec);
70 CLog::Log(LOGDEBUG,"CDVDAudioCodecFFmpeg::Open() Unable to find codec %d", hints.codec);
74 m_pCodecContext = m_dllAvCodec.avcodec_alloc_context3(pCodec);
75 m_pCodecContext->debug_mv = 0;
76 m_pCodecContext->debug = 0;
77 m_pCodecContext->workaround_bugs = 1;
79 if (pCodec->capabilities & CODEC_CAP_TRUNCATED)
80 m_pCodecContext->flags |= CODEC_FLAG_TRUNCATED;
83 m_pCodecContext->channels = hints.channels;
84 m_pCodecContext->sample_rate = hints.samplerate;
85 m_pCodecContext->block_align = hints.blockalign;
86 m_pCodecContext->bit_rate = hints.bitrate;
87 m_pCodecContext->bits_per_coded_sample = hints.bitspersample;
89 if(m_pCodecContext->bits_per_coded_sample == 0)
90 m_pCodecContext->bits_per_coded_sample = 16;
92 if( hints.extradata && hints.extrasize > 0 )
94 m_pCodecContext->extradata = (uint8_t*)m_dllAvUtil.av_mallocz(hints.extrasize + FF_INPUT_BUFFER_PADDING_SIZE);
95 if(m_pCodecContext->extradata)
97 m_pCodecContext->extradata_size = hints.extrasize;
98 memcpy(m_pCodecContext->extradata, hints.extradata, hints.extrasize);
102 if (m_dllAvCodec.avcodec_open2(m_pCodecContext, pCodec, NULL) < 0)
104 CLog::Log(LOGDEBUG,"CDVDAudioCodecFFmpeg::Open() Unable to open codec");
109 m_pFrame1 = m_dllAvCodec.avcodec_alloc_frame();
110 m_bOpenedCodec = true;
111 m_iSampleFormat = AV_SAMPLE_FMT_NONE;
116 void CDVDAudioCodecFFmpeg::Dispose()
118 if (m_pFrame1) m_dllAvUtil.av_free(m_pFrame1);
122 m_dllSwResample.swr_free(&m_pConvert);
125 m_dllAvUtil.av_freep(&m_pBuffer2);
129 if (m_bOpenedCodec) m_dllAvCodec.avcodec_close(m_pCodecContext);
130 m_bOpenedCodec = false;
131 m_dllAvUtil.av_free(m_pCodecContext);
132 m_pCodecContext = NULL;
135 m_dllAvCodec.Unload();
136 m_dllAvUtil.Unload();
137 m_dllSwResample.Unload();
141 m_iBufferTotalSize2 = 0;
145 int CDVDAudioCodecFFmpeg::Decode(uint8_t* pData, int iSize)
147 int iBytesUsed, got_frame;
148 if (!m_pCodecContext) return -1;
153 m_dllAvCodec.av_init_packet(&avpkt);
156 iBytesUsed = m_dllAvCodec.avcodec_decode_audio4( m_pCodecContext
160 if (iBytesUsed < 0 || !got_frame)
165 m_iBufferSize1 = m_pFrame1->nb_samples * m_pCodecContext->channels * m_dllAvUtil.av_get_bytes_per_sample(m_pCodecContext->sample_fmt);
167 /* some codecs will attempt to consume more data than what we gave */
168 if (iBytesUsed > iSize)
170 CLog::Log(LOGWARNING, "CDVDAudioCodecFFmpeg::Decode - decoder attempted to consume more data than given");
174 if(m_iBufferSize1 == 0 && iBytesUsed >= 0)
175 m_iBuffered += iBytesUsed;
179 bool convert = false;
180 switch(m_pCodecContext->sample_fmt)
182 case AV_SAMPLE_FMT_U8:
183 case AV_SAMPLE_FMT_S16:
184 case AV_SAMPLE_FMT_S32:
185 case AV_SAMPLE_FMT_FLT:
186 case AV_SAMPLE_FMT_DBL:
188 case AV_SAMPLE_FMT_NONE:
189 CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Decode - invalid data format");
200 void CDVDAudioCodecFFmpeg::ConvertToFloat()
202 if(m_pCodecContext->sample_fmt != AV_SAMPLE_FMT_FLT && m_iBufferSize1 > 0)
204 if(m_pConvert && (m_pCodecContext->sample_fmt != m_iSampleFormat || m_channels != m_pCodecContext->channels))
205 m_dllSwResample.swr_free(&m_pConvert);
209 m_iSampleFormat = m_pCodecContext->sample_fmt;
210 m_pConvert = m_dllSwResample.swr_alloc_set_opts(NULL,
211 m_dllAvUtil.av_get_default_channel_layout(m_pCodecContext->channels), AV_SAMPLE_FMT_FLT, m_pCodecContext->sample_rate,
212 m_dllAvUtil.av_get_default_channel_layout(m_pCodecContext->channels), m_pCodecContext->sample_fmt, m_pCodecContext->sample_rate,
215 if(!m_pConvert || m_dllSwResample.swr_init(m_pConvert) < 0)
217 CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Decode - Unable to convert %d to AV_SAMPLE_FMT_FLT", m_pCodecContext->sample_fmt);
224 int needed_buf_size = m_dllAvUtil.av_samples_get_buffer_size(NULL, m_pCodecContext->channels, m_pFrame1->nb_samples, AV_SAMPLE_FMT_FLT, 0);
225 if(m_iBufferTotalSize2 < needed_buf_size)
227 m_pBuffer2 = (uint8_t*)m_dllAvUtil.av_realloc(m_pBuffer2, needed_buf_size);
230 CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Decode - Unable to allocate a %i bytes buffer for resampling", needed_buf_size);
233 m_iBufferTotalSize2 = 0;
236 m_iBufferTotalSize2 = needed_buf_size;
240 outsamples = m_dllSwResample.swr_convert(m_pConvert, &m_pBuffer2, m_iBufferTotalSize2, (const uint8_t**)m_pFrame1->extended_data, m_pFrame1->nb_samples);
244 CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Decode - Unable to convert %d to AV_SAMPLE_FMT_FLT", (int)m_pCodecContext->sample_fmt);
250 if(outsamples < m_pFrame1->nb_samples)
252 CLog::Log(LOGWARNING, "CDVDAudioCodecFFmpeg::Decode - Resampler produced less samples than what it was given");
256 m_iBufferSize2 = m_pFrame1->nb_samples * m_pCodecContext->channels * m_dllAvUtil.av_get_bytes_per_sample(AV_SAMPLE_FMT_FLT);
260 int CDVDAudioCodecFFmpeg::GetData(uint8_t** dst)
264 *dst = m_pFrame1->data[0];
265 return m_iBufferSize1;
271 return m_iBufferSize2;
277 void CDVDAudioCodecFFmpeg::Reset()
279 if (m_pCodecContext) m_dllAvCodec.avcodec_flush_buffers(m_pCodecContext);
285 int CDVDAudioCodecFFmpeg::GetChannels()
287 return m_pCodecContext->channels;
290 int CDVDAudioCodecFFmpeg::GetSampleRate()
293 return m_pCodecContext->sample_rate;
297 int CDVDAudioCodecFFmpeg::GetEncodedSampleRate()
300 return m_pCodecContext->sample_rate;
304 enum AEDataFormat CDVDAudioCodecFFmpeg::GetDataFormat()
306 switch(m_pCodecContext->sample_fmt)
308 case AV_SAMPLE_FMT_U8 : return AE_FMT_U8;
309 case AV_SAMPLE_FMT_S16: return AE_FMT_S16NE;
310 case AV_SAMPLE_FMT_S32: return AE_FMT_S32NE;
311 case AV_SAMPLE_FMT_FLT: return AE_FMT_FLOAT;
312 case AV_SAMPLE_FMT_DBL: return AE_FMT_DOUBLE;
313 case AV_SAMPLE_FMT_NONE:
314 CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::GetDataFormat - invalid data format");
315 return AE_FMT_INVALID;
321 int CDVDAudioCodecFFmpeg::GetBitRate()
323 if (m_pCodecContext) return m_pCodecContext->bit_rate;
327 static unsigned count_bits(int64_t value)
335 void CDVDAudioCodecFFmpeg::BuildChannelMap()
337 if (m_channels == m_pCodecContext->channels && m_layout == m_pCodecContext->channel_layout)
338 return; //nothing to do here
340 m_channels = m_pCodecContext->channels;
341 m_layout = m_pCodecContext->channel_layout;
345 int bits = count_bits(m_pCodecContext->channel_layout);
346 if (bits == m_pCodecContext->channels)
347 layout = m_pCodecContext->channel_layout;
350 CLog::Log(LOGINFO, "CDVDAudioCodecFFmpeg::GetChannelMap - FFmpeg reported %d channels, but the layout contains %d ignoring", m_pCodecContext->channels, bits);
351 layout = m_dllAvUtil.av_get_default_channel_layout(m_pCodecContext->channels);
354 m_channelLayout.Reset();
356 if (layout & AV_CH_FRONT_LEFT ) m_channelLayout += AE_CH_FL ;
357 if (layout & AV_CH_FRONT_RIGHT ) m_channelLayout += AE_CH_FR ;
358 if (layout & AV_CH_FRONT_CENTER ) m_channelLayout += AE_CH_FC ;
359 if (layout & AV_CH_LOW_FREQUENCY ) m_channelLayout += AE_CH_LFE ;
360 if (layout & AV_CH_BACK_LEFT ) m_channelLayout += AE_CH_BL ;
361 if (layout & AV_CH_BACK_RIGHT ) m_channelLayout += AE_CH_BR ;
362 if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) m_channelLayout += AE_CH_FLOC;
363 if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) m_channelLayout += AE_CH_FROC;
364 if (layout & AV_CH_BACK_CENTER ) m_channelLayout += AE_CH_BC ;
365 if (layout & AV_CH_SIDE_LEFT ) m_channelLayout += AE_CH_SL ;
366 if (layout & AV_CH_SIDE_RIGHT ) m_channelLayout += AE_CH_SR ;
367 if (layout & AV_CH_TOP_CENTER ) m_channelLayout += AE_CH_TC ;
368 if (layout & AV_CH_TOP_FRONT_LEFT ) m_channelLayout += AE_CH_TFL ;
369 if (layout & AV_CH_TOP_FRONT_CENTER ) m_channelLayout += AE_CH_TFC ;
370 if (layout & AV_CH_TOP_FRONT_RIGHT ) m_channelLayout += AE_CH_TFR ;
371 if (layout & AV_CH_TOP_BACK_LEFT ) m_channelLayout += AE_CH_BL ;
372 if (layout & AV_CH_TOP_BACK_CENTER ) m_channelLayout += AE_CH_BC ;
373 if (layout & AV_CH_TOP_BACK_RIGHT ) m_channelLayout += AE_CH_BR ;
375 m_channels = m_pCodecContext->channels;
378 CAEChannelInfo CDVDAudioCodecFFmpeg::GetChannelMap()
381 return m_channelLayout;