Newer
Older
Fabrice Bellard
committed
Fabrice Bellard
committed
static int mpegts_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
MpegTSContext *ts = s->priv_data;
ByteIOContext *pb = &s->pb;
uint8_t buf[1024];
Fabrice Bellard
committed
int len, sid;
Fabrice Bellard
committed
int64_t pos;
MpegTSService *service;
Fabrice Bellard
committed
if (ap) {
ts->mpeg2ts_raw = ap->mpeg2ts_raw;
ts->mpeg2ts_compute_pcr = ap->mpeg2ts_compute_pcr;
}
Fabrice Bellard
committed
/* read the first 1024 bytes to get packet size */
pos = url_ftell(pb);
len = get_buffer(pb, buf, sizeof(buf));
if (len != sizeof(buf))
goto fail;
ts->raw_packet_size = get_packet_size(buf, sizeof(buf));
if (ts->raw_packet_size <= 0)
goto fail;
Fabrice Bellard
committed
ts->stream = s;
Fabrice Bellard
committed
ts->auto_guess = 0;
Fabrice Bellard
committed
if (!ts->mpeg2ts_raw) {
/* normal demux */
Fabrice Bellard
committed
Fabrice Bellard
committed
if (!ts->auto_guess) {
ts->set_service_ret = -1;
Michael Niedermayer
committed
Fabrice Bellard
committed
/* first do a scaning to get all the services */
Fabrice Bellard
committed
url_fseek(pb, pos, SEEK_SET);
Fabrice Bellard
committed
mpegts_scan_sdt(ts);
Fabrice Bellard
committed
Fabrice Bellard
committed
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
handle_packets(ts, MAX_SCAN_PACKETS);
if (ts->nb_services <= 0) {
/* no SDT found, we try to look at the PAT */
/* First remove the SDT filters from each PID */
int i;
for (i=0; i < NB_PID_MAX; i++) {
if (ts->pids[i])
mpegts_close_filter(ts, ts->pids[i]);
}
url_fseek(pb, pos, SEEK_SET);
mpegts_scan_pat(ts);
handle_packets(ts, MAX_SCAN_PACKETS);
}
if (ts->nb_services <= 0)
return -1;
/* tune to first service found */
service = ts->services[0];
sid = service->sid;
Fabrice Bellard
committed
#ifdef DEBUG_SI
Fabrice Bellard
committed
printf("tuning to '%s'\n", service->name);
Fabrice Bellard
committed
#endif
Fabrice Bellard
committed
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
/* now find the info for the first service if we found any,
otherwise try to filter all PATs */
url_fseek(pb, pos, SEEK_SET);
mpegts_set_service(ts, sid, set_service_cb, ts);
handle_packets(ts, MAX_SCAN_PACKETS);
/* if could not find service, exit */
if (ts->set_service_ret != 0)
return -1;
#ifdef DEBUG_SI
printf("tuning done\n");
#endif
}
s->ctx_flags |= AVFMTCTX_NOHEADER;
} else {
AVStream *st;
int pcr_pid, pid, nb_packets, nb_pcrs, ret, pcr_l;
int64_t pcrs[2], pcr_h;
int packet_count[2];
uint8_t packet[TS_PACKET_SIZE];
/* only read packets */
Michael Niedermayer
committed
Fabrice Bellard
committed
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
s->pts_num = 1;
s->pts_den = 27000000;
st = av_new_stream(s, 0);
if (!st)
goto fail;
st->codec.codec_type = CODEC_TYPE_DATA;
st->codec.codec_id = CODEC_ID_MPEG2TS;
/* we iterate until we find two PCRs to estimate the bitrate */
pcr_pid = -1;
nb_pcrs = 0;
nb_packets = 0;
for(;;) {
ret = read_packet(&s->pb, packet, ts->raw_packet_size);
if (ret < 0)
return -1;
pid = ((packet[1] & 0x1f) << 8) | packet[2];
if ((pcr_pid == -1 || pcr_pid == pid) &&
parse_pcr(&pcr_h, &pcr_l, packet) == 0) {
pcr_pid = pid;
packet_count[nb_pcrs] = nb_packets;
pcrs[nb_pcrs] = pcr_h * 300 + pcr_l;
nb_pcrs++;
if (nb_pcrs >= 2)
break;
}
nb_packets++;
}
Fabrice Bellard
committed
Fabrice Bellard
committed
/* NOTE1: the bitrate is computed without the FEC */
/* NOTE2: it is only the bitrate of the start of the stream */
ts->pcr_incr = (pcrs[1] - pcrs[0]) / (packet_count[1] - packet_count[0]);
ts->cur_pcr = pcrs[0] - ts->pcr_incr * packet_count[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 * 1000000.0 / 27.0e6;
#if 0
printf("start=%0.3f pcr=%0.3f incr=%d\n",
st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr);
Fabrice Bellard
committed
#endif
Fabrice Bellard
committed
url_fseek(pb, pos, SEEK_SET);
Fabrice Bellard
committed
fail:
return -1;
}
Fabrice Bellard
committed
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
#define MAX_PACKET_READAHEAD ((128 * 1024) / 188)
static int mpegts_raw_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
MpegTSContext *ts = s->priv_data;
int ret, i;
int64_t pcr_h, next_pcr_h, pos;
int pcr_l, next_pcr_l;
uint8_t pcr_buf[12];
if (av_new_packet(pkt, TS_PACKET_SIZE) < 0)
return -ENOMEM;
ret = read_packet(&s->pb, pkt->data, ts->raw_packet_size);
if (ret < 0) {
av_free_packet(pkt);
return ret;
}
if (ts->mpeg2ts_compute_pcr) {
/* compute exact PCR for each packet */
if (parse_pcr(&pcr_h, &pcr_l, pkt->data) == 0) {
/* we read the next PCR (XXX: optimize it by using a bigger buffer */
pos = url_ftell(&s->pb);
for(i = 0; i < MAX_PACKET_READAHEAD; i++) {
url_fseek(&s->pb, pos + i * ts->raw_packet_size, SEEK_SET);
get_buffer(&s->pb, pcr_buf, 12);
if (parse_pcr(&next_pcr_h, &next_pcr_l, pcr_buf) == 0) {
/* XXX: not precise enough */
ts->pcr_incr = ((next_pcr_h - pcr_h) * 300 + (next_pcr_l - pcr_l)) /
(i + 1);
break;
}
}
url_fseek(&s->pb, pos, SEEK_SET);
/* no next PCR found: we use previous increment */
ts->cur_pcr = pcr_h * 300 + pcr_l;
}
pkt->pts = ts->cur_pcr;
pkt->duration = ts->pcr_incr;
ts->cur_pcr += ts->pcr_incr;
}
pkt->stream_index = 0;
return 0;
}
Fabrice Bellard
committed
static int mpegts_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
MpegTSContext *ts = s->priv_data;
Fabrice Bellard
committed
if (!ts->mpeg2ts_raw) {
ts->pkt = pkt;
return handle_packets(ts, 0);
} else {
return mpegts_raw_read_packet(s, pkt);
}
}
static int mpegts_read_close(AVFormatContext *s)
{
MpegTSContext *ts = s->priv_data;
int i;
for(i=0;i<NB_PID_MAX;i++)
return 0;
}
Fabrice Bellard
committed
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
/**************************************************************/
/* parsing functions - called from other demuxers such as RTP */
MpegTSContext *mpegts_parse_open(AVFormatContext *s)
{
MpegTSContext *ts;
ts = av_mallocz(sizeof(MpegTSContext));
if (!ts)
return NULL;
/* no stream case, currently used by RTP */
ts->raw_packet_size = TS_PACKET_SIZE;
ts->stream = s;
ts->auto_guess = 1;
return ts;
}
/* return the consumed length if a packet was output, or -1 if no
packet is output */
int mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt,
const uint8_t *buf, int len)
{
int len1;
len1 = len;
ts->pkt = pkt;
ts->stop_parse = 0;
for(;;) {
if (ts->stop_parse)
break;
if (len < TS_PACKET_SIZE)
return -1;
if (buf[0] != 0x47) {
buf--;
len--;
} else {
handle_packet(ts, buf);
buf += TS_PACKET_SIZE;
len -= TS_PACKET_SIZE;
}
}
return len1 - len;
}
void mpegts_parse_close(MpegTSContext *ts)
{
int i;
for(i=0;i<NB_PID_MAX;i++)
av_free(ts->pids[i]);
av_free(ts);
}
AVInputFormat mpegts_demux = {
"mpegts",
"MPEG2 transport stream format",
sizeof(MpegTSContext),
mpegts_probe,
mpegts_read_header,
mpegts_read_packet,
mpegts_read_close,
Fabrice Bellard
committed
.flags = AVFMT_SHOW_IDS,
};
int mpegts_init(void)
{
av_register_input_format(&mpegts_demux);
#ifdef CONFIG_ENCODERS
Fabrice Bellard
committed
av_register_output_format(&mpegts_mux);
return 0;
}