summaryrefslogtreecommitdiff
path: root/libavcodec
diff options
context:
space:
mode:
authorNicolas George <nicolas.george@normalesup.org>2011-01-30 20:18:31 +0100
committerMichael Niedermayer <michaelni@gmx.at>2011-02-07 19:32:07 +0100
commit76ad67cae751658ce2d84e83b38a4d673e9e85a3 (patch)
treefd7a80906aa640e700f427539a9c87dd2d27b5c0 /libavcodec
parent52b2e95cd9f829b83b879a0694173d4ef1558c46 (diff)
Implement guessed_pts in avcodec_decode_video2
Signed-off-by: Nicolas George <nicolas.george@normalesup.org> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/avcodec.h18
-rw-r--r--libavcodec/utils.c43
2 files changed, 60 insertions, 1 deletions
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index dbfb77795d..f96ae84740 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1026,6 +1026,13 @@ typedef struct AVPanScan{
* - decoding: Read by user.\
*/\
int64_t pkt_dts;\
+\
+ /**\
+ * frame timestamp estimated using various heuristics, in stream time base\
+ * - encoding: unused\
+ * - decoding: set by libavcodec, read by user.\
+ */\
+ int64_t best_effort_timestamp;\
#define FF_QSCALE_TYPE_MPEG1 0
@@ -2825,6 +2832,17 @@ typedef struct AVCodecContext {
* - encoding: unused
*/
AVPacket *pkt;
+
+ /**
+ * Current statistics for PTS correction.
+ * - decoding: maintained and used by libavcodec
+ * - encoding: unused
+ */
+ int64_t pts_correction_num_faulty_pts; /// Number of incorrect PTS values so far
+ int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far
+ int64_t pts_correction_last_pts; /// PTS of the last frame
+ int64_t pts_correction_last_dts; /// DTS of the last frame
+
} AVCodecContext;
/**
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index e9db33e9d7..2a95975273 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -448,7 +448,7 @@ enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum
void avcodec_get_frame_defaults(AVFrame *pic){
memset(pic, 0, sizeof(AVFrame));
- pic->pts= AV_NOPTS_VALUE;
+ pic->pts = pic->best_effort_timestamp = AV_NOPTS_VALUE;
pic->key_frame= 1;
}
@@ -538,6 +538,11 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec)
goto free_and_end;
}
+ avctx->pts_correction_num_faulty_pts =
+ avctx->pts_correction_num_faulty_dts = 0;
+ avctx->pts_correction_last_pts =
+ avctx->pts_correction_last_dts = INT64_MIN;
+
if(avctx->codec->init){
ret = avctx->codec->init(avctx);
if (ret < 0) {
@@ -608,6 +613,39 @@ int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size,
return ret;
}
+/**
+ * Attempt to guess proper monotonic timestamps for decoded video frames
+ * which might have incorrect times. Input timestamps may wrap around, in
+ * which case the output will as well.
+ *
+ * @param pts the pts field of the decoded AVPacket, as passed through
+ * AVFrame.pkt_pts
+ * @param dts the dts field of the decoded AVPacket
+ * @return one of the input values, may be AV_NOPTS_VALUE
+ */
+static int64_t guess_correct_pts(AVCodecContext *ctx,
+ int64_t reordered_pts, int64_t dts)
+{
+ int64_t pts = AV_NOPTS_VALUE;
+
+ if (dts != AV_NOPTS_VALUE) {
+ ctx->pts_correction_num_faulty_dts += dts <= ctx->pts_correction_last_dts;
+ ctx->pts_correction_last_dts = dts;
+ }
+ if (reordered_pts != AV_NOPTS_VALUE) {
+ ctx->pts_correction_num_faulty_pts += reordered_pts <= ctx->pts_correction_last_pts;
+ ctx->pts_correction_last_pts = reordered_pts;
+ }
+ if ((ctx->pts_correction_num_faulty_pts<=ctx->pts_correction_num_faulty_dts || dts == AV_NOPTS_VALUE)
+ && reordered_pts != AV_NOPTS_VALUE)
+ pts = reordered_pts;
+ else
+ pts = dts;
+
+ return pts;
+}
+
+
#if FF_API_VIDEO_OLD
int attribute_align_arg avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture,
int *got_picture_ptr,
@@ -643,6 +681,9 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi
emms_c(); //needed to avoid an emms_c() call before every return;
picture->pkt_dts= avpkt->dts;
+ picture->best_effort_timestamp = guess_correct_pts(avctx,
+ picture->pkt_pts,
+ picture->pkt_dts);
if (*got_picture_ptr)
avctx->frame_number++;