NuMediaExtractor.cpp revision ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6
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" 245778822d86b0337407514b9372562b86edfa91cdAndreas Huber 255778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/foundation/ABuffer.h> 265778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/foundation/ADebug.h> 275778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/foundation/AMessage.h> 285778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/DataSource.h> 295778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/MediaBuffer.h> 305778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/MediaDefs.h> 315778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/MediaErrors.h> 325778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/MediaExtractor.h> 335778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/MediaSource.h> 345778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/MetaData.h> 355778822d86b0337407514b9372562b86edfa91cdAndreas Huber#include <media/stagefright/Utils.h> 365778822d86b0337407514b9372562b86edfa91cdAndreas Huber 375778822d86b0337407514b9372562b86edfa91cdAndreas Hubernamespace android { 385778822d86b0337407514b9372562b86edfa91cdAndreas Huber 395778822d86b0337407514b9372562b86edfa91cdAndreas HuberNuMediaExtractor::NuMediaExtractor() { 405778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 415778822d86b0337407514b9372562b86edfa91cdAndreas Huber 425778822d86b0337407514b9372562b86edfa91cdAndreas HuberNuMediaExtractor::~NuMediaExtractor() { 435778822d86b0337407514b9372562b86edfa91cdAndreas Huber releaseTrackSamples(); 445778822d86b0337407514b9372562b86edfa91cdAndreas Huber 455778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (size_t i = 0; i < mSelectedTracks.size(); ++i) { 465778822d86b0337407514b9372562b86edfa91cdAndreas Huber TrackInfo *info = &mSelectedTracks.editItemAt(i); 475778822d86b0337407514b9372562b86edfa91cdAndreas Huber 485778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_EQ((status_t)OK, info->mSource->stop()); 495778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 505778822d86b0337407514b9372562b86edfa91cdAndreas Huber 515778822d86b0337407514b9372562b86edfa91cdAndreas Huber mSelectedTracks.clear(); 525778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 535778822d86b0337407514b9372562b86edfa91cdAndreas Huber 545778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatus_t NuMediaExtractor::setDataSource(const char *path) { 555778822d86b0337407514b9372562b86edfa91cdAndreas Huber sp<DataSource> dataSource = DataSource::CreateFromURI(path); 565778822d86b0337407514b9372562b86edfa91cdAndreas Huber 575778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (dataSource == NULL) { 585778822d86b0337407514b9372562b86edfa91cdAndreas Huber return -ENOENT; 595778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 605778822d86b0337407514b9372562b86edfa91cdAndreas Huber 615778822d86b0337407514b9372562b86edfa91cdAndreas Huber mImpl = MediaExtractor::Create(dataSource); 625778822d86b0337407514b9372562b86edfa91cdAndreas Huber 635778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (mImpl == NULL) { 645778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ERROR_UNSUPPORTED; 655778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 665778822d86b0337407514b9372562b86edfa91cdAndreas Huber 675778822d86b0337407514b9372562b86edfa91cdAndreas Huber return OK; 685778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 695778822d86b0337407514b9372562b86edfa91cdAndreas Huber 705778822d86b0337407514b9372562b86edfa91cdAndreas Hubersize_t NuMediaExtractor::countTracks() const { 715778822d86b0337407514b9372562b86edfa91cdAndreas Huber return mImpl == NULL ? 0 : mImpl->countTracks(); 725778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 735778822d86b0337407514b9372562b86edfa91cdAndreas Huber 745778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatus_t NuMediaExtractor::getTrackFormat( 755778822d86b0337407514b9372562b86edfa91cdAndreas Huber size_t index, sp<AMessage> *format) const { 765778822d86b0337407514b9372562b86edfa91cdAndreas Huber *format = NULL; 775778822d86b0337407514b9372562b86edfa91cdAndreas Huber 785778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (mImpl == NULL) { 795778822d86b0337407514b9372562b86edfa91cdAndreas Huber return -EINVAL; 805778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 815778822d86b0337407514b9372562b86edfa91cdAndreas Huber 825778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (index >= mImpl->countTracks()) { 835778822d86b0337407514b9372562b86edfa91cdAndreas Huber return -ERANGE; 845778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 855778822d86b0337407514b9372562b86edfa91cdAndreas Huber 865778822d86b0337407514b9372562b86edfa91cdAndreas Huber sp<MetaData> meta = mImpl->getTrackMetaData(index); 875778822d86b0337407514b9372562b86edfa91cdAndreas Huber 885778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char *mime; 895778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(meta->findCString(kKeyMIMEType, &mime)); 905778822d86b0337407514b9372562b86edfa91cdAndreas Huber 915778822d86b0337407514b9372562b86edfa91cdAndreas Huber sp<AMessage> msg = new AMessage; 925778822d86b0337407514b9372562b86edfa91cdAndreas Huber msg->setString("mime", mime); 935778822d86b0337407514b9372562b86edfa91cdAndreas Huber 945778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (!strncasecmp("video/", mime, 6)) { 955778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t width, height; 965778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(meta->findInt32(kKeyWidth, &width)); 975778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(meta->findInt32(kKeyHeight, &height)); 985778822d86b0337407514b9372562b86edfa91cdAndreas Huber 995778822d86b0337407514b9372562b86edfa91cdAndreas Huber msg->setInt32("width", width); 1005778822d86b0337407514b9372562b86edfa91cdAndreas Huber msg->setInt32("height", height); 1015778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 1025778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(!strncasecmp("audio/", mime, 6)); 1035778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1045778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t numChannels, sampleRate; 1055778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); 1065778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); 1075778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1085778822d86b0337407514b9372562b86edfa91cdAndreas Huber msg->setInt32("channel-count", numChannels); 1095778822d86b0337407514b9372562b86edfa91cdAndreas Huber msg->setInt32("sample-rate", sampleRate); 110ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber 111ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber int32_t isADTS; 112ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber if (meta->findInt32(kKeyIsADTS, &isADTS)) { 113ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber msg->setInt32("is-adts", true); 114ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber } 1155778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1165778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1175778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t maxInputSize; 1185778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) { 1195778822d86b0337407514b9372562b86edfa91cdAndreas Huber msg->setInt32("max-input-size", maxInputSize); 1205778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1215778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1225778822d86b0337407514b9372562b86edfa91cdAndreas Huber uint32_t type; 1235778822d86b0337407514b9372562b86edfa91cdAndreas Huber const void *data; 1245778822d86b0337407514b9372562b86edfa91cdAndreas Huber size_t size; 1255778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (meta->findData(kKeyAVCC, &type, &data, &size)) { 1265778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Parse the AVCDecoderConfigurationRecord 1275778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1285778822d86b0337407514b9372562b86edfa91cdAndreas Huber const uint8_t *ptr = (const uint8_t *)data; 1295778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1305778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(size >= 7); 1315778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 1325778822d86b0337407514b9372562b86edfa91cdAndreas Huber uint8_t profile = ptr[1]; 1335778822d86b0337407514b9372562b86edfa91cdAndreas Huber uint8_t level = ptr[3]; 1345778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1355778822d86b0337407514b9372562b86edfa91cdAndreas Huber // There is decodable content out there that fails the following 1365778822d86b0337407514b9372562b86edfa91cdAndreas Huber // assertion, let's be lenient for now... 1375778822d86b0337407514b9372562b86edfa91cdAndreas Huber // CHECK((ptr[4] >> 2) == 0x3f); // reserved 1385778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1395778822d86b0337407514b9372562b86edfa91cdAndreas Huber size_t lengthSize = 1 + (ptr[4] & 3); 1405778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1415778822d86b0337407514b9372562b86edfa91cdAndreas Huber // commented out check below as H264_QVGA_500_NO_AUDIO.3gp 1425778822d86b0337407514b9372562b86edfa91cdAndreas Huber // violates it... 1435778822d86b0337407514b9372562b86edfa91cdAndreas Huber // CHECK((ptr[5] >> 5) == 7); // reserved 1445778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1455778822d86b0337407514b9372562b86edfa91cdAndreas Huber size_t numSeqParameterSets = ptr[5] & 31; 1465778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1475778822d86b0337407514b9372562b86edfa91cdAndreas Huber ptr += 6; 1485778822d86b0337407514b9372562b86edfa91cdAndreas Huber size -= 6; 1495778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1505778822d86b0337407514b9372562b86edfa91cdAndreas Huber sp<ABuffer> buffer = new ABuffer(1024); 1515778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->setRange(0, 0); 1525778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1535778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (size_t i = 0; i < numSeqParameterSets; ++i) { 1545778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(size >= 2); 1555778822d86b0337407514b9372562b86edfa91cdAndreas Huber size_t length = U16_AT(ptr); 1565778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1575778822d86b0337407514b9372562b86edfa91cdAndreas Huber ptr += 2; 1585778822d86b0337407514b9372562b86edfa91cdAndreas Huber size -= 2; 1595778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1605778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(size >= length); 1615778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1625778822d86b0337407514b9372562b86edfa91cdAndreas Huber memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4); 1635778822d86b0337407514b9372562b86edfa91cdAndreas Huber memcpy(buffer->data() + buffer->size() + 4, ptr, length); 1645778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->setRange(0, buffer->size() + 4 + length); 1655778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1665778822d86b0337407514b9372562b86edfa91cdAndreas Huber ptr += length; 1675778822d86b0337407514b9372562b86edfa91cdAndreas Huber size -= length; 1685778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1695778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1705778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->meta()->setInt32("csd", true); 1715778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->meta()->setInt64("timeUs", 0); 1725778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1732d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber msg->setBuffer("csd-0", buffer); 1745778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1755778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer = new ABuffer(1024); 1765778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->setRange(0, 0); 1775778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1785778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(size >= 1); 1795778822d86b0337407514b9372562b86edfa91cdAndreas Huber size_t numPictureParameterSets = *ptr; 1805778822d86b0337407514b9372562b86edfa91cdAndreas Huber ++ptr; 1815778822d86b0337407514b9372562b86edfa91cdAndreas Huber --size; 1825778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1835778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (size_t i = 0; i < numPictureParameterSets; ++i) { 1845778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(size >= 2); 1855778822d86b0337407514b9372562b86edfa91cdAndreas Huber size_t length = U16_AT(ptr); 1865778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1875778822d86b0337407514b9372562b86edfa91cdAndreas Huber ptr += 2; 1885778822d86b0337407514b9372562b86edfa91cdAndreas Huber size -= 2; 1895778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1905778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(size >= length); 1915778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1925778822d86b0337407514b9372562b86edfa91cdAndreas Huber memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4); 1935778822d86b0337407514b9372562b86edfa91cdAndreas Huber memcpy(buffer->data() + buffer->size() + 4, ptr, length); 1945778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->setRange(0, buffer->size() + 4 + length); 1955778822d86b0337407514b9372562b86edfa91cdAndreas Huber 1965778822d86b0337407514b9372562b86edfa91cdAndreas Huber ptr += length; 1975778822d86b0337407514b9372562b86edfa91cdAndreas Huber size -= length; 1985778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 1995778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2005778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->meta()->setInt32("csd", true); 2015778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->meta()->setInt64("timeUs", 0); 2022d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber msg->setBuffer("csd-1", buffer); 2035778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (meta->findData(kKeyESDS, &type, &data, &size)) { 2045778822d86b0337407514b9372562b86edfa91cdAndreas Huber ESDS esds((const char *)data, size); 2055778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_EQ(esds.InitCheck(), (status_t)OK); 2065778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2075778822d86b0337407514b9372562b86edfa91cdAndreas Huber const void *codec_specific_data; 2085778822d86b0337407514b9372562b86edfa91cdAndreas Huber size_t codec_specific_data_size; 2095778822d86b0337407514b9372562b86edfa91cdAndreas Huber esds.getCodecSpecificInfo( 2105778822d86b0337407514b9372562b86edfa91cdAndreas Huber &codec_specific_data, &codec_specific_data_size); 2115778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2125778822d86b0337407514b9372562b86edfa91cdAndreas Huber sp<ABuffer> buffer = new ABuffer(codec_specific_data_size); 2135778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2145778822d86b0337407514b9372562b86edfa91cdAndreas Huber memcpy(buffer->data(), codec_specific_data, 2155778822d86b0337407514b9372562b86edfa91cdAndreas Huber codec_specific_data_size); 2165778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2175778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->meta()->setInt32("csd", true); 2185778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->meta()->setInt64("timeUs", 0); 2192d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber msg->setBuffer("csd-0", buffer); 2205778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) { 2215778822d86b0337407514b9372562b86edfa91cdAndreas Huber sp<ABuffer> buffer = new ABuffer(size); 2225778822d86b0337407514b9372562b86edfa91cdAndreas Huber memcpy(buffer->data(), data, size); 2235778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2245778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->meta()->setInt32("csd", true); 2255778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->meta()->setInt64("timeUs", 0); 2262d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber msg->setBuffer("csd-0", buffer); 2275778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2285778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (!meta->findData(kKeyVorbisBooks, &type, &data, &size)) { 2295778822d86b0337407514b9372562b86edfa91cdAndreas Huber return -EINVAL; 2305778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2315778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2325778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer = new ABuffer(size); 2335778822d86b0337407514b9372562b86edfa91cdAndreas Huber memcpy(buffer->data(), data, size); 2345778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2355778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->meta()->setInt32("csd", true); 2365778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->meta()->setInt64("timeUs", 0); 2372d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber msg->setBuffer("csd-1", buffer); 2385778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2395778822d86b0337407514b9372562b86edfa91cdAndreas Huber 240ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber if (meta->findData(kKeyEMM, &type, &data, &size)) { 241ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber sp<ABuffer> emm = new ABuffer(size); 242ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber memcpy(emm->data(), data, size); 243ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber 244ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber msg->setBuffer("emm", emm); 245ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber } 246ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber 247ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber if (meta->findData(kKeyECM, &type, &data, &size)) { 248ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber sp<ABuffer> ecm = new ABuffer(size); 249ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber memcpy(ecm->data(), data, size); 250ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber 251ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber msg->setBuffer("ecm", ecm); 252ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber } 253ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber 2545778822d86b0337407514b9372562b86edfa91cdAndreas Huber *format = msg; 2555778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2565778822d86b0337407514b9372562b86edfa91cdAndreas Huber return OK; 2575778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 2585778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2595778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatus_t NuMediaExtractor::selectTrack(size_t index) { 2605778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (mImpl == NULL) { 2615778822d86b0337407514b9372562b86edfa91cdAndreas Huber return -EINVAL; 2625778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2635778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2645778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (index >= mImpl->countTracks()) { 2655778822d86b0337407514b9372562b86edfa91cdAndreas Huber return -ERANGE; 2665778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2675778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2685778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (size_t i = 0; i < mSelectedTracks.size(); ++i) { 2695778822d86b0337407514b9372562b86edfa91cdAndreas Huber TrackInfo *info = &mSelectedTracks.editItemAt(i); 2705778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2715778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (info->mTrackIndex == index) { 2725778822d86b0337407514b9372562b86edfa91cdAndreas Huber // This track has already been selected. 2735778822d86b0337407514b9372562b86edfa91cdAndreas Huber return OK; 2745778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2755778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2765778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2775778822d86b0337407514b9372562b86edfa91cdAndreas Huber sp<MediaSource> source = mImpl->getTrack(index); 2785778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2795778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK_EQ((status_t)OK, source->start()); 2805778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2815778822d86b0337407514b9372562b86edfa91cdAndreas Huber mSelectedTracks.push(); 2825778822d86b0337407514b9372562b86edfa91cdAndreas Huber TrackInfo *info = &mSelectedTracks.editItemAt(mSelectedTracks.size() - 1); 2835778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2845778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mSource = source; 2855778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mTrackIndex = index; 2865778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mFinalResult = OK; 2875778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mSample = NULL; 2885778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mSampleTimeUs = -1ll; 289ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber info->mSampleFlags = 0; 290ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber info->mTrackFlags = 0; 2915778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2925778822d86b0337407514b9372562b86edfa91cdAndreas Huber const char *mime; 2935778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(source->getFormat()->findCString(kKeyMIMEType, &mime)); 2945778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2955778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { 296ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber info->mTrackFlags |= kIsVorbis; 2975778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 2985778822d86b0337407514b9372562b86edfa91cdAndreas Huber 2995778822d86b0337407514b9372562b86edfa91cdAndreas Huber return OK; 3005778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 3015778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3025778822d86b0337407514b9372562b86edfa91cdAndreas Hubervoid NuMediaExtractor::releaseTrackSamples() { 3035778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (size_t i = 0; i < mSelectedTracks.size(); ++i) { 3045778822d86b0337407514b9372562b86edfa91cdAndreas Huber TrackInfo *info = &mSelectedTracks.editItemAt(i); 3055778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3065778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (info->mSample != NULL) { 3075778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mSample->release(); 3085778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mSample = NULL; 3095778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3105778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mSampleTimeUs = -1ll; 311ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber info->mSampleFlags = 0; 3125778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3135778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3145778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 3155778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3165778822d86b0337407514b9372562b86edfa91cdAndreas Huberssize_t NuMediaExtractor::fetchTrackSamples(int64_t seekTimeUs) { 3175778822d86b0337407514b9372562b86edfa91cdAndreas Huber TrackInfo *minInfo = NULL; 3185778822d86b0337407514b9372562b86edfa91cdAndreas Huber ssize_t minIndex = -1; 3195778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3205778822d86b0337407514b9372562b86edfa91cdAndreas Huber for (size_t i = 0; i < mSelectedTracks.size(); ++i) { 3215778822d86b0337407514b9372562b86edfa91cdAndreas Huber TrackInfo *info = &mSelectedTracks.editItemAt(i); 3225778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3235778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (seekTimeUs >= 0ll) { 3245778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mFinalResult = OK; 3255778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3265778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (info->mSample != NULL) { 3275778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mSample->release(); 3285778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mSample = NULL; 3295778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mSampleTimeUs = -1ll; 330ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber info->mSampleFlags = 0; 3315778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3325778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else if (info->mFinalResult != OK) { 3335778822d86b0337407514b9372562b86edfa91cdAndreas Huber continue; 3345778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3355778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3365778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (info->mSample == NULL) { 3375778822d86b0337407514b9372562b86edfa91cdAndreas Huber MediaSource::ReadOptions options; 3385778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (seekTimeUs >= 0ll) { 3395778822d86b0337407514b9372562b86edfa91cdAndreas Huber options.setSeekTo(seekTimeUs); 3405778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3415778822d86b0337407514b9372562b86edfa91cdAndreas Huber status_t err = info->mSource->read(&info->mSample, &options); 3425778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3435778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (err != OK) { 3445778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(info->mSample == NULL); 3455778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3465778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mFinalResult = err; 3475778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mSampleTimeUs = -1ll; 348ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber info->mSampleFlags = 0; 3495778822d86b0337407514b9372562b86edfa91cdAndreas Huber continue; 3505778822d86b0337407514b9372562b86edfa91cdAndreas Huber } else { 3515778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(info->mSample != NULL); 3525778822d86b0337407514b9372562b86edfa91cdAndreas Huber CHECK(info->mSample->meta_data()->findInt64( 3535778822d86b0337407514b9372562b86edfa91cdAndreas Huber kKeyTime, &info->mSampleTimeUs)); 354ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber 355ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber info->mSampleFlags = 0; 356ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber 357ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber int32_t val; 358ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber if (info->mSample->meta_data()->findInt32( 359ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber kKeyIsSyncFrame, &val) && val != 0) { 360ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber info->mSampleFlags |= SAMPLE_FLAG_SYNC; 361ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber } 362ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber 363ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber if (info->mSample->meta_data()->findInt32( 364ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber kKeyScrambling, &val) && val != 0) { 365ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber info->mSampleFlags |= SAMPLE_FLAG_ENCRYPTED; 366ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber } 3675778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3685778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3695778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3705778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (minInfo == NULL || info->mSampleTimeUs < minInfo->mSampleTimeUs) { 3715778822d86b0337407514b9372562b86edfa91cdAndreas Huber minInfo = info; 3725778822d86b0337407514b9372562b86edfa91cdAndreas Huber minIndex = i; 3735778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3745778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3755778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3765778822d86b0337407514b9372562b86edfa91cdAndreas Huber return minIndex; 3775778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 3785778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3795778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatus_t NuMediaExtractor::seekTo(int64_t timeUs) { 3805778822d86b0337407514b9372562b86edfa91cdAndreas Huber return fetchTrackSamples(timeUs); 3815778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 3825778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3835778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatus_t NuMediaExtractor::advance() { 3845778822d86b0337407514b9372562b86edfa91cdAndreas Huber ssize_t minIndex = fetchTrackSamples(); 3855778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3865778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (minIndex < 0) { 3875778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ERROR_END_OF_STREAM; 3885778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 3895778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3905778822d86b0337407514b9372562b86edfa91cdAndreas Huber TrackInfo *info = &mSelectedTracks.editItemAt(minIndex); 3915778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3925778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mSample->release(); 3935778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mSample = NULL; 3945778822d86b0337407514b9372562b86edfa91cdAndreas Huber info->mSampleTimeUs = -1ll; 3955778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3965778822d86b0337407514b9372562b86edfa91cdAndreas Huber return OK; 3975778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 3985778822d86b0337407514b9372562b86edfa91cdAndreas Huber 3995778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatus_t NuMediaExtractor::readSampleData(const sp<ABuffer> &buffer) { 4005778822d86b0337407514b9372562b86edfa91cdAndreas Huber ssize_t minIndex = fetchTrackSamples(); 4015778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4025778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (minIndex < 0) { 4035778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ERROR_END_OF_STREAM; 4045778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4055778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4065778822d86b0337407514b9372562b86edfa91cdAndreas Huber TrackInfo *info = &mSelectedTracks.editItemAt(minIndex); 4075778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4085778822d86b0337407514b9372562b86edfa91cdAndreas Huber size_t sampleSize = info->mSample->range_length(); 4095778822d86b0337407514b9372562b86edfa91cdAndreas Huber 410ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber if (info->mTrackFlags & kIsVorbis) { 4115778822d86b0337407514b9372562b86edfa91cdAndreas Huber // Each sample's data is suffixed by the number of page samples 4125778822d86b0337407514b9372562b86edfa91cdAndreas Huber // or -1 if not available. 4135778822d86b0337407514b9372562b86edfa91cdAndreas Huber sampleSize += sizeof(int32_t); 4145778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4155778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4165778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (buffer->capacity() < sampleSize) { 4175778822d86b0337407514b9372562b86edfa91cdAndreas Huber return -ENOMEM; 4185778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4195778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4205778822d86b0337407514b9372562b86edfa91cdAndreas Huber const uint8_t *src = 4215778822d86b0337407514b9372562b86edfa91cdAndreas Huber (const uint8_t *)info->mSample->data() 4225778822d86b0337407514b9372562b86edfa91cdAndreas Huber + info->mSample->range_offset(); 4235778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4245778822d86b0337407514b9372562b86edfa91cdAndreas Huber memcpy((uint8_t *)buffer->data(), src, info->mSample->range_length()); 4255778822d86b0337407514b9372562b86edfa91cdAndreas Huber 426ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber if (info->mTrackFlags & kIsVorbis) { 4275778822d86b0337407514b9372562b86edfa91cdAndreas Huber int32_t numPageSamples; 4285778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (!info->mSample->meta_data()->findInt32( 4295778822d86b0337407514b9372562b86edfa91cdAndreas Huber kKeyValidSamples, &numPageSamples)) { 4305778822d86b0337407514b9372562b86edfa91cdAndreas Huber numPageSamples = -1; 4315778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4325778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4335778822d86b0337407514b9372562b86edfa91cdAndreas Huber memcpy((uint8_t *)buffer->data() + info->mSample->range_length(), 4345778822d86b0337407514b9372562b86edfa91cdAndreas Huber &numPageSamples, 4355778822d86b0337407514b9372562b86edfa91cdAndreas Huber sizeof(numPageSamples)); 4365778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4375778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4385778822d86b0337407514b9372562b86edfa91cdAndreas Huber buffer->setRange(0, sampleSize); 4395778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4405778822d86b0337407514b9372562b86edfa91cdAndreas Huber return OK; 4415778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 4425778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4435778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatus_t NuMediaExtractor::getSampleTrackIndex(size_t *trackIndex) { 4445778822d86b0337407514b9372562b86edfa91cdAndreas Huber ssize_t minIndex = fetchTrackSamples(); 4455778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4465778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (minIndex < 0) { 4475778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ERROR_END_OF_STREAM; 4485778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4495778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4505778822d86b0337407514b9372562b86edfa91cdAndreas Huber TrackInfo *info = &mSelectedTracks.editItemAt(minIndex); 4515778822d86b0337407514b9372562b86edfa91cdAndreas Huber *trackIndex = info->mTrackIndex; 4525778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4535778822d86b0337407514b9372562b86edfa91cdAndreas Huber return OK; 4545778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 4555778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4565778822d86b0337407514b9372562b86edfa91cdAndreas Huberstatus_t NuMediaExtractor::getSampleTime(int64_t *sampleTimeUs) { 4575778822d86b0337407514b9372562b86edfa91cdAndreas Huber ssize_t minIndex = fetchTrackSamples(); 4585778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4595778822d86b0337407514b9372562b86edfa91cdAndreas Huber if (minIndex < 0) { 4605778822d86b0337407514b9372562b86edfa91cdAndreas Huber return ERROR_END_OF_STREAM; 4615778822d86b0337407514b9372562b86edfa91cdAndreas Huber } 4625778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4635778822d86b0337407514b9372562b86edfa91cdAndreas Huber TrackInfo *info = &mSelectedTracks.editItemAt(minIndex); 4645778822d86b0337407514b9372562b86edfa91cdAndreas Huber *sampleTimeUs = info->mSampleTimeUs; 4655778822d86b0337407514b9372562b86edfa91cdAndreas Huber 4665778822d86b0337407514b9372562b86edfa91cdAndreas Huber return OK; 4675778822d86b0337407514b9372562b86edfa91cdAndreas Huber} 4685778822d86b0337407514b9372562b86edfa91cdAndreas Huber 469ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huberstatus_t NuMediaExtractor::getSampleFlags(uint32_t *sampleFlags) { 470ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber ssize_t minIndex = fetchTrackSamples(); 471ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber 472ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber if (minIndex < 0) { 473ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber return ERROR_END_OF_STREAM; 474ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber } 475ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber 476ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber TrackInfo *info = &mSelectedTracks.editItemAt(minIndex); 477ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber *sampleFlags = info->mSampleFlags; 478ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber 479ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber return OK; 480ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber} 481ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber 4825778822d86b0337407514b9372562b86edfa91cdAndreas Huber} // namespace android 483