X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmpegtsenc.c;h=ea78721de0e49dd8814ffdbfc4e7d8fb9c1a5baa;hb=dce25564cc554cc85c8c28928b1b8d3f965c1b16;hp=77815d0949440966f2e4dc1e4c7ce3d2024162e7;hpb=5541759f6fabccb5067da158fbb7458fb96b0155;p=ffmpeg diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index 77815d09494..ea78721de0e 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -1,6 +1,6 @@ /* * MPEG2 transport stream (aka DVB) muxer - * Copyright (c) 2003 Fabrice Bellard. + * Copyright (c) 2003 Fabrice Bellard * * This file is part of FFmpeg. * @@ -385,6 +385,7 @@ static int mpegts_write_header(AVFormatContext *s) AVStream *st; int i, total_bit_rate; const char *service_name; + uint64_t sdt_size, pat_pmt_size, pos; ts->tsid = DEFAULT_TSID; ts->onid = DEFAULT_ONID; @@ -440,20 +441,39 @@ static int mpegts_write_header(AVFormatContext *s) (TS_PACKET_SIZE * 8 * 1000); ts->pat_packet_freq = (total_bit_rate * PAT_RETRANS_TIME) / (TS_PACKET_SIZE * 8 * 1000); -#if 0 - printf("%d %d %d\n", - total_bit_rate, ts->sdt_packet_freq, ts->pat_packet_freq); -#endif - ts->mux_rate = total_bit_rate; + ts->mux_rate = 1; // avoid div by 0 /* write info at the start of the file, so that it will be fast to find them */ + pos = url_ftell(s->pb); mpegts_write_sdt(s); + sdt_size = url_ftell(s->pb) - pos; + pos = url_ftell(s->pb); mpegts_write_pat(s); for(i = 0; i < ts->nb_services; i++) { mpegts_write_pmt(s, ts->services[i]); } + pat_pmt_size = url_ftell(s->pb) - pos; + + total_bit_rate += + total_bit_rate * 25 / (8 * DEFAULT_PES_PAYLOAD_SIZE) + /* PES header size */ + total_bit_rate * 4 / (8 * TS_PACKET_SIZE) + /* TS header size */ + SDT_RETRANS_TIME * sdt_size + /* SDT size */ + PAT_RETRANS_TIME * pat_pmt_size + /* PAT+PMT size */ + PCR_RETRANS_TIME * 8; /* PCR size */ + + av_log(s, AV_LOG_DEBUG, "muxrate %d freq sdt %d pat %d\n", + total_bit_rate, ts->sdt_packet_freq, ts->pat_packet_freq); + + if (s->mux_rate) + ts->mux_rate = s->mux_rate; + else + ts->mux_rate = total_bit_rate; + + // adjust pcr + ts->cur_pcr /= ts->mux_rate; + put_flush_packet(s->pb); return 0; @@ -539,6 +559,8 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, if (write_pcr) { // add 11, pcr references the last byte of program clock reference base pcr = ts->cur_pcr + (4+7)*8*90000LL / ts->mux_rate; + if (dts != AV_NOPTS_VALUE && dts < pcr) + av_log(s, AV_LOG_WARNING, "dts < pcr, TS is invalid\n"); *q++ = 7; /* AFC length */ *q++ = 0x10; /* flags: PCR present */ *q++ = pcr >> 25; @@ -669,20 +691,27 @@ 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; + uint8_t *data= NULL; MpegTSWriteStream *ts_st = st->priv_data; int len, max_payload_size; const uint8_t *access_unit_index = NULL; const uint64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE); + int64_t dts = AV_NOPTS_VALUE, pts = AV_NOPTS_VALUE; + + if (pkt->pts != AV_NOPTS_VALUE) + pts = pkt->pts + delay; + if (pkt->dts != AV_NOPTS_VALUE) + dts = pkt->dts + delay; 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, AV_NOPTS_VALUE); + mpegts_write_pes(s, st, buf, size, pts, AV_NOPTS_VALUE); return 0; } if (st->codec->codec_id == CODEC_ID_DIRAC) { /* for Dirac, a single PES packet must be generated */ - mpegts_write_pes(s, st, buf, size, pkt->pts, pkt->dts); + mpegts_write_pes(s, st, buf, size, pts, dts); return 0; } max_payload_size = DEFAULT_PES_PAYLOAD_SIZE; @@ -698,7 +727,24 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt) break; } } - } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) { + } if (st->codec->codec_id == CODEC_ID_H264) { + if (pkt->size < 5 || AV_RB32(pkt->data) != 0x0000001) { + av_log(s, AV_LOG_ERROR, "h264 bitstream malformated\n"); + return -1; + } + if (pkt->data[4] != 0x09) { // AUD NAL + data = av_malloc(pkt->size+6); + if (!data) + return -1; + memcpy(data+6, pkt->data, pkt->size); + AV_WB32(data, 0x00000001); + data[4] = 0x09; + data[5] = 0xe0; // any slice type + buf = data; + size = pkt->size+6; + } + access_unit_index = buf; + } else { access_unit_index = pkt->data; } @@ -718,8 +764,8 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt) if (access_unit_index && access_unit_index < buf && ts_st->payload_pts == AV_NOPTS_VALUE && ts_st->payload_dts == AV_NOPTS_VALUE) { - ts_st->payload_dts = pkt->dts + delay; - ts_st->payload_pts = pkt->pts + delay; + ts_st->payload_dts = dts; + ts_st->payload_pts = pts; } if (ts_st->payload_index >= max_payload_size) { mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index, @@ -730,6 +776,9 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt) access_unit_index = NULL; // unset access unit to avoid setting pts/dts again } } + + av_free(data); + return 0; }