blob: 36009abf990c5f9a5b87039286648230d7407205 [file] [log] [blame]
Andreas Huberc751ecc2010-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>
31
32#include "include/ESDS.h"
33
34namespace android {
35
36struct MPEG2TSWriter::SourceInfo : public AHandler {
37 SourceInfo(const sp<MediaSource> &source);
38
39 void start(const sp<AMessage> &notify);
40 void stop();
41
42 unsigned streamType() const;
43 unsigned incrementContinuityCounter();
44
Andreas Huberfb16f702010-12-10 15:08:23 -080045 void readMore();
46
Andreas Huberc751ecc2010-09-27 12:04:43 -070047 enum {
48 kNotifyStartFailed,
49 kNotifyBuffer,
50 kNotifyReachedEOS,
51 };
52
Andreas Huberfb16f702010-12-10 15:08:23 -080053 sp<ABuffer> lastAccessUnit();
54 int64_t lastAccessUnitTimeUs();
55 void setLastAccessUnit(const sp<ABuffer> &accessUnit);
56
57 void setEOSReceived();
58 bool eosReceived() const;
59
Andreas Huberc751ecc2010-09-27 12:04:43 -070060protected:
61 virtual void onMessageReceived(const sp<AMessage> &msg);
62
63 virtual ~SourceInfo();
64
65private:
66 enum {
67 kWhatStart = 'strt',
68 kWhatRead = 'read',
69 };
70
71 sp<MediaSource> mSource;
72 sp<ALooper> mLooper;
73 sp<AMessage> mNotify;
74
Andreas Huber9adf4662010-10-12 14:17:45 -070075 sp<ABuffer> mAACCodecSpecificData;
76
Andreas Huberc751ecc2010-09-27 12:04:43 -070077 sp<ABuffer> mAACBuffer;
78
Andreas Huberfb16f702010-12-10 15:08:23 -080079 sp<ABuffer> mLastAccessUnit;
80 bool mEOSReceived;
81
Andreas Huberc751ecc2010-09-27 12:04:43 -070082 unsigned mStreamType;
83 unsigned mContinuityCounter;
84
85 void extractCodecSpecificData();
86
Andreas Huberfb16f702010-12-10 15:08:23 -080087 bool appendAACFrames(MediaBuffer *buffer);
88 bool flushAACFrames();
Andreas Huberc751ecc2010-09-27 12:04:43 -070089
90 void postAVCFrame(MediaBuffer *buffer);
91
92 DISALLOW_EVIL_CONSTRUCTORS(SourceInfo);
93};
94
95MPEG2TSWriter::SourceInfo::SourceInfo(const sp<MediaSource> &source)
96 : mSource(source),
97 mLooper(new ALooper),
Andreas Huberfb16f702010-12-10 15:08:23 -080098 mEOSReceived(false),
Andreas Huberc751ecc2010-09-27 12:04:43 -070099 mStreamType(0),
100 mContinuityCounter(0) {
101 mLooper->setName("MPEG2TSWriter source");
102
103 sp<MetaData> meta = mSource->getFormat();
104 const char *mime;
105 CHECK(meta->findCString(kKeyMIMEType, &mime));
106
107 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
108 mStreamType = 0x0f;
109 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
110 mStreamType = 0x1b;
111 } else {
112 TRESPASS();
113 }
114}
115
116MPEG2TSWriter::SourceInfo::~SourceInfo() {
117}
118
119unsigned MPEG2TSWriter::SourceInfo::streamType() const {
120 return mStreamType;
121}
122
123unsigned MPEG2TSWriter::SourceInfo::incrementContinuityCounter() {
124 if (++mContinuityCounter == 16) {
125 mContinuityCounter = 0;
126 }
127
128 return mContinuityCounter;
129}
130
131void MPEG2TSWriter::SourceInfo::start(const sp<AMessage> &notify) {
132 mLooper->registerHandler(this);
133 mLooper->start();
134
135 mNotify = notify;
136
137 (new AMessage(kWhatStart, id()))->post();
138}
139
140void MPEG2TSWriter::SourceInfo::stop() {
141 mLooper->unregisterHandler(id());
142 mLooper->stop();
Andreas Huber9adf4662010-10-12 14:17:45 -0700143
144 mSource->stop();
Andreas Huberc751ecc2010-09-27 12:04:43 -0700145}
146
147void MPEG2TSWriter::SourceInfo::extractCodecSpecificData() {
148 sp<MetaData> meta = mSource->getFormat();
149
150 const char *mime;
151 CHECK(meta->findCString(kKeyMIMEType, &mime));
152
Andreas Huber9adf4662010-10-12 14:17:45 -0700153 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
154 uint32_t type;
155 const void *data;
156 size_t size;
157 if (!meta->findData(kKeyESDS, &type, &data, &size)) {
158 // Codec specific data better be in the first data buffer.
159 return;
160 }
161
162 ESDS esds((const char *)data, size);
163 CHECK_EQ(esds.InitCheck(), (status_t)OK);
164
165 const uint8_t *codec_specific_data;
166 size_t codec_specific_data_size;
167 esds.getCodecSpecificInfo(
168 (const void **)&codec_specific_data, &codec_specific_data_size);
169
170 CHECK_GE(codec_specific_data_size, 2u);
171
172 mAACCodecSpecificData = new ABuffer(codec_specific_data_size);
173
174 memcpy(mAACCodecSpecificData->data(), codec_specific_data,
175 codec_specific_data_size);
176
177 return;
178 }
179
Andreas Huberc751ecc2010-09-27 12:04:43 -0700180 if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
181 return;
182 }
183
Andreas Huber9adf4662010-10-12 14:17:45 -0700184 uint32_t type;
185 const void *data;
186 size_t size;
187 if (!meta->findData(kKeyAVCC, &type, &data, &size)) {
188 // Codec specific data better be part of the data stream then.
189 return;
190 }
191
Andreas Huberc751ecc2010-09-27 12:04:43 -0700192 sp<ABuffer> out = new ABuffer(1024);
193 out->setRange(0, 0);
194
Andreas Huberc751ecc2010-09-27 12:04:43 -0700195 const uint8_t *ptr = (const uint8_t *)data;
196
197 size_t numSeqParameterSets = ptr[5] & 31;
198
199 ptr += 6;
200 size -= 6;
201
202 for (size_t i = 0; i < numSeqParameterSets; ++i) {
203 CHECK(size >= 2);
204 size_t length = U16_AT(ptr);
205
206 ptr += 2;
207 size -= 2;
208
209 CHECK(size >= length);
210
211 CHECK_LE(out->size() + 4 + length, out->capacity());
212 memcpy(out->data() + out->size(), "\x00\x00\x00\x01", 4);
213 memcpy(out->data() + out->size() + 4, ptr, length);
214 out->setRange(0, out->size() + length + 4);
215
216 ptr += length;
217 size -= length;
218 }
219
220 CHECK(size >= 1);
221 size_t numPictureParameterSets = *ptr;
222 ++ptr;
223 --size;
224
225 for (size_t i = 0; i < numPictureParameterSets; ++i) {
226 CHECK(size >= 2);
227 size_t length = U16_AT(ptr);
228
229 ptr += 2;
230 size -= 2;
231
232 CHECK(size >= length);
233
234 CHECK_LE(out->size() + 4 + length, out->capacity());
235 memcpy(out->data() + out->size(), "\x00\x00\x00\x01", 4);
236 memcpy(out->data() + out->size() + 4, ptr, length);
237 out->setRange(0, out->size() + length + 4);
238
239 ptr += length;
240 size -= length;
241 }
242
243 out->meta()->setInt64("timeUs", 0ll);
244
245 sp<AMessage> notify = mNotify->dup();
246 notify->setInt32("what", kNotifyBuffer);
247 notify->setObject("buffer", out);
Andreas Huberfb16f702010-12-10 15:08:23 -0800248 notify->setInt32("oob", true);
Andreas Huberc751ecc2010-09-27 12:04:43 -0700249 notify->post();
250}
251
252void MPEG2TSWriter::SourceInfo::postAVCFrame(MediaBuffer *buffer) {
253 sp<AMessage> notify = mNotify->dup();
254 notify->setInt32("what", kNotifyBuffer);
255
256 sp<ABuffer> copy =
257 new ABuffer(buffer->range_length());
258 memcpy(copy->data(),
259 (const uint8_t *)buffer->data()
260 + buffer->range_offset(),
261 buffer->range_length());
262
263 int64_t timeUs;
264 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
265 copy->meta()->setInt64("timeUs", timeUs);
266
267 int32_t isSync;
268 if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)
269 && isSync != 0) {
270 copy->meta()->setInt32("isSync", true);
271 }
272
273 notify->setObject("buffer", copy);
274 notify->post();
275}
276
Andreas Huberfb16f702010-12-10 15:08:23 -0800277bool MPEG2TSWriter::SourceInfo::appendAACFrames(MediaBuffer *buffer) {
278 bool accessUnitPosted = false;
279
Andreas Huberc751ecc2010-09-27 12:04:43 -0700280 if (mAACBuffer != NULL
281 && mAACBuffer->size() + 7 + buffer->range_length()
282 > mAACBuffer->capacity()) {
Andreas Huberfb16f702010-12-10 15:08:23 -0800283 accessUnitPosted = flushAACFrames();
Andreas Huberc751ecc2010-09-27 12:04:43 -0700284 }
285
286 if (mAACBuffer == NULL) {
287 size_t alloc = 4096;
288 if (buffer->range_length() + 7 > alloc) {
289 alloc = 7 + buffer->range_length();
290 }
291
292 mAACBuffer = new ABuffer(alloc);
293
294 int64_t timeUs;
295 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
296
297 mAACBuffer->meta()->setInt64("timeUs", timeUs);
298 mAACBuffer->meta()->setInt32("isSync", true);
299
300 mAACBuffer->setRange(0, 0);
301 }
302
Andreas Huber9adf4662010-10-12 14:17:45 -0700303 const uint8_t *codec_specific_data = mAACCodecSpecificData->data();
Andreas Huberc751ecc2010-09-27 12:04:43 -0700304
305 unsigned profile = (codec_specific_data[0] >> 3) - 1;
306
307 unsigned sampling_freq_index =
308 ((codec_specific_data[0] & 7) << 1)
309 | (codec_specific_data[1] >> 7);
310
311 unsigned channel_configuration =
312 (codec_specific_data[1] >> 3) & 0x0f;
313
314 uint8_t *ptr = mAACBuffer->data() + mAACBuffer->size();
315
316 const uint32_t aac_frame_length = buffer->range_length() + 7;
317
318 *ptr++ = 0xff;
319 *ptr++ = 0xf1; // b11110001, ID=0, layer=0, protection_absent=1
320
321 *ptr++ =
322 profile << 6
323 | sampling_freq_index << 2
324 | ((channel_configuration >> 2) & 1); // private_bit=0
325
326 // original_copy=0, home=0, copyright_id_bit=0, copyright_id_start=0
327 *ptr++ =
328 (channel_configuration & 3) << 6
329 | aac_frame_length >> 11;
330 *ptr++ = (aac_frame_length >> 3) & 0xff;
331 *ptr++ = (aac_frame_length & 7) << 5;
332
333 // adts_buffer_fullness=0, number_of_raw_data_blocks_in_frame=0
334 *ptr++ = 0;
335
336 memcpy(ptr,
337 (const uint8_t *)buffer->data() + buffer->range_offset(),
338 buffer->range_length());
339
340 ptr += buffer->range_length();
341
342 mAACBuffer->setRange(0, ptr - mAACBuffer->data());
Andreas Huberfb16f702010-12-10 15:08:23 -0800343
344 return accessUnitPosted;
Andreas Huberc751ecc2010-09-27 12:04:43 -0700345}
346
Andreas Huberfb16f702010-12-10 15:08:23 -0800347bool MPEG2TSWriter::SourceInfo::flushAACFrames() {
Andreas Huberc751ecc2010-09-27 12:04:43 -0700348 if (mAACBuffer == NULL) {
Andreas Huberfb16f702010-12-10 15:08:23 -0800349 return false;
Andreas Huberc751ecc2010-09-27 12:04:43 -0700350 }
351
352 sp<AMessage> notify = mNotify->dup();
353 notify->setInt32("what", kNotifyBuffer);
354 notify->setObject("buffer", mAACBuffer);
355 notify->post();
356
357 mAACBuffer.clear();
Andreas Huberfb16f702010-12-10 15:08:23 -0800358
359 return true;
360}
361
362void MPEG2TSWriter::SourceInfo::readMore() {
363 (new AMessage(kWhatRead, id()))->post();
Andreas Huberc751ecc2010-09-27 12:04:43 -0700364}
365
366void MPEG2TSWriter::SourceInfo::onMessageReceived(const sp<AMessage> &msg) {
367 switch (msg->what()) {
368 case kWhatStart:
369 {
370 status_t err = mSource->start();
371 if (err != OK) {
372 sp<AMessage> notify = mNotify->dup();
373 notify->setInt32("what", kNotifyStartFailed);
374 notify->post();
375 break;
376 }
377
378 extractCodecSpecificData();
379
Andreas Huberfb16f702010-12-10 15:08:23 -0800380 readMore();
Andreas Huberc751ecc2010-09-27 12:04:43 -0700381 break;
382 }
383
384 case kWhatRead:
385 {
386 MediaBuffer *buffer;
387 status_t err = mSource->read(&buffer);
388
389 if (err != OK && err != INFO_FORMAT_CHANGED) {
390 if (mStreamType == 0x0f) {
391 flushAACFrames();
392 }
393
394 sp<AMessage> notify = mNotify->dup();
395 notify->setInt32("what", kNotifyReachedEOS);
396 notify->setInt32("status", err);
397 notify->post();
398 break;
399 }
400
401 if (err == OK) {
Andreas Huber9adf4662010-10-12 14:17:45 -0700402 if (mStreamType == 0x0f && mAACCodecSpecificData == NULL) {
403 // The first buffer contains codec specific data.
404
405 CHECK_GE(buffer->range_length(), 2u);
406
407 mAACCodecSpecificData = new ABuffer(buffer->range_length());
408
409 memcpy(mAACCodecSpecificData->data(),
410 (const uint8_t *)buffer->data()
411 + buffer->range_offset(),
412 buffer->range_length());
413 } else if (buffer->range_length() > 0) {
Andreas Huberc751ecc2010-09-27 12:04:43 -0700414 if (mStreamType == 0x0f) {
Andreas Huberfb16f702010-12-10 15:08:23 -0800415 if (!appendAACFrames(buffer)) {
416 msg->post();
417 }
Andreas Huberc751ecc2010-09-27 12:04:43 -0700418 } else {
419 postAVCFrame(buffer);
420 }
421 }
422
423 buffer->release();
424 buffer = NULL;
425 }
426
Andreas Huberfb16f702010-12-10 15:08:23 -0800427 // Do not read more data until told to.
Andreas Huberc751ecc2010-09-27 12:04:43 -0700428 break;
429 }
430
431 default:
432 TRESPASS();
433 }
434}
435
Andreas Huberfb16f702010-12-10 15:08:23 -0800436sp<ABuffer> MPEG2TSWriter::SourceInfo::lastAccessUnit() {
437 return mLastAccessUnit;
438}
439
440void MPEG2TSWriter::SourceInfo::setLastAccessUnit(
441 const sp<ABuffer> &accessUnit) {
442 mLastAccessUnit = accessUnit;
443}
444
445int64_t MPEG2TSWriter::SourceInfo::lastAccessUnitTimeUs() {
446 if (mLastAccessUnit == NULL) {
447 return -1;
448 }
449
450 int64_t timeUs;
451 CHECK(mLastAccessUnit->meta()->findInt64("timeUs", &timeUs));
452
453 return timeUs;
454}
455
456void MPEG2TSWriter::SourceInfo::setEOSReceived() {
457 CHECK(!mEOSReceived);
458 mEOSReceived = true;
459}
460
461bool MPEG2TSWriter::SourceInfo::eosReceived() const {
462 return mEOSReceived;
463}
464
Andreas Huberc751ecc2010-09-27 12:04:43 -0700465////////////////////////////////////////////////////////////////////////////////
466
Andreas Huber9adf4662010-10-12 14:17:45 -0700467MPEG2TSWriter::MPEG2TSWriter(int fd)
James Dong2747e0e2010-11-18 20:59:13 -0800468 : mFile(fdopen(dup(fd), "wb")),
Andreas Huber068dbbf2011-06-27 15:47:56 -0700469 mWriteCookie(NULL),
470 mWriteFunc(NULL),
Andreas Huber9adf4662010-10-12 14:17:45 -0700471 mStarted(false),
472 mNumSourcesDone(0),
473 mNumTSPacketsWritten(0),
474 mNumTSPacketsBeforeMeta(0) {
475 init();
476}
477
Andreas Huberc751ecc2010-09-27 12:04:43 -0700478MPEG2TSWriter::MPEG2TSWriter(const char *filename)
479 : mFile(fopen(filename, "wb")),
Andreas Huber068dbbf2011-06-27 15:47:56 -0700480 mWriteCookie(NULL),
481 mWriteFunc(NULL),
482 mStarted(false),
483 mNumSourcesDone(0),
484 mNumTSPacketsWritten(0),
485 mNumTSPacketsBeforeMeta(0) {
486 init();
487}
488
489MPEG2TSWriter::MPEG2TSWriter(
490 void *cookie,
491 ssize_t (*write)(void *cookie, const void *data, size_t size))
492 : mFile(NULL),
493 mWriteCookie(cookie),
494 mWriteFunc(write),
Andreas Huberc751ecc2010-09-27 12:04:43 -0700495 mStarted(false),
496 mNumSourcesDone(0),
497 mNumTSPacketsWritten(0),
498 mNumTSPacketsBeforeMeta(0) {
Andreas Huber9adf4662010-10-12 14:17:45 -0700499 init();
500}
501
502void MPEG2TSWriter::init() {
Andreas Huber068dbbf2011-06-27 15:47:56 -0700503 CHECK(mFile != NULL || mWriteFunc != NULL);
Andreas Huberc751ecc2010-09-27 12:04:43 -0700504
505 mLooper = new ALooper;
506 mLooper->setName("MPEG2TSWriter");
507
508 mReflector = new AHandlerReflector<MPEG2TSWriter>(this);
509
510 mLooper->registerHandler(mReflector);
511 mLooper->start();
512}
513
514MPEG2TSWriter::~MPEG2TSWriter() {
Andreas Huber9adf4662010-10-12 14:17:45 -0700515 if (mStarted) {
516 stop();
517 }
518
Andreas Huberc751ecc2010-09-27 12:04:43 -0700519 mLooper->unregisterHandler(mReflector->id());
520 mLooper->stop();
521
Andreas Huber068dbbf2011-06-27 15:47:56 -0700522 if (mFile != NULL) {
523 fclose(mFile);
524 mFile = NULL;
525 }
Andreas Huberc751ecc2010-09-27 12:04:43 -0700526}
527
528status_t MPEG2TSWriter::addSource(const sp<MediaSource> &source) {
529 CHECK(!mStarted);
530
531 sp<MetaData> meta = source->getFormat();
532 const char *mime;
533 CHECK(meta->findCString(kKeyMIMEType, &mime));
534
535 if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
536 && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
537 return ERROR_UNSUPPORTED;
538 }
539
540 sp<SourceInfo> info = new SourceInfo(source);
541
542 mSources.push(info);
543
544 return OK;
545}
546
547status_t MPEG2TSWriter::start(MetaData *param) {
548 CHECK(!mStarted);
549
550 mStarted = true;
551 mNumSourcesDone = 0;
552 mNumTSPacketsWritten = 0;
553 mNumTSPacketsBeforeMeta = 0;
554
555 for (size_t i = 0; i < mSources.size(); ++i) {
556 sp<AMessage> notify =
557 new AMessage(kWhatSourceNotify, mReflector->id());
558
559 notify->setInt32("source-index", i);
560
561 mSources.editItemAt(i)->start(notify);
562 }
563
564 return OK;
565}
566
567status_t MPEG2TSWriter::stop() {
568 CHECK(mStarted);
569
570 for (size_t i = 0; i < mSources.size(); ++i) {
571 mSources.editItemAt(i)->stop();
572 }
573 mStarted = false;
574
575 return OK;
576}
577
578status_t MPEG2TSWriter::pause() {
579 CHECK(mStarted);
580
581 return OK;
582}
583
584bool MPEG2TSWriter::reachedEOS() {
585 return !mStarted || (mNumSourcesDone == mSources.size() ? true : false);
586}
587
588status_t MPEG2TSWriter::dump(int fd, const Vector<String16> &args) {
589 return OK;
590}
591
592void MPEG2TSWriter::onMessageReceived(const sp<AMessage> &msg) {
593 switch (msg->what()) {
594 case kWhatSourceNotify:
595 {
596 int32_t sourceIndex;
597 CHECK(msg->findInt32("source-index", &sourceIndex));
598
599 int32_t what;
600 CHECK(msg->findInt32("what", &what));
601
602 if (what == SourceInfo::kNotifyReachedEOS
603 || what == SourceInfo::kNotifyStartFailed) {
Andreas Huberfb16f702010-12-10 15:08:23 -0800604 sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
605 source->setEOSReceived();
606
607 sp<ABuffer> buffer = source->lastAccessUnit();
608 source->setLastAccessUnit(NULL);
609
610 if (buffer != NULL) {
611 writeTS();
612 writeAccessUnit(sourceIndex, buffer);
613 }
614
Andreas Huberc751ecc2010-09-27 12:04:43 -0700615 ++mNumSourcesDone;
616 } else if (what == SourceInfo::kNotifyBuffer) {
617 sp<RefBase> obj;
618 CHECK(msg->findObject("buffer", &obj));
619
Andreas Huberc751ecc2010-09-27 12:04:43 -0700620 sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
Andreas Huberfb16f702010-12-10 15:08:23 -0800621
622 int32_t oob;
623 if (msg->findInt32("oob", &oob) && oob) {
624 // This is codec specific data delivered out of band.
625 // It can be written out immediately.
626 writeTS();
627 writeAccessUnit(sourceIndex, buffer);
628 break;
629 }
630
631 // We don't just write out data as we receive it from
632 // the various sources. That would essentially write them
633 // out in random order (as the thread scheduler determines
634 // how the messages are dispatched).
635 // Instead we gather an access unit for all tracks and
636 // write out the one with the smallest timestamp, then
637 // request more data for the written out track.
638 // Rinse, repeat.
639 // If we don't have data on any track we don't write
640 // anything just yet.
641
642 sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
643
644 CHECK(source->lastAccessUnit() == NULL);
645 source->setLastAccessUnit(buffer);
646
Steve Block06ade6a2011-10-20 11:56:00 +0100647 ALOGV("lastAccessUnitTimeUs[%d] = %.2f secs",
Andreas Huberfb16f702010-12-10 15:08:23 -0800648 sourceIndex, source->lastAccessUnitTimeUs() / 1E6);
649
650 int64_t minTimeUs = -1;
651 size_t minIndex = 0;
652
653 for (size_t i = 0; i < mSources.size(); ++i) {
654 const sp<SourceInfo> &source = mSources.editItemAt(i);
655
656 if (source->eosReceived()) {
657 continue;
658 }
659
660 int64_t timeUs = source->lastAccessUnitTimeUs();
661 if (timeUs < 0) {
662 minTimeUs = -1;
663 break;
664 } else if (minTimeUs < 0 || timeUs < minTimeUs) {
665 minTimeUs = timeUs;
666 minIndex = i;
667 }
668 }
669
670 if (minTimeUs < 0) {
Steve Block06ade6a2011-10-20 11:56:00 +0100671 ALOGV("not a all tracks have valid data.");
Andreas Huberfb16f702010-12-10 15:08:23 -0800672 break;
673 }
674
Steve Block06ade6a2011-10-20 11:56:00 +0100675 ALOGV("writing access unit at time %.2f secs (index %d)",
Andreas Huberfb16f702010-12-10 15:08:23 -0800676 minTimeUs / 1E6, minIndex);
677
678 source = mSources.editItemAt(minIndex);
679
680 buffer = source->lastAccessUnit();
681 source->setLastAccessUnit(NULL);
682
683 writeTS();
684 writeAccessUnit(minIndex, buffer);
685
686 source->readMore();
Andreas Huberc751ecc2010-09-27 12:04:43 -0700687 }
688 break;
689 }
690
691 default:
692 TRESPASS();
693 }
694}
695
696void MPEG2TSWriter::writeProgramAssociationTable() {
697 // 0x47
698 // transport_error_indicator = b0
699 // payload_unit_start_indicator = b1
700 // transport_priority = b0
701 // PID = b0000000000000 (13 bits)
702 // transport_scrambling_control = b00
703 // adaptation_field_control = b01 (no adaptation field, payload only)
704 // continuity_counter = b????
705 // skip = 0x00
706 // --- payload follows
707 // table_id = 0x00
708 // section_syntax_indicator = b1
709 // must_be_zero = b0
710 // reserved = b11
711 // section_length = 0x00d
712 // transport_stream_id = 0x0000
713 // reserved = b11
714 // version_number = b00001
715 // current_next_indicator = b1
716 // section_number = 0x00
717 // last_section_number = 0x00
718 // one program follows:
719 // program_number = 0x0001
720 // reserved = b111
721 // program_map_PID = 0x01e0 (13 bits!)
722 // CRC = 0x????????
723
724 static const uint8_t kData[] = {
725 0x47,
726 0x40, 0x00, 0x10, 0x00, // b0100 0000 0000 0000 0001 ???? 0000 0000
727 0x00, 0xb0, 0x0d, 0x00, // b0000 0000 1011 0000 0000 1101 0000 0000
728 0x00, 0xc3, 0x00, 0x00, // b0000 0000 1100 0011 0000 0000 0000 0000
729 0x00, 0x01, 0xe1, 0xe0, // b0000 0000 0000 0001 1110 0001 1110 0000
730 0x00, 0x00, 0x00, 0x00 // b???? ???? ???? ???? ???? ???? ???? ????
731 };
732
733 sp<ABuffer> buffer = new ABuffer(188);
734 memset(buffer->data(), 0, buffer->size());
735 memcpy(buffer->data(), kData, sizeof(kData));
736
737 static const unsigned kContinuityCounter = 5;
738 buffer->data()[3] |= kContinuityCounter;
739
Andreas Huber068dbbf2011-06-27 15:47:56 -0700740 CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
Andreas Huberc751ecc2010-09-27 12:04:43 -0700741}
742
743void MPEG2TSWriter::writeProgramMap() {
744 // 0x47
745 // transport_error_indicator = b0
746 // payload_unit_start_indicator = b1
747 // transport_priority = b0
748 // PID = b0 0001 1110 0000 (13 bits) [0x1e0]
749 // transport_scrambling_control = b00
750 // adaptation_field_control = b01 (no adaptation field, payload only)
751 // continuity_counter = b????
752 // skip = 0x00
753 // -- payload follows
754 // table_id = 0x02
755 // section_syntax_indicator = b1
756 // must_be_zero = b0
757 // reserved = b11
758 // section_length = 0x???
759 // program_number = 0x0001
760 // reserved = b11
761 // version_number = b00001
762 // current_next_indicator = b1
763 // section_number = 0x00
764 // last_section_number = 0x00
765 // reserved = b111
766 // PCR_PID = b? ???? ???? ???? (13 bits)
767 // reserved = b1111
768 // program_info_length = 0x000
769 // one or more elementary stream descriptions follow:
770 // stream_type = 0x??
771 // reserved = b111
772 // elementary_PID = b? ???? ???? ???? (13 bits)
773 // reserved = b1111
774 // ES_info_length = 0x000
775 // CRC = 0x????????
776
777 static const uint8_t kData[] = {
778 0x47,
779 0x41, 0xe0, 0x10, 0x00, // b0100 0001 1110 0000 0001 ???? 0000 0000
780 0x02, 0xb0, 0x00, 0x00, // b0000 0010 1011 ???? ???? ???? 0000 0000
781 0x01, 0xc3, 0x00, 0x00, // b0000 0001 1100 0011 0000 0000 0000 0000
782 0xe0, 0x00, 0xf0, 0x00 // b111? ???? ???? ???? 1111 0000 0000 0000
783 };
784
785 sp<ABuffer> buffer = new ABuffer(188);
786 memset(buffer->data(), 0, buffer->size());
787 memcpy(buffer->data(), kData, sizeof(kData));
788
789 static const unsigned kContinuityCounter = 5;
790 buffer->data()[3] |= kContinuityCounter;
791
792 size_t section_length = 5 * mSources.size() + 4 + 9;
793 buffer->data()[6] |= section_length >> 8;
794 buffer->data()[7] = section_length & 0xff;
795
796 static const unsigned kPCR_PID = 0x1e1;
797 buffer->data()[13] |= (kPCR_PID >> 8) & 0x1f;
798 buffer->data()[14] = kPCR_PID & 0xff;
799
800 uint8_t *ptr = &buffer->data()[sizeof(kData)];
801 for (size_t i = 0; i < mSources.size(); ++i) {
802 *ptr++ = mSources.editItemAt(i)->streamType();
803
804 const unsigned ES_PID = 0x1e0 + i + 1;
805 *ptr++ = 0xe0 | (ES_PID >> 8);
806 *ptr++ = ES_PID & 0xff;
807 *ptr++ = 0xf0;
808 *ptr++ = 0x00;
809 }
810
811 *ptr++ = 0x00;
812 *ptr++ = 0x00;
813 *ptr++ = 0x00;
814 *ptr++ = 0x00;
815
Andreas Huber068dbbf2011-06-27 15:47:56 -0700816 CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
Andreas Huberc751ecc2010-09-27 12:04:43 -0700817}
818
819void MPEG2TSWriter::writeAccessUnit(
820 int32_t sourceIndex, const sp<ABuffer> &accessUnit) {
821 // 0x47
822 // transport_error_indicator = b0
823 // payload_unit_start_indicator = b1
824 // transport_priority = b0
825 // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
826 // transport_scrambling_control = b00
827 // adaptation_field_control = b01 (no adaptation field, payload only)
828 // continuity_counter = b????
829 // -- payload follows
830 // packet_startcode_prefix = 0x000001
831 // stream_id = 0x?? (0xe0 for avc video, 0xc0 for aac audio)
832 // PES_packet_length = 0x????
833 // reserved = b10
834 // PES_scrambling_control = b00
835 // PES_priority = b0
836 // data_alignment_indicator = b1
837 // copyright = b0
838 // original_or_copy = b0
839 // PTS_DTS_flags = b10 (PTS only)
840 // ESCR_flag = b0
841 // ES_rate_flag = b0
842 // DSM_trick_mode_flag = b0
843 // additional_copy_info_flag = b0
844 // PES_CRC_flag = b0
845 // PES_extension_flag = b0
846 // PES_header_data_length = 0x05
847 // reserved = b0010 (PTS)
848 // PTS[32..30] = b???
849 // reserved = b1
850 // PTS[29..15] = b??? ???? ???? ???? (15 bits)
851 // reserved = b1
852 // PTS[14..0] = b??? ???? ???? ???? (15 bits)
853 // reserved = b1
854 // the first fragment of "buffer" follows
855
856 sp<ABuffer> buffer = new ABuffer(188);
857 memset(buffer->data(), 0, buffer->size());
858
859 const unsigned PID = 0x1e0 + sourceIndex + 1;
860
861 const unsigned continuity_counter =
862 mSources.editItemAt(sourceIndex)->incrementContinuityCounter();
863
864 // XXX if there are multiple streams of a kind (more than 1 audio or
865 // more than 1 video) they need distinct stream_ids.
866 const unsigned stream_id =
867 mSources.editItemAt(sourceIndex)->streamType() == 0x0f ? 0xc0 : 0xe0;
868
869 int64_t timeUs;
870 CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
871
872 uint32_t PTS = (timeUs * 9ll) / 100ll;
873
874 size_t PES_packet_length = accessUnit->size() + 8;
875
Andreas Huber99bc1da2010-10-15 11:30:21 -0700876 if (PES_packet_length >= 65536) {
877 // This really should only happen for video.
878 CHECK_EQ(stream_id, 0xe0u);
879
880 // It's valid to set this to 0 for video according to the specs.
881 PES_packet_length = 0;
882 }
883
Andreas Huberc751ecc2010-09-27 12:04:43 -0700884 uint8_t *ptr = buffer->data();
885 *ptr++ = 0x47;
886 *ptr++ = 0x40 | (PID >> 8);
887 *ptr++ = PID & 0xff;
888 *ptr++ = 0x10 | continuity_counter;
889 *ptr++ = 0x00;
890 *ptr++ = 0x00;
891 *ptr++ = 0x01;
892 *ptr++ = stream_id;
893 *ptr++ = PES_packet_length >> 8;
894 *ptr++ = PES_packet_length & 0xff;
895 *ptr++ = 0x84;
896 *ptr++ = 0x80;
897 *ptr++ = 0x05;
898 *ptr++ = 0x20 | (((PTS >> 30) & 7) << 1) | 1;
899 *ptr++ = (PTS >> 22) & 0xff;
900 *ptr++ = (((PTS >> 15) & 0x7f) << 1) | 1;
901 *ptr++ = (PTS >> 7) & 0xff;
902 *ptr++ = ((PTS & 0x7f) << 1) | 1;
903
904 size_t sizeLeft = buffer->data() + buffer->size() - ptr;
905 size_t copy = accessUnit->size();
906 if (copy > sizeLeft) {
907 copy = sizeLeft;
908 }
909
910 memcpy(ptr, accessUnit->data(), copy);
911
Andreas Huber068dbbf2011-06-27 15:47:56 -0700912 CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
Andreas Huberc751ecc2010-09-27 12:04:43 -0700913
914 size_t offset = copy;
915 while (offset < accessUnit->size()) {
916 // for subsequent fragments of "buffer":
917 // 0x47
918 // transport_error_indicator = b0
919 // payload_unit_start_indicator = b0
920 // transport_priority = b0
921 // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
922 // transport_scrambling_control = b00
923 // adaptation_field_control = b01 (no adaptation field, payload only)
924 // continuity_counter = b????
925 // the fragment of "buffer" follows.
926
927 memset(buffer->data(), 0, buffer->size());
928
929 const unsigned continuity_counter =
930 mSources.editItemAt(sourceIndex)->incrementContinuityCounter();
931
932 ptr = buffer->data();
933 *ptr++ = 0x47;
934 *ptr++ = 0x00 | (PID >> 8);
935 *ptr++ = PID & 0xff;
936 *ptr++ = 0x10 | continuity_counter;
937
938 size_t sizeLeft = buffer->data() + buffer->size() - ptr;
939 size_t copy = accessUnit->size() - offset;
940 if (copy > sizeLeft) {
941 copy = sizeLeft;
942 }
943
944 memcpy(ptr, accessUnit->data() + offset, copy);
Andreas Huber068dbbf2011-06-27 15:47:56 -0700945 CHECK_EQ(internalWrite(buffer->data(), buffer->size()),
Andreas Huberc751ecc2010-09-27 12:04:43 -0700946 buffer->size());
947
948 offset += copy;
949 }
950}
951
952void MPEG2TSWriter::writeTS() {
953 if (mNumTSPacketsWritten >= mNumTSPacketsBeforeMeta) {
954 writeProgramAssociationTable();
955 writeProgramMap();
956
957 mNumTSPacketsBeforeMeta = mNumTSPacketsWritten + 2500;
958 }
959}
960
Andreas Huber068dbbf2011-06-27 15:47:56 -0700961ssize_t MPEG2TSWriter::internalWrite(const void *data, size_t size) {
962 if (mFile != NULL) {
963 return fwrite(data, 1, size, mFile);
964 }
965
966 return (*mWriteFunc)(mWriteCookie, data, size);
967}
968
Andreas Huberc751ecc2010-09-27 12:04:43 -0700969} // namespace android
970