summaryrefslogtreecommitdiff
path: root/media/libstagefright/wifi-display/source/TSPacketizer.cpp
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2012-10-30 15:53:03 -0700
committerAndreas Huber <andih@google.com>2012-10-31 09:21:24 -0700
commit90a92053219ae50ddf4bb54e3d54db2d309e2b8d (patch)
tree1d624b3c800a6cd2e755c379058bb43949f91ab0 /media/libstagefright/wifi-display/source/TSPacketizer.cpp
parent2295ce2c6fcf07ffaa134440691a8cea5fe35b43 (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.cpp159
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;