bool CAEEncoderFFmpeg::IsCompatible(const AEAudioFormat &format) { if (!m_CodecCtx) return false; bool match = ( format.m_dataFormat == m_CurrentFormat.m_dataFormat && format.m_sampleRate == m_CurrentFormat.m_sampleRate ); if (match) { CAEChannelInfo layout; BuildChannelLayout(AV_CH_LAYOUT_5POINT1_BACK, layout); /* hard coded for AC3 & DTS currently */ match = (m_CurrentFormat.m_channelLayout == layout); } return match; }
bool CAEEncoderFFmpeg::Initialize(AEAudioFormat &format, bool allow_planar_input) { Reset(); bool ac3 = CSettings::Get().GetBool("audiooutput.ac3passthrough"); AVCodec *codec = NULL; #if 0 /* the DCA encoder is currently useless for transcode, it creates a 196 kHz DTS-HD like mongrel which is useless for SPDIF */ bool dts = CSettings::Get().GetBool("audiooutput.dtspassthrough"); if (dts && (!ac3 || g_advancedSettings.m_audioTranscodeTo.Equals("dts"))) { m_CodecName = "DTS"; m_CodecID = AV_CODEC_ID_DTS; m_PackFunc = &CAEPackIEC61937::PackDTS_1024; m_BitRate = DTS_ENCODE_BITRATE; codec = avcodec_find_encoder(m_CodecID); } #endif /* fallback to ac3 if we support it, we might not have DTS support */ if (!codec && ac3) { m_CodecName = "AC3"; m_CodecID = AV_CODEC_ID_AC3; m_PackFunc = &CAEPackIEC61937::PackAC3; m_BitRate = AC3_ENCODE_BITRATE; codec = avcodec_find_encoder(m_CodecID); } /* check we got the codec */ if (!codec) return false; m_CodecCtx = avcodec_alloc_context3(codec); m_CodecCtx->bit_rate = m_BitRate; m_CodecCtx->sample_rate = format.m_sampleRate; m_CodecCtx->channel_layout = AV_CH_LAYOUT_5POINT1_BACK; /* select a suitable data format */ if (codec->sample_fmts) { bool hasFloat = false; bool hasDouble = false; bool hasS32 = false; bool hasS16 = false; bool hasU8 = false; bool hasFloatP = false; bool hasUnknownFormat = false; for(int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; ++i) { switch (codec->sample_fmts[i]) { case AV_SAMPLE_FMT_FLT: hasFloat = true; break; case AV_SAMPLE_FMT_DBL: hasDouble = true; break; case AV_SAMPLE_FMT_S32: hasS32 = true; break; case AV_SAMPLE_FMT_S16: hasS16 = true; break; case AV_SAMPLE_FMT_U8 : hasU8 = true; break; case AV_SAMPLE_FMT_FLTP: if (allow_planar_input) hasFloatP = true; else hasUnknownFormat = true; break; case AV_SAMPLE_FMT_NONE: return false; default: hasUnknownFormat = true; break; } } if (hasFloat) { m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_FLT; format.m_dataFormat = AE_FMT_FLOAT; } else if (hasFloatP) { m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP; format.m_dataFormat = AE_FMT_FLOATP; } else if (hasDouble) { m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_DBL; format.m_dataFormat = AE_FMT_DOUBLE; } else if (hasS32) { m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_S32; format.m_dataFormat = AE_FMT_S32NE; } else if (hasS16) { m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_S16; format.m_dataFormat = AE_FMT_S16NE; } else if (hasU8) { m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_U8; format.m_dataFormat = AE_FMT_U8; } else if (hasUnknownFormat) { m_CodecCtx->sample_fmt = codec->sample_fmts[0]; format.m_dataFormat = AE_FMT_FLOAT; m_NeedConversion = true; CLog::Log(LOGNOTICE, "CAEEncoderFFmpeg::Initialize - Unknown audio format, it will be resampled."); } else { CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Initialize - Unable to find a suitable data format for the codec (%s)", m_CodecName.c_str()); return false; } } m_CodecCtx->channels = BuildChannelLayout(m_CodecCtx->channel_layout, m_Layout); /* open the codec */ if (avcodec_open2(m_CodecCtx, codec, NULL)) { av_freep(&m_CodecCtx); return false; } format.m_frames = m_CodecCtx->frame_size; format.m_frameSamples = m_CodecCtx->frame_size * m_CodecCtx->channels; format.m_frameSize = m_CodecCtx->channels * (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3); format.m_channelLayout = m_Layout; m_CurrentFormat = format; m_NeededFrames = format.m_frames; m_OutputSize = m_PackFunc(NULL, 0, m_Buffer); m_OutputRatio = (double)m_NeededFrames / m_OutputSize; m_SampleRateMul = 1.0 / (double)m_CodecCtx->sample_rate; if (m_NeedConversion) { m_SwrCtx = swr_alloc_set_opts(NULL, m_CodecCtx->channel_layout, m_CodecCtx->sample_fmt, m_CodecCtx->sample_rate, m_CodecCtx->channel_layout, AV_SAMPLE_FMT_FLT, m_CodecCtx->sample_rate, 0, NULL); if (!m_SwrCtx || swr_init(m_SwrCtx) < 0) { CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Initialize - Failed to initialise resampler."); return false; } } CLog::Log(LOGNOTICE, "CAEEncoderFFmpeg::Initialize - %s encoder ready", m_CodecName.c_str()); return true; }
bool CAEEncoderFFmpeg::Initialize(AEAudioFormat &format, bool allow_planar_input) { Reset(); bool ac3 = CServiceBroker::GetSettings().GetBool(CSettings::SETTING_AUDIOOUTPUT_AC3PASSTHROUGH); AVCodec *codec = NULL; /* fallback to ac3 if we support it, we might not have DTS support */ if (!codec && ac3) { m_CodecName = "AC3"; m_CodecID = AV_CODEC_ID_AC3; m_BitRate = AC3_ENCODE_BITRATE; codec = avcodec_find_encoder(m_CodecID); } /* check we got the codec */ if (!codec) return false; m_CodecCtx = avcodec_alloc_context3(codec); if (!m_CodecCtx) return false; m_CodecCtx->bit_rate = m_BitRate; m_CodecCtx->sample_rate = format.m_sampleRate; m_CodecCtx->channel_layout = AV_CH_LAYOUT_5POINT1_BACK; /* select a suitable data format */ if (codec->sample_fmts) { bool hasFloat = false; bool hasDouble = false; bool hasS32 = false; bool hasS16 = false; bool hasU8 = false; bool hasFloatP = false; bool hasUnknownFormat = false; for(int i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; ++i) { switch (codec->sample_fmts[i]) { case AV_SAMPLE_FMT_FLT: hasFloat = true; break; case AV_SAMPLE_FMT_DBL: hasDouble = true; break; case AV_SAMPLE_FMT_S32: hasS32 = true; break; case AV_SAMPLE_FMT_S16: hasS16 = true; break; case AV_SAMPLE_FMT_U8 : hasU8 = true; break; case AV_SAMPLE_FMT_FLTP: if (allow_planar_input) hasFloatP = true; else hasUnknownFormat = true; break; case AV_SAMPLE_FMT_NONE: return false; default: hasUnknownFormat = true; break; } } if (hasFloat) { m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_FLT; format.m_dataFormat = AE_FMT_FLOAT; } else if (hasFloatP) { m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP; format.m_dataFormat = AE_FMT_FLOATP; } else if (hasDouble) { m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_DBL; format.m_dataFormat = AE_FMT_DOUBLE; } else if (hasS32) { m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_S32; format.m_dataFormat = AE_FMT_S32NE; } else if (hasS16) { m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_S16; format.m_dataFormat = AE_FMT_S16NE; } else if (hasU8) { m_CodecCtx->sample_fmt = AV_SAMPLE_FMT_U8; format.m_dataFormat = AE_FMT_U8; } else if (hasUnknownFormat) { m_CodecCtx->sample_fmt = codec->sample_fmts[0]; format.m_dataFormat = AE_FMT_FLOAT; m_NeedConversion = true; CLog::Log(LOGNOTICE, "CAEEncoderFFmpeg::Initialize - Unknown audio format, it will be resampled."); } else { CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Initialize - Unable to find a suitable data format for the codec (%s)", m_CodecName.c_str()); avcodec_free_context(&m_CodecCtx); return false; } } m_CodecCtx->channels = BuildChannelLayout(m_CodecCtx->channel_layout, m_Layout); /* open the codec */ if (avcodec_open2(m_CodecCtx, codec, NULL)) { avcodec_free_context(&m_CodecCtx); return false; } format.m_frames = m_CodecCtx->frame_size; format.m_frameSize = m_CodecCtx->channels * (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3); format.m_channelLayout = m_Layout; m_CurrentFormat = format; m_NeededFrames = format.m_frames; m_OutputRatio = (double)m_NeededFrames / m_OutputSize; m_SampleRateMul = 1.0 / (double)m_CodecCtx->sample_rate; if (m_NeedConversion) { m_SwrCtx = swr_alloc_set_opts(NULL, m_CodecCtx->channel_layout, m_CodecCtx->sample_fmt, m_CodecCtx->sample_rate, m_CodecCtx->channel_layout, AV_SAMPLE_FMT_FLT, m_CodecCtx->sample_rate, 0, NULL); if (!m_SwrCtx || swr_init(m_SwrCtx) < 0) { CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Initialize - Failed to initialise resampler."); swr_free(&m_SwrCtx); avcodec_free_context(&m_CodecCtx); return false; } } CLog::Log(LOGNOTICE, "CAEEncoderFFmpeg::Initialize - %s encoder ready", m_CodecName.c_str()); return true; }