audio_core: hle: mf: make DetectMediaType return a struct

This commit is contained in:
liushuyu 2019-02-08 22:23:40 -07:00 committed by B3N30
parent 168f2ee79a
commit ab1f47ed15
3 changed files with 23 additions and 16 deletions

View file

@ -163,7 +163,7 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ
if (!initalized) { if (!initalized) {
LOG_DEBUG(Audio_DSP, "Decoder not initalized"); LOG_DEBUG(Audio_DSP, "Decoder not initalized");
// This is a hack to continue games that are not compiled with the aac codec // This is a hack to continue games when decoder failed to initialize
return response; return response;
} }
@ -176,21 +176,21 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ
std::array<std::vector<u8>, 2> out_streams; std::array<std::vector<u8>, 2> out_streams;
unique_mfptr<IMFSample> sample; unique_mfptr<IMFSample> sample;
ADTSData adts_header;
char* aac_tag = (char*)calloc(1, 14);
MFInputState input_status = MFInputState::OK; MFInputState input_status = MFInputState::OK;
std::optional<ADTSMeta> adts_meta = DetectMediaType((char*)data, request.size);
if (DetectMediaType((char*)data, request.size, &adts_header, &aac_tag) != 0) { if (!adts_meta) {
LOG_ERROR(Audio_DSP, "Unable to deduce decoding parameters from ADTS stream"); LOG_ERROR(Audio_DSP, "Unable to deduce decoding parameters from ADTS stream");
return response; return response;
} }
response.num_channels = adts_header.channels; response.num_channels = adts_meta->ADTSHeader.channels;
if (!selected) { if (!selected) {
LOG_DEBUG(Audio_DSP, "New ADTS stream: channels = {}, sample rate = {}", LOG_DEBUG(Audio_DSP, "New ADTS stream: channels = {}, sample rate = {}",
adts_header.channels, adts_header.samplerate); adts_meta->ADTSHeader.channels, adts_meta->ADTSHeader.samplerate);
SelectInputMediaType(transform.get(), in_stream_id, adts_header, (UINT8*)aac_tag, 14); SelectInputMediaType(transform.get(), in_stream_id, adts_meta->ADTSHeader,
adts_meta->AACTag, 14);
SelectOutputMediaType(transform.get(), out_stream_id); SelectOutputMediaType(transform.get(), out_stream_id);
SendSample(transform.get(), in_stream_id, nullptr); SendSample(transform.get(), in_stream_id, nullptr);
// cache the result from detect_mediatype and call select_*_mediatype only once // cache the result from detect_mediatype and call select_*_mediatype only once
@ -205,7 +205,7 @@ std::optional<BinaryResponse> WMFDecoder::Impl::Decode(const BinaryRequest& requ
while (true) { while (true) {
input_status = SendSample(transform.get(), in_stream_id, sample.get()); input_status = SendSample(transform.get(), in_stream_id, sample.get());
if (DecodingLoop(adts_header, out_streams) == MFOutputState::FatalError) { if (DecodingLoop(adts_meta->ADTSHeader, out_streams) == MFOutputState::FatalError) {
// if the decode issues are caused by MFT not accepting new samples, try again // if the decode issues are caused by MFT not accepting new samples, try again
// NOTICE: you are required to check the output even if you already knew/guessed // NOTICE: you are required to check the output even if you already knew/guessed
// MFT didn't accept the input sample // MFT didn't accept the input sample

View file

@ -209,17 +209,18 @@ bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id, GUID audi
return false; return false;
} }
int DetectMediaType(char* buffer, size_t len, ADTSData* output, char** aac_tag) { std::optional<ADTSMeta> DetectMediaType(char* buffer, size_t len) {
if (len < 7) { if (len < 7) {
return -1; return std::nullopt;
} }
ADTSData tmp; ADTSData tmp;
ADTSMeta result;
// see https://docs.microsoft.com/en-us/windows/desktop/api/mmreg/ns-mmreg-heaacwaveinfo_tag // see https://docs.microsoft.com/en-us/windows/desktop/api/mmreg/ns-mmreg-heaacwaveinfo_tag
// for the meaning of the byte array below // for the meaning of the byte array below
// it might be a good idea to wrap the parameters into a struct // it might be a good idea to wrap the parameters into a struct
// and pass that struct into the function but this will lead to messier code // and pass that struct into the function but doing that will lead to messier code
// const UINT8 aac_data[] = { 0x01, 0x00, 0xfe, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x11, 0x90 // const UINT8 aac_data[] = { 0x01, 0x00, 0xfe, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x11, 0x90
// }; first byte: 0: raw aac 1: adts 2: adif 3: latm/laos // }; first byte: 0: raw aac 1: adts 2: adif 3: latm/laos
UINT8 aac_tmp[] = {0x01, 0x00, 0xfe, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x00, 0x00}; UINT8 aac_tmp[] = {0x01, 0x00, 0xfe, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x00, 0x00};
@ -227,15 +228,15 @@ int DetectMediaType(char* buffer, size_t len, ADTSData* output, char** aac_tag)
tmp = ParseADTS(buffer); tmp = ParseADTS(buffer);
if (tmp.length == 0) { if (tmp.length == 0) {
return -1; return std::nullopt;
} }
tag = MFGetAACTag(tmp); tag = MFGetAACTag(tmp);
aac_tmp[12] |= (tag & 0xff00) >> 8; aac_tmp[12] |= (tag & 0xff00) >> 8;
aac_tmp[13] |= (tag & 0x00ff); aac_tmp[13] |= (tag & 0x00ff);
std::memcpy(*aac_tag, aac_tmp, 14); std::memcpy(&(result.ADTSHeader), &tmp, sizeof(ADTSData));
std::memcpy(output, &tmp, sizeof(ADTSData)); std::memcpy(&(result.AACTag), aac_tmp, 14);
return 0; return result;
} }
void MFFlush(IMFTransform* transform) { void MFFlush(IMFTransform* transform) {

View file

@ -58,6 +58,12 @@ auto Amp(SmartPtr& smart_ptr) {
// convient function for formatting error messages // convient function for formatting error messages
void ReportError(std::string msg, HRESULT hr); void ReportError(std::string msg, HRESULT hr);
// data type for transferring ADTS metadata between functions
struct ADTSMeta {
ADTSData ADTSHeader;
u8 AACTag[14];
};
// exported functions // exported functions
bool MFCoInit(); bool MFCoInit();
unique_mfptr<IMFTransform> MFDecoderInit(GUID audio_format = MFAudioFormat_AAC); unique_mfptr<IMFTransform> MFDecoderInit(GUID audio_format = MFAudioFormat_AAC);
@ -67,7 +73,7 @@ unique_mfptr<IMFSample> CreateSample(void* data, DWORD len, DWORD alignment = 1,
bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSData& adts, bool SelectInputMediaType(IMFTransform* transform, int in_stream_id, const ADTSData& adts,
UINT8* user_data, UINT32 user_data_len, UINT8* user_data, UINT32 user_data_len,
GUID audio_format = MFAudioFormat_AAC); GUID audio_format = MFAudioFormat_AAC);
int DetectMediaType(char* buffer, size_t len, ADTSData* output, char** aac_tag); std::optional<ADTSMeta> DetectMediaType(char* buffer, size_t len);
bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id, bool SelectOutputMediaType(IMFTransform* transform, int out_stream_id,
GUID audio_format = MFAudioFormat_PCM); GUID audio_format = MFAudioFormat_PCM);
void MFFlush(IMFTransform* transform); void MFFlush(IMFTransform* transform);