working with first descriptor
This commit is contained in:
parent
d91dccdd7b
commit
db87f8326e
10
Makefile
10
Makefile
|
@ -12,11 +12,17 @@ MAKE=gmake
|
|||
DEFS=-D_REENTRANT -D_TS_ERRNO -DHMT_PROTECT
|
||||
# -DWITH_MPATROL
|
||||
|
||||
SRCS= epg.c \
|
||||
SRCS= descriptor.c \
|
||||
epg.c \
|
||||
file.c \
|
||||
main.c \
|
||||
util.c
|
||||
|
||||
HDRS= descriptor.h \
|
||||
epg.h \
|
||||
lint.h \
|
||||
util.h
|
||||
|
||||
OBJS= $(SRCS:.c=.o)
|
||||
CC=gcc
|
||||
#CC=mipsel-linux-gcc
|
||||
|
@ -61,5 +67,5 @@ tags:
|
|||
@echo " $<"
|
||||
@$(CC) $(CFLAGS) ${WARN} ${DEFS} ${INCS} -c $< -o $@
|
||||
|
||||
${OBJS}: lint.h
|
||||
${OBJS}: ${HDRS}
|
||||
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "lint.h"
|
||||
|
||||
struct descriptor *
|
||||
read_descriptor_header(struct epg *epg)
|
||||
{
|
||||
static struct descriptor d;
|
||||
|
||||
if (epg->binsize - epg->offset < 2)
|
||||
return NULL;
|
||||
|
||||
memcpy(&d, epg->bin + epg->offset, 2);
|
||||
|
||||
epg->offset += 2;
|
||||
|
||||
return &d;
|
||||
}
|
||||
|
||||
void
|
||||
read_descriptor(struct epg *epg, struct descriptor *d)
|
||||
{
|
||||
switch (d->tag)
|
||||
{
|
||||
case 77:
|
||||
memcpy(d->content.d77.language, epg->bin + epg->offset, 3);
|
||||
epg->offset += 3;
|
||||
|
||||
d->content.d77.namelen = epg->bin[epg->offset++];
|
||||
d->content.d77.name = read_string_len(epg->bin + epg->offset,
|
||||
d->content.d77.namelen);
|
||||
epg->offset += d->content.d77.namelen;
|
||||
|
||||
d->content.d77.textlen = epg->bin[epg->offset++];
|
||||
d->content.d77.text = read_string_len(epg->bin + epg->offset,
|
||||
d->content.d77.textlen);
|
||||
epg->offset += d->content.d77.textlen;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
epg->offset += d->len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
skip_descriptor(struct epg *epg, struct descriptor *d)
|
||||
{
|
||||
epg->offset += d->len;
|
||||
}
|
||||
|
||||
void
|
||||
free_descriptor(struct descriptor *d)
|
||||
{
|
||||
switch (d->tag)
|
||||
{
|
||||
case DS_SHORT_EVENT:
|
||||
free(d->content.d77.name);
|
||||
free(d->content.d77.text);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
descriptor_name(struct descriptor *d)
|
||||
{
|
||||
switch (d->tag)
|
||||
{
|
||||
case DS_LINKAGE: return "linkage";
|
||||
case DS_SHORT_EVENT: return "short event";
|
||||
case DS_COMPONENT: return "component";
|
||||
case DS_CONTENT: return "content";
|
||||
case DS_PRIVATE_DATA_SPECIFIER: return "private data spec.";
|
||||
case DS_CONTENT_IDENTIFIER: return "content id";
|
||||
case DS_FTA_CONTENT_MGMT: return "content mgmt";
|
||||
case DS_USER_DEFINED: return "user defined";
|
||||
default: return "Unknown";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
void
|
||||
dump_descriptor(struct descriptor *d, int content)
|
||||
{
|
||||
printf("Descriptor header:\n");
|
||||
printf(" %30s: %#x [%d] (%s)\n", "descriptor", d->tag, d->tag,
|
||||
descriptor_name(d));
|
||||
DUMPINT(d, len);
|
||||
|
||||
if (!content)
|
||||
return;
|
||||
|
||||
switch (d->tag)
|
||||
{
|
||||
case DS_SHORT_EVENT:
|
||||
DUMPNSTR(d, content.d77.language, 3);
|
||||
DUMPINT(d, content.d77.namelen);
|
||||
//DUMPNSTR(d, content.d77.name, d->content.d77.namelen);
|
||||
DUMPHEX(d, content.d77.name, d->content.d77.namelen);
|
||||
DUMPINT(d, content.d77.textlen);
|
||||
//DUMPNSTR(d, content.d77.text, d->content.d77.textlen);
|
||||
DUMPHEX(d, content.d77.text, d->content.d77.textlen);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#define DS_LINKAGE 74
|
||||
#define DS_SHORT_EVENT 77
|
||||
#define DS_COMPONENT 80
|
||||
#define DS_CONTENT 84
|
||||
#define DS_PRIVATE_DATA_SPECIFIER 95
|
||||
#define DS_CONTENT_IDENTIFIER 118
|
||||
#define DS_FTA_CONTENT_MGMT 126
|
||||
#define DS_USER_DEFINED 137
|
||||
|
||||
struct descriptor {
|
||||
unsigned int tag:8;
|
||||
unsigned int len:8;
|
||||
union {
|
||||
struct {
|
||||
char language[3];
|
||||
unsigned int namelen:8;
|
||||
unsigned int textlen:8;
|
||||
char *name;
|
||||
char *text;
|
||||
} d77;
|
||||
} content;
|
||||
};
|
||||
|
110
epg.c
110
epg.c
|
@ -9,18 +9,16 @@
|
|||
|
||||
#include "lint.h"
|
||||
|
||||
#define _swap16(v) ((((v) >> 8) & 0xff) | (((v) & 0xff) << 8))
|
||||
|
||||
struct section_header *
|
||||
read_section_header(struct epg *epg)
|
||||
struct section *
|
||||
read_section(struct epg *epg)
|
||||
{
|
||||
static struct section_header h;
|
||||
static struct section h;
|
||||
|
||||
if (epg->binsize - epg->offset < sizeof(h))
|
||||
return NULL;
|
||||
|
||||
memcpy(&h, epg->bin + epg->offset, sizeof(h));
|
||||
if (memcmp(h.magic, SECTION_HEADER_MAGIC, sizeof(h.magic)))
|
||||
if (memcmp(h.magic, SECTION_MAGIC, sizeof(h.magic)))
|
||||
{
|
||||
printf("Section header magic mismatch.\n");
|
||||
return NULL;
|
||||
|
@ -38,6 +36,27 @@ read_section_header(struct epg *epg)
|
|||
return &h;
|
||||
}
|
||||
|
||||
void
|
||||
dump_section(struct section *h)
|
||||
{
|
||||
printf("Section header:\n");
|
||||
DUMPINT(h, total_length);
|
||||
DUMPINT(h, table_id);
|
||||
DUMPINT(h, u1.u.syntax_indicator);
|
||||
DUMPINT(h, u1.u.reserved);
|
||||
DUMPINT(h, u1.u.length);
|
||||
DUMPINT(h, service_id);
|
||||
DUMPINT(h, reserved2);
|
||||
DUMPINT(h, version_number);
|
||||
DUMPINT(h, current_next_indicator);
|
||||
DUMPINT(h, section_number);
|
||||
DUMPINT(h, last_section_number);
|
||||
DUMPINT(h, transport_stream_id);
|
||||
DUMPINT(h, original_network_id);
|
||||
DUMPINT(h, segment_last_section_number);
|
||||
DUMPINT(h, last_table_id);
|
||||
}
|
||||
|
||||
struct data *
|
||||
read_data(struct epg *epg)
|
||||
{
|
||||
|
@ -57,58 +76,6 @@ read_data(struct epg *epg)
|
|||
return &d;
|
||||
}
|
||||
|
||||
struct descriptor_header *
|
||||
read_descriptor_header(struct epg *epg)
|
||||
{
|
||||
static struct descriptor_header d;
|
||||
|
||||
if (epg->binsize - epg->offset < sizeof(d))
|
||||
return NULL;
|
||||
|
||||
memcpy(&d, epg->bin + epg->offset, sizeof(d));
|
||||
|
||||
epg->offset += sizeof(d);
|
||||
|
||||
return &d;
|
||||
}
|
||||
|
||||
#define DUMPINT(ss,xx) printf(" %30s: %d\n", #xx, ss->xx)
|
||||
#define DUMPSTR(ss,xx) printf(" %30s: %s\n", #xx, ss->xx)
|
||||
#define DUMPHEX(ss,xx) printf(" %30s: %s\n", #xx, \
|
||||
hexstr(ss->xx, sizeof(ss->xx)))
|
||||
|
||||
char *
|
||||
ctime_nl(time_t *tm)
|
||||
{
|
||||
static char buf[26];
|
||||
|
||||
strcpy(buf, ctime(tm));
|
||||
*strchr(buf, '\n') = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
dump_section_header(struct section_header *h)
|
||||
{
|
||||
printf("Section header:\n");
|
||||
DUMPINT(h, total_length);
|
||||
DUMPINT(h, table_id);
|
||||
DUMPINT(h, u1.u.syntax_indicator);
|
||||
DUMPINT(h, u1.u.reserved);
|
||||
DUMPINT(h, u1.u.length);
|
||||
DUMPINT(h, service_id);
|
||||
DUMPINT(h, reserved2);
|
||||
DUMPINT(h, version_number);
|
||||
DUMPINT(h, current_next_indicator);
|
||||
DUMPINT(h, section_number);
|
||||
DUMPINT(h, last_section_number);
|
||||
DUMPINT(h, transport_stream_id);
|
||||
DUMPINT(h, original_network_id);
|
||||
DUMPINT(h, segment_last_section_number);
|
||||
DUMPINT(h, last_table_id);
|
||||
}
|
||||
|
||||
void
|
||||
dump_data(struct data *d)
|
||||
{
|
||||
|
@ -131,30 +98,3 @@ dump_data(struct data *d)
|
|||
DUMPINT(d, u1.u.descriptors_loop_length);
|
||||
}
|
||||
|
||||
char *
|
||||
descriptor_name(struct descriptor_header *d)
|
||||
{
|
||||
switch (d->tag)
|
||||
{
|
||||
case 77: return "short event";
|
||||
case 80: return "component";
|
||||
case 137: return "user defined";
|
||||
case 118: return "content identifier";
|
||||
case 74: return "linkage";
|
||||
case 84: return "content";
|
||||
case 95: return "private data specifier";
|
||||
case 126: return "FTA content management";
|
||||
default: return "Unknown";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
void
|
||||
dump_descriptor_header(struct descriptor_header *d)
|
||||
{
|
||||
printf("Descriptor header:\n");
|
||||
printf(" %30s: %#x [%d] (%s)\n", "descriptor", d->tag, d->tag,
|
||||
descriptor_name(d));
|
||||
DUMPINT(d, len);
|
||||
}
|
||||
|
||||
|
|
10
epg.h
10
epg.h
|
@ -9,10 +9,10 @@ struct epg {
|
|||
uint32_t binsize;
|
||||
};
|
||||
|
||||
#define SECTION_HEADER_MAGIC "(Gq\x87\x00\x00\x00\x00\x02\x00\x00\x00\x00\x01"
|
||||
#define SECTION_MAGIC "(Gq\x87\x00\x00\x00\x00\x02\x00\x00\x00\x00\x01"
|
||||
|
||||
#pragma pack(1)
|
||||
struct section_header {
|
||||
struct section {
|
||||
char magic[14];
|
||||
unsigned int total_length:16;
|
||||
unsigned int magic2:32;
|
||||
|
@ -37,6 +37,7 @@ struct section_header {
|
|||
unsigned int last_table_id:8;
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
struct data {
|
||||
unsigned int event_id:16;
|
||||
unsigned int start_date:16;
|
||||
|
@ -56,8 +57,3 @@ struct data {
|
|||
} u1;
|
||||
};
|
||||
|
||||
struct descriptor_header {
|
||||
unsigned int tag:8;
|
||||
unsigned int len:8;
|
||||
};
|
||||
|
||||
|
|
19
lint.h
19
lint.h
|
@ -1,8 +1,7 @@
|
|||
|
||||
#include "epg.h"
|
||||
|
||||
/* Works for modern dates, 1970 - 2038 */
|
||||
#define MJD_TO_UNIX(xx) (((xx) - 40587) * 86400)
|
||||
#include "descriptor.h"
|
||||
#include "util.h"
|
||||
|
||||
extern int debug;
|
||||
extern const char *version;
|
||||
|
@ -11,17 +10,21 @@ extern unsigned long sysopts;
|
|||
inline uint16_t read_uint16(uint8_t *, int);
|
||||
inline uint32_t read_uint32(uint8_t *, int);
|
||||
void hexdump(uint8_t *, uint32_t, uint32_t);
|
||||
void hexstr(uint8_t *, uint32_t);
|
||||
char *hexstr(uint8_t *, uint32_t);
|
||||
char *ctime_nl(time_t *);
|
||||
char *read_string_len(uint8_t *, uint32_t);
|
||||
|
||||
struct epg *open_file(char *);
|
||||
void close_file(struct epg *);
|
||||
|
||||
struct section_header *read_section_header(struct epg *);
|
||||
void dump_section_header(struct section_header *);
|
||||
struct section *read_section(struct epg *);
|
||||
void dump_section(struct section *);
|
||||
|
||||
struct data *read_data(struct epg *);
|
||||
void dump_data(struct data *);
|
||||
|
||||
struct descriptor_header *read_descriptor_header(struct epg *);
|
||||
void dump_descriptor_header(struct descriptor_header *);
|
||||
struct descriptor *read_descriptor_header(struct epg *);
|
||||
void read_descriptor(struct epg *, struct descriptor *);
|
||||
void skip_descriptor(struct epg *, struct descriptor *);
|
||||
void dump_descriptor(struct descriptor *, int);
|
||||
|
||||
|
|
37
main.c
37
main.c
|
@ -36,8 +36,7 @@ syntax()
|
|||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct section_header *h;
|
||||
struct data *d;
|
||||
struct section *h;
|
||||
struct epg *epg;
|
||||
|
||||
if (!(epg = open_file("../epg.dat")))
|
||||
|
@ -45,36 +44,44 @@ main(int argc, char **argv)
|
|||
|
||||
while (epg->offset < epg->binsize)
|
||||
{
|
||||
uint32_t end;
|
||||
uint32_t send;
|
||||
|
||||
if (!(h = read_section_header(epg)))
|
||||
if (!(h = read_section(epg)))
|
||||
break;
|
||||
dump_section_header(h);
|
||||
//dump_section(h);
|
||||
|
||||
end = epg->offset - 11 + h->u1.u.length - 4;
|
||||
send = epg->offset - 11 + h->u1.u.length - 4;
|
||||
|
||||
while (epg->offset < end)
|
||||
while (epg->offset < send)
|
||||
{
|
||||
struct data *d;
|
||||
uint32_t dend;
|
||||
|
||||
if (!(d = read_data(epg)))
|
||||
break;
|
||||
dump_data(d);
|
||||
//dump_data(d);
|
||||
|
||||
dend = epg->offset + d->u1.u.descriptors_loop_length;
|
||||
while (epg->offset < dend)
|
||||
{
|
||||
struct descriptor_header *dh;
|
||||
struct descriptor *ds;
|
||||
|
||||
dh = read_descriptor_header(epg);
|
||||
dump_descriptor_header(dh);
|
||||
|
||||
epg->offset += dh->len;
|
||||
ds = read_descriptor_header(epg);
|
||||
if (ds->tag == DS_SHORT_EVENT)
|
||||
{
|
||||
read_descriptor(epg, ds);
|
||||
dump_descriptor(ds, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
dump_descriptor(ds, 0);
|
||||
skip_descriptor(epg, ds);
|
||||
}
|
||||
printf("Offset: %d / %d\n", epg->offset, dend);
|
||||
}
|
||||
//goto stop;
|
||||
}
|
||||
|
||||
/* Section CRC */
|
||||
/* Skip CRC */
|
||||
epg->offset += 4;
|
||||
|
||||
/* Skip padding bytes... */
|
||||
|
|
27
util.c
27
util.c
|
@ -12,6 +12,26 @@
|
|||
|
||||
#include "lint.h"
|
||||
|
||||
char *
|
||||
ctime_nl(time_t *tm)
|
||||
{
|
||||
static char buf[26];
|
||||
|
||||
strcpy(buf, ctime(tm));
|
||||
*strchr(buf, '\n') = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
inline char *
|
||||
read_string_len(uint8_t *src, uint32_t len)
|
||||
{
|
||||
char *s = malloc(len + 1);
|
||||
memcpy(s, src, len);
|
||||
s[len] = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
read_uint32(uint8_t *p, int le)
|
||||
{
|
||||
|
@ -77,9 +97,10 @@ hexdump(uint8_t *s, uint32_t len, uint32_t o)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
char *
|
||||
hexstr(uint8_t *s, uint32_t len)
|
||||
{
|
||||
static char buf[0x1000];
|
||||
uint16_t off;
|
||||
|
||||
if (!s)
|
||||
|
@ -88,6 +109,7 @@ hexstr(uint8_t *s, uint32_t len)
|
|||
if (!len)
|
||||
len = strlen((char *)s);
|
||||
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
for (off = 0; off < len; off += 16)
|
||||
{
|
||||
uint32_t i;
|
||||
|
@ -95,9 +117,10 @@ hexstr(uint8_t *s, uint32_t len)
|
|||
for (i = off; i - off < 16; i++)
|
||||
{
|
||||
if (i < len)
|
||||
printf("%02x", s[i] & 0xff);
|
||||
sprintf(buf + i * 3, "%02x ", s[i] & 0xff);
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
/* Works for modern dates, 1970 - 2038 */
|
||||
#define MJD_TO_UNIX(xx) (((xx) - 40587) * 86400)
|
||||
|
||||
#define _swap16(v) ((((v) >> 8) & 0xff) | (((v) & 0xff) << 8))
|
||||
|
||||
#define DUMPINT(ss,xx) printf(" %30s: %d\n", #xx, ss->xx)
|
||||
#define DUMPSTR(ss,xx) printf(" %30s: %s\n", #xx, ss->xx)
|
||||
#define DUMPNSTR(ss,xx,nn) printf(" %30s: %.*s\n", #xx, nn, ss->xx)
|
||||
#define DUMPHEX(ss,xx,nn) printf(" %30s: %s\n", #xx, hexstr(ss->xx, nn))
|
||||
|
Loading…
Reference in New Issue