1// Copyright 2013 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 "content/browser/android/browser_media_player_manager.h"
6
7#include "content/browser/android/content_view_core_impl.h"
8#include "content/browser/android/media_resource_getter_impl.h"
9#include "content/browser/web_contents/web_contents_view_android.h"
10#include "content/common/media/media_player_messages_android.h"
11#include "content/public/browser/browser_context.h"
12#include "content/public/browser/render_process_host.h"
13#include "content/public/browser/render_view_host.h"
14#include "content/public/browser/storage_partition.h"
15#include "content/public/browser/web_contents.h"
16#include "media/base/android/media_drm_bridge.h"
17
18using media::MediaDrmBridge;
19using media::MediaPlayerAndroid;
20
21// Threshold on the number of media players per renderer before we start
22// attempting to release inactive media players.
23static const int kMediaPlayerThreshold = 1;
24
25namespace media {
26
27static MediaPlayerManager::FactoryFunction g_factory_function = NULL;
28
29// static
30CONTENT_EXPORT void MediaPlayerManager::RegisterFactoryFunction(
31    FactoryFunction factory_function) {
32  g_factory_function = factory_function;
33}
34
35// static
36media::MediaPlayerManager* MediaPlayerManager::Create(
37    content::RenderViewHost* render_view_host) {
38  if (g_factory_function)
39    return g_factory_function(render_view_host);
40  return new content::BrowserMediaPlayerManager(render_view_host);
41}
42
43}  // namespace media
44
45namespace content {
46
47BrowserMediaPlayerManager::BrowserMediaPlayerManager(
48    RenderViewHost* render_view_host)
49    : RenderViewHostObserver(render_view_host),
50      fullscreen_player_id_(-1),
51      web_contents_(WebContents::FromRenderViewHost(render_view_host)) {
52}
53
54BrowserMediaPlayerManager::~BrowserMediaPlayerManager() {}
55
56bool BrowserMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) {
57  bool handled = true;
58  IPC_BEGIN_MESSAGE_MAP(BrowserMediaPlayerManager, msg)
59    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_EnterFullscreen, OnEnterFullscreen)
60    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_ExitFullscreen, OnExitFullscreen)
61    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Initialize, OnInitialize)
62    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Start, OnStart)
63    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Seek, OnSeek)
64    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Pause, OnPause)
65    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_SetVolume, OnSetVolume)
66    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_Release, OnReleaseResources)
67    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyMediaPlayer, OnDestroyPlayer)
68    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DestroyAllMediaPlayers,
69                        DestroyAllMediaPlayers)
70    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DemuxerReady,
71                        OnDemuxerReady)
72    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_ReadFromDemuxerAck,
73                        OnReadFromDemuxerAck)
74    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_DurationChanged,
75                        OnDurationChanged)
76    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_MediaSeekRequestAck,
77                        OnMediaSeekRequestAck)
78    IPC_MESSAGE_HANDLER(MediaKeysHostMsg_InitializeCDM,
79                        OnInitializeCDM)
80    IPC_MESSAGE_HANDLER(MediaKeysHostMsg_GenerateKeyRequest,
81                        OnGenerateKeyRequest)
82    IPC_MESSAGE_HANDLER(MediaKeysHostMsg_AddKey, OnAddKey)
83    IPC_MESSAGE_HANDLER(MediaKeysHostMsg_CancelKeyRequest,
84                        OnCancelKeyRequest)
85#if defined(GOOGLE_TV)
86    IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_NotifyExternalSurface,
87                        OnNotifyExternalSurface)
88#endif
89    IPC_MESSAGE_UNHANDLED(handled = false)
90  IPC_END_MESSAGE_MAP()
91  return handled;
92}
93
94void BrowserMediaPlayerManager::FullscreenPlayerPlay() {
95  MediaPlayerAndroid* player = GetFullscreenPlayer();
96  if (player) {
97    player->Start();
98    Send(new MediaPlayerMsg_DidMediaPlayerPlay(
99        routing_id(), fullscreen_player_id_));
100  }
101}
102
103void BrowserMediaPlayerManager::FullscreenPlayerPause() {
104  MediaPlayerAndroid* player = GetFullscreenPlayer();
105  if (player) {
106    player->Pause();
107    Send(new MediaPlayerMsg_DidMediaPlayerPause(
108        routing_id(), fullscreen_player_id_));
109  }
110}
111
112void BrowserMediaPlayerManager::FullscreenPlayerSeek(int msec) {
113  MediaPlayerAndroid* player = GetFullscreenPlayer();
114  if (player)
115    player->SeekTo(base::TimeDelta::FromMilliseconds(msec));
116}
117
118void BrowserMediaPlayerManager::ExitFullscreen(bool release_media_player) {
119  Send(new MediaPlayerMsg_DidExitFullscreen(
120      routing_id(), fullscreen_player_id_));
121  video_view_.reset();
122  MediaPlayerAndroid* player = GetFullscreenPlayer();
123  fullscreen_player_id_ = -1;
124  if (!player)
125    return;
126  if (release_media_player)
127    player->Release();
128  else
129    player->SetVideoSurface(gfx::ScopedJavaSurface());
130}
131
132void BrowserMediaPlayerManager::OnTimeUpdate(int player_id,
133                                             base::TimeDelta current_time) {
134  Send(new MediaPlayerMsg_MediaTimeUpdate(
135      routing_id(), player_id, current_time));
136}
137
138void BrowserMediaPlayerManager::SetVideoSurface(
139    gfx::ScopedJavaSurface surface) {
140  MediaPlayerAndroid* player = GetFullscreenPlayer();
141  if (player) {
142    player->SetVideoSurface(surface.Pass());
143    Send(new MediaPlayerMsg_DidEnterFullscreen(
144        routing_id(), player->player_id()));
145  }
146}
147
148void BrowserMediaPlayerManager::OnMediaMetadataChanged(
149    int player_id, base::TimeDelta duration, int width, int height,
150    bool success) {
151  Send(new MediaPlayerMsg_MediaMetadataChanged(
152      routing_id(), player_id, duration, width, height, success));
153  if (fullscreen_player_id_ != -1)
154    video_view_->UpdateMediaMetadata();
155}
156
157void BrowserMediaPlayerManager::OnPlaybackComplete(int player_id) {
158  Send(new MediaPlayerMsg_MediaPlaybackCompleted(routing_id(), player_id));
159  if (fullscreen_player_id_ != -1)
160    video_view_->OnPlaybackComplete();
161}
162
163void BrowserMediaPlayerManager::OnMediaInterrupted(int player_id) {
164  // Tell WebKit that the audio should be paused, then release all resources
165  Send(new MediaPlayerMsg_DidMediaPlayerPause(routing_id(), player_id));
166  OnReleaseResources(player_id);
167}
168
169void BrowserMediaPlayerManager::OnBufferingUpdate(
170    int player_id, int percentage) {
171  Send(new MediaPlayerMsg_MediaBufferingUpdate(
172      routing_id(), player_id, percentage));
173  if (fullscreen_player_id_ != -1)
174    video_view_->OnBufferingUpdate(percentage);
175}
176
177void BrowserMediaPlayerManager::OnSeekComplete(int player_id,
178                                               base::TimeDelta current_time) {
179  Send(new MediaPlayerMsg_MediaSeekCompleted(
180      routing_id(), player_id, current_time));
181}
182
183void BrowserMediaPlayerManager::OnError(int player_id, int error) {
184  Send(new MediaPlayerMsg_MediaError(routing_id(), player_id, error));
185  if (fullscreen_player_id_ != -1)
186    video_view_->OnMediaPlayerError(error);
187}
188
189void BrowserMediaPlayerManager::OnVideoSizeChanged(
190    int player_id, int width, int height) {
191  Send(new MediaPlayerMsg_MediaVideoSizeChanged(routing_id(), player_id,
192      width, height));
193  if (fullscreen_player_id_ != -1)
194    video_view_->OnVideoSizeChanged(width, height);
195}
196
197void BrowserMediaPlayerManager::OnReadFromDemuxer(
198    int player_id, media::DemuxerStream::Type type) {
199  Send(new MediaPlayerMsg_ReadFromDemuxer(routing_id(), player_id, type));
200}
201
202void BrowserMediaPlayerManager::RequestMediaResources(int player_id) {
203  int num_active_player = 0;
204  ScopedVector<MediaPlayerAndroid>::iterator it;
205  for (it = players_.begin(); it != players_.end(); ++it) {
206    if (!(*it)->IsPlayerReady())
207      continue;
208
209    // The player is already active, ignore it.
210    if ((*it)->player_id() == player_id)
211      return;
212    else
213      num_active_player++;
214  }
215
216  // Number of active players are less than the threshold, do nothing.
217  if (num_active_player < kMediaPlayerThreshold)
218    return;
219
220  for (it = players_.begin(); it != players_.end(); ++it) {
221    if ((*it)->IsPlayerReady() && !(*it)->IsPlaying() &&
222        fullscreen_player_id_ != (*it)->player_id()) {
223      (*it)->Release();
224      Send(new MediaPlayerMsg_MediaPlayerReleased(
225          routing_id(), (*it)->player_id()));
226    }
227  }
228}
229
230void BrowserMediaPlayerManager::ReleaseMediaResources(int player_id) {
231  // Nothing needs to be done.
232}
233
234media::MediaResourceGetter*
235BrowserMediaPlayerManager::GetMediaResourceGetter() {
236  if (!media_resource_getter_.get()) {
237    RenderProcessHost* host = render_view_host()->GetProcess();
238    BrowserContext* context = host->GetBrowserContext();
239    StoragePartition* partition = host->GetStoragePartition();
240    fileapi::FileSystemContext* file_system_context =
241        partition ? partition->GetFileSystemContext() : NULL;
242    media_resource_getter_.reset(new MediaResourceGetterImpl(
243        context, file_system_context, host->GetID(), routing_id()));
244  }
245  return media_resource_getter_.get();
246}
247
248MediaPlayerAndroid* BrowserMediaPlayerManager::GetFullscreenPlayer() {
249  return GetPlayer(fullscreen_player_id_);
250}
251
252MediaPlayerAndroid* BrowserMediaPlayerManager::GetPlayer(int player_id) {
253  for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
254      it != players_.end(); ++it) {
255    if ((*it)->player_id() == player_id)
256      return *it;
257  }
258  return NULL;
259}
260
261MediaDrmBridge* BrowserMediaPlayerManager::GetDrmBridge(int media_keys_id) {
262  for (ScopedVector<MediaDrmBridge>::iterator it = drm_bridges_.begin();
263      it != drm_bridges_.end(); ++it) {
264    if ((*it)->media_keys_id() == media_keys_id)
265      return *it;
266  }
267  return NULL;
268}
269
270void BrowserMediaPlayerManager::DestroyAllMediaPlayers() {
271  players_.clear();
272  if (fullscreen_player_id_ != -1) {
273    video_view_.reset();
274    fullscreen_player_id_ = -1;
275  }
276}
277
278void BrowserMediaPlayerManager::OnMediaSeekRequest(
279    int player_id, base::TimeDelta time_to_seek, unsigned seek_request_id) {
280  Send(new MediaPlayerMsg_MediaSeekRequest(
281      routing_id(), player_id, time_to_seek, seek_request_id));
282}
283
284void BrowserMediaPlayerManager::OnMediaConfigRequest(int player_id) {
285  Send(new MediaPlayerMsg_MediaConfigRequest(routing_id(), player_id));
286}
287
288void BrowserMediaPlayerManager::OnProtectedSurfaceRequested(int player_id) {
289  if (fullscreen_player_id_ == player_id)
290    return;
291  if (fullscreen_player_id_ != -1) {
292    // TODO(qinmin): Determine the correct error code we should report to WMPA.
293    OnError(player_id, MediaPlayerAndroid::MEDIA_ERROR_DECODE);
294    return;
295  }
296  OnEnterFullscreen(player_id);
297}
298
299void BrowserMediaPlayerManager::OnKeyAdded(int media_keys_id,
300                                           const std::string& session_id) {
301  Send(new MediaKeysMsg_KeyAdded(routing_id(), media_keys_id, session_id));
302}
303
304void BrowserMediaPlayerManager::OnKeyError(
305    int media_keys_id,
306    const std::string& session_id,
307    media::MediaKeys::KeyError error_code,
308    int system_code) {
309  Send(new MediaKeysMsg_KeyError(routing_id(), media_keys_id,
310                                 session_id, error_code, system_code));
311}
312
313void BrowserMediaPlayerManager::OnKeyMessage(
314    int media_keys_id,
315    const std::string& session_id,
316    const std::vector<uint8>& message,
317    const std::string& destination_url) {
318  Send(new MediaKeysMsg_KeyMessage(routing_id(), media_keys_id,
319                                   session_id, message, destination_url));
320}
321
322#if defined(GOOGLE_TV)
323void BrowserMediaPlayerManager::AttachExternalVideoSurface(int player_id,
324                                                           jobject surface) {
325  MediaPlayerAndroid* player = GetPlayer(player_id);
326  if (player) {
327    player->SetVideoSurface(
328        gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
329  }
330}
331
332void BrowserMediaPlayerManager::DetachExternalVideoSurface(int player_id) {
333  MediaPlayerAndroid* player = GetPlayer(player_id);
334  if (player)
335    player->SetVideoSurface(gfx::ScopedJavaSurface());
336}
337
338void BrowserMediaPlayerManager::OnNotifyExternalSurface(
339    int player_id, bool is_request, const gfx::RectF& rect) {
340  if (!web_contents_)
341    return;
342
343  WebContentsViewAndroid* view =
344      static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
345  if (view)
346    view->NotifyExternalSurface(player_id, is_request, rect);
347}
348#endif
349
350void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id) {
351  DCHECK_EQ(fullscreen_player_id_, -1);
352
353  if (video_view_.get()) {
354    fullscreen_player_id_ = player_id;
355    video_view_->OpenVideo();
356  } else if (!ContentVideoView::HasContentVideoView()) {
357    // In Android WebView, two ContentViewCores could both try to enter
358    // fullscreen video, we just ignore the second one.
359    fullscreen_player_id_ = player_id;
360    WebContents* web_contents =
361        WebContents::FromRenderViewHost(render_view_host());
362    ContentViewCoreImpl* content_view_core_impl =
363        ContentViewCoreImpl::FromWebContents(web_contents);
364    video_view_.reset(new ContentVideoView(content_view_core_impl->GetContext(),
365        content_view_core_impl->GetContentVideoViewClient(), this));
366  }
367}
368
369void BrowserMediaPlayerManager::OnExitFullscreen(int player_id) {
370  if (fullscreen_player_id_ == player_id) {
371    MediaPlayerAndroid* player = GetPlayer(player_id);
372    if (player)
373      player->SetVideoSurface(gfx::ScopedJavaSurface());
374    video_view_->OnExitFullscreen();
375  }
376}
377
378void BrowserMediaPlayerManager::OnInitialize(
379    int player_id,
380    const GURL& url,
381    media::MediaPlayerAndroid::SourceType source_type,
382    const GURL& first_party_for_cookies) {
383  RemovePlayer(player_id);
384
385  RenderProcessHost* host = render_view_host()->GetProcess();
386  ContentViewCoreImpl* content_view_core_impl =
387      static_cast<ContentViewCoreImpl*>(
388          ContentViewCore::FromWebContents(web_contents_));
389  AddPlayer(media::MediaPlayerAndroid::Create(
390      player_id, url, source_type, first_party_for_cookies,
391      host->GetBrowserContext()->IsOffTheRecord(), this,
392      !content_view_core_impl->ShouldBlockMediaRequest(url)));
393}
394
395void BrowserMediaPlayerManager::OnStart(int player_id) {
396  MediaPlayerAndroid* player = GetPlayer(player_id);
397  if (player)
398    player->Start();
399}
400
401void BrowserMediaPlayerManager::OnSeek(int player_id, base::TimeDelta time) {
402  MediaPlayerAndroid* player = GetPlayer(player_id);
403  if (player)
404    player->SeekTo(time);
405}
406
407void BrowserMediaPlayerManager::OnPause(int player_id) {
408  MediaPlayerAndroid* player = GetPlayer(player_id);
409  if (player)
410    player->Pause();
411}
412
413void BrowserMediaPlayerManager::OnSetVolume(int player_id, double volume) {
414  MediaPlayerAndroid* player = GetPlayer(player_id);
415  if (player)
416    player->SetVolume(volume);
417}
418
419void BrowserMediaPlayerManager::OnReleaseResources(int player_id) {
420  MediaPlayerAndroid* player = GetPlayer(player_id);
421  // Don't release the fullscreen player when tab visibility changes,
422  // it will be released when user hit the back/home button or when
423  // OnDestroyPlayer is called.
424  if (player && player_id != fullscreen_player_id_)
425    player->Release();
426
427#if defined(GOOGLE_TV)
428  WebContentsViewAndroid* view =
429      static_cast<WebContentsViewAndroid*>(web_contents_->GetView());
430  if (view)
431    view->NotifyExternalSurface(player_id, false, gfx::RectF());
432#endif
433}
434
435void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) {
436  RemovePlayer(player_id);
437  if (fullscreen_player_id_ == player_id)
438    fullscreen_player_id_ = -1;
439}
440
441void BrowserMediaPlayerManager::OnDemuxerReady(
442    int player_id,
443    const media::MediaPlayerHostMsg_DemuxerReady_Params& params) {
444  MediaPlayerAndroid* player = GetPlayer(player_id);
445  if (player)
446    player->DemuxerReady(params);
447}
448
449void BrowserMediaPlayerManager::OnReadFromDemuxerAck(
450    int player_id,
451    const media::MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) {
452  MediaPlayerAndroid* player = GetPlayer(player_id);
453  if (player)
454    player->ReadFromDemuxerAck(params);
455}
456
457void BrowserMediaPlayerManager::OnMediaSeekRequestAck(
458    int player_id, unsigned seek_request_id) {
459  MediaPlayerAndroid* player = GetPlayer(player_id);
460  if (player)
461    player->OnSeekRequestAck(seek_request_id);
462}
463
464void BrowserMediaPlayerManager::OnInitializeCDM(
465    int media_keys_id,
466    const std::vector<uint8>& uuid) {
467  AddDrmBridge(media_keys_id, uuid);
468  // In EME v0.1b MediaKeys lives in the media element. So the |media_keys_id|
469  // is the same as the |player_id|.
470  OnSetMediaKeys(media_keys_id, media_keys_id);
471}
472
473void BrowserMediaPlayerManager::OnGenerateKeyRequest(
474    int media_keys_id,
475    const std::string& type,
476    const std::vector<uint8>& init_data) {
477  MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
478  if (drm_bridge)
479    drm_bridge->GenerateKeyRequest(type, &init_data[0], init_data.size());
480}
481
482void BrowserMediaPlayerManager::OnAddKey(int media_keys_id,
483                                         const std::vector<uint8>& key,
484                                         const std::vector<uint8>& init_data,
485                                         const std::string& session_id) {
486  MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
487  if (drm_bridge) {
488    drm_bridge->AddKey(&key[0], key.size(), &init_data[0], init_data.size(),
489                       session_id);
490  }
491}
492
493void BrowserMediaPlayerManager::OnCancelKeyRequest(
494    int media_keys_id,
495    const std::string& session_id) {
496  MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
497  if (drm_bridge)
498    drm_bridge->CancelKeyRequest(session_id);
499}
500
501void BrowserMediaPlayerManager::OnDurationChanged(
502    int player_id, const base::TimeDelta& duration) {
503  MediaPlayerAndroid* player = GetPlayer(player_id);
504  if (player)
505    player->DurationChanged(duration);
506}
507
508void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) {
509  DCHECK(!GetPlayer(player->player_id()));
510  players_.push_back(player);
511}
512
513void BrowserMediaPlayerManager::RemovePlayer(int player_id) {
514  for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
515      it != players_.end(); ++it) {
516    if ((*it)->player_id() == player_id) {
517      players_.erase(it);
518      break;
519    }
520  }
521}
522
523void BrowserMediaPlayerManager::AddDrmBridge(int media_keys_id,
524                                             const std::vector<uint8>& uuid) {
525  DCHECK(!GetDrmBridge(media_keys_id));
526  scoped_ptr<MediaDrmBridge> drm_bridge(
527      MediaDrmBridge::Create(media_keys_id, uuid, this));
528  DCHECK(drm_bridge) << "failed to create drm bridge. ";
529  drm_bridges_.push_back(drm_bridge.release());
530}
531
532void BrowserMediaPlayerManager::RemoveDrmBridge(int media_keys_id) {
533  for (ScopedVector<MediaDrmBridge>::iterator it = drm_bridges_.begin();
534      it != drm_bridges_.end(); ++it) {
535    if ((*it)->media_keys_id() == media_keys_id) {
536      drm_bridges_.erase(it);
537      break;
538    }
539  }
540}
541
542void BrowserMediaPlayerManager::OnSetMediaKeys(int player_id,
543                                               int media_keys_id) {
544  MediaPlayerAndroid* player = GetPlayer(player_id);
545  MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id);
546  if (!player || !drm_bridge) {
547    NOTREACHED() << "OnSetMediaKeys(): Player and MediaKeys must be present.";
548    return;
549  }
550  // TODO(qinmin): add the logic to decide whether we should create the
551  // fullscreen surface for EME lv1.
552  player->SetDrmBridge(drm_bridge);
553}
554
555}  // namespace content
556