summaryrefslogtreecommitdiff
path: root/ffmpeg/libavformat/mux.c
diff options
context:
space:
mode:
authorTim Redfern <tim@eclectronics.org>2013-12-29 12:19:38 +0000
committerTim Redfern <tim@eclectronics.org>2013-12-29 12:19:38 +0000
commitf7813a5324be39d13ab536c245d15dfc602a7849 (patch)
treefad99148b88823d34a5df2f0a25881a002eb291b /ffmpeg/libavformat/mux.c
parentb7a5a477b8ff4d4e3028b9dfb9a9df0a41463f92 (diff)
basic type mechanism working
Diffstat (limited to 'ffmpeg/libavformat/mux.c')
-rw-r--r--ffmpeg/libavformat/mux.c135
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);
+}