OSDN Git Service

9d4c59b21170cbbb9d6cb9250dabbfef7ba6f051
[iptd/iPTd.git] / src / ry0 / iPTd / Analyzer.cpp
1 /**\r
2  * @file Analyzer.cpp\r
3  *\r
4  */\r
5 \r
6 #include <time.h>\r
7 \r
8 #define DBG_LEVEL 0\r
9 #include "Raym/Log.h"\r
10 \r
11 #include "Raym/Raym.h"\r
12 #include "b25/aribstr.h"\r
13 #include "ry0/iPTd/Analyzer.h"\r
14 \r
15 using namespace Raym;\r
16 \r
17 namespace ry0\r
18 {\r
19 namespace iPTd\r
20 {\r
21 \r
22 Analyzer::Analyzer()\r
23 {\r
24     _sdt = NULL;\r
25     _eit = NULL;\r
26     _demux.setListener(this);\r
27 }\r
28 \r
29 Analyzer::~Analyzer()\r
30 {\r
31     if (_sdt != NULL)\r
32     {\r
33         delete _sdt;\r
34     }\r
35 }\r
36 \r
37 Analyzer *Analyzer::alloc()\r
38 {\r
39     return new Analyzer();\r
40 }\r
41 \r
42 Analyzer *Analyzer::init()\r
43 {\r
44     return this;\r
45 }\r
46 \r
47 Dictionary *Analyzer::stationInfo()\r
48 {\r
49     Dictionary *result = NULL;\r
50 \r
51     _demux.setFlag(MPEG2::TS::Demultiplexer::FLG_SDT, true);\r
52 \r
53     RaymLock(this);\r
54 \r
55     uint8_t count = 0;\r
56     while ((result == NULL) && (count++ < 32))\r
57     {\r
58         while (_sdt == NULL)\r
59         {\r
60             RaymCondWait(this);\r
61         }\r
62 \r
63         if (_sdt->_table_id == 0x42)\r
64         {\r
65             result = Dictionary::dictionaryWithCapacity(0);\r
66             Array *services = Array::arrayWithCapacity(0);\r
67             result->setObject(services, KEY_SERVICES);\r
68             for (uint32_t i = 0; i < _sdt->_service_count; ++i)\r
69             {\r
70                 Dictionary *service = Dictionary::dictionaryWithCapacity(0);\r
71                 services->addObject(service);\r
72                 char tmp[32];\r
73                 sprintf_s(tmp, "%d", _sdt->_services[i]._service_id);\r
74                 service->setString(tmp, KEY_SERVICE_ID);\r
75                 sprintf_s(tmp, "%d", _sdt->_services[i]._desc->service_type);\r
76                 service->setString(tmp, KEY_SERVICE_TYPE);\r
77                 if (_sdt->_services[i]._desc->service_name_length > 0)\r
78                 {\r
79                     String *name = String::stringWithCString(_sdt->_services[i]._desc->service_name, ShiftJISStringEncoding);\r
80                     service->setString(name, KEY_NAME);\r
81                     if (i == 0)\r
82                     {\r
83                         result->setString(name, KEY_NAME);\r
84                     }\r
85                 }\r
86             }\r
87         }\r
88 \r
89         delete _sdt;\r
90         _sdt = NULL;\r
91     }\r
92 \r
93     RaymUnlock(this);\r
94 \r
95     _demux.setFlag(MPEG2::TS::Demultiplexer::FLG_SDT, false);\r
96 \r
97     return result;\r
98 }\r
99 \r
100 Array *Analyzer::collectEPGs(time_t limit)\r
101 {\r
102     _demux.setFlag(MPEG2::TS::Demultiplexer::FLG_EIT, true);\r
103 \r
104     std::vector<MPEG2::TS::EIT *> eits;\r
105 \r
106     RaymLock(this);\r
107 \r
108     time_t start = time(NULL);\r
109     while (true)\r
110     {\r
111         while ((_eit == NULL) && (time(NULL) < start + limit))\r
112         {\r
113             RaymCondTimedWait(this, 1000);\r
114         }\r
115 \r
116         if (_eit != NULL)\r
117         {\r
118             eits.push_back(_eit);\r
119             _eit = NULL;\r
120         }\r
121         else\r
122         {\r
123             break;\r
124         }\r
125     }\r
126 \r
127     RaymUnlock(this);\r
128 \r
129     _demux.setFlag(MPEG2::TS::Demultiplexer::FLG_EIT, false);\r
130 \r
131     Array *result = Array::arrayWithCapacity(0);\r
132 \r
133     std::vector<MPEG2::TS::EIT *>::iterator it;\r
134     for (it = eits.begin(); it != eits.end(); ++it)\r
135     {\r
136         MPEG2::TS::EIT *eit = (*it);\r
137         if ((eit->_table_id == MPEG2::TS::EIT::TABLE_ID_SELF) ||\r
138             ((MPEG2::TS::EIT::TABLE_ID_SELF_SCHEDULE_BEGIN <= eit->_table_id) && (eit->_table_id <= MPEG2::TS::EIT::TABLE_ID_SELF_SCHEDULE_END)))\r
139         {\r
140             MPEG2::TS::EIT::Event *event;\r
141             while ((event = eit->nextEvent()) != NULL)\r
142             {\r
143                 char service_id[32];\r
144                 sprintf_s(service_id, "%d", eit->_service_id);\r
145 \r
146                 char event_id[32];\r
147                 sprintf_s(event_id, "%d", event->_event_id);\r
148 \r
149                 Dictionary *epg = NULL;\r
150 \r
151                 for (uint32_t i = 0; i < result->count(); ++i)\r
152                 {\r
153                     epg = (Dictionary *)result->objectAtIndex(i);\r
154                     if (epg->stringForKey(KEY_EPG_SERVICE_ID)->isEqualToString(service_id) &&\r
155                         epg->stringForKey(KEY_EPG_EVENT_ID)->isEqualToString(event_id))\r
156                     {\r
157                         break;\r
158                     }\r
159                     epg = NULL;\r
160                 }\r
161 \r
162                 if (epg == NULL)\r
163                 {\r
164                     epg = Dictionary::dictionaryWithCapacity(0);\r
165                     epg->setString(service_id, KEY_EPG_SERVICE_ID);\r
166                     epg->setString(event_id, KEY_EPG_EVENT_ID);\r
167 \r
168                     char date[16];\r
169                     sprintf_s(date, sizeof(date), "%02d/%02d/%02d", event->_st_year, event->_st_month, event->_st_day);\r
170                     epg->setString(date, KEY_EPG_DATE);\r
171 \r
172                     char start[16];\r
173                     sprintf_s(start, sizeof(start), "%02d:%02d:%02d", event->_st_hour, event->_st_min, event->_st_sec);\r
174                     epg->setString(start, KEY_EPG_START);\r
175 \r
176                     int hour = event->_st_hour + event->_dur_hour;\r
177                     int min = event->_st_min + event->_dur_min;\r
178                     int sec = event->_st_sec + event->_dur_sec;\r
179                     if (sec >= 60)\r
180                     {\r
181                         min += 1;\r
182                         sec -= 60;\r
183                     }\r
184                     if (min >= 60)\r
185                     {\r
186                         hour += 1;\r
187                         min -= 60;\r
188                     }\r
189                     char end[16];\r
190                     sprintf_s(end, sizeof(end), "%02d:%02d:%02d", hour, min, sec);\r
191                     epg->setString(end, KEY_EPG_END);\r
192 \r
193                     char duration[8];\r
194                     sprintf_s(duration, sizeof(duration), "%d", event->_dur_hour * 3600 + event->_dur_min * 60 + event->_dur_sec);\r
195                     epg->setString(duration, KEY_EPG_DURATION);\r
196 \r
197                     result->addObject(epg);\r
198                 }\r
199 \r
200                 Array *ext_items = NULL;\r
201                 String *ext_item_desc = NULL;\r
202                 Data *ext_item = NULL;\r
203                 Data *ext_text = NULL;\r
204 \r
205                 MPEG2::TS::Descriptor *desc;\r
206                 while ((desc = event->nextDescriptor()) != NULL)\r
207                 {\r
208                     switch (desc->_descriptor_tag)\r
209                     {\r
210                     case MPEG2::TS::TAG_BOUQUET_NAME_DESCRIPTOR:\r
211                         DebugLog3("TAG_BOUQUET_NAME_DESCRIPTOR\n");\r
212                         break;\r
213 \r
214                     case MPEG2::TS::TAG_SERVICE_DESCRIPTOR:\r
215                         DebugLog3("TAG_SERVICE_DESCRIPTOR\n");\r
216                         break;\r
217 \r
218                     case MPEG2::TS::TAG_SHORT_EVENT_DESCRIPTOR:\r
219                         DebugLog3("TAG_SHORT_EVENT_DESCRIPTOR\n");\r
220                         if (desc->_short_event._event_name_length > 0)\r
221                         {\r
222                             char *tmp = (char *)malloc(desc->_short_event._event_name_length * 3);\r
223                             if (tmp != NULL)\r
224                             {\r
225                                 AribToString(tmp, (const char *)desc->_short_event._event_name, desc->_short_event._event_name_length);\r
226                                 String *event_name = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
227                                 if (event_name != NULL)\r
228                                 {\r
229                                     epg->setString(event_name, KEY_EPG_TITLE);\r
230                                 }\r
231                                 free(tmp);\r
232                             }\r
233                         }\r
234                         if (desc->_short_event._text_length > 0)\r
235                         {\r
236                             char *tmp = (char *)malloc(desc->_short_event._text_length * 3);\r
237                             if (tmp != NULL)\r
238                             {\r
239                                 AribToString(tmp, (const char *)desc->_short_event._text, desc->_short_event._text_length);\r
240                                 String *text = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
241                                 if (text != NULL)\r
242                                 {\r
243                                     epg->setString(text, KEY_EPG_DESCRIPTION);\r
244                                 }\r
245                                 free(tmp);\r
246                             }\r
247                         }\r
248                         break;\r
249 \r
250                     case MPEG2::TS::TAG_EXTENDED_EVENT_DESCRIPTOR:\r
251                         DebugLog3("TAG_EXTENDED_EVENT_DESCRIPTOR\n");\r
252                         {\r
253                             for (int i = 0; i < desc->_extended_event._item_count; ++i)\r
254                             {\r
255                                 if (ext_items == NULL)\r
256                                 {\r
257                                     ext_items = Array::arrayWithCapacity(0);\r
258                                     epg->setObject(ext_items, KEY_EPG_EXT_ITEMS);\r
259                                 }\r
260 \r
261                                 if (desc->_extended_event._items[i]._item_description_length > 0)\r
262                                 {\r
263                                     if (ext_item != NULL)\r
264                                     {\r
265                                         char *tmp = (char *)malloc(ext_item->length() * 3);\r
266                                         if (tmp != NULL)\r
267                                         {\r
268                                             AribToString(tmp, (const char *)ext_item->bytes(), ext_item->length());\r
269                                             String *desc = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
270                                             if (desc != NULL)\r
271                                             {\r
272                                                 Dictionary *dict = Dictionary::dictionaryWithCapacity(0);\r
273                                                 if (ext_item_desc != NULL)\r
274                                                 {\r
275                                                     dict->setString(ext_item_desc, KEY_EPG_EXT_ITEM_DESCRIPTION);\r
276                                                     ext_item_desc = NULL;\r
277                                                 }\r
278                                                 dict->setString(desc, KEY_EPG_EXT_ITEM);\r
279                                                 ext_items->addObject(dict);\r
280                                             }\r
281                                             free(tmp);\r
282                                         }\r
283                                         ext_item = NULL;\r
284                                     }\r
285 \r
286                                     char *tmp = (char *)malloc(desc->_extended_event._items[i]._item_description_length * 3);\r
287                                     if (tmp != NULL)\r
288                                     {\r
289                                         AribToString(tmp, (const char *)desc->_extended_event._items[i]._item_description,\r
290                                                     desc->_extended_event._items[i]._item_description_length);\r
291                                         ext_item_desc = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
292                                         free(tmp);\r
293                                     }\r
294                                     else\r
295                                     {\r
296                                         ext_item_desc = NULL;\r
297                                     }\r
298                                 }\r
299 \r
300                                 if (desc->_extended_event._items[i]._item_length > 0)\r
301                                 {\r
302                                     if (ext_item == NULL)\r
303                                     {\r
304                                         ext_item = Data::dataWithCapacity(0);\r
305                                     }\r
306                                     ext_item->appendBytes(desc->_extended_event._items[i]._item,\r
307                                                           desc->_extended_event._items[i]._item_length);\r
308                                 }\r
309                             }\r
310                             if (desc->_extended_event._text_length > 0)\r
311                             {\r
312                                 if (ext_text == NULL)\r
313                                 {\r
314                                     ext_text = Data::dataWithCapacity(0);\r
315                                 }\r
316                                 ext_text->appendBytes(desc->_extended_event._text, desc->_extended_event._text_length);\r
317                             }\r
318                         }\r
319                         break;\r
320 \r
321                     case MPEG2::TS::TAG_CONTENT_DESCRIPTOR:\r
322                         DebugLog3("TAG_CONTENT_DESCRIPTOR\n");\r
323                         break;\r
324 \r
325                     case MPEG2::TS::TAG_SERIES_DESCRIPTOR:\r
326                         DebugLog3("TAG_SERIES_DESCRIPTOR\n");\r
327                         break;\r
328 \r
329                     case MPEG2::TS::TAG_EVENT_GROUP_DESCRIPTOR:\r
330                         DebugLog3("TAG_EVENT_GROUP_DESCRIPTOR\n");\r
331                         break;\r
332 \r
333                     case MPEG2::TS::TAG_COMPONENT_DESCRIPTOR:\r
334                         DebugLog3("TAG_COMPONENT_DESCRIPTOR\n");\r
335                         break;\r
336 \r
337                     case MPEG2::TS::TAG_DIGITAL_COPY_CONTROL_DESCRIPTOR:\r
338                         DebugLog3("TAG_DIGITAL_COPY_CONTROL_DESCRIPTOR\n");\r
339                         break;\r
340 \r
341                     case MPEG2::TS::TAG_AUDIO_COMPONENT_DESCRIPTOR:\r
342                         DebugLog3("TAG_AUDIO_COMPONENT_DESCRIPTOR\n");\r
343                         break;\r
344 \r
345                     case MPEG2::TS::TAG_DATA_CONTENT_DESCRIPTOR:\r
346                         DebugLog3("TAG_AUDIO_COMPONENT_DESCRIPTOR\n");\r
347                         break;\r
348 \r
349                     default:\r
350                         DebugLog3("Unknown descriptor: 0x%02X\n", desc->_descriptor_tag);\r
351                         break;\r
352                     }\r
353                 }\r
354 \r
355                 if (ext_item != NULL)\r
356                 {\r
357                     char *tmp = (char *)malloc(ext_item->length() * 3);\r
358                     if (tmp != NULL)\r
359                     {\r
360                         AribToString(tmp, (const char *)ext_item->bytes(), ext_item->length());\r
361                         String *desc = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
362                         if (desc != NULL)\r
363                         {\r
364                             Dictionary *dict = Dictionary::dictionaryWithCapacity(0);\r
365                             if (ext_item_desc != NULL)\r
366                             {\r
367                                 dict->setString(ext_item_desc, KEY_EPG_EXT_ITEM_DESCRIPTION);\r
368                                 ext_item_desc = NULL;\r
369                             }\r
370                             dict->setString(desc, KEY_EPG_EXT_ITEM);\r
371                             ext_items->addObject(dict);\r
372                         }\r
373                         free(tmp);\r
374                     }\r
375                     ext_item = NULL;\r
376                 }\r
377 \r
378                 if (ext_text != NULL)\r
379                 {\r
380                     char *tmp = (char *)malloc(ext_text->length() * 3);\r
381                     if (tmp != NULL)\r
382                     {\r
383                         AribToString(tmp, (const char *)ext_text->bytes(), ext_text->length());\r
384                         String *desc = String::stringWithCString(tmp, ShiftJISStringEncoding);\r
385                         if (desc != NULL)\r
386                         {\r
387                             Dictionary *dict = Dictionary::dictionaryWithCapacity(0);\r
388                             dict->setString("no desc", KEY_EPG_EXT_ITEM_DESCRIPTION);\r
389                             dict->setString(desc, KEY_EPG_EXT_ITEM);\r
390                             ext_items->addObject(dict);\r
391                         }\r
392                         free(tmp);\r
393                     }\r
394                     ext_text = NULL;\r
395                 }\r
396             }\r
397         }\r
398 \r
399         delete *it;\r
400     }\r
401 \r
402     return result;\r
403 }\r
404 \r
405 void Analyzer::put(uint8_t *buffer, uint32_t size)\r
406 {\r
407     _demux.put(buffer, size);\r
408 }\r
409 \r
410 void Analyzer::detect(MPEG2::TS::SDT *sdt)\r
411 {\r
412     RaymLock(this);\r
413     if (_sdt != NULL)\r
414     {\r
415         delete _sdt;\r
416         _sdt = NULL;\r
417     }\r
418     _sdt = new MPEG2::TS::SDT(*sdt);\r
419     RaymCondSignal(this);\r
420     RaymUnlock(this);\r
421 }\r
422 \r
423 void Analyzer::detect(MPEG2::TS::EIT *eit)\r
424 {\r
425     RaymLock(this);\r
426     if (_eit != NULL)\r
427     {\r
428         delete _eit;\r
429         _eit = NULL;\r
430     }\r
431     _eit = new MPEG2::TS::EIT(*eit);\r
432     RaymCondSignal(this);\r
433     RaymUnlock(this);\r
434 }\r
435 \r
436 } // iPTd\r
437 } // ry0\r