Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: media/filters/chunk_demuxer.cc

Issue 10829108: Cap sourceBuffered() on duration and truncate duration on EoS (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase ToT Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | media/filters/chunk_demuxer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback_helpers.h" 8 #include "base/callback_helpers.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 169
170 void StartWaitingForSeek(); 170 void StartWaitingForSeek();
171 void Seek(TimeDelta time); 171 void Seek(TimeDelta time);
172 bool IsSeekPending() const; 172 bool IsSeekPending() const;
173 173
174 // Add buffers to this stream. Buffers are stored in SourceBufferStreams, 174 // Add buffers to this stream. Buffers are stored in SourceBufferStreams,
175 // which handle ordering and overlap resolution. 175 // which handle ordering and overlap resolution.
176 // Returns true if buffers were successfully added. 176 // Returns true if buffers were successfully added.
177 bool Append(const StreamParser::BufferQueue& buffers); 177 bool Append(const StreamParser::BufferQueue& buffers);
178 178
179 // Returns the range of buffered data in this stream, capped at |duration|.
180 Ranges<TimeDelta> GetBufferedRanges(base::TimeDelta duration) const;
181
179 // Signal to the stream that buffers handed in through subsequent calls to 182 // Signal to the stream that buffers handed in through subsequent calls to
180 // Append() belong to a media segment that starts at |start_timestamp|. 183 // Append() belong to a media segment that starts at |start_timestamp|.
181 void OnNewMediaSegment(TimeDelta start_timestamp); 184 void OnNewMediaSegment(TimeDelta start_timestamp);
182 185
183 // Notifies the stream that it begins at |start_time|. 186 // Notifies the stream that it begins at |start_time|.
184 void SetStartTime(TimeDelta start_time); 187 void SetStartTime(TimeDelta start_time);
185 188
186 // Called when mid-stream config updates occur. 189 // Called when mid-stream config updates occur.
187 // Returns true if the new config is accepted. 190 // Returns true if the new config is accepted.
188 // Returns false if the new config should trigger an error. 191 // Returns false if the new config should trigger an error.
189 bool UpdateAudioConfig(const AudioDecoderConfig& config); 192 bool UpdateAudioConfig(const AudioDecoderConfig& config);
190 bool UpdateVideoConfig(const VideoDecoderConfig& config); 193 bool UpdateVideoConfig(const VideoDecoderConfig& config);
191 194
192 void EndOfStream(); 195 void EndOfStream();
193 bool CanEndOfStream() const; 196 bool CanEndOfStream() const;
194 void Shutdown(); 197 void Shutdown();
195 198
196 // DemuxerStream methods. 199 // DemuxerStream methods.
197 virtual void Read(const ReadCB& read_cb) OVERRIDE; 200 virtual void Read(const ReadCB& read_cb) OVERRIDE;
198 virtual Type type() OVERRIDE; 201 virtual Type type() OVERRIDE;
199 virtual void EnableBitstreamConverter() OVERRIDE; 202 virtual void EnableBitstreamConverter() OVERRIDE;
200 virtual const AudioDecoderConfig& audio_decoder_config() OVERRIDE; 203 virtual const AudioDecoderConfig& audio_decoder_config() OVERRIDE;
201 virtual const VideoDecoderConfig& video_decoder_config() OVERRIDE; 204 virtual const VideoDecoderConfig& video_decoder_config() OVERRIDE;
202 virtual Ranges<TimeDelta> GetBufferedRanges() OVERRIDE;
203 205
204 protected: 206 protected:
205 virtual ~ChunkDemuxerStream(); 207 virtual ~ChunkDemuxerStream();
206 208
207 private: 209 private:
208 enum State { 210 enum State {
209 RETURNING_DATA_FOR_READS, 211 RETURNING_DATA_FOR_READS,
210 WAITING_FOR_SEEK, 212 WAITING_FOR_SEEK,
211 SHUTDOWN, 213 SHUTDOWN,
212 }; 214 };
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 } 313 }
312 CreateReadDoneClosures_Locked(&closures); 314 CreateReadDoneClosures_Locked(&closures);
313 } 315 }
314 316
315 for (ClosureQueue::iterator it = closures.begin(); it != closures.end(); ++it) 317 for (ClosureQueue::iterator it = closures.begin(); it != closures.end(); ++it)
316 it->Run(); 318 it->Run();
317 319
318 return true; 320 return true;
319 } 321 }
320 322
321 Ranges<TimeDelta> ChunkDemuxerStream::GetBufferedRanges() { 323 Ranges<TimeDelta> ChunkDemuxerStream::GetBufferedRanges(
324 base::TimeDelta duration) const {
322 base::AutoLock auto_lock(lock_); 325 base::AutoLock auto_lock(lock_);
323 return stream_->GetBufferedTime(); 326 Ranges<TimeDelta> range = stream_->GetBufferedTime();
327
328 if (range.size() == 0u)
329 return range;
330
331 // Clamp the end of the stream's buffered ranges to fit within the duration.
332 // This can be done by intersecting the stream's range with the valid time
333 // range.
334 Ranges<TimeDelta> valid_time_range;
335 valid_time_range.Add(range.start(0), duration);
336 return range.IntersectionWith(valid_time_range);
324 } 337 }
325 338
326 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config) { 339 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config) {
327 DCHECK(config.IsValidConfig()); 340 DCHECK(config.IsValidConfig());
328 DCHECK_EQ(type_, AUDIO); 341 DCHECK_EQ(type_, AUDIO);
329 return stream_->UpdateAudioConfig(config); 342 return stream_->UpdateAudioConfig(config);
330 } 343 }
331 344
332 bool ChunkDemuxerStream::UpdateVideoConfig(const VideoDecoderConfig& config) { 345 bool ChunkDemuxerStream::UpdateVideoConfig(const VideoDecoderConfig& config) {
333 DCHECK(config.IsValidConfig()); 346 DCHECK(config.IsValidConfig());
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 677
665 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const { 678 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const {
666 DCHECK(!id.empty()); 679 DCHECK(!id.empty());
667 DCHECK(IsValidId(id)); 680 DCHECK(IsValidId(id));
668 DCHECK(id == source_id_audio_ || id == source_id_video_); 681 DCHECK(id == source_id_audio_ || id == source_id_video_);
669 682
670 base::AutoLock auto_lock(lock_); 683 base::AutoLock auto_lock(lock_);
671 684
672 if (id == source_id_audio_ && id != source_id_video_) { 685 if (id == source_id_audio_ && id != source_id_video_) {
673 // Only include ranges that have been buffered in |audio_| 686 // Only include ranges that have been buffered in |audio_|
674 return audio_ ? audio_->GetBufferedRanges() : Ranges<TimeDelta>(); 687 return audio_ ? audio_->GetBufferedRanges(duration_) : Ranges<TimeDelta>();
675 } 688 }
676 689
677 if (id != source_id_audio_ && id == source_id_video_) { 690 if (id != source_id_audio_ && id == source_id_video_) {
678 // Only include ranges that have been buffered in |video_| 691 // Only include ranges that have been buffered in |video_|
679 return video_ ? video_->GetBufferedRanges() : Ranges<TimeDelta>(); 692 return video_ ? video_->GetBufferedRanges(duration_) : Ranges<TimeDelta>();
680 } 693 }
681 694
682 return ComputeIntersection(); 695 return ComputeIntersection();
683 } 696 }
684 697
685 Ranges<TimeDelta> ChunkDemuxer::ComputeIntersection() const { 698 Ranges<TimeDelta> ChunkDemuxer::ComputeIntersection() const {
686 lock_.AssertAcquired(); 699 lock_.AssertAcquired();
687 700
688 if (!audio_ || !video_) 701 if (!audio_ || !video_)
689 return Ranges<TimeDelta>(); 702 return Ranges<TimeDelta>();
690 703
691 // Include ranges that have been buffered in both |audio_| and |video_|. 704 // Include ranges that have been buffered in both |audio_| and |video_|.
692 Ranges<TimeDelta> audio_ranges = audio_->GetBufferedRanges(); 705 Ranges<TimeDelta> audio_ranges = audio_->GetBufferedRanges(duration_);
693 Ranges<TimeDelta> video_ranges = video_->GetBufferedRanges(); 706 Ranges<TimeDelta> video_ranges = video_->GetBufferedRanges(duration_);
694 Ranges<TimeDelta> result = audio_ranges.IntersectionWith(video_ranges); 707 Ranges<TimeDelta> result = audio_ranges.IntersectionWith(video_ranges);
695 708
696 if (state_ == ENDED && result.size() > 0) { 709 if (state_ == ENDED && result.size() > 0) {
697 // If appending has ended, extend the last intersection range to include the 710 // If appending has ended, extend the last intersection range to include the
698 // max end time of the last audio/video range. This allows the buffered 711 // max end time of the last audio/video range. This allows the buffered
699 // information to match the actual time range that will get played out if 712 // information to match the actual time range that will get played out if
700 // the streams have slightly different lengths. 713 // the streams have slightly different lengths.
701 TimeDelta audio_start = audio_ranges.start(audio_ranges.size() - 1); 714 TimeDelta audio_start = audio_ranges.start(audio_ranges.size() - 1);
702 TimeDelta audio_end = audio_ranges.end(audio_ranges.size() - 1); 715 TimeDelta audio_end = audio_ranges.end(audio_ranges.size() - 1);
703 TimeDelta video_start = video_ranges.start(video_ranges.size() - 1); 716 TimeDelta video_start = video_ranges.start(video_ranges.size() - 1);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 DVLOG(1) << "AppendData(): called in unexpected state " << state_; 769 DVLOG(1) << "AppendData(): called in unexpected state " << state_;
757 return false; 770 return false;
758 } 771 }
759 772
760 // Check to see if data was appended at the pending seek point. This 773 // Check to see if data was appended at the pending seek point. This
761 // indicates we have parsed enough data to complete the seek. 774 // indicates we have parsed enough data to complete the seek.
762 if (old_seek_pending && !IsSeekPending_Locked() && !seek_cb_.is_null()) { 775 if (old_seek_pending && !IsSeekPending_Locked() && !seek_cb_.is_null()) {
763 std::swap(cb, seek_cb_); 776 std::swap(cb, seek_cb_);
764 } 777 }
765 778
766 if (audio_ && !video_) { 779 ranges = GetBufferedRanges();
767 ranges = audio_->GetBufferedRanges();
768 } else if (!audio_ && video_) {
769 ranges = video_->GetBufferedRanges();
770 } else {
771 ranges = ComputeIntersection();
772 }
773 } 780 }
774 781
775 for (size_t i = 0; i < ranges.size(); ++i) 782 for (size_t i = 0; i < ranges.size(); ++i)
776 host_->AddBufferedTimeRange(ranges.start(i), ranges.end(i)); 783 host_->AddBufferedTimeRange(ranges.start(i), ranges.end(i));
777 784
778 if (!cb.is_null()) 785 if (!cb.is_null())
779 cb.Run(PIPELINE_OK); 786 cb.Run(PIPELINE_OK);
780 787
781 return true; 788 return true;
782 } 789 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
818 825
819 if (!CanEndOfStream_Locked() && status == PIPELINE_OK) 826 if (!CanEndOfStream_Locked() && status == PIPELINE_OK)
820 return false; 827 return false;
821 828
822 if (audio_) 829 if (audio_)
823 audio_->EndOfStream(); 830 audio_->EndOfStream();
824 831
825 if (video_) 832 if (video_)
826 video_->EndOfStream(); 833 video_->EndOfStream();
827 834
828 if (status != PIPELINE_OK) 835 if (status != PIPELINE_OK) {
829 ReportError_Locked(status); 836 ReportError_Locked(status);
830 else 837 } else {
831 ChangeState_Locked(ENDED); 838 ChangeState_Locked(ENDED);
839 DecreaseDurationIfNecessary();
840 }
832 841
833 return true; 842 return true;
834 } 843 }
835 844
836 void ChunkDemuxer::Shutdown() { 845 void ChunkDemuxer::Shutdown() {
837 DVLOG(1) << "Shutdown()"; 846 DVLOG(1) << "Shutdown()";
838 PipelineStatusCB cb; 847 PipelineStatusCB cb;
839 { 848 {
840 base::AutoLock auto_lock(lock_); 849 base::AutoLock auto_lock(lock_);
841 850
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
1114 host_->SetDuration(new_duration); 1123 host_->SetDuration(new_duration);
1115 } 1124 }
1116 1125
1117 void ChunkDemuxer::IncreaseDurationIfNecessary( 1126 void ChunkDemuxer::IncreaseDurationIfNecessary(
1118 const StreamParser::BufferQueue& buffers, 1127 const StreamParser::BufferQueue& buffers,
1119 const scoped_refptr<ChunkDemuxerStream>& stream) { 1128 const scoped_refptr<ChunkDemuxerStream>& stream) {
1120 DCHECK(!buffers.empty()); 1129 DCHECK(!buffers.empty());
1121 if (buffers.back()->GetTimestamp() <= duration_) 1130 if (buffers.back()->GetTimestamp() <= duration_)
1122 return; 1131 return;
1123 1132
1124 Ranges<TimeDelta> ranges = stream->GetBufferedRanges(); 1133 Ranges<TimeDelta> ranges = stream->GetBufferedRanges(kInfiniteDuration());
1125 DCHECK_GT(ranges.size(), 0u); 1134 DCHECK_GT(ranges.size(), 0u);
1126 1135
1127 base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1); 1136 base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1);
1128 if (last_timestamp_buffered > duration_) 1137 if (last_timestamp_buffered > duration_)
1129 UpdateDuration(last_timestamp_buffered); 1138 UpdateDuration(last_timestamp_buffered);
1130 } 1139 }
1131 1140
1141 void ChunkDemuxer::DecreaseDurationIfNecessary() {
1142 Ranges<TimeDelta> ranges = GetBufferedRanges();
1143 if (ranges.size() == 0u)
1144 return;
1145
1146 base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1);
1147 if (last_timestamp_buffered < duration_)
1148 UpdateDuration(last_timestamp_buffered);
1149 }
1150
1151 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const {
1152 if (audio_ && !video_)
1153 return audio_->GetBufferedRanges(duration_);
1154 else if (!audio_ && video_)
1155 return video_->GetBufferedRanges(duration_);
1156 return ComputeIntersection();
1157 }
1158
1132 } // namespace media 1159 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | media/filters/chunk_demuxer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698