diff options
Diffstat (limited to 'libavformat/mpegenc.c')
-rw-r--r-- | libavformat/mpegenc.c | 128 |
1 files changed, 84 insertions, 44 deletions
diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c index 33eaefd9ff..af40fd3b31 100644 --- a/libavformat/mpegenc.c +++ b/libavformat/mpegenc.c @@ -2,20 +2,20 @@ * MPEG1/2 muxer * Copyright (c) 2000, 2001, 2002 Fabrice Bellard * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -35,9 +35,6 @@ #define MAX_PAYLOAD_SIZE 4096 -#undef NDEBUG -#include <assert.h> - typedef struct PacketDesc { int64_t pts; int64_t dts; @@ -69,6 +66,7 @@ typedef struct MpegMuxContext { int pack_header_freq; /* frequency (in packets^-1) at which we send pack headers */ int system_header_freq; int system_header_size; + int user_mux_rate; /* bitrate in units of bits/s */ int mux_rate; /* bitrate in units of 50 bytes/s */ /* stream info */ int audio_bound; @@ -268,8 +266,7 @@ static int put_system_header(AVFormatContext *ctx, uint8_t *buf, flush_put_bits(&pb); size = put_bits_ptr(&pb) - pb.buf; /* patch packet size */ - buf[4] = (size - 6) >> 8; - buf[5] = (size - 6) & 0xff; + AV_WB16(buf + 4, size - 6); return size; } @@ -324,7 +321,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) } else s->packet_size = 2048; if (ctx->max_delay < 0) /* Not set by the caller */ - ctx->max_delay = 0; + ctx->max_delay = 0.7*AV_TIME_BASE; s->vcd_padding_bytes_written = 0; s->vcd_padding_bitrate = 0; @@ -351,6 +348,15 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) switch (st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: + if (!s->is_mpeg2 && + (st->codec->codec_id == AV_CODEC_ID_AC3 || + st->codec->codec_id == AV_CODEC_ID_DTS || + st->codec->codec_id == AV_CODEC_ID_PCM_S16BE)) + av_log(ctx, AV_LOG_WARNING, + "%s in MPEG-1 system streams is not widely supported, " + "consider using the vob or the dvd muxer " + "to force a MPEG-2 program stream.\n", + avcodec_get_name(st->codec->codec_id)); if (st->codec->codec_id == AV_CODEC_ID_AC3) { stream->id = ac3_id++; } else if (st->codec->codec_id == AV_CODEC_ID_DTS) { @@ -387,10 +393,16 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) stream->max_buffer_size = 6 * 1024 + st->codec->rc_buffer_size / 8; else { av_log(ctx, AV_LOG_WARNING, - "VBV buffer size not set, muxing may fail\n"); + "VBV buffer size not set, using default size of 130KB\n" + "If you want the mpeg file to be compliant to some specification\n" + "Like DVD, VCD or others, make sure you set the correct buffer size\n"); // FIXME: this is probably too small as default stream->max_buffer_size = 230 * 1024; } + if (stream->max_buffer_size > 1024 * 8191) { + av_log(ctx, AV_LOG_WARNING, "buffer size %d, too large\n", stream->max_buffer_size); + stream->max_buffer_size = 1024 * 8191; + } s->video_bound++; break; case AVMEDIA_TYPE_SUBTITLE: @@ -429,12 +441,18 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) video_bitrate += codec_rate; } - if (!s->mux_rate) { + if (s->user_mux_rate) { + s->mux_rate = (s->user_mux_rate + (8 * 50) - 1) / (8 * 50); + } else { /* we increase slightly the bitrate to take into account the * headers. XXX: compute it exactly */ bitrate += bitrate / 20; bitrate += 10000; s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50); + if (s->mux_rate >= (1<<22)) { + av_log(ctx, AV_LOG_WARNING, "mux rate %d is too large\n", s->mux_rate); + s->mux_rate = (1<<22) - 1; + } } if (s->is_vcd) { @@ -493,12 +511,12 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) stream->packet_number = 0; } s->system_header_size = get_system_header_size(ctx); - s->last_scr = 0; + s->last_scr = AV_NOPTS_VALUE; return 0; fail: for (i = 0; i < ctx->nb_streams; i++) - av_free(ctx->streams[i]->priv_data); + av_freep(&ctx->streams[i]->priv_data); return AVERROR(ENOMEM); } @@ -852,7 +870,7 @@ static int flush_packet(AVFormatContext *ctx, int stream_index, } /* output data */ - assert(payload_size - stuffing_size <= av_fifo_size(stream->fifo)); + av_assert0(payload_size - stuffing_size <= av_fifo_size(stream->fifo)); av_fifo_generic_read(stream->fifo, ctx->pb, payload_size - stuffing_size, (void (*)(void*, void*, int))avio_write); @@ -920,7 +938,7 @@ static int remove_decoded_packets(AVFormatContext *ctx, int64_t scr) if (stream->buffer_index < pkt_desc->size || stream->predecode_packet == stream->premux_packet) { av_log(ctx, AV_LOG_ERROR, - "buffer underflow i=%d bufi=%d size=%d\n", + "buffer underflow st=%d bufi=%d size=%d\n", i, stream->buffer_index, pkt_desc->size); break; } @@ -942,6 +960,7 @@ static int output_packet(AVFormatContext *ctx, int flush) int best_i = -1; int best_score = INT_MIN; int ignore_constraints = 0; + int ignore_delay = 0; int64_t scr = s->last_scr; PacketDesc *timestamp_packet; const int64_t max_delay = av_rescale(ctx->max_delay, 90000, AV_TIME_BASE); @@ -952,7 +971,7 @@ retry: StreamInfo *stream = st->priv_data; const int avail_data = av_fifo_size(stream->fifo); const int space = stream->max_buffer_size - stream->buffer_index; - int rel_space = 1024 * space / stream->max_buffer_size; + int rel_space = 1024LL * space / stream->max_buffer_size; PacketDesc *next_pkt = stream->premux_packet; /* for subtitle, a single PES packet must be generated, @@ -962,14 +981,16 @@ retry: return 0; if (avail_data == 0) continue; - assert(avail_data > 0); + av_assert0(avail_data > 0); if (space < s->packet_size && !ignore_constraints) continue; - if (next_pkt && next_pkt->dts - scr > max_delay) + if (next_pkt && next_pkt->dts - scr > max_delay && !ignore_delay) continue; - + if ( stream->predecode_packet + && stream->predecode_packet->size > stream->buffer_index) + rel_space += 1<<28; if (rel_space > best_score) { best_score = rel_space; best_i = i; @@ -979,6 +1000,7 @@ retry: if (best_i < 0) { int64_t best_dts = INT64_MAX; + int has_premux = 0; for (i = 0; i < ctx->nb_streams; i++) { AVStream *st = ctx->streams[i]; @@ -986,32 +1008,40 @@ retry: PacketDesc *pkt_desc = stream->predecode_packet; if (pkt_desc && pkt_desc->dts < best_dts) best_dts = pkt_desc->dts; + has_premux |= !!stream->premux_packet; } - av_log(ctx, AV_LOG_TRACE, "bumping scr, scr:%f, dts:%f\n", - scr / 90000.0, best_dts / 90000.0); - if (best_dts == INT64_MAX) - return 0; + if (best_dts < INT64_MAX) { + av_log(ctx, AV_LOG_TRACE, "bumping scr, scr:%f, dts:%f\n", + scr / 90000.0, best_dts / 90000.0); - if (scr >= best_dts + 1 && !ignore_constraints) { + if (scr >= best_dts + 1 && !ignore_constraints) { + av_log(ctx, AV_LOG_ERROR, + "packet too large, ignoring buffer limits to mux it\n"); + ignore_constraints = 1; + } + scr = FFMAX(best_dts + 1, scr); + if (remove_decoded_packets(ctx, scr) < 0) + return -1; + } else if (has_premux && flush) { av_log(ctx, AV_LOG_ERROR, - "packet too large, ignoring buffer limits to mux it\n"); + "delay too large, ignoring ...\n"); + ignore_delay = 1; ignore_constraints = 1; - } - scr = FFMAX(best_dts + 1, scr); - if (remove_decoded_packets(ctx, scr) < 0) - return -1; + } else + return 0; + goto retry; } - assert(best_i >= 0); + av_assert0(best_i >= 0); st = ctx->streams[best_i]; stream = st->priv_data; - assert(av_fifo_size(stream->fifo) > 0); + av_assert0(av_fifo_size(stream->fifo) > 0); - assert(avail_space >= s->packet_size || ignore_constraints); + av_assert0(avail_space >= s->packet_size || ignore_constraints); timestamp_packet = stream->premux_packet; if (timestamp_packet->unwritten_size == timestamp_packet->size) { @@ -1029,7 +1059,7 @@ retry: es_size = flush_packet(ctx, best_i, timestamp_packet->pts, timestamp_packet->dts, scr, trailer_size); } else { - assert(av_fifo_size(stream->fifo) == trailer_size); + av_assert0(av_fifo_size(stream->fifo) == trailer_size); es_size = flush_packet(ctx, best_i, AV_NOPTS_VALUE, AV_NOPTS_VALUE, scr, trailer_size); } @@ -1056,8 +1086,10 @@ retry: es_size -= stream->premux_packet->unwritten_size; stream->premux_packet = stream->premux_packet->next; } - if (stream->premux_packet && es_size) + if (es_size) { + av_assert0(stream->premux_packet); stream->premux_packet->unwritten_size -= es_size; + } if (remove_decoded_packets(ctx, s->last_scr) < 0) return -1; @@ -1084,14 +1116,22 @@ static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt) pts = pkt->pts; dts = pkt->dts; - if (pts != AV_NOPTS_VALUE) - pts += 2 * preload; - if (dts != AV_NOPTS_VALUE) { - if (!s->last_scr) - s->last_scr = dts + preload; - dts += 2 * preload; + if (s->last_scr == AV_NOPTS_VALUE) { + if (dts == AV_NOPTS_VALUE || (dts < preload && ctx->avoid_negative_ts) || s->is_dvd) { + if (dts != AV_NOPTS_VALUE) + s->preload += av_rescale(-dts, AV_TIME_BASE, 90000); + s->last_scr = 0; + } else { + s->last_scr = dts - preload; + s->preload = 0; + } + preload = av_rescale(s->preload, 90000, AV_TIME_BASE); + av_log(ctx, AV_LOG_DEBUG, "First SCR: %"PRId64" First DTS: %"PRId64"\n", s->last_scr, dts + preload); } + if (dts != AV_NOPTS_VALUE) dts += preload; + if (pts != AV_NOPTS_VALUE) pts += preload; + av_log(ctx, AV_LOG_TRACE, "dts:%f pts:%f flags:%d stream:%d nopts:%d\n", dts / 90000.0, pts / 90000.0, pkt->flags, pkt->stream_index, pts != AV_NOPTS_VALUE); @@ -1152,8 +1192,8 @@ static int mpeg_mux_end(AVFormatContext *ctx) for (i = 0; i < ctx->nb_streams; i++) { stream = ctx->streams[i]->priv_data; - assert(av_fifo_size(stream->fifo) == 0); - av_fifo_free(stream->fifo); + av_assert0(av_fifo_size(stream->fifo) == 0); + av_fifo_freep(&stream->fifo); } return 0; } @@ -1161,7 +1201,7 @@ static int mpeg_mux_end(AVFormatContext *ctx) #define OFFSET(x) offsetof(MpegMuxContext, x) #define E AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "muxrate", NULL, OFFSET(mux_rate), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, (1 << 22) - 1, E }, + { "muxrate", NULL, OFFSET(user_mux_rate), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, ((1<<22) - 1) * (8 * 50), E }, { "preload", "Initial demux-decode delay in microseconds.", OFFSET(preload), AV_OPT_TYPE_INT, { .i64 = 500000 }, 0, INT_MAX, E }, { NULL }, }; |