NuMediaExtractor.cpp revision faf35c0c279114b11a36615dc6630c126e767da0
15778822d86b0337407514b9372562b86edfa91cdAndreas Huber/*
25778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Copyright 2012, The Android Open Source Project
35778822d86b0337407514b9372562b86edfa91cdAndreas Huber *
45778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
55778822d86b0337407514b9372562b86edfa91cdAndreas Huber * you may not use this file except in compliance with the License.
65778822d86b0337407514b9372562b86edfa91cdAndreas Huber * You may obtain a copy of the License at
75778822d86b0337407514b9372562b86edfa91cdAndreas Huber *
85778822d86b0337407514b9372562b86edfa91cdAndreas Huber *     http://www.apache.org/licenses/LICENSE-2.0
95778822d86b0337407514b9372562b86edfa91cdAndreas Huber *
105778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Unless required by applicable law or agreed to in writing, software
115778822d86b0337407514b9372562b86edfa91cdAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
125778822d86b0337407514b9372562b86edfa91cdAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135778822d86b0337407514b9372562b86edfa91cdAndreas Huber * See the License for the specific language governing permissions and
145778822d86b0337407514b9372562b86edfa91cdAndreas Huber * limitations under the License.
155778822d86b0337407514b9372562b86edfa91cdAndreas Huber */
165778822d86b0337407514b9372562b86edfa91cdAndreas Huber
175778822d86b0337407514b9372562b86edfa91cdAndreas Huber//#define LOG_NDEBUG 0
185778822d86b0337407514b9372562b86edfa91cdAndreas Huber#define LOG_TAG "NuMediaExtractor"
195778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <utils/Log.h>
205778822d86b0337407514b9372562b86edfa91cdAndreas Huber
215778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/NuMediaExtractor.h>
225778822d86b0337407514b9372562b86edfa91cdAndreas Huber
235778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include "include/ESDS.h"
24a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber#include "include/NuCachedSource2.h"
251608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber#include "include/WVMExtractor.h"
265778822d86b0337407514b9372562b86edfa91cdAndreas Huber
275778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/foundation/ABuffer.h>
285778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/foundation/ADebug.h>
295778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/foundation/AMessage.h>
305778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/DataSource.h>
31918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber#include <media/stagefright/FileSource.h>
325778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/MediaBuffer.h>
335778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/MediaDefs.h>
345778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/MediaErrors.h>
355778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/MediaExtractor.h>
365778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/MediaSource.h>
375778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/MetaData.h>
385778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/Utils.h>
395778822d86b0337407514b9372562b86edfa91cdAndreas Huber
405778822d86b0337407514b9372562b86edfa91cdAndreas Hubernamespace android {
415778822d86b0337407514b9372562b86edfa91cdAndreas Huber
42a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas HuberNuMediaExtractor::NuMediaExtractor()
43a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    : mIsWidevineExtractor(false),
44a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber      mTotalBitrate(-1ll),
45a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber      mDurationUs(-1ll) {
465778822d86b0337407514b9372562b86edfa91cdAndreas Huber}
475778822d86b0337407514b9372562b86edfa91cdAndreas Huber
485778822d86b0337407514b9372562b86edfa91cdAndreas HuberNuMediaExtractor::~NuMediaExtractor() {
495778822d86b0337407514b9372562b86edfa91cdAndreas Huber    releaseTrackSamples();
505778822d86b0337407514b9372562b86edfa91cdAndreas Huber
515778822d86b0337407514b9372562b86edfa91cdAndreas Huber    for (size_t i = 0; i < mSelectedTracks.size(); ++i) {
525778822d86b0337407514b9372562b86edfa91cdAndreas Huber        TrackInfo *info = &mSelectedTracks.editItemAt(i);
535778822d86b0337407514b9372562b86edfa91cdAndreas Huber
545778822d86b0337407514b9372562b86edfa91cdAndreas Huber        CHECK_EQ((status_t)OK, info->mSource->stop());
555778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
565778822d86b0337407514b9372562b86edfa91cdAndreas Huber
575778822d86b0337407514b9372562b86edfa91cdAndreas Huber    mSelectedTracks.clear();
585778822d86b0337407514b9372562b86edfa91cdAndreas Huber}
595778822d86b0337407514b9372562b86edfa91cdAndreas Huber
60918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huberstatus_t NuMediaExtractor::setDataSource(
611b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const sp<IMediaHTTPService> &httpService,
621b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const char *path,
631b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const KeyedVector<String8, String8> *headers) {
64dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber    Mutex::Autolock autoLock(mLock);
65dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber
66918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber    if (mImpl != NULL) {
67918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber        return -EINVAL;
68918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber    }
69918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber
701608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber    sp<DataSource> dataSource =
711b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        DataSource::CreateFromURI(httpService, path, headers);
725778822d86b0337407514b9372562b86edfa91cdAndreas Huber
735778822d86b0337407514b9372562b86edfa91cdAndreas Huber    if (dataSource == NULL) {
745778822d86b0337407514b9372562b86edfa91cdAndreas Huber        return -ENOENT;
755778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
765778822d86b0337407514b9372562b86edfa91cdAndreas Huber
77a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    mIsWidevineExtractor = false;
781608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber    if (!strncasecmp("widevine://", path, 11)) {
791608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber        String8 mimeType;
801608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber        float confidence;
811608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber        sp<AMessage> dummy;
821608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber        bool success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
831608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber
841608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber        if (!success
851608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber                || strcasecmp(
861608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
871608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber            return ERROR_UNSUPPORTED;
881608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber        }
891608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber
901608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber        sp<WVMExtractor> extractor = new WVMExtractor(dataSource);
911608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber        extractor->setAdaptiveStreamingMode(true);
921608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber
931608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber        mImpl = extractor;
94a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        mIsWidevineExtractor = true;
951608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber    } else {
961608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber        mImpl = MediaExtractor::Create(dataSource);
971608735ef488ecd8c3c012a3b0d4b1d4ef3d93c7Andreas Huber    }
985778822d86b0337407514b9372562b86edfa91cdAndreas Huber
995778822d86b0337407514b9372562b86edfa91cdAndreas Huber    if (mImpl == NULL) {
1005778822d86b0337407514b9372562b86edfa91cdAndreas Huber        return ERROR_UNSUPPORTED;
1015778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
1025778822d86b0337407514b9372562b86edfa91cdAndreas Huber
10394c1c8c99b70f2fdab87e131812eb253271e5500Andreas Huber    sp<MetaData> fileMeta = mImpl->getMetaData();
10494c1c8c99b70f2fdab87e131812eb253271e5500Andreas Huber    const char *containerMime;
10594c1c8c99b70f2fdab87e131812eb253271e5500Andreas Huber    if (fileMeta != NULL
10694c1c8c99b70f2fdab87e131812eb253271e5500Andreas Huber            && fileMeta->findCString(kKeyMIMEType, &containerMime)
10794c1c8c99b70f2fdab87e131812eb253271e5500Andreas Huber            && !strcasecmp(containerMime, "video/wvm")) {
10894c1c8c99b70f2fdab87e131812eb253271e5500Andreas Huber        // We always want to use "cryptoPluginMode" when using the wvm
10994c1c8c99b70f2fdab87e131812eb253271e5500Andreas Huber        // extractor. We can tell that it is this extractor by looking
11094c1c8c99b70f2fdab87e131812eb253271e5500Andreas Huber        // at the container mime type.
11194c1c8c99b70f2fdab87e131812eb253271e5500Andreas Huber        // The cryptoPluginMode ensures that the extractor will actually
11294c1c8c99b70f2fdab87e131812eb253271e5500Andreas Huber        // give us data in a call to MediaSource::read(), unlike its
113e4d40ad91f3516bde106658673b2cb076b5dfcb7Lajos Molnar        // default mode that we used in AwesomePlayer.
114e4d40ad91f3516bde106658673b2cb076b5dfcb7Lajos Molnar        // TODO: change default mode
11594c1c8c99b70f2fdab87e131812eb253271e5500Andreas Huber        static_cast<WVMExtractor *>(mImpl.get())->setCryptoPluginMode(true);
1163499e2d178960ca3392855716c963eec7403a089James Dong    } else if (mImpl->getDrmFlag()) {
1173499e2d178960ca3392855716c963eec7403a089James Dong        // For all other drm content, we don't want to expose decrypted
1183499e2d178960ca3392855716c963eec7403a089James Dong        // content to Java application.
1193499e2d178960ca3392855716c963eec7403a089James Dong        mImpl.clear();
1203499e2d178960ca3392855716c963eec7403a089James Dong        mImpl = NULL;
1213499e2d178960ca3392855716c963eec7403a089James Dong        return ERROR_UNSUPPORTED;
12294c1c8c99b70f2fdab87e131812eb253271e5500Andreas Huber    }
12394c1c8c99b70f2fdab87e131812eb253271e5500Andreas Huber
124faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    status_t err = updateDurationAndBitrate();
125faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    if (err == OK) {
126faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar        mDataSource = dataSource;
127faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    }
128a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
1295778822d86b0337407514b9372562b86edfa91cdAndreas Huber    return OK;
1305778822d86b0337407514b9372562b86edfa91cdAndreas Huber}
1315778822d86b0337407514b9372562b86edfa91cdAndreas Huber
132918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huberstatus_t NuMediaExtractor::setDataSource(int fd, off64_t offset, off64_t size) {
133fd7ec80f3d0e30c8df61b86951d926ab9c8c6d25Marco Nelissen
13483b0fd9997b558f6c2ebf5e6e4db20570cb233b8Marco Nelissen    ALOGV("setDataSource fd=%d (%s), offset=%lld, length=%lld",
13583b0fd9997b558f6c2ebf5e6e4db20570cb233b8Marco Nelissen            fd, nameForFd(fd).c_str(), (long long) offset, (long long) size);
13683b0fd9997b558f6c2ebf5e6e4db20570cb233b8Marco Nelissen
137dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber    Mutex::Autolock autoLock(mLock);
138dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber
139918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber    if (mImpl != NULL) {
140918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber        return -EINVAL;
141918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber    }
142918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber
143918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber    sp<FileSource> fileSource = new FileSource(dup(fd), offset, size);
144918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber
145fd7ec80f3d0e30c8df61b86951d926ab9c8c6d25Marco Nelissen    status_t err = fileSource->initCheck();
146fd7ec80f3d0e30c8df61b86951d926ab9c8c6d25Marco Nelissen    if (err != OK) {
147fd7ec80f3d0e30c8df61b86951d926ab9c8c6d25Marco Nelissen        return err;
148fd7ec80f3d0e30c8df61b86951d926ab9c8c6d25Marco Nelissen    }
149fd7ec80f3d0e30c8df61b86951d926ab9c8c6d25Marco Nelissen
150fd7ec80f3d0e30c8df61b86951d926ab9c8c6d25Marco Nelissen    mImpl = MediaExtractor::Create(fileSource);
151fd7ec80f3d0e30c8df61b86951d926ab9c8c6d25Marco Nelissen
152fd7ec80f3d0e30c8df61b86951d926ab9c8c6d25Marco Nelissen    if (mImpl == NULL) {
153fd7ec80f3d0e30c8df61b86951d926ab9c8c6d25Marco Nelissen        return ERROR_UNSUPPORTED;
154fd7ec80f3d0e30c8df61b86951d926ab9c8c6d25Marco Nelissen    }
155fd7ec80f3d0e30c8df61b86951d926ab9c8c6d25Marco Nelissen
156faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    err = updateDurationAndBitrate();
157faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    if (err == OK) {
158faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar        mDataSource = fileSource;
159faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    }
160fd7ec80f3d0e30c8df61b86951d926ab9c8c6d25Marco Nelissen
161fd7ec80f3d0e30c8df61b86951d926ab9c8c6d25Marco Nelissen    return OK;
162dbcb4c17f16230dfc6af908f176681c49f61b13eMarco Nelissen}
163dbcb4c17f16230dfc6af908f176681c49f61b13eMarco Nelissen
164dbcb4c17f16230dfc6af908f176681c49f61b13eMarco Nelissenstatus_t NuMediaExtractor::setDataSource(const sp<DataSource> &source) {
165dbcb4c17f16230dfc6af908f176681c49f61b13eMarco Nelissen    Mutex::Autolock autoLock(mLock);
166dbcb4c17f16230dfc6af908f176681c49f61b13eMarco Nelissen
167dbcb4c17f16230dfc6af908f176681c49f61b13eMarco Nelissen    if (mImpl != NULL) {
168dbcb4c17f16230dfc6af908f176681c49f61b13eMarco Nelissen        return -EINVAL;
169dbcb4c17f16230dfc6af908f176681c49f61b13eMarco Nelissen    }
170dbcb4c17f16230dfc6af908f176681c49f61b13eMarco Nelissen
171dbcb4c17f16230dfc6af908f176681c49f61b13eMarco Nelissen    status_t err = source->initCheck();
172918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber    if (err != OK) {
173918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber        return err;
174918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber    }
175918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber
176dbcb4c17f16230dfc6af908f176681c49f61b13eMarco Nelissen    mImpl = MediaExtractor::Create(source);
177918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber
178918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber    if (mImpl == NULL) {
179918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber        return ERROR_UNSUPPORTED;
180918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber    }
181918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber
182faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    err = updateDurationAndBitrate();
183faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    if (err == OK) {
184faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar        mDataSource = source;
185faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    }
186a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
187faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    return err;
188918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber}
189918c7652b9a38c02e26c0c46541cea82070c0e43Andreas Huber
190faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnarstatus_t NuMediaExtractor::updateDurationAndBitrate() {
191faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    if (mImpl->countTracks() > kMaxTrackCount) {
192faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar        return ERROR_UNSUPPORTED;
193faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    }
194faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar
195a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    mTotalBitrate = 0ll;
196a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    mDurationUs = -1ll;
197a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
198a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    for (size_t i = 0; i < mImpl->countTracks(); ++i) {
199a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        sp<MetaData> meta = mImpl->getTrackMetaData(i);
20059e469e0b0d95bba2aee3bbda003b7042fd1cdd9Marco Nelissen        if (meta == NULL) {
20159e469e0b0d95bba2aee3bbda003b7042fd1cdd9Marco Nelissen            ALOGW("no metadata for track %zu", i);
20259e469e0b0d95bba2aee3bbda003b7042fd1cdd9Marco Nelissen            continue;
20359e469e0b0d95bba2aee3bbda003b7042fd1cdd9Marco Nelissen        }
204a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
205a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        int32_t bitrate;
206a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        if (!meta->findInt32(kKeyBitRate, &bitrate)) {
207a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber            const char *mime;
208a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber            CHECK(meta->findCString(kKeyMIMEType, &mime));
209a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber            ALOGV("track of type '%s' does not publish bitrate", mime);
210a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
211a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber            mTotalBitrate = -1ll;
212a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        } else if (mTotalBitrate >= 0ll) {
213a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber            mTotalBitrate += bitrate;
214a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        }
215a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
216a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        int64_t durationUs;
217a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        if (meta->findInt64(kKeyDuration, &durationUs)
218a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber                && durationUs > mDurationUs) {
219a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber            mDurationUs = durationUs;
220a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        }
221a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    }
222faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    return OK;
223a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber}
224a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
2255778822d86b0337407514b9372562b86edfa91cdAndreas Hubersize_t NuMediaExtractor::countTracks() const {
226dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber    Mutex::Autolock autoLock(mLock);
227dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber
2285778822d86b0337407514b9372562b86edfa91cdAndreas Huber    return mImpl == NULL ? 0 : mImpl->countTracks();
2295778822d86b0337407514b9372562b86edfa91cdAndreas Huber}
2305778822d86b0337407514b9372562b86edfa91cdAndreas Huber
2315778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatus_t NuMediaExtractor::getTrackFormat(
2325778822d86b0337407514b9372562b86edfa91cdAndreas Huber        size_t index, sp<AMessage> *format) const {
233dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber    Mutex::Autolock autoLock(mLock);
234dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber
2355778822d86b0337407514b9372562b86edfa91cdAndreas Huber    *format = NULL;
2365778822d86b0337407514b9372562b86edfa91cdAndreas Huber
2375778822d86b0337407514b9372562b86edfa91cdAndreas Huber    if (mImpl == NULL) {
2385778822d86b0337407514b9372562b86edfa91cdAndreas Huber        return -EINVAL;
2395778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
2405778822d86b0337407514b9372562b86edfa91cdAndreas Huber
2415778822d86b0337407514b9372562b86edfa91cdAndreas Huber    if (index >= mImpl->countTracks()) {
2425778822d86b0337407514b9372562b86edfa91cdAndreas Huber        return -ERANGE;
2435778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
2445778822d86b0337407514b9372562b86edfa91cdAndreas Huber
2455778822d86b0337407514b9372562b86edfa91cdAndreas Huber    sp<MetaData> meta = mImpl->getTrackMetaData(index);
246faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    // Extractors either support trackID-s or not, so either all tracks have trackIDs or none.
247faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    // Generate trackID if missing.
248faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    int32_t trackID;
249faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    if (meta != NULL && !meta->findInt32(kKeyTrackID, &trackID)) {
250faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar        meta->setInt32(kKeyTrackID, (int32_t)index + 1);
251faf35c0c279114b11a36615dc6630c126e767da0Lajos Molnar    }
2529806555d3930be43e11106281dee354820ac1c88Andreas Huber    return convertMetaDataToMessage(meta, format);
2535778822d86b0337407514b9372562b86edfa91cdAndreas Huber}
2545778822d86b0337407514b9372562b86edfa91cdAndreas Huber
255ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t NuMediaExtractor::getFileFormat(sp<AMessage> *format) const {
256ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    Mutex::Autolock autoLock(mLock);
257ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
258ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    *format = NULL;
259ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
260ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mImpl == NULL) {
261ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return -EINVAL;
262ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
263ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
264ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    sp<MetaData> meta = mImpl->getMetaData();
265ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
266ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    const char *mime;
267ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    CHECK(meta->findCString(kKeyMIMEType, &mime));
268ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    *format = new AMessage();
269ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    (*format)->setString("mime", mime);
270ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
271ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t type;
272ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    const void *pssh;
273ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    size_t psshsize;
274ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (meta->findData(kKeyPssh, &type, &pssh, &psshsize)) {
275ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        sp<ABuffer> buf = new ABuffer(psshsize);
276ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memcpy(buf->data(), pssh, psshsize);
277ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        (*format)->setBuffer("pssh", buf);
278ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
279ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
280ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
281ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
282ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2835778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatus_t NuMediaExtractor::selectTrack(size_t index) {
284dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber    Mutex::Autolock autoLock(mLock);
285dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber
2865778822d86b0337407514b9372562b86edfa91cdAndreas Huber    if (mImpl == NULL) {
2875778822d86b0337407514b9372562b86edfa91cdAndreas Huber        return -EINVAL;
2885778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
2895778822d86b0337407514b9372562b86edfa91cdAndreas Huber
2905778822d86b0337407514b9372562b86edfa91cdAndreas Huber    if (index >= mImpl->countTracks()) {
2915778822d86b0337407514b9372562b86edfa91cdAndreas Huber        return -ERANGE;
2925778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
2935778822d86b0337407514b9372562b86edfa91cdAndreas Huber
2945778822d86b0337407514b9372562b86edfa91cdAndreas Huber    for (size_t i = 0; i < mSelectedTracks.size(); ++i) {
2955778822d86b0337407514b9372562b86edfa91cdAndreas Huber        TrackInfo *info = &mSelectedTracks.editItemAt(i);
2965778822d86b0337407514b9372562b86edfa91cdAndreas Huber
2975778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (info->mTrackIndex == index) {
2985778822d86b0337407514b9372562b86edfa91cdAndreas Huber            // This track has already been selected.
2995778822d86b0337407514b9372562b86edfa91cdAndreas Huber            return OK;
3005778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
3015778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
3025778822d86b0337407514b9372562b86edfa91cdAndreas Huber
303b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen    sp<IMediaSource> source = mImpl->getTrack(index);
3045778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3055778822d86b0337407514b9372562b86edfa91cdAndreas Huber    CHECK_EQ((status_t)OK, source->start());
3065778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3075778822d86b0337407514b9372562b86edfa91cdAndreas Huber    mSelectedTracks.push();
3085778822d86b0337407514b9372562b86edfa91cdAndreas Huber    TrackInfo *info = &mSelectedTracks.editItemAt(mSelectedTracks.size() - 1);
3095778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3105778822d86b0337407514b9372562b86edfa91cdAndreas Huber    info->mSource = source;
3115778822d86b0337407514b9372562b86edfa91cdAndreas Huber    info->mTrackIndex = index;
3125778822d86b0337407514b9372562b86edfa91cdAndreas Huber    info->mFinalResult = OK;
3135778822d86b0337407514b9372562b86edfa91cdAndreas Huber    info->mSample = NULL;
3145778822d86b0337407514b9372562b86edfa91cdAndreas Huber    info->mSampleTimeUs = -1ll;
315ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    info->mTrackFlags = 0;
3165778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3175778822d86b0337407514b9372562b86edfa91cdAndreas Huber    const char *mime;
3185778822d86b0337407514b9372562b86edfa91cdAndreas Huber    CHECK(source->getFormat()->findCString(kKeyMIMEType, &mime));
3195778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3205778822d86b0337407514b9372562b86edfa91cdAndreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
321ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        info->mTrackFlags |= kIsVorbis;
3225778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
3235778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3245778822d86b0337407514b9372562b86edfa91cdAndreas Huber    return OK;
3255778822d86b0337407514b9372562b86edfa91cdAndreas Huber}
3265778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3279d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huberstatus_t NuMediaExtractor::unselectTrack(size_t index) {
3289d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    Mutex::Autolock autoLock(mLock);
3299d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber
3309d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    if (mImpl == NULL) {
3319d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber        return -EINVAL;
3329d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    }
3339d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber
3349d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    if (index >= mImpl->countTracks()) {
3359d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber        return -ERANGE;
3369d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    }
3379d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber
3389d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    size_t i;
3399d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    for (i = 0; i < mSelectedTracks.size(); ++i) {
3409d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber        TrackInfo *info = &mSelectedTracks.editItemAt(i);
3419d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber
3429d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber        if (info->mTrackIndex == index) {
3439d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber            break;
3449d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber        }
3459d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    }
3469d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber
3479d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    if (i == mSelectedTracks.size()) {
3489d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber        // Not selected.
3499d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber        return OK;
3509d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    }
3519d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber
3529d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    TrackInfo *info = &mSelectedTracks.editItemAt(i);
3539d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber
3549d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    if (info->mSample != NULL) {
3559d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber        info->mSample->release();
3569d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber        info->mSample = NULL;
3579d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber
3589d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber        info->mSampleTimeUs = -1ll;
3599d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    }
3609d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber
3619d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    CHECK_EQ((status_t)OK, info->mSource->stop());
3629d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber
3639d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    mSelectedTracks.removeAt(i);
3649d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber
3659d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    return OK;
3669d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber}
3679d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber
3685778822d86b0337407514b9372562b86edfa91cdAndreas Hubervoid NuMediaExtractor::releaseTrackSamples() {
3695778822d86b0337407514b9372562b86edfa91cdAndreas Huber    for (size_t i = 0; i < mSelectedTracks.size(); ++i) {
3705778822d86b0337407514b9372562b86edfa91cdAndreas Huber        TrackInfo *info = &mSelectedTracks.editItemAt(i);
3715778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3725778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (info->mSample != NULL) {
3735778822d86b0337407514b9372562b86edfa91cdAndreas Huber            info->mSample->release();
3745778822d86b0337407514b9372562b86edfa91cdAndreas Huber            info->mSample = NULL;
3755778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3765778822d86b0337407514b9372562b86edfa91cdAndreas Huber            info->mSampleTimeUs = -1ll;
3775778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
3785778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
3795778822d86b0337407514b9372562b86edfa91cdAndreas Huber}
3805778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3819d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huberssize_t NuMediaExtractor::fetchTrackSamples(
3829d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber        int64_t seekTimeUs, MediaSource::ReadOptions::SeekMode mode) {
3835778822d86b0337407514b9372562b86edfa91cdAndreas Huber    TrackInfo *minInfo = NULL;
3845778822d86b0337407514b9372562b86edfa91cdAndreas Huber    ssize_t minIndex = -1;
3855778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3865778822d86b0337407514b9372562b86edfa91cdAndreas Huber    for (size_t i = 0; i < mSelectedTracks.size(); ++i) {
3875778822d86b0337407514b9372562b86edfa91cdAndreas Huber        TrackInfo *info = &mSelectedTracks.editItemAt(i);
3885778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3895778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (seekTimeUs >= 0ll) {
3905778822d86b0337407514b9372562b86edfa91cdAndreas Huber            info->mFinalResult = OK;
3915778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3925778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (info->mSample != NULL) {
3935778822d86b0337407514b9372562b86edfa91cdAndreas Huber                info->mSample->release();
3945778822d86b0337407514b9372562b86edfa91cdAndreas Huber                info->mSample = NULL;
3955778822d86b0337407514b9372562b86edfa91cdAndreas Huber                info->mSampleTimeUs = -1ll;
3965778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
3975778822d86b0337407514b9372562b86edfa91cdAndreas Huber        } else if (info->mFinalResult != OK) {
3985778822d86b0337407514b9372562b86edfa91cdAndreas Huber            continue;
3995778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
4005778822d86b0337407514b9372562b86edfa91cdAndreas Huber
4015778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (info->mSample == NULL) {
4025778822d86b0337407514b9372562b86edfa91cdAndreas Huber            MediaSource::ReadOptions options;
4035778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (seekTimeUs >= 0ll) {
4049d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber                options.setSeekTo(seekTimeUs, mode);
4055778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
4065778822d86b0337407514b9372562b86edfa91cdAndreas Huber            status_t err = info->mSource->read(&info->mSample, &options);
4075778822d86b0337407514b9372562b86edfa91cdAndreas Huber
4085778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (err != OK) {
4095778822d86b0337407514b9372562b86edfa91cdAndreas Huber                CHECK(info->mSample == NULL);
4105778822d86b0337407514b9372562b86edfa91cdAndreas Huber
4115778822d86b0337407514b9372562b86edfa91cdAndreas Huber                info->mFinalResult = err;
412bc098410be55f9d96f394b3981a0c482b83859b6Andreas Huber
413bc098410be55f9d96f394b3981a0c482b83859b6Andreas Huber                if (info->mFinalResult != ERROR_END_OF_STREAM) {
414a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                    ALOGW("read on track %zu failed with error %d",
415bc098410be55f9d96f394b3981a0c482b83859b6Andreas Huber                          info->mTrackIndex, err);
416bc098410be55f9d96f394b3981a0c482b83859b6Andreas Huber                }
417bc098410be55f9d96f394b3981a0c482b83859b6Andreas Huber
4185778822d86b0337407514b9372562b86edfa91cdAndreas Huber                info->mSampleTimeUs = -1ll;
4195778822d86b0337407514b9372562b86edfa91cdAndreas Huber                continue;
4205778822d86b0337407514b9372562b86edfa91cdAndreas Huber            } else {
4215778822d86b0337407514b9372562b86edfa91cdAndreas Huber                CHECK(info->mSample != NULL);
4225778822d86b0337407514b9372562b86edfa91cdAndreas Huber                CHECK(info->mSample->meta_data()->findInt64(
4235778822d86b0337407514b9372562b86edfa91cdAndreas Huber                            kKeyTime, &info->mSampleTimeUs));
4245778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
4255778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
4265778822d86b0337407514b9372562b86edfa91cdAndreas Huber
4275778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (minInfo == NULL  || info->mSampleTimeUs < minInfo->mSampleTimeUs) {
4285778822d86b0337407514b9372562b86edfa91cdAndreas Huber            minInfo = info;
4295778822d86b0337407514b9372562b86edfa91cdAndreas Huber            minIndex = i;
4305778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
4315778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
4325778822d86b0337407514b9372562b86edfa91cdAndreas Huber
4335778822d86b0337407514b9372562b86edfa91cdAndreas Huber    return minIndex;
4345778822d86b0337407514b9372562b86edfa91cdAndreas Huber}
4355778822d86b0337407514b9372562b86edfa91cdAndreas Huber
4369d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huberstatus_t NuMediaExtractor::seekTo(
4379d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber        int64_t timeUs, MediaSource::ReadOptions::SeekMode mode) {
438dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber    Mutex::Autolock autoLock(mLock);
439dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber
4409d07855aaff8a6b502a3ab058002cdd4a278b965Andreas Huber    ssize_t minIndex = fetchTrackSamples(timeUs, mode);
4414835705370584f6904c80afebcc6e8b9fdb110a5Andreas Huber
4424835705370584f6904c80afebcc6e8b9fdb110a5Andreas Huber    if (minIndex < 0) {
4434835705370584f6904c80afebcc6e8b9fdb110a5Andreas Huber        return ERROR_END_OF_STREAM;
4444835705370584f6904c80afebcc6e8b9fdb110a5Andreas Huber    }
4454835705370584f6904c80afebcc6e8b9fdb110a5Andreas Huber
4464835705370584f6904c80afebcc6e8b9fdb110a5Andreas Huber    return OK;
4475778822d86b0337407514b9372562b86edfa91cdAndreas Huber}
4485778822d86b0337407514b9372562b86edfa91cdAndreas Huber
4495778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatus_t NuMediaExtractor::advance() {
450dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber    Mutex::Autolock autoLock(mLock);
451dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber
4525778822d86b0337407514b9372562b86edfa91cdAndreas Huber    ssize_t minIndex = fetchTrackSamples();
4535778822d86b0337407514b9372562b86edfa91cdAndreas Huber
4545778822d86b0337407514b9372562b86edfa91cdAndreas Huber    if (minIndex < 0) {
4555778822d86b0337407514b9372562b86edfa91cdAndreas Huber        return ERROR_END_OF_STREAM;
4565778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
4575778822d86b0337407514b9372562b86edfa91cdAndreas Huber
4585778822d86b0337407514b9372562b86edfa91cdAndreas Huber    TrackInfo *info = &mSelectedTracks.editItemAt(minIndex);
4595778822d86b0337407514b9372562b86edfa91cdAndreas Huber
4605778822d86b0337407514b9372562b86edfa91cdAndreas Huber    info->mSample->release();
4615778822d86b0337407514b9372562b86edfa91cdAndreas Huber    info->mSample = NULL;
4625778822d86b0337407514b9372562b86edfa91cdAndreas Huber    info->mSampleTimeUs = -1ll;
4635778822d86b0337407514b9372562b86edfa91cdAndreas Huber
4645778822d86b0337407514b9372562b86edfa91cdAndreas Huber    return OK;
4655778822d86b0337407514b9372562b86edfa91cdAndreas Huber}
4665778822d86b0337407514b9372562b86edfa91cdAndreas Huber
467793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shihstatus_t NuMediaExtractor::appendVorbisNumPageSamples(TrackInfo *info, const sp<ABuffer> &buffer) {
468793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    int32_t numPageSamples;
469793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    if (!info->mSample->meta_data()->findInt32(
470793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih            kKeyValidSamples, &numPageSamples)) {
471793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        numPageSamples = -1;
472793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    }
473793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih
474793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    memcpy((uint8_t *)buffer->data() + info->mSample->range_length(),
475793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih           &numPageSamples,
476793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih           sizeof(numPageSamples));
477793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih
478793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    uint32_t type;
479793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    const void *data;
480793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    size_t size, size2;
481793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    if (info->mSample->meta_data()->findData(kKeyEncryptedSizes, &type, &data, &size)) {
482793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        // Signal numPageSamples (a plain int32_t) is appended at the end,
483793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        // i.e. sizeof(numPageSamples) plain bytes + 0 encrypted bytes
484793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        if (SIZE_MAX - size < sizeof(int32_t)) {
485793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih            return -ENOMEM;
486793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        }
487793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih
488793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        size_t newSize = size + sizeof(int32_t);
489793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        sp<ABuffer> abuf = new ABuffer(newSize);
490793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        uint8_t *adata = static_cast<uint8_t *>(abuf->data());
491793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        if (adata == NULL) {
492793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih            return -ENOMEM;
493793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        }
494793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih
495793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        // append 0 to encrypted sizes
496793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        int32_t zero = 0;
497793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        memcpy(adata, data, size);
498793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        memcpy(adata + size, &zero, sizeof(zero));
499793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        info->mSample->meta_data()->setData(kKeyEncryptedSizes, type, adata, newSize);
500793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih
501793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        if (info->mSample->meta_data()->findData(kKeyPlainSizes, &type, &data, &size2)) {
502793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih            if (size2 != size) {
503793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih                return ERROR_MALFORMED;
504793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih            }
505793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih            memcpy(adata, data, size);
506793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        } else {
507793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih            // if sample meta data does not include plain size array, assume filled with zeros,
508793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih            // i.e. entire buffer is encrypted
509793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih            memset(adata, 0, size);
510793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        }
511793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        // append sizeof(numPageSamples) to plain sizes.
512793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        int32_t int32Size = sizeof(numPageSamples);
513793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        memcpy(adata + size, &int32Size, sizeof(int32Size));
514793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        info->mSample->meta_data()->setData(kKeyPlainSizes, type, adata, newSize);
515793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    }
516793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih
517793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    return OK;
518793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih}
519793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih
5205778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatus_t NuMediaExtractor::readSampleData(const sp<ABuffer> &buffer) {
521dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber    Mutex::Autolock autoLock(mLock);
522dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber
5235778822d86b0337407514b9372562b86edfa91cdAndreas Huber    ssize_t minIndex = fetchTrackSamples();
5245778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5255778822d86b0337407514b9372562b86edfa91cdAndreas Huber    if (minIndex < 0) {
5265778822d86b0337407514b9372562b86edfa91cdAndreas Huber        return ERROR_END_OF_STREAM;
5275778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
5285778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5295778822d86b0337407514b9372562b86edfa91cdAndreas Huber    TrackInfo *info = &mSelectedTracks.editItemAt(minIndex);
5305778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5315778822d86b0337407514b9372562b86edfa91cdAndreas Huber    size_t sampleSize = info->mSample->range_length();
5325778822d86b0337407514b9372562b86edfa91cdAndreas Huber
533ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    if (info->mTrackFlags & kIsVorbis) {
5345778822d86b0337407514b9372562b86edfa91cdAndreas Huber        // Each sample's data is suffixed by the number of page samples
5355778822d86b0337407514b9372562b86edfa91cdAndreas Huber        // or -1 if not available.
5365778822d86b0337407514b9372562b86edfa91cdAndreas Huber        sampleSize += sizeof(int32_t);
5375778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
5385778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5395778822d86b0337407514b9372562b86edfa91cdAndreas Huber    if (buffer->capacity() < sampleSize) {
5405778822d86b0337407514b9372562b86edfa91cdAndreas Huber        return -ENOMEM;
5415778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
5425778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5435778822d86b0337407514b9372562b86edfa91cdAndreas Huber    const uint8_t *src =
5445778822d86b0337407514b9372562b86edfa91cdAndreas Huber        (const uint8_t *)info->mSample->data()
5455778822d86b0337407514b9372562b86edfa91cdAndreas Huber            + info->mSample->range_offset();
5465778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5475778822d86b0337407514b9372562b86edfa91cdAndreas Huber    memcpy((uint8_t *)buffer->data(), src, info->mSample->range_length());
5485778822d86b0337407514b9372562b86edfa91cdAndreas Huber
549793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    status_t err = OK;
550ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    if (info->mTrackFlags & kIsVorbis) {
551793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        err = appendVorbisNumPageSamples(info, buffer);
5525778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
5535778822d86b0337407514b9372562b86edfa91cdAndreas Huber
554793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    if (err == OK) {
555793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih        buffer->setRange(0, sampleSize);
556793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    }
5575778822d86b0337407514b9372562b86edfa91cdAndreas Huber
558793c9fb11114c7be4636b8cae5477995aadeb71dRobert Shih    return err;
5595778822d86b0337407514b9372562b86edfa91cdAndreas Huber}
5605778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5615778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatus_t NuMediaExtractor::getSampleTrackIndex(size_t *trackIndex) {
562dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber    Mutex::Autolock autoLock(mLock);
563dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber
5645778822d86b0337407514b9372562b86edfa91cdAndreas Huber    ssize_t minIndex = fetchTrackSamples();
5655778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5665778822d86b0337407514b9372562b86edfa91cdAndreas Huber    if (minIndex < 0) {
5675778822d86b0337407514b9372562b86edfa91cdAndreas Huber        return ERROR_END_OF_STREAM;
5685778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
5695778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5705778822d86b0337407514b9372562b86edfa91cdAndreas Huber    TrackInfo *info = &mSelectedTracks.editItemAt(minIndex);
5715778822d86b0337407514b9372562b86edfa91cdAndreas Huber    *trackIndex = info->mTrackIndex;
5725778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5735778822d86b0337407514b9372562b86edfa91cdAndreas Huber    return OK;
5745778822d86b0337407514b9372562b86edfa91cdAndreas Huber}
5755778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5765778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatus_t NuMediaExtractor::getSampleTime(int64_t *sampleTimeUs) {
577dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber    Mutex::Autolock autoLock(mLock);
578dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber
5795778822d86b0337407514b9372562b86edfa91cdAndreas Huber    ssize_t minIndex = fetchTrackSamples();
5805778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5815778822d86b0337407514b9372562b86edfa91cdAndreas Huber    if (minIndex < 0) {
5825778822d86b0337407514b9372562b86edfa91cdAndreas Huber        return ERROR_END_OF_STREAM;
5835778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
5845778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5855778822d86b0337407514b9372562b86edfa91cdAndreas Huber    TrackInfo *info = &mSelectedTracks.editItemAt(minIndex);
5865778822d86b0337407514b9372562b86edfa91cdAndreas Huber    *sampleTimeUs = info->mSampleTimeUs;
5875778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5885778822d86b0337407514b9372562b86edfa91cdAndreas Huber    return OK;
5895778822d86b0337407514b9372562b86edfa91cdAndreas Huber}
5905778822d86b0337407514b9372562b86edfa91cdAndreas Huber
591f69e53033f23f9f70fcdb28a3c2e650de0147459Andreas Huberstatus_t NuMediaExtractor::getSampleMeta(sp<MetaData> *sampleMeta) {
592dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber    Mutex::Autolock autoLock(mLock);
593dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber
594f69e53033f23f9f70fcdb28a3c2e650de0147459Andreas Huber    *sampleMeta = NULL;
595f69e53033f23f9f70fcdb28a3c2e650de0147459Andreas Huber
596ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    ssize_t minIndex = fetchTrackSamples();
597ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
598ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    if (minIndex < 0) {
599ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        return ERROR_END_OF_STREAM;
600ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    }
601ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
602ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    TrackInfo *info = &mSelectedTracks.editItemAt(minIndex);
603f69e53033f23f9f70fcdb28a3c2e650de0147459Andreas Huber    *sampleMeta = info->mSample->meta_data();
604ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
605ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber    return OK;
606ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber}
607ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber
608a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huberbool NuMediaExtractor::getTotalBitrate(int64_t *bitrate) const {
609a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    if (mTotalBitrate >= 0) {
610a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        *bitrate = mTotalBitrate;
611a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        return true;
612a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    }
613a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
614a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    off64_t size;
615a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    if (mDurationUs >= 0 && mDataSource->getSize(&size) == OK) {
616a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        *bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
617a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        return true;
618a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    }
619a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
620a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    return false;
621a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber}
622a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
623a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber// Returns true iff cached duration is available/applicable.
624a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huberbool NuMediaExtractor::getCachedDuration(
625a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        int64_t *durationUs, bool *eos) const {
626dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber    Mutex::Autolock autoLock(mLock);
627dc7431e70b4b030b5f42d0dfc3ef244d4f583dd2Andreas Huber
628a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    int64_t bitrate;
629a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    if (mIsWidevineExtractor) {
630a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        sp<WVMExtractor> wvmExtractor =
631a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber            static_cast<WVMExtractor *>(mImpl.get());
632a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
633a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        status_t finalStatus;
634a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        *durationUs = wvmExtractor->getCachedDurationUs(&finalStatus);
635a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        *eos = (finalStatus != OK);
636a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        return true;
637a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    } else if ((mDataSource->flags() & DataSource::kIsCachingDataSource)
638a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber            && getTotalBitrate(&bitrate)) {
639a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        sp<NuCachedSource2> cachedSource =
640a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber            static_cast<NuCachedSource2 *>(mDataSource.get());
641a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
642a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        status_t finalStatus;
643a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        size_t cachedDataRemaining =
644a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber            cachedSource->approxDataRemaining(&finalStatus);
645a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
646a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        *durationUs = cachedDataRemaining * 8000000ll / bitrate;
647a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        *eos = (finalStatus != OK);
648a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber        return true;
649a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    }
650a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
651a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber    return false;
652a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber}
653a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Huber
6545778822d86b0337407514b9372562b86edfa91cdAndreas Huber}  // namespace android
655