10da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber/*
20da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber * Copyright (C) 2010 The Android Open Source Project
30da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber *
40da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
50da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber * you may not use this file except in compliance with the License.
60da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber * You may obtain a copy of the License at
70da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber *
80da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
90da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber *
100da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber * Unless required by applicable law or agreed to in writing, software
110da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
120da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber * See the License for the specific language governing permissions and
140da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber * limitations under the License.
150da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber */
160da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
170da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber//#define LOG_NDEBUG 0
180da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber#define LOG_TAG "MPEG2TSWriter"
190da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
20d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/MediaSource.h>
21d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/stagefright/foundation/ADebug.h>
220da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber#include <media/stagefright/foundation/hexdump.h>
230da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
240da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber#include <media/stagefright/foundation/AMessage.h>
25607612858f3afad1ade51a098aafa2a41523b5f7Dongwon Kang#include <media/stagefright/foundation/ByteUtils.h>
260da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber#include <media/stagefright/MPEG2TSWriter.h>
270da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber#include <media/stagefright/MediaBuffer.h>
280da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber#include <media/stagefright/MediaDefs.h>
290da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber#include <media/stagefright/MediaErrors.h>
300da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber#include <media/stagefright/MetaData.h>
31983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello#include <arpa/inet.h>
320da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
330da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber#include "include/ESDS.h"
340da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
350da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Hubernamespace android {
360da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
370da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huberstruct MPEG2TSWriter::SourceInfo : public AHandler {
38ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kang    explicit SourceInfo(const sp<MediaSource> &source);
390da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
408f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    void start(const sp<AMessage> &notify, const sp<MetaData> &params);
410da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    void stop();
420da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
430da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    unsigned streamType() const;
440da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    unsigned incrementContinuityCounter();
450da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
463a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    void readMore();
473a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
480da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    enum {
490da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        kNotifyStartFailed,
500da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        kNotifyBuffer,
510da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        kNotifyReachedEOS,
520da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    };
530da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
543a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    sp<ABuffer> lastAccessUnit();
553a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    int64_t lastAccessUnitTimeUs();
563a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    void setLastAccessUnit(const sp<ABuffer> &accessUnit);
573a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
583a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    void setEOSReceived();
593a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    bool eosReceived() const;
603a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
610da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huberprotected:
620da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    virtual void onMessageReceived(const sp<AMessage> &msg);
630da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
640da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    virtual ~SourceInfo();
650da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
660da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huberprivate:
670da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    enum {
680da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        kWhatStart = 'strt',
690da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        kWhatRead  = 'read',
700da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    };
710da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
72ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kang    sp<MediaSource> mSource;
730da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    sp<ALooper> mLooper;
740da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    sp<AMessage> mNotify;
750da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
7659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    sp<ABuffer> mAACCodecSpecificData;
7759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
788f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    sp<ABuffer> mBuffer;
790da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
803a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    sp<ABuffer> mLastAccessUnit;
813a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    bool mEOSReceived;
823a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
830da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    unsigned mStreamType;
840da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    unsigned mContinuityCounter;
850da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
860da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    void extractCodecSpecificData();
870da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
881889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang    void appendAACFrames(MediaBufferBase *buffer);
891889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang    void appendAVCFrame(MediaBufferBase *buffer);
900da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
910da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(SourceInfo);
920da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber};
930da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
94ba8128f9db82da66f28c6e6740d4721d80da954eDongwon KangMPEG2TSWriter::SourceInfo::SourceInfo(const sp<MediaSource> &source)
950da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    : mSource(source),
960da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber      mLooper(new ALooper),
973a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber      mEOSReceived(false),
980da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber      mStreamType(0),
990da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber      mContinuityCounter(0) {
1000da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mLooper->setName("MPEG2TSWriter source");
1010da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1020da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    sp<MetaData> meta = mSource->getFormat();
1030da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    const char *mime;
1040da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    CHECK(meta->findCString(kKeyMIMEType, &mime));
1050da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1060da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1070da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        mStreamType = 0x0f;
1080da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1090da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        mStreamType = 0x1b;
1100da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    } else {
1110da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        TRESPASS();
1120da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
1130da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
1140da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1150da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas HuberMPEG2TSWriter::SourceInfo::~SourceInfo() {
1160da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
1170da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1180da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huberunsigned MPEG2TSWriter::SourceInfo::streamType() const {
1190da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    return mStreamType;
1200da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
1210da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1220da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huberunsigned MPEG2TSWriter::SourceInfo::incrementContinuityCounter() {
1230da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    if (++mContinuityCounter == 16) {
1240da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        mContinuityCounter = 0;
1250da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
1260da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1270da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    return mContinuityCounter;
1280da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
1290da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1308f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuangvoid MPEG2TSWriter::SourceInfo::start(const sp<AMessage> &notify, const sp<MetaData> &params) {
1310da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mLooper->registerHandler(this);
1320da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mLooper->start();
1330da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mNotify = notify;
1340da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1358f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    sp<AMessage> msg = new AMessage(kWhatStart, this);
1368f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    msg->setObject("meta", params);
1378f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    msg->post();
1380da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
1390da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1400da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Hubervoid MPEG2TSWriter::SourceInfo::stop() {
1410da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mLooper->unregisterHandler(id());
1420da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mLooper->stop();
14359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
14459b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    mSource->stop();
1450da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
1460da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1470da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Hubervoid MPEG2TSWriter::SourceInfo::extractCodecSpecificData() {
1480da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    sp<MetaData> meta = mSource->getFormat();
1490da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1500da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    const char *mime;
1510da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    CHECK(meta->findCString(kKeyMIMEType, &mime));
1520da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
15359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
15459b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        uint32_t type;
15559b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        const void *data;
15659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        size_t size;
15759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        if (!meta->findData(kKeyESDS, &type, &data, &size)) {
15859b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber            // Codec specific data better be in the first data buffer.
15959b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber            return;
16059b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        }
16159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
16259b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        ESDS esds((const char *)data, size);
16359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        CHECK_EQ(esds.InitCheck(), (status_t)OK);
16459b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
16559b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        const uint8_t *codec_specific_data;
16659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        size_t codec_specific_data_size;
16759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        esds.getCodecSpecificInfo(
16859b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber                (const void **)&codec_specific_data, &codec_specific_data_size);
16959b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
17059b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        CHECK_GE(codec_specific_data_size, 2u);
17159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
17259b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        mAACCodecSpecificData = new ABuffer(codec_specific_data_size);
17359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
17459b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        memcpy(mAACCodecSpecificData->data(), codec_specific_data,
17559b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber               codec_specific_data_size);
17659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
1770da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        return;
1780da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
1790da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
18059b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
18159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        return;
18259b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    }
1830da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1840da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    uint32_t type;
1850da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    const void *data;
1860da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    size_t size;
18759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    if (!meta->findData(kKeyAVCC, &type, &data, &size)) {
18859b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        // Codec specific data better be part of the data stream then.
18959b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber        return;
19059b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    }
19159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
19259b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    sp<ABuffer> out = new ABuffer(1024);
19359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    out->setRange(0, 0);
1940da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1950da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    const uint8_t *ptr = (const uint8_t *)data;
1960da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1970da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    size_t numSeqParameterSets = ptr[5] & 31;
1980da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
1990da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    ptr += 6;
2000da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    size -= 6;
2010da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2020da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    for (size_t i = 0; i < numSeqParameterSets; ++i) {
2030da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        CHECK(size >= 2);
2040da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        size_t length = U16_AT(ptr);
2050da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2060da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        ptr += 2;
2070da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        size -= 2;
2080da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2090da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        CHECK(size >= length);
2100da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2110da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        CHECK_LE(out->size() + 4 + length, out->capacity());
2120da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        memcpy(out->data() + out->size(), "\x00\x00\x00\x01", 4);
2130da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        memcpy(out->data() + out->size() + 4, ptr, length);
2140da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        out->setRange(0, out->size() + length + 4);
2150da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2160da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        ptr += length;
2170da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        size -= length;
2180da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
2190da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2200da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    CHECK(size >= 1);
2210da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    size_t numPictureParameterSets = *ptr;
2220da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    ++ptr;
2230da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    --size;
2240da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2250da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    for (size_t i = 0; i < numPictureParameterSets; ++i) {
2260da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        CHECK(size >= 2);
2270da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        size_t length = U16_AT(ptr);
2280da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2290da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        ptr += 2;
2300da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        size -= 2;
2310da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2320da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        CHECK(size >= length);
2330da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2340da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        CHECK_LE(out->size() + 4 + length, out->capacity());
2350da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        memcpy(out->data() + out->size(), "\x00\x00\x00\x01", 4);
2360da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        memcpy(out->data() + out->size() + 4, ptr, length);
2370da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        out->setRange(0, out->size() + length + 4);
2380da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2390da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        ptr += length;
2400da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        size -= length;
2410da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
2420da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2430da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    out->meta()->setInt64("timeUs", 0ll);
2440da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2450da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    sp<AMessage> notify = mNotify->dup();
2460da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    notify->setInt32("what", kNotifyBuffer);
2472d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    notify->setBuffer("buffer", out);
2483a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    notify->setInt32("oob", true);
2490da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    notify->post();
2500da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
2510da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2521889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kangvoid MPEG2TSWriter::SourceInfo::appendAVCFrame(MediaBufferBase *buffer) {
2530da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    sp<AMessage> notify = mNotify->dup();
2540da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    notify->setInt32("what", kNotifyBuffer);
2550da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2568f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    if (mBuffer == NULL || buffer->range_length() > mBuffer->capacity()) {
2578f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang        mBuffer = new ABuffer(buffer->range_length());
2588f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    }
2598f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    mBuffer->setRange(0, 0);
2608f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang
2618f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    memcpy(mBuffer->data(),
2620da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber           (const uint8_t *)buffer->data()
2630da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            + buffer->range_offset(),
2640da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber           buffer->range_length());
2650da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2660da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    int64_t timeUs;
2673d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    CHECK(buffer->meta_data().findInt64(kKeyTime, &timeUs));
2688f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    mBuffer->meta()->setInt64("timeUs", timeUs);
2690da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2700da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    int32_t isSync;
2713d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    if (buffer->meta_data().findInt32(kKeyIsSyncFrame, &isSync)
2720da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            && isSync != 0) {
2738f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang        mBuffer->meta()->setInt32("isSync", true);
2740da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
2750da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2768f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    mBuffer->setRange(0, buffer->range_length());
2778f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang
2788f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    notify->setBuffer("buffer", mBuffer);
2790da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    notify->post();
2800da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
2810da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2821889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kangvoid MPEG2TSWriter::SourceInfo::appendAACFrames(MediaBufferBase *buffer) {
2838f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    sp<AMessage> notify = mNotify->dup();
2848f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    notify->setInt32("what", kNotifyBuffer);
2853a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
2868f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    if (mBuffer == NULL || 7 + buffer->range_length() > mBuffer->capacity()) {
2878f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang        mBuffer = new ABuffer(7 + buffer->range_length());
2880da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
2890da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2908f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    int64_t timeUs;
2913d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    CHECK(buffer->meta_data().findInt64(kKeyTime, &timeUs));
2920da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2938f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    mBuffer->meta()->setInt64("timeUs", timeUs);
2948f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    mBuffer->meta()->setInt32("isSync", true);
2950da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
2968f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    mBuffer->setRange(0, 0);
2970da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
29859b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    const uint8_t *codec_specific_data = mAACCodecSpecificData->data();
2990da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3000da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    unsigned profile = (codec_specific_data[0] >> 3) - 1;
3010da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3020da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    unsigned sampling_freq_index =
3030da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        ((codec_specific_data[0] & 7) << 1)
3040da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        | (codec_specific_data[1] >> 7);
3050da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3060da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    unsigned channel_configuration =
3070da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        (codec_specific_data[1] >> 3) & 0x0f;
3080da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3098f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    uint8_t *ptr = mBuffer->data() + mBuffer->size();
3100da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3110da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    const uint32_t aac_frame_length = buffer->range_length() + 7;
3120da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3130da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = 0xff;
3140da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = 0xf1;  // b11110001, ID=0, layer=0, protection_absent=1
3150da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3160da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ =
3170da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        profile << 6
3180da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        | sampling_freq_index << 2
3190da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        | ((channel_configuration >> 2) & 1);  // private_bit=0
3200da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3210da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // original_copy=0, home=0, copyright_id_bit=0, copyright_id_start=0
3220da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ =
3230da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        (channel_configuration & 3) << 6
3240da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        | aac_frame_length >> 11;
3250da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = (aac_frame_length >> 3) & 0xff;
3260da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = (aac_frame_length & 7) << 5;
3270da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3280da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // adts_buffer_fullness=0, number_of_raw_data_blocks_in_frame=0
3290da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = 0;
3300da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3310da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    memcpy(ptr,
3320da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber           (const uint8_t *)buffer->data() + buffer->range_offset(),
3330da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber           buffer->range_length());
3340da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3350da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    ptr += buffer->range_length();
3360da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3378f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    mBuffer->setRange(0, ptr - mBuffer->data());
3380da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3398f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang    notify->setBuffer("buffer", mBuffer);
3400da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    notify->post();
3413a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber}
3423a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
3433a1775247e26f274ef249442ef038ddf7217b68cAndreas Hubervoid MPEG2TSWriter::SourceInfo::readMore() {
3441d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatRead, this))->post();
3450da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
3460da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3470da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Hubervoid MPEG2TSWriter::SourceInfo::onMessageReceived(const sp<AMessage> &msg) {
3480da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    switch (msg->what()) {
3490da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        case kWhatStart:
3500da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        {
3518f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang            sp<RefBase> obj;
3528f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang            CHECK(msg->findObject("meta", &obj));
3538f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang            MetaData *params = static_cast<MetaData *>(obj.get());
3548f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang            status_t err = mSource->start(params);
3550da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            if (err != OK) {
3560da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                sp<AMessage> notify = mNotify->dup();
3570da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                notify->setInt32("what", kNotifyStartFailed);
3580da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                notify->post();
3590da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                break;
3600da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            }
3610da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3628f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang            // Extract CSD from config format.
3630da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            extractCodecSpecificData();
3640da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3653a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber            readMore();
3660da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            break;
3670da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        }
3680da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3690da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        case kWhatRead:
3700da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        {
3711889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang            MediaBufferBase *buffer;
3720da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            status_t err = mSource->read(&buffer);
3730da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3740da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            if (err != OK && err != INFO_FORMAT_CHANGED) {
3750da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                sp<AMessage> notify = mNotify->dup();
3760da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                notify->setInt32("what", kNotifyReachedEOS);
3770da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                notify->setInt32("status", err);
3780da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                notify->post();
3790da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                break;
3800da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            }
3810da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
3820da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            if (err == OK) {
38359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber                if (mStreamType == 0x0f && mAACCodecSpecificData == NULL) {
3848f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang                    // The first audio buffer must contain CSD if not received yet.
38559b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber                    CHECK_GE(buffer->range_length(), 2u);
38659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber                    mAACCodecSpecificData = new ABuffer(buffer->range_length());
38759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
38859b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber                    memcpy(mAACCodecSpecificData->data(),
38959b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber                           (const uint8_t *)buffer->data()
39059b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber                            + buffer->range_offset(),
39159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber                           buffer->range_length());
3928f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang                    readMore();
39359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber                } else if (buffer->range_length() > 0) {
3940da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                    if (mStreamType == 0x0f) {
3958f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang                        appendAACFrames(buffer);
3960da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                    } else {
3978f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang                        appendAVCFrame(buffer);
3980da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                    }
39902d18453d54a05c275c03b72a8290f3c9a964446Martin Storsjo                } else {
40002d18453d54a05c275c03b72a8290f3c9a964446Martin Storsjo                    readMore();
4010da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                }
4020da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
4030da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                buffer->release();
4040da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                buffer = NULL;
4050da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            }
4060da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
4073a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber            // Do not read more data until told to.
4080da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            break;
4090da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        }
4100da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
4110da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        default:
4120da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            TRESPASS();
4130da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
4140da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
4150da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
4163a1775247e26f274ef249442ef038ddf7217b68cAndreas Hubersp<ABuffer> MPEG2TSWriter::SourceInfo::lastAccessUnit() {
4173a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    return mLastAccessUnit;
4183a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber}
4193a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
4203a1775247e26f274ef249442ef038ddf7217b68cAndreas Hubervoid MPEG2TSWriter::SourceInfo::setLastAccessUnit(
4213a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber        const sp<ABuffer> &accessUnit) {
4223a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    mLastAccessUnit = accessUnit;
4233a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber}
4243a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
4253a1775247e26f274ef249442ef038ddf7217b68cAndreas Huberint64_t MPEG2TSWriter::SourceInfo::lastAccessUnitTimeUs() {
4263a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    if (mLastAccessUnit == NULL) {
4273a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber        return -1;
4283a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    }
4293a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
4303a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    int64_t timeUs;
4313a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    CHECK(mLastAccessUnit->meta()->findInt64("timeUs", &timeUs));
4323a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    return timeUs;
4333a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber}
4343a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
4353a1775247e26f274ef249442ef038ddf7217b68cAndreas Hubervoid MPEG2TSWriter::SourceInfo::setEOSReceived() {
4363a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    CHECK(!mEOSReceived);
4373a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    mEOSReceived = true;
4383a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber}
4393a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
4403a1775247e26f274ef249442ef038ddf7217b68cAndreas Huberbool MPEG2TSWriter::SourceInfo::eosReceived() const {
4413a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber    return mEOSReceived;
4423a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber}
4433a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
4440da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber////////////////////////////////////////////////////////////////////////////////
4450da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
44659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas HuberMPEG2TSWriter::MPEG2TSWriter(int fd)
447674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFile(fdopen(dup(fd), "wb")),
4483e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber      mWriteCookie(NULL),
4493e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber      mWriteFunc(NULL),
45059b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber      mStarted(false),
45159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber      mNumSourcesDone(0),
45259b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber      mNumTSPacketsWritten(0),
453d4e5af6bc0a012e8d43975ca8b5627631333920dPaul Fariello      mNumTSPacketsBeforeMeta(0),
454d4e5af6bc0a012e8d43975ca8b5627631333920dPaul Fariello      mPATContinuityCounter(0),
455d4e5af6bc0a012e8d43975ca8b5627631333920dPaul Fariello      mPMTContinuityCounter(0) {
45659b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    init();
45759b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber}
45859b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
4593e1763ecdf14769a534f75e94a56785f63174b47Andreas HuberMPEG2TSWriter::MPEG2TSWriter(
4603e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber        void *cookie,
4613e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber        ssize_t (*write)(void *cookie, const void *data, size_t size))
4623e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber    : mFile(NULL),
4633e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber      mWriteCookie(cookie),
4643e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber      mWriteFunc(write),
4650da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber      mStarted(false),
4660da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber      mNumSourcesDone(0),
4670da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber      mNumTSPacketsWritten(0),
468d4e5af6bc0a012e8d43975ca8b5627631333920dPaul Fariello      mNumTSPacketsBeforeMeta(0),
469d4e5af6bc0a012e8d43975ca8b5627631333920dPaul Fariello      mPATContinuityCounter(0),
470d4e5af6bc0a012e8d43975ca8b5627631333920dPaul Fariello      mPMTContinuityCounter(0) {
47159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    init();
47259b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber}
47359b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
47459b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Hubervoid MPEG2TSWriter::init() {
4753e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber    CHECK(mFile != NULL || mWriteFunc != NULL);
4760da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
477983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    initCrcTable();
478983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello
4790da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mLooper = new ALooper;
4800da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mLooper->setName("MPEG2TSWriter");
4810da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
4820da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mReflector = new AHandlerReflector<MPEG2TSWriter>(this);
4830da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
4840da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mLooper->registerHandler(mReflector);
4850da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mLooper->start();
4860da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
4870da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
4880da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas HuberMPEG2TSWriter::~MPEG2TSWriter() {
48959b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    if (mStarted) {
4908bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dong        reset();
49159b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber    }
49259b7dc39ea8332d3418a599e51447d7edb612ac4Andreas Huber
4930da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mLooper->unregisterHandler(mReflector->id());
4940da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mLooper->stop();
4950da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
4963e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber    if (mFile != NULL) {
4973e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber        fclose(mFile);
4983e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber        mFile = NULL;
4993e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber    }
5000da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
5010da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
502ba8128f9db82da66f28c6e6740d4721d80da954eDongwon Kangstatus_t MPEG2TSWriter::addSource(const sp<MediaSource> &source) {
5030da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    CHECK(!mStarted);
5040da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5050da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    sp<MetaData> meta = source->getFormat();
5060da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    const char *mime;
5070da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    CHECK(meta->findCString(kKeyMIMEType, &mime));
5080da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5090da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
5100da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
5110da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        return ERROR_UNSUPPORTED;
5120da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
5130da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5140da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    sp<SourceInfo> info = new SourceInfo(source);
5150da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5160da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mSources.push(info);
5170da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5180da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    return OK;
5190da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
5200da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5218f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuangstatus_t MPEG2TSWriter::start(MetaData *param ) {
5220da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    CHECK(!mStarted);
5230da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5240da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mStarted = true;
5250da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mNumSourcesDone = 0;
5260da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mNumTSPacketsWritten = 0;
5270da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mNumTSPacketsBeforeMeta = 0;
5280da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5290da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    for (size_t i = 0; i < mSources.size(); ++i) {
5300da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        sp<AMessage> notify =
5311d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar            new AMessage(kWhatSourceNotify, mReflector);
5320da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5330da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        notify->setInt32("source-index", i);
5340da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5358f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang        mSources.editItemAt(i)->start(notify, param);
5360da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
5370da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5380da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    return OK;
5390da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
5400da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5418bcc65c753085fe3328592cceda0cf0e8f8b0a45James Dongstatus_t MPEG2TSWriter::reset() {
5420da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    CHECK(mStarted);
5430da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5440da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    for (size_t i = 0; i < mSources.size(); ++i) {
5450da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        mSources.editItemAt(i)->stop();
5460da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
5470da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    mStarted = false;
5480da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5490da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    return OK;
5500da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
5510da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5520da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huberstatus_t MPEG2TSWriter::pause() {
5530da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    CHECK(mStarted);
5540da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5550da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    return OK;
5560da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
5570da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5580da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huberbool MPEG2TSWriter::reachedEOS() {
5590da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    return !mStarted || (mNumSourcesDone == mSources.size() ? true : false);
5600da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
5610da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
56284333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG2TSWriter::dump(
56384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        int /* fd */, const Vector<String16> & /* args */) {
5640da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    return OK;
5650da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
5660da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5670da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Hubervoid MPEG2TSWriter::onMessageReceived(const sp<AMessage> &msg) {
5680da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    switch (msg->what()) {
5690da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        case kWhatSourceNotify:
5700da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        {
5710da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            int32_t sourceIndex;
5720da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            CHECK(msg->findInt32("source-index", &sourceIndex));
5738f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang            sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
5740da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5750da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            int32_t what;
5760da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            CHECK(msg->findInt32("what", &what));
5770da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
5780da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            if (what == SourceInfo::kNotifyReachedEOS
5790da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                    || what == SourceInfo::kNotifyStartFailed) {
5803a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                source->setEOSReceived();
5813a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
5823a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                sp<ABuffer> buffer = source->lastAccessUnit();
5833a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                source->setLastAccessUnit(NULL);
5843a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
5853a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                if (buffer != NULL) {
5863a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    writeTS();
5873a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    writeAccessUnit(sourceIndex, buffer);
5883a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                }
5893a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
5900da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                ++mNumSourcesDone;
5910da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            } else if (what == SourceInfo::kNotifyBuffer) {
5922d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber                sp<ABuffer> buffer;
5932d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber                CHECK(msg->findBuffer("buffer", &buffer));
5948f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang                CHECK(source->lastAccessUnit() == NULL);
5953a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
5963a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                int32_t oob;
5973a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                if (msg->findInt32("oob", &oob) && oob) {
5983a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    // This is codec specific data delivered out of band.
5993a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    // It can be written out immediately.
6003a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    writeTS();
6013a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    writeAccessUnit(sourceIndex, buffer);
6023a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    break;
6033a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                }
6043a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
6053a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                // We don't just write out data as we receive it from
6063a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                // the various sources. That would essentially write them
6073a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                // out in random order (as the thread scheduler determines
6083a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                // how the messages are dispatched).
6093a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                // Instead we gather an access unit for all tracks and
6103a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                // write out the one with the smallest timestamp, then
6113a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                // request more data for the written out track.
6123a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                // Rinse, repeat.
6133a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                // If we don't have data on any track we don't write
6143a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                // anything just yet.
6153a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                source->setLastAccessUnit(buffer);
6163a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
6173856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("lastAccessUnitTimeUs[%d] = %.2f secs",
6188f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang                    sourceIndex, source->lastAccessUnitTimeUs() / 1E6);
6193a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                int64_t minTimeUs = -1;
6203a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                size_t minIndex = 0;
6213a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
6223a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                for (size_t i = 0; i < mSources.size(); ++i) {
6233a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    const sp<SourceInfo> &source = mSources.editItemAt(i);
6243a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
6253a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    if (source->eosReceived()) {
6263a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                        continue;
6273a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    }
6283a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
6293a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    int64_t timeUs = source->lastAccessUnitTimeUs();
6303a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    if (timeUs < 0) {
6313a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                        minTimeUs = -1;
6323a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                        break;
6333a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    } else if (minTimeUs < 0 || timeUs < minTimeUs) {
6343a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                        minTimeUs = timeUs;
6353a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                        minIndex = i;
6363a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    }
6373a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                }
6383a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
6393a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                if (minTimeUs < 0) {
6408f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang                    ALOGV("not all tracks have valid data.");
6413a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                    break;
6423a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                }
6433a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
644a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                ALOGV("writing access unit at time %.2f secs (index %zu)",
6458f889be4754d40f39c9377b055988f58f3ed64a8Hangyu Kuang                    minTimeUs / 1E6, minIndex);
6463a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
6473a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                source = mSources.editItemAt(minIndex);
6483a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                buffer = source->lastAccessUnit();
6493a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                source->setLastAccessUnit(NULL);
6503a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber
6510da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber                writeTS();
6523a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                writeAccessUnit(minIndex, buffer);
6530da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
6543a1775247e26f274ef249442ef038ddf7217b68cAndreas Huber                source->readMore();
6550da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            }
6560da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            break;
6570da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        }
6580da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
6590da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        default:
6600da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            TRESPASS();
6610da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
6620da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
6630da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
6640da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Hubervoid MPEG2TSWriter::writeProgramAssociationTable() {
6650da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // 0x47
6660da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // transport_error_indicator = b0
6670da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // payload_unit_start_indicator = b1
6680da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // transport_priority = b0
6690da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // PID = b0000000000000 (13 bits)
6700da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // transport_scrambling_control = b00
6710da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // adaptation_field_control = b01 (no adaptation field, payload only)
6720da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // continuity_counter = b????
6730da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // skip = 0x00
6740da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // --- payload follows
6750da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // table_id = 0x00
6760da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // section_syntax_indicator = b1
6770da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // must_be_zero = b0
6780da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // reserved = b11
6790da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // section_length = 0x00d
6800da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // transport_stream_id = 0x0000
6810da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // reserved = b11
6820da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // version_number = b00001
6830da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // current_next_indicator = b1
6840da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // section_number = 0x00
6850da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // last_section_number = 0x00
6860da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    //   one program follows:
6870da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    //   program_number = 0x0001
6880da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    //   reserved = b111
6890da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    //   program_map_PID = 0x01e0 (13 bits!)
6900da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // CRC = 0x????????
6910da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
6920da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    static const uint8_t kData[] = {
6930da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        0x47,
6940da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        0x40, 0x00, 0x10, 0x00,  // b0100 0000 0000 0000 0001 ???? 0000 0000
6950da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        0x00, 0xb0, 0x0d, 0x00,  // b0000 0000 1011 0000 0000 1101 0000 0000
6960da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        0x00, 0xc3, 0x00, 0x00,  // b0000 0000 1100 0011 0000 0000 0000 0000
6970da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        0x00, 0x01, 0xe1, 0xe0,  // b0000 0000 0000 0001 1110 0001 1110 0000
6980da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        0x00, 0x00, 0x00, 0x00   // b???? ???? ???? ???? ???? ???? ???? ????
6990da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    };
7000da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
7010da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    sp<ABuffer> buffer = new ABuffer(188);
702983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    memset(buffer->data(), 0xff, buffer->size());
7030da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    memcpy(buffer->data(), kData, sizeof(kData));
7040da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
705d4e5af6bc0a012e8d43975ca8b5627631333920dPaul Fariello    if (++mPATContinuityCounter == 16) {
706d4e5af6bc0a012e8d43975ca8b5627631333920dPaul Fariello        mPATContinuityCounter = 0;
707d4e5af6bc0a012e8d43975ca8b5627631333920dPaul Fariello    }
708d4e5af6bc0a012e8d43975ca8b5627631333920dPaul Fariello    buffer->data()[3] |= mPATContinuityCounter;
7090da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
710983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    uint32_t crc = htonl(crc32(&buffer->data()[5], 12));
711983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    memcpy(&buffer->data()[17], &crc, sizeof(crc));
712983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello
7136f51c153ea5e4187a313e47ac8bad9a1a999d4e1Colin Cross    CHECK_EQ(internalWrite(buffer->data(), buffer->size()), (ssize_t)buffer->size());
7140da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
7150da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
7160da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Hubervoid MPEG2TSWriter::writeProgramMap() {
7170da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // 0x47
7180da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // transport_error_indicator = b0
7190da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // payload_unit_start_indicator = b1
7200da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // transport_priority = b0
7210da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // PID = b0 0001 1110 0000 (13 bits) [0x1e0]
7220da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // transport_scrambling_control = b00
7230da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // adaptation_field_control = b01 (no adaptation field, payload only)
7240da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // continuity_counter = b????
7250da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // skip = 0x00
7260da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // -- payload follows
7270da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // table_id = 0x02
7280da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // section_syntax_indicator = b1
7290da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // must_be_zero = b0
7300da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // reserved = b11
7310da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // section_length = 0x???
7320da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // program_number = 0x0001
7330da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // reserved = b11
7340da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // version_number = b00001
7350da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // current_next_indicator = b1
7360da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // section_number = 0x00
7370da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // last_section_number = 0x00
7380da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // reserved = b111
7390da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // PCR_PID = b? ???? ???? ???? (13 bits)
7400da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // reserved = b1111
7410da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // program_info_length = 0x000
7420da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    //   one or more elementary stream descriptions follow:
7430da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    //   stream_type = 0x??
7440da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    //   reserved = b111
7450da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    //   elementary_PID = b? ???? ???? ???? (13 bits)
7460da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    //   reserved = b1111
7470da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    //   ES_info_length = 0x000
7480da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // CRC = 0x????????
7490da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
7500da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    static const uint8_t kData[] = {
7510da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        0x47,
7520da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        0x41, 0xe0, 0x10, 0x00,  // b0100 0001 1110 0000 0001 ???? 0000 0000
7530da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        0x02, 0xb0, 0x00, 0x00,  // b0000 0010 1011 ???? ???? ???? 0000 0000
7540da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        0x01, 0xc3, 0x00, 0x00,  // b0000 0001 1100 0011 0000 0000 0000 0000
7550da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        0xe0, 0x00, 0xf0, 0x00   // b111? ???? ???? ???? 1111 0000 0000 0000
7560da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    };
7570da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
7580da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    sp<ABuffer> buffer = new ABuffer(188);
759983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    memset(buffer->data(), 0xff, buffer->size());
7600da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    memcpy(buffer->data(), kData, sizeof(kData));
7610da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
762d4e5af6bc0a012e8d43975ca8b5627631333920dPaul Fariello    if (++mPMTContinuityCounter == 16) {
763d4e5af6bc0a012e8d43975ca8b5627631333920dPaul Fariello        mPMTContinuityCounter = 0;
764d4e5af6bc0a012e8d43975ca8b5627631333920dPaul Fariello    }
765d4e5af6bc0a012e8d43975ca8b5627631333920dPaul Fariello    buffer->data()[3] |= mPMTContinuityCounter;
7660da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
7670da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    size_t section_length = 5 * mSources.size() + 4 + 9;
7680da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    buffer->data()[6] |= section_length >> 8;
7690da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    buffer->data()[7] = section_length & 0xff;
7700da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
7710da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    static const unsigned kPCR_PID = 0x1e1;
7720da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    buffer->data()[13] |= (kPCR_PID >> 8) & 0x1f;
7730da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    buffer->data()[14] = kPCR_PID & 0xff;
7740da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
7750da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    uint8_t *ptr = &buffer->data()[sizeof(kData)];
7760da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    for (size_t i = 0; i < mSources.size(); ++i) {
7770da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        *ptr++ = mSources.editItemAt(i)->streamType();
7780da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
7790da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        const unsigned ES_PID = 0x1e0 + i + 1;
7800da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        *ptr++ = 0xe0 | (ES_PID >> 8);
7810da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        *ptr++ = ES_PID & 0xff;
7820da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        *ptr++ = 0xf0;
7830da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        *ptr++ = 0x00;
7840da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
7850da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
786983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    uint32_t crc = htonl(crc32(&buffer->data()[5], 12+mSources.size()*5));
787983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    memcpy(&buffer->data()[17+mSources.size()*5], &crc, sizeof(crc));
7880da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
7896f51c153ea5e4187a313e47ac8bad9a1a999d4e1Colin Cross    CHECK_EQ(internalWrite(buffer->data(), buffer->size()), (ssize_t)buffer->size());
7900da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
7910da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
7920da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Hubervoid MPEG2TSWriter::writeAccessUnit(
7930da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        int32_t sourceIndex, const sp<ABuffer> &accessUnit) {
7940da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // 0x47
7950da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // transport_error_indicator = b0
7960da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // payload_unit_start_indicator = b1
7970da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // transport_priority = b0
7980da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
7990da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // transport_scrambling_control = b00
80099b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello    // adaptation_field_control = b??
8010da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // continuity_counter = b????
8020da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // -- payload follows
8030da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // packet_startcode_prefix = 0x000001
8040da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // stream_id = 0x?? (0xe0 for avc video, 0xc0 for aac audio)
8050da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // PES_packet_length = 0x????
8060da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // reserved = b10
8070da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // PES_scrambling_control = b00
8080da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // PES_priority = b0
8090da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // data_alignment_indicator = b1
8100da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // copyright = b0
8110da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // original_or_copy = b0
8120da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // PTS_DTS_flags = b10  (PTS only)
8130da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // ESCR_flag = b0
8140da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // ES_rate_flag = b0
8150da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // DSM_trick_mode_flag = b0
8160da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // additional_copy_info_flag = b0
8170da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // PES_CRC_flag = b0
8180da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // PES_extension_flag = b0
8190da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // PES_header_data_length = 0x05
8200da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // reserved = b0010 (PTS)
8210da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // PTS[32..30] = b???
8220da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // reserved = b1
8230da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // PTS[29..15] = b??? ???? ???? ???? (15 bits)
8240da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // reserved = b1
8250da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // PTS[14..0] = b??? ???? ???? ???? (15 bits)
8260da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // reserved = b1
8270da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // the first fragment of "buffer" follows
8280da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
8290da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    sp<ABuffer> buffer = new ABuffer(188);
83099b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello    memset(buffer->data(), 0xff, buffer->size());
8310da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
8320da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    const unsigned PID = 0x1e0 + sourceIndex + 1;
8330da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
8340da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    const unsigned continuity_counter =
8350da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        mSources.editItemAt(sourceIndex)->incrementContinuityCounter();
8360da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
8370da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // XXX if there are multiple streams of a kind (more than 1 audio or
8380da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    // more than 1 video) they need distinct stream_ids.
8390da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    const unsigned stream_id =
8400da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        mSources.editItemAt(sourceIndex)->streamType() == 0x0f ? 0xc0 : 0xe0;
8410da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
8420da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    int64_t timeUs;
8430da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
8440da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
8450da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    uint32_t PTS = (timeUs * 9ll) / 100ll;
8460da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
8470da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    size_t PES_packet_length = accessUnit->size() + 8;
84899b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello    bool padding = (accessUnit->size() < (188 - 18));
8490da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
850acc82a3bad22af17008a839d993e3bd7a5d9b5afAndreas Huber    if (PES_packet_length >= 65536) {
851acc82a3bad22af17008a839d993e3bd7a5d9b5afAndreas Huber        // This really should only happen for video.
852acc82a3bad22af17008a839d993e3bd7a5d9b5afAndreas Huber        CHECK_EQ(stream_id, 0xe0u);
853acc82a3bad22af17008a839d993e3bd7a5d9b5afAndreas Huber
854acc82a3bad22af17008a839d993e3bd7a5d9b5afAndreas Huber        // It's valid to set this to 0 for video according to the specs.
855acc82a3bad22af17008a839d993e3bd7a5d9b5afAndreas Huber        PES_packet_length = 0;
856acc82a3bad22af17008a839d993e3bd7a5d9b5afAndreas Huber    }
857acc82a3bad22af17008a839d993e3bd7a5d9b5afAndreas Huber
8580da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    uint8_t *ptr = buffer->data();
8590da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = 0x47;
8600da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = 0x40 | (PID >> 8);
8610da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = PID & 0xff;
86299b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello    *ptr++ = (padding ? 0x30 : 0x10) | continuity_counter;
86399b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello    if (padding) {
86499b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello        int paddingSize = 188 - accessUnit->size() - 18;
86599b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello        *ptr++ = paddingSize - 1;
86699b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello        if (paddingSize >= 2) {
86799b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello            *ptr++ = 0x00;
86899b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello            ptr += paddingSize - 2;
86999b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello        }
87099b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello    }
8710da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = 0x00;
8720da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = 0x00;
8730da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = 0x01;
8740da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = stream_id;
8750da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = PES_packet_length >> 8;
8760da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = PES_packet_length & 0xff;
8770da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = 0x84;
8780da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = 0x80;
8790da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = 0x05;
8800da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = 0x20 | (((PTS >> 30) & 7) << 1) | 1;
8810da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = (PTS >> 22) & 0xff;
8820da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = (((PTS >> 15) & 0x7f) << 1) | 1;
8830da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = (PTS >> 7) & 0xff;
8840da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    *ptr++ = ((PTS & 0x7f) << 1) | 1;
8850da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
8860da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    size_t sizeLeft = buffer->data() + buffer->size() - ptr;
8870da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    size_t copy = accessUnit->size();
8880da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    if (copy > sizeLeft) {
8890da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        copy = sizeLeft;
8900da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
8910da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
8920da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    memcpy(ptr, accessUnit->data(), copy);
8930da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
8946f51c153ea5e4187a313e47ac8bad9a1a999d4e1Colin Cross    CHECK_EQ(internalWrite(buffer->data(), buffer->size()), (ssize_t)buffer->size());
8950da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
8960da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    size_t offset = copy;
8970da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    while (offset < accessUnit->size()) {
898c867a50ec5317e74602798e2e8435cde313b91e9Martin Storsjo        bool lastAccessUnit = ((accessUnit->size() - offset) < 184);
8990da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        // for subsequent fragments of "buffer":
9000da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        // 0x47
9010da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        // transport_error_indicator = b0
9020da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        // payload_unit_start_indicator = b0
9030da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        // transport_priority = b0
9040da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
9050da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        // transport_scrambling_control = b00
90699b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello        // adaptation_field_control = b??
9070da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        // continuity_counter = b????
9080da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        // the fragment of "buffer" follows.
9090da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
91099b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello        memset(buffer->data(), 0xff, buffer->size());
9110da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
9120da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        const unsigned continuity_counter =
9130da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            mSources.editItemAt(sourceIndex)->incrementContinuityCounter();
9140da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
9150da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        ptr = buffer->data();
9160da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        *ptr++ = 0x47;
9170da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        *ptr++ = 0x00 | (PID >> 8);
9180da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        *ptr++ = PID & 0xff;
91999b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello        *ptr++ = (lastAccessUnit ? 0x30 : 0x10) | continuity_counter;
92099b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello
92199b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello        if (lastAccessUnit) {
92299b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello            // Pad packet using an adaptation field
92399b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello            // Adaptation header all to 0 execpt size
92499b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello            uint8_t paddingSize = (uint8_t)184 - (accessUnit->size() - offset);
92599b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello            *ptr++ = paddingSize - 1;
92699b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello            if (paddingSize >= 2) {
92799b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello                *ptr++ = 0x00;
92899b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello                ptr += paddingSize - 2;
92999b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello            }
93099b99df476b1bfb49da74fda9d6960d82b5ffd10Paul Fariello        }
9310da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
9320da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        size_t sizeLeft = buffer->data() + buffer->size() - ptr;
9330da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        size_t copy = accessUnit->size() - offset;
9340da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        if (copy > sizeLeft) {
9350da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber            copy = sizeLeft;
9360da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        }
9370da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
9380da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        memcpy(ptr, accessUnit->data() + offset, copy);
9393e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber        CHECK_EQ(internalWrite(buffer->data(), buffer->size()),
9406f51c153ea5e4187a313e47ac8bad9a1a999d4e1Colin Cross                 (ssize_t)buffer->size());
9410da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
9420da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        offset += copy;
9430da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
9440da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
9450da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
9460da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Hubervoid MPEG2TSWriter::writeTS() {
9470da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    if (mNumTSPacketsWritten >= mNumTSPacketsBeforeMeta) {
9480da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        writeProgramAssociationTable();
9490da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        writeProgramMap();
9500da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
9510da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber        mNumTSPacketsBeforeMeta = mNumTSPacketsWritten + 2500;
9520da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber    }
9530da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}
9540da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
955983995747ed3adaf25035c433df1ccbaa056a898Paul Fariellovoid MPEG2TSWriter::initCrcTable() {
956983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    uint32_t poly = 0x04C11DB7;
957983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello
958983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    for (int i = 0; i < 256; i++) {
959983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello        uint32_t crc = i << 24;
960983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello        for (int j = 0; j < 8; j++) {
961983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello            crc = (crc << 1) ^ ((crc & 0x80000000) ? (poly) : 0);
962983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello        }
963983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello        mCrcTable[i] = crc;
964983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    }
965983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello}
966983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello
967983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello/**
968983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello * Compute CRC32 checksum for buffer starting at offset start and for length
969983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello * bytes.
970983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello */
971983995747ed3adaf25035c433df1ccbaa056a898Paul Fariellouint32_t MPEG2TSWriter::crc32(const uint8_t *p_start, size_t length) {
972983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    uint32_t crc = 0xFFFFFFFF;
973983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    const uint8_t *p;
974983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello
975983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    for (p = p_start; p < p_start + length; p++) {
976983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello        crc = (crc << 8) ^ mCrcTable[((crc >> 24) ^ *p) & 0xFF];
977983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    }
978983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello
979983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello    return crc;
980983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello}
981983995747ed3adaf25035c433df1ccbaa056a898Paul Fariello
9823e1763ecdf14769a534f75e94a56785f63174b47Andreas Huberssize_t MPEG2TSWriter::internalWrite(const void *data, size_t size) {
9833e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber    if (mFile != NULL) {
9843e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber        return fwrite(data, 1, size, mFile);
9853e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber    }
9863e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber
9873e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber    return (*mWriteFunc)(mWriteCookie, data, size);
9883e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber}
9893e1763ecdf14769a534f75e94a56785f63174b47Andreas Huber
9900da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber}  // namespace android
9910da4dab0a45a2bc1d95cbc6ef6a4850ed2569584Andreas Huber
992