blob: 72d1d7c57f93893b95d1acee9c29d364995472d6 [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,
37 SETDRMFLAG,
38 GETDRMFLAG,
39 GETDRMTRACKINFO,
40 SETUID,
41 NAME
42};
43
44class BpMediaExtractor : public BpInterface<IMediaExtractor> {
45public:
46 BpMediaExtractor(const sp<IBinder>& impl)
47 : BpInterface<IMediaExtractor>(impl)
48 {
49 }
50
51 virtual size_t countTracks() {
52 ALOGV("countTracks");
53 Parcel data, reply;
54 data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
55 status_t ret = remote()->transact(COUNTTRACKS, data, &reply);
56 size_t numTracks = 0;
57 if (ret == NO_ERROR) {
58 numTracks = reply.readUint32();
59 }
60 return numTracks;
61 }
62 virtual sp<IMediaSource> getTrack(size_t index) {
63 ALOGV("getTrack(%zu)", index);
64 Parcel data, reply;
65 data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
66 data.writeUint32(index);
67 status_t ret = remote()->transact(GETTRACK, data, &reply);
68 if (ret == NO_ERROR) {
69 return interface_cast<IMediaSource>(reply.readStrongBinder());
70 }
71 return NULL;
72 }
73
74 virtual sp<MetaData> getTrackMetaData(
75 size_t index, uint32_t flags) {
76 ALOGV("getTrackMetaData(%zu, %u)", index, flags);
77 Parcel data, reply;
78 data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
79 data.writeUint32(index);
80 data.writeUint32(flags);
81 status_t ret = remote()->transact(GETTRACKMETADATA, data, &reply);
82 if (ret == NO_ERROR) {
83 return MetaData::createFromParcel(reply);
84 }
85 return NULL;
86 }
87
88 virtual sp<MetaData> getMetaData() {
89 ALOGV("getMetaData");
90 Parcel data, reply;
91 data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
92 status_t ret = remote()->transact(GETMETADATA, data, &reply);
93 if (ret == NO_ERROR) {
94 return MetaData::createFromParcel(reply);
95 }
96 return NULL;
97 }
98
99 virtual uint32_t flags() const {
100 ALOGV("flags NOT IMPLEMENTED");
101 return 0;
102 }
103
104 virtual void setDrmFlag(bool flag __unused) {
105 ALOGV("setDrmFlag NOT IMPLEMENTED");
106 }
107 virtual bool getDrmFlag() {
108 ALOGV("getDrmFlag NOT IMPLEMENTED");
109 return false;
110 }
111 virtual char* getDrmTrackInfo(size_t trackID __unused, int *len __unused) {
112 ALOGV("getDrmTrackInfo NOT IMPLEMENTED");
113 return NULL;
114 }
115 virtual void setUID(uid_t uid __unused) {
116 ALOGV("setUID NOT IMPLEMENTED");
117 }
118
119 virtual const char * name() {
120 ALOGV("name NOT IMPLEMENTED");
121 return NULL;
122 }
123};
124
125IMPLEMENT_META_INTERFACE(MediaExtractor, "android.media.IMediaExtractor");
126
127#undef LOG_TAG
128#define LOG_TAG "BnMediaExtractor"
129
130status_t BnMediaExtractor::onTransact(
131 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
132{
133 switch (code) {
134 case COUNTTRACKS: {
135 ALOGV("countTracks");
136 CHECK_INTERFACE(IMediaExtractor, data, reply);
137 size_t numTracks = countTracks();
138 if (numTracks > INT32_MAX) {
139 numTracks = 0;
140 }
141 reply->writeUint32(uint32_t(numTracks));
142 return NO_ERROR;
143 }
144 case GETTRACK: {
145 ALOGV("getTrack()");
146 CHECK_INTERFACE(IMediaExtractor, data, reply);
147 uint32_t idx;
148 if (data.readUint32(&idx) == NO_ERROR) {
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800149 const sp<IMediaSource> track = getTrack(size_t(idx));
150 registerMediaSource(this, track);
151 return reply->writeStrongBinder(IInterface::asBinder(track));
Marco Nelissenb2487f02015-09-01 13:23:23 -0700152 }
153 return UNKNOWN_ERROR;
154 }
155 case GETTRACKMETADATA: {
156 ALOGV("getTrackMetaData");
157 CHECK_INTERFACE(IMediaExtractor, data, reply);
158 uint32_t idx;
159 uint32_t flags;
160 if (data.readUint32(&idx) == NO_ERROR &&
161 data.readUint32(&flags) == NO_ERROR) {
162 sp<MetaData> meta = getTrackMetaData(idx, flags);
Marco Nelissen0d138242016-10-06 15:31:52 -0700163 if (meta == NULL) {
164 return UNKNOWN_ERROR;
165 }
Marco Nelissenb2487f02015-09-01 13:23:23 -0700166 meta->writeToParcel(*reply);
167 return NO_ERROR;
168 }
169 return UNKNOWN_ERROR;
170 }
171 case GETMETADATA: {
172 ALOGV("getMetaData");
173 CHECK_INTERFACE(IMediaExtractor, data, reply);
174 sp<MetaData> meta = getMetaData();
175 if (meta != NULL) {
176 meta->writeToParcel(*reply);
177 return NO_ERROR;
178 }
179 return UNKNOWN_ERROR;
180 }
181 default:
182 return BBinder::onTransact(code, data, reply, flags);
183 }
184}
185
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800186typedef struct {
187 String8 mime;
188 String8 name;
189 String8 sourceDescription;
190 pid_t owner;
191 wp<IMediaExtractor> extractor;
192 Vector<wp<IMediaSource>> tracks;
193 Vector<String8> trackDescriptions;
194 String8 toString() const;
195} ExtractorInstance;
196
197String8 ExtractorInstance::toString() const {
198 String8 str = name;
199 str.append(" for mime ");
200 str.append(mime);
201 str.append(", source ");
202 str.append(sourceDescription);
203 str.append(String8::format(", pid %d: ", owner));
204 if (extractor.promote() == NULL) {
205 str.append("deleted\n");
206 } else {
207 str.append("active\n");
208 }
209 for (size_t i = 0; i < tracks.size(); i++) {
210 const String8 desc = trackDescriptions.itemAt(i);
211 str.appendFormat(" track {%s} ", desc.string());
212 const sp<IMediaSource> source = tracks.itemAt(i).promote();
213 if (source == NULL) {
214 str.append(": deleted\n");
215 } else {
216 str.appendFormat(": active\n");
217 }
218 }
219 return str;
220}
221
Marco Nelissen8d27f5e2016-04-14 08:06:26 -0700222static Vector<ExtractorInstance> sExtractors;
223static Mutex sExtractorsLock;
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800224
225void registerMediaSource(
226 const sp<IMediaExtractor> &ex,
227 const sp<IMediaSource> &source) {
Marco Nelissen8d27f5e2016-04-14 08:06:26 -0700228 Mutex::Autolock lock(sExtractorsLock);
229 for (size_t i = 0; i < sExtractors.size(); i++) {
230 ExtractorInstance &instance = sExtractors.editItemAt(i);
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800231 sp<IMediaExtractor> extractor = instance.extractor.promote();
232 if (extractor != NULL && extractor == ex) {
233 if (instance.tracks.size() > 5) {
234 instance.tracks.resize(5);
235 }
236 instance.tracks.push_front(source);
237 instance.trackDescriptions.add(source->getFormat()->toString());
238 break;
239 }
240 }
241}
242
243void registerMediaExtractor(
244 const sp<IMediaExtractor> &extractor,
Marco Nelissena3214692016-05-06 10:57:20 -0700245 const sp<DataSource> &source,
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800246 const char *mime) {
247 ExtractorInstance ex;
248 ex.mime = mime == NULL ? "NULL" : mime;
249 ex.name = extractor->name();
250 ex.sourceDescription = source->toString();
251 ex.owner = IPCThreadState::self()->getCallingPid();
252 ex.extractor = extractor;
253
Marco Nelissen8d27f5e2016-04-14 08:06:26 -0700254 {
255 Mutex::Autolock lock(sExtractorsLock);
256 if (sExtractors.size() > 10) {
257 sExtractors.resize(10);
258 }
259 sExtractors.push_front(ex);
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800260 }
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800261}
262
263status_t dumpExtractors(int fd, const Vector<String16>&) {
264 String8 out;
265 out.append("Recent extractors, most recent first:\n");
Marco Nelissen8d27f5e2016-04-14 08:06:26 -0700266 {
267 Mutex::Autolock lock(sExtractorsLock);
268 for (size_t i = 0; i < sExtractors.size(); i++) {
269 const ExtractorInstance &instance = sExtractors.itemAt(i);
270 out.append(" ");
271 out.append(instance.toString());
272 }
Marco Nelissen69d3d8a2016-03-07 13:20:01 -0800273 }
274 write(fd, out.string(), out.size());
275 return OK;
276}
277
Marco Nelissenb2487f02015-09-01 13:23:23 -0700278
279} // namespace android
280