add pid cache
[vuplus_dvbapp] / lib / dvb / pmt.cpp
1  #include <lib/base/eerror.h>
2 #include <lib/dvb/pmt.h>
3 #include <lib/dvb/specs.h>
4 #include <lib/dvb/dvb.h>
5 #include <lib/dvb/metaparser.h>
6
7 eDVBServicePMTHandler::eDVBServicePMTHandler()
8 {
9         eDVBResourceManager::getInstance(m_resourceManager);
10         CONNECT(m_PMT.tableReady, eDVBServicePMTHandler::PMTready);
11         CONNECT(m_PAT.tableReady, eDVBServicePMTHandler::PATready);
12 }
13
14 void eDVBServicePMTHandler::channelStateChanged(iDVBChannel *channel)
15 {
16         int state;
17         channel->getState(state);
18         
19         if ((m_last_channel_state != iDVBChannel::state_ok)
20                 && (state == iDVBChannel::state_ok) && (!m_demux))
21         {
22                 if (m_channel)
23                         if (m_channel->getDemux(m_demux))
24                                 eDebug("shit it failed.. again.");
25                 
26                 serviceEvent(eventTuned);
27                 
28                 if (m_demux)
29                 {
30                         eDebug("ok ... now we start!!");
31
32                         /* emit */ m_resourceManager->m_channelRunning(channel);
33
34                         m_PAT.begin(eApp, eDVBPATSpec(), m_demux);
35
36                         if ( m_service && !m_service->cacheEmpty() )
37                                 serviceEvent(eventNewProgramInfo);
38                 }
39         }
40 }
41
42 void eDVBServicePMTHandler::PMTready(int error)
43 {
44         if (error)
45                 serviceEvent(eventNoPMT);
46         else
47                 serviceEvent(eventNewProgramInfo);
48 }
49
50 void eDVBServicePMTHandler::PATready(int)
51 {
52         eDebug("got PAT");
53         ePtr<eTable<ProgramAssociationTable> > ptr;
54         if (!m_PAT.getCurrent(ptr))
55         {
56                 int pmtpid = -1;
57                 ProgramAssociationTableConstIterator i;
58                 for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i)
59                 {
60                         const ProgramAssociationTable &pat = **i;
61                         ProgramAssociationConstIterator program;
62                         for (program = pat.getPrograms()->begin(); program != pat.getPrograms()->end(); ++program)
63                                 if (eServiceID((*program)->getProgramNumber()) == m_reference.getServiceID())
64                                         pmtpid = (*program)->getProgramMapPid();
65                 }
66                 if (pmtpid == -1)
67                         serviceEvent(eventNoPATEntry);
68                 else
69                         m_PMT.begin(eApp, eDVBPMTSpec(pmtpid, m_reference.getServiceID().get()), m_demux);
70         } else
71                 serviceEvent(eventNoPAT);
72 }
73
74 int eDVBServicePMTHandler::getProgramInfo(struct program &program)
75 {
76         eDebug("got PMT");
77         ePtr<eTable<ProgramMapTable> > ptr;
78
79         program.videoStreams.clear();
80         program.audioStreams.clear();
81         program.pcrPid = -1;
82
83         if (!m_PMT.getCurrent(ptr))
84         {
85                 ProgramMapTableConstIterator i;
86                 for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i)
87                 {
88                         const ProgramMapTable &pmt = **i;
89                         program.pcrPid = pmt.getPcrPid();
90                         
91                         ElementaryStreamInfoConstIterator es;
92                         for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
93                         {
94                                 int isaudio = 0, isvideo = 0;
95                                 videoStream video;
96                                 audioStream audio;
97                                 
98                                 video.pid = (*es)->getPid();
99                                 audio.pid = (*es)->getPid();
100                                 
101                                 switch ((*es)->getType())
102                                 {
103                                 case 0x01: // MPEG 1 video
104                                 case 0x02: // MPEG 2 video
105                                         isvideo = 1;
106                                         break;
107                                 case 0x03: // MPEG 1 audio
108                                 case 0x04: // MPEG 2 audio:
109                                         isaudio = 1;
110                                         audio.type = audioStream::atMPEG;
111                                         break;
112                                 }
113                                 if (isaudio)
114                                         program.audioStreams.push_back(audio);
115                                 if (isvideo)
116                                         program.videoStreams.push_back(video);
117                         }
118                 }
119                 return 0;
120         }
121         else if ( m_service && !m_service->cacheEmpty() )
122         {
123                 int vpid = m_service->getCachePID(eDVBService::cVPID),
124                         apid_ac3 = m_service->getCachePID(eDVBService::cAPID),
125                         apid_mpeg = m_service->getCachePID(eDVBService::cAC3PID),
126                         pcrpid = m_service->getCachePID(eDVBService::cPCRPID),
127                         cnt=0;
128                 if ( vpid != -1 )
129                 {
130                         videoStream s;
131                         s.pid = vpid;
132                         program.videoStreams.push_back(s);
133                         ++cnt;
134                 }
135                 if ( apid_ac3 != -1 )
136                 {
137                         audioStream s;
138                         s.type = audioStream::atAC3;
139                         s.pid = apid_ac3;
140                         program.audioStreams.push_back(s);
141                         ++cnt;
142                 }
143                 if ( apid_mpeg != -1 )
144                 {
145                         audioStream s;
146                         s.type = audioStream::atMPEG;
147                         s.pid = apid_mpeg;
148                         program.audioStreams.push_back(s);
149                         ++cnt;
150                 }
151                 if ( pcrpid != -1 )
152                 {
153                         ++cnt;
154                         program.pcrPid = pcrpid;
155                 }
156                 if ( cnt )
157                         return 0;
158         }
159         return -1;
160 }
161
162 int eDVBServicePMTHandler::getDemux(ePtr<iDVBDemux> &demux)
163 {
164         demux = m_demux;
165         if (demux)
166                 return 0;
167         else
168                 return -1;
169 }
170
171 int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref)
172 {
173         RESULT res;
174         m_reference = ref;
175         
176 //      ref.path = "/viva.ts"; // hrhr.
177         
178                 /* is this a normal (non PVR) channel? */
179         if (ref.path.empty())
180         {
181                 eDVBChannelID chid;
182                 ref.getChannelID(chid);
183                 res = m_resourceManager->allocateChannel(chid, m_channel);
184         } else
185         {
186                 eDVBMetaParser parser;
187                 
188                 if (parser.parseFile(ref.path))
189                         eWarning("no .meta file found, trying original service ref.");
190                 else
191                         m_reference = parser.m_ref;
192                 
193                 eDebug("alloc PVR");
194                         /* allocate PVR */
195                 res = m_resourceManager->allocatePVRChannel(m_pvr_channel);
196                 if (res)
197                         eDebug("allocatePVRChannel failed!\n");
198                 m_channel = m_pvr_channel;
199         }
200         
201         if (m_channel)
202         {
203                 m_channel->connectStateChange(
204                         slot(*this, &eDVBServicePMTHandler::channelStateChanged), 
205                         m_channelStateChanged_connection);
206                 m_last_channel_state = -1;
207                 channelStateChanged(m_channel);
208         }
209
210         if (m_pvr_channel)
211                 m_pvr_channel->playFile(ref.path.c_str());
212
213         ePtr<iDVBChannelList> db;
214         if (!m_resourceManager->getChannelList(db))
215                 db->getService((eServiceReferenceDVB&)m_reference, m_service);
216
217         return res;
218 }