audio_core: hle: mf: return values as std::optional
This commit is contained in:
parent
25fa10327b
commit
6332e57069
5 changed files with 44 additions and 34 deletions
|
@ -16,7 +16,7 @@ struct ADTSData {
|
||||||
u32 samplerate;
|
u32 samplerate;
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 ParseADTS(char* buffer, ADTSData* out);
|
ADTSData ParseADTS(char* buffer);
|
||||||
|
|
||||||
// last two bytes of MF AAC decoder user data
|
// last two bytes of MF AAC decoder user data
|
||||||
// see https://docs.microsoft.com/en-us/windows/desktop/medfound/aac-decoder#example-media-types
|
// see https://docs.microsoft.com/en-us/windows/desktop/medfound/aac-decoder#example-media-types
|
||||||
|
|
|
@ -8,36 +8,39 @@ constexpr std::array<u32, 16> freq_table = {96000, 88200, 64000, 48000, 44100, 3
|
||||||
16000, 12000, 11025, 8000, 7350, 0, 0, 0};
|
16000, 12000, 11025, 8000, 7350, 0, 0, 0};
|
||||||
constexpr std::array<u8, 8> channel_table = {0, 1, 2, 3, 4, 5, 6, 8};
|
constexpr std::array<u8, 8> channel_table = {0, 1, 2, 3, 4, 5, 6, 8};
|
||||||
|
|
||||||
u32 ParseADTS(char* buffer, ADTSData* out) {
|
ADTSData ParseADTS(char* buffer) {
|
||||||
u32 tmp = 0;
|
u32 tmp = 0;
|
||||||
|
ADTSData out;
|
||||||
|
|
||||||
// sync word 0xfff
|
// sync word 0xfff
|
||||||
tmp = (buffer[0] << 8) | (buffer[1] & 0xf0);
|
tmp = (buffer[0] << 8) | (buffer[1] & 0xf0);
|
||||||
if ((tmp & 0xffff) != 0xfff0)
|
if ((tmp & 0xffff) != 0xfff0) {
|
||||||
return 0;
|
out.length = 0;
|
||||||
out->MPEG2 = (buffer[1] >> 3) & 0x1;
|
return out;
|
||||||
|
}
|
||||||
|
out.MPEG2 = (buffer[1] >> 3) & 0x1;
|
||||||
// bit 17 to 18
|
// bit 17 to 18
|
||||||
out->profile = (buffer[2] >> 6) + 1;
|
out.profile = (buffer[2] >> 6) + 1;
|
||||||
// bit 19 to 22
|
// bit 19 to 22
|
||||||
tmp = (buffer[2] >> 2) & 0xf;
|
tmp = (buffer[2] >> 2) & 0xf;
|
||||||
out->samplerate_idx = tmp;
|
out.samplerate_idx = tmp;
|
||||||
out->samplerate = (tmp > 15) ? 0 : freq_table[tmp];
|
out.samplerate = (tmp > 15) ? 0 : freq_table[tmp];
|
||||||
// bit 24 to 26
|
// bit 24 to 26
|
||||||
tmp = ((buffer[2] & 0x1) << 2) | ((buffer[3] >> 6) & 0x3);
|
tmp = ((buffer[2] & 0x1) << 2) | ((buffer[3] >> 6) & 0x3);
|
||||||
out->channel_idx = tmp;
|
out.channel_idx = tmp;
|
||||||
out->channels = (tmp > 7) ? 0 : channel_table[tmp];
|
out.channels = (tmp > 7) ? 0 : channel_table[tmp];
|
||||||
|
|
||||||
// bit 55 to 56
|
// bit 55 to 56
|
||||||
out->framecount = (buffer[6] & 0x3) + 1;
|
out.framecount = (buffer[6] & 0x3) + 1;
|
||||||
|
|
||||||
// bit 31 to 43
|
// bit 31 to 43
|
||||||
tmp = (buffer[3] & 0x3) << 11;
|
tmp = (buffer[3] & 0x3) << 11;
|
||||||
tmp |= (buffer[4] << 3) & 0x7f8;
|
tmp |= (buffer[4] << 3) & 0x7f8;
|
||||||
tmp |= (buffer[5] >> 5) & 0x7;
|
tmp |= (buffer[5] >> 5) & 0x7;
|
||||||
|
|
||||||
out->length = tmp;
|
out.length = tmp;
|
||||||
|
|
||||||
return tmp;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// last two bytes of MF AAC decoder user data
|
// last two bytes of MF AAC decoder user data
|
||||||
|
|
|
@ -104,8 +104,7 @@ void WMFDecoder::Impl::Clear() {
|
||||||
MFOutputState WMFDecoder::Impl::DecodingLoop(ADTSData adts_header,
|
MFOutputState WMFDecoder::Impl::DecodingLoop(ADTSData adts_header,
|
||||||
std::array<std::vector<u8>, 2>& out_streams) {
|
std::array<std::vector<u8>, 2>& out_streams) {
|
||||||
MFOutputState output_status = MFOutputState::OK;
|
MFOutputState output_status = MFOutputState::OK;
|
||||||
char* output_buffer = nullptr;
|
std::optional<std::vector<f32>> output_buffer;
|
||||||
DWORD output_len = 0;
|
|
||||||
unique_mfptr<IMFSample> output;
|
unique_mfptr<IMFSample> output;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -113,22 +112,18 @@ MFOutputState WMFDecoder::Impl::DecodingLoop(ADTSData adts_header,
|
||||||
|
|
||||||
// 0 -> okay; 3 -> okay but more data available (buffer too small)
|
// 0 -> okay; 3 -> okay but more data available (buffer too small)
|
||||||
if (output_status == MFOutputState::OK || output_status == MFOutputState::HaveMoreData) {
|
if (output_status == MFOutputState::OK || output_status == MFOutputState::HaveMoreData) {
|
||||||
CopySampleToBuffer(output.get(), (void**)&output_buffer, &output_len);
|
output_buffer = CopySampleToBuffer(output.get());
|
||||||
|
|
||||||
// the following was taken from ffmpeg version of the decoder
|
// the following was taken from ffmpeg version of the decoder
|
||||||
f32 val_f32;
|
f32 val_f32;
|
||||||
for (size_t i = 0; i < output_len;) {
|
for (size_t i = 0; i < output_buffer->size(); i++) {
|
||||||
for (std::size_t channel = 0; channel < adts_header.channels; channel++) {
|
for (std::size_t channel = 0; channel < adts_header.channels; channel++) {
|
||||||
std::memcpy(&val_f32, output_buffer + i, sizeof(val_f32));
|
val_f32 = output_buffer->at(i);
|
||||||
s16 val = static_cast<s16>(0x7FFF * val_f32);
|
s16 val = static_cast<s16>(0x7FFF * val_f32);
|
||||||
out_streams[channel].push_back(val & 0xFF);
|
out_streams[channel].push_back(val & 0xFF);
|
||||||
out_streams[channel].push_back(val >> 8);
|
out_streams[channel].push_back(val >> 8);
|
||||||
i += sizeof(val_f32);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output_buffer)
|
|
||||||
free(output_buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// in case of "ok" only, just return quickly
|
// in case of "ok" only, just return quickly
|
||||||
|
|
|
@ -25,6 +25,12 @@ void ReportError(std::string msg, HRESULT hr) {
|
||||||
|
|
||||||
bool MFCoInit() {
|
bool MFCoInit() {
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
hr = CoInitialize(NULL);
|
||||||
|
// S_FALSE will be returned when COM has already been initialized
|
||||||
|
if (hr != S_OK && hr != S_FALSE) {
|
||||||
|
ReportError("Failed to start COM components", hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// lite startup is faster and all what we need is included
|
// lite startup is faster and all what we need is included
|
||||||
hr = MFStartup(MF_VERSION, MFSTARTUP_LITE);
|
hr = MFStartup(MF_VERSION, MFSTARTUP_LITE);
|
||||||
|
@ -216,8 +222,8 @@ int DetectMediaType(char* buffer, size_t len, ADTSData* output, char** aac_tag)
|
||||||
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};
|
||||||
uint16_t tag = 0;
|
uint16_t tag = 0;
|
||||||
|
|
||||||
uint32_t result = ParseADTS(buffer, &tmp);
|
tmp = ParseADTS(buffer);
|
||||||
if (result == 0) {
|
if (tmp.length == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,33 +331,37 @@ std::tuple<MFOutputState, unique_mfptr<IMFSample>> ReceiveSample(IMFTransform* t
|
||||||
return std::make_tuple(MFOutputState::OK, std::move(sample));
|
return std::make_tuple(MFOutputState::OK, std::move(sample));
|
||||||
}
|
}
|
||||||
|
|
||||||
int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len) {
|
std::optional<std::vector<f32>> CopySampleToBuffer(IMFSample* sample) {
|
||||||
unique_mfptr<IMFMediaBuffer> buffer;
|
unique_mfptr<IMFMediaBuffer> buffer;
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
std::optional<std::vector<f32>> output;
|
||||||
|
std::vector<f32> output_buffer;
|
||||||
BYTE* data;
|
BYTE* data;
|
||||||
|
DWORD len = 0;
|
||||||
|
|
||||||
hr = sample->GetTotalLength(len);
|
hr = sample->GetTotalLength(&len);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
ReportError("Failed to get the length of sample buffer", hr);
|
ReportError("Failed to get the length of sample buffer", hr);
|
||||||
return -1;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = sample->ConvertToContiguousBuffer(Amp(buffer));
|
hr = sample->ConvertToContiguousBuffer(Amp(buffer));
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
ReportError("Failed to get sample buffer", hr);
|
ReportError("Failed to get sample buffer", hr);
|
||||||
return -1;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = buffer->Lock(&data, nullptr, nullptr);
|
hr = buffer->Lock(&data, nullptr, nullptr);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
ReportError("Failed to lock the buffer", hr);
|
ReportError("Failed to lock the buffer", hr);
|
||||||
return -1;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
*output = malloc(*len);
|
output_buffer.resize(len / sizeof(f32));
|
||||||
std::memcpy(*output, data, *len);
|
std::memcpy(output_buffer.data(), data, len);
|
||||||
|
output = output_buffer;
|
||||||
|
|
||||||
// if buffer unlock fails, then... whatever, we have already got data
|
// if buffer unlock fails, then... whatever, we have already got data
|
||||||
buffer->Unlock();
|
buffer->Unlock();
|
||||||
return 0;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,10 @@
|
||||||
// AAC decoder related APIs are only available with WIN7+
|
// AAC decoder related APIs are only available with WIN7+
|
||||||
#define WINVER _WIN32_WINNT_WIN7
|
#define WINVER _WIN32_WINNT_WIN7
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <vector>
|
||||||
#include <comdef.h>
|
#include <comdef.h>
|
||||||
#include <mfapi.h>
|
#include <mfapi.h>
|
||||||
#include <mferror.h>
|
#include <mferror.h>
|
||||||
|
@ -45,7 +47,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SmartPtr& smart_ptr;
|
SmartPtr& smart_ptr;
|
||||||
RawPtr raw_ptr;
|
RawPtr raw_ptr = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename SmartPtr>
|
template <typename SmartPtr>
|
||||||
|
@ -72,4 +74,4 @@ void MFFlush(IMFTransform* transform);
|
||||||
MFInputState SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample);
|
MFInputState SendSample(IMFTransform* transform, DWORD in_stream_id, IMFSample* in_sample);
|
||||||
std::tuple<MFOutputState, unique_mfptr<IMFSample>> ReceiveSample(IMFTransform* transform,
|
std::tuple<MFOutputState, unique_mfptr<IMFSample>> ReceiveSample(IMFTransform* transform,
|
||||||
DWORD out_stream_id);
|
DWORD out_stream_id);
|
||||||
int CopySampleToBuffer(IMFSample* sample, void** output, DWORD* len);
|
std::optional<std::vector<f32>> CopySampleToBuffer(IMFSample* sample);
|
||||||
|
|
Loading…
Reference in a new issue