blob: 3e6d7d67308e4cd0090e3a14975bf59730edfde6 [file] [log] [blame]
Robert Shih0df451b2017-12-08 14:16:50 -08001/*
2 * Copyright (C) 2018 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_NDEBUG 0
18#define LOG_TAG "NdkMediaDataSource"
19
Dichen Zhang3445f032020-02-18 10:46:29 -080020#include "NdkJavaVMHelperPriv.h"
Robert Shih0df451b2017-12-08 14:16:50 -080021#include "NdkMediaDataSourcePriv.h"
22
23#include <inttypes.h>
24#include <jni.h>
25#include <unistd.h>
26
Jooyung Hanf92acc72019-03-07 17:43:25 +090027#include <android_runtime/AndroidRuntime.h>
28#include <android_util_Binder.h>
Robert Shih0df451b2017-12-08 14:16:50 -080029#include <cutils/properties.h>
Marco Nelissenfa8be7d2019-09-23 12:15:57 -070030#include <datasource/DataSourceFactory.h>
31#include <datasource/HTTPBase.h>
32#include <datasource/NuCachedSource2.h>
Robert Shih730af222018-09-14 14:02:57 -070033#include <media/IMediaHTTPService.h>
Robert Shih0df451b2017-12-08 14:16:50 -080034#include <media/NdkMediaError.h>
35#include <media/NdkMediaDataSource.h>
36#include <media/stagefright/InterfaceUtils.h>
Marco Nelissenfa8be7d2019-09-23 12:15:57 -070037#include <utils/Log.h>
38#include <utils/StrongPointer.h>
Robert Shih0df451b2017-12-08 14:16:50 -080039
Robert Shih2568eb92018-09-19 10:00:46 -070040#include "NdkMediaDataSourceCallbacksPriv.h"
Robert Shih0df451b2017-12-08 14:16:50 -080041
Jooyung Han99f4a732019-02-21 15:27:38 +090042
Robert Shih0df451b2017-12-08 14:16:50 -080043using namespace android;
44
45struct AMediaDataSource {
46 void *userdata;
47 AMediaDataSourceReadAt readAt;
48 AMediaDataSourceGetSize getSize;
Robert Shih45b88d22018-02-05 13:52:39 -080049 AMediaDataSourceClose close;
Robert Shihca198ce2018-09-22 16:31:55 -070050 AMediaDataSourceGetAvailableSize getAvailableSize;
Robert Shiha601f4a2018-10-01 15:10:35 -070051 sp<DataSource> mImpl;
52 uint32_t mFlags;
Robert Shih0df451b2017-12-08 14:16:50 -080053};
54
55NdkDataSource::NdkDataSource(AMediaDataSource *dataSource)
Robert Shihd4faf9e2018-01-21 17:52:25 -080056 : mDataSource(AMediaDataSource_new()) {
Robert Shiha601f4a2018-10-01 15:10:35 -070057 AMediaDataSource_setReadAt(mDataSource, dataSource->readAt);
58 AMediaDataSource_setGetSize(mDataSource, dataSource->getSize);
59 AMediaDataSource_setClose(mDataSource, dataSource->close);
60 AMediaDataSource_setUserdata(mDataSource, dataSource->userdata);
Robert Shihea388862018-11-20 02:11:30 -080061 AMediaDataSource_setGetAvailableSize(mDataSource, dataSource->getAvailableSize);
Robert Shiha601f4a2018-10-01 15:10:35 -070062 mDataSource->mImpl = dataSource->mImpl;
63 mDataSource->mFlags = dataSource->mFlags;
Robert Shihd4faf9e2018-01-21 17:52:25 -080064}
65
66NdkDataSource::~NdkDataSource() {
67 AMediaDataSource_delete(mDataSource);
Robert Shih0df451b2017-12-08 14:16:50 -080068}
69
70status_t NdkDataSource::initCheck() const {
71 return OK;
72}
73
Robert Shiha601f4a2018-10-01 15:10:35 -070074uint32_t NdkDataSource::flags() {
75 return mDataSource->mFlags;
76}
77
Robert Shih0df451b2017-12-08 14:16:50 -080078ssize_t NdkDataSource::readAt(off64_t offset, void *data, size_t size) {
79 Mutex::Autolock l(mLock);
Robert Shiha601f4a2018-10-01 15:10:35 -070080 if (mDataSource->readAt == NULL || mDataSource->userdata == NULL) {
Robert Shih0df451b2017-12-08 14:16:50 -080081 return -1;
82 }
83 return mDataSource->readAt(mDataSource->userdata, offset, data, size);
84}
85
86status_t NdkDataSource::getSize(off64_t *size) {
87 Mutex::Autolock l(mLock);
88 if (mDataSource->getSize == NULL || mDataSource->userdata == NULL) {
89 return NO_INIT;
90 }
91 if (size != NULL) {
92 *size = mDataSource->getSize(mDataSource->userdata);
93 }
94 return OK;
95}
96
97String8 NdkDataSource::toString() {
98 return String8::format("NdkDataSource(pid %d, uid %d)", getpid(), getuid());
99}
100
101String8 NdkDataSource::getMIMEType() const {
102 return String8("application/octet-stream");
103}
104
Robert Shih45b88d22018-02-05 13:52:39 -0800105void NdkDataSource::close() {
106 if (mDataSource->close != NULL && mDataSource->userdata != NULL) {
107 mDataSource->close(mDataSource->userdata);
108 }
109}
110
Robert Shihca198ce2018-09-22 16:31:55 -0700111status_t NdkDataSource::getAvailableSize(off64_t offset, off64_t *sizeptr) {
112 off64_t size = -1;
113 if (mDataSource->getAvailableSize != NULL
114 && mDataSource->userdata != NULL
115 && sizeptr != NULL) {
116 size = mDataSource->getAvailableSize(mDataSource->userdata, offset);
117 *sizeptr = size;
118 }
119 return size >= 0 ? OK : UNKNOWN_ERROR;
120}
121
Marco Nelissend1ecb912019-09-24 09:27:40 -0700122static sp<MediaHTTPService> createMediaHttpServiceFromJavaObj(JNIEnv *env, jobject obj) {
Robert Shih730af222018-09-14 14:02:57 -0700123 if (obj == NULL) {
124 return NULL;
125 }
Marco Nelissend1ecb912019-09-24 09:27:40 -0700126 return interface_cast<IMediaHTTPService>(ibinderForJavaObject(env, obj));
Robert Shih730af222018-09-14 14:02:57 -0700127}
128
129static sp<MediaHTTPService> createMediaHttpServiceTemplate(
130 JNIEnv *env,
131 const char *uri,
132 const char *clazz,
133 const char *method,
Marco Nelissend1ecb912019-09-24 09:27:40 -0700134 const char *signature) {
Robert Shih730af222018-09-14 14:02:57 -0700135 jobject service = NULL;
136 if (env == NULL) {
137 ALOGE("http service must be created from Java thread");
138 return NULL;
139 }
140
141 jclass mediahttpclass = env->FindClass(clazz);
142 if (mediahttpclass == NULL) {
143 ALOGE("can't find Media(2)HttpService");
144 env->ExceptionClear();
145 return NULL;
146 }
147
148 jmethodID mediaHttpCreateMethod = env->GetStaticMethodID(mediahttpclass, method, signature);
149 if (mediaHttpCreateMethod == NULL) {
150 ALOGE("can't find method");
151 env->ExceptionClear();
152 return NULL;
153 }
154
155 jstring juri = env->NewStringUTF(uri);
156
157 service = env->CallStaticObjectMethod(mediahttpclass, mediaHttpCreateMethod, juri);
158 env->DeleteLocalRef(juri);
159
160 env->ExceptionClear();
Marco Nelissend1ecb912019-09-24 09:27:40 -0700161 sp<MediaHTTPService> httpService = createMediaHttpServiceFromJavaObj(env, service);
Robert Shih730af222018-09-14 14:02:57 -0700162 return httpService;
163
164}
165
Marco Nelissend1ecb912019-09-24 09:27:40 -0700166sp<MediaHTTPService> createMediaHttpService(const char *uri) {
Robert Shih730af222018-09-14 14:02:57 -0700167
168 JNIEnv *env;
169 const char *clazz, *method, *signature;
170
Dichen Zhang52a243e2019-11-08 11:02:03 -0800171 env = NdkJavaVMHelper::getJNIEnv();
172
Marco Nelissend1ecb912019-09-24 09:27:40 -0700173 clazz = "android/media/MediaHTTPService";
174 method = "createHttpServiceBinderIfNecessary";
175 signature = "(Ljava/lang/String;)Landroid/os/IBinder;";
Robert Shih730af222018-09-14 14:02:57 -0700176
Marco Nelissend1ecb912019-09-24 09:27:40 -0700177 return createMediaHttpServiceTemplate(env, uri, clazz, method, signature);
Robert Shih730af222018-09-14 14:02:57 -0700178
179}
180
Robert Shih0df451b2017-12-08 14:16:50 -0800181extern "C" {
182
183EXPORT
184AMediaDataSource* AMediaDataSource_new() {
185 AMediaDataSource *mSource = new AMediaDataSource();
186 mSource->userdata = NULL;
187 mSource->readAt = NULL;
188 mSource->getSize = NULL;
Robert Shih45b88d22018-02-05 13:52:39 -0800189 mSource->close = NULL;
Robert Shih0df451b2017-12-08 14:16:50 -0800190 return mSource;
191}
192
193EXPORT
Robert Shih2568eb92018-09-19 10:00:46 -0700194AMediaDataSource* AMediaDataSource_newUri(
195 const char *uri,
196 int numheaders,
197 const char * const *key_values) {
198
Marco Nelissend1ecb912019-09-24 09:27:40 -0700199 sp<MediaHTTPService> service = createMediaHttpService(uri);
Robert Shih2568eb92018-09-19 10:00:46 -0700200 KeyedVector<String8, String8> headers;
201 for (int i = 0; i < numheaders; ++i) {
202 String8 key8(key_values[i * 2]);
203 String8 value8(key_values[i * 2 + 1]);
204 headers.add(key8, value8);
205 }
206
Dongwon Kang79b0c242019-10-13 08:17:34 -0700207 sp<DataSource> source = DataSourceFactory::getInstance()->CreateFromURI(service, uri, &headers);
Robert Shih49fb89d2018-01-31 17:53:19 -0800208 if (source == NULL) {
209 ALOGE("AMediaDataSource_newUri source is null");
210 return NULL;
211 }
212 ALOGI("AMediaDataSource_newUri source %s flags %u", source->toString().c_str(), source->flags());
Robert Shiha601f4a2018-10-01 15:10:35 -0700213 AMediaDataSource* aSource = convertDataSourceToAMediaDataSource(source);
214 aSource->mImpl = source;
215 aSource->mFlags = source->flags();
216 return aSource;
Robert Shih2568eb92018-09-19 10:00:46 -0700217}
218
219EXPORT
Robert Shih0df451b2017-12-08 14:16:50 -0800220void AMediaDataSource_delete(AMediaDataSource *mSource) {
221 ALOGV("dtor");
222 if (mSource != NULL) {
223 delete mSource;
224 }
225}
226
227EXPORT
228void AMediaDataSource_setUserdata(AMediaDataSource *mSource, void *userdata) {
229 mSource->userdata = userdata;
230}
231
232EXPORT
233void AMediaDataSource_setReadAt(AMediaDataSource *mSource, AMediaDataSourceReadAt readAt) {
234 mSource->readAt = readAt;
235}
236
237EXPORT
238void AMediaDataSource_setGetSize(AMediaDataSource *mSource, AMediaDataSourceGetSize getSize) {
239 mSource->getSize = getSize;
240}
241
Robert Shih45b88d22018-02-05 13:52:39 -0800242EXPORT
243void AMediaDataSource_setClose(AMediaDataSource *mSource, AMediaDataSourceClose close) {
244 mSource->close = close;
245}
246
Robert Shihdabe9d92018-09-22 16:18:05 -0700247EXPORT
248void AMediaDataSource_close(AMediaDataSource *mSource) {
249 return mSource->close(mSource->userdata);
250}
251
Robert Shihca198ce2018-09-22 16:31:55 -0700252EXPORT
253void AMediaDataSource_setGetAvailableSize(AMediaDataSource *mSource,
254 AMediaDataSourceGetAvailableSize getAvailableSize) {
255 mSource->getAvailableSize = getAvailableSize;
256}
257
Robert Shih0df451b2017-12-08 14:16:50 -0800258} // extern "C"
259