diff options
author | Andreas Huber <andih@google.com> | 2012-10-30 15:53:03 -0700 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2012-10-31 09:21:24 -0700 |
commit | 90a92053219ae50ddf4bb54e3d54db2d309e2b8d (patch) | |
tree | 1d624b3c800a6cd2e755c379058bb43949f91ab0 /media/libstagefright/wifi-display/source/TSPacketizer.cpp | |
parent | 2295ce2c6fcf07ffaa134440691a8cea5fe35b43 (diff) |
Various tweaks to wfd
related-to-bug: 7426218
Squashed commit of the following:
commit 1553f1a1c66af998674168f7f7a3be23fcb0c794
Author: Andreas Huber <andih@google.com>
Date: Tue Oct 30 15:51:27 2012 -0700
Add LPCM, AVC and AVC HRD descriptors as necessary.
Change-Id: Ibc836fced0fe37e8a25574c2295e886765b9ea6f
commit 4e74db61d2d31ebe239acbdec8f110f88016a4ea
Author: Andreas Huber <andih@google.com>
Date: Tue Oct 30 15:50:52 2012 -0700
added copyright headers to Sender.{cpp,h}
Change-Id: If615ccb8767e32bd83ed1f0f669acc39a72489f6
commit 7144bf8ae68c5cdb8faa6e219547aabbd750f04e
Author: Andreas Huber <andih@google.com>
Date: Tue Oct 30 15:50:25 2012 -0700
Reenable suspension of the RepeaterSource
Change-Id: I765338fcde89c65e4b69be45a5949eba6bcdcf6f
commit 812164bcfa0699821d7d8eefcc0dff96b2e2cd08
Author: Andreas Huber <andih@google.com>
Date: Tue Oct 30 14:03:50 2012 -0700
Add 2 stuffing bytes to the PES headers for audio tracks.
Change-Id: I8b9c634f6a565ab7fa7ecdb610f7d8557e0b139b
commit a084a741a63015d47c92d99fcd8b980fe615dc7d
Author: Andreas Huber <andih@google.com>
Date: Tue Oct 30 13:19:38 2012 -0700
Fix PCM audio packetization in WFD.
Change-Id: I99a435f9fe6b4397f24d6c22afae5ae2505ffc14
commit c5cb9369585f701f34bce41534940d5f9b59248f
Author: Andreas Huber <andih@google.com>
Date: Tue Oct 30 13:19:12 2012 -0700
Support extraction of PCM audio from transport streams.
Change-Id: I28a0516756ebcb5587325b6588df013ac871ffb9
commit b0a0512300ae037d6b39c2d04952d34b5fc12b2d
Author: Andreas Huber <andih@google.com>
Date: Tue Oct 30 08:54:13 2012 -0700
disable suspend of the RepeaterSource
Change-Id: Ibf42a98185b0567f817ae582a82e6580f95d3d40
commit 4330e8b7668dc92a6d882b5622c0697cf292d04c
Author: Andreas Huber <andih@google.com>
Date: Mon Oct 29 14:11:25 2012 -0700
Better handling of datagrams in ANetworkSession
reduce unnecessary copy overhead.
Change-Id: I2ed8c767274ba07764f03e8d4913041168e5755f
commit a44e73c322ba3f2c336f7cc4e1d63d3a74faa75d
Author: Andreas Huber <andih@google.com>
Date: Mon Oct 29 11:14:47 2012 -0700
Network traffic is now handled on a separate thread.
Audio and video are queued to ensure proper A/V interleaving.
Scheduled packet sends according to capture timestamps to reduce
send-jitter.
Change-Id: Ibd6357c1e663086cf87bec0a98f8e54dfdfaa0e5
related-to-bug: 7426218
Change-Id: Ia440129d656c35814abf18df06da50b73d5bb554
Diffstat (limited to 'media/libstagefright/wifi-display/source/TSPacketizer.cpp')
-rw-r--r-- | media/libstagefright/wifi-display/source/TSPacketizer.cpp | 159 |
1 files changed, 146 insertions, 13 deletions
diff --git a/media/libstagefright/wifi-display/source/TSPacketizer.cpp b/media/libstagefright/wifi-display/source/TSPacketizer.cpp index 7e660724..a5679ad9 100644 --- a/media/libstagefright/wifi-display/source/TSPacketizer.cpp +++ b/media/libstagefright/wifi-display/source/TSPacketizer.cpp @@ -49,10 +49,16 @@ struct TSPacketizer::Track : public RefBase { bool isH264() const; bool isAAC() const; bool lacksADTSHeader() const; + bool isPCMAudio() const; sp<ABuffer> prependCSD(const sp<ABuffer> &accessUnit) const; sp<ABuffer> prependADTSHeader(const sp<ABuffer> &accessUnit) const; + size_t countDescriptors() const; + sp<ABuffer> descriptorAt(size_t index) const; + + void finalize(); + protected: virtual ~Track(); @@ -67,7 +73,10 @@ private: AString mMIME; Vector<sp<ABuffer> > mCSD; + Vector<sp<ABuffer> > mDescriptors; + bool mAudioLacksATDSHeaders; + bool mFinalized; DISALLOW_EVIL_CONSTRUCTORS(Track); }; @@ -80,7 +89,8 @@ TSPacketizer::Track::Track( mStreamType(streamType), mStreamID(streamID), mContinuityCounter(0), - mAudioLacksATDSHeaders(false) { + mAudioLacksATDSHeaders(false), + mFinalized(false) { CHECK(format->findString("mime", &mMIME)); if (!strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_VIDEO_AVC) @@ -144,6 +154,10 @@ bool TSPacketizer::Track::isAAC() const { return !strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_AUDIO_AAC); } +bool TSPacketizer::Track::isPCMAudio() const { + return !strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_AUDIO_RAW); +} + bool TSPacketizer::Track::lacksADTSHeader() const { return mAudioLacksATDSHeaders; } @@ -213,6 +227,96 @@ sp<ABuffer> TSPacketizer::Track::prependADTSHeader( return dup; } +size_t TSPacketizer::Track::countDescriptors() const { + return mDescriptors.size(); +} + +sp<ABuffer> TSPacketizer::Track::descriptorAt(size_t index) const { + CHECK_LT(index, mDescriptors.size()); + return mDescriptors.itemAt(index); +} + +void TSPacketizer::Track::finalize() { + if (mFinalized) { + return; + } + + if (isH264()) { + { + // AVC video descriptor (40) + + sp<ABuffer> descriptor = new ABuffer(6); + uint8_t *data = descriptor->data(); + data[0] = 40; // descriptor_tag + data[1] = 4; // descriptor_length + + CHECK_EQ(mCSD.size(), 1u); + const sp<ABuffer> &sps = mCSD.itemAt(0); + CHECK(!memcmp("\x00\x00\x00\x01", sps->data(), 4)); + CHECK_GE(sps->size(), 7u); + // profile_idc, constraint_set*, level_idc + memcpy(&data[2], sps->data() + 4, 3); + + // AVC_still_present=0, AVC_24_hour_picture_flag=0, reserved + data[5] = 0x3f; + + mDescriptors.push_back(descriptor); + } + + { + // AVC timing and HRD descriptor (42) + + sp<ABuffer> descriptor = new ABuffer(4); + uint8_t *data = descriptor->data(); + data[0] = 42; // descriptor_tag + data[1] = 2; // descriptor_length + + // hrd_management_valid_flag = 0 + // reserved = 111111b + // picture_and_timing_info_present = 0 + + data[2] = 0x7e; + + // fixed_frame_rate_flag = 0 + // temporal_poc_flag = 0 + // picture_to_display_conversion_flag = 0 + // reserved = 11111b + data[3] = 0x1f; + + mDescriptors.push_back(descriptor); + } + } else if (isPCMAudio()) { + // LPCM audio stream descriptor (0x83) + + int32_t channelCount; + CHECK(mFormat->findInt32("channel-count", &channelCount)); + CHECK_EQ(channelCount, 2); + + int32_t sampleRate; + CHECK(mFormat->findInt32("sample-rate", &sampleRate)); + CHECK(sampleRate == 44100 || sampleRate == 48000); + + sp<ABuffer> descriptor = new ABuffer(4); + uint8_t *data = descriptor->data(); + data[0] = 0x83; // descriptor_tag + data[1] = 2; // descriptor_length + + unsigned sampling_frequency = (sampleRate == 44100) ? 1 : 2; + + data[2] = (sampling_frequency << 5) + | (3 /* reserved */ << 1) + | 0 /* emphasis_flag */; + + data[3] = + (1 /* number_of_channels = stereo */ << 5) + | 0xf /* reserved */; + + mDescriptors.push_back(descriptor); + } + + mFinalized = true; +} + //////////////////////////////////////////////////////////////////////////////// TSPacketizer::TSPacketizer() @@ -289,7 +393,8 @@ status_t TSPacketizer::packetize( const sp<ABuffer> &_accessUnit, sp<ABuffer> *packets, uint32_t flags, - const uint8_t *PES_private_data, size_t PES_private_data_len) { + const uint8_t *PES_private_data, size_t PES_private_data_len, + size_t numStuffingBytes) { sp<ABuffer> accessUnit = _accessUnit; int64_t timeUs; @@ -347,7 +452,7 @@ status_t TSPacketizer::packetize( // reserved = b1 // the first fragment of "buffer" follows - size_t PES_packet_length = accessUnit->size() + 8; + size_t PES_packet_length = accessUnit->size() + 8 + numStuffingBytes; if (PES_private_data_len > 0) { PES_packet_length += PES_private_data_len + 1; } @@ -410,7 +515,7 @@ status_t TSPacketizer::packetize( *ptr++ = 0x10 | mPATContinuityCounter; *ptr++ = 0x00; - const uint8_t *crcDataStart = ptr; + uint8_t *crcDataStart = ptr; *ptr++ = 0x00; *ptr++ = 0xb0; *ptr++ = 0x0d; @@ -472,8 +577,6 @@ status_t TSPacketizer::packetize( mPMTContinuityCounter = 0; } - size_t section_length = 5 * mTracks.size() + 4 + 9; - ptr = packetDataStart; *ptr++ = 0x47; *ptr++ = 0x40 | (kPID_PMT >> 8); @@ -483,8 +586,10 @@ status_t TSPacketizer::packetize( crcDataStart = ptr; *ptr++ = 0x02; - *ptr++ = 0xb0 | (section_length >> 8); - *ptr++ = section_length & 0xff; + + *ptr++ = 0x00; // section_length to be filled in below. + *ptr++ = 0x00; + *ptr++ = 0x00; *ptr++ = 0x01; *ptr++ = 0xc3; @@ -498,14 +603,34 @@ status_t TSPacketizer::packetize( for (size_t i = 0; i < mTracks.size(); ++i) { const sp<Track> &track = mTracks.itemAt(i); + // Make sure all the decriptors have been added. + track->finalize(); + *ptr++ = track->streamType(); *ptr++ = 0xe0 | (track->PID() >> 8); *ptr++ = track->PID() & 0xff; - *ptr++ = 0xf0; - *ptr++ = 0x00; + + size_t ES_info_length = 0; + for (size_t i = 0; i < track->countDescriptors(); ++i) { + ES_info_length += track->descriptorAt(i)->size(); + } + CHECK_LE(ES_info_length, 0xfff); + + *ptr++ = 0xf0 | (ES_info_length >> 8); + *ptr++ = (ES_info_length & 0xff); + + for (size_t i = 0; i < track->countDescriptors(); ++i) { + const sp<ABuffer> &descriptor = track->descriptorAt(i); + memcpy(ptr, descriptor->data(), descriptor->size()); + ptr += descriptor->size(); + } } - CHECK_EQ(ptr - crcDataStart, 12 + mTracks.size() * 5); + size_t section_length = ptr - (crcDataStart + 3) + 4 /* CRC */; + + crcDataStart[1] = 0xb0 | (section_length >> 8); + crcDataStart[2] = section_length & 0xff; + crc = htonl(crc32(crcDataStart, ptr - crcDataStart)); memcpy(ptr, &crc, 4); ptr += 4; @@ -601,8 +726,12 @@ status_t TSPacketizer::packetize( *ptr++ = 0x84; *ptr++ = (PES_private_data_len > 0) ? 0x81 : 0x80; - *ptr++ = (PES_private_data_len > 0) - ? (1 + PES_private_data_len + 0x05) : 0x05; + size_t headerLength = 0x05 + numStuffingBytes; + if (PES_private_data_len > 0) { + headerLength += 1 + PES_private_data_len; + } + + *ptr++ = headerLength; *ptr++ = 0x20 | (((PTS >> 30) & 7) << 1) | 1; *ptr++ = (PTS >> 22) & 0xff; @@ -616,6 +745,10 @@ status_t TSPacketizer::packetize( ptr += PES_private_data_len; } + for (size_t i = 0; i < numStuffingBytes; ++i) { + *ptr++ = 0xff; + } + // 18 bytes of TS/PES header leave 188 - 18 = 170 bytes for the payload size_t sizeLeft = packetDataStart + 188 - ptr; |