1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "media/renderers/win/media_engine_notify_impl.h"
6 
7 namespace media {
8 
9 namespace {
10 
MediaEngineStatusToPipelineStatus(MF_MEDIA_ENGINE_ERR media_engine_status)11 PipelineStatus MediaEngineStatusToPipelineStatus(
12     MF_MEDIA_ENGINE_ERR media_engine_status) {
13   switch (media_engine_status) {
14     case MF_MEDIA_ENGINE_ERR_NOERROR:
15       return PipelineStatus::PIPELINE_OK;
16     case MF_MEDIA_ENGINE_ERR_ABORTED:
17       return PipelineStatus::PIPELINE_ERROR_ABORT;
18     case MF_MEDIA_ENGINE_ERR_NETWORK:
19       return PipelineStatus::PIPELINE_ERROR_NETWORK;
20     case MF_MEDIA_ENGINE_ERR_DECODE:
21       FALLTHROUGH;
22     case MF_MEDIA_ENGINE_ERR_ENCRYPTED:
23       return PipelineStatus::PIPELINE_ERROR_DECODE;
24     case MF_MEDIA_ENGINE_ERR_SRC_NOT_SUPPORTED:
25       return PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN;
26     default:
27       NOTREACHED();
28       return PipelineStatus::PIPELINE_ERROR_INVALID_STATE;
29   }
30 }
31 
32 }  // namespace
33 
34 MediaEngineNotifyImpl::MediaEngineNotifyImpl() = default;
35 MediaEngineNotifyImpl::~MediaEngineNotifyImpl() = default;
36 
RuntimeClassInitialize(ErrorCB error_cb,EndedCB ended_cb,DurationChangedCB duration_changed_cb,BufferingStateChangedCB buffering_state_changed_cb,VideoNaturalSizeChangedCB video_natural_size_changed_cb)37 HRESULT MediaEngineNotifyImpl::RuntimeClassInitialize(
38     ErrorCB error_cb,
39     EndedCB ended_cb,
40     DurationChangedCB duration_changed_cb,
41     BufferingStateChangedCB buffering_state_changed_cb,
42     VideoNaturalSizeChangedCB video_natural_size_changed_cb) {
43   DVLOG(1) << __func__ << ": this=" << this;
44 
45   error_cb_ = std::move(error_cb);
46   ended_cb_ = std::move(ended_cb);
47   duration_changed_cb_ = std::move(duration_changed_cb);
48   buffering_state_changed_cb_ = std::move(buffering_state_changed_cb);
49   video_natural_size_changed_cb_ = std::move(video_natural_size_changed_cb);
50   return S_OK;
51 }
52 
53 // |param1| and |param2|'s meaning depends on the |event_code| from
54 // https://docs.microsoft.com/en-us/windows/win32/api/mfmediaengine/ne-mfmediaengine-mf_media_engine_event
55 // This method always return S_OK. Even for error |event_code| because we
56 // successfully handled the event.
EventNotify(DWORD event_code,DWORD_PTR param1,DWORD param2)57 HRESULT MediaEngineNotifyImpl::EventNotify(DWORD event_code,
58                                            DWORD_PTR param1,
59                                            DWORD param2) {
60   DVLOG(3) << __func__ << ": this=" << this << ",eventCode=" << event_code
61            << ",param1=" << static_cast<unsigned>(param1)
62            << ",param2=" << static_cast<unsigned>(param2);
63 
64   base::AutoLock lock(lock_);
65   if (has_shutdown_)
66     return S_OK;
67 
68   switch (static_cast<MF_MEDIA_ENGINE_EVENT>(event_code)) {
69     case MF_MEDIA_ENGINE_EVENT_ERROR: {
70       // |param1| - A member of the MF_MEDIA_ENGINE_ERR enumeration.
71       // |param2| - An HRESULT error code, or zero.
72       MF_MEDIA_ENGINE_ERR error = static_cast<MF_MEDIA_ENGINE_ERR>(param1);
73       DLOG(ERROR) << __func__ << ": error=" << error << ",hr=" << param2;
74       error_cb_.Run(MediaEngineStatusToPipelineStatus(error));
75       break;
76     }
77     case MF_MEDIA_ENGINE_EVENT_ENDED:
78       ended_cb_.Run();
79       break;
80     case MF_MEDIA_ENGINE_EVENT_DURATIONCHANGE:
81       duration_changed_cb_.Run();
82       break;
83     case MF_MEDIA_ENGINE_EVENT_FORMATCHANGE:
84       video_natural_size_changed_cb_.Run();
85       break;
86     case MF_MEDIA_ENGINE_EVENT_LOADEDDATA:
87       video_natural_size_changed_cb_.Run();
88       FALLTHROUGH;
89     case MF_MEDIA_ENGINE_EVENT_PLAYING:
90       buffering_state_changed_cb_.Run(
91           BufferingState::BUFFERING_HAVE_ENOUGH,
92           BufferingStateChangeReason::BUFFERING_CHANGE_REASON_UNKNOWN);
93       break;
94     case MF_MEDIA_ENGINE_EVENT_WAITING:
95       buffering_state_changed_cb_.Run(
96           BufferingState::BUFFERING_HAVE_NOTHING,
97           BufferingStateChangeReason::BUFFERING_CHANGE_REASON_UNKNOWN);
98       break;
99     default:
100       DVLOG(3) << __func__ << ": this=" << this
101                << ", unhandled event_code=" << event_code;
102       break;
103   }
104   return S_OK;
105 }
106 
Shutdown()107 void MediaEngineNotifyImpl::Shutdown() {
108   DVLOG(1) << __func__ << ": this=" << this;
109 
110   base::AutoLock lock(lock_);
111   has_shutdown_ = true;
112 }
113 
114 }  // namespace media
115