Commit 2dac3838 authored by Frank Li's avatar Frank Li Committed by Commit Bot

media: MediaEngineNotifyImpl - implements IMFMediaEngineNotify

This CL adds MediaEngineNotifyImpl to implement IMFMediaEngineNotify
required by IMFMediaEngine (https://docs.microsoft.com/en-us/windows/win32/api/mfmediaengine/nn-mfmediaengine-imfmediaengine).

Explainer:
https://docs.microsoft.com/en-us/windows/win32/medfound/protected-media-path

Design Doc:
https://docs.google.com/document/d/1kXMdmfsSKU3tcwTxG-wFU-MaEA6sN3by45PCGBV8zJU

Bug: 999747
Change-Id: I082f3dd29dcfc8fb409d387af040aa1c97ff79aa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2064454Reviewed-by: default avatarXiaohan Wang <xhwang@chromium.org>
Commit-Queue: Frank Li <frankli@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#743858}
parent 062eee29
......@@ -103,6 +103,8 @@ source_set("unit_tests") {
if (is_win) {
source_set("media_foundation_renderer") {
sources = [
"win/media_engine_notify_impl.cc",
"win/media_engine_notify_impl.h",
"win/media_foundation_audio_stream.cc",
"win/media_foundation_audio_stream.h",
"win/media_foundation_source_wrapper.cc",
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/renderers/win/media_engine_notify_impl.h"
namespace media {
namespace {
PipelineStatus MediaEngineStatusToPipelineStatus(
MF_MEDIA_ENGINE_ERR media_engine_status) {
switch (media_engine_status) {
case MF_MEDIA_ENGINE_ERR_NOERROR:
return PipelineStatus::PIPELINE_OK;
case MF_MEDIA_ENGINE_ERR_ABORTED:
return PipelineStatus::PIPELINE_ERROR_ABORT;
case MF_MEDIA_ENGINE_ERR_NETWORK:
return PipelineStatus::PIPELINE_ERROR_NETWORK;
case MF_MEDIA_ENGINE_ERR_DECODE:
FALLTHROUGH;
case MF_MEDIA_ENGINE_ERR_ENCRYPTED:
return PipelineStatus::PIPELINE_ERROR_DECODE;
case MF_MEDIA_ENGINE_ERR_SRC_NOT_SUPPORTED:
return PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN;
default:
NOTREACHED();
return PipelineStatus::PIPELINE_ERROR_INVALID_STATE;
}
}
} // namespace
MediaEngineNotifyImpl::MediaEngineNotifyImpl() = default;
MediaEngineNotifyImpl::~MediaEngineNotifyImpl() = default;
HRESULT MediaEngineNotifyImpl::RuntimeClassInitialize(
ErrorCB error_cb,
EndedCB ended_cb,
DurationChangedCB duration_changed_cb,
BufferingStateChangedCB buffering_state_changed_cb,
VideoNaturalSizeChangedCB video_natural_size_changed_cb) {
DVLOG(1) << __func__ << ": this=" << this;
error_cb_ = std::move(error_cb);
ended_cb_ = std::move(ended_cb);
duration_changed_cb_ = std::move(duration_changed_cb);
buffering_state_changed_cb_ = std::move(buffering_state_changed_cb);
video_natural_size_changed_cb_ = std::move(video_natural_size_changed_cb);
return S_OK;
}
// |param1| and |param2|'s meaning depends on the |event_code| from
// https://docs.microsoft.com/en-us/windows/win32/api/mfmediaengine/ne-mfmediaengine-mf_media_engine_event
// This method always return S_OK. Even for error |event_code| because we
// successfully handled the event.
HRESULT MediaEngineNotifyImpl::EventNotify(DWORD event_code,
DWORD_PTR param1,
DWORD param2) {
DVLOG(3) << __func__ << ": this=" << this << ",eventCode=" << event_code
<< ",param1=" << static_cast<unsigned>(param1)
<< ",param2=" << static_cast<unsigned>(param2);
base::AutoLock lock(lock_);
if (has_shutdown_)
return S_OK;
switch (static_cast<MF_MEDIA_ENGINE_EVENT>(event_code)) {
case MF_MEDIA_ENGINE_EVENT_ERROR: {
// |param1| - A member of the MF_MEDIA_ENGINE_ERR enumeration.
// |param2| - An HRESULT error code, or zero.
MF_MEDIA_ENGINE_ERR error = static_cast<MF_MEDIA_ENGINE_ERR>(param1);
DLOG(ERROR) << __func__ << ": error=" << error << ",hr=" << param2;
error_cb_.Run(MediaEngineStatusToPipelineStatus(error));
break;
}
case MF_MEDIA_ENGINE_EVENT_ENDED:
ended_cb_.Run();
break;
case MF_MEDIA_ENGINE_EVENT_DURATIONCHANGE:
duration_changed_cb_.Run();
break;
case MF_MEDIA_ENGINE_EVENT_FORMATCHANGE:
video_natural_size_changed_cb_.Run();
break;
case MF_MEDIA_ENGINE_EVENT_LOADEDDATA:
video_natural_size_changed_cb_.Run();
FALLTHROUGH;
case MF_MEDIA_ENGINE_EVENT_PLAYING:
buffering_state_changed_cb_.Run(
BufferingState::BUFFERING_HAVE_ENOUGH,
BufferingStateChangeReason::BUFFERING_CHANGE_REASON_UNKNOWN);
break;
case MF_MEDIA_ENGINE_EVENT_WAITING:
buffering_state_changed_cb_.Run(
BufferingState::BUFFERING_HAVE_NOTHING,
BufferingStateChangeReason::BUFFERING_CHANGE_REASON_UNKNOWN);
break;
default:
DVLOG(3) << __func__ << ": this=" << this
<< ", unhandled event_code=" << event_code;
break;
}
return S_OK;
}
void MediaEngineNotifyImpl::Shutdown() {
DVLOG(1) << __func__ << ": this=" << this;
base::AutoLock lock(lock_);
has_shutdown_ = true;
}
} // namespace media
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_RENDERERS_WIN_MEDIA_ENGINE_NOTIFY_IMPL_H_
#define MEDIA_RENDERERS_WIN_MEDIA_ENGINE_NOTIFY_IMPL_H_
#include <mfmediaengine.h>
#include <wrl.h>
#include "base/callback.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "media/base/buffering_state.h"
#include "media/base/pipeline_status.h"
namespace media {
using ErrorCB = base::RepeatingCallback<void(PipelineStatus)>;
using EndedCB = base::RepeatingClosure;
using DurationChangedCB = base::RepeatingClosure;
using BufferingStateChangedCB =
base::RepeatingCallback<void(BufferingState, BufferingStateChangeReason)>;
using VideoNaturalSizeChangedCB = base::RepeatingClosure;
// Implements IMFMediaEngineNotify required by IMFMediaEngine
// (https://docs.microsoft.com/en-us/windows/win32/api/mfmediaengine/nn-mfmediaengine-imfmediaengine).
//
class MediaEngineNotifyImpl
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<
Microsoft::WRL::RuntimeClassType::ClassicCom>,
IMFMediaEngineNotify> {
public:
MediaEngineNotifyImpl();
~MediaEngineNotifyImpl() override;
HRESULT RuntimeClassInitialize(
ErrorCB error_cb,
EndedCB ended_cb,
DurationChangedCB duration_changed_cb,
BufferingStateChangedCB buffering_state_changed_cb,
VideoNaturalSizeChangedCB video_natural_size_changed_cb);
// IMFMediaEngineNotify implementation.
IFACEMETHODIMP EventNotify(DWORD event_code,
DWORD_PTR param1,
DWORD param2) override;
void Shutdown();
private:
// Callbacks are called on the MF threadpool thread and the creator of this
// object must make sure the callbacks are safe to be called on that thread,
// e.g. using BindToCurrentLoop().
ErrorCB error_cb_;
EndedCB ended_cb_;
DurationChangedCB duration_changed_cb_;
BufferingStateChangedCB buffering_state_changed_cb_;
VideoNaturalSizeChangedCB video_natural_size_changed_cb_;
// EventNotify is invoked from MF threadpool thread where the callbacks are
// called.
// Shutdown is invoked from media stack thread. When this object is shutting
// down, callbacks should not be called.
base::Lock lock_;
bool has_shutdown_ GUARDED_BY(lock_) = false;
};
} // namespace media
#endif // MEDIA_RENDERERS_WIN_MEDIA_ENGINE_NOTIFY_IMPL_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment