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 | 8 |
9 #include "base/base64.h" | 9 #include "base/base64.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 pending_seek_(false), | 735 pending_seek_(false), |
736 data_source_(data_source), | 736 data_source_(data_source), |
737 media_log_(media_log), | 737 media_log_(media_log), |
738 bitrate_(0), | 738 bitrate_(0), |
739 start_time_(kNoTimestamp()), | 739 start_time_(kNoTimestamp()), |
740 preferred_stream_for_seeking_(-1, kNoTimestamp()), | 740 preferred_stream_for_seeking_(-1, kNoTimestamp()), |
741 fallback_stream_for_seeking_(-1, kNoTimestamp()), | 741 fallback_stream_for_seeking_(-1, kNoTimestamp()), |
742 text_enabled_(false), | 742 text_enabled_(false), |
743 duration_known_(false), | 743 duration_known_(false), |
744 encrypted_media_init_data_cb_(encrypted_media_init_data_cb), | 744 encrypted_media_init_data_cb_(encrypted_media_init_data_cb), |
| 745 stream_memory_usage_(0), |
745 weak_factory_(this) { | 746 weak_factory_(this) { |
746 DCHECK(task_runner_.get()); | 747 DCHECK(task_runner_.get()); |
747 DCHECK(data_source_); | 748 DCHECK(data_source_); |
748 } | 749 } |
749 | 750 |
750 FFmpegDemuxer::~FFmpegDemuxer() {} | 751 FFmpegDemuxer::~FFmpegDemuxer() {} |
751 | 752 |
752 void FFmpegDemuxer::Stop() { | 753 void FFmpegDemuxer::Stop() { |
753 DCHECK(task_runner_->BelongsToCurrentThread()); | 754 DCHECK(task_runner_->BelongsToCurrentThread()); |
754 | 755 |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
911 std::string language = stream->GetMetadata("language"); | 912 std::string language = stream->GetMetadata("language"); |
912 | 913 |
913 // TODO: Implement "id" metadata in FFMPEG. | 914 // TODO: Implement "id" metadata in FFMPEG. |
914 // See: http://crbug.com/323183 | 915 // See: http://crbug.com/323183 |
915 host_->AddTextStream(stream, TextTrackConfig(kind, title, language, | 916 host_->AddTextStream(stream, TextTrackConfig(kind, title, language, |
916 std::string())); | 917 std::string())); |
917 } | 918 } |
918 } | 919 } |
919 | 920 |
920 int64_t FFmpegDemuxer::GetMemoryUsage() const { | 921 int64_t FFmpegDemuxer::GetMemoryUsage() const { |
921 int64_t allocation_size = 0; | 922 base::AutoLock locker(stream_memory_usage_lock_); |
922 for (const auto& stream : streams_) { | 923 return stream_memory_usage_; |
923 if (stream) | |
924 allocation_size += stream->MemoryUsage(); | |
925 } | |
926 return allocation_size; | |
927 } | 924 } |
928 | 925 |
929 // Helper for calculating the bitrate of the media based on information stored | 926 // Helper for calculating the bitrate of the media based on information stored |
930 // in |format_context| or failing that the size and duration of the media. | 927 // in |format_context| or failing that the size and duration of the media. |
931 // | 928 // |
932 // Returns 0 if a bitrate could not be determined. | 929 // Returns 0 if a bitrate could not be determined. |
933 static int CalculateBitrate( | 930 static int CalculateBitrate( |
934 AVFormatContext* format_context, | 931 AVFormatContext* format_context, |
935 const base::TimeDelta& duration, | 932 const base::TimeDelta& duration, |
936 int64 filesize_in_bytes) { | 933 int64 filesize_in_bytes) { |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1369 | 1366 |
1370 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { | 1367 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) { |
1371 DCHECK(task_runner_->BelongsToCurrentThread()); | 1368 DCHECK(task_runner_->BelongsToCurrentThread()); |
1372 DCHECK(pending_read_); | 1369 DCHECK(pending_read_); |
1373 pending_read_ = false; | 1370 pending_read_ = false; |
1374 | 1371 |
1375 if (!blocking_thread_.IsRunning() || pending_seek_) { | 1372 if (!blocking_thread_.IsRunning() || pending_seek_) { |
1376 return; | 1373 return; |
1377 } | 1374 } |
1378 | 1375 |
| 1376 // Max allowed memory usage, all streams combined. |
| 1377 const int64_t kDemuxerMemoryLimit = 150 * 1024 * 1024; |
| 1378 const bool is_max_memory_usage_reached = |
| 1379 UpdateMemoryUsage() > kDemuxerMemoryLimit; |
| 1380 |
1379 // Consider the stream as ended if: | 1381 // Consider the stream as ended if: |
1380 // - either underlying ffmpeg returned an error | 1382 // - either underlying ffmpeg returned an error |
1381 // - or FFMpegDemuxer reached the maximum allowed memory usage. | 1383 // - or FFMpegDemuxer reached the maximum allowed memory usage. |
1382 if (result < 0 || IsMaxMemoryUsageReached()) { | 1384 if (result < 0 || is_max_memory_usage_reached) { |
1383 // Update the duration based on the highest elapsed time across all streams | 1385 // Update the duration based on the highest elapsed time across all streams |
1384 // if it was previously unknown. | 1386 // if it was previously unknown. |
1385 if (!duration_known_) { | 1387 if (!duration_known_) { |
1386 base::TimeDelta max_duration; | 1388 base::TimeDelta max_duration; |
1387 | 1389 |
1388 for (StreamVector::iterator iter = streams_.begin(); | 1390 for (StreamVector::iterator iter = streams_.begin(); |
1389 iter != streams_.end(); | 1391 iter != streams_.end(); |
1390 ++iter) { | 1392 ++iter) { |
1391 if (!*iter) | 1393 if (!*iter) |
1392 continue; | 1394 continue; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1438 DCHECK(task_runner_->BelongsToCurrentThread()); | 1440 DCHECK(task_runner_->BelongsToCurrentThread()); |
1439 StreamVector::iterator iter; | 1441 StreamVector::iterator iter; |
1440 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 1442 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
1441 if (*iter && (*iter)->HasAvailableCapacity()) { | 1443 if (*iter && (*iter)->HasAvailableCapacity()) { |
1442 return true; | 1444 return true; |
1443 } | 1445 } |
1444 } | 1446 } |
1445 return false; | 1447 return false; |
1446 } | 1448 } |
1447 | 1449 |
1448 bool FFmpegDemuxer::IsMaxMemoryUsageReached() const { | 1450 int64_t FFmpegDemuxer::UpdateMemoryUsage() { |
1449 DCHECK(task_runner_->BelongsToCurrentThread()); | 1451 DCHECK(task_runner_->BelongsToCurrentThread()); |
1450 | 1452 |
1451 // Max allowed memory usage, all streams combined. | 1453 base::AutoLock locker(stream_memory_usage_lock_); |
1452 const size_t kDemuxerMemoryLimit = 150 * 1024 * 1024; | 1454 stream_memory_usage_ = 0; |
1453 | 1455 for (const auto& stream : streams_) { |
1454 size_t memory_left = kDemuxerMemoryLimit; | 1456 if (stream) |
1455 for (StreamVector::const_iterator iter = streams_.begin(); | 1457 stream_memory_usage_ += stream->MemoryUsage(); |
1456 iter != streams_.end(); ++iter) { | |
1457 if (!(*iter)) | |
1458 continue; | |
1459 | |
1460 size_t stream_memory_usage = (*iter)->MemoryUsage(); | |
1461 if (stream_memory_usage > memory_left) | |
1462 return true; | |
1463 memory_left -= stream_memory_usage; | |
1464 } | 1458 } |
1465 return false; | 1459 return stream_memory_usage_; |
1466 } | 1460 } |
1467 | 1461 |
1468 void FFmpegDemuxer::StreamHasEnded() { | 1462 void FFmpegDemuxer::StreamHasEnded() { |
1469 DCHECK(task_runner_->BelongsToCurrentThread()); | 1463 DCHECK(task_runner_->BelongsToCurrentThread()); |
1470 StreamVector::iterator iter; | 1464 StreamVector::iterator iter; |
1471 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { | 1465 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { |
1472 if (!*iter) | 1466 if (!*iter) |
1473 continue; | 1467 continue; |
1474 (*iter)->SetEndOfStream(); | 1468 (*iter)->SetEndOfStream(); |
1475 } | 1469 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1512 | 1506 |
1513 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { | 1507 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { |
1514 DCHECK(task_runner_->BelongsToCurrentThread()); | 1508 DCHECK(task_runner_->BelongsToCurrentThread()); |
1515 for (const auto& stream : streams_) { // |stream| is a ref to a pointer. | 1509 for (const auto& stream : streams_) { // |stream| is a ref to a pointer. |
1516 if (stream) | 1510 if (stream) |
1517 stream->SetLiveness(liveness); | 1511 stream->SetLiveness(liveness); |
1518 } | 1512 } |
1519 } | 1513 } |
1520 | 1514 |
1521 } // namespace media | 1515 } // namespace media |
OLD | NEW |