| // Copyright (c) 2010 The WebM project authors. All Rights Reserved. | |
| // | |
| // Use of this source code is governed by a BSD-style license | |
| // that can be found in the LICENSE file in the root of the source | |
| // tree. An additional intellectual property rights grant can be found | |
| // in the file PATENTS. All contributing project authors may | |
| // be found in the AUTHORS file in the root of the source tree. | |
| #include <windows.h> | |
| #include <windowsx.h> | |
| #include <mfapi.h> | |
| #include <mferror.h> | |
| #include <mfidl.h> | |
| #include <new> | |
| #include "debugutil.hpp" | |
| #include "webmsdl.hpp" | |
| #include "webmtypes.hpp" | |
| namespace WebmSdl | |
| { | |
| SdlInstance::SdlInstance(): | |
| ref_count_(0) | |
| { | |
| DBGLOG("ctor"); | |
| } | |
| SdlInstance::~SdlInstance() | |
| { | |
| SDL_Quit(); | |
| DBGLOG("dtor"); | |
| } | |
| HRESULT SdlInstance::CreateInstance(SdlInstance** ptr_instance) | |
| { | |
| SdlInstance* ptr_sdl_instance = new (std::nothrow) SdlInstance(); | |
| if (!ptr_sdl_instance) | |
| { | |
| DBGLOG("ERROR, null SdlInstance, E_OUTOFMEMORY"); | |
| return E_OUTOFMEMORY; | |
| } | |
| HRESULT hr = SDL_Init(SDL_INIT_EVERYTHING); | |
| if (FAILED(hr)) | |
| { | |
| DBGLOG("SDL_Init failed, " << SDL_GetError()); | |
| return hr; | |
| } | |
| ptr_sdl_instance->AddRef(); | |
| *ptr_instance = ptr_sdl_instance; | |
| return S_OK; | |
| } | |
| ULONG SdlInstance::AddRef() | |
| { | |
| return InterlockedIncrement(&ref_count_); | |
| } | |
| ULONG SdlInstance::Release() | |
| { | |
| UINT ref_count = InterlockedDecrement(&ref_count_); | |
| if (ref_count == 0) | |
| { | |
| delete this; | |
| } | |
| return ref_count; | |
| } | |
| SdlPlayerBase::SdlPlayerBase(): | |
| ptr_sdl_instance_(NULL) | |
| { | |
| DBGLOG("ctor"); | |
| } | |
| SdlPlayerBase::~SdlPlayerBase() | |
| { | |
| if (ptr_sdl_instance_) | |
| { | |
| ptr_sdl_instance_->Release(); | |
| ptr_sdl_instance_ = NULL; | |
| } | |
| DBGLOG("dtor"); | |
| } | |
| HRESULT SdlPlayerBase::InitPlayer(SdlInstance* ptr_instance, | |
| IMFMediaType* ptr_media_type) | |
| { | |
| if (!ptr_instance) | |
| { | |
| DBGLOG("ERROR, NULL SdlInstance, E_INVALIDARG"); | |
| return E_INVALIDARG; | |
| } | |
| if (!ptr_media_type) | |
| { | |
| DBGLOG("ERROR, NULL IMFMediaType, E_INVALIDARG"); | |
| return E_INVALIDARG; | |
| } | |
| GUID guid = GUID_NULL; | |
| HRESULT hr = ptr_media_type->GetGUID(MF_MT_MAJOR_TYPE, &guid); | |
| if (FAILED(hr)) | |
| { | |
| DBGLOG("ERROR, unable to obtain major type, MF_E_INVALIDMEDIATYPE"); | |
| return MF_E_INVALIDMEDIATYPE; | |
| } | |
| if (MFMediaType_Audio != guid && MFMediaType_Video != guid) | |
| { | |
| DBGLOG("ERROR, unsupported major type, MF_E_INVALIDMEDIATYPE"); | |
| return MF_E_INVALIDMEDIATYPE; | |
| } | |
| ptr_instance->AddRef(); | |
| ptr_sdl_instance_ = ptr_instance; | |
| return S_OK; | |
| } | |
| SdlAudioPlayer::SdlAudioPlayer() | |
| { | |
| DBGLOG("ctor"); | |
| } | |
| SdlAudioPlayer::~SdlAudioPlayer() | |
| { | |
| DBGLOG("dtor"); | |
| } | |
| HRESULT SdlAudioPlayer::InitPlayer(SdlInstance* ptr_sdl_instance, | |
| IMFMediaType* ptr_media_type) | |
| { | |
| HRESULT hr = SdlPlayerBase::InitPlayer(ptr_sdl_instance, ptr_media_type); | |
| if (FAILED(hr)) | |
| { | |
| DBGLOG("SdlPlayerBase::InitPlayer failed" << HRLOG(hr)); | |
| return hr; | |
| } | |
| GUID subtype = GUID_NULL; | |
| hr = ptr_media_type->GetGUID(MF_MT_SUBTYPE, &subtype); | |
| if (FAILED(hr)) | |
| { | |
| DBGLOG("media type GetGUID MF_MT_SUBTYPE failed" << HRLOG(hr)); | |
| return hr; | |
| } | |
| // TODO(tomfinegan): support MFAudioFormat_PCM-- we have to resample for | |
| // SDL anyway, so we might as well allow it to come in | |
| // that way. | |
| if (MFAudioFormat_Float != subtype) | |
| { | |
| DBGLOG("ERROR, unsupported media subtype, MF_E_INVALIDMEDIATYPE"); | |
| return MF_E_INVALIDMEDIATYPE; | |
| } | |
| // Store the audio input format | |
| hr = StoreAudioInputFormat_(ptr_media_type); | |
| if (FAILED(hr)) | |
| { | |
| DBGLOG("StoreAudioInputFormat_ failed" << HRLOG(hr)); | |
| return hr; | |
| } | |
| return hr; | |
| } | |
| HRESULT SdlAudioPlayer::StoreAudioInputFormat_(IMFMediaType* ptr_media_type) | |
| { | |
| // caller already checked ptr_media_type excessively | |
| HRESULT hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, | |
| &bits_per_sample_); | |
| if (FAILED(hr)) | |
| { | |
| DBGLOG("unable to obtain sample size" << HRLOG(hr)); | |
| return hr; | |
| } | |
| if (0 == bits_per_sample_) | |
| { | |
| DBGLOG("invalid sample size"); | |
| return MF_E_INVALIDMEDIATYPE; | |
| } | |
| hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_align_); | |
| if (FAILED(hr)) | |
| { | |
| DBGLOG("unable to obtain block alignment" << HRLOG(hr)); | |
| return hr; | |
| } | |
| if (0 == block_align_) | |
| { | |
| DBGLOG("invalid block alignment"); | |
| return MF_E_INVALIDMEDIATYPE; | |
| } | |
| hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, | |
| &bytes_per_sec_); | |
| if (FAILED(hr)) | |
| { | |
| DBGLOG("unable to obtain bytes per second" << HRLOG(hr)); | |
| return hr; | |
| } | |
| if (0 == bytes_per_sec_) | |
| { | |
| DBGLOG("invalid bytes per sec"); | |
| return MF_E_INVALIDMEDIATYPE; | |
| } | |
| hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &channels_); | |
| if (FAILED(hr)) | |
| { | |
| DBGLOG("unable to obtain channel count" << HRLOG(hr)); | |
| return hr; | |
| } | |
| if (0 == channels_) | |
| { | |
| DBGLOG("invalid channel count"); | |
| return MF_E_INVALIDMEDIATYPE; | |
| } | |
| hr = ptr_media_type->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, | |
| &sample_rate_); | |
| if (FAILED(hr)) | |
| { | |
| DBGLOG("unable to sample rate" << HRLOG(hr)); | |
| return hr; | |
| } | |
| if (0 == sample_rate_) | |
| { | |
| DBGLOG("invalid sample rate"); | |
| return MF_E_INVALIDMEDIATYPE; | |
| } | |
| return S_OK; | |
| } | |
| } // WebmSdl namespace |