[libdvbpsi-devel] How to decode EIT and SDT?
Bernhard Ehlers
b-ehlers at gmx.de
Tue Feb 21 13:48:10 CET 2012
Hi
for EIT decoding you register a function via dvbpsi_AttachDemux.
Afterwards you attach the EIT decoder function with dvbpsi_AttachEIT.
This doesn't have to happen in the AttachDemux callback function as
shown in this example. In another program I do the dvbpsi_AttachEIT
in the PAT decoder.
With SDT it works similar.
Have a look at the following program, which does a basic EIT decoding.
Please note, that this program ignores the charset in the EIT data.
A correct charset handling is quite complex.
Best regards
Bernhard
/*
* eit - some basic informations about EIT contents
*
* Usage: eit [-e <EIT Pid>] [-s <Service ID>] <file>
*/
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <dvbpsi/dvbpsi.h>
#include <dvbpsi/demux.h>
#include <dvbpsi/descriptor.h>
#include <dvbpsi/dr_4d.h>
#include <dvbpsi/dr_69.h>
#include <dvbpsi/eit.h>
#define EIT_PID 18 /* EIT pid */
#define TS_LEN 188 /* length of MPEG-2 TS frame */
#define BUF_SIZE (TS_LEN*256) /* Buffer size */
static int eit_pid = EIT_PID;
static int service_id = -1;
static void usage(void) {
fprintf(stderr, "\
eit - some basic informations about EIT contents\n\n\
Usage: eit [-e <EIT Pid>] [-s <Service ID>] <file>\n\
");
exit(1);
}
/*
* printf_err - printf to stderr and exit(1)
*/
static void printf_err(char *format, ...) {
va_list varg;
va_start(varg, format);
fprintf(stderr, "tseit: ");
vfprintf(stderr, format, varg);
va_end(varg);
exit(1);
}
/*
* si_time - convert DVB-SI time to seconds since 00:00
*/
int si_time(uint32_t time) {
int hour, min, sec;
hour = (time >> 16) & 0xff;
hour = (hour >> 4) * 10 + (hour & 0x0f);
min = (time >> 8) & 0xff;
min = (min >> 4) * 10 + (min & 0x0f);
sec = time & 0xff;
sec = (sec >> 4) * 10 + (sec & 0x0f);
return ((hour * 60) + min) * 60 + sec;
}
/*
* si_date - convert DVB-SI date to unix time (seconds since 1970-01-01)
*/
time_t si_date(uint64_t date) {
time_t epoch;
epoch = (date >> 24) & 0xffff; /* modified julian date */
if (epoch < 40587) return 0; /* mjd-40587 = days since 1970-01-01 */
epoch = (epoch-40587) * 24*60*60 + si_time((uint32_t)date & 0xffffff);
return epoch;
}
/*
* asc_localtime - generate date string
*/
static char *asc_localtime(time_t *clock) {
struct tm tm;
static char strtime[20];
localtime_r(clock, &tm);
sprintf(strtime, "%02d.%02d.%04d %02d:%02d:%02d",
tm.tm_mday, tm.tm_mon + 1, tm.tm_year + 1900,
tm.tm_hour, tm.tm_min, tm.tm_sec);
return strtime;
}
/*
* copy SI string to C string, ignore charset
*/
void cp_si(char *dest, int size, unsigned char *si, int len) {
if (len > 0 && *si < 0x20) {
si++; len--;
}
if (len >= size) len = size-1;
memcpy(dest, si, len);
dest[len] = '\0';
}
void show_eit(void *private, dvbpsi_eit_t* eit) {
dvbpsi_eit_event_t *event;
dvbpsi_descriptor_t *descriptor;
dvbpsi_short_event_dr_t *short_dr;
dvbpsi_PDC_dr_t *pdc_dr;
time_t start, end;
char title[129], subtitle[129];
char pdc[6];
for (event = eit->p_first_event; event != NULL; event = event->p_next) {
if (event->i_running_status == 1) continue;
start = si_date(event->i_start_time);
end = start + si_time(event->i_duration);
title[0] = '\0';
subtitle[0] = '\0';
pdc[0] = '\0';
for (descriptor = event->p_first_descriptor;
descriptor != NULL; descriptor = descriptor->p_next)
switch (descriptor->i_tag) {
case 0x4d: /* short event descriptor */
short_dr = dvbpsi_DecodeShortEventDr(descriptor);
if (short_dr->i_event_name_length != short_dr->i_text_length ||
memcmp(short_dr->i_event_name, short_dr->i_text,
short_dr->i_event_name_length) != 0) {
cp_si(subtitle, sizeof(subtitle),
short_dr->i_text, short_dr->i_text_length);
}
cp_si(title, sizeof(title),
short_dr->i_event_name, short_dr->i_event_name_length);
break;
case 0x69: /* PDC descriptor */
pdc_dr = dvbpsi_DecodePDCDr(descriptor);
sprintf(pdc, "%02d:%02d", pdc_dr->i_PDC[2], pdc_dr->i_PDC[3]);
break;
default:
break;
}
/* output event */
printf("Service=%u ", eit->i_service_id);
printf("%d ", event->i_running_status);
printf("%.16s", asc_localtime(&start));
printf("-%.5s", asc_localtime(&end)+11);
if (pdc[0] != '\0')
printf(" PDC=%s", pdc);
printf(" %s", title);
if (subtitle[0] != '\0')
printf(" / %s", subtitle);
printf("\n");
}
dvbpsi_DeleteEIT(eit);
}
void NewEIT(void *private, dvbpsi_handle h_dvbpsi,
uint8_t table_id, uint16_t extension) {
if (table_id == 0x4E) {
if (service_id < 0 || service_id == extension)
dvbpsi_AttachEIT(h_dvbpsi, table_id, extension, show_eit, NULL);
}
}
static dvbpsi_handle dvbpsi_eit = NULL;
/*
* analyze_buf - analyze a buffer with several MPEG transport frames
*/
static void analyze_buf(unsigned char *buffer, int len) {
// static int num = 0;
unsigned char *bp;
int pid;
for (bp = buffer; len >= TS_LEN; bp += TS_LEN, len -= TS_LEN) {
if (bp[0] != 0x47)
printf_err("Invalid sync byte 0x%02X - should be 0x47\n", bp[0]);
pid = ((bp[1] & 0x1f) << 8) + bp[2];
if (pid == eit_pid) {
dvbpsi_PushPacket(dvbpsi_eit, bp);
}
}
if (len != 0)
printf_err("Input data size not multiple of %d.\n", TS_LEN);
}
/*
* read_file - read MPEG from file
*/
static void read_file(char *fname) {
int fd;
int len;
unsigned char buffer[BUF_SIZE];
if ((fd = open(fname, O_RDONLY)) < 0)
{ perror(fname); exit(1); }
/* analyze file */
while (1) {
len = read(fd, buffer, sizeof(buffer));
if (len < 0) { perror("read"); exit(1); }
if (len == 0) break;
analyze_buf(buffer, len);
}
close(fd);
}
int main(int argc, char *argv[]) {
int ch;
char *fname;
eit_pid = EIT_PID;
service_id = -1;
/* handle command line options */
while ((ch = getopt(argc, argv, "e:s:")) > 0) {
switch (ch) {
case 'e':
eit_pid = atoi(optarg);
break;
case 's':
service_id = atoi(optarg);
break;
case '?':
default:
usage();
break;
}
}
if ((argc - optind) != 1) usage();
fname = argv[optind];
dvbpsi_eit = dvbpsi_AttachDemux(NewEIT, NULL);
read_file(fname);
dvbpsi_DetachDemux(dvbpsi_eit);
return 0;
}
--
Empfehlen Sie GMX DSL Ihren Freunden und Bekannten und wir
belohnen Sie mit bis zu 50,- Euro! https://freundschaftswerbung.gmx.de
More information about the libdvbpsi-devel
mailing list