Commit c4bf7402 authored by Michael Niedermayer's avatar Michael Niedermayer

Merge commit 'c2cb01d4'

* commit 'c2cb01d4':
  lavf: introduce AVFMT_TS_NEGATIVE

Conflicts:
	libavformat/avformat.h
	libavformat/mux.c
	tests/ref/lavf/asf
	tests/ref/lavf/mkv
	tests/ref/lavf/mpg
	tests/ref/lavf/ts
	tests/ref/seek/lavf-asf
	tests/ref/seek/lavf-mkv
	tests/ref/seek/lavf-mpg
	tests/ref/seek/lavf-ts

This commit does not change the default ts behaviour, such
change will, if its done, be done separately.
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents 05f4c050 c2cb01d4
...@@ -366,6 +366,11 @@ typedef struct AVProbeData { ...@@ -366,6 +366,11 @@ typedef struct AVProbeData {
/**< Format does not require strictly /**< Format does not require strictly
increasing timestamps, but they must increasing timestamps, but they must
still be monotonic */ 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. */
#define AVFMT_SEEK_TO_PTS 0x4000000 /**< Seeking is based on PTS */ #define AVFMT_SEEK_TO_PTS 0x4000000 /**< Seeking is based on PTS */
...@@ -1258,6 +1263,18 @@ typedef struct AVFormatContext { ...@@ -1258,6 +1263,18 @@ typedef struct AVFormatContext {
#define RAW_PACKET_BUFFER_SIZE 2500000 #define RAW_PACKET_BUFFER_SIZE 2500000
int raw_packet_buffer_remaining_size; int raw_packet_buffer_remaining_size;
/**
* Offset to remap timestamps to be non-negative.
* Expressed in timebase units.
* @see AVStream.mux_ts_offset
*/
int64_t offset;
/**
* Timebase for the timestamp offset.
*/
AVRational offset_timebase;
/** /**
* IO repositioned flag. * IO repositioned flag.
* This is set by avformat when the underlaying IO context read pointer * This is set by avformat when the underlaying IO context read pointer
......
...@@ -277,4 +277,5 @@ AVOutputFormat ff_ffm_muxer = { ...@@ -277,4 +277,5 @@ AVOutputFormat ff_ffm_muxer = {
.write_header = ffm_write_header, .write_header = ffm_write_header,
.write_packet = ffm_write_packet, .write_packet = ffm_write_packet,
.write_trailer = ffm_write_trailer, .write_trailer = ffm_write_trailer,
.flags = AVFMT_TS_NEGATIVE,
}; };
...@@ -56,5 +56,6 @@ AVOutputFormat ff_framecrc_muxer = { ...@@ -56,5 +56,6 @@ AVOutputFormat ff_framecrc_muxer = {
.video_codec = AV_CODEC_ID_RAWVIDEO, .video_codec = AV_CODEC_ID_RAWVIDEO,
.write_header = ff_framehash_write_header, .write_header = ff_framehash_write_header,
.write_packet = framecrc_write_packet, .write_packet = framecrc_write_packet,
.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
AVFMT_TS_NEGATIVE,
}; };
...@@ -125,6 +125,7 @@ AVOutputFormat ff_framemd5_muxer = { ...@@ -125,6 +125,7 @@ AVOutputFormat ff_framemd5_muxer = {
.write_header = framemd5_write_header, .write_header = framemd5_write_header,
.write_packet = framemd5_write_packet, .write_packet = framemd5_write_packet,
.write_trailer = framemd5_write_trailer, .write_trailer = framemd5_write_trailer,
.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
AVFMT_TS_NEGATIVE,
}; };
#endif #endif
...@@ -485,12 +485,52 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt) ...@@ -485,12 +485,52 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
} }
/** /**
* Move side data from payload to internal struct, call muxer, and restore * Make timestamps non negative, move side data from payload to internal struct, call muxer, and restore
* original packet. * 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; int ret, did_split, i;
if (s->avoid_negative_ts > 0) {
AVStream *st = s->streams[pkt->stream_index];
if (pkt->dts != AV_NOPTS_VALUE) {
if (!st->mux_ts_offset && pkt->dts < 0) {
for (i = 0; i < s->nb_streams; i++) {
s->streams[i]->mux_ts_offset =
av_rescale_q_rnd(-pkt->dts,
st->time_base,
s->streams[i]->time_base,
AV_ROUND_UP);
}
}
pkt->dts += st->mux_ts_offset;
}
if (pkt->pts != AV_NOPTS_VALUE)
pkt->pts += st->mux_ts_offset;
}
if (!(s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) && 0) {
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;
}
did_split = av_packet_split_side_data(pkt); did_split = av_packet_split_side_data(pkt);
ret = s->oformat->write_packet(s, pkt); ret = s->oformat->write_packet(s, pkt);
...@@ -522,7 +562,7 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt) ...@@ -522,7 +562,7 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt)
if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
return ret; return ret;
ret = split_write_packet(s, pkt); ret = write_packet(s, pkt);
if (ret >= 0 && s->pb && s->pb->error < 0) if (ret >= 0 && s->pb && s->pb->error < 0)
ret = s->pb->error; ret = s->pb->error;
...@@ -679,23 +719,6 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, ...@@ -679,23 +719,6 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out,
st->last_in_packet_buffer = NULL; st->last_in_packet_buffer = NULL;
av_freep(&pktl); 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; return 1;
} else { } else {
av_init_packet(out); av_init_packet(out);
...@@ -752,7 +775,7 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) ...@@ -752,7 +775,7 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
if (ret <= 0) //FIXME cleanup needed for ret<0 ? if (ret <= 0) //FIXME cleanup needed for ret<0 ?
return ret; return ret;
ret = split_write_packet(s, &opkt); ret = write_packet(s, &opkt);
if (ret >= 0) if (ret >= 0)
s->streams[opkt.stream_index]->nb_frames++; s->streams[opkt.stream_index]->nb_frames++;
...@@ -778,7 +801,7 @@ int av_write_trailer(AVFormatContext *s) ...@@ -778,7 +801,7 @@ int av_write_trailer(AVFormatContext *s)
if (!ret) if (!ret)
break; break;
ret = split_write_packet(s, &pkt); ret = write_packet(s, &pkt);
if (ret >= 0) if (ret >= 0)
s->streams[pkt.stream_index]->nb_frames++; s->streams[pkt.stream_index]->nb_frames++;
......
...@@ -632,5 +632,6 @@ AVOutputFormat ff_ogg_muxer = { ...@@ -632,5 +632,6 @@ AVOutputFormat ff_ogg_muxer = {
.write_header = ogg_write_header, .write_header = ogg_write_header,
.write_packet = ogg_write_packet, .write_packet = ogg_write_packet,
.write_trailer = ogg_write_trailer, .write_trailer = ogg_write_trailer,
.flags = AVFMT_TS_NEGATIVE,
.priv_class = &ogg_muxer_class, .priv_class = &ogg_muxer_class,
}; };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment