Bug 945863 - Handle CodecDelay and SeekPreroll for Opus in WebM. r=kinetik

This commit is contained in:
Jan Gerber 2013-12-10 10:36:05 +01:00
parent 38439ea439
commit e286df484b
2 changed files with 28 additions and 10 deletions

View File

@ -11,6 +11,7 @@
#include "WebMBufferedParser.h"
#include "mozilla/dom/TimeRanges.h"
#include "VorbisUtils.h"
#include <algorithm>
#define VPX_DONT_DEFINE_STDINT_TYPES
#include "vpx/vp8dx.h"
@ -147,6 +148,7 @@ WebMReader::WebMReader(AbstractMediaDecoder* aDecoder)
mOpusParser(nullptr),
mOpusDecoder(nullptr),
mSkip(0),
mSeekPreroll(0),
#endif
mVideoTrack(0),
mAudioTrack(0),
@ -218,10 +220,20 @@ nsresult WebMReader::ResetDecode()
res = NS_ERROR_FAILURE;
}
if (mAudioCodec == NESTEGG_CODEC_VORBIS) {
// Ignore failed results from vorbis_synthesis_restart. They
// aren't fatal and it fails when ResetDecode is called at a
// time when no vorbis data has been read.
vorbis_synthesis_restart(&mVorbisDsp);
#ifdef MOZ_OPUS
} else if (mAudioCodec == NESTEGG_CODEC_OPUS) {
if (mOpusDecoder) {
// Reset the decoder.
opus_multistream_decoder_ctl(mOpusDecoder, OPUS_RESET_STATE);
mSkip = mOpusParser->mPreSkip;
}
#endif
}
mVideoPackets.Reset();
mAudioPackets.Reset();
@ -431,6 +443,8 @@ nsresult WebMReader::ReadMetadata(MediaInfo* aInfo,
mInfo.mAudio.mChannels = mOpusParser->mChannels;
mInfo.mAudio.mChannels = mInfo.mAudio.mChannels > 2 ? 2 : mInfo.mAudio.mChannels;
mChannels = mInfo.mAudio.mChannels;
mSeekPreroll = params.seek_preroll;
#endif
} else {
Cleanup();
@ -627,6 +641,7 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
if (ret < 0)
return false;
NS_ASSERTION(ret == frames, "Opus decoded too few audio samples");
CheckedInt64 startTime = tstamp_usecs;
// Trim the initial frames while the decoder is settling.
if (mSkip > 0) {
@ -643,7 +658,7 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
nsAutoArrayPtr<AudioDataValue> trimBuffer(new AudioDataValue[samples]);
for (int i = 0; i < samples; i++)
trimBuffer[i] = buffer[skipFrames*channels + i];
startTime = startTime + FramesToUsecs(skipFrames, rate);
frames = keepFrames;
buffer = trimBuffer;
@ -708,14 +723,12 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
NS_WARNING("Int overflow converting WebM audio duration");
return false;
}
CheckedInt64 time = tstamp_usecs;
CheckedInt64 time = startTime - (mCodecDelay / NS_PER_USEC);
if (!time.isValid()) {
NS_WARNING("Int overflow adding total_duration and tstamp_usecs");
NS_WARNING("Int overflow shifting tstamp by codec delay");
nestegg_free_packet(aPacket);
return false;
};
AudioQueue().Push(new AudioData(mDecoder->GetResource()->Tell(),
time.value(),
duration.value(),
@ -982,7 +995,11 @@ nsresult WebMReader::Seek(int64_t aTarget, int64_t aStartTime, int64_t aEndTime,
return NS_ERROR_FAILURE;
}
uint32_t trackToSeek = mHasVideo ? mVideoTrack : mAudioTrack;
int r = nestegg_track_seek(mContext, trackToSeek, aTarget * NS_PER_USEC);
uint64_t target = aTarget * NS_PER_USEC;
if (mSeekPreroll) {
target = std::max(static_cast<uint64_t>(aStartTime * NS_PER_USEC), target - mSeekPreroll);
}
int r = nestegg_track_seek(mContext, trackToSeek, target);
if (r != 0) {
return NS_ERROR_FAILURE;
}

View File

@ -197,6 +197,7 @@ private:
nsAutoPtr<OpusParser> mOpusParser;
OpusMSDecoder *mOpusDecoder;
int mSkip; // Number of samples left to trim before playback.
uint64_t mSeekPreroll; // Number of nanoseconds that must be discarded after seeking.
#endif
// Queue of video and audio packets that have been read but not decoded. These