120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//#define LOG_NDEBUG 0
1820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#define LOG_TAG "MediaExtractor"
1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/Log.h>
20d5e5b15ddb2fe23dd7183c03cdaf16c67cb35d7cMarco Nelissen#include <inttypes.h>
21b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen#include <pwd.h>
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2366326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber#include "include/AMRExtractor.h"
2466326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber#include "include/MP3Extractor.h"
2566326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber#include "include/MPEG4Extractor.h"
260dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber#include "include/WAVExtractor.h"
27ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include "include/OggExtractor.h"
282944eca607304a095ea43ba2b8f0b9de61249f9fAndreas Huber#include "include/MPEG2PSExtractor.h"
29cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber#include "include/MPEG2TSExtractor.h"
30856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten#include "include/FLACExtractor.h"
3150c44c79d2d7dd6cd1485d9d939f67f80b8da1caGloria Wang#include "include/AACExtractor.h"
32faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen#include "include/MidiExtractor.h"
3366326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber
34093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber#include "matroska/MatroskaExtractor.h"
35093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
36b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen#include <binder/IServiceManager.h>
37b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen#include <binder/MemoryDealer.h>
38b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen
39db1221479a7ffe7094c51c463bbd36522ed106abRay Essick#include <media/MediaAnalyticsItem.h>
40b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen#include <media/stagefright/foundation/ADebug.h>
415a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber#include <media/stagefright/foundation/AMessage.h>
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/DataSource.h>
4318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaExtractor.h>
45fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include <media/stagefright/MetaData.h>
46b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen#include <media/IMediaExtractorService.h>
47b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen#include <cutils/properties.h>
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h>
49b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen#include <private/android_filesystem_config.h>
50b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen
51db1221479a7ffe7094c51c463bbd36522ed106abRay Essick// still doing some on/off toggling here.
52db1221479a7ffe7094c51c463bbd36522ed106abRay Essick#define MEDIA_LOG       1
53db1221479a7ffe7094c51c463bbd36522ed106abRay Essick
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57db1221479a7ffe7094c51c463bbd36522ed106abRay Essick// key for media statistics
58ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essickstatic const char *kKeyExtractor = "extractor";
59db1221479a7ffe7094c51c463bbd36522ed106abRay Essick// attrs for media statistics
60afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kExtractorMime = "android.media.mediaextractor.mime";
61afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kExtractorTracks = "android.media.mediaextractor.ntrk";
62afb43f76821e6a63e17e6484289a40430ada6978Ray Essickstatic const char *kExtractorFormat = "android.media.mediaextractor.fmt";
63db1221479a7ffe7094c51c463bbd36522ed106abRay Essick
644453f452577064b4907a941225f7fc6e87800e37Marco NelissenMediaExtractor::MediaExtractor() {
65b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    if (!LOG_NDEBUG) {
66b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        uid_t uid = getuid();
67b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        struct passwd *pw = getpwuid(uid);
68b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        ALOGI("extractor created in uid: %d (%s)", getuid(), pw->pw_name);
69b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    }
70b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen
71db1221479a7ffe7094c51c463bbd36522ed106abRay Essick    mAnalyticsItem = NULL;
72db1221479a7ffe7094c51c463bbd36522ed106abRay Essick    if (MEDIA_LOG) {
73ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick        mAnalyticsItem = new MediaAnalyticsItem(kKeyExtractor);
74db1221479a7ffe7094c51c463bbd36522ed106abRay Essick        (void) mAnalyticsItem->generateSessionID();
75db1221479a7ffe7094c51c463bbd36522ed106abRay Essick    }
76b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen}
77b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen
78db1221479a7ffe7094c51c463bbd36522ed106abRay EssickMediaExtractor::~MediaExtractor() {
79db1221479a7ffe7094c51c463bbd36522ed106abRay Essick
80db1221479a7ffe7094c51c463bbd36522ed106abRay Essick    // log the current record, provided it has some information worth recording
81db1221479a7ffe7094c51c463bbd36522ed106abRay Essick    if (MEDIA_LOG) {
82db1221479a7ffe7094c51c463bbd36522ed106abRay Essick        if (mAnalyticsItem != NULL) {
83db1221479a7ffe7094c51c463bbd36522ed106abRay Essick            if (mAnalyticsItem->count() > 0) {
84db1221479a7ffe7094c51c463bbd36522ed106abRay Essick                mAnalyticsItem->setFinalized(true);
85db1221479a7ffe7094c51c463bbd36522ed106abRay Essick                mAnalyticsItem->selfrecord();
86db1221479a7ffe7094c51c463bbd36522ed106abRay Essick            }
87db1221479a7ffe7094c51c463bbd36522ed106abRay Essick        }
88db1221479a7ffe7094c51c463bbd36522ed106abRay Essick    }
89db1221479a7ffe7094c51c463bbd36522ed106abRay Essick    if (mAnalyticsItem != NULL) {
90db1221479a7ffe7094c51c463bbd36522ed106abRay Essick        delete mAnalyticsItem;
91db1221479a7ffe7094c51c463bbd36522ed106abRay Essick        mAnalyticsItem = NULL;
92db1221479a7ffe7094c51c463bbd36522ed106abRay Essick    }
93db1221479a7ffe7094c51c463bbd36522ed106abRay Essick}
94b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen
95fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubersp<MetaData> MediaExtractor::getMetaData() {
96fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return new MetaData;
97fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
98fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
99ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essickstatus_t MediaExtractor::getMetrics(Parcel *reply) {
100ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick
101ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick    if (mAnalyticsItem == NULL || reply == NULL) {
102ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick        return UNKNOWN_ERROR;
103ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick    }
104ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick
105ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick    populateMetrics();
106ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick    mAnalyticsItem->writeToParcel(reply);
107ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick
108ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick    return OK;
109ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick}
110ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick
111ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essickvoid MediaExtractor::populateMetrics() {
112ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick    ALOGV("MediaExtractor::populateMetrics");
113ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick    // normally overridden in subclasses
114ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick}
115ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick
116acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huberuint32_t MediaExtractor::flags() const {
11770f521de2675ce6eedf4b22beed94ea1289b0f38Andreas Huber    return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE | CAN_SEEK;
118acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huber}
119acdd9d0f59c3d8bdc3de80664a609527ec3d21e2Andreas Huber
12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
121b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissensp<IMediaExtractor> MediaExtractor::Create(
122b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        const sp<DataSource> &source, const char *mime) {
123b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    ALOGV("MediaExtractor::Create %s", mime);
124b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen
12596626b7f9a4e5c9e1e04f7f710383631d1470364Marco Nelissen    if (!property_get_bool("media.stagefright.extractremote", true)) {
126b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        // local extractor
127b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        ALOGW("creating media extractor in calling process");
128b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        return CreateFromService(source, mime);
129b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    } else {
130d7581056d0962784b50570c7f477b7a406c08a57Wei Jia        // remote extractor
131d7581056d0962784b50570c7f477b7a406c08a57Wei Jia        ALOGV("get service manager");
132d7581056d0962784b50570c7f477b7a406c08a57Wei Jia        sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor"));
133d7581056d0962784b50570c7f477b7a406c08a57Wei Jia
134b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        if (binder != 0) {
135b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen            sp<IMediaExtractorService> mediaExService(interface_cast<IMediaExtractorService>(binder));
136d49dbd6b625cddb82f3f7bbeac62d48ef338ef0fAndy Hung            sp<IMediaExtractor> ex = mediaExService->makeExtractor(source->asIDataSource(), mime);
137b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen            return ex;
138b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        } else {
139b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen            ALOGE("extractor service not running");
140b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen            return NULL;
141b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen        }
142b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    }
143b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    return NULL;
144b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen}
145b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen
146b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissensp<MediaExtractor> MediaExtractor::CreateFromService(
147693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, const char *mime) {
148b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen
149b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    ALOGV("MediaExtractor::CreateFromService %s", mime);
15092d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    RegisterDefaultSniffers();
151b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen
1524453f452577064b4907a941225f7fc6e87800e37Marco Nelissen    // initialize source decryption if needed
153d49dbd6b625cddb82f3f7bbeac62d48ef338ef0fAndy Hung    source->DrmInitialization(nullptr /* mime */);
1544453f452577064b4907a941225f7fc6e87800e37Marco Nelissen
1555a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    sp<AMessage> meta;
1565a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber
15720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    String8 tmp;
15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mime == NULL) {
15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        float confidence;
16092d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen        if (!sniff(source, &tmp, &confidence, &meta)) {
161161dc698c7604cfd73310e96503179581822943bWei Jia            ALOGW("FAILED to autodetect media content.");
16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mime = tmp.string();
1673856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Autodetected media content as '%s' with confidence %.2f",
16820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber             mime, confidence);
16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
17020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1718ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten    MediaExtractor *ret = NULL;
17218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4)
17318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            || !strcasecmp(mime, "audio/mp4")) {
174ab89ac209fd1c3b0a2227168a48d7f3ae9bc43f3Marco Nelissen        ret = new MPEG4Extractor(source);
17518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
1768ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten        ret = new MP3Extractor(source, meta);
17718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)
17818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
1798ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten        ret = new AMRExtractor(source);
180856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
1818ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten        ret = new FLACExtractor(source);
1820dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WAV)) {
1838ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten        ret = new WAVExtractor(source);
184ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_OGG)) {
1858ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten        ret = new OggExtractor(source);
186093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MATROSKA)) {
1878ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten        ret = new MatroskaExtractor(source);
188cda17c606b0fe3ccda4dc68a6d43882410ea2462Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
1898ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten        ret = new MPEG2TSExtractor(source);
19050c44c79d2d7dd6cd1485d9d939f67f80b8da1caGloria Wang    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC_ADTS)) {
19114da736f1707a6dbefa52405e910ecb1b3bc2dd2Andreas Huber        ret = new AACExtractor(source, meta);
1922944eca607304a095ea43ba2b8f0b9de61249f9fAndreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2PS)) {
1932944eca607304a095ea43ba2b8f0b9de61249f9fAndreas Huber        ret = new MPEG2PSExtractor(source);
194faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MIDI)) {
195faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        ret = new MidiExtractor(source);
1968ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten    }
1970d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang
198db1221479a7ffe7094c51c463bbd36522ed106abRay Essick    if (ret != NULL) {
199db1221479a7ffe7094c51c463bbd36522ed106abRay Essick       // track the container format (mpeg, aac, wvm, etc)
200db1221479a7ffe7094c51c463bbd36522ed106abRay Essick       if (MEDIA_LOG) {
201db1221479a7ffe7094c51c463bbd36522ed106abRay Essick          if (ret->mAnalyticsItem != NULL) {
202ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick              size_t ntracks = ret->countTracks();
203afb43f76821e6a63e17e6484289a40430ada6978Ray Essick              ret->mAnalyticsItem->setCString(kExtractorFormat,  ret->name());
204db1221479a7ffe7094c51c463bbd36522ed106abRay Essick              // tracks (size_t)
205afb43f76821e6a63e17e6484289a40430ada6978Ray Essick              ret->mAnalyticsItem->setInt32(kExtractorTracks,  ntracks);
206db1221479a7ffe7094c51c463bbd36522ed106abRay Essick              // metadata
207db1221479a7ffe7094c51c463bbd36522ed106abRay Essick              sp<MetaData> pMetaData = ret->getMetaData();
208db1221479a7ffe7094c51c463bbd36522ed106abRay Essick              if (pMetaData != NULL) {
209db1221479a7ffe7094c51c463bbd36522ed106abRay Essick                String8 xx = pMetaData->toString();
210db1221479a7ffe7094c51c463bbd36522ed106abRay Essick                // 'titl' -- but this verges into PII
211db1221479a7ffe7094c51c463bbd36522ed106abRay Essick                // 'mime'
212db1221479a7ffe7094c51c463bbd36522ed106abRay Essick                const char *mime = NULL;
213db1221479a7ffe7094c51c463bbd36522ed106abRay Essick                if (pMetaData->findCString(kKeyMIMEType, &mime)) {
214afb43f76821e6a63e17e6484289a40430ada6978Ray Essick                    ret->mAnalyticsItem->setCString(kExtractorMime,  mime);
215db1221479a7ffe7094c51c463bbd36522ed106abRay Essick                }
216ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick                // what else is interesting and not already available?
217db1221479a7ffe7094c51c463bbd36522ed106abRay Essick              }
218ba13b7bc3d46d958bc4a395f2c162cb112ec1f3aRay Essick	  }
219db1221479a7ffe7094c51c463bbd36522ed106abRay Essick       }
220db1221479a7ffe7094c51c463bbd36522ed106abRay Essick    }
221db1221479a7ffe7094c51c463bbd36522ed106abRay Essick
2228ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten    return ret;
22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22592d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco NelissenMutex MediaExtractor::gSnifferMutex;
22692d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco NelissenList<MediaExtractor::SnifferFunc> MediaExtractor::gSniffers;
22792d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissenbool MediaExtractor::gSniffersRegistered = false;
22892d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen
22992d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen// static
23092d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissenbool MediaExtractor::sniff(
23192d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen        const sp<DataSource> &source, String8 *mimeType, float *confidence, sp<AMessage> *meta) {
23292d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    *mimeType = "";
23392d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    *confidence = 0.0f;
23492d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    meta->clear();
23592d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen
23692d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    {
23792d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen        Mutex::Autolock autoLock(gSnifferMutex);
23892d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen        if (!gSniffersRegistered) {
23992d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen            return false;
24092d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen        }
24192d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    }
24292d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen
24392d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    for (List<SnifferFunc>::iterator it = gSniffers.begin();
24492d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen         it != gSniffers.end(); ++it) {
24592d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen        String8 newMimeType;
24692d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen        float newConfidence;
24792d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen        sp<AMessage> newMeta;
24892d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen        if ((*it)(source, &newMimeType, &newConfidence, &newMeta)) {
24992d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen            if (newConfidence > *confidence) {
25092d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen                *mimeType = newMimeType;
25192d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen                *confidence = newConfidence;
25292d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen                *meta = newMeta;
25392d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen            }
25492d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen        }
25592d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    }
25692d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen
25792d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    return *confidence > 0.0;
25892d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen}
25992d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen
26092d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen// static
26192d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissenvoid MediaExtractor::RegisterSniffer_l(SnifferFunc func) {
26292d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    for (List<SnifferFunc>::iterator it = gSniffers.begin();
26392d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen         it != gSniffers.end(); ++it) {
26492d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen        if (*it == func) {
26592d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen            return;
26692d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen        }
26792d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    }
26892d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen
26992d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    gSniffers.push_back(func);
27092d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen}
27192d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen
27292d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen// static
27392d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissenvoid MediaExtractor::RegisterDefaultSniffers() {
27492d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    Mutex::Autolock autoLock(gSnifferMutex);
27592d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    if (gSniffersRegistered) {
27692d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen        return;
27792d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    }
27892d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen
27992d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    RegisterSniffer_l(SniffMPEG4);
28092d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    RegisterSniffer_l(SniffMatroska);
28192d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    RegisterSniffer_l(SniffOgg);
28292d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    RegisterSniffer_l(SniffWAV);
28392d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    RegisterSniffer_l(SniffFLAC);
28492d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    RegisterSniffer_l(SniffAMR);
28592d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    RegisterSniffer_l(SniffMPEG2TS);
28692d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    RegisterSniffer_l(SniffMP3);
28792d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    RegisterSniffer_l(SniffAAC);
28892d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    RegisterSniffer_l(SniffMPEG2PS);
28992d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    RegisterSniffer_l(SniffMidi);
29092d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen
29192d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen    gSniffersRegistered = true;
29292d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen}
29392d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen
29492d57f926eb39d72e8fd8f3b3c9e40d25f77ad47Marco Nelissen
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
296