summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorLuca Barbato <lu_zero@gentoo.org>2013-04-03 14:11:10 +0200
committerLuca Barbato <lu_zero@gentoo.org>2013-04-25 10:13:27 +0200
commitc2cb01d418dd18e1cf997c038d37378d773121be (patch)
tree4a9a581316f6a1f9cba7de6460319224601d21f3 /libavformat
parentfc18cc44ebfae07da153dc782572e7ce2f6fe47d (diff)
lavf: introduce AVFMT_TS_NEGATIVE
Most formats do not support negative timestamps, shift them to avoid unexpected behaviour and a number of bad crashes. CC:libav-stable@libav.org Signed-off-by: Anton Khirnov <anton@khirnov.net> Signed-off-by: Luca Barbato <lu_zero@gentoo.org>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/avformat.h17
-rw-r--r--libavformat/ffmenc.c1
-rw-r--r--libavformat/framecrcenc.c3
-rw-r--r--libavformat/md5enc.c3
-rw-r--r--libavformat/mux.c34
-rw-r--r--libavformat/oggenc.c1
6 files changed, 54 insertions, 5 deletions
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 067a7874b9..2512e36020 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -360,6 +360,11 @@ typedef struct AVProbeData {
#define AVFMT_TS_NONSTRICT 0x20000 /**< Format does not require strictly
increasing timestamps, but they must
still be monotonic */
+#define AVFMT_TS_NEGATIVE 0x40000 /**< Format allows muxing negative
+ timestamps. If not set the timestamp
+ will be shifted in av_write_frame and
+ av_interleaved_write_frame so they
+ start from 0. */
/**
* @addtogroup lavf_encoding
@@ -1021,6 +1026,18 @@ typedef struct AVFormatContext {
*/
#define RAW_PACKET_BUFFER_SIZE 2500000
int raw_packet_buffer_remaining_size;
+
+ /**
+ * Offset to remap timestamps to be non-negative.
+ * Expressed in timebase units.
+ */
+ int64_t offset;
+
+ /**
+ * Timebase for the timestamp offset.
+ */
+ AVRational offset_timebase;
+
} AVFormatContext;
typedef struct AVPacketList {
diff --git a/libavformat/ffmenc.c b/libavformat/ffmenc.c
index 386487f1f9..91658e12dd 100644
--- a/libavformat/ffmenc.c
+++ b/libavformat/ffmenc.c
@@ -245,4 +245,5 @@ AVOutputFormat ff_ffm_muxer = {
.write_header = ffm_write_header,
.write_packet = ffm_write_packet,
.write_trailer = ffm_write_trailer,
+ .flags = AVFMT_TS_NEGATIVE,
};
diff --git a/libavformat/framecrcenc.c b/libavformat/framecrcenc.c
index de6fa2b960..fed0cca430 100644
--- a/libavformat/framecrcenc.c
+++ b/libavformat/framecrcenc.c
@@ -43,5 +43,6 @@ AVOutputFormat ff_framecrc_muxer = {
.video_codec = AV_CODEC_ID_RAWVIDEO,
.write_header = ff_framehash_write_header,
.write_packet = framecrc_write_packet,
- .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT,
+ .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
+ AVFMT_TS_NEGATIVE,
};
diff --git a/libavformat/md5enc.c b/libavformat/md5enc.c
index 16412c9a34..92497045eb 100644
--- a/libavformat/md5enc.c
+++ b/libavformat/md5enc.c
@@ -127,6 +127,7 @@ AVOutputFormat ff_framemd5_muxer = {
.write_header = framemd5_write_header,
.write_packet = framemd5_write_packet,
.write_trailer = framemd5_write_trailer,
- .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT,
+ .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
+ AVFMT_TS_NEGATIVE,
};
#endif
diff --git a/libavformat/mux.c b/libavformat/mux.c
index 76b0fb4dc6..0b537b8c1f 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -391,6 +391,34 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
return 0;
}
+/*
+ * 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 int write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ if (!(s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS))) {
+ AVRational time_base = s->streams[pkt->stream_index]->time_base;
+ int64_t offset = 0;
+
+ if (!s->offset && pkt->dts != AV_NOPTS_VALUE && pkt->dts < 0) {
+ s->offset = -pkt->dts;
+ s->offset_timebase = time_base;
+ }
+ if (s->offset)
+ offset = av_rescale_q(s->offset, s->offset_timebase, time_base);
+
+ if (pkt->dts != AV_NOPTS_VALUE)
+ pkt->dts += offset;
+ if (pkt->pts != AV_NOPTS_VALUE)
+ pkt->pts += offset;
+ }
+ return s->oformat->write_packet(s, pkt);
+}
+
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
{
int ret;
@@ -406,7 +434,7 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt)
if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
return ret;
- ret = s->oformat->write_packet(s, pkt);
+ ret = write_packet(s, pkt);
if (ret >= 0)
s->streams[pkt->stream_index]->nb_frames++;
@@ -544,7 +572,7 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
if (ret <= 0) //FIXME cleanup needed for ret<0 ?
return ret;
- ret = s->oformat->write_packet(s, &opkt);
+ ret = write_packet(s, &opkt);
if (ret >= 0)
s->streams[opkt.stream_index]->nb_frames++;
@@ -568,7 +596,7 @@ int av_write_trailer(AVFormatContext *s)
if (!ret)
break;
- ret = s->oformat->write_packet(s, &pkt);
+ ret = write_packet(s, &pkt);
if (ret >= 0)
s->streams[pkt.stream_index]->nb_frames++;
diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c
index 6212d16373..e01c365125 100644
--- a/libavformat/oggenc.c
+++ b/libavformat/oggenc.c
@@ -619,5 +619,6 @@ AVOutputFormat ff_ogg_muxer = {
.write_header = ogg_write_header,
.write_packet = ogg_write_packet,
.write_trailer = ogg_write_trailer,
+ .flags = AVFMT_TS_NEGATIVE,
.priv_class = &ogg_muxer_class,
};