blob: 4fa378dbde2067e006b4b211ea875974b5111aef [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/media_common.h"
#include <Mfapi.h>
#include <Mferror.h>
#include <Mfidl.h>
#include <Mfobjects.h>
#include <Rpc.h>
#include <comutil.h>
#include <wrl\client.h> // For ComPtr.
#include "starboard/common/log.h"
#include "starboard/common/mutex.h"
#include "starboard/common/ref_counted.h"
#include "starboard/common/string.h"
#include "starboard/configuration.h"
#include "starboard/media.h"
#include "starboard/shared/starboard/player/filter/player_components.h"
#include "starboard/shared/starboard/player/input_buffer_internal.h"
namespace starboard {
namespace shared {
namespace win32 {
// Converts microseconds to 10Mhz (100ns time).
int64_t ConvertUsecToWin32Time(int64_t input) {
int64_t out = input;
out *= 10;
return out;
}
// Convert the other way around.
int64_t ConvertWin32TimeToUsec(int64_t input) {
int64_t out = input;
out /= 10;
return out;
}
std::vector<ComPtr<IMFMediaType>> GetAllOutputMediaTypes(
int stream_id,
IMFTransform* decoder) {
std::vector<ComPtr<IMFMediaType>> output;
for (int index = 0;; ++index) {
ComPtr<IMFMediaType> media_type;
HRESULT hr = decoder->GetOutputAvailableType(stream_id, index, &media_type);
if (SUCCEEDED(hr)) {
output.push_back(media_type);
} else {
SB_DCHECK(hr == MF_E_NO_MORE_TYPES);
break;
}
}
return output;
}
std::vector<ComPtr<IMFMediaType>> GetAllInputMediaTypes(
int stream_id,
IMFTransform* transform) {
std::vector<ComPtr<IMFMediaType>> input_types;
for (DWORD i = 0;; ++i) {
ComPtr<IMFMediaType> curr_type;
HRESULT hr = transform->GetInputAvailableType(stream_id, i,
curr_type.GetAddressOf());
if (FAILED(hr)) {
break;
}
input_types.push_back(curr_type);
}
return input_types;
}
std::vector<ComPtr<IMFMediaType>> FilterMediaBySubType(
const std::vector<ComPtr<IMFMediaType>>& input,
GUID sub_type_filter) {
std::vector<ComPtr<IMFMediaType>> output;
for (auto it = input.begin(); it != input.end(); ++it) {
ComPtr<IMFMediaType> media_type = *it;
GUID media_sub_type = {0};
media_type->GetGUID(MF_MT_SUBTYPE, &media_sub_type);
if (IsEqualGUID(media_sub_type, sub_type_filter)) {
output.push_back(media_type);
}
}
return output;
}
HRESULT CreateAV1Decoder(const IID& iid, void** object) {
MFT_REGISTER_TYPE_INFO type_info = {MFMediaType_Video, MFVideoFormat_AV1};
MFT_REGISTER_TYPE_INFO output_info = {MFMediaType_Video, MFVideoFormat_NV12};
IMFActivate** acts;
UINT32 acts_num = 0;
HRESULT hr = ::MFTEnumEx(MFT_CATEGORY_VIDEO_DECODER,
MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT |
MFT_ENUM_FLAG_UNTRUSTED_STOREMFT,
&type_info, &output_info, &acts, &acts_num);
if (FAILED(hr))
return hr;
if (acts_num < 1)
return E_FAIL;
hr = acts[0]->ActivateObject(iid, object);
for (UINT32 i = 0; i < acts_num; ++i)
acts[i]->Release();
CoTaskMemFree(acts);
return hr;
}
HRESULT CreateDecoderTransform(const GUID& decoder_guid,
ComPtr<IMFTransform>* transform) {
if (decoder_guid == MFVideoFormat_AV1) {
return CreateAV1Decoder(IID_PPV_ARGS(transform->GetAddressOf()));
}
return CoCreateInstance(decoder_guid, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(transform->GetAddressOf()));
}
bool IsHardwareAv1DecoderSupported() {
static bool av1_decoder_supported = false;
static bool av1_support_checked = false;
if (!av1_support_checked) {
MFT_REGISTER_TYPE_INFO type_info = {MFMediaType_Video, MFVideoFormat_AV1};
MFT_REGISTER_TYPE_INFO output_info = {MFMediaType_Video,
MFVideoFormat_NV12};
IMFActivate** acts;
UINT32 acts_num = 0;
HRESULT hr = ::MFTEnumEx(MFT_CATEGORY_VIDEO_DECODER,
MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT |
MFT_ENUM_FLAG_UNTRUSTED_STOREMFT,
&type_info, &output_info, &acts, &acts_num);
for (UINT32 i = 0; i < acts_num; ++i)
acts[i]->Release();
av1_decoder_supported = SUCCEEDED(hr) && acts_num >= 1;
av1_support_checked = true;
}
return av1_decoder_supported;
}
} // namespace win32
} // namespace shared
} // namespace starboard