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/base64.h" | 10 #include "base/base64.h" |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
316 // TODO(scherkus): Remove early return and reenable time-based capacity | 316 // TODO(scherkus): Remove early return and reenable time-based capacity |
317 // after our data sources support canceling/concurrent reads, see | 317 // after our data sources support canceling/concurrent reads, see |
318 // http://crbug.com/165762 for details. | 318 // http://crbug.com/165762 for details. |
319 return !read_cb_.is_null(); | 319 return !read_cb_.is_null(); |
320 | 320 |
321 // Try to have one second's worth of encoded data per stream. | 321 // Try to have one second's worth of encoded data per stream. |
322 const base::TimeDelta kCapacity = base::TimeDelta::FromSeconds(1); | 322 const base::TimeDelta kCapacity = base::TimeDelta::FromSeconds(1); |
323 return buffer_queue_.IsEmpty() || buffer_queue_.Duration() < kCapacity; | 323 return buffer_queue_.IsEmpty() || buffer_queue_.Duration() < kCapacity; |
324 } | 324 } |
325 | 325 |
326 size_t FFmpegDemuxerStream::MemoryUsage() const { | |
DaleCurtis
2014/02/19 20:56:21
You can declare this inline as memory_usage() if y
damienv1
2014/02/19 22:07:28
Prefer to keep the current approach (similar to Ha
| |
327 return buffer_queue_.data_size(); | |
328 } | |
329 | |
326 TextKind FFmpegDemuxerStream::GetTextKind() const { | 330 TextKind FFmpegDemuxerStream::GetTextKind() const { |
327 DCHECK_EQ(type_, DemuxerStream::TEXT); | 331 DCHECK_EQ(type_, DemuxerStream::TEXT); |
328 | 332 |
329 if (stream_->disposition & AV_DISPOSITION_CAPTIONS) | 333 if (stream_->disposition & AV_DISPOSITION_CAPTIONS) |
330 return kTextCaptions; | 334 return kTextCaptions; |
331 | 335 |
332 if (stream_->disposition & AV_DISPOSITION_DESCRIPTIONS) | 336 if (stream_->disposition & AV_DISPOSITION_DESCRIPTIONS) |
333 return kTextDescriptions; | 337 return kTextDescriptions; |
334 | 338 |
335 if (stream_->disposition & AV_DISPOSITION_METADATA) | 339 if (stream_->disposition & AV_DISPOSITION_METADATA) |
(...skipping 10 matching lines...) Expand all Loading... | |
346 | 350 |
347 // static | 351 // static |
348 base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp( | 352 base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp( |
349 const AVRational& time_base, int64 timestamp) { | 353 const AVRational& time_base, int64 timestamp) { |
350 if (timestamp == static_cast<int64>(AV_NOPTS_VALUE)) | 354 if (timestamp == static_cast<int64>(AV_NOPTS_VALUE)) |
351 return kNoTimestamp(); | 355 return kNoTimestamp(); |
352 | 356 |
353 return ConvertFromTimeBase(time_base, timestamp); | 357 return ConvertFromTimeBase(time_base, timestamp); |
354 } | 358 } |
355 | 359 |
360 // Max allowed memory usage, all streams combined. | |
361 static const size_t kDemuxerMemoryLimit = 150 * 1024 * 1024; | |
DaleCurtis
2014/02/19 20:56:21
Since this is only used in one spot, just stick it
damienv1
2014/02/19 22:07:28
Done.
| |
362 | |
356 // | 363 // |
357 // FFmpegDemuxer | 364 // FFmpegDemuxer |
358 // | 365 // |
359 FFmpegDemuxer::FFmpegDemuxer( | 366 FFmpegDemuxer::FFmpegDemuxer( |
360 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 367 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
361 DataSource* data_source, | 368 DataSource* data_source, |
362 const NeedKeyCB& need_key_cb, | 369 const NeedKeyCB& need_key_cb, |
363 const scoped_refptr<MediaLog>& media_log) | 370 const scoped_refptr<MediaLog>& media_log) |
364 : host_(NULL), | 371 : host_(NULL), |
365 task_runner_(task_runner), | 372 task_runner_(task_runner), |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
793 | 800 |
794 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { | 801 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { |
795 DCHECK(task_runner_->BelongsToCurrentThread()); | 802 DCHECK(task_runner_->BelongsToCurrentThread()); |
796 DCHECK(pending_read_); | 803 DCHECK(pending_read_); |
797 pending_read_ = false; | 804 pending_read_ = false; |
798 | 805 |
799 if (!blocking_thread_.IsRunning() || pending_seek_) { | 806 if (!blocking_thread_.IsRunning() || pending_seek_) { |
800 return; | 807 return; |
801 } | 808 } |
802 | 809 |
803 if (result < 0) { | 810 // Consider the stream as ended if: |
811 // - either underlying ffmpeg returned an error | |
812 // - or FFMpegDemuxer reached the maximum allowed memory usage. | |
813 if (result < 0 || IsMaxMemoryUsageReached()) { | |
804 // Update the duration based on the highest elapsed time across all streams | 814 // Update the duration based on the highest elapsed time across all streams |
805 // if it was previously unknown. | 815 // if it was previously unknown. |
806 if (!duration_known_) { | 816 if (!duration_known_) { |
807 base::TimeDelta max_duration; | 817 base::TimeDelta max_duration; |
808 | 818 |
809 for (StreamVector::iterator iter = streams_.begin(); | 819 for (StreamVector::iterator iter = streams_.begin(); |
810 iter != streams_.end(); | 820 iter != streams_.end(); |
811 ++iter) { | 821 ++iter) { |
812 if (!*iter) | 822 if (!*iter) |
813 continue; | 823 continue; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
900 DCHECK(task_runner_->BelongsToCurrentThread()); | 910 DCHECK(task_runner_->BelongsToCurrentThread()); |
901 StreamVector::iterator iter; | 911 StreamVector::iterator iter; |
902 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 912 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
903 if (*iter && (*iter)->HasAvailableCapacity()) { | 913 if (*iter && (*iter)->HasAvailableCapacity()) { |
904 return true; | 914 return true; |
905 } | 915 } |
906 } | 916 } |
907 return false; | 917 return false; |
908 } | 918 } |
909 | 919 |
920 bool FFmpegDemuxer::IsMaxMemoryUsageReached() const { | |
921 DCHECK(task_runner_->BelongsToCurrentThread()); | |
922 size_t memory_left = kDemuxerMemoryLimit; | |
923 for (StreamVector::const_iterator iter = streams_.begin(); | |
924 iter != streams_.end(); ++iter) { | |
925 if (!(*iter)) | |
926 continue; | |
927 | |
928 size_t stream_memory_usage = (*iter)->MemoryUsage(); | |
929 if (stream_memory_usage > memory_left) | |
930 return true; | |
931 memory_left -= stream_memory_usage; | |
932 } | |
933 return false; | |
934 } | |
935 | |
910 void FFmpegDemuxer::StreamHasEnded() { | 936 void FFmpegDemuxer::StreamHasEnded() { |
911 DCHECK(task_runner_->BelongsToCurrentThread()); | 937 DCHECK(task_runner_->BelongsToCurrentThread()); |
912 StreamVector::iterator iter; | 938 StreamVector::iterator iter; |
913 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 939 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
914 if (!*iter || | 940 if (!*iter || |
915 (audio_disabled_ && (*iter)->type() == DemuxerStream::AUDIO)) { | 941 (audio_disabled_ && (*iter)->type() == DemuxerStream::AUDIO)) { |
916 continue; | 942 continue; |
917 } | 943 } |
918 (*iter)->SetEndOfStream(); | 944 (*iter)->SetEndOfStream(); |
919 } | 945 } |
(...skipping 27 matching lines...) Expand all Loading... | |
947 } | 973 } |
948 for (size_t i = 0; i < buffered.size(); ++i) | 974 for (size_t i = 0; i < buffered.size(); ++i) |
949 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); | 975 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); |
950 } | 976 } |
951 | 977 |
952 void FFmpegDemuxer::OnDataSourceError() { | 978 void FFmpegDemuxer::OnDataSourceError() { |
953 host_->OnDemuxerError(PIPELINE_ERROR_READ); | 979 host_->OnDemuxerError(PIPELINE_ERROR_READ); |
954 } | 980 } |
955 | 981 |
956 } // namespace media | 982 } // namespace media |
OLD | NEW |