/* write DVB SI sections */
-static uint32_t crc_table[256] = {
+static const uint32_t crc_table[256] = {
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
/* a PES packet header is generated every DEFAULT_PES_HEADER_FREQ packets */
#define DEFAULT_PES_HEADER_FREQ 16
+#define DEFAULT_PES_PAYLOAD_SIZE ((DEFAULT_PES_HEADER_FREQ - 1) * 184 + 170)
/* we retransmit the SI info at this rate */
#define SDT_RETRANS_TIME 500
typedef struct MpegTSWriteStream {
int pid; /* stream associated pid */
int cc;
- int packet_index;
- int pes_packet_count;
- uint8_t packet[TS_PACKET_SIZE];
+ int payload_index;
+ int64_t payload_pts;
+ uint8_t payload[DEFAULT_PES_PAYLOAD_SIZE];
} MpegTSWriteStream;
typedef struct MpegTSService {
for(i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
MpegTSWriteStream *ts_st = st->priv_data;
- switch(st->codec.codec_type) {
- case CODEC_TYPE_VIDEO:
- stream_type = STREAM_TYPE_VIDEO_MPEG2; //XXX/FIXME is this (and the define) correct?
+ switch(st->codec.codec_id) {
+ case CODEC_ID_MPEG1VIDEO:
+ case CODEC_ID_MPEG2VIDEO:
+ stream_type = STREAM_TYPE_VIDEO_MPEG2;
break;
- case CODEC_TYPE_AUDIO:
+ case CODEC_ID_MPEG4:
+ stream_type = STREAM_TYPE_VIDEO_MPEG4;
+ break;
+ case CODEC_ID_H264:
+ stream_type = STREAM_TYPE_VIDEO_H264;
+ break;
+ case CODEC_ID_MP2:
+ case CODEC_ID_MP3:
stream_type = STREAM_TYPE_AUDIO_MPEG1;
break;
+ case CODEC_ID_AAC:
+ stream_type = STREAM_TYPE_AUDIO_AAC;
+ break;
+ case CODEC_ID_AC3:
+ stream_type = STREAM_TYPE_AUDIO_AC3;
+ break;
default:
stream_type = STREAM_TYPE_PRIVATE_DATA;
break;
goto fail;
st->priv_data = ts_st;
ts_st->pid = DEFAULT_START_PID + i;
+ ts_st->payload_pts = AV_NOPTS_VALUE;
/* update PCR pid if needed */
if (st->codec.codec_type == CODEC_TYPE_VIDEO &&
service->pcr_pid == 0x1fff)
}
}
-static int mpegts_write_packet(AVFormatContext *s, int stream_index,
- uint8_t *buf, int size, int pts1)
+/* 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)
{
- AVStream *st = s->streams[stream_index];
MpegTSWriteStream *ts_st = st->priv_data;
+ uint8_t buf[TS_PACKET_SIZE];
uint8_t *q;
- int val, write_pts, is_start, len;
- int64_t pts;
+ int val, is_start, len, ts_len, header_len;
- while (size > 0) {
- if (ts_st->packet_index == 0) {
- retransmit_si_info(s);
+ is_start = 1;
+ while (payload_size > 0) {
+ retransmit_si_info(s);
- /* new PES header ? */
- is_start = 0;
- if (++ts_st->pes_packet_count == DEFAULT_PES_HEADER_FREQ) {
- ts_st->pes_packet_count = 0;
- is_start = 1;
- }
- /* prepare packet header */
- q = ts_st->packet;
- *q++ = 0x47;
- val = (ts_st->pid >> 8);
- if (is_start)
- val |= 0x40;
- *q++ = val;
- *q++ = ts_st->pid;
- *q++ = 0x10 | ts_st->cc;
- ts_st->cc = (ts_st->cc + 1) & 0xf;
- if (is_start) {
- /* write PES header */
+ /* prepare packet header */
+ q = buf;
+ *q++ = 0x47;
+ val = (ts_st->pid >> 8);
+ if (is_start)
+ val |= 0x40;
+ *q++ = val;
+ *q++ = ts_st->pid;
+ *q++ = 0x10 | ts_st->cc;
+ ts_st->cc = (ts_st->cc + 1) & 0xf;
+ if (is_start) {
+ /* write PES header */
+ *q++ = 0x00;
+ *q++ = 0x00;
+ *q++ = 0x01;
+ if (st->codec.codec_type == CODEC_TYPE_VIDEO)
+ *q++ = 0xe0;
+ else
+ *q++ = 0xc0;
+ if (pts != AV_NOPTS_VALUE)
+ header_len = 8;
+ else
+ header_len = 3;
+ len = payload_size + header_len;
+ *q++ = len >> 8;
+ *q++ = len;
+ *q++ = 0x80;
+ 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;
- *q++ = 0x01;
- if (st->codec.codec_type == CODEC_TYPE_VIDEO)
- *q++ = 0xe0;
- else
- *q++ = 0xc0;
- *q++ = 0; /* unbounded size */
- *q++ = 0;
- *q++ = 0x80;
- write_pts = 0; /* XXX: enable it */
- if (write_pts) {
- *q++ = 0x80; /* PTS only */
- *q++ = 0x05; /* header len */
- pts = pts1;
- 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;
- }
}
- ts_st->packet_index = q - ts_st->packet;
+ is_start = 0;
}
- len = TS_PACKET_SIZE - ts_st->packet_index;
- if (len == 0) {
- put_buffer(&s->pb, ts_st->packet, TS_PACKET_SIZE);
- ts_st->packet_index = 0;
- } else {
- if (len > size)
- len = size;
- memcpy(ts_st->packet + ts_st->packet_index, buf, len);
- size -= len;
- buf += len;
- ts_st->packet_index += len;
+ /* write header */
+ ts_len = q - buf;
+ put_buffer(&s->pb, buf, ts_len);
+ /* write data */
+ len = TS_PACKET_SIZE - ts_len;
+ if (len > payload_size)
+ len = payload_size;
+ put_buffer(&s->pb, payload, len);
+ payload += len;
+ payload_size -= len;
+ ts_len += len;
+ /* stuffing */
+ len = TS_PACKET_SIZE - ts_len;
+ if (len > 0) {
+ memset(buf, 0xff, len);
+ put_buffer(&s->pb, buf, len);
}
}
put_flush_packet(&s->pb);
+}
+
+static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ AVStream *st = s->streams[pkt->stream_index];
+ int size= pkt->size;
+ uint8_t *buf= pkt->data;
+ MpegTSWriteStream *ts_st = st->priv_data;
+ int len;
+
+ while (size > 0) {
+ len = DEFAULT_PES_PAYLOAD_SIZE - ts_st->payload_index;
+ if (len > size)
+ len = size;
+ memcpy(ts_st->payload + ts_st->payload_index, buf, len);
+ buf += len;
+ size -= len;
+ ts_st->payload_index += len;
+ if (ts_st->payload_pts == AV_NOPTS_VALUE)
+ ts_st->payload_pts = pkt->pts;
+ if (ts_st->payload_index >= DEFAULT_PES_PAYLOAD_SIZE) {
+ mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index,
+ ts_st->payload_pts);
+ ts_st->payload_pts = AV_NOPTS_VALUE;
+ ts_st->payload_index = 0;
+ }
+ }
return 0;
}
for(i = 0; i < s->nb_streams; i++) {
st = s->streams[i];
ts_st = st->priv_data;
- if (ts_st->packet_index != 0) {
- /* put a known value at the end */
- memset(ts_st->packet + ts_st->packet_index, 0xff,
- TS_PACKET_SIZE - ts_st->packet_index);
- put_buffer(&s->pb, ts_st->packet, TS_PACKET_SIZE);
+ if (ts_st->payload_index > 0) {
+ mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index,
+ ts_st->payload_pts);
}
}
put_flush_packet(&s->pb);
}
av_free(ts->services);
- for(i = 0; i < s->nb_streams; i++) {
- st = s->streams[i];
- av_free(st->priv_data);
- }
return 0;
}
"ts",
sizeof(MpegTSWrite),
CODEC_ID_MP2,
- CODEC_ID_MPEG1VIDEO,
+ CODEC_ID_MPEG2VIDEO,
mpegts_write_header,
mpegts_write_packet,
mpegts_write_end,