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 
RemoteMediaExtractor(MediaExtractor * extractor,const sp<DataSource> & source,const sp<RefBase> & plugin)43 RemoteMediaExtractor::RemoteMediaExtractor(
44         MediaExtractor *extractor,
45         const sp<DataSource> &source,
46         const sp<RefBase> &plugin)
47     :mExtractor(extractor),
48      mSource(source),
49      mExtractorPlugin(plugin) {
50 
51     mMetricsItem = nullptr;
52     if (MEDIA_LOG) {
53         mMetricsItem = mediametrics::Item::create(kKeyExtractor);
54 
55         // we're in the extractor service, we want to attribute to the app
56         // that invoked us.
57         int uid = IPCThreadState::self()->getCallingUid();
58         mMetricsItem->setUid(uid);
59 
60         // track the container format (mpeg, aac, wvm, etc)
61         size_t ntracks = extractor->countTracks();
62         mMetricsItem->setCString(kExtractorFormat, extractor->name());
63         // tracks (size_t)
64         mMetricsItem->setInt32(kExtractorTracks, ntracks);
65         // metadata
66         MetaDataBase pMetaData;
67         if (extractor->getMetaData(pMetaData) == OK) {
68             String8 xx = pMetaData.toString();
69             // 'titl' -- but this verges into PII
70             // 'mime'
71             const char *mime = nullptr;
72             if (pMetaData.findCString(kKeyMIMEType, &mime)) {
73                 mMetricsItem->setCString(kExtractorMime,  mime);
74             }
75             // what else is interesting and not already available?
76         }
77     }
78 }
79 
~RemoteMediaExtractor()80 RemoteMediaExtractor::~RemoteMediaExtractor() {
81     delete mExtractor;
82     mSource->close();
83     mSource.clear();
84     mExtractorPlugin = nullptr;
85     // log the current record, provided it has some information worth recording
86     if (MEDIA_LOG) {
87         if (mMetricsItem != nullptr) {
88             if (mMetricsItem->count() > 0) {
89                 mMetricsItem->selfrecord();
90             }
91         }
92     }
93     if (mMetricsItem != nullptr) {
94         delete mMetricsItem;
95         mMetricsItem = nullptr;
96     }
97 }
98 
countTracks()99 size_t RemoteMediaExtractor::countTracks() {
100     return mExtractor->countTracks();
101 }
102 
getTrack(size_t index)103 sp<IMediaSource> RemoteMediaExtractor::getTrack(size_t index) {
104     MediaTrack *source = mExtractor->getTrack(index);
105     return (source == nullptr)
106             ? nullptr : CreateIMediaSourceFromMediaSourceBase(this, source, mExtractorPlugin);
107 }
108 
getTrackMetaData(size_t index,uint32_t flags)109 sp<MetaData> RemoteMediaExtractor::getTrackMetaData(size_t index, uint32_t flags) {
110     sp<MetaData> meta = new MetaData();
111     if (mExtractor->getTrackMetaData(*meta.get(), index, flags) == OK) {
112         return meta;
113     }
114     return nullptr;
115 }
116 
getMetaData()117 sp<MetaData> RemoteMediaExtractor::getMetaData() {
118     sp<MetaData> meta = new MetaData();
119     if (mExtractor->getMetaData(*meta.get()) == OK) {
120         return meta;
121     }
122     return nullptr;
123 }
124 
getMetrics(Parcel * reply)125 status_t RemoteMediaExtractor::getMetrics(Parcel *reply) {
126     if (mMetricsItem == nullptr || reply == nullptr) {
127         return UNKNOWN_ERROR;
128     }
129 
130     mMetricsItem->writeToParcel(reply);
131     return OK;
132 }
133 
flags() const134 uint32_t RemoteMediaExtractor::flags() const {
135     return mExtractor->flags();
136 }
137 
setMediaCas(const HInterfaceToken & casToken)138 status_t RemoteMediaExtractor::setMediaCas(const HInterfaceToken &casToken) {
139     return mExtractor->setMediaCas((uint8_t*)casToken.data(), casToken.size());
140 }
141 
name()142 String8 RemoteMediaExtractor::name() {
143     return String8(mExtractor->name());
144 }
145 
146 ////////////////////////////////////////////////////////////////////////////////
147 
148 // static
wrap(MediaExtractor * extractor,const sp<DataSource> & source,const sp<RefBase> & plugin)149 sp<IMediaExtractor> RemoteMediaExtractor::wrap(
150         MediaExtractor *extractor,
151         const sp<DataSource> &source,
152         const sp<RefBase> &plugin) {
153     if (extractor == nullptr) {
154         return nullptr;
155     }
156     return new RemoteMediaExtractor(extractor, source, plugin);
157 }
158 
159 }  // namespace android
160