diff options
Diffstat (limited to 'media/libstagefright/MPEG2TSWriter.cpp')
-rw-r--r-- | media/libstagefright/MPEG2TSWriter.cpp | 100 |
1 files changed, 81 insertions, 19 deletions
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp index f702376..217c17a 100644 --- a/media/libstagefright/MPEG2TSWriter.cpp +++ b/media/libstagefright/MPEG2TSWriter.cpp @@ -28,6 +28,7 @@ #include <media/stagefright/MediaSource.h> #include <media/stagefright/MetaData.h> #include <media/stagefright/Utils.h> +#include <arpa/inet.h> #include "include/ESDS.h" @@ -471,7 +472,9 @@ MPEG2TSWriter::MPEG2TSWriter(int fd) mStarted(false), mNumSourcesDone(0), mNumTSPacketsWritten(0), - mNumTSPacketsBeforeMeta(0) { + mNumTSPacketsBeforeMeta(0), + mPATContinuityCounter(0), + mPMTContinuityCounter(0) { init(); } @@ -482,7 +485,9 @@ MPEG2TSWriter::MPEG2TSWriter(const char *filename) mStarted(false), mNumSourcesDone(0), mNumTSPacketsWritten(0), - mNumTSPacketsBeforeMeta(0) { + mNumTSPacketsBeforeMeta(0), + mPATContinuityCounter(0), + mPMTContinuityCounter(0) { init(); } @@ -495,13 +500,17 @@ MPEG2TSWriter::MPEG2TSWriter( mStarted(false), mNumSourcesDone(0), mNumTSPacketsWritten(0), - mNumTSPacketsBeforeMeta(0) { + mNumTSPacketsBeforeMeta(0), + mPATContinuityCounter(0), + mPMTContinuityCounter(0) { init(); } void MPEG2TSWriter::init() { CHECK(mFile != NULL || mWriteFunc != NULL); + initCrcTable(); + mLooper = new ALooper; mLooper->setName("MPEG2TSWriter"); @@ -729,11 +738,16 @@ void MPEG2TSWriter::writeProgramAssociationTable() { }; sp<ABuffer> buffer = new ABuffer(188); - memset(buffer->data(), 0, buffer->size()); + memset(buffer->data(), 0xff, buffer->size()); memcpy(buffer->data(), kData, sizeof(kData)); - static const unsigned kContinuityCounter = 5; - buffer->data()[3] |= kContinuityCounter; + if (++mPATContinuityCounter == 16) { + mPATContinuityCounter = 0; + } + buffer->data()[3] |= mPATContinuityCounter; + + uint32_t crc = htonl(crc32(&buffer->data()[5], 12)); + memcpy(&buffer->data()[17], &crc, sizeof(crc)); CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size()); } @@ -781,11 +795,13 @@ void MPEG2TSWriter::writeProgramMap() { }; sp<ABuffer> buffer = new ABuffer(188); - memset(buffer->data(), 0, buffer->size()); + memset(buffer->data(), 0xff, buffer->size()); memcpy(buffer->data(), kData, sizeof(kData)); - static const unsigned kContinuityCounter = 5; - buffer->data()[3] |= kContinuityCounter; + if (++mPMTContinuityCounter == 16) { + mPMTContinuityCounter = 0; + } + buffer->data()[3] |= mPMTContinuityCounter; size_t section_length = 5 * mSources.size() + 4 + 9; buffer->data()[6] |= section_length >> 8; @@ -806,10 +822,8 @@ void MPEG2TSWriter::writeProgramMap() { *ptr++ = 0x00; } - *ptr++ = 0x00; - *ptr++ = 0x00; - *ptr++ = 0x00; - *ptr++ = 0x00; + uint32_t crc = htonl(crc32(&buffer->data()[5], 12+mSources.size()*5)); + memcpy(&buffer->data()[17+mSources.size()*5], &crc, sizeof(crc)); CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size()); } @@ -822,7 +836,7 @@ void MPEG2TSWriter::writeAccessUnit( // transport_priority = b0 // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex] // transport_scrambling_control = b00 - // adaptation_field_control = b01 (no adaptation field, payload only) + // adaptation_field_control = b?? // continuity_counter = b???? // -- payload follows // packet_startcode_prefix = 0x000001 @@ -852,7 +866,7 @@ void MPEG2TSWriter::writeAccessUnit( // the first fragment of "buffer" follows sp<ABuffer> buffer = new ABuffer(188); - memset(buffer->data(), 0, buffer->size()); + memset(buffer->data(), 0xff, buffer->size()); const unsigned PID = 0x1e0 + sourceIndex + 1; @@ -870,6 +884,7 @@ void MPEG2TSWriter::writeAccessUnit( uint32_t PTS = (timeUs * 9ll) / 100ll; size_t PES_packet_length = accessUnit->size() + 8; + bool padding = (accessUnit->size() < (188 - 18)); if (PES_packet_length >= 65536) { // This really should only happen for video. @@ -883,7 +898,15 @@ void MPEG2TSWriter::writeAccessUnit( *ptr++ = 0x47; *ptr++ = 0x40 | (PID >> 8); *ptr++ = PID & 0xff; - *ptr++ = 0x10 | continuity_counter; + *ptr++ = (padding ? 0x30 : 0x10) | continuity_counter; + if (padding) { + int paddingSize = 188 - accessUnit->size() - 18; + *ptr++ = paddingSize - 1; + if (paddingSize >= 2) { + *ptr++ = 0x00; + ptr += paddingSize - 2; + } + } *ptr++ = 0x00; *ptr++ = 0x00; *ptr++ = 0x01; @@ -911,6 +934,7 @@ void MPEG2TSWriter::writeAccessUnit( size_t offset = copy; while (offset < accessUnit->size()) { + bool lastAccessUnit = ((accessUnit->size() - offset) < 183); // for subsequent fragments of "buffer": // 0x47 // transport_error_indicator = b0 @@ -918,11 +942,11 @@ void MPEG2TSWriter::writeAccessUnit( // transport_priority = b0 // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex] // transport_scrambling_control = b00 - // adaptation_field_control = b01 (no adaptation field, payload only) + // adaptation_field_control = b?? // continuity_counter = b???? // the fragment of "buffer" follows. - memset(buffer->data(), 0, buffer->size()); + memset(buffer->data(), 0xff, buffer->size()); const unsigned continuity_counter = mSources.editItemAt(sourceIndex)->incrementContinuityCounter(); @@ -931,7 +955,18 @@ void MPEG2TSWriter::writeAccessUnit( *ptr++ = 0x47; *ptr++ = 0x00 | (PID >> 8); *ptr++ = PID & 0xff; - *ptr++ = 0x10 | continuity_counter; + *ptr++ = (lastAccessUnit ? 0x30 : 0x10) | continuity_counter; + + if (lastAccessUnit) { + // Pad packet using an adaptation field + // Adaptation header all to 0 execpt size + uint8_t paddingSize = (uint8_t)184 - (accessUnit->size() - offset); + *ptr++ = paddingSize - 1; + if (paddingSize >= 2) { + *ptr++ = 0x00; + ptr += paddingSize - 2; + } + } size_t sizeLeft = buffer->data() + buffer->size() - ptr; size_t copy = accessUnit->size() - offset; @@ -956,6 +991,33 @@ void MPEG2TSWriter::writeTS() { } } +void MPEG2TSWriter::initCrcTable() { + uint32_t poly = 0x04C11DB7; + + for (int i = 0; i < 256; i++) { + uint32_t crc = i << 24; + for (int j = 0; j < 8; j++) { + crc = (crc << 1) ^ ((crc & 0x80000000) ? (poly) : 0); + } + mCrcTable[i] = crc; + } +} + +/** + * Compute CRC32 checksum for buffer starting at offset start and for length + * bytes. + */ +uint32_t MPEG2TSWriter::crc32(const uint8_t *p_start, size_t length) { + uint32_t crc = 0xFFFFFFFF; + const uint8_t *p; + + for (p = p_start; p < p_start + length; p++) { + crc = (crc << 8) ^ mCrcTable[((crc >> 24) ^ *p) & 0xFF]; + } + + return crc; +} + ssize_t MPEG2TSWriter::internalWrite(const void *data, size_t size) { if (mFile != NULL) { return fwrite(data, 1, size, mFile); |