Chromium Code Reviews| 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/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/callback.h" | 6 #include "base/callback.h" |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 45 return static_cast<size_t>(packet_->size); | 45 return static_cast<size_t>(packet_->size); |
| 46 } | 46 } |
| 47 | 47 |
| 48 private: | 48 private: |
| 49 scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet_; | 49 scoped_ptr_malloc<AVPacket, ScopedPtrAVFreePacket> packet_; |
| 50 | 50 |
| 51 DISALLOW_COPY_AND_ASSIGN(AVPacketBuffer); | 51 DISALLOW_COPY_AND_ASSIGN(AVPacketBuffer); |
| 52 }; | 52 }; |
| 53 | 53 |
| 54 | 54 |
| 55 // Helper class that is always at end of stream. Used to signal the demuxer | |
| 56 // that a stream has seen Stop(). | |
| 57 class EndOfStreamBuffer : public Buffer { | |
|
acolwell GONE FROM CHROMIUM
2011/10/07 15:50:47
It feels like this should go in media/base somewhe
Ami GONE FROM CHROMIUM
2011/10/07 16:44:47
As soon as there's another customer, I'm happy for
acolwell GONE FROM CHROMIUM
2011/10/07 16:56:59
ChunkDemuxer could be that customer. It currently
Ami GONE FROM CHROMIUM
2011/10/07 17:11:10
Doing the latter (mimicking).
| |
| 58 public: | |
| 59 virtual const uint8* GetData() const { return NULL; } | |
| 60 virtual size_t GetDataSize() const { return 0; } | |
| 61 }; | |
| 62 | |
| 63 | |
| 55 // | 64 // |
| 56 // FFmpegDemuxerStream | 65 // FFmpegDemuxerStream |
| 57 // | 66 // |
| 58 FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, | 67 FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, |
| 59 AVStream* stream) | 68 AVStream* stream) |
| 60 : demuxer_(demuxer), | 69 : demuxer_(demuxer), |
| 61 stream_(stream), | 70 stream_(stream), |
| 62 type_(UNKNOWN), | 71 type_(UNKNOWN), |
| 63 discontinuous_(false), | 72 discontinuous_(false), |
| 64 stopped_(false) { | 73 stopped_(false) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 132 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); | 141 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); |
| 133 base::AutoLock auto_lock(lock_); | 142 base::AutoLock auto_lock(lock_); |
| 134 DCHECK(read_queue_.empty()) << "Read requests should be empty"; | 143 DCHECK(read_queue_.empty()) << "Read requests should be empty"; |
| 135 buffer_queue_.clear(); | 144 buffer_queue_.clear(); |
| 136 } | 145 } |
| 137 | 146 |
| 138 void FFmpegDemuxerStream::Stop() { | 147 void FFmpegDemuxerStream::Stop() { |
| 139 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); | 148 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); |
| 140 base::AutoLock auto_lock(lock_); | 149 base::AutoLock auto_lock(lock_); |
| 141 buffer_queue_.clear(); | 150 buffer_queue_.clear(); |
| 151 for (ReadQueue::iterator it = read_queue_.begin(); | |
| 152 it != read_queue_.end(); ++it) { | |
| 153 it->Run(new EndOfStreamBuffer()); | |
| 154 } | |
| 142 read_queue_.clear(); | 155 read_queue_.clear(); |
| 143 stopped_ = true; | 156 stopped_ = true; |
| 144 } | 157 } |
| 145 | 158 |
| 146 base::TimeDelta FFmpegDemuxerStream::duration() { | 159 base::TimeDelta FFmpegDemuxerStream::duration() { |
| 147 return duration_; | 160 return duration_; |
| 148 } | 161 } |
| 149 | 162 |
| 150 DemuxerStream::Type FFmpegDemuxerStream::type() { | 163 DemuxerStream::Type FFmpegDemuxerStream::type() { |
| 151 return type_; | 164 return type_; |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 // TODO(hclam): close the codecs in the corresponding decoders. | 295 // TODO(hclam): close the codecs in the corresponding decoders. |
| 283 if (!format_context_) | 296 if (!format_context_) |
| 284 return; | 297 return; |
| 285 | 298 |
| 286 DestroyAVFormatContext(format_context_); | 299 DestroyAVFormatContext(format_context_); |
| 287 format_context_ = NULL; | 300 format_context_ = NULL; |
| 288 } | 301 } |
| 289 | 302 |
| 290 void FFmpegDemuxer::PostDemuxTask() { | 303 void FFmpegDemuxer::PostDemuxTask() { |
| 291 message_loop_->PostTask(FROM_HERE, | 304 message_loop_->PostTask(FROM_HERE, |
| 292 base::Bind(&FFmpegDemuxer::DemuxTask, this)); | 305 base::Bind(&FFmpegDemuxer::DemuxTask, this)); |
| 293 } | 306 } |
| 294 | 307 |
| 295 void FFmpegDemuxer::Stop(const base::Closure& callback) { | 308 void FFmpegDemuxer::Stop(const base::Closure& callback) { |
| 296 // Post a task to notify the streams to stop as well. | 309 // Post a task to notify the streams to stop as well. |
| 297 message_loop_->PostTask(FROM_HERE, | 310 message_loop_->PostTask(FROM_HERE, |
| 298 base::Bind(&FFmpegDemuxer::StopTask, this, callback)); | 311 base::Bind(&FFmpegDemuxer::StopTask, this, callback)); |
| 299 | 312 |
| 300 // Then wakes up the thread from reading. | 313 // Then wakes up the thread from reading. |
| 301 SignalReadCompleted(DataSource::kReadError); | 314 SignalReadCompleted(DataSource::kReadError); |
| 302 } | 315 } |
| 303 | 316 |
| 304 void FFmpegDemuxer::Seek(base::TimeDelta time, const FilterStatusCB& cb) { | 317 void FFmpegDemuxer::Seek(base::TimeDelta time, const FilterStatusCB& cb) { |
| 305 message_loop_->PostTask(FROM_HERE, | 318 message_loop_->PostTask(FROM_HERE, |
| 306 base::Bind(&FFmpegDemuxer::SeekTask, this, time, cb)); | 319 base::Bind(&FFmpegDemuxer::SeekTask, this, time, cb)); |
| 307 } | 320 } |
| 308 | 321 |
| 309 void FFmpegDemuxer::SetPlaybackRate(float playback_rate) { | 322 void FFmpegDemuxer::SetPlaybackRate(float playback_rate) { |
| 310 DCHECK(data_source_.get()); | 323 DCHECK(data_source_.get()); |
| 311 data_source_->SetPlaybackRate(playback_rate); | 324 data_source_->SetPlaybackRate(playback_rate); |
| 312 } | 325 } |
| 313 | 326 |
| 314 void FFmpegDemuxer::SetPreload(Preload preload) { | 327 void FFmpegDemuxer::SetPreload(Preload preload) { |
| 315 DCHECK(data_source_.get()); | 328 DCHECK(data_source_.get()); |
| 316 data_source_->SetPreload(preload); | 329 data_source_->SetPreload(preload); |
| 317 } | 330 } |
| 318 | 331 |
| 319 void FFmpegDemuxer::OnAudioRendererDisabled() { | 332 void FFmpegDemuxer::OnAudioRendererDisabled() { |
| 320 message_loop_->PostTask(FROM_HERE, | 333 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 321 base::Bind(&FFmpegDemuxer::DisableAudioStreamTask, this)); | 334 &FFmpegDemuxer::DisableAudioStreamTask, this)); |
| 322 } | 335 } |
| 323 | 336 |
| 324 void FFmpegDemuxer::set_host(FilterHost* filter_host) { | 337 void FFmpegDemuxer::set_host(FilterHost* filter_host) { |
| 325 Demuxer::set_host(filter_host); | 338 Demuxer::set_host(filter_host); |
| 326 if (data_source_) | 339 if (data_source_) |
| 327 data_source_->set_host(filter_host); | 340 data_source_->set_host(filter_host); |
| 328 if (max_duration_.InMicroseconds() >= 0) | 341 if (max_duration_.InMicroseconds() >= 0) |
| 329 host()->SetDuration(max_duration_); | 342 host()->SetDuration(max_duration_); |
| 330 if (read_position_ > 0) | 343 if (read_position_ > 0) |
| 331 host()->SetCurrentReadPosition(read_position_); | 344 host()->SetCurrentReadPosition(read_position_); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 466 base::TimeDelta max_duration; | 479 base::TimeDelta max_duration; |
| 467 const bool kDemuxerIsWebm = !strcmp("webm", format_context_->iformat->name); | 480 const bool kDemuxerIsWebm = !strcmp("webm", format_context_->iformat->name); |
| 468 bool no_supported_streams = true; | 481 bool no_supported_streams = true; |
| 469 for (size_t i = 0; i < format_context_->nb_streams; ++i) { | 482 for (size_t i = 0; i < format_context_->nb_streams; ++i) { |
| 470 AVCodecContext* codec_context = format_context_->streams[i]->codec; | 483 AVCodecContext* codec_context = format_context_->streams[i]->codec; |
| 471 AVMediaType codec_type = codec_context->codec_type; | 484 AVMediaType codec_type = codec_context->codec_type; |
| 472 if (codec_type == AVMEDIA_TYPE_AUDIO || codec_type == AVMEDIA_TYPE_VIDEO) { | 485 if (codec_type == AVMEDIA_TYPE_AUDIO || codec_type == AVMEDIA_TYPE_VIDEO) { |
| 473 AVStream* stream = format_context_->streams[i]; | 486 AVStream* stream = format_context_->streams[i]; |
| 474 // WebM is currently strictly VP8 and Vorbis. | 487 // WebM is currently strictly VP8 and Vorbis. |
| 475 if (kDemuxerIsWebm && (stream->codec->codec_id != CODEC_ID_VP8 && | 488 if (kDemuxerIsWebm && (stream->codec->codec_id != CODEC_ID_VP8 && |
| 476 stream->codec->codec_id != CODEC_ID_VORBIS)) { | 489 stream->codec->codec_id != CODEC_ID_VORBIS)) { |
| 477 packet_streams_.push_back(NULL); | 490 packet_streams_.push_back(NULL); |
| 478 continue; | 491 continue; |
| 479 } | 492 } |
| 480 | 493 |
| 481 scoped_refptr<FFmpegDemuxerStream> demuxer_stream( | 494 scoped_refptr<FFmpegDemuxerStream> demuxer_stream( |
| 482 new FFmpegDemuxerStream(this, stream)); | 495 new FFmpegDemuxerStream(this, stream)); |
| 483 if (!streams_[demuxer_stream->type()]) { | 496 if (!streams_[demuxer_stream->type()]) { |
| 484 no_supported_streams = false; | 497 no_supported_streams = false; |
| 485 streams_[demuxer_stream->type()] = demuxer_stream; | 498 streams_[demuxer_stream->type()] = demuxer_stream; |
| 486 max_duration = std::max(max_duration, demuxer_stream->duration()); | 499 max_duration = std::max(max_duration, demuxer_stream->duration()); |
| 487 | 500 |
| 488 if (stream->first_dts != static_cast<int64_t>(AV_NOPTS_VALUE)) { | 501 if (stream->first_dts != static_cast<int64_t>(AV_NOPTS_VALUE)) { |
| 489 const base::TimeDelta first_dts = ConvertFromTimeBase( | 502 const base::TimeDelta first_dts = ConvertFromTimeBase( |
| 490 stream->time_base, stream->first_dts); | 503 stream->time_base, stream->first_dts); |
| 491 if (start_time_ == kNoTimestamp || first_dts < start_time_) | 504 if (start_time_ == kNoTimestamp || first_dts < start_time_) |
| 492 start_time_ = first_dts; | 505 start_time_ = first_dts; |
| 493 } | 506 } |
| 494 } | 507 } |
| 495 packet_streams_.push_back(demuxer_stream); | 508 packet_streams_.push_back(demuxer_stream); |
| 496 } else { | 509 } else { |
| 497 packet_streams_.push_back(NULL); | 510 packet_streams_.push_back(NULL); |
| 498 } | 511 } |
| 499 } | 512 } |
| 500 if (no_supported_streams) { | 513 if (no_supported_streams) { |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 715 read_event_.Wait(); | 728 read_event_.Wait(); |
| 716 return last_read_bytes_; | 729 return last_read_bytes_; |
| 717 } | 730 } |
| 718 | 731 |
| 719 void FFmpegDemuxer::SignalReadCompleted(size_t size) { | 732 void FFmpegDemuxer::SignalReadCompleted(size_t size) { |
| 720 last_read_bytes_ = size; | 733 last_read_bytes_ = size; |
| 721 read_event_.Signal(); | 734 read_event_.Signal(); |
| 722 } | 735 } |
| 723 | 736 |
| 724 } // namespace media | 737 } // namespace media |
| OLD | NEW |