Ticket #2311: mhegstartpatch.txt

File mhegstartpatch.txt, 10.5 KB (added by dm@…, 19 years ago)
Line 
1Index: libs/libmythtv/avformatdecoder.cpp
2===================================================================
3--- libs/libmythtv/avformatdecoder.cpp (revision 11558)
4+++ libs/libmythtv/avformatdecoder.cpp (working copy)
5@@ -1251,6 +1251,64 @@
6 }
7 }
8
9+/** \fn AvFormatDecoder::ScanDSMCCStreams(void)
10+ * \brief Check to see whether there is a Network Boot Ifo sub-descriptor in the PMT which
11+ * requires the MHEG application to reboot.
12+ */
13+void AvFormatDecoder::ScanDSMCCStreams(void)
14+{
15+ if (!ic->cur_pmt_sect)
16+ return;
17+
18+ if (!itv && ! (itv = GetNVP()->GetInteractiveTV()))
19+ return;
20+
21+ const PESPacket pes = PESPacket::ViewData(ic->cur_pmt_sect);
22+ const PSIPTable psip(pes);
23+ const ProgramMapTable pmt(psip);
24+
25+ for (uint i = 0; i < pmt.StreamCount(); i++)
26+ {
27+ if (! StreamID::IsObjectCarousel(pmt.StreamType(i)))
28+ continue;
29+
30+ const desc_list_t desc_list = MPEGDescriptor::ParseOnlyInclude(
31+ pmt.StreamInfo(i), pmt.StreamInfoLength(i),
32+ DescriptorID::data_broadcast_id);
33+
34+ for (uint j = 0; j < desc_list.size(); j++)
35+ {
36+ const unsigned char *desc = desc_list[j];
37+ desc++; // Skip tag
38+ uint length = *desc++;
39+ const unsigned char *endDesc = desc+length;
40+ uint dataBroadcastId = desc[0]<<8 | desc[1];
41+ if (dataBroadcastId != 0x0106) // ETSI/UK Profile
42+ continue;
43+ desc += 2; // Skip data ID
44+ while (desc != endDesc)
45+ {
46+ uint appTypeCode = desc[0]<<8 | desc[1];
47+ desc += 3; // Skip app type code and boot priority hint
48+ uint appSpecDataLen = *desc++;
49+ if (appTypeCode == 0x101) // UK MHEG profile
50+ {
51+ const unsigned char *subDescEnd = desc + appSpecDataLen;
52+ while (desc < subDescEnd)
53+ {
54+ uint sub_desc_tag = *desc++;
55+ uint sub_desc_len = *desc++;
56+ if (sub_desc_tag == 1) // Network boot info sub-descriptor.
57+ itv->SetNetBootInfo(desc, sub_desc_len);
58+ desc += sub_desc_len;
59+ }
60+ }
61+ else desc += appSpecDataLen;
62+ }
63+ }
64+ }
65+}
66+
67 int AvFormatDecoder::ScanStreams(bool novideo)
68 {
69 int scanerror = 0;
70@@ -1562,6 +1620,8 @@
71 if (GetNVP()->IsErrored())
72 scanerror = -1;
73
74+ ScanDSMCCStreams();
75+
76 return scanerror;
77 }
78
79Index: libs/libmythtv/dsmccobjcarousel.cpp
80===================================================================
81--- libs/libmythtv/dsmccobjcarousel.cpp (revision 11558)
82+++ libs/libmythtv/dsmccobjcarousel.cpp (working copy)
83@@ -150,20 +150,26 @@
84 VERBOSE(VB_DSMCC, QString("[dsmcc] Already Know "
85 "Module %1")
86 .arg(info->module_id));
87-
88- return;
89+ if (cachep->ModuleSize() == info->module_size)
90+ return;
91+ // It seems that when ITV4 starts broadcasting it
92+ // updates the contents of a file but doesn't
93+ // update the version. This is a work-around.
94+ VERBOSE(VB_DSMCC, QString("[dsmcc] Module %1 size "
95+ "has changed (%2 to %3) "
96+ "but version has not!!")
97+ .arg(info->module_id)
98+ .arg(info->module_size)
99+ .arg(cachep->DataSize()));
100 }
101- else
102- {
103- // Version has change - Drop old data.
104- VERBOSE(VB_DSMCC, QString("[dsmcc] Updated "
105- "Module %1")
106- .arg(info->module_id));
107+ // Version has changed - Drop old data.
108+ VERBOSE(VB_DSMCC, QString("[dsmcc] Updated "
109+ "Module %1")
110+ .arg(info->module_id));
111
112- // Remove and delete the cache object.
113- m_Cache.remove();
114- break;
115- }
116+ // Remove and delete the cache object.
117+ m_Cache.remove();
118+ break;
119 }
120 }
121
122Index: libs/libmythtv/interactivetv.cpp
123===================================================================
124--- libs/libmythtv/interactivetv.cpp (revision 11558)
125+++ libs/libmythtv/interactivetv.cpp (working copy)
126@@ -75,3 +75,8 @@
127 {
128 m_context->GetInitialStreams(audioTag, videoTag);
129 }
130+
131+void InteractiveTV::SetNetBootInfo(const unsigned char *data, uint length)
132+{
133+ m_context->SetNetBootInfo(data, length);
134+}
135Index: libs/libmythtv/dsmccobjcarousel.h
136===================================================================
137--- libs/libmythtv/dsmccobjcarousel.h (revision 11558)
138+++ libs/libmythtv/dsmccobjcarousel.h (working copy)
139@@ -35,6 +35,7 @@
140 unsigned short ModuleId(void) const { return m_module_id; }
141 unsigned short StreamId(void) const { return m_stream_id; }
142 unsigned char Version(void) const { return m_version; }
143+ unsigned long ModuleSize(void) const { return m_moduleSize; }
144
145 /// Return the, possibly uncompressed, module size
146 unsigned long DataSize(void) const
147Index: libs/libmythtv/mhi.h
148===================================================================
149--- libs/libmythtv/mhi.h (revision 11558)
150+++ libs/libmythtv/mhi.h (working copy)
151@@ -44,6 +44,8 @@
152
153 void QueueDSMCCPacket(unsigned char *data, int length, int componentTag,
154 unsigned carouselId, int dataBroadcastId);
155+ // A NetworkBootInfo sub-descriptor is present in the PMT.
156+ void SetNetBootInfo(const unsigned char *data, uint length);
157 /// Restart the MHEG engine.
158 void Restart(uint chanid, uint cardid, bool isLive);
159 // Offer a key press. Returns true if it accepts it.
160@@ -133,6 +135,7 @@
161 static void *StartMHEGEngine(void *param);
162 void RunMHEGEngine(void);
163 void ProcessDSMCCQueue(void);
164+ void NetworkBootRequested(void);
165
166 InteractiveTV *m_parent;
167
168@@ -169,6 +172,9 @@
169 int m_audioTag;
170 int m_videoTag;
171 int m_tuningTo;
172+
173+ uint m_lastNbiVersion;
174+ QMemArray<unsigned char> m_nbiData;
175 };
176
177 // Object for drawing text.
178Index: libs/libmythtv/interactivetv.h
179===================================================================
180--- libs/libmythtv/interactivetv.h (revision 11558)
181+++ libs/libmythtv/interactivetv.h (working copy)
182@@ -21,6 +21,9 @@
183 int componentTag, unsigned carouselId,
184 int dataBroadcastId);
185
186+ // A NetworkBootInfo sub-descriptor is present in the PMT
187+ void SetNetBootInfo(const unsigned char *data, uint length);
188+
189 // See if the image has changed.
190 bool ImageHasChanged(void);
191 // Draw the (updated) image.
192Index: libs/libmythtv/avformatdecoder.h
193===================================================================
194--- libs/libmythtv/avformatdecoder.h (revision 11558)
195+++ libs/libmythtv/avformatdecoder.h (working copy)
196@@ -147,6 +147,7 @@
197
198 void ScanATSCCaptionStreams(int av_stream_index);
199 void ScanTeletextCaptions(int av_stream_index);
200+ void ScanDSMCCStreams(void);
201 int AutoSelectAudioTrack(void);
202
203 private:
204Index: libs/libmythtv/mhi.cpp
205===================================================================
206--- libs/libmythtv/mhi.cpp (revision 11558)
207+++ libs/libmythtv/mhi.cpp (working copy)
208@@ -21,6 +21,10 @@
209 int m_y;
210 };
211
212+// Special values for the NetworkBootInfo version. Real values are a byte.
213+#define NBI_VERSION_UNSET 257
214+#define NBI_VERSION_ABSENT 256
215+
216 MHIContext::MHIContext(InteractiveTV *parent)
217 : m_parent(parent), m_dsmcc(NULL),
218 m_engine(NULL), m_stop(false),
219@@ -29,7 +33,7 @@
220 m_face_loaded(false), m_currentChannel(-1),
221 m_isLive(false), m_currentCard(0),
222 m_audioTag(-1), m_videoTag(-1),
223- m_tuningTo(-1)
224+ m_tuningTo(-1), m_lastNbiVersion(NBI_VERSION_UNSET)
225 {
226 m_display.setAutoDelete(true);
227 m_dsmccQueue.setAutoDelete(true);
228@@ -146,6 +150,8 @@
229 m_updated = true;
230 m_stop = false;
231 m_isLive = isLive;
232+ // Don't set the NBI version here. Restart is called
233+ // after the PMT is processed.
234 m_stopped = pthread_create(&m_engineThread, NULL,
235 StartMHEGEngine, this) != 0;
236 m_audioTag = -1;
237@@ -173,6 +179,7 @@
238 int key = 0;
239 do
240 {
241+ (void)NetworkBootRequested();
242 ProcessDSMCCQueue();
243 {
244 QMutexLocker locker(&m_keyLock);
245@@ -242,6 +249,40 @@
246 m_engine_wait.wakeAll();
247 }
248
249+// A NetworkBootInfo sub-descriptor is present in the PMT.
250+void MHIContext::SetNetBootInfo(const unsigned char *data, uint length)
251+{
252+ if (length < 2) return;
253+ QMutexLocker locker(&m_dsmccLock);
254+ // Save the data from the descriptor.
255+ m_nbiData.duplicate(data, length);
256+ // If there is no Network Boot Info or we're setting it
257+ // for the first time just update the "last version".
258+ if (length < 2)
259+ m_lastNbiVersion = NBI_VERSION_ABSENT;
260+ else if (m_lastNbiVersion == NBI_VERSION_UNSET)
261+ m_lastNbiVersion = data[0];
262+ else
263+ m_engine_wait.wakeAll();
264+}
265+
266+void MHIContext::NetworkBootRequested(void)
267+{
268+ QMutexLocker locker(&m_dsmccLock);
269+ if (m_nbiData.size() >= 2 && m_nbiData[0] != m_lastNbiVersion)
270+ {
271+ m_lastNbiVersion = m_nbiData[0]; // Update the saved version
272+ if (m_nbiData[1] == 1)
273+ {
274+ m_dsmcc->Reset();
275+ m_engine->SetBooting();
276+ m_display.clear();
277+ m_updated = true;
278+ }
279+ // TODO: else if it is 2 generate an EngineEvent.
280+ }
281+}
282+
283 // Called by the engine to check for the presence of an object in the carousel.
284 bool MHIContext::CheckCarouselObject(QString objectPath)
285 {
286@@ -549,7 +590,10 @@
287 // Post an event requesting a channel change.
288 MythEvent me(QString("NETWORK_CONTROL CHANID %1").arg(channel));
289 gContext->dispatch(me);
290-
291+ // Reset the NBI version here to prevent a reboot.
292+ QMutexLocker locker(&m_dsmccLock);
293+ m_lastNbiVersion = NBI_VERSION_UNSET;
294+ m_nbiData.resize(0);
295 return true;
296 }
297