blob: 5a03f94947b63db5069fe0a6ef364dc915af3b61 [file] [log] [blame]
// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "starboard/shared/win32/audio_transform.h"
#include <vector>
#include "starboard/memory.h"
#include "starboard/shared/win32/error_utils.h"
#include "starboard/shared/win32/media_common.h"
#include "starboard/shared/win32/media_foundation_utils.h"
namespace starboard {
namespace shared {
namespace win32 {
using Microsoft::WRL::ComPtr;
namespace {
GUID ConvertToWin32AudioCodec(SbMediaAudioCodec codec) {
switch (codec) {
case kSbMediaAudioCodecNone: {
return MFAudioFormat_PCM;
}
case kSbMediaAudioCodecAac: {
return MFAudioFormat_AAC;
}
case kSbMediaAudioCodecOpus: {
return MFAudioFormat_Opus;
}
default: {
SB_NOTIMPLEMENTED();
return MFAudioFormat_PCM;
}
}
}
class WinAudioFormat {
public:
explicit WinAudioFormat(const SbMediaAudioSampleInfo& audio_sample_info) {
// The HEAACWAVEFORMAT structure has many specializations with varying data
// appended at the end.
// The "-1" is used to account for pbAudioSpecificConfig[1] at the end of
// HEAACWAVEFORMAT.
format_buffer_.resize(sizeof(HEAACWAVEFORMAT) +
audio_sample_info.audio_specific_config_size - 1);
HEAACWAVEFORMAT* wave_format =
reinterpret_cast<HEAACWAVEFORMAT*>(format_buffer_.data());
wave_format->wfInfo.wfx.nAvgBytesPerSec = 0;
wave_format->wfInfo.wfx.nBlockAlign = audio_sample_info.block_alignment;
wave_format->wfInfo.wfx.nChannels = audio_sample_info.number_of_channels;
wave_format->wfInfo.wfx.nSamplesPerSec =
audio_sample_info.samples_per_second;
wave_format->wfInfo.wfx.wBitsPerSample = audio_sample_info.bits_per_sample;
wave_format->wfInfo.wfx.wFormatTag = WAVE_FORMAT_MPEG_HEAAC;
// The "-1" is used to account for pbAudioSpecificConfig[1] at the end of
// HEAACWAVEFORMAT.
wave_format->wfInfo.wfx.cbSize =
sizeof(HEAACWAVEFORMAT) - sizeof(WAVEFORMATEX) +
audio_sample_info.audio_specific_config_size - 1;
wave_format->wfInfo.wPayloadType = 0; // RAW
wave_format->wfInfo.wAudioProfileLevelIndication = 0xfe; // Unknown Profile
wave_format->wfInfo.wStructType = 0; // AudioSpecificConfig()
if (audio_sample_info.audio_specific_config_size > 0) {
memcpy(wave_format->pbAudioSpecificConfig,
audio_sample_info.audio_specific_config,
audio_sample_info.audio_specific_config_size);
}
}
WAVEFORMATEX* WaveFormatData() {
return reinterpret_cast<WAVEFORMATEX*>(format_buffer_.data());
}
UINT32 Size() const { return static_cast<UINT32>(format_buffer_.size()); }
private:
std::vector<uint8_t> format_buffer_;
};
} // namespace.
scoped_ptr<MediaTransform> CreateAudioTransform(
const SbMediaAudioSampleInfo& audio,
SbMediaAudioCodec codec) {
ComPtr<IMFTransform> transform;
HRESULT hr = CreateDecoderTransform(CLSID_MSAACDecMFT, &transform);
CheckResult(hr);
ComPtr<IMFMediaType> input_type;
hr = MFCreateMediaType(&input_type);
CheckResult(hr);
WinAudioFormat audio_fmt(audio);
hr = MFInitMediaTypeFromWaveFormatEx(
input_type.Get(), audio_fmt.WaveFormatData(), audio_fmt.Size());
CheckResult(hr);
GUID win32_audio_type = ConvertToWin32AudioCodec(codec);
std::vector<ComPtr<IMFMediaType>> available_types =
GetAllInputMediaTypes(MediaTransform::kStreamId, transform.Get());
available_types = FilterMediaBySubType(available_types, win32_audio_type);
SB_DCHECK(available_types.size());
ComPtr<IMFMediaType> selected = available_types[0];
CopyProperties(input_type.Get(), selected.Get());
scoped_ptr<MediaTransform> output(new MediaTransform(transform));
output->SetInputType(selected);
output->SetOutputTypeBySubType(MFAudioFormat_Float);
return output.Pass();
}
} // namespace win32
} // namespace shared
} // namespace starboard