• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "BpMediaExtractor"
19 #include <utils/Log.h>
20 
21 #include <stdint.h>
22 #include <sys/types.h>
23 
24 #include <binder/IPCThreadState.h>
25 #include <binder/Parcel.h>
26 #include <media/IMediaExtractor.h>
27 #include <media/stagefright/MetaData.h>
28 
29 namespace android {
30 
31 enum {
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 
44 class BpMediaExtractor : public BpInterface<IMediaExtractor> {
45 public:
BpMediaExtractor(const sp<IBinder> & impl)46     BpMediaExtractor(const sp<IBinder>& impl)
47         : BpInterface<IMediaExtractor>(impl)
48     {
49     }
50 
countTracks()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     }
getTrack(size_t index)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 
getTrackMetaData(size_t index,uint32_t flags)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 
getMetaData()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 
flags() const99     virtual uint32_t flags() const {
100         ALOGV("flags NOT IMPLEMENTED");
101         return 0;
102     }
103 
setDrmFlag(bool flag __unused)104     virtual void setDrmFlag(bool flag __unused) {
105         ALOGV("setDrmFlag NOT IMPLEMENTED");
106     }
getDrmFlag()107     virtual bool getDrmFlag() {
108         ALOGV("getDrmFlag NOT IMPLEMENTED");
109        return false;
110     }
getDrmTrackInfo(size_t trackID __unused,int * len __unused)111     virtual char* getDrmTrackInfo(size_t trackID __unused, int *len __unused) {
112         ALOGV("getDrmTrackInfo NOT IMPLEMENTED");
113         return NULL;
114     }
setUID(uid_t uid __unused)115     virtual void setUID(uid_t uid __unused) {
116         ALOGV("setUID NOT IMPLEMENTED");
117     }
118 
name()119     virtual const char * name() {
120         ALOGV("name NOT IMPLEMENTED");
121         return NULL;
122     }
123 };
124 
125 IMPLEMENT_META_INTERFACE(MediaExtractor, "android.media.IMediaExtractor");
126 
127 #undef LOG_TAG
128 #define LOG_TAG "BnMediaExtractor"
129 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)130 status_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) {
149                 const sp<IMediaSource> track = getTrack(size_t(idx));
150                 registerMediaSource(this, track);
151                 return reply->writeStrongBinder(IInterface::asBinder(track));
152             }
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);
163                 if (meta == NULL) {
164                     return UNKNOWN_ERROR;
165                 }
166                 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 
186 typedef 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 
toString() const197 String8 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 
222 static Vector<ExtractorInstance> sExtractors;
223 static Mutex sExtractorsLock;
224 
registerMediaSource(const sp<IMediaExtractor> & ex,const sp<IMediaSource> & source)225 void registerMediaSource(
226         const sp<IMediaExtractor> &ex,
227         const sp<IMediaSource> &source) {
228     Mutex::Autolock lock(sExtractorsLock);
229     for (size_t i = 0; i < sExtractors.size(); i++) {
230         ExtractorInstance &instance = sExtractors.editItemAt(i);
231         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 
registerMediaExtractor(const sp<IMediaExtractor> & extractor,const sp<DataSource> & source,const char * mime)243 void registerMediaExtractor(
244         const sp<IMediaExtractor> &extractor,
245         const sp<DataSource> &source,
246         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 
254     {
255         Mutex::Autolock lock(sExtractorsLock);
256         if (sExtractors.size() > 10) {
257             sExtractors.resize(10);
258         }
259         sExtractors.push_front(ex);
260     }
261 }
262 
dumpExtractors(int fd,const Vector<String16> &)263 status_t dumpExtractors(int fd, const Vector<String16>&) {
264     String8 out;
265     out.append("Recent extractors, most recent first:\n");
266     {
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         }
273     }
274     write(fd, out.string(), out.size());
275     return OK;
276 }
277 
278 
279 }  // namespace android
280 
281