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

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: rebase 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
« no previous file with comments | « media/base/android/media_source_player.h ('k') | webkit/media/android/media_source_delegate.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 } 213 }
212 214
213 MediaSourcePlayer::~MediaSourcePlayer() { 215 MediaSourcePlayer::~MediaSourcePlayer() {
214 Release(); 216 Release();
215 } 217 }
216 218
217 void MediaSourcePlayer::SetVideoSurface(jobject surface) { 219 void MediaSourcePlayer::SetVideoSurface(jobject surface) {
218 video_decoder_job_.reset(); 220 use_empty_surface_ = surface ? false : true;
219 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();
220 return; 229 return;
221 } 230 }
222 231
223 if (HasVideo()) { 232 if (HasVideo()) {
224 video_decoder_job_.reset(new VideoDecoderJob( 233 video_decoder_job_.reset(new VideoDecoderJob(
225 base::MessageLoopProxy::current(), video_codec_, 234 base::MessageLoopProxy::current(), video_codec_,
226 gfx::Size(width_, height_), surface)); 235 gfx::Size(width_, height_), surface));
227 } 236 }
228 237
229 if (pending_play_)
230 StartInternal();
231
232 // Inform the fullscreen view the player is ready. 238 // Inform the fullscreen view the player is ready.
233 // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way 239 // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way
234 // to inform ContentVideoView. 240 // to inform ContentVideoView.
235 OnMediaMetadataChanged(duration_, width_, height_, true); 241 OnMediaMetadataChanged(duration_, width_, height_, true);
242
243 if (pending_event_ & SURFACE_CHANGE_EVENT_PENDING) {
244 // We should already requested a seek in this case.
245 pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
246 } else {
247 // Perform a seek so the new decoder can get the I-frame first.
248 pending_event_ |= SEEK_EVENT_PENDING;
249 ProcessPendingEvents();
250 return;
251 }
252
253 if (playing_)
254 StartInternal();
236 } 255 }
237 256
238 void MediaSourcePlayer::Start() { 257 void MediaSourcePlayer::Start() {
258 playing_ = true;
239 if (HasAudio() && !audio_decoder_job_) { 259 if (HasAudio() && !audio_decoder_job_) {
240 audio_decoder_job_.reset(new AudioDecoderJob( 260 audio_decoder_job_.reset(new AudioDecoderJob(
241 base::MessageLoopProxy::current(), audio_codec_, sampling_rate_, 261 base::MessageLoopProxy::current(), audio_codec_, sampling_rate_,
242 num_channels_, &audio_extra_data_[0], audio_extra_data_.size())); 262 num_channels_, &audio_extra_data_[0], audio_extra_data_.size()));
243 } 263 }
244 264
245 if (HasVideo() && !video_decoder_job_) { 265 if (HasVideo() && !video_decoder_job_) {
246 // StartInternal() will be delayed until SetVideoSurface() gets called. 266 // StartInternal() will be delayed until SetVideoSurface() gets called.
247 pending_play_ = true;
248 return; 267 return;
249 } 268 }
250 269
251 StartInternal(); 270 StartInternal();
252 } 271 }
253 272
254 void MediaSourcePlayer::Pause() { 273 void MediaSourcePlayer::Pause() {
255 pending_play_ = false;
256 playing_ = false; 274 playing_ = false;
257 start_wallclock_time_ = base::Time(); 275 start_wallclock_time_ = base::Time();
258 } 276 }
259 277
260 bool MediaSourcePlayer::IsPlaying() { 278 bool MediaSourcePlayer::IsPlaying() {
261 return pending_play_ || playing_; 279 return playing_;
262 } 280 }
263 281
264 int MediaSourcePlayer::GetVideoWidth() { 282 int MediaSourcePlayer::GetVideoWidth() {
265 return width_; 283 return width_;
266 } 284 }
267 285
268 int MediaSourcePlayer::GetVideoHeight() { 286 int MediaSourcePlayer::GetVideoHeight() {
269 return height_; 287 return height_;
270 } 288 }
271 289
272 void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) { 290 void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) {
273 last_presentation_timestamp_ = timestamp; 291 last_presentation_timestamp_ = timestamp;
274 start_wallclock_time_ = base::Time(); 292 pending_event_ |= SEEK_EVENT_PENDING;
275 last_seek_time_ = base::Time::Now(); 293 ProcessPendingEvents();
276 if (audio_decoder_job_)
277 audio_decoder_job_->Flush();
278 if (video_decoder_job_)
279 video_decoder_job_->Flush();
280 received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
281 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
282 audio_access_unit_index_ = 0;
283 video_access_unit_index_ = 0;
284 OnSeekComplete();
285 } 294 }
286 295
287 base::TimeDelta MediaSourcePlayer::GetCurrentTime() { 296 base::TimeDelta MediaSourcePlayer::GetCurrentTime() {
288 return last_presentation_timestamp_; 297 return last_presentation_timestamp_;
289 } 298 }
290 299
291 base::TimeDelta MediaSourcePlayer::GetDuration() { 300 base::TimeDelta MediaSourcePlayer::GetDuration() {
292 return duration_; 301 return duration_;
293 } 302 }
294 303
295 void MediaSourcePlayer::Release() { 304 void MediaSourcePlayer::Release() {
305 ClearDecodingData();
296 audio_decoder_job_.reset(); 306 audio_decoder_job_.reset();
297 video_decoder_job_.reset(); 307 video_decoder_job_.reset();
308 active_decoding_tasks_ = 0;
309 playing_ = false;
310 pending_event_ = NO_EVENT_PENDING;
298 ReleaseMediaResourcesFromManager(); 311 ReleaseMediaResourcesFromManager();
299 } 312 }
300 313
301 void MediaSourcePlayer::SetVolume(float leftVolume, float rightVolume) { 314 void MediaSourcePlayer::SetVolume(float leftVolume, float rightVolume) {
302 } 315 }
303 316
304 bool MediaSourcePlayer::CanPause() { 317 bool MediaSourcePlayer::CanPause() {
305 return seekable_; 318 return seekable_;
306 } 319 }
307 320
308 bool MediaSourcePlayer::CanSeekForward() { 321 bool MediaSourcePlayer::CanSeekForward() {
309 return seekable_; 322 return seekable_;
310 } 323 }
311 324
312 bool MediaSourcePlayer::CanSeekBackward() { 325 bool MediaSourcePlayer::CanSeekBackward() {
313 return seekable_; 326 return seekable_;
314 } 327 }
315 328
316 bool MediaSourcePlayer::IsPlayerReady() { 329 bool MediaSourcePlayer::IsPlayerReady() {
317 return audio_decoder_job_ || video_decoder_job_; 330 return audio_decoder_job_ || video_decoder_job_;
318 } 331 }
319 332
320 void MediaSourcePlayer::StartInternal() { 333 void MediaSourcePlayer::StartInternal() {
321 if (playing_) 334 // Do nothing if the decoders are already running.
335 if (active_decoding_tasks_ > 0 || pending_event_ != NO_EVENT_PENDING)
322 return; 336 return;
323 playing_ = true;
324 337
325 if (HasAudio()) { 338 if (HasAudio()) {
326 audio_finished_ = false; 339 audio_finished_ = false;
327 DecodeMoreAudio(); 340 DecodeMoreAudio();
328 } 341 }
329 if (HasVideo()) { 342 if (HasVideo()) {
330 video_finished_ = false; 343 video_finished_ = false;
331 DecodeMoreVideo(); 344 DecodeMoreVideo();
332 } 345 }
333 } 346 }
334 347
335 void MediaSourcePlayer::DemuxerReady( 348 void MediaSourcePlayer::DemuxerReady(
336 const MediaPlayerHostMsg_DemuxerReady_Params& params) { 349 const MediaPlayerHostMsg_DemuxerReady_Params& params) {
337 if (params.duration_ms == std::numeric_limits<int>::max()) 350 if (params.duration_ms == std::numeric_limits<int>::max())
338 seekable_ = false; 351 seekable_ = false;
339 duration_ = base::TimeDelta::FromMilliseconds(params.duration_ms); 352 duration_ = base::TimeDelta::FromMilliseconds(params.duration_ms);
340 width_ = params.video_size.width(); 353 width_ = params.video_size.width();
341 height_ = params.video_size.height(); 354 height_ = params.video_size.height();
342 num_channels_ = params.audio_channels; 355 num_channels_ = params.audio_channels;
343 sampling_rate_ = params.audio_sampling_rate; 356 sampling_rate_ = params.audio_sampling_rate;
344 audio_codec_ = params.audio_codec; 357 audio_codec_ = params.audio_codec;
345 video_codec_ = params.video_codec; 358 video_codec_ = params.video_codec;
346 audio_extra_data_ = params.audio_extra_data; 359 audio_extra_data_ = params.audio_extra_data;
347 OnMediaMetadataChanged(duration_, width_, height_, true); 360 OnMediaMetadataChanged(duration_, width_, height_, true);
348 } 361 }
349 362
350 void MediaSourcePlayer::ReadFromDemuxerAck( 363 void MediaSourcePlayer::ReadFromDemuxerAck(
351 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) { 364 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) {
365 if (params.type == DemuxerStream::AUDIO)
366 waiting_for_audio_data_ = false;
367 else
368 waiting_for_video_data_ = false;
369
370 // If there is a pending seek request, ignore the data from the chunk demuxer.
371 // The data will be requested later when OnSeekRequestAck() is called.
372 if (pending_event_ & SEEK_EVENT_PENDING)
373 return;
374
352 if (params.type == DemuxerStream::AUDIO) { 375 if (params.type == DemuxerStream::AUDIO) {
353 DCHECK_EQ(0u, audio_access_unit_index_); 376 DCHECK_EQ(0u, audio_access_unit_index_);
354 received_audio_ = params; 377 received_audio_ = params;
355 waiting_for_audio_data_ = false; 378 if (!pending_event_)
356 DecodeMoreAudio(); 379 DecodeMoreAudio();
357 } else { 380 } else {
358 DCHECK_EQ(0u, video_access_unit_index_); 381 DCHECK_EQ(0u, video_access_unit_index_);
359 received_video_ = params; 382 received_video_ = params;
360 waiting_for_video_data_ = false; 383 if (!pending_event_)
361 DecodeMoreVideo(); 384 DecodeMoreVideo();
362 } 385 }
363 } 386 }
364 387
388 void MediaSourcePlayer::OnSeekRequestAck() {
389 pending_event_ &= ~SEEK_EVENT_PENDING;
390 OnSeekComplete();
391 if (playing_)
392 StartInternal();
393 }
394
365 void MediaSourcePlayer::UpdateTimestamps( 395 void MediaSourcePlayer::UpdateTimestamps(
366 const base::Time& kickoff_time,
367 const base::TimeDelta& presentation_timestamp, 396 const base::TimeDelta& presentation_timestamp,
368 const base::Time& wallclock_time) { 397 const base::Time& wallclock_time) {
369 // If the job was posted after last seek, update the presentation time. 398 last_presentation_timestamp_ = presentation_timestamp;
370 // Otherwise, ignore it. 399 OnTimeUpdated();
371 if (kickoff_time > last_seek_time_) { 400 if (start_wallclock_time_.is_null() && playing_) {
372 last_presentation_timestamp_ = presentation_timestamp; 401 start_wallclock_time_ = wallclock_time;
373 OnTimeUpdated(); 402 start_presentation_timestamp_ = last_presentation_timestamp_;
374 if (start_wallclock_time_.is_null() && playing_) {
375 start_wallclock_time_ = wallclock_time;
376 start_presentation_timestamp_ = last_presentation_timestamp_;
377 }
378 } 403 }
379 } 404 }
380 405
406 void MediaSourcePlayer::ProcessPendingEvents() {
407 // Wait for all the decoding jobs to finish before sending a seek request.
408 if (active_decoding_tasks_ > 0)
409 return;
410
411 DCHECK(pending_event_ != NO_EVENT_PENDING);
412 if (use_empty_surface_ && (pending_event_ & SURFACE_CHANGE_EVENT_PENDING)) {
413 video_decoder_job_.reset();
414 pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
415 }
416
417 ClearDecodingData();
418 manager()->OnMediaSeekRequest(player_id(),
419 last_presentation_timestamp_,
420 pending_event_ & SURFACE_CHANGE_EVENT_PENDING);
421 }
422
381 void MediaSourcePlayer::MediaDecoderCallback( 423 void MediaSourcePlayer::MediaDecoderCallback(
382 bool is_audio, const base::Time& kickoff_time, 424 bool is_audio, const base::TimeDelta& presentation_timestamp,
383 const base::TimeDelta& presentation_timestamp,
384 const base::Time& wallclock_time, bool end_of_stream) { 425 const base::Time& wallclock_time, bool end_of_stream) {
426 if (active_decoding_tasks_ > 0)
427 active_decoding_tasks_--;
428
429 if (pending_event_ != NO_EVENT_PENDING) {
430 ProcessPendingEvents();
431 return;
432 }
433
385 if (is_audio || !HasAudio()) 434 if (is_audio || !HasAudio())
386 UpdateTimestamps(kickoff_time, presentation_timestamp, wallclock_time); 435 UpdateTimestamps(presentation_timestamp, wallclock_time);
387 436
388 if (end_of_stream) { 437 if (end_of_stream) {
389 PlaybackCompleted(is_audio); 438 PlaybackCompleted(is_audio);
390 return; 439 return;
391 } 440 }
392 441
393 if (!playing_) 442 if (!playing_)
394 return; 443 return;
395 444
396 if (is_audio) 445 if (is_audio)
(...skipping 10 matching lines...) Expand all
407 audio_access_unit_index_ = 0; 456 audio_access_unit_index_ = 0;
408 waiting_for_audio_data_ = true; 457 waiting_for_audio_data_ = true;
409 } 458 }
410 return; 459 return;
411 } 460 }
412 461
413 audio_decoder_job_->Decode( 462 audio_decoder_job_->Decode(
414 received_audio_.access_units[audio_access_unit_index_], 463 received_audio_.access_units[audio_access_unit_index_],
415 start_wallclock_time_, start_presentation_timestamp_, 464 start_wallclock_time_, start_presentation_timestamp_,
416 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, 465 base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
417 weak_this_.GetWeakPtr(), true, base::Time::Now())); 466 weak_this_.GetWeakPtr(), true));
418 ++audio_access_unit_index_; 467 active_decoding_tasks_++;
468 audio_access_unit_index_++;
419 } 469 }
420 470
421 void MediaSourcePlayer::DecodeMoreVideo() { 471 void MediaSourcePlayer::DecodeMoreVideo() {
422 if (video_access_unit_index_ >= received_video_.access_units.size()) { 472 if (video_access_unit_index_ >= received_video_.access_units.size()) {
423 if (!waiting_for_video_data_) { 473 if (!waiting_for_video_data_) {
424 manager()->OnReadFromDemuxer(player_id(), DemuxerStream::VIDEO, true); 474 manager()->OnReadFromDemuxer(player_id(), DemuxerStream::VIDEO, true);
425 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params(); 475 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
426 video_access_unit_index_ = 0; 476 video_access_unit_index_ = 0;
427 waiting_for_video_data_ = true; 477 waiting_for_video_data_ = true;
428 } 478 }
429 return; 479 return;
430 } 480 }
431 481
432 video_decoder_job_->Decode( 482 video_decoder_job_->Decode(
433 received_video_.access_units[video_access_unit_index_], 483 received_video_.access_units[video_access_unit_index_],
434 start_wallclock_time_, start_presentation_timestamp_, 484 start_wallclock_time_, start_presentation_timestamp_,
435 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, 485 base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
436 weak_this_.GetWeakPtr(), false, base::Time::Now())); 486 weak_this_.GetWeakPtr(), false));
437 ++video_access_unit_index_; 487 active_decoding_tasks_++;
488 video_access_unit_index_++;
438 } 489 }
439 490
440 491
441 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { 492 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) {
442 if (is_audio) 493 if (is_audio)
443 audio_finished_ = true; 494 audio_finished_ = true;
444 else 495 else
445 video_finished_ = true; 496 video_finished_ = true;
446 497
447 if ((!HasAudio() || audio_finished_) && (!HasVideo() || video_finished_)) { 498 if ((!HasAudio() || audio_finished_) && (!HasVideo() || video_finished_)) {
448 playing_ = false; 499 playing_ = false;
449 start_wallclock_time_ = base::Time(); 500 start_wallclock_time_ = base::Time();
450 OnPlaybackComplete(); 501 OnPlaybackComplete();
451 } 502 }
452 } 503 }
453 504
505 void MediaSourcePlayer::ClearDecodingData() {
506 if (audio_decoder_job_)
507 audio_decoder_job_->Flush();
508 if (video_decoder_job_)
509 video_decoder_job_->Flush();
510 start_wallclock_time_ = base::Time();
511 received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
512 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
513 audio_access_unit_index_ = 0;
514 video_access_unit_index_ = 0;
515 }
516
454 bool MediaSourcePlayer::HasVideo() { 517 bool MediaSourcePlayer::HasVideo() {
455 return kUnknownVideoCodec != video_codec_; 518 return kUnknownVideoCodec != video_codec_;
456 } 519 }
457 520
458 bool MediaSourcePlayer::HasAudio() { 521 bool MediaSourcePlayer::HasAudio() {
459 return kUnknownAudioCodec != audio_codec_; 522 return kUnknownAudioCodec != audio_codec_;
460 } 523 }
461 524
462 } // namespace media 525 } // namespace media
OLDNEW
« no previous file with comments | « media/base/android/media_source_player.h ('k') | webkit/media/android/media_source_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698