| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/callback.h" | 5 #include "base/callback.h" |
| 6 #include "base/command_line.h" | 6 #include "base/command_line.h" |
| 7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/stl_util-inl.h" | 9 #include "base/stl_util-inl.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 | 306 |
| 307 void FFmpegDemuxer::Stop(FilterCallback* callback) { | 307 void FFmpegDemuxer::Stop(FilterCallback* callback) { |
| 308 // Post a task to notify the streams to stop as well. | 308 // Post a task to notify the streams to stop as well. |
| 309 message_loop_->PostTask(FROM_HERE, | 309 message_loop_->PostTask(FROM_HERE, |
| 310 NewRunnableMethod(this, &FFmpegDemuxer::StopTask, callback)); | 310 NewRunnableMethod(this, &FFmpegDemuxer::StopTask, callback)); |
| 311 | 311 |
| 312 // Then wakes up the thread from reading. | 312 // Then wakes up the thread from reading. |
| 313 SignalReadCompleted(DataSource::kReadError); | 313 SignalReadCompleted(DataSource::kReadError); |
| 314 } | 314 } |
| 315 | 315 |
| 316 void FFmpegDemuxer::Seek(base::TimeDelta time, FilterCallback* callback) { | 316 void FFmpegDemuxer::Seek(base::TimeDelta time, const FilterStatusCB& cb) { |
| 317 // TODO(hclam): by returning from this method, it is assumed that the seek | 317 // TODO(hclam): by returning from this method, it is assumed that the seek |
| 318 // operation is completed and filters behind the demuxer is good to issue | 318 // operation is completed and filters behind the demuxer is good to issue |
| 319 // more reads, but we are posting a task here, which makes the seek operation | 319 // more reads, but we are posting a task here, which makes the seek operation |
| 320 // asynchronous, should change how seek works to make it fully asynchronous. | 320 // asynchronous, should change how seek works to make it fully asynchronous. |
| 321 message_loop_->PostTask(FROM_HERE, | 321 message_loop_->PostTask(FROM_HERE, |
| 322 NewRunnableMethod(this, &FFmpegDemuxer::SeekTask, time, callback)); | 322 NewRunnableMethod(this, &FFmpegDemuxer::SeekTask, time, cb)); |
| 323 } | 323 } |
| 324 | 324 |
| 325 void FFmpegDemuxer::SetPlaybackRate(float playback_rate) { | 325 void FFmpegDemuxer::SetPlaybackRate(float playback_rate) { |
| 326 DCHECK(data_source_.get()); | 326 DCHECK(data_source_.get()); |
| 327 data_source_->SetPlaybackRate(playback_rate); | 327 data_source_->SetPlaybackRate(playback_rate); |
| 328 } | 328 } |
| 329 | 329 |
| 330 void FFmpegDemuxer::SetPreload(Preload preload) { | 330 void FFmpegDemuxer::SetPreload(Preload preload) { |
| 331 DCHECK(data_source_.get()); | 331 DCHECK(data_source_.get()); |
| 332 data_source_->SetPreload(preload); | 332 data_source_->SetPreload(preload); |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 Limits::kMaxTimeInMicroseconds); | 521 Limits::kMaxTimeInMicroseconds); |
| 522 } | 522 } |
| 523 | 523 |
| 524 // Good to go: set the duration and notify we're done initializing. | 524 // Good to go: set the duration and notify we're done initializing. |
| 525 if (host()) | 525 if (host()) |
| 526 host()->SetDuration(max_duration); | 526 host()->SetDuration(max_duration); |
| 527 max_duration_ = max_duration; | 527 max_duration_ = max_duration; |
| 528 callback->Run(PIPELINE_OK); | 528 callback->Run(PIPELINE_OK); |
| 529 } | 529 } |
| 530 | 530 |
| 531 void FFmpegDemuxer::SeekTask(base::TimeDelta time, FilterCallback* callback) { | 531 void FFmpegDemuxer::SeekTask(base::TimeDelta time, const FilterStatusCB& cb) { |
| 532 DCHECK_EQ(MessageLoop::current(), message_loop_); | 532 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 533 scoped_ptr<FilterCallback> c(callback); | |
| 534 | 533 |
| 535 // Tell streams to flush buffers due to seeking. | 534 // Tell streams to flush buffers due to seeking. |
| 536 StreamVector::iterator iter; | 535 StreamVector::iterator iter; |
| 537 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 536 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
| 538 if (*iter) | 537 if (*iter) |
| 539 (*iter)->FlushBuffers(); | 538 (*iter)->FlushBuffers(); |
| 540 } | 539 } |
| 541 | 540 |
| 542 // Always seek to a timestamp less than or equal to the desired timestamp. | 541 // Always seek to a timestamp less than or equal to the desired timestamp. |
| 543 int flags = AVSEEK_FLAG_BACKWARD; | 542 int flags = AVSEEK_FLAG_BACKWARD; |
| 544 | 543 |
| 545 // Passing -1 as our stream index lets FFmpeg pick a default stream. FFmpeg | 544 // Passing -1 as our stream index lets FFmpeg pick a default stream. FFmpeg |
| 546 // will attempt to use the lowest-index video stream, if present, followed by | 545 // will attempt to use the lowest-index video stream, if present, followed by |
| 547 // the lowest-index audio stream. | 546 // the lowest-index audio stream. |
| 548 if (av_seek_frame(format_context_, -1, time.InMicroseconds(), flags) < 0) { | 547 if (av_seek_frame(format_context_, -1, time.InMicroseconds(), flags) < 0) { |
| 549 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being | 548 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being |
| 550 // captured from stdout and contaminates testing. | 549 // captured from stdout and contaminates testing. |
| 551 // TODO(scherkus): Implement this properly and signal error (BUG=23447). | 550 // TODO(scherkus): Implement this properly and signal error (BUG=23447). |
| 552 VLOG(1) << "Not implemented"; | 551 VLOG(1) << "Not implemented"; |
| 553 } | 552 } |
| 554 | 553 |
| 555 // Notify we're finished seeking. | 554 // Notify we're finished seeking. |
| 556 callback->Run(); | 555 cb.Run(PIPELINE_OK); |
| 557 } | 556 } |
| 558 | 557 |
| 559 void FFmpegDemuxer::DemuxTask() { | 558 void FFmpegDemuxer::DemuxTask() { |
| 560 DCHECK_EQ(MessageLoop::current(), message_loop_); | 559 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 561 | 560 |
| 562 // Make sure we have work to do before demuxing. | 561 // Make sure we have work to do before demuxing. |
| 563 if (!StreamsHavePendingReads()) { | 562 if (!StreamsHavePendingReads()) { |
| 564 return; | 563 return; |
| 565 } | 564 } |
| 566 | 565 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 read_event_.Wait(); | 671 read_event_.Wait(); |
| 673 return last_read_bytes_; | 672 return last_read_bytes_; |
| 674 } | 673 } |
| 675 | 674 |
| 676 void FFmpegDemuxer::SignalReadCompleted(size_t size) { | 675 void FFmpegDemuxer::SignalReadCompleted(size_t size) { |
| 677 last_read_bytes_ = size; | 676 last_read_bytes_ = size; |
| 678 read_event_.Signal(); | 677 read_event_.Signal(); |
| 679 } | 678 } |
| 680 | 679 |
| 681 } // namespace media | 680 } // namespace media |
| OLD | NEW |