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 25 namespace media { 26 class ChunkDemuxer; 27 class DecoderBuffer; 28 class DecryptingDemuxerStream; 29 class DemuxerStream; 30 class MediaLog; 31 struct DemuxerConfigs; 32 struct DemuxerData; 33 } 34 35 namespace content { 36 37 class RendererDemuxerAndroid; 38 39 class 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 blink::WebTimeRanges Buffered() const; 71 size_t DecodedFrameCount() const; 72 size_t DroppedFrameCount() const; 73 size_t AudioDecodedByteCount() const; 74 size_t VideoDecodedByteCount() const; 75 76 // In MSE case, calls ChunkDemuxer::CancelPendingSeek(). Also sets the 77 // expectation that a regular seek will be arriving and to trivially finish 78 // any browser seeks that may be requested prior to the regular seek. 79 void CancelPendingSeek(const base::TimeDelta& seek_time); 80 81 // In MSE case, calls ChunkDemuxer::StartWaitingForSeek(), first calling 82 // ChunkDemuxer::CancelPendingSeek() if a browser seek is in progress. 83 // Also sets the expectation that a regular seek will be arriving and to 84 // trivially finish any browser seeks that may be requested prior to the 85 // regular seek. 86 void StartWaitingForSeek(const base::TimeDelta& seek_time); 87 88 // Seeks the demuxer and later calls OnDemuxerSeekDone() after the seek has 89 // been completed. There must be no other seek of the demuxer currently in 90 // process when this method is called. 91 // If |is_browser_seek| is true, then this is a short-term hack browser 92 // seek. 93 // TODO(wolenetz): Instead of doing browser seek, browser player should replay 94 // cached data since last keyframe. See http://crbug.com/304234. 95 void Seek(const base::TimeDelta& seek_time, bool is_browser_seek); 96 97 // Called when DemuxerStreamPlayer needs to read data from ChunkDemuxer. 98 void OnReadFromDemuxer(media::DemuxerStream::Type type); 99 100 // Called by the Destroyer to destroy an instance of this object. 101 void Destroy(); 102 103 // Called on the main thread to check whether the video stream is encrypted. 104 bool IsVideoEncrypted(); 105 106 // Gets the ChunkDemuxer timeline offset. 107 base::Time GetTimelineOffset() const; 108 109 private: 110 // This is private to enforce use of the Destroyer. 111 virtual ~MediaSourceDelegate(); 112 113 // Methods inherited from DemuxerHost. 114 virtual void AddBufferedTimeRange(base::TimeDelta start, 115 base::TimeDelta end) OVERRIDE; 116 virtual void SetDuration(base::TimeDelta duration) OVERRIDE; 117 virtual void OnDemuxerError(media::PipelineStatus status) OVERRIDE; 118 virtual void AddTextStream(media::DemuxerStream* text_stream, 119 const media::TextTrackConfig& config) OVERRIDE; 120 virtual void RemoveTextStream(media::DemuxerStream* text_stream) OVERRIDE; 121 122 // Notifies |demuxer_client_| and fires |duration_changed_cb_|. 123 void OnDurationChanged(const base::TimeDelta& duration); 124 125 // Callback for ChunkDemuxer initialization. 126 void OnDemuxerInitDone(media::PipelineStatus status); 127 128 // Initializes DecryptingDemuxerStreams if audio/video stream is encrypted. 129 void InitAudioDecryptingDemuxerStream(); 130 void InitVideoDecryptingDemuxerStream(); 131 132 // Callbacks for DecryptingDemuxerStream::Initialize(). 133 void OnAudioDecryptingDemuxerStreamInitDone(media::PipelineStatus status); 134 void OnVideoDecryptingDemuxerStreamInitDone(media::PipelineStatus status); 135 136 // Callback for ChunkDemuxer::Seek() and callback chain for resetting 137 // decrypted audio/video streams if present. 138 // 139 // Runs on the media thread. 140 void OnDemuxerSeekDone(media::PipelineStatus status); 141 void ResetAudioDecryptingDemuxerStream(); 142 void ResetVideoDecryptingDemuxerStream(); 143 void FinishResettingDecryptingDemuxerStreams(); 144 145 // Callback for ChunkDemuxer::Stop() and helper for deleting |this| on the 146 // main thread. 147 void OnDemuxerStopDone(); 148 void DeleteSelf(); 149 150 void OnDemuxerOpened(); 151 void OnNeedKey(const std::string& type, 152 const std::vector<uint8>& init_data); 153 void NotifyDemuxerReady(); 154 155 void StopDemuxer(); 156 void InitializeDemuxer(); 157 void SeekInternal(const base::TimeDelta& seek_time); 158 // Reads an access unit from the demuxer stream |stream| and stores it in 159 // the |index|th access unit in |params|. 160 void ReadFromDemuxerStream(media::DemuxerStream::Type type, 161 scoped_ptr<media::DemuxerData> data, 162 size_t index); 163 void OnBufferReady(media::DemuxerStream::Type type, 164 scoped_ptr<media::DemuxerData> data, 165 size_t index, 166 media::DemuxerStream::Status status, 167 const scoped_refptr<media::DecoderBuffer>& buffer); 168 169 // Helper function for calculating duration. 170 base::TimeDelta GetDuration() const; 171 172 bool IsSeeking() const; 173 174 // Returns |seek_time| if it is still buffered or if there is no currently 175 // buffered range including or soon after |seek_time|. If |seek_time| is not 176 // buffered, but there is a later range buffered near to |seek_time|, returns 177 // next buffered range's start time instead. Only call this for browser seeks. 178 // |seeking_lock_| must be held by caller. 179 base::TimeDelta FindBufferedBrowserSeekTime_Locked( 180 const base::TimeDelta& seek_time) const; 181 182 // Get the demuxer configs for a particular stream identified by |is_audio|. 183 // Returns true on success, of false otherwise. 184 bool GetDemuxerConfigFromStream(media::DemuxerConfigs* configs, 185 bool is_audio); 186 187 RendererDemuxerAndroid* demuxer_client_; 188 int demuxer_client_id_; 189 190 scoped_refptr<media::MediaLog> media_log_; 191 UpdateNetworkStateCB update_network_state_cb_; 192 DurationChangeCB duration_change_cb_; 193 194 scoped_ptr<media::ChunkDemuxer> chunk_demuxer_; 195 bool is_demuxer_ready_; 196 197 media::SetDecryptorReadyCB set_decryptor_ready_cb_; 198 199 scoped_ptr<media::DecryptingDemuxerStream> audio_decrypting_demuxer_stream_; 200 scoped_ptr<media::DecryptingDemuxerStream> video_decrypting_demuxer_stream_; 201 202 media::DemuxerStream* audio_stream_; 203 media::DemuxerStream* video_stream_; 204 205 media::PipelineStatistics statistics_; 206 media::Ranges<base::TimeDelta> buffered_time_ranges_; 207 208 MediaSourceOpenedCB media_source_opened_cb_; 209 media::Demuxer::NeedKeyCB need_key_cb_; 210 211 // Temporary for EME v0.1. In the future the init data type should be passed 212 // through GenerateKeyRequest() directly from WebKit. 213 std::string init_data_type_; 214 215 // Lock used to serialize access for |seeking_|. 216 mutable base::Lock seeking_lock_; 217 bool seeking_; 218 219 // Lock used to serialize access for |is_video_encrypted_|. 220 mutable base::Lock is_video_encrypted_lock_; 221 bool is_video_encrypted_; 222 223 // Track if we are currently performing a browser seek, and track whether or 224 // not a regular seek is expected soon. If a regular seek is expected soon, 225 // then any in-progress browser seek will be canceled pending the 226 // regular seek, if using |chunk_demuxer_|, and any requested browser seek 227 // will be trivially finished. Access is serialized by |seeking_lock_|. 228 bool doing_browser_seek_; 229 base::TimeDelta browser_seek_time_; 230 bool expecting_regular_seek_; 231 232 size_t access_unit_size_; 233 234 // Message loop for main renderer and media threads. 235 const scoped_refptr<base::MessageLoopProxy> main_loop_; 236 const scoped_refptr<base::MessageLoopProxy> media_loop_; 237 238 // NOTE: Weak pointers must be invalidated before all other member variables. 239 base::WeakPtrFactory<MediaSourceDelegate> main_weak_factory_; 240 base::WeakPtrFactory<MediaSourceDelegate> media_weak_factory_; 241 base::WeakPtr<MediaSourceDelegate> main_weak_this_; 242 243 DISALLOW_COPY_AND_ASSIGN(MediaSourceDelegate); 244 }; 245 246 } // namespace content 247 248 #endif // CONTENT_RENDERER_MEDIA_ANDROID_MEDIA_SOURCE_DELEGATE_H_ 249