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 <algorithm> | 7 #include <algorithm> |
8 #include <deque> | 8 #include <deque> |
9 #include <limits> | 9 #include <limits> |
10 | 10 |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
166 class ChunkDemuxerStream : public DemuxerStream { | 166 class ChunkDemuxerStream : public DemuxerStream { |
167 public: | 167 public: |
168 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; | 168 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; |
169 typedef std::deque<ReadCB> ReadCBQueue; | 169 typedef std::deque<ReadCB> ReadCBQueue; |
170 typedef std::deque<base::Closure> ClosureQueue; | 170 typedef std::deque<base::Closure> ClosureQueue; |
171 | 171 |
172 ChunkDemuxerStream(const AudioDecoderConfig& audio_config, | 172 ChunkDemuxerStream(const AudioDecoderConfig& audio_config, |
173 const LogCB& log_cb); | 173 const LogCB& log_cb); |
174 ChunkDemuxerStream(const VideoDecoderConfig& video_config, | 174 ChunkDemuxerStream(const VideoDecoderConfig& video_config, |
175 const LogCB& log_cb); | 175 const LogCB& log_cb); |
176 virtual ~ChunkDemuxerStream(); | |
176 | 177 |
177 void StartWaitingForSeek(); | 178 void StartWaitingForSeek(); |
178 void Seek(TimeDelta time); | 179 void Seek(TimeDelta time); |
179 void CancelPendingSeek(); | 180 void CancelPendingSeek(); |
180 bool IsSeekPending() const; | 181 bool IsSeekPending() const; |
181 | 182 |
182 // Add buffers to this stream. Buffers are stored in SourceBufferStreams, | 183 // Add buffers to this stream. Buffers are stored in SourceBufferStreams, |
183 // which handle ordering and overlap resolution. | 184 // which handle ordering and overlap resolution. |
184 // Returns true if buffers were successfully added. | 185 // Returns true if buffers were successfully added. |
185 bool Append(const StreamParser::BufferQueue& buffers); | 186 bool Append(const StreamParser::BufferQueue& buffers); |
(...skipping 20 matching lines...) Expand all Loading... | |
206 | 207 |
207 void Shutdown(); | 208 void Shutdown(); |
208 | 209 |
209 // DemuxerStream methods. | 210 // DemuxerStream methods. |
210 virtual void Read(const ReadCB& read_cb) OVERRIDE; | 211 virtual void Read(const ReadCB& read_cb) OVERRIDE; |
211 virtual Type type() OVERRIDE; | 212 virtual Type type() OVERRIDE; |
212 virtual void EnableBitstreamConverter() OVERRIDE; | 213 virtual void EnableBitstreamConverter() OVERRIDE; |
213 virtual const AudioDecoderConfig& audio_decoder_config() OVERRIDE; | 214 virtual const AudioDecoderConfig& audio_decoder_config() OVERRIDE; |
214 virtual const VideoDecoderConfig& video_decoder_config() OVERRIDE; | 215 virtual const VideoDecoderConfig& video_decoder_config() OVERRIDE; |
215 | 216 |
216 protected: | |
217 virtual ~ChunkDemuxerStream(); | |
218 | |
219 private: | 217 private: |
220 enum State { | 218 enum State { |
221 RETURNING_DATA_FOR_READS, | 219 RETURNING_DATA_FOR_READS, |
222 WAITING_FOR_SEEK, | 220 WAITING_FOR_SEEK, |
223 CANCELED, | 221 CANCELED, |
224 SHUTDOWN, | 222 SHUTDOWN, |
225 }; | 223 }; |
226 | 224 |
227 // Assigns |state_| to |state| | 225 // Assigns |state_| to |state| |
228 void ChangeState_Locked(State state); | 226 void ChangeState_Locked(State state); |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
608 | 606 |
609 status = PIPELINE_OK; | 607 status = PIPELINE_OK; |
610 } | 608 } |
611 } | 609 } |
612 | 610 |
613 cb.Run(status); | 611 cb.Run(status); |
614 } | 612 } |
615 | 613 |
616 void ChunkDemuxer::OnAudioRendererDisabled() { | 614 void ChunkDemuxer::OnAudioRendererDisabled() { |
617 base::AutoLock auto_lock(lock_); | 615 base::AutoLock auto_lock(lock_); |
618 audio_ = NULL; | 616 audio_.reset(); // XXX: IS THIS OK? |
scherkus (not reviewing)
2013/04/17 17:21:59
FYI
acolwell GONE FROM CHROMIUM
2013/04/17 20:24:53
I don't think so. Won't the decoder still have a p
| |
619 } | 617 } |
620 | 618 |
621 // Demuxer implementation. | 619 // Demuxer implementation. |
622 scoped_refptr<DemuxerStream> ChunkDemuxer::GetStream( | 620 DemuxerStream* ChunkDemuxer::GetStream(DemuxerStream::Type type) { |
623 DemuxerStream::Type type) { | |
624 base::AutoLock auto_lock(lock_); | 621 base::AutoLock auto_lock(lock_); |
625 if (type == DemuxerStream::VIDEO) | 622 if (type == DemuxerStream::VIDEO) |
626 return video_; | 623 return video_.get(); |
627 | 624 |
628 if (type == DemuxerStream::AUDIO) | 625 if (type == DemuxerStream::AUDIO) |
629 return audio_; | 626 return audio_.get(); |
630 | 627 |
631 return NULL; | 628 return NULL; |
632 } | 629 } |
633 | 630 |
634 TimeDelta ChunkDemuxer::GetStartTime() const { | 631 TimeDelta ChunkDemuxer::GetStartTime() const { |
635 return TimeDelta(); | 632 return TimeDelta(); |
636 } | 633 } |
637 | 634 |
638 void ChunkDemuxer::StartWaitingForSeek() { | 635 void ChunkDemuxer::StartWaitingForSeek() { |
639 DVLOG(1) << "StartWaitingForSeek()"; | 636 DVLOG(1) << "StartWaitingForSeek()"; |
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1135 << (has_video ? " specifies" : " does not specify") | 1132 << (has_video ? " specifies" : " does not specify") |
1136 << " a video codec."; | 1133 << " a video codec."; |
1137 return false; | 1134 return false; |
1138 } | 1135 } |
1139 | 1136 |
1140 bool success = true; | 1137 bool success = true; |
1141 if (audio_config.IsValidConfig()) { | 1138 if (audio_config.IsValidConfig()) { |
1142 if (audio_) { | 1139 if (audio_) { |
1143 success &= audio_->UpdateAudioConfig(audio_config); | 1140 success &= audio_->UpdateAudioConfig(audio_config); |
1144 } else { | 1141 } else { |
1145 audio_ = new ChunkDemuxerStream(audio_config, log_cb_); | 1142 audio_.reset(new ChunkDemuxerStream(audio_config, log_cb_)); |
1146 } | 1143 } |
1147 } | 1144 } |
1148 | 1145 |
1149 if (video_config.IsValidConfig()) { | 1146 if (video_config.IsValidConfig()) { |
1150 if (video_) { | 1147 if (video_) { |
1151 success &= video_->UpdateVideoConfig(video_config); | 1148 success &= video_->UpdateVideoConfig(video_config); |
1152 } else { | 1149 } else { |
1153 video_ = new ChunkDemuxerStream(video_config, log_cb_); | 1150 video_.reset(new ChunkDemuxerStream(video_config, log_cb_)); |
1154 } | 1151 } |
1155 } | 1152 } |
1156 | 1153 |
1157 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); | 1154 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); |
1158 return success; | 1155 return success; |
1159 } | 1156 } |
1160 | 1157 |
1161 bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) { | 1158 bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) { |
1162 lock_.AssertAcquired(); | 1159 lock_.AssertAcquired(); |
1163 DCHECK_NE(state_, SHUTDOWN); | 1160 DCHECK_NE(state_, SHUTDOWN); |
1164 | 1161 |
1165 if (!audio_) | 1162 if (!audio_) |
1166 return false; | 1163 return false; |
1167 | 1164 |
1168 CHECK(IsValidId(source_id_audio_)); | 1165 CHECK(IsValidId(source_id_audio_)); |
1169 if (!audio_->Append(buffers)) | 1166 if (!audio_->Append(buffers)) |
1170 return false; | 1167 return false; |
1171 | 1168 |
1172 IncreaseDurationIfNecessary(buffers, audio_); | 1169 IncreaseDurationIfNecessary(buffers, audio_.get()); |
1173 return true; | 1170 return true; |
1174 } | 1171 } |
1175 | 1172 |
1176 bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) { | 1173 bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) { |
1177 lock_.AssertAcquired(); | 1174 lock_.AssertAcquired(); |
1178 DCHECK_NE(state_, SHUTDOWN); | 1175 DCHECK_NE(state_, SHUTDOWN); |
1179 | 1176 |
1180 if (!video_) | 1177 if (!video_) |
1181 return false; | 1178 return false; |
1182 | 1179 |
1183 CHECK(IsValidId(source_id_video_)); | 1180 CHECK(IsValidId(source_id_video_)); |
1184 if (!video_->Append(buffers)) | 1181 if (!video_->Append(buffers)) |
1185 return false; | 1182 return false; |
1186 | 1183 |
1187 IncreaseDurationIfNecessary(buffers, video_); | 1184 IncreaseDurationIfNecessary(buffers, video_.get()); |
1188 return true; | 1185 return true; |
1189 } | 1186 } |
1190 | 1187 |
1191 // TODO(acolwell): Remove bool from StreamParser::NeedKeyCB so that | 1188 // TODO(acolwell): Remove bool from StreamParser::NeedKeyCB so that |
1192 // this method can be removed and need_key_cb_ can be passed directly | 1189 // this method can be removed and need_key_cb_ can be passed directly |
1193 // to the parser. | 1190 // to the parser. |
1194 bool ChunkDemuxer::OnNeedKey(const std::string& type, | 1191 bool ChunkDemuxer::OnNeedKey(const std::string& type, |
1195 scoped_ptr<uint8[]> init_data, | 1192 scoped_ptr<uint8[]> init_data, |
1196 int init_data_size) { | 1193 int init_data_size) { |
1197 lock_.AssertAcquired(); | 1194 lock_.AssertAcquired(); |
(...skipping 22 matching lines...) Expand all Loading... | |
1220 | 1217 |
1221 void ChunkDemuxer::UpdateDuration(base::TimeDelta new_duration) { | 1218 void ChunkDemuxer::UpdateDuration(base::TimeDelta new_duration) { |
1222 DCHECK(duration_ != new_duration); | 1219 DCHECK(duration_ != new_duration); |
1223 user_specified_duration_ = -1; | 1220 user_specified_duration_ = -1; |
1224 duration_ = new_duration; | 1221 duration_ = new_duration; |
1225 host_->SetDuration(new_duration); | 1222 host_->SetDuration(new_duration); |
1226 } | 1223 } |
1227 | 1224 |
1228 void ChunkDemuxer::IncreaseDurationIfNecessary( | 1225 void ChunkDemuxer::IncreaseDurationIfNecessary( |
1229 const StreamParser::BufferQueue& buffers, | 1226 const StreamParser::BufferQueue& buffers, |
1230 const scoped_refptr<ChunkDemuxerStream>& stream) { | 1227 ChunkDemuxerStream* stream) { |
1231 DCHECK(!buffers.empty()); | 1228 DCHECK(!buffers.empty()); |
1232 if (buffers.back()->GetTimestamp() <= duration_) | 1229 if (buffers.back()->GetTimestamp() <= duration_) |
1233 return; | 1230 return; |
1234 | 1231 |
1235 Ranges<TimeDelta> ranges = stream->GetBufferedRanges(kInfiniteDuration()); | 1232 Ranges<TimeDelta> ranges = stream->GetBufferedRanges(kInfiniteDuration()); |
1236 DCHECK_GT(ranges.size(), 0u); | 1233 DCHECK_GT(ranges.size(), 0u); |
1237 | 1234 |
1238 base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1); | 1235 base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1); |
1239 if (last_timestamp_buffered > duration_) | 1236 if (last_timestamp_buffered > duration_) |
1240 UpdateDuration(last_timestamp_buffered); | 1237 UpdateDuration(last_timestamp_buffered); |
(...skipping 11 matching lines...) Expand all Loading... | |
1252 | 1249 |
1253 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { | 1250 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { |
1254 if (audio_ && !video_) | 1251 if (audio_ && !video_) |
1255 return audio_->GetBufferedRanges(duration_); | 1252 return audio_->GetBufferedRanges(duration_); |
1256 else if (!audio_ && video_) | 1253 else if (!audio_ && video_) |
1257 return video_->GetBufferedRanges(duration_); | 1254 return video_->GetBufferedRanges(duration_); |
1258 return ComputeIntersection(); | 1255 return ComputeIntersection(); |
1259 } | 1256 } |
1260 | 1257 |
1261 } // namespace media | 1258 } // namespace media |
OLD | NEW |