| @@ -28,6 +28,7 @@ · 27 unmodified lines |
| 28 | #include <ass/ass.h> | 28 | #include <ass/ass.h> |
| 29 | #include <libavutil/avstring.h> | 29 | #include <libavutil/avstring.h> |
| 30 | #include <libavutil/common.h> | 30 | #include <libavutil/common.h> |
| | 31 | #include <libavutil/timecode.h> |
| 31 | | 32 | |
| 32 | #include "mpv_talloc.h" | 33 | #include "mpv_talloc.h" |
| 33 | #include "client.h" | 34 | #include "client.h" |
| @@ -2524,11 +2525,40 @@ static int mp_property_video_frame_info(void *ctx, struct m_property *prop, · 2490 unmodified lines |
| 2524 | const char *pict_type = f->pict_type >= 1 && f->pict_type <= 3 | 2525 | const char *pict_type = f->pict_type >= 1 && f->pict_type <= 3 |
| 2525 | ? pict_types[f->pict_type] : NULL; | 2526 | ? pict_types[f->pict_type] : NULL; |
| 2526 | | 2527 | |
| | 2528 | char gop_tc[AV_TIMECODE_STR_SIZE] = {0}; |
| | 2529 | char s12m_tc[AV_TIMECODE_STR_SIZE] = {0}; |
| | 2530 | for (int n = 0; n < f->num_ff_side_data; n++) { |
| | 2531 | |
| | 2532 | struct mp_ff_side_data *mpsd = &f->ff_side_data[n]; |
| | 2533 | if (mpsd->type == AV_FRAME_DATA_GOP_TIMECODE) |
| | 2534 | av_timecode_make_mpeg_tc_string(gop_tc, *(int64_t*)(mpsd->buf->data)); |
| | 2535 | if (mpctx->vo_chain && mpsd->type == AV_FRAME_DATA_S12M_TIMECODE) { |
| | 2536 | av_timecode_make_smpte_tc_string2(s12m_tc, |
| | 2537 | av_d2q(mpctx->vo_chain->filter->container_fps, INT_MAX), |
| | 2538 | *(uint32_t*)(mpsd->buf->data), 0, 0); |
| | 2539 | } |
| | 2540 | } |
| | 2541 | |
| | 2542 | char approx_smpte[AV_TIMECODE_STR_SIZE] = {0}; |
| | 2543 | if (s12m_tc[0] == '\0' && mpctx->vo_chain) { |
| | 2544 | const AVTimecode tcr = { |
| | 2545 | .start = 0, |
| | 2546 | .flags = AV_TIMECODE_FLAG_DROPFRAME, |
| | 2547 | .rate = av_d2q(mpctx->vo_chain->filter->container_fps, INT_MAX), |
| | 2548 | .fps = lrint(mpctx->vo_chain->filter->container_fps), |
| | 2549 | }; |
| | 2550 | int frame = lrint(get_current_pos_ratio(mpctx, false) * get_frame_count(mpctx)); |
| | 2551 | av_timecode_make_string(&tcr, approx_smpte, frame); |
| | 2552 | } |
| | 2553 | |
| 2527 | struct m_sub_property props[] = { | 2554 | struct m_sub_property props[] = { |
| 2528 | {"picture-type", SUB_PROP_STR(pict_type), .unavailable = !pict_type}, | 2555 | {"picture-type", SUB_PROP_STR(pict_type), .unavailable = !pict_type}, |
| 2529 | {"interlaced", SUB_PROP_BOOL(!!(f->fields & MP_IMGFIELD_INTERLACED))}, | 2556 | {"interlaced", SUB_PROP_BOOL(!!(f->fields & MP_IMGFIELD_INTERLACED))}, |
| 2530 | {"tff", SUB_PROP_BOOL(!!(f->fields & MP_IMGFIELD_TOP_FIRST))}, | 2557 | {"tff", SUB_PROP_BOOL(!!(f->fields & MP_IMGFIELD_TOP_FIRST))}, |
| 2531 | {"repeat", SUB_PROP_BOOL(!!(f->fields & MP_IMGFIELD_REPEAT_FIRST))}, | 2558 | {"repeat", SUB_PROP_BOOL(!!(f->fields & MP_IMGFIELD_REPEAT_FIRST))}, |
| | 2559 | {"gop-timecode", SUB_PROP_STR(gop_tc), .unavailable = gop_tc[0] == '\0'}, |
| | 2560 | {"smpte-timecode", SUB_PROP_STR(s12m_tc), .unavailable = s12m_tc[0] == '\0'}, |
| | 2561 | {"estimated-smpte-timecode", SUB_PROP_STR(approx_smpte), .unavailable = approx_smpte[0] == '\0'}, |
| 2532 | {0} | 2562 | {0} |
| 2533 | }; | 2563 | }; |
| 2534 | | 2564 | |