Ticket #8825: 0001-avformat-webvttdec-Add-support-for-HLS-WebVTT-MPEG-t.patch

File 0001-avformat-webvttdec-Add-support-for-HLS-WebVTT-MPEG-t.patch, 4.2 KB (added by giwiniswut, 6 years ago)

The original patch by Franklin Phillips <​​franklinphillips@gmx.com> applied to the current master.

  • libavformat/webvttdec.c

    From fa10332596c499454cc2df440ee6d82560a45cb5 Mon Sep 17 00:00:00 2001
    From: Franklin Phillips <franklinphillips@gmx.com>
    Date: Tue, 5 Jan 2021 03:38:01 +0100
    Subject: [PATCH 1/3] avformat/webvttdec: Add support for HLS WebVTT MPEG
     timestamp map
    
    ---
     libavformat/webvttdec.c | 46 ++++++++++++++++++++++++++++++++++++++++-
     1 file changed, 45 insertions(+), 1 deletion(-)
    
    diff --git a/libavformat/webvttdec.c b/libavformat/webvttdec.c
    index 8d2fdfed37..3e71517509 100644
    a b typedef struct {  
    3535    const AVClass *class;
    3636    FFDemuxSubtitlesQueue q;
    3737    int kind;
     38    int prefer_hls_mpegts_pts;
    3839} WebVTTContext;
    3940
    4041static int webvtt_probe(const AVProbeData *p)
    … … static int webvtt_probe(const AVProbeData *p)  
    4950    return 0;
    5051}
    5152
     53static int64_t convert_to_hls_mpegts_ts(int64_t timestamp, int64_t offset)
     54{
     55    return (timestamp * 90 + offset) & ((1LL << 33) - 1);
     56}
     57
    5258static int64_t read_ts(const char *s)
    5359{
    5460    int hh, mm, ss, ms;
    … … static int webvtt_read_header(AVFormatContext *s)  
    6369    AVBPrint cue;
    6470    int res = 0;
    6571    AVStream *st = avformat_new_stream(s, NULL);
     72    int has_hls_timestamp_map = 0;
     73    int64_t hls_ts_offset;
    6674
    6775    if (!st)
    6876        return AVERROR(ENOMEM);
    … … static int webvtt_read_header(AVFormatContext *s)  
    92100        /* ignore header chunk */
    93101        if (!strncmp(p, "\xEF\xBB\xBFWEBVTT", 9) ||
    94102            !strncmp(p, "WEBVTT", 6) ||
    95             !strncmp(p, "NOTE", 4))
     103            !strncmp(p, "NOTE", 4)) {
     104
     105            if (webvtt->prefer_hls_mpegts_pts) {
     106                /*
     107                * WebVTT files in HLS streams contain a timestamp offset for
     108                * syncing with the main stream:
     109                *
     110                * X-TIMESTAMP-MAP=LOCAL:00:00:00.000,MPEGTS:900000
     111                * (LOCAL and MPEGTS can be reversed even though HLS spec
     112                *  does not say so)
     113                */
     114
     115                char *hls_timestamp_map = strstr(p, "\nX-TIMESTAMP-MAP=");
     116                if (hls_timestamp_map) {
     117                    char *native_str = strstr(hls_timestamp_map, "LOCAL:");
     118                    char *mpegts_str = strstr(hls_timestamp_map, "MPEGTS:");
     119                    if (native_str && mpegts_str) {
     120                        int64_t native_ts = read_ts(native_str + 6);
     121                        int64_t mpegts_ts = strtoll(mpegts_str + 7, NULL, 10);
     122
     123                        if (native_ts != AV_NOPTS_VALUE) {
     124                            hls_ts_offset = mpegts_ts - native_ts * 90;
     125                            has_hls_timestamp_map = 1;
     126                            avpriv_set_pts_info(st, 33, 1, 90000);
     127                        }
     128                    }
     129                }
     130            }
     131
    96132            continue;
     133        }
    97134
    98135        /* optional cue identifier (can be a number like in SRT or some kind of
    99136         * chaptering id) */
    … … static int webvtt_read_header(AVFormatContext *s)  
    124161        if ((ts_end = read_ts(p)) == AV_NOPTS_VALUE)
    125162            break;
    126163
     164        if (has_hls_timestamp_map) {
     165            /* convert and truncate to MPEG TS timestamps */
     166            ts_start = convert_to_hls_mpegts_ts(ts_start, hls_ts_offset);
     167            ts_end = convert_to_hls_mpegts_ts(ts_end, hls_ts_offset);
     168        }
     169
    127170        /* optional cue settings */
    128171        p += strcspn(p, "\n\r\t ");
    129172        while (*p == '\t' || *p == ' ')
    … … static const AVOption options[] = {  
    200243        { "captions",     "WebVTT captions kind",     0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS },     INT_MIN, INT_MAX, KIND_FLAGS, "webvtt_kind" },
    201244        { "descriptions", "WebVTT descriptions kind", 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS }, INT_MIN, INT_MAX, KIND_FLAGS, "webvtt_kind" },
    202245        { "metadata",     "WebVTT metadata kind",     0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA },     INT_MIN, INT_MAX, KIND_FLAGS, "webvtt_kind" },
     246    { "prefer_hls_mpegts_pts", "Use WebVTT embedded HLS MPEGTS timestamps if available.", OFFSET(prefer_hls_mpegts_pts), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM },
    203247    { NULL }
    204248};
    205249