162cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber/*
262cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber * Copyright (C) 2010 The Android Open Source Project
362cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber *
462cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
562cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber * you may not use this file except in compliance with the License.
662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber * You may obtain a copy of the License at
762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber *
862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
962cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber *
1062cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber * Unless required by applicable law or agreed to in writing, software
1162cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1262cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1362cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber * See the License for the specific language governing permissions and
1462cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber * limitations under the License.
1562cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber */
1662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
176e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber//#define LOG_NDEBUG 0
186e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#define LOG_TAG "AMPEG4ElementaryAssembler"
196e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#include <utils/Log.h>
206e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber
2162cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber#include "AMPEG4ElementaryAssembler.h"
2262cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
2362cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber#include "ARTPSource.h"
248647bbe4420ca487467318404127f52c567e346bAndreas Huber#include "ASessionDescription.h"
2562cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
264dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber#include <media/stagefright/foundation/ABitReader.h>
2762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
2862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber#include <media/stagefright/foundation/ADebug.h>
2962cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber#include <media/stagefright/foundation/AMessage.h>
3062cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber#include <media/stagefright/foundation/hexdump.h>
314dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber#include <media/stagefright/Utils.h>
3262cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
334dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber#include <ctype.h>
3462cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber#include <stdint.h>
3562cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
3662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Hubernamespace android {
3762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
384dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huberstatic bool GetAttribute(const char *s, const char *key, AString *value) {
394dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    value->clear();
404dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
414dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    size_t keyLen = strlen(key);
424dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
434dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    for (;;) {
444dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        while (isspace(*s)) {
454dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            ++s;
464dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        }
474dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
484dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        const char *colonPos = strchr(s, ';');
494dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
504dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        size_t len =
514dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            (colonPos == NULL) ? strlen(s) : colonPos - s;
524dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
534dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        if (len >= keyLen + 1 && s[keyLen] == '='
544dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                && !strncasecmp(s, key, keyLen)) {
554dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            value->setTo(&s[keyLen + 1], len - keyLen - 1);
564dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            return true;
574dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        }
584dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
594dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        if (colonPos == NULL) {
604dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            return false;
614dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        }
624dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
634dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        s = colonPos + 1;
644dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    }
654dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber}
664dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
674dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huberstatic bool GetIntegerAttribute(
684dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        const char *s, const char *key, unsigned *x) {
694dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    *x = 0;
704dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
714dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    AString val;
724dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    if (!GetAttribute(s, key, &val)) {
734dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        return false;
744dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    }
754dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
764dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    s = val.c_str();
774dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    char *end;
784dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    unsigned y = strtoul(s, &end, 10);
794dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
804dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    if (end == s || *end != '\0') {
814dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        return false;
824dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    }
834dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
844dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    *x = y;
854dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
864dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    return true;
874dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber}
884dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
898647bbe4420ca487467318404127f52c567e346bAndreas Huberstatic bool GetSampleRateIndex(int32_t sampleRate, size_t *tableIndex) {
908647bbe4420ca487467318404127f52c567e346bAndreas Huber    static const int32_t kSampleRateTable[] = {
918647bbe4420ca487467318404127f52c567e346bAndreas Huber        96000, 88200, 64000, 48000, 44100, 32000,
928647bbe4420ca487467318404127f52c567e346bAndreas Huber        24000, 22050, 16000, 12000, 11025, 8000
938647bbe4420ca487467318404127f52c567e346bAndreas Huber    };
948647bbe4420ca487467318404127f52c567e346bAndreas Huber    const size_t kNumSampleRates =
958647bbe4420ca487467318404127f52c567e346bAndreas Huber        sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]);
968647bbe4420ca487467318404127f52c567e346bAndreas Huber
978647bbe4420ca487467318404127f52c567e346bAndreas Huber    *tableIndex = 0;
988647bbe4420ca487467318404127f52c567e346bAndreas Huber    for (size_t index = 0; index < kNumSampleRates; ++index) {
998647bbe4420ca487467318404127f52c567e346bAndreas Huber        if (sampleRate == kSampleRateTable[index]) {
1008647bbe4420ca487467318404127f52c567e346bAndreas Huber            *tableIndex = index;
1018647bbe4420ca487467318404127f52c567e346bAndreas Huber            return true;
1028647bbe4420ca487467318404127f52c567e346bAndreas Huber        }
1038647bbe4420ca487467318404127f52c567e346bAndreas Huber    }
1048647bbe4420ca487467318404127f52c567e346bAndreas Huber
1058647bbe4420ca487467318404127f52c567e346bAndreas Huber    return false;
1068647bbe4420ca487467318404127f52c567e346bAndreas Huber}
1078647bbe4420ca487467318404127f52c567e346bAndreas Huber
10862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber// static
1094dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas HuberAMPEG4ElementaryAssembler::AMPEG4ElementaryAssembler(
1104dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        const sp<AMessage> &notify, const AString &desc, const AString &params)
11162cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    : mNotifyMsg(notify),
1124dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber      mIsGeneric(false),
1134dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber      mParams(params),
1144dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber      mSizeLength(0),
1154dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber      mIndexLength(0),
1164dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber      mIndexDeltaLength(0),
1174dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber      mCTSDeltaLength(0),
1184dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber      mDTSDeltaLength(0),
1194dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber      mRandomAccessIndication(false),
1204dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber      mStreamStateIndication(0),
1214dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber      mAuxiliaryDataSizeLength(0),
1224dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber      mHasAUHeader(false),
1238647bbe4420ca487467318404127f52c567e346bAndreas Huber      mChannelConfig(0),
1248647bbe4420ca487467318404127f52c567e346bAndreas Huber      mSampleRateIndex(0),
12562cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber      mAccessUnitRTPTime(0),
12662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber      mNextExpectedSeqNoValid(false),
12762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber      mNextExpectedSeqNo(0),
12862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber      mAccessUnitDamaged(false) {
129dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber    mIsGeneric = !strncasecmp(desc.c_str(),"mpeg4-generic/", 14);
1304dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
1314dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    if (mIsGeneric) {
1324dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        AString value;
1334dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        CHECK(GetAttribute(params.c_str(), "mode", &value));
1344dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
1354dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        if (!GetIntegerAttribute(params.c_str(), "sizeLength", &mSizeLength)) {
1364dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            mSizeLength = 0;
1374dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        }
1384dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
1394dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        if (!GetIntegerAttribute(
1404dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    params.c_str(), "indexLength", &mIndexLength)) {
1414dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            mIndexLength = 0;
1424dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        }
1434dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
1444dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        if (!GetIntegerAttribute(
1454dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    params.c_str(), "indexDeltaLength", &mIndexDeltaLength)) {
1464dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            mIndexDeltaLength = 0;
1474dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        }
1484dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
1494dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        if (!GetIntegerAttribute(
1504dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    params.c_str(), "CTSDeltaLength", &mCTSDeltaLength)) {
1514dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            mCTSDeltaLength = 0;
1524dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        }
1534dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
1544dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        if (!GetIntegerAttribute(
1554dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    params.c_str(), "DTSDeltaLength", &mDTSDeltaLength)) {
1564dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            mDTSDeltaLength = 0;
1574dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        }
1584dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
1594dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        unsigned x;
1604dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        if (!GetIntegerAttribute(
1614dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    params.c_str(), "randomAccessIndication", &x)) {
1624dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            mRandomAccessIndication = false;
1634dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        } else {
1644dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            CHECK(x == 0 || x == 1);
1654dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            mRandomAccessIndication = (x != 0);
1664dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        }
1674dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
1684dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        if (!GetIntegerAttribute(
1694dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    params.c_str(), "streamStateIndication",
1704dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    &mStreamStateIndication)) {
1714dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            mStreamStateIndication = 0;
1724dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        }
1734dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
1744dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        if (!GetIntegerAttribute(
1754dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    params.c_str(), "auxiliaryDataSizeLength",
1764dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    &mAuxiliaryDataSizeLength)) {
1774dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            mAuxiliaryDataSizeLength = 0;
1784dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        }
1794dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
1804dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        mHasAUHeader =
1814dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            mSizeLength > 0
1824dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            || mIndexLength > 0
1834dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            || mIndexDeltaLength > 0
1844dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            || mCTSDeltaLength > 0
1854dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            || mDTSDeltaLength > 0
1864dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            || mRandomAccessIndication
1874dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            || mStreamStateIndication > 0;
1888647bbe4420ca487467318404127f52c567e346bAndreas Huber
1898647bbe4420ca487467318404127f52c567e346bAndreas Huber        int32_t sampleRate, numChannels;
1908647bbe4420ca487467318404127f52c567e346bAndreas Huber        ASessionDescription::ParseFormatDesc(
1918647bbe4420ca487467318404127f52c567e346bAndreas Huber                desc.c_str(), &sampleRate, &numChannels);
1928647bbe4420ca487467318404127f52c567e346bAndreas Huber
1938647bbe4420ca487467318404127f52c567e346bAndreas Huber        mChannelConfig = numChannels;
1948647bbe4420ca487467318404127f52c567e346bAndreas Huber        CHECK(GetSampleRateIndex(sampleRate, &mSampleRateIndex));
1954dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    }
19662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber}
19762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
19862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas HuberAMPEG4ElementaryAssembler::~AMPEG4ElementaryAssembler() {
19962cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber}
20062cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
2014dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huberstruct AUHeader {
2024dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    unsigned mSize;
2034dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    unsigned mSerial;
2044dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber};
2054dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
20662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas HuberARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket(
20762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber        const sp<ARTPSource> &source) {
20862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    List<sp<ABuffer> > *queue = source->queue();
20962cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
21062cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    if (queue->empty()) {
21162cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber        return NOT_ENOUGH_DATA;
21262cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    }
21362cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
21462cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    if (mNextExpectedSeqNoValid) {
21562cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber        List<sp<ABuffer> >::iterator it = queue->begin();
21662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber        while (it != queue->end()) {
21762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber            if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
21862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber                break;
21962cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber            }
22062cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
22162cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber            it = queue->erase(it);
22262cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber        }
22362cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
22462cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber        if (queue->empty()) {
22562cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber            return NOT_ENOUGH_DATA;
22662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber        }
22762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    }
22862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
22962cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    sp<ABuffer> buffer = *queue->begin();
23062cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
23162cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    if (!mNextExpectedSeqNoValid) {
23262cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber        mNextExpectedSeqNoValid = true;
23362cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber        mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
23462cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
2353856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Not the sequence number I expected");
23662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
23762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber        return WRONG_SEQUENCE_NUMBER;
23862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    }
23962cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
24062cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    uint32_t rtpTime;
24162cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
24262cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
24362cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) {
24462cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber        submitAccessUnit();
24562cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    }
24662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    mAccessUnitRTPTime = rtpTime;
24762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
2484dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    if (!mIsGeneric) {
2494dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        mPackets.push_back(buffer);
2504dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    } else {
2514dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        // hexdump(buffer->data(), buffer->size());
252dc9aa7e2cb903bb4ebfce558671a97088477bb6eChong Zhang        if (buffer->size() < 2) {
253dc9aa7e2cb903bb4ebfce558671a97088477bb6eChong Zhang            return MALFORMED_PACKET;
254dc9aa7e2cb903bb4ebfce558671a97088477bb6eChong Zhang        }
2554dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
2564dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        unsigned AU_headers_length = U16_AT(buffer->data());  // in bits
2574dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
258dc9aa7e2cb903bb4ebfce558671a97088477bb6eChong Zhang        if (buffer->size() < 2 + (AU_headers_length + 7) / 8) {
259dc9aa7e2cb903bb4ebfce558671a97088477bb6eChong Zhang            return MALFORMED_PACKET;
260dc9aa7e2cb903bb4ebfce558671a97088477bb6eChong Zhang        }
2614dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
2624dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        List<AUHeader> headers;
2634dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
2644dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        ABitReader bits(buffer->data() + 2, buffer->size() - 2);
2654dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        unsigned numBitsLeft = AU_headers_length;
2664dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
2674dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        unsigned AU_serial = 0;
2684dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        for (;;) {
2694dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            if (numBitsLeft < mSizeLength) { break; }
2704dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
2714dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            unsigned AU_size = bits.getBits(mSizeLength);
2724dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            numBitsLeft -= mSizeLength;
2734dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
2744dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            size_t n = headers.empty() ? mIndexLength : mIndexDeltaLength;
2754dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            if (numBitsLeft < n) { break; }
2764dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
2774dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            unsigned AU_index = bits.getBits(n);
2784dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            numBitsLeft -= n;
2794dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
2804dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            if (headers.empty()) {
2814dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                AU_serial = AU_index;
2824dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            } else {
2834dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                AU_serial += 1 + AU_index;
2844dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            }
2854dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
2864dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            if (mCTSDeltaLength > 0) {
2874dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                if (numBitsLeft < 1) {
2884dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    break;
2894dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                }
2904dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                --numBitsLeft;
2914dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                if (bits.getBits(1)) {
2924dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    if (numBitsLeft < mCTSDeltaLength) {
2934dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                        break;
2944dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    }
2954dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    bits.skipBits(mCTSDeltaLength);
2964dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    numBitsLeft -= mCTSDeltaLength;
2974dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                }
2984dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            }
2994dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
3004dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            if (mDTSDeltaLength > 0) {
3014dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                if (numBitsLeft < 1) {
3024dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    break;
3034dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                }
3044dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                --numBitsLeft;
3054dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                if (bits.getBits(1)) {
3064dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    if (numBitsLeft < mDTSDeltaLength) {
3074dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                        break;
3084dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    }
3094dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    bits.skipBits(mDTSDeltaLength);
3104dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    numBitsLeft -= mDTSDeltaLength;
3114dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                }
3124dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            }
3134dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
3144dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            if (mRandomAccessIndication) {
3154dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                if (numBitsLeft < 1) {
3164dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    break;
3174dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                }
3184dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                bits.skipBits(1);
3194dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                --numBitsLeft;
3204dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            }
3214dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
3224dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            if (mStreamStateIndication > 0) {
3234dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                if (numBitsLeft < mStreamStateIndication) {
3244dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                    break;
3254dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                }
3264dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber                bits.skipBits(mStreamStateIndication);
3274dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            }
3284dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
3294dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            AUHeader header;
3304dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            header.mSize = AU_size;
3314dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            header.mSerial = AU_serial;
3324dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            headers.push_back(header);
3334dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        }
3344dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
3354dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        size_t offset = 2 + (AU_headers_length + 7) / 8;
3364dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
3374dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        if (mAuxiliaryDataSizeLength > 0) {
3384dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            ABitReader bits(buffer->data() + offset, buffer->size() - offset);
3394dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
3404dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            unsigned auxSize = bits.getBits(mAuxiliaryDataSizeLength);
3414dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
3424dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            offset += (mAuxiliaryDataSizeLength + auxSize + 7) / 8;
3434dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        }
3444dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
3454dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        for (List<AUHeader>::iterator it = headers.begin();
3464dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber             it != headers.end(); ++it) {
3474dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            const AUHeader &header = *it;
3484dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
349dc9aa7e2cb903bb4ebfce558671a97088477bb6eChong Zhang            if (buffer->size() < offset + header.mSize) {
350dc9aa7e2cb903bb4ebfce558671a97088477bb6eChong Zhang                return MALFORMED_PACKET;
351dc9aa7e2cb903bb4ebfce558671a97088477bb6eChong Zhang            }
3524dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
3534dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            sp<ABuffer> accessUnit = new ABuffer(header.mSize);
3544dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            memcpy(accessUnit->data(), buffer->data() + offset, header.mSize);
3554dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
3564dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            offset += header.mSize;
3574dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber
3584dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            CopyTimes(accessUnit, buffer);
3594dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber            mPackets.push_back(accessUnit);
3604dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber        }
36180804f4e953d6c5f6ed0c3c8e004c4cce280f5c1Chong Zhang
36280804f4e953d6c5f6ed0c3c8e004c4cce280f5c1Chong Zhang        if (offset != buffer->size()) {
363cd8d9c6cfe5ca53f17be1ea8edac6b324e203f52Chih-Hung Hsieh            ALOGW("potentially malformed packet (offset %zu, size %zu)",
36480804f4e953d6c5f6ed0c3c8e004c4cce280f5c1Chong Zhang                    offset, buffer->size());
36580804f4e953d6c5f6ed0c3c8e004c4cce280f5c1Chong Zhang        }
3664dba3e90f211eb5f5af19b10c5d3fc8c967b0086Andreas Huber    }
36762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
36862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    queue->erase(queue->begin());
36962cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    ++mNextExpectedSeqNo;
37062cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
37162cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    return OK;
37262cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber}
37362cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
37462cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Hubervoid AMPEG4ElementaryAssembler::submitAccessUnit() {
37562cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    CHECK(!mPackets.empty());
37662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
377b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81Colin Cross    ALOGV("Access unit complete (%zu nal units)", mPackets.size());
37862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
3798647bbe4420ca487467318404127f52c567e346bAndreas Huber    sp<ABuffer> accessUnit;
38062cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
3818647bbe4420ca487467318404127f52c567e346bAndreas Huber    if (mIsGeneric) {
3828647bbe4420ca487467318404127f52c567e346bAndreas Huber        accessUnit = MakeADTSCompoundFromAACFrames(
3838647bbe4420ca487467318404127f52c567e346bAndreas Huber                OMX_AUDIO_AACObjectLC - 1,
3848647bbe4420ca487467318404127f52c567e346bAndreas Huber                mSampleRateIndex,
3858647bbe4420ca487467318404127f52c567e346bAndreas Huber                mChannelConfig,
3868647bbe4420ca487467318404127f52c567e346bAndreas Huber                mPackets);
3878647bbe4420ca487467318404127f52c567e346bAndreas Huber    } else {
3888647bbe4420ca487467318404127f52c567e346bAndreas Huber        accessUnit = MakeCompoundFromPackets(mPackets);
38962cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    }
39062cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
39162cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber#if 0
39262cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    printf(mAccessUnitDamaged ? "X" : ".");
39362cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    fflush(stdout);
39462cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber#endif
39562cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
39662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    if (mAccessUnitDamaged) {
39762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber        accessUnit->meta()->setInt32("damaged", true);
39862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    }
39962cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
40062cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    mPackets.clear();
40162cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    mAccessUnitDamaged = false;
40262cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
40362cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    sp<AMessage> msg = mNotifyMsg->dup();
4042d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    msg->setBuffer("access-unit", accessUnit);
40562cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    msg->post();
40662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber}
40762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
40862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas HuberARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::assembleMore(
40962cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber        const sp<ARTPSource> &source) {
41062cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    AssemblyStatus status = addPacket(source);
41162cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    if (status == MALFORMED_PACKET) {
412dc9aa7e2cb903bb4ebfce558671a97088477bb6eChong Zhang        ALOGI("access unit is damaged");
41362cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber        mAccessUnitDamaged = true;
41462cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    }
41562cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    return status;
41662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber}
41762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
41862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Hubervoid AMPEG4ElementaryAssembler::packetLost() {
41962cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    CHECK(mNextExpectedSeqNoValid);
4203856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("packetLost (expected %d)", mNextExpectedSeqNo);
42162cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
42262cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    ++mNextExpectedSeqNo;
42362cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
42462cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    mAccessUnitDamaged = true;
42562cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber}
42662cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
42762cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Hubervoid AMPEG4ElementaryAssembler::onByeReceived() {
42862cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    sp<AMessage> msg = mNotifyMsg->dup();
42962cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    msg->setInt32("eos", true);
43062cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber    msg->post();
43162cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber}
43262cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
43362cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber}  // namespace android
434