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 <media/stagefright/InterfaceUtils.h>
22 #include <media/MediaAnalyticsItem.h>
23 #include <media/MediaSource.h>
24 #include <media/stagefright/RemoteMediaExtractor.h>
25 
26 // still doing some on/off toggling here.
27 #define MEDIA_LOG       1
28 
29 namespace android {
30 
31 // key for media statistics
32 static const char *kKeyExtractor = "extractor";
33 
34 // attrs for media statistics
35 // NB: these are matched with public Java API constants defined
36 // in frameworks/base/media/java/android/media/MediaExtractor.java
37 // These must be kept synchronized with the constants there.
38 static const char *kExtractorFormat = "android.media.mediaextractor.fmt";
39 static const char *kExtractorMime = "android.media.mediaextractor.mime";
40 static const char *kExtractorTracks = "android.media.mediaextractor.ntrk";
41 
RemoteMediaExtractor(MediaExtractor * extractor,const sp<DataSource> & source,const sp<RefBase> & plugin)42 RemoteMediaExtractor::RemoteMediaExtractor(
43         MediaExtractor *extractor,
44         const sp<DataSource> &source,
45         const sp<RefBase> &plugin)
46     :mExtractor(extractor),
47      mSource(source),
48      mExtractorPlugin(plugin) {
49 
50     mAnalyticsItem = nullptr;
51     if (MEDIA_LOG) {
52         mAnalyticsItem = new MediaAnalyticsItem(kKeyExtractor);
53 
54         // track the container format (mpeg, aac, wvm, etc)
55         size_t ntracks = extractor->countTracks();
56         mAnalyticsItem->setCString(kExtractorFormat, extractor->name());
57         // tracks (size_t)
58         mAnalyticsItem->setInt32(kExtractorTracks, ntracks);
59         // metadata
60         MetaDataBase pMetaData;
61         if (extractor->getMetaData(pMetaData) == OK) {
62             String8 xx = pMetaData.toString();
63             // 'titl' -- but this verges into PII
64             // 'mime'
65             const char *mime = nullptr;
66             if (pMetaData.findCString(kKeyMIMEType, &mime)) {
67                 mAnalyticsItem->setCString(kExtractorMime,  mime);
68             }
69             // what else is interesting and not already available?
70         }
71     }
72 }
73 
~RemoteMediaExtractor()74 RemoteMediaExtractor::~RemoteMediaExtractor() {
75     delete mExtractor;
76     mSource->close();
77     mSource.clear();
78     mExtractorPlugin = nullptr;
79     // log the current record, provided it has some information worth recording
80     if (MEDIA_LOG) {
81         if (mAnalyticsItem != nullptr) {
82             if (mAnalyticsItem->count() > 0) {
83                 mAnalyticsItem->selfrecord();
84             }
85         }
86     }
87     if (mAnalyticsItem != nullptr) {
88         delete mAnalyticsItem;
89         mAnalyticsItem = nullptr;
90     }
91 }
92 
countTracks()93 size_t RemoteMediaExtractor::countTracks() {
94     return mExtractor->countTracks();
95 }
96 
getTrack(size_t index)97 sp<IMediaSource> RemoteMediaExtractor::getTrack(size_t index) {
98     MediaTrack *source = mExtractor->getTrack(index);
99     return (source == nullptr)
100             ? nullptr : CreateIMediaSourceFromMediaSourceBase(this, source, mExtractorPlugin);
101 }
102 
getTrackMetaData(size_t index,uint32_t flags)103 sp<MetaData> RemoteMediaExtractor::getTrackMetaData(size_t index, uint32_t flags) {
104     sp<MetaData> meta = new MetaData();
105     if (mExtractor->getTrackMetaData(*meta.get(), index, flags) == OK) {
106         return meta;
107     }
108     return nullptr;
109 }
110 
getMetaData()111 sp<MetaData> RemoteMediaExtractor::getMetaData() {
112     sp<MetaData> meta = new MetaData();
113     if (mExtractor->getMetaData(*meta.get()) == OK) {
114         return meta;
115     }
116     return nullptr;
117 }
118 
getMetrics(Parcel * reply)119 status_t RemoteMediaExtractor::getMetrics(Parcel *reply) {
120     if (mAnalyticsItem == nullptr || reply == nullptr) {
121         return UNKNOWN_ERROR;
122     }
123 
124     mAnalyticsItem->writeToParcel(reply);
125     return OK;
126 }
127 
flags() const128 uint32_t RemoteMediaExtractor::flags() const {
129     return mExtractor->flags();
130 }
131 
setMediaCas(const HInterfaceToken & casToken)132 status_t RemoteMediaExtractor::setMediaCas(const HInterfaceToken &casToken) {
133     return mExtractor->setMediaCas((uint8_t*)casToken.data(), casToken.size());
134 }
135 
name()136 const char * RemoteMediaExtractor::name() {
137     return mExtractor->name();
138 }
139 
140 ////////////////////////////////////////////////////////////////////////////////
141 
142 // static
wrap(MediaExtractor * extractor,const sp<DataSource> & source,const sp<RefBase> & plugin)143 sp<IMediaExtractor> RemoteMediaExtractor::wrap(
144         MediaExtractor *extractor,
145         const sp<DataSource> &source,
146         const sp<RefBase> &plugin) {
147     if (extractor == nullptr) {
148         return nullptr;
149     }
150     return new RemoteMediaExtractor(extractor, source, plugin);
151 }
152 
153 }  // namespace android
154