| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/media/android/media_source_delegate.h" | 5 #include "content/renderer/media/android/media_source_delegate.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 namespace content { | 41 namespace content { |
| 42 | 42 |
| 43 static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log, | 43 static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log, |
| 44 const std::string& error) { | 44 const std::string& error) { |
| 45 media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error)); | 45 media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error)); |
| 46 } | 46 } |
| 47 | 47 |
| 48 MediaSourceDelegate::MediaSourceDelegate( | 48 MediaSourceDelegate::MediaSourceDelegate( |
| 49 RendererDemuxerAndroid* demuxer_client, | 49 RendererDemuxerAndroid* demuxer_client, |
| 50 int demuxer_client_id, | 50 int demuxer_client_id, |
| 51 const scoped_refptr<base::MessageLoopProxy>& media_loop, | 51 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, |
| 52 const scoped_refptr<media::MediaLog> media_log) | 52 const scoped_refptr<media::MediaLog> media_log) |
| 53 : demuxer_client_(demuxer_client), | 53 : demuxer_client_(demuxer_client), |
| 54 demuxer_client_id_(demuxer_client_id), | 54 demuxer_client_id_(demuxer_client_id), |
| 55 media_log_(media_log), | 55 media_log_(media_log), |
| 56 is_demuxer_ready_(false), | 56 is_demuxer_ready_(false), |
| 57 audio_stream_(NULL), | 57 audio_stream_(NULL), |
| 58 video_stream_(NULL), | 58 video_stream_(NULL), |
| 59 seeking_(false), | 59 seeking_(false), |
| 60 is_video_encrypted_(false), | 60 is_video_encrypted_(false), |
| 61 doing_browser_seek_(false), | 61 doing_browser_seek_(false), |
| 62 browser_seek_time_(media::kNoTimestamp()), | 62 browser_seek_time_(media::kNoTimestamp()), |
| 63 expecting_regular_seek_(false), | 63 expecting_regular_seek_(false), |
| 64 access_unit_size_(0), | 64 access_unit_size_(0), |
| 65 main_loop_(base::MessageLoopProxy::current()), | 65 main_task_runner_(base::MessageLoopProxy::current()), |
| 66 media_loop_(media_loop), | 66 media_task_runner_(media_task_runner), |
| 67 main_weak_factory_(this), | 67 main_weak_factory_(this), |
| 68 media_weak_factory_(this), | 68 media_weak_factory_(this), |
| 69 main_weak_this_(main_weak_factory_.GetWeakPtr()) { | 69 main_weak_this_(main_weak_factory_.GetWeakPtr()) { |
| 70 DCHECK(main_loop_->BelongsToCurrentThread()); | 70 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 71 } | 71 } |
| 72 | 72 |
| 73 MediaSourceDelegate::~MediaSourceDelegate() { | 73 MediaSourceDelegate::~MediaSourceDelegate() { |
| 74 DCHECK(main_loop_->BelongsToCurrentThread()); | 74 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 75 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 75 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
| 76 DCHECK(!chunk_demuxer_); | 76 DCHECK(!chunk_demuxer_); |
| 77 DCHECK(!demuxer_client_); | 77 DCHECK(!demuxer_client_); |
| 78 DCHECK(!audio_decrypting_demuxer_stream_); | 78 DCHECK(!audio_decrypting_demuxer_stream_); |
| 79 DCHECK(!video_decrypting_demuxer_stream_); | 79 DCHECK(!video_decrypting_demuxer_stream_); |
| 80 DCHECK(!audio_stream_); | 80 DCHECK(!audio_stream_); |
| 81 DCHECK(!video_stream_); | 81 DCHECK(!video_stream_); |
| 82 } | 82 } |
| 83 | 83 |
| 84 void MediaSourceDelegate::Destroy() { | 84 void MediaSourceDelegate::Destroy() { |
| 85 DCHECK(main_loop_->BelongsToCurrentThread()); | 85 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 86 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 86 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
| 87 | 87 |
| 88 if (!chunk_demuxer_) { | 88 if (!chunk_demuxer_) { |
| 89 DCHECK(!demuxer_client_); | 89 DCHECK(!demuxer_client_); |
| 90 delete this; | 90 delete this; |
| 91 return; | 91 return; |
| 92 } | 92 } |
| 93 | 93 |
| 94 duration_change_cb_.Reset(); | 94 duration_change_cb_.Reset(); |
| 95 update_network_state_cb_.Reset(); | 95 update_network_state_cb_.Reset(); |
| 96 media_source_opened_cb_.Reset(); | 96 media_source_opened_cb_.Reset(); |
| 97 | 97 |
| 98 main_weak_factory_.InvalidateWeakPtrs(); | 98 main_weak_factory_.InvalidateWeakPtrs(); |
| 99 DCHECK(!main_weak_factory_.HasWeakPtrs()); | 99 DCHECK(!main_weak_factory_.HasWeakPtrs()); |
| 100 | 100 |
| 101 chunk_demuxer_->Shutdown(); | 101 chunk_demuxer_->Shutdown(); |
| 102 | 102 |
| 103 // |this| will be transferred to the callback StopDemuxer() and | 103 // |this| will be transferred to the callback StopDemuxer() and |
| 104 // OnDemuxerStopDone(). They own |this| and OnDemuxerStopDone() will delete | 104 // OnDemuxerStopDone(). They own |this| and OnDemuxerStopDone() will delete |
| 105 // it when called, hence using base::Unretained(this) is safe here. | 105 // it when called, hence using base::Unretained(this) is safe here. |
| 106 media_loop_->PostTask(FROM_HERE, | 106 media_task_runner_->PostTask(FROM_HERE, |
| 107 base::Bind(&MediaSourceDelegate::StopDemuxer, | 107 base::Bind(&MediaSourceDelegate::StopDemuxer, |
| 108 base::Unretained(this))); | 108 base::Unretained(this))); |
| 109 } | 109 } |
| 110 | 110 |
| 111 bool MediaSourceDelegate::IsVideoEncrypted() { | 111 bool MediaSourceDelegate::IsVideoEncrypted() { |
| 112 DCHECK(main_loop_->BelongsToCurrentThread()); | 112 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 113 base::AutoLock auto_lock(is_video_encrypted_lock_); | 113 base::AutoLock auto_lock(is_video_encrypted_lock_); |
| 114 return is_video_encrypted_; | 114 return is_video_encrypted_; |
| 115 } | 115 } |
| 116 | 116 |
| 117 base::Time MediaSourceDelegate::GetTimelineOffset() const { | 117 base::Time MediaSourceDelegate::GetTimelineOffset() const { |
| 118 DCHECK(main_loop_->BelongsToCurrentThread()); | 118 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 119 if (!chunk_demuxer_) | 119 if (!chunk_demuxer_) |
| 120 return base::Time(); | 120 return base::Time(); |
| 121 | 121 |
| 122 return chunk_demuxer_->GetTimelineOffset(); | 122 return chunk_demuxer_->GetTimelineOffset(); |
| 123 } | 123 } |
| 124 | 124 |
| 125 void MediaSourceDelegate::StopDemuxer() { | 125 void MediaSourceDelegate::StopDemuxer() { |
| 126 DCHECK(media_loop_->BelongsToCurrentThread()); | 126 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 127 DCHECK(chunk_demuxer_); | 127 DCHECK(chunk_demuxer_); |
| 128 | 128 |
| 129 demuxer_client_->RemoveDelegate(demuxer_client_id_); | 129 demuxer_client_->RemoveDelegate(demuxer_client_id_); |
| 130 demuxer_client_ = NULL; | 130 demuxer_client_ = NULL; |
| 131 | 131 |
| 132 audio_stream_ = NULL; | 132 audio_stream_ = NULL; |
| 133 video_stream_ = NULL; | 133 video_stream_ = NULL; |
| 134 // TODO(xhwang): Figure out if we need to Reset the DDSs after Seeking or | 134 // TODO(xhwang): Figure out if we need to Reset the DDSs after Seeking or |
| 135 // before destroying them. | 135 // before destroying them. |
| 136 audio_decrypting_demuxer_stream_.reset(); | 136 audio_decrypting_demuxer_stream_.reset(); |
| 137 video_decrypting_demuxer_stream_.reset(); | 137 video_decrypting_demuxer_stream_.reset(); |
| 138 | 138 |
| 139 media_weak_factory_.InvalidateWeakPtrs(); | 139 media_weak_factory_.InvalidateWeakPtrs(); |
| 140 DCHECK(!media_weak_factory_.HasWeakPtrs()); | 140 DCHECK(!media_weak_factory_.HasWeakPtrs()); |
| 141 | 141 |
| 142 // The callback OnDemuxerStopDone() owns |this| and will delete it when | 142 // The callback OnDemuxerStopDone() owns |this| and will delete it when |
| 143 // called. Hence using base::Unretained(this) is safe here. | 143 // called. Hence using base::Unretained(this) is safe here. |
| 144 chunk_demuxer_->Stop(base::Bind(&MediaSourceDelegate::OnDemuxerStopDone, | 144 chunk_demuxer_->Stop(base::Bind(&MediaSourceDelegate::OnDemuxerStopDone, |
| 145 base::Unretained(this))); | 145 base::Unretained(this))); |
| 146 } | 146 } |
| 147 | 147 |
| 148 void MediaSourceDelegate::InitializeMediaSource( | 148 void MediaSourceDelegate::InitializeMediaSource( |
| 149 const MediaSourceOpenedCB& media_source_opened_cb, | 149 const MediaSourceOpenedCB& media_source_opened_cb, |
| 150 const media::Demuxer::NeedKeyCB& need_key_cb, | 150 const media::Demuxer::NeedKeyCB& need_key_cb, |
| 151 const media::SetDecryptorReadyCB& set_decryptor_ready_cb, | 151 const media::SetDecryptorReadyCB& set_decryptor_ready_cb, |
| 152 const UpdateNetworkStateCB& update_network_state_cb, | 152 const UpdateNetworkStateCB& update_network_state_cb, |
| 153 const DurationChangeCB& duration_change_cb) { | 153 const DurationChangeCB& duration_change_cb) { |
| 154 DCHECK(main_loop_->BelongsToCurrentThread()); | 154 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 155 DCHECK(!media_source_opened_cb.is_null()); | 155 DCHECK(!media_source_opened_cb.is_null()); |
| 156 media_source_opened_cb_ = media_source_opened_cb; | 156 media_source_opened_cb_ = media_source_opened_cb; |
| 157 need_key_cb_ = need_key_cb; | 157 need_key_cb_ = need_key_cb; |
| 158 set_decryptor_ready_cb_ = set_decryptor_ready_cb; | 158 set_decryptor_ready_cb_ = set_decryptor_ready_cb; |
| 159 update_network_state_cb_ = media::BindToCurrentLoop(update_network_state_cb); | 159 update_network_state_cb_ = media::BindToCurrentLoop(update_network_state_cb); |
| 160 duration_change_cb_ = duration_change_cb; | 160 duration_change_cb_ = duration_change_cb; |
| 161 access_unit_size_ = kAccessUnitSizeForMediaSource; | 161 access_unit_size_ = kAccessUnitSizeForMediaSource; |
| 162 | 162 |
| 163 chunk_demuxer_.reset(new media::ChunkDemuxer( | 163 chunk_demuxer_.reset(new media::ChunkDemuxer( |
| 164 media::BindToCurrentLoop( | 164 media::BindToCurrentLoop( |
| 165 base::Bind(&MediaSourceDelegate::OnDemuxerOpened, main_weak_this_)), | 165 base::Bind(&MediaSourceDelegate::OnDemuxerOpened, main_weak_this_)), |
| 166 media::BindToCurrentLoop( | 166 media::BindToCurrentLoop( |
| 167 base::Bind(&MediaSourceDelegate::OnNeedKey, main_weak_this_)), | 167 base::Bind(&MediaSourceDelegate::OnNeedKey, main_weak_this_)), |
| 168 base::Bind(&LogMediaSourceError, media_log_), | 168 base::Bind(&LogMediaSourceError, media_log_), |
| 169 false)); | 169 false)); |
| 170 | 170 |
| 171 // |this| will be retained until StopDemuxer() is posted, so Unretained() is | 171 // |this| will be retained until StopDemuxer() is posted, so Unretained() is |
| 172 // safe here. | 172 // safe here. |
| 173 media_loop_->PostTask(FROM_HERE, | 173 media_task_runner_->PostTask(FROM_HERE, |
| 174 base::Bind(&MediaSourceDelegate::InitializeDemuxer, | 174 base::Bind(&MediaSourceDelegate::InitializeDemuxer, |
| 175 base::Unretained(this))); | 175 base::Unretained(this))); |
| 176 } | 176 } |
| 177 | 177 |
| 178 void MediaSourceDelegate::InitializeDemuxer() { | 178 void MediaSourceDelegate::InitializeDemuxer() { |
| 179 DCHECK(media_loop_->BelongsToCurrentThread()); | 179 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 180 demuxer_client_->AddDelegate(demuxer_client_id_, this); | 180 demuxer_client_->AddDelegate(demuxer_client_id_, this); |
| 181 chunk_demuxer_->Initialize(this, | 181 chunk_demuxer_->Initialize(this, |
| 182 base::Bind(&MediaSourceDelegate::OnDemuxerInitDone, | 182 base::Bind(&MediaSourceDelegate::OnDemuxerInitDone, |
| 183 media_weak_factory_.GetWeakPtr()), | 183 media_weak_factory_.GetWeakPtr()), |
| 184 false); | 184 false); |
| 185 } | 185 } |
| 186 | 186 |
| 187 blink::WebTimeRanges MediaSourceDelegate::Buffered() const { | 187 blink::WebTimeRanges MediaSourceDelegate::Buffered() const { |
| 188 return ConvertToWebTimeRanges(buffered_time_ranges_); | 188 return ConvertToWebTimeRanges(buffered_time_ranges_); |
| 189 } | 189 } |
| 190 | 190 |
| 191 size_t MediaSourceDelegate::DecodedFrameCount() const { | 191 size_t MediaSourceDelegate::DecodedFrameCount() const { |
| 192 return statistics_.video_frames_decoded; | 192 return statistics_.video_frames_decoded; |
| 193 } | 193 } |
| 194 | 194 |
| 195 size_t MediaSourceDelegate::DroppedFrameCount() const { | 195 size_t MediaSourceDelegate::DroppedFrameCount() const { |
| 196 return statistics_.video_frames_dropped; | 196 return statistics_.video_frames_dropped; |
| 197 } | 197 } |
| 198 | 198 |
| 199 size_t MediaSourceDelegate::AudioDecodedByteCount() const { | 199 size_t MediaSourceDelegate::AudioDecodedByteCount() const { |
| 200 return statistics_.audio_bytes_decoded; | 200 return statistics_.audio_bytes_decoded; |
| 201 } | 201 } |
| 202 | 202 |
| 203 size_t MediaSourceDelegate::VideoDecodedByteCount() const { | 203 size_t MediaSourceDelegate::VideoDecodedByteCount() const { |
| 204 return statistics_.video_bytes_decoded; | 204 return statistics_.video_bytes_decoded; |
| 205 } | 205 } |
| 206 | 206 |
| 207 void MediaSourceDelegate::CancelPendingSeek(const base::TimeDelta& seek_time) { | 207 void MediaSourceDelegate::CancelPendingSeek(const base::TimeDelta& seek_time) { |
| 208 DCHECK(main_loop_->BelongsToCurrentThread()); | 208 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 209 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : " | 209 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : " |
| 210 << demuxer_client_id_; | 210 << demuxer_client_id_; |
| 211 | 211 |
| 212 if (!chunk_demuxer_) | 212 if (!chunk_demuxer_) |
| 213 return; | 213 return; |
| 214 | 214 |
| 215 { | 215 { |
| 216 // Remember to trivially finish any newly arriving browser seek requests | 216 // Remember to trivially finish any newly arriving browser seek requests |
| 217 // that may arrive prior to the next regular seek request. | 217 // that may arrive prior to the next regular seek request. |
| 218 base::AutoLock auto_lock(seeking_lock_); | 218 base::AutoLock auto_lock(seeking_lock_); |
| 219 expecting_regular_seek_ = true; | 219 expecting_regular_seek_ = true; |
| 220 } | 220 } |
| 221 | 221 |
| 222 // Cancel any previously expected or in-progress regular or browser seek. | 222 // Cancel any previously expected or in-progress regular or browser seek. |
| 223 // It is possible that we have just finished the seek, but caller does | 223 // It is possible that we have just finished the seek, but caller does |
| 224 // not know this yet. It is still safe to cancel in this case because the | 224 // not know this yet. It is still safe to cancel in this case because the |
| 225 // caller will always call StartWaitingForSeek() when it is notified of | 225 // caller will always call StartWaitingForSeek() when it is notified of |
| 226 // the finished seek. | 226 // the finished seek. |
| 227 chunk_demuxer_->CancelPendingSeek(seek_time); | 227 chunk_demuxer_->CancelPendingSeek(seek_time); |
| 228 } | 228 } |
| 229 | 229 |
| 230 void MediaSourceDelegate::StartWaitingForSeek( | 230 void MediaSourceDelegate::StartWaitingForSeek( |
| 231 const base::TimeDelta& seek_time) { | 231 const base::TimeDelta& seek_time) { |
| 232 DCHECK(main_loop_->BelongsToCurrentThread()); | 232 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 233 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : " | 233 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : " |
| 234 << demuxer_client_id_; | 234 << demuxer_client_id_; |
| 235 | 235 |
| 236 if (!chunk_demuxer_) | 236 if (!chunk_demuxer_) |
| 237 return; | 237 return; |
| 238 | 238 |
| 239 bool cancel_browser_seek = false; | 239 bool cancel_browser_seek = false; |
| 240 { | 240 { |
| 241 // Remember to trivially finish any newly arriving browser seek requests | 241 // Remember to trivially finish any newly arriving browser seek requests |
| 242 // that may arrive prior to the next regular seek request. | 242 // that may arrive prior to the next regular seek request. |
| 243 base::AutoLock auto_lock(seeking_lock_); | 243 base::AutoLock auto_lock(seeking_lock_); |
| 244 expecting_regular_seek_ = true; | 244 expecting_regular_seek_ = true; |
| 245 | 245 |
| 246 // Remember to cancel any in-progress browser seek. | 246 // Remember to cancel any in-progress browser seek. |
| 247 if (seeking_) { | 247 if (seeking_) { |
| 248 DCHECK(doing_browser_seek_); | 248 DCHECK(doing_browser_seek_); |
| 249 cancel_browser_seek = true; | 249 cancel_browser_seek = true; |
| 250 } | 250 } |
| 251 } | 251 } |
| 252 | 252 |
| 253 if (cancel_browser_seek) | 253 if (cancel_browser_seek) |
| 254 chunk_demuxer_->CancelPendingSeek(seek_time); | 254 chunk_demuxer_->CancelPendingSeek(seek_time); |
| 255 chunk_demuxer_->StartWaitingForSeek(seek_time); | 255 chunk_demuxer_->StartWaitingForSeek(seek_time); |
| 256 } | 256 } |
| 257 | 257 |
| 258 void MediaSourceDelegate::Seek( | 258 void MediaSourceDelegate::Seek( |
| 259 const base::TimeDelta& seek_time, bool is_browser_seek) { | 259 const base::TimeDelta& seek_time, bool is_browser_seek) { |
| 260 DCHECK(media_loop_->BelongsToCurrentThread()); | 260 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 261 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ", " | 261 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ", " |
| 262 << (is_browser_seek ? "browser seek" : "regular seek") << ") : " | 262 << (is_browser_seek ? "browser seek" : "regular seek") << ") : " |
| 263 << demuxer_client_id_; | 263 << demuxer_client_id_; |
| 264 | 264 |
| 265 base::TimeDelta internal_seek_time = seek_time; | 265 base::TimeDelta internal_seek_time = seek_time; |
| 266 { | 266 { |
| 267 base::AutoLock auto_lock(seeking_lock_); | 267 base::AutoLock auto_lock(seeking_lock_); |
| 268 DCHECK(!seeking_); | 268 DCHECK(!seeking_); |
| 269 seeking_ = true; | 269 seeking_ = true; |
| 270 doing_browser_seek_ = is_browser_seek; | 270 doing_browser_seek_ = is_browser_seek; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 292 // Prepare |chunk_demuxer_| for browser seek. | 292 // Prepare |chunk_demuxer_| for browser seek. |
| 293 if (is_browser_seek) { | 293 if (is_browser_seek) { |
| 294 chunk_demuxer_->CancelPendingSeek(internal_seek_time); | 294 chunk_demuxer_->CancelPendingSeek(internal_seek_time); |
| 295 chunk_demuxer_->StartWaitingForSeek(internal_seek_time); | 295 chunk_demuxer_->StartWaitingForSeek(internal_seek_time); |
| 296 } | 296 } |
| 297 | 297 |
| 298 SeekInternal(internal_seek_time); | 298 SeekInternal(internal_seek_time); |
| 299 } | 299 } |
| 300 | 300 |
| 301 void MediaSourceDelegate::SeekInternal(const base::TimeDelta& seek_time) { | 301 void MediaSourceDelegate::SeekInternal(const base::TimeDelta& seek_time) { |
| 302 DCHECK(media_loop_->BelongsToCurrentThread()); | 302 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 303 DCHECK(IsSeeking()); | 303 DCHECK(IsSeeking()); |
| 304 chunk_demuxer_->Seek(seek_time, base::Bind( | 304 chunk_demuxer_->Seek(seek_time, base::Bind( |
| 305 &MediaSourceDelegate::OnDemuxerSeekDone, | 305 &MediaSourceDelegate::OnDemuxerSeekDone, |
| 306 media_weak_factory_.GetWeakPtr())); | 306 media_weak_factory_.GetWeakPtr())); |
| 307 } | 307 } |
| 308 | 308 |
| 309 void MediaSourceDelegate::AddBufferedTimeRange(base::TimeDelta start, | 309 void MediaSourceDelegate::AddBufferedTimeRange(base::TimeDelta start, |
| 310 base::TimeDelta end) { | 310 base::TimeDelta end) { |
| 311 buffered_time_ranges_.Add(start, end); | 311 buffered_time_ranges_.Add(start, end); |
| 312 } | 312 } |
| 313 | 313 |
| 314 void MediaSourceDelegate::SetDuration(base::TimeDelta duration) { | 314 void MediaSourceDelegate::SetDuration(base::TimeDelta duration) { |
| 315 DCHECK(main_loop_->BelongsToCurrentThread()); | 315 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 316 DVLOG(1) << __FUNCTION__ << "(" << duration.InSecondsF() << ") : " | 316 DVLOG(1) << __FUNCTION__ << "(" << duration.InSecondsF() << ") : " |
| 317 << demuxer_client_id_; | 317 << demuxer_client_id_; |
| 318 | 318 |
| 319 // Force duration change notification to be async to avoid reentrancy into | 319 // Force duration change notification to be async to avoid reentrancy into |
| 320 // ChunkDemxuer. | 320 // ChunkDemxuer. |
| 321 main_loop_->PostTask(FROM_HERE, base::Bind( | 321 main_task_runner_->PostTask(FROM_HERE, base::Bind( |
| 322 &MediaSourceDelegate::OnDurationChanged, main_weak_this_, duration)); | 322 &MediaSourceDelegate::OnDurationChanged, main_weak_this_, duration)); |
| 323 } | 323 } |
| 324 | 324 |
| 325 void MediaSourceDelegate::OnDurationChanged(const base::TimeDelta& duration) { | 325 void MediaSourceDelegate::OnDurationChanged(const base::TimeDelta& duration) { |
| 326 DCHECK(main_loop_->BelongsToCurrentThread()); | 326 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 327 if (demuxer_client_) | 327 if (demuxer_client_) |
| 328 demuxer_client_->DurationChanged(demuxer_client_id_, duration); | 328 demuxer_client_->DurationChanged(demuxer_client_id_, duration); |
| 329 if (!duration_change_cb_.is_null()) | 329 if (!duration_change_cb_.is_null()) |
| 330 duration_change_cb_.Run(duration); | 330 duration_change_cb_.Run(duration); |
| 331 } | 331 } |
| 332 | 332 |
| 333 void MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type) { | 333 void MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type) { |
| 334 DCHECK(media_loop_->BelongsToCurrentThread()); | 334 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 335 DVLOG(1) << __FUNCTION__ << "(" << type << ") : " << demuxer_client_id_; | 335 DVLOG(1) << __FUNCTION__ << "(" << type << ") : " << demuxer_client_id_; |
| 336 if (IsSeeking()) | 336 if (IsSeeking()) |
| 337 return; // Drop the request during seeking. | 337 return; // Drop the request during seeking. |
| 338 | 338 |
| 339 DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO); | 339 DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO); |
| 340 // The access unit size should have been initialized properly at this stage. | 340 // The access unit size should have been initialized properly at this stage. |
| 341 DCHECK_GT(access_unit_size_, 0u); | 341 DCHECK_GT(access_unit_size_, 0u); |
| 342 scoped_ptr<DemuxerData> data(new DemuxerData()); | 342 scoped_ptr<DemuxerData> data(new DemuxerData()); |
| 343 data->type = type; | 343 data->type = type; |
| 344 data->access_units.resize(access_unit_size_); | 344 data->access_units.resize(access_unit_size_); |
| 345 ReadFromDemuxerStream(type, data.Pass(), 0); | 345 ReadFromDemuxerStream(type, data.Pass(), 0); |
| 346 } | 346 } |
| 347 | 347 |
| 348 void MediaSourceDelegate::ReadFromDemuxerStream(media::DemuxerStream::Type type, | 348 void MediaSourceDelegate::ReadFromDemuxerStream(media::DemuxerStream::Type type, |
| 349 scoped_ptr<DemuxerData> data, | 349 scoped_ptr<DemuxerData> data, |
| 350 size_t index) { | 350 size_t index) { |
| 351 DCHECK(media_loop_->BelongsToCurrentThread()); | 351 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 352 // DemuxerStream::Read() always returns the read callback asynchronously. | 352 // DemuxerStream::Read() always returns the read callback asynchronously. |
| 353 DemuxerStream* stream = | 353 DemuxerStream* stream = |
| 354 (type == DemuxerStream::AUDIO) ? audio_stream_ : video_stream_; | 354 (type == DemuxerStream::AUDIO) ? audio_stream_ : video_stream_; |
| 355 stream->Read(base::Bind( | 355 stream->Read(base::Bind( |
| 356 &MediaSourceDelegate::OnBufferReady, | 356 &MediaSourceDelegate::OnBufferReady, |
| 357 media_weak_factory_.GetWeakPtr(), type, base::Passed(&data), index)); | 357 media_weak_factory_.GetWeakPtr(), type, base::Passed(&data), index)); |
| 358 } | 358 } |
| 359 | 359 |
| 360 void MediaSourceDelegate::OnBufferReady( | 360 void MediaSourceDelegate::OnBufferReady( |
| 361 media::DemuxerStream::Type type, | 361 media::DemuxerStream::Type type, |
| 362 scoped_ptr<DemuxerData> data, | 362 scoped_ptr<DemuxerData> data, |
| 363 size_t index, | 363 size_t index, |
| 364 DemuxerStream::Status status, | 364 DemuxerStream::Status status, |
| 365 const scoped_refptr<media::DecoderBuffer>& buffer) { | 365 const scoped_refptr<media::DecoderBuffer>& buffer) { |
| 366 DCHECK(media_loop_->BelongsToCurrentThread()); | 366 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 367 DVLOG(1) << __FUNCTION__ << "(" << index << ", " << status << ", " | 367 DVLOG(1) << __FUNCTION__ << "(" << index << ", " << status << ", " |
| 368 << ((!buffer || buffer->end_of_stream()) ? | 368 << ((!buffer || buffer->end_of_stream()) ? |
| 369 -1 : buffer->timestamp().InMilliseconds()) | 369 -1 : buffer->timestamp().InMilliseconds()) |
| 370 << ") : " << demuxer_client_id_; | 370 << ") : " << demuxer_client_id_; |
| 371 DCHECK(chunk_demuxer_); | 371 DCHECK(chunk_demuxer_); |
| 372 | 372 |
| 373 // No new OnReadFromDemuxer() will be called during seeking. So this callback | 373 // No new OnReadFromDemuxer() will be called during seeking. So this callback |
| 374 // must be from previous OnReadFromDemuxer() call and should be ignored. | 374 // must be from previous OnReadFromDemuxer() call and should be ignored. |
| 375 if (IsSeeking()) { | 375 if (IsSeeking()) { |
| 376 DVLOG(1) << __FUNCTION__ << ": Ignore previous read during seeking."; | 376 DVLOG(1) << __FUNCTION__ << ": Ignore previous read during seeking."; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 NOTIMPLEMENTED(); | 474 NOTIMPLEMENTED(); |
| 475 } | 475 } |
| 476 | 476 |
| 477 void MediaSourceDelegate::RemoveTextStream( | 477 void MediaSourceDelegate::RemoveTextStream( |
| 478 media::DemuxerStream* /* text_stream */ ) { | 478 media::DemuxerStream* /* text_stream */ ) { |
| 479 // TODO(matthewjheaney): remove text stream (http://crbug/322115). | 479 // TODO(matthewjheaney): remove text stream (http://crbug/322115). |
| 480 NOTIMPLEMENTED(); | 480 NOTIMPLEMENTED(); |
| 481 } | 481 } |
| 482 | 482 |
| 483 void MediaSourceDelegate::OnDemuxerInitDone(media::PipelineStatus status) { | 483 void MediaSourceDelegate::OnDemuxerInitDone(media::PipelineStatus status) { |
| 484 DCHECK(media_loop_->BelongsToCurrentThread()); | 484 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 485 DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; | 485 DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; |
| 486 DCHECK(chunk_demuxer_); | 486 DCHECK(chunk_demuxer_); |
| 487 | 487 |
| 488 if (status != media::PIPELINE_OK) { | 488 if (status != media::PIPELINE_OK) { |
| 489 OnDemuxerError(status); | 489 OnDemuxerError(status); |
| 490 return; | 490 return; |
| 491 } | 491 } |
| 492 | 492 |
| 493 audio_stream_ = chunk_demuxer_->GetStream(DemuxerStream::AUDIO); | 493 audio_stream_ = chunk_demuxer_->GetStream(DemuxerStream::AUDIO); |
| 494 video_stream_ = chunk_demuxer_->GetStream(DemuxerStream::VIDEO); | 494 video_stream_ = chunk_demuxer_->GetStream(DemuxerStream::VIDEO); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 506 InitVideoDecryptingDemuxerStream(); | 506 InitVideoDecryptingDemuxerStream(); |
| 507 return; | 507 return; |
| 508 } | 508 } |
| 509 | 509 |
| 510 // Notify demuxer ready when both streams are not encrypted. | 510 // Notify demuxer ready when both streams are not encrypted. |
| 511 is_demuxer_ready_ = true; | 511 is_demuxer_ready_ = true; |
| 512 NotifyDemuxerReady(); | 512 NotifyDemuxerReady(); |
| 513 } | 513 } |
| 514 | 514 |
| 515 void MediaSourceDelegate::InitAudioDecryptingDemuxerStream() { | 515 void MediaSourceDelegate::InitAudioDecryptingDemuxerStream() { |
| 516 DCHECK(media_loop_->BelongsToCurrentThread()); | 516 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 517 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 517 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
| 518 DCHECK(!set_decryptor_ready_cb_.is_null()); | 518 DCHECK(!set_decryptor_ready_cb_.is_null()); |
| 519 | 519 |
| 520 audio_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream( | 520 audio_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream( |
| 521 media_loop_, set_decryptor_ready_cb_)); | 521 media_task_runner_, set_decryptor_ready_cb_)); |
| 522 audio_decrypting_demuxer_stream_->Initialize( | 522 audio_decrypting_demuxer_stream_->Initialize( |
| 523 audio_stream_, | 523 audio_stream_, |
| 524 base::Bind(&MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone, | 524 base::Bind(&MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone, |
| 525 media_weak_factory_.GetWeakPtr())); | 525 media_weak_factory_.GetWeakPtr())); |
| 526 } | 526 } |
| 527 | 527 |
| 528 void MediaSourceDelegate::InitVideoDecryptingDemuxerStream() { | 528 void MediaSourceDelegate::InitVideoDecryptingDemuxerStream() { |
| 529 DCHECK(media_loop_->BelongsToCurrentThread()); | 529 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 530 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 530 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
| 531 DCHECK(!set_decryptor_ready_cb_.is_null()); | 531 DCHECK(!set_decryptor_ready_cb_.is_null()); |
| 532 | 532 |
| 533 video_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream( | 533 video_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream( |
| 534 media_loop_, set_decryptor_ready_cb_)); | 534 media_task_runner_, set_decryptor_ready_cb_)); |
| 535 video_decrypting_demuxer_stream_->Initialize( | 535 video_decrypting_demuxer_stream_->Initialize( |
| 536 video_stream_, | 536 video_stream_, |
| 537 base::Bind(&MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone, | 537 base::Bind(&MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone, |
| 538 media_weak_factory_.GetWeakPtr())); | 538 media_weak_factory_.GetWeakPtr())); |
| 539 } | 539 } |
| 540 | 540 |
| 541 void MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone( | 541 void MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone( |
| 542 media::PipelineStatus status) { | 542 media::PipelineStatus status) { |
| 543 DCHECK(media_loop_->BelongsToCurrentThread()); | 543 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 544 DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; | 544 DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; |
| 545 DCHECK(chunk_demuxer_); | 545 DCHECK(chunk_demuxer_); |
| 546 | 546 |
| 547 if (status != media::PIPELINE_OK) | 547 if (status != media::PIPELINE_OK) |
| 548 audio_decrypting_demuxer_stream_.reset(); | 548 audio_decrypting_demuxer_stream_.reset(); |
| 549 else | 549 else |
| 550 audio_stream_ = audio_decrypting_demuxer_stream_.get(); | 550 audio_stream_ = audio_decrypting_demuxer_stream_.get(); |
| 551 | 551 |
| 552 if (video_stream_ && video_stream_->video_decoder_config().is_encrypted()) { | 552 if (video_stream_ && video_stream_->video_decoder_config().is_encrypted()) { |
| 553 InitVideoDecryptingDemuxerStream(); | 553 InitVideoDecryptingDemuxerStream(); |
| 554 return; | 554 return; |
| 555 } | 555 } |
| 556 | 556 |
| 557 // Try to notify demuxer ready when audio DDS initialization finished and | 557 // Try to notify demuxer ready when audio DDS initialization finished and |
| 558 // video is not encrypted. | 558 // video is not encrypted. |
| 559 is_demuxer_ready_ = true; | 559 is_demuxer_ready_ = true; |
| 560 NotifyDemuxerReady(); | 560 NotifyDemuxerReady(); |
| 561 } | 561 } |
| 562 | 562 |
| 563 void MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone( | 563 void MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone( |
| 564 media::PipelineStatus status) { | 564 media::PipelineStatus status) { |
| 565 DCHECK(media_loop_->BelongsToCurrentThread()); | 565 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 566 DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; | 566 DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; |
| 567 DCHECK(chunk_demuxer_); | 567 DCHECK(chunk_demuxer_); |
| 568 | 568 |
| 569 if (status != media::PIPELINE_OK) | 569 if (status != media::PIPELINE_OK) |
| 570 video_decrypting_demuxer_stream_.reset(); | 570 video_decrypting_demuxer_stream_.reset(); |
| 571 else | 571 else |
| 572 video_stream_ = video_decrypting_demuxer_stream_.get(); | 572 video_stream_ = video_decrypting_demuxer_stream_.get(); |
| 573 | 573 |
| 574 // Try to notify demuxer ready when video DDS initialization finished. | 574 // Try to notify demuxer ready when video DDS initialization finished. |
| 575 is_demuxer_ready_ = true; | 575 is_demuxer_ready_ = true; |
| 576 NotifyDemuxerReady(); | 576 NotifyDemuxerReady(); |
| 577 } | 577 } |
| 578 | 578 |
| 579 void MediaSourceDelegate::OnDemuxerSeekDone(media::PipelineStatus status) { | 579 void MediaSourceDelegate::OnDemuxerSeekDone(media::PipelineStatus status) { |
| 580 DCHECK(media_loop_->BelongsToCurrentThread()); | 580 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 581 DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; | 581 DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; |
| 582 DCHECK(IsSeeking()); | 582 DCHECK(IsSeeking()); |
| 583 | 583 |
| 584 if (status != media::PIPELINE_OK) { | 584 if (status != media::PIPELINE_OK) { |
| 585 OnDemuxerError(status); | 585 OnDemuxerError(status); |
| 586 return; | 586 return; |
| 587 } | 587 } |
| 588 | 588 |
| 589 ResetAudioDecryptingDemuxerStream(); | 589 ResetAudioDecryptingDemuxerStream(); |
| 590 } | 590 } |
| 591 | 591 |
| 592 void MediaSourceDelegate::ResetAudioDecryptingDemuxerStream() { | 592 void MediaSourceDelegate::ResetAudioDecryptingDemuxerStream() { |
| 593 DCHECK(media_loop_->BelongsToCurrentThread()); | 593 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 594 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 594 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
| 595 if (audio_decrypting_demuxer_stream_) { | 595 if (audio_decrypting_demuxer_stream_) { |
| 596 audio_decrypting_demuxer_stream_->Reset( | 596 audio_decrypting_demuxer_stream_->Reset( |
| 597 base::Bind(&MediaSourceDelegate::ResetVideoDecryptingDemuxerStream, | 597 base::Bind(&MediaSourceDelegate::ResetVideoDecryptingDemuxerStream, |
| 598 media_weak_factory_.GetWeakPtr())); | 598 media_weak_factory_.GetWeakPtr())); |
| 599 return; | 599 return; |
| 600 } | 600 } |
| 601 | 601 |
| 602 ResetVideoDecryptingDemuxerStream(); | 602 ResetVideoDecryptingDemuxerStream(); |
| 603 } | 603 } |
| 604 | 604 |
| 605 void MediaSourceDelegate::ResetVideoDecryptingDemuxerStream() { | 605 void MediaSourceDelegate::ResetVideoDecryptingDemuxerStream() { |
| 606 DCHECK(media_loop_->BelongsToCurrentThread()); | 606 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 607 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 607 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
| 608 if (video_decrypting_demuxer_stream_) { | 608 if (video_decrypting_demuxer_stream_) { |
| 609 video_decrypting_demuxer_stream_->Reset(base::Bind( | 609 video_decrypting_demuxer_stream_->Reset(base::Bind( |
| 610 &MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams, | 610 &MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams, |
| 611 media_weak_factory_.GetWeakPtr())); | 611 media_weak_factory_.GetWeakPtr())); |
| 612 return; | 612 return; |
| 613 } | 613 } |
| 614 | 614 |
| 615 FinishResettingDecryptingDemuxerStreams(); | 615 FinishResettingDecryptingDemuxerStreams(); |
| 616 } | 616 } |
| 617 | 617 |
| 618 void MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams() { | 618 void MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams() { |
| 619 DCHECK(media_loop_->BelongsToCurrentThread()); | 619 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 620 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 620 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
| 621 | 621 |
| 622 base::AutoLock auto_lock(seeking_lock_); | 622 base::AutoLock auto_lock(seeking_lock_); |
| 623 DCHECK(seeking_); | 623 DCHECK(seeking_); |
| 624 seeking_ = false; | 624 seeking_ = false; |
| 625 doing_browser_seek_ = false; | 625 doing_browser_seek_ = false; |
| 626 demuxer_client_->DemuxerSeekDone(demuxer_client_id_, browser_seek_time_); | 626 demuxer_client_->DemuxerSeekDone(demuxer_client_id_, browser_seek_time_); |
| 627 } | 627 } |
| 628 | 628 |
| 629 void MediaSourceDelegate::OnDemuxerStopDone() { | 629 void MediaSourceDelegate::OnDemuxerStopDone() { |
| 630 DCHECK(media_loop_->BelongsToCurrentThread()); | 630 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 631 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 631 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
| 632 main_loop_->PostTask( | 632 main_task_runner_->PostTask( |
| 633 FROM_HERE, | 633 FROM_HERE, |
| 634 base::Bind(&MediaSourceDelegate::DeleteSelf, base::Unretained(this))); | 634 base::Bind(&MediaSourceDelegate::DeleteSelf, base::Unretained(this))); |
| 635 } | 635 } |
| 636 | 636 |
| 637 void MediaSourceDelegate::DeleteSelf() { | 637 void MediaSourceDelegate::DeleteSelf() { |
| 638 DCHECK(main_loop_->BelongsToCurrentThread()); | 638 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 639 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 639 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
| 640 chunk_demuxer_.reset(); | 640 chunk_demuxer_.reset(); |
| 641 delete this; | 641 delete this; |
| 642 } | 642 } |
| 643 | 643 |
| 644 void MediaSourceDelegate::NotifyDemuxerReady() { | 644 void MediaSourceDelegate::NotifyDemuxerReady() { |
| 645 DCHECK(media_loop_->BelongsToCurrentThread()); | 645 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 646 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; | 646 DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; |
| 647 DCHECK(is_demuxer_ready_); | 647 DCHECK(is_demuxer_ready_); |
| 648 | 648 |
| 649 scoped_ptr<DemuxerConfigs> configs(new DemuxerConfigs()); | 649 scoped_ptr<DemuxerConfigs> configs(new DemuxerConfigs()); |
| 650 GetDemuxerConfigFromStream(configs.get(), true); | 650 GetDemuxerConfigFromStream(configs.get(), true); |
| 651 GetDemuxerConfigFromStream(configs.get(), false); | 651 GetDemuxerConfigFromStream(configs.get(), false); |
| 652 configs->duration = GetDuration(); | 652 configs->duration = GetDuration(); |
| 653 | 653 |
| 654 if (demuxer_client_) | 654 if (demuxer_client_) |
| 655 demuxer_client_->DemuxerReady(demuxer_client_id_, *configs); | 655 demuxer_client_->DemuxerReady(demuxer_client_id_, *configs); |
| 656 | 656 |
| 657 base::AutoLock auto_lock(is_video_encrypted_lock_); | 657 base::AutoLock auto_lock(is_video_encrypted_lock_); |
| 658 is_video_encrypted_ = configs->is_video_encrypted; | 658 is_video_encrypted_ = configs->is_video_encrypted; |
| 659 } | 659 } |
| 660 | 660 |
| 661 base::TimeDelta MediaSourceDelegate::GetDuration() const { | 661 base::TimeDelta MediaSourceDelegate::GetDuration() const { |
| 662 DCHECK(media_loop_->BelongsToCurrentThread()); | 662 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 663 if (!chunk_demuxer_) | 663 if (!chunk_demuxer_) |
| 664 return media::kNoTimestamp(); | 664 return media::kNoTimestamp(); |
| 665 | 665 |
| 666 double duration = chunk_demuxer_->GetDuration(); | 666 double duration = chunk_demuxer_->GetDuration(); |
| 667 if (duration == std::numeric_limits<double>::infinity()) | 667 if (duration == std::numeric_limits<double>::infinity()) |
| 668 return media::kInfiniteDuration(); | 668 return media::kInfiniteDuration(); |
| 669 | 669 |
| 670 return ConvertSecondsToTimestamp(duration); | 670 return ConvertSecondsToTimestamp(duration); |
| 671 } | 671 } |
| 672 | 672 |
| 673 void MediaSourceDelegate::OnDemuxerOpened() { | 673 void MediaSourceDelegate::OnDemuxerOpened() { |
| 674 DCHECK(main_loop_->BelongsToCurrentThread()); | 674 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 675 if (media_source_opened_cb_.is_null()) | 675 if (media_source_opened_cb_.is_null()) |
| 676 return; | 676 return; |
| 677 | 677 |
| 678 media_source_opened_cb_.Run(new WebMediaSourceImpl( | 678 media_source_opened_cb_.Run(new WebMediaSourceImpl( |
| 679 chunk_demuxer_.get(), base::Bind(&LogMediaSourceError, media_log_))); | 679 chunk_demuxer_.get(), base::Bind(&LogMediaSourceError, media_log_))); |
| 680 } | 680 } |
| 681 | 681 |
| 682 void MediaSourceDelegate::OnNeedKey(const std::string& type, | 682 void MediaSourceDelegate::OnNeedKey(const std::string& type, |
| 683 const std::vector<uint8>& init_data) { | 683 const std::vector<uint8>& init_data) { |
| 684 DCHECK(main_loop_->BelongsToCurrentThread()); | 684 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 685 if (need_key_cb_.is_null()) | 685 if (need_key_cb_.is_null()) |
| 686 return; | 686 return; |
| 687 | 687 |
| 688 need_key_cb_.Run(type, init_data); | 688 need_key_cb_.Run(type, init_data); |
| 689 } | 689 } |
| 690 | 690 |
| 691 bool MediaSourceDelegate::IsSeeking() const { | 691 bool MediaSourceDelegate::IsSeeking() const { |
| 692 base::AutoLock auto_lock(seeking_lock_); | 692 base::AutoLock auto_lock(seeking_lock_); |
| 693 return seeking_; | 693 return seeking_; |
| 694 } | 694 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 729 // unlikely. This may cause unexpected playback stall due to seek pending an | 729 // unlikely. This may cause unexpected playback stall due to seek pending an |
| 730 // append for a GOP prior to the last GOP demuxed. | 730 // append for a GOP prior to the last GOP demuxed. |
| 731 // TODO(wolenetz): Remove the possibility for this seek to cause unexpected | 731 // TODO(wolenetz): Remove the possibility for this seek to cause unexpected |
| 732 // player stall by replaying cached data since last keyframe in browser player | 732 // player stall by replaying cached data since last keyframe in browser player |
| 733 // rather than issuing browser seek. See http://crbug.com/304234. | 733 // rather than issuing browser seek. See http://crbug.com/304234. |
| 734 return seek_time; | 734 return seek_time; |
| 735 } | 735 } |
| 736 | 736 |
| 737 bool MediaSourceDelegate::GetDemuxerConfigFromStream( | 737 bool MediaSourceDelegate::GetDemuxerConfigFromStream( |
| 738 media::DemuxerConfigs* configs, bool is_audio) { | 738 media::DemuxerConfigs* configs, bool is_audio) { |
| 739 DCHECK(media_loop_->BelongsToCurrentThread()); | 739 DCHECK(media_task_runner_->BelongsToCurrentThread()); |
| 740 if (!is_demuxer_ready_) | 740 if (!is_demuxer_ready_) |
| 741 return false; | 741 return false; |
| 742 if (is_audio && audio_stream_) { | 742 if (is_audio && audio_stream_) { |
| 743 media::AudioDecoderConfig config = audio_stream_->audio_decoder_config(); | 743 media::AudioDecoderConfig config = audio_stream_->audio_decoder_config(); |
| 744 configs->audio_codec = config.codec(); | 744 configs->audio_codec = config.codec(); |
| 745 configs->audio_channels = | 745 configs->audio_channels = |
| 746 media::ChannelLayoutToChannelCount(config.channel_layout()); | 746 media::ChannelLayoutToChannelCount(config.channel_layout()); |
| 747 configs->audio_sampling_rate = config.samples_per_second(); | 747 configs->audio_sampling_rate = config.samples_per_second(); |
| 748 configs->is_audio_encrypted = config.is_encrypted(); | 748 configs->is_audio_encrypted = config.is_encrypted(); |
| 749 configs->audio_extra_data = std::vector<uint8>( | 749 configs->audio_extra_data = std::vector<uint8>( |
| 750 config.extra_data(), config.extra_data() + config.extra_data_size()); | 750 config.extra_data(), config.extra_data() + config.extra_data_size()); |
| 751 return true; | 751 return true; |
| 752 } | 752 } |
| 753 if (!is_audio && video_stream_) { | 753 if (!is_audio && video_stream_) { |
| 754 media::VideoDecoderConfig config = video_stream_->video_decoder_config(); | 754 media::VideoDecoderConfig config = video_stream_->video_decoder_config(); |
| 755 configs->video_codec = config.codec(); | 755 configs->video_codec = config.codec(); |
| 756 configs->video_size = config.natural_size(); | 756 configs->video_size = config.natural_size(); |
| 757 configs->is_video_encrypted = config.is_encrypted(); | 757 configs->is_video_encrypted = config.is_encrypted(); |
| 758 configs->video_extra_data = std::vector<uint8>( | 758 configs->video_extra_data = std::vector<uint8>( |
| 759 config.extra_data(), config.extra_data() + config.extra_data_size()); | 759 config.extra_data(), config.extra_data() + config.extra_data_size()); |
| 760 return true; | 760 return true; |
| 761 } | 761 } |
| 762 return false; | 762 return false; |
| 763 } | 763 } |
| 764 | 764 |
| 765 } // namespace content | 765 } // namespace content |
| OLD | NEW |