| | 113 | /// This tries to find TS sync bytes at 188, 204,and 208 byte intervals. |
| | 114 | /// If it finds them it returns kStreamTypeTS otherwise it returns |
| | 115 | /// kStreamTypePES. Ideally we'd really detect PES streams and return |
| | 116 | /// kStreamTypeUnknown if it isn't a PES stream either, but this is |
| | 117 | /// a start. |
| | 118 | static IPTVSignalMonitor::StreamType detect_stream_type( |
| | 119 | const vector<unsigned char> &data) |
| | 120 | { |
| | 121 | IPTVSignalMonitor::StreamType st = IPTVSignalMonitor::kStreamTypePES; |
| | 122 | |
| | 123 | QList<uint> sync_locations; |
| | 124 | for (uint i = 0; i < data.size(); i++) |
| | 125 | { |
| | 126 | if (SYNC_BYTE == data[i]) |
| | 127 | sync_locations.push_back(i); |
| | 128 | } |
| | 129 | |
| | 130 | if (sync_locations.empty()) |
| | 131 | return st; |
| | 132 | |
| | 133 | QMap<uint, uint> counts; |
| | 134 | |
| | 135 | QSet<uint> sizes; |
| | 136 | sizes.insert(sizeof(TSPacket)); |
| | 137 | sizes.insert(sizeof(TSDVBEmissionPacket)); |
| | 138 | sizes.insert(sizeof(TSISDBEmissionPacket)); |
| | 139 | sizes.insert(sizeof(TS8VSBEmissionPacket)); |
| | 140 | |
| | 141 | QSet<uint>::const_iterator sit = sizes.begin(); |
| | 142 | for (; sit != sizes.end(); ++sit) |
| | 143 | { |
| | 144 | uint count = 0; |
| | 145 | uint last_loc = sync_locations[0]; |
| | 146 | for (uint i = 1; i < data.size(); i++) |
| | 147 | { |
| | 148 | uint next = i + 1; |
| | 149 | for (uint j = i; j < data.size() && data[j] <= last_loc + *sit; j++) |
| | 150 | { |
| | 151 | if (data[j] == last_loc + *sit) |
| | 152 | { |
| | 153 | count++; |
| | 154 | next = j; |
| | 155 | break; |
| | 156 | } |
| | 157 | } |
| | 158 | } |
| | 159 | counts[*sit] = count; |
| | 160 | } |
| | 161 | |
| | 162 | for (sit = sizes.begin(); sit != sizes.end(); ++sit) |
| | 163 | { |
| | 164 | int expected = (data.size() / *sit) - 1; |
| | 165 | LOG(VB_GENERAL, LOG_INFO, QString("Count for %1 was %2, expected %3") |
| | 166 | .arg(*sit).arg(counts[*sit]).arg(expected)); |
| | 167 | if ((counts[*sit] >= 1) && (expected >= 1) && |
| | 168 | (counts[*sit] >= (expected * 0.8f))) |
| | 169 | { |
| | 170 | st = IPTVSignalMonitor::kStreamTypeTS; |
| | 171 | } |
| | 172 | } |
| | 173 | |
| | 174 | return st; |
| | 175 | } |
| | 176 | |
| | 182 | if (kStreamTypeUnknown != streamType) |
| | 183 | return; |
| | 184 | |
| | 185 | if (streamTypeDetectionBuffer.size() < kStreamTypeDetectionMinSize) |
| | 186 | { |
| | 187 | uint old_size = streamTypeDetectionBuffer.size(); |
| | 188 | streamTypeDetectionBuffer.resize(old_size + dataSize); |
| | 189 | memcpy(&streamTypeDetectionBuffer[old_size], data, dataSize); |
| | 190 | } |
| | 191 | |
| | 192 | if (streamTypeDetectionBuffer.size() >= kStreamTypeDetectionMinSize) |
| | 193 | { |
| | 194 | streamType = detect_stream_type(streamTypeDetectionBuffer); |
| | 195 | streamTypeDetectionBuffer.clear(); |
| | 196 | LOG(VB_GENERAL, LOG_INFO, LOC + QString("AddData(...%1) st %2") |
| | 197 | .arg(dataSize).arg(streamType)); |
| | 198 | } |
| | 199 | |
| | 200 | if (kStreamTypePES == streamType) |
| | 201 | { |
| | 202 | QMutexLocker locker(&statusLock); |
| | 203 | RemoveFlags(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT | |
| | 204 | kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT | |
| | 205 | kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT | |
| | 206 | kDTVSigMon_WaitForCrypt); |
| | 207 | } |