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

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: change unsigned to uint32 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 DCHECK(!decoding_);
90 decoding_ = true;
88 thread_->message_loop()->PostTask(FROM_HERE, base::Bind( 91 thread_->message_loop()->PostTask(FROM_HERE, base::Bind(
89 &MediaDecoderJob::DecodeInternal, base::Unretained(this), unit, 92 &MediaDecoderJob::DecodeInternal, base::Unretained(this), unit,
90 start_wallclock_time, start_presentation_timestamp, needs_flush_, 93 start_wallclock_time, start_presentation_timestamp, needs_flush_,
91 callback)); 94 callback));
92 needs_flush_ = false; 95 needs_flush_ = false;
93 } 96 }
94 97
95 void MediaDecoderJob::DecodeInternal( 98 void MediaDecoderJob::DecodeInternal(
96 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params::AccessUnit& unit, 99 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params::AccessUnit& unit,
97 const base::Time& start_wallclock_time, 100 const base::Time& start_wallclock_time,
98 const base::TimeDelta& start_presentation_timestamp, 101 const base::TimeDelta& start_presentation_timestamp,
99 bool needs_flush, 102 bool needs_flush,
100 const MediaDecoderJob::DecoderCallback& callback) { 103 const MediaDecoderJob::DecoderCallback& callback) {
101 if (needs_flush) 104 if (needs_flush)
102 media_codec_bridge_->Reset(); 105 media_codec_bridge_->Reset();
103 base::TimeDelta timeout = base::TimeDelta::FromMicroseconds( 106 base::TimeDelta timeout = base::TimeDelta::FromMicroseconds(
104 kMediaCodecTimeoutInMicroseconds); 107 kMediaCodecTimeoutInMicroseconds);
105 int input_buf_index = media_codec_bridge_->DequeueInputBuffer(timeout); 108 int input_buf_index = media_codec_bridge_->DequeueInputBuffer(timeout);
109 if (input_buf_index == MediaCodecBridge::INFO_MEDIA_CODEC_ERROR) {
110 message_loop_->PostTask(FROM_HERE, base::Bind(
111 callback, false, start_presentation_timestamp, start_wallclock_time,
112 false));
113 return;
114 }
106 // TODO(qinmin): skip frames if video is falling far behind. 115 // TODO(qinmin): skip frames if video is falling far behind.
107 if (input_buf_index >= 0) { 116 if (input_buf_index >= 0) {
108 if (unit.end_of_stream) { 117 if (unit.end_of_stream) {
109 media_codec_bridge_->QueueEOS(input_buf_index); 118 media_codec_bridge_->QueueEOS(input_buf_index);
110 } else { 119 } else {
111 media_codec_bridge_->QueueInputBuffer( 120 media_codec_bridge_->QueueInputBuffer(
112 input_buf_index, &unit.data[0], unit.data.size(), unit.timestamp); 121 input_buf_index, &unit.data[0], unit.data.size(), unit.timestamp);
113 } 122 }
114 } 123 }
115 size_t offset = 0; 124 size_t offset = 0;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 if (is_audio_) { 181 if (is_audio_) {
173 static_cast<AudioCodecBridge*>(media_codec_bridge_.get())->PlayOutputBuffer( 182 static_cast<AudioCodecBridge*>(media_codec_bridge_.get())->PlayOutputBuffer(
174 outputBufferIndex, size); 183 outputBufferIndex, size);
175 } 184 }
176 media_codec_bridge_->ReleaseOutputBuffer(outputBufferIndex, !is_audio_); 185 media_codec_bridge_->ReleaseOutputBuffer(outputBufferIndex, !is_audio_);
177 message_loop_->PostTask(FROM_HERE, base::Bind( 186 message_loop_->PostTask(FROM_HERE, base::Bind(
178 callback, true, presentation_timestamp, base::Time::Now(), 187 callback, true, presentation_timestamp, base::Time::Now(),
179 end_of_stream)); 188 end_of_stream));
180 } 189 }
181 190
191 void MediaDecoderJob::OnDecodeCompleted() {
192 decoding_ = false;
193 }
194
182 void MediaDecoderJob::Flush() { 195 void MediaDecoderJob::Flush() {
183 // Do nothing, flush when the next Decode() happens. 196 // Do nothing, flush when the next Decode() happens.
184 needs_flush_ = true; 197 needs_flush_ = true;
185 } 198 }
186 199
187 void MediaDecoderJob::Release() { 200 void MediaDecoderJob::Release() {
188 if (thread_->IsRunning() && 201 // If |decoding_| is false, there is nothing running on the decoder thread.
189 thread_->message_loop() != base::MessageLoop::current()) { 202 // So it is safe to delete the MediaDecoderJob on the UI thread. However,
203 // if we post a task to the decoder thread to delete object, then we cannot
204 // immediately pass the surface to a new MediaDecoderJob instance because
205 // the java surface is still owned by the old object. New decoder creation
206 // will be blocked on the UI thread until the previous decoder gets deleted.
207 // This introduces extra latency during config changes, and makes the logic in
208 // MediaSourcePlayer more complicated.
209 //
210 // TODO(qinmin): Figure out the logic to passing the surface to a new
211 // MediaDecoderJob instance after the previous one gets deleted on the decoder
212 // thread.
213 if (decoding_ && thread_->message_loop() != base::MessageLoop::current())
190 thread_->message_loop()->DeleteSoon(FROM_HERE, this); 214 thread_->message_loop()->DeleteSoon(FROM_HERE, this);
191 } else { 215 else
192 delete this; 216 delete this;
193 }
194 } 217 }
195 218
196 VideoDecoderJob::VideoDecoderJob( 219 VideoDecoderJob::VideoDecoderJob(
197 const VideoCodec video_codec, const gfx::Size& size, jobject surface) 220 const VideoCodec video_codec, const gfx::Size& size, jobject surface)
198 : MediaDecoderJob(g_video_decoder_thread.Pointer(), false) { 221 : MediaDecoderJob(g_video_decoder_thread.Pointer(), false) {
199 scoped_ptr<VideoCodecBridge> codec(VideoCodecBridge::Create(video_codec)); 222 scoped_ptr<VideoCodecBridge> codec(VideoCodecBridge::Create(video_codec));
200 codec->Start(video_codec, size, surface); 223 codec->Start(video_codec, size, surface);
201 media_codec_bridge_.reset(codec.release()); 224 media_codec_bridge_.reset(codec.release());
202 } 225 }
203 226
204 AudioDecoderJob::AudioDecoderJob( 227 AudioDecoderJob::AudioDecoderJob(
205 const AudioCodec audio_codec, 228 const AudioCodec audio_codec,
206 int sample_rate, 229 int sample_rate,
207 int channel_count, 230 int channel_count,
208 const uint8* extra_data, 231 const uint8* extra_data,
209 size_t extra_data_size) 232 size_t extra_data_size)
210 : MediaDecoderJob(g_audio_decoder_thread.Pointer(), true) { 233 : MediaDecoderJob(g_audio_decoder_thread.Pointer(), true) {
211 scoped_ptr<AudioCodecBridge> codec(AudioCodecBridge::Create(audio_codec)); 234 scoped_ptr<AudioCodecBridge> codec(AudioCodecBridge::Create(audio_codec));
212 codec->Start(audio_codec, sample_rate, channel_count, extra_data, 235 codec->Start(audio_codec, sample_rate, channel_count, extra_data,
213 extra_data_size, true); 236 extra_data_size, true);
214 media_codec_bridge_.reset(codec.release()); 237 media_codec_bridge_.reset(codec.release());
215 } 238 }
216 239
217 MediaSourcePlayer::MediaSourcePlayer( 240 MediaSourcePlayer::MediaSourcePlayer(
218 int player_id, 241 int player_id,
219 MediaPlayerManager* manager) 242 MediaPlayerManager* manager)
220 : MediaPlayerAndroid(player_id, manager), 243 : MediaPlayerAndroid(player_id, manager),
221 pending_event_(NO_EVENT_PENDING), 244 pending_event_(NO_EVENT_PENDING),
222 active_decoding_tasks_(0), 245 active_decoding_tasks_(0),
246 seek_request_id_(0),
223 width_(0), 247 width_(0),
224 height_(0), 248 height_(0),
225 audio_codec_(kUnknownAudioCodec), 249 audio_codec_(kUnknownAudioCodec),
226 video_codec_(kUnknownVideoCodec), 250 video_codec_(kUnknownVideoCodec),
227 num_channels_(0), 251 num_channels_(0),
228 sampling_rate_(0), 252 sampling_rate_(0),
229 seekable_(true), 253 seekable_(true),
230 audio_finished_(true), 254 audio_finished_(true),
231 video_finished_(true), 255 video_finished_(true),
232 playing_(false), 256 playing_(false),
257 reconfig_audio_decoder_(false),
258 reconfig_video_decoder_(false),
233 audio_access_unit_index_(0), 259 audio_access_unit_index_(0),
234 video_access_unit_index_(0), 260 video_access_unit_index_(0),
235 waiting_for_audio_data_(false), 261 waiting_for_audio_data_(false),
236 waiting_for_video_data_(false), 262 waiting_for_video_data_(false),
237 use_empty_surface_(true),
238 weak_this_(this) { 263 weak_this_(this) {
239 } 264 }
240 265
241 MediaSourcePlayer::~MediaSourcePlayer() { 266 MediaSourcePlayer::~MediaSourcePlayer() {
242 Release(); 267 Release();
243 } 268 }
244 269
245 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { 270 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) {
246 use_empty_surface_ = surface.IsSurfaceEmpty(); 271 surface_ = surface.Pass();
247 272 pending_event_ |= SURFACE_CHANGE_EVENT_PENDING;
248 // If we haven't processed a surface change event, do so now. 273 // Setting a new surface will require a new MediaCodec to be created.
249 if (active_decoding_tasks_ > 0) { 274 // Request a seek so that the new decoder will decode an I-frame first.
250 pending_event_ |= SURFACE_CHANGE_EVENT_PENDING; 275 // Or otherwise, the new MediaCodec might crash. See b/8950387.
251 // Request a seek so that the next decoder will decode an I-frame first. 276 pending_event_ |= SEEK_EVENT_PENDING;
252 // Or otherwise, MediaCodec might crash. See b/8950387. 277 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 } 278 }
281 279
282 void MediaSourcePlayer::Start() { 280 void MediaSourcePlayer::Start() {
283 playing_ = true; 281 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 282
290 if (HasVideo() && !video_decoder_job_) { 283 CreateAudioDecoderJob();
291 // StartInternal() will be delayed until SetVideoSurface() gets called. 284 CreateVideoDecoderJob();
292 return;
293 }
294 285
295 StartInternal(); 286 StartInternal();
296 } 287 }
297 288
298 void MediaSourcePlayer::Pause() { 289 void MediaSourcePlayer::Pause() {
299 playing_ = false; 290 playing_ = false;
300 start_wallclock_time_ = base::Time(); 291 start_wallclock_time_ = base::Time();
301 } 292 }
302 293
303 bool MediaSourcePlayer::IsPlaying() { 294 bool MediaSourcePlayer::IsPlaying() {
(...skipping 19 matching lines...) Expand all
323 } 314 }
324 315
325 base::TimeDelta MediaSourcePlayer::GetDuration() { 316 base::TimeDelta MediaSourcePlayer::GetDuration() {
326 return duration_; 317 return duration_;
327 } 318 }
328 319
329 void MediaSourcePlayer::Release() { 320 void MediaSourcePlayer::Release() {
330 ClearDecodingData(); 321 ClearDecodingData();
331 audio_decoder_job_.reset(); 322 audio_decoder_job_.reset();
332 video_decoder_job_.reset(); 323 video_decoder_job_.reset();
324 reconfig_audio_decoder_ = true;
acolwell GONE FROM CHROMIUM 2013/06/06 14:32:19 nit: Should these be false too so they match the c
qinmin 2013/06/06 16:32:34 Yes. Since the decoder jobs are deleted, we will a
325 reconfig_video_decoder_ = true;
333 active_decoding_tasks_ = 0; 326 active_decoding_tasks_ = 0;
334 playing_ = false; 327 playing_ = false;
335 pending_event_ = NO_EVENT_PENDING; 328 pending_event_ = NO_EVENT_PENDING;
329 surface_ = gfx::ScopedJavaSurface();
336 ReleaseMediaResourcesFromManager(); 330 ReleaseMediaResourcesFromManager();
337 } 331 }
338 332
339 void MediaSourcePlayer::SetVolume(float leftVolume, float rightVolume) { 333 void MediaSourcePlayer::SetVolume(float leftVolume, float rightVolume) {
340 } 334 }
341 335
342 bool MediaSourcePlayer::CanPause() { 336 bool MediaSourcePlayer::CanPause() {
343 return seekable_; 337 return seekable_;
344 } 338 }
345 339
346 bool MediaSourcePlayer::CanSeekForward() { 340 bool MediaSourcePlayer::CanSeekForward() {
347 return seekable_; 341 return seekable_;
348 } 342 }
349 343
350 bool MediaSourcePlayer::CanSeekBackward() { 344 bool MediaSourcePlayer::CanSeekBackward() {
351 return seekable_; 345 return seekable_;
352 } 346 }
353 347
354 bool MediaSourcePlayer::IsPlayerReady() { 348 bool MediaSourcePlayer::IsPlayerReady() {
355 return audio_decoder_job_ || video_decoder_job_; 349 return audio_decoder_job_ || video_decoder_job_;
356 } 350 }
357 351
358 void MediaSourcePlayer::StartInternal() { 352 void MediaSourcePlayer::StartInternal() {
359 // Do nothing if the decoders are already running. 353 // Do nothing if the decoders are already running.
360 if (active_decoding_tasks_ > 0 || pending_event_ != NO_EVENT_PENDING) 354 if (active_decoding_tasks_ > 0 || pending_event_ != NO_EVENT_PENDING)
361 return; 355 return;
362 356
357 // If one of the decoder job is not ready, do nothing.
358 if ((HasAudio() && !audio_decoder_job_) ||
359 (HasVideo() && !video_decoder_job_)) {
360 return;
361 }
362
363 if (HasAudio()) { 363 if (HasAudio()) {
364 audio_finished_ = false; 364 audio_finished_ = false;
365 DecodeMoreAudio(); 365 DecodeMoreAudio();
366 } 366 }
367 if (HasVideo()) { 367 if (HasVideo()) {
368 video_finished_ = false; 368 video_finished_ = false;
369 DecodeMoreVideo(); 369 DecodeMoreVideo();
370 } 370 }
371 } 371 }
372 372
373 void MediaSourcePlayer::DemuxerReady( 373 void MediaSourcePlayer::DemuxerReady(
374 const MediaPlayerHostMsg_DemuxerReady_Params& params) { 374 const MediaPlayerHostMsg_DemuxerReady_Params& params) {
375 if (params.duration_ms == std::numeric_limits<int>::max()) 375 if (params.duration_ms == std::numeric_limits<int>::max())
376 seekable_ = false; 376 seekable_ = false;
377 duration_ = base::TimeDelta::FromMilliseconds(params.duration_ms); 377 duration_ = base::TimeDelta::FromMilliseconds(params.duration_ms);
378 width_ = params.video_size.width(); 378 width_ = params.video_size.width();
379 height_ = params.video_size.height(); 379 height_ = params.video_size.height();
380 num_channels_ = params.audio_channels; 380 num_channels_ = params.audio_channels;
381 sampling_rate_ = params.audio_sampling_rate; 381 sampling_rate_ = params.audio_sampling_rate;
382 audio_codec_ = params.audio_codec; 382 audio_codec_ = params.audio_codec;
383 video_codec_ = params.video_codec; 383 video_codec_ = params.video_codec;
384 audio_extra_data_ = params.audio_extra_data; 384 audio_extra_data_ = params.audio_extra_data;
385 OnMediaMetadataChanged(duration_, width_, height_, true); 385 OnMediaMetadataChanged(duration_, width_, height_, true);
386 if (pending_event_ & CONFIG_CHANGE_EVENT_PENDING) {
387 if (reconfig_audio_decoder_) {
388 CreateAudioDecoderJob();
389 }
390 // If there is a pending surface change, we can merge it with the config
391 // change.
392 if (reconfig_video_decoder_) {
393 pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
394 CreateVideoDecoderJob();
395 }
396 pending_event_ &= ~CONFIG_CHANGE_EVENT_PENDING;
397 if (playing_ && pending_event_ == NO_EVENT_PENDING)
398 StartInternal();
399 }
386 } 400 }
387 401
388 void MediaSourcePlayer::ReadFromDemuxerAck( 402 void MediaSourcePlayer::ReadFromDemuxerAck(
389 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) { 403 const MediaPlayerHostMsg_ReadFromDemuxerAck_Params& params) {
390 if (params.type == DemuxerStream::AUDIO) 404 if (params.type == DemuxerStream::AUDIO)
391 waiting_for_audio_data_ = false; 405 waiting_for_audio_data_ = false;
392 else 406 else
393 waiting_for_video_data_ = false; 407 waiting_for_video_data_ = false;
394 408
395 // If there is a pending seek request, ignore the data from the chunk demuxer. 409 // 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. 410 // The data will be requested later when OnSeekRequestAck() is called.
397 if (pending_event_ & SEEK_EVENT_PENDING) 411 if (pending_event_ & SEEK_EVENT_PENDING)
398 return; 412 return;
399 413
400 if (params.type == DemuxerStream::AUDIO) { 414 if (params.type == DemuxerStream::AUDIO) {
401 DCHECK_EQ(0u, audio_access_unit_index_); 415 DCHECK_EQ(0u, audio_access_unit_index_);
402 received_audio_ = params; 416 received_audio_ = params;
403 if (!pending_event_) 417 if (!pending_event_)
404 DecodeMoreAudio(); 418 DecodeMoreAudio();
405 } else { 419 } else {
406 DCHECK_EQ(0u, video_access_unit_index_); 420 DCHECK_EQ(0u, video_access_unit_index_);
407 received_video_ = params; 421 received_video_ = params;
408 if (!pending_event_) 422 if (!pending_event_)
409 DecodeMoreVideo(); 423 DecodeMoreVideo();
410 } 424 }
411 } 425 }
412 426
413 void MediaSourcePlayer::OnSeekRequestAck() { 427 void MediaSourcePlayer::OnSeekRequestAck(unsigned seek_request_id) {
428 // Do nothing until the most recent seek request is processed.
429 if (seek_request_id_ != seek_request_id)
430 return;
414 pending_event_ &= ~SEEK_EVENT_PENDING; 431 pending_event_ &= ~SEEK_EVENT_PENDING;
415 OnSeekComplete(); 432 OnSeekComplete();
416 if (playing_) 433 ProcessPendingEvents();
417 StartInternal();
418 } 434 }
419 435
420 void MediaSourcePlayer::UpdateTimestamps( 436 void MediaSourcePlayer::UpdateTimestamps(
421 const base::TimeDelta& presentation_timestamp, 437 const base::TimeDelta& presentation_timestamp,
422 const base::Time& wallclock_time) { 438 const base::Time& wallclock_time) {
423 last_presentation_timestamp_ = presentation_timestamp; 439 last_presentation_timestamp_ = presentation_timestamp;
424 OnTimeUpdated(); 440 OnTimeUpdated();
425 if (start_wallclock_time_.is_null() && playing_) { 441 if (start_wallclock_time_.is_null() && playing_) {
426 start_wallclock_time_ = wallclock_time; 442 start_wallclock_time_ = wallclock_time;
427 start_presentation_timestamp_ = last_presentation_timestamp_; 443 start_presentation_timestamp_ = last_presentation_timestamp_;
428 } 444 }
429 } 445 }
430 446
431 void MediaSourcePlayer::ProcessPendingEvents() { 447 void MediaSourcePlayer::ProcessPendingEvents() {
432 // Wait for all the decoding jobs to finish before sending a seek request. 448 // Wait for all the decoding jobs to finish before processing pending tasks.
433 if (active_decoding_tasks_ > 0) 449 if (active_decoding_tasks_ > 0)
434 return; 450 return;
435 451
436 DCHECK(pending_event_ != NO_EVENT_PENDING); 452 if (pending_event_ & SEEK_EVENT_PENDING) {
437 if (use_empty_surface_ && (pending_event_ & SURFACE_CHANGE_EVENT_PENDING)) { 453 ClearDecodingData();
454 manager()->OnMediaSeekRequest(
455 player_id(), last_presentation_timestamp_, ++seek_request_id_);
456 return;
457 }
458
459 start_wallclock_time_ = base::Time();
460 if (pending_event_ & CONFIG_CHANGE_EVENT_PENDING) {
461 DCHECK(reconfig_audio_decoder_ || reconfig_video_decoder_);
462 manager()->OnMediaConfigRequest(player_id());
463 return;
464 }
465
466 if (pending_event_ & SURFACE_CHANGE_EVENT_PENDING) {
438 video_decoder_job_.reset(); 467 video_decoder_job_.reset();
468 CreateVideoDecoderJob();
439 pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING; 469 pending_event_ &= ~SURFACE_CHANGE_EVENT_PENDING;
440 } 470 }
441 471
442 ClearDecodingData(); 472 if (playing_ && pending_event_ == NO_EVENT_PENDING)
443 manager()->OnMediaSeekRequest(player_id(), 473 StartInternal();
444 last_presentation_timestamp_,
445 pending_event_ & SURFACE_CHANGE_EVENT_PENDING);
446 } 474 }
447 475
448 void MediaSourcePlayer::MediaDecoderCallback( 476 void MediaSourcePlayer::MediaDecoderCallback(
449 bool is_audio, bool decode_succeeded, 477 bool is_audio, bool decode_succeeded,
450 const base::TimeDelta& presentation_timestamp, 478 const base::TimeDelta& presentation_timestamp,
451 const base::Time& wallclock_time, bool end_of_stream) { 479 const base::Time& wallclock_time, bool end_of_stream) {
452 if (active_decoding_tasks_ > 0) 480 if (active_decoding_tasks_ > 0)
453 active_decoding_tasks_--; 481 active_decoding_tasks_--;
454 482
483 if (is_audio && audio_decoder_job_)
484 audio_decoder_job_->OnDecodeCompleted();
485 if (!is_audio && video_decoder_job_)
486 video_decoder_job_->OnDecodeCompleted();
487
455 if (!decode_succeeded) { 488 if (!decode_succeeded) {
456 Release(); 489 Release();
457 OnMediaError(MEDIA_ERROR_DECODE); 490 OnMediaError(MEDIA_ERROR_DECODE);
458 return; 491 return;
459 } 492 }
460 493
461 if (pending_event_ != NO_EVENT_PENDING) { 494 if (pending_event_ != NO_EVENT_PENDING) {
462 ProcessPendingEvents(); 495 ProcessPendingEvents();
463 return; 496 return;
464 } 497 }
(...skipping 19 matching lines...) Expand all
484 if (audio_access_unit_index_ >= received_audio_.access_units.size()) { 517 if (audio_access_unit_index_ >= received_audio_.access_units.size()) {
485 if (!waiting_for_audio_data_) { 518 if (!waiting_for_audio_data_) {
486 manager()->OnReadFromDemuxer(player_id(), DemuxerStream::AUDIO, true); 519 manager()->OnReadFromDemuxer(player_id(), DemuxerStream::AUDIO, true);
487 received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params(); 520 received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
488 audio_access_unit_index_ = 0; 521 audio_access_unit_index_ = 0;
489 waiting_for_audio_data_ = true; 522 waiting_for_audio_data_ = true;
490 } 523 }
491 return; 524 return;
492 } 525 }
493 526
527 if (DemuxerStream::kConfigChanged ==
528 received_audio_.access_units[audio_access_unit_index_].status) {
529 // Wait for demuxer ready message.
530 reconfig_audio_decoder_ = true;
531 pending_event_ |= CONFIG_CHANGE_EVENT_PENDING;
532 received_audio_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
533 audio_access_unit_index_ = 0;
534 ProcessPendingEvents();
535 return;
536 }
537
494 audio_decoder_job_->Decode( 538 audio_decoder_job_->Decode(
495 received_audio_.access_units[audio_access_unit_index_], 539 received_audio_.access_units[audio_access_unit_index_],
496 start_wallclock_time_, start_presentation_timestamp_, 540 start_wallclock_time_, start_presentation_timestamp_,
497 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, 541 base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
498 weak_this_.GetWeakPtr(), true)); 542 weak_this_.GetWeakPtr(), true));
499 active_decoding_tasks_++; 543 active_decoding_tasks_++;
500 audio_access_unit_index_++; 544 audio_access_unit_index_++;
501 } 545 }
502 546
503 void MediaSourcePlayer::DecodeMoreVideo() { 547 void MediaSourcePlayer::DecodeMoreVideo() {
504 if (video_access_unit_index_ >= received_video_.access_units.size()) { 548 if (video_access_unit_index_ >= received_video_.access_units.size()) {
505 if (!waiting_for_video_data_) { 549 if (!waiting_for_video_data_) {
506 manager()->OnReadFromDemuxer(player_id(), DemuxerStream::VIDEO, true); 550 manager()->OnReadFromDemuxer(player_id(), DemuxerStream::VIDEO, true);
507 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params(); 551 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
508 video_access_unit_index_ = 0; 552 video_access_unit_index_ = 0;
509 waiting_for_video_data_ = true; 553 waiting_for_video_data_ = true;
510 } 554 }
511 return; 555 return;
512 } 556 }
513 557
558 if (DemuxerStream::kConfigChanged ==
559 received_video_.access_units[video_access_unit_index_].status) {
560 // Wait for demuxer ready message.
561 reconfig_video_decoder_ = true;
562 pending_event_ |= CONFIG_CHANGE_EVENT_PENDING;
563 received_video_ = MediaPlayerHostMsg_ReadFromDemuxerAck_Params();
564 video_access_unit_index_ = 0;
565 ProcessPendingEvents();
566 return;
567 }
568
514 video_decoder_job_->Decode( 569 video_decoder_job_->Decode(
515 received_video_.access_units[video_access_unit_index_], 570 received_video_.access_units[video_access_unit_index_],
516 start_wallclock_time_, start_presentation_timestamp_, 571 start_wallclock_time_, start_presentation_timestamp_,
517 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, 572 base::Bind(&MediaSourcePlayer::MediaDecoderCallback,
518 weak_this_.GetWeakPtr(), false)); 573 weak_this_.GetWeakPtr(), false));
519 active_decoding_tasks_++; 574 active_decoding_tasks_++;
520 video_access_unit_index_++; 575 video_access_unit_index_++;
521 } 576 }
522 577
523 578
(...skipping 23 matching lines...) Expand all
547 } 602 }
548 603
549 bool MediaSourcePlayer::HasVideo() { 604 bool MediaSourcePlayer::HasVideo() {
550 return kUnknownVideoCodec != video_codec_; 605 return kUnknownVideoCodec != video_codec_;
551 } 606 }
552 607
553 bool MediaSourcePlayer::HasAudio() { 608 bool MediaSourcePlayer::HasAudio() {
554 return kUnknownAudioCodec != audio_codec_; 609 return kUnknownAudioCodec != audio_codec_;
555 } 610 }
556 611
612 void MediaSourcePlayer::CreateAudioDecoderJob() {
613 DCHECK_EQ(0, active_decoding_tasks_);
614
615 // Create audio decoder job only if config changes.
616 if (HasAudio() && (reconfig_audio_decoder_ || !audio_decoder_job_)) {
617 audio_decoder_job_.reset(new AudioDecoderJob(
618 audio_codec_, sampling_rate_, num_channels_,
619 &audio_extra_data_[0], audio_extra_data_.size()));
620 reconfig_audio_decoder_ = false;
621 }
622 }
623
624 void MediaSourcePlayer::CreateVideoDecoderJob() {
625 DCHECK_EQ(0, active_decoding_tasks_);
626
627 if (!HasVideo() || surface_.IsSurfaceEmpty()) {
628 video_decoder_job_.reset();
629 return;
630 }
631
632 if (reconfig_video_decoder_ || !video_decoder_job_) {
633 video_decoder_job_.reset();
634 video_decoder_job_.reset(new VideoDecoderJob(
635 video_codec_, gfx::Size(width_, height_), surface_.j_surface().obj()));
636 reconfig_video_decoder_ = false;
637 }
638
639 // Inform the fullscreen view the player is ready.
640 // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way
641 // to inform ContentVideoView.
642 OnMediaMetadataChanged(duration_, width_, height_, true);
643 }
644
557 } // namespace media 645 } // namespace media
OLDNEW
« no previous file with comments | « media/base/android/media_source_player.h ('k') | webkit/renderer/media/android/media_source_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698