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

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

Issue 2855373002: Use ffmpeg packet.pos for restarting reading after reenabling video
Patch Set: reset pending_seek_position_ after calling the pending_seek_cb_ Created 3 years, 7 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 #include "media/media_features.h" 44 #include "media/media_features.h"
45 45
46 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) 46 #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
47 #include "media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.h" 47 #include "media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.h"
48 #endif 48 #endif
49 49
50 namespace media { 50 namespace media {
51 51
52 namespace { 52 namespace {
53 53
54 // Try to have two second's worth of encoded data per stream.
55 const base::TimeDelta kDefaultStreamCapacity = base::TimeDelta::FromSeconds(2);
DaleCurtis 2017/05/24 22:24:17 constexpr or this is a static initializer.
servolk 2017/05/24 22:58:19 Done.
56
54 void SetAVStreamDiscard(AVStream* stream, AVDiscard discard) { 57 void SetAVStreamDiscard(AVStream* stream, AVDiscard discard) {
55 DCHECK(stream); 58 DCHECK(stream);
56 stream->discard = discard; 59 stream->discard = discard;
57 } 60 }
58 61
59 } // namespace 62 } // namespace
60 63
61 static base::Time ExtractTimelineOffset( 64 static base::Time ExtractTimelineOffset(
62 container_names::MediaContainerName container, 65 container_names::MediaContainerName container,
63 const AVFormatContext* format_context) { 66 const AVFormatContext* format_context) {
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 media_log_(media_log), 298 media_log_(media_log),
296 type_(UNKNOWN), 299 type_(UNKNOWN),
297 liveness_(LIVENESS_UNKNOWN), 300 liveness_(LIVENESS_UNKNOWN),
298 end_of_stream_(false), 301 end_of_stream_(false),
299 last_packet_timestamp_(kNoTimestamp), 302 last_packet_timestamp_(kNoTimestamp),
300 last_packet_duration_(kNoTimestamp), 303 last_packet_duration_(kNoTimestamp),
301 video_rotation_(VIDEO_ROTATION_0), 304 video_rotation_(VIDEO_ROTATION_0),
302 is_enabled_(true), 305 is_enabled_(true),
303 waiting_for_keyframe_(false), 306 waiting_for_keyframe_(false),
304 aborted_(false), 307 aborted_(false),
305 fixup_negative_timestamps_(false) { 308 fixup_negative_timestamps_(false),
309 stream_capacity_(kDefaultStreamCapacity) {
306 DCHECK(demuxer_); 310 DCHECK(demuxer_);
307 311
308 bool is_encrypted = false; 312 bool is_encrypted = false;
309 int rotation = 0; 313 int rotation = 0;
310 AVDictionaryEntry* rotation_entry = NULL; 314 AVDictionaryEntry* rotation_entry = NULL;
311 315
312 // Determine our media format. 316 // Determine our media format.
313 switch (stream->codecpar->codec_type) { 317 switch (stream->codecpar->codec_type) {
314 case AVMEDIA_TYPE_AUDIO: 318 case AVMEDIA_TYPE_AUDIO:
315 DCHECK(audio_config_.get() && !video_config_.get()); 319 DCHECK(audio_config_.get() && !video_config_.get());
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 } 808 }
805 } 809 }
806 810
807 // Have capacity? Ask for more! 811 // Have capacity? Ask for more!
808 if (HasAvailableCapacity() && !end_of_stream_) { 812 if (HasAvailableCapacity() && !end_of_stream_) {
809 demuxer_->NotifyCapacityAvailable(); 813 demuxer_->NotifyCapacityAvailable();
810 } 814 }
811 } 815 }
812 816
813 bool FFmpegDemuxerStream::HasAvailableCapacity() { 817 bool FFmpegDemuxerStream::HasAvailableCapacity() {
814 // Try to have two second's worth of encoded data per stream. 818 return buffer_queue_.IsEmpty() || buffer_queue_.Duration() < stream_capacity_;
815 const base::TimeDelta kCapacity = base::TimeDelta::FromSeconds(2);
816 return buffer_queue_.IsEmpty() || buffer_queue_.Duration() < kCapacity;
817 } 819 }
818 820
819 size_t FFmpegDemuxerStream::MemoryUsage() const { 821 size_t FFmpegDemuxerStream::MemoryUsage() const {
820 return buffer_queue_.data_size(); 822 return buffer_queue_.data_size();
821 } 823 }
822 824
823 TextKind FFmpegDemuxerStream::GetTextKind() const { 825 TextKind FFmpegDemuxerStream::GetTextKind() const {
824 DCHECK_EQ(type_, DemuxerStream::TEXT); 826 DCHECK_EQ(type_, DemuxerStream::TEXT);
825 827
826 if (stream_->disposition & AV_DISPOSITION_CAPTIONS) 828 if (stream_->disposition & AV_DISPOSITION_CAPTIONS)
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 : host_(NULL), 865 : host_(NULL),
864 task_runner_(task_runner), 866 task_runner_(task_runner),
865 // FFmpeg has no asynchronous API, so we use base::WaitableEvents inside 867 // FFmpeg has no asynchronous API, so we use base::WaitableEvents inside
866 // the BlockingUrlProtocol to handle hops to the render thread for network 868 // the BlockingUrlProtocol to handle hops to the render thread for network
867 // reads and seeks. 869 // reads and seeks.
868 blocking_task_runner_(base::CreateSequencedTaskRunnerWithTraits( 870 blocking_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
869 {base::MayBlock(), base::WithBaseSyncPrimitives(), 871 {base::MayBlock(), base::WithBaseSyncPrimitives(),
870 base::TaskPriority::USER_BLOCKING})), 872 base::TaskPriority::USER_BLOCKING})),
871 stopped_(false), 873 stopped_(false),
872 pending_read_(false), 874 pending_read_(false),
875 pending_seek_position_(kNoTimestamp),
873 data_source_(data_source), 876 data_source_(data_source),
874 media_log_(media_log), 877 media_log_(media_log),
875 bitrate_(0), 878 bitrate_(0),
876 start_time_(kNoTimestamp), 879 start_time_(kNoTimestamp),
877 text_enabled_(false), 880 text_enabled_(false),
878 duration_known_(false), 881 duration_known_(false),
879 encrypted_media_init_data_cb_(encrypted_media_init_data_cb), 882 encrypted_media_init_data_cb_(encrypted_media_init_data_cb),
880 media_tracks_updated_cb_(media_tracks_updated_cb), 883 media_tracks_updated_cb_(media_tracks_updated_cb),
884 last_audio_packet_pos_(-1),
885 restarting_stream_(nullptr),
881 cancel_pending_seek_factory_(this), 886 cancel_pending_seek_factory_(this),
882 weak_factory_(this) { 887 weak_factory_(this) {
883 DCHECK(task_runner_.get()); 888 DCHECK(task_runner_.get());
884 DCHECK(data_source_); 889 DCHECK(data_source_);
885 DCHECK(!media_tracks_updated_cb_.is_null()); 890 DCHECK(!media_tracks_updated_cb_.is_null());
886 } 891 }
887 892
888 FFmpegDemuxer::~FFmpegDemuxer() { 893 FFmpegDemuxer::~FFmpegDemuxer() {
889 // NOTE: This class is not destroyed on |task_runner|, so we must ensure that 894 // NOTE: This class is not destroyed on |task_runner|, so we must ensure that
890 // there are no outstanding WeakPtrs by the time we reach here. 895 // there are no outstanding WeakPtrs by the time we reach here.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
961 blocking_task_runner_->PostTask( 966 blocking_task_runner_->PostTask(
962 FROM_HERE, 967 FROM_HERE,
963 base::Bind(&UnmarkEndOfStreamAndClearError, glue_->format_context())); 968 base::Bind(&UnmarkEndOfStreamAndClearError, glue_->format_context()));
964 pending_read_ = false; 969 pending_read_ = false;
965 970
966 // TODO(dalecurtis): We probably should report PIPELINE_ERROR_ABORT here 971 // TODO(dalecurtis): We probably should report PIPELINE_ERROR_ABORT here
967 // instead to avoid any preroll work that may be started upon return, but 972 // instead to avoid any preroll work that may be started upon return, but
968 // currently the PipelineImpl does not know how to handle this. 973 // currently the PipelineImpl does not know how to handle this.
969 if (!pending_seek_cb_.is_null()) 974 if (!pending_seek_cb_.is_null())
970 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_OK); 975 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_OK);
976 pending_seek_position_ = kNoTimestamp;
971 } 977 }
972 978
973 void FFmpegDemuxer::Stop() { 979 void FFmpegDemuxer::Stop() {
974 DCHECK(task_runner_->BelongsToCurrentThread()); 980 DCHECK(task_runner_->BelongsToCurrentThread());
975 981
976 // The order of Stop() and Abort() is important here. If Abort() is called 982 // The order of Stop() and Abort() is important here. If Abort() is called
977 // first, control may pass into FFmpeg where it can destruct buffers that are 983 // first, control may pass into FFmpeg where it can destruct buffers that are
978 // in the process of being fulfilled by the DataSource. 984 // in the process of being fulfilled by the DataSource.
979 data_source_->Stop(); 985 data_source_->Stop();
980 url_protocol_->Abort(); 986 url_protocol_->Abort();
(...skipping 21 matching lines...) Expand all
1002 } else { 1008 } else {
1003 // Don't use GetWeakPtr() here since we are on the wrong thread. 1009 // Don't use GetWeakPtr() here since we are on the wrong thread.
1004 task_runner_->PostTask( 1010 task_runner_->PostTask(
1005 FROM_HERE, base::Bind(&FFmpegDemuxer::AbortPendingReads, weak_this_)); 1011 FROM_HERE, base::Bind(&FFmpegDemuxer::AbortPendingReads, weak_this_));
1006 } 1012 }
1007 } 1013 }
1008 1014
1009 void FFmpegDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) { 1015 void FFmpegDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) {
1010 DCHECK(task_runner_->BelongsToCurrentThread()); 1016 DCHECK(task_runner_->BelongsToCurrentThread());
1011 CHECK(pending_seek_cb_.is_null()); 1017 CHECK(pending_seek_cb_.is_null());
1018 DCHECK_EQ(pending_seek_position_, kNoTimestamp);
1019 pending_seek_cb_ = cb;
1020 pending_seek_position_ = time;
1012 1021
1013 // FFmpeg requires seeks to be adjusted according to the lowest starting time. 1022 SeekInternal(
1014 // Since EnqueuePacket() rebased negative timestamps by the start time, we 1023 time, nullptr,
1015 // must correct the shift here.
1016 //
1017 // Additionally, to workaround limitations in how we expose seekable ranges to
1018 // Blink (http://crbug.com/137275), we also want to clamp seeks before the
1019 // start time to the start time.
1020 base::TimeDelta seek_time = start_time_ < base::TimeDelta()
1021 ? time + start_time_
1022 : time < start_time_ ? start_time_ : time;
1023
1024 // When seeking in an opus stream we need to ensure we deliver enough data to
1025 // satisfy the seek preroll; otherwise the audio at the actual seek time will
1026 // not be entirely accurate.
1027 FFmpegDemuxerStream* audio_stream =
1028 GetFirstEnabledFFmpegStream(DemuxerStream::AUDIO);
1029 if (audio_stream) {
1030 const AudioDecoderConfig& config = audio_stream->audio_decoder_config();
1031 if (config.codec() == kCodecOpus)
1032 seek_time = std::max(start_time_, seek_time - config.seek_preroll());
1033 }
1034
1035 // Choose the seeking stream based on whether it contains the seek time, if no
1036 // match can be found prefer the preferred stream.
1037 //
1038 // TODO(dalecurtis): Currently FFmpeg does not ensure that all streams in a
1039 // given container will demux all packets after the seek point. Instead it
1040 // only guarantees that all packets after the file position of the seek will
1041 // be demuxed. It's an open question whether FFmpeg should fix this:
1042 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html
1043 // Tracked by http://crbug.com/387996.
1044 FFmpegDemuxerStream* demux_stream = FindPreferredStreamForSeeking(seek_time);
1045 DCHECK(demux_stream);
1046 const AVStream* seeking_stream = demux_stream->av_stream();
1047 DCHECK(seeking_stream);
1048
1049 pending_seek_cb_ = cb;
1050 base::PostTaskAndReplyWithResult(
1051 blocking_task_runner_.get(), FROM_HERE,
1052 base::Bind(&av_seek_frame, glue_->format_context(), seeking_stream->index,
1053 ConvertToTimeBase(seeking_stream->time_base, seek_time),
1054 // Always seek to a timestamp <= to the desired timestamp.
1055 AVSEEK_FLAG_BACKWARD),
1056 base::Bind(&FFmpegDemuxer::OnSeekFrameDone, weak_factory_.GetWeakPtr())); 1024 base::Bind(&FFmpegDemuxer::OnSeekFrameDone, weak_factory_.GetWeakPtr()));
1057 } 1025 }
1058 1026
1059 base::Time FFmpegDemuxer::GetTimelineOffset() const { 1027 base::Time FFmpegDemuxer::GetTimelineOffset() const {
1060 return timeline_offset_; 1028 return timeline_offset_;
1061 } 1029 }
1062 1030
1063 std::vector<DemuxerStream*> FFmpegDemuxer::GetAllStreams() { 1031 std::vector<DemuxerStream*> FFmpegDemuxer::GetAllStreams() {
1064 DCHECK(task_runner_->BelongsToCurrentThread()); 1032 DCHECK(task_runner_->BelongsToCurrentThread());
1065 std::vector<DemuxerStream*> result; 1033 std::vector<DemuxerStream*> result;
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after
1652 return nullptr; 1620 return nullptr;
1653 } 1621 }
1654 1622
1655 void FFmpegDemuxer::OnSeekFrameDone(int result) { 1623 void FFmpegDemuxer::OnSeekFrameDone(int result) {
1656 DCHECK(task_runner_->BelongsToCurrentThread()); 1624 DCHECK(task_runner_->BelongsToCurrentThread());
1657 CHECK(!pending_seek_cb_.is_null()); 1625 CHECK(!pending_seek_cb_.is_null());
1658 1626
1659 if (stopped_) { 1627 if (stopped_) {
1660 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state"; 1628 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
1661 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_ERROR_ABORT); 1629 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_ERROR_ABORT);
1630 pending_seek_position_ = kNoTimestamp;
1662 return; 1631 return;
1663 } 1632 }
1664 1633
1665 if (result < 0) { 1634 if (result < 0) {
1666 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being 1635 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being
1667 // captured from stdout and contaminates testing. 1636 // captured from stdout and contaminates testing.
1668 // TODO(scherkus): Implement this properly and signal error (BUG=23447). 1637 // TODO(scherkus): Implement this properly and signal error (BUG=23447).
1669 VLOG(1) << "Not implemented"; 1638 VLOG(1) << "Not implemented";
1670 } 1639 }
1671 1640
1641 // If we had been restarting the video stream, we can cancel that now, because
DaleCurtis 2017/05/25 00:08:06 I think this isn't true since you don't know how f
1642 // we'll just restart reading it automatically from the new position after
1643 // this new seek request is completed.
1644 if (restarting_stream_) {
1645 DVLOG(2) << "Cancelled stream restart due to intervening seek";
1646 restarting_stream_ = nullptr;
1647 }
1648 last_audio_packet_pos_ = -1;
1649
1672 // Tell streams to flush buffers due to seeking. 1650 // Tell streams to flush buffers due to seeking.
1673 for (const auto& stream : streams_) { 1651 for (const auto& stream : streams_) {
1674 if (stream) 1652 if (stream)
1675 stream->FlushBuffers(); 1653 stream->FlushBuffers();
1676 } 1654 }
1677 1655
1678 // Resume reading until capacity. 1656 // Resume reading until capacity.
1679 ReadFrameIfNeeded(); 1657 ReadFrameIfNeeded();
1680 1658
1681 // Notify we're finished seeking. 1659 // Notify we're finished seeking.
1682 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_OK); 1660 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_OK);
1661 pending_seek_position_ = kNoTimestamp;
1683 } 1662 }
1684 1663
1685 void FFmpegDemuxer::OnEnabledAudioTracksChanged( 1664 void FFmpegDemuxer::OnEnabledAudioTracksChanged(
1686 const std::vector<MediaTrack::Id>& track_ids, 1665 const std::vector<MediaTrack::Id>& track_ids,
1687 base::TimeDelta curr_time) { 1666 base::TimeDelta curr_time) {
1688 DCHECK(task_runner_->BelongsToCurrentThread()); 1667 DCHECK(task_runner_->BelongsToCurrentThread());
1689 1668
1690 std::set<FFmpegDemuxerStream*> enabled_streams; 1669 std::set<FFmpegDemuxerStream*> enabled_streams;
1691 for (const auto& id : track_ids) { 1670 for (const auto& id : track_ids) {
1692 FFmpegDemuxerStream* stream = track_id_to_demux_stream_map_[id]; 1671 FFmpegDemuxerStream* stream = track_id_to_demux_stream_map_[id];
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1735 for (const auto& stream : streams_) { 1714 for (const auto& stream : streams_) {
1736 if (stream && stream->type() == DemuxerStream::VIDEO && 1715 if (stream && stream->type() == DemuxerStream::VIDEO &&
1737 stream.get() != selected_stream) { 1716 stream.get() != selected_stream) {
1738 DVLOG(1) << __func__ << ": disabling stream " << stream.get(); 1717 DVLOG(1) << __func__ << ": disabling stream " << stream.get();
1739 stream->SetEnabled(false, curr_time); 1718 stream->SetEnabled(false, curr_time);
1740 } 1719 }
1741 } 1720 }
1742 if (selected_stream) { 1721 if (selected_stream) {
1743 DVLOG(1) << __func__ << ": enabling stream " << selected_stream; 1722 DVLOG(1) << __func__ << ": enabling stream " << selected_stream;
1744 selected_stream->SetEnabled(true, curr_time); 1723 selected_stream->SetEnabled(true, curr_time);
1724 // Now that the video stream is re-enabled we'll want video renderer to
1725 // restart playback from the |curr_time| position. For that we'll need to
1726 // seek back to the last key frame preceeding |curr_time| in the
1727 // |selected_stream|.
1728 if (!pending_seek_cb_) {
1729 selected_stream->FlushBuffers();
1730 SeekInternal(curr_time, selected_stream,
1731 base::Bind(&FFmpegDemuxer::OnSeekDoneForRestartingStream,
1732 weak_factory_.GetWeakPtr(), selected_stream));
1733 } else {
DaleCurtis 2017/05/24 22:24:18 Lets avoid this whole issue by just not allowing t
servolk 2017/05/24 22:58:19 Sure, if we didn't allow track changes during pend
DaleCurtis 2017/05/24 23:15:46 We're not talking about prohibiting them, we're ta
1734 // If there's already pending seek, we'll need to restart it after its
1735 // completion and after SetAVStreamDiscard initiated by SetEnabled takes
1736 // effect, in order to ensure we get a key frame for |selected_stream|.
1737 auto old_pending_seek_cb = pending_seek_cb_;
1738 DCHECK_NE(pending_seek_position_, kNoTimestamp);
1739 DVLOG(2) << __func__ << ": Pending seek to " << pending_seek_position_
1740 << " detected, postponing stream restart until seek completes.";
1741 pending_seek_cb_ = base::Bind(
1742 &FFmpegDemuxer::RestartPendingSeek, weak_factory_.GetWeakPtr(),
1743 pending_seek_position_, old_pending_seek_cb);
1744 }
1745 } 1745 }
1746 } 1746 }
1747 1747
1748 void FFmpegDemuxer::OnSeekDoneForRestartingStream(FFmpegDemuxerStream* stream,
1749 int result) {
1750 DCHECK(task_runner_->BelongsToCurrentThread());
1751 if (result < 0) {
1752 MEDIA_LOG(ERROR, media_log_)
1753 << __func__ << ": seek failed: " << AVErrorToString(result);
1754 return;
1755 }
1756 DVLOG(2) << __func__ << ": will drop packets until last_audio_packet_pos_="
1757 << last_audio_packet_pos_;
1758 if (restarting_stream_)
DaleCurtis 2017/05/25 00:08:06 This will need an early exit if a seek() comes in
1759 restarting_stream_->FlushBuffers();
1760 restarting_stream_ = stream;
1761 }
1762
1748 void FFmpegDemuxer::ReadFrameIfNeeded() { 1763 void FFmpegDemuxer::ReadFrameIfNeeded() {
1749 DCHECK(task_runner_->BelongsToCurrentThread()); 1764 DCHECK(task_runner_->BelongsToCurrentThread());
1750 1765
1751 // Make sure we have work to do before reading. 1766 // Make sure we have work to do before reading.
1752 if (stopped_ || !StreamsHaveAvailableCapacity() || pending_read_ || 1767 if (stopped_ || !StreamsHaveAvailableCapacity() || pending_read_ ||
1753 !pending_seek_cb_.is_null()) { 1768 !pending_seek_cb_.is_null()) {
1754 return; 1769 return;
1755 } 1770 }
1756 1771
1757 // Allocate and read an AVPacket from the media. Save |packet_ptr| since 1772 // Allocate and read an AVPacket from the media. Save |packet_ptr| since
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1822 // 1837 //
1823 // https://code.google.com/p/chromium/issues/detail?id=169133#c10 1838 // https://code.google.com/p/chromium/issues/detail?id=169133#c10
1824 if (!packet->data) { 1839 if (!packet->data) {
1825 ScopedAVPacket new_packet(new AVPacket()); 1840 ScopedAVPacket new_packet(new AVPacket());
1826 av_new_packet(new_packet.get(), 0); 1841 av_new_packet(new_packet.get(), 0);
1827 av_packet_copy_props(new_packet.get(), packet.get()); 1842 av_packet_copy_props(new_packet.get(), packet.get());
1828 packet.swap(new_packet); 1843 packet.swap(new_packet);
1829 } 1844 }
1830 1845
1831 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index].get(); 1846 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index].get();
1832 if (demuxer_stream->IsEnabled()) 1847
1848 DVLOG(5) << "Got AVPacket: stream_index=" << packet->stream_index
1849 << " type=" << demuxer_stream->type() << " pos=" << packet->pos
1850 << " pts=" << packet->pts;
1851
1852 // If |restarting_stream_| is not null, we are in stream restart mode, which
1853 // means we seeked back the ffmpeg reading position and now we need to drop
1854 // packets from other streams until we reach the previously seen read
1855 // position |last_audio_packet_pos_|.
1856 bool drop_seen_packet =
1857 restarting_stream_ && demuxer_stream != restarting_stream_ &&
1858 last_audio_packet_pos_ >= 0 && packet->pos <= last_audio_packet_pos_;
1859 if (drop_seen_packet) {
1860 DVLOG(4) << "Dropping already seen packet packet: pos=" << packet->pos;
1861 } else if (restarting_stream_ && demuxer_stream != restarting_stream_) {
1862 DVLOG(2) << "Restarting reading packets: pos=" << packet->pos;
1863 restarting_stream_ = nullptr;
1864 }
1865
1866 if (!restarting_stream_ && demuxer_stream->type() == DemuxerStream::AUDIO)
DaleCurtis 2017/05/24 22:24:18 Isn't this going to be incorrect for streams with
1867 last_audio_packet_pos_ = packet->pos;
1868
1869 if (demuxer_stream->IsEnabled() && !drop_seen_packet)
1833 demuxer_stream->EnqueuePacket(std::move(packet)); 1870 demuxer_stream->EnqueuePacket(std::move(packet));
1834 1871
1835 // If duration estimate was incorrect, update it and tell higher layers. 1872 // If duration estimate was incorrect, update it and tell higher layers.
1836 if (duration_known_) { 1873 if (duration_known_) {
1837 const base::TimeDelta duration = demuxer_stream->duration(); 1874 const base::TimeDelta duration = demuxer_stream->duration();
1838 if (duration != kNoTimestamp && duration > duration_) { 1875 if (duration != kNoTimestamp && duration > duration_) {
1839 duration_ = duration; 1876 duration_ = duration;
1840 host_->SetDuration(duration_); 1877 host_->SetDuration(duration_);
1841 } 1878 }
1842 } 1879 }
1843 } 1880 }
1844 1881
1845 // Keep reading until we've reached capacity. 1882 // Keep reading until we've reached capacity.
1846 ReadFrameIfNeeded(); 1883 ReadFrameIfNeeded();
1847 } 1884 }
1848 1885
1849 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() { 1886 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() {
1850 DCHECK(task_runner_->BelongsToCurrentThread()); 1887 DCHECK(task_runner_->BelongsToCurrentThread());
1851 for (const auto& stream : streams_) { 1888 for (const auto& stream : streams_) {
1852 if (stream && stream->HasAvailableCapacity()) 1889 if (stream && stream->IsEnabled() && stream->HasAvailableCapacity())
1853 return true; 1890 return true;
1854 } 1891 }
1855 return false; 1892 return false;
1856 } 1893 }
1857 1894
1858 bool FFmpegDemuxer::IsMaxMemoryUsageReached() const { 1895 bool FFmpegDemuxer::IsMaxMemoryUsageReached() const {
1859 DCHECK(task_runner_->BelongsToCurrentThread()); 1896 DCHECK(task_runner_->BelongsToCurrentThread());
1860 1897
1861 // Max allowed memory usage, all streams combined. 1898 // Max allowed memory usage, all streams combined.
1862 const size_t kDemuxerMemoryLimit = 150 * 1024 * 1024; 1899 const size_t kDemuxerMemoryLimit = 150 * 1024 * 1024;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1894 } 1931 }
1895 1932
1896 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { 1933 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) {
1897 DCHECK(task_runner_->BelongsToCurrentThread()); 1934 DCHECK(task_runner_->BelongsToCurrentThread());
1898 for (const auto& stream : streams_) { 1935 for (const auto& stream : streams_) {
1899 if (stream) 1936 if (stream)
1900 stream->SetLiveness(liveness); 1937 stream->SetLiveness(liveness);
1901 } 1938 }
1902 } 1939 }
1903 1940
1941 void FFmpegDemuxer::SeekInternal(base::TimeDelta time,
1942 FFmpegDemuxerStream* preferred_stream,
1943 const FFmpegSeekDoneCB& ffmpeg_seek_done_cb) {
1944 DCHECK(task_runner_->BelongsToCurrentThread());
1945 DVLOG(2) << __func__ << " time=" << time << " stream=" << preferred_stream;
1946
1947 // FFmpeg requires seeks to be adjusted according to the lowest starting time.
1948 // Since EnqueuePacket() rebased negative timestamps by the start time, we
1949 // must correct the shift here.
1950 //
1951 // Additionally, to workaround limitations in how we expose seekable ranges to
1952 // Blink (http://crbug.com/137275), we also want to clamp seeks before the
1953 // start time to the start time.
1954 base::TimeDelta seek_time = start_time_ < base::TimeDelta()
1955 ? time + start_time_
1956 : time < start_time_ ? start_time_ : time;
1957
1958 // When seeking in an opus stream we need to ensure we deliver enough data to
1959 // satisfy the seek preroll; otherwise the audio at the actual seek time will
1960 // not be entirely accurate.
1961 FFmpegDemuxerStream* audio_stream =
1962 GetFirstEnabledFFmpegStream(DemuxerStream::AUDIO);
1963 if (audio_stream) {
1964 const AudioDecoderConfig& config = audio_stream->audio_decoder_config();
1965 if (config.codec() == kCodecOpus)
1966 seek_time = std::max(start_time_, seek_time - config.seek_preroll());
1967 }
1968
1969 if (!preferred_stream) {
1970 // Choose the seeking stream based on whether it contains the seek time, if
1971 // no match can be found prefer the preferred stream.
1972 //
1973 // TODO(dalecurtis): Currently FFmpeg does not ensure that all streams in a
DaleCurtis 2017/05/24 22:24:18 Note we may run into this issue now more frequentl
servolk 2017/05/24 22:58:19 We might, especially considering that this is goin
DaleCurtis 2017/05/25 00:08:06 I don't think that API fixes the issue. I experime
1974 // given container will demux all packets after the seek point. Instead it
1975 // only guarantees that all packets after the file position of the seek will
1976 // be demuxed. It's an open question whether FFmpeg should fix this:
1977 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html
1978 // Tracked by http://crbug.com/387996.
1979 preferred_stream = FindPreferredStreamForSeeking(seek_time);
1980 DCHECK(preferred_stream);
1981 }
1982 const AVStream* ffmpeg_stream = preferred_stream->av_stream();
1983 DCHECK(ffmpeg_stream);
1984
1985 base::PostTaskAndReplyWithResult(
1986 blocking_task_runner_.get(), FROM_HERE,
1987 base::Bind(&av_seek_frame, glue_->format_context(), ffmpeg_stream->index,
1988 ConvertToTimeBase(ffmpeg_stream->time_base, seek_time),
1989 // Always seek to a timestamp <= to the desired timestamp.
1990 AVSEEK_FLAG_BACKWARD),
1991 ffmpeg_seek_done_cb);
1992 }
1993
1994 void FFmpegDemuxer::RestartPendingSeek(base::TimeDelta time,
1995 const PipelineStatusCB& cb,
1996 PipelineStatus prev_seek_status) {
1997 DCHECK(task_runner_->BelongsToCurrentThread());
1998 DCHECK_NE(pending_seek_position_, kNoTimestamp);
1999 DCHECK(cb);
2000 // We are going to ignore prev_seek_status here, because we are about to
2001 // repeat the seek anyway. The previous seek outcome doesn't matter now.
2002 DVLOG(2) << __func__ << ": Previous seek completed, re-seeking to "
2003 << pending_seek_position_ << " to complete video stream restart.";
2004 base::ResetAndReturn(&pending_seek_cb_);
2005 pending_seek_position_ = kNoTimestamp;
2006 Seek(time, cb);
2007 }
2008
1904 } // namespace media 2009 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698