Merge "TunerHAL Handle PES Header in MediaFilterHandler"
diff --git a/tv/tuner/aidl/default/Filter.cpp b/tv/tuner/aidl/default/Filter.cpp
index 3b9ca43..ade265c 100644
--- a/tv/tuner/aidl/default/Filter.cpp
+++ b/tv/tuner/aidl/default/Filter.cpp
@@ -853,11 +853,17 @@
return ::ndk::ScopedAStatus::ok();
}
+// Read PES (Packetized Elementary Stream) Packets from TransportStreams
+// as defined in ISO/IEC 13818-1 Section 2.4.3.6. Create MediaEvents
+// containing only their data without TS or PES headers.
::ndk::ScopedAStatus Filter::startMediaFilterHandler() {
if (mFilterOutput.empty()) {
return ::ndk::ScopedAStatus::ok();
}
+ // mPts being set before our MediaFilterHandler begins indicates that all
+ // metadata has already been handled. We can therefore create an event
+ // with the existing data. This method is used when processing ES files.
::ndk::ScopedAStatus result;
if (mPts) {
result = createMediaFilterEventWithIon(mFilterOutput);
@@ -868,17 +874,38 @@
}
for (int i = 0; i < mFilterOutput.size(); i += 188) {
+ // Every packet has a 4 Byte TS Header preceding it
+ uint32_t headerSize = 4;
+
if (mPesSizeLeft == 0) {
- uint32_t prefix = (mFilterOutput[i + 4] << 16) | (mFilterOutput[i + 5] << 8) |
- mFilterOutput[i + 6];
+ // Packet Start Code Prefix is defined as the first 3 bytes of
+ // the PES Header and should always have the value 0x000001
+ uint32_t prefix = (static_cast<uint8_t>(mFilterOutput[i + 4]) << 16) |
+ (static_cast<uint8_t>(mFilterOutput[i + 5]) << 8) |
+ static_cast<uint8_t>(mFilterOutput[i + 6]);
if (DEBUG_FILTER) {
ALOGD("[Filter] prefix %d", prefix);
}
if (prefix == 0x000001) {
- // TODO handle mulptiple Pes filters
+ // TODO handle multiple Pes filters
+ // Location of PES fields from ISO/IEC 13818-1 Section 2.4.3.6
mPesSizeLeft = (static_cast<uint8_t>(mFilterOutput[i + 8]) << 8) |
static_cast<uint8_t>(mFilterOutput[i + 9]);
- mPesSizeLeft += 6;
+ bool hasPts = static_cast<uint8_t>(mFilterOutput[i + 11]) & 0x80;
+ uint8_t optionalFieldsLength = static_cast<uint8_t>(mFilterOutput[i + 12]);
+ headerSize += 9 + optionalFieldsLength;
+
+ if (hasPts) {
+ // Pts is a 33-bit field which is stored across 5 bytes, with
+ // bits in between as reserved fields which must be ignored
+ mPts = 0;
+ mPts |= (static_cast<uint8_t>(mFilterOutput[i + 13]) & 0x0e) << 29;
+ mPts |= (static_cast<uint8_t>(mFilterOutput[i + 14]) & 0xff) << 22;
+ mPts |= (static_cast<uint8_t>(mFilterOutput[i + 15]) & 0xfe) << 14;
+ mPts |= (static_cast<uint8_t>(mFilterOutput[i + 16]) & 0xff) << 7;
+ mPts |= (static_cast<uint8_t>(mFilterOutput[i + 17]) & 0xfe) >> 1;
+ }
+
if (DEBUG_FILTER) {
ALOGD("[Filter] pes data length %d", mPesSizeLeft);
}
@@ -887,10 +914,10 @@
}
}
- uint32_t endPoint = min(184u, mPesSizeLeft);
+ uint32_t endPoint = min(188u - headerSize, mPesSizeLeft);
// append data and check size
- vector<int8_t>::const_iterator first = mFilterOutput.begin() + i + 4;
- vector<int8_t>::const_iterator last = mFilterOutput.begin() + i + 4 + endPoint;
+ vector<int8_t>::const_iterator first = mFilterOutput.begin() + i + headerSize;
+ vector<int8_t>::const_iterator last = mFilterOutput.begin() + i + headerSize + endPoint;
mPesOutput.insert(mPesOutput.end(), first, last);
// size does not match then continue
mPesSizeLeft -= endPoint;