HRESULT CLAVAudio::InitDTSDecoder() { if (!m_hDllExtraDecoder) { // Add path of LAVAudio.ax into the Dll search path WCHAR wModuleFile[1024]; GetModuleFileName(g_hInst, wModuleFile, 1024); PathRemoveFileSpecW(wModuleFile); wcscat_s(wModuleFile, TEXT("\\dtsdecoderdll.dll")); // Try loading from the filters directory HMODULE hDll = LoadLibraryEx(wModuleFile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); // And try from any global directories if this failed if (hDll == NULL) { hDll = LoadLibrary(TEXT("dtsdecoderdll.dll")); } CheckPointer(hDll, E_FAIL); m_hDllExtraDecoder = hDll; } DTSDecoder *context = new DTSDecoder(); context->pDtsOpen = (DtsOpen)GetProcAddress(m_hDllExtraDecoder, "DtsApiDecOpen"); if(!context->pDtsOpen) goto fail; context->pDtsClose = (DtsClose)GetProcAddress(m_hDllExtraDecoder, "DtsApiDecClose"); if(!context->pDtsClose) goto fail; context->pDtsReset = (DtsReset)GetProcAddress(m_hDllExtraDecoder, "DtsApiDecReset"); if(!context->pDtsReset) goto fail; context->pDtsSetParam = (DtsSetParam)GetProcAddress(m_hDllExtraDecoder, "DtsApiDecSetParam"); if(!context->pDtsSetParam) goto fail; context->pDtsDecode = (DtsDecode)GetProcAddress(m_hDllExtraDecoder, "DtsApiDecodeData"); if(!context->pDtsDecode) goto fail; context->dtsContext = context->pDtsOpen(); if(!context->dtsContext) goto fail; context->dtsPCMBuffer = (BYTE *)av_mallocz(LAV_AUDIO_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); m_DTSBitDepth = 24; m_DTSDecodeChannels = 8; m_pDTSDecoderContext = context; FlushDTSDecoder(); return S_OK; fail: SAFE_DELETE(context); FreeLibrary(m_hDllExtraDecoder); m_hDllExtraDecoder = NULL; return E_FAIL; }
HRESULT CLAVAudio::InitDTSDecoder() { if (!m_hDllExtraDecoder) { // Add path of LAVAudio.ax into the Dll search path WCHAR wModuleFile[1024]; GetModuleFileName(g_hInst, wModuleFile, 1024); PathRemoveFileSpecW(wModuleFile); wcscat_s(wModuleFile, TEXT("\\dtsdecoderdll.dll")); // Try loading from the filters directory HMODULE hDll = LoadLibraryEx(wModuleFile, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH); // And try from any global directories if this failed if (hDll == nullptr) { hDll = LoadLibrary(TEXT("dtsdecoderdll.dll")); } CheckPointer(hDll, E_FAIL); BOOL bIncompatibleDecoder = FALSE; if (GetModuleFileName(hDll, wModuleFile, 1024) > 0) { DWORD dwVersionSize = GetFileVersionInfoSize(wModuleFile, nullptr); if (dwVersionSize > 0) { void *versionInfo = CoTaskMemAlloc(dwVersionSize); BOOL bVersionInfoPresent = GetFileVersionInfo(wModuleFile, 0, dwVersionSize, versionInfo); if (bVersionInfoPresent) { VS_FIXEDFILEINFO *info; unsigned cbInfo; BOOL bInfoPresent = VerQueryValue(versionInfo, TEXT("\\"), (LPVOID*)&info, &cbInfo); if (bInfoPresent) { bInfoPresent = bInfoPresent; uint64_t version = info->dwFileVersionMS; version <<= 32; version += info->dwFileVersionLS; if (version && version < 0x0001000100000000i64) bIncompatibleDecoder = TRUE; } } CoTaskMemFree(versionInfo); } } if (bIncompatibleDecoder) { FreeLibrary(hDll); hDll = nullptr; return E_FAIL; } m_hDllExtraDecoder = hDll; } DTSDecoder *context = new DTSDecoder(); context->pDtsOpen = (DtsOpen)GetProcAddress(m_hDllExtraDecoder, "DtsApiDecOpen"); if(!context->pDtsOpen) goto fail; context->pDtsClose = (DtsClose)GetProcAddress(m_hDllExtraDecoder, "DtsApiDecClose"); if(!context->pDtsClose) goto fail; context->pDtsReset = (DtsReset)GetProcAddress(m_hDllExtraDecoder, "DtsApiDecReset"); if(!context->pDtsReset) goto fail; context->pDtsSetParam = (DtsSetParam)GetProcAddress(m_hDllExtraDecoder, "DtsApiDecSetParam"); if(!context->pDtsSetParam) goto fail; context->pDtsDecode = (DtsDecode)GetProcAddress(m_hDllExtraDecoder, "DtsApiDecodeData"); if(!context->pDtsDecode) goto fail; context->dtsContext = context->pDtsOpen(); if(!context->dtsContext) goto fail; context->dtsPCMBuffer = (BYTE *)av_mallocz(LAV_AUDIO_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); m_DTSBitDepth = 24; m_DTSDecodeChannels = 8; m_pDTSDecoderContext = context; FlushDTSDecoder(); return S_OK; fail: SAFE_DELETE(context); FreeLibrary(m_hDllExtraDecoder); m_hDllExtraDecoder = nullptr; return E_FAIL; }
HRESULT CLAVAudio::DecodeDTS(const BYTE * pDataBuffer, int buffsize, int &consumed, HRESULT *hrDeliver) { HRESULT hr = S_FALSE; int nPCMLength = 0; BOOL bFlush = (pDataBuffer == nullptr); BufferDetails out; consumed = 0; while (buffsize > 0) { nPCMLength = 0; if (bFlush) buffsize = 0; ASSERT(m_pParser); BYTE *pOut = nullptr; int pOut_size = 0; int used_bytes = av_parser_parse2(m_pParser, m_pAVCtx, &pOut, &pOut_size, pDataBuffer, buffsize, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); if (used_bytes < 0) { return E_FAIL; } else if(used_bytes == 0 && pOut_size == 0) { DbgLog((LOG_TRACE, 50, L"::Decode() - could not process buffer, starving?")); break; } // Timestamp cache to compensate for one frame delay the parser might introduce, in case the frames were already perfectly sliced apart // If we used more (or equal) bytes then was output again, we encountered a new frame, update timestamps if (used_bytes >= pOut_size && m_bUpdateTimeCache) { m_rtStartInputCache = m_rtStartInput; m_rtStopInputCache = m_rtStopInput; m_rtStartInput = m_rtStopInput = AV_NOPTS_VALUE; m_bUpdateTimeCache = FALSE; } if (!bFlush && used_bytes > 0) { buffsize -= used_bytes; pDataBuffer += used_bytes; consumed += used_bytes; } if (pOut && pOut_size > 0) { // Parse DTS headers m_bsParser.Parse(AV_CODEC_ID_DTS, pOut, pOut_size, nullptr); unsigned decode_channels = dts_determine_decode_channels(m_bsParser.m_DTSHeader); // Init Decoder with new Parameters, if required if (m_DTSDecodeChannels != decode_channels) { DbgLog((LOG_TRACE, 20, L"::Decode(): Switching to %d channel decoding", decode_channels)); m_DTSDecodeChannels = decode_channels; FlushDTSDecoder(); } int bitdepth = 0, channels = 0, CoreSampleRate = 0, HDSampleRate = 0, profile = 0; int unk4 = 0, unk5 = 0; nPCMLength = SafeDTSDecode(pOut, pOut_size, m_pDTSDecoderContext->dtsPCMBuffer, 0, 8, &bitdepth, &channels, &CoreSampleRate, &unk4, &HDSampleRate, &unk5, &profile); if (nPCMLength > 0 && bitdepth != m_DTSBitDepth) { int decodeBits = bitdepth > 16 ? 24 : 16; // If the bit-depth changed, instruct the DTS Decoder to decode to the new bit depth, and decode the previous sample again. if (decodeBits != m_DTSBitDepth && out.bBuffer->GetCount() == 0) { DbgLog((LOG_TRACE, 20, L"::Decode(): The DTS decoder indicated that it outputs %d bits, changing config to %d bits to compensate", bitdepth, decodeBits)); m_DTSBitDepth = decodeBits; FlushDTSDecoder(); nPCMLength = SafeDTSDecode(pOut, pOut_size, m_pDTSDecoderContext->dtsPCMBuffer, 0, 2, &bitdepth, &channels, &CoreSampleRate, &unk4, &HDSampleRate, &unk5, &profile); } } if (nPCMLength <= 0) { DbgLog((LOG_TRACE, 50, L"::Decode() - DTS decoding failed")); FlushDTSDecoder(TRUE); m_bQueueResync = TRUE; continue; } out.wChannels = channels; out.dwSamplesPerSec = HDSampleRate; out.sfFormat = m_DTSBitDepth == 24 ? SampleFormat_24 : SampleFormat_16; out.dwChannelMask = get_channel_mask(channels); // TODO out.wBitsPerSample = bitdepth; int profile_index = 0; while(profile >>= 1) profile_index++; if (profile_index > 7) m_pAVCtx->profile = FF_PROFILE_UNKNOWN; else if (profile == 0 && !m_bsParser.m_DTSHeader.HasCore) m_pAVCtx->profile = FF_PROFILE_DTS_EXPRESS; else m_pAVCtx->profile = DTSProfiles[profile_index]; // TODO: get rid of these m_pAVCtx->sample_rate = HDSampleRate; m_pAVCtx->bits_per_raw_sample = bitdepth; // Send current input time to the delivery function out.rtStart = m_rtStartInputCache; m_rtStartInputCache = AV_NOPTS_VALUE; m_bUpdateTimeCache = TRUE; } // Send to Output if (nPCMLength > 0) { hr = S_OK; out.bBuffer->Append(m_pDTSDecoderContext->dtsPCMBuffer, nPCMLength); out.nSamples = out.bBuffer->GetCount() / get_byte_per_sample(out.sfFormat) / out.wChannels; if (m_pAVCtx->profile != (1 << 7)) { DTSRemapOutputChannels(&out, m_bsParser.m_DTSHeader); } m_pAVCtx->channels = out.wChannels; m_DecodeFormat = out.sfFormat; m_DecodeLayout = out.dwChannelMask; if (SUCCEEDED(PostProcess(&out))) { *hrDeliver = QueueOutput(out); if (FAILED(*hrDeliver)) { return S_FALSE; } } } }