MediaExtractor.cpp revision ba13b7bc3d46d958bc4a395f2c162cb112ec1f3a
1/* 2 * Copyright (C) 2009 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 "MediaExtractor" 19#include <utils/Log.h> 20#include <inttypes.h> 21#include <pwd.h> 22 23#include "include/AMRExtractor.h" 24#include "include/MP3Extractor.h" 25#include "include/MPEG4Extractor.h" 26#include "include/WAVExtractor.h" 27#include "include/OggExtractor.h" 28#include "include/MPEG2PSExtractor.h" 29#include "include/MPEG2TSExtractor.h" 30#include "include/FLACExtractor.h" 31#include "include/AACExtractor.h" 32#include "include/MidiExtractor.h" 33 34#include "matroska/MatroskaExtractor.h" 35 36#include <binder/IServiceManager.h> 37#include <binder/MemoryDealer.h> 38 39#include <media/MediaAnalyticsItem.h> 40#include <media/stagefright/foundation/ADebug.h> 41#include <media/stagefright/foundation/AMessage.h> 42#include <media/stagefright/DataSource.h> 43#include <media/stagefright/MediaDefs.h> 44#include <media/stagefright/MediaExtractor.h> 45#include <media/stagefright/MetaData.h> 46#include <media/IMediaExtractorService.h> 47#include <cutils/properties.h> 48#include <utils/String8.h> 49#include <private/android_filesystem_config.h> 50 51// still doing some on/off toggling here. 52#define MEDIA_LOG 1 53 54 55namespace android { 56 57// key for media statistics 58static const char *kKeyExtractor = "extractor"; 59// attrs for media statistics 60 61MediaExtractor::MediaExtractor() { 62 if (!LOG_NDEBUG) { 63 uid_t uid = getuid(); 64 struct passwd *pw = getpwuid(uid); 65 ALOGI("extractor created in uid: %d (%s)", getuid(), pw->pw_name); 66 } 67 68 mAnalyticsItem = NULL; 69 if (MEDIA_LOG) { 70 mAnalyticsItem = new MediaAnalyticsItem(kKeyExtractor); 71 (void) mAnalyticsItem->generateSessionID(); 72 } 73} 74 75MediaExtractor::~MediaExtractor() { 76 77 // log the current record, provided it has some information worth recording 78 if (MEDIA_LOG) { 79 if (mAnalyticsItem != NULL) { 80 if (mAnalyticsItem->count() > 0) { 81 mAnalyticsItem->setFinalized(true); 82 mAnalyticsItem->selfrecord(); 83 } 84 } 85 } 86 if (mAnalyticsItem != NULL) { 87 delete mAnalyticsItem; 88 mAnalyticsItem = NULL; 89 } 90} 91 92sp<MetaData> MediaExtractor::getMetaData() { 93 return new MetaData; 94} 95 96status_t MediaExtractor::getMetrics(Parcel *reply) { 97 98 if (mAnalyticsItem == NULL || reply == NULL) { 99 return UNKNOWN_ERROR; 100 } 101 102 populateMetrics(); 103 mAnalyticsItem->writeToParcel(reply); 104 105 return OK; 106} 107 108void MediaExtractor::populateMetrics() { 109 ALOGV("MediaExtractor::populateMetrics"); 110 // normally overridden in subclasses 111} 112 113uint32_t MediaExtractor::flags() const { 114 return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE | CAN_SEEK; 115} 116 117 118 119class RemoteDataSource : public BnDataSource { 120public: 121 enum { 122 kBufferSize = 64 * 1024, 123 }; 124 125 static sp<IDataSource> wrap(const sp<DataSource> &source); 126 virtual ~RemoteDataSource(); 127 128 virtual sp<IMemory> getIMemory(); 129 virtual ssize_t readAt(off64_t offset, size_t size); 130 virtual status_t getSize(off64_t* size); 131 virtual void close(); 132 virtual uint32_t getFlags(); 133 virtual String8 toString(); 134 virtual sp<DecryptHandle> DrmInitialization(const char *mime); 135 136private: 137 sp<IMemory> mMemory; 138 sp<DataSource> mSource; 139 String8 mName; 140 explicit RemoteDataSource(const sp<DataSource> &source); 141 DISALLOW_EVIL_CONSTRUCTORS(RemoteDataSource); 142}; 143 144 145sp<IDataSource> RemoteDataSource::wrap(const sp<DataSource> &source) { 146 return new RemoteDataSource(source); 147} 148RemoteDataSource::RemoteDataSource(const sp<DataSource> &source) { 149 mSource = source; 150 sp<MemoryDealer> memoryDealer = new MemoryDealer(kBufferSize, "RemoteDataSource"); 151 mMemory = memoryDealer->allocate(kBufferSize); 152 if (mMemory == NULL) { 153 ALOGE("Failed to allocate memory!"); 154 } 155 mName = String8::format("RemoteDataSource(%s)", mSource->toString().string()); 156} 157RemoteDataSource::~RemoteDataSource() { 158 close(); 159} 160sp<IMemory> RemoteDataSource::getIMemory() { 161 return mMemory; 162} 163ssize_t RemoteDataSource::readAt(off64_t offset, size_t size) { 164 ALOGV("readAt(%" PRId64 ", %zu)", offset, size); 165 return mSource->readAt(offset, mMemory->pointer(), size); 166} 167status_t RemoteDataSource::getSize(off64_t* size) { 168 return mSource->getSize(size); 169} 170void RemoteDataSource::close() { 171 mSource = NULL; 172} 173uint32_t RemoteDataSource::getFlags() { 174 return mSource->flags(); 175} 176 177String8 RemoteDataSource::toString() { 178 return mName; 179} 180 181sp<DecryptHandle> RemoteDataSource::DrmInitialization(const char *mime) { 182 return mSource->DrmInitialization(mime); 183} 184 185// static 186sp<IMediaExtractor> MediaExtractor::Create( 187 const sp<DataSource> &source, const char *mime) { 188 ALOGV("MediaExtractor::Create %s", mime); 189 190 if (!property_get_bool("media.stagefright.extractremote", true)) { 191 // local extractor 192 ALOGW("creating media extractor in calling process"); 193 return CreateFromService(source, mime); 194 } else { 195 // remote extractor 196 ALOGV("get service manager"); 197 sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor")); 198 199 if (binder != 0) { 200 sp<IMediaExtractorService> mediaExService(interface_cast<IMediaExtractorService>(binder)); 201 sp<IMediaExtractor> ex = mediaExService->makeExtractor(RemoteDataSource::wrap(source), mime); 202 return ex; 203 } else { 204 ALOGE("extractor service not running"); 205 return NULL; 206 } 207 } 208 return NULL; 209} 210 211sp<MediaExtractor> MediaExtractor::CreateFromService( 212 const sp<DataSource> &source, const char *mime) { 213 214 ALOGV("MediaExtractor::CreateFromService %s", mime); 215 RegisterDefaultSniffers(); 216 217 // initialize source decryption if needed 218 source->DrmInitialization(); 219 220 sp<AMessage> meta; 221 222 String8 tmp; 223 if (mime == NULL) { 224 float confidence; 225 if (!sniff(source, &tmp, &confidence, &meta)) { 226 ALOGV("FAILED to autodetect media content."); 227 228 return NULL; 229 } 230 231 mime = tmp.string(); 232 ALOGV("Autodetected media content as '%s' with confidence %.2f", 233 mime, confidence); 234 } 235 236 MediaExtractor *ret = NULL; 237 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4) 238 || !strcasecmp(mime, "audio/mp4")) { 239 ret = new MPEG4Extractor(source); 240 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { 241 ret = new MP3Extractor(source, meta); 242 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB) 243 || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { 244 ret = new AMRExtractor(source); 245 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) { 246 ret = new FLACExtractor(source); 247 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WAV)) { 248 ret = new WAVExtractor(source); 249 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_OGG)) { 250 ret = new OggExtractor(source); 251 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MATROSKA)) { 252 ret = new MatroskaExtractor(source); 253 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) { 254 ret = new MPEG2TSExtractor(source); 255 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC_ADTS)) { 256 ret = new AACExtractor(source, meta); 257 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2PS)) { 258 ret = new MPEG2PSExtractor(source); 259 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MIDI)) { 260 ret = new MidiExtractor(source); 261 } 262 263 if (ret != NULL) { 264 // track the container format (mpeg, aac, wvm, etc) 265 if (MEDIA_LOG) { 266 if (ret->mAnalyticsItem != NULL) { 267 size_t ntracks = ret->countTracks(); 268 ret->mAnalyticsItem->setCString("fmt", ret->name()); 269 // tracks (size_t) 270 ret->mAnalyticsItem->setInt32("ntrk", ntracks); 271 // metadata 272 sp<MetaData> pMetaData = ret->getMetaData(); 273 if (pMetaData != NULL) { 274 String8 xx = pMetaData->toString(); 275 // 'titl' -- but this verges into PII 276 // 'mime' 277 const char *mime = NULL; 278 if (pMetaData->findCString(kKeyMIMEType, &mime)) { 279 ret->mAnalyticsItem->setCString("mime", mime); 280 } 281 // what else is interesting and not already available? 282 } 283 } 284 } 285 } 286 287 return ret; 288} 289 290Mutex MediaExtractor::gSnifferMutex; 291List<MediaExtractor::SnifferFunc> MediaExtractor::gSniffers; 292bool MediaExtractor::gSniffersRegistered = false; 293 294// static 295bool MediaExtractor::sniff( 296 const sp<DataSource> &source, String8 *mimeType, float *confidence, sp<AMessage> *meta) { 297 *mimeType = ""; 298 *confidence = 0.0f; 299 meta->clear(); 300 301 { 302 Mutex::Autolock autoLock(gSnifferMutex); 303 if (!gSniffersRegistered) { 304 return false; 305 } 306 } 307 308 for (List<SnifferFunc>::iterator it = gSniffers.begin(); 309 it != gSniffers.end(); ++it) { 310 String8 newMimeType; 311 float newConfidence; 312 sp<AMessage> newMeta; 313 if ((*it)(source, &newMimeType, &newConfidence, &newMeta)) { 314 if (newConfidence > *confidence) { 315 *mimeType = newMimeType; 316 *confidence = newConfidence; 317 *meta = newMeta; 318 } 319 } 320 } 321 322 return *confidence > 0.0; 323} 324 325// static 326void MediaExtractor::RegisterSniffer_l(SnifferFunc func) { 327 for (List<SnifferFunc>::iterator it = gSniffers.begin(); 328 it != gSniffers.end(); ++it) { 329 if (*it == func) { 330 return; 331 } 332 } 333 334 gSniffers.push_back(func); 335} 336 337// static 338void MediaExtractor::RegisterDefaultSniffers() { 339 Mutex::Autolock autoLock(gSnifferMutex); 340 if (gSniffersRegistered) { 341 return; 342 } 343 344 RegisterSniffer_l(SniffMPEG4); 345 RegisterSniffer_l(SniffMatroska); 346 RegisterSniffer_l(SniffOgg); 347 RegisterSniffer_l(SniffWAV); 348 RegisterSniffer_l(SniffFLAC); 349 RegisterSniffer_l(SniffAMR); 350 RegisterSniffer_l(SniffMPEG2TS); 351 RegisterSniffer_l(SniffMP3); 352 RegisterSniffer_l(SniffAAC); 353 RegisterSniffer_l(SniffMPEG2PS); 354 RegisterSniffer_l(SniffMidi); 355 356 gSniffersRegistered = true; 357} 358 359 360} // namespace android 361