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/ffmpeg_demuxer.h" | 5 #include "media/filters/ffmpeg_demuxer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "media/ffmpeg/ffmpeg_common.h" | 23 #include "media/ffmpeg/ffmpeg_common.h" |
24 #include "media/filters/bitstream_converter.h" | 24 #include "media/filters/bitstream_converter.h" |
25 #include "media/filters/ffmpeg_glue.h" | 25 #include "media/filters/ffmpeg_glue.h" |
26 #include "media/filters/ffmpeg_h264_bitstream_converter.h" | 26 #include "media/filters/ffmpeg_h264_bitstream_converter.h" |
27 | 27 |
28 namespace media { | 28 namespace media { |
29 | 29 |
30 // | 30 // |
31 // FFmpegDemuxerStream | 31 // FFmpegDemuxerStream |
32 // | 32 // |
33 FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, | 33 FFmpegDemuxerStream::FFmpegDemuxerStream( |
34 AVStream* stream) | 34 FFmpegDemuxer* demuxer, |
| 35 AVStream* stream) |
35 : demuxer_(demuxer), | 36 : demuxer_(demuxer), |
36 stream_(stream), | 37 stream_(stream), |
37 type_(UNKNOWN), | 38 type_(UNKNOWN), |
38 discontinuous_(false), | 39 discontinuous_(false), |
39 stopped_(false) { | 40 stopped_(false), |
| 41 last_packet_timestamp_(kNoTimestamp()) { |
40 DCHECK(demuxer_); | 42 DCHECK(demuxer_); |
41 | 43 |
42 // Determine our media format. | 44 // Determine our media format. |
43 switch (stream->codec->codec_type) { | 45 switch (stream->codec->codec_type) { |
44 case AVMEDIA_TYPE_AUDIO: | 46 case AVMEDIA_TYPE_AUDIO: |
45 type_ = AUDIO; | 47 type_ = AUDIO; |
46 AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_); | 48 AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_); |
47 break; | 49 break; |
48 case AVMEDIA_TYPE_VIDEO: | 50 case AVMEDIA_TYPE_VIDEO: |
49 type_ = VIDEO; | 51 type_ = VIDEO; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 } | 89 } |
88 | 90 |
89 // If a packet is returned by FFmpeg's av_parser_parse2() the packet will | 91 // If a packet is returned by FFmpeg's av_parser_parse2() the packet will |
90 // reference inner memory of FFmpeg. As such we should transfer the packet | 92 // reference inner memory of FFmpeg. As such we should transfer the packet |
91 // into memory we control. | 93 // into memory we control. |
92 buffer = DecoderBuffer::CopyFrom(packet->data, packet->size); | 94 buffer = DecoderBuffer::CopyFrom(packet->data, packet->size); |
93 buffer->SetTimestamp(ConvertStreamTimestamp( | 95 buffer->SetTimestamp(ConvertStreamTimestamp( |
94 stream_->time_base, packet->pts)); | 96 stream_->time_base, packet->pts)); |
95 buffer->SetDuration(ConvertStreamTimestamp( | 97 buffer->SetDuration(ConvertStreamTimestamp( |
96 stream_->time_base, packet->duration)); | 98 stream_->time_base, packet->duration)); |
| 99 if (buffer->GetTimestamp() != kNoTimestamp() && |
| 100 last_packet_timestamp_ != kNoTimestamp() && |
| 101 last_packet_timestamp_ < buffer->GetTimestamp()) { |
| 102 buffered_ranges_.Add(last_packet_timestamp_, buffer->GetTimestamp()); |
| 103 demuxer_->message_loop()->PostTask(FROM_HERE, base::Bind( |
| 104 &FFmpegDemuxer::NotifyBufferingChanged, demuxer_)); |
| 105 } |
| 106 last_packet_timestamp_ = buffer->GetTimestamp(); |
97 } | 107 } |
98 | 108 |
99 buffer_queue_.push_back(buffer); | 109 buffer_queue_.push_back(buffer); |
100 FulfillPendingRead(); | 110 FulfillPendingRead(); |
101 return; | 111 return; |
102 } | 112 } |
103 | 113 |
104 void FFmpegDemuxerStream::FlushBuffers() { | 114 void FFmpegDemuxerStream::FlushBuffers() { |
105 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); | 115 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); |
106 base::AutoLock auto_lock(lock_); | 116 base::AutoLock auto_lock(lock_); |
107 DCHECK(read_queue_.empty()) << "Read requests should be empty"; | 117 DCHECK(read_queue_.empty()) << "Read requests should be empty"; |
108 buffer_queue_.clear(); | 118 buffer_queue_.clear(); |
| 119 last_packet_timestamp_ = kNoTimestamp(); |
109 } | 120 } |
110 | 121 |
111 void FFmpegDemuxerStream::Stop() { | 122 void FFmpegDemuxerStream::Stop() { |
112 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); | 123 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); |
113 base::AutoLock auto_lock(lock_); | 124 base::AutoLock auto_lock(lock_); |
114 buffer_queue_.clear(); | 125 buffer_queue_.clear(); |
115 for (ReadQueue::iterator it = read_queue_.begin(); | 126 for (ReadQueue::iterator it = read_queue_.begin(); |
116 it != read_queue_.end(); ++it) { | 127 it != read_queue_.end(); ++it) { |
117 it->Run(scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer())); | 128 it->Run(scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer())); |
118 } | 129 } |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 base::AutoLock auto_lock(lock_); | 239 base::AutoLock auto_lock(lock_); |
229 DCHECK(stopped_); | 240 DCHECK(stopped_); |
230 DCHECK(read_queue_.empty()); | 241 DCHECK(read_queue_.empty()); |
231 DCHECK(buffer_queue_.empty()); | 242 DCHECK(buffer_queue_.empty()); |
232 } | 243 } |
233 | 244 |
234 base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const { | 245 base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const { |
235 return ConvertStreamTimestamp(stream_->time_base, stream_->cur_dts); | 246 return ConvertStreamTimestamp(stream_->time_base, stream_->cur_dts); |
236 } | 247 } |
237 | 248 |
| 249 Ranges<base::TimeDelta> FFmpegDemuxerStream::GetBufferedRanges() { |
| 250 base::AutoLock auto_lock(lock_); |
| 251 return buffered_ranges_; |
| 252 } |
| 253 |
238 // static | 254 // static |
239 base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp( | 255 base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp( |
240 const AVRational& time_base, int64 timestamp) { | 256 const AVRational& time_base, int64 timestamp) { |
241 if (timestamp == static_cast<int64>(AV_NOPTS_VALUE)) | 257 if (timestamp == static_cast<int64>(AV_NOPTS_VALUE)) |
242 return kNoTimestamp(); | 258 return kNoTimestamp(); |
243 | 259 |
244 return ConvertFromTimeBase(time_base, timestamp); | 260 return ConvertFromTimeBase(time_base, timestamp); |
245 } | 261 } |
246 | 262 |
247 // | 263 // |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 int FFmpegDemuxer::WaitForRead() { | 716 int FFmpegDemuxer::WaitForRead() { |
701 read_event_.Wait(); | 717 read_event_.Wait(); |
702 return last_read_bytes_; | 718 return last_read_bytes_; |
703 } | 719 } |
704 | 720 |
705 void FFmpegDemuxer::SignalReadCompleted(int size) { | 721 void FFmpegDemuxer::SignalReadCompleted(int size) { |
706 last_read_bytes_ = size; | 722 last_read_bytes_ = size; |
707 read_event_.Signal(); | 723 read_event_.Signal(); |
708 } | 724 } |
709 | 725 |
| 726 void FFmpegDemuxer::NotifyBufferingChanged() { |
| 727 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 728 Ranges<base::TimeDelta> buffered; |
| 729 scoped_refptr<DemuxerStream> audio = |
| 730 audio_disabled_ ? NULL : GetStream(DemuxerStream::AUDIO); |
| 731 scoped_refptr<DemuxerStream> video = GetStream(DemuxerStream::VIDEO); |
| 732 if (audio && video) { |
| 733 buffered = audio->GetBufferedRanges().IntersectionWith( |
| 734 video->GetBufferedRanges()); |
| 735 } else if (audio) { |
| 736 buffered = audio->GetBufferedRanges(); |
| 737 } else if (video) { |
| 738 buffered = video->GetBufferedRanges(); |
| 739 } |
| 740 for (size_t i = 0; i < buffered.size(); ++i) |
| 741 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); |
| 742 } |
| 743 |
710 } // namespace media | 744 } // namespace media |
OLD | NEW |