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