diff options
Diffstat (limited to 'ffmpeg/libavformat/mux.c')
| -rw-r--r-- | ffmpeg/libavformat/mux.c | 135 |
1 files changed, 97 insertions, 38 deletions
diff --git a/ffmpeg/libavformat/mux.c b/ffmpeg/libavformat/mux.c index 3578a52..f01b82b 100644 --- a/ffmpeg/libavformat/mux.c +++ b/ffmpeg/libavformat/mux.c @@ -19,8 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* #define DEBUG */ - #include "avformat.h" #include "avio_internal.h" #include "internal.h" @@ -34,6 +32,7 @@ #include "id3v2.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" +#include "libavutil/internal.h" #include "libavutil/mathematics.h" #include "libavutil/parseutils.h" #include "libavutil/time.h" @@ -238,7 +237,7 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) // some sanity checks if (s->nb_streams == 0 && !(of->flags & AVFMT_NOSTREAMS)) { - av_log(s, AV_LOG_ERROR, "no streams\n"); + av_log(s, AV_LOG_ERROR, "No streams to mux were specified\n"); ret = AVERROR(EINVAL); goto fail; } @@ -275,13 +274,18 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) if (av_cmp_q(st->sample_aspect_ratio, codec->sample_aspect_ratio) && FFABS(av_q2d(st->sample_aspect_ratio) - av_q2d(codec->sample_aspect_ratio)) > 0.004*av_q2d(st->sample_aspect_ratio) ) { - av_log(s, AV_LOG_ERROR, "Aspect ratio mismatch between muxer " - "(%d/%d) and encoder layer (%d/%d)\n", - st->sample_aspect_ratio.num, st->sample_aspect_ratio.den, - codec->sample_aspect_ratio.num, - codec->sample_aspect_ratio.den); - ret = AVERROR(EINVAL); - goto fail; + if (st->sample_aspect_ratio.num != 0 && + st->sample_aspect_ratio.den != 0 && + codec->sample_aspect_ratio.den != 0 && + codec->sample_aspect_ratio.den != 0) { + av_log(s, AV_LOG_ERROR, "Aspect ratio mismatch between muxer " + "(%d/%d) and encoder layer (%d/%d)\n", + st->sample_aspect_ratio.num, st->sample_aspect_ratio.den, + codec->sample_aspect_ratio.num, + codec->sample_aspect_ratio.den); + ret = AVERROR(EINVAL); + goto fail; + } } break; } @@ -298,12 +302,12 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) } if (codec->codec_tag) { if (!validate_codec_tag(s, st)) { - char tagbuf[32], cortag[32]; + char tagbuf[32], tagbuf2[32]; av_get_codec_tag_string(tagbuf, sizeof(tagbuf), codec->codec_tag); - av_get_codec_tag_string(cortag, sizeof(cortag), av_codec_get_tag(s->oformat->codec_tag, codec->codec_id)); + av_get_codec_tag_string(tagbuf2, sizeof(tagbuf2), av_codec_get_tag(s->oformat->codec_tag, codec->codec_id)); av_log(s, AV_LOG_ERROR, "Tag %s/0x%08x incompatible with output codec id '%d' (%s)\n", - tagbuf, codec->codec_tag, codec->codec_id, cortag); + tagbuf, codec->codec_tag, codec->codec_id, tagbuf2); ret = AVERROR_INVALIDDATA; goto fail; } @@ -335,6 +339,8 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) /* set muxer identification string */ if (s->nb_streams && !(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) { av_dict_set(&s->metadata, "encoder", LIBAVFORMAT_IDENT, 0); + } else { + av_dict_set(&s->metadata, "encoder", NULL, 0); } if (options) { @@ -398,6 +404,13 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options) if ((ret = init_pts(s)) < 0) return ret; + if (s->avoid_negative_ts < 0) { + if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) { + s->avoid_negative_ts = 0; + } else + s->avoid_negative_ts = 1; + } + return 0; } @@ -485,17 +498,52 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt) } /** - * Move side data from payload to internal struct, call muxer, and restore - * original packet. + * Make timestamps non negative, move side data from payload to internal struct, call muxer, and restore + * sidedata. + * + * FIXME: this function should NEVER get undefined pts/dts beside when the + * AVFMT_NOTIMESTAMPS is set. + * Those additional safety checks should be dropped once the correct checks + * are set in the callers. */ -static inline int split_write_packet(AVFormatContext *s, AVPacket *pkt) +static int write_packet(AVFormatContext *s, AVPacket *pkt) { int ret, did_split; + if (s->avoid_negative_ts > 0) { + AVStream *st = s->streams[pkt->stream_index]; + int64_t offset = st->mux_ts_offset; + + if (pkt->dts < 0 && pkt->dts != AV_NOPTS_VALUE && !s->offset) { + s->offset = -pkt->dts; + s->offset_timebase = st->time_base; + } + + if (s->offset && !offset) { + offset = st->mux_ts_offset = + av_rescale_q_rnd(s->offset, + s->offset_timebase, + st->time_base, + AV_ROUND_UP); + } + + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts += offset; + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts += offset; + + av_assert2(pkt->dts == AV_NOPTS_VALUE || pkt->dts >= 0); + } + did_split = av_packet_split_side_data(pkt); ret = s->oformat->write_packet(s, pkt); + + if (s->flush_packets && s->pb && ret >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS) + avio_flush(s->pb); + if (did_split) av_packet_merge_side_data(pkt); + return ret; } @@ -506,6 +554,8 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt) if (!pkt) { if (s->oformat->flags & AVFMT_ALLOW_FLUSH) { ret = s->oformat->write_packet(s, NULL); + if (s->flush_packets && s->pb && s->pb->error >= 0) + avio_flush(s->pb); if (ret >= 0 && s->pb && s->pb->error < 0) ret = s->pb->error; return ret; @@ -518,7 +568,7 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt) if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) return ret; - ret = split_write_packet(s, pkt); + ret = write_packet(s, pkt); if (ret >= 0 && s->pb && s->pb->error < 0) ret = s->pb->error; @@ -541,10 +591,13 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, return AVERROR(ENOMEM); this_pktl->pkt = *pkt; #if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS pkt->destruct = NULL; // do not free original but only the copy +FF_ENABLE_DEPRECATION_WARNINGS #endif pkt->buf = NULL; av_dup_packet(&this_pktl->pkt); // duplicate the packet if it uses non-allocated memory + av_copy_packet_side_data(&this_pktl->pkt, &this_pktl->pkt); // copy side data if (s->streams[pkt->stream_index]->last_in_packet_buffer) { next_point = &(st->last_in_packet_buffer->next); @@ -596,7 +649,8 @@ next_non_null: return 0; } -static int ff_interleave_compare_dts(AVFormatContext *s, AVPacket *next, AVPacket *pkt) +static int interleave_compare_dts(AVFormatContext *s, AVPacket *next, + AVPacket *pkt) { AVStream *st = s->streams[pkt->stream_index]; AVStream *st2 = s->streams[next->stream_index]; @@ -627,7 +681,7 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, int i, ret; if (pkt) { - ret = ff_interleave_add_packet(s, pkt, ff_interleave_compare_dts); + ret = ff_interleave_add_packet(s, pkt, interleave_compare_dts); if (ret < 0) return ret; } @@ -675,23 +729,6 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, st->last_in_packet_buffer = NULL; av_freep(&pktl); - if (s->avoid_negative_ts > 0) { - if (out->dts != AV_NOPTS_VALUE) { - if (!st->mux_ts_offset && out->dts < 0) { - for (i = 0; i < s->nb_streams; i++) { - s->streams[i]->mux_ts_offset = - av_rescale_q_rnd(-out->dts, - st->time_base, - s->streams[i]->time_base, - AV_ROUND_UP); - } - } - out->dts += st->mux_ts_offset; - } - if (out->pts != AV_NOPTS_VALUE) - out->pts += st->mux_ts_offset; - } - return 1; } else { av_init_packet(out); @@ -748,7 +785,7 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) if (ret <= 0) //FIXME cleanup needed for ret<0 ? return ret; - ret = split_write_packet(s, &opkt); + ret = write_packet(s, &opkt); if (ret >= 0) s->streams[opkt.stream_index]->nb_frames++; @@ -774,7 +811,7 @@ int av_write_trailer(AVFormatContext *s) if (!ret) break; - ret = split_write_packet(s, &pkt); + ret = write_packet(s, &pkt); if (ret >= 0) s->streams[pkt.stream_index]->nb_frames++; @@ -812,3 +849,25 @@ int av_get_output_timestamp(struct AVFormatContext *s, int stream, s->oformat->get_output_timestamp(s, stream, dts, wall); return 0; } + +int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, + AVFormatContext *src) +{ + AVPacket local_pkt; + + local_pkt = *pkt; + local_pkt.stream_index = dst_stream; + if (pkt->pts != AV_NOPTS_VALUE) + local_pkt.pts = av_rescale_q(pkt->pts, + src->streams[pkt->stream_index]->time_base, + dst->streams[dst_stream]->time_base); + if (pkt->dts != AV_NOPTS_VALUE) + local_pkt.dts = av_rescale_q(pkt->dts, + src->streams[pkt->stream_index]->time_base, + dst->streams[dst_stream]->time_base); + if (pkt->duration) + local_pkt.duration = av_rescale_q(pkt->duration, + src->streams[pkt->stream_index]->time_base, + dst->streams[dst_stream]->time_base); + return av_write_frame(dst, &local_pkt); +} |
