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