1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "WVMExtractor"
18 #include <utils/Log.h>
19 
20 #include "include/WVMExtractor.h"
21 
22 #include <arpa/inet.h>
23 #include <utils/String8.h>
24 #include <media/stagefright/foundation/ADebug.h>
25 #include <media/stagefright/Utils.h>
26 #include <media/stagefright/DataSource.h>
27 #include <media/stagefright/MediaSource.h>
28 #include <media/stagefright/MediaDefs.h>
29 #include <media/stagefright/MetaData.h>
30 #include <media/stagefright/MediaErrors.h>
31 #include <media/stagefright/MediaBuffer.h>
32 #include <dlfcn.h>
33 
34 #include <utils/Errors.h>
35 
36 /* The extractor lifetime is short - just long enough to get
37  * the media sources constructed - so the shared lib needs to remain open
38  * beyond the lifetime of the extractor.  So keep the handle as a global
39  * rather than a member of the extractor
40  */
41 void *gVendorLibHandle = NULL;
42 
43 namespace android {
44 
45 static Mutex gWVMutex;
46 
WVMExtractor(const sp<DataSource> & source)47 WVMExtractor::WVMExtractor(const sp<DataSource> &source)
48     : mDataSource(source)
49 {
50     Mutex::Autolock autoLock(gWVMutex);
51 
52     if (!getVendorLibHandle()) {
53         return;
54     }
55 
56     typedef WVMLoadableExtractor *(*GetInstanceFunc)(sp<DataSource>);
57     GetInstanceFunc getInstanceFunc =
58         (GetInstanceFunc) dlsym(gVendorLibHandle,
59                 "_ZN7android11GetInstanceENS_2spINS_10DataSourceEEE");
60 
61     if (getInstanceFunc) {
62         if (source->DrmInitialization(
63                 MEDIA_MIMETYPE_CONTAINER_WVM) != NULL) {
64             mImpl = (*getInstanceFunc)(source);
65             CHECK(mImpl != NULL);
66             setDrmFlag(true);
67         } else {
68             ALOGE("Drm manager failed to initialize.");
69         }
70     } else {
71         ALOGE("Failed to locate GetInstance in libwvm.so");
72     }
73 }
74 
init_routine()75 static void init_routine()
76 {
77     gVendorLibHandle = dlopen("libwvm.so", RTLD_NOW);
78     if (gVendorLibHandle == NULL) {
79         ALOGE("Failed to open libwvm.so: %s", dlerror());
80     }
81 }
82 
getVendorLibHandle()83 bool WVMExtractor::getVendorLibHandle()
84 {
85     static pthread_once_t sOnceControl = PTHREAD_ONCE_INIT;
86     pthread_once(&sOnceControl, init_routine);
87 
88     return gVendorLibHandle != NULL;
89 }
90 
~WVMExtractor()91 WVMExtractor::~WVMExtractor() {
92 }
93 
countTracks()94 size_t WVMExtractor::countTracks() {
95     return (mImpl != NULL) ? mImpl->countTracks() : 0;
96 }
97 
getTrack(size_t index)98 sp<MediaSource> WVMExtractor::getTrack(size_t index) {
99     if (mImpl == NULL) {
100         return NULL;
101     }
102     return mImpl->getTrack(index);
103 }
104 
getTrackMetaData(size_t index,uint32_t flags)105 sp<MetaData> WVMExtractor::getTrackMetaData(size_t index, uint32_t flags) {
106     if (mImpl == NULL) {
107         return NULL;
108     }
109     return mImpl->getTrackMetaData(index, flags);
110 }
111 
getMetaData()112 sp<MetaData> WVMExtractor::getMetaData() {
113     if (mImpl == NULL) {
114         return NULL;
115     }
116     return mImpl->getMetaData();
117 }
118 
getCachedDurationUs(status_t * finalStatus)119 int64_t WVMExtractor::getCachedDurationUs(status_t *finalStatus) {
120     if (mImpl == NULL) {
121         return 0;
122     }
123 
124     return mImpl->getCachedDurationUs(finalStatus);
125 }
126 
getEstimatedBandwidthKbps(int32_t * kbps)127 status_t WVMExtractor::getEstimatedBandwidthKbps(int32_t *kbps) {
128     if (mImpl == NULL) {
129         return UNKNOWN_ERROR;
130     }
131 
132     return mImpl->getEstimatedBandwidthKbps(kbps);
133 }
134 
135 
setAdaptiveStreamingMode(bool adaptive)136 void WVMExtractor::setAdaptiveStreamingMode(bool adaptive) {
137     if (mImpl != NULL) {
138         mImpl->setAdaptiveStreamingMode(adaptive);
139     }
140 }
141 
setCryptoPluginMode(bool cryptoPluginMode)142 void WVMExtractor::setCryptoPluginMode(bool cryptoPluginMode) {
143     if (mImpl != NULL) {
144         mImpl->setCryptoPluginMode(cryptoPluginMode);
145     }
146 }
147 
setUID(uid_t uid)148 void WVMExtractor::setUID(uid_t uid) {
149     if (mImpl != NULL) {
150         mImpl->setUID(uid);
151     }
152 }
153 
getError()154 status_t WVMExtractor::getError() {
155     if (mImpl == NULL) {
156        return UNKNOWN_ERROR;
157     }
158 
159     return mImpl->getError();
160 }
161 
setError(status_t err)162 void WVMExtractor::setError(status_t err) {
163     if (mImpl != NULL) {
164         mImpl->setError(err);
165     }
166 }
167 
SniffWVM(const sp<DataSource> & source,String8 * mimeType,float * confidence,sp<AMessage> *)168 bool SniffWVM(
169     const sp<DataSource> &source, String8 *mimeType, float *confidence,
170         sp<AMessage> *) {
171 
172     Mutex::Autolock autoLock(gWVMutex);
173 
174     if (!WVMExtractor::getVendorLibHandle()) {
175         return false;
176     }
177 
178     typedef WVMLoadableExtractor *(*SnifferFunc)(const sp<DataSource>&);
179     SnifferFunc snifferFunc =
180         (SnifferFunc) dlsym(gVendorLibHandle,
181                             "_ZN7android15IsWidevineMediaERKNS_2spINS_10DataSourceEEE");
182 
183     if (snifferFunc) {
184         if ((*snifferFunc)(source)) {
185             *mimeType = MEDIA_MIMETYPE_CONTAINER_WVM;
186             *confidence = 10.0f;
187             return true;
188         }
189     } else {
190         ALOGE("IsWidevineMedia not found in libwvm.so");
191     }
192 
193     return false;
194 }
195 
196 } //namespace android
197 
198