| OLD | NEW |
| 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/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 | 204 |
| 205 // Adds the callback to |read_cbs_| so it can be called later when we | 205 // Adds the callback to |read_cbs_| so it can be called later when we |
| 206 // have data. | 206 // have data. |
| 207 void DeferRead_Locked(const ReadCB& read_cb); | 207 void DeferRead_Locked(const ReadCB& read_cb); |
| 208 | 208 |
| 209 // Creates closures that bind ReadCBs in |read_cbs_| to data in | 209 // Creates closures that bind ReadCBs in |read_cbs_| to data in |
| 210 // |buffers_| and pops the callbacks & buffers from the respecive queues. | 210 // |buffers_| and pops the callbacks & buffers from the respecive queues. |
| 211 void CreateReadDoneClosures_Locked(ClosureQueue* closures); | 211 void CreateReadDoneClosures_Locked(ClosureQueue* closures); |
| 212 | 212 |
| 213 // Gets the value to pass to the next Read() callback. Returns true if | 213 // Gets the value to pass to the next Read() callback. Returns true if |
| 214 // |buffer| should be passed to the callback. False indicates that |buffer| | 214 // |status| and |buffer| should be passed to the callback. False indicates |
| 215 // was not set and more data is needed. | 215 // that |status| and |buffer| were not set and more data is needed. |
| 216 bool GetNextBuffer_Locked(scoped_refptr<StreamParserBuffer>* buffer); | 216 bool GetNextBuffer_Locked(DemuxerStream::Status* status, |
| 217 scoped_refptr<StreamParserBuffer>* buffer); |
| 217 | 218 |
| 218 // Specifies the type of the stream (must be AUDIO or VIDEO for now). | 219 // Specifies the type of the stream (must be AUDIO or VIDEO for now). |
| 219 Type type_; | 220 Type type_; |
| 220 | 221 |
| 221 scoped_ptr<SourceBufferStream> stream_; | 222 scoped_ptr<SourceBufferStream> stream_; |
| 222 | 223 |
| 223 mutable base::Lock lock_; | 224 mutable base::Lock lock_; |
| 224 State state_; | 225 State state_; |
| 225 ReadCBQueue read_cbs_; | 226 ReadCBQueue read_cbs_; |
| 226 bool end_of_stream_; | 227 bool end_of_stream_; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 246 DVLOG(1) << "StartWaitingForSeek()"; | 247 DVLOG(1) << "StartWaitingForSeek()"; |
| 247 ReadCBQueue read_cbs; | 248 ReadCBQueue read_cbs; |
| 248 { | 249 { |
| 249 base::AutoLock auto_lock(lock_); | 250 base::AutoLock auto_lock(lock_); |
| 250 ChangeState_Locked(WAITING_FOR_SEEK); | 251 ChangeState_Locked(WAITING_FOR_SEEK); |
| 251 end_of_stream_ = false; | 252 end_of_stream_ = false; |
| 252 std::swap(read_cbs_, read_cbs); | 253 std::swap(read_cbs_, read_cbs); |
| 253 } | 254 } |
| 254 | 255 |
| 255 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) | 256 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) |
| 256 it->Run(NULL); | 257 it->Run(kAborted, NULL); |
| 257 } | 258 } |
| 258 | 259 |
| 259 void ChunkDemuxerStream::Seek(TimeDelta time) { | 260 void ChunkDemuxerStream::Seek(TimeDelta time) { |
| 260 base::AutoLock auto_lock(lock_); | 261 base::AutoLock auto_lock(lock_); |
| 261 | 262 |
| 262 DCHECK(read_cbs_.empty()); | 263 DCHECK(read_cbs_.empty()); |
| 263 | 264 |
| 264 stream_->Seek(time); | 265 stream_->Seek(time); |
| 265 | 266 |
| 266 if (state_ == WAITING_FOR_SEEK) | 267 if (state_ == WAITING_FOR_SEEK) |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 ReadCBQueue read_cbs; | 379 ReadCBQueue read_cbs; |
| 379 { | 380 { |
| 380 base::AutoLock auto_lock(lock_); | 381 base::AutoLock auto_lock(lock_); |
| 381 ChangeState_Locked(SHUTDOWN); | 382 ChangeState_Locked(SHUTDOWN); |
| 382 std::swap(read_cbs_, read_cbs); | 383 std::swap(read_cbs_, read_cbs); |
| 383 } | 384 } |
| 384 | 385 |
| 385 // Pass end of stream buffers to all callbacks to signal that no more data | 386 // Pass end of stream buffers to all callbacks to signal that no more data |
| 386 // will be sent. | 387 // will be sent. |
| 387 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) | 388 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) |
| 388 it->Run(StreamParserBuffer::CreateEOSBuffer()); | 389 it->Run(DemuxerStream::kOk, StreamParserBuffer::CreateEOSBuffer()); |
| 389 } | 390 } |
| 390 | 391 |
| 391 // Helper function that makes sure |read_cb| runs on |message_loop|. | 392 // Helper function that makes sure |read_cb| runs on |message_loop|. |
| 392 static void RunOnMessageLoop(const DemuxerStream::ReadCB& read_cb, | 393 static void RunOnMessageLoop(const DemuxerStream::ReadCB& read_cb, |
| 393 MessageLoop* message_loop, | 394 MessageLoop* message_loop, |
| 395 DemuxerStream::Status status, |
| 394 const scoped_refptr<DecoderBuffer>& buffer) { | 396 const scoped_refptr<DecoderBuffer>& buffer) { |
| 395 if (MessageLoop::current() != message_loop) { | 397 if (MessageLoop::current() != message_loop) { |
| 396 message_loop->PostTask(FROM_HERE, base::Bind( | 398 message_loop->PostTask(FROM_HERE, base::Bind( |
| 397 &RunOnMessageLoop, read_cb, message_loop, buffer)); | 399 &RunOnMessageLoop, read_cb, message_loop, status, buffer)); |
| 398 return; | 400 return; |
| 399 } | 401 } |
| 400 | 402 |
| 401 read_cb.Run(buffer); | 403 read_cb.Run(status, buffer); |
| 402 } | 404 } |
| 403 | 405 |
| 404 // DemuxerStream methods. | 406 // DemuxerStream methods. |
| 405 void ChunkDemuxerStream::Read(const ReadCB& read_cb) { | 407 void ChunkDemuxerStream::Read(const ReadCB& read_cb) { |
| 408 DemuxerStream::Status status = kOk; |
| 406 scoped_refptr<StreamParserBuffer> buffer; | 409 scoped_refptr<StreamParserBuffer> buffer; |
| 407 { | 410 { |
| 408 base::AutoLock auto_lock(lock_); | 411 base::AutoLock auto_lock(lock_); |
| 409 if (!read_cbs_.empty() || !GetNextBuffer_Locked(&buffer)) { | 412 if (!read_cbs_.empty() || !GetNextBuffer_Locked(&status, &buffer)) { |
| 410 DeferRead_Locked(read_cb); | 413 DeferRead_Locked(read_cb); |
| 411 return; | 414 return; |
| 412 } | 415 } |
| 413 } | 416 } |
| 414 | 417 |
| 415 read_cb.Run(buffer); | 418 read_cb.Run(status, buffer); |
| 416 } | 419 } |
| 417 | 420 |
| 418 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; } | 421 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; } |
| 419 | 422 |
| 420 void ChunkDemuxerStream::EnableBitstreamConverter() {} | 423 void ChunkDemuxerStream::EnableBitstreamConverter() {} |
| 421 | 424 |
| 422 const AudioDecoderConfig& ChunkDemuxerStream::audio_decoder_config() { | 425 const AudioDecoderConfig& ChunkDemuxerStream::audio_decoder_config() { |
| 423 CHECK_EQ(type_, AUDIO); | 426 CHECK_EQ(type_, AUDIO); |
| 424 base::AutoLock auto_lock(lock_); | 427 base::AutoLock auto_lock(lock_); |
| 425 return stream_->GetCurrentAudioDecoderConfig(); | 428 return stream_->GetCurrentAudioDecoderConfig(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 445 read_cbs_.push_back(base::Bind(&RunOnMessageLoop, read_cb, | 448 read_cbs_.push_back(base::Bind(&RunOnMessageLoop, read_cb, |
| 446 MessageLoop::current())); | 449 MessageLoop::current())); |
| 447 } | 450 } |
| 448 | 451 |
| 449 void ChunkDemuxerStream::CreateReadDoneClosures_Locked(ClosureQueue* closures) { | 452 void ChunkDemuxerStream::CreateReadDoneClosures_Locked(ClosureQueue* closures) { |
| 450 lock_.AssertAcquired(); | 453 lock_.AssertAcquired(); |
| 451 | 454 |
| 452 if (state_ != RETURNING_DATA_FOR_READS) | 455 if (state_ != RETURNING_DATA_FOR_READS) |
| 453 return; | 456 return; |
| 454 | 457 |
| 458 DemuxerStream::Status status; |
| 455 scoped_refptr<StreamParserBuffer> buffer; | 459 scoped_refptr<StreamParserBuffer> buffer; |
| 456 while (!read_cbs_.empty()) { | 460 while (!read_cbs_.empty()) { |
| 457 if (!GetNextBuffer_Locked(&buffer)) | 461 if (!GetNextBuffer_Locked(&status, &buffer)) |
| 458 return; | 462 return; |
| 459 closures->push_back(base::Bind(read_cbs_.front(), buffer)); | 463 closures->push_back(base::Bind(read_cbs_.front(), |
| 464 status, buffer)); |
| 460 read_cbs_.pop_front(); | 465 read_cbs_.pop_front(); |
| 461 } | 466 } |
| 462 } | 467 } |
| 463 | 468 |
| 464 bool ChunkDemuxerStream::GetNextBuffer_Locked( | 469 bool ChunkDemuxerStream::GetNextBuffer_Locked( |
| 470 DemuxerStream::Status* status, |
| 465 scoped_refptr<StreamParserBuffer>* buffer) { | 471 scoped_refptr<StreamParserBuffer>* buffer) { |
| 466 lock_.AssertAcquired(); | 472 lock_.AssertAcquired(); |
| 467 | 473 |
| 468 switch (state_) { | 474 switch (state_) { |
| 469 case RETURNING_DATA_FOR_READS: | 475 case RETURNING_DATA_FOR_READS: |
| 470 if (stream_->GetNextBuffer(buffer)) | 476 if (stream_->GetNextBuffer(buffer)) { |
| 477 *status = DemuxerStream::kOk; |
| 471 return true; | 478 return true; |
| 479 } |
| 472 | 480 |
| 473 if (end_of_stream_) { | 481 if (end_of_stream_) { |
| 482 *status = DemuxerStream::kOk; |
| 474 *buffer = StreamParserBuffer::CreateEOSBuffer(); | 483 *buffer = StreamParserBuffer::CreateEOSBuffer(); |
| 475 return true; | 484 return true; |
| 476 } | 485 } |
| 477 return false; | 486 return false; |
| 478 case WAITING_FOR_SEEK: | 487 case WAITING_FOR_SEEK: |
| 479 // Null buffers should be returned in this state since we are waiting | 488 // Null buffers should be returned in this state since we are waiting |
| 480 // for a seek. Any buffers in the SourceBuffer should NOT be returned | 489 // for a seek. Any buffers in the SourceBuffer should NOT be returned |
| 481 // because they are associated with the seek. | 490 // because they are associated with the seek. |
| 482 DCHECK(read_cbs_.empty()); | 491 DCHECK(read_cbs_.empty()); |
| 492 *status = DemuxerStream::kAborted; |
| 483 *buffer = NULL; | 493 *buffer = NULL; |
| 484 return true; | 494 return true; |
| 485 case SHUTDOWN: | 495 case SHUTDOWN: |
| 486 DCHECK(read_cbs_.empty()); | 496 DCHECK(read_cbs_.empty()); |
| 497 *status = DemuxerStream::kOk; |
| 487 *buffer = StreamParserBuffer::CreateEOSBuffer(); | 498 *buffer = StreamParserBuffer::CreateEOSBuffer(); |
| 488 return true; | 499 return true; |
| 489 } | 500 } |
| 490 | 501 |
| 491 NOTREACHED(); | 502 NOTREACHED(); |
| 492 return false; | 503 return false; |
| 493 } | 504 } |
| 494 | 505 |
| 495 ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) | 506 ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) |
| 496 : state_(WAITING_FOR_INIT), | 507 : state_(WAITING_FOR_INIT), |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1038 video_->SetStartTime(start_time_); | 1049 video_->SetStartTime(start_time_); |
| 1039 video_->Seek(start_time_); | 1050 video_->Seek(start_time_); |
| 1040 } | 1051 } |
| 1041 | 1052 |
| 1042 // The demuxer is now initialized after the |start_timestamp_| was set. | 1053 // The demuxer is now initialized after the |start_timestamp_| was set. |
| 1043 ChangeState_Locked(INITIALIZED); | 1054 ChangeState_Locked(INITIALIZED); |
| 1044 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 1055 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
| 1045 } | 1056 } |
| 1046 | 1057 |
| 1047 } // namespace media | 1058 } // namespace media |
| OLD | NEW |