Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: media/filters/ffmpeg_demuxer.cc

Issue 2645953004: Update duration when demuxed packets exceed known duration. (Closed)
Patch Set: Remove broken CGI server. Rate limit duration changed events. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698