OSDN Git Service

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