Originally committed as revision 25241 to svn://svn.ffmpeg.org/ffmpeg/trunk
| ... | ... |
@@ -677,3 +677,30 @@ int read_file(const char *filename, char **bufptr, size_t *size) |
| 677 | 677 |
fclose(f); |
| 678 | 678 |
return 0; |
| 679 | 679 |
} |
| 680 |
+ |
|
| 681 |
+void init_pts_correction(PtsCorrectionContext *ctx) |
|
| 682 |
+{
|
|
| 683 |
+ ctx->num_faulty_pts = ctx->num_faulty_dts = 0; |
|
| 684 |
+ ctx->last_pts = ctx->last_dts = INT64_MIN; |
|
| 685 |
+} |
|
| 686 |
+ |
|
| 687 |
+int64_t guess_correct_pts(PtsCorrectionContext *ctx, int64_t reordered_pts, int64_t dts) |
|
| 688 |
+{
|
|
| 689 |
+ int64_t pts = AV_NOPTS_VALUE; |
|
| 690 |
+ |
|
| 691 |
+ if (dts != AV_NOPTS_VALUE) {
|
|
| 692 |
+ ctx->num_faulty_dts += dts <= ctx->last_dts; |
|
| 693 |
+ ctx->last_dts = dts; |
|
| 694 |
+ } |
|
| 695 |
+ if (reordered_pts != AV_NOPTS_VALUE) {
|
|
| 696 |
+ ctx->num_faulty_pts += reordered_pts <= ctx->last_pts; |
|
| 697 |
+ ctx->last_pts = reordered_pts; |
|
| 698 |
+ } |
|
| 699 |
+ if ((ctx->num_faulty_pts<ctx->num_faulty_dts || dts == AV_NOPTS_VALUE) |
|
| 700 |
+ && reordered_pts != AV_NOPTS_VALUE) |
|
| 701 |
+ pts = reordered_pts; |
|
| 702 |
+ else |
|
| 703 |
+ pts = dts; |
|
| 704 |
+ |
|
| 705 |
+ return pts; |
|
| 706 |
+} |
| ... | ... |
@@ -226,4 +226,28 @@ int read_yesno(void); |
| 226 | 226 |
*/ |
| 227 | 227 |
int read_file(const char *filename, char **bufptr, size_t *size); |
| 228 | 228 |
|
| 229 |
+typedef struct {
|
|
| 230 |
+ int64_t num_faulty_pts; /// Number of incorrect PTS values so far |
|
| 231 |
+ int64_t num_faulty_dts; /// Number of incorrect DTS values so far |
|
| 232 |
+ int64_t last_pts; /// PTS of the last frame |
|
| 233 |
+ int64_t last_dts; /// DTS of the last frame |
|
| 234 |
+} PtsCorrectionContext; |
|
| 235 |
+ |
|
| 236 |
+/** |
|
| 237 |
+ * Resets the state of the PtsCorrectionContext. |
|
| 238 |
+ */ |
|
| 239 |
+void init_pts_correction(PtsCorrectionContext *ctx); |
|
| 240 |
+ |
|
| 241 |
+/** |
|
| 242 |
+ * Attempts to guess proper monotonic timestamps for decoded video frames |
|
| 243 |
+ * which might have incorrect times. Input timestamps may wrap around, in |
|
| 244 |
+ * which case the output will as well. |
|
| 245 |
+ * |
|
| 246 |
+ * @param pts The pts field of the decoded AVPacket, as passed through |
|
| 247 |
+ * AVCodecContext.reordered_opaque |
|
| 248 |
+ * @param dts The dts field of the decoded AVPacket |
|
| 249 |
+ * @return One of the input values. May be AV_NOPTS_VALUE. |
|
| 250 |
+ */ |
|
| 251 |
+int64_t guess_correct_pts(PtsCorrectionContext *ctx, int64_t pts, int64_t dts); |
|
| 252 |
+ |
|
| 229 | 253 |
#endif /* FFMPEG_CMDUTILS_H */ |
| ... | ... |
@@ -207,10 +207,7 @@ typedef struct VideoState {
|
| 207 | 207 |
char filename[1024]; |
| 208 | 208 |
int width, height, xleft, ytop; |
| 209 | 209 |
|
| 210 |
- int64_t faulty_pts; |
|
| 211 |
- int64_t faulty_dts; |
|
| 212 |
- int64_t last_dts_for_fault_detection; |
|
| 213 |
- int64_t last_pts_for_fault_detection; |
|
| 210 |
+ PtsCorrectionContext pts_ctx; |
|
| 214 | 211 |
|
| 215 | 212 |
#if CONFIG_AVFILTER |
| 216 | 213 |
AVFilterContext *out_video_filter; ///<the last filter in the video chain |
| ... | ... |
@@ -1286,7 +1283,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->faulty_dts, is->faulty_pts); |
|
| 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); |
|
| 1290 | 1290 |
fflush(stdout); |
| 1291 | 1291 |
last_time = cur_time; |
| 1292 | 1292 |
} |
| ... | ... |
@@ -1565,8 +1562,7 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke |
| 1565 | 1565 |
is->video_current_pos= -1; |
| 1566 | 1566 |
SDL_UnlockMutex(is->pictq_mutex); |
| 1567 | 1567 |
|
| 1568 |
- is->last_dts_for_fault_detection= |
|
| 1569 |
- is->last_pts_for_fault_detection= INT64_MIN; |
|
| 1568 |
+ init_pts_correction(&is->pts_ctx); |
|
| 1570 | 1569 |
is->frame_last_pts= AV_NOPTS_VALUE; |
| 1571 | 1570 |
is->frame_last_delay = 0; |
| 1572 | 1571 |
is->frame_timer = (double)av_gettime() / 1000000.0; |
| ... | ... |
@@ -1583,26 +1579,19 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke |
| 1583 | 1583 |
pkt); |
| 1584 | 1584 |
|
| 1585 | 1585 |
if (got_picture) {
|
| 1586 |
- if(pkt->dts != AV_NOPTS_VALUE){
|
|
| 1587 |
- is->faulty_dts += pkt->dts <= is->last_dts_for_fault_detection; |
|
| 1588 |
- is->last_dts_for_fault_detection= pkt->dts; |
|
| 1586 |
+ if (decoder_reorder_pts == -1) {
|
|
| 1587 |
+ *pts = guess_correct_pts(&is->pts_ctx, frame->reordered_opaque, pkt->dts); |
|
| 1588 |
+ } else if (decoder_reorder_pts) {
|
|
| 1589 |
+ *pts = frame->reordered_opaque; |
|
| 1590 |
+ } else {
|
|
| 1591 |
+ *pts = pkt->dts; |
|
| 1589 | 1592 |
} |
| 1590 |
- if(frame->reordered_opaque != AV_NOPTS_VALUE){
|
|
| 1591 |
- is->faulty_pts += frame->reordered_opaque <= is->last_pts_for_fault_detection; |
|
| 1592 |
- is->last_pts_for_fault_detection= frame->reordered_opaque; |
|
| 1593 |
+ |
|
| 1594 |
+ if (*pts == AV_NOPTS_VALUE) {
|
|
| 1595 |
+ *pts = 0; |
|
| 1593 | 1596 |
} |
| 1594 | 1597 |
} |
| 1595 | 1598 |
|
| 1596 |
- if( ( decoder_reorder_pts==1 |
|
| 1597 |
- || (decoder_reorder_pts && is->faulty_pts<is->faulty_dts) |
|
| 1598 |
- || pkt->dts == AV_NOPTS_VALUE) |
|
| 1599 |
- && frame->reordered_opaque != AV_NOPTS_VALUE) |
|
| 1600 |
- *pts= frame->reordered_opaque; |
|
| 1601 |
- else if(pkt->dts != AV_NOPTS_VALUE) |
|
| 1602 |
- *pts= pkt->dts; |
|
| 1603 |
- else |
|
| 1604 |
- *pts= 0; |
|
| 1605 |
- |
|
| 1606 | 1599 |
// if (len1 < 0) |
| 1607 | 1600 |
// break; |
| 1608 | 1601 |
if (got_picture){
|