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/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 int FFmpegDemuxerStream::MemoryUsage() const { | |
| 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 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 793 | 797 |
| 794 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { | 798 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { |
| 795 DCHECK(task_runner_->BelongsToCurrentThread()); | 799 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 796 DCHECK(pending_read_); | 800 DCHECK(pending_read_); |
| 797 pending_read_ = false; | 801 pending_read_ = false; |
| 798 | 802 |
| 799 if (!blocking_thread_.IsRunning() || pending_seek_) { | 803 if (!blocking_thread_.IsRunning() || pending_seek_) { |
| 800 return; | 804 return; |
| 801 } | 805 } |
| 802 | 806 |
| 803 if (result < 0) { | 807 // Consider the stream as ended if: |
| 808 // - either underlying ffmpeg returned an error | |
| 809 // - or any stream reached its maximum memory usage. | |
| 810 if (result < 0 || IsMaxMemoryReached()) { | |
| 804 // Update the duration based on the highest elapsed time across all streams | 811 // Update the duration based on the highest elapsed time across all streams |
| 805 // if it was previously unknown. | 812 // if it was previously unknown. |
| 806 if (!duration_known_) { | 813 if (!duration_known_) { |
| 807 base::TimeDelta max_duration; | 814 base::TimeDelta max_duration; |
| 808 | 815 |
| 809 for (StreamVector::iterator iter = streams_.begin(); | 816 for (StreamVector::iterator iter = streams_.begin(); |
| 810 iter != streams_.end(); | 817 iter != streams_.end(); |
| 811 ++iter) { | 818 ++iter) { |
| 812 if (!*iter) | 819 if (!*iter) |
| 813 continue; | 820 continue; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 900 DCHECK(task_runner_->BelongsToCurrentThread()); | 907 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 901 StreamVector::iterator iter; | 908 StreamVector::iterator iter; |
| 902 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 909 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
| 903 if (*iter && (*iter)->HasAvailableCapacity()) { | 910 if (*iter && (*iter)->HasAvailableCapacity()) { |
| 904 return true; | 911 return true; |
| 905 } | 912 } |
| 906 } | 913 } |
| 907 return false; | 914 return false; |
| 908 } | 915 } |
| 909 | 916 |
| 917 bool FFmpegDemuxer::IsMaxMemoryReached() { | |
| 918 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 919 const int kMaxMemoryForAudioStream = 12 * 1024 * 1024; | |
| 920 const int kMaxMemoryForVideoStream = 150 * 1024 * 1024; | |
| 921 StreamVector::iterator iter; | |
| 922 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | |
| 923 if (!(*iter)) | |
| 924 continue; | |
| 925 switch ((*iter)->type()) { | |
| 926 case DemuxerStream::VIDEO: | |
| 927 if ((*iter)->MemoryUsage() >= kMaxMemoryForVideoStream) | |
| 928 return true; | |
| 929 break; | |
| 930 case DemuxerStream::AUDIO: | |
| 931 if ((*iter)->MemoryUsage() >= kMaxMemoryForAudioStream) | |
| 932 return true; | |
| 933 break; | |
| 934 default: | |
|
acolwell GONE FROM CHROMIUM
2014/02/18 22:16:20
nit: Please don't use default here. Explicitly ind
damienv1
2014/02/18 23:38:03
I changed the code so that the contribution of eve
| |
| 935 break; | |
| 936 } | |
| 937 } | |
| 938 return false; | |
| 939 } | |
| 940 | |
| 910 void FFmpegDemuxer::StreamHasEnded() { | 941 void FFmpegDemuxer::StreamHasEnded() { |
| 911 DCHECK(task_runner_->BelongsToCurrentThread()); | 942 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 912 StreamVector::iterator iter; | 943 StreamVector::iterator iter; |
| 913 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 944 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
| 914 if (!*iter || | 945 if (!*iter || |
| 915 (audio_disabled_ && (*iter)->type() == DemuxerStream::AUDIO)) { | 946 (audio_disabled_ && (*iter)->type() == DemuxerStream::AUDIO)) { |
| 916 continue; | 947 continue; |
| 917 } | 948 } |
| 918 (*iter)->SetEndOfStream(); | 949 (*iter)->SetEndOfStream(); |
| 919 } | 950 } |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 947 } | 978 } |
| 948 for (size_t i = 0; i < buffered.size(); ++i) | 979 for (size_t i = 0; i < buffered.size(); ++i) |
| 949 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); | 980 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); |
| 950 } | 981 } |
| 951 | 982 |
| 952 void FFmpegDemuxer::OnDataSourceError() { | 983 void FFmpegDemuxer::OnDataSourceError() { |
| 953 host_->OnDemuxerError(PIPELINE_ERROR_READ); | 984 host_->OnDemuxerError(PIPELINE_ERROR_READ); |
| 954 } | 985 } |
| 955 | 986 |
| 956 } // namespace media | 987 } // namespace media |
| OLD | NEW |