|
|
|
@ -143,6 +143,7 @@ typedef struct MpegTSWriteStream { |
|
|
|
|
int cc; |
|
|
|
|
int payload_index; |
|
|
|
|
int64_t payload_pts; |
|
|
|
|
int64_t payload_dts; |
|
|
|
|
uint8_t payload[DEFAULT_PES_PAYLOAD_SIZE]; |
|
|
|
|
} MpegTSWriteStream; |
|
|
|
|
|
|
|
|
@ -396,6 +397,7 @@ static int mpegts_write_header(AVFormatContext *s) |
|
|
|
|
ts_st->service = service; |
|
|
|
|
ts_st->pid = DEFAULT_START_PID + i; |
|
|
|
|
ts_st->payload_pts = AV_NOPTS_VALUE; |
|
|
|
|
ts_st->payload_dts = AV_NOPTS_VALUE; |
|
|
|
|
/* update PCR pid by using the first video stream */ |
|
|
|
|
if (st->codec->codec_type == CODEC_TYPE_VIDEO && |
|
|
|
|
service->pcr_pid == 0x1fff) |
|
|
|
@ -460,15 +462,29 @@ static void retransmit_si_info(AVFormatContext *s) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void write_pts(uint8_t *q, int fourbits, int64_t pts) |
|
|
|
|
{ |
|
|
|
|
int val; |
|
|
|
|
|
|
|
|
|
val = fourbits << 4 | (((pts >> 30) & 0x07) << 1) | 1; |
|
|
|
|
*q++ = val; |
|
|
|
|
val = (((pts >> 15) & 0x7fff) << 1) | 1; |
|
|
|
|
*q++ = val >> 8; |
|
|
|
|
*q++ = val; |
|
|
|
|
val = (((pts) & 0x7fff) << 1) | 1; |
|
|
|
|
*q++ = val >> 8; |
|
|
|
|
*q++ = val; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* NOTE: pes_data contains all the PES packet */ |
|
|
|
|
static void mpegts_write_pes(AVFormatContext *s, AVStream *st, |
|
|
|
|
const uint8_t *payload, int payload_size, |
|
|
|
|
int64_t pts) |
|
|
|
|
int64_t pts, int64_t dts) |
|
|
|
|
{ |
|
|
|
|
MpegTSWriteStream *ts_st = st->priv_data; |
|
|
|
|
uint8_t buf[TS_PACKET_SIZE]; |
|
|
|
|
uint8_t *q; |
|
|
|
|
int val, is_start, len, header_len, write_pcr, private_code; |
|
|
|
|
int val, is_start, len, header_len, write_pcr, private_code, flags; |
|
|
|
|
int afc_len, stuffing_len; |
|
|
|
|
int64_t pcr = -1; /* avoid warning */ |
|
|
|
|
|
|
|
|
@ -527,13 +543,19 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, |
|
|
|
|
private_code = 0x20; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (pts != AV_NOPTS_VALUE) |
|
|
|
|
header_len = 8; |
|
|
|
|
else |
|
|
|
|
header_len = 3; |
|
|
|
|
header_len = 0; |
|
|
|
|
flags = 0; |
|
|
|
|
if (pts != AV_NOPTS_VALUE) { |
|
|
|
|
header_len += 5; |
|
|
|
|
flags |= 0x80; |
|
|
|
|
} |
|
|
|
|
if (dts != AV_NOPTS_VALUE) { |
|
|
|
|
header_len += 5; |
|
|
|
|
flags |= 0x40; |
|
|
|
|
} |
|
|
|
|
len = payload_size + header_len + 3; |
|
|
|
|
if (private_code != 0) |
|
|
|
|
header_len++; |
|
|
|
|
len = payload_size + header_len; |
|
|
|
|
len++; |
|
|
|
|
*q++ = len >> 8; |
|
|
|
|
*q++ = len; |
|
|
|
|
val = 0x80; |
|
|
|
@ -541,21 +563,15 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, |
|
|
|
|
if (st->codec->codec_type == CODEC_TYPE_SUBTITLE) |
|
|
|
|
val |= 0x04; |
|
|
|
|
*q++ = val; |
|
|
|
|
*q++ = flags; |
|
|
|
|
*q++ = header_len; |
|
|
|
|
if (pts != AV_NOPTS_VALUE) { |
|
|
|
|
*q++ = 0x80; /* PTS only */ |
|
|
|
|
*q++ = 0x05; /* header len */ |
|
|
|
|
val = (0x02 << 4) | |
|
|
|
|
(((pts >> 30) & 0x07) << 1) | 1; |
|
|
|
|
*q++ = val; |
|
|
|
|
val = (((pts >> 15) & 0x7fff) << 1) | 1; |
|
|
|
|
*q++ = val >> 8; |
|
|
|
|
*q++ = val; |
|
|
|
|
val = (((pts) & 0x7fff) << 1) | 1; |
|
|
|
|
*q++ = val >> 8; |
|
|
|
|
*q++ = val; |
|
|
|
|
} else { |
|
|
|
|
*q++ = 0x00; |
|
|
|
|
*q++ = 0x00; |
|
|
|
|
write_pts(q, flags >> 6, pts); |
|
|
|
|
q += 5; |
|
|
|
|
} |
|
|
|
|
if (dts != AV_NOPTS_VALUE) { |
|
|
|
|
write_pts(q, 1, dts); |
|
|
|
|
q += 5; |
|
|
|
|
} |
|
|
|
|
if (private_code != 0) |
|
|
|
|
*q++ = private_code; |
|
|
|
@ -607,7 +623,7 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt) |
|
|
|
|
|
|
|
|
|
if (st->codec->codec_type == CODEC_TYPE_SUBTITLE) { |
|
|
|
|
/* for subtitle, a single PES packet must be generated */ |
|
|
|
|
mpegts_write_pes(s, st, buf, size, pkt->pts); |
|
|
|
|
mpegts_write_pes(s, st, buf, size, pkt->pts, AV_NOPTS_VALUE); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -622,10 +638,13 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt) |
|
|
|
|
ts_st->payload_index += len; |
|
|
|
|
if (ts_st->payload_pts == AV_NOPTS_VALUE) |
|
|
|
|
ts_st->payload_pts = pkt->pts; |
|
|
|
|
if (ts_st->payload_dts == AV_NOPTS_VALUE) |
|
|
|
|
ts_st->payload_dts = pkt->dts; |
|
|
|
|
if (ts_st->payload_index >= max_payload_size) { |
|
|
|
|
mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index, |
|
|
|
|
ts_st->payload_pts); |
|
|
|
|
ts_st->payload_pts, ts_st->payload_dts); |
|
|
|
|
ts_st->payload_pts = AV_NOPTS_VALUE; |
|
|
|
|
ts_st->payload_dts = AV_NOPTS_VALUE; |
|
|
|
|
ts_st->payload_index = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -646,7 +665,7 @@ static int mpegts_write_end(AVFormatContext *s) |
|
|
|
|
ts_st = st->priv_data; |
|
|
|
|
if (ts_st->payload_index > 0) { |
|
|
|
|
mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index, |
|
|
|
|
ts_st->payload_pts); |
|
|
|
|
ts_st->payload_pts, ts_st->payload_dts); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
put_flush_packet(&s->pb); |
|
|
|
|