Commit ee092b7f authored by bellard's avatar bellard

cosmetic change in resync code - added PAT scanning code if no SDT is found...

cosmetic change in resync code - added PAT scanning code if no SDT is found (in the futur it would be interesting to give an API to change channel - also useful for DV input number or TV grab tunning


git-svn-id: file:///var/local/repositories/ffmpeg/trunk@2043 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
parent efe7169d
...@@ -23,7 +23,11 @@ ...@@ -23,7 +23,11 @@
//#define DEBUG_SI //#define DEBUG_SI
/* 1.0 second at 24Mbit/s */ /* 1.0 second at 24Mbit/s */
#define MAX_SCAN_PACKETS 16000 #define MAX_SCAN_PACKETS 32000
/* maximum size in which we look for synchronisation if
synchronisation is lost */
#define MAX_RESYNC_SIZE 4096
static int add_pes_stream(AVFormatContext *s, int pid); static int add_pes_stream(AVFormatContext *s, int pid);
...@@ -32,7 +36,6 @@ enum MpegTSFilterType { ...@@ -32,7 +36,6 @@ enum MpegTSFilterType {
MPEGTS_SECTION, MPEGTS_SECTION,
}; };
/* XXX: suppress 'pkt' parameter */
typedef void PESCallback(void *opaque, const uint8_t *buf, int len, int is_start); typedef void PESCallback(void *opaque, const uint8_t *buf, int len, int is_start);
typedef struct MpegTSPESFilter { typedef struct MpegTSPESFilter {
...@@ -432,7 +435,7 @@ static void pat_cb(void *opaque, const uint8_t *section, int section_len) ...@@ -432,7 +435,7 @@ static void pat_cb(void *opaque, const uint8_t *section, int section_len)
if (sid == 0x0000) { if (sid == 0x0000) {
/* NIT info */ /* NIT info */
} else { } else {
if (ts->req_sid == sid || ts->req_sid < 0) { if (ts->req_sid == sid) {
ts->pmt_filter = mpegts_open_section_filter(ts, pmt_pid, ts->pmt_filter = mpegts_open_section_filter(ts, pmt_pid,
pmt_cb, ts, 1); pmt_cb, ts, 1);
goto found; goto found;
...@@ -447,6 +450,59 @@ static void pat_cb(void *opaque, const uint8_t *section, int section_len) ...@@ -447,6 +450,59 @@ static void pat_cb(void *opaque, const uint8_t *section, int section_len)
ts->pat_filter = NULL; ts->pat_filter = NULL;
} }
/* add all services found in the PAT */
static void pat_scan_cb(void *opaque, const uint8_t *section, int section_len)
{
MpegTSContext *ts = opaque;
SectionHeader h1, *h = &h1;
const uint8_t *p, *p_end;
int sid, pmt_pid;
char *provider_name, *name;
char buf[256];
#ifdef DEBUG_SI
printf("PAT:\n");
av_hex_dump((uint8_t *)section, section_len);
#endif
p_end = section + section_len - 4;
p = section;
if (parse_section_header(h, &p, p_end) < 0)
return;
if (h->tid != PAT_TID)
return;
for(;;) {
sid = get16(&p, p_end);
if (sid < 0)
break;
pmt_pid = get16(&p, p_end) & 0x1fff;
if (pmt_pid < 0)
break;
#ifdef DEBUG_SI
printf("sid=0x%x pid=0x%x\n", sid, pmt_pid);
#endif
if (sid == 0x0000) {
/* NIT info */
} else {
/* add the service with a dummy name */
snprintf(buf, sizeof(buf), "Service %x\n", sid);
name = av_strdup(buf);
provider_name = av_strdup("");
if (name && provider_name) {
new_service(ts, sid, provider_name, name);
} else {
av_freep(&name);
av_freep(&provider_name);
}
}
}
ts->stop_parse = 1;
/* remove filter */
mpegts_close_filter(ts, ts->pat_filter);
ts->pat_filter = NULL;
}
void mpegts_set_service(MpegTSContext *ts, int sid, void mpegts_set_service(MpegTSContext *ts, int sid,
SetServiceCallback *set_service_cb, void *opaque) SetServiceCallback *set_service_cb, void *opaque)
{ {
...@@ -533,13 +589,20 @@ static void sdt_cb(void *opaque, const uint8_t *section, int section_len) ...@@ -533,13 +589,20 @@ static void sdt_cb(void *opaque, const uint8_t *section, int section_len)
ts->sdt_filter = NULL; ts->sdt_filter = NULL;
} }
/* scan services an a transport stream by looking at the sdt */ /* scan services in a transport stream by looking at the SDT */
void mpegts_scan_sdt(MpegTSContext *ts) void mpegts_scan_sdt(MpegTSContext *ts)
{ {
ts->sdt_filter = mpegts_open_section_filter(ts, SDT_PID, ts->sdt_filter = mpegts_open_section_filter(ts, SDT_PID,
sdt_cb, ts, 1); sdt_cb, ts, 1);
} }
/* scan services in a transport stream by looking at the PAT (better
than nothing !) */
void mpegts_scan_pat(MpegTSContext *ts)
{
ts->pat_filter = mpegts_open_section_filter(ts, PAT_PID,
pat_scan_cb, ts, 1);
}
/* TS stream handling */ /* TS stream handling */
...@@ -795,7 +858,7 @@ static void handle_packet(AVFormatContext *s, uint8_t *packet) ...@@ -795,7 +858,7 @@ static void handle_packet(AVFormatContext *s, uint8_t *packet)
if (cc_ok) { if (cc_ok) {
write_section_data(s, tss, write_section_data(s, tss,
p, p_end - p, 0); p, p_end - p, 0);
} }
} }
} else { } else {
tss->u.pes_filter.pes_cb(tss->u.pes_filter.opaque, tss->u.pes_filter.pes_cb(tss->u.pes_filter.opaque,
...@@ -803,13 +866,32 @@ static void handle_packet(AVFormatContext *s, uint8_t *packet) ...@@ -803,13 +866,32 @@ static void handle_packet(AVFormatContext *s, uint8_t *packet)
} }
} }
/* XXX: try to find a better synchro over several packets (use
get_packet_size() ?) */
static int mpegts_resync(AVFormatContext *s)
{
ByteIOContext *pb = &s->pb;
int c, i;
for(i = 0;i < MAX_RESYNC_SIZE; i++) {
c = url_fgetc(pb);
if (c < 0)
return -1;
if (c == 0x47) {
url_fseek(pb, -1, SEEK_CUR);
return 0;
}
}
/* no sync found */
return -1;
}
static int handle_packets(AVFormatContext *s, int nb_packets) static int handle_packets(AVFormatContext *s, int nb_packets)
{ {
MpegTSContext *ts = s->priv_data; MpegTSContext *ts = s->priv_data;
ByteIOContext *pb = &s->pb; ByteIOContext *pb = &s->pb;
uint8_t packet[TS_FEC_PACKET_SIZE]; uint8_t packet[TS_FEC_PACKET_SIZE];
int packet_num, len; int packet_num, len;
int i, found = 0;
int64_t pos; int64_t pos;
ts->stop_parse = 0; ts->stop_parse = 0;
...@@ -825,26 +907,13 @@ static int handle_packets(AVFormatContext *s, int nb_packets) ...@@ -825,26 +907,13 @@ static int handle_packets(AVFormatContext *s, int nb_packets)
if (len != ts->raw_packet_size) if (len != ts->raw_packet_size)
return AVERROR_IO; return AVERROR_IO;
/* check paquet sync byte */ /* check paquet sync byte */
if (packet[0] != 0x47) if (packet[0] != 0x47) {
{ /* find a new packet start */
//printf("bad packet: 0x%x\n", packet[0]); url_fseek(pb, -ts->raw_packet_size, SEEK_CUR);
found = 0; if (mpegts_resync(s) < 0)
for (i = 0; i < ts->raw_packet_size; i++) return AVERROR_INVALIDDATA;
{ else
if (packet[i] == 0x47) continue;
{
found = 1;
//printf("packet start at: %d\n", i);
break;
}
}
if (found)
{
url_fseek(pb, pos + i, SEEK_SET);
continue;
}
return AVERROR_INVALIDDATA;
} }
handle_packet(s, packet); handle_packet(s, packet);
} }
...@@ -853,11 +922,19 @@ static int handle_packets(AVFormatContext *s, int nb_packets) ...@@ -853,11 +922,19 @@ static int handle_packets(AVFormatContext *s, int nb_packets)
static int mpegts_probe(AVProbeData *p) static int mpegts_probe(AVProbeData *p)
{ {
#if 1
int size; int size;
size = get_packet_size(p->buf, p->buf_size); size = get_packet_size(p->buf, p->buf_size);
if (size < 0) if (size < 0)
return 0; return 0;
return AVPROBE_SCORE_MAX - 1; return AVPROBE_SCORE_MAX - 1;
#else
/* only use the extension for safer guess */
if (match_ext(p->filename, "ts"))
return AVPROBE_SCORE_MAX;
else
return 0;
#endif
} }
void set_service_cb(void *opaque, int ret) void set_service_cb(void *opaque, int ret)
...@@ -873,7 +950,7 @@ static int mpegts_read_header(AVFormatContext *s, ...@@ -873,7 +950,7 @@ static int mpegts_read_header(AVFormatContext *s,
MpegTSContext *ts = s->priv_data; MpegTSContext *ts = s->priv_data;
ByteIOContext *pb = &s->pb; ByteIOContext *pb = &s->pb;
uint8_t buf[1024]; uint8_t buf[1024];
int len; int len, sid;
int64_t pos; int64_t pos;
MpegTSService *service; MpegTSService *service;
...@@ -888,24 +965,32 @@ static int mpegts_read_header(AVFormatContext *s, ...@@ -888,24 +965,32 @@ static int mpegts_read_header(AVFormatContext *s,
ts->auto_guess = 0; ts->auto_guess = 0;
if (!ts->auto_guess) { if (!ts->auto_guess) {
int sid = -1;
ts->set_service_ret = -1; ts->set_service_ret = -1;
/* first do a scaning to get all the services */ /* first do a scaning to get all the services */
url_fseek(pb, pos, SEEK_SET); url_fseek(pb, pos, SEEK_SET);
mpegts_scan_sdt(ts); mpegts_scan_sdt(ts);
handle_packets(s, MAX_SCAN_PACKETS); handle_packets(s, MAX_SCAN_PACKETS);
if (ts->nb_services > 0) if (ts->nb_services <= 0) {
{ /* no SDT found, we try to look at the PAT */
/* tune to first service found */
service = ts->services[0]; url_fseek(pb, pos, SEEK_SET);
sid = service->sid; mpegts_scan_pat(ts);
handle_packets(s, MAX_SCAN_PACKETS);
}
if (ts->nb_services <= 0)
return -1;
/* tune to first service found */
service = ts->services[0];
sid = service->sid;
#ifdef DEBUG_SI #ifdef DEBUG_SI
printf("tuning to '%s'\n", service->name); printf("tuning to '%s'\n", service->name);
#endif #endif
}
/* now find the info for the first service if we found any, /* now find the info for the first service if we found any,
otherwise try to filter all PATs */ otherwise try to filter all PATs */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment