comparison mpegtsenc.c @ 250:2d4dcb1d3e21 libavformat

generate correct PTS in transport stream - use mpeg2 encoder by default
author bellard
date Tue, 16 Sep 2003 12:56:42 +0000
parents 3d92f793fd67
children 622892a75ddb
comparison
equal deleted inserted replaced
249:86232f9cd4f0 250:2d4dcb1d3e21
183 #define DEFAULT_TSID 0x0001 183 #define DEFAULT_TSID 0x0001
184 #define DEFAULT_SID 0x0001 184 #define DEFAULT_SID 0x0001
185 185
186 /* a PES packet header is generated every DEFAULT_PES_HEADER_FREQ packets */ 186 /* a PES packet header is generated every DEFAULT_PES_HEADER_FREQ packets */
187 #define DEFAULT_PES_HEADER_FREQ 16 187 #define DEFAULT_PES_HEADER_FREQ 16
188 #define DEFAULT_PES_PAYLOAD_SIZE ((DEFAULT_PES_HEADER_FREQ - 1) * 184 + 170)
188 189
189 /* we retransmit the SI info at this rate */ 190 /* we retransmit the SI info at this rate */
190 #define SDT_RETRANS_TIME 500 191 #define SDT_RETRANS_TIME 500
191 #define PAT_RETRANS_TIME 100 192 #define PAT_RETRANS_TIME 100
192 193
193 typedef struct MpegTSWriteStream { 194 typedef struct MpegTSWriteStream {
194 int pid; /* stream associated pid */ 195 int pid; /* stream associated pid */
195 int cc; 196 int cc;
196 int packet_index; 197 int payload_index;
197 int pes_packet_count; 198 int64_t payload_pts;
198 uint8_t packet[TS_PACKET_SIZE]; 199 uint8_t payload[DEFAULT_PES_PAYLOAD_SIZE];
199 } MpegTSWriteStream; 200 } MpegTSWriteStream;
200 201
201 typedef struct MpegTSService { 202 typedef struct MpegTSService {
202 MpegTSSection pmt; /* MPEG2 pmt table context */ 203 MpegTSSection pmt; /* MPEG2 pmt table context */
203 int pcr_pid; 204 int pcr_pid;
396 ts_st = av_mallocz(sizeof(MpegTSWriteStream)); 397 ts_st = av_mallocz(sizeof(MpegTSWriteStream));
397 if (!ts_st) 398 if (!ts_st)
398 goto fail; 399 goto fail;
399 st->priv_data = ts_st; 400 st->priv_data = ts_st;
400 ts_st->pid = DEFAULT_START_PID + i; 401 ts_st->pid = DEFAULT_START_PID + i;
402 ts_st->payload_pts = AV_NOPTS_VALUE;
401 /* update PCR pid if needed */ 403 /* update PCR pid if needed */
402 if (st->codec.codec_type == CODEC_TYPE_VIDEO && 404 if (st->codec.codec_type == CODEC_TYPE_VIDEO &&
403 service->pcr_pid == 0x1fff) 405 service->pcr_pid == 0x1fff)
404 service->pcr_pid = ts_st->pid; 406 service->pcr_pid = ts_st->pid;
405 total_bit_rate += st->codec.bit_rate; 407 total_bit_rate += st->codec.bit_rate;
451 mpegts_write_pmt(s, ts->services[i]); 453 mpegts_write_pmt(s, ts->services[i]);
452 } 454 }
453 } 455 }
454 } 456 }
455 457
458 /* NOTE: pes_data contains all the PES packet */
459 static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
460 const uint8_t *payload, int payload_size,
461 int64_t pts)
462 {
463 MpegTSWriteStream *ts_st = st->priv_data;
464 uint8_t buf[TS_PACKET_SIZE];
465 uint8_t *q;
466 int val, is_start, len, ts_len, header_len;
467
468 is_start = 1;
469 while (payload_size > 0) {
470 retransmit_si_info(s);
471
472 /* prepare packet header */
473 q = buf;
474 *q++ = 0x47;
475 val = (ts_st->pid >> 8);
476 if (is_start)
477 val |= 0x40;
478 *q++ = val;
479 *q++ = ts_st->pid;
480 *q++ = 0x10 | ts_st->cc;
481 ts_st->cc = (ts_st->cc + 1) & 0xf;
482 if (is_start) {
483 /* write PES header */
484 *q++ = 0x00;
485 *q++ = 0x00;
486 *q++ = 0x01;
487 if (st->codec.codec_type == CODEC_TYPE_VIDEO)
488 *q++ = 0xe0;
489 else
490 *q++ = 0xc0;
491 if (pts != AV_NOPTS_VALUE)
492 header_len = 8;
493 else
494 header_len = 3;
495 len = payload_size + header_len;
496 *q++ = len >> 8;
497 *q++ = len;
498 *q++ = 0x80;
499 if (pts != AV_NOPTS_VALUE) {
500 *q++ = 0x80; /* PTS only */
501 *q++ = 0x05; /* header len */
502 val = (0x02 << 4) |
503 (((pts >> 30) & 0x07) << 1) | 1;
504 *q++ = val;
505 val = (((pts >> 15) & 0x7fff) << 1) | 1;
506 *q++ = val >> 8;
507 *q++ = val;
508 val = (((pts) & 0x7fff) << 1) | 1;
509 *q++ = val >> 8;
510 *q++ = val;
511 } else {
512 *q++ = 0x00;
513 *q++ = 0x00;
514 }
515 is_start = 0;
516 }
517 /* write header */
518 ts_len = q - buf;
519 put_buffer(&s->pb, buf, ts_len);
520 /* write data */
521 len = TS_PACKET_SIZE - ts_len;
522 if (len > payload_size)
523 len = payload_size;
524 put_buffer(&s->pb, payload, len);
525 payload += len;
526 payload_size -= len;
527 ts_len += len;
528 /* stuffing */
529 len = TS_PACKET_SIZE - ts_len;
530 if (len > 0) {
531 memset(buf, 0xff, len);
532 put_buffer(&s->pb, buf, len);
533 }
534 }
535 put_flush_packet(&s->pb);
536 }
537
456 static int mpegts_write_packet(AVFormatContext *s, int stream_index, 538 static int mpegts_write_packet(AVFormatContext *s, int stream_index,
457 const uint8_t *buf, int size, int64_t pts1) 539 const uint8_t *buf, int size, int64_t pts1)
458 { 540 {
459 AVStream *st = s->streams[stream_index]; 541 AVStream *st = s->streams[stream_index];
460 MpegTSWriteStream *ts_st = st->priv_data; 542 MpegTSWriteStream *ts_st = st->priv_data;
461 uint8_t *q; 543 int len;
462 int val, write_pts, is_start, len;
463 int64_t pts;
464 544
465 while (size > 0) { 545 while (size > 0) {
466 if (ts_st->packet_index == 0) { 546 len = DEFAULT_PES_PAYLOAD_SIZE - ts_st->payload_index;
467 retransmit_si_info(s); 547 if (len > size)
468 548 len = size;
469 /* new PES header ? */ 549 memcpy(ts_st->payload + ts_st->payload_index, buf, len);
470 is_start = 0; 550 buf += len;
471 if (++ts_st->pes_packet_count == DEFAULT_PES_HEADER_FREQ) { 551 size -= len;
472 ts_st->pes_packet_count = 0; 552 ts_st->payload_index += len;
473 is_start = 1; 553 if (ts_st->payload_pts == AV_NOPTS_VALUE)
474 } 554 ts_st->payload_pts = pts1;
475 /* prepare packet header */ 555 if (ts_st->payload_index >= DEFAULT_PES_PAYLOAD_SIZE) {
476 q = ts_st->packet; 556 mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index,
477 *q++ = 0x47; 557 ts_st->payload_pts);
478 val = (ts_st->pid >> 8); 558 ts_st->payload_pts = AV_NOPTS_VALUE;
479 if (is_start) 559 ts_st->payload_index = 0;
480 val |= 0x40;
481 *q++ = val;
482 *q++ = ts_st->pid;
483 *q++ = 0x10 | ts_st->cc;
484 ts_st->cc = (ts_st->cc + 1) & 0xf;
485 if (is_start) {
486 /* write PES header */
487 *q++ = 0x00;
488 *q++ = 0x00;
489 *q++ = 0x01;
490 if (st->codec.codec_type == CODEC_TYPE_VIDEO)
491 *q++ = 0xe0;
492 else
493 *q++ = 0xc0;
494 *q++ = 0; /* unbounded size */
495 *q++ = 0;
496 *q++ = 0x80;
497 write_pts = 0; /* XXX: enable it */
498 if (write_pts) {
499 *q++ = 0x80; /* PTS only */
500 *q++ = 0x05; /* header len */
501 pts = pts1;
502 val = (0x02 << 4) |
503 (((pts >> 30) & 0x07) << 1) | 1;
504 *q++ = val;
505 val = (((pts >> 15) & 0x7fff) << 1) | 1;
506 *q++ = val >> 8;
507 *q++ = val;
508 val = (((pts) & 0x7fff) << 1) | 1;
509 *q++ = val >> 8;
510 *q++ = val;
511 } else {
512 *q++ = 0x00;
513 *q++ = 0x00;
514 }
515 }
516 ts_st->packet_index = q - ts_st->packet;
517 } 560 }
518 len = TS_PACKET_SIZE - ts_st->packet_index; 561 }
519 if (len == 0) {
520 put_buffer(&s->pb, ts_st->packet, TS_PACKET_SIZE);
521 ts_st->packet_index = 0;
522 } else {
523 if (len > size)
524 len = size;
525 memcpy(ts_st->packet + ts_st->packet_index, buf, len);
526 size -= len;
527 buf += len;
528 ts_st->packet_index += len;
529 }
530 }
531 put_flush_packet(&s->pb);
532 return 0; 562 return 0;
533 } 563 }
534 564
535 static int mpegts_write_end(AVFormatContext *s) 565 static int mpegts_write_end(AVFormatContext *s)
536 { 566 {
542 572
543 /* flush current packets */ 573 /* flush current packets */
544 for(i = 0; i < s->nb_streams; i++) { 574 for(i = 0; i < s->nb_streams; i++) {
545 st = s->streams[i]; 575 st = s->streams[i];
546 ts_st = st->priv_data; 576 ts_st = st->priv_data;
547 if (ts_st->packet_index != 0) { 577 if (ts_st->payload_index > 0) {
548 /* put a known value at the end */ 578 mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index,
549 memset(ts_st->packet + ts_st->packet_index, 0xff, 579 ts_st->payload_pts);
550 TS_PACKET_SIZE - ts_st->packet_index);
551 put_buffer(&s->pb, ts_st->packet, TS_PACKET_SIZE);
552 } 580 }
553 } 581 }
554 put_flush_packet(&s->pb); 582 put_flush_packet(&s->pb);
555 583
556 for(i = 0; i < ts->nb_services; i++) { 584 for(i = 0; i < ts->nb_services; i++) {
573 "MPEG2 transport stream format", 601 "MPEG2 transport stream format",
574 "video/x-mpegts", 602 "video/x-mpegts",
575 "ts", 603 "ts",
576 sizeof(MpegTSWrite), 604 sizeof(MpegTSWrite),
577 CODEC_ID_MP2, 605 CODEC_ID_MP2,
578 CODEC_ID_MPEG1VIDEO, 606 CODEC_ID_MPEG2VIDEO,
579 mpegts_write_header, 607 mpegts_write_header,
580 mpegts_write_packet, 608 mpegts_write_packet,
581 mpegts_write_end, 609 mpegts_write_end,
582 }; 610 };