| 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 <limits> |
| 8 #include <string> | 9 #include <string> |
| 9 | 10 |
| 10 #include "base/base64.h" | 11 #include "base/base64.h" |
| 11 #include "base/bind.h" | 12 #include "base/bind.h" |
| 12 #include "base/callback.h" | 13 #include "base/callback.h" |
| 13 #include "base/callback_helpers.h" | 14 #include "base/callback_helpers.h" |
| 14 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 15 #include "base/message_loop/message_loop_proxy.h" | 16 #include "base/message_loop/message_loop_proxy.h" |
| 16 #include "base/metrics/sparse_histogram.h" | 17 #include "base/metrics/sparse_histogram.h" |
| 17 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 // TODO(scherkus): Remove early return and reenable time-based capacity | 317 // TODO(scherkus): Remove early return and reenable time-based capacity |
| 317 // after our data sources support canceling/concurrent reads, see | 318 // after our data sources support canceling/concurrent reads, see |
| 318 // http://crbug.com/165762 for details. | 319 // http://crbug.com/165762 for details. |
| 319 return !read_cb_.is_null(); | 320 return !read_cb_.is_null(); |
| 320 | 321 |
| 321 // Try to have one second's worth of encoded data per stream. | 322 // Try to have one second's worth of encoded data per stream. |
| 322 const base::TimeDelta kCapacity = base::TimeDelta::FromSeconds(1); | 323 const base::TimeDelta kCapacity = base::TimeDelta::FromSeconds(1); |
| 323 return buffer_queue_.IsEmpty() || buffer_queue_.Duration() < kCapacity; | 324 return buffer_queue_.IsEmpty() || buffer_queue_.Duration() < kCapacity; |
| 324 } | 325 } |
| 325 | 326 |
| 327 int FFmpegDemuxerStream::MemoryUsage() const { |
| 328 return buffer_queue_.data_size(); |
| 329 } |
| 330 |
| 326 TextKind FFmpegDemuxerStream::GetTextKind() const { | 331 TextKind FFmpegDemuxerStream::GetTextKind() const { |
| 327 DCHECK_EQ(type_, DemuxerStream::TEXT); | 332 DCHECK_EQ(type_, DemuxerStream::TEXT); |
| 328 | 333 |
| 329 if (stream_->disposition & AV_DISPOSITION_CAPTIONS) | 334 if (stream_->disposition & AV_DISPOSITION_CAPTIONS) |
| 330 return kTextCaptions; | 335 return kTextCaptions; |
| 331 | 336 |
| 332 if (stream_->disposition & AV_DISPOSITION_DESCRIPTIONS) | 337 if (stream_->disposition & AV_DISPOSITION_DESCRIPTIONS) |
| 333 return kTextDescriptions; | 338 return kTextDescriptions; |
| 334 | 339 |
| 335 if (stream_->disposition & AV_DISPOSITION_METADATA) | 340 if (stream_->disposition & AV_DISPOSITION_METADATA) |
| (...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 793 | 798 |
| 794 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { | 799 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { |
| 795 DCHECK(task_runner_->BelongsToCurrentThread()); | 800 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 796 DCHECK(pending_read_); | 801 DCHECK(pending_read_); |
| 797 pending_read_ = false; | 802 pending_read_ = false; |
| 798 | 803 |
| 799 if (!blocking_thread_.IsRunning() || pending_seek_) { | 804 if (!blocking_thread_.IsRunning() || pending_seek_) { |
| 800 return; | 805 return; |
| 801 } | 806 } |
| 802 | 807 |
| 803 if (result < 0) { | 808 // Consider the stream as ended if: |
| 809 // - either underlying ffmpeg returned an error |
| 810 // - or any stream reached its maximum memory usage. |
| 811 if (result < 0 || IsMaxMemoryReached()) { |
| 804 // Update the duration based on the highest elapsed time across all streams | 812 // Update the duration based on the highest elapsed time across all streams |
| 805 // if it was previously unknown. | 813 // if it was previously unknown. |
| 806 if (!duration_known_) { | 814 if (!duration_known_) { |
| 807 base::TimeDelta max_duration; | 815 base::TimeDelta max_duration; |
| 808 | 816 |
| 809 for (StreamVector::iterator iter = streams_.begin(); | 817 for (StreamVector::iterator iter = streams_.begin(); |
| 810 iter != streams_.end(); | 818 iter != streams_.end(); |
| 811 ++iter) { | 819 ++iter) { |
| 812 if (!*iter) | 820 if (!*iter) |
| 813 continue; | 821 continue; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 DCHECK(task_runner_->BelongsToCurrentThread()); | 908 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 901 StreamVector::iterator iter; | 909 StreamVector::iterator iter; |
| 902 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 910 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
| 903 if (*iter && (*iter)->HasAvailableCapacity()) { | 911 if (*iter && (*iter)->HasAvailableCapacity()) { |
| 904 return true; | 912 return true; |
| 905 } | 913 } |
| 906 } | 914 } |
| 907 return false; | 915 return false; |
| 908 } | 916 } |
| 909 | 917 |
| 918 bool FFmpegDemuxer::IsMaxMemoryReached() { |
| 919 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 920 // Max memory usage, all streams combined. |
| 921 const int kMemoryLimit = 150 * 1024 * 1024; |
| 922 int memory_usage = 0; |
| 923 StreamVector::iterator iter; |
| 924 for (StreamVector::iterator iter = streams_.begin(); |
| 925 iter != streams_.end(); ++iter) { |
| 926 if (!(*iter)) |
| 927 continue; |
| 928 DCHECK_LE((*iter)->MemoryUsage(), |
| 929 std::numeric_limits<int>::max() - memory_usage); |
| 930 memory_usage += (*iter)->MemoryUsage(); |
| 931 } |
| 932 return (memory_usage >= kMemoryLimit); |
| 933 } |
| 934 |
| 910 void FFmpegDemuxer::StreamHasEnded() { | 935 void FFmpegDemuxer::StreamHasEnded() { |
| 911 DCHECK(task_runner_->BelongsToCurrentThread()); | 936 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 912 StreamVector::iterator iter; | 937 StreamVector::iterator iter; |
| 913 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 938 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
| 914 if (!*iter || | 939 if (!*iter || |
| 915 (audio_disabled_ && (*iter)->type() == DemuxerStream::AUDIO)) { | 940 (audio_disabled_ && (*iter)->type() == DemuxerStream::AUDIO)) { |
| 916 continue; | 941 continue; |
| 917 } | 942 } |
| 918 (*iter)->SetEndOfStream(); | 943 (*iter)->SetEndOfStream(); |
| 919 } | 944 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 947 } | 972 } |
| 948 for (size_t i = 0; i < buffered.size(); ++i) | 973 for (size_t i = 0; i < buffered.size(); ++i) |
| 949 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); | 974 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); |
| 950 } | 975 } |
| 951 | 976 |
| 952 void FFmpegDemuxer::OnDataSourceError() { | 977 void FFmpegDemuxer::OnDataSourceError() { |
| 953 host_->OnDemuxerError(PIPELINE_ERROR_READ); | 978 host_->OnDemuxerError(PIPELINE_ERROR_READ); |
| 954 } | 979 } |
| 955 | 980 |
| 956 } // namespace media | 981 } // namespace media |
| OLD | NEW |