Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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_play_(false), |
| 196 pending_media_seek_request_(false), | |
| 197 active_decoding_tasks_(0), | |
| 196 width_(0), | 198 width_(0), |
| 197 height_(0), | 199 height_(0), |
| 198 audio_codec_(kUnknownAudioCodec), | 200 audio_codec_(kUnknownAudioCodec), |
| 199 video_codec_(kUnknownVideoCodec), | 201 video_codec_(kUnknownVideoCodec), |
| 200 num_channels_(0), | 202 num_channels_(0), |
| 201 sampling_rate_(0), | 203 sampling_rate_(0), |
| 202 seekable_(true), | 204 seekable_(true), |
| 203 audio_finished_(true), | 205 audio_finished_(true), |
| 204 video_finished_(true), | 206 video_finished_(true), |
| 205 playing_(false), | 207 playing_(false), |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 264 return width_; | 266 return width_; |
| 265 } | 267 } |
| 266 | 268 |
| 267 int MediaSourcePlayer::GetVideoHeight() { | 269 int MediaSourcePlayer::GetVideoHeight() { |
| 268 return height_; | 270 return height_; |
| 269 } | 271 } |
| 270 | 272 |
| 271 void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) { | 273 void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) { |
| 272 last_presentation_timestamp_ = timestamp; | 274 last_presentation_timestamp_ = timestamp; |
| 273 start_wallclock_time_ = base::Time(); | 275 start_wallclock_time_ = base::Time(); |
| 274 last_seek_time_ = base::Time::Now(); | |
| 275 if (audio_decoder_job_) | 276 if (audio_decoder_job_) |
| 276 audio_decoder_job_->Flush(); | 277 audio_decoder_job_->Flush(); |
| 277 if (video_decoder_job_) | 278 if (video_decoder_job_) |
| 278 video_decoder_job_->Flush(); | 279 video_decoder_job_->Flush(); |
| 279 received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params(); | 280 received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params(); |
| 280 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params(); | 281 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params(); |
| 281 audio_access_unit_index_ = 0; | 282 audio_access_unit_index_ = 0; |
| 282 video_access_unit_index_ = 0; | 283 video_access_unit_index_ = 0; |
| 283 OnSeekComplete(); | 284 pending_media_seek_request_ = true; |
| 285 if (!active_decoding_tasks_) | |
| 286 manager()->OnMediaSeekRequest(player_id(), last_presentation_timestamp_); | |
| 284 } | 287 } |
| 285 | 288 |
| 286 base::TimeDelta MediaSourcePlayer::GetCurrentTime() { | 289 base::TimeDelta MediaSourcePlayer::GetCurrentTime() { |
| 287 return last_presentation_timestamp_; | 290 return last_presentation_timestamp_; |
| 288 } | 291 } |
| 289 | 292 |
| 290 base::TimeDelta MediaSourcePlayer::GetDuration() { | 293 base::TimeDelta MediaSourcePlayer::GetDuration() { |
| 291 return duration_; | 294 return duration_; |
| 292 } | 295 } |
| 293 | 296 |
| 294 void MediaSourcePlayer::Release() { | 297 void MediaSourcePlayer::Release() { |
| 295 audio_decoder_job_.reset(); | 298 audio_decoder_job_.reset(); |
| 296 video_decoder_job_.reset(); | 299 video_decoder_job_.reset(); |
| 300 active_decoding_tasks_ = 0; | |
| 297 ReleaseMediaResourcesFromManager(); | 301 ReleaseMediaResourcesFromManager(); |
| 298 } | 302 } |
| 299 | 303 |
| 300 void MediaSourcePlayer::SetVolume(float leftVolume, float rightVolume) { | 304 void MediaSourcePlayer::SetVolume(float leftVolume, float rightVolume) { |
| 301 } | 305 } |
| 302 | 306 |
| 303 bool MediaSourcePlayer::CanPause() { | 307 bool MediaSourcePlayer::CanPause() { |
| 304 return seekable_; | 308 return seekable_; |
| 305 } | 309 } |
| 306 | 310 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 341 num_channels_ = params.audio_channels; | 345 num_channels_ = params.audio_channels; |
| 342 sampling_rate_ = params.audio_sampling_rate; | 346 sampling_rate_ = params.audio_sampling_rate; |
| 343 audio_codec_ = params.audio_codec; | 347 audio_codec_ = params.audio_codec; |
| 344 video_codec_ = params.video_codec; | 348 video_codec_ = params.video_codec; |
| 345 audio_extra_data_ = params.audio_extra_data; | 349 audio_extra_data_ = params.audio_extra_data; |
| 346 OnMediaMetadataChanged(duration_, width_, height_, true); | 350 OnMediaMetadataChanged(duration_, width_, height_, true); |
| 347 } | 351 } |
| 348 | 352 |
| 349 void MediaSourcePlayer::ReadFromDemuxerAck( | 353 void MediaSourcePlayer::ReadFromDemuxerAck( |
| 350 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) { | 354 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) { |
| 355 if (params.type == DemuxerStream::AUDIO) | |
| 356 waiting_for_audio_data_ = false; | |
| 357 else | |
| 358 waiting_for_video_data_ = false; | |
| 359 | |
| 360 // If there is a pending seek request, ignore the data from the chunk demuxer. | |
| 361 // The data will be requested later when OnSeekRequestAck() is called. | |
| 362 if (pending_media_seek_request_) | |
| 363 return; | |
| 364 | |
| 351 if (params.type == DemuxerStream::AUDIO) { | 365 if (params.type == DemuxerStream::AUDIO) { |
| 352 DCHECK_EQ(0u, audio_access_unit_index_); | 366 DCHECK_EQ(0u, audio_access_unit_index_); |
| 353 received_audio_ = params; | 367 received_audio_ = params; |
| 354 waiting_for_audio_data_ = false; | |
| 355 DecodeMoreAudio(); | 368 DecodeMoreAudio(); |
| 356 } else { | 369 } else { |
| 357 DCHECK_EQ(0u, video_access_unit_index_); | 370 DCHECK_EQ(0u, video_access_unit_index_); |
| 358 received_video_ = params; | 371 received_video_ = params; |
| 359 waiting_for_video_data_ = false; | |
| 360 DecodeMoreVideo(); | 372 DecodeMoreVideo(); |
| 361 } | 373 } |
| 362 } | 374 } |
| 363 | 375 |
| 376 void MediaSourcePlayer::OnSeekRequestAck() { | |
| 377 pending_media_seek_request_ = false; | |
| 378 OnSeekComplete(); | |
| 379 if (!playing_) | |
| 380 return; | |
| 381 | |
| 382 if (HasAudio()) | |
| 383 DecodeMoreAudio(); | |
| 384 if (HasVideo()) | |
| 385 DecodeMoreVideo(); | |
| 386 } | |
| 387 | |
| 364 void MediaSourcePlayer::UpdateTimestamps( | 388 void MediaSourcePlayer::UpdateTimestamps( |
| 365 const base::Time& kickoff_time, | |
| 366 const base::TimeDelta& presentation_timestamp, | 389 const base::TimeDelta& presentation_timestamp, |
| 367 const base::Time& wallclock_time) { | 390 const base::Time& wallclock_time) { |
| 368 // If the job was posted after last seek, update the presentation time. | 391 last_presentation_timestamp_ = presentation_timestamp; |
| 369 // Otherwise, ignore it. | 392 OnTimeUpdated(); |
| 370 if (kickoff_time > last_seek_time_) { | 393 if (start_wallclock_time_.is_null() && playing_) { |
| 371 last_presentation_timestamp_ = presentation_timestamp; | 394 start_wallclock_time_ = wallclock_time; |
| 372 OnTimeUpdated(); | 395 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 } | 396 } |
| 378 } | 397 } |
| 379 | 398 |
| 380 void MediaSourcePlayer::MediaDecoderCallback( | 399 void MediaSourcePlayer::MediaDecoderCallback( |
| 381 bool is_audio, const base::Time& kickoff_time, | 400 bool is_audio, const base::TimeDelta& presentation_timestamp, |
| 382 const base::TimeDelta& presentation_timestamp, | |
| 383 const base::Time& wallclock_time, bool end_of_stream) { | 401 const base::Time& wallclock_time, bool end_of_stream) { |
| 402 if (active_decoding_tasks_) | |
|
acolwell GONE FROM CHROMIUM
2013/05/21 17:49:42
nit add '> 0' just to be safe or a DCHECK_GE(activ
qinmin
2013/05/21 23:04:56
Done.
| |
| 403 active_decoding_tasks_--; | |
| 404 | |
| 405 if (pending_media_seek_request_) { | |
| 406 // Wait for all the decoding jobs to finish before sending a seek request. | |
| 407 if (!active_decoding_tasks_) { | |
| 408 manager()->OnMediaSeekRequest(player_id(), | |
| 409 last_presentation_timestamp_); | |
| 410 } | |
| 411 return; | |
| 412 } | |
| 413 | |
| 384 if (is_audio || !HasAudio()) | 414 if (is_audio || !HasAudio()) |
| 385 UpdateTimestamps(kickoff_time, presentation_timestamp, wallclock_time); | 415 UpdateTimestamps(presentation_timestamp, wallclock_time); |
| 386 | 416 |
| 387 if (end_of_stream) { | 417 if (end_of_stream) { |
| 388 PlaybackCompleted(is_audio); | 418 PlaybackCompleted(is_audio); |
| 389 return; | 419 return; |
| 390 } | 420 } |
| 391 | 421 |
| 392 if (!playing_) | 422 if (!playing_) |
| 393 return; | 423 return; |
| 394 | 424 |
| 395 if (is_audio) | 425 if (is_audio) |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 406 audio_access_unit_index_ = 0; | 436 audio_access_unit_index_ = 0; |
| 407 waiting_for_audio_data_ = true; | 437 waiting_for_audio_data_ = true; |
| 408 } | 438 } |
| 409 return; | 439 return; |
| 410 } | 440 } |
| 411 | 441 |
| 412 audio_decoder_job_->Decode( | 442 audio_decoder_job_->Decode( |
| 413 received_audio_.access_units[audio_access_unit_index_], | 443 received_audio_.access_units[audio_access_unit_index_], |
| 414 start_wallclock_time_, start_presentation_timestamp_, | 444 start_wallclock_time_, start_presentation_timestamp_, |
| 415 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, | 445 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, |
| 416 weak_this_.GetWeakPtr(), true, base::Time::Now())); | 446 weak_this_.GetWeakPtr(), true)); |
| 417 ++audio_access_unit_index_; | 447 active_decoding_tasks_++; |
| 448 audio_access_unit_index_++; | |
| 418 } | 449 } |
| 419 | 450 |
| 420 void MediaSourcePlayer::DecodeMoreVideo() { | 451 void MediaSourcePlayer::DecodeMoreVideo() { |
| 421 if (video_access_unit_index_ >= received_video_.access_units.size()) { | 452 if (video_access_unit_index_ >= received_video_.access_units.size()) { |
| 422 if (!waiting_for_video_data_) { | 453 if (!waiting_for_video_data_) { |
| 423 manager()->OnReadFromDemuxer(player_id(), DemuxerStream::VIDEO, true); | 454 manager()->OnReadFromDemuxer(player_id(), DemuxerStream::VIDEO, true); |
| 424 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params(); | 455 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params(); |
| 425 video_access_unit_index_ = 0; | 456 video_access_unit_index_ = 0; |
| 426 waiting_for_video_data_ = true; | 457 waiting_for_video_data_ = true; |
| 427 } | 458 } |
| 428 return; | 459 return; |
| 429 } | 460 } |
| 430 | 461 |
| 431 video_decoder_job_->Decode( | 462 video_decoder_job_->Decode( |
| 432 received_video_.access_units[video_access_unit_index_], | 463 received_video_.access_units[video_access_unit_index_], |
| 433 start_wallclock_time_, start_presentation_timestamp_, | 464 start_wallclock_time_, start_presentation_timestamp_, |
| 434 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, | 465 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, |
| 435 weak_this_.GetWeakPtr(), false, base::Time::Now())); | 466 weak_this_.GetWeakPtr(), false)); |
| 436 ++video_access_unit_index_; | 467 active_decoding_tasks_++; |
| 468 video_access_unit_index_++; | |
| 437 } | 469 } |
| 438 | 470 |
| 439 | 471 |
| 440 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { | 472 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { |
| 441 if (is_audio) | 473 if (is_audio) |
| 442 audio_finished_ = true; | 474 audio_finished_ = true; |
| 443 else | 475 else |
| 444 video_finished_ = true; | 476 video_finished_ = true; |
| 445 | 477 |
| 446 if ((!HasAudio() || audio_finished_) && (!HasVideo() || video_finished_)) { | 478 if ((!HasAudio() || audio_finished_) && (!HasVideo() || video_finished_)) { |
| 447 playing_ = false; | 479 playing_ = false; |
| 448 start_wallclock_time_ = base::Time(); | 480 start_wallclock_time_ = base::Time(); |
| 449 OnPlaybackComplete(); | 481 OnPlaybackComplete(); |
| 450 } | 482 } |
| 451 } | 483 } |
| 452 | 484 |
| 453 bool MediaSourcePlayer::HasVideo() { | 485 bool MediaSourcePlayer::HasVideo() { |
| 454 return kUnknownVideoCodec != video_codec_; | 486 return kUnknownVideoCodec != video_codec_; |
| 455 } | 487 } |
| 456 | 488 |
| 457 bool MediaSourcePlayer::HasAudio() { | 489 bool MediaSourcePlayer::HasAudio() { |
| 458 return kUnknownAudioCodec != audio_codec_; | 490 return kUnknownAudioCodec != audio_codec_; |
| 459 } | 491 } |
| 460 | 492 |
| 461 } // namespace media | 493 } // namespace media |
| OLD | NEW |