1 /*
2 * Copyright 2017, 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 "RemoteMediaExtractor"
19 #include <utils/Log.h>
20
21 #include <binder/IPCThreadState.h>
22 #include <media/stagefright/InterfaceUtils.h>
23 #include <media/MediaMetricsItem.h>
24 #include <media/stagefright/MediaSource.h>
25 #include <media/stagefright/RemoteMediaExtractor.h>
26
27 // still doing some on/off toggling here.
28 #define MEDIA_LOG 1
29
30 namespace android {
31
32 // key for media statistics
33 static const char *kKeyExtractor = "extractor";
34
35 // attrs for media statistics
36 // NB: these are matched with public Java API constants defined
37 // in frameworks/base/media/java/android/media/MediaExtractor.java
38 // These must be kept synchronized with the constants there.
39 static const char *kExtractorFormat = "android.media.mediaextractor.fmt";
40 static const char *kExtractorMime = "android.media.mediaextractor.mime";
41 static const char *kExtractorTracks = "android.media.mediaextractor.ntrk";
42 static const char *kExtractorEntryPoint = "android.media.mediaextractor.entry";
43
44 static const char *kEntryPointSdk = "sdk";
45 static const char *kEntryPointWithJvm = "ndk-with-jvm";
46 static const char *kEntryPointNoJvm = "ndk-no-jvm";
47 static const char *kEntryPointOther = "other";
48
RemoteMediaExtractor(MediaExtractor * extractor,const sp<DataSource> & source,const sp<RefBase> & plugin)49 RemoteMediaExtractor::RemoteMediaExtractor(
50 MediaExtractor *extractor,
51 const sp<DataSource> &source,
52 const sp<RefBase> &plugin)
53 :mExtractor(extractor),
54 mSource(source),
55 mExtractorPlugin(plugin) {
56
57 mMetricsItem = nullptr;
58 if (MEDIA_LOG) {
59 mMetricsItem = mediametrics::Item::create(kKeyExtractor);
60
61 // we're in the extractor service, we want to attribute to the app
62 // that invoked us.
63 int uid = IPCThreadState::self()->getCallingUid();
64 mMetricsItem->setUid(uid);
65
66 // track the container format (mpeg, aac, wvm, etc)
67 size_t ntracks = extractor->countTracks();
68 mMetricsItem->setCString(kExtractorFormat, extractor->name());
69 // tracks (size_t)
70 mMetricsItem->setInt32(kExtractorTracks, ntracks);
71 // metadata
72 MetaDataBase pMetaData;
73 if (extractor->getMetaData(pMetaData) == OK) {
74 String8 xx = pMetaData.toString();
75 // 'titl' -- but this verges into PII
76 // 'mime'
77 const char *mime = nullptr;
78 if (pMetaData.findCString(kKeyMIMEType, &mime)) {
79 mMetricsItem->setCString(kExtractorMime, mime);
80 }
81 // what else is interesting and not already available?
82 }
83 // By default, we set the entry point to be "other". Clients of this
84 // class will override this value by calling setEntryPoint.
85 mMetricsItem->setCString(kExtractorEntryPoint, kEntryPointOther);
86 }
87 }
88
~RemoteMediaExtractor()89 RemoteMediaExtractor::~RemoteMediaExtractor() {
90 delete mExtractor;
91 mSource->close();
92 mSource.clear();
93 mExtractorPlugin = nullptr;
94 // log the current record, provided it has some information worth recording
95 if (MEDIA_LOG) {
96 if (mMetricsItem != nullptr) {
97 if (mMetricsItem->count() > 0) {
98 mMetricsItem->selfrecord();
99 }
100 }
101 }
102 if (mMetricsItem != nullptr) {
103 delete mMetricsItem;
104 mMetricsItem = nullptr;
105 }
106 }
107
countTracks()108 size_t RemoteMediaExtractor::countTracks() {
109 return mExtractor->countTracks();
110 }
111
getTrack(size_t index)112 sp<IMediaSource> RemoteMediaExtractor::getTrack(size_t index) {
113 MediaTrack *source = mExtractor->getTrack(index);
114 return (source == nullptr)
115 ? nullptr : CreateIMediaSourceFromMediaSourceBase(this, source, mExtractorPlugin);
116 }
117
getTrackMetaData(size_t index,uint32_t flags)118 sp<MetaData> RemoteMediaExtractor::getTrackMetaData(size_t index, uint32_t flags) {
119 sp<MetaData> meta = new MetaData();
120 if (mExtractor->getTrackMetaData(*meta.get(), index, flags) == OK) {
121 return meta;
122 }
123 return nullptr;
124 }
125
getMetaData()126 sp<MetaData> RemoteMediaExtractor::getMetaData() {
127 sp<MetaData> meta = new MetaData();
128 if (mExtractor->getMetaData(*meta.get()) == OK) {
129 return meta;
130 }
131 return nullptr;
132 }
133
getMetrics(Parcel * reply)134 status_t RemoteMediaExtractor::getMetrics(Parcel *reply) {
135 if (mMetricsItem == nullptr || reply == nullptr) {
136 return UNKNOWN_ERROR;
137 }
138
139 mMetricsItem->writeToParcel(reply);
140 return OK;
141 }
142
flags() const143 uint32_t RemoteMediaExtractor::flags() const {
144 return mExtractor->flags();
145 }
146
setMediaCas(const HInterfaceToken & casToken)147 status_t RemoteMediaExtractor::setMediaCas(const HInterfaceToken &casToken) {
148 return mExtractor->setMediaCas((uint8_t*)casToken.data(), casToken.size());
149 }
150
name()151 String8 RemoteMediaExtractor::name() {
152 return String8(mExtractor->name());
153 }
154
setEntryPoint(EntryPoint entryPoint)155 status_t RemoteMediaExtractor::setEntryPoint(EntryPoint entryPoint) {
156 const char* entryPointString;
157 switch (entryPoint) {
158 case EntryPoint::SDK:
159 entryPointString = kEntryPointSdk;
160 break;
161 case EntryPoint::NDK_WITH_JVM:
162 entryPointString = kEntryPointWithJvm;
163 break;
164 case EntryPoint::NDK_NO_JVM:
165 entryPointString = kEntryPointNoJvm;
166 break;
167 case EntryPoint::OTHER:
168 entryPointString = kEntryPointOther;
169 break;
170 default:
171 return BAD_VALUE;
172 }
173 mMetricsItem->setCString(kExtractorEntryPoint, entryPointString);
174 return OK;
175 }
176
177 ////////////////////////////////////////////////////////////////////////////////
178
179 // static
wrap(MediaExtractor * extractor,const sp<DataSource> & source,const sp<RefBase> & plugin)180 sp<IMediaExtractor> RemoteMediaExtractor::wrap(
181 MediaExtractor *extractor,
182 const sp<DataSource> &source,
183 const sp<RefBase> &plugin) {
184 if (extractor == nullptr) {
185 return nullptr;
186 }
187 return new RemoteMediaExtractor(extractor, source, plugin);
188 }
189
190 } // namespace android
191