Ticket #7205: 0003-Generate-PSI-packets-for-broken-firmware-cable-boxes.patch
File 0003-Generate-PSI-packets-for-broken-firmware-cable-boxes.patch, 13.1 KB (added by , 13 years ago) |
---|
-
mythtv/libs/libmythtv/darwinfirewiredevice.cpp
From ca5f31b9e4fb1368cf23a7144fd55c445c0bd107 Mon Sep 17 00:00:00 2001 From: Chase Douglas <chase.douglas@canonical.com> Date: Sun, 31 Jul 2011 10:46:29 -0700 Subject: [PATCH 3/4] Generate PSI packets for broken firmware cable boxes If the firewire_gen_psip option is set for the capture device, generate MPEG2-TS PAT and PMT packets (aka Program Specific Information (PSI) packets). --- mythtv/libs/libmythtv/darwinfirewiredevice.cpp | 4 +- mythtv/libs/libmythtv/darwinfirewiredevice.h | 3 +- mythtv/libs/libmythtv/firewirechannel.cpp | 6 +- mythtv/libs/libmythtv/firewiredevice.cpp | 183 +++++++++++++++++++++++- mythtv/libs/libmythtv/firewiredevice.h | 25 +++- mythtv/libs/libmythtv/linuxfirewiredevice.cpp | 4 +- mythtv/libs/libmythtv/linuxfirewiredevice.h | 2 +- 7 files changed, 215 insertions(+), 12 deletions(-) diff --git a/mythtv/libs/libmythtv/darwinfirewiredevice.cpp b/mythtv/libs/libmythtv/darwinfirewiredevice.cpp index 58224c9..8fa57d7 100644
a b class DFDPriv 114 114 }; 115 115 116 116 DarwinFirewireDevice::DarwinFirewireDevice( 117 uint64_t guid, uint subunitid, uint speed ) :118 FirewireDevice(guid, subunitid, speed ),117 uint64_t guid, uint subunitid, uint speed, bool gen_psip) : 118 FirewireDevice(guid, subunitid, speed, gen_psip), 119 119 m_local_node(-1), m_remote_node(-1), m_priv(new DFDPriv()) 120 120 { 121 121 -
mythtv/libs/libmythtv/darwinfirewiredevice.h
diff --git a/mythtv/libs/libmythtv/darwinfirewiredevice.h b/mythtv/libs/libmythtv/darwinfirewiredevice.h index 4ed70df..68c1f35 100644
a b class DarwinFirewireDevice : public FirewireDevice 20 20 21 21 22 22 public: 23 DarwinFirewireDevice(uint64_t guid, uint subunitid, uint speed); 23 DarwinFirewireDevice(uint64_t guid, uint subunitid, uint speed, 24 bool gen_psip = false); 24 25 ~DarwinFirewireDevice(); 25 26 26 27 virtual bool OpenPort(void); -
mythtv/libs/libmythtv/firewirechannel.cpp
diff --git a/mythtv/libs/libmythtv/firewirechannel.cpp b/mythtv/libs/libmythtv/firewirechannel.cpp index adf6e09..a397614 100644
a b FirewireChannel::FirewireChannel(TVRec *parent, const QString &_videodevice, 28 28 #ifdef USING_LINUX_FIREWIRE 29 29 device = new LinuxFirewireDevice( 30 30 guid, subunitid, fw_opts.speed, 31 LinuxFirewireDevice::kConnectionP2P == (uint) fw_opts.connection); 31 LinuxFirewireDevice::kConnectionP2P == (uint) fw_opts.connection, 32 fw_opts.gen_psip); 32 33 #endif // USING_LINUX_FIREWIRE 33 34 34 35 #ifdef USING_OSX_FIREWIRE 35 device = new DarwinFirewireDevice(guid, subunitid, fw_opts.speed); 36 device = new DarwinFirewireDevice(guid, subunitid, fw_opts.speed, 37 fw_opts.gen_psip); 36 38 #endif // USING_OSX_FIREWIRE 37 39 } 38 40 -
mythtv/libs/libmythtv/firewiredevice.cpp
diff --git a/mythtv/libs/libmythtv/firewiredevice.cpp b/mythtv/libs/libmythtv/firewiredevice.cpp index 2015e57..a074026 100644
a b 1 1 /** 2 2 * FirewireDevice 3 3 * Copyright (c) 2005 by Jim Westfall 4 * Copyright (c) 2011 by Chase Douglas 4 5 * Distributed as part of MythTV under GPL v2 and later. 5 6 */ 6 7 … … 15 16 #include "darwinfirewiredevice.h" 16 17 #include "mythlogging.h" 17 18 #include "pespacket.h" 19 #include "mpegtables.h" 18 20 19 21 #define LOC QString("FireDev(%1): ").arg(guid_to_string(m_guid)) 20 22 23 extern "C" { 24 extern const uint8_t *ff_find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *state); 25 } 26 21 27 static void fw_init(QMap<uint64_t,QString> &id_to_model); 22 28 23 29 QMap<uint64_t,QString> FirewireDevice::s_id_to_model; 24 30 QMutex FirewireDevice::s_static_lock; 25 31 26 FirewireDevice::FirewireDevice(uint64_t guid, uint subunitid, uint speed) : 32 FirewireDevice::FirewireDevice(uint64_t guid, uint subunitid, uint speed, 33 bool gen_psip) : 27 34 m_guid(guid), m_subunitid(subunitid), 28 35 m_speed(speed), 29 36 m_last_channel(0), m_last_crc(0), 30 37 m_buffer_cleared(true), m_open_port_cnt(0), 31 m_lock() 38 m_lock(), m_gen_psip(gen_psip), 39 m_vpid(0), m_apid(0), m_pat(NULL), m_pat_cc(0), m_pmt(NULL), m_pmt_cc(0) 40 { 41 } 42 43 FirewireDevice::~FirewireDevice() 32 44 { 45 delete m_pat; 46 delete m_pmt; 33 47 } 34 48 35 49 void FirewireDevice::AddListener(TSDataListener *listener) … … bool FirewireDevice::SetChannel(const QString &panel_model, 303 317 return true; 304 318 } 305 319 320 m_apid = 0; 321 m_vpid = 0; 322 m_pat_timer.stop(); 323 delete m_pat; 324 m_pat = NULL; 325 m_pmt_timer.stop(); 326 delete m_pmt; 327 m_pmt = NULL; 328 329 return false; 330 } 331 332 void FirewireDevice::SendPAT() 333 { 334 vector<TSPacket> m_pat_pkts; 335 m_pat->GetAsTSPackets(m_pat_pkts, m_pat_cc); 336 for (vector<TSPacket>::const_iterator it = m_pat_pkts.begin(); it != m_pat_pkts.end(); ++it) 337 SendDataToListeners(it->data(), TSPacket::kSize); 338 m_pat_cc = (m_pat_pkts.back().ContinuityCounter() + 1) & 0xf; 339 } 340 341 void FirewireDevice::SendPMT() 342 { 343 vector<TSPacket> m_pmt_pkts; 344 m_pmt->GetAsTSPackets(m_pmt_pkts, m_pmt_cc); 345 for (vector<TSPacket>::const_iterator it = m_pmt_pkts.begin(); it != m_pmt_pkts.end(); ++it) 346 SendDataToListeners(it->data(), TSPacket::kSize); 347 m_pmt_cc = (m_pmt_pkts.back().ContinuityCounter() + 1) & 0xf; 348 } 349 350 void FirewireDevice::GetTSPackets(const unsigned char *data, uint len, vector<const TSPacket*> *packets) 351 { 352 uint bufsz = m_buffer.size(); 353 if ((SYNC_BYTE == data[0]) && (TSPacket::kSize == len) && 354 (TSPacket::kSize > bufsz)) 355 { 356 m_buffer.clear(); 357 358 packets->push_back(reinterpret_cast<const TSPacket*>(data)); 359 return; 360 } 361 362 m_buffer.insert(m_buffer.end(), data, data + len); 363 bufsz += len; 364 365 uint sync_at; 366 for (sync_at = 0; sync_at < bufsz; sync_at++) 367 if (m_buffer[sync_at] == SYNC_BYTE) 368 break; 369 370 if (sync_at == bufsz) 371 return; 372 373 while (sync_at + TSPacket::kSize < bufsz) 374 { 375 packets->push_back(reinterpret_cast<const TSPacket*>( 376 &m_buffer[0] + sync_at)); 377 378 sync_at += TSPacket::kSize; 379 } 380 381 m_buffer.erase(m_buffer.begin(), m_buffer.begin() + sync_at); 382 383 return; 384 } 385 386 /* Check for MPEG2 video PES packet header */ 387 static bool IsMPEG2Frame(const TSPacket &tspacket) 388 { 389 const uint8_t *bufptr = tspacket.data() + tspacket.AFCOffset(); 390 const uint8_t *bufend = tspacket.data() + TSPacket::kSize; 391 uint32_t start_code; 392 393 while (bufptr < bufend) 394 { 395 bufptr = ff_find_start_code(bufptr, bufend, &start_code); 396 if ((start_code & 0xffffff00) == 0x00000100) 397 { 398 const int stream_id = start_code & 0x000000ff; 399 400 if (stream_id == PESStreamID::PictureStartCode || 401 stream_id == PESStreamID::GOPStartCode) 402 return true; 403 } 404 } 405 306 406 return false; 307 407 } 308 408 409 /* Firewire devices emit one video and one audio elementary stream. We must 410 * figure out which PID is the video stream and which is the audio stream. It's 411 * easy to determine the video stream, so find it first. Then assume the other 412 * is audio. 413 */ 414 void FirewireDevice::GeneratePSIP(const unsigned char *data, uint dataSize) 415 { 416 vector<const TSPacket*> packets; 417 418 /* If PAT packet hasn't been generated, chunk data into packets for analyzing */ 419 if (!m_pat) 420 GetTSPackets(data, dataSize, &packets); 421 422 for (vector<const TSPacket*>::const_iterator it = packets.begin(); it != packets.end(); ++it) 423 { 424 const TSPacket *tspacket = *it; 425 426 if (!m_vpid) 427 { 428 if (IsMPEG2Frame(*tspacket)) 429 m_vpid = tspacket->PID(); 430 continue; 431 } 432 433 if (m_vpid && !m_apid && tspacket->PID() != m_vpid && 434 tspacket->PID() != TSPacket::kNullPacket->PID()) 435 { 436 m_apid = tspacket->PID(); 437 438 /* Generate PAT */ 439 vector<uint> programs; 440 programs.push_back(1); 441 vector<uint> pids; 442 pids.push_back(10); 443 444 m_pat = ProgramAssociationTable::Create(0, 0, programs, pids); 445 SendPAT(); 446 m_pat_timer.start(); 447 448 /* Generate PMT */ 449 vector<uint> ppids; 450 ppids.push_back(m_vpid); 451 ppids.push_back(m_apid); 452 vector<uint> types; 453 types.push_back(StreamID::MPEG2Video); 454 types.push_back(StreamID::AC3Audio); 455 456 m_pmt = ProgramMapTable::Create(1, 10, 0x1fff, 0, ppids, types); 457 SendPMT(); 458 m_pmt_timer.start(); 459 } 460 } 461 462 /* The ATSC standard is a reasonable choice to mimic. It says a PAT must 463 * occur at least once every 100 ms. A PMT must occur at least once every 464 * 400 ms. We'll set the frequencies at 75% of the limits. */ 465 466 if (m_pat_timer.isRunning() && m_pat_timer.elapsed() >= 75) 467 { 468 SendPAT(); 469 m_pat_timer.start(); 470 } 471 472 if (m_pmt_timer.isRunning() && m_pmt_timer.elapsed() >= 300) 473 { 474 SendPMT(); 475 m_pmt_timer.start(); 476 } 477 } 478 309 479 void FirewireDevice::BroadcastToListeners( 310 480 const unsigned char *data, uint dataSize) 311 481 { 482 if (m_gen_psip) 483 GeneratePSIP(data, dataSize); 484 485 SendDataToListeners(data, dataSize); 486 } 487 488 void FirewireDevice::SendDataToListeners(const unsigned char *data, 489 uint dataSize) 490 { 312 491 if ((dataSize >= TSPacket::kSize) && (data[0] == SYNC_BYTE) && 313 492 ((data[1] & 0x1f) == 0) && (data[2] == 0)) 314 493 { -
mythtv/libs/libmythtv/firewiredevice.h
diff --git a/mythtv/libs/libmythtv/firewiredevice.h b/mythtv/libs/libmythtv/firewiredevice.h index 4151220..381020b 100644
a b using namespace std; 18 18 // MythTV headers 19 19 #include "streamlisteners.h" 20 20 #include "avcinfo.h" 21 #include "mythtimer.h" 21 22 22 23 class TSPacket; 23 24 … … class FirewireDevice 190 191 191 192 } IEEE1394PanelPassThroughParam0; 192 193 193 virtual ~FirewireDevice() { }194 virtual ~FirewireDevice(); 194 195 195 196 // Commands 196 197 virtual bool OpenPort(void) = 0; … … class FirewireDevice 218 219 static vector<AVCInfo> GetSTBList(void); 219 220 220 221 protected: 221 FirewireDevice(uint64_t guid, uint subunitid, uint speed );222 FirewireDevice(uint64_t guid, uint subunitid, uint speed, bool gen_psip); 222 223 223 224 virtual bool SendAVCCommand(const vector<uint8_t> &cmd, 224 225 vector<uint8_t> &result, … … class FirewireDevice 229 230 void ProcessPATPacket(const TSPacket&); 230 231 virtual void BroadcastToListeners( 231 232 const unsigned char *data, uint dataSize); 233 void SendDataToListeners(const unsigned char *data, uint dataSize); 234 void GeneratePSIP(const unsigned char *data, uint dataSize); 235 void GetTSPackets(const unsigned char *data, uint len, 236 vector<const TSPacket*> *packets); 237 void SendPAT(); 238 void SendPMT(); 232 239 233 240 uint64_t m_guid; 234 241 uint m_subunitid; … … class FirewireDevice 241 248 vector<TSDataListener*> m_listeners; 242 249 mutable QMutex m_lock; 243 250 251 bool m_gen_psip; 252 vector<unsigned char> m_buffer; 253 254 uint m_vpid; 255 uint m_apid; 256 257 ProgramAssociationTable *m_pat; 258 uint m_pat_cc; 259 MythTimer m_pat_timer; 260 261 ProgramMapTable *m_pmt; 262 uint m_pmt_cc; 263 MythTimer m_pmt_timer; 264 244 265 /// Vendor ID + Model ID to FirewireDevice STB model string 245 266 static QMap<uint64_t,QString> s_id_to_model; 246 267 static QMutex s_static_lock; -
mythtv/libs/libmythtv/linuxfirewiredevice.cpp
diff --git a/mythtv/libs/libmythtv/linuxfirewiredevice.cpp b/mythtv/libs/libmythtv/linuxfirewiredevice.cpp index 7ef8dd1..1eee67e 100644
a b static int linux_firewire_device_bus_reset_handler( 136 136 137 137 LinuxFirewireDevice::LinuxFirewireDevice( 138 138 uint64_t guid, uint subunitid, 139 uint speed, bool use_p2p, uint av_buffer_size_in_bytes) :140 FirewireDevice(guid, subunitid, speed ),139 uint speed, bool use_p2p, bool gen_psip, uint av_buffer_size_in_bytes) : 140 FirewireDevice(guid, subunitid, speed, gen_psip), 141 141 m_bufsz(av_buffer_size_in_bytes), 142 142 m_db_reset_disabled(false), 143 143 m_use_p2p(use_p2p), m_priv(new LFDPriv()) -
mythtv/libs/libmythtv/linuxfirewiredevice.h
diff --git a/mythtv/libs/libmythtv/linuxfirewiredevice.h b/mythtv/libs/libmythtv/linuxfirewiredevice.h index adb71aa..9187486 100644
a b class LinuxFirewireDevice : public FirewireDevice 33 33 34 34 public: 35 35 LinuxFirewireDevice(uint64_t guid, uint subunitid, 36 uint speed, bool use_p2p, 36 uint speed, bool use_p2p, bool gen_psip = false, 37 37 uint av_buffer_size_in_bytes = 0); 38 38 ~LinuxFirewireDevice(); 39 39