Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(385)

Side by Side Diff: media/base/android/media_source_player.cc

Issue 15499006: Enable seek in fullscreen mode for MSE impl on android (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add CancelPendingSeek() Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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 "media/base/android/media_source_player.h" 5 #include "media/base/android/media_source_player.h"
6 6
7 #include "base/android/jni_android.h" 7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h" 8 #include "base/android/jni_string.h"
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 codec->Start(audio_codec, sample_rate, channel_count, extra_data, 185 codec->Start(audio_codec, sample_rate, channel_count, extra_data,
186 extra_data_size, true); 186 extra_data_size, true);
187 media_codec_bridge_.reset(codec.release()); 187 media_codec_bridge_.reset(codec.release());
188 thread_.reset(new base::Thread("MediaSource_AudioDecoderThread")); 188 thread_.reset(new base::Thread("MediaSource_AudioDecoderThread"));
189 } 189 }
190 190
191 MediaSourcePlayer::MediaSourcePlayer( 191 MediaSourcePlayer::MediaSourcePlayer(
192 int player_id, 192 int player_id,
193 MediaPlayerManager* manager) 193 MediaPlayerManager* manager)
194 : MediaPlayerAndroid(player_id, manager), 194 : MediaPlayerAndroid(player_id, manager),
195 pending_play_(false), 195 pending_event_(NO_EVENT_PENDING),
196 active_decoding_tasks_(0),
196 width_(0), 197 width_(0),
197 height_(0), 198 height_(0),
198 audio_codec_(kUnknownAudioCodec), 199 audio_codec_(kUnknownAudioCodec),
199 video_codec_(kUnknownVideoCodec), 200 video_codec_(kUnknownVideoCodec),
200 num_channels_(0), 201 num_channels_(0),
201 sampling_rate_(0), 202 sampling_rate_(0),
202 seekable_(true), 203 seekable_(true),
203 audio_finished_(true), 204 audio_finished_(true),
204 video_finished_(true), 205 video_finished_(true),
205 playing_(false), 206 playing_(false),
206 audio_access_unit_index_(0), 207 audio_access_unit_index_(0),
207 video_access_unit_index_(0), 208 video_access_unit_index_(0),
208 waiting_for_audio_data_(false), 209 waiting_for_audio_data_(false),
209 waiting_for_video_data_(false), 210 waiting_for_video_data_(false),
211 use_empty_surface_(true),
210 weak_this_(this) { 212 weak_this_(this) {
211 OnMediaMetadataChanged(duration_, width_, height_, false);
212 } 213 }
213 214
214 MediaSourcePlayer::~MediaSourcePlayer() { 215 MediaSourcePlayer::~MediaSourcePlayer() {
215 Release(); 216 Release();
216 } 217 }
217 218
218 void MediaSourcePlayer::SetVideoSurface(jobject surface) { 219 void MediaSourcePlayer::SetVideoSurface(jobject surface) {
219 video_decoder_job_.reset(); 220 use_empty_surface_ = surface ? false : true;
220 if (!surface) { 221
222 // If we haven't processed a surface change event, do so now.
223 if (active_decoding_tasks_ > 0) {
224 pending_event_ |= SURFACE_CHANGE_EVENT_PENDING;
225 // Request a seek so that the next decoder will decode an I-frame first.
226 // Or otherwise, MediaCodec might crash. See b/8950387.
227 pending_event_ |= SEEK_EVENT_PENDING;
228 ProcessPendingEvents();
221 return; 229 return;
222 } 230 }
223 231
224 video_decoder_job_.reset(new VideoDecoderJob( 232 video_decoder_job_.reset(new VideoDecoderJob(
225 base::MessageLoopProxy::current(), video_codec_, 233 base::MessageLoopProxy::current(), video_codec_,
226 gfx::Size(width_, height_), surface)); 234 gfx::Size(width_, height_), surface));
227 235
228 if (pending_play_)
229 StartInternal();
230
231 // Inform the fullscreen view the player is ready. 236 // Inform the fullscreen view the player is ready.
232 // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way 237 // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way
233 // to inform ContentVideoView. 238 // to inform ContentVideoView.
234 OnMediaMetadataChanged(duration_, width_, height_, true); 239 OnMediaMetadataChanged(duration_, width_, height_, true);
240
241 if (pending_event_ & SURFACE_CHANGE_EVENT_PENDING) {
242 // We should already performed a seek in this case.
243 pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
acolwell GONE FROM CHROMIUM 2013/05/23 20:58:27 nit: DCHECK_EQ(pending_event_ & SEEK_EVENT_PENDING
qinmin 2013/05/23 22:03:36 We cannot guarantee the bit is cleared at this tim
244 } else {
245 // Perform a seek so the new decoder can get the I-frame first.
246 pending_event_ |= SEEK_EVENT_PENDING;
247 ProcessPendingEvents();
248 return;
249 }
250
251 if (playing_)
252 StartInternal();
235 } 253 }
236 254
237 void MediaSourcePlayer::Start() { 255 void MediaSourcePlayer::Start() {
256 playing_ = true;
238 if (HasAudio() && !audio_decoder_job_) { 257 if (HasAudio() && !audio_decoder_job_) {
239 audio_decoder_job_.reset(new AudioDecoderJob( 258 audio_decoder_job_.reset(new AudioDecoderJob(
240 base::MessageLoopProxy::current(), audio_codec_, sampling_rate_, 259 base::MessageLoopProxy::current(), audio_codec_, sampling_rate_,
241 num_channels_, &audio_extra_data_[0], audio_extra_data_.size())); 260 num_channels_, &audio_extra_data_[0], audio_extra_data_.size()));
242 } 261 }
243 262
244 if (HasVideo() && !video_decoder_job_) { 263 if (HasVideo() && !video_decoder_job_) {
245 // StartInternal() will be delayed until SetVideoSurface() gets called. 264 // StartInternal() will be delayed until SetVideoSurface() gets called.
246 pending_play_ = true;
247 return; 265 return;
248 } 266 }
249 267
250 StartInternal(); 268 StartInternal();
251 } 269 }
252 270
253 void MediaSourcePlayer::Pause() { 271 void MediaSourcePlayer::Pause() {
254 pending_play_ = false;
255 playing_ = false; 272 playing_ = false;
256 start_wallclock_time_ = base::Time(); 273 start_wallclock_time_ = base::Time();
257 } 274 }
258 275
259 bool MediaSourcePlayer::IsPlaying() { 276 bool MediaSourcePlayer::IsPlaying() {
260 return pending_play_ || playing_; 277 return playing_;
261 } 278 }
262 279
263 int MediaSourcePlayer::GetVideoWidth() { 280 int MediaSourcePlayer::GetVideoWidth() {
264 return width_; 281 return width_;
265 } 282 }
266 283
267 int MediaSourcePlayer::GetVideoHeight() { 284 int MediaSourcePlayer::GetVideoHeight() {
268 return height_; 285 return height_;
269 } 286 }
270 287
271 void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) { 288 void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) {
272 last_presentation_timestamp_ = timestamp; 289 last_presentation_timestamp_ = timestamp;
273 start_wallclock_time_ = base::Time(); 290 pending_event_ |= SEEK_EVENT_PENDING;
274 last_seek_time_ = base::Time::Now(); 291 ProcessPendingEvents();
275 if (audio_decoder_job_)
276 audio_decoder_job_->Flush();
277 if (video_decoder_job_)
278 video_decoder_job_->Flush();
279 received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
280 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
281 audio_access_unit_index_ = 0;
282 video_access_unit_index_ = 0;
283 OnSeekComplete();
284 } 292 }
285 293
286 base::TimeDelta MediaSourcePlayer::GetCurrentTime() { 294 base::TimeDelta MediaSourcePlayer::GetCurrentTime() {
287 return last_presentation_timestamp_; 295 return last_presentation_timestamp_;
288 } 296 }
289 297
290 base::TimeDelta MediaSourcePlayer::GetDuration() { 298 base::TimeDelta MediaSourcePlayer::GetDuration() {
291 return duration_; 299 return duration_;
292 } 300 }
293 301
294 void MediaSourcePlayer::Release() { 302 void MediaSourcePlayer::Release() {
303 ClearDecodingData();
295 audio_decoder_job_.reset(); 304 audio_decoder_job_.reset();
296 video_decoder_job_.reset(); 305 video_decoder_job_.reset();
306 active_decoding_tasks_ = 0;
307 playing_ = false;
308 pending_event_ = NO_EVENT_PENDING;
297 ReleaseMediaResourcesFromManager(); 309 ReleaseMediaResourcesFromManager();
298 } 310 }
299 311
300 void MediaSourcePlayer::SetVolume(float leftVolume, float rightVolume) { 312 void MediaSourcePlayer::SetVolume(float leftVolume, float rightVolume) {
301 } 313 }
302 314
303 bool MediaSourcePlayer::CanPause() { 315 bool MediaSourcePlayer::CanPause() {
304 return seekable_; 316 return seekable_;
305 } 317 }
306 318
307 bool MediaSourcePlayer::CanSeekForward() { 319 bool MediaSourcePlayer::CanSeekForward() {
308 return seekable_; 320 return seekable_;
309 } 321 }
310 322
311 bool MediaSourcePlayer::CanSeekBackward() { 323 bool MediaSourcePlayer::CanSeekBackward() {
312 return seekable_; 324 return seekable_;
313 } 325 }
314 326
315 bool MediaSourcePlayer::IsPlayerReady() { 327 bool MediaSourcePlayer::IsPlayerReady() {
316 return audio_decoder_job_ || video_decoder_job_; 328 return audio_decoder_job_ || video_decoder_job_;
317 } 329 }
318 330
319 void MediaSourcePlayer::StartInternal() { 331 void MediaSourcePlayer::StartInternal() {
320 if (playing_) 332 // Do nothing if the decoders are already running.
333 if (active_decoding_tasks_ > 0 || pending_event_ != NO_EVENT_PENDING)
321 return; 334 return;
322 playing_ = true;
323 335
324 if (HasAudio()) { 336 if (HasAudio()) {
325 audio_finished_ = false; 337 audio_finished_ = false;
326 DecodeMoreAudio(); 338 DecodeMoreAudio();
327 } 339 }
328 if (HasVideo()) { 340 if (HasVideo()) {
329 video_finished_ = false; 341 video_finished_ = false;
330 DecodeMoreVideo(); 342 DecodeMoreVideo();
331 } 343 }
332 } 344 }
333 345
334 void MediaSourcePlayer::DemuxerReady( 346 void MediaSourcePlayer::DemuxerReady(
335 const MediaPlayerHostMsg_DemuxerReady_Params& params) { 347 const MediaPlayerHostMsg_DemuxerReady_Params& params) {
336 if (params.duration_ms == std::numeric_limits<int>::max()) 348 if (params.duration_ms == std::numeric_limits<int>::max())
337 seekable_ = false; 349 seekable_ = false;
338 duration_ = base::TimeDelta::FromMilliseconds(params.duration_ms); 350 duration_ = base::TimeDelta::FromMilliseconds(params.duration_ms);
339 width_ = params.video_size.width(); 351 width_ = params.video_size.width();
340 height_ = params.video_size.height(); 352 height_ = params.video_size.height();
341 num_channels_ = params.audio_channels; 353 num_channels_ = params.audio_channels;
342 sampling_rate_ = params.audio_sampling_rate; 354 sampling_rate_ = params.audio_sampling_rate;
343 audio_codec_ = params.audio_codec; 355 audio_codec_ = params.audio_codec;
344 video_codec_ = params.video_codec; 356 video_codec_ = params.video_codec;
345 audio_extra_data_ = params.audio_extra_data; 357 audio_extra_data_ = params.audio_extra_data;
346 OnMediaMetadataChanged(duration_, width_, height_, true); 358 OnMediaMetadataChanged(duration_, width_, height_, true);
347 } 359 }
348 360
349 void MediaSourcePlayer::ReadFromDemuxerAck( 361 void MediaSourcePlayer::ReadFromDemuxerAck(
350 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) { 362 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) {
363 if (params.type == DemuxerStream::AUDIO)
364 waiting_for_audio_data_ = false;
365 else
366 waiting_for_video_data_ = false;
367
368 // If there is a pending seek request, ignore the data from the chunk demuxer.
369 // The data will be requested later when OnSeekRequestAck() is called.
370 if (pending_event_ & SEEK_EVENT_PENDING)
371 return;
372
351 if (params.type == DemuxerStream::AUDIO) { 373 if (params.type == DemuxerStream::AUDIO) {
352 DCHECK_EQ(0u, audio_access_unit_index_); 374 DCHECK_EQ(0u, audio_access_unit_index_);
353 received_audio_ = params; 375 received_audio_ = params;
354 waiting_for_audio_data_ = false; 376 if (!pending_event_)
355 DecodeMoreAudio(); 377 DecodeMoreAudio();
356 } else { 378 } else {
357 DCHECK_EQ(0u, video_access_unit_index_); 379 DCHECK_EQ(0u, video_access_unit_index_);
358 received_video_ = params; 380 received_video_ = params;
359 waiting_for_video_data_ = false; 381 if (!pending_event_)
360 DecodeMoreVideo(); 382 DecodeMoreVideo();
361 } 383 }
362 } 384 }
363 385
386 void MediaSourcePlayer::OnSeekRequestAck() {
387 pending_event_ &= ~SEEK_EVENT_PENDING;
388 OnSeekComplete();
389 if (playing_)
390 StartInternal();
391 }
392
364 void MediaSourcePlayer::UpdateTimestamps( 393 void MediaSourcePlayer::UpdateTimestamps(
365 const base::Time& kickoff_time,
366 const base::TimeDelta& presentation_timestamp, 394 const base::TimeDelta& presentation_timestamp,
367 const base::Time& wallclock_time) { 395 const base::Time& wallclock_time) {
368 // If the job was posted after last seek, update the presentation time. 396 last_presentation_timestamp_ = presentation_timestamp;
369 // Otherwise, ignore it. 397 OnTimeUpdated();
370 if (kickoff_time > last_seek_time_) { 398 if (start_wallclock_time_.is_null() && playing_) {
371 last_presentation_timestamp_ = presentation_timestamp; 399 start_wallclock_time_ = wallclock_time;
372 OnTimeUpdated(); 400 start_presentation_timestamp_ = last_presentation_timestamp_;
373 if (start_wallclock_time_.is_null() && playing_) {
374 start_wallclock_time_ = wallclock_time;
375 start_presentation_timestamp_ = last_presentation_timestamp_;
376 }
377 } 401 }
378 } 402 }
379 403
404 void MediaSourcePlayer::ProcessPendingEvents() {
405 // Wait for all the decoding jobs to finish before sending a seek request.
406 if (active_decoding_tasks_ > 0)
407 return;
408
409 DCHECK(pending_event_ != NO_EVENT_PENDING);
410 if (use_empty_surface_ && (pending_event_ & SURFACE_CHANGE_EVENT_PENDING)) {
411 video_decoder_job_.reset();
412 pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
413 }
414
415 ClearDecodingData();
416 manager()->OnMediaSeekRequest(player_id(),
417 last_presentation_timestamp_,
418 pending_event_ & SURFACE_CHANGE_EVENT_PENDING);
419 }
420
380 void MediaSourcePlayer::MediaDecoderCallback( 421 void MediaSourcePlayer::MediaDecoderCallback(
381 bool is_audio, const base::Time& kickoff_time, 422 bool is_audio, const base::TimeDelta& presentation_timestamp,
382 const base::TimeDelta& presentation_timestamp,
383 const base::Time& wallclock_time, bool end_of_stream) { 423 const base::Time& wallclock_time, bool end_of_stream) {
424 if (active_decoding_tasks_ > 0)
425 active_decoding_tasks_--;
426
427 if (pending_event_ != NO_EVENT_PENDING) {
428 ProcessPendingEvents();
429 return;
430 }
431
384 if (is_audio || !HasAudio()) 432 if (is_audio || !HasAudio())
385 UpdateTimestamps(kickoff_time, presentation_timestamp, wallclock_time); 433 UpdateTimestamps(presentation_timestamp, wallclock_time);
386 434
387 if (end_of_stream) { 435 if (end_of_stream) {
388 PlaybackCompleted(is_audio); 436 PlaybackCompleted(is_audio);
389 return; 437 return;
390 } 438 }
391 439
392 if (!playing_) 440 if (!playing_)
393 return; 441 return;
394 442
395 if (is_audio) 443 if (is_audio)
(...skipping 10 matching lines...) Expand all
406 audio_access_unit_index_ = 0; 454 audio_access_unit_index_ = 0;
407 waiting_for_audio_data_ = true; 455 waiting_for_audio_data_ = true;
408 } 456 }
409 return; 457 return;
410 } 458 }
411 459
412 audio_decoder_job_->Decode( 460 audio_decoder_job_->Decode(
413 received_audio_.access_units[audio_access_unit_index_], 461 received_audio_.access_units[audio_access_unit_index_],
414 start_wallclock_time_, start_presentation_timestamp_, 462 start_wallclock_time_, start_presentation_timestamp_,
415 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, 463 base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
416 weak_this_.GetWeakPtr(), true, base::Time::Now())); 464 weak_this_.GetWeakPtr(), true));
417 ++audio_access_unit_index_; 465 active_decoding_tasks_++;
466 audio_access_unit_index_++;
418 } 467 }
419 468
420 void MediaSourcePlayer::DecodeMoreVideo() { 469 void MediaSourcePlayer::DecodeMoreVideo() {
421 if (video_access_unit_index_ >= received_video_.access_units.size()) { 470 if (video_access_unit_index_ >= received_video_.access_units.size()) {
422 if (!waiting_for_video_data_) { 471 if (!waiting_for_video_data_) {
423 manager()->OnReadFromDemuxer(player_id(), DemuxerStream::VIDEO, true); 472 manager()->OnReadFromDemuxer(player_id(), DemuxerStream::VIDEO, true);
424 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params(); 473 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
425 video_access_unit_index_ = 0; 474 video_access_unit_index_ = 0;
426 waiting_for_video_data_ = true; 475 waiting_for_video_data_ = true;
427 } 476 }
428 return; 477 return;
429 } 478 }
430 479
431 video_decoder_job_->Decode( 480 video_decoder_job_->Decode(
432 received_video_.access_units[video_access_unit_index_], 481 received_video_.access_units[video_access_unit_index_],
433 start_wallclock_time_, start_presentation_timestamp_, 482 start_wallclock_time_, start_presentation_timestamp_,
434 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, 483 base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
435 weak_this_.GetWeakPtr(), false, base::Time::Now())); 484 weak_this_.GetWeakPtr(), false));
436 ++video_access_unit_index_; 485 active_decoding_tasks_++;
486 video_access_unit_index_++;
437 } 487 }
438 488
439 489
440 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { 490 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) {
441 if (is_audio) 491 if (is_audio)
442 audio_finished_ = true; 492 audio_finished_ = true;
443 else 493 else
444 video_finished_ = true; 494 video_finished_ = true;
445 495
446 if ((!HasAudio() || audio_finished_) && (!HasVideo() || video_finished_)) { 496 if ((!HasAudio() || audio_finished_) && (!HasVideo() || video_finished_)) {
447 playing_ = false; 497 playing_ = false;
448 start_wallclock_time_ = base::Time(); 498 start_wallclock_time_ = base::Time();
449 OnPlaybackComplete(); 499 OnPlaybackComplete();
450 } 500 }
451 } 501 }
452 502
503 void MediaSourcePlayer::ClearDecodingData() {
504 if (audio_decoder_job_)
505 audio_decoder_job_->Flush();
506 if (video_decoder_job_)
507 video_decoder_job_->Flush();
508 start_wallclock_time_ = base::Time();
509 received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
510 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
511 audio_access_unit_index_ = 0;
512 video_access_unit_index_ = 0;
513 }
514
453 bool MediaSourcePlayer::HasVideo() { 515 bool MediaSourcePlayer::HasVideo() {
454 return kUnknownVideoCodec != video_codec_; 516 return kUnknownVideoCodec != video_codec_;
455 } 517 }
456 518
457 bool MediaSourcePlayer::HasAudio() { 519 bool MediaSourcePlayer::HasAudio() {
458 return kUnknownAudioCodec != audio_codec_; 520 return kUnknownAudioCodec != audio_codec_;
459 } 521 }
460 522
461 } // namespace media 523 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698