Signed-off-by: Nicolas George <nicolas.george@normalesup.org>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
... | ... |
@@ -749,33 +749,6 @@ int read_file(const char *filename, char **bufptr, size_t *size) |
749 | 749 |
return 0; |
750 | 750 |
} |
751 | 751 |
|
752 |
-void init_pts_correction(PtsCorrectionContext *ctx) |
|
753 |
-{ |
|
754 |
- ctx->num_faulty_pts = ctx->num_faulty_dts = 0; |
|
755 |
- ctx->last_pts = ctx->last_dts = INT64_MIN; |
|
756 |
-} |
|
757 |
- |
|
758 |
-int64_t guess_correct_pts(PtsCorrectionContext *ctx, int64_t reordered_pts, int64_t dts) |
|
759 |
-{ |
|
760 |
- int64_t pts = AV_NOPTS_VALUE; |
|
761 |
- |
|
762 |
- if (dts != AV_NOPTS_VALUE) { |
|
763 |
- ctx->num_faulty_dts += dts <= ctx->last_dts; |
|
764 |
- ctx->last_dts = dts; |
|
765 |
- } |
|
766 |
- if (reordered_pts != AV_NOPTS_VALUE) { |
|
767 |
- ctx->num_faulty_pts += reordered_pts <= ctx->last_pts; |
|
768 |
- ctx->last_pts = reordered_pts; |
|
769 |
- } |
|
770 |
- if ((ctx->num_faulty_pts<=ctx->num_faulty_dts || dts == AV_NOPTS_VALUE) |
|
771 |
- && reordered_pts != AV_NOPTS_VALUE) |
|
772 |
- pts = reordered_pts; |
|
773 |
- else |
|
774 |
- pts = dts; |
|
775 |
- |
|
776 |
- return pts; |
|
777 |
-} |
|
778 |
- |
|
779 | 752 |
FILE *get_preset_file(char *filename, size_t filename_size, |
780 | 753 |
const char *preset_name, int is_path, const char *codec_name) |
781 | 754 |
{ |
... | ... |
@@ -235,30 +235,6 @@ int read_yesno(void); |
235 | 235 |
*/ |
236 | 236 |
int read_file(const char *filename, char **bufptr, size_t *size); |
237 | 237 |
|
238 |
-typedef struct { |
|
239 |
- int64_t num_faulty_pts; /// Number of incorrect PTS values so far |
|
240 |
- int64_t num_faulty_dts; /// Number of incorrect DTS values so far |
|
241 |
- int64_t last_pts; /// PTS of the last frame |
|
242 |
- int64_t last_dts; /// DTS of the last frame |
|
243 |
-} PtsCorrectionContext; |
|
244 |
- |
|
245 |
-/** |
|
246 |
- * Reset the state of the PtsCorrectionContext. |
|
247 |
- */ |
|
248 |
-void init_pts_correction(PtsCorrectionContext *ctx); |
|
249 |
- |
|
250 |
-/** |
|
251 |
- * Attempt to guess proper monotonic timestamps for decoded video frames |
|
252 |
- * which might have incorrect times. Input timestamps may wrap around, in |
|
253 |
- * which case the output will as well. |
|
254 |
- * |
|
255 |
- * @param pts the pts field of the decoded AVPacket, as passed through |
|
256 |
- * AVCodecContext.reordered_opaque |
|
257 |
- * @param dts the dts field of the decoded AVPacket |
|
258 |
- * @return one of the input values, may be AV_NOPTS_VALUE |
|
259 |
- */ |
|
260 |
-int64_t guess_correct_pts(PtsCorrectionContext *ctx, int64_t pts, int64_t dts); |
|
261 |
- |
|
262 | 238 |
/** |
263 | 239 |
* Get a file corresponding to a preset file. |
264 | 240 |
* |
... | ... |
@@ -320,7 +320,6 @@ typedef struct AVInputStream { |
320 | 320 |
int64_t next_pts; /* synthetic pts for cases where pkt.pts |
321 | 321 |
is not defined */ |
322 | 322 |
int64_t pts; /* current pts */ |
323 |
- PtsCorrectionContext pts_ctx; |
|
324 | 323 |
int is_start; /* is 1 at the start and after a discontinuity */ |
325 | 324 |
int showed_multi_packet_warning; |
326 | 325 |
int is_past_recording_time; |
... | ... |
@@ -1561,7 +1560,7 @@ static int output_packet(AVInputStream *ist, int ist_index, |
1561 | 1561 |
/* no picture yet */ |
1562 | 1562 |
goto discard_packet; |
1563 | 1563 |
} |
1564 |
- ist->next_pts = ist->pts = guess_correct_pts(&ist->pts_ctx, picture.pkt_pts, picture.pkt_dts); |
|
1564 |
+ ist->next_pts = ist->pts = picture.best_effort_timestamp; |
|
1565 | 1565 |
if (ist->st->codec->time_base.num != 0) { |
1566 | 1566 |
int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame; |
1567 | 1567 |
ist->next_pts += ((int64_t)AV_TIME_BASE * |
... | ... |
@@ -2364,7 +2363,6 @@ static int transcode(AVFormatContext **output_files, |
2364 | 2364 |
st= ist->st; |
2365 | 2365 |
ist->pts = st->avg_frame_rate.num ? - st->codec->has_b_frames*AV_TIME_BASE / av_q2d(st->avg_frame_rate) : 0; |
2366 | 2366 |
ist->next_pts = AV_NOPTS_VALUE; |
2367 |
- init_pts_correction(&ist->pts_ctx); |
|
2368 | 2367 |
ist->is_start = 1; |
2369 | 2368 |
} |
2370 | 2369 |
|
... | ... |
@@ -208,8 +208,6 @@ typedef struct VideoState { |
208 | 208 |
char filename[1024]; |
209 | 209 |
int width, height, xleft, ytop; |
210 | 210 |
|
211 |
- PtsCorrectionContext pts_ctx; |
|
212 |
- |
|
213 | 211 |
#if CONFIG_AVFILTER |
214 | 212 |
AVFilterContext *out_video_filter; ///<the last filter in the video chain |
215 | 213 |
#endif |
... | ... |
@@ -1286,7 +1284,7 @@ retry: |
1286 | 1286 |
if (is->audio_st && is->video_st) |
1287 | 1287 |
av_diff = get_audio_clock(is) - get_video_clock(is); |
1288 | 1288 |
printf("%7.2f A-V:%7.3f s:%3.1f aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r", |
1289 |
- get_master_clock(is), av_diff, FFMAX(is->skip_frames-1, 0), aqsize / 1024, vqsize / 1024, sqsize, is->pts_ctx.num_faulty_dts, is->pts_ctx.num_faulty_pts); |
|
1289 |
+ get_master_clock(is), av_diff, FFMAX(is->skip_frames-1, 0), aqsize / 1024, vqsize / 1024, sqsize, is->video_st->codec->pts_correction_num_faulty_dts, is->video_st->codec->pts_correction_num_faulty_pts); |
|
1290 | 1290 |
fflush(stdout); |
1291 | 1291 |
last_time = cur_time; |
1292 | 1292 |
} |
... | ... |
@@ -1561,7 +1559,6 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke |
1561 | 1561 |
is->video_current_pos = -1; |
1562 | 1562 |
SDL_UnlockMutex(is->pictq_mutex); |
1563 | 1563 |
|
1564 |
- init_pts_correction(&is->pts_ctx); |
|
1565 | 1564 |
is->frame_last_pts = AV_NOPTS_VALUE; |
1566 | 1565 |
is->frame_last_delay = 0; |
1567 | 1566 |
is->frame_timer = (double)av_gettime() / 1000000.0; |
... | ... |
@@ -1576,7 +1573,7 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke |
1576 | 1576 |
|
1577 | 1577 |
if (got_picture) { |
1578 | 1578 |
if (decoder_reorder_pts == -1) { |
1579 |
- *pts = guess_correct_pts(&is->pts_ctx, frame->pkt_pts, frame->pkt_dts); |
|
1579 |
+ *pts = frame->best_effort_timestamp; |
|
1580 | 1580 |
} else if (decoder_reorder_pts) { |
1581 | 1581 |
*pts = frame->pkt_pts; |
1582 | 1582 |
} else { |
... | ... |
@@ -1026,6 +1026,13 @@ typedef struct AVPanScan{ |
1026 | 1026 |
* - decoding: Read by user.\ |
1027 | 1027 |
*/\ |
1028 | 1028 |
int64_t pkt_dts;\ |
1029 |
+\ |
|
1030 |
+ /**\ |
|
1031 |
+ * frame timestamp estimated using various heuristics, in stream time base\ |
|
1032 |
+ * - encoding: unused\ |
|
1033 |
+ * - decoding: set by libavcodec, read by user.\ |
|
1034 |
+ */\ |
|
1035 |
+ int64_t best_effort_timestamp;\ |
|
1029 | 1036 |
|
1030 | 1037 |
|
1031 | 1038 |
#define FF_QSCALE_TYPE_MPEG1 0 |
... | ... |
@@ -2825,6 +2832,17 @@ typedef struct AVCodecContext { |
2825 | 2825 |
* - encoding: unused |
2826 | 2826 |
*/ |
2827 | 2827 |
AVPacket *pkt; |
2828 |
+ |
|
2829 |
+ /** |
|
2830 |
+ * Current statistics for PTS correction. |
|
2831 |
+ * - decoding: maintained and used by libavcodec |
|
2832 |
+ * - encoding: unused |
|
2833 |
+ */ |
|
2834 |
+ int64_t pts_correction_num_faulty_pts; /// Number of incorrect PTS values so far |
|
2835 |
+ int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far |
|
2836 |
+ int64_t pts_correction_last_pts; /// PTS of the last frame |
|
2837 |
+ int64_t pts_correction_last_dts; /// DTS of the last frame |
|
2838 |
+ |
|
2828 | 2839 |
} AVCodecContext; |
2829 | 2840 |
|
2830 | 2841 |
/** |
... | ... |
@@ -448,7 +448,7 @@ enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum |
448 | 448 |
void avcodec_get_frame_defaults(AVFrame *pic){ |
449 | 449 |
memset(pic, 0, sizeof(AVFrame)); |
450 | 450 |
|
451 |
- pic->pts= AV_NOPTS_VALUE; |
|
451 |
+ pic->pts = pic->best_effort_timestamp = AV_NOPTS_VALUE; |
|
452 | 452 |
pic->key_frame= 1; |
453 | 453 |
} |
454 | 454 |
|
... | ... |
@@ -538,6 +538,11 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) |
538 | 538 |
goto free_and_end; |
539 | 539 |
} |
540 | 540 |
|
541 |
+ avctx->pts_correction_num_faulty_pts = |
|
542 |
+ avctx->pts_correction_num_faulty_dts = 0; |
|
543 |
+ avctx->pts_correction_last_pts = |
|
544 |
+ avctx->pts_correction_last_dts = INT64_MIN; |
|
545 |
+ |
|
541 | 546 |
if(avctx->codec->init){ |
542 | 547 |
ret = avctx->codec->init(avctx); |
543 | 548 |
if (ret < 0) { |
... | ... |
@@ -608,6 +613,39 @@ int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, |
608 | 608 |
return ret; |
609 | 609 |
} |
610 | 610 |
|
611 |
+/** |
|
612 |
+ * Attempt to guess proper monotonic timestamps for decoded video frames |
|
613 |
+ * which might have incorrect times. Input timestamps may wrap around, in |
|
614 |
+ * which case the output will as well. |
|
615 |
+ * |
|
616 |
+ * @param pts the pts field of the decoded AVPacket, as passed through |
|
617 |
+ * AVFrame.pkt_pts |
|
618 |
+ * @param dts the dts field of the decoded AVPacket |
|
619 |
+ * @return one of the input values, may be AV_NOPTS_VALUE |
|
620 |
+ */ |
|
621 |
+static int64_t guess_correct_pts(AVCodecContext *ctx, |
|
622 |
+ int64_t reordered_pts, int64_t dts) |
|
623 |
+{ |
|
624 |
+ int64_t pts = AV_NOPTS_VALUE; |
|
625 |
+ |
|
626 |
+ if (dts != AV_NOPTS_VALUE) { |
|
627 |
+ ctx->pts_correction_num_faulty_dts += dts <= ctx->pts_correction_last_dts; |
|
628 |
+ ctx->pts_correction_last_dts = dts; |
|
629 |
+ } |
|
630 |
+ if (reordered_pts != AV_NOPTS_VALUE) { |
|
631 |
+ ctx->pts_correction_num_faulty_pts += reordered_pts <= ctx->pts_correction_last_pts; |
|
632 |
+ ctx->pts_correction_last_pts = reordered_pts; |
|
633 |
+ } |
|
634 |
+ if ((ctx->pts_correction_num_faulty_pts<=ctx->pts_correction_num_faulty_dts || dts == AV_NOPTS_VALUE) |
|
635 |
+ && reordered_pts != AV_NOPTS_VALUE) |
|
636 |
+ pts = reordered_pts; |
|
637 |
+ else |
|
638 |
+ pts = dts; |
|
639 |
+ |
|
640 |
+ return pts; |
|
641 |
+} |
|
642 |
+ |
|
643 |
+ |
|
611 | 644 |
#if FF_API_VIDEO_OLD |
612 | 645 |
int attribute_align_arg avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture, |
613 | 646 |
int *got_picture_ptr, |
... | ... |
@@ -643,6 +681,9 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi |
643 | 643 |
emms_c(); //needed to avoid an emms_c() call before every return; |
644 | 644 |
|
645 | 645 |
picture->pkt_dts= avpkt->dts; |
646 |
+ picture->best_effort_timestamp = guess_correct_pts(avctx, |
|
647 |
+ picture->pkt_pts, |
|
648 |
+ picture->pkt_dts); |
|
646 | 649 |
|
647 | 650 |
if (*got_picture_ptr) |
648 | 651 |
avctx->frame_number++; |