---
avconv.c | 11 +++++------
libavcodec/internal.h | 14 ++++++++++++++
libavcodec/utils.c | 15 +++++++++++++++
3 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/avconv.c b/avconv.c
index a1efce2..6a72af5 100644
--- a/avconv.c
+++ b/avconv.c
@@ -1105,15 +1105,14 @@ static int decode_audio(InputStream *ist, AVPacket
*pkt, int *got_output)
return ret;
}
- /* if the decoder provides a pts, use it instead of the last packet pts.
- the decoder could be delaying output by a packet or more. */
+ /* If the decoder provides a pts, use it instead of the last packet pts.
+ Libavcodec can interpolate timestamps for multiple frames in the same
+ packet. Also, the decoder could be delaying output. */
if (decoded_frame->pts != AV_NOPTS_VALUE)
ist->next_dts = av_rescale_q(decoded_frame->pts, avctx->time_base,
AV_TIME_BASE_Q);
- else if (pkt->pts != AV_NOPTS_VALUE) {
- decoded_frame->pts = pkt->pts;
- pkt->pts = AV_NOPTS_VALUE;
- }
+ pkt->pts = AV_NOPTS_VALUE;
+
if (ist->next_dts != AV_NOPTS_VALUE)
ist->next_dts += av_rescale_q(decoded_frame->nb_samples,
avctx->time_base,
AV_TIME_BASE_Q);
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 0bfc924..d03c256 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -76,6 +76,20 @@ typedef struct AVCodecInternal {
* padded with silence. Reject all subsequent frames.
*/
int last_audio_frame;
+
+ /**
+ * pts of the last packet passed to the decoder (audio only)
+ * This is used to detect duplicate pts for timestamp interpolation.
+ * It is reset to AV_NOPTS_VALUE on flush.
+ */
+ int64_t last_pts;
+
+ /**
+ * Interpolated pts for the next decoded frame (audio only).
+ * This is used when there are multiple frames per packet or duplicate pts
+ * in subsequent packets.
+ */
+ int64_t next_pts;
} AVCodecInternal;
struct AVCodecDefault {
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index cb386a6..1b8cf38 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -716,6 +716,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext
*avctx, const AVCodec *code
ret = AVERROR(ENOMEM);
goto end;
}
+ avctx->internal->last_pts = avctx->internal->next_pts = AV_NOPTS_VALUE;
if (codec->priv_data_size > 0) {
if (!avctx->priv_data) {
@@ -1387,10 +1388,23 @@ int attribute_align_arg
avcodec_decode_audio4(AVCodecContext *avctx,
if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size) {
ret = avctx->codec->decode(avctx, frame, got_frame_ptr, avpkt);
if (ret >= 0 && *got_frame_ptr) {
+ AVCodecInternal *avci = avctx->internal;
+
avctx->frame_number++;
frame->pkt_dts = avpkt->dts;
if (frame->format == AV_SAMPLE_FMT_NONE)
frame->format = avctx->sample_fmt;
+
+ /* timestamp interpolation */
+ if (frame->pts == AV_NOPTS_VALUE) {
+ if (avpkt->pts == AV_NOPTS_VALUE || avci->last_pts ==
avpkt->pts)
+ frame->pts = avci->next_pts;
+ else
+ frame->pts = avpkt->pts;
+ }
+ if (frame->pts != AV_NOPTS_VALUE)
+ avci->next_pts = frame->pts + frame->nb_samples;
+ avci->last_pts = avpkt->pts;
}
}
@@ -1727,6 +1741,7 @@ void avcodec_flush_buffers(AVCodecContext *avctx)
ff_thread_flush(avctx);
else if (avctx->codec->flush)
avctx->codec->flush(avctx);
+ avctx->internal->last_pts = avctx->internal->next_pts = AV_NOPTS_VALUE;
}
static void video_free_buffers(AVCodecContext *s)
--
1.7.1
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel