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

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

Issue 2855373002: Use ffmpeg packet.pos for restarting reading after reenabling video
Patch Set: fixed audio rewinding 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
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 849 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 stopped_(false), 860 stopped_(false),
861 pending_read_(false), 861 pending_read_(false),
862 data_source_(data_source), 862 data_source_(data_source),
863 media_log_(media_log), 863 media_log_(media_log),
864 bitrate_(0), 864 bitrate_(0),
865 start_time_(kNoTimestamp), 865 start_time_(kNoTimestamp),
866 text_enabled_(false), 866 text_enabled_(false),
867 duration_known_(false), 867 duration_known_(false),
868 encrypted_media_init_data_cb_(encrypted_media_init_data_cb), 868 encrypted_media_init_data_cb_(encrypted_media_init_data_cb),
869 media_tracks_updated_cb_(media_tracks_updated_cb), 869 media_tracks_updated_cb_(media_tracks_updated_cb),
870 last_packet_pos_(-1),
871 restarting_stream_(nullptr),
870 cancel_pending_seek_factory_(this), 872 cancel_pending_seek_factory_(this),
871 weak_factory_(this) { 873 weak_factory_(this) {
872 DCHECK(task_runner_.get()); 874 DCHECK(task_runner_.get());
873 DCHECK(data_source_); 875 DCHECK(data_source_);
874 DCHECK(!media_tracks_updated_cb_.is_null()); 876 DCHECK(!media_tracks_updated_cb_.is_null());
875 } 877 }
876 878
877 FFmpegDemuxer::~FFmpegDemuxer() { 879 FFmpegDemuxer::~FFmpegDemuxer() {
878 // NOTE: This class is not destroyed on |task_runner|, so we must ensure that 880 // NOTE: This class is not destroyed on |task_runner|, so we must ensure that
879 // there are no outstanding WeakPtrs by the time we reach here. 881 // there are no outstanding WeakPtrs by the time we reach here.
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after
1648 return; 1650 return;
1649 } 1651 }
1650 1652
1651 if (result < 0) { 1653 if (result < 0) {
1652 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being 1654 // Use VLOG(1) instead of NOTIMPLEMENTED() to prevent the message being
1653 // captured from stdout and contaminates testing. 1655 // captured from stdout and contaminates testing.
1654 // TODO(scherkus): Implement this properly and signal error (BUG=23447). 1656 // TODO(scherkus): Implement this properly and signal error (BUG=23447).
1655 VLOG(1) << "Not implemented"; 1657 VLOG(1) << "Not implemented";
1656 } 1658 }
1657 1659
1660 last_packet_pos_ = -1;
1661
1658 // Tell streams to flush buffers due to seeking. 1662 // Tell streams to flush buffers due to seeking.
1659 for (const auto& stream : streams_) { 1663 for (const auto& stream : streams_) {
1660 if (stream) 1664 if (stream)
1661 stream->FlushBuffers(); 1665 stream->FlushBuffers();
1662 } 1666 }
1663 1667
1664 // Resume reading until capacity. 1668 // Resume reading until capacity.
1665 ReadFrameIfNeeded(); 1669 ReadFrameIfNeeded();
1666 1670
1667 // Notify we're finished seeking. 1671 // Notify we're finished seeking.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1721 for (const auto& stream : streams_) { 1725 for (const auto& stream : streams_) {
1722 if (stream && stream->type() == DemuxerStream::VIDEO && 1726 if (stream && stream->type() == DemuxerStream::VIDEO &&
1723 stream.get() != selected_stream) { 1727 stream.get() != selected_stream) {
1724 DVLOG(1) << __func__ << ": disabling stream " << stream.get(); 1728 DVLOG(1) << __func__ << ": disabling stream " << stream.get();
1725 stream->SetEnabled(false, curr_time); 1729 stream->SetEnabled(false, curr_time);
1726 } 1730 }
1727 } 1731 }
1728 if (selected_stream) { 1732 if (selected_stream) {
1729 DVLOG(1) << __func__ << ": enabling stream " << selected_stream; 1733 DVLOG(1) << __func__ << ": enabling stream " << selected_stream;
1730 selected_stream->SetEnabled(true, curr_time); 1734 selected_stream->SetEnabled(true, curr_time);
1735 selected_stream->FlushBuffers();
1736
1737 base::TimeDelta seek_time =
DaleCurtis 2017/05/04 18:53:03 Extract common code from Seek() and put in an inte
servolk 2017/05/04 19:15:16 Will do.
servolk 2017/05/04 22:13:16 Done (I've extracted most of the common seeking lo
1738 start_time_ < base::TimeDelta()
1739 ? curr_time + start_time_
1740 : curr_time < start_time_ ? start_time_ : curr_time;
1741
1742 base::PostTaskAndReplyWithResult(
1743 blocking_task_runner_.get(), FROM_HERE,
1744 base::Bind(&av_seek_frame, glue_->format_context(),
1745 selected_stream->av_stream()->index,
1746 ConvertToTimeBase(selected_stream->av_stream()->time_base,
1747 seek_time),
1748 // Always seek to a timestamp <= to the desired timestamp.
1749 AVSEEK_FLAG_BACKWARD),
1750 base::Bind(&FFmpegDemuxer::OnSeekDoneForRestartingStream,
1751 weak_factory_.GetWeakPtr(), selected_stream));
1731 } 1752 }
1732 } 1753 }
1733 1754
1755 void FFmpegDemuxer::OnSeekDoneForRestartingStream(FFmpegDemuxerStream* stream,
1756 int result) {
1757 DCHECK(task_runner_->BelongsToCurrentThread());
1758 if (result < 0) {
1759 DVLOG(1) << __func__ << ": seek failed: " << AVErrorToString(result);
1760 return;
1761 }
1762 DVLOG(2) << __func__
1763 << ": will drop packets until last_packet_pos_=" << last_packet_pos_;
1764 restarting_stream_ = stream;
DaleCurtis 2017/05/04 18:53:03 What happens if another track is enabled and tramp
servolk 2017/05/04 19:15:16 Great question. I think it could happen, but we sh
DaleCurtis 2017/05/04 21:21:06 Isn't that wrong though? I.e. the stream we restar
servolk 2017/05/04 21:38:30 I think that's ok, because we only use this logic
DaleCurtis 2017/05/04 21:41:12 Even if we just consider audio, depending on how t
DaleCurtis 2017/05/04 21:46:12 Oh right I see what you mean, we only run the seek
1765 }
1766
1734 void FFmpegDemuxer::ReadFrameIfNeeded() { 1767 void FFmpegDemuxer::ReadFrameIfNeeded() {
1735 DCHECK(task_runner_->BelongsToCurrentThread()); 1768 DCHECK(task_runner_->BelongsToCurrentThread());
1736 1769
1737 // Make sure we have work to do before reading. 1770 // Make sure we have work to do before reading.
1738 if (stopped_ || !StreamsHaveAvailableCapacity() || pending_read_ || 1771 if (stopped_ || !StreamsHaveAvailableCapacity() || pending_read_ ||
1739 !pending_seek_cb_.is_null()) { 1772 !pending_seek_cb_.is_null()) {
1740 return; 1773 return;
1741 } 1774 }
1742 1775
1743 // Allocate and read an AVPacket from the media. Save |packet_ptr| since 1776 // Allocate and read an AVPacket from the media. Save |packet_ptr| since
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1808 // 1841 //
1809 // https://code.google.com/p/chromium/issues/detail?id=169133#c10 1842 // https://code.google.com/p/chromium/issues/detail?id=169133#c10
1810 if (!packet->data) { 1843 if (!packet->data) {
1811 ScopedAVPacket new_packet(new AVPacket()); 1844 ScopedAVPacket new_packet(new AVPacket());
1812 av_new_packet(new_packet.get(), 0); 1845 av_new_packet(new_packet.get(), 0);
1813 av_packet_copy_props(new_packet.get(), packet.get()); 1846 av_packet_copy_props(new_packet.get(), packet.get());
1814 packet.swap(new_packet); 1847 packet.swap(new_packet);
1815 } 1848 }
1816 1849
1817 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index].get(); 1850 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index].get();
1818 if (demuxer_stream->IsEnabled()) 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_packet_pos_|.
1856 bool drop_seen_packet =
DaleCurtis 2017/05/04 18:53:03 Drop unnecessary parens.
servolk 2017/05/04 19:15:16 Done.
1857 (restarting_stream_ && demuxer_stream != restarting_stream_ &&
1858 last_packet_pos_ >= 0 && packet.get()->pos <= last_packet_pos_);
DaleCurtis 2017/05/04 18:53:03 Is pos monotonically increasing? I.e. this won't b
servolk 2017/05/04 19:15:15 I don't know for sure, but I think it should be mo
1859 if (drop_seen_packet) {
1860 DVLOG(4) << "Dropping packet: pos=" << packet.get()->pos;
DaleCurtis 2017/05/04 18:53:03 "already seen packet"
servolk 2017/05/04 19:15:16 Done.
1861 } else if (restarting_stream_ && demuxer_stream != restarting_stream_) {
1862 DVLOG(2) << "Restarting reading packets: pos=" << packet.get()->pos;
1863 restarting_stream_ = nullptr;
1864 }
1865
1866 if (!restarting_stream_)
1867 last_packet_pos_ = packet.get()->pos;
1868
1869 if (demuxer_stream->IsEnabled() && !drop_seen_packet)
1819 demuxer_stream->EnqueuePacket(std::move(packet)); 1870 demuxer_stream->EnqueuePacket(std::move(packet));
1820 1871
1821 // If duration estimate was incorrect, update it and tell higher layers. 1872 // If duration estimate was incorrect, update it and tell higher layers.
1822 if (duration_known_) { 1873 if (duration_known_) {
1823 const base::TimeDelta duration = demuxer_stream->duration(); 1874 const base::TimeDelta duration = demuxer_stream->duration();
1824 if (duration != kNoTimestamp && duration > duration_) { 1875 if (duration != kNoTimestamp && duration > duration_) {
1825 duration_ = duration; 1876 duration_ = duration;
1826 host_->SetDuration(duration_); 1877 host_->SetDuration(duration_);
1827 } 1878 }
1828 } 1879 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1881 1932
1882 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { 1933 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) {
1883 DCHECK(task_runner_->BelongsToCurrentThread()); 1934 DCHECK(task_runner_->BelongsToCurrentThread());
1884 for (const auto& stream : streams_) { 1935 for (const auto& stream : streams_) {
1885 if (stream) 1936 if (stream)
1886 stream->SetLiveness(liveness); 1937 stream->SetLiveness(liveness);
1887 } 1938 }
1888 } 1939 }
1889 1940
1890 } // namespace media 1941 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698