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 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |