FFmpeg
Loading...
Searching...
No Matches
hlsenc.c
Go to the documentation of this file.
1/*
2 * Apple HTTP Live Streaming segmenter
3 * Copyright (c) 2012, Luca Barbato
4 * Copyright (c) 2017 Akamai Technologies, Inc.
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include "config.h"
24#include "config_components.h"
25#include <stdint.h>
26#include <time.h>
27#if HAVE_UNISTD_H
28#include <unistd.h>
29#endif
30
32#include "libavutil/avassert.h"
33#include "libavutil/macros.h"
35#include "libavutil/avstring.h"
36#include "libavutil/bprint.h"
38#include "libavutil/mem.h"
39#include "libavutil/opt.h"
41#include "libavutil/log.h"
43#include "libavutil/time.h"
45
46#include "libavcodec/defs.h"
47
48#include "avformat.h"
49#include "avio_internal.h"
50#if CONFIG_HTTP_PROTOCOL
51#include "http.h"
52#endif
53#include "hlsplaylist.h"
54#include "internal.h"
55#include "mux.h"
56#if CONFIG_MP4_MUXER
57#include "movenc.h"
58#endif
59#include "os_support.h"
60#include "url.h"
61
69
74
75#define KEYSIZE 16
76#define LINE_BUFFER_SIZE MAX_URL_SIZE
77#define HLS_MICROSECOND_UNIT 1000000
78#define BUFSIZE (16 * 1024)
79#define POSTFIX_PATTERN "_%d"
80
81typedef struct HLSSegment {
82 const char *filename;
83 const char *sub_filename;
84 double duration; /* in seconds */
89
90 const char *key_uri;
91 char iv_string[KEYSIZE*2 + 1];
92
95
96 char buf[]; /* for filename, sub_filename and key_uri */
98
99typedef enum HLSFlags {
100 // Generate a single media file and use byte ranges in the playlist.
101 HLS_SINGLE_FILE = (1 << 0),
107 HLS_APPEND_LIST = (1 << 6),
109 HLS_SECOND_LEVEL_SEGMENT_INDEX = (1 << 8), // include segment index in segment filenames when use_localtime e.g.: %%03d
110 HLS_SECOND_LEVEL_SEGMENT_DURATION = (1 << 9), // include segment duration (microsec) in segment filenames when use_localtime e.g.: %%09t
111 HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size (bytes) in segment filenames when use_localtime e.g.: %%014s
112 HLS_TEMP_FILE = (1 << 11),
115 HLS_I_FRAMES_ONLY = (1 << 14),
116} HLSFlags;
117
122
123typedef struct VariantStream {
125 unsigned number;
133 uint8_t *temp_buffer;
134 uint8_t *init_buffer;
135
138
143 double dpp; // duration per packet
147 double duration; // last segment duration computed so far, in seconds
148 int64_t start_pos; // last segment starting position
149 int64_t size; // last segment size
154
159
163
165 char *basename;
169
171 char current_segment_final_filename_fmt[MAX_URL_SIZE]; // when renaming segments
172
175
177
180 char key_string[KEYSIZE*2 + 1];
181 char iv_string[KEYSIZE*2 + 1];
182
184 char codec_attr[128];
186 unsigned int nb_streams;
187 int m3u8_created; /* status of media play-list creation */
188 int is_default; /* default status of audio group */
189 const char *language; /* audio language name */
190 const char *agroup; /* audio group name */
191 const char *sgroup; /* subtitle group name */
192 const char *ccgroup; /* closed caption group name */
193 const char *varname; /* variant name */
194 const char *subtitle_varname; /* subtitle variant name */
196
197typedef struct ClosedCaptionsStream {
198 const char *ccgroup; /* closed caption group name */
199 const char *instreamid; /* closed captions INSTREAM-ID */
200 const char *language; /* closed captions language */
202
203typedef struct HLSContext {
204 const AVClass *class; // Class for private options.
206 uint32_t start_sequence_source_type; // enum StartSequenceSourceType
207
208 int64_t time; // Set by a private option.
209 int64_t init_time; // Set by a private option.
210 int max_nb_segments; // Set by a private option.
211 int hls_delete_threshold; // Set by a private option.
212 uint32_t flags; // enum HLSFlags
213 uint32_t pl_type; // enum PlaylistType
217 int resend_init_file; ///< resend init file into disk after refresh m3u8
218
219 int use_localtime; ///< flag to expand filename with localtime
220 int use_localtime_mkdir;///< flag to mkdir dirname in timebased filename
223 int64_t max_seg_size; // every segment file max size
224
225 char *baseurl;
229
231 char *key;
232 char *key_url;
233 char *iv;
236
240 char key_string[KEYSIZE*2 + 1];
241 char iv_string[KEYSIZE*2 + 1];
243
244 char *method;
246
248 unsigned int nb_varstreams;
250 unsigned int nb_ccstreams;
251
252 int master_m3u8_created; /* status of master play-list creation */
253 char *master_m3u8_url; /* URL of the master m3u8 file */
254 int version; /* HLS version */
255 char *var_stream_map; /* user specified variant stream map string */
256 char *cc_stream_map; /* user specified closed caption streams map string */
259 int http_persistent;
265 char *headers;
266 int has_default_key; /* has DEFAULT field of var_stream_map */
267 int has_video_m3u8; /* has video stream m3u8 list */
268} HLSContext;
269
270static int strftime_expand(const char *fmt, char **dest)
271{
272 int r = 1;
273 time_t now0;
274 struct tm *tm, tmpbuf;
275 char *buf;
276
278 if (!buf)
279 return AVERROR(ENOMEM);
280
281 time(&now0);
282 tm = localtime_r(&now0, &tmpbuf);
283 r = strftime(buf, MAX_URL_SIZE, fmt, tm);
284 if (!r) {
285 av_free(buf);
286 return AVERROR(EINVAL);
287 }
288 *dest = buf;
289
290 return r;
291}
292
293static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, const char *filename,
295{
296 HLSContext *hls = s->priv_data;
297 int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
298 int err = AVERROR_MUXER_NOT_FOUND;
299 if (!*pb || !http_base_proto || !hls->http_persistent) {
300 err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
301#if CONFIG_HTTP_PROTOCOL
302 } else {
303 URLContext *http_url_context = ffio_geturlcontext(*pb);
304 av_assert0(http_url_context);
305 err = ff_http_do_new_request(http_url_context, filename);
306 if (err < 0)
308
309#endif
310 }
311 return err;
312}
313
314static int hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename)
315{
316 HLSContext *hls = s->priv_data;
317 int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
318 int ret = 0;
319 if (!*pb)
320 return ret;
321 if (!http_base_proto || !hls->http_persistent || hls->key_info_file || hls->encrypt) {
323#if CONFIG_HTTP_PROTOCOL
324 } else {
325 URLContext *http_url_context = ffio_geturlcontext(*pb);
326 av_assert0(http_url_context);
327 avio_flush(*pb);
328 ret = ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE);
329#endif
330 }
331 return ret;
332}
333
335{
336 int http_base_proto = ff_is_http_proto(s->url);
337
338 if (c->method) {
339 av_dict_set(options, "method", c->method, 0);
340 } else if (http_base_proto) {
341 av_dict_set(options, "method", "PUT", 0);
342 }
343 if (c->user_agent)
344 av_dict_set(options, "user_agent", c->user_agent, 0);
345 if (c->http_persistent)
346 av_dict_set_int(options, "multiple_requests", 1, 0);
347 if (c->timeout >= 0)
348 av_dict_set_int(options, "timeout", c->timeout, 0);
349 if (c->headers)
350 av_dict_set(options, "headers", c->headers, 0);
351}
352
354{
355 int codec_strlen = strlen(vs->codec_attr);
356 char attr[32];
357 AVBPrint buffer;
358
360 return;
362 return;
363
364 av_bprint_init_for_buffer(&buffer, attr, sizeof(attr));
365 if (ff_make_codec_str(vs->avf, st->codecpar, &st->avg_frame_rate,
366 &buffer) < 0)
367 goto fail;
368
369 // Don't write the same attribute multiple times
370 if (!av_stristr(vs->codec_attr, attr)) {
371 snprintf(vs->codec_attr + codec_strlen,
372 sizeof(vs->codec_attr) - codec_strlen,
373 "%s%s", codec_strlen ? "," : "", attr);
374 }
375 return;
376
377fail:
378 vs->codec_attr[0] = '\0';
380 return;
381}
382
383static int replace_str_data_in_filename(char **s, const char *filename, char placeholder, const char *datastring)
384{
385 const char *p;
386 char c;
387 int addchar_count;
388 int found_count = 0;
389 AVBPrint buf;
390 int ret;
391
393
394 p = filename;
395 for (;;) {
396 c = *p;
397 if (c == '\0')
398 break;
399 if (c == '%' && *(p+1) == '%') // %%
400 addchar_count = 2;
401 else if (c == '%' && *(p+1) == placeholder) {
402 av_bprintf(&buf, "%s", datastring);
403 p += 2;
404 addchar_count = 0;
405 found_count ++;
406 } else
407 addchar_count = 1;
408
409 if (addchar_count > 0) {
410 av_bprint_append_data(&buf, p, addchar_count);
411 p += addchar_count;
412 }
413 }
414 if (!av_bprint_is_complete(&buf)) {
416 return AVERROR(ENOMEM);
417 }
418 if ((ret = av_bprint_finalize(&buf, s)) < 0)
419 return ret;
420 return found_count;
421}
422
423static int replace_int_data_in_filename(char **s, const char *filename, char placeholder, int64_t number)
424{
425 const char *p;
426 char c;
427 int nd, addchar_count;
428 int found_count = 0;
429 AVBPrint buf;
430 int ret;
431
433
434 p = filename;
435 for (;;) {
436 c = *p;
437 if (c == '\0')
438 break;
439 if (c == '%' && *(p+1) == '%') // %%
440 addchar_count = 2;
441 else if (c == '%' && (av_isdigit(*(p+1)) || *(p+1) == placeholder)) {
442 nd = 0;
443 addchar_count = 1;
444 while (av_isdigit(*(p + addchar_count))) {
445 nd = nd * 10 + *(p + addchar_count) - '0';
446 addchar_count++;
447 }
448
449 if (*(p + addchar_count) == placeholder) {
450 av_bprintf(&buf, "%0*"PRId64, (number < 0) ? nd : nd++, number);
451 p += (addchar_count + 1);
452 addchar_count = 0;
453 found_count++;
454 }
455
456 } else
457 addchar_count = 1;
458
459 av_bprint_append_data(&buf, p, addchar_count);
460 p += addchar_count;
461 }
462 if (!av_bprint_is_complete(&buf)) {
464 return AVERROR(ENOMEM);
465 }
466 if ((ret = av_bprint_finalize(&buf, s)) < 0)
467 return ret;
468 return found_count;
469}
470
471static void write_styp(AVIOContext *pb)
472{
473 avio_wb32(pb, 24);
474 ffio_wfourcc(pb, "styp");
475 ffio_wfourcc(pb, "msdh");
476 avio_wb32(pb, 0); /* minor */
477 ffio_wfourcc(pb, "msdh");
478 ffio_wfourcc(pb, "msix");
479}
480
481static int flush_dynbuf(VariantStream *vs, int *range_length)
482{
483 AVFormatContext *ctx = vs->avf;
484
485 if (!ctx->pb) {
486 return AVERROR(EINVAL);
487 }
488
489 // flush
491
492 // write out to file
493 *range_length = avio_close_dyn_buf(ctx->pb, &vs->temp_buffer);
494 ctx->pb = NULL;
495 avio_write(vs->out, vs->temp_buffer, *range_length);
496 avio_flush(vs->out);
497
498 // re-open buffer
499 return avio_open_dyn_buf(&ctx->pb);
500}
501
502static void reflush_dynbuf(VariantStream *vs, int *range_length)
503{
504 // re-open buffer
505 avio_write(vs->out, vs->temp_buffer, *range_length);
506}
507
509 char *path, const char *proto)
510{
511 if (hls->method || (proto && !av_strcasecmp(proto, "http"))) {
512 AVDictionary *opt = NULL;
513 int ret;
514
515 set_http_options(avf, &opt, hls);
516 av_dict_set(&opt, "method", "DELETE", 0);
517
518 ret = hlsenc_io_open(avf, &hls->http_delete, path, &opt);
519 av_dict_free(&opt);
520 if (ret < 0)
521 return hls->ignore_io_errors ? 1 : ret;
522
523 //Nothing to write
524 hlsenc_io_close(avf, &hls->http_delete, path);
525 } else if (unlink(path) < 0) {
526 av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n",
527 path, strerror(errno));
528 }
529 return 0;
530}
531
533 VariantStream *vs)
534{
535
536 HLSSegment *segment, *previous_segment = NULL;
537 float playlist_duration = 0.0f;
538 int ret = 0;
539 int segment_cnt = 0;
540 AVBPrint path;
541 const char *dirname = NULL;
542 char *dirname_r = NULL;
543 char *dirname_repl = NULL;
544 const char *vtt_dirname = NULL;
545 char *vtt_dirname_r = NULL;
546 const char *proto = NULL;
547
549
550 segment = vs->segments;
551 while (segment) {
552 playlist_duration += segment->duration;
553 segment = segment->next;
554 }
555
556 segment = vs->old_segments;
557 segment_cnt = 0;
558 while (segment) {
559 playlist_duration -= segment->duration;
560 previous_segment = segment;
561 segment = previous_segment->next;
562 segment_cnt++;
563 if (playlist_duration <= -previous_segment->duration) {
564 previous_segment->next = NULL;
565 break;
566 }
567 if (segment_cnt >= hls->hls_delete_threshold) {
568 previous_segment->next = NULL;
569 break;
570 }
571 }
572
573 if (segment && !hls->use_localtime_mkdir) {
574 dirname_r = hls->segment_filename ? av_strdup(hls->segment_filename): av_strdup(vs->avf->url);
575 dirname = av_dirname(dirname_r);
576 }
577
578 /* if %v is present in the file's directory
579 * all segment belongs to the same variant, so do it only once before the loop*/
580 if (dirname && av_stristr(dirname, "%v")) {
581 if (!vs->varname) {
582 if (replace_int_data_in_filename(&dirname_repl, dirname, 'v', segment->var_stream_idx) < 1) {
583 ret = AVERROR(EINVAL);
584 goto fail;
585 }
586 } else {
587 if (replace_str_data_in_filename(&dirname_repl, dirname, 'v', vs->varname) < 1) {
588 ret = AVERROR(EINVAL);
589 goto fail;
590 }
591 }
592
593 dirname = dirname_repl;
594 }
595
596 while (segment) {
597 av_log(hls, AV_LOG_DEBUG, "deleting old segment %s\n",
598 segment->filename);
599 if (!hls->use_localtime_mkdir) // segment->filename contains basename only
600 av_bprintf(&path, "%s/", dirname);
601 av_bprintf(&path, "%s", segment->filename);
602
603 if (!av_bprint_is_complete(&path)) {
604 ret = AVERROR(ENOMEM);
605 goto fail;
606 }
607
608 proto = avio_find_protocol_name(s->url);
609 if (ret = hls_delete_file(hls, s, path.str, proto))
610 goto fail;
611
612 if ((segment->sub_filename[0] != '\0')) {
613 vtt_dirname_r = av_strdup(vs->vtt_avf->url);
614 vtt_dirname = av_dirname(vtt_dirname_r);
615
616 av_bprint_clear(&path);
617 av_bprintf(&path, "%s/%s", vtt_dirname, segment->sub_filename);
618 av_freep(&vtt_dirname_r);
619
620 if (!av_bprint_is_complete(&path)) {
621 ret = AVERROR(ENOMEM);
622 goto fail;
623 }
624
625 if (ret = hls_delete_file(hls, s, path.str, proto))
626 goto fail;
627 }
628 av_bprint_clear(&path);
629 previous_segment = segment;
630 segment = previous_segment->next;
631 av_freep(&previous_segment);
632 }
633
634fail:
635 av_bprint_finalize(&path, NULL);
636 av_freep(&dirname_r);
637 av_freep(&dirname_repl);
638
639 return ret;
640}
641
643{
644 HLSContext *hls = s->priv_data;
645 int ret;
646 int len;
647 AVIOContext *pb;
648 uint8_t key[KEYSIZE];
649 char * key_basename_source = (hls->master_m3u8_url) ? hls->master_m3u8_url : s->url;
650
651 len = strlen(key_basename_source) + 4 + 1;
653 if (!hls->key_basename)
654 return AVERROR(ENOMEM);
655
656 av_strlcpy(hls->key_basename, key_basename_source, len);
657 av_strlcat(hls->key_basename, ".key", len);
658
659 if (hls->key_url) {
660 av_strlcpy(hls->key_file, hls->key_url, sizeof(hls->key_file));
661 av_strlcpy(hls->key_uri, hls->key_url, sizeof(hls->key_uri));
662 } else {
663 av_strlcpy(hls->key_file, hls->key_basename, sizeof(hls->key_file));
664 av_strlcpy(hls->key_uri, hls->key_basename, sizeof(hls->key_uri));
665 }
666
667 if (!*hls->iv_string) {
668 uint8_t iv[16] = { 0 };
669 char buf[33];
670
671 if (!hls->iv) {
672 AV_WB64(iv + 8, vs->sequence);
673 } else {
674 memcpy(iv, hls->iv, sizeof(iv));
675 }
676 ff_data_to_hex(buf, iv, sizeof(iv), 0);
677 memcpy(hls->iv_string, buf, sizeof(hls->iv_string));
678 }
679
680 if (!*hls->key_uri) {
681 av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
682 return AVERROR(EINVAL);
683 }
684
685 if (!*hls->key_file) {
686 av_log(hls, AV_LOG_ERROR, "no key file specified in key info file\n");
687 return AVERROR(EINVAL);
688 }
689
690 if (!*hls->key_string) {
692 if (!hls->key) {
693 if ((ret = av_random_bytes(key, sizeof(key))) < 0) {
694 av_log(s, AV_LOG_ERROR, "Cannot generate a strong random key\n");
695 return ret;
696 }
697 } else {
698 memcpy(key, hls->key, sizeof(key));
699 }
700
701 ff_data_to_hex(hls->key_string, key, sizeof(key), 0);
702 set_http_options(s, &options, hls);
703 ret = s->io_open(s, &pb, hls->key_file, AVIO_FLAG_WRITE, &options);
705 if (ret < 0)
706 return ret;
707 avio_seek(pb, 0, SEEK_CUR);
708 avio_write(pb, key, KEYSIZE);
709 ff_format_io_close(s, &pb);
710 }
711 return 0;
712}
713
714
716{
717 HLSContext *hls = s->priv_data;
718 int ret;
719 AVIOContext *pb;
720 uint8_t key[KEYSIZE];
722
723 set_http_options(s, &options, hls);
724 ret = s->io_open(s, &pb, hls->key_info_file, AVIO_FLAG_READ, &options);
726 if (ret < 0) {
727 av_log(hls, AV_LOG_ERROR,
728 "error opening key info file %s\n", hls->key_info_file);
729 return ret;
730 }
731
732 ff_get_line(pb, vs->key_uri, sizeof(vs->key_uri));
733 vs->key_uri[strcspn(vs->key_uri, "\r\n")] = '\0';
734
735 ff_get_line(pb, vs->key_file, sizeof(vs->key_file));
736 vs->key_file[strcspn(vs->key_file, "\r\n")] = '\0';
737
738 ff_get_line(pb, vs->iv_string, sizeof(vs->iv_string));
739 vs->iv_string[strcspn(vs->iv_string, "\r\n")] = '\0';
740
741 ff_format_io_close(s, &pb);
742
743 if (!*vs->key_uri) {
744 av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n");
745 return AVERROR(EINVAL);
746 }
747
748 if (!*vs->key_file) {
749 av_log(hls, AV_LOG_ERROR, "no key file specified in key info file\n");
750 return AVERROR(EINVAL);
751 }
752
753 set_http_options(s, &options, hls);
754 ret = s->io_open(s, &pb, vs->key_file, AVIO_FLAG_READ, &options);
756 if (ret < 0) {
757 av_log(hls, AV_LOG_ERROR, "error opening key file %s\n", vs->key_file);
758 return ret;
759 }
760
761 ret = avio_read(pb, key, sizeof(key));
762 ff_format_io_close(s, &pb);
763 if (ret != sizeof(key)) {
764 av_log(hls, AV_LOG_ERROR, "error reading key file %s\n", vs->key_file);
765 if (ret >= 0 || ret == AVERROR_EOF)
766 ret = AVERROR(EINVAL);
767 return ret;
768 }
769 ff_data_to_hex(vs->key_string, key, sizeof(key), 0);
770
771 return 0;
772}
773
775{
777 HLSContext *hls = s->priv_data;
778 AVFormatContext *oc;
779 AVFormatContext *vtt_oc = NULL;
780 int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
781 int remaining_options;
782 int i, ret;
783
785 if (ret < 0)
786 return ret;
787 oc = vs->avf;
788
789 oc->url = av_strdup("");
790 if (!oc->url)
791 return AVERROR(ENOMEM);
792
793 oc->interrupt_callback = s->interrupt_callback;
794 oc->max_delay = s->max_delay;
795 oc->opaque = s->opaque;
796 oc->io_open = s->io_open;
797 oc->io_close2 = s->io_close2;
798 oc->strict_std_compliance = s->strict_std_compliance;
799 oc->flags = s->flags;
800 av_dict_copy(&oc->metadata, s->metadata, 0);
801
802 if (vs->vtt_oformat) {
804 if (ret < 0)
805 return ret;
806 vtt_oc = vs->vtt_avf;
807 vtt_oc->flags = s->flags;
808 av_dict_copy(&vtt_oc->metadata, s->metadata, 0);
809 }
810
811 for (i = 0; i < vs->nb_streams; i++) {
812 AVStream *st;
813 AVFormatContext *loc;
815 loc = vtt_oc;
816 else
817 loc = oc;
818
819 if (!(st = avformat_new_stream(loc, NULL)))
820 return AVERROR(ENOMEM);
822 if (ret < 0)
823 return ret;
824 if (!oc->oformat->codec_tag ||
828 } else {
829 st->codecpar->codec_tag = 0;
830 }
831
833 st->time_base = vs->streams[i]->time_base;
834 av_dict_copy(&st->metadata, vs->streams[i]->metadata, 0);
835 st->id = vs->streams[i]->id;
836 }
837
838 for (i = 0; i < s->nb_programs; i++) {
839 ret = av_program_copy(oc, (const AVFormatContext *)s, s->programs[i]->id, 0);
840 if (ret < 0) {
841 av_log(s, AV_LOG_ERROR, "unable to transfer program %d to child muxer\n", s->programs[i]->id);
842 return ret;
843 }
844 }
845
846 vs->start_pos = 0;
847 vs->new_start = 1;
848
849 if (hls->segment_type == SEGMENT_TYPE_FMP4 && hls->max_seg_size > 0) {
850 if (hls->http_persistent > 0) {
851 //TODO: Support fragment fmp4 for http persistent in HLS muxer.
852 av_log(s, AV_LOG_WARNING, "http persistent mode is currently unsupported for fragment mp4 in the HLS muxer.\n");
853 }
854 if (hls->max_seg_size > 0) {
855 av_log(s, AV_LOG_WARNING, "Multi-file byterange mode is currently unsupported in the HLS muxer.\n");
857 }
858 }
859
860 if ((ret = avio_open_dyn_buf(&oc->pb)) < 0)
861 return ret;
862
863 if (hls->segment_type == SEGMENT_TYPE_FMP4) {
864 set_http_options(s, &options, hls);
865 if (byterange_mode) {
866 ret = hlsenc_io_open(s, &vs->out, vs->basename, &options);
867 } else {
868 ret = hlsenc_io_open(s, &vs->out, vs->base_output_dirname, &options);
869 }
871 }
872 if (ret < 0) {
873 av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", vs->fmp4_init_filename);
874 return ret;
875 }
876
878 if (hls->segment_type == SEGMENT_TYPE_FMP4) {
879 av_dict_set(&options, "fflags", "-autobsf", 0);
880 av_dict_set(&options, "movflags", "+frag_custom+dash+delay_moov", AV_DICT_APPEND);
881 } else {
882 /* We only require one PAT/PMT per segment. */
883 char period[21];
884 snprintf(period, sizeof(period), "%d", (INT_MAX / 2) - 1);
885 av_dict_set(&options, "sdt_period", period, AV_DICT_DONT_OVERWRITE);
886 av_dict_set(&options, "pat_period", period, AV_DICT_DONT_OVERWRITE);
887 }
888 ret = avformat_init_output(oc, &options);
889 remaining_options = av_dict_count(options);
891 if (ret < 0)
892 return ret;
893 if (remaining_options) {
894 av_log(s, AV_LOG_ERROR, "Some of the provided format options are not recognized\n");
895 return AVERROR(EINVAL);
896 }
897 avio_flush(oc->pb);
898 return 0;
899}
900
902{
903 while (segment) {
904 if (!av_strcasecmp(segment->filename,filename))
905 return segment;
906 segment = segment->next;
907 }
908 return (HLSSegment *) NULL;
909}
910
912 VariantStream *vs,
914{
917 char * new_url = av_strdup(vs->current_segment_final_filename_fmt);
918 if (!new_url) {
919 return AVERROR(ENOMEM);
920 }
921 ff_format_set_url(vs->avf, new_url);
923 char *filename = NULL;
924 if (replace_int_data_in_filename(&filename, vs->avf->url, 's', pos + size) < 1) {
925 av_log(hls, AV_LOG_ERROR,
926 "Invalid second level segment filename template '%s', "
927 "you can try to remove second_level_segment_size flag\n",
928 vs->avf->url);
929 av_freep(&filename);
930 return AVERROR(EINVAL);
931 }
932 ff_format_set_url(vs->avf, filename);
933 }
935 char *filename = NULL;
936 if (replace_int_data_in_filename(&filename, vs->avf->url,
938 av_log(hls, AV_LOG_ERROR,
939 "Invalid second level segment filename template '%s', "
940 "you can try to remove second_level_segment_duration flag\n",
941 vs->avf->url);
942 av_freep(&filename);
943 return AVERROR(EINVAL);
944 }
945 ff_format_set_url(vs->avf, filename);
946 }
947 }
948 return 0;
949}
950
952{
953 int ret = 0;
954
956 av_log(hls, AV_LOG_ERROR,
957 "second_level_segment_duration hls_flag requires strftime to be true\n");
958 ret = AVERROR(EINVAL);
959 }
961 av_log(hls, AV_LOG_ERROR,
962 "second_level_segment_size hls_flag requires strfime to be true\n");
963 ret = AVERROR(EINVAL);
964 }
966 av_log(hls, AV_LOG_ERROR,
967 "second_level_segment_index hls_flag requires strftime to be true\n");
968 ret = AVERROR(EINVAL);
969 }
970
971 return ret;
972}
973
975{
976 const char *proto = avio_find_protocol_name(vs->basename);
977 int segment_renaming_ok = proto && !strcmp(proto, "file");
978 int ret = 0;
979
980 if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) && !segment_renaming_ok) {
981 av_log(hls, AV_LOG_ERROR,
982 "second_level_segment_duration hls_flag works only with file protocol segment names\n");
983 ret = AVERROR(EINVAL);
984 }
985 if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) && !segment_renaming_ok) {
986 av_log(hls, AV_LOG_ERROR,
987 "second_level_segment_size hls_flag works only with file protocol segment names\n");
988 ret = AVERROR(EINVAL);
989 }
990
991 return ret;
992}
993
994static void sls_flag_file_rename(HLSContext *hls, VariantStream *vs, char *old_filename) {
997 ff_rename(old_filename, vs->avf->url, hls);
998 }
999}
1000
1002{
1003 if (c->flags & HLS_SECOND_LEVEL_SEGMENT_INDEX) {
1004 char *filename = NULL;
1005 if (replace_int_data_in_filename(&filename,
1006 oc->url, 'd', vs->sequence) < 1) {
1007 av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1008 "you can try to remove second_level_segment_index flag\n",
1009 oc->url);
1010 av_freep(&filename);
1011 return AVERROR(EINVAL);
1012 }
1013 ff_format_set_url(oc, filename);
1014 }
1018 if (c->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) {
1019 char *filename = NULL;
1020 if (replace_int_data_in_filename(&filename, oc->url, 's', 0) < 1) {
1021 av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1022 "you can try to remove second_level_segment_size flag\n",
1023 oc->url);
1024 av_freep(&filename);
1025 return AVERROR(EINVAL);
1026 }
1027 ff_format_set_url(oc, filename);
1028 }
1029 if (c->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) {
1030 char *filename = NULL;
1031 if (replace_int_data_in_filename(&filename, oc->url, 't', 0) < 1) {
1032 av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', "
1033 "you can try to remove second_level_segment_duration flag\n",
1034 oc->url);
1035 av_freep(&filename);
1036 return AVERROR(EINVAL);
1037 }
1038 ff_format_set_url(oc, filename);
1039 }
1040 }
1041 return 0;
1042}
1043
1044/* Create a new segment and append it to the segment list */
1046 VariantStream *vs, double duration, int64_t pos,
1047 int64_t size)
1048{
1049 HLSSegment en0 = {0};
1050 HLSSegment *en = &en0;
1051 const char *filename;
1052 int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
1053 int ret;
1054 AVBPrint bp;
1055
1056 vs->total_size += size;
1057 vs->total_duration += duration;
1058 if (duration > 0.5) {
1059 // Don't include the final, possibly very short segment in the
1060 // calculation of the max bitrate.
1061 int cur_bitrate = (int)(8 * size / duration);
1062 if (cur_bitrate > vs->max_bitrate)
1063 vs->max_bitrate = cur_bitrate;
1064 }
1065 if (vs->total_duration > 0)
1066 vs->avg_bitrate = (int)(8 * vs->total_size / vs->total_duration);
1067
1069 ret = sls_flags_filename_process(s, hls, vs, duration, pos, size);
1070 if (ret < 0)
1071 return ret;
1072
1073 filename = av_basename(vs->avf->url);
1074
1075 if (hls->use_localtime_mkdir) {
1076 filename = vs->avf->url;
1077 }
1078 if (vs->nb_entries <= 5000 && (find_segment_by_filename(vs->segments, filename) || find_segment_by_filename(vs->old_segments, filename))
1079 && !byterange_mode) {
1080 av_log(hls, AV_LOG_WARNING, "Duplicated segment filename detected: %s\n", filename);
1081 }
1082
1084 av_bprintf(&bp, "%s%c", filename, 0);
1085 av_bprintf(&bp, "%s%c", vs->has_subtitle ? av_basename(vs->vtt_avf->url) : "", 0);
1086
1087 en->duration = duration;
1088 en->pos = pos;
1089 en->size = size;
1090
1091 if (vs->discontinuity) {
1092 en->discont = 1;
1093 vs->discontinuity = 0;
1094 }
1095
1096 if (hls->key_info_file || hls->encrypt) {
1097 av_bprintf(&bp, "%s%c", vs->key_uri, 0);
1098 av_strlcpy(en->iv_string, vs->iv_string, sizeof(en->iv_string));
1099 } else {
1100 av_bprint_chars(&bp, 0, 1);
1101 }
1102
1103 en = ff_bprint_finalize_as_fam(&bp, &en0, offsetof(HLSSegment, buf));
1104 if (!en)
1105 return AVERROR(ENOMEM);
1106#define NEXT(s) ((s) + strlen(s) + 1)
1107 en->filename = en->buf;
1108 en->sub_filename = NEXT(en->filename);
1109 en->key_uri = NEXT(en->sub_filename);
1110#undef NEXT
1111
1112 if (!vs->segments)
1113 vs->segments = en;
1114 else
1115 vs->last_segment->next = en;
1116
1117 vs->last_segment = en;
1118
1119 // EVENT or VOD playlists imply sliding window cannot be used
1120 if (hls->pl_type != PLAYLIST_TYPE_NONE)
1121 hls->max_nb_segments = 0;
1122
1123 if (hls->max_nb_segments && vs->nb_entries >= hls->max_nb_segments) {
1124 en = vs->segments;
1127 vs->segments = en->next;
1128 if (en && hls->flags & HLS_DELETE_SEGMENTS &&
1129 !(hls->flags & HLS_SINGLE_FILE)) {
1130 en->next = vs->old_segments;
1131 vs->old_segments = en;
1132 if ((ret = hls_delete_old_segments(s, hls, vs)) < 0)
1133 return ret;
1134 } else
1135 av_freep(&en);
1136 } else
1137 vs->nb_entries++;
1138
1139 if (hls->max_seg_size > 0) {
1140 return 0;
1141 }
1142 vs->sequence++;
1143
1144 return 0;
1145}
1146
1147static int extract_segment_number(const char *filename)
1148{
1149 const char *dot = strrchr(filename, '.');
1150 const char *num_start;
1151 char *end;
1152 long value;
1153
1154 if (!dot)
1155 return -1;
1156 if (dot == filename)
1157 return -1;
1158
1159 num_start = dot;
1160 while (num_start > filename &&
1161 num_start[-1] >= '0' && num_start[-1] <= '9')
1162 num_start--;
1163 if (num_start == dot)
1164 return -1;
1165
1166 errno = 0;
1167 value = strtol(num_start, &end, 10);
1168 if (errno == ERANGE || end != dot || value > INT_MAX)
1169 return -1;
1170
1171 return (int)value;
1172}
1173
1174static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs)
1175{
1176 HLSContext *hls = s->priv_data;
1177 AVIOContext *in;
1178 int ret = 0, is_segment = 0;
1179 int64_t new_start_pos;
1180 char line[MAX_URL_SIZE];
1181 const char *ptr;
1182 const char *end;
1183 double discont_program_date_time = 0;
1184
1185 if ((ret = s->io_open(s, &in, url, AVIO_FLAG_READ, NULL)) < 0)
1186 return ret;
1187
1188 ff_get_chomp_line(in, line, sizeof(line));
1189 if (strcmp(line, "#EXTM3U")) {
1190 ret = AVERROR_INVALIDDATA;
1191 goto fail;
1192 }
1193
1194 vs->discontinuity = 0;
1195 while (!avio_feof(in)) {
1196 ff_get_chomp_line(in, line, sizeof(line));
1197 if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
1198 int64_t tmp_sequence = strtoll(ptr, NULL, 10);
1199 if (tmp_sequence < vs->sequence)
1201 "Found playlist sequence number was smaller """
1202 "than specified start sequence number: %"PRId64" < %"PRId64", "
1203 "omitting\n", tmp_sequence, hls->start_sequence);
1204 else {
1205 av_log(hls, AV_LOG_DEBUG, "Found playlist sequence number: %"PRId64"\n", tmp_sequence);
1206 vs->sequence = tmp_sequence;
1207 }
1208 } else if (av_strstart(line, "#EXT-X-DISCONTINUITY", &ptr)) {
1209 is_segment = 1;
1210 vs->discontinuity = 1;
1211 } else if (av_strstart(line, "#EXTINF:", &ptr)) {
1212 is_segment = 1;
1213 vs->duration = atof(ptr);
1214 } else if (av_stristart(line, "#EXT-X-KEY:", &ptr)) {
1215 ptr = av_stristr(line, "URI=\"");
1216 if (ptr) {
1217 ptr += strlen("URI=\"");
1218 end = strchr(ptr, '"');
1219 if (end) {
1220 av_strlcpy(vs->key_uri, ptr,
1221 FFMIN(end - ptr + 1, sizeof(vs->key_uri)));
1222 } else {
1223 ret = AVERROR_INVALIDDATA;
1224 goto fail;
1225 }
1226 }
1227
1228 ptr = av_stristr(line, "IV=0x");
1229 if (ptr) {
1230 ptr += strlen("IV=0x");
1231 end = av_stristr(ptr, ",");
1232 if (end) {
1233 av_strlcpy(vs->iv_string, ptr, FFMIN(end - ptr + 1, sizeof(vs->iv_string)));
1234 } else {
1235 av_strlcpy(vs->iv_string, ptr, sizeof(vs->iv_string));
1236 }
1237 }
1238 } else if (av_strstart(line, "#EXT-X-PROGRAM-DATE-TIME:", &ptr)) {
1239 struct tm program_date_time = { 0 };
1240 double ms = 0;
1241 char *q = av_small_strptime(ptr, "%Y-%m-%dT%H:%M:%S", &program_date_time);
1242
1243 if (!q) {
1244 ret = AVERROR_INVALIDDATA;
1245 goto fail;
1246 }
1247 if (*q == '.')
1248 ms = atof(q + 1);
1249 program_date_time.tm_isdst = -1;
1250
1251 errno = 0;
1252 time_t t = mktime(&program_date_time);
1253 if (t == (time_t)-1 && errno == EOVERFLOW) {
1254 ret = AVERROR_INVALIDDATA;
1255 goto fail;
1256 }
1257 discont_program_date_time = t;
1258
1259 discont_program_date_time += (double)(ms / 1000);
1260 } else if (av_strstart(line, "#", NULL)) {
1261 continue;
1262 } else if (line[0]) {
1263 if (is_segment) {
1264 char *new_file = av_strdup(line);
1265 if (!new_file) {
1266 ret = AVERROR(ENOMEM);
1267 goto fail;
1268 }
1269 ff_format_set_url(vs->avf, new_file);
1270
1271 if (vs->has_subtitle) {
1272 int vtt_index = extract_segment_number(line);
1273 const char *vtt_basename = av_basename(vs->vtt_basename);
1274 char *vtt_file = NULL;
1275 ret = replace_int_data_in_filename(&vtt_file, vtt_basename, 'd', vtt_index);
1276 if (ret < 0 || !vtt_file) {
1277 ret = AVERROR(ENOMEM);
1278 goto fail;
1279 }
1280
1281 ff_format_set_url(vs->vtt_avf, vtt_file);
1282 }
1283
1284 is_segment = 0;
1285 new_start_pos = avio_tell(vs->avf->pb);
1286 vs->size = new_start_pos - vs->start_pos;
1287 ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size);
1288 if (discont_program_date_time) {
1289 vs->last_segment->discont_program_date_time = discont_program_date_time;
1290 discont_program_date_time += vs->duration;
1291 }
1292 if (ret < 0)
1293 goto fail;
1294 vs->start_pos = new_start_pos;
1295 }
1296 }
1297 }
1298
1299fail:
1300 ff_format_io_close(s, &in);
1301 return ret;
1302}
1303
1305{
1306 HLSSegment *en;
1307
1308 while (p) {
1309 en = p;
1310 p = p->next;
1311 av_freep(&en);
1312 }
1313}
1314
1316{
1317 size_t len = strlen(oc->url);
1318 char *final_filename = av_strdup(oc->url);
1319 int ret;
1320
1321 if (!final_filename)
1322 return AVERROR(ENOMEM);
1323 final_filename[len-4] = '\0';
1324 ret = ff_rename(oc->url, final_filename, s);
1325 oc->url[len-4] = '\0';
1326 av_freep(&final_filename);
1327 return ret;
1328}
1329
1330static const char* get_relative_url(const char *master_url, const char *media_url)
1331{
1332 const char *p = strrchr(master_url, '/');
1333 size_t base_len = 0;
1334
1335 if (!p) p = strrchr(master_url, '\\');
1336
1337 if (p) {
1338 base_len = p - master_url;
1339 if (av_strncasecmp(master_url, media_url, base_len)) {
1340 av_log(NULL, AV_LOG_WARNING, "Unable to find relative url\n");
1341 return NULL;
1342 }
1343 } else {
1344 return media_url;
1345 }
1346
1347 return media_url + base_len + 1;
1348}
1349
1351{
1355 );
1356
1357 if (stream->codecpar->bit_rate)
1358 return stream->codecpar->bit_rate;
1359 else if (sd) {
1360 AVCPBProperties *props = (AVCPBProperties*)sd->data;
1361 return props->max_bitrate;
1362 }
1363
1364 return 0;
1365}
1366
1368 VariantStream * const input_vs,
1369 int final)
1370{
1371 HLSContext *hls = s->priv_data;
1372 VariantStream *vs, *temp_vs;
1373 AVStream *vid_st, *aud_st;
1375 unsigned int i, j;
1376 int ret, bandwidth, avg_bandwidth;
1377 const char *m3u8_rel_name = NULL;
1378 const char *vtt_m3u8_rel_name = NULL;
1379 const char *ccgroup;
1380 const char *sgroup = NULL;
1382 const char *proto = avio_find_protocol_name(hls->master_m3u8_url);
1383 int is_file_proto = proto && !strcmp(proto, "file");
1384 int use_temp_file = is_file_proto && ((hls->flags & HLS_TEMP_FILE) || hls->master_publish_rate);
1385 char temp_filename[MAX_URL_SIZE];
1386 int nb_channels;
1387
1388 input_vs->m3u8_created = 1;
1389 if (!hls->master_m3u8_created) {
1390 /* For the first time, wait until all the media playlists are created */
1391 for (i = 0; i < hls->nb_varstreams; i++)
1392 if (!hls->var_streams[i].m3u8_created)
1393 return 0;
1394 } else {
1395 /* Keep publishing the master playlist at the configured rate */
1396 if ((&hls->var_streams[0] != input_vs || !hls->master_publish_rate ||
1397 input_vs->number % hls->master_publish_rate) && !final)
1398 return 0;
1399 }
1400
1401 set_http_options(s, &options, hls);
1402 snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : "%s", hls->master_m3u8_url);
1403 ret = hlsenc_io_open(s, &hls->m3u8_out, temp_filename, &options);
1405 if (ret < 0) {
1406 av_log(s, AV_LOG_ERROR, "Failed to open master play list file '%s'\n",
1407 temp_filename);
1408 goto fail;
1409 }
1410
1412
1413 for (i = 0; i < hls->nb_ccstreams; i++) {
1414 ccs = &(hls->cc_streams[i]);
1415 avio_printf(hls->m3u8_out, "#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS");
1416 avio_printf(hls->m3u8_out, ",GROUP-ID=\"%s\"", ccs->ccgroup);
1417 avio_printf(hls->m3u8_out, ",NAME=\"%s\"", ccs->instreamid);
1418 if (ccs->language)
1419 avio_printf(hls->m3u8_out, ",LANGUAGE=\"%s\"", ccs->language);
1420 avio_printf(hls->m3u8_out, ",INSTREAM-ID=\"%s\"\n", ccs->instreamid);
1421 }
1422
1423 /* For audio only variant streams add #EXT-X-MEDIA tag with attributes*/
1424 for (i = 0; i < hls->nb_varstreams; i++) {
1425 vs = &(hls->var_streams[i]);
1426
1427 if (vs->has_video || vs->has_subtitle || !vs->agroup)
1428 continue;
1429
1430 m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->m3u8_name);
1431 if (!m3u8_rel_name) {
1432 av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
1433 goto fail;
1434 }
1435 nb_channels = 0;
1436 for (j = 0; j < vs->nb_streams; j++)
1438 if (vs->streams[j]->codecpar->ch_layout.nb_channels > nb_channels)
1439 nb_channels = vs->streams[j]->codecpar->ch_layout.nb_channels;
1440
1441 ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name, vs->language, i, hls->has_default_key ? vs->is_default : 1, nb_channels);
1442 }
1443
1444 /* For variant streams with video add #EXT-X-STREAM-INF tag with attributes*/
1445 for (i = 0; i < hls->nb_varstreams; i++) {
1446 vs = &(hls->var_streams[i]);
1447
1448 m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->m3u8_name);
1449 if (!m3u8_rel_name) {
1450 av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n");
1451 goto fail;
1452 }
1453
1454 vid_st = NULL;
1455 aud_st = NULL;
1456 for (j = 0; j < vs->nb_streams; j++) {
1458 vid_st = vs->streams[j];
1459 else if (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
1460 aud_st = vs->streams[j];
1461 }
1462
1463 if (!vid_st && !aud_st) {
1464 av_log(s, AV_LOG_WARNING, "Media stream not found\n");
1465 continue;
1466 }
1467
1468 /**
1469 * Traverse through the list of audio only rendition streams and find
1470 * the rendition which has highest bitrate in the same audio group
1471 */
1472 if (vs->agroup) {
1473 for (j = 0; j < hls->nb_varstreams; j++) {
1474 temp_vs = &(hls->var_streams[j]);
1475 if (!temp_vs->has_video && !temp_vs->has_subtitle &&
1476 temp_vs->agroup &&
1477 !av_strcasecmp(temp_vs->agroup, vs->agroup)) {
1478 if (!aud_st)
1479 aud_st = temp_vs->streams[0];
1480 if (temp_vs->streams[0]->codecpar->bit_rate >
1481 aud_st->codecpar->bit_rate)
1482 aud_st = temp_vs->streams[0];
1483 }
1484 }
1485 }
1486
1487 if (final) {
1488 bandwidth = vs->max_bitrate;
1489 avg_bandwidth = vs->avg_bitrate;
1490 } else {
1491 bandwidth = 0;
1492 avg_bandwidth = 0;
1493 if (vid_st)
1494 bandwidth += get_stream_bit_rate(vid_st);
1495 if (aud_st)
1496 bandwidth += get_stream_bit_rate(aud_st);
1497 bandwidth += bandwidth / 10;
1498 }
1499
1500 ccgroup = NULL;
1501 if (vid_st && vs->ccgroup) {
1502 /* check if this group name is available in the cc map string */
1503 for (j = 0; j < hls->nb_ccstreams; j++) {
1504 ccs = &(hls->cc_streams[j]);
1505 if (!av_strcasecmp(ccs->ccgroup, vs->ccgroup)) {
1506 ccgroup = vs->ccgroup;
1507 break;
1508 }
1509 }
1510 if (j == hls->nb_ccstreams)
1511 av_log(s, AV_LOG_WARNING, "mapping ccgroup %s not found\n",
1512 vs->ccgroup);
1513 }
1514
1515 if (vid_st && vs->sgroup) {
1516 sgroup = vs->sgroup;
1517 vtt_m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->vtt_m3u8_name);
1518 if (!vtt_m3u8_rel_name) {
1519 av_log(s, AV_LOG_WARNING, "Unable to find relative subtitle URL\n");
1520 break;
1521 }
1522
1523 ff_hls_write_subtitle_rendition(hls->m3u8_out, sgroup, vtt_m3u8_rel_name, vs->language,
1524 vs->subtitle_varname, i, hls->has_default_key ? vs->is_default : 1);
1525 }
1526
1527 if (!hls->has_default_key || !hls->has_video_m3u8) {
1528 ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, avg_bandwidth, m3u8_rel_name,
1529 aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup, sgroup);
1530 } else {
1531 if (vid_st) {
1532 ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, avg_bandwidth, m3u8_rel_name,
1533 aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup, sgroup);
1534 }
1535 }
1536 }
1537fail:
1538 if (ret >=0)
1539 hls->master_m3u8_created = 1;
1540 hlsenc_io_close(s, &hls->m3u8_out, temp_filename);
1541 if (use_temp_file)
1542 ff_rename(temp_filename, hls->master_m3u8_url, s);
1543
1544 return ret;
1545}
1546
1547static int hls_window(AVFormatContext *s, int last, VariantStream *vs)
1548{
1549 HLSContext *hls = s->priv_data;
1550 HLSSegment *en;
1551 int target_duration = 0;
1552 int ret = 0;
1553 char temp_filename[MAX_URL_SIZE];
1554 char temp_vtt_filename[MAX_URL_SIZE];
1555 int64_t sequence = FFMAX(hls->start_sequence, vs->sequence - vs->nb_entries);
1556 const char *proto = avio_find_protocol_name(vs->m3u8_name);
1557 int is_file_proto = proto && !strcmp(proto, "file");
1558 int use_temp_file = is_file_proto && ((hls->flags & HLS_TEMP_FILE) || !(hls->pl_type == PLAYLIST_TYPE_VOD));
1559 static unsigned warned_non_file;
1560 const char *key_uri = NULL;
1561 char *iv_string = NULL;
1563 double prog_date_time = vs->initial_prog_date_time;
1564 double *prog_date_time_p = (hls->flags & HLS_PROGRAM_DATE_TIME) ? &prog_date_time : NULL;
1565 int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
1566
1567 hls->version = 2;
1568 if (!(hls->flags & HLS_ROUND_DURATIONS)) {
1569 hls->version = 3;
1570 }
1571
1572 if (byterange_mode) {
1573 hls->version = 4;
1574 sequence = 0;
1575 }
1576
1577 if (hls->flags & HLS_I_FRAMES_ONLY) {
1578 hls->version = 4;
1579 }
1580
1581 if (hls->flags & HLS_INDEPENDENT_SEGMENTS) {
1582 hls->version = 6;
1583 }
1584
1585 if (hls->segment_type == SEGMENT_TYPE_FMP4) {
1586 hls->version = 7;
1587 }
1588
1589 if (!is_file_proto && (hls->flags & HLS_TEMP_FILE) && !warned_non_file++)
1590 av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
1591
1592 set_http_options(s, &options, hls);
1593 snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : "%s", vs->m3u8_name);
1594 ret = hlsenc_io_open(s, byterange_mode ? &hls->m3u8_out : &vs->out, temp_filename, &options);
1596 if (ret < 0) {
1597 goto fail;
1598 }
1599
1600 for (en = vs->segments; en; en = en->next) {
1601 if (target_duration <= en->duration)
1602 target_duration = lrint(en->duration);
1603 }
1604
1605 vs->discontinuity_set = 0;
1606 ff_hls_write_playlist_header(byterange_mode ? hls->m3u8_out : vs->out, hls->version, hls->allowcache,
1607 target_duration, sequence, hls->pl_type, hls->flags & HLS_I_FRAMES_ONLY);
1608
1609 if ((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && vs->discontinuity_set==0) {
1610 avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-DISCONTINUITY\n");
1611 vs->discontinuity_set = 1;
1612 }
1613 if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) {
1614 avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-INDEPENDENT-SEGMENTS\n");
1615 }
1616 for (en = vs->segments; en; en = en->next) {
1617 if ((hls->encrypt || hls->key_info_file) && (!key_uri || strcmp(en->key_uri, key_uri) ||
1618 av_strcasecmp(en->iv_string, iv_string))) {
1619 avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri);
1620 if (*en->iv_string)
1621 avio_printf(byterange_mode ? hls->m3u8_out : vs->out, ",IV=0x%s", en->iv_string);
1622 avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "\n");
1623 key_uri = en->key_uri;
1624 iv_string = en->iv_string;
1625 }
1626
1627 if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == vs->segments)) {
1628 ff_hls_write_init_file(byterange_mode ? hls->m3u8_out : vs->out, (hls->flags & HLS_SINGLE_FILE) ? en->filename : vs->fmp4_init_filename,
1629 hls->flags & HLS_SINGLE_FILE, vs->init_range_length, 0);
1630 }
1631
1632 ret = ff_hls_write_file_entry(byterange_mode ? hls->m3u8_out : vs->out, en->discont, byterange_mode,
1634 en->size, en->pos, hls->baseurl,
1635 en->filename,
1636 en->discont_program_date_time ? &en->discont_program_date_time : prog_date_time_p,
1637 hls->flags & HLS_I_FRAMES_ONLY);
1640 if (ret < 0) {
1641 av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
1642 }
1643 }
1644
1645 if (last && (hls->flags & HLS_OMIT_ENDLIST)==0)
1646 ff_hls_write_end_list(byterange_mode ? hls->m3u8_out : vs->out);
1647
1648 if (vs->vtt_m3u8_name) {
1649 set_http_options(vs->vtt_avf, &options, hls);
1650 snprintf(temp_vtt_filename, sizeof(temp_vtt_filename), use_temp_file ? "%s.tmp" : "%s", vs->vtt_m3u8_name);
1651 ret = hlsenc_io_open(s, &hls->sub_m3u8_out, temp_vtt_filename, &options);
1653 if (ret < 0) {
1654 goto fail;
1655 }
1657 target_duration, sequence, PLAYLIST_TYPE_NONE, 0);
1658 for (en = vs->segments; en; en = en->next) {
1659 ret = ff_hls_write_file_entry(hls->sub_m3u8_out, en->discont, byterange_mode,
1660 en->duration, 0, en->size, en->pos,
1661 hls->baseurl, en->sub_filename, NULL, 0);
1662 if (ret < 0) {
1663 av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
1664 }
1665 }
1666
1667 if (last && !(hls->flags & HLS_OMIT_ENDLIST))
1669
1670 }
1671
1672fail:
1674 ret = hlsenc_io_close(s, byterange_mode ? &hls->m3u8_out : &vs->out, temp_filename);
1675 if (ret < 0) {
1676 return ret;
1677 }
1679 if (use_temp_file) {
1680 ff_rename(temp_filename, vs->m3u8_name, s);
1681 if (vs->vtt_m3u8_name)
1682 ff_rename(temp_vtt_filename, vs->vtt_m3u8_name, s);
1683 }
1684 if (ret >= 0 && hls->master_pl_name)
1685 if (create_master_playlist(s, vs, last) < 0)
1686 av_log(s, AV_LOG_WARNING, "Master playlist creation failed\n");
1687
1688 return ret;
1689}
1690
1692{
1693 HLSContext *c = s->priv_data;
1694 AVFormatContext *oc = vs->avf;
1695 AVFormatContext *vtt_oc = vs->vtt_avf;
1697 const char *proto = NULL;
1698 int use_temp_file = 0;
1699 char iv_string[KEYSIZE*2 + 1];
1700 int err = 0;
1701
1702 if (c->flags & HLS_SINGLE_FILE) {
1703 char *new_name = av_strdup(vs->basename);
1704 if (!new_name)
1705 return AVERROR(ENOMEM);
1706 ff_format_set_url(oc, new_name);
1707 if (vs->vtt_basename) {
1708 new_name = av_strdup(vs->vtt_basename);
1709 if (!new_name)
1710 return AVERROR(ENOMEM);
1711 ff_format_set_url(vtt_oc, new_name);
1712 }
1713 } else if (c->max_seg_size > 0) {
1714 char *filename = NULL;
1715 if (replace_int_data_in_filename(&filename,
1716 vs->basename, 'd', vs->sequence) < 1) {
1717 av_freep(&filename);
1718 av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -strftime 1 with it\n", vs->basename);
1719 return AVERROR(EINVAL);
1720 }
1721 ff_format_set_url(oc, filename);
1722 } else {
1723 if (c->use_localtime) {
1724 int r;
1725 char *expanded = NULL;
1726
1727 r = strftime_expand(vs->basename, &expanded);
1728 if (r < 0) {
1729 av_log(oc, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
1730 return r;
1731 }
1732 ff_format_set_url(oc, expanded);
1733
1734 err = sls_flag_use_localtime_filename(oc, c, vs);
1735 if (err < 0) {
1736 return AVERROR(ENOMEM);
1737 }
1738
1739 if (c->use_localtime_mkdir) {
1740 const char *dir;
1741 char *fn_copy = av_strdup(oc->url);
1742 if (!fn_copy)
1743 return AVERROR(ENOMEM);
1744 dir = av_dirname(fn_copy);
1745 if (ff_mkdir_p(dir) == -1 && errno != EEXIST) {
1746 av_log(oc, AV_LOG_ERROR, "Could not create directory %s with use_localtime_mkdir\n", dir);
1747 av_freep(&fn_copy);
1748 return AVERROR(errno);
1749 }
1750 av_freep(&fn_copy);
1751 }
1752 } else {
1753 char *filename = NULL;
1754 if (replace_int_data_in_filename(&filename,
1755 vs->basename, 'd', vs->sequence) < 1) {
1756 av_freep(&filename);
1757 av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -strftime 1 with it\n", vs->basename);
1758 return AVERROR(EINVAL);
1759 }
1760 ff_format_set_url(oc, filename);
1761 }
1762 if (vs->vtt_basename) {
1763 char *filename = NULL;
1764 if (replace_int_data_in_filename(&filename,
1765 vs->vtt_basename, 'd', vs->sequence) < 1) {
1766 av_freep(&filename);
1767 av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", vs->vtt_basename);
1768 return AVERROR(EINVAL);
1769 }
1770 ff_format_set_url(vtt_oc, filename);
1771 }
1772 }
1773
1774 proto = avio_find_protocol_name(oc->url);
1775 use_temp_file = proto && !strcmp(proto, "file") && (c->flags & HLS_TEMP_FILE);
1776
1777 if (use_temp_file) {
1778 char *new_name = av_asprintf("%s.tmp", oc->url);
1779 if (!new_name)
1780 return AVERROR(ENOMEM);
1781 ff_format_set_url(oc, new_name);
1782 }
1783
1784 if (c->key_info_file || c->encrypt) {
1785 if (c->segment_type == SEGMENT_TYPE_FMP4) {
1786 av_log(s, AV_LOG_ERROR, "Encrypted fmp4 not yet supported\n");
1787 return AVERROR_PATCHWELCOME;
1788 }
1789
1790 if (c->key_info_file && c->encrypt) {
1791 av_log(s, AV_LOG_WARNING, "Cannot use both -hls_key_info_file and -hls_enc,"
1792 " ignoring -hls_enc\n");
1793 }
1794
1795 if (!vs->encrypt_started || (c->flags & HLS_PERIODIC_REKEY)) {
1796 if (c->key_info_file) {
1797 if ((err = hls_encryption_start(s, vs)) < 0)
1798 goto fail;
1799 } else {
1800 if (!c->encrypt_started) {
1801 if ((err = do_encrypt(s, vs)) < 0)
1802 goto fail;
1803 c->encrypt_started = 1;
1804 }
1805 av_strlcpy(vs->key_uri, c->key_uri, sizeof(vs->key_uri));
1806 av_strlcpy(vs->key_string, c->key_string, sizeof(vs->key_string));
1807 av_strlcpy(vs->iv_string, c->iv_string, sizeof(vs->iv_string));
1808 }
1809 vs->encrypt_started = 1;
1810 }
1811 err = av_strlcpy(iv_string, vs->iv_string, sizeof(iv_string));
1812 if (!err) {
1813 snprintf(iv_string, sizeof(iv_string), "%032"PRIx64, vs->sequence);
1814 memset(vs->iv_string, 0, sizeof(vs->iv_string));
1815 memcpy(vs->iv_string, iv_string, sizeof(iv_string));
1816 }
1817 }
1818 if (c->segment_type != SEGMENT_TYPE_FMP4) {
1819 if (oc->oformat->priv_class && oc->priv_data) {
1820 av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
1821 }
1822 if (c->flags & HLS_SINGLE_FILE) {
1823 if (c->key_info_file || c->encrypt) {
1824 av_dict_set(&options, "encryption_key", vs->key_string, 0);
1825 av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
1826
1827 /* Write temp file with cryption content */
1828 av_freep(&vs->basename_tmp);
1829 vs->basename_tmp = av_asprintf("crypto:%s.tmp", oc->url);
1830
1831 /* append temp file content into single file */
1832 av_freep(&vs->basename);
1833 vs->basename = av_asprintf("%s", oc->url);
1834 } else {
1835 vs->basename_tmp = vs->basename;
1836 }
1838 if (!vs->out_single_file)
1839 if ((err = hlsenc_io_open(s, &vs->out_single_file, vs->basename, &options)) < 0) {
1840 if (c->ignore_io_errors)
1841 err = 0;
1842 goto fail;
1843 }
1844
1845 if ((err = hlsenc_io_open(s, &vs->out, vs->basename_tmp, &options)) < 0) {
1846 if (c->ignore_io_errors)
1847 err = 0;
1848 goto fail;
1849 }
1850
1851 }
1852 }
1853 if (vs->vtt_basename) {
1855 if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->url, &options)) < 0) {
1856 if (c->ignore_io_errors)
1857 err = 0;
1858 goto fail;
1859 }
1860 }
1862
1863 if (vs->vtt_basename) {
1864 err = avformat_write_header(vtt_oc,NULL);
1865 if (err < 0)
1866 return err;
1867 }
1868
1869 return 0;
1870fail:
1872
1873 return err;
1874}
1875
1877{
1878 HLSContext *hls = s->priv_data;
1879#if HAVE_LIBC_MSVCRT
1880 // no %s support on MSVC, which invokes the invalid parameter handler
1881 // on unsupported format strings, instead of returning an error
1882 int strftime_s_supported = 0;
1883#else
1884 char b[21];
1885 time_t t = time(NULL);
1886 struct tm tmbuf, *p = localtime_r(&t, &tmbuf);
1887 // no %s support when strftime returned error or left format string unchanged
1888 int strftime_s_supported = strftime(b, sizeof(b), "%s", p) && strcmp(b, "%s");
1889#endif
1890
1891 if (hls->segment_type == SEGMENT_TYPE_FMP4) {
1892 return strftime_s_supported ? "-%s.m4s" : "-%Y%m%d%H%M%S.m4s";
1893 }
1894 return strftime_s_supported ? "-%s.ts" : "-%Y%m%d%H%M%S.ts";
1895}
1896
1897static int append_postfix(char *name, int name_buf_len, int i)
1898{
1899 char *p;
1900 char extension[10] = {'\0'};
1901
1902 p = strrchr(name, '.');
1903 if (p) {
1904 av_strlcpy(extension, p, sizeof(extension));
1905 *p = '\0';
1906 }
1907
1908 snprintf(name + strlen(name), name_buf_len - strlen(name), POSTFIX_PATTERN, i);
1909
1910 if (strlen(extension))
1911 av_strlcat(name, extension, name_buf_len);
1912
1913 return 0;
1914}
1915
1916static int validate_name(int nb_vs, const char *fn)
1917{
1918 const char *filename, *subdir_name;
1919 char *fn_dup = NULL;
1920 int ret = 0;
1921
1922 if (!fn)
1923 return AVERROR(EINVAL);
1924
1925 fn_dup = av_strdup(fn);
1926 if (!fn_dup)
1927 return AVERROR(ENOMEM);
1928 filename = av_basename(fn);
1929 subdir_name = av_dirname(fn_dup);
1930
1931 if (nb_vs > 1 && !av_stristr(filename, "%v") && !av_stristr(subdir_name, "%v")) {
1932 av_log(NULL, AV_LOG_ERROR, "More than 1 variant streams are present, %%v is expected "
1933 "either in the filename or in the sub-directory name of file %s\n", fn);
1934 ret = AVERROR(EINVAL);
1935 goto fail;
1936 }
1937
1938 if (av_stristr(filename, "%v") && av_stristr(subdir_name, "%v")) {
1939 av_log(NULL, AV_LOG_ERROR, "%%v is expected either in the filename or "
1940 "in the sub-directory name of file %s, but only in one of them\n", fn);
1941 ret = AVERROR(EINVAL);
1942 goto fail;
1943 }
1944
1945fail:
1946 av_freep(&fn_dup);
1947 return ret;
1948}
1949
1950static int format_name(const char *buf, char **s, int index, const char *varname)
1951{
1952 const char *proto, *dir;
1953 char *orig_buf_dup = NULL, *mod_buf_dup = NULL;
1954 int ret = 0;
1955
1956 orig_buf_dup = av_strdup(buf);
1957 if (!orig_buf_dup)
1958 return AVERROR(ENOMEM);
1959
1960 if (!av_stristr(buf, "%v")) {
1961 *s = orig_buf_dup;
1962 return 0;
1963 }
1964
1965 if (!varname) {
1966 if (replace_int_data_in_filename(s, orig_buf_dup, 'v', index) < 1) {
1967 ret = AVERROR(EINVAL);
1968 goto fail;
1969 }
1970 } else {
1971 if (replace_str_data_in_filename(s, orig_buf_dup, 'v', varname) < 1) {
1972 ret = AVERROR(EINVAL);
1973 goto fail;
1974 }
1975 }
1976
1977 proto = avio_find_protocol_name(orig_buf_dup);
1978 dir = av_dirname(orig_buf_dup);
1979
1980 /* if %v is present in the file's directory, create sub-directory */
1981 if (av_stristr(dir, "%v") && proto && !strcmp(proto, "file")) {
1982 mod_buf_dup = av_strdup(*s);
1983 dir = av_dirname(mod_buf_dup);
1984 if (ff_mkdir_p(dir) == -1 && errno != EEXIST) {
1985 ret = AVERROR(errno);
1986 goto fail;
1987 }
1988 }
1989
1990fail:
1991 av_freep(&orig_buf_dup);
1992 av_freep(&mod_buf_dup);
1993 return ret;
1994}
1995
1998 int64_t stream_id)
1999{
2000 unsigned int stream_index, cnt;
2001 if (stream_id < 0 || stream_id > s->nb_streams - 1)
2002 return -1;
2003 cnt = 0;
2004 for (stream_index = 0; stream_index < s->nb_streams; stream_index++) {
2005 if (s->streams[stream_index]->codecpar->codec_type != codec_type)
2006 continue;
2007 if (cnt == stream_id)
2008 return stream_index;
2009 cnt++;
2010 }
2011 return -1;
2012}
2013
2015{
2016 HLSContext *hls = s->priv_data;
2017 VariantStream *vs;
2018 int stream_index, i, j;
2020 int nb_varstreams = 0, nb_streams;
2021 char *p, *q, *saveptr1, *saveptr2, *varstr, *keyval;
2022 const char *val;
2023
2024 /**
2025 * Expected format for var_stream_map string is as below:
2026 * "a:0,v:0 a:1,v:1"
2027 * "a:0,agroup:a0,default:1,language:ENG a:1,agroup:a1,default:0 v:0,agroup:a0 v:1,agroup:a1"
2028 * This string specifies how to group the audio, video and subtitle streams
2029 * into different variant streams. The variant stream groups are separated
2030 * by space.
2031 *
2032 * a:, v:, s: are keys to specify audio, video and subtitle streams
2033 * respectively. Allowed values are 0 to 9 digits (limited just based on
2034 * practical usage)
2035 *
2036 * agroup: is key to specify audio group. A string can be given as value.
2037 * sgroup: is key to specify subtitle group. A string can be given as value.
2038 */
2039 p = av_strdup(hls->var_stream_map);
2040 if (!p)
2041 return AVERROR(ENOMEM);
2042
2043 q = p;
2044 while (av_strtok(q, " \t", &saveptr1)) {
2045 q = NULL;
2046 nb_varstreams++;
2047 }
2048 av_freep(&p);
2049
2050 hls->var_streams = av_mallocz(sizeof(*hls->var_streams) * nb_varstreams);
2051 if (!hls->var_streams)
2052 return AVERROR(ENOMEM);
2053 hls->nb_varstreams = nb_varstreams;
2054
2055 p = hls->var_stream_map;
2056 nb_varstreams = 0;
2057 while (varstr = av_strtok(p, " \t", &saveptr1)) {
2058 p = NULL;
2059
2060 if (nb_varstreams < hls->nb_varstreams) {
2061 vs = &(hls->var_streams[nb_varstreams]);
2062 vs->var_stream_idx = nb_varstreams;
2063 vs->is_default = 0;
2064 nb_varstreams++;
2065 } else
2066 return AVERROR(EINVAL);
2067
2068 q = varstr;
2069 while (1) {
2070 if (!av_strncasecmp(q, "a:", 2) || !av_strncasecmp(q, "v:", 2) ||
2071 !av_strncasecmp(q, "s:", 2))
2072 vs->nb_streams++;
2073 q = strchr(q, ',');
2074 if (!q)
2075 break;
2076 q++;
2077 }
2078 vs->streams = av_mallocz(sizeof(AVStream *) * vs->nb_streams);
2079 if (!vs->streams)
2080 return AVERROR(ENOMEM);
2081
2082 nb_streams = 0;
2083 while (keyval = av_strtok(varstr, ",", &saveptr2)) {
2084 int64_t num;
2085 char *end;
2086 varstr = NULL;
2087 if (av_strstart(keyval, "language:", &val)) {
2088 vs->language = val;
2089 continue;
2090 } else if (av_strstart(keyval, "default:", &val)) {
2091 vs->is_default = (!av_strncasecmp(val, "YES", strlen("YES")) ||
2092 (!av_strncasecmp(val, "1", strlen("1"))));
2093 hls->has_default_key = 1;
2094 continue;
2095 } else if (av_strstart(keyval, "name:", &val)) {
2096 vs->varname = val;
2097 continue;
2098 } else if (av_strstart(keyval, "sname:", &val)) {
2099 vs->subtitle_varname = val;
2100 continue;
2101 } else if (av_strstart(keyval, "agroup:", &val)) {
2102 vs->agroup = val;
2103 continue;
2104 } else if (av_strstart(keyval, "sgroup:", &val)) {
2105 vs->sgroup = val;
2106 continue;
2107 } else if (av_strstart(keyval, "ccgroup:", &val)) {
2108 vs->ccgroup = val;
2109 continue;
2110 } else if (av_strstart(keyval, "v:", &val)) {
2112 hls->has_video_m3u8 = 1;
2113 } else if (av_strstart(keyval, "a:", &val)) {
2115 } else if (av_strstart(keyval, "s:", &val)) {
2117 } else {
2118 av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval);
2119 return AVERROR(EINVAL);
2120 }
2121
2122 num = strtoll(val, &end, 10);
2123 if (!av_isdigit(*val) || *end != '\0') {
2124 av_log(s, AV_LOG_ERROR, "Invalid stream number: '%s'\n", val);
2125 return AVERROR(EINVAL);
2126 }
2127 stream_index = get_nth_codec_stream_index(s, codec_type, num);
2128
2129 if (stream_index >= 0 && nb_streams < vs->nb_streams) {
2130 for (i = 0; nb_streams > 0 && i < nb_streams; i++) {
2131 if (vs->streams[i] == s->streams[stream_index]) {
2132 av_log(s, AV_LOG_ERROR, "Same elementary stream found more than once inside "
2133 "variant definition #%d\n", nb_varstreams - 1);
2134 return AVERROR(EINVAL);
2135 }
2136 }
2137 for (j = 0; nb_varstreams > 1 && j < nb_varstreams - 1; j++) {
2138 for (i = 0; i < hls->var_streams[j].nb_streams; i++) {
2139 if (hls->var_streams[j].streams[i] == s->streams[stream_index]) {
2140 av_log(s, AV_LOG_ERROR, "Same elementary stream found more than once "
2141 "in two different variant definitions #%d and #%d\n",
2142 j, nb_varstreams - 1);
2143 return AVERROR(EINVAL);
2144 }
2145 }
2146 }
2147 vs->streams[nb_streams++] = s->streams[stream_index];
2148 } else {
2149 av_log(s, AV_LOG_ERROR, "Unable to map stream at %s\n", keyval);
2150 return AVERROR(EINVAL);
2151 }
2152 }
2153 }
2154 av_log(s, AV_LOG_DEBUG, "Number of variant streams %d\n",
2155 hls->nb_varstreams);
2156
2157 return 0;
2158}
2159
2161{
2162 HLSContext *hls = s->priv_data;
2163 int nb_ccstreams = 0;
2164 char *p, *q, *ccstr, *keyval;
2165 char *saveptr1 = NULL, *saveptr2 = NULL;
2166 const char *val;
2168
2169 p = av_strdup(hls->cc_stream_map);
2170 if(!p)
2171 return AVERROR(ENOMEM);
2172
2173 q = p;
2174 while (av_strtok(q, " \t", &saveptr1)) {
2175 q = NULL;
2176 nb_ccstreams++;
2177 }
2178 av_freep(&p);
2179
2180 hls->cc_streams = av_mallocz(sizeof(*hls->cc_streams) * nb_ccstreams);
2181 if (!hls->cc_streams)
2182 return AVERROR(ENOMEM);
2183 hls->nb_ccstreams = nb_ccstreams;
2184
2185 p = hls->cc_stream_map;
2186 nb_ccstreams = 0;
2187 while (ccstr = av_strtok(p, " \t", &saveptr1)) {
2188 p = NULL;
2189
2190 if (nb_ccstreams < hls->nb_ccstreams)
2191 ccs = &(hls->cc_streams[nb_ccstreams++]);
2192 else
2193 return AVERROR(EINVAL);
2194
2195 while (keyval = av_strtok(ccstr, ",", &saveptr2)) {
2196 ccstr = NULL;
2197
2198 if (av_strstart(keyval, "ccgroup:", &val)) {
2199 ccs->ccgroup = val;
2200 } else if (av_strstart(keyval, "instreamid:", &val)) {
2201 ccs->instreamid = val;
2202 } else if (av_strstart(keyval, "language:", &val)) {
2203 ccs->language = val;
2204 } else {
2205 av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval);
2206 return AVERROR(EINVAL);
2207 }
2208 }
2209
2210 if (!ccs->ccgroup || !ccs->instreamid) {
2211 av_log(s, AV_LOG_ERROR, "Insufficient parameters in cc stream map string\n");
2212 return AVERROR(EINVAL);
2213 }
2214
2215 if (av_strstart(ccs->instreamid, "CC", &val)) {
2216 if (atoi(val) < 1 || atoi(val) > 4) {
2217 av_log(s, AV_LOG_ERROR, "Invalid instream ID CC index %d in %s, range 1-4\n",
2218 atoi(val), ccs->instreamid);
2219 return AVERROR(EINVAL);
2220 }
2221 } else if (av_strstart(ccs->instreamid, "SERVICE", &val)) {
2222 if (atoi(val) < 1 || atoi(val) > 63) {
2223 av_log(s, AV_LOG_ERROR, "Invalid instream ID SERVICE index %d in %s, range 1-63 \n",
2224 atoi(val), ccs->instreamid);
2225 return AVERROR(EINVAL);
2226 }
2227 } else {
2228 av_log(s, AV_LOG_ERROR, "Invalid instream ID %s, supported are CCn or SERVICEn\n",
2229 ccs->instreamid);
2230 return AVERROR(EINVAL);
2231 }
2232 }
2233
2234 return 0;
2235}
2236
2238{
2239 HLSContext *hls = s->priv_data;
2240 unsigned int i;
2241 int ret = 0;
2242
2243 if (hls->cc_stream_map) {
2245 if (ret < 0)
2246 return ret;
2247 }
2248
2249 if (hls->var_stream_map) {
2251 } else {
2252 //By default, a single variant stream with all the codec streams is created
2253 hls->var_streams = av_mallocz(sizeof(*hls->var_streams));
2254 if (!hls->var_streams)
2255 return AVERROR(ENOMEM);
2256 hls->nb_varstreams = 1;
2257
2258 hls->var_streams[0].var_stream_idx = 0;
2259 hls->var_streams[0].nb_streams = s->nb_streams;
2260 hls->var_streams[0].streams = av_mallocz(sizeof(AVStream *) *
2261 hls->var_streams[0].nb_streams);
2262 if (!hls->var_streams[0].streams)
2263 return AVERROR(ENOMEM);
2264
2265 //by default, the first available ccgroup is mapped to the variant stream
2266 if (hls->nb_ccstreams)
2267 hls->var_streams[0].ccgroup = hls->cc_streams[0].ccgroup;
2268
2269 for (i = 0; i < s->nb_streams; i++)
2270 hls->var_streams[0].streams[i] = s->streams[i];
2271 }
2272 return 0;
2273}
2274
2276{
2277 HLSContext *hls = s->priv_data;
2278 const char *dir;
2279 char *fn1= NULL, *fn2 = NULL;
2280 int ret = 0;
2281
2282 fn1 = av_strdup(s->url);
2283 if (!fn1)
2284 return AVERROR(ENOMEM);
2285 dir = av_dirname(fn1);
2286
2287 /**
2288 * if output file's directory has %v, variants are created in sub-directories
2289 * then master is created at the sub-directories level
2290 */
2291 if (dir && av_stristr(av_basename(dir), "%v")) {
2292 fn2 = av_strdup(dir);
2293 if (!fn2) {
2294 ret = AVERROR(ENOMEM);
2295 goto fail;
2296 }
2297 dir = av_dirname(fn2);
2298 }
2299
2300 if (dir && strcmp(dir, "."))
2302 else
2304
2305 if (!hls->master_m3u8_url) {
2306 ret = AVERROR(ENOMEM);
2307 goto fail;
2308 }
2309
2310fail:
2311 av_freep(&fn1);
2312 av_freep(&fn2);
2313
2314 return ret;
2315}
2316
2318{
2319 HLSContext *hls = s->priv_data;
2320 int ret, i, j;
2321 VariantStream *vs = NULL;
2322
2323 for (i = 0; i < hls->nb_varstreams; i++) {
2324 int subtitle_streams = 0;
2325 vs = &hls->var_streams[i];
2326
2327 ret = avformat_write_header(vs->avf, NULL);
2328 if (ret < 0)
2329 return ret;
2330 //av_assert0(s->nb_streams == hls->avf->nb_streams);
2331 for (j = 0; j < vs->nb_streams; j++) {
2332 AVStream *inner_st;
2333 AVStream *outer_st = vs->streams[j];
2334
2335 if (hls->max_seg_size > 0) {
2336 if ((outer_st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
2337 (outer_st->codecpar->bit_rate > hls->max_seg_size)) {
2338 av_log(s, AV_LOG_WARNING, "Your video bitrate is bigger than hls_segment_size, "
2339 "(%"PRId64 " > %"PRId64 "), the result maybe not be what you want.",
2340 outer_st->codecpar->bit_rate, hls->max_seg_size);
2341 }
2342 }
2343
2344 if (outer_st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
2345 inner_st = vs->avf->streams[j - subtitle_streams];
2346 else if (vs->vtt_avf) {
2347 inner_st = vs->vtt_avf->streams[0];
2348 subtitle_streams++;
2349 } else {
2350 /* We have a subtitle stream, when the user does not want one */
2351 inner_st = NULL;
2352 continue;
2353 }
2354 avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den);
2355 if (outer_st->codecpar->codec_id == AV_CODEC_ID_HEVC &&
2356 outer_st->codecpar->codec_tag != MKTAG('h','v','c','1')) {
2357 av_log(s, AV_LOG_WARNING, "Stream HEVC is not hvc1, you should use tag:v hvc1 to set it.\n");
2358 }
2359 write_codec_attr(outer_st, vs);
2360
2361 }
2362 /* Update the Codec Attr string for the mapped audio groups */
2363 if (vs->has_video && vs->agroup) {
2364 for (j = 0; j < hls->nb_varstreams; j++) {
2365 VariantStream *vs_agroup = &(hls->var_streams[j]);
2366 if (!vs_agroup->has_video && !vs_agroup->has_subtitle &&
2367 vs_agroup->agroup &&
2368 !av_strcasecmp(vs_agroup->agroup, vs->agroup)) {
2369 write_codec_attr(vs_agroup->streams[0], vs);
2370 }
2371 }
2372 }
2373 }
2374
2375 return 0;
2376}
2377
2379{
2380 HLSContext *hls = s->priv_data;
2382 int ret = 0;
2383
2384 set_http_options(s, &options, hls);
2385 ret = hlsenc_io_open(s, &vs->out, vs->base_output_dirname, &options);
2387 if (ret < 0)
2388 return ret;
2391
2392 return ret;
2393}
2394
2396{
2397 int64_t ret = 0;
2398 int64_t read_byte = 0;
2399 int64_t total_size = 0;
2400 char *filename = NULL;
2401 char buf[BUFSIZE];
2402 AVFormatContext *oc = vs->avf;
2403
2404 hlsenc_io_close(s, &vs->out, vs->basename_tmp);
2405 filename = av_asprintf("%s.tmp", oc->url);
2406 ret = s->io_open(s, &vs->out, filename, AVIO_FLAG_READ, NULL);
2407 if (ret < 0) {
2408 av_free(filename);
2409 return ret;
2410 }
2411
2412 do {
2413 read_byte = avio_read(vs->out, buf, BUFSIZE);
2414 if (read_byte > 0) {
2415 avio_write(vs->out_single_file, buf, read_byte);
2416 total_size += read_byte;
2417 ret = total_size;
2418 }
2419 } while (read_byte > 0);
2420
2421 hlsenc_io_close(s, &vs->out, filename);
2422 av_free(filename);
2423
2424 return ret;
2425}
2427{
2428 HLSContext *hls = s->priv_data;
2429 AVFormatContext *oc = NULL;
2430 AVStream *st = s->streams[pkt->stream_index];
2431 int64_t end_pts = 0;
2432 int is_ref_pkt = 1;
2433 int ret = 0, can_split = 1, i, j;
2434 int stream_index = 0;
2435 int range_length = 0;
2436 const char *proto = NULL;
2437 int use_temp_file = 0;
2438 VariantStream *vs = NULL;
2439 char *old_filename = NULL;
2440
2441 for (i = 0; i < hls->nb_varstreams; i++) {
2442 int subtitle_streams = 0;
2443 vs = &hls->var_streams[i];
2444 for (j = 0; j < vs->nb_streams; j++) {
2446 subtitle_streams++;
2447 }
2448 if (vs->streams[j] == st) {
2450 oc = vs->vtt_avf;
2451 stream_index = 0;
2452 } else {
2453 oc = vs->avf;
2454 stream_index = j - subtitle_streams;
2455 }
2456 break;
2457 }
2458 }
2459
2460 if (oc)
2461 break;
2462 }
2463
2464 if (!oc) {
2465 av_log(s, AV_LOG_ERROR, "Unable to find mapping variant stream\n");
2466 return AVERROR(ENOMEM);
2467 }
2468
2469 end_pts = hls->recording_time * vs->number;
2470
2471 if (vs->sequence - vs->nb_entries > hls->start_sequence && hls->init_time > 0) {
2472 /* reset end_pts, hls->recording_time at end of the init hls list */
2473 int64_t init_list_dur = hls->init_time * vs->nb_entries;
2474 int64_t after_init_list_dur = (vs->sequence - hls->start_sequence - vs->nb_entries) * hls->time;
2475 hls->recording_time = hls->time;
2476 end_pts = init_list_dur + after_init_list_dur ;
2477 }
2478
2479 if (vs->start_pts == AV_NOPTS_VALUE) {
2482 vs->start_pts_from_audio = 1;
2483 }
2485 int64_t video_start = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q);
2486 if (vs->start_pts > video_start) {
2487 vs->start_pts = video_start;
2488 vs->start_pts_from_audio = 0;
2489 }
2490 }
2491
2492 if (vs->has_video) {
2494 ((pkt->flags & AV_PKT_FLAG_KEY) || (hls->flags & HLS_SPLIT_BY_TIME));
2495 is_ref_pkt = (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && (pkt->stream_index == vs->reference_stream_index);
2496 }
2497 if (pkt->pts == AV_NOPTS_VALUE)
2498 is_ref_pkt = can_split = 0;
2499
2500 if (is_ref_pkt) {
2501 if (vs->end_pts == AV_NOPTS_VALUE)
2502 vs->end_pts = pkt->pts;
2503 if (vs->new_start) {
2504 vs->new_start = 0;
2505 vs->duration = (double)(pkt->pts - vs->end_pts)
2506 * st->time_base.num / st->time_base.den;
2507 vs->dpp = (double)(pkt->duration) * st->time_base.num / st->time_base.den;
2508 } else {
2509 if (pkt->duration) {
2510 vs->duration += (double)(pkt->duration) * st->time_base.num / st->time_base.den;
2511 } else {
2512 av_log(s, AV_LOG_WARNING, "Stream %d packet with pts %" PRId64 " has duration 0. The segment duration may not be precise.\n",
2513 pkt->stream_index, pkt->pts);
2514 vs->duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den;
2515 }
2516 }
2517 }
2518
2519 can_split = can_split && (pkt->pts - vs->end_pts > 0);
2521 >= end_pts)) {
2522 int64_t new_start_pos;
2523 int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
2524 double cur_duration;
2525
2526#if CONFIG_MP4_MUXER
2527 if (hls->segment_type == SEGMENT_TYPE_FMP4 && is_ref_pkt &&
2528 pkt->dts != AV_NOPTS_VALUE)
2529 ff_mov_set_fragment_end_hint(oc, stream_index, pkt, st->time_base);
2530#endif
2531 av_write_frame(oc, NULL); /* Flush any buffered data */
2532 new_start_pos = avio_tell(oc->pb);
2533 vs->size = new_start_pos - vs->start_pos;
2534 avio_flush(oc->pb);
2535 if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2536 if (!vs->init_range_length) {
2537 range_length = avio_close_dyn_buf(oc->pb, &vs->init_buffer);
2538 if (range_length <= 0)
2539 return AVERROR(EINVAL);
2540 avio_write(vs->out, vs->init_buffer, range_length);
2541 if (!hls->resend_init_file)
2542 av_freep(&vs->init_buffer);
2543 vs->init_range_length = range_length;
2544 avio_open_dyn_buf(&oc->pb);
2545 vs->packets_written = 0;
2546 vs->start_pos = range_length;
2547 if (!byterange_mode) {
2549 }
2550 }
2551 }
2552 if (!byterange_mode) {
2553 if (vs->vtt_avf) {
2554 hlsenc_io_close(s, &vs->vtt_avf->pb, vs->vtt_avf->url);
2555 }
2556 }
2557
2558 if (hls->flags & HLS_SINGLE_FILE) {
2559 ret = flush_dynbuf(vs, &range_length);
2560 av_freep(&vs->temp_buffer);
2561 if (ret < 0) {
2562 return ret;
2563 }
2564 vs->size = range_length;
2565 if (hls->key_info_file || hls->encrypt)
2566 vs->size = append_single_file(s, vs);
2567 } else {
2568 if (oc->url[0]) {
2569 proto = avio_find_protocol_name(oc->url);
2570 use_temp_file = proto && !strcmp(proto, "file")
2571 && (hls->flags & HLS_TEMP_FILE);
2572 }
2573
2574 if ((hls->max_seg_size > 0 && (vs->size + vs->start_pos >= hls->max_seg_size)) || !byterange_mode) {
2576 char *filename = NULL;
2577 if (hls->key_info_file || hls->encrypt) {
2578 av_dict_set(&options, "encryption_key", vs->key_string, 0);
2579 av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
2580 filename = av_asprintf("crypto:%s", oc->url);
2581 } else {
2582 filename = av_asprintf("%s", oc->url);
2583 }
2584 if (!filename) {
2586 return AVERROR(ENOMEM);
2587 }
2588
2589 // look to rename the asset name
2590 if (use_temp_file)
2591 av_dict_set(&options, "mpegts_flags", "resend_headers", 0);
2592
2593 set_http_options(s, &options, hls);
2594
2595 ret = hlsenc_io_open(s, &vs->out, filename, &options);
2596 if (ret < 0) {
2598 "Failed to open file '%s'\n", filename);
2599 av_freep(&filename);
2601 return hls->ignore_io_errors ? 0 : ret;
2602 }
2603 if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2604 write_styp(vs->out);
2605 }
2606 ret = flush_dynbuf(vs, &range_length);
2607 if (ret < 0) {
2608 av_freep(&filename);
2610 return ret;
2611 }
2612 vs->size = range_length;
2613 ret = hlsenc_io_close(s, &vs->out, filename);
2614 if (ret < 0) {
2615 av_log(s, AV_LOG_WARNING, "upload segment failed,"
2616 " will retry with a new http session.\n");
2617 ff_format_io_close(s, &vs->out);
2618 ret = hlsenc_io_open(s, &vs->out, filename, &options);
2619 if (ret >= 0) {
2620 reflush_dynbuf(vs, &range_length);
2621 ret = hlsenc_io_close(s, &vs->out, filename);
2622 }
2623 }
2625 av_freep(&vs->temp_buffer);
2626 av_freep(&filename);
2627 }
2628
2629 if (use_temp_file)
2631 }
2632
2633 if (ret < 0)
2634 return ret;
2635
2636 old_filename = av_strdup(oc->url);
2637 if (!old_filename) {
2638 return AVERROR(ENOMEM);
2639 }
2640
2641 cur_duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den;
2642 ret = hls_append_segment(s, hls, vs, cur_duration, vs->start_pos, vs->size);
2643 vs->end_pts = pkt->pts;
2644 vs->duration = 0;
2645 if (ret < 0) {
2646 av_freep(&old_filename);
2647 return ret;
2648 }
2649
2650 // if we're building a VOD playlist, skip writing the manifest multiple times, and just wait until the end
2651 if (hls->pl_type != PLAYLIST_TYPE_VOD) {
2652 if ((ret = hls_window(s, 0, vs)) < 0) {
2653 av_log(s, AV_LOG_WARNING, "upload playlist failed, will retry with a new http session.\n");
2654 ff_format_io_close(s, &vs->out);
2655 if ((ret = hls_window(s, 0, vs)) < 0) {
2656 av_freep(&old_filename);
2657 return ret;
2658 }
2659 }
2660 }
2661
2662 if (hls->resend_init_file && hls->segment_type == SEGMENT_TYPE_FMP4) {
2663 ret = hls_init_file_resend(s, vs);
2664 if (ret < 0) {
2665 av_freep(&old_filename);
2666 return ret;
2667 }
2668 }
2669
2670 if (hls->flags & HLS_SINGLE_FILE) {
2671 vs->start_pos += vs->size;
2672 if (hls->key_info_file || hls->encrypt)
2673 ret = hls_start(s, vs);
2674 if (hls->segment_type == SEGMENT_TYPE_MPEGTS && oc->oformat->priv_class && oc->priv_data) {
2675 av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
2676 }
2677 } else if (hls->max_seg_size > 0) {
2678 if (vs->size + vs->start_pos >= hls->max_seg_size) {
2679 vs->sequence++;
2680 sls_flag_file_rename(hls, vs, old_filename);
2681 ret = hls_start(s, vs);
2682 vs->start_pos = 0;
2683 /* When split segment by byte, the duration is short than hls_time,
2684 * so it is not enough one segment duration as hls_time, */
2685 } else {
2686 vs->start_pos = new_start_pos;
2687 }
2688 } else {
2689 vs->start_pos = 0;
2690 sls_flag_file_rename(hls, vs, old_filename);
2691 ret = hls_start(s, vs);
2692 }
2693 vs->number++;
2694 av_freep(&old_filename);
2695
2696 if (ret < 0) {
2697 return ret;
2698 }
2699 }
2700
2701 vs->packets_written++;
2702 if (oc->pb) {
2703 ret = ff_write_chained(oc, stream_index, pkt, s, 0);
2704 if (hls->ignore_io_errors)
2705 ret = 0;
2706 }
2707
2708 return ret;
2709}
2710
2712{
2713 HLSContext *hls = s->priv_data;
2714 int i = 0;
2715 VariantStream *vs = NULL;
2716
2717 for (i = 0; i < hls->nb_varstreams; i++) {
2718 vs = &hls->var_streams[i];
2719
2720 av_freep(&vs->basename);
2723 av_freep(&vs->vtt_basename);
2724 av_freep(&vs->vtt_m3u8_name);
2725
2728 if (hls->resend_init_file)
2729 av_freep(&vs->init_buffer);
2732 av_freep(&vs->m3u8_name);
2733 av_freep(&vs->streams);
2734 }
2735
2739 av_freep(&hls->key_basename);
2740 av_freep(&hls->var_streams);
2741 av_freep(&hls->cc_streams);
2743}
2744
2746{
2747 HLSContext *hls = s->priv_data;
2748 AVFormatContext *oc = NULL;
2749 AVFormatContext *vtt_oc = NULL;
2750 char *old_filename = NULL;
2751 const char *proto = NULL;
2752 int use_temp_file = 0;
2753 int i;
2754 int ret = 0;
2755 VariantStream *vs = NULL;
2757 int range_length, byterange_mode;
2758
2759 for (i = 0; i < hls->nb_varstreams; i++) {
2760 char *filename = NULL;
2761 vs = &hls->var_streams[i];
2762 oc = vs->avf;
2763 vtt_oc = vs->vtt_avf;
2764 old_filename = av_strdup(oc->url);
2765 use_temp_file = 0;
2766
2767 if (!old_filename) {
2768 return AVERROR(ENOMEM);
2769 }
2770 if (hls->key_info_file || hls->encrypt) {
2771 av_dict_set(&options, "encryption_key", vs->key_string, 0);
2772 av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
2773 filename = av_asprintf("crypto:%s", oc->url);
2774 } else {
2775 filename = av_asprintf("%s", oc->url);
2776 }
2777 if (!filename) {
2779 av_freep(&old_filename);
2780 return AVERROR(ENOMEM);
2781 }
2782
2783 if (hls->segment_type == SEGMENT_TYPE_FMP4) {
2784 if (!vs->init_range_length) {
2785 uint8_t *buffer = NULL;
2786 av_write_frame(oc, NULL); /* Flush any buffered data */
2787
2788 int init_range_length = avio_close_dyn_buf(oc->pb, &buffer);
2789 avio_write(vs->out, buffer, init_range_length);
2790 av_freep(&buffer);
2791 vs->init_range_length = init_range_length;
2792 avio_open_dyn_buf(&oc->pb);
2793 vs->packets_written = 0;
2794 vs->start_pos = init_range_length;
2795 byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
2796 if (!byterange_mode) {
2797 ff_format_io_close(s, &vs->out);
2799 }
2800 }
2801 }
2802 if (!(hls->flags & HLS_SINGLE_FILE)) {
2803 set_http_options(s, &options, hls);
2804 ret = hlsenc_io_open(s, &vs->out, filename, &options);
2805 if (ret < 0) {
2806 av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", oc->url);
2807 goto failed;
2808 }
2809 if (hls->segment_type == SEGMENT_TYPE_FMP4)
2810 write_styp(vs->out);
2811 }
2812 ret = flush_dynbuf(vs, &range_length);
2813 if (ret < 0)
2814 goto failed;
2815
2816 vs->size = range_length;
2817 ret = hlsenc_io_close(s, &vs->out, filename);
2818 if (ret < 0) {
2819 av_log(s, AV_LOG_WARNING, "upload segment failed, will retry with a new http session.\n");
2820 ff_format_io_close(s, &vs->out);
2821 ret = hlsenc_io_open(s, &vs->out, filename, &options);
2822 if (ret < 0) {
2823 av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", oc->url);
2824 goto failed;
2825 }
2826 reflush_dynbuf(vs, &range_length);
2827 ret = hlsenc_io_close(s, &vs->out, filename);
2828 if (ret < 0)
2829 av_log(s, AV_LOG_WARNING, "Failed to upload file '%s' at the end.\n", oc->url);
2830 }
2831 if (hls->flags & HLS_SINGLE_FILE) {
2832 if (hls->key_info_file || hls->encrypt) {
2833 vs->size = append_single_file(s, vs);
2834 }
2836 }
2837failed:
2838 av_freep(&vs->temp_buffer);
2840 av_freep(&filename);
2841 av_write_trailer(oc);
2842 if (oc->url[0]) {
2843 proto = avio_find_protocol_name(oc->url);
2844 use_temp_file = proto && !strcmp(proto, "file") && (hls->flags & HLS_TEMP_FILE);
2845 }
2846
2847 // rename that segment from .tmp to the real one
2848 if (use_temp_file && !(hls->flags & HLS_SINGLE_FILE)) {
2850 av_freep(&old_filename);
2851 old_filename = av_strdup(oc->url);
2852
2853 if (!old_filename) {
2854 return AVERROR(ENOMEM);
2855 }
2856 }
2857
2858 /* after av_write_trailer, then duration + 1 duration per packet */
2859 hls_append_segment(s, hls, vs, vs->duration + vs->dpp, vs->start_pos, vs->size);
2860
2861 sls_flag_file_rename(hls, vs, old_filename);
2862
2863 if (vtt_oc) {
2864 if (vtt_oc->pb)
2865 av_write_trailer(vtt_oc);
2866 vs->size = avio_tell(vs->vtt_avf->pb) - vs->start_pos;
2867 ff_format_io_close(s, &vtt_oc->pb);
2868 }
2869 ret = hls_window(s, 1, vs);
2870 if (ret < 0) {
2871 av_log(s, AV_LOG_WARNING, "upload playlist failed, will retry with a new http session.\n");
2872 ff_format_io_close(s, &vs->out);
2873 hls_window(s, 1, vs);
2874 }
2875 ffio_free_dyn_buf(&oc->pb);
2876
2877 av_free(old_filename);
2878 }
2879
2880 return 0;
2881}
2882
2883
2885{
2886 int ret = 0;
2887 int i = 0;
2888 int j = 0;
2889 HLSContext *hls = s->priv_data;
2890 const char *pattern;
2891 VariantStream *vs = NULL;
2892 const char *vtt_pattern = hls->flags & HLS_SINGLE_FILE ? ".vtt" : "%d.vtt";
2893 int http_base_proto = ff_is_http_proto(s->url);
2894 int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1;
2895 double initial_program_date_time = av_gettime() / 1000000.0;
2896
2897 if (hls->use_localtime) {
2899 } else {
2900 pattern = hls->segment_type == SEGMENT_TYPE_FMP4 ? "%d.m4s" : "%d.ts";
2901 if (hls->flags & HLS_SINGLE_FILE)
2902 pattern += 2;
2903 }
2904
2905 hls->has_default_key = 0;
2906 hls->has_video_m3u8 = 0;
2908 if (ret < 0) {
2909 av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n",
2910 ret);
2911 return ret;
2912 }
2913
2914 if (!hls->method && http_base_proto) {
2915 av_log(hls, AV_LOG_WARNING, "No HTTP method set, hls muxer defaulting to method PUT.\n");
2916 }
2917
2918 ret = validate_name(hls->nb_varstreams, s->url);
2919 if (ret < 0)
2920 return ret;
2921
2922 if (hls->segment_filename) {
2924 if (ret < 0)
2925 return ret;
2926 }
2927
2928 if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) {
2930 if (ret < 0)
2931 return ret;
2932 }
2933
2934 if (hls->subtitle_filename) {
2936 if (ret < 0)
2937 return ret;
2938 }
2939
2940 if (hls->master_pl_name) {
2941 ret = update_master_pl_info(s);
2942 if (ret < 0) {
2943 av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n",
2944 ret);
2945 return ret;
2946 }
2947 }
2948
2952 time_t t = time(NULL);
2954 hls->start_sequence = av_gettime();
2956 hls->start_sequence = (int64_t)t;
2958 char b[15];
2959 struct tm *p, tmbuf;
2960 if (!(p = localtime_r(&t, &tmbuf)))
2961 return AVERROR(errno);
2962 if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p))
2963 return AVERROR(ENOMEM);
2964 hls->start_sequence = strtoll(b, NULL, 10);
2965 }
2966 av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence);
2967 }
2968
2969 hls->recording_time = hls->init_time && hls->max_nb_segments > 0 ? hls->init_time : hls->time;
2970
2972 // Independent segments cannot be guaranteed when splitting by time
2975 "'split_by_time' and 'independent_segments' cannot be "
2976 "enabled together. Disabling 'independent_segments' flag\n");
2977 }
2978
2979 for (i = 0; i < hls->nb_varstreams; i++) {
2980 vs = &hls->var_streams[i];
2981
2982 ret = format_name(s->url, &vs->m3u8_name, i, vs->varname);
2983 if (ret < 0)
2984 return ret;
2985
2986 vs->sequence = hls->start_sequence;
2988 vs->end_pts = AV_NOPTS_VALUE;
2990 vs->initial_prog_date_time = initial_program_date_time;
2991
2992 for (j = 0; j < vs->nb_streams; j++) {
2994 /* Get one video stream to reference for split segments
2995 * so use the first video stream index. */
2996 if ((vs->has_video == 1) && (vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) {
2997 vs->reference_stream_index = vs->streams[j]->index;
2998 }
3000 }
3001
3002 if (vs->has_video > 1)
3003 av_log(s, AV_LOG_WARNING, "More than a single video stream present, expect issues decoding it.\n");
3004 if (hls->segment_type == SEGMENT_TYPE_FMP4) {
3005#if CONFIG_MP4_MUXER
3007 vs->oformat = &ff_mp4_muxer.p;
3008#else
3010#endif
3011 } else {
3013 vs->oformat = &ff_mpegts_muxer.p;
3014 }
3015
3016 if (hls->segment_filename) {
3017 ret = format_name(hls->segment_filename, &vs->basename, i, vs->varname);
3018 if (ret < 0)
3019 return ret;
3020 } else {
3021 char *p = strrchr(vs->m3u8_name, '.');
3022 if (p)
3023 *p = '\0';
3024
3025 vs->basename = av_asprintf("%s%s", vs->m3u8_name, pattern);
3026 if (!vs->basename)
3027 return AVERROR(ENOMEM);
3028
3029 if (p)
3030 *p = '.';
3031 }
3032
3033 if (hls->segment_type == SEGMENT_TYPE_FMP4) {
3034 if (hls->nb_varstreams > 1)
3035 fmp4_init_filename_len += strlen(POSTFIX_PATTERN);
3036 if (hls->flags & HLS_SINGLE_FILE) {
3038 if (!vs->fmp4_init_filename)
3039 return AVERROR(ENOMEM);
3040 } else {
3041 vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len);
3042 if (!vs->fmp4_init_filename)
3043 return AVERROR(ENOMEM);
3045 fmp4_init_filename_len);
3046 if (hls->nb_varstreams > 1) {
3047 if (av_stristr(vs->fmp4_init_filename, "%v")) {
3050 &vs->fmp4_init_filename, i, vs->varname);
3051 } else {
3052 ret = append_postfix(vs->fmp4_init_filename, fmp4_init_filename_len, i);
3053 }
3054 if (ret < 0)
3055 return ret;
3056 }
3057
3058 if (hls->use_localtime) {
3059 int r;
3060 char *expanded = NULL;
3061
3062 r = strftime_expand(vs->fmp4_init_filename, &expanded);
3063 if (r < 0) {
3064 av_log(s, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
3065 return r;
3066 }
3068 vs->fmp4_init_filename = expanded;
3069 }
3070
3071 char *p = strrchr(vs->m3u8_name, '/');
3072 if (p) {
3073 char tmp = *(++p);
3074 *p = '\0';
3075 vs->base_output_dirname = av_asprintf("%s%s", vs->m3u8_name,
3076 vs->fmp4_init_filename);
3077 *p = tmp;
3078 } else {
3080 }
3081 if (!vs->base_output_dirname)
3082 return AVERROR(ENOMEM);
3083 }
3084 }
3085
3087 if (ret < 0)
3088 return ret;
3089
3090 if (vs->has_subtitle) {
3093
3094 char *p = strrchr(vs->m3u8_name, '.');
3095 if (p)
3096 *p = '\0';
3097
3098 vs->vtt_basename = av_asprintf("%s%s", vs->m3u8_name, vtt_pattern);
3099 if (!vs->vtt_basename)
3100 return AVERROR(ENOMEM);
3101
3102 if (hls->subtitle_filename) {
3103 ret = format_name(hls->subtitle_filename, &vs->vtt_m3u8_name, i, vs->varname);
3104 if (ret < 0)
3105 return ret;
3106 } else {
3107 vs->vtt_m3u8_name = av_asprintf("%s_vtt.m3u8", vs->m3u8_name);
3108 if (!vs->vtt_m3u8_name)
3109 return AVERROR(ENOMEM);
3110 }
3111 if (p)
3112 *p = '.';
3113 }
3114
3115 if ((ret = hls_mux_init(s, vs)) < 0)
3116 return ret;
3117
3118 if (hls->flags & HLS_APPEND_LIST) {
3119 parse_playlist(s, vs->m3u8_name, vs);
3120 vs->discontinuity = 1;
3121 if (hls->init_time > 0) {
3122 av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time,"
3123 " hls_init_time value will have no effect\n");
3124 hls->init_time = 0;
3125 hls->recording_time = hls->time;
3126 }
3127 }
3128
3129 if ((ret = hls_start(s, vs)) < 0)
3130 return ret;
3131 vs->number++;
3132 }
3133
3134 return ret;
3135}
3136
3137#define OFFSET(x) offsetof(HLSContext, x)
3138#define E AV_OPT_FLAG_ENCODING_PARAM
3139static const AVOption options[] = {
3140 {"start_number", "set first number in the sequence", OFFSET(start_sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E},
3141 {"hls_time", "set segment length", OFFSET(time), AV_OPT_TYPE_DURATION, {.i64 = 2000000}, 0, INT64_MAX, E},
3142 {"hls_init_time", "set segment length at init list", OFFSET(init_time), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, E},
3143 {"hls_list_size", "set maximum number of playlist entries", OFFSET(max_nb_segments), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E},
3144 {"hls_delete_threshold", "set number of unreferenced segments to keep before deleting", OFFSET(hls_delete_threshold), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, E},
3145 {"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},
3146 {"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},
3147 {"hls_base_url", "url to prepend to each playlist entry", OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3148 {"hls_segment_filename", "filename template for segment files", OFFSET(segment_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3149 {"hls_segment_options","set segments files format options of hls", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E},
3150 {"hls_segment_size", "maximum size per segment file, (in bytes)", OFFSET(max_seg_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E},
3151 {"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},
3152 {"hls_enc", "enable AES128 encryption support", OFFSET(encrypt), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E},
3153 {"hls_enc_key", "hex-coded 16 byte key to encrypt the segments", OFFSET(key), AV_OPT_TYPE_STRING, .flags = E},
3154 {"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},
3155 {"hls_enc_iv", "hex-coded 16 byte initialization vector", OFFSET(iv), AV_OPT_TYPE_STRING, .flags = E},
3156 {"hls_subtitle_path", "set path of hls subtitles", OFFSET(subtitle_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3157 {"hls_segment_type", "set hls segment files type", OFFSET(segment_type), AV_OPT_TYPE_INT, {.i64 = SEGMENT_TYPE_MPEGTS }, 0, SEGMENT_TYPE_FMP4, E, .unit = "segment_type"},
3158 {"mpegts", "make segment file to mpegts files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MPEGTS }, 0, UINT_MAX, E, .unit = "segment_type"},
3159 {"fmp4", "make segment file to fragment mp4 files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_FMP4 }, 0, UINT_MAX, E, .unit = "segment_type"},
3160 {"hls_fmp4_init_filename", "set fragment mp4 file init filename", OFFSET(fmp4_init_filename), AV_OPT_TYPE_STRING, {.str = "init.mp4"}, 0, 0, E},
3161 {"hls_fmp4_init_resend", "resend fragment mp4 init file after refresh m3u8 every time", OFFSET(resend_init_file), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3162 {"hls_flags", "set flags affecting HLS playlist and media file generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, .unit = "flags"},
3163 {"single_file", "generate a single media file indexed with byte ranges", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SINGLE_FILE }, 0, UINT_MAX, E, .unit = "flags"},
3164 {"temp_file", "write segment and playlist to temporary file and rename when complete", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_TEMP_FILE }, 0, UINT_MAX, E, .unit = "flags"},
3165 {"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, .unit = "flags"},
3166 {"round_durations", "round durations in m3u8 to whole numbers", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX, E, .unit = "flags"},
3167 {"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX, E, .unit = "flags"},
3168 {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX, E, .unit = "flags"},
3169 {"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, .unit = "flags"},
3170 {"append_list", "append the new segments into old hls segment list", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_APPEND_LIST }, 0, UINT_MAX, E, .unit = "flags"},
3171 {"program_date_time", "add EXT-X-PROGRAM-DATE-TIME", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PROGRAM_DATE_TIME }, 0, UINT_MAX, E, .unit = "flags"},
3172 {"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, .unit = "flags"},
3173 {"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, .unit = "flags"},
3174 {"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, .unit = "flags"},
3175 {"periodic_rekey", "reload keyinfo file periodically for re-keying", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PERIODIC_REKEY }, 0, UINT_MAX, E, .unit = "flags"},
3176 {"independent_segments", "add EXT-X-INDEPENDENT-SEGMENTS, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_INDEPENDENT_SEGMENTS }, 0, UINT_MAX, E, .unit = "flags"},
3177 {"iframes_only", "add EXT-X-I-FRAMES-ONLY, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_I_FRAMES_ONLY }, 0, UINT_MAX, E, .unit = "flags"},
3178 {"strftime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3179 {"strftime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3180 {"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, .unit = "pl_type" },
3181 {"event", "EVENT playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_EVENT }, INT_MIN, INT_MAX, E, .unit = "pl_type" },
3182 {"vod", "VOD playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_VOD }, INT_MIN, INT_MAX, E, .unit = "pl_type" },
3183 {"method", "set the HTTP method(default: PUT)", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3184 {"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_LAST-1, E, .unit = "start_sequence_source_type" },
3185 {"generic", "start_number value (default)", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_START_NUMBER }, INT_MIN, INT_MAX, E, .unit = "start_sequence_source_type" },
3186 {"epoch", "seconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, .unit = "start_sequence_source_type" },
3187 {"epoch_us", "microseconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, .unit = "start_sequence_source_type" },
3188 {"datetime", "current datetime as YYYYMMDDhhmmss", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_FORMATTED_DATETIME }, INT_MIN, INT_MAX, E, .unit = "start_sequence_source_type" },
3189 {"http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3190 {"var_stream_map", "Variant stream map string", OFFSET(var_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3191 {"cc_stream_map", "Closed captions stream map string", OFFSET(cc_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3192 {"master_pl_name", "Create HLS master playlist with this name", OFFSET(master_pl_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
3193 {"master_pl_publish_rate", "Publish master play list every after this many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT_MAX, E},
3194 {"http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
3195 {"timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
3196 {"ignore_io_errors", "Ignore IO errors for stable long-duration runs with network output", OFFSET(ignore_io_errors), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
3197 {"headers", "set custom HTTP headers, can override built in default headers", OFFSET(headers), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
3198 { NULL },
3199};
3200
3201static const AVClass hls_class = {
3202 .class_name = "hls muxer",
3203 .item_name = av_default_item_name,
3204 .option = options,
3205 .version = LIBAVUTIL_VERSION_INT,
3206};
3207
3208
3210 .p.name = "hls",
3211 .p.long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
3212 .p.extensions = "m3u8",
3213 .p.audio_codec = AV_CODEC_ID_AAC,
3214 .p.video_codec = AV_CODEC_ID_H264,
3215 .p.subtitle_codec = AV_CODEC_ID_WEBVTT,
3217 .p.priv_class = &hls_class,
3218 .flags_internal = FF_OFMT_FLAG_ALLOW_FLUSH,
3219 .priv_data_size = sizeof(HLSContext),
3220 .init = hls_init,
3224 .deinit = hls_deinit,
3225};
#define fn(a)
#define fn2(a, b)
static double val(void *priv, double ch)
Definition aeval.c:77
const FFOutputFormat ff_mpegts_muxer
Definition mpegtsenc.c:2455
const FFOutputFormat ff_webvtt_muxer
Definition webvttenc.c:100
const FFOutputFormat ff_mp4_muxer
const FFOutputFormat ff_hls_muxer
Definition hlsenc.c:3209
static AVFormatContext * ctx
#define EXTERN
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
#define E
Definition avdct.c:34
int ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition avformat.c:961
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition avformat.c:834
void ff_format_set_url(AVFormatContext *s, char *url)
Set AVFormatContext url field to the provided pointer.
Definition avformat.c:923
Main libavformat public API header.
#define AVFMT_NODIMENSIONS
Format does not need width/height.
Definition avformat.h:502
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition avformat.h:488
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition avformat.h:497
int avformat_alloc_output_context2(AVFormatContext **ctx, const AVOutputFormat *oformat, const char *format_name, const char *filename)
Allocate an AVFormatContext for an output format.
Definition mux.c:95
int ffurl_shutdown(URLContext *h, int flags)
Signal the URLContext that we are done reading or writing the stream.
Definition avio.c:915
URLContext * ffio_geturlcontext(AVIOContext *s)
Return the URLContext associated with the AVIOContext.
Definition avio.c:112
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition avio.c:725
int ff_rename(const char *url_src, const char *url_dst, void *logctx)
Wrap ffurl_move() and log if error happens.
Definition avio.c:929
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition aviobuf.c:236
void avio_wb32(AVIOContext *s, unsigned int val)
Definition aviobuf.c:368
#define AVIO_FLAG_READ
read-only
Definition avio.h:617
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition aviobuf.c:349
#define AVIO_FLAG_WRITE
write-only
Definition avio.h:618
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition avio.h:494
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
Writes a formatted string to the context.
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition aviobuf.c:1410
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition aviobuf.c:615
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition aviobuf.c:206
void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition aviobuf.c:228
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition aviobuf.c:1365
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition aviobuf.c:1438
static av_always_inline void ffio_wfourcc(AVIOContext *pb, const uint8_t *s)
int ff_get_chomp_line(AVIOContext *s, char *buf, int maxlen)
Same as ff_get_line but strip the white-space characters in the text tail.
Definition aviobuf.c:789
int ff_get_line(AVIOContext *s, char *buf, int maxlen)
Read a whole line of text from AVIOContext.
Definition aviobuf.c:772
char * av_asprintf(const char *fmt,...)
Definition avstring.c:115
#define fn1(name, depth)
Definition blend_modes.c:90
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition bprint.c:122
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition bprint.c:69
AVBPrint public header.
#define AV_BPRINT_SIZE_UNLIMITED
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
static void deinit(AVFormatContext *s)
Definition chromaprint.c:53
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Definition codec_par.c:107
int ff_make_codec_str(void *logctx, const AVCodecParameters *par, const AVRational *frame_rate, struct AVBPrint *out)
Make a RFC 4281/6381 like string describing a codec.
Definition codecstring.c:64
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static void can_split(const VVCLocalContext *lc, int x0, int y0, int cb_width, int cb_height, int mtt_depth, int depth_offset, int part_idx, VVCSplitMode last_split_mode, VVCTreeType tree_type, VVCModeType mode_type, VVCAllowedSplit *split)
Definition ctu.c:526
Misc types and constants that do not belong anywhere else.
static AVPacket * pkt
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
double value
Definition eval.c:102
static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
Definition ffmpeg_mux.c:204
const char * key
static int64_t duration
Definition ffplay.c:330
static unsigned int nb_streams
Definition ffprobe.c:352
static void write_header(FFV1Context *f)
Definition ffv1enc.c:384
#define fail
Definition test.h:479
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_DURATION
Underlying C type is int64_t.
Definition opt.h:318
@ AV_OPT_TYPE_FLAGS
Underlying C type is unsigned int.
Definition opt.h:254
@ AV_OPT_TYPE_INT64
Underlying C type is int64_t.
Definition opt.h:262
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_DICT
Underlying C type is AVDictionary*.
Definition opt.h:289
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition opt.h:326
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
@ AV_CODEC_ID_H264
Definition codec_id.h:77
@ AV_CODEC_ID_WEBVTT
Definition codec_id.h:584
@ AV_CODEC_ID_HEVC
Definition codec_id.h:223
@ AV_CODEC_ID_AAC
Definition codec_id.h:455
const AVPacketSideData * av_packet_side_data_get(const AVPacketSideData *sd, int nb_sd, enum AVPacketSideDataType type)
Get side information from a side data array.
Definition packet.c:570
@ AV_PKT_DATA_CPB_PROPERTIES
This side data corresponds to the AVCPBProperties struct.
Definition packet.h:142
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
int av_program_copy(AVFormatContext *dst, const AVFormatContext *src, int progid, int flags)
Copy an AVProgram from one AVFormatContext to another.
Definition avformat.c:349
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition avformat.c:150
av_warn_unused_result int avformat_init_output(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and initialize the codec, but do not write the header.
Definition mux.c:446
av_warn_unused_result int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
Definition mux.c:467
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition mux.c:1238
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition mux.c:1176
unsigned int av_codec_get_tag(const struct AVCodecTag *const *tags, enum AVCodecID id)
Get the codec tag for the given codec id id.
enum AVCodecID av_codec_get_id(const struct AVCodecTag *const *tags, unsigned int tag)
Get the AVCodecID for the given codec tag tag.
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition bprint.h:218
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition bprint.c:235
void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size)
Append data to a print buffer.
Definition bprint.c:148
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
Definition bprint.c:130
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition bprint.c:227
void av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size)
Init a print buffer using a pre-existing buffer.
Definition bprint.c:85
int av_random_bytes(uint8_t *buf, size_t len)
Generate cryptographically secure random data, i.e.
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:233
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition dict.c:247
#define AV_DICT_APPEND
If the entry already exists, append to it.
Definition dict.h:82
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition dict.c:86
#define AV_DICT_DONT_OVERWRITE
Don't overwrite existing entries.
Definition dict.h:81
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
Definition dict.c:37
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set() that converts the value to a string and stores it.
Definition dict.c:177
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition error.h:64
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition error.h:62
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
AVMediaType
Definition avutil.h:198
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AVMEDIA_TYPE_SUBTITLE
Definition avutil.h:203
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes,...
Definition avstring.c:95
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle.
Definition avstring.c:58
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
Definition avstring.c:179
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition avstring.c:208
static av_const int av_isdigit(int c)
Locale-independent conversion of ASCII isdigit.
Definition avstring.h:202
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition avstring.c:36
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition avstring.c:85
const char * av_dirname(char *path)
Thread safe dirname.
Definition avstring.c:271
const char * av_basename(const char *path)
Thread safe basename.
Definition avstring.c:253
int av_stristart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str independent of case.
Definition avstring.c:47
char * av_append_path_component(const char *path, const char *component)
Append path component to the existing path.
Definition avstring.c:292
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition avstring.c:218
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition avutil.h:263
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition opt.c:889
int index
Definition gxfenc.c:90
static const AVClass hls_class
Definition hls.c:3171
static int sls_flag_check_duration_size_index(HLSContext *hls)
Definition hlsenc.c:951
static int update_variant_stream_info(AVFormatContext *s)
Definition hlsenc.c:2237
static int64_t get_stream_bit_rate(AVStream *stream)
Definition hlsenc.c:1350
static HLSSegment * find_segment_by_filename(HLSSegment *segment, const char *filename)
Definition hlsenc.c:901
static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSContext *c)
Definition hlsenc.c:334
static int create_master_playlist(AVFormatContext *s, VariantStream *const input_vs, int final)
Definition hlsenc.c:1367
static int hls_init(AVFormatContext *s)
Definition hlsenc.c:2884
static int hls_window(AVFormatContext *s, int last, VariantStream *vs)
Definition hlsenc.c:1547
@ SEGMENT_TYPE_FMP4
Definition hlsenc.c:120
@ SEGMENT_TYPE_MPEGTS
Definition hlsenc.c:119
static int validate_name(int nb_vs, const char *fn)
Definition hlsenc.c:1916
#define KEYSIZE
Definition hlsenc.c:75
static const char * get_relative_url(const char *master_url, const char *media_url)
Definition hlsenc.c:1330
static int get_nth_codec_stream_index(AVFormatContext *s, enum AVMediaType codec_type, int64_t stream_id)
Definition hlsenc.c:1996
static int hls_rename_temp_file(AVFormatContext *s, AVFormatContext *oc)
Definition hlsenc.c:1315
static int parse_variant_stream_mapstring(AVFormatContext *s)
Definition hlsenc.c:2014
static int extract_segment_number(const char *filename)
Definition hlsenc.c:1147
#define NEXT(s)
static int append_postfix(char *name, int name_buf_len, int i)
Definition hlsenc.c:1897
static void hls_free_segments(HLSSegment *p)
Definition hlsenc.c:1304
static int hls_write_header(AVFormatContext *s)
Definition hlsenc.c:2317
static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, VariantStream *vs, double duration, int64_t pos, int64_t size)
Definition hlsenc.c:1045
static int format_name(const char *buf, char **s, int index, const char *varname)
Definition hlsenc.c:1950
static int replace_int_data_in_filename(char **s, const char *filename, char placeholder, int64_t number)
Definition hlsenc.c:423
static int replace_str_data_in_filename(char **s, const char *filename, char placeholder, const char *datastring)
Definition hlsenc.c:383
static void reflush_dynbuf(VariantStream *vs, int *range_length)
Definition hlsenc.c:502
static int do_encrypt(AVFormatContext *s, VariantStream *vs)
Definition hlsenc.c:642
static int sls_flag_use_localtime_filename(AVFormatContext *oc, HLSContext *c, VariantStream *vs)
Definition hlsenc.c:1001
static int hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename)
Definition hlsenc.c:314
static int hls_init_file_resend(AVFormatContext *s, VariantStream *vs)
Definition hlsenc.c:2378
static int64_t append_single_file(AVFormatContext *s, VariantStream *vs)
Definition hlsenc.c:2395
static void sls_flag_file_rename(HLSContext *hls, VariantStream *vs, char *old_filename)
Definition hlsenc.c:994
static int strftime_expand(const char *fmt, char **dest)
Definition hlsenc.c:270
static int hls_write_trailer(struct AVFormatContext *s)
Definition hlsenc.c:2745
static void hls_deinit(AVFormatContext *s)
Definition hlsenc.c:2711
StartSequenceSourceType
Definition hlsenc.c:62
@ HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH
Definition hlsenc.c:66
@ HLS_START_SEQUENCE_AS_FORMATTED_DATETIME
Definition hlsenc.c:65
@ HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH
Definition hlsenc.c:64
@ HLS_START_SEQUENCE_LAST
Definition hlsenc.c:67
@ HLS_START_SEQUENCE_AS_START_NUMBER
Definition hlsenc.c:63
static int flush_dynbuf(VariantStream *vs, int *range_length)
Definition hlsenc.c:481
static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, const char *filename, AVDictionary **options)
Definition hlsenc.c:293
static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs)
Definition hlsenc.c:1174
#define HLS_MICROSECOND_UNIT
Definition hlsenc.c:77
#define POSTFIX_PATTERN
Definition hlsenc.c:79
static int hls_start(AVFormatContext *s, VariantStream *vs)
Definition hlsenc.c:1691
static void write_styp(AVIOContext *pb)
Definition hlsenc.c:471
static const char * get_default_pattern_localtime_fmt(AVFormatContext *s)
Definition hlsenc.c:1876
static int hls_encryption_start(AVFormatContext *s, VariantStream *vs)
Definition hlsenc.c:715
static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition hlsenc.c:2426
static int hls_mux_init(AVFormatContext *s, VariantStream *vs)
Definition hlsenc.c:774
static int parse_cc_stream_mapstring(AVFormatContext *s)
Definition hlsenc.c:2160
#define OFFSET(x)
Definition hlsenc.c:3137
HLSFlags
Definition hlsenc.c:99
@ HLS_OMIT_ENDLIST
Definition hlsenc.c:105
@ HLS_PERIODIC_REKEY
Definition hlsenc.c:113
@ HLS_SINGLE_FILE
Definition hlsenc.c:101
@ HLS_DELETE_SEGMENTS
Definition hlsenc.c:102
@ HLS_APPEND_LIST
Definition hlsenc.c:107
@ HLS_TEMP_FILE
Definition hlsenc.c:112
@ HLS_SECOND_LEVEL_SEGMENT_INDEX
Definition hlsenc.c:109
@ HLS_PROGRAM_DATE_TIME
Definition hlsenc.c:108
@ HLS_ROUND_DURATIONS
Definition hlsenc.c:103
@ HLS_SPLIT_BY_TIME
Definition hlsenc.c:106
@ HLS_DISCONT_START
Definition hlsenc.c:104
@ HLS_INDEPENDENT_SEGMENTS
Definition hlsenc.c:114
@ HLS_SECOND_LEVEL_SEGMENT_DURATION
Definition hlsenc.c:110
@ HLS_SECOND_LEVEL_SEGMENT_SIZE
Definition hlsenc.c:111
@ HLS_I_FRAMES_ONLY
Definition hlsenc.c:115
CodecAttributeStatus
Definition hlsenc.c:70
@ CODEC_ATTRIBUTE_WILL_NOT_BE_WRITTEN
Definition hlsenc.c:72
@ CODEC_ATTRIBUTE_WRITTEN
Definition hlsenc.c:71
#define BUFSIZE
Definition hlsenc.c:78
static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, VariantStream *vs)
Definition hlsenc.c:532
static int hls_delete_file(HLSContext *hls, AVFormatContext *avf, char *path, const char *proto)
Definition hlsenc.c:508
static int sls_flags_filename_process(struct AVFormatContext *s, HLSContext *hls, VariantStream *vs, double duration, int64_t pos, int64_t size)
Definition hlsenc.c:911
static int sls_flag_check_duration_size(HLSContext *hls, VariantStream *vs)
Definition hlsenc.c:974
static int update_master_pl_info(AVFormatContext *s)
Definition hlsenc.c:2275
#define LINE_BUFFER_SIZE
Definition hlsenc.c:76
static void write_codec_attr(AVStream *st, VariantStream *vs)
Definition hlsenc.c:353
void ff_hls_write_playlist_version(AVIOContext *out, int version)
Definition hlsplaylist.c:32
void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, int target_duration, int64_t sequence, uint32_t playlist_type, int iframe_mode)
void ff_hls_write_audio_rendition(AVIOContext *out, const char *agroup, const char *filename, const char *language, int name_id, int is_default, int nb_channels)
Definition hlsplaylist.c:40
void ff_hls_write_init_file(AVIOContext *out, const char *filename, int byterange_mode, int64_t size, int64_t pos)
void ff_hls_write_subtitle_rendition(AVIOContext *out, const char *sgroup, const char *filename, const char *language, const char *sname, int name_id, int is_default)
Definition hlsplaylist.c:58
void ff_hls_write_end_list(AVIOContext *out)
int ff_hls_write_file_entry(AVIOContext *out, int insert_discont, int byterange_mode, double duration, int round_duration, int64_t size, int64_t pos, const char *baseurl, const char *filename, double *prog_date_time, int iframe_mode)
void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, int avg_bandwidth, const char *filename, const char *agroup, const char *codecs, const char *ccgroup, const char *sgroup)
Definition hlsplaylist.c:78
@ PLAYLIST_TYPE_VOD
Definition hlsplaylist.h:34
@ PLAYLIST_TYPE_NB
Definition hlsplaylist.h:35
@ PLAYLIST_TYPE_NONE
Definition hlsplaylist.h:32
@ PLAYLIST_TYPE_EVENT
Definition hlsplaylist.h:33
int ff_http_do_new_request(URLContext *h, const char *uri)
Send a new HTTP request, reusing the old connection.
Definition http.c:545
#define r
Definition input.c:42
#define b
Definition input.c:43
#define AV_WB64(p, v)
int ff_mkdir_p(const char *path)
Automatically create sub-directories.
Definition utils.c:424
int ff_is_http_proto(const char *filename)
Utility function to check if the file uses http or https protocol.
Definition utils.c:588
char * ff_data_to_hex(char *buf, const uint8_t *src, int size, int lowercase)
Write hexadecimal string corresponding to given binary data.
Definition utils.c:464
void * ff_bprint_finalize_as_fam(struct AVBPrint *bp, const void *struct_ptr, size_t fam_offset)
Allocate copy of a structure and copy contents of an AVBPrint buffer to the flexible array member of ...
Definition utils.c:695
#define MAX_URL_SIZE
Definition internal.h:30
int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, AVFormatContext *src, int interleave)
Write a packet to another muxer than the one the user originally intended.
Definition mux.c:1337
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
static av_always_inline av_const double round(double x)
Definition libm.h:446
Utility Preprocessor macros.
#define FFMIN(a, b)
Definition macros.h:49
#define MKTAG(a, b, c, d)
Definition macros.h:55
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
int ff_mov_set_fragment_end_hint(AVFormatContext *s, int stream_index, const AVPacket *pkt, AVRational src_time_base)
Definition movenc.c:6965
#define FF_OFMT_FLAG_ALLOW_FLUSH
This flag indicates that the muxer stores data internally and supports flushing it.
Definition mux.h:38
#define av_strdup(s)
Definition ops_static.c:55
#define av_malloc(s)
Definition ops_static.c:52
AVOptions.
miscellaneous OS support macros and functions.
char * av_small_strptime(const char *p, const char *fmt, struct tm *dt)
Simplified version of strptime.
Definition parseutils.c:494
misc parsing utilities
SegmentType
Definition pgssubdec.c:42
const char * name
Definition qsvenc.c:142
enum AVMediaType codec_type
Definition rtp.c:37
static const uint8_t start_sequence[]
Definition rtpdec_h264.c:66
#define snprintf
Definition snprintf.h:34
unsigned int pos
Definition spdifenc.c:431
This structure describes the bitrate properties of an encoded bitstream.
Definition defs.h:282
int64_t max_bitrate
Maximum bitrate of the stream, in bits per second.
Definition defs.h:287
int nb_channels
Number of channels in this layout.
Describe the class of an AVClass context structure.
Definition log.h:76
int nb_coded_side_data
Amount of entries in coded_side_data.
Definition codec_par.h:88
AVChannelLayout ch_layout
The channel layout and number of channels.
Definition codec_par.h:207
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition codec_par.h:99
enum AVMediaType codec_type
General type of the encoded data.
Definition codec_par.h:53
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition codec_par.h:61
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
AVPacketSideData * coded_side_data
Additional data associated with the entire stream.
Definition codec_par.h:83
Format I/O context.
Definition avformat.h:1333
int(* io_close2)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition avformat.h:1963
AVIOContext * pb
I/O context.
Definition avformat.h:1375
AVDictionary * metadata
Metadata that applies to the whole file.
Definition avformat.h:1580
int flags
Flags modifying the (de)muxer behaviour.
Definition avformat.h:1484
const struct AVOutputFormat * oformat
The output container format.
Definition avformat.h:1352
int strict_std_compliance
Allow non-standard and experimental extension.
Definition avformat.h:1707
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition avformat.h:1618
char * url
input or output URL.
Definition avformat.h:1449
void * opaque
User data.
Definition avformat.h:1912
void * priv_data
Format private data.
Definition avformat.h:1361
AVStream ** streams
A list of all streams in the file.
Definition avformat.h:1401
int(* io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options)
A callback for opening new IO streams.
Definition avformat.h:1953
Bytestream IO Context.
Definition avio.h:160
AVOption.
Definition opt.h:428
const struct AVCodecTag *const * codec_tag
List of supported codec_id-codec_tag pairs, ordered by "betterchoice first".
Definition avformat.h:552
const AVClass * priv_class
AVClass for the private context.
Definition avformat.h:555
This structure stores auxiliary information for decoding, presenting, or otherwise processing the cod...
Definition packet.h:424
uint8_t * data
Definition packet.h:425
This structure stores compressed data.
Definition packet.h:580
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
Stream structure.
Definition avformat.h:766
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:789
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition avformat.h:844
AVDictionary * metadata
Definition avformat.h:846
int id
Format-specific stream ID.
Definition avformat.h:778
int index
stream index in AVFormatContext
Definition avformat.h:772
int pts_wrap_bits
Number of bits in timestamps.
Definition avformat.h:909
AVRational avg_frame_rate
Average framerate.
Definition avformat.h:855
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition avformat.h:805
const char * instreamid
Definition hlsenc.c:199
const char * language
Definition hlsenc.c:200
const char * ccgroup
Definition hlsenc.c:198
char * master_pl_name
Definition hlsenc.c:257
unsigned int nb_ccstreams
Definition hlsenc.c:250
char * cc_stream_map
Definition hlsenc.c:256
uint32_t pl_type
Definition hlsenc.c:213
char * method
Definition hlsenc.c:244
char * segment_filename
Definition hlsenc.c:214
int has_video_m3u8
Definition hlsenc.c:267
ClosedCaptionsStream * cc_streams
Definition hlsenc.c:249
int hls_delete_threshold
Definition hlsenc.c:211
AVDictionary * format_options
Definition hlsenc.c:228
int ignore_io_errors
Definition hlsenc.c:264
char * subtitle_filename
Definition hlsenc.c:227
int encrypt_started
Definition hlsenc.c:235
unsigned int master_publish_rate
Definition hlsenc.c:258
char * iv
Definition hlsenc.c:233
char * master_m3u8_url
Definition hlsenc.c:253
char * key_info_file
Definition hlsenc.c:237
char * user_agent
Definition hlsenc.c:245
uint32_t flags
Definition hlsenc.c:212
char * key_basename
Definition hlsenc.c:234
int has_default_key
Definition hlsenc.c:266
char * headers
Definition hlsenc.c:265
int http_persistent
Definition hls.c:245
VariantStream * var_streams
Definition hlsenc.c:247
uint32_t start_sequence_source_type
Definition hlsenc.c:206
AVIOContext * sub_m3u8_out
Definition hlsenc.c:261
char key_string[KEYSIZE *2+1]
Definition hlsenc.c:240
int version
Definition hlsenc.c:254
char * fmp4_init_filename
Definition hlsenc.c:215
int max_nb_segments
Definition hlsenc.c:210
char * var_stream_map
Definition hlsenc.c:255
int segment_type
Definition hlsenc.c:216
char key_uri[LINE_BUFFER_SIZE+1]
Definition hlsenc.c:239
int use_localtime_mkdir
flag to mkdir dirname in timebased filename
Definition hlsenc.c:220
AVIOContext * m3u8_out
Definition hlsenc.c:260
char * vtt_format_options_str
Definition hlsenc.c:226
int64_t timeout
Definition hlsenc.c:263
int use_localtime
flag to expand filename with localtime
Definition hlsenc.c:219
int64_t init_time
Definition hlsenc.c:209
AVIOContext * http_delete
Definition hlsenc.c:262
int64_t time
Definition hlsenc.c:208
char * key_url
Definition hlsenc.c:232
int64_t max_seg_size
Definition hlsenc.c:223
int64_t start_sequence
Definition hlsenc.c:205
unsigned int nb_varstreams
Definition hlsenc.c:248
int resend_init_file
resend init file into disk after refresh m3u8
Definition hlsenc.c:217
int allowcache
Definition hlsenc.c:221
char * baseurl
Definition hlsenc.c:225
char * key
Definition hlsenc.c:231
int64_t recording_time
Definition hlsenc.c:222
char iv_string[KEYSIZE *2+1]
Definition hlsenc.c:241
AVDictionary * vtt_format_options
Definition hlsenc.c:242
char key_file[LINE_BUFFER_SIZE+1]
Definition hlsenc.c:238
int encrypt
Definition hlsenc.c:230
int master_m3u8_created
Definition hlsenc.c:252
int discont
Definition hlsenc.c:85
double discont_program_date_time
Definition hlsenc.c:94
double duration
Definition hlsenc.c:84
struct HLSSegment * next
Definition hlsenc.c:93
const char * sub_filename
Definition hlsenc.c:83
const char * filename
Definition hlsenc.c:82
char buf[]
Definition hlsenc.c:96
char iv_string[KEYSIZE *2+1]
Definition hlsenc.c:91
int64_t pos
Definition hlsenc.c:86
unsigned var_stream_idx
Definition hlsenc.c:88
const char * key_uri
Definition hlsenc.c:90
int64_t size
Definition hlsenc.c:87
int discontinuity_set
Definition hlsenc.c:151
int discontinuity
Definition hlsenc.c:152
char * basename
Definition hlsenc.c:165
int is_default
Definition hlsenc.c:188
char key_file[LINE_BUFFER_SIZE+1]
Definition hlsenc.c:178
double initial_prog_date_time
Definition hlsenc.c:170
const char * language
Definition hlsenc.c:189
char * vtt_m3u8_name
Definition hlsenc.c:167
int start_pts_from_audio
Definition hlsenc.c:142
int64_t size
Definition hlsenc.c:149
int m3u8_created
Definition hlsenc.c:187
HLSSegment * old_segments
Definition hlsenc.c:162
char codec_attr[128]
Definition hlsenc.c:184
char * vtt_basename
Definition hlsenc.c:166
int init_range_length
Definition hlsenc.c:132
AVIOContext * out_single_file
Definition hlsenc.c:130
unsigned int nb_streams
Definition hlsenc.c:186
int64_t sequence
Definition hlsenc.c:126
int encrypt_started
Definition hlsenc.c:176
uint8_t * init_buffer
Definition hlsenc.c:134
const char * subtitle_varname
Definition hlsenc.c:194
int has_subtitle
Definition hlsenc.c:140
int nb_entries
Definition hlsenc.c:150
const AVOutputFormat * vtt_oformat
Definition hlsenc.c:128
AVStream ** streams
Definition hlsenc.c:183
int64_t end_pts
Definition hlsenc.c:145
int reference_stream_index
Definition hlsenc.c:153
const AVOutputFormat * oformat
Definition hlsenc.c:127
char * fmp4_init_filename
Definition hlsenc.c:173
int64_t start_pos
Definition hlsenc.c:148
AVIOContext * out
Definition hlsenc.c:129
const char * agroup
Definition hlsenc.c:190
char key_string[KEYSIZE *2+1]
Definition hlsenc.c:180
int64_t start_pts
Definition hlsenc.c:144
unsigned var_stream_idx
Definition hlsenc.c:124
uint8_t * temp_buffer
Definition hlsenc.c:133
int64_t avg_bitrate
Definition hlsenc.c:157
int has_video
Definition hlsenc.c:139
char key_uri[LINE_BUFFER_SIZE+1]
Definition hlsenc.c:179
int64_t total_size
Definition hlsenc.c:155
AVFormatContext * vtt_avf
Definition hlsenc.c:137
unsigned number
Definition hlsenc.c:125
const char * sgroup
Definition hlsenc.c:191
double dpp
Definition hlsenc.c:143
HLSSegment * segments
Definition hlsenc.c:160
const char * varname
Definition hlsenc.c:193
int new_start
Definition hlsenc.c:141
AVFormatContext * avf
Definition hlsenc.c:136
const char * ccgroup
Definition hlsenc.c:192
char * m3u8_name
Definition hlsenc.c:168
char * base_output_dirname
Definition hlsenc.c:174
int64_t max_bitrate
Definition hlsenc.c:158
CodecAttributeStatus attr_status
Definition hlsenc.c:185
char current_segment_final_filename_fmt[MAX_URL_SIZE]
Definition hlsenc.c:171
char * basename_tmp
Definition hlsenc.c:164
int packets_written
Definition hlsenc.c:131
double duration
Definition hlsenc.c:147
double total_duration
Definition hlsenc.c:156
char iv_string[KEYSIZE *2+1]
Definition hlsenc.c:181
HLSSegment * last_segment
Definition hlsenc.c:161
int64_t video_lastpos
Definition hlsenc.c:146
Definition hls.c:77
int64_t duration
Definition hls.c:78
#define lrint
Definition tablegen.h:53
#define av_free(p)
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
static uint8_t tmp[40]
Definition aes_ctr.c:52
static char buffer[20]
Definition seek.c:32
int64_t av_gettime(void)
Get the current time in microseconds.
Definition time.c:40
#define localtime_r
int size
unbuffered private I/O API
static int write_trailer(AVFormatContext *s1)
Definition v4l2enc.c:101
int len
static double c[64]