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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/ffmpeg_demuxer.cc
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index 081bcbf1a452be23ee45adb6a080e11bd5b55c77..238c31eeb6a53c3b3cf0b3977ec91a01ec1b482a 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -867,6 +867,8 @@ FFmpegDemuxer::FFmpegDemuxer(
duration_known_(false),
encrypted_media_init_data_cb_(encrypted_media_init_data_cb),
media_tracks_updated_cb_(media_tracks_updated_cb),
+ last_packet_pos_(-1),
+ restarting_stream_(nullptr),
cancel_pending_seek_factory_(this),
weak_factory_(this) {
DCHECK(task_runner_.get());
@@ -1655,6 +1657,8 @@ void FFmpegDemuxer::OnSeekFrameDone(int result) {
VLOG(1) << "Not implemented";
}
+ last_packet_pos_ = -1;
+
// Tell streams to flush buffers due to seeking.
for (const auto& stream : streams_) {
if (stream)
@@ -1728,9 +1732,38 @@ void FFmpegDemuxer::OnSelectedVideoTrackChanged(
if (selected_stream) {
DVLOG(1) << __func__ << ": enabling stream " << selected_stream;
selected_stream->SetEnabled(true, curr_time);
+ selected_stream->FlushBuffers();
+
+ 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
+ start_time_ < base::TimeDelta()
+ ? curr_time + start_time_
+ : curr_time < start_time_ ? start_time_ : curr_time;
+
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner_.get(), FROM_HERE,
+ base::Bind(&av_seek_frame, glue_->format_context(),
+ selected_stream->av_stream()->index,
+ ConvertToTimeBase(selected_stream->av_stream()->time_base,
+ seek_time),
+ // Always seek to a timestamp <= to the desired timestamp.
+ AVSEEK_FLAG_BACKWARD),
+ base::Bind(&FFmpegDemuxer::OnSeekDoneForRestartingStream,
+ weak_factory_.GetWeakPtr(), selected_stream));
}
}
+void FFmpegDemuxer::OnSeekDoneForRestartingStream(FFmpegDemuxerStream* stream,
+ int result) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ if (result < 0) {
+ DVLOG(1) << __func__ << ": seek failed: " << AVErrorToString(result);
+ return;
+ }
+ DVLOG(2) << __func__
+ << ": will drop packets until last_packet_pos_=" << last_packet_pos_;
+ 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
+}
+
void FFmpegDemuxer::ReadFrameIfNeeded() {
DCHECK(task_runner_->BelongsToCurrentThread());
@@ -1815,7 +1848,25 @@ void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) {
}
FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index].get();
- if (demuxer_stream->IsEnabled())
+
+ // If |restarting_stream_| is not null, we are in stream restart mode, which
+ // means we seeked back the ffmpeg reading position and now we need to drop
+ // packets from other streams until we reach the previously seen read
+ // position |last_packet_pos_|.
+ bool drop_seen_packet =
DaleCurtis 2017/05/04 18:53:03 Drop unnecessary parens.
servolk 2017/05/04 19:15:16 Done.
+ (restarting_stream_ && demuxer_stream != restarting_stream_ &&
+ 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
+ if (drop_seen_packet) {
+ 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.
+ } else if (restarting_stream_ && demuxer_stream != restarting_stream_) {
+ DVLOG(2) << "Restarting reading packets: pos=" << packet.get()->pos;
+ restarting_stream_ = nullptr;
+ }
+
+ if (!restarting_stream_)
+ last_packet_pos_ = packet.get()->pos;
+
+ if (demuxer_stream->IsEnabled() && !drop_seen_packet)
demuxer_stream->EnqueuePacket(std::move(packet));
// If duration estimate was incorrect, update it and tell higher layers.
« 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