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 #include "media/base/win/mf_helpers.h"
8
9 namespace media {
10
11 namespace {
12
13 #define ENUM_TO_STRING(enum) \
14 case enum: \
15 return #enum
16
MediaEngineEventToString(MF_MEDIA_ENGINE_EVENT event)17 std::string MediaEngineEventToString(MF_MEDIA_ENGINE_EVENT event) {
18 switch (event) {
19 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_LOADSTART);
20 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_PROGRESS);
21 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_SUSPEND);
22 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_ABORT);
23 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_ERROR);
24 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_EMPTIED);
25 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_STALLED);
26 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_PLAY);
27 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_PAUSE);
28 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_LOADEDMETADATA);
29 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_LOADEDDATA);
30 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_WAITING);
31 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_PLAYING);
32 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_CANPLAY);
33 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_CANPLAYTHROUGH);
34 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_SEEKING);
35 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_SEEKED);
36 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_TIMEUPDATE);
37 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_ENDED);
38 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_RATECHANGE);
39 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_DURATIONCHANGE);
40 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_VOLUMECHANGE);
41 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_FORMATCHANGE);
42 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_PURGEQUEUEDEVENTS);
43 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_TIMELINE_MARKER);
44 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_BALANCECHANGE);
45 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_DOWNLOADCOMPLETE);
46 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_BUFFERINGSTARTED);
47 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_BUFFERINGENDED);
48 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_FRAMESTEPCOMPLETED);
49 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_NOTIFYSTABLESTATE);
50 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_FIRSTFRAMEREADY);
51 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_TRACKSCHANGE);
52 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_OPMINFO);
53 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_RESOURCELOST);
54 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_DELAYLOADEVENT_CHANGED);
55 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_STREAMRENDERINGERROR);
56 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_SUPPORTEDRATES_CHANGED);
57 ENUM_TO_STRING(MF_MEDIA_ENGINE_EVENT_AUDIOENDPOINTCHANGE);
58 default:
59 return "Unknown MF_MEDIA_ENGINE_EVENT";
60 }
61 }
62
63 #undef ENUM_TO_STRING
64
MediaEngineStatusToPipelineStatus(MF_MEDIA_ENGINE_ERR media_engine_status)65 PipelineStatus MediaEngineStatusToPipelineStatus(
66 MF_MEDIA_ENGINE_ERR media_engine_status) {
67 switch (media_engine_status) {
68 case MF_MEDIA_ENGINE_ERR_NOERROR:
69 return PipelineStatus::PIPELINE_OK;
70 case MF_MEDIA_ENGINE_ERR_ABORTED:
71 return PipelineStatus::PIPELINE_ERROR_ABORT;
72 case MF_MEDIA_ENGINE_ERR_NETWORK:
73 return PipelineStatus::PIPELINE_ERROR_NETWORK;
74 case MF_MEDIA_ENGINE_ERR_DECODE:
75 FALLTHROUGH;
76 case MF_MEDIA_ENGINE_ERR_ENCRYPTED:
77 return PipelineStatus::PIPELINE_ERROR_DECODE;
78 case MF_MEDIA_ENGINE_ERR_SRC_NOT_SUPPORTED:
79 return PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN;
80 default:
81 NOTREACHED();
82 return PipelineStatus::PIPELINE_ERROR_INVALID_STATE;
83 }
84 }
85
86 } // namespace
87
88 MediaEngineNotifyImpl::MediaEngineNotifyImpl() = default;
89 MediaEngineNotifyImpl::~MediaEngineNotifyImpl() = default;
90
RuntimeClassInitialize(ErrorCB error_cb,EndedCB ended_cb,BufferingStateChangedCB buffering_state_changed_cb,VideoNaturalSizeChangedCB video_natural_size_changed_cb,TimeUpdateCB time_update_cb)91 HRESULT MediaEngineNotifyImpl::RuntimeClassInitialize(
92 ErrorCB error_cb,
93 EndedCB ended_cb,
94 BufferingStateChangedCB buffering_state_changed_cb,
95 VideoNaturalSizeChangedCB video_natural_size_changed_cb,
96 TimeUpdateCB time_update_cb) {
97 DVLOG_FUNC(1);
98
99 error_cb_ = std::move(error_cb);
100 ended_cb_ = std::move(ended_cb);
101 buffering_state_changed_cb_ = std::move(buffering_state_changed_cb);
102 video_natural_size_changed_cb_ = std::move(video_natural_size_changed_cb);
103 time_update_cb_ = std::move(time_update_cb);
104 return S_OK;
105 }
106
107 // |param1| and |param2|'s meaning depends on the |event_code| from
108 // https://docs.microsoft.com/en-us/windows/win32/api/mfmediaengine/ne-mfmediaengine-mf_media_engine_event
109 // This method always return S_OK. Even for error |event_code| because we
110 // successfully handled the event.
EventNotify(DWORD event_code,DWORD_PTR param1,DWORD param2)111 HRESULT MediaEngineNotifyImpl::EventNotify(DWORD event_code,
112 DWORD_PTR param1,
113 DWORD param2) {
114 auto event = static_cast<MF_MEDIA_ENGINE_EVENT>(event_code);
115 DVLOG_FUNC(3) << "event=" << MediaEngineEventToString(event);
116
117 base::AutoLock lock(lock_);
118 if (has_shutdown_)
119 return S_OK;
120
121 switch (event) {
122 case MF_MEDIA_ENGINE_EVENT_ERROR: {
123 // |param1| - A member of the MF_MEDIA_ENGINE_ERR enumeration.
124 // |param2| - An HRESULT error code, or zero.
125 MF_MEDIA_ENGINE_ERR error = static_cast<MF_MEDIA_ENGINE_ERR>(param1);
126 LOG(ERROR) << __func__ << ": error=" << error
127 << ", hr=" << PrintHr(param2);
128 error_cb_.Run(MediaEngineStatusToPipelineStatus(error));
129 break;
130 }
131 case MF_MEDIA_ENGINE_EVENT_ENDED:
132 ended_cb_.Run();
133 break;
134 case MF_MEDIA_ENGINE_EVENT_FORMATCHANGE:
135 video_natural_size_changed_cb_.Run();
136 break;
137 case MF_MEDIA_ENGINE_EVENT_LOADEDDATA:
138 video_natural_size_changed_cb_.Run();
139 FALLTHROUGH;
140 case MF_MEDIA_ENGINE_EVENT_PLAYING:
141 buffering_state_changed_cb_.Run(
142 BufferingState::BUFFERING_HAVE_ENOUGH,
143 BufferingStateChangeReason::BUFFERING_CHANGE_REASON_UNKNOWN);
144 break;
145 case MF_MEDIA_ENGINE_EVENT_WAITING:
146 buffering_state_changed_cb_.Run(
147 BufferingState::BUFFERING_HAVE_NOTHING,
148 BufferingStateChangeReason::BUFFERING_CHANGE_REASON_UNKNOWN);
149 break;
150 case MF_MEDIA_ENGINE_EVENT_TIMEUPDATE:
151 time_update_cb_.Run();
152 break;
153
154 default:
155 DVLOG_FUNC(2) << "Unhandled event=" << MediaEngineEventToString(event);
156 break;
157 }
158 return S_OK;
159 }
160
Shutdown()161 void MediaEngineNotifyImpl::Shutdown() {
162 DVLOG_FUNC(1);
163
164 base::AutoLock lock(lock_);
165 has_shutdown_ = true;
166 }
167
168 } // namespace media
169