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 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
566 demuxer_->NotifyBufferingChanged(); | 566 demuxer_->NotifyBufferingChanged(); |
567 } | 567 } |
568 } | 568 } |
569 | 569 |
570 if (packet.get()->flags & AV_PKT_FLAG_KEY) | 570 if (packet.get()->flags & AV_PKT_FLAG_KEY) |
571 buffer->set_is_key_frame(true); | 571 buffer->set_is_key_frame(true); |
572 | 572 |
573 last_packet_timestamp_ = buffer->timestamp(); | 573 last_packet_timestamp_ = buffer->timestamp(); |
574 last_packet_duration_ = buffer->duration(); | 574 last_packet_duration_ = buffer->duration(); |
575 | 575 |
576 const base::TimeDelta new_duration = | |
577 last_packet_timestamp_ + last_packet_duration_; | |
578 if (new_duration > duration_ || duration_ == kNoTimestamp) | |
579 duration_ = new_duration; | |
580 | |
576 buffer_queue_.Push(buffer); | 581 buffer_queue_.Push(buffer); |
577 SatisfyPendingRead(); | 582 SatisfyPendingRead(); |
578 } | 583 } |
579 | 584 |
580 void FFmpegDemuxerStream::SetEndOfStream() { | 585 void FFmpegDemuxerStream::SetEndOfStream() { |
581 DCHECK(task_runner_->BelongsToCurrentThread()); | 586 DCHECK(task_runner_->BelongsToCurrentThread()); |
582 end_of_stream_ = true; | 587 end_of_stream_ = true; |
583 SatisfyPendingRead(); | 588 SatisfyPendingRead(); |
584 } | 589 } |
585 | 590 |
(...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1430 SetLiveness(DemuxerStream::LIVENESS_LIVE); | 1435 SetLiveness(DemuxerStream::LIVENESS_LIVE); |
1431 } else if (max_duration != kInfiniteDuration) { | 1436 } else if (max_duration != kInfiniteDuration) { |
1432 SetLiveness(DemuxerStream::LIVENESS_RECORDED); | 1437 SetLiveness(DemuxerStream::LIVENESS_RECORDED); |
1433 } else { | 1438 } else { |
1434 SetLiveness(DemuxerStream::LIVENESS_UNKNOWN); | 1439 SetLiveness(DemuxerStream::LIVENESS_UNKNOWN); |
1435 } | 1440 } |
1436 | 1441 |
1437 // Good to go: set the duration and bitrate and notify we're done | 1442 // Good to go: set the duration and bitrate and notify we're done |
1438 // initializing. | 1443 // initializing. |
1439 host_->SetDuration(max_duration); | 1444 host_->SetDuration(max_duration); |
1445 duration_ = max_duration; | |
1440 duration_known_ = (max_duration != kInfiniteDuration); | 1446 duration_known_ = (max_duration != kInfiniteDuration); |
1441 | 1447 |
1442 int64_t filesize_in_bytes = 0; | 1448 int64_t filesize_in_bytes = 0; |
1443 url_protocol_->GetSize(&filesize_in_bytes); | 1449 url_protocol_->GetSize(&filesize_in_bytes); |
1444 bitrate_ = CalculateBitrate(format_context, max_duration, filesize_in_bytes); | 1450 bitrate_ = CalculateBitrate(format_context, max_duration, filesize_in_bytes); |
1445 if (bitrate_ > 0) | 1451 if (bitrate_ > 0) |
1446 data_source_->SetBitrate(bitrate_); | 1452 data_source_->SetBitrate(bitrate_); |
1447 | 1453 |
1448 LogMetadata(format_context, max_duration); | 1454 LogMetadata(format_context, max_duration); |
1449 media_tracks_updated_cb_.Run(std::move(media_tracks)); | 1455 media_tracks_updated_cb_.Run(std::move(media_tracks)); |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1665 | 1671 |
1666 if (!blocking_thread_.IsRunning() || !pending_seek_cb_.is_null()) | 1672 if (!blocking_thread_.IsRunning() || !pending_seek_cb_.is_null()) |
1667 return; | 1673 return; |
1668 | 1674 |
1669 // Consider the stream as ended if: | 1675 // Consider the stream as ended if: |
1670 // - either underlying ffmpeg returned an error | 1676 // - either underlying ffmpeg returned an error |
1671 // - or FFMpegDemuxer reached the maximum allowed memory usage. | 1677 // - or FFMpegDemuxer reached the maximum allowed memory usage. |
1672 if (result < 0 || IsMaxMemoryUsageReached()) { | 1678 if (result < 0 || IsMaxMemoryUsageReached()) { |
1673 DVLOG(1) << __func__ << " result=" << result | 1679 DVLOG(1) << __func__ << " result=" << result |
1674 << " IsMaxMemoryUsageReached=" << IsMaxMemoryUsageReached(); | 1680 << " IsMaxMemoryUsageReached=" << IsMaxMemoryUsageReached(); |
1675 // Update the duration based on the highest elapsed time across all streams | 1681 // Update the duration based on the highest elapsed time across all streams. |
1676 // if it was previously unknown. | 1682 base::TimeDelta max_duration; |
1677 if (!duration_known_) { | 1683 for (const auto& stream : streams_) { |
1678 base::TimeDelta max_duration; | 1684 if (!stream) |
1685 continue; | |
1679 | 1686 |
1680 for (const auto& stream : streams_) { | 1687 base::TimeDelta duration = |
1681 if (!stream) | 1688 duration_known_ ? stream->duration() : stream->GetElapsedTime(); |
chcunningham
2016/10/24 20:18:53
why not always pick GetElapsedTime here? Or why no
| |
1682 continue; | 1689 if (duration != kNoTimestamp && duration > max_duration) |
1690 max_duration = duration; | |
1691 } | |
1683 | 1692 |
1684 base::TimeDelta duration = stream->GetElapsedTime(); | 1693 if (duration_ == kInfiniteDuration || max_duration > duration_) { |
chcunningham
2016/10/24 20:18:54
I'm confused about when/why we want to override In
| |
1685 if (duration != kNoTimestamp && duration > max_duration) | 1694 host_->SetDuration(max_duration); |
1686 max_duration = duration; | 1695 duration_known_ = true; |
1687 } | 1696 duration_ = max_duration; |
1697 } | |
1688 | 1698 |
1689 if (max_duration > base::TimeDelta()) { | |
1690 host_->SetDuration(max_duration); | |
1691 duration_known_ = true; | |
1692 } | |
1693 } | |
1694 // If we have reached the end of stream, tell the downstream filters about | 1699 // If we have reached the end of stream, tell the downstream filters about |
1695 // the event. | 1700 // the event. |
1696 StreamHasEnded(); | 1701 StreamHasEnded(); |
1697 return; | 1702 return; |
1698 } | 1703 } |
1699 | 1704 |
1700 // Queue the packet with the appropriate stream. | 1705 // Queue the packet with the appropriate stream. |
1701 DCHECK_GE(packet->stream_index, 0); | 1706 DCHECK_GE(packet->stream_index, 0); |
1702 DCHECK_LT(packet->stream_index, static_cast<int>(streams_.size())); | 1707 DCHECK_LT(packet->stream_index, static_cast<int>(streams_.size())); |
1703 | 1708 |
1704 // Defend against ffmpeg giving us a bad stream index. | 1709 // Defend against ffmpeg giving us a bad stream index. |
1705 if (packet->stream_index >= 0 && | 1710 if (packet->stream_index >= 0 && |
1706 packet->stream_index < static_cast<int>(streams_.size()) && | 1711 packet->stream_index < static_cast<int>(streams_.size()) && |
1707 streams_[packet->stream_index]) { | 1712 streams_[packet->stream_index]) { |
1708 // TODO(scherkus): Fix demuxing upstream to never return packets w/o data | 1713 // TODO(scherkus): Fix demuxing upstream to never return packets w/o data |
1709 // when av_read_frame() returns success code. See bug comment for ideas: | 1714 // when av_read_frame() returns success code. See bug comment for ideas: |
1710 // | 1715 // |
1711 // https://code.google.com/p/chromium/issues/detail?id=169133#c10 | 1716 // https://code.google.com/p/chromium/issues/detail?id=169133#c10 |
1712 if (!packet->data) { | 1717 if (!packet->data) { |
1713 ScopedAVPacket new_packet(new AVPacket()); | 1718 ScopedAVPacket new_packet(new AVPacket()); |
1714 av_new_packet(new_packet.get(), 0); | 1719 av_new_packet(new_packet.get(), 0); |
1715 av_packet_copy_props(new_packet.get(), packet.get()); | 1720 av_packet_copy_props(new_packet.get(), packet.get()); |
1716 packet.swap(new_packet); | 1721 packet.swap(new_packet); |
1717 } | 1722 } |
1718 | 1723 |
1719 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index].get(); | 1724 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index].get(); |
1720 if (demuxer_stream->enabled()) | 1725 if (demuxer_stream->enabled()) |
1721 demuxer_stream->EnqueuePacket(std::move(packet)); | 1726 demuxer_stream->EnqueuePacket(std::move(packet)); |
1727 | |
1728 // If duration estimate was incorrect, update it and tell higher layers. | |
1729 if (duration_known_) { | |
1730 const base::TimeDelta duration = demuxer_stream->duration(); | |
1731 if (duration != kNoTimestamp && duration > duration_) { | |
1732 duration_ = duration; | |
1733 host_->SetDuration(duration_); | |
1734 } | |
1735 } | |
1722 } | 1736 } |
1723 | 1737 |
1724 // Keep reading until we've reached capacity. | 1738 // Keep reading until we've reached capacity. |
1725 ReadFrameIfNeeded(); | 1739 ReadFrameIfNeeded(); |
1726 } | 1740 } |
1727 | 1741 |
1728 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() { | 1742 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() { |
1729 DCHECK(task_runner_->BelongsToCurrentThread()); | 1743 DCHECK(task_runner_->BelongsToCurrentThread()); |
1730 for (const auto& stream : streams_) { | 1744 for (const auto& stream : streams_) { |
1731 if (stream && stream->HasAvailableCapacity()) | 1745 if (stream && stream->HasAvailableCapacity()) |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1768 | 1782 |
1769 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { | 1783 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { |
1770 DCHECK(task_runner_->BelongsToCurrentThread()); | 1784 DCHECK(task_runner_->BelongsToCurrentThread()); |
1771 for (const auto& stream : streams_) { | 1785 for (const auto& stream : streams_) { |
1772 if (stream) | 1786 if (stream) |
1773 stream->SetLiveness(liveness); | 1787 stream->SetLiveness(liveness); |
1774 } | 1788 } |
1775 } | 1789 } |
1776 | 1790 |
1777 } // namespace media | 1791 } // namespace media |
OLD | NEW |