Bug 1304252: P3. Further error details for agnostic decoders. r?gerald
MozReview-Commit-ID: 1tb4f9xQKyr
--- a/dom/media/platforms/agnostic/OpusDecoder.cpp
+++ b/dom/media/platforms/agnostic/OpusDecoder.cpp
@@ -167,43 +167,48 @@ OpusDataDecoder::DoDecode(MediaRawData*
aDiscardPadding = BigEndian::readInt64(aSample->mExtraData->Elements());
}
uint32_t channels = mOpusParser->mChannels;
if (mPaddingDiscarded) {
// Discard padding should be used only on the final packet, so
// decoding after a padding discard is invalid.
OPUS_DEBUG("Opus error, discard padding on interstitial packet");
- return NS_ERROR_DOM_MEDIA_FATAL_ERR;
+ return MediaResult(
+ NS_ERROR_DOM_MEDIA_FATAL_ERR,
+ RESULT_DETAIL("Discard padding on interstitial packet"));
}
if (!mLastFrameTime || mLastFrameTime.ref() != aSample->mTime) {
// We are starting a new block.
mFrames = 0;
mLastFrameTime = Some(aSample->mTime);
}
// Maximum value is 63*2880, so there's no chance of overflow.
int32_t frames_number = opus_packet_get_nb_frames(aSample->Data(),
aSample->Size());
if (frames_number <= 0) {
OPUS_DEBUG("Invalid packet header: r=%ld length=%ld",
frames_number, aSample->Size());
- return NS_ERROR_DOM_MEDIA_DECODE_ERR;
+ return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("Invalid packet header: r=%d length=%u",
+ frames_number, uint32_t(aSample->Size())));
}
int32_t samples = opus_packet_get_samples_per_frame(aSample->Data(),
opus_int32(mOpusParser->mRate));
// A valid Opus packet must be between 2.5 and 120 ms long (48kHz).
int32_t frames = frames_number*samples;
if (frames < 120 || frames > 5760) {
OPUS_DEBUG("Invalid packet frames: %ld", frames);
- return NS_ERROR_DOM_MEDIA_DECODE_ERR;
+ return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("Invalid packet frames:%d", frames));
}
AlignedAudioBuffer buffer(frames * channels);
if (!buffer) {
return MediaResult(NS_ERROR_OUT_OF_MEMORY, __func__);
}
// Decode to the appropriate sample type.
@@ -212,17 +217,18 @@ OpusDataDecoder::DoDecode(MediaRawData*
aSample->Data(), aSample->Size(),
buffer.get(), frames, false);
#else
int ret = opus_multistream_decode(mOpusDecoder,
aSample->Data(), aSample->Size(),
buffer.get(), frames, false);
#endif
if (ret < 0) {
- return NS_ERROR_DOM_MEDIA_DECODE_ERR;
+ return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("Opus decoding error:%d", ret));
}
NS_ASSERTION(ret == frames, "Opus decoded too few audio samples");
CheckedInt64 startTime = aSample->mTime;
// Trim the initial frames while the decoder is settling.
if (mSkip > 0) {
int32_t skipFrames = std::min<int32_t>(mSkip, frames);
int32_t keepFrames = frames - skipFrames;
@@ -233,31 +239,34 @@ OpusDataDecoder::DoDecode(MediaRawData*
startTime = startTime + FramesToUsecs(skipFrames, mOpusParser->mRate);
frames = keepFrames;
mSkip -= skipFrames;
}
if (aDiscardPadding < 0) {
// Negative discard padding is invalid.
OPUS_DEBUG("Opus error, negative discard padding");
- return NS_ERROR_DOM_MEDIA_FATAL_ERR;
+ return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
+ RESULT_DETAIL("Negative discard padding"));
}
if (aDiscardPadding > 0) {
OPUS_DEBUG("OpusDecoder discardpadding %" PRId64 "", aDiscardPadding);
CheckedInt64 discardFrames =
TimeUnitToFrames(media::TimeUnit::FromNanoseconds(aDiscardPadding),
mOpusParser->mRate);
if (!discardFrames.isValid()) {
- NS_WARNING("Int overflow in DiscardPadding");
- return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
+ return MediaResult(NS_ERROR_DOM_MEDIA_OVERFLOW_ERR,
+ RESULT_DETAIL("Overflow in DiscardPadding"));
}
if (discardFrames.value() > frames) {
// Discarding more than the entire packet is invalid.
OPUS_DEBUG("Opus error, discard padding larger than packet");
- return NS_ERROR_DOM_MEDIA_FATAL_ERR;
+ return MediaResult(
+ NS_ERROR_DOM_MEDIA_FATAL_ERR,
+ RESULT_DETAIL("Discard padding larger than packet"));
}
OPUS_DEBUG("Opus decoder discarding %d of %d frames",
int32_t(discardFrames.value()), frames);
// Padding discard is only supposed to happen on the final packet.
// Record the discard so we can return an error if another packet is
// decoded.
mPaddingDiscarded = true;
int32_t keepFrames = frames - discardFrames.value();
@@ -281,25 +290,27 @@ OpusDataDecoder::DoDecode(MediaRawData*
int32_t val = static_cast<int32_t>((gain_Q16*buffer[i] + 32768)>>16);
buffer[i] = static_cast<AudioDataValue>(MOZ_CLIP_TO_15(val));
}
}
#endif
CheckedInt64 duration = FramesToUsecs(frames, mOpusParser->mRate);
if (!duration.isValid()) {
- NS_WARNING("OpusDataDecoder: Int overflow converting WebM audio duration");
- return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
+ return MediaResult(
+ NS_ERROR_DOM_MEDIA_OVERFLOW_ERR,
+ RESULT_DETAIL("Overflow converting WebM audio duration"));
}
CheckedInt64 time =
startTime - FramesToUsecs(mOpusParser->mPreSkip, mOpusParser->mRate) +
FramesToUsecs(mFrames, mOpusParser->mRate);
if (!time.isValid()) {
- NS_WARNING("OpusDataDecoder: Int overflow shifting tstamp by codec delay");
- return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
+ return MediaResult(
+ NS_ERROR_DOM_MEDIA_OVERFLOW_ERR,
+ RESULT_DETAIL("Overflow shifting tstamp by codec delay"));
};
mCallback->Output(new AudioData(aSample->mOffset,
time.value(),
duration.value(),
frames,
Move(buffer),
mOpusParser->mChannels,
--- a/dom/media/platforms/agnostic/TheoraDecoder.cpp
+++ b/dom/media/platforms/agnostic/TheoraDecoder.cpp
@@ -182,17 +182,18 @@ TheoraDecoder::DoDecode(MediaRawData* aS
mTheoraInfo.frame_width, mTheoraInfo.frame_height, mInfo.mDisplay.width, mInfo.mDisplay.height,
mInfo.mImage.width, mInfo.mImage.height);
return MediaResult(NS_ERROR_OUT_OF_MEMORY, __func__);
}
mCallback->Output(v);
return NS_OK;
} else {
LOG("Theora Decode error: %d", ret);
- return NS_ERROR_DOM_MEDIA_DECODE_ERR;
+ return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("Theora decode error:%d", ret));
}
}
void
TheoraDecoder::ProcessDecode(MediaRawData* aSample)
{
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
if (mIsFlushing) {
--- a/dom/media/platforms/agnostic/VPXDecoder.cpp
+++ b/dom/media/platforms/agnostic/VPXDecoder.cpp
@@ -111,17 +111,19 @@ VPXDecoder::DoDecode(MediaRawData* aSamp
vpx_codec_peek_stream_info(vpx_codec_vp9_dx(), aSample->Data(), aSample->Size(), &si);
}
NS_ASSERTION(bool(si.is_kf) == aSample->mKeyframe,
"VPX Decode Keyframe error sample->mKeyframe and si.si_kf out of sync");
#endif
if (vpx_codec_err_t r = vpx_codec_decode(&mVPX, aSample->Data(), aSample->Size(), nullptr, 0)) {
LOG("VPX Decode error: %s", vpx_codec_err_to_string(r));
- return NS_ERROR_DOM_MEDIA_DECODE_ERR;
+ return MediaResult(
+ NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("VPX error: %s", vpx_codec_err_to_string(r)));
}
vpx_codec_iter_t iter = nullptr;
vpx_image_t *img;
while ((img = vpx_codec_get_frame(&mVPX, &iter))) {
NS_ASSERTION(img->fmt == VPX_IMG_FMT_I420 ||
img->fmt == VPX_IMG_FMT_I444,
@@ -152,17 +154,18 @@ VPXDecoder::DoDecode(MediaRawData* aSamp
} else if (img->fmt == VPX_IMG_FMT_I444) {
b.mPlanes[1].mHeight = img->d_h;
b.mPlanes[1].mWidth = img->d_w;
b.mPlanes[2].mHeight = img->d_h;
b.mPlanes[2].mWidth = img->d_w;
} else {
LOG("VPX Unknown image format");
- return NS_ERROR_DOM_MEDIA_DECODE_ERR;
+ return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("VPX Unknown image format"));
}
RefPtr<VideoData> v =
VideoData::CreateAndCopyData(mInfo,
mImageContainer,
aSample->mOffset,
aSample->mTime,
aSample->mDuration,
--- a/dom/media/platforms/agnostic/VorbisDecoder.cpp
+++ b/dom/media/platforms/agnostic/VorbisDecoder.cpp
@@ -163,23 +163,26 @@ VorbisDataDecoder::DoDecode(MediaRawData
// We are starting a new block.
mFrames = 0;
mLastFrameTime = Some(aSample->mTime);
}
ogg_packet pkt = InitVorbisPacket(aData, aLength, false, aSample->mEOS,
aSample->mTimecode, mPacketCount++);
- if (vorbis_synthesis(&mVorbisBlock, &pkt) != 0) {
- return NS_ERROR_DOM_MEDIA_DECODE_ERR;
+ int err = vorbis_synthesis(&mVorbisBlock, &pkt);
+ if (err) {
+ return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("vorbis_synthesis:%d", err));
}
- if (vorbis_synthesis_blockin(&mVorbisDsp,
- &mVorbisBlock) != 0) {
- return NS_ERROR_DOM_MEDIA_DECODE_ERR;
+ err = vorbis_synthesis_blockin(&mVorbisDsp, &mVorbisBlock);
+ if (err) {
+ return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("vorbis_synthesis_blockin:%d", err));
}
VorbisPCMValue** pcm = 0;
int32_t frames = vorbis_synthesis_pcmout(&mVorbisDsp, &pcm);
if (frames == 0) {
return NS_OK;
}
while (frames > 0) {
@@ -193,55 +196,61 @@ VorbisDataDecoder::DoDecode(MediaRawData
VorbisPCMValue* channel = pcm[j];
for (uint32_t i = 0; i < uint32_t(frames); ++i) {
buffer[i*channels + j] = MOZ_CONVERT_VORBIS_SAMPLE(channel[i]);
}
}
CheckedInt64 duration = FramesToUsecs(frames, rate);
if (!duration.isValid()) {
- NS_WARNING("Int overflow converting WebM audio duration");
- return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
+ return MediaResult(NS_ERROR_DOM_MEDIA_OVERFLOW_ERR,
+ RESULT_DETAIL("Overflow converting audio duration"));
}
CheckedInt64 total_duration = FramesToUsecs(mFrames, rate);
if (!total_duration.isValid()) {
- NS_WARNING("Int overflow converting WebM audio total_duration");
- return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
+ return MediaResult(
+ NS_ERROR_DOM_MEDIA_OVERFLOW_ERR,
+ RESULT_DETAIL("Overflow converting audio total_duration"));
}
CheckedInt64 time = total_duration + aTstampUsecs;
if (!time.isValid()) {
- NS_WARNING("Int overflow adding total_duration and aTstampUsecs");
- return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
+ return MediaResult(
+ NS_ERROR_DOM_MEDIA_OVERFLOW_ERR,
+ RESULT_DETAIL("Overflow adding total_duration and aTstampUsecs"));
};
if (!mAudioConverter) {
AudioConfig in(AudioConfig::ChannelLayout(channels, VorbisLayout(channels)),
rate);
AudioConfig out(channels, rate);
if (!in.IsValid() || !out.IsValid()) {
- return NS_ERROR_DOM_MEDIA_FATAL_ERR;
+ return MediaResult(
+ NS_ERROR_DOM_MEDIA_FATAL_ERR,
+ RESULT_DETAIL("Invalid channel layout:%u", channels));
}
mAudioConverter = MakeUnique<AudioConverter>(in, out);
}
MOZ_ASSERT(mAudioConverter->CanWorkInPlace());
AudioSampleBuffer data(Move(buffer));
data = mAudioConverter->Process(Move(data));
aTotalFrames += frames;
mCallback->Output(new AudioData(aOffset,
time.value(),
duration.value(),
frames,
data.Forget(),
channels,
rate));
mFrames += frames;
- if (vorbis_synthesis_read(&mVorbisDsp, frames) != 0) {
- return NS_ERROR_DOM_MEDIA_DECODE_ERR;
+ err = vorbis_synthesis_read(&mVorbisDsp, frames);
+ if (err) {
+ return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("vorbis_synthesis_read:%d", err));
}
frames = vorbis_synthesis_pcmout(&mVorbisDsp, &pcm);
}
return NS_OK;
}