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

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

Issue 16098014: Handle config changes for MSE on android (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 48
49 } 49 }
50 50
51 namespace media { 51 namespace media {
52 52
53 MediaDecoderJob::MediaDecoderJob(base::Thread* thread, bool is_audio) 53 MediaDecoderJob::MediaDecoderJob(base::Thread* thread, bool is_audio)
54 : message_loop_(base::MessageLoopProxy::current()), 54 : message_loop_(base::MessageLoopProxy::current()),
55 thread_(thread), 55 thread_(thread),
56 needs_flush_(false), 56 needs_flush_(false),
57 is_audio_(is_audio), 57 is_audio_(is_audio),
58 weak_this_(this) { 58 weak_this_(this),
59 decoding_(false) {
59 } 60 }
60 61
61 MediaDecoderJob::~MediaDecoderJob() {} 62 MediaDecoderJob::~MediaDecoderJob() {}
62 63
63 // Class for managing audio decoding jobs. 64 // Class for managing audio decoding jobs.
64 class AudioDecoderJob : public MediaDecoderJob { 65 class AudioDecoderJob : public MediaDecoderJob {
65 public: 66 public:
66 AudioDecoderJob( 67 AudioDecoderJob(
67 const AudioCodec audio_codec, int sample_rate, 68 const AudioCodec audio_codec, int sample_rate,
68 int channel_count, const uint8* extra_data, size_t extra_data_size); 69 int channel_count, const uint8* extra_data, size_t extra_data_size);
69 virtual ~AudioDecoderJob() {} 70 virtual ~AudioDecoderJob() {}
70 }; 71 };
71 72
72 // Class for managing video decoding jobs. 73 // Class for managing video decoding jobs.
73 class VideoDecoderJob : public MediaDecoderJob { 74 class VideoDecoderJob : public MediaDecoderJob {
74 public: 75 public:
75 VideoDecoderJob( 76 VideoDecoderJob(
76 const VideoCodec video_codec, const gfx::Size& size, jobject surface); 77 const VideoCodec video_codec, const gfx::Size& size, jobject surface);
77 virtual ~VideoDecoderJob() {} 78 virtual ~VideoDecoderJob() {}
78 79
79 void Configure( 80 void Configure(
80 const VideoCodec codec, const gfx::Size& size, jobject surface); 81 const VideoCodec codec, const gfx::Size& size, jobject surface);
81 }; 82 };
82 83
83 void MediaDecoderJob::Decode( 84 void MediaDecoderJob::Decode(
84 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params::AccessUnit& unit, 85 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params::AccessUnit& unit,
85 const base::Time& start_wallclock_time, 86 const base::Time& start_wallclock_time,
86 const base::TimeDelta& start_presentation_timestamp, 87 const base::TimeDelta& start_presentation_timestamp,
87 const MediaDecoderJob::DecoderCallback& callback) { 88 const MediaDecoderJob::DecoderCallback& callback) {
89 decoding_ = true;
acolwell GONE FROM CHROMIUM 2013/06/04 15:19:14 Should there be a DCHECK(!decoding_) here?
qinmin 2013/06/04 19:03:23 Done.
88 thread_->message_loop()->PostTask(FROM_HERE, base::Bind( 90 thread_->message_loop()->PostTask(FROM_HERE, base::Bind(
89 &MediaDecoderJob::DecodeInternal, base::Unretained(this), unit, 91 &MediaDecoderJob::DecodeInternal, base::Unretained(this), unit,
90 start_wallclock_time, start_presentation_timestamp, needs_flush_, 92 start_wallclock_time, start_presentation_timestamp, needs_flush_,
91 callback)); 93 callback));
92 needs_flush_ = false; 94 needs_flush_ = false;
93 } 95 }
94 96
95 void MediaDecoderJob::DecodeInternal( 97 void MediaDecoderJob::DecodeInternal(
96 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params::AccessUnit& unit, 98 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params::AccessUnit& unit,
97 const base::Time& start_wallclock_time, 99 const base::Time& start_wallclock_time,
98 const base::TimeDelta& start_presentation_timestamp, 100 const base::TimeDelta& start_presentation_timestamp,
99 bool needs_flush, 101 bool needs_flush,
100 const MediaDecoderJob::DecoderCallback& callback) { 102 const MediaDecoderJob::DecoderCallback& callback) {
101 if (needs_flush) 103 if (needs_flush)
102 media_codec_bridge_->Reset(); 104 media_codec_bridge_->Reset();
103 base::TimeDelta timeout = base::TimeDelta::FromMicroseconds( 105 base::TimeDelta timeout = base::TimeDelta::FromMicroseconds(
104 kMediaCodecTimeoutInMicroseconds); 106 kMediaCodecTimeoutInMicroseconds);
105 int input_buf_index = media_codec_bridge_->DequeueInputBuffer(timeout); 107 int input_buf_index = media_codec_bridge_->DequeueInputBuffer(timeout);
108 if (input_buf_index == MediaCodecBridge::INFO_MEDIA_CODEC_ERROR) {
109 message_loop_->PostTask(FROM_HERE, base::Bind(
110 callback, false, start_presentation_timestamp, start_wallclock_time,
111 false));
112 return;
113 }
106 // TODO(qinmin): skip frames if video is falling far behind. 114 // TODO(qinmin): skip frames if video is falling far behind.
107 if (input_buf_index >= 0) { 115 if (input_buf_index >= 0) {
108 if (unit.end_of_stream) { 116 if (unit.end_of_stream) {
109 media_codec_bridge_->QueueEOS(input_buf_index); 117 media_codec_bridge_->QueueEOS(input_buf_index);
110 } else { 118 } else {
111 media_codec_bridge_->QueueInputBuffer( 119 media_codec_bridge_->QueueInputBuffer(
112 input_buf_index, &unit.data[0], unit.data.size(), unit.timestamp); 120 input_buf_index, &unit.data[0], unit.data.size(), unit.timestamp);
113 } 121 }
114 } 122 }
115 size_t offset = 0; 123 size_t offset = 0;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 if (is_audio_) { 180 if (is_audio_) {
173 static_cast<AudioCodecBridge*>(media_codec_bridge_.get())->PlayOutputBuffer( 181 static_cast<AudioCodecBridge*>(media_codec_bridge_.get())->PlayOutputBuffer(
174 outputBufferIndex, size); 182 outputBufferIndex, size);
175 } 183 }
176 media_codec_bridge_->ReleaseOutputBuffer(outputBufferIndex, !is_audio_); 184 media_codec_bridge_->ReleaseOutputBuffer(outputBufferIndex, !is_audio_);
177 message_loop_->PostTask(FROM_HERE, base::Bind( 185 message_loop_->PostTask(FROM_HERE, base::Bind(
178 callback, true, presentation_timestamp, base::Time::Now(), 186 callback, true, presentation_timestamp, base::Time::Now(),
179 end_of_stream)); 187 end_of_stream));
180 } 188 }
181 189
190 void MediaDecoderJob::OnDecodeCompleted() {
191 decoding_ = false;
192 }
193
182 void MediaDecoderJob::Flush() { 194 void MediaDecoderJob::Flush() {
183 // Do nothing, flush when the next Decode() happens. 195 // Do nothing, flush when the next Decode() happens.
184 needs_flush_ = true; 196 needs_flush_ = true;
185 } 197 }
186 198
187 void MediaDecoderJob::Release() { 199 void MediaDecoderJob::Release() {
188 if (thread_->IsRunning() && 200 if (decoding_ && thread_->message_loop() != base::MessageLoop::current())
acolwell GONE FROM CHROMIUM 2013/06/04 15:19:14 This doesn't seem right. Shouldn't this code look
qinmin 2013/06/04 19:03:23 Backgroud info: there is a problem in android that
189 thread_->message_loop() != base::MessageLoop::current()) {
190 thread_->message_loop()->DeleteSoon(FROM_HERE, this); 201 thread_->message_loop()->DeleteSoon(FROM_HERE, this);
191 } else { 202 else
192 delete this; 203 delete this;
193 }
194 } 204 }
195 205
196 VideoDecoderJob::VideoDecoderJob( 206 VideoDecoderJob::VideoDecoderJob(
197 const VideoCodec video_codec, const gfx::Size& size, jobject surface) 207 const VideoCodec video_codec, const gfx::Size& size, jobject surface)
198 : MediaDecoderJob(g_video_decoder_thread.Pointer(), false) { 208 : MediaDecoderJob(g_video_decoder_thread.Pointer(), false) {
199 scoped_ptr<VideoCodecBridge> codec(VideoCodecBridge::Create(video_codec)); 209 scoped_ptr<VideoCodecBridge> codec(VideoCodecBridge::Create(video_codec));
200 codec->Start(video_codec, size, surface); 210 codec->Start(video_codec, size, surface);
201 media_codec_bridge_.reset(codec.release()); 211 media_codec_bridge_.reset(codec.release());
202 } 212 }
203 213
204 AudioDecoderJob::AudioDecoderJob( 214 AudioDecoderJob::AudioDecoderJob(
205 const AudioCodec audio_codec, 215 const AudioCodec audio_codec,
206 int sample_rate, 216 int sample_rate,
207 int channel_count, 217 int channel_count,
208 const uint8* extra_data, 218 const uint8* extra_data,
209 size_t extra_data_size) 219 size_t extra_data_size)
210 : MediaDecoderJob(g_audio_decoder_thread.Pointer(), true) { 220 : MediaDecoderJob(g_audio_decoder_thread.Pointer(), true) {
211 scoped_ptr<AudioCodecBridge> codec(AudioCodecBridge::Create(audio_codec)); 221 scoped_ptr<AudioCodecBridge> codec(AudioCodecBridge::Create(audio_codec));
212 codec->Start(audio_codec, sample_rate, channel_count, extra_data, 222 codec->Start(audio_codec, sample_rate, channel_count, extra_data,
213 extra_data_size, true); 223 extra_data_size, true);
214 media_codec_bridge_.reset(codec.release()); 224 media_codec_bridge_.reset(codec.release());
215 } 225 }
216 226
217 MediaSourcePlayer::MediaSourcePlayer( 227 MediaSourcePlayer::MediaSourcePlayer(
218 int player_id, 228 int player_id,
219 MediaPlayerManager* manager) 229 MediaPlayerManager* manager)
220 : MediaPlayerAndroid(player_id, manager), 230 : MediaPlayerAndroid(player_id, manager),
221 pending_event_(NO_EVENT_PENDING), 231 pending_event_(NO_EVENT_PENDING),
222 active_decoding_tasks_(0), 232 active_decoding_tasks_(0),
233 seek_request_id_(0),
223 width_(0), 234 width_(0),
224 height_(0), 235 height_(0),
225 audio_codec_(kUnknownAudioCodec), 236 audio_codec_(kUnknownAudioCodec),
226 video_codec_(kUnknownVideoCodec), 237 video_codec_(kUnknownVideoCodec),
227 num_channels_(0), 238 num_channels_(0),
228 sampling_rate_(0), 239 sampling_rate_(0),
229 seekable_(true), 240 seekable_(true),
230 audio_finished_(true), 241 audio_finished_(true),
231 video_finished_(true), 242 video_finished_(true),
232 playing_(false), 243 playing_(false),
233 audio_access_unit_index_(0), 244 audio_access_unit_index_(0),
234 video_access_unit_index_(0), 245 video_access_unit_index_(0),
235 waiting_for_audio_data_(false), 246 waiting_for_audio_data_(false),
236 waiting_for_video_data_(false), 247 waiting_for_video_data_(false),
237 use_empty_surface_(true),
238 weak_this_(this) { 248 weak_this_(this) {
239 } 249 }
240 250
241 MediaSourcePlayer::~MediaSourcePlayer() { 251 MediaSourcePlayer::~MediaSourcePlayer() {
242 Release(); 252 Release();
243 } 253 }
244 254
245 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { 255 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) {
246 use_empty_surface_ = surface.IsSurfaceEmpty(); 256 surface_ = surface.Pass();
247 257
248 // If we haven't processed a surface change event, do so now. 258 pending_event_ |= SURFACE_CHANGE_EVENT_PENDING;
249 if (active_decoding_tasks_ > 0) { 259 // Request a seek so that the next decoder will decode an I-frame first.
250 pending_event_ |= SURFACE_CHANGE_EVENT_PENDING; 260 // Or otherwise, MediaCodec might crash. See b/8950387.
acolwell GONE FROM CHROMIUM 2013/06/04 15:19:14 The seek is needed because you have to create a ne
qinmin 2013/06/04 19:03:23 Done.
251 // Request a seek so that the next decoder will decode an I-frame first. 261 pending_event_ |= SEEK_EVENT_PENDING;
252 // Or otherwise, MediaCodec might crash. See b/8950387. 262 ProcessPendingEvents();
253 pending_event_ |= SEEK_EVENT_PENDING;
254 ProcessPendingEvents();
255 return;
256 }
257
258 if (HasVideo()) {
259 video_decoder_job_.reset(new VideoDecoderJob(
260 video_codec_, gfx::Size(width_, height_), surface.j_surface().obj()));
261 }
262
263 // Inform the fullscreen view the player is ready.
264 // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way
265 // to inform ContentVideoView.
266 OnMediaMetadataChanged(duration_, width_, height_, true);
267
268 if (pending_event_ & SURFACE_CHANGE_EVENT_PENDING) {
269 // We should already requested a seek in this case.
270 pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
271 } else {
272 // Perform a seek so the new decoder can get the I-frame first.
273 pending_event_ |= SEEK_EVENT_PENDING;
274 ProcessPendingEvents();
275 return;
276 }
277
278 if (playing_)
279 StartInternal();
280 } 263 }
281 264
282 void MediaSourcePlayer::Start() { 265 void MediaSourcePlayer::Start() {
283 playing_ = true; 266 playing_ = true;
284 if (HasAudio() && !audio_decoder_job_) {
285 audio_decoder_job_.reset(new AudioDecoderJob(
286 audio_codec_, sampling_rate_, num_channels_,
287 &audio_extra_data_[0], audio_extra_data_.size()));
288 }
289 267
290 if (HasVideo() && !video_decoder_job_) { 268 CreateMediaDecoderJobs(false);
291 // StartInternal() will be delayed until SetVideoSurface() gets called.
292 return;
293 }
294 269
295 StartInternal(); 270 StartInternal();
296 } 271 }
297 272
298 void MediaSourcePlayer::Pause() { 273 void MediaSourcePlayer::Pause() {
299 playing_ = false; 274 playing_ = false;
300 start_wallclock_time_ = base::Time(); 275 start_wallclock_time_ = base::Time();
301 } 276 }
302 277
303 bool MediaSourcePlayer::IsPlaying() { 278 bool MediaSourcePlayer::IsPlaying() {
(...skipping 22 matching lines...) Expand all
326 return duration_; 301 return duration_;
327 } 302 }
328 303
329 void MediaSourcePlayer::Release() { 304 void MediaSourcePlayer::Release() {
330 ClearDecodingData(); 305 ClearDecodingData();
331 audio_decoder_job_.reset(); 306 audio_decoder_job_.reset();
332 video_decoder_job_.reset(); 307 video_decoder_job_.reset();
333 active_decoding_tasks_ = 0; 308 active_decoding_tasks_ = 0;
334 playing_ = false; 309 playing_ = false;
335 pending_event_ = NO_EVENT_PENDING; 310 pending_event_ = NO_EVENT_PENDING;
311 surface_ = gfx::ScopedJavaSurface();
336 ReleaseMediaResourcesFromManager(); 312 ReleaseMediaResourcesFromManager();
337 } 313 }
338 314
339 void MediaSourcePlayer::SetVolume(float leftVolume, float rightVolume) { 315 void MediaSourcePlayer::SetVolume(float leftVolume, float rightVolume) {
340 } 316 }
341 317
342 bool MediaSourcePlayer::CanPause() { 318 bool MediaSourcePlayer::CanPause() {
343 return seekable_; 319 return seekable_;
344 } 320 }
345 321
346 bool MediaSourcePlayer::CanSeekForward() { 322 bool MediaSourcePlayer::CanSeekForward() {
347 return seekable_; 323 return seekable_;
348 } 324 }
349 325
350 bool MediaSourcePlayer::CanSeekBackward() { 326 bool MediaSourcePlayer::CanSeekBackward() {
351 return seekable_; 327 return seekable_;
352 } 328 }
353 329
354 bool MediaSourcePlayer::IsPlayerReady() { 330 bool MediaSourcePlayer::IsPlayerReady() {
355 return audio_decoder_job_ || video_decoder_job_; 331 return audio_decoder_job_ || video_decoder_job_;
356 } 332 }
357 333
358 void MediaSourcePlayer::StartInternal() { 334 void MediaSourcePlayer::StartInternal() {
359 // Do nothing if the decoders are already running. 335 // Do nothing if the decoders are already running.
360 if (active_decoding_tasks_ > 0 || pending_event_ != NO_EVENT_PENDING) 336 if (active_decoding_tasks_ > 0 || pending_event_ != NO_EVENT_PENDING)
361 return; 337 return;
362 338
339 // If one of the decoder job is not ready, do nothing.
340 if ((HasAudio() && !audio_decoder_job_) ||
341 (HasVideo() && !video_decoder_job_)) {
342 return;
343 }
344
363 if (HasAudio()) { 345 if (HasAudio()) {
364 audio_finished_ = false; 346 audio_finished_ = false;
365 DecodeMoreAudio(); 347 DecodeMoreAudio();
366 } 348 }
367 if (HasVideo()) { 349 if (HasVideo()) {
368 video_finished_ = false; 350 video_finished_ = false;
369 DecodeMoreVideo(); 351 DecodeMoreVideo();
370 } 352 }
371 } 353 }
372 354
373 void MediaSourcePlayer::DemuxerReady( 355 void MediaSourcePlayer::DemuxerReady(
374 const MediaPlayerHostMsg_DemuxerReady_Params& params) { 356 const MediaPlayerHostMsg_DemuxerReady_Params& params) {
375 if (params.duration_ms == std::numeric_limits<int>::max()) 357 if (params.duration_ms == std::numeric_limits<int>::max())
376 seekable_ = false; 358 seekable_ = false;
377 duration_ = base::TimeDelta::FromMilliseconds(params.duration_ms); 359 duration_ = base::TimeDelta::FromMilliseconds(params.duration_ms);
378 width_ = params.video_size.width(); 360 width_ = params.video_size.width();
379 height_ = params.video_size.height(); 361 height_ = params.video_size.height();
380 num_channels_ = params.audio_channels; 362 num_channels_ = params.audio_channels;
381 sampling_rate_ = params.audio_sampling_rate; 363 sampling_rate_ = params.audio_sampling_rate;
382 audio_codec_ = params.audio_codec; 364 audio_codec_ = params.audio_codec;
383 video_codec_ = params.video_codec; 365 video_codec_ = params.video_codec;
384 audio_extra_data_ = params.audio_extra_data; 366 audio_extra_data_ = params.audio_extra_data;
385 OnMediaMetadataChanged(duration_, width_, height_, true); 367 OnMediaMetadataChanged(duration_, width_, height_, true);
368 if (pending_event_ & CONFIG_CHANGE_EVENT_PENDING) {
369 CreateMediaDecoderJobs(true);
370 pending_event_ &= ~CONFIG_CHANGE_EVENT_PENDING;
371 // If there is a pending surface change, we can merge it with the config
372 // change.
373 pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
374 if (playing_ && pending_event_ == NO_EVENT_PENDING)
375 StartInternal();
376 }
386 } 377 }
387 378
388 void MediaSourcePlayer::ReadFromDemuxerAck( 379 void MediaSourcePlayer::ReadFromDemuxerAck(
389 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) { 380 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) {
390 if (params.type == DemuxerStream::AUDIO) 381 if (params.type == DemuxerStream::AUDIO)
391 waiting_for_audio_data_ = false; 382 waiting_for_audio_data_ = false;
392 else 383 else
393 waiting_for_video_data_ = false; 384 waiting_for_video_data_ = false;
394 385
395 // If there is a pending seek request, ignore the data from the chunk demuxer. 386 // If there is a pending seek request, ignore the data from the chunk demuxer.
396 // The data will be requested later when OnSeekRequestAck() is called. 387 // The data will be requested later when OnSeekRequestAck() is called.
397 if (pending_event_ & SEEK_EVENT_PENDING) 388 if (pending_event_ & SEEK_EVENT_PENDING)
398 return; 389 return;
399 390
400 if (params.type == DemuxerStream::AUDIO) { 391 if (params.type == DemuxerStream::AUDIO) {
401 DCHECK_EQ(0u, audio_access_unit_index_); 392 DCHECK_EQ(0u, audio_access_unit_index_);
402 received_audio_ = params; 393 received_audio_ = params;
403 if (!pending_event_) 394 if (!pending_event_)
404 DecodeMoreAudio(); 395 DecodeMoreAudio();
405 } else { 396 } else {
406 DCHECK_EQ(0u, video_access_unit_index_); 397 DCHECK_EQ(0u, video_access_unit_index_);
407 received_video_ = params; 398 received_video_ = params;
408 if (!pending_event_) 399 if (!pending_event_)
409 DecodeMoreVideo(); 400 DecodeMoreVideo();
410 } 401 }
411 } 402 }
412 403
413 void MediaSourcePlayer::OnSeekRequestAck() { 404 void MediaSourcePlayer::OnSeekRequestAck(unsigned request_id) {
acolwell GONE FROM CHROMIUM 2013/06/04 15:19:14 nit:s/request/seek_request/
qinmin 2013/06/04 19:03:23 Done.
405 // Do nothing until the most recent seek request is processed.
406 if (seek_request_id_ != request_id)
407 return;
414 pending_event_ &= ~SEEK_EVENT_PENDING; 408 pending_event_ &= ~SEEK_EVENT_PENDING;
415 OnSeekComplete(); 409 OnSeekComplete();
416 if (playing_) 410 ProcessPendingEvents();
417 StartInternal();
418 } 411 }
419 412
420 void MediaSourcePlayer::UpdateTimestamps( 413 void MediaSourcePlayer::UpdateTimestamps(
421 const base::TimeDelta& presentation_timestamp, 414 const base::TimeDelta& presentation_timestamp,
422 const base::Time& wallclock_time) { 415 const base::Time& wallclock_time) {
423 last_presentation_timestamp_ = presentation_timestamp; 416 last_presentation_timestamp_ = presentation_timestamp;
424 OnTimeUpdated(); 417 OnTimeUpdated();
425 if (start_wallclock_time_.is_null() && playing_) { 418 if (start_wallclock_time_.is_null() && playing_) {
426 start_wallclock_time_ = wallclock_time; 419 start_wallclock_time_ = wallclock_time;
427 start_presentation_timestamp_ = last_presentation_timestamp_; 420 start_presentation_timestamp_ = last_presentation_timestamp_;
428 } 421 }
429 } 422 }
430 423
431 void MediaSourcePlayer::ProcessPendingEvents() { 424 void MediaSourcePlayer::ProcessPendingEvents() {
432 // Wait for all the decoding jobs to finish before sending a seek request. 425 // Wait for all the decoding jobs to finish before processing pending tasks.
433 if (active_decoding_tasks_ > 0) 426 if (active_decoding_tasks_ > 0)
434 return; 427 return;
435 428
436 DCHECK(pending_event_ != NO_EVENT_PENDING); 429 if (pending_event_ & SEEK_EVENT_PENDING) {
437 if (use_empty_surface_ && (pending_event_ & SURFACE_CHANGE_EVENT_PENDING)) { 430 ClearDecodingData();
438 video_decoder_job_.reset(); 431 manager()->OnMediaSeekRequest(
432 player_id(), last_presentation_timestamp_, ++seek_request_id_);
433 return;
434 }
435
436 start_wallclock_time_ = base::Time();
437 if (pending_event_ & CONFIG_CHANGE_EVENT_PENDING) {
438 manager()->OnMediaConfigRequest(player_id());
439 return;
440 }
441
442 if (pending_event_ & SURFACE_CHANGE_EVENT_PENDING) {
443 CreateMediaDecoderJobs(false);
439 pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING; 444 pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
440 } 445 }
441 446
442 ClearDecodingData(); 447 if (playing_ && pending_event_ == NO_EVENT_PENDING)
443 manager()->OnMediaSeekRequest(player_id(), 448 StartInternal();
444 last_presentation_timestamp_,
445 pending_event_ & SURFACE_CHANGE_EVENT_PENDING);
446 } 449 }
447 450
448 void MediaSourcePlayer::MediaDecoderCallback( 451 void MediaSourcePlayer::MediaDecoderCallback(
449 bool is_audio, bool decode_succeeded, 452 bool is_audio, bool decode_succeeded,
450 const base::TimeDelta& presentation_timestamp, 453 const base::TimeDelta& presentation_timestamp,
451 const base::Time& wallclock_time, bool end_of_stream) { 454 const base::Time& wallclock_time, bool end_of_stream) {
452 if (active_decoding_tasks_ > 0) 455 if (active_decoding_tasks_ > 0)
453 active_decoding_tasks_--; 456 active_decoding_tasks_--;
454 457
458 if (is_audio && audio_decoder_job_)
459 audio_decoder_job_->OnDecodeCompleted();
460 if (!is_audio && video_decoder_job_)
461 video_decoder_job_->OnDecodeCompleted();
462
455 if (!decode_succeeded) { 463 if (!decode_succeeded) {
456 Release(); 464 Release();
457 OnMediaError(MEDIA_ERROR_DECODE); 465 OnMediaError(MEDIA_ERROR_DECODE);
458 return; 466 return;
459 } 467 }
460 468
461 if (pending_event_ != NO_EVENT_PENDING) { 469 if (pending_event_ != NO_EVENT_PENDING) {
462 ProcessPendingEvents(); 470 ProcessPendingEvents();
463 return; 471 return;
464 } 472 }
(...skipping 19 matching lines...) Expand all
484 if (audio_access_unit_index_ >= received_audio_.access_units.size()) { 492 if (audio_access_unit_index_ >= received_audio_.access_units.size()) {
485 if (!waiting_for_audio_data_) { 493 if (!waiting_for_audio_data_) {
486 manager()->OnReadFromDemuxer(player_id(), DemuxerStream::AUDIO, true); 494 manager()->OnReadFromDemuxer(player_id(), DemuxerStream::AUDIO, true);
487 received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params(); 495 received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
488 audio_access_unit_index_ = 0; 496 audio_access_unit_index_ = 0;
489 waiting_for_audio_data_ = true; 497 waiting_for_audio_data_ = true;
490 } 498 }
491 return; 499 return;
492 } 500 }
493 501
502 if (DemuxerStream::kConfigChanged ==
503 received_audio_.access_units[audio_access_unit_index_].status) {
504 // Wait for demuxer ready message.
505 pending_event_ |= CONFIG_CHANGE_EVENT_PENDING;
506 received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
507 audio_access_unit_index_ = 0;
508 ProcessPendingEvents();
509 return;
510 }
511
494 audio_decoder_job_->Decode( 512 audio_decoder_job_->Decode(
495 received_audio_.access_units[audio_access_unit_index_], 513 received_audio_.access_units[audio_access_unit_index_],
496 start_wallclock_time_, start_presentation_timestamp_, 514 start_wallclock_time_, start_presentation_timestamp_,
497 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, 515 base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
498 weak_this_.GetWeakPtr(), true)); 516 weak_this_.GetWeakPtr(), true));
499 active_decoding_tasks_++; 517 active_decoding_tasks_++;
500 audio_access_unit_index_++; 518 audio_access_unit_index_++;
501 } 519 }
502 520
503 void MediaSourcePlayer::DecodeMoreVideo() { 521 void MediaSourcePlayer::DecodeMoreVideo() {
504 if (video_access_unit_index_ >= received_video_.access_units.size()) { 522 if (video_access_unit_index_ >= received_video_.access_units.size()) {
505 if (!waiting_for_video_data_) { 523 if (!waiting_for_video_data_) {
506 manager()->OnReadFromDemuxer(player_id(), DemuxerStream::VIDEO, true); 524 manager()->OnReadFromDemuxer(player_id(), DemuxerStream::VIDEO, true);
507 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params(); 525 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
508 video_access_unit_index_ = 0; 526 video_access_unit_index_ = 0;
509 waiting_for_video_data_ = true; 527 waiting_for_video_data_ = true;
510 } 528 }
511 return; 529 return;
512 } 530 }
513 531
532 if (DemuxerStream::kConfigChanged ==
533 received_video_.access_units[video_access_unit_index_].status) {
534 // Wait for demuxer ready message.
535 pending_event_ |= CONFIG_CHANGE_EVENT_PENDING;
536 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
537 video_access_unit_index_ = 0;
538 ProcessPendingEvents();
539 return;
540 }
541
514 video_decoder_job_->Decode( 542 video_decoder_job_->Decode(
515 received_video_.access_units[video_access_unit_index_], 543 received_video_.access_units[video_access_unit_index_],
516 start_wallclock_time_, start_presentation_timestamp_, 544 start_wallclock_time_, start_presentation_timestamp_,
517 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, 545 base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
518 weak_this_.GetWeakPtr(), false)); 546 weak_this_.GetWeakPtr(), false));
519 active_decoding_tasks_++; 547 active_decoding_tasks_++;
520 video_access_unit_index_++; 548 video_access_unit_index_++;
521 } 549 }
522 550
523 551
(...skipping 23 matching lines...) Expand all
547 } 575 }
548 576
549 bool MediaSourcePlayer::HasVideo() { 577 bool MediaSourcePlayer::HasVideo() {
550 return kUnknownVideoCodec != video_codec_; 578 return kUnknownVideoCodec != video_codec_;
551 } 579 }
552 580
553 bool MediaSourcePlayer::HasAudio() { 581 bool MediaSourcePlayer::HasAudio() {
554 return kUnknownAudioCodec != audio_codec_; 582 return kUnknownAudioCodec != audio_codec_;
555 } 583 }
556 584
585 void MediaSourcePlayer::CreateMediaDecoderJobs(bool config_change) {
586 DCHECK_EQ(0, active_decoding_tasks_);
587
588 // Create audio decoder job only if config changes.
589 if (HasAudio() && (config_change || !audio_decoder_job_)) {
acolwell GONE FROM CHROMIUM 2013/06/04 15:19:14 I don't think this is quite right. Audio & Video c
qinmin 2013/06/04 19:03:23 added 2 new variable, |reconfig_audio_decoder_| an
590 audio_decoder_job_.reset(new AudioDecoderJob(
591 audio_codec_, sampling_rate_, num_channels_,
592 &audio_extra_data_[0], audio_extra_data_.size()));
593 }
594
595 video_decoder_job_.reset();
596 if (!HasVideo() || surface_.IsSurfaceEmpty())
597 return;
598
599 // For video, the java surface might have changed even if config does not
600 // change. So always recreate the video decoder job.
601 video_decoder_job_.reset(new VideoDecoderJob(
602 video_codec_, gfx::Size(width_, height_), surface_.j_surface().obj()));
603
604 // Inform the fullscreen view the player is ready.
605 // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way
606 // to inform ContentVideoView.
607 OnMediaMetadataChanged(duration_, width_, height_, true);
608 }
609
557 } // namespace media 610 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698