* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-//#define DEBUG
-//#define DEBUG_SEEK
//#define USE_SYNCPOINT_SEARCH
#include "libavutil/crc.h"
#include "libavutil/intreadwrite.h"
+#include "libavutil/log.h"
+#include "libavutil/dict.h"
+#include "libavutil/opt.h"
#include "libavcodec/bytestream.h"
#include "avformat.h"
#include "mpegts.h"
};
struct MpegTSContext {
+ const AVClass *class;
/* user data */
AVFormatContext *stream;
/** raw packet size, including FEC if present */
MpegTSFilter *pids[NB_PID_MAX];
};
+static const AVOption options[] = {
+ {"compute_pcr", "Compute exact PCR for each transport stream packet.", offsetof(MpegTSContext, mpeg2ts_compute_pcr), FF_OPT_TYPE_INT,
+ {.dbl = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
+ { NULL },
+};
+
+static const AVClass mpegtsraw_class = {
+ .class_name = "mpegtsraw demuxer",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
/* TS stream handling */
enum MpegTSState {
p->pids[p->nb_pids++] = pid;
}
+static void set_pcr_pid(AVFormatContext *s, unsigned int programid, unsigned int pid)
+{
+ int i;
+ for(i=0; i<s->nb_programs; i++) {
+ if(s->programs[i]->id == programid) {
+ s->programs[i]->pcr_pid = pid;
+ break;
+ }
+ }
+}
+
/**
* \brief discard_pid() decides if the pid is to be discarded according
* to caller's programs selection
static const StreamType REGD_types[] = {
{ MKTAG('d','r','a','c'), AVMEDIA_TYPE_VIDEO, CODEC_ID_DIRAC },
{ MKTAG('A','C','-','3'), AVMEDIA_TYPE_AUDIO, CODEC_ID_AC3 },
+ { MKTAG('B','S','S','D'), AVMEDIA_TYPE_AUDIO, CODEC_ID_S302M },
{ 0 },
};
if (stream_type == types->stream_type) {
st->codec->codec_type = types->codec_type;
st->codec->codec_id = types->codec_id;
+ st->request_probe = 0;
return;
}
}
if (pes->data_index == PES_START_SIZE) {
/* we got all the PES or section header. We can now
decide */
-#if 0
- av_hex_dump_log(pes->stream, AV_LOG_DEBUG, pes->header, pes->data_index);
-#endif
if (pes->header[0] == 0x00 && pes->header[1] == 0x00 &&
pes->header[2] == 0x01) {
/* it must be an mpeg2 PES stream */
code == 0x1be) /* padding_stream */
goto skip;
-#if FF_API_MAX_STREAMS
- if (!pes->st && pes->stream->nb_streams == MAX_STREAMS)
- goto skip;
-#endif
-
/* stream not present in PMT */
if (!pes->st) {
pes->st = av_new_stream(ts->stream, pes->pid);
code != 0x1ff && code != 0x1f2 && /* program_stream_directory, DSMCC_stream */
code != 0x1f8) { /* ITU-T Rec. H.222.1 type E stream */
pes->state = MPEGTS_PESHEADER;
- if (pes->st->codec->codec_id == CODEC_ID_NONE) {
+ if (pes->st->codec->codec_id == CODEC_ID_NONE && !pes->st->request_probe) {
av_dlog(pes->stream, "pid=%x stream_type=%x probing\n",
pes->pid, pes->stream_type);
- pes->st->codec->codec_id = CODEC_ID_PROBE;
+ pes->st->request_probe= 1;
}
} else {
pes->state = MPEGTS_PAYLOAD;
language[1] = get8(pp, desc_end);
language[2] = get8(pp, desc_end);
language[3] = 0;
- av_metadata_set2(&st->metadata, "language", language, 0);
+ av_dict_set(&st->metadata, "language", language, 0);
break;
case 0x59: /* subtitling descriptor */
language[0] = get8(pp, desc_end);
}
}
*pp += 4;
- av_metadata_set2(&st->metadata, "language", language, 0);
+ av_dict_set(&st->metadata, "language", language, 0);
break;
case 0x0a: /* ISO 639 language descriptor */
for (i = 0; i + 4 <= desc_len; i += 4) {
}
if (i) {
language[i - 1] = 0;
- av_metadata_set2(&st->metadata, "language", language, 0);
+ av_dict_set(&st->metadata, "language", language, 0);
}
break;
case 0x05: /* registration descriptor */
stream_type == STREAM_TYPE_PRIVATE_DATA)
mpegts_find_stream_type(st, st->codec->codec_tag, REGD_types);
break;
+ case 0x52: /* stream identifier descriptor */
+ st->stream_identifier = 1 + get8(pp, desc_end);
+ break;
default:
break;
}
int mp4_dec_config_descr_len = 0;
int mp4_es_id = 0;
-#ifdef DEBUG
av_dlog(ts->stream, "PMT: len %i\n", section_len);
- av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len);
-#endif
+ hex_dump_debug(ts->stream, (uint8_t *)section, section_len);
p_end = section + section_len - 4;
p = section;
if (pcr_pid < 0)
return;
add_pid_to_pmt(ts, h->id, pcr_pid);
+ set_pcr_pid(ts->stream, h->id, pcr_pid);
av_dlog(ts->stream, "pcr_pid=0x%x\n", pcr_pid);
SectionHeader h1, *h = &h1;
const uint8_t *p, *p_end;
int sid, pmt_pid;
+ AVProgram *program;
-#ifdef DEBUG
av_dlog(ts->stream, "PAT:\n");
- av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len);
-#endif
+ hex_dump_debug(ts->stream, (uint8_t *)section, section_len);
+
p_end = section + section_len - 4;
p = section;
if (parse_section_header(h, &p, p_end) < 0)
if (h->tid != PAT_TID)
return;
+ ts->stream->ts_id = h->id;
+
clear_programs(ts);
for(;;) {
sid = get16(&p, p_end);
if (sid == 0x0000) {
/* NIT info */
} else {
- av_new_program(ts->stream, sid);
+ program = av_new_program(ts->stream, sid);
+ program->program_num = sid;
+ program->pmt_pid = pmt_pid;
if (ts->pids[pmt_pid])
mpegts_close_filter(ts, ts->pids[pmt_pid]);
mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1);
int onid, val, sid, desc_list_len, desc_tag, desc_len, service_type;
char *name, *provider_name;
-#ifdef DEBUG
av_dlog(ts->stream, "SDT:\n");
- av_hex_dump_log(ts->stream, AV_LOG_DEBUG, (uint8_t *)section, section_len);
-#endif
+ hex_dump_debug(ts->stream, (uint8_t *)section, section_len);
p_end = section + section_len - 4;
p = section;
if (name) {
AVProgram *program = av_new_program(ts->stream, sid);
if(program) {
- av_metadata_set2(&program->metadata, "service_name", name, 0);
- av_metadata_set2(&program->metadata, "service_provider", provider_name, 0);
+ av_dict_set(&program->metadata, "service_name", name, 0);
+ av_dict_set(&program->metadata, "service_provider", provider_name, 0);
}
}
av_free(name);
{
MpegTSContext *ts = s->priv_data;
AVIOContext *pb = s->pb;
- uint8_t buf[5*1024];
+ uint8_t buf[8*1024];
int len;
int64_t pos;
+#if FF_API_FORMAT_PARAMETERS
if (ap) {
- ts->mpeg2ts_compute_pcr = ap->mpeg2ts_compute_pcr;
+ if (ap->mpeg2ts_compute_pcr)
+ ts->mpeg2ts_compute_pcr = ap->mpeg2ts_compute_pcr;
if(ap->mpeg2ts_raw){
av_log(s, AV_LOG_ERROR, "use mpegtsraw_demuxer!\n");
return -1;
}
}
+#endif
/* read the first 1024 bytes to get packet size */
pos = avio_tell(pb);
if (len != sizeof(buf))
goto fail;
ts->raw_packet_size = get_packet_size(buf, sizeof(buf));
- if (ts->raw_packet_size <= 0)
- goto fail;
+ if (ts->raw_packet_size <= 0) {
+ av_log(s, AV_LOG_WARNING, "Could not detect TS packet size, defaulting to non-FEC/DVHS\n");
+ ts->raw_packet_size = TS_PACKET_SIZE;
+ }
ts->stream = s;
ts->auto_guess = 0;
s->bit_rate = (TS_PACKET_SIZE * 8) * 27e6 / ts->pcr_incr;
st->codec->bit_rate = s->bit_rate;
st->start_time = ts->cur_pcr;
-#if 0
- av_log(ts->stream, AV_LOG_DEBUG, "start=%0.3f pcr=%0.3f incr=%d\n",
- st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr);
-#endif
+ av_dlog(ts->stream, "start=%0.3f pcr=%0.3f incr=%d\n",
+ st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr);
}
avio_seek(pb, pos, SEEK_SET);
#ifdef USE_SYNCPOINT_SEARCH
.read_seek2 = read_seek2,
#endif
+ .priv_class = &mpegtsraw_class,
};