Add AOMDecoder::IsKeyframe method. draft
authorRalph Giles <giles@mozilla.com>
Thu, 20 Apr 2017 14:56:28 -0700
changeset 566133 2f306954584b783a8a548efc00af29225c33b86f
parent 566132 d73235c928692396d512622ec3157e9fd623415c
child 625201 362ae2fc9575c569cd766676f25466f3264f746a
push id55094
push userbmo:giles@thaumas.net
push dateThu, 20 Apr 2017 22:03:17 +0000
milestone55.0a1
Add AOMDecoder::IsKeyframe method. WebMDemuxer needs to ask the decoder if a given sample is a keyframe, to relay that information to higher levels for planning purposes. Right now it just calls the libvpx keyframe check directly, but that doesn't work for av1 data. Add a method on AOMDecoder to do this for us. MozReview-Commit-ID: 3wiLBJUThWl
dom/media/platforms/agnostic/AOMDecoder.cpp
dom/media/platforms/agnostic/AOMDecoder.h
dom/media/webm/WebMDemuxer.cpp
--- a/dom/media/platforms/agnostic/AOMDecoder.cpp
+++ b/dom/media/platforms/agnostic/AOMDecoder.cpp
@@ -222,11 +222,25 @@ AOMDecoder::Drain()
 /* static */
 bool
 AOMDecoder::IsAV1(const nsACString& aMimeType)
 {
   return aMimeType.EqualsLiteral("video/webm; codecs=av1")
          || aMimeType.EqualsLiteral("video/av1");
 }
 
+/* static */
+bool IsKeyframe(Span<const uint8_t>& packet) {
+  aom_codec_stream_info_t info;
+  auto res = aom_codec_peek_stream_info(aom_codec_av1_dx(),
+                                        packet.Elements(),
+                                        packet.Length(),
+                                        &info);
+  if (res != AOM_CODEC_OK) {
+    LOG_RESULT(res, "aom_codec_peek_stream_info");
+    return false;
+  }
+
+  return bool(info.is_kf);
+}
 
 } // namespace mozilla
 #undef LOG
--- a/dom/media/platforms/agnostic/AOMDecoder.h
+++ b/dom/media/platforms/agnostic/AOMDecoder.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(AOMDecoder_h_)
 #define AOMDecoder_h_
 
 #include "PlatformDecoderModule.h"
 
 #include <stdint.h>
 #include "aom/aom_decoder.h"
+#include "mozilla/Span.h"
 
 namespace mozilla {
 
 class AOMDecoder : public MediaDataDecoder
 {
 public:
   explicit AOMDecoder(const CreateDecoderParams& aParams);
 
@@ -27,16 +28,19 @@ public:
   {
     return "libaom (AV1) video decoder";
   }
 
   // Return true if aMimeType is a one of the strings used
   // by our demuxers to identify AV1 streams.
   static bool IsAV1(const nsACString& aMimeType);
 
+  // Return true if a sample is a keyframe.
+  static bool IsKeyframe(Span<const uint8_t>& packet);
+
 private:
   ~AOMDecoder();
   RefPtr<DecodePromise> ProcessDecode(MediaRawData* aSample);
 
   const RefPtr<layers::ImageContainer> mImageContainer;
   const RefPtr<TaskQueue> mTaskQueue;
 
   // AOM decoder state
--- a/dom/media/webm/WebMDemuxer.cpp
+++ b/dom/media/webm/WebMDemuxer.cpp
@@ -23,16 +23,18 @@
 #include "prprf.h"           // leaving it for PR_vsnprintf()
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/SizePrintfMacros.h"
 #include "mozilla/Sprintf.h"
 
 #include <algorithm>
 #include <stdint.h>
 
+#include "aom/aom_decoder.h"
+#include "aom/aomdx.h"
 #define VPX_DONT_DEFINE_STDINT_TYPES
 #include "vpx/vp8dx.h"
 #include "vpx/vpx_decoder.h"
 #include <numeric>
 
 #define WEBM_DEBUG(arg, ...) MOZ_LOG(gMediaDemuxerLog, mozilla::LogLevel::Debug, ("WebMDemuxer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
 extern mozilla::LazyLogModule gMediaDemuxerLog;
 
@@ -681,22 +683,28 @@ WebMDemuxer::GetNextPacket(TrackInfo::Tr
                      == NESTEGG_PACKET_HAS_KEYFRAME_TRUE;
       } else {
         vpx_codec_stream_info_t si;
         PodZero(&si);
         si.sz = sizeof(si);
         switch (mVideoCodec) {
         case NESTEGG_CODEC_VP8:
           vpx_codec_peek_stream_info(vpx_codec_vp8_dx(), data, length, &si);
+          isKeyframe = si.is_kf;
           break;
         case NESTEGG_CODEC_VP9:
           vpx_codec_peek_stream_info(vpx_codec_vp9_dx(), data, length, &si);
+          isKeyframe = si.is_kf;
+          break;
+        case NESTEGG_CODEC_AV1:
+          aom_codec_stream_info_t info;
+          aom_codec_peek_stream_info(aom_codec_av1_dx(), data, length, &info);
+          isKeyframe = info.is_kf;
           break;
         }
-        isKeyframe = si.is_kf;
         if (isKeyframe) {
           // We only look for resolution changes on keyframes for both VP8 and
           // VP9. Other resolution changes are invalid.
           if (mLastSeenFrameWidth.isSome()
               && mLastSeenFrameHeight.isSome()
               && (si.w != mLastSeenFrameWidth.value()
                   || si.h != mLastSeenFrameHeight.value())) {
             mInfo.mVideo.mDisplay = nsIntSize(si.w, si.h);