| 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 <memory> | 8 #include <memory> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 demuxer_->NotifyBufferingChanged(); | 559 demuxer_->NotifyBufferingChanged(); |
| 560 } | 560 } |
| 561 } | 561 } |
| 562 | 562 |
| 563 if (packet.get()->flags & AV_PKT_FLAG_KEY) | 563 if (packet.get()->flags & AV_PKT_FLAG_KEY) |
| 564 buffer->set_is_key_frame(true); | 564 buffer->set_is_key_frame(true); |
| 565 | 565 |
| 566 last_packet_timestamp_ = buffer->timestamp(); | 566 last_packet_timestamp_ = buffer->timestamp(); |
| 567 last_packet_duration_ = buffer->duration(); | 567 last_packet_duration_ = buffer->duration(); |
| 568 | 568 |
| 569 const base::TimeDelta new_duration = last_packet_timestamp_; |
| 570 if (new_duration > duration_ || duration_ == kNoTimestamp) |
| 571 duration_ = new_duration; |
| 572 |
| 569 buffer_queue_.Push(buffer); | 573 buffer_queue_.Push(buffer); |
| 570 SatisfyPendingRead(); | 574 SatisfyPendingRead(); |
| 571 } | 575 } |
| 572 | 576 |
| 573 void FFmpegDemuxerStream::SetEndOfStream() { | 577 void FFmpegDemuxerStream::SetEndOfStream() { |
| 574 DCHECK(task_runner_->BelongsToCurrentThread()); | 578 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 575 end_of_stream_ = true; | 579 end_of_stream_ = true; |
| 576 SatisfyPendingRead(); | 580 SatisfyPendingRead(); |
| 577 } | 581 } |
| 578 | 582 |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 DCHECK(!cb.is_null()); | 750 DCHECK(!cb.is_null()); |
| 747 stream_status_change_cb_ = cb; | 751 stream_status_change_cb_ = cb; |
| 748 } | 752 } |
| 749 | 753 |
| 750 void FFmpegDemuxerStream::SetLiveness(Liveness liveness) { | 754 void FFmpegDemuxerStream::SetLiveness(Liveness liveness) { |
| 751 DCHECK(task_runner_->BelongsToCurrentThread()); | 755 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 752 DCHECK_EQ(liveness_, LIVENESS_UNKNOWN); | 756 DCHECK_EQ(liveness_, LIVENESS_UNKNOWN); |
| 753 liveness_ = liveness; | 757 liveness_ = liveness; |
| 754 } | 758 } |
| 755 | 759 |
| 756 base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const { | |
| 757 return ConvertStreamTimestamp(stream_->time_base, stream_->cur_dts); | |
| 758 } | |
| 759 | |
| 760 Ranges<base::TimeDelta> FFmpegDemuxerStream::GetBufferedRanges() const { | 760 Ranges<base::TimeDelta> FFmpegDemuxerStream::GetBufferedRanges() const { |
| 761 return buffered_ranges_; | 761 return buffered_ranges_; |
| 762 } | 762 } |
| 763 | 763 |
| 764 void FFmpegDemuxerStream::SatisfyPendingRead() { | 764 void FFmpegDemuxerStream::SatisfyPendingRead() { |
| 765 DCHECK(task_runner_->BelongsToCurrentThread()); | 765 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 766 if (!read_cb_.is_null()) { | 766 if (!read_cb_.is_null()) { |
| 767 if (!buffer_queue_.IsEmpty()) { | 767 if (!buffer_queue_.IsEmpty()) { |
| 768 base::ResetAndReturn(&read_cb_).Run( | 768 base::ResetAndReturn(&read_cb_).Run( |
| 769 DemuxerStream::kOk, buffer_queue_.Pop()); | 769 DemuxerStream::kOk, buffer_queue_.Pop()); |
| (...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 SetLiveness(DemuxerStream::LIVENESS_LIVE); | 1438 SetLiveness(DemuxerStream::LIVENESS_LIVE); |
| 1439 } else if (max_duration != kInfiniteDuration) { | 1439 } else if (max_duration != kInfiniteDuration) { |
| 1440 SetLiveness(DemuxerStream::LIVENESS_RECORDED); | 1440 SetLiveness(DemuxerStream::LIVENESS_RECORDED); |
| 1441 } else { | 1441 } else { |
| 1442 SetLiveness(DemuxerStream::LIVENESS_UNKNOWN); | 1442 SetLiveness(DemuxerStream::LIVENESS_UNKNOWN); |
| 1443 } | 1443 } |
| 1444 | 1444 |
| 1445 // Good to go: set the duration and bitrate and notify we're done | 1445 // Good to go: set the duration and bitrate and notify we're done |
| 1446 // initializing. | 1446 // initializing. |
| 1447 host_->SetDuration(max_duration); | 1447 host_->SetDuration(max_duration); |
| 1448 duration_ = max_duration; |
| 1448 duration_known_ = (max_duration != kInfiniteDuration); | 1449 duration_known_ = (max_duration != kInfiniteDuration); |
| 1449 | 1450 |
| 1450 int64_t filesize_in_bytes = 0; | 1451 int64_t filesize_in_bytes = 0; |
| 1451 url_protocol_->GetSize(&filesize_in_bytes); | 1452 url_protocol_->GetSize(&filesize_in_bytes); |
| 1452 bitrate_ = CalculateBitrate(format_context, max_duration, filesize_in_bytes); | 1453 bitrate_ = CalculateBitrate(format_context, max_duration, filesize_in_bytes); |
| 1453 if (bitrate_ > 0) | 1454 if (bitrate_ > 0) |
| 1454 data_source_->SetBitrate(bitrate_); | 1455 data_source_->SetBitrate(bitrate_); |
| 1455 | 1456 |
| 1456 LogMetadata(format_context, max_duration); | 1457 LogMetadata(format_context, max_duration); |
| 1457 media_tracks_updated_cb_.Run(std::move(media_tracks)); | 1458 media_tracks_updated_cb_.Run(std::move(media_tracks)); |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1699 | 1700 |
| 1700 if (!blocking_thread_.IsRunning() || !pending_seek_cb_.is_null()) | 1701 if (!blocking_thread_.IsRunning() || !pending_seek_cb_.is_null()) |
| 1701 return; | 1702 return; |
| 1702 | 1703 |
| 1703 // Consider the stream as ended if: | 1704 // Consider the stream as ended if: |
| 1704 // - either underlying ffmpeg returned an error | 1705 // - either underlying ffmpeg returned an error |
| 1705 // - or FFMpegDemuxer reached the maximum allowed memory usage. | 1706 // - or FFMpegDemuxer reached the maximum allowed memory usage. |
| 1706 if (result < 0 || IsMaxMemoryUsageReached()) { | 1707 if (result < 0 || IsMaxMemoryUsageReached()) { |
| 1707 DVLOG(1) << __func__ << " result=" << result | 1708 DVLOG(1) << __func__ << " result=" << result |
| 1708 << " IsMaxMemoryUsageReached=" << IsMaxMemoryUsageReached(); | 1709 << " IsMaxMemoryUsageReached=" << IsMaxMemoryUsageReached(); |
| 1709 // Update the duration based on the highest elapsed time across all streams | 1710 // Update the duration based on the highest elapsed time across all streams. |
| 1710 // if it was previously unknown. | 1711 base::TimeDelta max_duration; |
| 1711 if (!duration_known_) { | 1712 for (const auto& stream : streams_) { |
| 1712 base::TimeDelta max_duration; | 1713 if (!stream) |
| 1714 continue; |
| 1713 | 1715 |
| 1714 for (const auto& stream : streams_) { | 1716 base::TimeDelta duration = stream->duration(); |
| 1715 if (!stream) | 1717 if (duration != kNoTimestamp && duration > max_duration) |
| 1716 continue; | 1718 max_duration = duration; |
| 1719 } |
| 1717 | 1720 |
| 1718 base::TimeDelta duration = stream->GetElapsedTime(); | 1721 if (duration_ == kInfiniteDuration || max_duration > duration_) { |
| 1719 if (duration != kNoTimestamp && duration > max_duration) | 1722 host_->SetDuration(max_duration); |
| 1720 max_duration = duration; | 1723 duration_known_ = true; |
| 1721 } | 1724 duration_ = max_duration; |
| 1725 } |
| 1722 | 1726 |
| 1723 if (max_duration > base::TimeDelta()) { | |
| 1724 host_->SetDuration(max_duration); | |
| 1725 duration_known_ = true; | |
| 1726 } | |
| 1727 } | |
| 1728 // If we have reached the end of stream, tell the downstream filters about | 1727 // If we have reached the end of stream, tell the downstream filters about |
| 1729 // the event. | 1728 // the event. |
| 1730 StreamHasEnded(); | 1729 StreamHasEnded(); |
| 1731 return; | 1730 return; |
| 1732 } | 1731 } |
| 1733 | 1732 |
| 1734 // Queue the packet with the appropriate stream. | 1733 // Queue the packet with the appropriate stream. |
| 1735 DCHECK_GE(packet->stream_index, 0); | 1734 DCHECK_GE(packet->stream_index, 0); |
| 1736 DCHECK_LT(packet->stream_index, static_cast<int>(streams_.size())); | 1735 DCHECK_LT(packet->stream_index, static_cast<int>(streams_.size())); |
| 1737 | 1736 |
| 1738 // Defend against ffmpeg giving us a bad stream index. | 1737 // Defend against ffmpeg giving us a bad stream index. |
| 1739 if (packet->stream_index >= 0 && | 1738 if (packet->stream_index >= 0 && |
| 1740 packet->stream_index < static_cast<int>(streams_.size()) && | 1739 packet->stream_index < static_cast<int>(streams_.size()) && |
| 1741 streams_[packet->stream_index]) { | 1740 streams_[packet->stream_index]) { |
| 1742 // TODO(scherkus): Fix demuxing upstream to never return packets w/o data | 1741 // TODO(scherkus): Fix demuxing upstream to never return packets w/o data |
| 1743 // when av_read_frame() returns success code. See bug comment for ideas: | 1742 // when av_read_frame() returns success code. See bug comment for ideas: |
| 1744 // | 1743 // |
| 1745 // https://code.google.com/p/chromium/issues/detail?id=169133#c10 | 1744 // https://code.google.com/p/chromium/issues/detail?id=169133#c10 |
| 1746 if (!packet->data) { | 1745 if (!packet->data) { |
| 1747 ScopedAVPacket new_packet(new AVPacket()); | 1746 ScopedAVPacket new_packet(new AVPacket()); |
| 1748 av_new_packet(new_packet.get(), 0); | 1747 av_new_packet(new_packet.get(), 0); |
| 1749 av_packet_copy_props(new_packet.get(), packet.get()); | 1748 av_packet_copy_props(new_packet.get(), packet.get()); |
| 1750 packet.swap(new_packet); | 1749 packet.swap(new_packet); |
| 1751 } | 1750 } |
| 1752 | 1751 |
| 1753 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index].get(); | 1752 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index].get(); |
| 1754 if (demuxer_stream->enabled()) | 1753 if (demuxer_stream->enabled()) |
| 1755 demuxer_stream->EnqueuePacket(std::move(packet)); | 1754 demuxer_stream->EnqueuePacket(std::move(packet)); |
| 1755 |
| 1756 // If duration estimate was incorrect, update it and tell higher layers. |
| 1757 if (duration_known_) { |
| 1758 const base::TimeDelta duration = demuxer_stream->duration(); |
| 1759 if (duration != kNoTimestamp && duration > duration_) { |
| 1760 duration_ = duration; |
| 1761 host_->SetDuration(duration_); |
| 1762 } |
| 1763 } |
| 1756 } | 1764 } |
| 1757 | 1765 |
| 1758 // Keep reading until we've reached capacity. | 1766 // Keep reading until we've reached capacity. |
| 1759 ReadFrameIfNeeded(); | 1767 ReadFrameIfNeeded(); |
| 1760 } | 1768 } |
| 1761 | 1769 |
| 1762 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() { | 1770 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() { |
| 1763 DCHECK(task_runner_->BelongsToCurrentThread()); | 1771 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 1764 for (const auto& stream : streams_) { | 1772 for (const auto& stream : streams_) { |
| 1765 if (stream && stream->HasAvailableCapacity()) | 1773 if (stream && stream->HasAvailableCapacity()) |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1808 | 1816 |
| 1809 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { | 1817 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { |
| 1810 DCHECK(task_runner_->BelongsToCurrentThread()); | 1818 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 1811 for (const auto& stream : streams_) { | 1819 for (const auto& stream : streams_) { |
| 1812 if (stream) | 1820 if (stream) |
| 1813 stream->SetLiveness(liveness); | 1821 stream->SetLiveness(liveness); |
| 1814 } | 1822 } |
| 1815 } | 1823 } |
| 1816 | 1824 |
| 1817 } // namespace media | 1825 } // namespace media |
| OLD | NEW |