/*
- * MPEG2 transport stream (aka DVB) demux
+ * MPEG2 transport stream (aka DVB) demuxer
* Copyright (c) 2002-2003 Fabrice Bellard.
*
- * This library is free software; you can redistribute it and/or
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
- * This library is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
typedef struct MpegTSService {
int running:1;
- int sid;
- char *provider_name;
- char *name;
+ int sid; /**< MPEG Program Number of stream */
+ char *provider_name; /**< DVB Network name, "" if not DVB stream */
+ char *name; /**< DVB Service name, "MPEG Program [sid]" if not DVB stream*/
} MpegTSService;
struct MpegTSContext {
/* user data */
AVFormatContext *stream;
- int raw_packet_size; /* raw packet size, including FEC if present */
- int auto_guess; /* if true, all pids are analized to find streams */
+ /** raw packet size, including FEC if present */
+ int raw_packet_size;
+ /** if true, all pids are analyzed to find streams */
+ int auto_guess;
int set_service_ret;
- int mpeg2ts_raw; /* force raw MPEG2 transport stream output, if possible */
- int mpeg2ts_compute_pcr; /* compute exact PCR for each transport stream packet */
+ /** force raw MPEG2 transport stream output, if possible */
+ int mpeg2ts_raw;
+ /** compute exact PCR for each transport stream packet */
+ int mpeg2ts_compute_pcr;
- /* used to estimate the exact PCR */
- int64_t cur_pcr;
- int pcr_incr;
- int pcr_pid;
+ int64_t cur_pcr; /**< used to estimate the exact PCR */
+ int pcr_incr; /**< used to estimate the exact PCR */
+ int pcr_pid; /**< used to estimate the exact PCR */
/* data needed to handle file based ts */
- int stop_parse; /* stop parsing loop */
- AVPacket *pkt; /* packet containing av data */
+ /** stop parsing loop */
+ int stop_parse;
+ /** packet containing Audio/Video data */
+ AVPacket *pkt;
/******************************************/
/* private mpegts data */
/* scan context */
MpegTSFilter *sdt_filter;
+ /** number of PMTs in the last PAT seen */
int nb_services;
+ /** list of PMTs in the last PAT seen */
MpegTSService **services;
/* set service context (XXX: allocated it ?) */
SetServiceCallback *set_service_cb;
void *set_service_opaque;
+ /** filter for the PAT */
MpegTSFilter *pat_filter;
+ /** filter for the PMT for the MPEG program number specified by req_sid */
MpegTSFilter *pmt_filter;
+ /** MPEG program number of stream we want to decode */
int req_sid;
+ /** filters for various streams specified by PMT + for the PAT and PMT */
MpegTSFilter *pids[NB_PID_MAX];
};
+/**
+ * Assembles PES packets out of TS packets, and then calls the "section_cb"
+ * function when they are complete.
+ */
static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1,
const uint8_t *buf, int buf_size, int is_start)
{
MpegTSSectionFilter *sec;
#ifdef DEBUG_SI
- printf("Filter: pid=0x%x\n", pid);
+ av_log(NULL, AV_LOG_DEBUG, "Filter: pid=0x%x\n", pid);
#endif
if (pid >= NB_PID_MAX || ts->pids[pid])
return NULL;
MpegTSService *service;
#ifdef DEBUG_SI
- printf("new_service: sid=0x%04x provider='%s' name='%s'\n",
+ av_log(NULL, AV_LOG_DEBUG, "new_service: "
+ "sid=0x%04x provider='%s' name='%s'\n",
sid, provider_name, name);
#endif
char language[4];
#ifdef DEBUG_SI
- printf("PMT:\n");
+ av_log(NULL, AV_LOG_DEBUG, "PMT: len %i\n", section_len);
av_hex_dump(stdout, (uint8_t *)section, section_len);
#endif
p_end = section + section_len - 4;
if (parse_section_header(h, &p, p_end) < 0)
return;
#ifdef DEBUG_SI
- printf("sid=0x%x sec_num=%d/%d\n", h->id, h->sec_num, h->last_sec_num);
+ av_log(NULL, AV_LOG_DEBUG, "sid=0x%x sec_num=%d/%d\n",
+ h->id, h->sec_num, h->last_sec_num);
#endif
if (h->tid != PMT_TID || (ts->req_sid >= 0 && h->id != ts->req_sid) )
return;
return;
ts->pcr_pid = pcr_pid;
#ifdef DEBUG_SI
- printf("pcr_pid=0x%x\n", pcr_pid);
+ av_log(NULL, AV_LOG_DEBUG, "pcr_pid=0x%x\n", pcr_pid);
#endif
program_info_length = get16(&p, p_end) & 0xfff;
if (program_info_length < 0)
if (desc_end > desc_list_end)
break;
#ifdef DEBUG_SI
- printf("tag: 0x%02x len=%d\n", desc_tag, desc_len);
+ av_log(NULL, AV_LOG_DEBUG, "tag: 0x%02x len=%d\n",
+ desc_tag, desc_len);
#endif
switch(desc_tag) {
case DVB_SUBT_DESCID:
p = desc_list_end;
#ifdef DEBUG_SI
- printf("stream_type=%d pid=0x%x\n", stream_type, pid);
+ av_log(NULL, AV_LOG_DEBUG, "stream_type=%d pid=0x%x\n",
+ stream_type, pid);
#endif
/* now create ffmpeg stream */
int sid, pmt_pid;
#ifdef DEBUG_SI
- printf("PAT:\n");
+ av_log(NULL, AV_LOG_DEBUG, "PAT:\n");
av_hex_dump(stdout, (uint8_t *)section, section_len);
#endif
p_end = section + section_len - 4;
if (pmt_pid < 0)
break;
#ifdef DEBUG_SI
- printf("sid=0x%x pid=0x%x\n", sid, pmt_pid);
+ av_log(NULL, AV_LOG_DEBUG, "sid=0x%x pid=0x%x\n", sid, pmt_pid);
#endif
if (sid == 0x0000) {
/* NIT info */
char buf[256];
#ifdef DEBUG_SI
- printf("PAT:\n");
+ av_log(NULL, AV_LOG_DEBUG, "PAT:\n");
av_hex_dump(stdout, (uint8_t *)section, section_len);
#endif
p_end = section + section_len - 4;
if (pmt_pid < 0)
break;
#ifdef DEBUG_SI
- printf("sid=0x%x pid=0x%x\n", sid, pmt_pid);
+ av_log(NULL, AV_LOG_DEBUG, "sid=0x%x pid=0x%x\n", sid, pmt_pid);
#endif
if (sid == 0x0000) {
/* NIT info */
char *name, *provider_name;
#ifdef DEBUG_SI
- printf("SDT:\n");
+ av_log(NULL, AV_LOG_DEBUG, "SDT:\n");
av_hex_dump(stdout, (uint8_t *)section, section_len);
#endif
if (desc_end > desc_list_end)
break;
#ifdef DEBUG_SI
- printf("tag: 0x%02x len=%d\n", desc_tag, desc_len);
+ av_log(NULL, AV_LOG_DEBUG, "tag: 0x%02x len=%d\n",
+ desc_tag, desc_len);
#endif
switch(desc_tag) {
case 0x48:
#endif
}
-void set_service_cb(void *opaque, int ret)
+static void set_service_cb(void *opaque, int ret)
{
MpegTSContext *ts = opaque;
ts->set_service_ret = ret;
url_fseek(pb, pos, SEEK_SET);
mpegts_scan_sdt(ts);
- handle_packets(ts, MAX_SCAN_PACKETS);
+ handle_packets(ts, s->probesize);
if (ts->nb_services <= 0) {
/* no SDT found, we try to look at the PAT */
url_fseek(pb, pos, SEEK_SET);
mpegts_scan_pat(ts);
- handle_packets(ts, MAX_SCAN_PACKETS);
+ handle_packets(ts, s->probesize);
}
if (ts->nb_services <= 0) {
service = ts->services[i];
sid = service->sid;
#ifdef DEBUG_SI
- printf("tuning to '%s'\n", service->name);
+ av_log(NULL, AV_LOG_DEBUG, "tuning to '%s'\n", service->name);
#endif
/* now find the info for the first service if we found any,
url_fseek(pb, pos, SEEK_SET);
mpegts_set_service(ts, sid, set_service_cb, ts);
- handle_packets(ts, MAX_SCAN_PACKETS);
+ handle_packets(ts, s->probesize);
}
/* if could not find service, exit */
}
#ifdef DEBUG_SI
- printf("tuning done\n");
+ av_log(NULL, AV_LOG_DEBUG, "tuning done\n");
#endif
}
s->ctx_flags |= AVFMTCTX_NOHEADER;
st->codec->bit_rate = s->bit_rate;
st->start_time = ts->cur_pcr;
#if 0
- printf("start=%0.3f pcr=%0.3f incr=%d\n",
+ av_log(NULL, AV_LOG_DEBUG, "start=%0.3f pcr=%0.3f incr=%d\n",
st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr);
#endif
}