Chromium Code Reviews| 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_->Shutdown(); |
| 617 disabled_audio_ = audio_.Pass(); | |
|
acolwell GONE FROM CHROMIUM
2013/04/24 06:09:57
nit: DCHECK(!disabled_audio_) just so we can catch
scherkus (not reviewing)
2013/04/25 00:12:53
I figured the null pointer dereference on 616 woul
| |
| 619 } | 618 } |
| 620 | 619 |
| 621 // Demuxer implementation. | 620 // Demuxer implementation. |
| 622 scoped_refptr<DemuxerStream> ChunkDemuxer::GetStream( | 621 DemuxerStream* ChunkDemuxer::GetStream(DemuxerStream::Type type) { |
| 623 DemuxerStream::Type type) { | |
| 624 base::AutoLock auto_lock(lock_); | 622 base::AutoLock auto_lock(lock_); |
| 625 if (type == DemuxerStream::VIDEO) | 623 if (type == DemuxerStream::VIDEO) |
| 626 return video_; | 624 return video_.get(); |
| 627 | 625 |
| 628 if (type == DemuxerStream::AUDIO) | 626 if (type == DemuxerStream::AUDIO) |
| 629 return audio_; | 627 return audio_.get() ? audio_.get() : disabled_audio_.get(); |
|
acolwell GONE FROM CHROMIUM
2013/04/24 06:09:57
Is this change actually needed? Doesn't this chang
scherkus (not reviewing)
2013/04/25 00:12:53
Done + updated unit test
| |
| 630 | 628 |
| 631 return NULL; | 629 return NULL; |
| 632 } | 630 } |
| 633 | 631 |
| 634 TimeDelta ChunkDemuxer::GetStartTime() const { | 632 TimeDelta ChunkDemuxer::GetStartTime() const { |
| 635 return TimeDelta(); | 633 return TimeDelta(); |
| 636 } | 634 } |
| 637 | 635 |
| 638 void ChunkDemuxer::StartWaitingForSeek() { | 636 void ChunkDemuxer::StartWaitingForSeek() { |
| 639 DVLOG(1) << "StartWaitingForSeek()"; | 637 DVLOG(1) << "StartWaitingForSeek()"; |
| (...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1135 << (has_video ? " specifies" : " does not specify") | 1133 << (has_video ? " specifies" : " does not specify") |
| 1136 << " a video codec."; | 1134 << " a video codec."; |
| 1137 return false; | 1135 return false; |
| 1138 } | 1136 } |
| 1139 | 1137 |
| 1140 bool success = true; | 1138 bool success = true; |
| 1141 if (audio_config.IsValidConfig()) { | 1139 if (audio_config.IsValidConfig()) { |
| 1142 if (audio_) { | 1140 if (audio_) { |
| 1143 success &= audio_->UpdateAudioConfig(audio_config); | 1141 success &= audio_->UpdateAudioConfig(audio_config); |
| 1144 } else { | 1142 } else { |
| 1145 audio_ = new ChunkDemuxerStream(audio_config, log_cb_); | 1143 audio_.reset(new ChunkDemuxerStream(audio_config, log_cb_)); |
| 1146 } | 1144 } |
| 1147 } | 1145 } |
| 1148 | 1146 |
| 1149 if (video_config.IsValidConfig()) { | 1147 if (video_config.IsValidConfig()) { |
| 1150 if (video_) { | 1148 if (video_) { |
| 1151 success &= video_->UpdateVideoConfig(video_config); | 1149 success &= video_->UpdateVideoConfig(video_config); |
| 1152 } else { | 1150 } else { |
| 1153 video_ = new ChunkDemuxerStream(video_config, log_cb_); | 1151 video_.reset(new ChunkDemuxerStream(video_config, log_cb_)); |
| 1154 } | 1152 } |
| 1155 } | 1153 } |
| 1156 | 1154 |
| 1157 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); | 1155 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); |
| 1158 return success; | 1156 return success; |
| 1159 } | 1157 } |
| 1160 | 1158 |
| 1161 bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) { | 1159 bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) { |
| 1162 lock_.AssertAcquired(); | 1160 lock_.AssertAcquired(); |
| 1163 DCHECK_NE(state_, SHUTDOWN); | 1161 DCHECK_NE(state_, SHUTDOWN); |
| 1164 | 1162 |
| 1165 if (!audio_) | 1163 if (!audio_) |
| 1166 return false; | 1164 return false; |
| 1167 | 1165 |
| 1168 CHECK(IsValidId(source_id_audio_)); | 1166 CHECK(IsValidId(source_id_audio_)); |
| 1169 if (!audio_->Append(buffers)) | 1167 if (!audio_->Append(buffers)) |
| 1170 return false; | 1168 return false; |
| 1171 | 1169 |
| 1172 IncreaseDurationIfNecessary(buffers, audio_); | 1170 IncreaseDurationIfNecessary(buffers, audio_.get()); |
| 1173 return true; | 1171 return true; |
| 1174 } | 1172 } |
| 1175 | 1173 |
| 1176 bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) { | 1174 bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) { |
| 1177 lock_.AssertAcquired(); | 1175 lock_.AssertAcquired(); |
| 1178 DCHECK_NE(state_, SHUTDOWN); | 1176 DCHECK_NE(state_, SHUTDOWN); |
| 1179 | 1177 |
| 1180 if (!video_) | 1178 if (!video_) |
| 1181 return false; | 1179 return false; |
| 1182 | 1180 |
| 1183 CHECK(IsValidId(source_id_video_)); | 1181 CHECK(IsValidId(source_id_video_)); |
| 1184 if (!video_->Append(buffers)) | 1182 if (!video_->Append(buffers)) |
| 1185 return false; | 1183 return false; |
| 1186 | 1184 |
| 1187 IncreaseDurationIfNecessary(buffers, video_); | 1185 IncreaseDurationIfNecessary(buffers, video_.get()); |
| 1188 return true; | 1186 return true; |
| 1189 } | 1187 } |
| 1190 | 1188 |
| 1191 // TODO(acolwell): Remove bool from StreamParser::NeedKeyCB so that | 1189 // TODO(acolwell): Remove bool from StreamParser::NeedKeyCB so that |
| 1192 // this method can be removed and need_key_cb_ can be passed directly | 1190 // this method can be removed and need_key_cb_ can be passed directly |
| 1193 // to the parser. | 1191 // to the parser. |
| 1194 bool ChunkDemuxer::OnNeedKey(const std::string& type, | 1192 bool ChunkDemuxer::OnNeedKey(const std::string& type, |
| 1195 scoped_ptr<uint8[]> init_data, | 1193 scoped_ptr<uint8[]> init_data, |
| 1196 int init_data_size) { | 1194 int init_data_size) { |
| 1197 lock_.AssertAcquired(); | 1195 lock_.AssertAcquired(); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1220 | 1218 |
| 1221 void ChunkDemuxer::UpdateDuration(base::TimeDelta new_duration) { | 1219 void ChunkDemuxer::UpdateDuration(base::TimeDelta new_duration) { |
| 1222 DCHECK(duration_ != new_duration); | 1220 DCHECK(duration_ != new_duration); |
| 1223 user_specified_duration_ = -1; | 1221 user_specified_duration_ = -1; |
| 1224 duration_ = new_duration; | 1222 duration_ = new_duration; |
| 1225 host_->SetDuration(new_duration); | 1223 host_->SetDuration(new_duration); |
| 1226 } | 1224 } |
| 1227 | 1225 |
| 1228 void ChunkDemuxer::IncreaseDurationIfNecessary( | 1226 void ChunkDemuxer::IncreaseDurationIfNecessary( |
| 1229 const StreamParser::BufferQueue& buffers, | 1227 const StreamParser::BufferQueue& buffers, |
| 1230 const scoped_refptr<ChunkDemuxerStream>& stream) { | 1228 ChunkDemuxerStream* stream) { |
| 1231 DCHECK(!buffers.empty()); | 1229 DCHECK(!buffers.empty()); |
| 1232 if (buffers.back()->GetTimestamp() <= duration_) | 1230 if (buffers.back()->GetTimestamp() <= duration_) |
| 1233 return; | 1231 return; |
| 1234 | 1232 |
| 1235 Ranges<TimeDelta> ranges = stream->GetBufferedRanges(kInfiniteDuration()); | 1233 Ranges<TimeDelta> ranges = stream->GetBufferedRanges(kInfiniteDuration()); |
| 1236 DCHECK_GT(ranges.size(), 0u); | 1234 DCHECK_GT(ranges.size(), 0u); |
| 1237 | 1235 |
| 1238 base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1); | 1236 base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1); |
| 1239 if (last_timestamp_buffered > duration_) | 1237 if (last_timestamp_buffered > duration_) |
| 1240 UpdateDuration(last_timestamp_buffered); | 1238 UpdateDuration(last_timestamp_buffered); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1252 | 1250 |
| 1253 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { | 1251 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { |
| 1254 if (audio_ && !video_) | 1252 if (audio_ && !video_) |
| 1255 return audio_->GetBufferedRanges(duration_); | 1253 return audio_->GetBufferedRanges(duration_); |
| 1256 else if (!audio_ && video_) | 1254 else if (!audio_ && video_) |
| 1257 return video_->GetBufferedRanges(duration_); | 1255 return video_->GetBufferedRanges(duration_); |
| 1258 return ComputeIntersection(); | 1256 return ComputeIntersection(); |
| 1259 } | 1257 } |
| 1260 | 1258 |
| 1261 } // namespace media | 1259 } // namespace media |
| OLD | NEW |