Index: firewiresignalmonitor.cpp =================================================================== --- firewiresignalmonitor.cpp (revision 20728) +++ firewiresignalmonitor.cpp (working copy) @@ -14,6 +14,12 @@ #include "firewirechannel.h" #include "firewiresignalmonitor.h" +extern "C" +{ +#include "../libavutil/crc.h" +#include "../libavutil/bswap.h" +} + #define LOC QString("FireSM(%1): ").arg(channel->GetDevice()) #define LOC_WARN QString("FireSM(%1), Warning: ").arg(channel->GetDevice()) #define LOC_ERR QString("FireSM(%1), Error: ").arg(channel->GetDevice()) @@ -46,7 +52,8 @@ dtvMonitorRunning(false), stb_needs_retune(true), stb_needs_to_wait_for_pat(false), - stb_needs_to_wait_for_power(false) + stb_needs_to_wait_for_power(false), + pid_video(0), pid_audio(0), audio_is_ac3(false) { VERBOSE(VB_CHANNEL, LOC + "ctor"); @@ -84,6 +91,7 @@ void FirewireSignalMonitor::HandlePAT(const ProgramAssociationTable *pat) { + VERBOSE(VB_CHANNEL, LOC + "HandlePAT() got PAT"); AddFlags(kDTVSigMon_PATSeen); FirewireChannel *fwchan = dynamic_cast(channel); @@ -91,6 +99,7 @@ return; bool crc_bogus = !fwchan->GetFirewireDevice()->IsSTBBufferCleared(); + crc_bogus = false; if (crc_bogus && stb_needs_to_wait_for_pat && (stb_wait_for_pat_timer.elapsed() < (int)kBufferTimeout)) { @@ -166,11 +175,88 @@ VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- end"); } +void FirewireSignalMonitor::ScanForAVPids(const unsigned char *data, uint len) +{ + if (len != 188) // TS packets are 188 bytes + return; + if (data[0] != 0x47) // First byte must be sync byte + return; + if ((data[1] & 0x40) == 0) // Payload unit start inidcator + return; + + int ofs, afc; + // 0x01 = Payload + // 0x02 - Has adaptation field + afc = (data[3] >> 4) & 3; + if ((afc & 0x01) == 0) // No payload + return; + if (afc & 0x02) + ofs = 4 + data[4] + 1; + else + ofs = 4; + + // PES Packets start with 0x00 0x00 0x01 + if (data[ofs] != 0x00 || data[ofs+1] != 0x00 || data[ofs+2] != 0x01) + return; + + int pid = ((data[1] & 0x1f) << 8) | data[2]; + switch (data[ofs+3]) + { + case PESStreamID::MPEGVideoStreamBegin ... PESStreamID::MPEGVideoStreamEnd: + VERBOSE(VB_CHANNEL, QString("Video SID seen in PID %2").arg(pid)); + pid_video = pid; + break; + case PESStreamID::MPEGAudioStreamBegin ... PESStreamID::MPEGAudioStreamEnd: + VERBOSE(VB_CHANNEL, QString("MP2A SID seen in PID %2").arg(pid)); + pid_audio = pid; + audio_is_ac3 = false; + break; + case PESStreamID::NonMPEGAudioVideo: // 0xbd + VERBOSE(VB_CHANNEL, QString("AC3A SID seen in PID %2").arg(pid)); + pid_audio = pid; + audio_is_ac3 = true; + break; + } +} + void FirewireSignalMonitor::AddData(const unsigned char *data, uint len) { if (!dtvMonitorRunning) return; + if (pid_video == 0 || pid_audio == 0) + ScanForAVPids(data, len); + + bool avpidsDiscovered = 0; // (pid_video != 0) && (pid_audio != 0); + if (GetStreamData() && pid_video != 0 && pid_audio != 0 && !HasFlags(kDTVSigMon_PMTMatch)) { + vector programs; + vector pids; + programs.push_back(0x0001); + pids.push_back(0x0fff); + ProgramAssociationTable *pat = ProgramAssociationTable::Create( + 0x0437, 20, programs, pids); + GetStreamData()->CachePAT(pat); + GetStreamData()->ProcessPAT(pat); + delete pat; + + vector streamtypes; + pids.clear(); + pids.push_back(pid_video); + streamtypes.push_back(0x02); + pids.push_back(pid_audio); + streamtypes.push_back(audio_is_ac3 ? 0x81 : 0x03); + + ProgramMapTable *pmt = ProgramMapTable::Create( + 0x001, // Program #1 + 0x0fff, // My PID + 0x0000, // PCR pid (we don't have one) + 20, // version 0 + pids, streamtypes); + GetStreamData()->CachePMT(pmt); + GetStreamData()->ProcessPMT(pmt); + delete pmt; + } + if (GetStreamData()) GetStreamData()->ProcessData((unsigned char *)data, len); } Index: mpeg/mpegstreamdata.h =================================================================== --- mpeg/mpegstreamdata.h (revision 20728) +++ mpeg/mpegstreamdata.h (working copy) @@ -280,10 +280,15 @@ bool CreatePATSingleProgram(const ProgramAssociationTable&); bool CreatePMTSingleProgram(const ProgramMapTable&); + + void ProcessPAT(const ProgramAssociationTable *pat); + void ProcessPMT(const ProgramMapTable *pmt); + PSIPTable* AssemblePSIP(const TSPacket* tspacket, bool& moreTablePackets); + void CachePAT(const ProgramAssociationTable *pat); + void CachePMT(const ProgramMapTable *pmt); protected: // Table processing -- for internal use - PSIPTable* AssemblePSIP(const TSPacket* tspacket, bool& moreTablePackets); bool AssemblePSIP(PSIPTable& psip, TSPacket* tspacket); void SavePartialPES(uint pid, PESPacket* packet); PESPacket* GetPartialPES(uint pid) @@ -291,8 +296,6 @@ void ClearPartialPES(uint pid) { _partial_pes_packet_cache.remove(pid); } void DeletePartialPES(uint pid); - void ProcessPAT(const ProgramAssociationTable *pat); - void ProcessPMT(const ProgramMapTable *pmt); void ProcessEncryptedPacket(const TSPacket&); static int ResyncStream(const unsigned char *buffer, int curr_pos, int len); @@ -302,8 +305,6 @@ // Caching void IncrementRefCnt(const PSIPTable *psip) const; virtual bool DeleteCachedTable(PSIPTable *psip) const; - void CachePAT(const ProgramAssociationTable *pat); - void CachePMT(const ProgramMapTable *pmt); protected: QString _sistandard; Index: firewiresignalmonitor.h =================================================================== --- firewiresignalmonitor.h (revision 20728) +++ firewiresignalmonitor.h (working copy) @@ -37,6 +37,7 @@ bool SupportsTSMonitoring(void); void AddData(const unsigned char *data, uint dataSize); + void ScanForAVPids(const unsigned char *data, uint dataSize); public: static const uint kPowerTimeout; @@ -50,6 +51,9 @@ bool stb_needs_to_wait_for_power; MythTimer stb_wait_for_pat_timer; MythTimer stb_wait_for_power_timer; + int pid_video; + int pid_audio; + bool audio_is_ac3; vector buffer;