/src/mozilla-central/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp
Line | Count | Source (jump to first uncovered line) |
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 "FFmpegRuntimeLinker.h" |
8 | | #include "FFmpegLibWrapper.h" |
9 | | #include "mozilla/ArrayUtils.h" |
10 | | #include "FFmpegLog.h" |
11 | | #include "prlink.h" |
12 | | |
13 | | namespace mozilla { |
14 | | |
15 | | FFmpegRuntimeLinker::LinkStatus FFmpegRuntimeLinker::sLinkStatus = |
16 | | LinkStatus_INIT; |
17 | | const char* FFmpegRuntimeLinker::sLinkStatusLibraryName = ""; |
18 | | |
19 | | template <int V> class FFmpegDecoderModule |
20 | | { |
21 | | public: |
22 | | static already_AddRefed<PlatformDecoderModule> Create(FFmpegLibWrapper*); |
23 | | }; |
24 | | |
25 | | static FFmpegLibWrapper sLibAV; |
26 | | |
27 | | static const char* sLibs[] = { |
28 | | #if defined(XP_DARWIN) |
29 | | "libavcodec.58.dylib", |
30 | | "libavcodec.57.dylib", |
31 | | "libavcodec.56.dylib", |
32 | | "libavcodec.55.dylib", |
33 | | "libavcodec.54.dylib", |
34 | | "libavcodec.53.dylib", |
35 | | #else |
36 | | "libavcodec.so.58", |
37 | | "libavcodec-ffmpeg.so.58", |
38 | | "libavcodec-ffmpeg.so.57", |
39 | | "libavcodec-ffmpeg.so.56", |
40 | | "libavcodec.so.57", |
41 | | "libavcodec.so.56", |
42 | | "libavcodec.so.55", |
43 | | "libavcodec.so.54", |
44 | | "libavcodec.so.53", |
45 | | #endif |
46 | | }; |
47 | | |
48 | | /* static */ bool |
49 | | FFmpegRuntimeLinker::Init() |
50 | 0 | { |
51 | 0 | if (sLinkStatus != LinkStatus_INIT) { |
52 | 0 | return sLinkStatus == LinkStatus_SUCCEEDED; |
53 | 0 | } |
54 | 0 | |
55 | 0 | // While going through all possible libs, this status will be updated with a |
56 | 0 | // more precise error if possible. |
57 | 0 | sLinkStatus = LinkStatus_NOT_FOUND; |
58 | 0 |
|
59 | 0 | for (size_t i = 0; i < ArrayLength(sLibs); i++) { |
60 | 0 | const char* lib = sLibs[i]; |
61 | 0 | PRLibSpec lspec; |
62 | 0 | lspec.type = PR_LibSpec_Pathname; |
63 | 0 | lspec.value.pathname = lib; |
64 | 0 | sLibAV.mAVCodecLib = |
65 | 0 | PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL); |
66 | 0 | if (sLibAV.mAVCodecLib) { |
67 | 0 | sLibAV.mAVUtilLib = sLibAV.mAVCodecLib; |
68 | 0 | switch (sLibAV.Link()) { |
69 | 0 | case FFmpegLibWrapper::LinkResult::Success: |
70 | 0 | sLinkStatus = LinkStatus_SUCCEEDED; |
71 | 0 | sLinkStatusLibraryName = lib; |
72 | 0 | return true; |
73 | 0 | case FFmpegLibWrapper::LinkResult::NoProvidedLib: |
74 | 0 | MOZ_ASSERT_UNREACHABLE("Incorrectly-setup sLibAV"); |
75 | 0 | break; |
76 | 0 | case FFmpegLibWrapper::LinkResult::NoAVCodecVersion: |
77 | 0 | if (sLinkStatus > LinkStatus_INVALID_CANDIDATE) { |
78 | 0 | sLinkStatus = LinkStatus_INVALID_CANDIDATE; |
79 | 0 | sLinkStatusLibraryName = lib; |
80 | 0 | } |
81 | 0 | break; |
82 | 0 | case FFmpegLibWrapper::LinkResult::CannotUseLibAV57: |
83 | 0 | if (sLinkStatus > LinkStatus_UNUSABLE_LIBAV57) { |
84 | 0 | sLinkStatus = LinkStatus_UNUSABLE_LIBAV57; |
85 | 0 | sLinkStatusLibraryName = lib; |
86 | 0 | } |
87 | 0 | break; |
88 | 0 | case FFmpegLibWrapper::LinkResult::BlockedOldLibAVVersion: |
89 | 0 | if (sLinkStatus > LinkStatus_OBSOLETE_LIBAV) { |
90 | 0 | sLinkStatus = LinkStatus_OBSOLETE_LIBAV; |
91 | 0 | sLinkStatusLibraryName = lib; |
92 | 0 | } |
93 | 0 | break; |
94 | 0 | case FFmpegLibWrapper::LinkResult::UnknownFutureLibAVVersion: |
95 | 0 | case FFmpegLibWrapper::LinkResult::MissingLibAVFunction: |
96 | 0 | if (sLinkStatus > LinkStatus_INVALID_LIBAV_CANDIDATE) { |
97 | 0 | sLinkStatus = LinkStatus_INVALID_LIBAV_CANDIDATE; |
98 | 0 | sLinkStatusLibraryName = lib; |
99 | 0 | } |
100 | 0 | break; |
101 | 0 | case FFmpegLibWrapper::LinkResult::UnknownFutureFFMpegVersion: |
102 | 0 | case FFmpegLibWrapper::LinkResult::MissingFFMpegFunction: |
103 | 0 | if (sLinkStatus > LinkStatus_INVALID_FFMPEG_CANDIDATE) { |
104 | 0 | sLinkStatus = LinkStatus_INVALID_FFMPEG_CANDIDATE; |
105 | 0 | sLinkStatusLibraryName = lib; |
106 | 0 | } |
107 | 0 | break; |
108 | 0 | case FFmpegLibWrapper::LinkResult::UnknownOlderFFMpegVersion: |
109 | 0 | if (sLinkStatus > LinkStatus_OBSOLETE_FFMPEG) { |
110 | 0 | sLinkStatus = LinkStatus_OBSOLETE_FFMPEG; |
111 | 0 | sLinkStatusLibraryName = lib; |
112 | 0 | } |
113 | 0 | break; |
114 | 0 | } |
115 | 0 | } |
116 | 0 | } |
117 | 0 |
|
118 | 0 | FFMPEG_LOG("H264/AAC codecs unsupported without ["); |
119 | 0 | for (size_t i = 0; i < ArrayLength(sLibs); i++) { |
120 | 0 | FFMPEG_LOG("%s %s", i ? "," : " ", sLibs[i]); |
121 | 0 | } |
122 | 0 | FFMPEG_LOG(" ]\n"); |
123 | 0 |
|
124 | 0 | return false; |
125 | 0 | } |
126 | | |
127 | | /* static */ already_AddRefed<PlatformDecoderModule> |
128 | | FFmpegRuntimeLinker::CreateDecoderModule() |
129 | 0 | { |
130 | 0 | if (!Init()) { |
131 | 0 | return nullptr; |
132 | 0 | } |
133 | 0 | RefPtr<PlatformDecoderModule> module; |
134 | 0 | switch (sLibAV.mVersion) { |
135 | 0 | case 53: module = FFmpegDecoderModule<53>::Create(&sLibAV); break; |
136 | 0 | case 54: module = FFmpegDecoderModule<54>::Create(&sLibAV); break; |
137 | 0 | case 55: |
138 | 0 | case 56: module = FFmpegDecoderModule<55>::Create(&sLibAV); break; |
139 | 0 | case 57: module = FFmpegDecoderModule<57>::Create(&sLibAV); break; |
140 | 0 | case 58: module = FFmpegDecoderModule<58>::Create(&sLibAV); break; |
141 | 0 | default: module = nullptr; |
142 | 0 | } |
143 | 0 | return module.forget(); |
144 | 0 | } |
145 | | |
146 | | /* static */ const char* |
147 | | FFmpegRuntimeLinker::LinkStatusString() |
148 | 0 | { |
149 | 0 | switch (sLinkStatus) { |
150 | 0 | case LinkStatus_INIT: |
151 | 0 | return "Libavcodec not initialized yet"; |
152 | 0 | case LinkStatus_SUCCEEDED: |
153 | 0 | return "Libavcodec linking succeeded"; |
154 | 0 | case LinkStatus_INVALID_FFMPEG_CANDIDATE: |
155 | 0 | return "Invalid FFMpeg libavcodec candidate"; |
156 | 0 | case LinkStatus_UNUSABLE_LIBAV57: |
157 | 0 | return "Unusable LibAV's libavcodec 57"; |
158 | 0 | case LinkStatus_INVALID_LIBAV_CANDIDATE: |
159 | 0 | return "Invalid LibAV libavcodec candidate"; |
160 | 0 | case LinkStatus_OBSOLETE_FFMPEG: |
161 | 0 | return "Obsolete FFMpeg libavcodec candidate"; |
162 | 0 | case LinkStatus_OBSOLETE_LIBAV: |
163 | 0 | return "Obsolete LibAV libavcodec candidate"; |
164 | 0 | case LinkStatus_INVALID_CANDIDATE: |
165 | 0 | return "Invalid libavcodec candidate"; |
166 | 0 | case LinkStatus_NOT_FOUND: |
167 | 0 | return "Libavcodec not found"; |
168 | 0 | } |
169 | 0 | MOZ_ASSERT_UNREACHABLE("Unknown sLinkStatus value"); |
170 | 0 | return "?"; |
171 | 0 | } |
172 | | |
173 | | } // namespace mozilla |