mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
Bug 1069660 - Factor Vorbis and Opus decoding out.
This commit is contained in:
parent
a0648a0cdf
commit
672372df86
@ -531,7 +531,6 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint32_t rate = mInfo.mAudio.mRate;
|
||||
uint64_t tstamp_usecs = tstamp / NS_PER_USEC;
|
||||
if (mAudioStartUsec == -1) {
|
||||
// This is the first audio chunk. Assume the start time of our decode
|
||||
@ -542,8 +541,8 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
||||
// the previous audio chunk, we need to increment the packet count so that
|
||||
// the vorbis decode doesn't use data from before the gap to help decode
|
||||
// from after the gap.
|
||||
CheckedInt64 tstamp_frames = UsecsToFrames(tstamp_usecs, rate);
|
||||
CheckedInt64 decoded_frames = UsecsToFrames(mAudioStartUsec, rate);
|
||||
CheckedInt64 tstamp_frames = UsecsToFrames(tstamp_usecs, mInfo.mAudio.mRate);
|
||||
CheckedInt64 decoded_frames = UsecsToFrames(mAudioStartUsec, mInfo.mAudio.mRate);
|
||||
if (!tstamp_frames.isValid() || !decoded_frames.isValid()) {
|
||||
NS_WARNING("Int overflow converting WebM times to frames");
|
||||
return false;
|
||||
@ -555,7 +554,7 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
||||
}
|
||||
if (tstamp_frames.value() > decoded_frames.value()) {
|
||||
#ifdef DEBUG
|
||||
CheckedInt64 usecs = FramesToUsecs(tstamp_frames.value() - decoded_frames.value(), rate);
|
||||
CheckedInt64 usecs = FramesToUsecs(tstamp_frames.value() - decoded_frames.value(), mInfo.mAudio.mRate);
|
||||
LOG(PR_LOG_DEBUG, ("WebMReader detected gap of %lld, %lld frames, in audio stream\n",
|
||||
usecs.isValid() ? usecs.value() : -1,
|
||||
tstamp_frames.value() - decoded_frames.value()));
|
||||
@ -574,7 +573,25 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
||||
return false;
|
||||
}
|
||||
if (mAudioCodec == NESTEGG_CODEC_VORBIS) {
|
||||
ogg_packet opacket = InitOggPacket(data, length, false, false, -1);
|
||||
if (!DecodeVorbis(data, length, aOffset, tstamp_usecs, &total_frames)) {
|
||||
return false;
|
||||
}
|
||||
} else if (mAudioCodec == NESTEGG_CODEC_OPUS) {
|
||||
#ifdef MOZ_OPUS
|
||||
if (!DecodeOpus(data, length, aOffset, tstamp_usecs, aPacket)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebMReader::DecodeVorbis(unsigned char* aData, size_t aLength,
|
||||
int64_t aOffset, uint64_t aTstampUsecs, int32_t* aTotalFrames)
|
||||
{
|
||||
ogg_packet opacket = InitOggPacket(aData, aLength, false, false, -1);
|
||||
|
||||
if (vorbis_synthesis(&mVorbisBlock, &opacket) != 0) {
|
||||
return false;
|
||||
@ -593,7 +610,7 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
||||
// time derived from the timecode of the first packet that produced
|
||||
// data.
|
||||
if (frames == 0 && mAudioFrames == 0) {
|
||||
AudioQueue().Push(new AudioData(aOffset, tstamp_usecs, 0, 0, nullptr, mChannels, rate));
|
||||
AudioQueue().Push(new AudioData(aOffset, aTstampUsecs, 0, 0, nullptr, mChannels, mInfo.mAudio.mRate));
|
||||
}
|
||||
while (frames > 0) {
|
||||
nsAutoArrayPtr<AudioDataValue> buffer(new AudioDataValue[frames * mChannels]);
|
||||
@ -604,31 +621,31 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
||||
}
|
||||
}
|
||||
|
||||
CheckedInt64 duration = FramesToUsecs(frames, rate);
|
||||
CheckedInt64 duration = FramesToUsecs(frames, mInfo.mAudio.mRate);
|
||||
if (!duration.isValid()) {
|
||||
NS_WARNING("Int overflow converting WebM audio duration");
|
||||
return false;
|
||||
}
|
||||
CheckedInt64 total_duration = FramesToUsecs(total_frames, rate);
|
||||
CheckedInt64 total_duration = FramesToUsecs(*aTotalFrames, mInfo.mAudio.mRate);
|
||||
if (!total_duration.isValid()) {
|
||||
NS_WARNING("Int overflow converting WebM audio total_duration");
|
||||
return false;
|
||||
}
|
||||
|
||||
CheckedInt64 time = total_duration + tstamp_usecs;
|
||||
CheckedInt64 time = total_duration + aTstampUsecs;
|
||||
if (!time.isValid()) {
|
||||
NS_WARNING("Int overflow adding total_duration and tstamp_usecs");
|
||||
NS_WARNING("Int overflow adding total_duration and aTstampUsecs");
|
||||
return false;
|
||||
};
|
||||
|
||||
total_frames += frames;
|
||||
*aTotalFrames += frames;
|
||||
AudioQueue().Push(new AudioData(aOffset,
|
||||
time.value(),
|
||||
duration.value(),
|
||||
frames,
|
||||
buffer.forget(),
|
||||
mChannels,
|
||||
rate));
|
||||
mInfo.mAudio.mRate));
|
||||
mAudioFrames += frames;
|
||||
if (vorbis_synthesis_read(&mVorbisDsp, frames) != 0) {
|
||||
return false;
|
||||
@ -636,17 +653,23 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
||||
|
||||
frames = vorbis_synthesis_pcmout(&mVorbisDsp, &pcm);
|
||||
}
|
||||
} else if (mAudioCodec == NESTEGG_CODEC_OPUS) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MOZ_OPUS
|
||||
bool WebMReader::DecodeOpus(unsigned char* aData, size_t aLength,
|
||||
int64_t aOffset, uint64_t aTstampUsecs, nestegg_packet* aPacket)
|
||||
{
|
||||
uint32_t channels = mOpusParser->mChannels;
|
||||
|
||||
// Maximum value is 63*2880, so there's no chance of overflow.
|
||||
int32_t frames_number = opus_packet_get_nb_frames(data, length);
|
||||
int32_t frames_number = opus_packet_get_nb_frames(aData, aLength);
|
||||
|
||||
if (frames_number <= 0)
|
||||
return false; // Invalid packet header.
|
||||
int32_t samples = opus_packet_get_samples_per_frame(data,
|
||||
(opus_int32) rate);
|
||||
int32_t samples = opus_packet_get_samples_per_frame(aData,
|
||||
(opus_int32) mInfo.mAudio.mRate);
|
||||
int32_t frames = frames_number*samples;
|
||||
|
||||
// A valid Opus packet must be between 2.5 and 120 ms long.
|
||||
@ -657,17 +680,17 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
||||
// Decode to the appropriate sample type.
|
||||
#ifdef MOZ_SAMPLE_TYPE_FLOAT32
|
||||
int ret = opus_multistream_decode_float(mOpusDecoder,
|
||||
data, length,
|
||||
aData, aLength,
|
||||
buffer, frames, false);
|
||||
#else
|
||||
int ret = opus_multistream_decode(mOpusDecoder,
|
||||
data, length,
|
||||
aData, aLength,
|
||||
buffer, frames, false);
|
||||
#endif
|
||||
if (ret < 0)
|
||||
return false;
|
||||
NS_ASSERTION(ret == frames, "Opus decoded too few audio samples");
|
||||
CheckedInt64 startTime = tstamp_usecs;
|
||||
CheckedInt64 startTime = aTstampUsecs;
|
||||
|
||||
// Trim the initial frames while the decoder is settling.
|
||||
if (mSkip > 0) {
|
||||
@ -683,7 +706,7 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
||||
int samples = keepFrames * channels;
|
||||
nsAutoArrayPtr<AudioDataValue> trimBuffer(new AudioDataValue[samples]);
|
||||
PodCopy(trimBuffer.get(), buffer.get() + skipFrames*channels, samples);
|
||||
startTime = startTime + FramesToUsecs(skipFrames, rate);
|
||||
startTime = startTime + FramesToUsecs(skipFrames, mInfo.mAudio.mRate);
|
||||
frames = keepFrames;
|
||||
buffer = trimBuffer;
|
||||
|
||||
@ -692,9 +715,9 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
||||
}
|
||||
|
||||
int64_t discardPadding = 0;
|
||||
r = nestegg_packet_discard_padding(aPacket, &discardPadding);
|
||||
(void) nestegg_packet_discard_padding(aPacket, &discardPadding);
|
||||
if (discardPadding > 0) {
|
||||
CheckedInt64 discardFrames = UsecsToFrames(discardPadding / NS_PER_USEC, rate);
|
||||
CheckedInt64 discardFrames = UsecsToFrames(discardPadding / NS_PER_USEC, mInfo.mAudio.mRate);
|
||||
if (!discardFrames.isValid()) {
|
||||
NS_WARNING("Int overflow in DiscardPadding");
|
||||
return false;
|
||||
@ -738,7 +761,7 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
||||
return false;
|
||||
}
|
||||
|
||||
CheckedInt64 duration = FramesToUsecs(frames, rate);
|
||||
CheckedInt64 duration = FramesToUsecs(frames, mInfo.mAudio.mRate);
|
||||
if (!duration.isValid()) {
|
||||
NS_WARNING("Int overflow converting WebM audio duration");
|
||||
return false;
|
||||
@ -748,23 +771,19 @@ bool WebMReader::DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset)
|
||||
NS_WARNING("Int overflow shifting tstamp by codec delay");
|
||||
return false;
|
||||
};
|
||||
AudioQueue().Push(new AudioData(mDecoder->GetResource()->Tell(),
|
||||
AudioQueue().Push(new AudioData(aOffset,
|
||||
time.value(),
|
||||
duration.value(),
|
||||
frames,
|
||||
buffer.forget(),
|
||||
mChannels,
|
||||
rate));
|
||||
mInfo.mAudio.mRate));
|
||||
|
||||
mAudioFrames += frames;
|
||||
#else
|
||||
return false;
|
||||
#endif /* MOZ_OPUS */
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif /* MOZ_OPUS */
|
||||
|
||||
nsReturnRef<NesteggPacketHolder> WebMReader::NextPacket(TrackType aTrackType)
|
||||
{
|
||||
|
@ -176,6 +176,12 @@ protected:
|
||||
// must be held during this call. The caller is responsible for freeing
|
||||
// aPacket.
|
||||
bool DecodeAudioPacket(nestegg_packet* aPacket, int64_t aOffset);
|
||||
bool DecodeVorbis(unsigned char* aData, size_t aLength,
|
||||
int64_t aOffset, uint64_t aTstampUsecs, int32_t* aTotalFrames);
|
||||
#ifdef MOZ_OPUS
|
||||
bool DecodeOpus(unsigned char* aData, size_t aLength,
|
||||
int64_t aOffset, uint64_t aTstampUsecs, nestegg_packet* aPacket);
|
||||
#endif
|
||||
|
||||
// Release context and set to null. Called when an error occurs during
|
||||
// reading metadata or destruction of the reader itself.
|
||||
|
Loading…
Reference in New Issue
Block a user