blob: c9ed5bb4663e31806e7f5b4b3040ab87344f3c97 [file] [log] [blame]
Andreas Huber0da4dab2010-09-27 12:04:43 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "MPEG2TSWriter"
19#include <media/stagefright/foundation/ADebug.h>
20
21#include <media/stagefright/foundation/hexdump.h>
22#include <media/stagefright/foundation/ABuffer.h>
23#include <media/stagefright/foundation/AMessage.h>
24#include <media/stagefright/MPEG2TSWriter.h>
25#include <media/stagefright/MediaBuffer.h>
26#include <media/stagefright/MediaDefs.h>
27#include <media/stagefright/MediaErrors.h>
28#include <media/stagefright/MediaSource.h>
29#include <media/stagefright/MetaData.h>
30#include <media/stagefright/Utils.h>
Paul Fariello98399572012-01-23 17:21:33 +010031#include <arpa/inet.h>
Andreas Huber0da4dab2010-09-27 12:04:43 -070032
33#include "include/ESDS.h"
34
35namespace android {
36
37struct MPEG2TSWriter::SourceInfo : public AHandler {
38 SourceInfo(const sp<MediaSource> &source);
39
40 void start(const sp<AMessage> &notify);
41 void stop();
42
43 unsigned streamType() const;
44 unsigned incrementContinuityCounter();
45
Andreas Huber3a177522010-12-10 15:08:23 -080046 void readMore();
47
Andreas Huber0da4dab2010-09-27 12:04:43 -070048 enum {
49 kNotifyStartFailed,
50 kNotifyBuffer,
51 kNotifyReachedEOS,
52 };
53
Andreas Huber3a177522010-12-10 15:08:23 -080054 sp<ABuffer> lastAccessUnit();
55 int64_t lastAccessUnitTimeUs();
56 void setLastAccessUnit(const sp<ABuffer> &accessUnit);
57
58 void setEOSReceived();
59 bool eosReceived() const;
60
Andreas Huber0da4dab2010-09-27 12:04:43 -070061protected:
62 virtual void onMessageReceived(const sp<AMessage> &msg);
63
64 virtual ~SourceInfo();
65
66private:
67 enum {
68 kWhatStart = 'strt',
69 kWhatRead = 'read',
70 };
71
72 sp<MediaSource> mSource;
73 sp<ALooper> mLooper;
74 sp<AMessage> mNotify;
75
Andreas Huber59b7dc32010-10-12 14:17:45 -070076 sp<ABuffer> mAACCodecSpecificData;
77
Andreas Huber0da4dab2010-09-27 12:04:43 -070078 sp<ABuffer> mAACBuffer;
79
Andreas Huber3a177522010-12-10 15:08:23 -080080 sp<ABuffer> mLastAccessUnit;
81 bool mEOSReceived;
82
Andreas Huber0da4dab2010-09-27 12:04:43 -070083 unsigned mStreamType;
84 unsigned mContinuityCounter;
85
86 void extractCodecSpecificData();
87
Andreas Huber3a177522010-12-10 15:08:23 -080088 bool appendAACFrames(MediaBuffer *buffer);
89 bool flushAACFrames();
Andreas Huber0da4dab2010-09-27 12:04:43 -070090
91 void postAVCFrame(MediaBuffer *buffer);
92
93 DISALLOW_EVIL_CONSTRUCTORS(SourceInfo);
94};
95
96MPEG2TSWriter::SourceInfo::SourceInfo(const sp<MediaSource> &source)
97 : mSource(source),
98 mLooper(new ALooper),
Andreas Huber3a177522010-12-10 15:08:23 -080099 mEOSReceived(false),
Andreas Huber0da4dab2010-09-27 12:04:43 -0700100 mStreamType(0),
101 mContinuityCounter(0) {
102 mLooper->setName("MPEG2TSWriter source");
103
104 sp<MetaData> meta = mSource->getFormat();
105 const char *mime;
106 CHECK(meta->findCString(kKeyMIMEType, &mime));
107
108 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
109 mStreamType = 0x0f;
110 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
111 mStreamType = 0x1b;
112 } else {
113 TRESPASS();
114 }
115}
116
117MPEG2TSWriter::SourceInfo::~SourceInfo() {
118}
119
120unsigned MPEG2TSWriter::SourceInfo::streamType() const {
121 return mStreamType;
122}
123
124unsigned MPEG2TSWriter::SourceInfo::incrementContinuityCounter() {
125 if (++mContinuityCounter == 16) {
126 mContinuityCounter = 0;
127 }
128
129 return mContinuityCounter;
130}
131
132void MPEG2TSWriter::SourceInfo::start(const sp<AMessage> &notify) {
133 mLooper->registerHandler(this);
134 mLooper->start();
135
136 mNotify = notify;
137
138 (new AMessage(kWhatStart, id()))->post();
139}
140
141void MPEG2TSWriter::SourceInfo::stop() {
142 mLooper->unregisterHandler(id());
143 mLooper->stop();
Andreas Huber59b7dc32010-10-12 14:17:45 -0700144
145 mSource->stop();
Andreas Huber0da4dab2010-09-27 12:04:43 -0700146}
147
148void MPEG2TSWriter::SourceInfo::extractCodecSpecificData() {
149 sp<MetaData> meta = mSource->getFormat();
150
151 const char *mime;
152 CHECK(meta->findCString(kKeyMIMEType, &mime));
153
Andreas Huber59b7dc32010-10-12 14:17:45 -0700154 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
155 uint32_t type;
156 const void *data;
157 size_t size;
158 if (!meta->findData(kKeyESDS, &type, &data, &size)) {
159 // Codec specific data better be in the first data buffer.
160 return;
161 }
162
163 ESDS esds((const char *)data, size);
164 CHECK_EQ(esds.InitCheck(), (status_t)OK);
165
166 const uint8_t *codec_specific_data;
167 size_t codec_specific_data_size;
168 esds.getCodecSpecificInfo(
169 (const void **)&codec_specific_data, &codec_specific_data_size);
170
171 CHECK_GE(codec_specific_data_size, 2u);
172
173 mAACCodecSpecificData = new ABuffer(codec_specific_data_size);
174
175 memcpy(mAACCodecSpecificData->data(), codec_specific_data,
176 codec_specific_data_size);
177
178 return;
179 }
180
Andreas Huber0da4dab2010-09-27 12:04:43 -0700181 if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
182 return;
183 }
184
Andreas Huber59b7dc32010-10-12 14:17:45 -0700185 uint32_t type;
186 const void *data;
187 size_t size;
188 if (!meta->findData(kKeyAVCC, &type, &data, &size)) {
189 // Codec specific data better be part of the data stream then.
190 return;
191 }
192
Andreas Huber0da4dab2010-09-27 12:04:43 -0700193 sp<ABuffer> out = new ABuffer(1024);
194 out->setRange(0, 0);
195
Andreas Huber0da4dab2010-09-27 12:04:43 -0700196 const uint8_t *ptr = (const uint8_t *)data;
197
198 size_t numSeqParameterSets = ptr[5] & 31;
199
200 ptr += 6;
201 size -= 6;
202
203 for (size_t i = 0; i < numSeqParameterSets; ++i) {
204 CHECK(size >= 2);
205 size_t length = U16_AT(ptr);
206
207 ptr += 2;
208 size -= 2;
209
210 CHECK(size >= length);
211
212 CHECK_LE(out->size() + 4 + length, out->capacity());
213 memcpy(out->data() + out->size(), "\x00\x00\x00\x01", 4);
214 memcpy(out->data() + out->size() + 4, ptr, length);
215 out->setRange(0, out->size() + length + 4);
216
217 ptr += length;
218 size -= length;
219 }
220
221 CHECK(size >= 1);
222 size_t numPictureParameterSets = *ptr;
223 ++ptr;
224 --size;
225
226 for (size_t i = 0; i < numPictureParameterSets; ++i) {
227 CHECK(size >= 2);
228 size_t length = U16_AT(ptr);
229
230 ptr += 2;
231 size -= 2;
232
233 CHECK(size >= length);
234
235 CHECK_LE(out->size() + 4 + length, out->capacity());
236 memcpy(out->data() + out->size(), "\x00\x00\x00\x01", 4);
237 memcpy(out->data() + out->size() + 4, ptr, length);
238 out->setRange(0, out->size() + length + 4);
239
240 ptr += length;
241 size -= length;
242 }
243
244 out->meta()->setInt64("timeUs", 0ll);
245
246 sp<AMessage> notify = mNotify->dup();
247 notify->setInt32("what", kNotifyBuffer);
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800248 notify->setBuffer("buffer", out);
Andreas Huber3a177522010-12-10 15:08:23 -0800249 notify->setInt32("oob", true);
Andreas Huber0da4dab2010-09-27 12:04:43 -0700250 notify->post();
251}
252
253void MPEG2TSWriter::SourceInfo::postAVCFrame(MediaBuffer *buffer) {
254 sp<AMessage> notify = mNotify->dup();
255 notify->setInt32("what", kNotifyBuffer);
256
257 sp<ABuffer> copy =
258 new ABuffer(buffer->range_length());
259 memcpy(copy->data(),
260 (const uint8_t *)buffer->data()
261 + buffer->range_offset(),
262 buffer->range_length());
263
264 int64_t timeUs;
265 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
266 copy->meta()->setInt64("timeUs", timeUs);
267
268 int32_t isSync;
269 if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)
270 && isSync != 0) {
271 copy->meta()->setInt32("isSync", true);
272 }
273
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800274 notify->setBuffer("buffer", copy);
Andreas Huber0da4dab2010-09-27 12:04:43 -0700275 notify->post();
276}
277
Andreas Huber3a177522010-12-10 15:08:23 -0800278bool MPEG2TSWriter::SourceInfo::appendAACFrames(MediaBuffer *buffer) {
279 bool accessUnitPosted = false;
280
Andreas Huber0da4dab2010-09-27 12:04:43 -0700281 if (mAACBuffer != NULL
282 && mAACBuffer->size() + 7 + buffer->range_length()
283 > mAACBuffer->capacity()) {
Andreas Huber3a177522010-12-10 15:08:23 -0800284 accessUnitPosted = flushAACFrames();
Andreas Huber0da4dab2010-09-27 12:04:43 -0700285 }
286
287 if (mAACBuffer == NULL) {
288 size_t alloc = 4096;
289 if (buffer->range_length() + 7 > alloc) {
290 alloc = 7 + buffer->range_length();
291 }
292
293 mAACBuffer = new ABuffer(alloc);
294
295 int64_t timeUs;
296 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
297
298 mAACBuffer->meta()->setInt64("timeUs", timeUs);
299 mAACBuffer->meta()->setInt32("isSync", true);
300
301 mAACBuffer->setRange(0, 0);
302 }
303
Andreas Huber59b7dc32010-10-12 14:17:45 -0700304 const uint8_t *codec_specific_data = mAACCodecSpecificData->data();
Andreas Huber0da4dab2010-09-27 12:04:43 -0700305
306 unsigned profile = (codec_specific_data[0] >> 3) - 1;
307
308 unsigned sampling_freq_index =
309 ((codec_specific_data[0] & 7) << 1)
310 | (codec_specific_data[1] >> 7);
311
312 unsigned channel_configuration =
313 (codec_specific_data[1] >> 3) & 0x0f;
314
315 uint8_t *ptr = mAACBuffer->data() + mAACBuffer->size();
316
317 const uint32_t aac_frame_length = buffer->range_length() + 7;
318
319 *ptr++ = 0xff;
320 *ptr++ = 0xf1; // b11110001, ID=0, layer=0, protection_absent=1
321
322 *ptr++ =
323 profile << 6
324 | sampling_freq_index << 2
325 | ((channel_configuration >> 2) & 1); // private_bit=0
326
327 // original_copy=0, home=0, copyright_id_bit=0, copyright_id_start=0
328 *ptr++ =
329 (channel_configuration & 3) << 6
330 | aac_frame_length >> 11;
331 *ptr++ = (aac_frame_length >> 3) & 0xff;
332 *ptr++ = (aac_frame_length & 7) << 5;
333
334 // adts_buffer_fullness=0, number_of_raw_data_blocks_in_frame=0
335 *ptr++ = 0;
336
337 memcpy(ptr,
338 (const uint8_t *)buffer->data() + buffer->range_offset(),
339 buffer->range_length());
340
341 ptr += buffer->range_length();
342
343 mAACBuffer->setRange(0, ptr - mAACBuffer->data());
Andreas Huber3a177522010-12-10 15:08:23 -0800344
345 return accessUnitPosted;
Andreas Huber0da4dab2010-09-27 12:04:43 -0700346}
347
Andreas Huber3a177522010-12-10 15:08:23 -0800348bool MPEG2TSWriter::SourceInfo::flushAACFrames() {
Andreas Huber0da4dab2010-09-27 12:04:43 -0700349 if (mAACBuffer == NULL) {
Andreas Huber3a177522010-12-10 15:08:23 -0800350 return false;
Andreas Huber0da4dab2010-09-27 12:04:43 -0700351 }
352
353 sp<AMessage> notify = mNotify->dup();
354 notify->setInt32("what", kNotifyBuffer);
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800355 notify->setBuffer("buffer", mAACBuffer);
Andreas Huber0da4dab2010-09-27 12:04:43 -0700356 notify->post();
357
358 mAACBuffer.clear();
Andreas Huber3a177522010-12-10 15:08:23 -0800359
360 return true;
361}
362
363void MPEG2TSWriter::SourceInfo::readMore() {
364 (new AMessage(kWhatRead, id()))->post();
Andreas Huber0da4dab2010-09-27 12:04:43 -0700365}
366
367void MPEG2TSWriter::SourceInfo::onMessageReceived(const sp<AMessage> &msg) {
368 switch (msg->what()) {
369 case kWhatStart:
370 {
371 status_t err = mSource->start();
372 if (err != OK) {
373 sp<AMessage> notify = mNotify->dup();
374 notify->setInt32("what", kNotifyStartFailed);
375 notify->post();
376 break;
377 }
378
379 extractCodecSpecificData();
380
Andreas Huber3a177522010-12-10 15:08:23 -0800381 readMore();
Andreas Huber0da4dab2010-09-27 12:04:43 -0700382 break;
383 }
384
385 case kWhatRead:
386 {
387 MediaBuffer *buffer;
388 status_t err = mSource->read(&buffer);
389
390 if (err != OK && err != INFO_FORMAT_CHANGED) {
391 if (mStreamType == 0x0f) {
392 flushAACFrames();
393 }
394
395 sp<AMessage> notify = mNotify->dup();
396 notify->setInt32("what", kNotifyReachedEOS);
397 notify->setInt32("status", err);
398 notify->post();
399 break;
400 }
401
402 if (err == OK) {
Andreas Huber59b7dc32010-10-12 14:17:45 -0700403 if (mStreamType == 0x0f && mAACCodecSpecificData == NULL) {
404 // The first buffer contains codec specific data.
405
406 CHECK_GE(buffer->range_length(), 2u);
407
408 mAACCodecSpecificData = new ABuffer(buffer->range_length());
409
410 memcpy(mAACCodecSpecificData->data(),
411 (const uint8_t *)buffer->data()
412 + buffer->range_offset(),
413 buffer->range_length());
414 } else if (buffer->range_length() > 0) {
Andreas Huber0da4dab2010-09-27 12:04:43 -0700415 if (mStreamType == 0x0f) {
Andreas Huber3a177522010-12-10 15:08:23 -0800416 if (!appendAACFrames(buffer)) {
417 msg->post();
418 }
Andreas Huber0da4dab2010-09-27 12:04:43 -0700419 } else {
420 postAVCFrame(buffer);
421 }
Martin Storsjo02d18452012-08-29 14:49:28 +0300422 } else {
423 readMore();
Andreas Huber0da4dab2010-09-27 12:04:43 -0700424 }
425
426 buffer->release();
427 buffer = NULL;
428 }
429
Andreas Huber3a177522010-12-10 15:08:23 -0800430 // Do not read more data until told to.
Andreas Huber0da4dab2010-09-27 12:04:43 -0700431 break;
432 }
433
434 default:
435 TRESPASS();
436 }
437}
438
Andreas Huber3a177522010-12-10 15:08:23 -0800439sp<ABuffer> MPEG2TSWriter::SourceInfo::lastAccessUnit() {
440 return mLastAccessUnit;
441}
442
443void MPEG2TSWriter::SourceInfo::setLastAccessUnit(
444 const sp<ABuffer> &accessUnit) {
445 mLastAccessUnit = accessUnit;
446}
447
448int64_t MPEG2TSWriter::SourceInfo::lastAccessUnitTimeUs() {
449 if (mLastAccessUnit == NULL) {
450 return -1;
451 }
452
453 int64_t timeUs;
454 CHECK(mLastAccessUnit->meta()->findInt64("timeUs", &timeUs));
455
456 return timeUs;
457}
458
459void MPEG2TSWriter::SourceInfo::setEOSReceived() {
460 CHECK(!mEOSReceived);
461 mEOSReceived = true;
462}
463
464bool MPEG2TSWriter::SourceInfo::eosReceived() const {
465 return mEOSReceived;
466}
467
Andreas Huber0da4dab2010-09-27 12:04:43 -0700468////////////////////////////////////////////////////////////////////////////////
469
Andreas Huber59b7dc32010-10-12 14:17:45 -0700470MPEG2TSWriter::MPEG2TSWriter(int fd)
James Dong674ebd02010-11-18 20:59:13 -0800471 : mFile(fdopen(dup(fd), "wb")),
Andreas Huber3e1763e2011-06-27 15:47:56 -0700472 mWriteCookie(NULL),
473 mWriteFunc(NULL),
Andreas Huber59b7dc32010-10-12 14:17:45 -0700474 mStarted(false),
475 mNumSourcesDone(0),
476 mNumTSPacketsWritten(0),
Paul Fariellod4e5af62012-01-23 17:24:35 +0100477 mNumTSPacketsBeforeMeta(0),
478 mPATContinuityCounter(0),
479 mPMTContinuityCounter(0) {
Andreas Huber59b7dc32010-10-12 14:17:45 -0700480 init();
481}
482
Andreas Huber0da4dab2010-09-27 12:04:43 -0700483MPEG2TSWriter::MPEG2TSWriter(const char *filename)
484 : mFile(fopen(filename, "wb")),
Andreas Huber3e1763e2011-06-27 15:47:56 -0700485 mWriteCookie(NULL),
486 mWriteFunc(NULL),
487 mStarted(false),
488 mNumSourcesDone(0),
489 mNumTSPacketsWritten(0),
Paul Fariellod4e5af62012-01-23 17:24:35 +0100490 mNumTSPacketsBeforeMeta(0),
491 mPATContinuityCounter(0),
492 mPMTContinuityCounter(0) {
Andreas Huber3e1763e2011-06-27 15:47:56 -0700493 init();
494}
495
496MPEG2TSWriter::MPEG2TSWriter(
497 void *cookie,
498 ssize_t (*write)(void *cookie, const void *data, size_t size))
499 : mFile(NULL),
500 mWriteCookie(cookie),
501 mWriteFunc(write),
Andreas Huber0da4dab2010-09-27 12:04:43 -0700502 mStarted(false),
503 mNumSourcesDone(0),
504 mNumTSPacketsWritten(0),
Paul Fariellod4e5af62012-01-23 17:24:35 +0100505 mNumTSPacketsBeforeMeta(0),
506 mPATContinuityCounter(0),
507 mPMTContinuityCounter(0) {
Andreas Huber59b7dc32010-10-12 14:17:45 -0700508 init();
509}
510
511void MPEG2TSWriter::init() {
Andreas Huber3e1763e2011-06-27 15:47:56 -0700512 CHECK(mFile != NULL || mWriteFunc != NULL);
Andreas Huber0da4dab2010-09-27 12:04:43 -0700513
Paul Fariello98399572012-01-23 17:21:33 +0100514 initCrcTable();
515
Andreas Huber0da4dab2010-09-27 12:04:43 -0700516 mLooper = new ALooper;
517 mLooper->setName("MPEG2TSWriter");
518
519 mReflector = new AHandlerReflector<MPEG2TSWriter>(this);
520
521 mLooper->registerHandler(mReflector);
522 mLooper->start();
523}
524
525MPEG2TSWriter::~MPEG2TSWriter() {
Andreas Huber59b7dc32010-10-12 14:17:45 -0700526 if (mStarted) {
James Dong8bcc65c2012-02-02 15:07:52 -0800527 reset();
Andreas Huber59b7dc32010-10-12 14:17:45 -0700528 }
529
Andreas Huber0da4dab2010-09-27 12:04:43 -0700530 mLooper->unregisterHandler(mReflector->id());
531 mLooper->stop();
532
Andreas Huber3e1763e2011-06-27 15:47:56 -0700533 if (mFile != NULL) {
534 fclose(mFile);
535 mFile = NULL;
536 }
Andreas Huber0da4dab2010-09-27 12:04:43 -0700537}
538
539status_t MPEG2TSWriter::addSource(const sp<MediaSource> &source) {
540 CHECK(!mStarted);
541
542 sp<MetaData> meta = source->getFormat();
543 const char *mime;
544 CHECK(meta->findCString(kKeyMIMEType, &mime));
545
546 if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
547 && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
548 return ERROR_UNSUPPORTED;
549 }
550
551 sp<SourceInfo> info = new SourceInfo(source);
552
553 mSources.push(info);
554
555 return OK;
556}
557
558status_t MPEG2TSWriter::start(MetaData *param) {
559 CHECK(!mStarted);
560
561 mStarted = true;
562 mNumSourcesDone = 0;
563 mNumTSPacketsWritten = 0;
564 mNumTSPacketsBeforeMeta = 0;
565
566 for (size_t i = 0; i < mSources.size(); ++i) {
567 sp<AMessage> notify =
568 new AMessage(kWhatSourceNotify, mReflector->id());
569
570 notify->setInt32("source-index", i);
571
572 mSources.editItemAt(i)->start(notify);
573 }
574
575 return OK;
576}
577
James Dong8bcc65c2012-02-02 15:07:52 -0800578status_t MPEG2TSWriter::reset() {
Andreas Huber0da4dab2010-09-27 12:04:43 -0700579 CHECK(mStarted);
580
581 for (size_t i = 0; i < mSources.size(); ++i) {
582 mSources.editItemAt(i)->stop();
583 }
584 mStarted = false;
585
586 return OK;
587}
588
589status_t MPEG2TSWriter::pause() {
590 CHECK(mStarted);
591
592 return OK;
593}
594
595bool MPEG2TSWriter::reachedEOS() {
596 return !mStarted || (mNumSourcesDone == mSources.size() ? true : false);
597}
598
599status_t MPEG2TSWriter::dump(int fd, const Vector<String16> &args) {
600 return OK;
601}
602
603void MPEG2TSWriter::onMessageReceived(const sp<AMessage> &msg) {
604 switch (msg->what()) {
605 case kWhatSourceNotify:
606 {
607 int32_t sourceIndex;
608 CHECK(msg->findInt32("source-index", &sourceIndex));
609
610 int32_t what;
611 CHECK(msg->findInt32("what", &what));
612
613 if (what == SourceInfo::kNotifyReachedEOS
614 || what == SourceInfo::kNotifyStartFailed) {
Andreas Huber3a177522010-12-10 15:08:23 -0800615 sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
616 source->setEOSReceived();
617
618 sp<ABuffer> buffer = source->lastAccessUnit();
619 source->setLastAccessUnit(NULL);
620
621 if (buffer != NULL) {
622 writeTS();
623 writeAccessUnit(sourceIndex, buffer);
624 }
625
Andreas Huber0da4dab2010-09-27 12:04:43 -0700626 ++mNumSourcesDone;
627 } else if (what == SourceInfo::kNotifyBuffer) {
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800628 sp<ABuffer> buffer;
629 CHECK(msg->findBuffer("buffer", &buffer));
Andreas Huber3a177522010-12-10 15:08:23 -0800630
631 int32_t oob;
632 if (msg->findInt32("oob", &oob) && oob) {
633 // This is codec specific data delivered out of band.
634 // It can be written out immediately.
635 writeTS();
636 writeAccessUnit(sourceIndex, buffer);
637 break;
638 }
639
640 // We don't just write out data as we receive it from
641 // the various sources. That would essentially write them
642 // out in random order (as the thread scheduler determines
643 // how the messages are dispatched).
644 // Instead we gather an access unit for all tracks and
645 // write out the one with the smallest timestamp, then
646 // request more data for the written out track.
647 // Rinse, repeat.
648 // If we don't have data on any track we don't write
649 // anything just yet.
650
651 sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
652
653 CHECK(source->lastAccessUnit() == NULL);
654 source->setLastAccessUnit(buffer);
655
Steve Block3856b092011-10-20 11:56:00 +0100656 ALOGV("lastAccessUnitTimeUs[%d] = %.2f secs",
Andreas Huber3a177522010-12-10 15:08:23 -0800657 sourceIndex, source->lastAccessUnitTimeUs() / 1E6);
658
659 int64_t minTimeUs = -1;
660 size_t minIndex = 0;
661
662 for (size_t i = 0; i < mSources.size(); ++i) {
663 const sp<SourceInfo> &source = mSources.editItemAt(i);
664
665 if (source->eosReceived()) {
666 continue;
667 }
668
669 int64_t timeUs = source->lastAccessUnitTimeUs();
670 if (timeUs < 0) {
671 minTimeUs = -1;
672 break;
673 } else if (minTimeUs < 0 || timeUs < minTimeUs) {
674 minTimeUs = timeUs;
675 minIndex = i;
676 }
677 }
678
679 if (minTimeUs < 0) {
Steve Block3856b092011-10-20 11:56:00 +0100680 ALOGV("not a all tracks have valid data.");
Andreas Huber3a177522010-12-10 15:08:23 -0800681 break;
682 }
683
Steve Block3856b092011-10-20 11:56:00 +0100684 ALOGV("writing access unit at time %.2f secs (index %d)",
Andreas Huber3a177522010-12-10 15:08:23 -0800685 minTimeUs / 1E6, minIndex);
686
687 source = mSources.editItemAt(minIndex);
688
689 buffer = source->lastAccessUnit();
690 source->setLastAccessUnit(NULL);
691
692 writeTS();
693 writeAccessUnit(minIndex, buffer);
694
695 source->readMore();
Andreas Huber0da4dab2010-09-27 12:04:43 -0700696 }
697 break;
698 }
699
700 default:
701 TRESPASS();
702 }
703}
704
705void MPEG2TSWriter::writeProgramAssociationTable() {
706 // 0x47
707 // transport_error_indicator = b0
708 // payload_unit_start_indicator = b1
709 // transport_priority = b0
710 // PID = b0000000000000 (13 bits)
711 // transport_scrambling_control = b00
712 // adaptation_field_control = b01 (no adaptation field, payload only)
713 // continuity_counter = b????
714 // skip = 0x00
715 // --- payload follows
716 // table_id = 0x00
717 // section_syntax_indicator = b1
718 // must_be_zero = b0
719 // reserved = b11
720 // section_length = 0x00d
721 // transport_stream_id = 0x0000
722 // reserved = b11
723 // version_number = b00001
724 // current_next_indicator = b1
725 // section_number = 0x00
726 // last_section_number = 0x00
727 // one program follows:
728 // program_number = 0x0001
729 // reserved = b111
730 // program_map_PID = 0x01e0 (13 bits!)
731 // CRC = 0x????????
732
733 static const uint8_t kData[] = {
734 0x47,
735 0x40, 0x00, 0x10, 0x00, // b0100 0000 0000 0000 0001 ???? 0000 0000
736 0x00, 0xb0, 0x0d, 0x00, // b0000 0000 1011 0000 0000 1101 0000 0000
737 0x00, 0xc3, 0x00, 0x00, // b0000 0000 1100 0011 0000 0000 0000 0000
738 0x00, 0x01, 0xe1, 0xe0, // b0000 0000 0000 0001 1110 0001 1110 0000
739 0x00, 0x00, 0x00, 0x00 // b???? ???? ???? ???? ???? ???? ???? ????
740 };
741
742 sp<ABuffer> buffer = new ABuffer(188);
Paul Fariello98399572012-01-23 17:21:33 +0100743 memset(buffer->data(), 0xff, buffer->size());
Andreas Huber0da4dab2010-09-27 12:04:43 -0700744 memcpy(buffer->data(), kData, sizeof(kData));
745
Paul Fariellod4e5af62012-01-23 17:24:35 +0100746 if (++mPATContinuityCounter == 16) {
747 mPATContinuityCounter = 0;
748 }
749 buffer->data()[3] |= mPATContinuityCounter;
Andreas Huber0da4dab2010-09-27 12:04:43 -0700750
Paul Fariello98399572012-01-23 17:21:33 +0100751 uint32_t crc = htonl(crc32(&buffer->data()[5], 12));
752 memcpy(&buffer->data()[17], &crc, sizeof(crc));
753
Andreas Huber3e1763e2011-06-27 15:47:56 -0700754 CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
Andreas Huber0da4dab2010-09-27 12:04:43 -0700755}
756
757void MPEG2TSWriter::writeProgramMap() {
758 // 0x47
759 // transport_error_indicator = b0
760 // payload_unit_start_indicator = b1
761 // transport_priority = b0
762 // PID = b0 0001 1110 0000 (13 bits) [0x1e0]
763 // transport_scrambling_control = b00
764 // adaptation_field_control = b01 (no adaptation field, payload only)
765 // continuity_counter = b????
766 // skip = 0x00
767 // -- payload follows
768 // table_id = 0x02
769 // section_syntax_indicator = b1
770 // must_be_zero = b0
771 // reserved = b11
772 // section_length = 0x???
773 // program_number = 0x0001
774 // reserved = b11
775 // version_number = b00001
776 // current_next_indicator = b1
777 // section_number = 0x00
778 // last_section_number = 0x00
779 // reserved = b111
780 // PCR_PID = b? ???? ???? ???? (13 bits)
781 // reserved = b1111
782 // program_info_length = 0x000
783 // one or more elementary stream descriptions follow:
784 // stream_type = 0x??
785 // reserved = b111
786 // elementary_PID = b? ???? ???? ???? (13 bits)
787 // reserved = b1111
788 // ES_info_length = 0x000
789 // CRC = 0x????????
790
791 static const uint8_t kData[] = {
792 0x47,
793 0x41, 0xe0, 0x10, 0x00, // b0100 0001 1110 0000 0001 ???? 0000 0000
794 0x02, 0xb0, 0x00, 0x00, // b0000 0010 1011 ???? ???? ???? 0000 0000
795 0x01, 0xc3, 0x00, 0x00, // b0000 0001 1100 0011 0000 0000 0000 0000
796 0xe0, 0x00, 0xf0, 0x00 // b111? ???? ???? ???? 1111 0000 0000 0000
797 };
798
799 sp<ABuffer> buffer = new ABuffer(188);
Paul Fariello98399572012-01-23 17:21:33 +0100800 memset(buffer->data(), 0xff, buffer->size());
Andreas Huber0da4dab2010-09-27 12:04:43 -0700801 memcpy(buffer->data(), kData, sizeof(kData));
802
Paul Fariellod4e5af62012-01-23 17:24:35 +0100803 if (++mPMTContinuityCounter == 16) {
804 mPMTContinuityCounter = 0;
805 }
806 buffer->data()[3] |= mPMTContinuityCounter;
Andreas Huber0da4dab2010-09-27 12:04:43 -0700807
808 size_t section_length = 5 * mSources.size() + 4 + 9;
809 buffer->data()[6] |= section_length >> 8;
810 buffer->data()[7] = section_length & 0xff;
811
812 static const unsigned kPCR_PID = 0x1e1;
813 buffer->data()[13] |= (kPCR_PID >> 8) & 0x1f;
814 buffer->data()[14] = kPCR_PID & 0xff;
815
816 uint8_t *ptr = &buffer->data()[sizeof(kData)];
817 for (size_t i = 0; i < mSources.size(); ++i) {
818 *ptr++ = mSources.editItemAt(i)->streamType();
819
820 const unsigned ES_PID = 0x1e0 + i + 1;
821 *ptr++ = 0xe0 | (ES_PID >> 8);
822 *ptr++ = ES_PID & 0xff;
823 *ptr++ = 0xf0;
824 *ptr++ = 0x00;
825 }
826
Paul Fariello98399572012-01-23 17:21:33 +0100827 uint32_t crc = htonl(crc32(&buffer->data()[5], 12+mSources.size()*5));
828 memcpy(&buffer->data()[17+mSources.size()*5], &crc, sizeof(crc));
Andreas Huber0da4dab2010-09-27 12:04:43 -0700829
Andreas Huber3e1763e2011-06-27 15:47:56 -0700830 CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
Andreas Huber0da4dab2010-09-27 12:04:43 -0700831}
832
833void MPEG2TSWriter::writeAccessUnit(
834 int32_t sourceIndex, const sp<ABuffer> &accessUnit) {
835 // 0x47
836 // transport_error_indicator = b0
837 // payload_unit_start_indicator = b1
838 // transport_priority = b0
839 // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
840 // transport_scrambling_control = b00
Paul Fariello99b99df2012-01-23 17:32:06 +0100841 // adaptation_field_control = b??
Andreas Huber0da4dab2010-09-27 12:04:43 -0700842 // continuity_counter = b????
843 // -- payload follows
844 // packet_startcode_prefix = 0x000001
845 // stream_id = 0x?? (0xe0 for avc video, 0xc0 for aac audio)
846 // PES_packet_length = 0x????
847 // reserved = b10
848 // PES_scrambling_control = b00
849 // PES_priority = b0
850 // data_alignment_indicator = b1
851 // copyright = b0
852 // original_or_copy = b0
853 // PTS_DTS_flags = b10 (PTS only)
854 // ESCR_flag = b0
855 // ES_rate_flag = b0
856 // DSM_trick_mode_flag = b0
857 // additional_copy_info_flag = b0
858 // PES_CRC_flag = b0
859 // PES_extension_flag = b0
860 // PES_header_data_length = 0x05
861 // reserved = b0010 (PTS)
862 // PTS[32..30] = b???
863 // reserved = b1
864 // PTS[29..15] = b??? ???? ???? ???? (15 bits)
865 // reserved = b1
866 // PTS[14..0] = b??? ???? ???? ???? (15 bits)
867 // reserved = b1
868 // the first fragment of "buffer" follows
869
870 sp<ABuffer> buffer = new ABuffer(188);
Paul Fariello99b99df2012-01-23 17:32:06 +0100871 memset(buffer->data(), 0xff, buffer->size());
Andreas Huber0da4dab2010-09-27 12:04:43 -0700872
873 const unsigned PID = 0x1e0 + sourceIndex + 1;
874
875 const unsigned continuity_counter =
876 mSources.editItemAt(sourceIndex)->incrementContinuityCounter();
877
878 // XXX if there are multiple streams of a kind (more than 1 audio or
879 // more than 1 video) they need distinct stream_ids.
880 const unsigned stream_id =
881 mSources.editItemAt(sourceIndex)->streamType() == 0x0f ? 0xc0 : 0xe0;
882
883 int64_t timeUs;
884 CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
885
886 uint32_t PTS = (timeUs * 9ll) / 100ll;
887
888 size_t PES_packet_length = accessUnit->size() + 8;
Paul Fariello99b99df2012-01-23 17:32:06 +0100889 bool padding = (accessUnit->size() < (188 - 18));
Andreas Huber0da4dab2010-09-27 12:04:43 -0700890
Andreas Huberacc82a32010-10-15 11:30:21 -0700891 if (PES_packet_length >= 65536) {
892 // This really should only happen for video.
893 CHECK_EQ(stream_id, 0xe0u);
894
895 // It's valid to set this to 0 for video according to the specs.
896 PES_packet_length = 0;
897 }
898
Andreas Huber0da4dab2010-09-27 12:04:43 -0700899 uint8_t *ptr = buffer->data();
900 *ptr++ = 0x47;
901 *ptr++ = 0x40 | (PID >> 8);
902 *ptr++ = PID & 0xff;
Paul Fariello99b99df2012-01-23 17:32:06 +0100903 *ptr++ = (padding ? 0x30 : 0x10) | continuity_counter;
904 if (padding) {
905 int paddingSize = 188 - accessUnit->size() - 18;
906 *ptr++ = paddingSize - 1;
907 if (paddingSize >= 2) {
908 *ptr++ = 0x00;
909 ptr += paddingSize - 2;
910 }
911 }
Andreas Huber0da4dab2010-09-27 12:04:43 -0700912 *ptr++ = 0x00;
913 *ptr++ = 0x00;
914 *ptr++ = 0x01;
915 *ptr++ = stream_id;
916 *ptr++ = PES_packet_length >> 8;
917 *ptr++ = PES_packet_length & 0xff;
918 *ptr++ = 0x84;
919 *ptr++ = 0x80;
920 *ptr++ = 0x05;
921 *ptr++ = 0x20 | (((PTS >> 30) & 7) << 1) | 1;
922 *ptr++ = (PTS >> 22) & 0xff;
923 *ptr++ = (((PTS >> 15) & 0x7f) << 1) | 1;
924 *ptr++ = (PTS >> 7) & 0xff;
925 *ptr++ = ((PTS & 0x7f) << 1) | 1;
926
927 size_t sizeLeft = buffer->data() + buffer->size() - ptr;
928 size_t copy = accessUnit->size();
929 if (copy > sizeLeft) {
930 copy = sizeLeft;
931 }
932
933 memcpy(ptr, accessUnit->data(), copy);
934
Andreas Huber3e1763e2011-06-27 15:47:56 -0700935 CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
Andreas Huber0da4dab2010-09-27 12:04:43 -0700936
937 size_t offset = copy;
938 while (offset < accessUnit->size()) {
Martin Storsjoc867a502012-08-20 14:34:14 +0100939 bool lastAccessUnit = ((accessUnit->size() - offset) < 184);
Andreas Huber0da4dab2010-09-27 12:04:43 -0700940 // for subsequent fragments of "buffer":
941 // 0x47
942 // transport_error_indicator = b0
943 // payload_unit_start_indicator = b0
944 // transport_priority = b0
945 // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
946 // transport_scrambling_control = b00
Paul Fariello99b99df2012-01-23 17:32:06 +0100947 // adaptation_field_control = b??
Andreas Huber0da4dab2010-09-27 12:04:43 -0700948 // continuity_counter = b????
949 // the fragment of "buffer" follows.
950
Paul Fariello99b99df2012-01-23 17:32:06 +0100951 memset(buffer->data(), 0xff, buffer->size());
Andreas Huber0da4dab2010-09-27 12:04:43 -0700952
953 const unsigned continuity_counter =
954 mSources.editItemAt(sourceIndex)->incrementContinuityCounter();
955
956 ptr = buffer->data();
957 *ptr++ = 0x47;
958 *ptr++ = 0x00 | (PID >> 8);
959 *ptr++ = PID & 0xff;
Paul Fariello99b99df2012-01-23 17:32:06 +0100960 *ptr++ = (lastAccessUnit ? 0x30 : 0x10) | continuity_counter;
961
962 if (lastAccessUnit) {
963 // Pad packet using an adaptation field
964 // Adaptation header all to 0 execpt size
965 uint8_t paddingSize = (uint8_t)184 - (accessUnit->size() - offset);
966 *ptr++ = paddingSize - 1;
967 if (paddingSize >= 2) {
968 *ptr++ = 0x00;
969 ptr += paddingSize - 2;
970 }
971 }
Andreas Huber0da4dab2010-09-27 12:04:43 -0700972
973 size_t sizeLeft = buffer->data() + buffer->size() - ptr;
974 size_t copy = accessUnit->size() - offset;
975 if (copy > sizeLeft) {
976 copy = sizeLeft;
977 }
978
979 memcpy(ptr, accessUnit->data() + offset, copy);
Andreas Huber3e1763e2011-06-27 15:47:56 -0700980 CHECK_EQ(internalWrite(buffer->data(), buffer->size()),
Andreas Huber0da4dab2010-09-27 12:04:43 -0700981 buffer->size());
982
983 offset += copy;
984 }
985}
986
987void MPEG2TSWriter::writeTS() {
988 if (mNumTSPacketsWritten >= mNumTSPacketsBeforeMeta) {
989 writeProgramAssociationTable();
990 writeProgramMap();
991
992 mNumTSPacketsBeforeMeta = mNumTSPacketsWritten + 2500;
993 }
994}
995
Paul Fariello98399572012-01-23 17:21:33 +0100996void MPEG2TSWriter::initCrcTable() {
997 uint32_t poly = 0x04C11DB7;
998
999 for (int i = 0; i < 256; i++) {
1000 uint32_t crc = i << 24;
1001 for (int j = 0; j < 8; j++) {
1002 crc = (crc << 1) ^ ((crc & 0x80000000) ? (poly) : 0);
1003 }
1004 mCrcTable[i] = crc;
1005 }
1006}
1007
1008/**
1009 * Compute CRC32 checksum for buffer starting at offset start and for length
1010 * bytes.
1011 */
1012uint32_t MPEG2TSWriter::crc32(const uint8_t *p_start, size_t length) {
1013 uint32_t crc = 0xFFFFFFFF;
1014 const uint8_t *p;
1015
1016 for (p = p_start; p < p_start + length; p++) {
1017 crc = (crc << 8) ^ mCrcTable[((crc >> 24) ^ *p) & 0xFF];
1018 }
1019
1020 return crc;
1021}
1022
Andreas Huber3e1763e2011-06-27 15:47:56 -07001023ssize_t MPEG2TSWriter::internalWrite(const void *data, size_t size) {
1024 if (mFile != NULL) {
1025 return fwrite(data, 1, size, mFile);
1026 }
1027
1028 return (*mWriteFunc)(mWriteCookie, data, size);
1029}
1030
Andreas Huber0da4dab2010-09-27 12:04:43 -07001031} // namespace android
1032