mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-14 22:13:31 +00:00
Bug 945863 - Handle CodecDelay and SeekPreroll for Opus in WebM. r=kinetik
This commit is contained in:
parent
38439ea439
commit
e286df484b
@ -11,6 +11,7 @@
|
|||||||
#include "WebMBufferedParser.h"
|
#include "WebMBufferedParser.h"
|
||||||
#include "mozilla/dom/TimeRanges.h"
|
#include "mozilla/dom/TimeRanges.h"
|
||||||
#include "VorbisUtils.h"
|
#include "VorbisUtils.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#define VPX_DONT_DEFINE_STDINT_TYPES
|
#define VPX_DONT_DEFINE_STDINT_TYPES
|
||||||
#include "vpx/vp8dx.h"
|
#include "vpx/vp8dx.h"
|
||||||
@ -147,6 +148,7 @@ WebMReader::WebMReader(AbstractMediaDecoder* aDecoder)
|
|||||||
mOpusParser(nullptr),
|
mOpusParser(nullptr),
|
||||||
mOpusDecoder(nullptr),
|
mOpusDecoder(nullptr),
|
||||||
mSkip(0),
|
mSkip(0),
|
||||||
|
mSeekPreroll(0),
|
||||||
#endif
|
#endif
|
||||||
mVideoTrack(0),
|
mVideoTrack(0),
|
||||||
mAudioTrack(0),
|
mAudioTrack(0),
|
||||||
@ -218,10 +220,20 @@ nsresult WebMReader::ResetDecode()
|
|||||||
res = NS_ERROR_FAILURE;
|
res = NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mAudioCodec == NESTEGG_CODEC_VORBIS) {
|
||||||
// Ignore failed results from vorbis_synthesis_restart. They
|
// Ignore failed results from vorbis_synthesis_restart. They
|
||||||
// aren't fatal and it fails when ResetDecode is called at a
|
// aren't fatal and it fails when ResetDecode is called at a
|
||||||
// time when no vorbis data has been read.
|
// time when no vorbis data has been read.
|
||||||
vorbis_synthesis_restart(&mVorbisDsp);
|
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();
|
mVideoPackets.Reset();
|
||||||
mAudioPackets.Reset();
|
mAudioPackets.Reset();
|
||||||
@ -431,6 +443,8 @@ nsresult WebMReader::ReadMetadata(MediaInfo* aInfo,
|
|||||||
|
|
||||||
mInfo.mAudio.mChannels = mOpusParser->mChannels;
|
mInfo.mAudio.mChannels = mOpusParser->mChannels;
|
||||||
mInfo.mAudio.mChannels = mInfo.mAudio.mChannels > 2 ? 2 : mInfo.mAudio.mChannels;
|
mInfo.mAudio.mChannels = mInfo.mAudio.mChannels > 2 ? 2 : mInfo.mAudio.mChannels;
|
||||||
|
mChannels = mInfo.mAudio.mChannels;
|
||||||
|
mSeekPreroll = params.seek_preroll;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
Cleanup();
|
Cleanup();
|
||||||
@ -627,6 +641,7 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return false;
|
return false;
|
||||||
NS_ASSERTION(ret == frames, "Opus decoded too few audio samples");
|
NS_ASSERTION(ret == frames, "Opus decoded too few audio samples");
|
||||||
|
CheckedInt64 startTime = tstamp_usecs;
|
||||||
|
|
||||||
// Trim the initial frames while the decoder is settling.
|
// Trim the initial frames while the decoder is settling.
|
||||||
if (mSkip > 0) {
|
if (mSkip > 0) {
|
||||||
@ -643,7 +658,7 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
|||||||
nsAutoArrayPtr<AudioDataValue> trimBuffer(new AudioDataValue[samples]);
|
nsAutoArrayPtr<AudioDataValue> trimBuffer(new AudioDataValue[samples]);
|
||||||
for (int i = 0; i < samples; i++)
|
for (int i = 0; i < samples; i++)
|
||||||
trimBuffer[i] = buffer[skipFrames*channels + i];
|
trimBuffer[i] = buffer[skipFrames*channels + i];
|
||||||
|
startTime = startTime + FramesToUsecs(skipFrames, rate);
|
||||||
frames = keepFrames;
|
frames = keepFrames;
|
||||||
buffer = trimBuffer;
|
buffer = trimBuffer;
|
||||||
|
|
||||||
@ -708,14 +723,12 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
|||||||
NS_WARNING("Int overflow converting WebM audio duration");
|
NS_WARNING("Int overflow converting WebM audio duration");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
CheckedInt64 time = startTime - (mCodecDelay / NS_PER_USEC);
|
||||||
CheckedInt64 time = tstamp_usecs;
|
|
||||||
if (!time.isValid()) {
|
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);
|
nestegg_free_packet(aPacket);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
AudioQueue().Push(new AudioData(mDecoder->GetResource()->Tell(),
|
AudioQueue().Push(new AudioData(mDecoder->GetResource()->Tell(),
|
||||||
time.value(),
|
time.value(),
|
||||||
duration.value(),
|
duration.value(),
|
||||||
@ -982,7 +995,11 @@ nsresult WebMReader::Seek(int64_t aTarget, int64_t aStartTime, int64_t aEndTime,
|
|||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
uint32_t trackToSeek = mHasVideo ? mVideoTrack : mAudioTrack;
|
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) {
|
if (r != 0) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -197,6 +197,7 @@ private:
|
|||||||
nsAutoPtr<OpusParser> mOpusParser;
|
nsAutoPtr<OpusParser> mOpusParser;
|
||||||
OpusMSDecoder *mOpusDecoder;
|
OpusMSDecoder *mOpusDecoder;
|
||||||
int mSkip; // Number of samples left to trim before playback.
|
int mSkip; // Number of samples left to trim before playback.
|
||||||
|
uint64_t mSeekPreroll; // Number of nanoseconds that must be discarded after seeking.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Queue of video and audio packets that have been read but not decoded. These
|
// Queue of video and audio packets that have been read but not decoded. These
|
||||||
|
Loading…
x
Reference in New Issue
Block a user