summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavformat/avformat.h2
-rw-r--r--libavformat/internal.h12
-rw-r--r--libavformat/mux.c22
-rw-r--r--libavformat/utils.c6
4 files changed, 33 insertions, 9 deletions
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 6933624f26..e83a374f6d 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1170,6 +1170,8 @@ typedef struct AVStream {
* - decoding: Set by libavformat to calculate sample_aspect_ratio internally
*/
AVRational display_aspect_ratio;
+
+ struct FFFrac *priv_pts;
} AVStream;
AVRational av_stream_get_r_frame_rate(const AVStream *s);
diff --git a/libavformat/internal.h b/libavformat/internal.h
index 352739e7dd..bd8a0bcf8a 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -49,6 +49,18 @@ typedef struct CodecMime{
enum AVCodecID id;
} CodecMime;
+/*************************************************/
+/* fractional numbers for exact pts handling */
+
+/**
+ * The exact value of the fractional number is: 'val + num / den'.
+ * num is assumed to be 0 <= num < den.
+ */
+typedef struct FFFrac {
+ int64_t val, num, den;
+} FFFrac;
+
+
struct AVFormatInternal {
/**
* Number of streams relevant for interleaving.
diff --git a/libavformat/mux.c b/libavformat/mux.c
index 7664872a4a..81c467648e 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -61,7 +61,7 @@
* @param num must be >= 0
* @param den must be >= 1
*/
-static void frac_init(AVFrac *f, int64_t val, int64_t num, int64_t den)
+static void frac_init(FFFrac *f, int64_t val, int64_t num, int64_t den)
{
num += (den >> 1);
if (num >= den) {
@@ -79,7 +79,7 @@ static void frac_init(AVFrac *f, int64_t val, int64_t num, int64_t den)
* @param f fractional number
* @param incr increment, can be positive or negative
*/
-static void frac_add(AVFrac *f, int64_t incr)
+static void frac_add(FFFrac *f, int64_t incr)
{
int64_t num, den;
@@ -414,11 +414,17 @@ static int init_pts(AVFormatContext *s)
default:
break;
}
+
+ if (!st->priv_pts)
+ st->priv_pts = av_mallocz(sizeof(*st->priv_pts));
+ if (!st->priv_pts)
+ return AVERROR(ENOMEM);
+
if (den != AV_NOPTS_VALUE) {
if (den <= 0)
return AVERROR_INVALIDDATA;
- frac_init(&st->pts, 0, 0, den);
+ frac_init(st->priv_pts, 0, 0, den);
}
}
@@ -502,7 +508,7 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
}
pkt->dts =
// pkt->pts= st->cur_dts;
- pkt->pts = st->pts.val;
+ pkt->pts = st->priv_pts->val;
}
//calculate dts from pts
@@ -538,7 +544,7 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
av_ts2str(pkt->pts), av_ts2str(pkt->dts));
st->cur_dts = pkt->dts;
- st->pts.val = pkt->dts;
+ st->priv_pts->val = pkt->dts;
/* update pts */
switch (st->codec->codec_type) {
@@ -550,12 +556,12 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
/* HACK/FIXME, we skip the initial 0 size packets as they are most
* likely equal to the encoder delay, but it would be better if we
* had the real timestamps from the encoder */
- if (frame_size >= 0 && (pkt->size || st->pts.num != st->pts.den >> 1 || st->pts.val)) {
- frac_add(&st->pts, (int64_t)st->time_base.den * frame_size);
+ if (frame_size >= 0 && (pkt->size || st->priv_pts->num != st->priv_pts->den >> 1 || st->priv_pts->val)) {
+ frac_add(st->priv_pts, (int64_t)st->time_base.den * frame_size);
}
break;
case AVMEDIA_TYPE_VIDEO:
- frac_add(&st->pts, (int64_t)st->time_base.den * st->codec->time_base.num);
+ frac_add(st->priv_pts, (int64_t)st->time_base.den * st->codec->time_base.num);
break;
}
return 0;
diff --git a/libavformat/utils.c b/libavformat/utils.c
index ccc2129126..758b9400b1 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -116,7 +116,10 @@ MAKE_ACCESSORS(AVFormatContext, format, AVOpenCallback, open_cb)
int64_t av_stream_get_end_pts(const AVStream *st)
{
- return st->pts.val;
+ if (st->priv_pts) {
+ return st->priv_pts->val;
+ } else
+ return AV_NOPTS_VALUE;
}
struct AVCodecParserContext *av_stream_get_parser(const AVStream *st)
@@ -3668,6 +3671,7 @@ void ff_free_stream(AVFormatContext *s, AVStream *st) {
av_freep(&st->info->duration_error);
av_freep(&st->info);
av_freep(&st->recommended_encoder_configuration);
+ av_freep(&st->priv_pts);
av_freep(&s->streams[ --s->nb_streams ]);
}