Bug 1304252: P3. Further error details for agnostic decoders. r?gerald draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 21 Sep 2016 13:25:00 +1000
changeset 415877 2b0e630740e98926a7acab95e3208f1788dcab18
parent 415811 8ff84b2064358cdb63c6e047cb64564e3331fa66
child 531723 a89c841fcd97af1bd6a80b98364ea54e5685a20f
push id29994
push userbmo:jyavenard@mozilla.com
push dateWed, 21 Sep 2016 06:47:33 +0000
reviewersgerald
bugs1304252
milestone52.0a1
Bug 1304252: P3. Further error details for agnostic decoders. r?gerald MozReview-Commit-ID: 1tb4f9xQKyr
dom/media/platforms/agnostic/OpusDecoder.cpp
dom/media/platforms/agnostic/TheoraDecoder.cpp
dom/media/platforms/agnostic/VPXDecoder.cpp
dom/media/platforms/agnostic/VorbisDecoder.cpp
--- 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;
 }