1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
|
// Copyright 2013 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_BLINK_WEBMEDIAPLAYER_IMPL_H_
#define MEDIA_BLINK_WEBMEDIAPLAYER_IMPL_H_
#include <stdint.h>
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "media/base/media_tracks.h"
#include "media/base/pipeline_impl.h"
#include "media/base/renderer_factory.h"
#include "media/base/surface_manager.h"
#include "media/base/text_track.h"
#include "media/blink/buffered_data_source.h"
#include "media/blink/buffered_data_source_host_impl.h"
#include "media/blink/media_blink_export.h"
#include "media/blink/multibuffer_data_source.h"
#include "media/blink/video_frame_compositor.h"
#include "media/blink/webmediaplayer_delegate.h"
#include "media/blink/webmediaplayer_params.h"
#include "media/blink/webmediaplayer_util.h"
#include "media/filters/pipeline_controller.h"
#include "media/renderers/skcanvas_video_renderer.h"
#include "third_party/WebKit/public/platform/WebAudioSourceProvider.h"
#include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "url/gurl.h"
#if defined(OS_ANDROID) // WMPI_CAST
// Delete this file when WMPI_CAST is no longer needed.
#include "media/blink/webmediaplayer_cast_android.h"
#endif
namespace blink {
class WebLocalFrame;
class WebMediaPlayerClient;
class WebMediaPlayerEncryptedMediaClient;
}
namespace base {
class SingleThreadTaskRunner;
class TaskRunner;
}
namespace cc_blink {
class WebLayerImpl;
}
namespace gpu {
namespace gles2 {
class GLES2Interface;
}
}
namespace media {
class AudioHardwareConfig;
class ChunkDemuxer;
class GpuVideoAcceleratorFactories;
class MediaLog;
class UrlIndex;
class VideoFrameCompositor;
class WebAudioSourceProviderImpl;
class WebMediaPlayerDelegate;
class WebTextTrackImpl;
// The canonical implementation of blink::WebMediaPlayer that's backed by
// Pipeline. Handles normal resource loading, Media Source, and
// Encrypted Media.
class MEDIA_BLINK_EXPORT WebMediaPlayerImpl
: public NON_EXPORTED_BASE(blink::WebMediaPlayer),
public NON_EXPORTED_BASE(WebMediaPlayerDelegate::Observer),
public base::SupportsWeakPtr<WebMediaPlayerImpl> {
public:
// Constructs a WebMediaPlayer implementation using Chromium's media stack.
// |delegate| may be null. |renderer_factory| must not be null.
WebMediaPlayerImpl(
blink::WebLocalFrame* frame,
blink::WebMediaPlayerClient* client,
blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
base::WeakPtr<WebMediaPlayerDelegate> delegate,
scoped_ptr<RendererFactory> renderer_factory,
linked_ptr<UrlIndex> url_index,
const WebMediaPlayerParams& params);
~WebMediaPlayerImpl() override;
void load(LoadType load_type,
const blink::WebURL& url,
CORSMode cors_mode) override;
// Playback controls.
void play() override;
void pause() override;
bool supportsSave() const override;
void seek(double seconds) override;
void setRate(double rate) override;
void setVolume(double volume) override;
void setSinkId(const blink::WebString& sink_id,
const blink::WebSecurityOrigin& security_origin,
blink::WebSetSinkIdCallbacks* web_callback) override;
void setPreload(blink::WebMediaPlayer::Preload preload) override;
void setBufferingStrategy(
blink::WebMediaPlayer::BufferingStrategy buffering_strategy) override;
blink::WebTimeRanges buffered() const override;
blink::WebTimeRanges seekable() const override;
// paint() the current video frame into |canvas|. This is used to support
// various APIs and functionalities, including but not limited to: <canvas>,
// WebGL texImage2D, ImageBitmap, printing and capturing capabilities.
void paint(blink::WebCanvas* canvas,
const blink::WebRect& rect,
unsigned char alpha,
SkXfermode::Mode mode) override;
// True if the loaded media has a playable video/audio track.
bool hasVideo() const override;
bool hasAudio() const override;
// Dimensions of the video.
blink::WebSize naturalSize() const override;
// Getters of playback state.
bool paused() const override;
bool seeking() const override;
double duration() const override;
virtual double timelineOffset() const;
double currentTime() const override;
// Internal states of loading and network.
// TODO(hclam): Ask the pipeline about the state rather than having reading
// them from members which would cause race conditions.
blink::WebMediaPlayer::NetworkState getNetworkState() const override;
blink::WebMediaPlayer::ReadyState getReadyState() const override;
blink::WebString getErrorMessage() override;
bool didLoadingProgress() override;
bool hasSingleSecurityOrigin() const override;
bool didPassCORSAccessCheck() const override;
double mediaTimeForTimeValue(double timeValue) const override;
unsigned decodedFrameCount() const override;
unsigned droppedFrameCount() const override;
size_t audioDecodedByteCount() const override;
size_t videoDecodedByteCount() const override;
bool copyVideoTextureToPlatformTexture(gpu::gles2::GLES2Interface* gl,
unsigned int texture,
unsigned int internal_format,
unsigned int type,
bool premultiply_alpha,
bool flip_y) override;
blink::WebAudioSourceProvider* getAudioSourceProvider() override;
void setContentDecryptionModule(
blink::WebContentDecryptionModule* cdm,
blink::WebContentDecryptionModuleResult result) override;
bool supportsOverlayFullscreenVideo() override;
void enteredFullscreen() override;
void exitedFullscreen() override;
// WebMediaPlayerDelegate::Observer implementation.
void OnHidden() override;
void OnShown() override;
void OnSuspendRequested(bool must_suspend) override;
void OnPlay() override;
void OnPause() override;
void OnVolumeMultiplierUpdate(double multiplier) override;
#if defined(OS_ANDROID) // WMPI_CAST
bool isRemote() const override;
void requestRemotePlayback() override;
void requestRemotePlaybackControl() override;
void SetMediaPlayerManager(
RendererMediaPlayerManagerInterface* media_player_manager);
void OnRemotePlaybackEnded();
void OnDisconnectedFromRemoteDevice(double t);
void SuspendForRemote();
void DisplayCastFrameAfterSuspend(const scoped_refptr<VideoFrame>& new_frame,
PipelineStatus status);
gfx::Size GetCanvasSize() const;
void SetDeviceScaleFactor(float scale_factor);
#endif
// Called from WebMediaPlayerCast.
// TODO(hubbe): WMPI_CAST make private.
void OnPipelineSeeked(bool time_updated);
// Distinct states that |delegate_| can be in.
// TODO(sandersd): This should move into WebMediaPlayerDelegate.
// (Public for testing.)
enum class DelegateState {
GONE,
PLAYING,
PAUSED,
PAUSED_BUT_NOT_IDLE,
ENDED,
};
// Playback state variables computed together in UpdatePlayState().
// (Public for testing.)
struct PlayState {
DelegateState delegate_state;
bool is_memory_reporting_enabled;
bool is_suspended;
};
private:
friend class WebMediaPlayerImplTest;
void OnPipelineSuspended();
void OnPipelineEnded();
void OnPipelineError(PipelineStatus error);
void OnPipelineMetadata(PipelineMetadata metadata);
void OnPipelineBufferingStateChanged(BufferingState buffering_state);
void OnDemuxerOpened();
void OnAddTextTrack(const TextTrackConfig& config,
const AddTextTrackDoneCB& done_cb);
// Actually seek. Avoids causing |should_notify_time_changed_| to be set when
// |time_updated| is false.
void DoSeek(base::TimeDelta time, bool time_updated);
// Ask for the renderer to be restarted (destructed and recreated).
void ScheduleRestart();
// Called after |defer_load_cb_| has decided to allow the load. If
// |defer_load_cb_| is null this is called immediately.
void DoLoad(LoadType load_type,
const blink::WebURL& url,
CORSMode cors_mode);
// Called after asynchronous initialization of a data source completed.
void DataSourceInitialized(bool success);
// Called when the data source is downloading or paused.
void NotifyDownloading(bool is_downloading);
void OnSurfaceRequested(const SurfaceCreatedCB& surface_created_cb);
// Creates a Renderer via the |renderer_factory_|.
scoped_ptr<Renderer> CreateRenderer();
// Finishes starting the pipeline due to a call to load().
void StartPipeline();
// Helpers that set the network/ready state and notifies the client if
// they've changed.
void SetNetworkState(blink::WebMediaPlayer::NetworkState state);
void SetReadyState(blink::WebMediaPlayer::ReadyState state);
// Gets the duration value reported by the pipeline.
double GetPipelineDuration() const;
// Callbacks from |pipeline_| that are forwarded to |client_|.
void OnDurationChanged();
void OnNaturalSizeChanged(gfx::Size size);
void OnOpacityChanged(bool opaque);
// Called by VideoRendererImpl on its internal thread with the new frame to be
// painted.
void FrameReady(const scoped_refptr<VideoFrame>& frame);
// Returns the current video frame from |compositor_|. Blocks until the
// compositor can return the frame.
scoped_refptr<VideoFrame> GetCurrentFrameFromCompositor();
// Called when the demuxer encounters encrypted streams.
void OnEncryptedMediaInitData(EmeInitDataType init_data_type,
const std::vector<uint8_t>& init_data);
// Called when the FFmpegDemuxer encounters new media tracks. This is only
// invoked when using FFmpegDemuxer, since MSE/ChunkDemuxer handle media
// tracks separately in WebSourceBufferImpl.
void OnFFmpegMediaTracksUpdated(scoped_ptr<MediaTracks> tracks);
// Called when a decoder detects that the key needed to decrypt the stream
// is not available.
void OnWaitingForDecryptionKey();
// Sets |cdm_context| on the pipeline and fires |cdm_attached_cb| when done.
// Parameter order is reversed for easy binding.
void SetCdm(const CdmAttachedCB& cdm_attached_cb, CdmContext* cdm_context);
// Called when a CDM has been attached to the |pipeline_|.
void OnCdmAttached(bool success);
// Inspects the current playback state and:
// - notifies |delegate_|,
// - toggles the memory usage reporting timer, and
// - toggles suspend/resume as necessary.
//
// This method should be called any time its dependent values change. These
// are:
// - isRemote(),
// - hasVideo(),
// - delegate_->IsHidden(),
// - network_state_, ready_state_,
// - is_idle_, must_suspend_,
// - paused_, ended_,
// - pending_suspend_resume_cycle_.
void UpdatePlayState();
// Methods internal to UpdatePlayState().
PlayState UpdatePlayState_ComputePlayState(bool is_remote,
bool is_backgrounded);
void SetDelegateState(DelegateState new_state);
void SetMemoryReportingState(bool is_memory_reporting_enabled);
void SetSuspendState(bool is_suspended);
// Called at low frequency to tell external observers how much memory we're
// using for video playback. Called by |memory_usage_reporting_timer_|.
// Memory usage reporting is done in two steps, because |demuxer_| must be
// accessed on the media thread.
void ReportMemoryUsage();
void FinishMemoryUsageReport(int64_t demuxer_memory_usage);
blink::WebLocalFrame* frame_;
// The playback state last reported to |delegate_|, to avoid setting duplicate
// states. (Which can have undesired effects like resetting the idle timer.)
DelegateState delegate_state_;
// Set when OnSuspendRequested() is called with |must_suspend| unset.
bool is_idle_;
// Set when OnSuspendRequested() is called with |must_suspend| set.
bool must_suspend_;
blink::WebMediaPlayer::NetworkState network_state_;
blink::WebMediaPlayer::ReadyState ready_state_;
blink::WebMediaPlayer::ReadyState highest_ready_state_;
// Preload state for when |data_source_| is created after setPreload().
BufferedDataSource::Preload preload_;
// Buffering strategy for when |data_source_| is created after
// setBufferingStrategy().
BufferedDataSource::BufferingStrategy buffering_strategy_;
// Task runner for posting tasks on Chrome's main thread. Also used
// for DCHECKs so methods calls won't execute in the wrong thread.
const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
scoped_refptr<base::TaskRunner> worker_task_runner_;
scoped_refptr<MediaLog> media_log_;
// |pipeline_controller_| references |pipeline_| and therefore must be
// constructed after and destructed before |pipeline_|.
PipelineImpl pipeline_;
PipelineController pipeline_controller_;
// The LoadType passed in the |load_type| parameter of the load() call.
LoadType load_type_;
// Cache of metadata for answering hasAudio(), hasVideo(), and naturalSize().
PipelineMetadata pipeline_metadata_;
// Whether the video is known to be opaque or not.
bool opaque_;
// Playback state.
//
// TODO(scherkus): we have these because Pipeline favours the simplicity of a
// single "playback rate" over worrying about paused/stopped etc... It forces
// all clients to manage the pause+playback rate externally, but is that
// really a bad thing?
//
// TODO(scherkus): since SetPlaybackRate(0) is asynchronous and we don't want
// to hang the render thread during pause(), we record the time at the same
// time we pause and then return that value in currentTime(). Otherwise our
// clock can creep forward a little bit while the asynchronous
// SetPlaybackRate(0) is being executed.
double playback_rate_;
// Set while paused. |paused_time_| is only valid when |paused_| is true.
bool paused_;
base::TimeDelta paused_time_;
// Set when starting, seeking, and resuming (all of which require a Pipeline
// seek). |seek_time_| is only valid when |seeking_| is true.
bool seeking_;
base::TimeDelta seek_time_;
// Set when doing a restart (a suspend and resume in sequence) of the pipeline
// in order to destruct and reinitialize the decoders. This is separate from
// |pending_resume_| and |pending_suspend_| because they can be elided in
// certain cases, whereas for a restart they must happen.
// TODO(sandersd,watk): Create a simpler interface for a pipeline restart.
bool pending_suspend_resume_cycle_;
// TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
// see http://crbug.com/409280
bool ended_;
// Tracks whether to issue time changed notifications during buffering state
// changes.
bool should_notify_time_changed_;
bool fullscreen_;
// Whether the current decoder requires a restart on fullscreen transitions.
bool decoder_requires_restart_for_fullscreen_;
// What to return from supportsOverlayFullscreenVideo(). This is usually
// equal to |decoder_requires_restart_for_fullscreen_| except that it doesn't
// change while we're in fullscreen. See supportsOverlayFullscreenVideo().
bool supports_overlay_fullscreen_video_;
blink::WebMediaPlayerClient* client_;
blink::WebMediaPlayerEncryptedMediaClient* encrypted_client_;
// WebMediaPlayer notifies the |delegate_| of playback state changes using
// |delegate_id_|; an id provided after registering with the delegate. The
// WebMediaPlayer may also receive directives (play, pause) from the delegate
// via the WebMediaPlayerDelegate::Observer interface after registration.
base::WeakPtr<WebMediaPlayerDelegate> delegate_;
int delegate_id_;
WebMediaPlayerParams::DeferLoadCB defer_load_cb_;
WebMediaPlayerParams::Context3DCB context_3d_cb_;
// Members for notifying upstream clients about internal memory usage. The
// |adjust_allocated_memory_cb_| must only be called on |main_task_runner_|.
base::RepeatingTimer memory_usage_reporting_timer_;
WebMediaPlayerParams::AdjustAllocatedMemoryCB adjust_allocated_memory_cb_;
int64_t last_reported_memory_usage_;
// Routes audio playback to either AudioRendererSink or WebAudio.
scoped_refptr<WebAudioSourceProviderImpl> audio_source_provider_;
bool supports_save_;
// These two are mutually exclusive:
// |data_source_| is used for regular resource loads.
// |chunk_demuxer_| is used for Media Source resource loads.
//
// |demuxer_| will contain the appropriate demuxer based on which resource
// load strategy we're using.
scoped_ptr<BufferedDataSourceInterface> data_source_;
scoped_ptr<Demuxer> demuxer_;
ChunkDemuxer* chunk_demuxer_;
BufferedDataSourceHostImpl buffered_data_source_host_;
linked_ptr<UrlIndex> url_index_;
// Video rendering members.
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
VideoFrameCompositor* compositor_; // Deleted on |compositor_task_runner_|.
SkCanvasVideoRenderer skcanvas_video_renderer_;
// The compositor layer for displaying the video content when using composited
// playback.
scoped_ptr<cc_blink::WebLayerImpl> video_weblayer_;
scoped_ptr<blink::WebContentDecryptionModuleResult> set_cdm_result_;
// Whether a CDM has been successfully attached.
bool is_cdm_attached_;
#if defined(OS_ANDROID) // WMPI_CAST
WebMediaPlayerCast cast_impl_;
#endif
// The last volume received by setVolume() and the last volume multiplier from
// OnVolumeMultiplierUpdate(). The multiplier is typical 1.0, but may be less
// if the WebMediaPlayerDelegate has requested a volume reduction (ducking)
// for a transient sound. Playout volume is derived by volume * multiplier.
double volume_;
double volume_multiplier_;
scoped_ptr<RendererFactory> renderer_factory_;
// For requesting surfaces on behalf of the Android H/W decoder in fullscreen.
// This will be null everywhere but Android.
SurfaceManager* surface_manager_;
// Suppresses calls to OnPipelineError() after destruction / shutdown has been
// started; prevents us from spuriously logging errors that are transient or
// unimportant.
bool suppress_destruction_errors_;
// State indicating if it's okay to suspend or not. Updated on the first time
// OnSuspendRequested() is called. If the state is UNKNOWN, the current frame
// from the compositor will be queried to see if suspend is supported; the
// state will be set to YES or NO respectively if a frame is available.
enum class CanSuspendState { UNKNOWN, YES, NO };
CanSuspendState can_suspend_state_;
DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl);
};
} // namespace media
#endif // MEDIA_BLINK_WEBMEDIAPLAYER_IMPL_H_
|