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#ifndef CONTENT_RENDERER_MEDIA_ANDROID_MEDIA_SOURCE_DELEGATE_H_
6#define CONTENT_RENDERER_MEDIA_ANDROID_MEDIA_SOURCE_DELEGATE_H_
7
8#include <string>
9#include <vector>
10
11#include "base/callback.h"
12#include "base/memory/ref_counted.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/memory/weak_ptr.h"
15#include "base/message_loop/message_loop.h"
16#include "base/time/time.h"
17#include "media/base/decryptor.h"
18#include "media/base/demuxer.h"
19#include "media/base/media_keys.h"
20#include "media/base/pipeline_status.h"
21#include "media/base/ranges.h"
22#include "media/base/text_track.h"
23#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
24
25namespace media {
26class ChunkDemuxer;
27class DecoderBuffer;
28class DecryptingDemuxerStream;
29class DemuxerStream;
30class MediaLog;
31struct DemuxerConfigs;
32struct DemuxerData;
33}
34
35namespace content {
36
37class RendererDemuxerAndroid;
38
39class MediaSourceDelegate : public media::DemuxerHost {
40 public:
41  typedef base::Callback<void(blink::WebMediaSource*)>
42      MediaSourceOpenedCB;
43  typedef base::Callback<void(blink::WebMediaPlayer::NetworkState)>
44      UpdateNetworkStateCB;
45  typedef base::Callback<void(const base::TimeDelta&)> DurationChangeCB;
46
47  // Helper class used by scoped_ptr to destroy an instance of
48  // MediaSourceDelegate.
49  class Destroyer {
50   public:
51    inline void operator()(void* media_source_delegate) const {
52      static_cast<MediaSourceDelegate*>(media_source_delegate)->Destroy();
53    }
54  };
55
56  MediaSourceDelegate(RendererDemuxerAndroid* demuxer_client,
57                      int demuxer_client_id,
58                      const scoped_refptr<base::MessageLoopProxy>& media_loop,
59                      media::MediaLog* media_log);
60
61  // Initialize the MediaSourceDelegate. |media_source| will be owned by
62  // this object after this call.
63  void InitializeMediaSource(
64      const MediaSourceOpenedCB& media_source_opened_cb,
65      const media::Demuxer::NeedKeyCB& need_key_cb,
66      const media::SetDecryptorReadyCB& set_decryptor_ready_cb,
67      const UpdateNetworkStateCB& update_network_state_cb,
68      const DurationChangeCB& duration_change_cb);
69
70#if defined(GOOGLE_TV)
71  void InitializeMediaStream(
72      media::Demuxer* demuxer,
73      const UpdateNetworkStateCB& update_network_state_cb);
74#endif
75
76  const blink::WebTimeRanges& Buffered();
77  size_t DecodedFrameCount() const;
78  size_t DroppedFrameCount() const;
79  size_t AudioDecodedByteCount() const;
80  size_t VideoDecodedByteCount() const;
81
82  // In MSE case, calls ChunkDemuxer::CancelPendingSeek(). Also sets the
83  // expectation that a regular seek will be arriving and to trivially finish
84  // any browser seeks that may be requested prior to the regular seek.
85  void CancelPendingSeek(const base::TimeDelta& seek_time);
86
87  // In MSE case, calls ChunkDemuxer::StartWaitingForSeek(), first calling
88  // ChunkDemuxer::CancelPendingSeek() if a browser seek is in progress.
89  // Also sets the expectation that a regular seek will be arriving and to
90  // trivially finish any browser seeks that may be requested prior to the
91  // regular seek.
92  void StartWaitingForSeek(const base::TimeDelta& seek_time);
93
94  // Seeks the demuxer and later calls OnDemuxerSeekDone() after the seek has
95  // been completed. There must be no other seek of the demuxer currently in
96  // process when this method is called.
97  // If |is_browser_seek| is true, then this is a short-term hack browser
98  // seek.
99  // TODO(wolenetz): Instead of doing browser seek, browser player should replay
100  // cached data since last keyframe. See http://crbug.com/304234.
101  void Seek(const base::TimeDelta& seek_time, bool is_browser_seek);
102
103  void NotifyKeyAdded(const std::string& key_system);
104
105  // Called when DemuxerStreamPlayer needs to read data from ChunkDemuxer.
106  void OnReadFromDemuxer(media::DemuxerStream::Type type);
107
108  // Called when the player needs the new config data from ChunkDemuxer.
109  void OnMediaConfigRequest();
110
111  // Called by the Destroyer to destroy an instance of this object.
112  void Destroy();
113
114 private:
115  typedef base::Callback<void(scoped_ptr<media::DemuxerData> data)>
116      ReadFromDemuxerAckCB;
117  typedef base::Callback<void(scoped_ptr<media::DemuxerConfigs> configs)>
118      DemuxerReadyCB;
119
120  // This is private to enforce use of the Destroyer.
121  virtual ~MediaSourceDelegate();
122
123  // Methods inherited from DemuxerHost.
124  virtual void SetTotalBytes(int64 total_bytes) OVERRIDE;
125  virtual void AddBufferedByteRange(int64 start, int64 end) OVERRIDE;
126  virtual void AddBufferedTimeRange(base::TimeDelta start,
127                                    base::TimeDelta end) OVERRIDE;
128  virtual void SetDuration(base::TimeDelta duration) OVERRIDE;
129  virtual void OnDemuxerError(media::PipelineStatus status) OVERRIDE;
130  virtual void AddTextStream(media::DemuxerStream* text_stream,
131                             const media::TextTrackConfig& config) OVERRIDE;
132  virtual void RemoveTextStream(media::DemuxerStream* text_stream) OVERRIDE;
133
134  // Notifies |demuxer_client_| and fires |duration_changed_cb_|.
135  void OnDurationChanged(const base::TimeDelta& duration);
136
137  // Callback for ChunkDemuxer initialization.
138  void OnDemuxerInitDone(media::PipelineStatus status);
139
140  // Initializes DecryptingDemuxerStreams if audio/video stream is encrypted.
141  void InitAudioDecryptingDemuxerStream();
142  void InitVideoDecryptingDemuxerStream();
143
144  // Callbacks for DecryptingDemuxerStream::Initialize().
145  void OnAudioDecryptingDemuxerStreamInitDone(media::PipelineStatus status);
146  void OnVideoDecryptingDemuxerStreamInitDone(media::PipelineStatus status);
147
148  // Callback for ChunkDemuxer::Seek() and callback chain for resetting
149  // decrypted audio/video streams if present.
150  //
151  // Runs on the media thread.
152  void OnDemuxerSeekDone(media::PipelineStatus status);
153  void ResetAudioDecryptingDemuxerStream();
154  void ResetVideoDecryptingDemuxerStream();
155  void FinishResettingDecryptingDemuxerStreams();
156
157  void OnDemuxerStopDone();
158  void OnDemuxerOpened();
159  void OnNeedKey(const std::string& type,
160                 const std::vector<uint8>& init_data);
161  void NotifyDemuxerReady();
162  bool CanNotifyDemuxerReady();
163
164  void StopDemuxer();
165  void InitializeDemuxer();
166  void SeekInternal(const base::TimeDelta& seek_time);
167  // Reads an access unit from the demuxer stream |stream| and stores it in
168  // the |index|th access unit in |params|.
169  void ReadFromDemuxerStream(media::DemuxerStream::Type type,
170                             scoped_ptr<media::DemuxerData> data,
171                             size_t index);
172  void OnBufferReady(media::DemuxerStream::Type type,
173                     scoped_ptr<media::DemuxerData> data,
174                     size_t index,
175                     media::DemuxerStream::Status status,
176                     const scoped_refptr<media::DecoderBuffer>& buffer);
177
178  // Helper function for calculating duration.
179  int GetDurationMs();
180
181  bool HasEncryptedStream();
182
183  bool IsSeeking() const;
184
185  // Returns |seek_time| if it is still buffered or if there is no currently
186  // buffered range including or soon after |seek_time|. If |seek_time| is not
187  // buffered, but there is a later range buffered near to |seek_time|, returns
188  // next buffered range's start time instead. Only call this for browser seeks.
189  // |seeking_lock_| must be held by caller.
190  base::TimeDelta FindBufferedBrowserSeekTime_Locked(
191      const base::TimeDelta& seek_time) const;
192
193  // Message loop for main renderer thread and corresponding weak pointer.
194  const scoped_refptr<base::MessageLoopProxy> main_loop_;
195  base::WeakPtrFactory<MediaSourceDelegate> main_weak_factory_;
196  base::WeakPtr<MediaSourceDelegate> main_weak_this_;
197
198  // Message loop for media thread and corresponding weak pointer.
199  const scoped_refptr<base::MessageLoopProxy> media_loop_;
200  base::WeakPtrFactory<MediaSourceDelegate> media_weak_factory_;
201
202  RendererDemuxerAndroid* demuxer_client_;
203  int demuxer_client_id_;
204
205  scoped_refptr<media::MediaLog> media_log_;
206  UpdateNetworkStateCB update_network_state_cb_;
207  DurationChangeCB duration_change_cb_;
208
209  scoped_ptr<media::ChunkDemuxer> chunk_demuxer_;
210  media::Demuxer* demuxer_;
211  bool is_demuxer_ready_;
212
213  media::SetDecryptorReadyCB set_decryptor_ready_cb_;
214
215  scoped_ptr<media::DecryptingDemuxerStream> audio_decrypting_demuxer_stream_;
216  scoped_ptr<media::DecryptingDemuxerStream> video_decrypting_demuxer_stream_;
217
218  media::DemuxerStream* audio_stream_;
219  media::DemuxerStream* video_stream_;
220
221  media::PipelineStatistics statistics_;
222  media::Ranges<base::TimeDelta> buffered_time_ranges_;
223  // Keep a list of buffered time ranges.
224  blink::WebTimeRanges buffered_web_time_ranges_;
225
226  MediaSourceOpenedCB media_source_opened_cb_;
227  media::Demuxer::NeedKeyCB need_key_cb_;
228
229  // The currently selected key system. Empty string means that no key system
230  // has been selected.
231  blink::WebString current_key_system_;
232
233  // Temporary for EME v0.1. In the future the init data type should be passed
234  // through GenerateKeyRequest() directly from WebKit.
235  std::string init_data_type_;
236
237  // Lock used to serialize access for |seeking_|.
238  mutable base::Lock seeking_lock_;
239  bool seeking_;
240
241  // Track if we are currently performing a browser seek, and track whether or
242  // not a regular seek is expected soon. If a regular seek is expected soon,
243  // then any in-progress browser seek will be canceled pending the
244  // regular seek, if using |chunk_demuxer_|, and any requested browser seek
245  // will be trivially finished. Access is serialized by |seeking_lock_|.
246  bool doing_browser_seek_;
247  base::TimeDelta browser_seek_time_;
248  bool expecting_regular_seek_;
249
250#if defined(GOOGLE_TV)
251  bool key_added_;
252  std::string key_system_;
253#endif  // defined(GOOGLE_TV)
254
255  size_t access_unit_size_;
256
257  DISALLOW_COPY_AND_ASSIGN(MediaSourceDelegate);
258};
259
260}  // namespace content
261
262#endif  // CONTENT_RENDERER_MEDIA_ANDROID_MEDIA_SOURCE_DELEGATE_H_
263