• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
43 // The following are not available in frameworks/base/media/java/android/media/MediaExtractor.java
44 // because they are not applicable or useful to that API.
45 static const char *kExtractorEntryPoint = "android.media.mediaextractor.entry";
46 static const char *kExtractorLogSessionId = "android.media.mediaextractor.logSessionId";
47 
48 static const char *kEntryPointSdk = "sdk";
49 static const char *kEntryPointWithJvm = "ndk-with-jvm";
50 static const char *kEntryPointNoJvm = "ndk-no-jvm";
51 static const char *kEntryPointOther = "other";
52 
RemoteMediaExtractor(MediaExtractor * extractor,const sp<DataSource> & source,const sp<RefBase> & plugin)53 RemoteMediaExtractor::RemoteMediaExtractor(
54         MediaExtractor *extractor,
55         const sp<DataSource> &source,
56         const sp<RefBase> &plugin)
57     :mExtractor(extractor),
58      mSource(source),
59      mExtractorPlugin(plugin) {
60 
61     mMetricsItem = nullptr;
62     if (MEDIA_LOG) {
63         mMetricsItem = mediametrics::Item::create(kKeyExtractor);
64 
65         // we're in the extractor service, we want to attribute to the app
66         // that invoked us.
67         int uid = IPCThreadState::self()->getCallingUid();
68         mMetricsItem->setUid(uid);
69 
70         // track the container format (mpeg, aac, wvm, etc)
71         size_t ntracks = extractor->countTracks();
72         mMetricsItem->setCString(kExtractorFormat, extractor->name());
73         // tracks (size_t)
74         mMetricsItem->setInt32(kExtractorTracks, ntracks);
75         // metadata
76         MetaDataBase pMetaData;
77         if (extractor->getMetaData(pMetaData) == OK) {
78             String8 xx = pMetaData.toString();
79             // 'titl' -- but this verges into PII
80             // 'mime'
81             const char *mime = nullptr;
82             if (pMetaData.findCString(kKeyMIMEType, &mime)) {
83                 mMetricsItem->setCString(kExtractorMime,  mime);
84             }
85             // what else is interesting and not already available?
86         }
87         // By default, we set the entry point to be "other". Clients of this
88         // class will override this value by calling setEntryPoint.
89         mMetricsItem->setCString(kExtractorEntryPoint, kEntryPointOther);
90     }
91 }
92 
~RemoteMediaExtractor()93 RemoteMediaExtractor::~RemoteMediaExtractor() {
94     delete mExtractor;
95     mSource->close();
96     mSource.clear();
97     mExtractorPlugin = nullptr;
98     // log the current record, provided it has some information worth recording
99     if (MEDIA_LOG) {
100         if (mMetricsItem != nullptr) {
101             if (mMetricsItem->count() > 0) {
102                 mMetricsItem->selfrecord();
103             }
104         }
105     }
106     if (mMetricsItem != nullptr) {
107         delete mMetricsItem;
108         mMetricsItem = nullptr;
109     }
110 }
111 
countTracks()112 size_t RemoteMediaExtractor::countTracks() {
113     return mExtractor->countTracks();
114 }
115 
getTrack(size_t index)116 sp<IMediaSource> RemoteMediaExtractor::getTrack(size_t index) {
117     MediaTrack *source = mExtractor->getTrack(index);
118     return (source == nullptr)
119             ? nullptr : CreateIMediaSourceFromMediaSourceBase(this, source, mExtractorPlugin);
120 }
121 
getTrackMetaData(size_t index,uint32_t flags)122 sp<MetaData> RemoteMediaExtractor::getTrackMetaData(size_t index, uint32_t flags) {
123     sp<MetaData> meta = new MetaData();
124     if (mExtractor->getTrackMetaData(*meta.get(), index, flags) == OK) {
125         return meta;
126     }
127     return nullptr;
128 }
129 
getMetaData()130 sp<MetaData> RemoteMediaExtractor::getMetaData() {
131     sp<MetaData> meta = new MetaData();
132     if (mExtractor->getMetaData(*meta.get()) == OK) {
133         return meta;
134     }
135     return nullptr;
136 }
137 
getMetrics(Parcel * reply)138 status_t RemoteMediaExtractor::getMetrics(Parcel *reply) {
139     if (mMetricsItem == nullptr || reply == nullptr) {
140         return UNKNOWN_ERROR;
141     }
142 
143     mMetricsItem->writeToParcel(reply);
144     return OK;
145 }
146 
flags() const147 uint32_t RemoteMediaExtractor::flags() const {
148     return mExtractor->flags();
149 }
150 
setMediaCas(const HInterfaceToken & casToken)151 status_t RemoteMediaExtractor::setMediaCas(const HInterfaceToken &casToken) {
152     return mExtractor->setMediaCas((uint8_t*)casToken.data(), casToken.size());
153 }
154 
name()155 String8 RemoteMediaExtractor::name() {
156     return String8(mExtractor->name());
157 }
158 
setEntryPoint(EntryPoint entryPoint)159 status_t RemoteMediaExtractor::setEntryPoint(EntryPoint entryPoint) {
160     const char* entryPointString;
161     switch (entryPoint) {
162       case EntryPoint::SDK:
163             entryPointString = kEntryPointSdk;
164             break;
165         case EntryPoint::NDK_WITH_JVM:
166             entryPointString = kEntryPointWithJvm;
167             break;
168         case EntryPoint::NDK_NO_JVM:
169             entryPointString = kEntryPointNoJvm;
170             break;
171         case EntryPoint::OTHER:
172             entryPointString = kEntryPointOther;
173             break;
174         default:
175             return BAD_VALUE;
176     }
177     mMetricsItem->setCString(kExtractorEntryPoint, entryPointString);
178     return OK;
179 }
180 
setLogSessionId(const String8 & logSessionId)181 status_t RemoteMediaExtractor::setLogSessionId(const String8& logSessionId) {
182     mMetricsItem->setCString(kExtractorLogSessionId, logSessionId.c_str());
183     return OK;
184 }
185 
186 ////////////////////////////////////////////////////////////////////////////////
187 
188 // static
wrap(MediaExtractor * extractor,const sp<DataSource> & source,const sp<RefBase> & plugin)189 sp<IMediaExtractor> RemoteMediaExtractor::wrap(
190         MediaExtractor *extractor,
191         const sp<DataSource> &source,
192         const sp<RefBase> &plugin) {
193     if (extractor == nullptr) {
194         return nullptr;
195     }
196     return new RemoteMediaExtractor(extractor, source, plugin);
197 }
198 
199 }  // namespace android
200