📄 atsctoepg.c
字号:
/*Copyright (C) 2006 Adam CharrettThis program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USAatsctoepg.cPlugin to collect EPG schedule information from ATSC/PSIP.*/#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include <string.h>#include <stdint.h>#include <time.h>#include "plugin.h"#include "epgdbase.h"#include "dvbpsi/atsc/ett.h"#include "dvbpsi/atsc/eit.h"#include "list.h"#include "logging.h"#include "subtableprocessor.h"#include "atsctext.h"#include "tuning.h"#include "deferredproc.h"/******************************************************************************** Defines ********************************************************************************/#define MAX_EITS 128 /* Maximum number of EIT tables (PIDs) */#define MAX_ETTS 128 /* Maximum number of ETT tables (PIDs) *//******************************************************************************** Typedefs ********************************************************************************/typedef struct TableInfo_s{ uint16_t pid; dvbpsi_handle decoder;}TableInfo_t;/******************************************************************************** Prototypes ********************************************************************************/static void InitEITFilter(PIDFilter_t *filter);static void DeinitEITFilter(PIDFilter_t *filter);static void NewMGT(dvbpsi_atsc_mgt_t *newMGT);static void NewSTT(dvbpsi_atsc_stt_t *newSTT);static int ATSCtoEPGFilterPacket(PIDFilter_t *pidfilter, void *arg, uint16_t pid, TSPacket_t *packet);static TSPacket_t * ATSCtoEPGProcessPacket(PIDFilter_t *pidfilter, void *arg, TSPacket_t *packet);static void ATSCtoEPGMultiplexChanged(PIDFilter_t *pidfilter, void *arg, Multiplex_t *newmultiplex);static void ClearTableInfo(void);static void SubTableHandler(void * arg, dvbpsi_handle demuxHandle, uint8_t tableId, uint16_t extension);static void ProcessETT(void *arg, dvbpsi_atsc_ett_t *newETT);static void ProcessEIT(void *arg, dvbpsi_atsc_eit_t *newEIT);static void DeferredProcessEIT(void *arg);static void DeferredProcessETT(void *arg);static void ProcessEvent(EPGServiceRef_t *serviceRef, dvbpsi_atsc_eit_event_t *event);static void DumpDescriptor(char *prefix, dvbpsi_descriptor_t *descriptor);static void ConvertToTM(uint32_t startSeconds, uint32_t duration, struct tm *startTime, struct tm *endTime);/******************************************************************************** Global variables ********************************************************************************/static PluginFilter_t filter = {NULL, InitEITFilter, DeinitEITFilter};static const char ATSCTOEPG[] = "ATSCtoEPG";static uint8_t GPStoUTCSecondsOffset = 14; /* From the test streams 24th May 2007 */static int EventInfoTableCount = 0;static TableInfo_t EventInfoTableInfo[MAX_EITS];static int ExtendedTextTableCount = 0;static TableInfo_t ExtendedTextTableInfo[MAX_ETTS];static time_t UnixEpochOffset = 315964800;/******************************************************************************** Plugin Setup ********************************************************************************/#ifdef __CYGWIN__#define PluginInterface ATSCtoEPGPluginInterface#endifPLUGIN_FEATURES( PLUGIN_FEATURE_FILTER(filter), PLUGIN_FEATURE_MGTPROCESSOR(NewMGT), PLUGIN_FEATURE_STTPROCESSOR(NewSTT) );PLUGIN_INTERFACE_F( PLUGIN_FOR_ATSC, "ATSCtoEPG", "0.1", "Plugin to capture ATSC EPG schedule information.", "charrea6@users.sourceforge.net" );/******************************************************************************** Filter Functions ********************************************************************************/static void InitEITFilter(PIDFilter_t *filter){ filter->name = "ATSC to EPG"; filter->enabled = TRUE; PIDFilterFilterPacketSet(filter, ATSCtoEPGFilterPacket, NULL); PIDFilterMultiplexChangeSet(filter, ATSCtoEPGMultiplexChanged, NULL); PIDFilterProcessPacketSet(filter, ATSCtoEPGProcessPacket, NULL); }static void DeinitEITFilter(PIDFilter_t *filter){ filter->enabled = FALSE; ClearTableInfo();}static void ClearTableInfo(void){ int i; for (i = 0; i < EventInfoTableCount; i ++) { dvbpsi_DetachDemux(EventInfoTableInfo[i].decoder); } EventInfoTableCount = 0; for (i = 0; i < ExtendedTextTableCount; i ++) { dvbpsi_atsc_DetachETT(ExtendedTextTableInfo[i].decoder); } ExtendedTextTableCount = 0;}static void NewMGT(dvbpsi_atsc_mgt_t *newMGT){ dvbpsi_atsc_mgt_table_t * table; ClearTableInfo(); for (table = newMGT->p_first_table; table; table = table->p_next) { if ((table->i_type >= 0x100) && (table->i_type <= 0x17f)) { EventInfoTableInfo[EventInfoTableCount].pid = table->i_pid; EventInfoTableInfo[EventInfoTableCount].decoder = dvbpsi_AttachDemux(SubTableHandler, NULL); EventInfoTableCount ++; } if ((table->i_type >= 0x200) && (table->i_type <= 0x27f)) { ExtendedTextTableInfo[ExtendedTextTableCount].pid = table->i_pid; ExtendedTextTableInfo[ExtendedTextTableCount].decoder = dvbpsi_atsc_AttachETT(ProcessETT, NULL); ExtendedTextTableCount ++; } }}static void NewSTT(dvbpsi_atsc_stt_t *newSTT){ GPStoUTCSecondsOffset = newSTT->i_gps_utc_offset;}static int ATSCtoEPGFilterPacket(PIDFilter_t *pidfilter, void *arg, uint16_t pid, TSPacket_t *packet){ int i; for (i = 0; i < EventInfoTableCount; i ++) { if (EventInfoTableInfo[i].pid == pid) { return TRUE; } } for (i = 0; i < ExtendedTextTableCount; i ++) { if (ExtendedTextTableInfo[i].pid == pid) { return TRUE; } } return FALSE;}static void ATSCtoEPGMultiplexChanged(PIDFilter_t *pidfilter, void *arg, Multiplex_t *newmultiplex){ ClearTableInfo();}static TSPacket_t * ATSCtoEPGProcessPacket(PIDFilter_t *pidfilter, void *arg, TSPacket_t *packet){ int i; uint16_t pid = TSPACKET_GETPID(*packet); for (i = 0; i < EventInfoTableCount; i ++) { if (EventInfoTableInfo[i].pid == pid) { dvbpsi_PushPacket(EventInfoTableInfo[i].decoder, (uint8_t*)packet); } } for (i = 0; i < ExtendedTextTableCount; i ++) { if (ExtendedTextTableInfo[i].pid == pid) { dvbpsi_PushPacket(ExtendedTextTableInfo[i].decoder, (uint8_t*)packet); } } return NULL;}static void SubTableHandler(void * arg, dvbpsi_handle demuxHandle, uint8_t tableId, uint16_t extension){ dvbpsi_atsc_AttachEIT(demuxHandle, tableId, extension, ProcessEIT, NULL);}static void ProcessETT(void *arg, dvbpsi_atsc_ett_t *newETT){ DeferredProcessingAddJob(DeferredProcessETT, newETT); ObjectRefDec(newETT); }static void ProcessEIT(void *arg, dvbpsi_atsc_eit_t *newEIT){ DeferredProcessingAddJob(DeferredProcessEIT, newEIT); ObjectRefDec(newEIT);}static void DeferredProcessEIT(void *arg){ dvbpsi_atsc_eit_t *eit = (dvbpsi_atsc_eit_t *)arg; Multiplex_t *multiplex = TuningCurrentMultiplexGet(); EPGServiceRef_t serviceRef; dvbpsi_atsc_eit_event_t *event; LogModule(LOG_DEBUG, ATSCTOEPG, "Processing EIT (version %d) source id %x\n", eit->i_version, eit->i_source_id); EPGDBaseTransactionStart(); serviceRef.netId = multiplex->networkId; serviceRef.tsId = multiplex->tsId; serviceRef.serviceId = eit->i_source_id; for (event = eit->p_first_event; event; event = event->p_next) { ProcessEvent(&serviceRef, event); } ObjectRefDec(eit); EPGDBaseTransactionCommit(); MultiplexRefDec(multiplex);}static void DeferredProcessETT(void *arg){ ATSCMultipleStrings_t *description; dvbpsi_atsc_ett_t *ett = (dvbpsi_atsc_ett_t*) arg; Multiplex_t *multiplex = TuningCurrentMultiplexGet(); EPGServiceRef_t serviceRef; unsigned int eventId; char lang[4]; int i; serviceRef.netId = multiplex->networkId; serviceRef.tsId = multiplex->tsId; serviceRef.serviceId = (ett->i_etm_id >> 16) & 0xffff; eventId = (ett->i_etm_id & 0xffff) >> 2; lang[3] = 0; EPGDBaseTransactionStart(); description = ATSCMultipleStringsConvert(ett->p_etm, ett->i_etm_length); LogModule(LOG_DEBUG, ATSCTOEPG,"Processing ETT for %04x.%04x.%04x.%04x (%08x): Number of strings %d\n", serviceRef.netId, serviceRef.tsId, serviceRef.serviceId, eventId,ett->i_etm_id, description->number_of_strings); for (i = 0; i < description->number_of_strings; i ++) { LogModule(LOG_DEBUG, ATSCTOEPG, "%d : (%c%c%c) %s\n", i + 1, description->strings[i].lang[0],description->strings[i].lang[1],description->strings[i].lang[2], description->strings[i].text); lang[0] = description->strings[i].lang[0]; lang[1] = description->strings[i].lang[1]; lang[2] = description->strings[i].lang[2]; EPGDBaseDetailAdd(&serviceRef,eventId, lang, EPG_EVENT_DETAIL_DESCRIPTION,description->strings[i].text); } EPGDBaseTransactionCommit(); ObjectRefDec(description); MultiplexRefDec(multiplex); ObjectRefDec(ett);}/******************************************************************************** Helper Functions ********************************************************************************/static void ProcessEvent(EPGServiceRef_t *serviceRef, dvbpsi_atsc_eit_event_t *eitevent){ EPGEvent_t epgevent; dvbpsi_descriptor_t *descriptor; char startTimeStr[25]; char endTimeStr[25]; ATSCMultipleStrings_t *title; int i; char lang[4]; epgevent.serviceRef = *serviceRef; epgevent.eventId = eitevent->i_event_id; ConvertToTM(eitevent->i_start_time, eitevent->i_length_seconds, &epgevent.startTime, &epgevent.endTime); epgevent.ca = FALSE; strftime(startTimeStr, sizeof(startTimeStr), "%Y-%m-%d %T", &epgevent.startTime); strftime(endTimeStr, sizeof(startTimeStr), "%Y-%m-%d %T", &epgevent.endTime); LogModule(LOG_DEBUG, ATSCTOEPG, "Processing EIT for %04x.%04x.%04x.%04x Start Time %s (%d) End Time %s (duration %d) Title Length %d ETM location=%d\n", serviceRef->netId, serviceRef->tsId, serviceRef->serviceId, epgevent.eventId, startTimeStr,eitevent->i_start_time, endTimeStr,eitevent->i_length_seconds, eitevent->i_title_length, eitevent->i_etm_location); if (EPGDBaseEventAdd(&epgevent) != 0) { return; } lang[3] = 0; title = ATSCMultipleStringsConvert(eitevent->i_title, eitevent->i_title_length); for (i = 0; i < title->number_of_strings; i ++) { LogModule(LOG_DEBUG, ATSCTOEPG, "%d : (%c%c%c) %s\n", i + 1, title->strings[i].lang[0],title->strings[i].lang[1],title->strings[i].lang[2], title->strings[i].text); lang[0] = title->strings[i].lang[0]; lang[1] = title->strings[i].lang[1]; lang[2] = title->strings[i].lang[2]; EPGDBaseDetailAdd(serviceRef,epgevent.eventId, lang, EPG_EVENT_DETAIL_TITLE,title->strings[i].text); } ObjectRefDec(title); LogModule(LOG_DEBUGV, ATSCTOEPG, "Start of Descriptors\n"); for (descriptor = eitevent->p_first_descriptor; descriptor; descriptor = descriptor->p_next) { DumpDescriptor("\t", descriptor); } LogModule(LOG_DEBUGV, ATSCTOEPG, "End of Descriptors:\n"); }static void ConvertToTM(uint32_t startSeconds, uint32_t duration, struct tm *startTime, struct tm *endTime){ struct tm *temp_time; time_t secs; secs = startSeconds + UnixEpochOffset - GPStoUTCSecondsOffset; temp_time = gmtime(&secs); *startTime = *temp_time; secs += duration; temp_time = gmtime(&secs); *endTime = *temp_time;}static void DumpDescriptor(char *prefix, dvbpsi_descriptor_t *descriptor){ int i; char line[(16 * 3) + 1]; line[0] = 0; LogModule(LOG_DEBUGV, ATSCTOEPG, "%sTag : 0x%02x (Length %d)\n", prefix, descriptor->i_tag, descriptor->i_length); for (i = 0; i < descriptor->i_length; i ++) { if (i && ((i % 16) == 0)) { LogModule(LOG_DEBUGV, ATSCTOEPG, "%s%s\n", prefix, line); line[0] = 0; } sprintf(line + strlen(line), "%02x ", descriptor->p_data[i]); } if (line[0]) { LogModule(LOG_DEBUGV, ATSCTOEPG, "%s%s\n", prefix, line); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -