hlsenc.c 63.3 KB
Newer Older
L
Luca Barbato 已提交
1 2 3 4
/*
 * Apple HTTP Live Streaming segmenter
 * Copyright (c) 2012, Luca Barbato
 *
5
 * This file is part of FFmpeg.
L
Luca Barbato 已提交
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
L
Luca Barbato 已提交
8 9 10 11
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
L
Luca Barbato 已提交
13 14 15 16 17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
L
Luca Barbato 已提交
19 20 21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

22
#include "config.h"
L
Luca Barbato 已提交
23
#include <float.h>
24
#include <stdint.h>
25 26 27
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
L
Luca Barbato 已提交
28

29 30 31 32 33 34
#if CONFIG_GCRYPT
#include <gcrypt.h>
#elif CONFIG_OPENSSL
#include <openssl/rand.h>
#endif

35
#include "libavutil/avassert.h"
L
Luca Barbato 已提交
36 37 38
#include "libavutil/mathematics.h"
#include "libavutil/parseutils.h"
#include "libavutil/avstring.h"
39 40
#include "libavutil/intreadwrite.h"
#include "libavutil/random_seed.h"
L
Luca Barbato 已提交
41 42
#include "libavutil/opt.h"
#include "libavutil/log.h"
43
#include "libavutil/time_internal.h"
L
Luca Barbato 已提交
44 45

#include "avformat.h"
46
#include "avio_internal.h"
L
Luca Barbato 已提交
47
#include "internal.h"
48
#include "os_support.h"
L
Luca Barbato 已提交
49

50 51 52 53 54 55
typedef enum {
  HLS_START_SEQUENCE_AS_START_NUMBER = 0,
  HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH = 1,
  HLS_START_SEQUENCE_AS_FORMATTED_DATETIME = 2,  // YYYYMMDDhhmmss
} StartSequenceSourceType;

56 57
#define KEYSIZE 16
#define LINE_BUFFER_SIZE 1024
58
#define HLS_MICROSECOND_UNIT   1000000
59

60 61
typedef struct HLSSegment {
    char filename[1024];
62
    char sub_filename[1024];
63
    double duration; /* in seconds */
64
    int discont;
65 66
    int64_t pos;
    int64_t size;
67

68 69 70
    char key_uri[LINE_BUFFER_SIZE + 1];
    char iv_string[KEYSIZE*2 + 1];

71 72
    struct HLSSegment *next;
} HLSSegment;
L
Luca Barbato 已提交
73

74 75 76
typedef enum HLSFlags {
    // Generate a single media file and use byte ranges in the playlist.
    HLS_SINGLE_FILE = (1 << 0),
77
    HLS_DELETE_SEGMENTS = (1 << 1),
78
    HLS_ROUND_DURATIONS = (1 << 2),
79
    HLS_DISCONT_START = (1 << 3),
80
    HLS_OMIT_ENDLIST = (1 << 4),
81
    HLS_SPLIT_BY_TIME = (1 << 5),
82
    HLS_APPEND_LIST = (1 << 6),
83
    HLS_PROGRAM_DATE_TIME = (1 << 7),
84
    HLS_SECOND_LEVEL_SEGMENT_INDEX = (1 << 8), // include segment index in segment filenames when use_localtime  e.g.: %%03d
85 86
    HLS_SECOND_LEVEL_SEGMENT_DURATION = (1 << 9), // include segment duration (microsec) in segment filenames when use_localtime  e.g.: %%09t
    HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size (bytes) in segment filenames when use_localtime  e.g.: %%014s
87
    HLS_TEMP_FILE = (1 << 11),
88 89
} HLSFlags;

90 91 92 93 94
typedef enum {
    SEGMENT_TYPE_MPEGTS,
    SEGMENT_TYPE_FMP4,
} SegmentType;

95 96 97 98 99 100 101
typedef enum {
    PLAYLIST_TYPE_NONE,
    PLAYLIST_TYPE_EVENT,
    PLAYLIST_TYPE_VOD,
    PLAYLIST_TYPE_NB,
} PlaylistType;

L
Luca Barbato 已提交
102 103
typedef struct HLSContext {
    const AVClass *class;  // Class for private options.
104
    unsigned number;
105
    int64_t sequence;
106
    int64_t start_sequence;
107
    uint32_t start_sequence_source_type;  // enum StartSequenceSourceType
L
Luca Barbato 已提交
108
    AVOutputFormat *oformat;
109
    AVOutputFormat *vtt_oformat;
110

L
Luca Barbato 已提交
111
    AVFormatContext *avf;
112
    AVFormatContext *vtt_avf;
113

L
Luca Barbato 已提交
114
    float time;            // Set by a private option.
115
    float init_time;       // Set by a private option.
116
    int max_nb_segments;   // Set by a private option.
117
#if FF_API_HLS_WRAP
L
Luca Barbato 已提交
118
    int  wrap;             // Set by a private option.
119
#endif
120
    uint32_t flags;        // enum HLSFlags
121
    uint32_t pl_type;      // enum PlaylistType
122
    char *segment_filename;
123 124 125
    char *fmp4_init_filename;
    int segment_type;
    int fmp4_init_mode;
126

127
    int use_localtime;      ///< flag to expand filename with localtime
128
    int use_localtime_mkdir;///< flag to mkdir dirname in timebased filename
129
    int allowcache;
L
Luca Barbato 已提交
130 131
    int64_t recording_time;
    int has_video;
132
    int has_subtitle;
133 134
    int new_start;
    double dpp;           // duration per packet
L
Luca Barbato 已提交
135 136
    int64_t start_pts;
    int64_t end_pts;
137
    double duration;      // last segment duration computed so far, in seconds
138 139
    int64_t start_pos;    // last segment starting position
    int64_t size;         // last segment size
140
    int64_t max_seg_size; // every segment file max size
141
    int nb_entries;
142
    int discontinuity_set;
143
    int discontinuity;
144

145 146
    HLSSegment *segments;
    HLSSegment *last_segment;
147
    HLSSegment *old_segments;
148

L
Luca Barbato 已提交
149
    char *basename;
150 151
    char *vtt_basename;
    char *vtt_m3u8_name;
152
    char *baseurl;
liuqi_123's avatar
liuqi_123 已提交
153
    char *format_options_str;
154 155
    char *vtt_format_options_str;
    char *subtitle_filename;
liuqi_123's avatar
liuqi_123 已提交
156
    AVDictionary *format_options;
157

158 159 160 161 162 163
    int encrypt;
    char *key;
    char *key_url;
    char *iv;
    char *key_basename;

164 165 166 167 168
    char *key_info_file;
    char key_file[LINE_BUFFER_SIZE + 1];
    char key_uri[LINE_BUFFER_SIZE + 1];
    char key_string[KEYSIZE*2 + 1];
    char iv_string[KEYSIZE*2 + 1];
169 170
    AVDictionary *vtt_format_options;

171 172
    char *method;

173
    double initial_prog_date_time;
174
    char current_segment_final_filename_fmt[1024]; // when renaming segments
L
Luca Barbato 已提交
175 176
} HLSContext;

177 178 179 180 181
static int get_int_from_double(double val)
{
    return (int)((val - (int)val) >= 0.001) ? (int)(val + 1) : (int)val;
}

182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
static int mkdir_p(const char *path) {
    int ret = 0;
    char *temp = av_strdup(path);
    char *pos = temp;
    char tmp_ch = '\0';

    if (!path || !temp) {
        return -1;
    }

    if (!strncmp(temp, "/", 1) || !strncmp(temp, "\\", 1)) {
        pos++;
    } else if (!strncmp(temp, "./", 2) || !strncmp(temp, ".\\", 2)) {
        pos += 2;
    }

    for ( ; *pos != '\0'; ++pos) {
        if (*pos == '/' || *pos == '\\') {
            tmp_ch = *pos;
            *pos = '\0';
            ret = mkdir(temp, 0755);
            *pos = tmp_ch;
        }
    }

    if ((*(pos - 1) != '/') || (*(pos - 1) != '\\')) {
        ret = mkdir(temp, 0755);
    }

    av_free(temp);
    return ret;
}

215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
static int replace_int_data_in_filename(char *buf, int buf_size, const char *filename, char placeholder, int64_t number)
{
    const char *p;
    char *q, buf1[20], c;
    int nd, len, addchar_count;
    int found_count = 0;

    q = buf;
    p = filename;
    for (;;) {
        c = *p;
        if (c == '\0')
            break;
        if (c == '%' && *(p+1) == '%')  // %%
            addchar_count = 2;
        else if (c == '%' && (av_isdigit(*(p+1)) || *(p+1) == placeholder)) {
            nd = 0;
            addchar_count = 1;
            while (av_isdigit(*(p + addchar_count))) {
                nd = nd * 10 + *(p + addchar_count) - '0';
                addchar_count++;
            }

            if (*(p + addchar_count) == placeholder) {
                len = snprintf(buf1, sizeof(buf1), "%0*"PRId64, (number < 0) ? nd : nd++, number);
                if (len < 1)  // returned error or empty buf1
                    goto fail;
                if ((q - buf + len) > buf_size - 1)
                    goto fail;
                memcpy(q, buf1, len);
                q += len;
                p += (addchar_count + 1);
                addchar_count = 0;
                found_count++;
            }

        } else
            addchar_count = 1;

        while (addchar_count--)
            if ((q - buf) < buf_size - 1)
                *q++ = *p++;
            else
                goto fail;
    }
    *q = '\0';
    return found_count;
fail:
    *q = '\0';
    return -1;
}

267 268 269 270 271 272 273 274 275 276
static void write_styp(AVIOContext *pb)
{
    avio_wb32(pb, 24);
    ffio_wfourcc(pb, "styp");
    ffio_wfourcc(pb, "msdh");
    avio_wb32(pb, 0); /* minor */
    ffio_wfourcc(pb, "msdh");
    ffio_wfourcc(pb, "msix");
}

277
static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls) {
278 279 280

    HLSSegment *segment, *previous_segment = NULL;
    float playlist_duration = 0.0f;
281
    int ret = 0, path_size, sub_path_size;
282 283
    char *dirname = NULL, *p, *sub_path;
    char *path = NULL;
284 285
    AVDictionary *options = NULL;
    AVIOContext *out = NULL;
286
    const char *proto = NULL;
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304

    segment = hls->segments;
    while (segment) {
        playlist_duration += segment->duration;
        segment = segment->next;
    }

    segment = hls->old_segments;
    while (segment) {
        playlist_duration -= segment->duration;
        previous_segment = segment;
        segment = previous_segment->next;
        if (playlist_duration <= -previous_segment->duration) {
            previous_segment->next = NULL;
            break;
        }
    }

305
    if (segment && !hls->use_localtime_mkdir) {
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
        if (hls->segment_filename) {
            dirname = av_strdup(hls->segment_filename);
        } else {
            dirname = av_strdup(hls->avf->filename);
        }
        if (!dirname) {
            ret = AVERROR(ENOMEM);
            goto fail;
        }
        p = (char *)av_basename(dirname);
        *p = '\0';
    }

    while (segment) {
        av_log(hls, AV_LOG_DEBUG, "deleting old segment %s\n",
                                  segment->filename);
322
        path_size =  (hls->use_localtime_mkdir ? 0 : strlen(dirname)) + strlen(segment->filename) + 1;
323 324 325 326 327
        path = av_malloc(path_size);
        if (!path) {
            ret = AVERROR(ENOMEM);
            goto fail;
        }
328

329 330 331 332 333 334 335
        if (hls->use_localtime_mkdir)
            av_strlcpy(path, segment->filename, path_size);
        else { // segment->filename contains basename only
            av_strlcpy(path, dirname, path_size);
            av_strlcat(path, segment->filename, path_size);
        }

336 337
        proto = avio_find_protocol_name(s->filename);
        if (hls->method || (proto && !av_strcasecmp(proto, "http"))) {
338 339 340
            av_dict_set(&options, "method", "DELETE", 0);
            if ((ret = hls->avf->io_open(hls->avf, &out, path, AVIO_FLAG_WRITE, &options)) < 0)
                goto fail;
341
            ff_format_io_close(hls->avf, &out);
342
        } else if (unlink(path) < 0) {
343 344 345
            av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n",
                                     path, strerror(errno));
        }
346

347 348
        if ((segment->sub_filename[0] != '\0')) {
            sub_path_size = strlen(segment->sub_filename) + 1 + (dirname ? strlen(dirname) : 0);
349 350 351 352 353 354 355 356
            sub_path = av_malloc(sub_path_size);
            if (!sub_path) {
                ret = AVERROR(ENOMEM);
                goto fail;
            }

            av_strlcpy(sub_path, dirname, sub_path_size);
            av_strlcat(sub_path, segment->sub_filename, sub_path_size);
357

358
            if (hls->method || (proto && !av_strcasecmp(proto, "http"))) {
359 360 361 362 363
                av_dict_set(&options, "method", "DELETE", 0);
                if ((ret = hls->avf->io_open(hls->avf, &out, sub_path, AVIO_FLAG_WRITE, &options)) < 0) {
                    av_free(sub_path);
                    goto fail;
                }
364
                ff_format_io_close(hls->avf, &out);
365
            } else if (unlink(sub_path) < 0) {
366 367 368 369
                av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n",
                                         sub_path, strerror(errno));
            }
            av_free(sub_path);
370
        }
371
        av_freep(&path);
372 373 374 375 376 377
        previous_segment = segment;
        segment = previous_segment->next;
        av_free(previous_segment);
    }

fail:
378
    av_free(path);
379 380 381 382 383
    av_free(dirname);

    return ret;
}

384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
static int randomize(uint8_t *buf, int len)
{
#if CONFIG_GCRYPT
    gcry_randomize(buf, len, GCRY_VERY_STRONG_RANDOM);
    return 0;
#elif CONFIG_OPENSSL
    if (RAND_bytes(buf, len))
        return 0;
#else
    return AVERROR(ENOSYS);
#endif
    return AVERROR(EINVAL);
}

static int do_encrypt(AVFormatContext *s)
{
    HLSContext *hls = s->priv_data;
    int ret;
    int len;
    AVIOContext *pb;
    uint8_t key[KEYSIZE];

    len = strlen(hls->basename) + 4 + 1;
    hls->key_basename = av_mallocz(len);
    if (!hls->key_basename)
        return AVERROR(ENOMEM);

    av_strlcpy(hls->key_basename, s->filename, len);
    av_strlcat(hls->key_basename, ".key", len);

    if (hls->key_url) {
S
Steven Liu 已提交
415 416
        av_strlcpy(hls->key_file, hls->key_url, sizeof(hls->key_file));
        av_strlcpy(hls->key_uri, hls->key_url, sizeof(hls->key_uri));
417
    } else {
S
Steven Liu 已提交
418 419
        av_strlcpy(hls->key_file, hls->key_basename, sizeof(hls->key_file));
        av_strlcpy(hls->key_uri, hls->key_basename, sizeof(hls->key_uri));
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
    }

    if (!*hls->iv_string) {
        uint8_t iv[16] = { 0 };
        char buf[33];

        if (!hls->iv) {
            AV_WB64(iv + 8, hls->sequence);
        } else {
            memcpy(iv, hls->iv, sizeof(iv));
        }
        ff_data_to_hex(buf, iv, sizeof(iv), 0);
        buf[32] = '\0';
        memcpy(hls->iv_string, buf, sizeof(hls->iv_string));
    }

    if (!*hls->key_uri) {
        av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
        return AVERROR(EINVAL);
    }

    if (!*hls->key_file) {
        av_log(hls, AV_LOG_ERROR, "no key file specified in key info file\n");
        return AVERROR(EINVAL);
    }

    if (!*hls->key_string) {
        if (!hls->key) {
            if ((ret = randomize(key, sizeof(key))) < 0) {
                av_log(s, AV_LOG_ERROR, "Cannot generate a strong random key\n");
                return ret;
            }
        } else {
            memcpy(key, hls->key, sizeof(key));
        }

        ff_data_to_hex(hls->key_string, key, sizeof(key), 0);
        if ((ret = s->io_open(s, &pb, hls->key_file, AVIO_FLAG_WRITE, NULL)) < 0)
            return ret;
        avio_seek(pb, 0, SEEK_CUR);
        avio_write(pb, key, KEYSIZE);
        avio_close(pb);
    }
    return 0;
}


467 468 469 470 471 472 473
static int hls_encryption_start(AVFormatContext *s)
{
    HLSContext *hls = s->priv_data;
    int ret;
    AVIOContext *pb;
    uint8_t key[KEYSIZE];

474
    if ((ret = s->io_open(s, &pb, hls->key_info_file, AVIO_FLAG_READ, NULL)) < 0) {
475 476 477 478 479 480 481 482 483 484 485 486 487 488
        av_log(hls, AV_LOG_ERROR,
                "error opening key info file %s\n", hls->key_info_file);
        return ret;
    }

    ff_get_line(pb, hls->key_uri, sizeof(hls->key_uri));
    hls->key_uri[strcspn(hls->key_uri, "\r\n")] = '\0';

    ff_get_line(pb, hls->key_file, sizeof(hls->key_file));
    hls->key_file[strcspn(hls->key_file, "\r\n")] = '\0';

    ff_get_line(pb, hls->iv_string, sizeof(hls->iv_string));
    hls->iv_string[strcspn(hls->iv_string, "\r\n")] = '\0';

489
    ff_format_io_close(s, &pb);
490 491 492 493 494 495 496 497 498 499 500

    if (!*hls->key_uri) {
        av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
        return AVERROR(EINVAL);
    }

    if (!*hls->key_file) {
        av_log(hls, AV_LOG_ERROR, "no key file specified in key info file\n");
        return AVERROR(EINVAL);
    }

501
    if ((ret = s->io_open(s, &pb, hls->key_file, AVIO_FLAG_READ, NULL)) < 0) {
502 503 504 505 506
        av_log(hls, AV_LOG_ERROR, "error opening key file %s\n", hls->key_file);
        return ret;
    }

    ret = avio_read(pb, key, sizeof(key));
507
    ff_format_io_close(s, &pb);
508 509 510 511 512 513 514 515 516 517 518
    if (ret != sizeof(key)) {
        av_log(hls, AV_LOG_ERROR, "error reading key file %s\n", hls->key_file);
        if (ret >= 0 || ret == AVERROR_EOF)
            ret = AVERROR(EINVAL);
        return ret;
    }
    ff_data_to_hex(hls->key_string, key, sizeof(key), 0);

    return 0;
}

519 520 521 522 523 524 525 526
static int read_chomp_line(AVIOContext *s, char *buf, int maxlen)
{
    int len = ff_get_line(s, buf, maxlen);
    while (len > 0 && av_isspace(buf[len - 1]))
        buf[--len] = '\0';
    return len;
}

L
Luca Barbato 已提交
527 528
static int hls_mux_init(AVFormatContext *s)
{
529
    AVDictionary *options = NULL;
L
Luca Barbato 已提交
530 531
    HLSContext *hls = s->priv_data;
    AVFormatContext *oc;
532
    AVFormatContext *vtt_oc = NULL;
533
    int i, ret;
L
Luca Barbato 已提交
534

535 536 537 538
    ret = avformat_alloc_output_context2(&hls->avf, hls->oformat, NULL, NULL);
    if (ret < 0)
        return ret;
    oc = hls->avf;
L
Luca Barbato 已提交
539

540
    oc->filename[0]        = '\0';
L
Luca Barbato 已提交
541 542
    oc->oformat            = hls->oformat;
    oc->interrupt_callback = s->interrupt_callback;
543
    oc->max_delay          = s->max_delay;
544 545 546
    oc->opaque             = s->opaque;
    oc->io_open            = s->io_open;
    oc->io_close           = s->io_close;
547
    av_dict_copy(&oc->metadata, s->metadata, 0);
L
Luca Barbato 已提交
548

549 550 551 552 553 554 555 556 557
    if(hls->vtt_oformat) {
        ret = avformat_alloc_output_context2(&hls->vtt_avf, hls->vtt_oformat, NULL, NULL);
        if (ret < 0)
            return ret;
        vtt_oc          = hls->vtt_avf;
        vtt_oc->oformat = hls->vtt_oformat;
        av_dict_copy(&vtt_oc->metadata, s->metadata, 0);
    }

L
Luca Barbato 已提交
558 559
    for (i = 0; i < s->nb_streams; i++) {
        AVStream *st;
560
        AVFormatContext *loc;
561
        if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
562 563 564 565 566
            loc = vtt_oc;
        else
            loc = oc;

        if (!(st = avformat_new_stream(loc, NULL)))
L
Luca Barbato 已提交
567
            return AVERROR(ENOMEM);
568
        avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar);
L
Luca Barbato 已提交
569
        st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
570
        st->time_base = s->streams[i]->time_base;
571
        av_dict_copy(&st->metadata, s->streams[i]->metadata, 0);
L
Luca Barbato 已提交
572
    }
573
    hls->start_pos = 0;
574
    hls->new_start = 1;
575
    hls->fmp4_init_mode = 0;
L
Luca Barbato 已提交
576

577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
    if (hls->segment_type == SEGMENT_TYPE_FMP4) {
        hls->fmp4_init_mode = 1;
        if ((ret = s->io_open(s, &oc->pb, hls->fmp4_init_filename, AVIO_FLAG_WRITE, NULL)) < 0) {
            av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", hls->fmp4_init_filename);
            return ret;
        }

        if (hls->format_options_str) {
            ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0);
            if (ret < 0) {
                av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n",
                       hls->format_options_str);
                return ret;
            }
        }

        av_dict_copy(&options, hls->format_options, 0);
        av_dict_set(&options, "fflags", "-autobsf", 0);
        av_dict_set(&options, "movflags", "frag_custom+dash+delay_moov", 0);
        ret = avformat_init_output(oc, &options);
        if (av_dict_count(options)) {
            av_log(s, AV_LOG_ERROR, "Some of the provided format options in '%s' are not recognized\n", hls->format_options_str);
            av_dict_free(&options);
            return AVERROR(EINVAL);
        }
        av_dict_free(&options);
    }
L
Luca Barbato 已提交
604 605 606
    return 0;
}

607 608 609 610 611 612 613 614 615 616
static HLSSegment *find_segment_by_filename(HLSSegment *segment, const char *filename)
{
    while (segment) {
        if (!av_strcasecmp(segment->filename,filename))
            return segment;
        segment = segment->next;
    }
    return (HLSSegment *) NULL;
}

617 618
static int sls_flags_filename_process(struct AVFormatContext *s, HLSContext *hls, HLSSegment *en, double duration,
                                         int64_t pos, int64_t size)
L
Luca Barbato 已提交
619
{
620 621 622 623 624
    if ((hls->flags & (HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION)) &&
        strlen(hls->current_segment_final_filename_fmt)) {
        av_strlcpy(hls->avf->filename, hls->current_segment_final_filename_fmt, sizeof(hls->avf->filename));
        if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) {
            char * filename = av_strdup(hls->avf->filename);  // %%s will be %s after strftime
625 626
            if (!filename) {
                av_free(en);
627
                return AVERROR(ENOMEM);
628
            }
629 630 631 632 633 634 635
            if (replace_int_data_in_filename(hls->avf->filename, sizeof(hls->avf->filename),
                filename, 's', pos + size) < 1) {
                av_log(hls, AV_LOG_ERROR,
                       "Invalid second level segment filename template '%s', "
                        "you can try to remove second_level_segment_size flag\n",
                       filename);
                av_free(filename);
636
                av_free(en);
637 638 639 640 641 642
                return AVERROR(EINVAL);
            }
            av_free(filename);
        }
        if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) {
            char * filename = av_strdup(hls->avf->filename);  // %%t will be %t after strftime
643 644
            if (!filename) {
                av_free(en);
645
                return AVERROR(ENOMEM);
646
            }
647
            if (replace_int_data_in_filename(hls->avf->filename, sizeof(hls->avf->filename),
648
                filename, 't',  (int64_t)round(duration * HLS_MICROSECOND_UNIT)) < 1) {
649 650 651 652 653
                av_log(hls, AV_LOG_ERROR,
                       "Invalid second level segment filename template '%s', "
                        "you can try to remove second_level_segment_time flag\n",
                       filename);
                av_free(filename);
654
                av_free(en);
655 656 657 658 659
                return AVERROR(EINVAL);
            }
            av_free(filename);
        }
    }
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771
    return 0;
}

static int sls_flag_check_duration_size_index(HLSContext *hls)
{
    int ret = 0;

    if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) {
         av_log(hls, AV_LOG_ERROR,
                "second_level_segment_duration hls_flag requires use_localtime to be true\n");
         ret = AVERROR(EINVAL);
    }
    if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) {
         av_log(hls, AV_LOG_ERROR,
                "second_level_segment_size hls_flag requires use_localtime to be true\n");
         ret = AVERROR(EINVAL);
    }
    if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_INDEX) {
        av_log(hls, AV_LOG_ERROR,
               "second_level_segment_index hls_flag requires use_localtime to be true\n");
        ret = AVERROR(EINVAL);
    }

    return ret;
}

static int sls_flag_check_duration_size(HLSContext *hls)
{
    const char *proto = avio_find_protocol_name(hls->basename);
    int segment_renaming_ok = proto && !strcmp(proto, "file");
    int ret = 0;

    if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) && !segment_renaming_ok) {
         av_log(hls, AV_LOG_ERROR,
                "second_level_segment_duration hls_flag works only with file protocol segment names\n");
         ret = AVERROR(EINVAL);
    }
    if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) && !segment_renaming_ok) {
         av_log(hls, AV_LOG_ERROR,
                "second_level_segment_size hls_flag works only with file protocol segment names\n");
         ret = AVERROR(EINVAL);
    }

    return ret;
}

static void sls_flag_file_rename(HLSContext *hls, char *old_filename) {
    if ((hls->flags & (HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION)) &&
        strlen(hls->current_segment_final_filename_fmt)) {
        ff_rename(old_filename, hls->avf->filename, hls);
    }
}

static int sls_flag_use_localtime_filename(AVFormatContext *oc, HLSContext *c)
{
    if (c->flags & HLS_SECOND_LEVEL_SEGMENT_INDEX) {
        char * filename = av_strdup(oc->filename);  // %%d will be %d after strftime
        if (!filename)
            return AVERROR(ENOMEM);
        if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename),
#if FF_API_HLS_WRAP
            filename, 'd', c->wrap ? c->sequence % c->wrap : c->sequence) < 1) {
#else
            filename, 'd', c->sequence) < 1) {
#endif
            av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
                    "you can try to remove second_level_segment_index flag\n",
                   filename);
            av_free(filename);
            return AVERROR(EINVAL);
        }
        av_free(filename);
    }
    if (c->flags & (HLS_SECOND_LEVEL_SEGMENT_SIZE | HLS_SECOND_LEVEL_SEGMENT_DURATION)) {
        av_strlcpy(c->current_segment_final_filename_fmt, oc->filename,
                   sizeof(c->current_segment_final_filename_fmt));
        if (c->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) {
            char * filename = av_strdup(oc->filename);  // %%s will be %s after strftime
            if (!filename)
                return AVERROR(ENOMEM);
            if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename), filename, 's', 0) < 1) {
                av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
                        "you can try to remove second_level_segment_size flag\n",
                       filename);
                av_free(filename);
                return AVERROR(EINVAL);
            }
            av_free(filename);
        }
        if (c->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) {
            char * filename = av_strdup(oc->filename);  // %%t will be %t after strftime
            if (!filename)
                return AVERROR(ENOMEM);
            if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename), filename, 't', 0) < 1) {
                av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
                        "you can try to remove second_level_segment_time flag\n",
                       filename);
                av_free(filename);
                return AVERROR(EINVAL);
            }
            av_free(filename);
        }
    }
    return 0;
}

/* Create a new segment and append it to the segment list */
static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, double duration,
                              int64_t pos, int64_t size)
{
    HLSSegment *en = av_malloc(sizeof(*en));
    const char  *filename;
772
    int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
773
    int ret;
774

775 776 777 778 779 780 781
    if (!en)
        return AVERROR(ENOMEM);

    ret = sls_flags_filename_process(s, hls, en, duration, pos, size);
    if (ret < 0) {
        return ret;
    }
782

783 784 785
    filename = av_basename(hls->avf->filename);

    if (hls->use_localtime_mkdir) {
786
        filename = hls->avf->filename;
787
    }
788 789
    if ((find_segment_by_filename(hls->segments, filename) || find_segment_by_filename(hls->old_segments, filename))
        && !byterange_mode) {
790 791
        av_log(hls, AV_LOG_WARNING, "Duplicated segment filename detected: %s\n", filename);
    }
792
    av_strlcpy(en->filename, filename, sizeof(en->filename));
L
Luca Barbato 已提交
793

794 795
    if(hls->has_subtitle)
        av_strlcpy(en->sub_filename, av_basename(hls->vtt_avf->filename), sizeof(en->sub_filename));
796 797
    else
        en->sub_filename[0] = '\0';
798

L
Luca Barbato 已提交
799
    en->duration = duration;
800 801
    en->pos      = pos;
    en->size     = size;
L
Luca Barbato 已提交
802
    en->next     = NULL;
803 804 805 806 807 808
    en->discont  = 0;

    if (hls->discontinuity) {
        en->discont = 1;
        hls->discontinuity = 0;
    }
L
Luca Barbato 已提交
809

810
    if (hls->key_info_file || hls->encrypt) {
811 812 813 814
        av_strlcpy(en->key_uri, hls->key_uri, sizeof(en->key_uri));
        av_strlcpy(en->iv_string, hls->iv_string, sizeof(en->iv_string));
    }

815 816
    if (!hls->segments)
        hls->segments = en;
L
Luca Barbato 已提交
817
    else
818
        hls->last_segment->next = en;
L
Luca Barbato 已提交
819

820
    hls->last_segment = en;
L
Luca Barbato 已提交
821

822 823 824 825
    // EVENT or VOD playlists imply sliding window cannot be used
    if (hls->pl_type != PLAYLIST_TYPE_NONE)
        hls->max_nb_segments = 0;

826 827
    if (hls->max_nb_segments && hls->nb_entries >= hls->max_nb_segments) {
        en = hls->segments;
828
        hls->initial_prog_date_time += en->duration;
829
        hls->segments = en->next;
830
        if (en && hls->flags & HLS_DELETE_SEGMENTS &&
831
#if FF_API_HLS_WRAP
832
                !(hls->flags & HLS_SINGLE_FILE || hls->wrap)) {
833 834 835
#else
                !(hls->flags & HLS_SINGLE_FILE)) {
#endif
836 837
            en->next = hls->old_segments;
            hls->old_segments = en;
838
            if ((ret = hls_delete_old_segments(s, hls)) < 0)
839 840 841
                return ret;
        } else
            av_free(en);
842 843
    } else
        hls->nb_entries++;
L
Luca Barbato 已提交
844

845 846 847
    if (hls->max_seg_size > 0) {
        return 0;
    }
848 849
    hls->sequence++;

L
Luca Barbato 已提交
850 851 852
    return 0;
}

853 854 855 856 857 858 859 860
static int parse_playlist(AVFormatContext *s, const char *url)
{
    HLSContext *hls = s->priv_data;
    AVIOContext *in;
    int ret = 0, is_segment = 0;
    int64_t new_start_pos;
    char line[1024];
    const char *ptr;
861
    const char *end;
862 863 864 865 866 867 868 869 870 871 872 873

    if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
                                   &s->interrupt_callback, NULL,
                                   s->protocol_whitelist, s->protocol_blacklist)) < 0)
        return ret;

    read_chomp_line(in, line, sizeof(line));
    if (strcmp(line, "#EXTM3U")) {
        ret = AVERROR_INVALIDDATA;
        goto fail;
    }

874
    hls->discontinuity = 0;
875 876 877
    while (!avio_feof(in)) {
        read_chomp_line(in, line, sizeof(line));
        if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
878 879 880 881 882 883 884 885 886 887
            int64_t tmp_sequence = strtoll(ptr, NULL, 10);
            if (tmp_sequence < hls->sequence)
              av_log(hls, AV_LOG_VERBOSE,
                     "Found playlist sequence number was smaller """
                     "than specified start sequence number: %"PRId64" < %"PRId64", "
                     "omitting\n", tmp_sequence, hls->start_sequence);
            else {
              av_log(hls, AV_LOG_DEBUG, "Found playlist sequence number: %"PRId64"\n", tmp_sequence);
              hls->sequence = tmp_sequence;
            }
888 889 890
        } else if (av_strstart(line, "#EXT-X-DISCONTINUITY", &ptr)) {
            is_segment = 1;
            hls->discontinuity = 1;
891 892 893
        } else if (av_strstart(line, "#EXTINF:", &ptr)) {
            is_segment = 1;
            hls->duration = atof(ptr);
894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916
        } else if (av_stristart(line, "#EXT-X-KEY:", &ptr)) {
            ptr = av_stristr(line, "URI=\"");
            if (ptr) {
                ptr += strlen("URI=\"");
                end = av_stristr(ptr, ",");
                if (end) {
                    av_strlcpy(hls->key_uri, ptr, end - ptr);
                } else {
                    av_strlcpy(hls->key_uri, ptr, sizeof(hls->key_uri));
                }
            }

            ptr = av_stristr(line, "IV=0x");
            if (ptr) {
                ptr += strlen("IV=0x");
                end = av_stristr(ptr, ",");
                if (end) {
                    av_strlcpy(hls->iv_string, ptr, end - ptr);
                } else {
                    av_strlcpy(hls->iv_string, ptr, sizeof(hls->iv_string));
                }
            }

917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937
        } else if (av_strstart(line, "#", NULL)) {
            continue;
        } else if (line[0]) {
            if (is_segment) {
                is_segment = 0;
                new_start_pos = avio_tell(hls->avf->pb);
                hls->size = new_start_pos - hls->start_pos;
                av_strlcpy(hls->avf->filename, line, sizeof(line));
                ret = hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size);
                if (ret < 0)
                    goto fail;
                hls->start_pos = new_start_pos;
            }
        }
    }

fail:
    avio_close(in);
    return ret;
}

938
static void hls_free_segments(HLSSegment *p)
L
Luca Barbato 已提交
939
{
940
    HLSSegment *en;
L
Luca Barbato 已提交
941 942 943 944 945 946 947 948

    while(p) {
        en = p;
        p = p->next;
        av_free(en);
    }
}

949
static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSContext *c)
950
{
951
    const char *proto = avio_find_protocol_name(s->filename);
952
    int http_base_proto = proto ? (!av_strcasecmp(proto, "http") || !av_strcasecmp(proto, "https")) : 0;
953 954

    if (c->method) {
955
        av_dict_set(options, "method", c->method, 0);
956
    } else if (http_base_proto) {
957 958 959
        av_log(c, AV_LOG_WARNING, "No HTTP method set, hls muxer defaulting to method PUT.\n");
        av_dict_set(options, "method", "PUT", 0);
    }
960 961
}

962 963 964 965 966 967 968 969 970 971
static void write_m3u8_head_block(HLSContext *hls, AVIOContext *out, int version,
                                  int target_duration, int64_t sequence)
{
    avio_printf(out, "#EXTM3U\n");
    avio_printf(out, "#EXT-X-VERSION:%d\n", version);
    if (hls->allowcache == 0 || hls->allowcache == 1) {
        avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", hls->allowcache == 0 ? "NO" : "YES");
    }
    avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
    avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
972 973 974
    if (hls->segment_type == SEGMENT_TYPE_FMP4) {
        avio_printf(out, "#EXT-X-MAP:URI=\"%s\"\n", hls->fmp4_init_filename);
    }
975 976 977
    av_log(hls, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
}

978 979 980 981 982 983 984 985 986 987 988
static void hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc)
{
    size_t len = strlen(oc->filename);
    char final_filename[sizeof(oc->filename)];

    av_strlcpy(final_filename, oc->filename, len);
    final_filename[len-4] = '\0';
    ff_rename(oc->filename, final_filename, s);
    oc->filename[len-4] = '\0';
}

L
Luca Barbato 已提交
989 990 991
static int hls_window(AVFormatContext *s, int last)
{
    HLSContext *hls = s->priv_data;
992
    HLSSegment *en;
993
    int target_duration = 0;
L
Luca Barbato 已提交
994
    int ret = 0;
995
    AVIOContext *out = NULL;
996
    AVIOContext *sub_out = NULL;
997
    char temp_filename[1024];
998
    int64_t sequence = FFMAX(hls->start_sequence, hls->sequence - hls->nb_entries);
999
    int version = 3;
1000 1001
    const char *proto = avio_find_protocol_name(s->filename);
    int use_rename = proto && !strcmp(proto, "file");
1002
    static unsigned warned_non_file;
1003 1004
    char *key_uri = NULL;
    char *iv_string = NULL;
1005
    AVDictionary *options = NULL;
1006
    double prog_date_time = hls->initial_prog_date_time;
1007 1008 1009 1010 1011 1012
    int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);

    if (byterange_mode) {
        version = 4;
        sequence = 0;
    }
1013

1014 1015 1016 1017
    if (hls->segment_type == SEGMENT_TYPE_FMP4) {
        version = 7;
    }

1018
    if (!use_rename && !warned_non_file++)
M
Moritz Barsnick 已提交
1019
        av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
L
Luca Barbato 已提交
1020

1021
    set_http_options(s, &options, hls);
1022
    snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->filename);
1023
    if ((ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, &options)) < 0)
L
Luca Barbato 已提交
1024 1025
        goto fail;

1026
    for (en = hls->segments; en; en = en->next) {
1027 1028
        if (target_duration <= en->duration)
            target_duration = get_int_from_double(en->duration);
1029 1030
    }

1031
    hls->discontinuity_set = 0;
1032
    write_m3u8_head_block(hls, out, version, target_duration, sequence);
1033 1034 1035 1036 1037
    if (hls->pl_type == PLAYLIST_TYPE_EVENT) {
        avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n");
    } else if (hls->pl_type == PLAYLIST_TYPE_VOD) {
        avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n");
    }
L
Luca Barbato 已提交
1038

1039 1040 1041 1042
    if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && hls->discontinuity_set==0 ){
        avio_printf(out, "#EXT-X-DISCONTINUITY\n");
        hls->discontinuity_set = 1;
    }
1043
    for (en = hls->segments; en; en = en->next) {
1044
        if ((hls->encrypt || hls->key_info_file) && (!key_uri || strcmp(en->key_uri, key_uri) ||
1045 1046 1047 1048 1049 1050 1051 1052 1053
                                    av_strcasecmp(en->iv_string, iv_string))) {
            avio_printf(out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri);
            if (*en->iv_string)
                avio_printf(out, ",IV=0x%s", en->iv_string);
            avio_printf(out, "\n");
            key_uri = en->key_uri;
            iv_string = en->iv_string;
        }

1054 1055 1056 1057
        if (en->discont) {
            avio_printf(out, "#EXT-X-DISCONTINUITY\n");
        }

1058
        if (hls->flags & HLS_ROUND_DURATIONS)
1059
            avio_printf(out, "#EXTINF:%ld,\n",  lrint(en->duration));
1060 1061
        else
            avio_printf(out, "#EXTINF:%f,\n", en->duration);
1062
        if (byterange_mode)
1063
             avio_printf(out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n",
1064
                         en->size, en->pos);
1065
        if (hls->flags & HLS_PROGRAM_DATE_TIME) {
1066
            time_t tt, wrongsecs;
1067 1068 1069 1070 1071 1072
            int milli;
            struct tm *tm, tmpbuf;
            char buf0[128], buf1[128];
            tt = (int64_t)prog_date_time;
            milli = av_clip(lrint(1000*(prog_date_time - tt)), 0, 999);
            tm = localtime_r(&tt, &tmpbuf);
1073
            strftime(buf0, sizeof(buf0), "%Y-%m-%dT%H:%M:%S", tm);
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
            if (!strftime(buf1, sizeof(buf1), "%z", tm) || buf1[1]<'0' ||buf1[1]>'2') {
                int tz_min, dst = tm->tm_isdst;
                tm = gmtime_r(&tt, &tmpbuf);
                tm->tm_isdst = dst;
                wrongsecs = mktime(tm);
                tz_min = (abs(wrongsecs - tt) + 30) / 60;
                snprintf(buf1, sizeof(buf1),
                         "%c%02d%02d",
                         wrongsecs <= tt ? '+' : '-',
                         tz_min / 60,
                         tz_min % 60);
            }
1086 1087 1088
            avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n", buf0, milli, buf1);
            prog_date_time += en->duration;
        }
1089
        if (hls->baseurl)
1090 1091
            avio_printf(out, "%s", hls->baseurl);
        avio_printf(out, "%s\n", en->filename);
L
Luca Barbato 已提交
1092 1093
    }

1094
    if (last && (hls->flags & HLS_OMIT_ENDLIST)==0)
1095
        avio_printf(out, "#EXT-X-ENDLIST\n");
L
Luca Barbato 已提交
1096

1097
    if( hls->vtt_m3u8_name ) {
1098
        if ((ret = s->io_open(s, &sub_out, hls->vtt_m3u8_name, AVIO_FLAG_WRITE, &options)) < 0)
1099
            goto fail;
1100
        write_m3u8_head_block(hls, sub_out, version, target_duration, sequence);
1101 1102 1103

        for (en = hls->segments; en; en = en->next) {
            avio_printf(sub_out, "#EXTINF:%f,\n", en->duration);
1104
            if (byterange_mode)
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
                 avio_printf(sub_out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n",
                         en->size, en->pos);
            if (hls->baseurl)
                avio_printf(sub_out, "%s", hls->baseurl);
            avio_printf(sub_out, "%s\n", en->sub_filename);
        }

        if (last)
            avio_printf(sub_out, "#EXT-X-ENDLIST\n");

    }

L
Luca Barbato 已提交
1117
fail:
1118
    av_dict_free(&options);
1119
    ff_format_io_close(s, &out);
1120
    ff_format_io_close(s, &sub_out);
1121
    if (ret >= 0 && use_rename)
1122
        ff_rename(temp_filename, s->filename, s);
L
Luca Barbato 已提交
1123 1124 1125 1126 1127 1128 1129
    return ret;
}

static int hls_start(AVFormatContext *s)
{
    HLSContext *c = s->priv_data;
    AVFormatContext *oc = c->avf;
1130
    AVFormatContext *vtt_oc = c->vtt_avf;
1131 1132
    AVDictionary *options = NULL;
    char *filename, iv_string[KEYSIZE*2 + 1];
L
Luca Barbato 已提交
1133 1134
    int err = 0;

1135
    if (c->flags & HLS_SINGLE_FILE) {
1136 1137
        av_strlcpy(oc->filename, c->basename,
                   sizeof(oc->filename));
1138 1139 1140
        if (c->vtt_basename)
            av_strlcpy(vtt_oc->filename, c->vtt_basename,
                  sizeof(vtt_oc->filename));
1141
    } else if (c->max_seg_size > 0) {
1142
        if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename),
1143
#if FF_API_HLS_WRAP
1144
            c->basename, 'd', c->wrap ? c->sequence % c->wrap : c->sequence) < 1) {
1145 1146 1147
#else
            c->basename, 'd', c->sequence) < 1) {
#endif
1148 1149 1150
                av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -use_localtime 1 with it\n", c->basename);
                return AVERROR(EINVAL);
        }
1151
    } else {
1152 1153 1154 1155 1156 1157 1158 1159 1160
        if (c->use_localtime) {
            time_t now0;
            struct tm *tm, tmpbuf;
            time(&now0);
            tm = localtime_r(&now0, &tmpbuf);
            if (!strftime(oc->filename, sizeof(oc->filename), c->basename, tm)) {
                av_log(oc, AV_LOG_ERROR, "Could not get segment filename with use_localtime\n");
                return AVERROR(EINVAL);
            }
1161 1162 1163 1164

            err = sls_flag_use_localtime_filename(oc, c);
            if (err < 0) {
                return AVERROR(ENOMEM);
1165
            }
1166

1167 1168 1169 1170 1171 1172 1173
            if (c->use_localtime_mkdir) {
                const char *dir;
                char *fn_copy = av_strdup(oc->filename);
                if (!fn_copy) {
                    return AVERROR(ENOMEM);
                }
                dir = av_dirname(fn_copy);
1174
                if (mkdir_p(dir) == -1 && errno != EEXIST) {
1175 1176 1177 1178 1179 1180
                    av_log(oc, AV_LOG_ERROR, "Could not create directory %s with use_localtime_mkdir\n", dir);
                    av_free(fn_copy);
                    return AVERROR(errno);
                }
                av_free(fn_copy);
            }
1181
        } else if (replace_int_data_in_filename(oc->filename, sizeof(oc->filename),
1182
#if FF_API_HLS_WRAP
1183
                   c->basename, 'd', c->wrap ? c->sequence % c->wrap : c->sequence) < 1) {
1184 1185 1186
#else
                   c->basename, 'd', c->sequence) < 1) {
#endif
M
Moritz Barsnick 已提交
1187
            av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -use_localtime 1 with it\n", c->basename);
1188 1189
            return AVERROR(EINVAL);
        }
1190
        if( c->vtt_basename) {
1191
            if (replace_int_data_in_filename(vtt_oc->filename, sizeof(vtt_oc->filename),
1192
#if FF_API_HLS_WRAP
1193
                c->vtt_basename, 'd', c->wrap ? c->sequence % c->wrap : c->sequence) < 1) {
1194 1195 1196
#else
                c->vtt_basename, 'd', c->sequence) < 1) {
#endif
1197 1198 1199 1200 1201
                av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->vtt_basename);
                return AVERROR(EINVAL);
            }
       }
    }
1202
    c->number++;
L
Luca Barbato 已提交
1203

1204
    set_http_options(s, &options, c);
1205

1206 1207 1208 1209
    if (c->flags & HLS_TEMP_FILE) {
        av_strlcat(oc->filename, ".tmp", sizeof(oc->filename));
    }

1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221
    if (c->key_info_file || c->encrypt) {
        if (c->key_info_file && c->encrypt) {
            av_log(s, AV_LOG_WARNING, "Cannot use both -hls_key_info_file and -hls_enc,"
                  " will use -hls_key_info_file priority\n");
        }
        if (c->key_info_file) {
            if ((err = hls_encryption_start(s)) < 0)
                goto fail;
        } else {
            if ((err = do_encrypt(s)) < 0)
                goto fail;
        }
1222 1223
        if ((err = av_dict_set(&options, "encryption_key", c->key_string, 0))
                < 0)
1224
            goto fail;
1225 1226 1227 1228
        err = av_strlcpy(iv_string, c->iv_string, sizeof(iv_string));
        if (!err)
            snprintf(iv_string, sizeof(iv_string), "%032"PRIx64, c->sequence);
        if ((err = av_dict_set(&options, "encryption_iv", iv_string, 0)) < 0)
1229
           goto fail;
1230 1231 1232

        filename = av_asprintf("crypto:%s", oc->filename);
        if (!filename) {
1233 1234
            err = AVERROR(ENOMEM);
            goto fail;
1235
        }
1236
        err = s->io_open(s, &oc->pb, filename, AVIO_FLAG_WRITE, &options);
1237 1238 1239 1240 1241
        av_free(filename);
        av_dict_free(&options);
        if (err < 0)
            return err;
    } else
1242
        if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, &options)) < 0)
1243
            goto fail;
1244
    if (c->vtt_basename) {
1245
        set_http_options(s, &options, c);
1246
        if ((err = s->io_open(s, &vtt_oc->pb, vtt_oc->filename, AVIO_FLAG_WRITE, &options)) < 0)
1247
            goto fail;
1248
    }
1249
    av_dict_free(&options);
L
Luca Barbato 已提交
1250

1251 1252 1253 1254 1255 1256
    if (c->segment_type == SEGMENT_TYPE_FMP4) {
            write_styp(oc->pb);
    } else {
        /* We only require one PAT/PMT per segment. */
        if (oc->oformat->priv_class && oc->priv_data) {
            char period[21];
1257

1258
            snprintf(period, sizeof(period), "%d", (INT_MAX / 2) - 1);
1259

1260 1261 1262 1263
            av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
            av_opt_set(oc->priv_data, "sdt_period", period, 0);
            av_opt_set(oc->priv_data, "pat_period", period, 0);
        }
1264
    }
L
Luca Barbato 已提交
1265

1266 1267 1268 1269 1270
    if (c->vtt_basename) {
        err = avformat_write_header(vtt_oc,NULL);
        if (err < 0)
            return err;
    }
1271

L
Luca Barbato 已提交
1272
    return 0;
1273 1274 1275 1276
fail:
    av_dict_free(&options);

    return err;
L
Luca Barbato 已提交
1277 1278
}

1279 1280 1281 1282 1283 1284 1285
static const char * get_default_pattern_localtime_fmt(void)
{
    char b[21];
    time_t t = time(NULL);
    struct tm *p, tmbuf;
    p = localtime_r(&t, &tmbuf);
    // no %s support when strftime returned error or left format string unchanged
1286 1287
    // also no %s support on MSVC, which invokes the invalid parameter handler on unsupported format strings, instead of returning an error
    return (HAVE_LIBC_MSVCRT || !strftime(b, sizeof(b), "%s", p) || !strcmp(b, "%s")) ? "-%Y%m%d%H%M%S.ts" : "-%s.ts";
1288 1289
}

L
Luca Barbato 已提交
1290 1291 1292 1293 1294 1295
static int hls_write_header(AVFormatContext *s)
{
    HLSContext *hls = s->priv_data;
    int ret, i;
    char *p;
    const char *pattern = "%d.ts";
1296
    const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt();
1297
    const char *vtt_pattern = "%d.vtt";
liuqi_123's avatar
liuqi_123 已提交
1298
    AVDictionary *options = NULL;
1299
    int basename_size;
1300
    int vtt_basename_size;
L
Luca Barbato 已提交
1301

1302 1303
    if ((hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) ||
        (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME)) {
1304
        time_t t = time(NULL); // we will need it in either case
1305
        if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) {
1306
            hls->start_sequence = (int64_t)t;
1307
        } else if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME) {
1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318
            char b[15];
            struct tm *p, tmbuf;
            if (!(p = localtime_r(&t, &tmbuf)))
                return AVERROR(ENOMEM);
            if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p))
                return AVERROR(ENOMEM);
            hls->start_sequence = strtoll(b, NULL, 10);
        }
        av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence);
    }

1319
    hls->sequence       = hls->start_sequence;
1320
    hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE;
L
Luca Barbato 已提交
1321
    hls->start_pts      = AV_NOPTS_VALUE;
1322
    hls->current_segment_final_filename_fmt[0] = '\0';
L
Luca Barbato 已提交
1323

1324 1325 1326 1327 1328 1329
    if (hls->flags & HLS_PROGRAM_DATE_TIME) {
        time_t now0;
        time(&now0);
        hls->initial_prog_date_time = now0;
    }

liuqi_123's avatar
liuqi_123 已提交
1330 1331 1332 1333 1334 1335 1336 1337
    if (hls->format_options_str) {
        ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0);
        if (ret < 0) {
            av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n", hls->format_options_str);
            goto fail;
        }
    }

1338
    for (i = 0; i < s->nb_streams; i++) {
L
Luca Barbato 已提交
1339
        hls->has_video +=
1340
            s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
1341
        hls->has_subtitle +=
1342
            s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE;
1343
    }
L
Luca Barbato 已提交
1344 1345 1346 1347 1348 1349

    if (hls->has_video > 1)
        av_log(s, AV_LOG_WARNING,
               "More than a single video stream present, "
               "expect issues decoding it.\n");

1350 1351 1352 1353 1354
    if (hls->segment_type == SEGMENT_TYPE_FMP4) {
        hls->oformat = av_guess_format("mp4", NULL, NULL);
    } else {
        hls->oformat = av_guess_format("mpegts", NULL, NULL);
    }
L
Luca Barbato 已提交
1355 1356 1357 1358 1359 1360

    if (!hls->oformat) {
        ret = AVERROR_MUXER_NOT_FOUND;
        goto fail;
    }

1361 1362 1363 1364 1365 1366 1367 1368
    if(hls->has_subtitle) {
        hls->vtt_oformat = av_guess_format("webvtt", NULL, NULL);
        if (!hls->oformat) {
            ret = AVERROR_MUXER_NOT_FOUND;
            goto fail;
        }
    }

1369 1370 1371 1372 1373 1374 1375 1376 1377
    if (hls->segment_filename) {
        hls->basename = av_strdup(hls->segment_filename);
        if (!hls->basename) {
            ret = AVERROR(ENOMEM);
            goto fail;
        }
    } else {
        if (hls->flags & HLS_SINGLE_FILE)
            pattern = ".ts";
L
Luca Barbato 已提交
1378

1379 1380 1381 1382 1383
        if (hls->use_localtime) {
            basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1;
        } else {
            basename_size = strlen(s->filename) + strlen(pattern) + 1;
        }
1384 1385 1386 1387 1388
        hls->basename = av_malloc(basename_size);
        if (!hls->basename) {
            ret = AVERROR(ENOMEM);
            goto fail;
        }
L
Luca Barbato 已提交
1389

1390
        av_strlcpy(hls->basename, s->filename, basename_size);
L
Luca Barbato 已提交
1391

1392 1393 1394
        p = strrchr(hls->basename, '.');
        if (p)
            *p = '\0';
1395 1396 1397 1398 1399
        if (hls->use_localtime) {
            av_strlcat(hls->basename, pattern_localtime_fmt, basename_size);
        } else {
            av_strlcat(hls->basename, pattern, basename_size);
        }
1400
    }
1401
    if (!hls->use_localtime) {
1402 1403
        ret = sls_flag_check_duration_size_index(hls);
        if (ret < 0) {
1404 1405 1406
             goto fail;
        }
    } else {
1407 1408
        ret = sls_flag_check_duration_size(hls);
        if (ret < 0) {
1409 1410
             goto fail;
        }
1411
    }
1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440
    if(hls->has_subtitle) {

        if (hls->flags & HLS_SINGLE_FILE)
            vtt_pattern = ".vtt";
        vtt_basename_size = strlen(s->filename) + strlen(vtt_pattern) + 1;
        hls->vtt_basename = av_malloc(vtt_basename_size);
        if (!hls->vtt_basename) {
            ret = AVERROR(ENOMEM);
            goto fail;
        }
        hls->vtt_m3u8_name = av_malloc(vtt_basename_size);
        if (!hls->vtt_m3u8_name ) {
            ret = AVERROR(ENOMEM);
            goto fail;
        }
        av_strlcpy(hls->vtt_basename, s->filename, vtt_basename_size);
        p = strrchr(hls->vtt_basename, '.');
        if (p)
            *p = '\0';

        if( hls->subtitle_filename ) {
            strcpy(hls->vtt_m3u8_name, hls->subtitle_filename);
        } else {
            strcpy(hls->vtt_m3u8_name, hls->vtt_basename);
            av_strlcat(hls->vtt_m3u8_name, "_vtt.m3u8", vtt_basename_size);
        }
        av_strlcat(hls->vtt_basename, vtt_pattern, vtt_basename_size);
    }

L
Luca Barbato 已提交
1441 1442 1443
    if ((ret = hls_mux_init(s)) < 0)
        goto fail;

1444 1445
    if (hls->flags & HLS_APPEND_LIST) {
        parse_playlist(s, s->filename);
1446
        hls->discontinuity = 1;
1447 1448 1449 1450 1451 1452
        if (hls->init_time > 0) {
            av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time,"
                   " hls_init_time value will have no effect\n");
            hls->init_time = 0;
            hls->recording_time = hls->time * AV_TIME_BASE;
        }
1453 1454
    }

1455 1456 1457 1458
    if (hls->segment_type != SEGMENT_TYPE_FMP4) {
        if ((ret = hls_start(s)) < 0)
            goto fail;
    }
L
Luca Barbato 已提交
1459

liuqi_123's avatar
liuqi_123 已提交
1460 1461 1462 1463 1464
    av_dict_copy(&options, hls->format_options, 0);
    ret = avformat_write_header(hls->avf, &options);
    if (av_dict_count(options)) {
        av_log(s, AV_LOG_ERROR, "Some of provided format options in '%s' are not recognized\n", hls->format_options_str);
        ret = AVERROR(EINVAL);
1465
        goto fail;
liuqi_123's avatar
liuqi_123 已提交
1466
    }
1467
    //av_assert0(s->nb_streams == hls->avf->nb_streams);
1468
    for (i = 0; i < s->nb_streams; i++) {
1469
        AVStream *inner_st;
1470
        AVStream *outer_st = s->streams[i];
1471 1472 1473 1474 1475 1476 1477 1478 1479 1480

        if (hls->max_seg_size > 0) {
            if ((outer_st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
                (outer_st->codecpar->bit_rate > hls->max_seg_size)) {
                av_log(s, AV_LOG_WARNING, "Your video bitrate is bigger than hls_segment_size, "
                       "(%"PRId64 " > %"PRId64 "), the result maybe not be what you want.",
                       outer_st->codecpar->bit_rate, hls->max_seg_size);
            }
        }

1481
        if (outer_st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
1482 1483 1484 1485
            inner_st = hls->avf->streams[i];
        else if (hls->vtt_avf)
            inner_st = hls->vtt_avf->streams[0];
        else {
1486
            /* We have a subtitle stream, when the user does not want one */
1487 1488 1489
            inner_st = NULL;
            continue;
        }
1490
        avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den);
1491
    }
L
Luca Barbato 已提交
1492
fail:
liuqi_123's avatar
liuqi_123 已提交
1493 1494

    av_dict_free(&options);
1495
    if (ret < 0) {
1496
        av_freep(&hls->basename);
1497
        av_freep(&hls->vtt_basename);
1498
        av_freep(&hls->key_basename);
L
Luca Barbato 已提交
1499 1500
        if (hls->avf)
            avformat_free_context(hls->avf);
1501 1502 1503
        if (hls->vtt_avf)
            avformat_free_context(hls->vtt_avf);

L
Luca Barbato 已提交
1504 1505 1506 1507 1508 1509 1510
    }
    return ret;
}

static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
{
    HLSContext *hls = s->priv_data;
1511
    AVFormatContext *oc = NULL;
L
Luca Barbato 已提交
1512 1513
    AVStream *st = s->streams[pkt->stream_index];
    int64_t end_pts = hls->recording_time * hls->number;
1514
    int is_ref_pkt = 1;
1515
    int ret = 0, can_split = 1;
1516
    int stream_index = 0;
L
Luca Barbato 已提交
1517

1518 1519 1520 1521 1522 1523 1524 1525
    if (hls->sequence - hls->nb_entries > hls->start_sequence && hls->init_time > 0) {
        /* reset end_pts, hls->recording_time at end of the init hls list */
        int init_list_dur = hls->init_time * hls->nb_entries * AV_TIME_BASE;
        int after_init_list_dur = (hls->sequence - hls->nb_entries ) * hls->time * AV_TIME_BASE;
        hls->recording_time = hls->time * AV_TIME_BASE;
        end_pts = init_list_dur + after_init_list_dur ;
    }

1526
    if( st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE ) {
1527 1528 1529 1530 1531 1532
        oc = hls->vtt_avf;
        stream_index = 0;
    } else {
        oc = hls->avf;
        stream_index = pkt->stream_index;
    }
L
Luca Barbato 已提交
1533 1534 1535 1536 1537
    if (hls->start_pts == AV_NOPTS_VALUE) {
        hls->start_pts = pkt->pts;
        hls->end_pts   = pkt->pts;
    }

1538
    if (hls->has_video) {
1539
        can_split = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
1540
                    ((pkt->flags & AV_PKT_FLAG_KEY) || (hls->flags & HLS_SPLIT_BY_TIME));
1541
        is_ref_pkt = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
1542
    }
1543 1544
    if (pkt->pts == AV_NOPTS_VALUE)
        is_ref_pkt = can_split = 0;
1545

1546 1547 1548 1549 1550 1551 1552
    if (is_ref_pkt) {
        if (hls->new_start) {
            hls->new_start = 0;
            hls->duration = (double)(pkt->pts - hls->end_pts)
                                       * st->time_base.num / st->time_base.den;
            hls->dpp = (double)(pkt->duration) * st->time_base.num / st->time_base.den;
        } else {
1553 1554 1555 1556 1557 1558
            if (pkt->duration) {
                hls->duration += (double)(pkt->duration) * st->time_base.num / st->time_base.den;
            } else {
                av_log(s, AV_LOG_WARNING, "pkt->duration = 0, maybe the hls segment duration will not precise\n");
                hls->duration = (double)(pkt->pts - hls->end_pts) * st->time_base.num / st->time_base.den;
            }
1559
        }
L
Luca Barbato 已提交
1560

1561
    }
1562
    if (hls->fmp4_init_mode || can_split && av_compare_ts(pkt->pts - hls->start_pts, st->time_base,
1563
                                   end_pts, AV_TIME_BASE_Q) >= 0) {
1564
        int64_t new_start_pos;
1565
        char *old_filename = av_strdup(hls->avf->filename);
S
Steven Liu 已提交
1566
        int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
1567 1568 1569 1570 1571

        if (!old_filename) {
            return AVERROR(ENOMEM);
        }

1572
        av_write_frame(hls->avf, NULL); /* Flush any buffered data */
1573 1574 1575

        new_start_pos = avio_tell(hls->avf->pb);
        hls->size = new_start_pos - hls->start_pos;
1576

S
Steven Liu 已提交
1577 1578 1579 1580 1581
        if (!byterange_mode) {
            ff_format_io_close(s, &oc->pb);
            if (hls->vtt_avf) {
                ff_format_io_close(s, &hls->vtt_avf->pb);
            }
1582
        }
1583 1584
        if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) {
            if (!(hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size <= 0))
1585
                if ((hls->avf->oformat->priv_class && hls->avf->priv_data) && hls->segment_type != SEGMENT_TYPE_FMP4)
1586 1587 1588 1589
                    av_opt_set(hls->avf->priv_data, "mpegts_flags", "resend_headers", 0);
            hls_rename_temp_file(s, oc);
        }

1590 1591 1592 1593 1594 1595 1596
        if (hls->fmp4_init_mode) {
            hls->number--;
        }

        if (!hls->fmp4_init_mode)
            ret = hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size);

1597
        hls->start_pos = new_start_pos;
1598 1599
        if (ret < 0) {
            av_free(old_filename);
1600
            return ret;
1601
        }
1602

L
Luca Barbato 已提交
1603
        hls->end_pts = pkt->pts;
1604
        hls->duration = 0;
L
Luca Barbato 已提交
1605

1606
        hls->fmp4_init_mode = 0;
1607 1608
        if (hls->flags & HLS_SINGLE_FILE) {
            hls->number++;
1609 1610 1611
        } else if (hls->max_seg_size > 0) {
            if (hls->start_pos >= hls->max_seg_size) {
                hls->sequence++;
1612
                sls_flag_file_rename(hls, old_filename);
1613 1614 1615 1616 1617 1618 1619
                ret = hls_start(s);
                hls->start_pos = 0;
                /* When split segment by byte, the duration is short than hls_time,
                 * so it is not enough one segment duration as hls_time, */
                hls->number--;
            }
            hls->number++;
1620
        } else {
1621
            sls_flag_file_rename(hls, old_filename);
1622 1623
            ret = hls_start(s);
        }
1624
        av_free(old_filename);
L
Luca Barbato 已提交
1625

1626
        if (ret < 0) {
L
Luca Barbato 已提交
1627
            return ret;
1628
        }
L
Luca Barbato 已提交
1629

1630
        if ((ret = hls_window(s, 0)) < 0) {
L
Luca Barbato 已提交
1631
            return ret;
1632
        }
L
Luca Barbato 已提交
1633 1634
    }

1635
    ret = ff_write_chained(oc, stream_index, pkt, s, 0);
L
Luca Barbato 已提交
1636 1637 1638 1639 1640 1641 1642 1643

    return ret;
}

static int hls_write_trailer(struct AVFormatContext *s)
{
    HLSContext *hls = s->priv_data;
    AVFormatContext *oc = hls->avf;
1644
    AVFormatContext *vtt_oc = hls->vtt_avf;
1645 1646 1647 1648 1649 1650
    char *old_filename = av_strdup(hls->avf->filename);

    if (!old_filename) {
        return AVERROR(ENOMEM);
    }

L
Luca Barbato 已提交
1651 1652

    av_write_trailer(oc);
1653 1654
    if (oc->pb) {
        hls->size = avio_tell(hls->avf->pb) - hls->start_pos;
1655
        ff_format_io_close(s, &oc->pb);
1656 1657 1658 1659 1660

        if ((hls->flags & HLS_TEMP_FILE) && oc->filename[0]) {
            hls_rename_temp_file(s, oc);
        }

1661 1662
        /* after av_write_trailer, then duration + 1 duration per packet */
        hls_append_segment(s, hls, hls->duration + hls->dpp, hls->start_pos, hls->size);
1663
    }
1664

1665
    sls_flag_file_rename(hls, old_filename);
1666

1667 1668 1669 1670
    if (vtt_oc) {
        if (vtt_oc->pb)
            av_write_trailer(vtt_oc);
        hls->size = avio_tell(hls->vtt_avf->pb) - hls->start_pos;
1671
        ff_format_io_close(s, &vtt_oc->pb);
1672
    }
1673
    av_freep(&hls->basename);
1674
    av_freep(&hls->key_basename);
1675
    avformat_free_context(oc);
1676

1677 1678 1679
    hls->avf = NULL;
    hls_window(s, 1);

1680 1681 1682 1683 1684 1685
    if (vtt_oc) {
        av_freep(&hls->vtt_basename);
        av_freep(&hls->vtt_m3u8_name);
        avformat_free_context(vtt_oc);
    }

1686 1687
    hls_free_segments(hls->segments);
    hls_free_segments(hls->old_segments);
1688
    av_free(old_filename);
L
Luca Barbato 已提交
1689 1690 1691 1692 1693 1694
    return 0;
}

#define OFFSET(x) offsetof(HLSContext, x)
#define E AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
1695
    {"start_number",  "set first number in the sequence",        OFFSET(start_sequence),AV_OPT_TYPE_INT64,  {.i64 = 0},     0, INT64_MAX, E},
1696
    {"hls_time",      "set segment length in seconds",           OFFSET(time),    AV_OPT_TYPE_FLOAT,  {.dbl = 2},     0, FLT_MAX, E},
1697
    {"hls_init_time", "set segment length in seconds at init list",           OFFSET(init_time),    AV_OPT_TYPE_FLOAT,  {.dbl = 0},     0, FLT_MAX, E},
1698
    {"hls_list_size", "set maximum number of playlist entries",  OFFSET(max_nb_segments),    AV_OPT_TYPE_INT,    {.i64 = 5},     0, INT_MAX, E},
liuqi_123's avatar
liuqi_123 已提交
1699
    {"hls_ts_options","set hls mpegts list of options for the container format used for hls", OFFSET(format_options_str), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,    E},
1700
    {"hls_vtt_options","set hls vtt list of options for the container format used for hls", OFFSET(vtt_format_options_str), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,    E},
1701 1702 1703
#if FF_API_HLS_WRAP
    {"hls_wrap",      "set number after which the index wraps (will be deprecated)",  OFFSET(wrap),    AV_OPT_TYPE_INT,    {.i64 = 0},     0, INT_MAX, E},
#endif
1704
    {"hls_allow_cache", "explicitly set whether the client MAY (1) or MUST NOT (0) cache media segments", OFFSET(allowcache), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, E},
1705
    {"hls_base_url",  "url to prepend to each playlist entry",   OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,       E},
1706
    {"hls_segment_filename", "filename template for segment files", OFFSET(segment_filename),   AV_OPT_TYPE_STRING, {.str = NULL},            0,       0,         E},
1707
    {"hls_segment_size", "maximum size per segment file, (in bytes)",  OFFSET(max_seg_size),    AV_OPT_TYPE_INT,    {.i64 = 0},               0,       INT_MAX,   E},
1708
    {"hls_key_info_file",    "file with key URI and key file path", OFFSET(key_info_file),      AV_OPT_TYPE_STRING, {.str = NULL},            0,       0,         E},
1709 1710 1711 1712
    {"hls_enc",    "enable AES128 encryption support", OFFSET(encrypt),      AV_OPT_TYPE_BOOL, {.i64 = 0},            0,       1,         E},
    {"hls_enc_key",    "hex-coded 16 byte key to encrypt the segments", OFFSET(key),      AV_OPT_TYPE_STRING, .flags = E},
    {"hls_enc_key_url",    "url to access the key to decrypt the segments", OFFSET(key_url),      AV_OPT_TYPE_STRING, {.str = NULL},            0,       0,         E},
    {"hls_enc_iv",    "hex-coded 16 byte initialization vector", OFFSET(iv),      AV_OPT_TYPE_STRING, .flags = E},
1713
    {"hls_subtitle_path",     "set path of hls subtitles", OFFSET(subtitle_filename), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,    E},
1714 1715 1716 1717
    {"hls_segment_type",     "set hls segment files type", OFFSET(segment_type), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, "segment_type"},
    {"fmp4",   "make segment file to fragment mp4 files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_FMP4 }, 0, UINT_MAX,   E, "segment_type"},
    {"mpegts",   "make segment file to mpegts files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MPEGTS }, 0, UINT_MAX,   E, "segment_type"},
    {"hls_fmp4_init_filename", "set fragment mp4 file init filename", OFFSET(fmp4_init_filename),   AV_OPT_TYPE_STRING, {.str = "init.mp4"},            0,       0,         E},
1718 1719
    {"hls_flags",     "set flags affecting HLS playlist and media file generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, "flags"},
    {"single_file",   "generate a single media file indexed with byte ranges", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SINGLE_FILE }, 0, UINT_MAX,   E, "flags"},
1720
    {"temp_file", "write segment to temporary file and rename when complete", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_TEMP_FILE }, 0, UINT_MAX,   E, "flags"},
1721
    {"delete_segments", "delete segment files that are no longer part of the playlist", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DELETE_SEGMENTS }, 0, UINT_MAX,   E, "flags"},
1722
    {"round_durations", "round durations in m3u8 to whole numbers", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX,   E, "flags"},
1723
    {"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX,   E, "flags"},
1724
    {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX,   E, "flags"},
1725
    {"split_by_time", "split the hls segment by time which user set by hls_time", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SPLIT_BY_TIME }, 0, UINT_MAX,   E, "flags"},
1726
    {"append_list", "append the new segments into old hls segment list", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_APPEND_LIST }, 0, UINT_MAX,   E, "flags"},
1727
    {"program_date_time", "add EXT-X-PROGRAM-DATE-TIME", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PROGRAM_DATE_TIME }, 0, UINT_MAX,   E, "flags"},
1728
    {"second_level_segment_index", "include segment index in segment filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SECOND_LEVEL_SEGMENT_INDEX }, 0, UINT_MAX,   E, "flags"},
1729 1730
    {"second_level_segment_duration", "include segment duration in segment filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SECOND_LEVEL_SEGMENT_DURATION }, 0, UINT_MAX,   E, "flags"},
    {"second_level_segment_size", "include segment size in segment filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SECOND_LEVEL_SEGMENT_SIZE }, 0, UINT_MAX,   E, "flags"},
1731 1732
    {"use_localtime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
    {"use_localtime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
1733 1734 1735
    {"hls_playlist_type", "set the HLS playlist type", OFFSET(pl_type), AV_OPT_TYPE_INT, {.i64 = PLAYLIST_TYPE_NONE }, 0, PLAYLIST_TYPE_NB-1, E, "pl_type" },
    {"event", "EVENT playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_EVENT }, INT_MIN, INT_MAX, E, "pl_type" },
    {"vod", "VOD playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_VOD }, INT_MIN, INT_MAX, E, "pl_type" },
1736
    {"method", "set the HTTP method(default: PUT)", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,    E},
1737 1738 1739 1740
    {"hls_start_number_source", "set source of first number in sequence", OFFSET(start_sequence_source_type), AV_OPT_TYPE_INT, {.i64 = HLS_START_SEQUENCE_AS_START_NUMBER }, 0, HLS_START_SEQUENCE_AS_FORMATTED_DATETIME, E, "start_sequence_source_type" },
    {"generic", "start_number value (default)", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_START_NUMBER }, INT_MIN, INT_MAX, E, "start_sequence_source_type" },
    {"epoch", "seconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, "start_sequence_source_type" },
    {"datetime", "current datetime as YYYYMMDDhhmmss", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_FORMATTED_DATETIME }, INT_MIN, INT_MAX, E, "start_sequence_source_type" },
L
Luca Barbato 已提交
1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753
    { NULL },
};

static const AVClass hls_class = {
    .class_name = "hls muxer",
    .item_name  = av_default_item_name,
    .option     = options,
    .version    = LIBAVUTIL_VERSION_INT,
};


AVOutputFormat ff_hls_muxer = {
    .name           = "hls",
L
Luca Barbato 已提交
1754
    .long_name      = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
L
Luca Barbato 已提交
1755 1756
    .extensions     = "m3u8",
    .priv_data_size = sizeof(HLSContext),
1757 1758
    .audio_codec    = AV_CODEC_ID_AAC,
    .video_codec    = AV_CODEC_ID_H264,
1759
    .subtitle_codec = AV_CODEC_ID_WEBVTT,
1760
    .flags          = AVFMT_NOFILE | AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
L
Luca Barbato 已提交
1761 1762 1763 1764 1765
    .write_header   = hls_write_header,
    .write_packet   = hls_write_packet,
    .write_trailer  = hls_write_trailer,
    .priv_class     = &hls_class,
};