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

Unified Diff: media/filters/ffmpeg_demuxer.cc

Issue 353563002: Fix corrupted audio and video at playback start in ogg containers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove file code. Created 6 years, 6 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') | media/filters/ffmpeg_demuxer_unittest.cc » ('j') | 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 dcc178469e3bec2be3ca2838269e174465507964..05fa340ad55147d5b6d0934f35ea1b73c71d665d 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -84,10 +84,8 @@ static base::TimeDelta ExtractStartTime(AVStream* stream,
//
// FFmpegDemuxerStream
//
-FFmpegDemuxerStream::FFmpegDemuxerStream(
- FFmpegDemuxer* demuxer,
- AVStream* stream,
- bool discard_negative_timestamps)
+FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer,
+ AVStream* stream)
: demuxer_(demuxer),
task_runner_(base::MessageLoopProxy::current()),
stream_(stream),
@@ -95,7 +93,7 @@ FFmpegDemuxerStream::FFmpegDemuxerStream(
end_of_stream_(false),
last_packet_timestamp_(kNoTimestamp()),
bitstream_converter_enabled_(false),
- discard_negative_timestamps_(discard_negative_timestamps) {
+ fixup_negative_ogg_timestamps_(false) {
DCHECK(demuxer_);
bool is_encrypted = false;
@@ -262,11 +260,21 @@ void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) {
ConvertStreamTimestamp(stream_->time_base, packet->pts);
if (stream_timestamp != kNoTimestamp()) {
- buffer->set_timestamp(stream_timestamp - demuxer_->start_time());
+ // If this is an OGG file with negative timestamps don't rebase any other
+ // stream types against the negative starting time.
+ base::TimeDelta start_time = demuxer_->start_time();
+ if (fixup_negative_ogg_timestamps_ && type() != AUDIO &&
+ start_time < base::TimeDelta()) {
+ DCHECK(stream_timestamp >= base::TimeDelta());
+ start_time = base::TimeDelta();
+ }
+
+ buffer->set_timestamp(stream_timestamp - start_time);
// If enabled, mark packets with negative timestamps for post-decode
// discard.
- if (discard_negative_timestamps_ && stream_timestamp < base::TimeDelta()) {
+ if (fixup_negative_ogg_timestamps_ &&
+ stream_timestamp < base::TimeDelta()) {
if (stream_timestamp + buffer->duration() < base::TimeDelta()) {
// Discard the entire packet if it's entirely before zero.
buffer->set_discard_padding(
@@ -502,12 +510,21 @@ void FFmpegDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) {
// FFmpeg requires seeks to be adjusted according to the lowest starting time.
const base::TimeDelta seek_time = time + start_time_;
- // Choose the preferred stream if |seek_time| occurs after its starting time,
- // otherwise use the fallback stream.
+ // Choose the seeking stream based on whether it contains the seek time, if no
+ // match can be found prefer the preferred stream.
+ //
+ // TODO(dalecurtis): Currently FFmpeg does not ensure that all streams in a
+ // given container will demux all packets after the seek point. Instead it
+ // only guarantees that all packets after the file position of the seek will
+ // be demuxed. It's an open question whether FFmpeg should fix this:
+ // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html
+ // Tracked by http://crbug.com/387996.
DCHECK(preferred_stream_for_seeking_.second != kNoTimestamp());
- const int stream_index = seek_time >= preferred_stream_for_seeking_.second
- ? preferred_stream_for_seeking_.first
- : fallback_stream_for_seeking_.first;
+ const int stream_index =
+ seek_time < preferred_stream_for_seeking_.second &&
+ seek_time >= fallback_stream_for_seeking_.second
+ ? fallback_stream_for_seeking_.first
+ : preferred_stream_for_seeking_.first;
DCHECK_NE(stream_index, -1);
const AVStream* seeking_stream =
@@ -722,7 +739,6 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
AVStream* stream = format_context->streams[i];
const AVCodecContext* codec_context = stream->codec;
const AVMediaType codec_type = codec_context->codec_type;
- bool discard_negative_timestamps = false;
if (codec_type == AVMEDIA_TYPE_AUDIO) {
if (audio_stream)
@@ -737,13 +753,6 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
if (!audio_config.IsValidConfig())
continue;
audio_stream = stream;
-
- // Enable post-decode frame dropping for packets with negative timestamps
- // as outlined in section A.2 in the Ogg Vorbis spec:
- // http://xiph.org/vorbis/doc/Vorbis_I_spec.html
- discard_negative_timestamps =
- audio_config.codec() == kCodecVorbis &&
- strcmp(glue_->format_context()->iformat->name, "ogg") == 0;
} else if (codec_type == AVMEDIA_TYPE_VIDEO) {
if (video_stream)
continue;
@@ -766,8 +775,7 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
continue;
}
- streams_[i] =
- new FFmpegDemuxerStream(this, stream, discard_negative_timestamps);
+ streams_[i] = new FFmpegDemuxerStream(this, stream);
max_duration = std::max(max_duration, streams_[i]->duration());
const base::TimeDelta start_time =
@@ -813,6 +821,27 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb,
max_duration = kInfiniteDuration();
}
+ // Ogg has some peculiarities around negative timestamps, so use this flag to
+ // setup the FFmpegDemuxerStreams appropriately.
+ //
+ // Post-decode frame dropping for packets with negative timestamps is outlined
+ // in section A.2 in the Ogg Vorbis spec:
+ // http://xiph.org/vorbis/doc/Vorbis_I_spec.html
+ if (strcmp(format_context->iformat->name, "ogg") == 0 && audio_stream &&
+ audio_stream->codec->codec_id == AV_CODEC_ID_VORBIS) {
+ for (size_t i = 0; i < streams_.size(); ++i) {
+ if (streams_[i])
+ streams_[i]->enable_negative_timestamp_fixups_for_ogg();
+ }
+
+ // Fixup the seeking information to avoid selecting the audio stream simply
+ // because it has a lower starting time.
+ if (fallback_stream_for_seeking_.first == audio_stream->index &&
+ fallback_stream_for_seeking_.second < base::TimeDelta()) {
+ fallback_stream_for_seeking_.second = base::TimeDelta();
+ }
+ }
+
// If no start time could be determined, default to zero and prefer the video
// stream over the audio stream for seeking. E.g., The WAV demuxer does not
// put timestamps on its frames.
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | media/filters/ffmpeg_demuxer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698