1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "AppleATDecoder.h"
8 #include "AppleCMLinker.h"
9 #include "AppleDecoderModule.h"
10 #include "AppleVTDecoder.h"
11 #include "AppleVTLinker.h"
12 #include "MacIOSurfaceImage.h"
13 #include "MediaPrefs.h"
14 #include "mozilla/DebugOnly.h"
15 #include "mozilla/Logging.h"
16 #include "mozilla/gfx/gfxVars.h"
17 
18 namespace mozilla {
19 
20 bool AppleDecoderModule::sInitialized = false;
21 bool AppleDecoderModule::sIsCoreMediaAvailable = false;
22 bool AppleDecoderModule::sIsVTAvailable = false;
23 bool AppleDecoderModule::sIsVTHWAvailable = false;
24 bool AppleDecoderModule::sCanUseHardwareVideoDecoder = true;
25 
AppleDecoderModule()26 AppleDecoderModule::AppleDecoderModule()
27 {
28 }
29 
~AppleDecoderModule()30 AppleDecoderModule::~AppleDecoderModule()
31 {
32 }
33 
34 /* static */
35 void
Init()36 AppleDecoderModule::Init()
37 {
38   if (sInitialized) {
39     return;
40   }
41 
42   // Ensure IOSurface framework is loaded.
43   MacIOSurfaceLib::LoadLibrary();
44   const bool loaded = MacIOSurfaceLib::isInit();
45 
46   // dlopen CoreMedia.framework if it's available.
47   sIsCoreMediaAvailable = AppleCMLinker::Link();
48   // dlopen VideoToolbox.framework if it's available.
49   // We must link both CM and VideoToolbox framework to allow for proper
50   // paired Link/Unlink calls
51   bool haveVideoToolbox = loaded && AppleVTLinker::Link();
52   sIsVTAvailable = sIsCoreMediaAvailable && haveVideoToolbox;
53 
54   sIsVTHWAvailable = AppleVTLinker::skPropEnableHWAccel != nullptr;
55 
56   sCanUseHardwareVideoDecoder = loaded &&
57     gfx::gfxVars::CanUseHardwareVideoDecoding();
58 
59   sInitialized = true;
60 }
61 
62 nsresult
Startup()63 AppleDecoderModule::Startup()
64 {
65   if (!sInitialized || !sIsVTAvailable) {
66     return NS_ERROR_FAILURE;
67   }
68   return NS_OK;
69 }
70 
71 already_AddRefed<MediaDataDecoder>
CreateVideoDecoder(const CreateDecoderParams & aParams)72 AppleDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
73 {
74   RefPtr<MediaDataDecoder> decoder =
75     new AppleVTDecoder(aParams.VideoConfig(),
76                        aParams.mTaskQueue,
77                        aParams.mCallback,
78                        aParams.mImageContainer);
79   return decoder.forget();
80 }
81 
82 already_AddRefed<MediaDataDecoder>
CreateAudioDecoder(const CreateDecoderParams & aParams)83 AppleDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams)
84 {
85   RefPtr<MediaDataDecoder> decoder =
86     new AppleATDecoder(aParams.AudioConfig(),
87                        aParams.mTaskQueue,
88                        aParams.mCallback);
89   return decoder.forget();
90 }
91 
92 bool
SupportsMimeType(const nsACString & aMimeType,DecoderDoctorDiagnostics * aDiagnostics) const93 AppleDecoderModule::SupportsMimeType(const nsACString& aMimeType,
94                                      DecoderDoctorDiagnostics* aDiagnostics) const
95 {
96   return (sIsCoreMediaAvailable &&
97           (aMimeType.EqualsLiteral("audio/mpeg") ||
98            aMimeType.EqualsLiteral("audio/mp4a-latm"))) ||
99     (sIsVTAvailable && (aMimeType.EqualsLiteral("video/mp4") ||
100                         aMimeType.EqualsLiteral("video/avc")));
101 }
102 
103 PlatformDecoderModule::ConversionRequired
DecoderNeedsConversion(const TrackInfo & aConfig) const104 AppleDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const
105 {
106   if (aConfig.IsVideo()) {
107     return ConversionRequired::kNeedAVCC;
108   } else {
109     return ConversionRequired::kNeedNone;
110   }
111 }
112 
113 } // namespace mozilla
114