blob: bfc43a64df53a2d46fb76bba37a2dcb457e17f60 [file] [log] [blame]
Marco Nelissenb2487f02015-09-01 13:23:23 -07001/*
2 * Copyright (C) 2009 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
Marco Nelissenb65990f2015-11-09 15:39:49 -080017//#define LOG_NDEBUG 0
Marco Nelissenb2487f02015-09-01 13:23:23 -070018#define LOG_TAG "BpMediaExtractor"
19#include <utils/Log.h>
20
21#include <stdint.h>
22#include <sys/types.h>
23
Marco Nelissen69d3d8a2016-03-07 13:20:01 -080024#include <binder/IPCThreadState.h>
Marco Nelissenb2487f02015-09-01 13:23:23 -070025#include <binder/Parcel.h>
26#include <media/IMediaExtractor.h>
27#include <media/stagefright/MetaData.h>
28
29namespace android {
30
31enum {
32 COUNTTRACKS = IBinder::FIRST_CALL_TRANSACTION,
33 GETTRACK,
34 GETTRACKMETADATA,
35 GETMETADATA,
36 FLAGS,
Marco Nelissenb2487f02015-09-01 13:23:23 -070037 GETDRMTRACKINFO,
38 SETUID,
Ray Essickba13b7b2017-02-07 10:03:18 -080039 NAME,
40 GETMETRICS
Marco Nelissenb2487f02015-09-01 13:23:23 -070041};
42
43class BpMediaExtractor : public BpInterface<IMediaExtractor> {
44public:
Chih-Hung Hsieh64a28702016-05-03 09:52:51 -070045 explicit BpMediaExtractor(const sp<IBinder>& impl)
Marco Nelissenb2487f02015-09-01 13:23:23 -070046 : BpInterface<IMediaExtractor>(impl)
47 {
48 }
49
50 virtual size_t countTracks() {
51 ALOGV("countTracks");
52 Parcel data, reply;
53 data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
54 status_t ret = remote()->transact(COUNTTRACKS, data, &reply);
55 size_t numTracks = 0;
56 if (ret == NO_ERROR) {
57 numTracks = reply.readUint32();
58 }
59 return numTracks;
60 }
61 virtual sp<IMediaSource> getTrack(size_t index) {
62 ALOGV("getTrack(%zu)", index);
63 Parcel data, reply;
64 data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
65 data.writeUint32(index);
66 status_t ret = remote()->transact(GETTRACK, data, &reply);
67 if (ret == NO_ERROR) {
68 return interface_cast<IMediaSource>(reply.readStrongBinder());
69 }
70 return NULL;
71 }
72
73 virtual sp<MetaData> getTrackMetaData(
74 size_t index, uint32_t flags) {
75 ALOGV("getTrackMetaData(%zu, %u)", index, flags);
76 Parcel data, reply;
77 data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
78 data.writeUint32(index);
79 data.writeUint32(flags);
80 status_t ret = remote()->transact(GETTRACKMETADATA, data, &reply);
81 if (ret == NO_ERROR) {
82 return MetaData::createFromParcel(reply);
83 }
84 return NULL;
85 }
86
87 virtual sp<MetaData> getMetaData() {
88 ALOGV("getMetaData");
89 Parcel data, reply;
90 data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
91 status_t ret = remote()->transact(GETMETADATA, data, &reply);
92 if (ret == NO_ERROR) {
93 return MetaData::createFromParcel(reply);
94 }
95 return NULL;
96 }
97
Ray Essickba13b7b2017-02-07 10:03:18 -080098 virtual status_t getMetrics(Parcel * reply) {
99 Parcel data;
100 data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
101 status_t ret = remote()->transact(GETMETRICS, data, reply);
102 if (ret == NO_ERROR) {
103 return OK;
104 }
105 return UNKNOWN_ERROR;
106 }
107
Marco Nelissenb2487f02015-09-01 13:23:23 -0700108 virtual uint32_t flags() const {
109 ALOGV("flags NOT IMPLEMENTED");
110 return 0;
111 }
112
Marco Nelissenb2487f02015-09-01 13:23:23 -0700113 virtual char* getDrmTrackInfo(size_t trackID __unused, int *len __unused) {
114 ALOGV("getDrmTrackInfo NOT IMPLEMENTED");
115 return NULL;
116 }
117 virtual void setUID(uid_t uid __unused) {
118 ALOGV("setUID NOT IMPLEMENTED");
119 }
120
121 virtual const char * name() {
122 ALOGV("name NOT IMPLEMENTED");
123 return NULL;
124 }
125};
126
127IMPLEMENT_META_INTERFACE(MediaExtractor, "android.media.IMediaExtractor");
128
129#undef LOG_TAG
130#define LOG_TAG "BnMediaExtractor"
131
132status_t BnMediaExtractor::onTransact(
133 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
134{
135 switch (code) {
136 case COUNTTRACKS: {
137 ALOGV("countTracks");
138 CHECK_INTERFACE(IMediaExtractor, data, reply);
139 size_t numTracks = countTracks();
140 if (numTracks > INT32_MAX) {
141 numTracks = 0;
142 }
143 reply->writeUint32(uint32_t(numTracks));
144 return NO_ERROR;
145 }
146 case GETTRACK: {
147 ALOGV("getTrack()");
148 CHECK_INTERFACE(IMediaExtractor, data, reply);
149 uint32_t idx;
150 if (data.readUint32(&idx) == NO_ERROR) {
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800151 const sp<IMediaSource> track = getTrack(size_t(idx));
152 registerMediaSource(this, track);
153 return reply->writeStrongBinder(IInterface::asBinder(track));
Marco Nelissenb2487f02015-09-01 13:23:23 -0700154 }
155 return UNKNOWN_ERROR;
156 }
157 case GETTRACKMETADATA: {
158 ALOGV("getTrackMetaData");
159 CHECK_INTERFACE(IMediaExtractor, data, reply);
160 uint32_t idx;
161 uint32_t flags;
162 if (data.readUint32(&idx) == NO_ERROR &&
163 data.readUint32(&flags) == NO_ERROR) {
164 sp<MetaData> meta = getTrackMetaData(idx, flags);
Marco Nelissen0d138242016-10-06 15:31:52 -0700165 if (meta == NULL) {
166 return UNKNOWN_ERROR;
167 }
Marco Nelissenb2487f02015-09-01 13:23:23 -0700168 meta->writeToParcel(*reply);
169 return NO_ERROR;
170 }
171 return UNKNOWN_ERROR;
172 }
173 case GETMETADATA: {
174 ALOGV("getMetaData");
175 CHECK_INTERFACE(IMediaExtractor, data, reply);
176 sp<MetaData> meta = getMetaData();
177 if (meta != NULL) {
178 meta->writeToParcel(*reply);
179 return NO_ERROR;
180 }
181 return UNKNOWN_ERROR;
182 }
Ray Essickba13b7b2017-02-07 10:03:18 -0800183 case GETMETRICS: {
184 CHECK_INTERFACE(IMediaExtractor, data, reply);
185 status_t ret = getMetrics(reply);
186 return ret;
187 }
Marco Nelissenb2487f02015-09-01 13:23:23 -0700188 default:
189 return BBinder::onTransact(code, data, reply, flags);
190 }
191}
192
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800193typedef struct {
194 String8 mime;
195 String8 name;
196 String8 sourceDescription;
197 pid_t owner;
198 wp<IMediaExtractor> extractor;
199 Vector<wp<IMediaSource>> tracks;
200 Vector<String8> trackDescriptions;
201 String8 toString() const;
202} ExtractorInstance;
203
204String8 ExtractorInstance::toString() const {
205 String8 str = name;
206 str.append(" for mime ");
207 str.append(mime);
208 str.append(", source ");
209 str.append(sourceDescription);
210 str.append(String8::format(", pid %d: ", owner));
211 if (extractor.promote() == NULL) {
212 str.append("deleted\n");
213 } else {
214 str.append("active\n");
215 }
216 for (size_t i = 0; i < tracks.size(); i++) {
217 const String8 desc = trackDescriptions.itemAt(i);
218 str.appendFormat(" track {%s} ", desc.string());
Marco Nelissen460b7e82016-12-19 14:06:30 -0800219 wp<IMediaSource> wSource = tracks.itemAt(i);
220 if (wSource == NULL) {
221 str.append(": null\n");
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800222 } else {
Marco Nelissen460b7e82016-12-19 14:06:30 -0800223 const sp<IMediaSource> source = wSource.promote();
224 if (source == NULL) {
225 str.append(": deleted\n");
226 } else {
227 str.appendFormat(": active\n");
228 }
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800229 }
230 }
231 return str;
232}
233
Marco Nelissen8d27f5e2016-04-14 08:06:26 -0700234static Vector<ExtractorInstance> sExtractors;
235static Mutex sExtractorsLock;
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800236
237void registerMediaSource(
238 const sp<IMediaExtractor> &ex,
239 const sp<IMediaSource> &source) {
Marco Nelissen8d27f5e2016-04-14 08:06:26 -0700240 Mutex::Autolock lock(sExtractorsLock);
241 for (size_t i = 0; i < sExtractors.size(); i++) {
242 ExtractorInstance &instance = sExtractors.editItemAt(i);
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800243 sp<IMediaExtractor> extractor = instance.extractor.promote();
244 if (extractor != NULL && extractor == ex) {
245 if (instance.tracks.size() > 5) {
246 instance.tracks.resize(5);
Marco Nelissen460b7e82016-12-19 14:06:30 -0800247 instance.trackDescriptions.resize(5);
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800248 }
249 instance.tracks.push_front(source);
Marco Nelissen460b7e82016-12-19 14:06:30 -0800250 if (source != NULL) {
251 instance.trackDescriptions.push_front(source->getFormat()->toString());
252 } else {
253 instance.trackDescriptions.push_front(String8::empty());
254 }
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800255 break;
256 }
257 }
258}
259
260void registerMediaExtractor(
261 const sp<IMediaExtractor> &extractor,
Marco Nelissena3214692016-05-06 10:57:20 -0700262 const sp<DataSource> &source,
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800263 const char *mime) {
264 ExtractorInstance ex;
265 ex.mime = mime == NULL ? "NULL" : mime;
266 ex.name = extractor->name();
267 ex.sourceDescription = source->toString();
268 ex.owner = IPCThreadState::self()->getCallingPid();
269 ex.extractor = extractor;
270
Marco Nelissen8d27f5e2016-04-14 08:06:26 -0700271 {
272 Mutex::Autolock lock(sExtractorsLock);
273 if (sExtractors.size() > 10) {
274 sExtractors.resize(10);
275 }
276 sExtractors.push_front(ex);
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800277 }
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800278}
279
280status_t dumpExtractors(int fd, const Vector<String16>&) {
281 String8 out;
282 out.append("Recent extractors, most recent first:\n");
Marco Nelissen8d27f5e2016-04-14 08:06:26 -0700283 {
284 Mutex::Autolock lock(sExtractorsLock);
285 for (size_t i = 0; i < sExtractors.size(); i++) {
286 const ExtractorInstance &instance = sExtractors.itemAt(i);
287 out.append(" ");
288 out.append(instance.toString());
289 }
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800290 }
291 write(fd, out.string(), out.size());
292 return OK;
293}
294
Marco Nelissenb2487f02015-09-01 13:23:23 -0700295
296} // namespace android
297