blob: 31607909eef508eaa9abaf8b300fa6167493691f [file]
// 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 <comdef.h>
#include <mfapi.h>
#include <mferror.h>
#include <mfidl.h>
#include <string>
#include "debugutil.hpp"
#include "eventutil.hpp"
#include "memutil.hpp"
#include "mfsrcwrap.hpp"
#include "mftranswrap.hpp"
#include "mfutil.hpp"
// TODO(tomfinegan): relocate mf object dll paths include
#include "tests/mfdllpaths.hpp"
#include "webmtypes.hpp"
namespace WebmMfUtil
{
_COM_SMARTPTR_TYPEDEF(IMFMediaTypeHandler, IID_IMFMediaTypeHandler);
HRESULT copy_media_type(IMFMediaType* ptr_src, IMFMediaType** ptr_dest)
{
if (!ptr_src)
{
return E_INVALIDARG;
}
IMFMediaType* ptr_type;
HRESULT hr = MFCreateMediaType(&ptr_type);
if (FAILED(hr))
{
DBGLOG("ERROR, MFCreateMediaType failed" << HRLOG(hr));
return hr;
}
hr = ptr_src->CopyAllItems(ptr_type);
if (FAILED(hr))
{
DBGLOG("ERROR, CopyAllItems failed" << HRLOG(hr));
return hr;
}
*ptr_dest = ptr_type;
return hr;
}
HRESULT get_event_iunk_ptr(IMFMediaEvent* ptr_event, IUnknown** ptr_iunk)
{
if (!ptr_event)
{
return E_INVALIDARG;
}
PROPVARIANT event_val;
PropVariantInit(&event_val);
HRESULT hr = ptr_event->GetValue(&event_val);
if (FAILED(hr))
{
DBGLOG("ERROR, could not get event value" << HRLOG(hr));
return hr;
}
*ptr_iunk = event_val.punkVal;
return hr;
}
HRESULT get_media_type(IMFStreamDescriptor* ptr_desc, IMFMediaType** ptr_type)
{
if (!ptr_desc)
{
return E_INVALIDARG;
}
IMFMediaTypeHandlerPtr ptr_media_type_handler;
HRESULT hr = ptr_desc->GetMediaTypeHandler(&ptr_media_type_handler);
if (FAILED(hr) || !ptr_media_type_handler)
{
DBGLOG("ERROR, GetMediaTypeHandler failed" << HRLOG(hr));
return hr;
}
_COM_SMARTPTR_TYPEDEF(IMFMediaType, IID_IMFMediaType);
IMFMediaTypePtr ptr_temp_mt;
hr = ptr_media_type_handler->GetCurrentMediaType(&ptr_temp_mt);
if (FAILED(hr))
{
DBGLOG("ERROR, GetCurrentMediaType failed" << HRLOG(hr));
return hr;
}
return copy_media_type(ptr_temp_mt, ptr_type);
}
HRESULT get_major_type(IMFStreamDescriptor* ptr_desc, GUID* ptr_type)
{
if (!ptr_desc || !ptr_type)
{
return E_INVALIDARG;
}
IMFMediaTypeHandlerPtr ptr_media_type_handler;
HRESULT hr = ptr_desc->GetMediaTypeHandler(&ptr_media_type_handler);
if (FAILED(hr) || !ptr_media_type_handler)
{
DBGLOG("ERROR, GetMediaTypeHandler failed" << HRLOG(hr));
return hr;
}
hr = ptr_media_type_handler->GetMajorType(ptr_type);
if (FAILED(hr))
{
DBGLOG("ERROR, GetMajorType failed" << HRLOG(hr));
return hr;
}
return hr;
}
HRESULT get_sub_type(IMFStreamDescriptor* ptr_desc, GUID* ptr_sub_type)
{
if (!ptr_desc || !ptr_sub_type)
{
return E_INVALIDARG;
}
_COM_SMARTPTR_TYPEDEF(IMFMediaType, IID_IMFMediaType);
IMFMediaTypePtr ptr_type;
HRESULT hr = get_media_type(ptr_desc, &ptr_type);
if (FAILED(hr) || !ptr_type)
{
DBGLOG("ERROR, get_media_type failed" << HRLOG(hr));
return hr;
}
hr = ptr_type->GetGUID(MF_MT_SUBTYPE, ptr_sub_type);
if (FAILED(hr))
{
DBGLOG("ERROR, GetGUID MF_MT_SUBTYPE failed" << HRLOG(hr));
return hr;
}
return hr;
}
HRESULT mf_startup()
{
HRESULT hr = MFStartup(MF_VERSION);
if (FAILED(hr))
{
DBGLOG("ERROR, MFStartup failed, hr=" << hr);
}
return hr;
}
HRESULT mf_shutdown()
{
HRESULT hr = MFShutdown();
if (FAILED(hr))
{
DBGLOG("ERROR, MFShutdown failed, hr=" << hr);
}
return hr;
}
HRESULT get_webm_vorbis_sample(MfByteStreamHandlerWrapper* ptr_source,
IMFSample** ptr_out_sample)
{
if (!ptr_source)
{
DBGLOG("ERROR null ptr_source, E_INVALIDARG");
return E_INVALIDARG;
}
HRESULT hr;
IMFSamplePtr ptr_sample;
CHK(hr, ptr_source->GetAudioSample(&ptr_sample));
if (FAILED(hr))
{
return hr;
}
if (!ptr_sample)
{
DBGLOG("ERROR null ptr_source, E_FAIL");
return E_FAIL;
}
DWORD buffer_count = 0;
CHK(hr, ptr_sample->GetBufferCount(&buffer_count));
if (FAILED(hr))
{
return hr;
}
if (1 != buffer_count)
{
DBGLOG("ERROR sample buffer_count != 1");
return E_UNEXPECTED;
}
*ptr_out_sample = ptr_sample.Detach();
return hr;
}
HRESULT get_webm_vp8_sample(MfByteStreamHandlerWrapper* ptr_source,
IMFSample** ptr_out_sample)
{
if (!ptr_source)
{
DBGLOG("ERROR null ptr_source, E_INVALIDARG");
return E_INVALIDARG;
}
HRESULT hr;
IMFSamplePtr ptr_sample;
CHK(hr, ptr_source->GetVideoSample(&ptr_sample));
if (FAILED(hr))
{
return hr;
}
if (!ptr_sample)
{
DBGLOG("ERROR null ptr_source, E_FAIL");
return E_FAIL;
}
DWORD buffer_count = 0;
CHK(hr, ptr_sample->GetBufferCount(&buffer_count));
if (FAILED(hr))
{
return hr;
}
if (1 != buffer_count)
{
DBGLOG("ERROR sample buffer_count != 1");
return E_UNEXPECTED;
}
*ptr_out_sample = ptr_sample.Detach();
return hr;
}
HRESULT open_webm_source(const std::wstring& dll_path,
const std::wstring& url,
MfByteStreamHandlerWrapper** ptr_wrapper_instance)
{
MfByteStreamHandlerWrapper* ptr_mf_bsh = NULL;
HRESULT hr;
using WebmTypes::CLSID_WebmMfByteStreamHandler;
CHK(hr, MfByteStreamHandlerWrapper::Create(dll_path,
CLSID_WebmMfByteStreamHandler,
&ptr_mf_bsh));
if (FAILED(hr))
{
return hr;
}
CHK(hr, ptr_mf_bsh->OpenURL(url));
if (FAILED(hr))
{
return hr;
}
CHK(hr, ptr_mf_bsh->LoadMediaStreams());
if (SUCCEEDED(hr))
{
*ptr_wrapper_instance = ptr_mf_bsh;
}
return hr;
}
HRESULT open_webm_decoder(const std::wstring& dll_path, const GUID& clsid,
MfTransformWrapper** ptr_decoder_instance)
{
MfTransformWrapper* ptr_transform = NULL;
HRESULT hr;
CHK(hr, MfTransformWrapper::CreateInstance(dll_path, clsid,
&ptr_transform));
if (SUCCEEDED(hr))
{
*ptr_decoder_instance = ptr_transform;
}
return hr;
}
HRESULT setup_webm_decode(MfByteStreamHandlerWrapper* ptr_source,
MfTransformWrapper* ptr_decoder,
const GUID& major_type)
{
if (!ptr_source || !ptr_decoder)
{
DBGLOG("ERROR NULL ptr_source or ptr_decoder.");
return E_INVALIDARG;
}
HRESULT hr = E_INVALIDARG;
IMFMediaTypePtr ptr_type;
// get output type from |ptr_source|
if (MFMediaType_Audio == major_type)
{
CHK(hr, ptr_source->GetAudioMediaType(&ptr_type));
}
else if (MFMediaType_Video == major_type)
{
CHK(hr, ptr_source->GetVideoMediaType(&ptr_type));
}
if (FAILED(hr))
{
return hr;
}
// set |ptr_decoder| input type to the output type from |ptr_source|
CHK(hr, ptr_decoder->SetInputType(ptr_type));
if (FAILED(hr))
{
return hr;
}
// clear |ptr_type|: using an empty type lets the decoder use its default
ptr_type = 0;
CHK(hr, ptr_decoder->SetOutputType(ptr_type));
return hr;
}
HRESULT setup_webm_vorbis_decoder(const std::wstring& url,
MfByteStreamHandlerWrapper** ptr_bsh,
MfTransformWrapper** ptr_transform)
{
HRESULT hr;
using WebmUtil::auto_ref_counted_obj_ptr;
auto_ref_counted_obj_ptr<MfByteStreamHandlerWrapper> ptr_source(NULL);
CHK(hr, open_webm_source(WEBM_SOURCE_PATH, url, &ptr_source));
if (FAILED(hr))
{
return hr;
}
CHK(hr, ptr_source->Start(false, 0LL));
if (FAILED(hr))
{
return hr;
}
if (ptr_source->GetAudioStreamCount() < 1)
{
DBGLOG("ERROR no audio streams.");
return E_INVALIDARG;
}
using WebmTypes::CLSID_WebmMfVorbisDec;
auto_ref_counted_obj_ptr<MfTransformWrapper> ptr_decoder(NULL);
CHK(hr, open_webm_decoder(VORBISDEC_PATH, CLSID_WebmMfVorbisDec,
&ptr_decoder));
if (FAILED(hr))
{
return hr;
}
CHK(hr, setup_webm_decode(ptr_source, ptr_decoder, MFMediaType_Audio));
if (SUCCEEDED(hr))
{
*ptr_bsh = ptr_source.detach();
*ptr_transform = ptr_decoder.detach();
}
return hr;
}
HRESULT setup_webm_vp8_decoder(const std::wstring& url,
MfByteStreamHandlerWrapper** ptr_bsh,
MfTransformWrapper** ptr_transform)
{
HRESULT hr;
using WebmUtil::auto_ref_counted_obj_ptr;
auto_ref_counted_obj_ptr<MfByteStreamHandlerWrapper> ptr_source(NULL);
CHK(hr, open_webm_source(WEBM_SOURCE_PATH, url, &ptr_source));
if (FAILED(hr))
{
return hr;
}
CHK(hr, ptr_source->Start(false, 0LL));
if (FAILED(hr))
{
return hr;
}
if (ptr_source->GetVideoStreamCount() < 1)
{
DBGLOG("ERROR no video streams.");
return E_INVALIDARG;
}
using WebmTypes::CLSID_WebmMfVp8Dec;
auto_ref_counted_obj_ptr<MfTransformWrapper> ptr_decoder(NULL);
CHK(hr, open_webm_decoder(VP8DEC_PATH, CLSID_WebmMfVp8Dec, &ptr_decoder));
if (FAILED(hr))
{
return hr;
}
CHK(hr, setup_webm_decode(ptr_source, ptr_decoder, MFMediaType_Video));
if (SUCCEEDED(hr))
{
*ptr_bsh = ptr_source.detach();
*ptr_transform = ptr_decoder.detach();
}
return hr;
}
} // WebmMfUtil namespace