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

Side by Side Diff: media/filters/chunk_demuxer.cc

Issue 10696182: Add config change handling to SourceBufferStream & ChunkDemuxer (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 5 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/filters/chunk_demuxer.h" 5 #include "media/filters/chunk_demuxer.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 virtual const VideoDecoderConfig& video_decoder_config() OVERRIDE; 185 virtual const VideoDecoderConfig& video_decoder_config() OVERRIDE;
186 virtual Ranges<TimeDelta> GetBufferedRanges() OVERRIDE; 186 virtual Ranges<TimeDelta> GetBufferedRanges() OVERRIDE;
187 187
188 protected: 188 protected:
189 virtual ~ChunkDemuxerStream(); 189 virtual ~ChunkDemuxerStream();
190 190
191 private: 191 private:
192 enum State { 192 enum State {
193 RETURNING_DATA_FOR_READS, 193 RETURNING_DATA_FOR_READS,
194 WAITING_FOR_SEEK, 194 WAITING_FOR_SEEK,
195 CONFIG_CHANGE,
195 SHUTDOWN, 196 SHUTDOWN,
196 }; 197 };
197 198
198 // Assigns |state_| to |state| 199 // Assigns |state_| to |state|
199 void ChangeState_Locked(State state); 200 void ChangeState_Locked(State state);
200 201
201 // Adds the callback to |read_cbs_| so it can be called later when we 202 // Adds the callback to |read_cbs_| so it can be called later when we
202 // have data. 203 // have data.
203 void DeferRead_Locked(const ReadCB& read_cb); 204 void DeferRead_Locked(const ReadCB& read_cb);
204 205
205 // Creates closures that bind ReadCBs in |read_cbs_| to data in 206 // Creates closures that bind ReadCBs in |read_cbs_| to data in
206 // |buffers_| and pops the callbacks & buffers from the respecive queues. 207 // |buffers_| and pops the callbacks & buffers from the respecive queues.
207 void CreateReadDoneClosures_Locked(ClosureQueue* closures); 208 void CreateReadDoneClosures_Locked(ClosureQueue* closures);
208 209
210 // Called when audio_decoder_config() or video_decoder_config() is called.
211 // This method handles transitioning from
212 // CONFIG_CHANGE to RETURNING_DATA_FOR_READS if necessary.
213 void OnConfigRequest();
214
209 // Specifies the type of the stream (must be AUDIO or VIDEO for now). 215 // Specifies the type of the stream (must be AUDIO or VIDEO for now).
210 Type type_; 216 Type type_;
211 217
212 scoped_ptr<SourceBufferStream> stream_; 218 scoped_ptr<SourceBufferStream> stream_;
213 219
214 mutable base::Lock lock_; 220 mutable base::Lock lock_;
215 State state_; 221 State state_;
216 ReadCBQueue read_cbs_; 222 ReadCBQueue read_cbs_;
217 223
218 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); 224 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 } 293 }
288 294
289 Ranges<TimeDelta> ChunkDemuxerStream::GetBufferedRanges() { 295 Ranges<TimeDelta> ChunkDemuxerStream::GetBufferedRanges() {
290 base::AutoLock auto_lock(lock_); 296 base::AutoLock auto_lock(lock_);
291 return stream_->GetBufferedTime(); 297 return stream_->GetBufferedTime();
292 } 298 }
293 299
294 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config) { 300 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config) {
295 DCHECK(config.IsValidConfig()); 301 DCHECK(config.IsValidConfig());
296 DCHECK_EQ(type_, AUDIO); 302 DCHECK_EQ(type_, AUDIO);
297 303 return stream_->UpdateAudioConfig(config);
298 const AudioDecoderConfig& current_config =
299 stream_->GetCurrentAudioDecoderConfig();
300
301 bool success = (current_config.codec() == config.codec()) &&
302 (current_config.bits_per_channel() == config.bits_per_channel()) &&
303 (current_config.channel_layout() == config.channel_layout()) &&
304 (current_config.samples_per_second() == config.samples_per_second()) &&
305 (current_config.extra_data_size() == config.extra_data_size()) &&
306 (!current_config.extra_data() ||
307 !memcmp(current_config.extra_data(), config.extra_data(),
308 current_config.extra_data_size()));
309
310 if (!success)
311 DVLOG(1) << "UpdateAudioConfig() : Failed to update audio config.";
312
313 return success;
314 } 304 }
315 305
316 bool ChunkDemuxerStream::UpdateVideoConfig(const VideoDecoderConfig& config) { 306 bool ChunkDemuxerStream::UpdateVideoConfig(const VideoDecoderConfig& config) {
317 DCHECK(config.IsValidConfig()); 307 DCHECK(config.IsValidConfig());
318 DCHECK_EQ(type_, VIDEO); 308 DCHECK_EQ(type_, VIDEO);
319 const VideoDecoderConfig& current_config = 309 return stream_->UpdateVideoConfig(config);
320 stream_->GetCurrentVideoDecoderConfig();
321
322 bool success = (current_config.codec() == config.codec()) &&
323 (current_config.format() == config.format()) &&
324 (current_config.profile() == config.profile()) &&
325 (current_config.coded_size() == config.coded_size()) &&
326 (current_config.visible_rect() == config.visible_rect()) &&
327 (current_config.natural_size() == config.natural_size()) &&
328 (current_config.extra_data_size() == config.extra_data_size()) &&
329 (!current_config.extra_data() ||
330 !memcmp(current_config.extra_data(), config.extra_data(),
331 current_config.extra_data_size()));
332
333 if (!success)
334 DVLOG(1) << "UpdateVideoConfig() : Failed to update video config.";
335
336 return success;
337 } 310 }
338 311
339 void ChunkDemuxerStream::EndOfStream() { 312 void ChunkDemuxerStream::EndOfStream() {
340 ClosureQueue closures; 313 ClosureQueue closures;
341 { 314 {
342 base::AutoLock auto_lock(lock_); 315 base::AutoLock auto_lock(lock_);
343 stream_->EndOfStream(); 316 stream_->EndOfStream();
344 CreateReadDoneClosures_Locked(&closures); 317 CreateReadDoneClosures_Locked(&closures);
345 } 318 }
346 319
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 void ChunkDemuxerStream::Read(const ReadCB& read_cb) { 358 void ChunkDemuxerStream::Read(const ReadCB& read_cb) {
386 DemuxerStream::Status status = kOk; 359 DemuxerStream::Status status = kOk;
387 scoped_refptr<StreamParserBuffer> buffer; 360 scoped_refptr<StreamParserBuffer> buffer;
388 { 361 {
389 base::AutoLock auto_lock(lock_); 362 base::AutoLock auto_lock(lock_);
390 363
391 switch (state_) { 364 switch (state_) {
392 case RETURNING_DATA_FOR_READS: 365 case RETURNING_DATA_FOR_READS:
393 // If we already have pending reads or we don't have any buffers ready, 366 // If we already have pending reads or we don't have any buffers ready,
394 // then defer this read. 367 // then defer this read.
395 if (!read_cbs_.empty() || !stream_->GetNextBuffer(&buffer)) { 368 if (!read_cbs_.empty()) {
396 DeferRead_Locked(read_cb); 369 DeferRead_Locked(read_cb);
397 return; 370 return;
398 } 371 }
372
373 switch (stream_->GetNextBuffer(&buffer)) {
374 case SourceBufferStream::kSuccess:
375 // Do nothing and continue
vrk (LEFT CHROMIUM) 2012/07/12 19:37:55 nit: period at end
acolwell GONE FROM CHROMIUM 2012/07/12 23:07:58 Done.
376 break;
377 case SourceBufferStream::kNeedBuffer:
378 DeferRead_Locked(read_cb);
379 return;
380 case SourceBufferStream::kConfigChange:
381 ChangeState_Locked(CONFIG_CHANGE);
382 status = kConfigChanged;
383 break;
384 }
399 break; 385 break;
400 case WAITING_FOR_SEEK: 386 case WAITING_FOR_SEEK:
401 // Null buffers should be returned in this state since we are waiting 387 // Null buffers should be returned in this state since we are waiting
402 // for a seek. Any buffers in the SourceBuffer should NOT be returned 388 // for a seek. Any buffers in the SourceBuffer should NOT be returned
403 // because they are associated with the seek. 389 // because they are associated with the seek.
404 DCHECK(read_cbs_.empty()); 390 DCHECK(read_cbs_.empty());
405 status = kAborted; 391 status = kAborted;
406 break; 392 break;
393 case CONFIG_CHANGE:
394 DCHECK(read_cbs_.empty());
395 status = kConfigChanged;
396 break;
407 case SHUTDOWN: 397 case SHUTDOWN:
408 DCHECK(read_cbs_.empty()); 398 DCHECK(read_cbs_.empty());
409 buffer = StreamParserBuffer::CreateEOSBuffer(); 399 buffer = StreamParserBuffer::CreateEOSBuffer();
410 } 400 }
411 } 401 }
412 402
413 read_cb.Run(status, buffer); 403 read_cb.Run(status, buffer);
414 } 404 }
415 405
416 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; } 406 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; }
417 407
418 void ChunkDemuxerStream::EnableBitstreamConverter() {} 408 void ChunkDemuxerStream::EnableBitstreamConverter() {}
419 409
420 const AudioDecoderConfig& ChunkDemuxerStream::audio_decoder_config() { 410 const AudioDecoderConfig& ChunkDemuxerStream::audio_decoder_config() {
vrk (LEFT CHROMIUM) 2012/07/12 19:37:55 nit: {audio,video}_decoder_config() does more than
421 CHECK_EQ(type_, AUDIO); 411 CHECK_EQ(type_, AUDIO);
422 base::AutoLock auto_lock(lock_); 412 base::AutoLock auto_lock(lock_);
413 OnConfigRequest();
423 return stream_->GetCurrentAudioDecoderConfig(); 414 return stream_->GetCurrentAudioDecoderConfig();
424 } 415 }
425 416
426 const VideoDecoderConfig& ChunkDemuxerStream::video_decoder_config() { 417 const VideoDecoderConfig& ChunkDemuxerStream::video_decoder_config() {
427 CHECK_EQ(type_, VIDEO); 418 CHECK_EQ(type_, VIDEO);
428 base::AutoLock auto_lock(lock_); 419 base::AutoLock auto_lock(lock_);
420 OnConfigRequest();
429 return stream_->GetCurrentVideoDecoderConfig(); 421 return stream_->GetCurrentVideoDecoderConfig();
430 } 422 }
431 423
424 void ChunkDemuxerStream::OnConfigRequest() {
425 lock_.AssertAcquired();
426 if (state_ == CONFIG_CHANGE) {
427 stream_->UpdateCurrentConfigIndex();
vrk (LEFT CHROMIUM) 2012/07/12 19:37:55 Change method name to something like "CompleteConf
acolwell GONE FROM CHROMIUM 2012/07/12 23:07:58 Done.
428 ChangeState_Locked(RETURNING_DATA_FOR_READS);
429 }
430 }
431
432 void ChunkDemuxerStream::ChangeState_Locked(State state) { 432 void ChunkDemuxerStream::ChangeState_Locked(State state) {
433 lock_.AssertAcquired(); 433 lock_.AssertAcquired();
434 DVLOG(1) << "ChunkDemuxerStream::ChangeState_Locked() : "
435 << "type " << type_
436 << " - " << state_ << " -> " << state;
434 state_ = state; 437 state_ = state;
435 } 438 }
436 439
437 ChunkDemuxerStream::~ChunkDemuxerStream() {} 440 ChunkDemuxerStream::~ChunkDemuxerStream() {}
438 441
439 void ChunkDemuxerStream::DeferRead_Locked(const ReadCB& read_cb) { 442 void ChunkDemuxerStream::DeferRead_Locked(const ReadCB& read_cb) {
440 lock_.AssertAcquired(); 443 lock_.AssertAcquired();
441 // Wrap & store |read_cb| so that it will 444 // Wrap & store |read_cb| so that it will
442 // get called on the current MessageLoop. 445 // get called on the current MessageLoop.
443 read_cbs_.push_back(base::Bind(&RunOnMessageLoop, read_cb, 446 read_cbs_.push_back(base::Bind(&RunOnMessageLoop, read_cb,
444 MessageLoop::current())); 447 MessageLoop::current()));
445 } 448 }
446 449
447 void ChunkDemuxerStream::CreateReadDoneClosures_Locked(ClosureQueue* closures) { 450 void ChunkDemuxerStream::CreateReadDoneClosures_Locked(ClosureQueue* closures) {
448 lock_.AssertAcquired(); 451 lock_.AssertAcquired();
449 452
450 if (state_ != RETURNING_DATA_FOR_READS) 453 if (state_ != RETURNING_DATA_FOR_READS)
451 return; 454 return;
452 455
453 scoped_refptr<StreamParserBuffer> buffer; 456 bool configChange = false;
454 while (!read_cbs_.empty()) { 457 while (!read_cbs_.empty()) {
455 if (!stream_->GetNextBuffer(&buffer)) 458 scoped_refptr<StreamParserBuffer> buffer;
456 return; 459 switch (stream_->GetNextBuffer(&buffer)) {
457 closures->push_back(base::Bind(read_cbs_.front(), 460 case SourceBufferStream::kSuccess:
458 DemuxerStream::kOk, buffer)); 461 closures->push_back(base::Bind(read_cbs_.front(),
459 read_cbs_.pop_front(); 462 DemuxerStream::kOk, buffer));
463 read_cbs_.pop_front();
464 break;
465 case SourceBufferStream::kNeedBuffer:
466 return;
467 case SourceBufferStream::kConfigChange:
468 configChange = true;
469 closures->push_back(base::Bind(read_cbs_.front(),
470 DemuxerStream::kConfigChanged,
471 scoped_refptr<DecoderBuffer>()));
472 read_cbs_.pop_front();
473 }
460 } 474 }
475 if (configChange)
476 ChangeState_Locked(CONFIG_CHANGE);
461 } 477 }
462 478
463 ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) 479 ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client)
464 : state_(WAITING_FOR_INIT), 480 : state_(WAITING_FOR_INIT),
465 host_(NULL), 481 host_(NULL),
466 client_(client) { 482 client_(client) {
467 DCHECK(client); 483 DCHECK(client);
468 } 484 }
469 485
470 void ChunkDemuxer::Initialize(DemuxerHost* host, 486 void ChunkDemuxer::Initialize(DemuxerHost* host,
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 // TODO(vrk): There should be a special case for the first appends where all 998 // TODO(vrk): There should be a special case for the first appends where all
983 // streams (for both demuxed and muxed case) begin at the earliest stream 999 // streams (for both demuxed and muxed case) begin at the earliest stream
984 // timestamp. (crbug.com/132815) 1000 // timestamp. (crbug.com/132815)
985 if (audio_ && source_id == source_id_audio_) 1001 if (audio_ && source_id == source_id_audio_)
986 audio_->OnNewMediaSegment(start_timestamp); 1002 audio_->OnNewMediaSegment(start_timestamp);
987 if (video_ && source_id == source_id_video_) 1003 if (video_ && source_id == source_id_video_)
988 video_->OnNewMediaSegment(start_timestamp); 1004 video_->OnNewMediaSegment(start_timestamp);
989 } 1005 }
990 1006
991 } // namespace media 1007 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698