1 /*
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>
31 #include <arpa/inet.h>
32
33 #include "include/ESDS.h"
34
35 namespace android {
36
37 struct MPEG2TSWriter::SourceInfo : public AHandler {
38 SourceInfo(const sp<IMediaSource> &source);
39
40 void start(const sp<AMessage> ¬ify);
41 void stop();
42
43 unsigned streamType() const;
44 unsigned incrementContinuityCounter();
45
46 void readMore();
47
48 enum {
49 kNotifyStartFailed,
50 kNotifyBuffer,
51 kNotifyReachedEOS,
52 };
53
54 sp<ABuffer> lastAccessUnit();
55 int64_t lastAccessUnitTimeUs();
56 void setLastAccessUnit(const sp<ABuffer> &accessUnit);
57
58 void setEOSReceived();
59 bool eosReceived() const;
60
61 protected:
62 virtual void onMessageReceived(const sp<AMessage> &msg);
63
64 virtual ~SourceInfo();
65
66 private:
67 enum {
68 kWhatStart = 'strt',
69 kWhatRead = 'read',
70 };
71
72 sp<IMediaSource> mSource;
73 sp<ALooper> mLooper;
74 sp<AMessage> mNotify;
75
76 sp<ABuffer> mAACCodecSpecificData;
77
78 sp<ABuffer> mAACBuffer;
79
80 sp<ABuffer> mLastAccessUnit;
81 bool mEOSReceived;
82
83 unsigned mStreamType;
84 unsigned mContinuityCounter;
85
86 void extractCodecSpecificData();
87
88 bool appendAACFrames(MediaBuffer *buffer);
89 bool flushAACFrames();
90
91 void postAVCFrame(MediaBuffer *buffer);
92
93 DISALLOW_EVIL_CONSTRUCTORS(SourceInfo);
94 };
95
SourceInfo(const sp<IMediaSource> & source)96 MPEG2TSWriter::SourceInfo::SourceInfo(const sp<IMediaSource> &source)
97 : mSource(source),
98 mLooper(new ALooper),
99 mEOSReceived(false),
100 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
~SourceInfo()117 MPEG2TSWriter::SourceInfo::~SourceInfo() {
118 }
119
streamType() const120 unsigned MPEG2TSWriter::SourceInfo::streamType() const {
121 return mStreamType;
122 }
123
incrementContinuityCounter()124 unsigned MPEG2TSWriter::SourceInfo::incrementContinuityCounter() {
125 if (++mContinuityCounter == 16) {
126 mContinuityCounter = 0;
127 }
128
129 return mContinuityCounter;
130 }
131
start(const sp<AMessage> & notify)132 void MPEG2TSWriter::SourceInfo::start(const sp<AMessage> ¬ify) {
133 mLooper->registerHandler(this);
134 mLooper->start();
135
136 mNotify = notify;
137
138 (new AMessage(kWhatStart, this))->post();
139 }
140
stop()141 void MPEG2TSWriter::SourceInfo::stop() {
142 mLooper->unregisterHandler(id());
143 mLooper->stop();
144
145 mSource->stop();
146 }
147
extractCodecSpecificData()148 void MPEG2TSWriter::SourceInfo::extractCodecSpecificData() {
149 sp<MetaData> meta = mSource->getFormat();
150
151 const char *mime;
152 CHECK(meta->findCString(kKeyMIMEType, &mime));
153
154 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
181 if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
182 return;
183 }
184
185 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
193 sp<ABuffer> out = new ABuffer(1024);
194 out->setRange(0, 0);
195
196 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);
248 notify->setBuffer("buffer", out);
249 notify->setInt32("oob", true);
250 notify->post();
251 }
252
postAVCFrame(MediaBuffer * buffer)253 void 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
274 notify->setBuffer("buffer", copy);
275 notify->post();
276 }
277
appendAACFrames(MediaBuffer * buffer)278 bool MPEG2TSWriter::SourceInfo::appendAACFrames(MediaBuffer *buffer) {
279 bool accessUnitPosted = false;
280
281 if (mAACBuffer != NULL
282 && mAACBuffer->size() + 7 + buffer->range_length()
283 > mAACBuffer->capacity()) {
284 accessUnitPosted = flushAACFrames();
285 }
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
304 const uint8_t *codec_specific_data = mAACCodecSpecificData->data();
305
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());
344
345 return accessUnitPosted;
346 }
347
flushAACFrames()348 bool MPEG2TSWriter::SourceInfo::flushAACFrames() {
349 if (mAACBuffer == NULL) {
350 return false;
351 }
352
353 sp<AMessage> notify = mNotify->dup();
354 notify->setInt32("what", kNotifyBuffer);
355 notify->setBuffer("buffer", mAACBuffer);
356 notify->post();
357
358 mAACBuffer.clear();
359
360 return true;
361 }
362
readMore()363 void MPEG2TSWriter::SourceInfo::readMore() {
364 (new AMessage(kWhatRead, this))->post();
365 }
366
onMessageReceived(const sp<AMessage> & msg)367 void 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
381 readMore();
382 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) {
403 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) {
415 if (mStreamType == 0x0f) {
416 if (!appendAACFrames(buffer)) {
417 msg->post();
418 }
419 } else {
420 postAVCFrame(buffer);
421 }
422 } else {
423 readMore();
424 }
425
426 buffer->release();
427 buffer = NULL;
428 }
429
430 // Do not read more data until told to.
431 break;
432 }
433
434 default:
435 TRESPASS();
436 }
437 }
438
lastAccessUnit()439 sp<ABuffer> MPEG2TSWriter::SourceInfo::lastAccessUnit() {
440 return mLastAccessUnit;
441 }
442
setLastAccessUnit(const sp<ABuffer> & accessUnit)443 void MPEG2TSWriter::SourceInfo::setLastAccessUnit(
444 const sp<ABuffer> &accessUnit) {
445 mLastAccessUnit = accessUnit;
446 }
447
lastAccessUnitTimeUs()448 int64_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
setEOSReceived()459 void MPEG2TSWriter::SourceInfo::setEOSReceived() {
460 CHECK(!mEOSReceived);
461 mEOSReceived = true;
462 }
463
eosReceived() const464 bool MPEG2TSWriter::SourceInfo::eosReceived() const {
465 return mEOSReceived;
466 }
467
468 ////////////////////////////////////////////////////////////////////////////////
469
MPEG2TSWriter(int fd)470 MPEG2TSWriter::MPEG2TSWriter(int fd)
471 : mFile(fdopen(dup(fd), "wb")),
472 mWriteCookie(NULL),
473 mWriteFunc(NULL),
474 mStarted(false),
475 mNumSourcesDone(0),
476 mNumTSPacketsWritten(0),
477 mNumTSPacketsBeforeMeta(0),
478 mPATContinuityCounter(0),
479 mPMTContinuityCounter(0) {
480 init();
481 }
482
MPEG2TSWriter(void * cookie,ssize_t (* write)(void * cookie,const void * data,size_t size))483 MPEG2TSWriter::MPEG2TSWriter(
484 void *cookie,
485 ssize_t (*write)(void *cookie, const void *data, size_t size))
486 : mFile(NULL),
487 mWriteCookie(cookie),
488 mWriteFunc(write),
489 mStarted(false),
490 mNumSourcesDone(0),
491 mNumTSPacketsWritten(0),
492 mNumTSPacketsBeforeMeta(0),
493 mPATContinuityCounter(0),
494 mPMTContinuityCounter(0) {
495 init();
496 }
497
init()498 void MPEG2TSWriter::init() {
499 CHECK(mFile != NULL || mWriteFunc != NULL);
500
501 initCrcTable();
502
503 mLooper = new ALooper;
504 mLooper->setName("MPEG2TSWriter");
505
506 mReflector = new AHandlerReflector<MPEG2TSWriter>(this);
507
508 mLooper->registerHandler(mReflector);
509 mLooper->start();
510 }
511
~MPEG2TSWriter()512 MPEG2TSWriter::~MPEG2TSWriter() {
513 if (mStarted) {
514 reset();
515 }
516
517 mLooper->unregisterHandler(mReflector->id());
518 mLooper->stop();
519
520 if (mFile != NULL) {
521 fclose(mFile);
522 mFile = NULL;
523 }
524 }
525
addSource(const sp<IMediaSource> & source)526 status_t MPEG2TSWriter::addSource(const sp<IMediaSource> &source) {
527 CHECK(!mStarted);
528
529 sp<MetaData> meta = source->getFormat();
530 const char *mime;
531 CHECK(meta->findCString(kKeyMIMEType, &mime));
532
533 if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
534 && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
535 return ERROR_UNSUPPORTED;
536 }
537
538 sp<SourceInfo> info = new SourceInfo(source);
539
540 mSources.push(info);
541
542 return OK;
543 }
544
start(MetaData *)545 status_t MPEG2TSWriter::start(MetaData * /* param */) {
546 CHECK(!mStarted);
547
548 mStarted = true;
549 mNumSourcesDone = 0;
550 mNumTSPacketsWritten = 0;
551 mNumTSPacketsBeforeMeta = 0;
552
553 for (size_t i = 0; i < mSources.size(); ++i) {
554 sp<AMessage> notify =
555 new AMessage(kWhatSourceNotify, mReflector);
556
557 notify->setInt32("source-index", i);
558
559 mSources.editItemAt(i)->start(notify);
560 }
561
562 return OK;
563 }
564
reset()565 status_t MPEG2TSWriter::reset() {
566 CHECK(mStarted);
567
568 for (size_t i = 0; i < mSources.size(); ++i) {
569 mSources.editItemAt(i)->stop();
570 }
571 mStarted = false;
572
573 return OK;
574 }
575
pause()576 status_t MPEG2TSWriter::pause() {
577 CHECK(mStarted);
578
579 return OK;
580 }
581
reachedEOS()582 bool MPEG2TSWriter::reachedEOS() {
583 return !mStarted || (mNumSourcesDone == mSources.size() ? true : false);
584 }
585
dump(int,const Vector<String16> &)586 status_t MPEG2TSWriter::dump(
587 int /* fd */, const Vector<String16> & /* args */) {
588 return OK;
589 }
590
onMessageReceived(const sp<AMessage> & msg)591 void MPEG2TSWriter::onMessageReceived(const sp<AMessage> &msg) {
592 switch (msg->what()) {
593 case kWhatSourceNotify:
594 {
595 int32_t sourceIndex;
596 CHECK(msg->findInt32("source-index", &sourceIndex));
597
598 int32_t what;
599 CHECK(msg->findInt32("what", &what));
600
601 if (what == SourceInfo::kNotifyReachedEOS
602 || what == SourceInfo::kNotifyStartFailed) {
603 sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
604 source->setEOSReceived();
605
606 sp<ABuffer> buffer = source->lastAccessUnit();
607 source->setLastAccessUnit(NULL);
608
609 if (buffer != NULL) {
610 writeTS();
611 writeAccessUnit(sourceIndex, buffer);
612 }
613
614 ++mNumSourcesDone;
615 } else if (what == SourceInfo::kNotifyBuffer) {
616 sp<ABuffer> buffer;
617 CHECK(msg->findBuffer("buffer", &buffer));
618
619 int32_t oob;
620 if (msg->findInt32("oob", &oob) && oob) {
621 // This is codec specific data delivered out of band.
622 // It can be written out immediately.
623 writeTS();
624 writeAccessUnit(sourceIndex, buffer);
625 break;
626 }
627
628 // We don't just write out data as we receive it from
629 // the various sources. That would essentially write them
630 // out in random order (as the thread scheduler determines
631 // how the messages are dispatched).
632 // Instead we gather an access unit for all tracks and
633 // write out the one with the smallest timestamp, then
634 // request more data for the written out track.
635 // Rinse, repeat.
636 // If we don't have data on any track we don't write
637 // anything just yet.
638
639 sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
640
641 CHECK(source->lastAccessUnit() == NULL);
642 source->setLastAccessUnit(buffer);
643
644 ALOGV("lastAccessUnitTimeUs[%d] = %.2f secs",
645 sourceIndex, source->lastAccessUnitTimeUs() / 1E6);
646
647 int64_t minTimeUs = -1;
648 size_t minIndex = 0;
649
650 for (size_t i = 0; i < mSources.size(); ++i) {
651 const sp<SourceInfo> &source = mSources.editItemAt(i);
652
653 if (source->eosReceived()) {
654 continue;
655 }
656
657 int64_t timeUs = source->lastAccessUnitTimeUs();
658 if (timeUs < 0) {
659 minTimeUs = -1;
660 break;
661 } else if (minTimeUs < 0 || timeUs < minTimeUs) {
662 minTimeUs = timeUs;
663 minIndex = i;
664 }
665 }
666
667 if (minTimeUs < 0) {
668 ALOGV("not a all tracks have valid data.");
669 break;
670 }
671
672 ALOGV("writing access unit at time %.2f secs (index %zu)",
673 minTimeUs / 1E6, minIndex);
674
675 source = mSources.editItemAt(minIndex);
676
677 buffer = source->lastAccessUnit();
678 source->setLastAccessUnit(NULL);
679
680 writeTS();
681 writeAccessUnit(minIndex, buffer);
682
683 source->readMore();
684 }
685 break;
686 }
687
688 default:
689 TRESPASS();
690 }
691 }
692
writeProgramAssociationTable()693 void MPEG2TSWriter::writeProgramAssociationTable() {
694 // 0x47
695 // transport_error_indicator = b0
696 // payload_unit_start_indicator = b1
697 // transport_priority = b0
698 // PID = b0000000000000 (13 bits)
699 // transport_scrambling_control = b00
700 // adaptation_field_control = b01 (no adaptation field, payload only)
701 // continuity_counter = b????
702 // skip = 0x00
703 // --- payload follows
704 // table_id = 0x00
705 // section_syntax_indicator = b1
706 // must_be_zero = b0
707 // reserved = b11
708 // section_length = 0x00d
709 // transport_stream_id = 0x0000
710 // reserved = b11
711 // version_number = b00001
712 // current_next_indicator = b1
713 // section_number = 0x00
714 // last_section_number = 0x00
715 // one program follows:
716 // program_number = 0x0001
717 // reserved = b111
718 // program_map_PID = 0x01e0 (13 bits!)
719 // CRC = 0x????????
720
721 static const uint8_t kData[] = {
722 0x47,
723 0x40, 0x00, 0x10, 0x00, // b0100 0000 0000 0000 0001 ???? 0000 0000
724 0x00, 0xb0, 0x0d, 0x00, // b0000 0000 1011 0000 0000 1101 0000 0000
725 0x00, 0xc3, 0x00, 0x00, // b0000 0000 1100 0011 0000 0000 0000 0000
726 0x00, 0x01, 0xe1, 0xe0, // b0000 0000 0000 0001 1110 0001 1110 0000
727 0x00, 0x00, 0x00, 0x00 // b???? ???? ???? ???? ???? ???? ???? ????
728 };
729
730 sp<ABuffer> buffer = new ABuffer(188);
731 memset(buffer->data(), 0xff, buffer->size());
732 memcpy(buffer->data(), kData, sizeof(kData));
733
734 if (++mPATContinuityCounter == 16) {
735 mPATContinuityCounter = 0;
736 }
737 buffer->data()[3] |= mPATContinuityCounter;
738
739 uint32_t crc = htonl(crc32(&buffer->data()[5], 12));
740 memcpy(&buffer->data()[17], &crc, sizeof(crc));
741
742 CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
743 }
744
writeProgramMap()745 void MPEG2TSWriter::writeProgramMap() {
746 // 0x47
747 // transport_error_indicator = b0
748 // payload_unit_start_indicator = b1
749 // transport_priority = b0
750 // PID = b0 0001 1110 0000 (13 bits) [0x1e0]
751 // transport_scrambling_control = b00
752 // adaptation_field_control = b01 (no adaptation field, payload only)
753 // continuity_counter = b????
754 // skip = 0x00
755 // -- payload follows
756 // table_id = 0x02
757 // section_syntax_indicator = b1
758 // must_be_zero = b0
759 // reserved = b11
760 // section_length = 0x???
761 // program_number = 0x0001
762 // reserved = b11
763 // version_number = b00001
764 // current_next_indicator = b1
765 // section_number = 0x00
766 // last_section_number = 0x00
767 // reserved = b111
768 // PCR_PID = b? ???? ???? ???? (13 bits)
769 // reserved = b1111
770 // program_info_length = 0x000
771 // one or more elementary stream descriptions follow:
772 // stream_type = 0x??
773 // reserved = b111
774 // elementary_PID = b? ???? ???? ???? (13 bits)
775 // reserved = b1111
776 // ES_info_length = 0x000
777 // CRC = 0x????????
778
779 static const uint8_t kData[] = {
780 0x47,
781 0x41, 0xe0, 0x10, 0x00, // b0100 0001 1110 0000 0001 ???? 0000 0000
782 0x02, 0xb0, 0x00, 0x00, // b0000 0010 1011 ???? ???? ???? 0000 0000
783 0x01, 0xc3, 0x00, 0x00, // b0000 0001 1100 0011 0000 0000 0000 0000
784 0xe0, 0x00, 0xf0, 0x00 // b111? ???? ???? ???? 1111 0000 0000 0000
785 };
786
787 sp<ABuffer> buffer = new ABuffer(188);
788 memset(buffer->data(), 0xff, buffer->size());
789 memcpy(buffer->data(), kData, sizeof(kData));
790
791 if (++mPMTContinuityCounter == 16) {
792 mPMTContinuityCounter = 0;
793 }
794 buffer->data()[3] |= mPMTContinuityCounter;
795
796 size_t section_length = 5 * mSources.size() + 4 + 9;
797 buffer->data()[6] |= section_length >> 8;
798 buffer->data()[7] = section_length & 0xff;
799
800 static const unsigned kPCR_PID = 0x1e1;
801 buffer->data()[13] |= (kPCR_PID >> 8) & 0x1f;
802 buffer->data()[14] = kPCR_PID & 0xff;
803
804 uint8_t *ptr = &buffer->data()[sizeof(kData)];
805 for (size_t i = 0; i < mSources.size(); ++i) {
806 *ptr++ = mSources.editItemAt(i)->streamType();
807
808 const unsigned ES_PID = 0x1e0 + i + 1;
809 *ptr++ = 0xe0 | (ES_PID >> 8);
810 *ptr++ = ES_PID & 0xff;
811 *ptr++ = 0xf0;
812 *ptr++ = 0x00;
813 }
814
815 uint32_t crc = htonl(crc32(&buffer->data()[5], 12+mSources.size()*5));
816 memcpy(&buffer->data()[17+mSources.size()*5], &crc, sizeof(crc));
817
818 CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
819 }
820
writeAccessUnit(int32_t sourceIndex,const sp<ABuffer> & accessUnit)821 void MPEG2TSWriter::writeAccessUnit(
822 int32_t sourceIndex, const sp<ABuffer> &accessUnit) {
823 // 0x47
824 // transport_error_indicator = b0
825 // payload_unit_start_indicator = b1
826 // transport_priority = b0
827 // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
828 // transport_scrambling_control = b00
829 // adaptation_field_control = b??
830 // continuity_counter = b????
831 // -- payload follows
832 // packet_startcode_prefix = 0x000001
833 // stream_id = 0x?? (0xe0 for avc video, 0xc0 for aac audio)
834 // PES_packet_length = 0x????
835 // reserved = b10
836 // PES_scrambling_control = b00
837 // PES_priority = b0
838 // data_alignment_indicator = b1
839 // copyright = b0
840 // original_or_copy = b0
841 // PTS_DTS_flags = b10 (PTS only)
842 // ESCR_flag = b0
843 // ES_rate_flag = b0
844 // DSM_trick_mode_flag = b0
845 // additional_copy_info_flag = b0
846 // PES_CRC_flag = b0
847 // PES_extension_flag = b0
848 // PES_header_data_length = 0x05
849 // reserved = b0010 (PTS)
850 // PTS[32..30] = b???
851 // reserved = b1
852 // PTS[29..15] = b??? ???? ???? ???? (15 bits)
853 // reserved = b1
854 // PTS[14..0] = b??? ???? ???? ???? (15 bits)
855 // reserved = b1
856 // the first fragment of "buffer" follows
857
858 sp<ABuffer> buffer = new ABuffer(188);
859 memset(buffer->data(), 0xff, buffer->size());
860
861 const unsigned PID = 0x1e0 + sourceIndex + 1;
862
863 const unsigned continuity_counter =
864 mSources.editItemAt(sourceIndex)->incrementContinuityCounter();
865
866 // XXX if there are multiple streams of a kind (more than 1 audio or
867 // more than 1 video) they need distinct stream_ids.
868 const unsigned stream_id =
869 mSources.editItemAt(sourceIndex)->streamType() == 0x0f ? 0xc0 : 0xe0;
870
871 int64_t timeUs;
872 CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
873
874 uint32_t PTS = (timeUs * 9ll) / 100ll;
875
876 size_t PES_packet_length = accessUnit->size() + 8;
877 bool padding = (accessUnit->size() < (188 - 18));
878
879 if (PES_packet_length >= 65536) {
880 // This really should only happen for video.
881 CHECK_EQ(stream_id, 0xe0u);
882
883 // It's valid to set this to 0 for video according to the specs.
884 PES_packet_length = 0;
885 }
886
887 uint8_t *ptr = buffer->data();
888 *ptr++ = 0x47;
889 *ptr++ = 0x40 | (PID >> 8);
890 *ptr++ = PID & 0xff;
891 *ptr++ = (padding ? 0x30 : 0x10) | continuity_counter;
892 if (padding) {
893 int paddingSize = 188 - accessUnit->size() - 18;
894 *ptr++ = paddingSize - 1;
895 if (paddingSize >= 2) {
896 *ptr++ = 0x00;
897 ptr += paddingSize - 2;
898 }
899 }
900 *ptr++ = 0x00;
901 *ptr++ = 0x00;
902 *ptr++ = 0x01;
903 *ptr++ = stream_id;
904 *ptr++ = PES_packet_length >> 8;
905 *ptr++ = PES_packet_length & 0xff;
906 *ptr++ = 0x84;
907 *ptr++ = 0x80;
908 *ptr++ = 0x05;
909 *ptr++ = 0x20 | (((PTS >> 30) & 7) << 1) | 1;
910 *ptr++ = (PTS >> 22) & 0xff;
911 *ptr++ = (((PTS >> 15) & 0x7f) << 1) | 1;
912 *ptr++ = (PTS >> 7) & 0xff;
913 *ptr++ = ((PTS & 0x7f) << 1) | 1;
914
915 size_t sizeLeft = buffer->data() + buffer->size() - ptr;
916 size_t copy = accessUnit->size();
917 if (copy > sizeLeft) {
918 copy = sizeLeft;
919 }
920
921 memcpy(ptr, accessUnit->data(), copy);
922
923 CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
924
925 size_t offset = copy;
926 while (offset < accessUnit->size()) {
927 bool lastAccessUnit = ((accessUnit->size() - offset) < 184);
928 // for subsequent fragments of "buffer":
929 // 0x47
930 // transport_error_indicator = b0
931 // payload_unit_start_indicator = b0
932 // transport_priority = b0
933 // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
934 // transport_scrambling_control = b00
935 // adaptation_field_control = b??
936 // continuity_counter = b????
937 // the fragment of "buffer" follows.
938
939 memset(buffer->data(), 0xff, buffer->size());
940
941 const unsigned continuity_counter =
942 mSources.editItemAt(sourceIndex)->incrementContinuityCounter();
943
944 ptr = buffer->data();
945 *ptr++ = 0x47;
946 *ptr++ = 0x00 | (PID >> 8);
947 *ptr++ = PID & 0xff;
948 *ptr++ = (lastAccessUnit ? 0x30 : 0x10) | continuity_counter;
949
950 if (lastAccessUnit) {
951 // Pad packet using an adaptation field
952 // Adaptation header all to 0 execpt size
953 uint8_t paddingSize = (uint8_t)184 - (accessUnit->size() - offset);
954 *ptr++ = paddingSize - 1;
955 if (paddingSize >= 2) {
956 *ptr++ = 0x00;
957 ptr += paddingSize - 2;
958 }
959 }
960
961 size_t sizeLeft = buffer->data() + buffer->size() - ptr;
962 size_t copy = accessUnit->size() - offset;
963 if (copy > sizeLeft) {
964 copy = sizeLeft;
965 }
966
967 memcpy(ptr, accessUnit->data() + offset, copy);
968 CHECK_EQ(internalWrite(buffer->data(), buffer->size()),
969 buffer->size());
970
971 offset += copy;
972 }
973 }
974
writeTS()975 void MPEG2TSWriter::writeTS() {
976 if (mNumTSPacketsWritten >= mNumTSPacketsBeforeMeta) {
977 writeProgramAssociationTable();
978 writeProgramMap();
979
980 mNumTSPacketsBeforeMeta = mNumTSPacketsWritten + 2500;
981 }
982 }
983
initCrcTable()984 void MPEG2TSWriter::initCrcTable() {
985 uint32_t poly = 0x04C11DB7;
986
987 for (int i = 0; i < 256; i++) {
988 uint32_t crc = i << 24;
989 for (int j = 0; j < 8; j++) {
990 crc = (crc << 1) ^ ((crc & 0x80000000) ? (poly) : 0);
991 }
992 mCrcTable[i] = crc;
993 }
994 }
995
996 /**
997 * Compute CRC32 checksum for buffer starting at offset start and for length
998 * bytes.
999 */
crc32(const uint8_t * p_start,size_t length)1000 uint32_t MPEG2TSWriter::crc32(const uint8_t *p_start, size_t length) {
1001 uint32_t crc = 0xFFFFFFFF;
1002 const uint8_t *p;
1003
1004 for (p = p_start; p < p_start + length; p++) {
1005 crc = (crc << 8) ^ mCrcTable[((crc >> 24) ^ *p) & 0xFF];
1006 }
1007
1008 return crc;
1009 }
1010
internalWrite(const void * data,size_t size)1011 ssize_t MPEG2TSWriter::internalWrite(const void *data, size_t size) {
1012 if (mFile != NULL) {
1013 return fwrite(data, 1, size, mFile);
1014 }
1015
1016 return (*mWriteFunc)(mWriteCookie, data, size);
1017 }
1018
1019 } // namespace android
1020
1021