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> ¬ify, const sp<MetaData> ¶ms); 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> ¬ify, const sp<MetaData> ¶ms) { 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