Bug 1287370: Remove VDA decoder. r?cpearce draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Mon, 18 Jul 2016 17:02:51 +1000
changeset 388886 8a5852b04fe6250d711178cefa63c9223c5066da
parent 388824 19aff9dfeb099aa5f3cd382ffb54f71f9ca75f6d
child 388889 b3c8fa6583edb555afa67ce97f557fc82839afef
push id23253
push userbmo:jyavenard@mozilla.com
push dateMon, 18 Jul 2016 07:13:08 +0000
reviewerscpearce
bugs1287370
milestone50.0a1
Bug 1287370: Remove VDA decoder. r?cpearce The VDA decoder was no longer usable regardless. MozReview-Commit-ID: 6Q94jrp0OIG
dom/media/platforms/apple/AppleDecoderModule.cpp
dom/media/platforms/apple/AppleDecoderModule.h
dom/media/platforms/apple/AppleVDADecoder.cpp
dom/media/platforms/apple/AppleVDADecoder.h
dom/media/platforms/apple/AppleVDAFunctions.h
dom/media/platforms/apple/AppleVDALinker.cpp
dom/media/platforms/apple/AppleVDALinker.h
dom/media/platforms/apple/AppleVTDecoder.cpp
dom/media/platforms/apple/AppleVTDecoder.h
dom/media/platforms/apple/VideoDecodeAcceleration/VDADecoder.h
dom/media/platforms/moz.build
--- a/dom/media/platforms/apple/AppleDecoderModule.cpp
+++ b/dom/media/platforms/apple/AppleDecoderModule.cpp
@@ -2,32 +2,29 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AppleATDecoder.h"
 #include "AppleCMLinker.h"
 #include "AppleDecoderModule.h"
-#include "AppleVDADecoder.h"
-#include "AppleVDALinker.h"
 #include "AppleVTDecoder.h"
 #include "AppleVTLinker.h"
 #include "MacIOSurfaceImage.h"
 #include "MediaPrefs.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Logging.h"
 
 namespace mozilla {
 
 bool AppleDecoderModule::sInitialized = false;
 bool AppleDecoderModule::sIsCoreMediaAvailable = false;
 bool AppleDecoderModule::sIsVTAvailable = false;
 bool AppleDecoderModule::sIsVTHWAvailable = false;
-bool AppleDecoderModule::sIsVDAAvailable = false;
 bool AppleDecoderModule::sCanUseHardwareVideoDecoder = true;
 
 AppleDecoderModule::AppleDecoderModule()
 {
 }
 
 AppleDecoderModule::~AppleDecoderModule()
 {
@@ -40,19 +37,16 @@ AppleDecoderModule::Init()
   if (sInitialized) {
     return;
   }
 
   // Ensure IOSurface framework is loaded.
   MacIOSurfaceLib::LoadLibrary();
   const bool loaded = MacIOSurfaceLib::isInit();
 
-  // dlopen VideoDecodeAcceleration.framework if it's available.
-  sIsVDAAvailable = loaded && AppleVDALinker::Link();
-
   // dlopen CoreMedia.framework if it's available.
   sIsCoreMediaAvailable = AppleCMLinker::Link();
   // dlopen VideoToolbox.framework if it's available.
   // We must link both CM and VideoToolbox framework to allow for proper
   // paired Link/Unlink calls
   bool haveVideoToolbox = loaded && AppleVTLinker::Link();
   sIsVTAvailable = sIsCoreMediaAvailable && haveVideoToolbox;
 
@@ -62,46 +56,30 @@ AppleDecoderModule::Init()
     gfxPlatform::GetPlatform()->CanUseHardwareVideoDecoding();
 
   sInitialized = true;
 }
 
 nsresult
 AppleDecoderModule::Startup()
 {
-  if (!sInitialized || (!sIsVDAAvailable && !sIsVTAvailable)) {
+  if (!sInitialized || !sIsVTAvailable) {
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
 already_AddRefed<MediaDataDecoder>
 AppleDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
 {
-  RefPtr<MediaDataDecoder> decoder;
-
-  if (sIsVDAAvailable && (!sIsVTHWAvailable || MediaPrefs::AppleForceVDA())) {
-    decoder =
-      AppleVDADecoder::CreateVDADecoder(aParams.VideoConfig(),
-                                        aParams.mTaskQueue,
-                                        aParams.mCallback,
-                                        aParams.mImageContainer);
-    if (decoder) {
-      return decoder.forget();
-    }
-  }
-  // We fallback here if VDA isn't available, or is available but isn't
-  // supported by the current platform.
-  if (sIsVTAvailable) {
-    decoder =
-      new AppleVTDecoder(aParams.VideoConfig(),
-                         aParams.mTaskQueue,
-                         aParams.mCallback,
-                         aParams.mImageContainer);
-  }
+  RefPtr<MediaDataDecoder> decoder =
+    new AppleVTDecoder(aParams.VideoConfig(),
+                       aParams.mTaskQueue,
+                       aParams.mCallback,
+                       aParams.mImageContainer);
   return decoder.forget();
 }
 
 already_AddRefed<MediaDataDecoder>
 AppleDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams)
 {
   RefPtr<MediaDataDecoder> decoder =
     new AppleATDecoder(aParams.AudioConfig(),
@@ -112,19 +90,18 @@ AppleDecoderModule::CreateAudioDecoder(c
 
 bool
 AppleDecoderModule::SupportsMimeType(const nsACString& aMimeType,
                                      DecoderDoctorDiagnostics* aDiagnostics) const
 {
   return (sIsCoreMediaAvailable &&
           (aMimeType.EqualsLiteral("audio/mpeg") ||
            aMimeType.EqualsLiteral("audio/mp4a-latm"))) ||
-    ((sIsVTAvailable || sIsVDAAvailable) &&
-     (aMimeType.EqualsLiteral("video/mp4") ||
-      aMimeType.EqualsLiteral("video/avc")));
+    (sIsVTAvailable && (aMimeType.EqualsLiteral("video/mp4") ||
+                        aMimeType.EqualsLiteral("video/avc")));
 }
 
 PlatformDecoderModule::ConversionRequired
 AppleDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
 {
   if (aConfig.IsVideo()) {
     return kNeedAVCC;
   } else {
--- a/dom/media/platforms/apple/AppleDecoderModule.h
+++ b/dom/media/platforms/apple/AppleDecoderModule.h
@@ -36,14 +36,13 @@ public:
 
   static bool sCanUseHardwareVideoDecoder;
 
 private:
   static bool sInitialized;
   static bool sIsCoreMediaAvailable;
   static bool sIsVTAvailable;
   static bool sIsVTHWAvailable;
-  static bool sIsVDAAvailable;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_AppleDecoderModule_h
deleted file mode 100644
--- a/dom/media/platforms/apple/AppleVDADecoder.cpp
+++ /dev/null
@@ -1,700 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <CoreFoundation/CFString.h>
-
-#include "AppleDecoderModule.h"
-#include "AppleUtils.h"
-#include "AppleVDADecoder.h"
-#include "AppleVDALinker.h"
-#include "MediaInfo.h"
-#include "mp4_demuxer/H264.h"
-#include "MP4Decoder.h"
-#include "MediaData.h"
-#include "mozilla/ArrayUtils.h"
-#include "mozilla/SyncRunnable.h"
-#include "nsThreadUtils.h"
-#include "mozilla/Logging.h"
-#include "VideoUtils.h"
-#include <algorithm>
-#include "gfxPlatform.h"
-
-#ifndef MOZ_WIDGET_UIKIT
-#include "MacIOSurfaceImage.h"
-#endif
-
-#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
-//#define LOG_MEDIA_SHA1
-
-namespace mozilla {
-
-static uint32_t ComputeMaxRefFrames(const MediaByteBuffer* aExtraData)
-{
-  uint32_t maxRefFrames = 4;
-  // Retrieve video dimensions from H264 SPS NAL.
-  mp4_demuxer::SPSData spsdata;
-  if (mp4_demuxer::H264::DecodeSPSFromExtraData(aExtraData, spsdata)) {
-    // max_num_ref_frames determines the size of the sliding window
-    // we need to queue that many frames in order to guarantee proper
-    // pts frames ordering. Use a minimum of 4 to ensure proper playback of
-    // non compliant videos.
-    maxRefFrames =
-      std::min(std::max(maxRefFrames, spsdata.max_num_ref_frames + 1), 16u);
-  }
-  return maxRefFrames;
-}
-
-AppleVDADecoder::AppleVDADecoder(const VideoInfo& aConfig,
-                                 TaskQueue* aTaskQueue,
-                                 MediaDataDecoderCallback* aCallback,
-                                 layers::ImageContainer* aImageContainer)
-  : mExtraData(aConfig.mExtraData)
-  , mCallback(aCallback)
-  , mPictureWidth(aConfig.mImage.width)
-  , mPictureHeight(aConfig.mImage.height)
-  , mDisplayWidth(aConfig.mDisplay.width)
-  , mDisplayHeight(aConfig.mDisplay.height)
-  , mQueuedSamples(0)
-  , mTaskQueue(aTaskQueue)
-  , mDecoder(nullptr)
-  , mMaxRefFrames(ComputeMaxRefFrames(aConfig.mExtraData))
-  , mImageContainer(aImageContainer)
-  , mInputIncoming(0)
-  , mIsShutDown(false)
-#ifdef MOZ_WIDGET_UIKIT
-  , mUseSoftwareImages(true)
-#else
-  , mUseSoftwareImages(false)
-#endif
-  , mMonitor("AppleVideoDecoder")
-  , mIsFlushing(false)
-{
-  MOZ_COUNT_CTOR(AppleVDADecoder);
-  // TODO: Verify aConfig.mime_type.
-
-  LOG("Creating AppleVDADecoder for %dx%d (%dx%d) h.264 video",
-      mPictureWidth,
-      mPictureHeight,
-      mDisplayWidth,
-      mDisplayHeight
-     );
-}
-
-AppleVDADecoder::~AppleVDADecoder()
-{
-  MOZ_COUNT_DTOR(AppleVDADecoder);
-}
-
-RefPtr<MediaDataDecoder::InitPromise>
-AppleVDADecoder::Init()
-{
-  return InitPromise::CreateAndResolve(TrackType::kVideoTrack, __func__);
-}
-
-nsresult
-AppleVDADecoder::Shutdown()
-{
-  MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown);
-  mIsShutDown = true;
-  if (mTaskQueue) {
-    nsCOMPtr<nsIRunnable> runnable =
-      NewRunnableMethod(this, &AppleVDADecoder::ProcessShutdown);
-    mTaskQueue->Dispatch(runnable.forget());
-  } else {
-    ProcessShutdown();
-  }
-  return NS_OK;
-}
-
-void
-AppleVDADecoder::ProcessShutdown()
-{
-  if (mDecoder) {
-    LOG("%s: cleaning up decoder %p", __func__, mDecoder);
-    VDADecoderDestroy(mDecoder);
-    mDecoder = nullptr;
-  }
-}
-
-nsresult
-AppleVDADecoder::Input(MediaRawData* aSample)
-{
-  MOZ_ASSERT(mCallback->OnReaderTaskQueue());
-
-  LOG("mp4 input sample %p pts %lld duration %lld us%s %d bytes",
-      aSample,
-      aSample->mTime,
-      aSample->mDuration,
-      aSample->mKeyframe ? " keyframe" : "",
-      aSample->Size());
-
-  mInputIncoming++;
-
-  mTaskQueue->Dispatch(NewRunnableMethod<RefPtr<MediaRawData>>(
-    this, &AppleVDADecoder::ProcessDecode, aSample));
-  return NS_OK;
-}
-
-nsresult
-AppleVDADecoder::Flush()
-{
-  MOZ_ASSERT(mCallback->OnReaderTaskQueue());
-  mIsFlushing = true;
-  nsCOMPtr<nsIRunnable> runnable =
-    NewRunnableMethod(this, &AppleVDADecoder::ProcessFlush);
-  SyncRunnable::DispatchToThread(mTaskQueue, runnable);
-  mIsFlushing = false;
-  // All ProcessDecode() tasks should be done.
-  MOZ_ASSERT(mInputIncoming == 0);
-
-  mSeekTargetThreshold.reset();
-
-  return NS_OK;
-}
-
-nsresult
-AppleVDADecoder::Drain()
-{
-  MOZ_ASSERT(mCallback->OnReaderTaskQueue());
-  nsCOMPtr<nsIRunnable> runnable =
-    NewRunnableMethod(this, &AppleVDADecoder::ProcessDrain);
-  mTaskQueue->Dispatch(runnable.forget());
-  return NS_OK;
-}
-
-void
-AppleVDADecoder::ProcessFlush()
-{
-  AssertOnTaskQueueThread();
-
-  OSStatus rv = VDADecoderFlush(mDecoder, 0 /*dont emit*/);
-  if (rv != noErr) {
-    LOG("AppleVDADecoder::Flush failed waiting for platform decoder "
-        "with error:%d.", rv);
-  }
-  ClearReorderedFrames();
-}
-
-void
-AppleVDADecoder::ProcessDrain()
-{
-  AssertOnTaskQueueThread();
-
-  OSStatus rv = VDADecoderFlush(mDecoder, kVDADecoderFlush_EmitFrames);
-  if (rv != noErr) {
-    LOG("AppleVDADecoder::Drain failed waiting for platform decoder "
-        "with error:%d.", rv);
-  }
-  DrainReorderedFrames();
-  mCallback->DrainComplete();
-}
-
-//
-// Implementation details.
-//
-
-// Callback passed to the VideoToolbox decoder for returning data.
-// This needs to be static because the API takes a C-style pair of
-// function and userdata pointers. This validates parameters and
-// forwards the decoded image back to an object method.
-static void
-PlatformCallback(void* decompressionOutputRefCon,
-                 CFDictionaryRef frameInfo,
-                 OSStatus status,
-                 VDADecodeInfoFlags infoFlags,
-                 CVImageBufferRef image)
-{
-  LOG("AppleVDADecoder[%s] status %d flags %d retainCount %ld",
-      __func__, status, infoFlags, CFGetRetainCount(frameInfo));
-
-  // Validate our arguments.
-  // According to Apple's TN2267
-  // The output callback is still called for all flushed frames,
-  // but no image buffers will be returned.
-  // FIXME: Distinguish between errors and empty flushed frames.
-  if (status != noErr || !image) {
-    NS_WARNING("AppleVDADecoder decoder returned no data");
-    image = nullptr;
-  } else if (infoFlags & kVDADecodeInfo_FrameDropped) {
-    NS_WARNING("  ...frame dropped...");
-    image = nullptr;
-  } else {
-    MOZ_ASSERT(image || CFGetTypeID(image) == CVPixelBufferGetTypeID(),
-               "AppleVDADecoder returned an unexpected image type");
-  }
-
-  AppleVDADecoder* decoder =
-    static_cast<AppleVDADecoder*>(decompressionOutputRefCon);
-
-  AutoCFRelease<CFNumberRef> ptsref =
-    (CFNumberRef)CFDictionaryGetValue(frameInfo, CFSTR("FRAME_PTS"));
-  AutoCFRelease<CFNumberRef> dtsref =
-    (CFNumberRef)CFDictionaryGetValue(frameInfo, CFSTR("FRAME_DTS"));
-  AutoCFRelease<CFNumberRef> durref =
-    (CFNumberRef)CFDictionaryGetValue(frameInfo, CFSTR("FRAME_DURATION"));
-  AutoCFRelease<CFNumberRef> boref =
-    (CFNumberRef)CFDictionaryGetValue(frameInfo, CFSTR("FRAME_OFFSET"));
-  AutoCFRelease<CFNumberRef> kfref =
-    (CFNumberRef)CFDictionaryGetValue(frameInfo, CFSTR("FRAME_KEYFRAME"));
-
-  int64_t dts;
-  int64_t pts;
-  int64_t duration;
-  int64_t byte_offset;
-  char is_sync_point;
-
-  CFNumberGetValue(ptsref, kCFNumberSInt64Type, &pts);
-  CFNumberGetValue(dtsref, kCFNumberSInt64Type, &dts);
-  CFNumberGetValue(durref, kCFNumberSInt64Type, &duration);
-  CFNumberGetValue(boref, kCFNumberSInt64Type, &byte_offset);
-  CFNumberGetValue(kfref, kCFNumberSInt8Type, &is_sync_point);
-
-  AppleVDADecoder::AppleFrameRef frameRef(
-      media::TimeUnit::FromMicroseconds(dts),
-      media::TimeUnit::FromMicroseconds(pts),
-      media::TimeUnit::FromMicroseconds(duration),
-      byte_offset,
-      is_sync_point == 1);
-
-  decoder->OutputFrame(image, frameRef);
-}
-
-AppleVDADecoder::AppleFrameRef*
-AppleVDADecoder::CreateAppleFrameRef(const MediaRawData* aSample)
-{
-  MOZ_ASSERT(aSample);
-  return new AppleFrameRef(*aSample);
-}
-
-void
-AppleVDADecoder::DrainReorderedFrames()
-{
-  MonitorAutoLock mon(mMonitor);
-  while (!mReorderQueue.IsEmpty()) {
-    mCallback->Output(mReorderQueue.Pop().get());
-  }
-  mQueuedSamples = 0;
-}
-
-void
-AppleVDADecoder::ClearReorderedFrames()
-{
-  MonitorAutoLock mon(mMonitor);
-  while (!mReorderQueue.IsEmpty()) {
-    mReorderQueue.Pop();
-  }
-  mQueuedSamples = 0;
-}
-
-void
-AppleVDADecoder::SetSeekThreshold(const media::TimeUnit& aTime)
-{
-  LOG("SetSeekThreshold %lld", aTime.ToMicroseconds());
-  mSeekTargetThreshold = Some(aTime);
-}
-
-// Copy and return a decoded frame.
-nsresult
-AppleVDADecoder::OutputFrame(CVPixelBufferRef aImage,
-                             AppleVDADecoder::AppleFrameRef aFrameRef)
-{
-  if (mIsShutDown || mIsFlushing) {
-    // We are in the process of flushing or shutting down; ignore frame.
-    return NS_OK;
-  }
-
-  LOG("mp4 output frame %lld dts %lld pts %lld duration %lld us%s",
-      aFrameRef.byte_offset,
-      aFrameRef.decode_timestamp.ToMicroseconds(),
-      aFrameRef.composition_timestamp.ToMicroseconds(),
-      aFrameRef.duration.ToMicroseconds(),
-      aFrameRef.is_sync_point ? " keyframe" : ""
-  );
-
-  if (mQueuedSamples > mMaxRefFrames) {
-    // We had stopped requesting more input because we had received too much at
-    // the time. We can ask for more once again.
-    mCallback->InputExhausted();
-  }
-  MOZ_ASSERT(mQueuedSamples);
-  mQueuedSamples--;
-
-  if (!aImage) {
-    // Image was dropped by decoder.
-    return NS_OK;
-  }
-
-  bool useNullSample = false;
-  if (mSeekTargetThreshold.isSome()) {
-    if ((aFrameRef.composition_timestamp + aFrameRef.duration) < mSeekTargetThreshold.ref()) {
-      useNullSample = true;
-    } else {
-      mSeekTargetThreshold.reset();
-    }
-  }
-
-  // Where our resulting image will end up.
-  RefPtr<MediaData> data;
-  // Bounds.
-  VideoInfo info;
-  info.mDisplay = nsIntSize(mDisplayWidth, mDisplayHeight);
-  gfx::IntRect visible = gfx::IntRect(0,
-                                      0,
-                                      mPictureWidth,
-                                      mPictureHeight);
-
-  if (useNullSample) {
-    data = new NullData(aFrameRef.byte_offset,
-                        aFrameRef.composition_timestamp.ToMicroseconds(),
-                        aFrameRef.duration.ToMicroseconds());
-  } else if (mUseSoftwareImages) {
-    size_t width = CVPixelBufferGetWidth(aImage);
-    size_t height = CVPixelBufferGetHeight(aImage);
-    DebugOnly<size_t> planes = CVPixelBufferGetPlaneCount(aImage);
-    MOZ_ASSERT(planes == 2, "Likely not NV12 format and it must be.");
-
-    VideoData::YCbCrBuffer buffer;
-
-    // Lock the returned image data.
-    CVReturn rv = CVPixelBufferLockBaseAddress(aImage, kCVPixelBufferLock_ReadOnly);
-    if (rv != kCVReturnSuccess) {
-      NS_ERROR("error locking pixel data");
-      mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
-      return NS_ERROR_FAILURE;
-    }
-    // Y plane.
-    buffer.mPlanes[0].mData =
-      static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 0));
-    buffer.mPlanes[0].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 0);
-    buffer.mPlanes[0].mWidth = width;
-    buffer.mPlanes[0].mHeight = height;
-    buffer.mPlanes[0].mOffset = 0;
-    buffer.mPlanes[0].mSkip = 0;
-    // Cb plane.
-    buffer.mPlanes[1].mData =
-      static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 1));
-    buffer.mPlanes[1].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 1);
-    buffer.mPlanes[1].mWidth = (width+1) / 2;
-    buffer.mPlanes[1].mHeight = (height+1) / 2;
-    buffer.mPlanes[1].mOffset = 0;
-    buffer.mPlanes[1].mSkip = 1;
-    // Cr plane.
-    buffer.mPlanes[2].mData =
-      static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 1));
-    buffer.mPlanes[2].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 1);
-    buffer.mPlanes[2].mWidth = (width+1) / 2;
-    buffer.mPlanes[2].mHeight = (height+1) / 2;
-    buffer.mPlanes[2].mOffset = 1;
-    buffer.mPlanes[2].mSkip = 1;
-
-    // Copy the image data into our own format.
-    data =
-      VideoData::Create(info,
-                        mImageContainer,
-                        nullptr,
-                        aFrameRef.byte_offset,
-                        aFrameRef.composition_timestamp.ToMicroseconds(),
-                        aFrameRef.duration.ToMicroseconds(),
-                        buffer,
-                        aFrameRef.is_sync_point,
-                        aFrameRef.decode_timestamp.ToMicroseconds(),
-                        visible);
-    // Unlock the returned image data.
-    CVPixelBufferUnlockBaseAddress(aImage, kCVPixelBufferLock_ReadOnly);
-  } else {
-#ifndef MOZ_WIDGET_UIKIT
-    IOSurfacePtr surface = MacIOSurfaceLib::CVPixelBufferGetIOSurface(aImage);
-    MOZ_ASSERT(surface, "Decoder didn't return an IOSurface backed buffer");
-
-    RefPtr<MacIOSurface> macSurface = new MacIOSurface(surface);
-
-    RefPtr<layers::Image> image = new MacIOSurfaceImage(macSurface);
-
-    data =
-      VideoData::CreateFromImage(info,
-                                 mImageContainer,
-                                 aFrameRef.byte_offset,
-                                 aFrameRef.composition_timestamp.ToMicroseconds(),
-                                 aFrameRef.duration.ToMicroseconds(),
-                                 image.forget(),
-                                 aFrameRef.is_sync_point,
-                                 aFrameRef.decode_timestamp.ToMicroseconds(),
-                                 visible);
-#else
-    MOZ_ASSERT_UNREACHABLE("No MacIOSurface on iOS");
-#endif
-  }
-
-  if (!data) {
-    NS_ERROR("Couldn't create VideoData for frame");
-    mCallback->Error(MediaDataDecoderError::FATAL_ERROR);
-    return NS_ERROR_FAILURE;
-  }
-
-  // Frames come out in DTS order but we need to output them
-  // in composition order.
-  MonitorAutoLock mon(mMonitor);
-  mReorderQueue.Push(data);
-  while (mReorderQueue.Length() > mMaxRefFrames) {
-    mCallback->Output(mReorderQueue.Pop().get());
-  }
-  LOG("%llu decoded frames queued",
-      static_cast<unsigned long long>(mReorderQueue.Length()));
-
-  return NS_OK;
-}
-
-nsresult
-AppleVDADecoder::ProcessDecode(MediaRawData* aSample)
-{
-  AssertOnTaskQueueThread();
-
-  mInputIncoming--;
-
-  if (mIsFlushing) {
-    return NS_OK;
-  }
-
-  auto rv = DoDecode(aSample);
-  // Ask for more data.
-  if (NS_SUCCEEDED(rv) && !mInputIncoming && mQueuedSamples <= mMaxRefFrames) {
-    LOG("%s task queue empty; requesting more data", GetDescriptionName());
-    mCallback->InputExhausted();
-  }
-
-  return rv;
-}
-
-nsresult
-AppleVDADecoder::DoDecode(MediaRawData* aSample)
-{
-  AssertOnTaskQueueThread();
-
-  AutoCFRelease<CFDataRef> block =
-    CFDataCreate(kCFAllocatorDefault, aSample->Data(), aSample->Size());
-  if (!block) {
-    NS_ERROR("Couldn't create CFData");
-    return NS_ERROR_FAILURE;
-  }
-
-  AutoCFRelease<CFNumberRef> pts =
-    CFNumberCreate(kCFAllocatorDefault,
-                   kCFNumberSInt64Type,
-                   &aSample->mTime);
-  AutoCFRelease<CFNumberRef> dts =
-    CFNumberCreate(kCFAllocatorDefault,
-                   kCFNumberSInt64Type,
-                   &aSample->mTimecode);
-  AutoCFRelease<CFNumberRef> duration =
-    CFNumberCreate(kCFAllocatorDefault,
-                   kCFNumberSInt64Type,
-                   &aSample->mDuration);
-  AutoCFRelease<CFNumberRef> byte_offset =
-    CFNumberCreate(kCFAllocatorDefault,
-                   kCFNumberSInt64Type,
-                   &aSample->mOffset);
-  char keyframe = aSample->mKeyframe ? 1 : 0;
-  AutoCFRelease<CFNumberRef> cfkeyframe =
-    CFNumberCreate(kCFAllocatorDefault,
-                   kCFNumberSInt8Type,
-                   &keyframe);
-
-  const void* keys[] = { CFSTR("FRAME_PTS"),
-                         CFSTR("FRAME_DTS"),
-                         CFSTR("FRAME_DURATION"),
-                         CFSTR("FRAME_OFFSET"),
-                         CFSTR("FRAME_KEYFRAME") };
-  const void* values[] = { pts,
-                           dts,
-                           duration,
-                           byte_offset,
-                           cfkeyframe };
-  static_assert(ArrayLength(keys) == ArrayLength(values),
-                "Non matching keys/values array size");
-
-  AutoCFRelease<CFDictionaryRef> frameInfo =
-    CFDictionaryCreate(kCFAllocatorDefault,
-                       keys,
-                       values,
-                       ArrayLength(keys),
-                       &kCFTypeDictionaryKeyCallBacks,
-                       &kCFTypeDictionaryValueCallBacks);
-
-  mQueuedSamples++;
-
-  OSStatus rv = VDADecoderDecode(mDecoder,
-                                 0,
-                                 block,
-                                 frameInfo);
-
-  if (rv != noErr) {
-    NS_WARNING("AppleVDADecoder: Couldn't pass frame to decoder");
-    mCallback->Error(MediaDataDecoderError::FATAL_ERROR);
-    return NS_ERROR_FAILURE;
-  }
-
-  return NS_OK;
-}
-
-nsresult
-AppleVDADecoder::InitializeSession()
-{
-  OSStatus rv;
-
-  AutoCFRelease<CFDictionaryRef> decoderConfig =
-    CreateDecoderSpecification();
-
-  AutoCFRelease<CFDictionaryRef> outputConfiguration =
-    CreateOutputConfiguration();
-
-  rv =
-    VDADecoderCreate(decoderConfig,
-                     outputConfiguration,
-                     (VDADecoderOutputCallback*)PlatformCallback,
-                     this,
-                     &mDecoder);
-
-  if (rv != noErr) {
-    NS_WARNING("AppleVDADecoder: Couldn't create hardware VDA decoder");
-    return NS_ERROR_FAILURE;
-  }
-
-  return NS_OK;
-}
-
-CFDictionaryRef
-AppleVDADecoder::CreateDecoderSpecification()
-{
-  const uint8_t* extradata = mExtraData->Elements();
-  int extrasize = mExtraData->Length();
-
-  OSType format = 'avc1';
-  AutoCFRelease<CFNumberRef> avc_width  =
-    CFNumberCreate(kCFAllocatorDefault,
-                   kCFNumberSInt32Type,
-                   &mPictureWidth);
-  AutoCFRelease<CFNumberRef> avc_height =
-    CFNumberCreate(kCFAllocatorDefault,
-                   kCFNumberSInt32Type,
-                   &mPictureHeight);
-  AutoCFRelease<CFNumberRef> avc_format =
-    CFNumberCreate(kCFAllocatorDefault,
-                   kCFNumberSInt32Type,
-                   &format);
-  AutoCFRelease<CFDataRef> avc_data =
-    CFDataCreate(kCFAllocatorDefault,
-                 extradata,
-                 extrasize);
-
-  const void* decoderKeys[] = { AppleVDALinker::skPropWidth,
-                                AppleVDALinker::skPropHeight,
-                                AppleVDALinker::skPropSourceFormat,
-                                AppleVDALinker::skPropAVCCData };
-  const void* decoderValue[] = { avc_width,
-                                 avc_height,
-                                 avc_format,
-                                 avc_data };
-  static_assert(ArrayLength(decoderKeys) == ArrayLength(decoderValue),
-                "Non matching keys/values array size");
-
-  return CFDictionaryCreate(kCFAllocatorDefault,
-                            decoderKeys,
-                            decoderValue,
-                            ArrayLength(decoderKeys),
-                            &kCFTypeDictionaryKeyCallBacks,
-                            &kCFTypeDictionaryValueCallBacks);
-}
-
-CFDictionaryRef
-AppleVDADecoder::CreateOutputConfiguration()
-{
-  if (mUseSoftwareImages) {
-    // Output format type:
-    SInt32 PixelFormatTypeValue =
-      kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
-    AutoCFRelease<CFNumberRef> PixelFormatTypeNumber =
-      CFNumberCreate(kCFAllocatorDefault,
-                     kCFNumberSInt32Type,
-                     &PixelFormatTypeValue);
-    const void* outputKeys[] = { kCVPixelBufferPixelFormatTypeKey };
-    const void* outputValues[] = { PixelFormatTypeNumber };
-    static_assert(ArrayLength(outputKeys) == ArrayLength(outputValues),
-                  "Non matching keys/values array size");
-
-    return CFDictionaryCreate(kCFAllocatorDefault,
-                              outputKeys,
-                              outputValues,
-                              ArrayLength(outputKeys),
-                              &kCFTypeDictionaryKeyCallBacks,
-                              &kCFTypeDictionaryValueCallBacks);
-  }
-
-#ifndef MOZ_WIDGET_UIKIT
-  // Output format type:
-  SInt32 PixelFormatTypeValue = kCVPixelFormatType_422YpCbCr8;
-  AutoCFRelease<CFNumberRef> PixelFormatTypeNumber =
-    CFNumberCreate(kCFAllocatorDefault,
-                   kCFNumberSInt32Type,
-                   &PixelFormatTypeValue);
-  // Construct IOSurface Properties
-  const void* IOSurfaceKeys[] = { MacIOSurfaceLib::kPropIsGlobal };
-  const void* IOSurfaceValues[] = { kCFBooleanTrue };
-  static_assert(ArrayLength(IOSurfaceKeys) == ArrayLength(IOSurfaceValues),
-                "Non matching keys/values array size");
-
-  // Contruct output configuration.
-  AutoCFRelease<CFDictionaryRef> IOSurfaceProperties =
-    CFDictionaryCreate(kCFAllocatorDefault,
-                       IOSurfaceKeys,
-                       IOSurfaceValues,
-                       ArrayLength(IOSurfaceKeys),
-                       &kCFTypeDictionaryKeyCallBacks,
-                       &kCFTypeDictionaryValueCallBacks);
-
-  const void* outputKeys[] = { kCVPixelBufferIOSurfacePropertiesKey,
-                               kCVPixelBufferPixelFormatTypeKey,
-                               kCVPixelBufferOpenGLCompatibilityKey };
-  const void* outputValues[] = { IOSurfaceProperties,
-                                 PixelFormatTypeNumber,
-                                 kCFBooleanTrue };
-  static_assert(ArrayLength(outputKeys) == ArrayLength(outputValues),
-                "Non matching keys/values array size");
-
-  return CFDictionaryCreate(kCFAllocatorDefault,
-                            outputKeys,
-                            outputValues,
-                            ArrayLength(outputKeys),
-                            &kCFTypeDictionaryKeyCallBacks,
-                            &kCFTypeDictionaryValueCallBacks);
-#else
-  MOZ_ASSERT_UNREACHABLE("No MacIOSurface on iOS");
-#endif
-}
-
-/* static */
-already_AddRefed<AppleVDADecoder>
-AppleVDADecoder::CreateVDADecoder(
-  const VideoInfo& aConfig,
-  TaskQueue* aTaskQueue,
-  MediaDataDecoderCallback* aCallback,
-  layers::ImageContainer* aImageContainer)
-{
-  if (!AppleDecoderModule::sCanUseHardwareVideoDecoder) {
-    // This GPU is blacklisted for hardware decoding.
-    return nullptr;
-  }
-
-  RefPtr<AppleVDADecoder> decoder =
-    new AppleVDADecoder(aConfig, aTaskQueue, aCallback, aImageContainer);
-
-  if (NS_FAILED(decoder->InitializeSession())) {
-    return nullptr;
-  }
-
-  return decoder.forget();
-}
-
-} // namespace mozilla
deleted file mode 100644
--- a/dom/media/platforms/apple/AppleVDADecoder.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_AppleVDADecoder_h
-#define mozilla_AppleVDADecoder_h
-
-#include "PlatformDecoderModule.h"
-#include "mozilla/Atomics.h"
-#include "mozilla/ReentrantMonitor.h"
-#include "MP4Decoder.h"
-#include "nsIThread.h"
-#include "ReorderQueue.h"
-#include "TimeUnits.h"
-
-#include "VideoDecodeAcceleration/VDADecoder.h"
-
-namespace mozilla {
-
-class TaskQueue;
-class MediaDataDecoderCallback;
-namespace layers {
-  class ImageContainer;
-} // namespace layers
-
-class AppleVDADecoder : public MediaDataDecoder {
-public:
-  class AppleFrameRef {
-  public:
-    media::TimeUnit decode_timestamp;
-    media::TimeUnit composition_timestamp;
-    media::TimeUnit duration;
-    int64_t byte_offset;
-    bool is_sync_point;
-
-    explicit AppleFrameRef(const MediaRawData& aSample)
-      : decode_timestamp(media::TimeUnit::FromMicroseconds(aSample.mTimecode))
-      , composition_timestamp(media::TimeUnit::FromMicroseconds(aSample.mTime))
-      , duration(media::TimeUnit::FromMicroseconds(aSample.mDuration))
-      , byte_offset(aSample.mOffset)
-      , is_sync_point(aSample.mKeyframe)
-    {
-    }
-
-    AppleFrameRef(const media::TimeUnit& aDts,
-                  const media::TimeUnit& aPts,
-                  const media::TimeUnit& aDuration,
-                  int64_t aByte_offset,
-                  bool aIs_sync_point)
-      : decode_timestamp(aDts)
-      , composition_timestamp(aPts)
-      , duration(aDuration)
-      , byte_offset(aByte_offset)
-      , is_sync_point(aIs_sync_point)
-    {
-    }
-  };
-
-  // Return a new created AppleVDADecoder or nullptr if media or hardware is
-  // not supported by current configuration.
-  static already_AddRefed<AppleVDADecoder> CreateVDADecoder(
-    const VideoInfo& aConfig,
-    TaskQueue* aTaskQueue,
-    MediaDataDecoderCallback* aCallback,
-    layers::ImageContainer* aImageContainer);
-
-  // Access from the taskqueue and the decoder's thread.
-  // OutputFrame is thread-safe.
-  nsresult OutputFrame(CVPixelBufferRef aImage,
-                       AppleFrameRef aFrameRef);
-
-  RefPtr<InitPromise> Init() override;
-  nsresult Input(MediaRawData* aSample) override;
-  nsresult Flush() override;
-  nsresult Drain() override;
-  nsresult Shutdown() override;
-  bool IsHardwareAccelerated(nsACString& aFailureReason) const override
-  {
-    return true;
-  }
-
-  const char* GetDescriptionName() const override
-  {
-    return "apple VDA decoder";
-  }
-
-  void SetSeekThreshold(const media::TimeUnit& aTime) override;
-
-protected:
-  AppleVDADecoder(const VideoInfo& aConfig,
-                  TaskQueue* aTaskQueue,
-                  MediaDataDecoderCallback* aCallback,
-                  layers::ImageContainer* aImageContainer);
-  virtual ~AppleVDADecoder();
-
-  void AssertOnTaskQueueThread()
-  {
-    MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
-  }
-
-  AppleFrameRef* CreateAppleFrameRef(const MediaRawData* aSample);
-  void DrainReorderedFrames();
-  void ClearReorderedFrames();
-  CFDictionaryRef CreateOutputConfiguration();
-
-  const RefPtr<MediaByteBuffer> mExtraData;
-  MediaDataDecoderCallback* mCallback;
-  const uint32_t mPictureWidth;
-  const uint32_t mPictureHeight;
-  const uint32_t mDisplayWidth;
-  const uint32_t mDisplayHeight;
-
-  // Number of times a sample was queued via Input(). Will be decreased upon
-  // the decoder's callback being invoked.
-  // This is used to calculate how many frames has been buffered by the decoder.
-  Atomic<uint32_t> mQueuedSamples;
-
-private:
-  // Flush and Drain operation, always run
-  virtual void ProcessFlush();
-  virtual void ProcessDrain();
-  virtual void ProcessShutdown();
-
-  const RefPtr<TaskQueue> mTaskQueue;
-  VDADecoder mDecoder;
-  const uint32_t mMaxRefFrames;
-  const RefPtr<layers::ImageContainer> mImageContainer;
-  // Increased when Input is called, and decreased when ProcessFrame runs.
-  // Reaching 0 indicates that there's no pending Input.
-  Atomic<uint32_t> mInputIncoming;
-  Atomic<bool> mIsShutDown;
-  const bool mUseSoftwareImages;
-
-  // Protects mReorderQueue.
-  Monitor mMonitor;
-  // Set on reader/decode thread calling Flush() to indicate that output is
-  // not required and so input samples on mTaskQueue need not be processed.
-  // Cleared on mTaskQueue in ProcessDrain().
-  Atomic<bool> mIsFlushing;
-  ReorderQueue mReorderQueue;
-  // Decoded frame will be dropped if its pts is smaller than this
-  // value. It shold be initialized before Input() or after Flush(). So it is
-  // safe to access it in OutputFrame without protecting.
-  Maybe<media::TimeUnit> mSeekTargetThreshold;
-
-  // Method to set up the decompression session.
-  nsresult InitializeSession();
-
-  // Method to pass a frame to VideoToolbox for decoding.
-  nsresult ProcessDecode(MediaRawData* aSample);
-  virtual nsresult DoDecode(MediaRawData* aSample);
-  CFDictionaryRef CreateDecoderSpecification();
-};
-
-} // namespace mozilla
-
-#endif // mozilla_AppleVDADecoder_h
deleted file mode 100644
--- a/dom/media/platforms/apple/AppleVDAFunctions.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// Construct references to each of the VDA symbols we use.
-
-LINK_FUNC(VDADecoderCreate)
-LINK_FUNC(VDADecoderDecode)
-LINK_FUNC(VDADecoderFlush)
-LINK_FUNC(VDADecoderDestroy)
deleted file mode 100644
--- a/dom/media/platforms/apple/AppleVDALinker.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <dlfcn.h>
-
-#include "AppleVDALinker.h"
-#include "nsDebug.h"
-
-#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
-
-namespace mozilla {
-
-AppleVDALinker::LinkStatus
-AppleVDALinker::sLinkStatus = LinkStatus_INIT;
-
-void* AppleVDALinker::sLink = nullptr;
-CFStringRef AppleVDALinker::skPropWidth = nullptr;
-CFStringRef AppleVDALinker::skPropHeight = nullptr;
-CFStringRef AppleVDALinker::skPropSourceFormat = nullptr;
-CFStringRef AppleVDALinker::skPropAVCCData = nullptr;
-
-#define LINK_FUNC(func) typeof(func) func;
-#include "AppleVDAFunctions.h"
-#undef LINK_FUNC
-
-/* static */ bool
-AppleVDALinker::Link()
-{
-  if (sLinkStatus) {
-    return sLinkStatus == LinkStatus_SUCCEEDED;
-  }
-
-  const char* dlname =
-    "/System/Library/Frameworks/VideoDecodeAcceleration.framework/VideoDecodeAcceleration";
-
-  if (!(sLink = dlopen(dlname, RTLD_NOW | RTLD_LOCAL))) {
-    NS_WARNING("Couldn't load VideoDecodeAcceleration framework");
-    goto fail;
-  }
-
-#define LINK_FUNC(func)                                                   \
-  func = (typeof(func))dlsym(sLink, #func);                               \
-  if (!func) {                                                            \
-    NS_WARNING("Couldn't load VideoDecodeAcceleration function " #func ); \
-    goto fail;                                                            \
-  }
-#include "AppleVDAFunctions.h"
-#undef LINK_FUNC
-
-  skPropWidth = GetIOConst("kVDADecoderConfiguration_Width");
-  skPropHeight = GetIOConst("kVDADecoderConfiguration_Height");
-  skPropSourceFormat = GetIOConst("kVDADecoderConfiguration_SourceFormat");
-  skPropAVCCData = GetIOConst("kVDADecoderConfiguration_avcCData");
-
-  if (!skPropWidth || !skPropHeight || !skPropSourceFormat || !skPropAVCCData) {
-    goto fail;
-  }
-
-  LOG("Loaded VideoDecodeAcceleration framework.");
-  sLinkStatus = LinkStatus_SUCCEEDED;
-  return true;
-
-fail:
-  Unlink();
-
-  sLinkStatus = LinkStatus_FAILED;
-  return false;
-}
-
-/* static */ void
-AppleVDALinker::Unlink()
-{
-  if (sLink) {
-    LOG("Unlinking VideoDecodeAcceleration framework.");
-#define LINK_FUNC(func)                                                   \
-    func = nullptr;
-#include "AppleVDAFunctions.h"
-#undef LINK_FUNC
-    dlclose(sLink);
-    sLink = nullptr;
-    skPropWidth = nullptr;
-    skPropHeight = nullptr;
-    skPropSourceFormat = nullptr;
-    skPropAVCCData = nullptr;
-    sLinkStatus = LinkStatus_INIT;
-  }
-}
-
-/* static */ CFStringRef
-AppleVDALinker::GetIOConst(const char* symbol)
-{
-  CFStringRef* address = (CFStringRef*)dlsym(sLink, symbol);
-  if (!address) {
-    return nullptr;
-  }
-
-  return *address;
-}
-
-} // namespace mozilla
deleted file mode 100644
--- a/dom/media/platforms/apple/AppleVDALinker.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef AppleVDALinker_h
-#define AppleVDALinker_h
-
-extern "C" {
-#pragma GCC visibility push(default)
-#include "VideoDecodeAcceleration/VDADecoder.h"
-#pragma GCC visibility pop
-}
-
-#include "nscore.h"
-
-namespace mozilla {
-
-class AppleVDALinker
-{
-public:
-  static bool Link();
-  static void Unlink();
-  static CFStringRef skPropWidth;
-  static CFStringRef skPropHeight;
-  static CFStringRef skPropSourceFormat;
-  static CFStringRef skPropAVCCData;
-
-private:
-  static void* sLink;
-  static nsrefcnt sRefCount;
-
-  static enum LinkStatus {
-    LinkStatus_INIT = 0,
-    LinkStatus_FAILED,
-    LinkStatus_SUCCEEDED
-  } sLinkStatus;
-
-  static CFStringRef GetIOConst(const char* symbol);
-};
-
-#define LINK_FUNC(func) extern typeof(func)* func;
-#include "AppleVDAFunctions.h"
-#undef LINK_FUNC
-
-} // namespace mozilla
-
-#endif // AppleVDALinker_h
--- a/dom/media/platforms/apple/AppleVTDecoder.cpp
+++ b/dom/media/platforms/apple/AppleVTDecoder.cpp
@@ -19,21 +19,55 @@
 #include "mozilla/Logging.h"
 #include "VideoUtils.h"
 #include "gfxPlatform.h"
 
 #define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
 
 namespace mozilla {
 
+static uint32_t ComputeMaxRefFrames(const MediaByteBuffer* aExtraData)
+{
+  uint32_t maxRefFrames = 4;
+  // Retrieve video dimensions from H264 SPS NAL.
+  mp4_demuxer::SPSData spsdata;
+  if (mp4_demuxer::H264::DecodeSPSFromExtraData(aExtraData, spsdata)) {
+    // max_num_ref_frames determines the size of the sliding window
+    // we need to queue that many frames in order to guarantee proper
+    // pts frames ordering. Use a minimum of 4 to ensure proper playback of
+    // non compliant videos.
+    maxRefFrames =
+      std::min(std::max(maxRefFrames, spsdata.max_num_ref_frames + 1), 16u);
+  }
+  return maxRefFrames;
+}
+
 AppleVTDecoder::AppleVTDecoder(const VideoInfo& aConfig,
                                TaskQueue* aTaskQueue,
                                MediaDataDecoderCallback* aCallback,
                                layers::ImageContainer* aImageContainer)
-  : AppleVDADecoder(aConfig, aTaskQueue, aCallback, aImageContainer)
+  : mExtraData(aConfig.mExtraData)
+  , mCallback(aCallback)
+  , mPictureWidth(aConfig.mImage.width)
+  , mPictureHeight(aConfig.mImage.height)
+  , mDisplayWidth(aConfig.mDisplay.width)
+  , mDisplayHeight(aConfig.mDisplay.height)
+  , mQueuedSamples(0)
+  , mTaskQueue(aTaskQueue)
+  , mMaxRefFrames(ComputeMaxRefFrames(aConfig.mExtraData))
+  , mImageContainer(aImageContainer)
+  , mInputIncoming(0)
+  , mIsShutDown(false)
+#ifdef MOZ_WIDGET_UIKIT
+  , mUseSoftwareImages(true)
+#else
+  , mUseSoftwareImages(false)
+#endif
+  , mIsFlushing(false)
+  , mMonitor("AppleVideoDecoder")
   , mFormat(nullptr)
   , mSession(nullptr)
   , mIsHardwareAccelerated(false)
 {
   MOZ_COUNT_CTOR(AppleVTDecoder);
   // TODO: Verify aConfig.mime_type.
   LOG("Creating AppleVTDecoder for %dx%d h.264 video",
       mDisplayWidth,
@@ -53,16 +87,98 @@ AppleVTDecoder::Init()
 
   if (NS_SUCCEEDED(rv)) {
     return InitPromise::CreateAndResolve(TrackType::kVideoTrack, __func__);
   }
 
   return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
 }
 
+nsresult
+AppleVTDecoder::Input(MediaRawData* aSample)
+{
+  MOZ_ASSERT(mCallback->OnReaderTaskQueue());
+
+  LOG("mp4 input sample %p pts %lld duration %lld us%s %d bytes",
+      aSample,
+      aSample->mTime,
+      aSample->mDuration,
+      aSample->mKeyframe ? " keyframe" : "",
+      aSample->Size());
+
+  mInputIncoming++;
+
+  mTaskQueue->Dispatch(NewRunnableMethod<RefPtr<MediaRawData>>(
+    this, &AppleVTDecoder::ProcessDecode, aSample));
+  return NS_OK;
+}
+
+nsresult
+AppleVTDecoder::Flush()
+{
+  MOZ_ASSERT(mCallback->OnReaderTaskQueue());
+  mIsFlushing = true;
+  nsCOMPtr<nsIRunnable> runnable =
+    NewRunnableMethod(this, &AppleVTDecoder::ProcessFlush);
+  SyncRunnable::DispatchToThread(mTaskQueue, runnable);
+  mIsFlushing = false;
+  // All ProcessDecode() tasks should be done.
+  MOZ_ASSERT(mInputIncoming == 0);
+
+  mSeekTargetThreshold.reset();
+
+  return NS_OK;
+}
+
+nsresult
+AppleVTDecoder::Drain()
+{
+  MOZ_ASSERT(mCallback->OnReaderTaskQueue());
+  nsCOMPtr<nsIRunnable> runnable =
+    NewRunnableMethod(this, &AppleVTDecoder::ProcessDrain);
+  mTaskQueue->Dispatch(runnable.forget());
+  return NS_OK;
+}
+
+nsresult
+AppleVTDecoder::Shutdown()
+{
+  MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown);
+  mIsShutDown = true;
+  if (mTaskQueue) {
+    nsCOMPtr<nsIRunnable> runnable =
+      NewRunnableMethod(this, &AppleVTDecoder::ProcessShutdown);
+    mTaskQueue->Dispatch(runnable.forget());
+  } else {
+    ProcessShutdown();
+  }
+  return NS_OK;
+}
+
+nsresult
+AppleVTDecoder::ProcessDecode(MediaRawData* aSample)
+{
+  AssertOnTaskQueueThread();
+
+  mInputIncoming--;
+
+  if (mIsFlushing) {
+    return NS_OK;
+  }
+
+  auto rv = DoDecode(aSample);
+  // Ask for more data.
+  if (NS_SUCCEEDED(rv) && !mInputIncoming && mQueuedSamples <= mMaxRefFrames) {
+    LOG("%s task queue empty; requesting more data", GetDescriptionName());
+    mCallback->InputExhausted();
+  }
+
+  return rv;
+}
+
 void
 AppleVTDecoder::ProcessShutdown()
 {
   if (mSession) {
     LOG("%s: cleaning up session %p", __func__, mSession);
     VTDecompressionSessionInvalidate(mSession);
     CFRelease(mSession);
     mSession = nullptr;
@@ -94,16 +210,50 @@ AppleVTDecoder::ProcessDrain()
   if (NS_FAILED(rv)) {
     LOG("AppleVTDecoder::Drain failed waiting for platform decoder "
         "with error:%d.", rv);
   }
   DrainReorderedFrames();
   mCallback->DrainComplete();
 }
 
+AppleVTDecoder::AppleFrameRef*
+AppleVTDecoder::CreateAppleFrameRef(const MediaRawData* aSample)
+{
+  MOZ_ASSERT(aSample);
+  return new AppleFrameRef(*aSample);
+}
+
+void
+AppleVTDecoder::DrainReorderedFrames()
+{
+  MonitorAutoLock mon(mMonitor);
+  while (!mReorderQueue.IsEmpty()) {
+    mCallback->Output(mReorderQueue.Pop().get());
+  }
+  mQueuedSamples = 0;
+}
+
+void
+AppleVTDecoder::ClearReorderedFrames()
+{
+  MonitorAutoLock mon(mMonitor);
+  while (!mReorderQueue.IsEmpty()) {
+    mReorderQueue.Pop();
+  }
+  mQueuedSamples = 0;
+}
+
+void
+AppleVTDecoder::SetSeekThreshold(const media::TimeUnit& aTime)
+{
+  LOG("SetSeekThreshold %lld", aTime.ToMicroseconds());
+  mSeekTargetThreshold = Some(aTime);
+}
+
 //
 // Implementation details.
 //
 
 // Callback passed to the VideoToolbox decoder for returning data.
 // This needs to be static because the API takes a C-style pair of
 // function and userdata pointers. This validates parameters and
 // forwards the decoded image back to an object method.
@@ -131,16 +281,167 @@ PlatformCallback(void* decompressionOutp
     NS_WARNING("  ...frame tagged as dropped...");
   } else {
     MOZ_ASSERT(CFGetTypeID(image) == CVPixelBufferGetTypeID(),
       "VideoToolbox returned an unexpected image type");
   }
   decoder->OutputFrame(image, *frameRef);
 }
 
+// Copy and return a decoded frame.
+nsresult
+AppleVTDecoder::OutputFrame(CVPixelBufferRef aImage,
+                            AppleVTDecoder::AppleFrameRef aFrameRef)
+{
+  if (mIsShutDown || mIsFlushing) {
+    // We are in the process of flushing or shutting down; ignore frame.
+    return NS_OK;
+  }
+
+  LOG("mp4 output frame %lld dts %lld pts %lld duration %lld us%s",
+      aFrameRef.byte_offset,
+      aFrameRef.decode_timestamp.ToMicroseconds(),
+      aFrameRef.composition_timestamp.ToMicroseconds(),
+      aFrameRef.duration.ToMicroseconds(),
+      aFrameRef.is_sync_point ? " keyframe" : ""
+  );
+
+  if (mQueuedSamples > mMaxRefFrames) {
+    // We had stopped requesting more input because we had received too much at
+    // the time. We can ask for more once again.
+    mCallback->InputExhausted();
+  }
+  MOZ_ASSERT(mQueuedSamples);
+  mQueuedSamples--;
+
+  if (!aImage) {
+    // Image was dropped by decoder.
+    return NS_OK;
+  }
+
+  bool useNullSample = false;
+  if (mSeekTargetThreshold.isSome()) {
+    if ((aFrameRef.composition_timestamp + aFrameRef.duration) < mSeekTargetThreshold.ref()) {
+      useNullSample = true;
+    } else {
+      mSeekTargetThreshold.reset();
+    }
+  }
+
+  // Where our resulting image will end up.
+  RefPtr<MediaData> data;
+  // Bounds.
+  VideoInfo info;
+  info.mDisplay = nsIntSize(mDisplayWidth, mDisplayHeight);
+  gfx::IntRect visible = gfx::IntRect(0,
+                                      0,
+                                      mPictureWidth,
+                                      mPictureHeight);
+
+  if (useNullSample) {
+    data = new NullData(aFrameRef.byte_offset,
+                        aFrameRef.composition_timestamp.ToMicroseconds(),
+                        aFrameRef.duration.ToMicroseconds());
+  } else if (mUseSoftwareImages) {
+    size_t width = CVPixelBufferGetWidth(aImage);
+    size_t height = CVPixelBufferGetHeight(aImage);
+    DebugOnly<size_t> planes = CVPixelBufferGetPlaneCount(aImage);
+    MOZ_ASSERT(planes == 2, "Likely not NV12 format and it must be.");
+
+    VideoData::YCbCrBuffer buffer;
+
+    // Lock the returned image data.
+    CVReturn rv = CVPixelBufferLockBaseAddress(aImage, kCVPixelBufferLock_ReadOnly);
+    if (rv != kCVReturnSuccess) {
+      NS_ERROR("error locking pixel data");
+      mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
+      return NS_ERROR_FAILURE;
+    }
+    // Y plane.
+    buffer.mPlanes[0].mData =
+      static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 0));
+    buffer.mPlanes[0].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 0);
+    buffer.mPlanes[0].mWidth = width;
+    buffer.mPlanes[0].mHeight = height;
+    buffer.mPlanes[0].mOffset = 0;
+    buffer.mPlanes[0].mSkip = 0;
+    // Cb plane.
+    buffer.mPlanes[1].mData =
+      static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 1));
+    buffer.mPlanes[1].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 1);
+    buffer.mPlanes[1].mWidth = (width+1) / 2;
+    buffer.mPlanes[1].mHeight = (height+1) / 2;
+    buffer.mPlanes[1].mOffset = 0;
+    buffer.mPlanes[1].mSkip = 1;
+    // Cr plane.
+    buffer.mPlanes[2].mData =
+      static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 1));
+    buffer.mPlanes[2].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 1);
+    buffer.mPlanes[2].mWidth = (width+1) / 2;
+    buffer.mPlanes[2].mHeight = (height+1) / 2;
+    buffer.mPlanes[2].mOffset = 1;
+    buffer.mPlanes[2].mSkip = 1;
+
+    // Copy the image data into our own format.
+    data =
+      VideoData::Create(info,
+                        mImageContainer,
+                        nullptr,
+                        aFrameRef.byte_offset,
+                        aFrameRef.composition_timestamp.ToMicroseconds(),
+                        aFrameRef.duration.ToMicroseconds(),
+                        buffer,
+                        aFrameRef.is_sync_point,
+                        aFrameRef.decode_timestamp.ToMicroseconds(),
+                        visible);
+    // Unlock the returned image data.
+    CVPixelBufferUnlockBaseAddress(aImage, kCVPixelBufferLock_ReadOnly);
+  } else {
+#ifndef MOZ_WIDGET_UIKIT
+    IOSurfacePtr surface = MacIOSurfaceLib::CVPixelBufferGetIOSurface(aImage);
+    MOZ_ASSERT(surface, "Decoder didn't return an IOSurface backed buffer");
+
+    RefPtr<MacIOSurface> macSurface = new MacIOSurface(surface);
+
+    RefPtr<layers::Image> image = new MacIOSurfaceImage(macSurface);
+
+    data =
+      VideoData::CreateFromImage(info,
+                                 mImageContainer,
+                                 aFrameRef.byte_offset,
+                                 aFrameRef.composition_timestamp.ToMicroseconds(),
+                                 aFrameRef.duration.ToMicroseconds(),
+                                 image.forget(),
+                                 aFrameRef.is_sync_point,
+                                 aFrameRef.decode_timestamp.ToMicroseconds(),
+                                 visible);
+#else
+    MOZ_ASSERT_UNREACHABLE("No MacIOSurface on iOS");
+#endif
+  }
+
+  if (!data) {
+    NS_ERROR("Couldn't create VideoData for frame");
+    mCallback->Error(MediaDataDecoderError::FATAL_ERROR);
+    return NS_ERROR_FAILURE;
+  }
+
+  // Frames come out in DTS order but we need to output them
+  // in composition order.
+  MonitorAutoLock mon(mMonitor);
+  mReorderQueue.Push(data);
+  while (mReorderQueue.Length() > mMaxRefFrames) {
+    mCallback->Output(mReorderQueue.Pop().get());
+  }
+  LOG("%llu decoded frames queued",
+      static_cast<unsigned long long>(mReorderQueue.Length()));
+
+  return NS_OK;
+}
+
 nsresult
 AppleVTDecoder::WaitForAsynchronousFrames()
 {
   OSStatus rv = VTDecompressionSessionWaitForAsynchronousFrames(mSession);
   if (rv != noErr) {
     LOG("AppleVTDecoder: Error %d waiting for asynchronous frames", rv);
     return NS_ERROR_FAILURE;
   }
@@ -334,9 +635,76 @@ AppleVTDecoder::CreateDecoderSpecificati
   return CFDictionaryCreate(kCFAllocatorDefault,
                             specKeys,
                             specValues,
                             ArrayLength(specKeys),
                             &kCFTypeDictionaryKeyCallBacks,
                             &kCFTypeDictionaryValueCallBacks);
 }
 
+CFDictionaryRef
+AppleVTDecoder::CreateOutputConfiguration()
+{
+  if (mUseSoftwareImages) {
+    // Output format type:
+    SInt32 PixelFormatTypeValue =
+      kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
+    AutoCFRelease<CFNumberRef> PixelFormatTypeNumber =
+      CFNumberCreate(kCFAllocatorDefault,
+                     kCFNumberSInt32Type,
+                     &PixelFormatTypeValue);
+    const void* outputKeys[] = { kCVPixelBufferPixelFormatTypeKey };
+    const void* outputValues[] = { PixelFormatTypeNumber };
+    static_assert(ArrayLength(outputKeys) == ArrayLength(outputValues),
+                  "Non matching keys/values array size");
+
+    return CFDictionaryCreate(kCFAllocatorDefault,
+                              outputKeys,
+                              outputValues,
+                              ArrayLength(outputKeys),
+                              &kCFTypeDictionaryKeyCallBacks,
+                              &kCFTypeDictionaryValueCallBacks);
+  }
+
+#ifndef MOZ_WIDGET_UIKIT
+  // Output format type:
+  SInt32 PixelFormatTypeValue = kCVPixelFormatType_422YpCbCr8;
+  AutoCFRelease<CFNumberRef> PixelFormatTypeNumber =
+    CFNumberCreate(kCFAllocatorDefault,
+                   kCFNumberSInt32Type,
+                   &PixelFormatTypeValue);
+  // Construct IOSurface Properties
+  const void* IOSurfaceKeys[] = { MacIOSurfaceLib::kPropIsGlobal };
+  const void* IOSurfaceValues[] = { kCFBooleanTrue };
+  static_assert(ArrayLength(IOSurfaceKeys) == ArrayLength(IOSurfaceValues),
+                "Non matching keys/values array size");
+
+  // Contruct output configuration.
+  AutoCFRelease<CFDictionaryRef> IOSurfaceProperties =
+    CFDictionaryCreate(kCFAllocatorDefault,
+                       IOSurfaceKeys,
+                       IOSurfaceValues,
+                       ArrayLength(IOSurfaceKeys),
+                       &kCFTypeDictionaryKeyCallBacks,
+                       &kCFTypeDictionaryValueCallBacks);
+
+  const void* outputKeys[] = { kCVPixelBufferIOSurfacePropertiesKey,
+                               kCVPixelBufferPixelFormatTypeKey,
+                               kCVPixelBufferOpenGLCompatibilityKey };
+  const void* outputValues[] = { IOSurfaceProperties,
+                                 PixelFormatTypeNumber,
+                                 kCFBooleanTrue };
+  static_assert(ArrayLength(outputKeys) == ArrayLength(outputValues),
+                "Non matching keys/values array size");
+
+  return CFDictionaryCreate(kCFAllocatorDefault,
+                            outputKeys,
+                            outputValues,
+                            ArrayLength(outputKeys),
+                            &kCFTypeDictionaryKeyCallBacks,
+                            &kCFTypeDictionaryValueCallBacks);
+#else
+  MOZ_ASSERT_UNREACHABLE("No MacIOSurface on iOS");
+#endif
+}
+
+
 } // namespace mozilla
--- a/dom/media/platforms/apple/AppleVTDecoder.h
+++ b/dom/media/platforms/apple/AppleVTDecoder.h
@@ -2,56 +2,133 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_AppleVTDecoder_h
 #define mozilla_AppleVTDecoder_h
 
-#include "AppleVDADecoder.h"
+#include "PlatformDecoderModule.h"
+#include "mozilla/Atomics.h"
+#include "nsIThread.h"
+#include "ReorderQueue.h"
+#include "TimeUnits.h"
 
 #include "VideoToolbox/VideoToolbox.h"
 
 namespace mozilla {
 
-class AppleVTDecoder : public AppleVDADecoder {
+class AppleVTDecoder : public MediaDataDecoder {
 public:
   AppleVTDecoder(const VideoInfo& aConfig,
                  TaskQueue* aTaskQueue,
                  MediaDataDecoderCallback* aCallback,
                  layers::ImageContainer* aImageContainer);
 
+  class AppleFrameRef {
+  public:
+    media::TimeUnit decode_timestamp;
+    media::TimeUnit composition_timestamp;
+    media::TimeUnit duration;
+    int64_t byte_offset;
+    bool is_sync_point;
+
+    explicit AppleFrameRef(const MediaRawData& aSample)
+      : decode_timestamp(media::TimeUnit::FromMicroseconds(aSample.mTimecode))
+      , composition_timestamp(media::TimeUnit::FromMicroseconds(aSample.mTime))
+      , duration(media::TimeUnit::FromMicroseconds(aSample.mDuration))
+      , byte_offset(aSample.mOffset)
+      , is_sync_point(aSample.mKeyframe)
+    {
+    }
+  };
+
   RefPtr<InitPromise> Init() override;
+  nsresult Input(MediaRawData* aSample) override;
+  nsresult Flush() override;
+  nsresult Drain() override;
+  nsresult Shutdown() override;
+  void SetSeekThreshold(const media::TimeUnit& aTime) override;
+
   bool IsHardwareAccelerated(nsACString& aFailureReason) const override
   {
     return mIsHardwareAccelerated;
   }
 
   const char* GetDescriptionName() const override
   {
     return mIsHardwareAccelerated
       ? "apple hardware VT decoder"
       : "apple software VT decoder";
   }
 
+  // Access from the taskqueue and the decoder's thread.
+  // OutputFrame is thread-safe.
+  nsresult OutputFrame(CVPixelBufferRef aImage,
+                       AppleFrameRef aFrameRef);
+
 private:
   virtual ~AppleVTDecoder();
-  void ProcessFlush() override;
-  void ProcessDrain() override;
-  void ProcessShutdown() override;
+  void ProcessFlush();
+  void ProcessDrain();
+  void ProcessShutdown();
+  nsresult ProcessDecode(MediaRawData* aSample);
+
+  void AssertOnTaskQueueThread()
+  {
+    MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
+  }
 
-  CMVideoFormatDescriptionRef mFormat;
-  VTDecompressionSessionRef mSession;
+  AppleFrameRef* CreateAppleFrameRef(const MediaRawData* aSample);
+  void DrainReorderedFrames();
+  void ClearReorderedFrames();
+  CFDictionaryRef CreateOutputConfiguration();
 
-  // Method to pass a frame to VideoToolbox for decoding.
-  nsresult DoDecode(MediaRawData* aSample) override;
+  const RefPtr<MediaByteBuffer> mExtraData;
+  MediaDataDecoderCallback* mCallback;
+  const uint32_t mPictureWidth;
+  const uint32_t mPictureHeight;
+  const uint32_t mDisplayWidth;
+  const uint32_t mDisplayHeight;
+
+  // Number of times a sample was queued via Input(). Will be decreased upon
+  // the decoder's callback being invoked.
+  // This is used to calculate how many frames has been buffered by the decoder.
+  Atomic<uint32_t> mQueuedSamples;
+
   // Method to set up the decompression session.
   nsresult InitializeSession();
   nsresult WaitForAsynchronousFrames();
   CFDictionaryRef CreateDecoderSpecification();
   CFDictionaryRef CreateDecoderExtensions();
+  // Method to pass a frame to VideoToolbox for decoding.
+  nsresult DoDecode(MediaRawData* aSample);
+
+  const RefPtr<TaskQueue> mTaskQueue;
+  const uint32_t mMaxRefFrames;
+  const RefPtr<layers::ImageContainer> mImageContainer;
+  // Increased when Input is called, and decreased when ProcessFrame runs.
+  // Reaching 0 indicates that there's no pending Input.
+  Atomic<uint32_t> mInputIncoming;
+  Atomic<bool> mIsShutDown;
+  const bool mUseSoftwareImages;
+
+  // Set on reader/decode thread calling Flush() to indicate that output is
+  // not required and so input samples on mTaskQueue need not be processed.
+  // Cleared on mTaskQueue in ProcessDrain().
+  Atomic<bool> mIsFlushing;
+  // Protects mReorderQueue.
+  Monitor mMonitor;
+  ReorderQueue mReorderQueue;
+  // Decoded frame will be dropped if its pts is smaller than this
+  // value. It shold be initialized before Input() or after Flush(). So it is
+  // safe to access it in OutputFrame without protecting.
+  Maybe<media::TimeUnit> mSeekTargetThreshold;
+
+  CMVideoFormatDescriptionRef mFormat;
+  VTDecompressionSessionRef mSession;
   Atomic<bool> mIsHardwareAccelerated;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_AppleVTDecoder_h
deleted file mode 100644
--- a/dom/media/platforms/apple/VideoDecodeAcceleration/VDADecoder.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// Stub header for VideoDecodeAcceleration framework API.
-// This is a private Framework on 10.6 see:
-// https://developer.apple.com/library/mac/technotes/tn2267/_index.html
-// We include our own copy so we can build on MacOS versions
-// where it's not available.
-
-#ifndef mozilla_VideoDecodeAcceleration_VDADecoder_h
-#define mozilla_VideoDecodeAcceleration_VDADecoder_h
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <CoreVideo/CoreVideo.h>
-
-typedef uint32_t VDADecodeFrameFlags;
-typedef uint32_t VDADecodeInfoFlags;
-
-enum {
-  kVDADecodeInfo_Asynchronous = 1UL << 0,
-  kVDADecodeInfo_FrameDropped = 1UL << 1
-};
-
-enum {
-  kVDADecoderFlush_EmitFrames = 1 << 0
-};
-
-typedef struct OpaqueVDADecoder* VDADecoder;
-
-typedef void (*VDADecoderOutputCallback)
-  (void* decompressionOutputRefCon,
-   CFDictionaryRef frameInfo,
-   OSStatus status,
-   uint32_t infoFlags,
-   CVImageBufferRef imageBuffer);
-
-OSStatus
-VDADecoderCreate(
-  CFDictionaryRef decoderConfiguration,
-  CFDictionaryRef destinationImageBufferAttributes, /* can be NULL */
-  VDADecoderOutputCallback* outputCallback,
-  void* decoderOutputCallbackRefcon,
-  VDADecoder* decoderOut);
-
-OSStatus
-VDADecoderDecode(
-  VDADecoder decoder,
-  uint32_t decodeFlags,
-  CFTypeRef compressedBuffer,
-  CFDictionaryRef frameInfo); /* can be NULL */
-
-OSStatus
-VDADecoderFlush(
-  VDADecoder decoder,
-  uint32_t flushFlags);
-
-OSStatus
-VDADecoderDestroy(VDADecoder decoder);
-
-#endif // mozilla_VideoDecodeAcceleration_VDADecoder_h
--- a/dom/media/platforms/moz.build
+++ b/dom/media/platforms/moz.build
@@ -58,18 +58,16 @@ if CONFIG['MOZ_FFMPEG']:
 if CONFIG['MOZ_APPLEMEDIA']:
   EXPORTS += [
       'apple/AppleDecoderModule.h',
   ]
   UNIFIED_SOURCES += [
       'apple/AppleATDecoder.cpp',
       'apple/AppleCMLinker.cpp',
       'apple/AppleDecoderModule.cpp',
-      'apple/AppleVDADecoder.cpp',
-      'apple/AppleVDALinker.cpp',
       'apple/AppleVTDecoder.cpp',
       'apple/AppleVTLinker.cpp',
   ]
   OS_LIBS += [
       '-framework AudioToolbox',
   ]
 
 if CONFIG['MOZ_GONK_MEDIACODEC']: