| 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 | } |