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