FFmpeg
hlsplaylist.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 <stdint.h>
25 
27 
28 #include "avformat.h"
29 #include "hlsplaylist.h"
30 
32 {
33  if (!out)
34  return;
35  avio_printf(out, "#EXTM3U\n");
36  avio_printf(out, "#EXT-X-VERSION:%d\n", version);
37 }
38 
39 void ff_hls_write_audio_rendition(AVIOContext *out, const char *agroup,
40  const char *filename, const char *language,
41  int name_id, int is_default)
42 {
43  if (!out || !agroup || !filename)
44  return;
45 
46  avio_printf(out, "#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"group_%s\"", agroup);
47  avio_printf(out, ",NAME=\"audio_%d\",DEFAULT=%s,", name_id, is_default ? "YES" : "NO");
48  if (language) {
49  avio_printf(out, "LANGUAGE=\"%s\",", language);
50  }
51  avio_printf(out, "URI=\"%s\"\n", filename);
52 }
53 
55  const char *filename, const char *language,
56  int name_id, int is_default)
57 {
58  if (!out || !filename)
59  return;
60 
61  avio_printf(out, "#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"%s\"", sgroup);
62  avio_printf(out, ",NAME=\"subtitle_%d\",DEFAULT=%s,", name_id, is_default ? "YES" : "NO");
63  if (language) {
64  avio_printf(out, "LANGUAGE=\"%s\",", language);
65  }
66  avio_printf(out, "URI=\"%s\"\n", filename);
67 }
68 
70  const char *filename, const char *agroup,
71  const char *codecs, const char *ccgroup,
72  const char *sgroup)
73 {
74  if (!out || !filename)
75  return;
76 
77  if (!bandwidth) {
79  "Bandwidth info not available, set audio and video bitrates\n");
80  return;
81  }
82 
83  avio_printf(out, "#EXT-X-STREAM-INF:BANDWIDTH=%d", bandwidth);
84  if (st && st->codecpar->width > 0 && st->codecpar->height > 0)
85  avio_printf(out, ",RESOLUTION=%dx%d", st->codecpar->width,
86  st->codecpar->height);
87  if (codecs && codecs[0])
88  avio_printf(out, ",CODECS=\"%s\"", codecs);
89  if (agroup && agroup[0])
90  avio_printf(out, ",AUDIO=\"group_%s\"", agroup);
91  if (ccgroup && ccgroup[0])
92  avio_printf(out, ",CLOSED-CAPTIONS=\"%s\"", ccgroup);
93  if (sgroup && sgroup[0])
94  avio_printf(out, ",SUBTITLES=\"%s\"", sgroup);
95  avio_printf(out, "\n%s\n\n", filename);
96 }
97 
99  int target_duration, int64_t sequence,
100  uint32_t playlist_type, int iframe_mode)
101 {
102  if (!out)
103  return;
104  ff_hls_write_playlist_version(out, version);
105  if (allowcache == 0 || allowcache == 1) {
106  avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", allowcache == 0 ? "NO" : "YES");
107  }
108  avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
109  avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
110  av_log(NULL, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
111 
112  if (playlist_type == PLAYLIST_TYPE_EVENT) {
113  avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n");
114  } else if (playlist_type == PLAYLIST_TYPE_VOD) {
115  avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n");
116  }
117  if (iframe_mode) {
118  avio_printf(out, "#EXT-X-I-FRAMES-ONLY\n");
119  }
120 }
121 
122 void ff_hls_write_init_file(AVIOContext *out, const char *filename,
123  int byterange_mode, int64_t size, int64_t pos)
124 {
125  avio_printf(out, "#EXT-X-MAP:URI=\"%s\"", filename);
126  if (byterange_mode) {
127  avio_printf(out, ",BYTERANGE=\"%"PRId64"@%"PRId64"\"", size, pos);
128  }
129  avio_printf(out, "\n");
130 }
131 
132 int ff_hls_write_file_entry(AVIOContext *out, int insert_discont,
133  int byterange_mode, double duration,
134  int round_duration, int64_t size,
135  int64_t pos /* Used only if HLS_SINGLE_FILE flag is set */,
136  const char *baseurl /* Ignored if NULL */,
137  const char *filename, double *prog_date_time,
138  int64_t video_keyframe_size, int64_t video_keyframe_pos,
139  int iframe_mode)
140 {
141  if (!out || !filename)
142  return AVERROR(EINVAL);
143 
144  if (insert_discont) {
145  avio_printf(out, "#EXT-X-DISCONTINUITY\n");
146  }
147  if (round_duration)
148  avio_printf(out, "#EXTINF:%ld,\n", lrint(duration));
149  else
150  avio_printf(out, "#EXTINF:%f,\n", duration);
151  if (byterange_mode)
152  avio_printf(out, "#EXT-X-BYTERANGE:%"PRId64"@%"PRId64"\n", iframe_mode ? video_keyframe_size : size,
153  iframe_mode ? video_keyframe_pos : pos);
154 
155  if (prog_date_time) {
156  time_t tt, wrongsecs;
157  int milli;
158  struct tm *tm, tmpbuf;
159  char buf0[128], buf1[128];
160  tt = (int64_t)*prog_date_time;
161  milli = av_clip(lrint(1000*(*prog_date_time - tt)), 0, 999);
162  tm = localtime_r(&tt, &tmpbuf);
163  if (!strftime(buf0, sizeof(buf0), "%Y-%m-%dT%H:%M:%S", tm)) {
164  av_log(NULL, AV_LOG_DEBUG, "strftime error in ff_hls_write_file_entry\n");
165  return AVERROR_UNKNOWN;
166  }
167  if (!strftime(buf1, sizeof(buf1), "%z", tm) || buf1[1]<'0' ||buf1[1]>'2') {
168  int tz_min, dst = tm->tm_isdst;
169  tm = gmtime_r(&tt, &tmpbuf);
170  tm->tm_isdst = dst;
171  wrongsecs = mktime(tm);
172  tz_min = (FFABS(wrongsecs - tt) + 30) / 60;
173  snprintf(buf1, sizeof(buf1),
174  "%c%02d%02d",
175  wrongsecs <= tt ? '+' : '-',
176  tz_min / 60,
177  tz_min % 60);
178  }
179  avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n", buf0, milli, buf1);
180  *prog_date_time += duration;
181  }
182  if (baseurl)
183  avio_printf(out, "%s", baseurl);
184  avio_printf(out, "%s\n", filename);
185 
186  return 0;
187 }
188 
190 {
191  if (!out)
192  return;
193  avio_printf(out, "#EXT-X-ENDLIST\n");
194 }
195 
#define NULL
Definition: coverity.c:32
Bytestream IO Context.
Definition: avio.h:161
version
Definition: libkvazaar.c:317
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
static struct codec_string codecs[]
void ff_hls_write_audio_rendition(AVIOContext *out, const char *agroup, const char *filename, const char *language, int name_id, int is_default)
Definition: hlsplaylist.c:39
#define gmtime_r
Definition: time_internal.h:34
int width
Video only.
Definition: codec_par.h:126
int64_t duration
Definition: movenc.c:63
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:210
ptrdiff_t size
Definition: opengl_enc.c:100
#define av_log(a,...)
unsigned int pos
Definition: spdifenc.c:410
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
void ff_hls_write_subtitle_rendition(AVIOContext *out, const char *sgroup, const char *filename, const char *language, int name_id, int is_default)
Definition: hlsplaylist.c:54
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)
Definition: hlsplaylist.c:98
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
Stream structure.
Definition: avformat.h:876
void ff_hls_write_playlist_version(AVIOContext *out, int version)
Definition: hlsplaylist.c:31
Undefined Behavior In the C language
Definition: undefined.txt:3
#define snprintf
Definition: snprintf.h:34
void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, const char *filename, const char *agroup, const char *codecs, const char *ccgroup, const char *sgroup)
Definition: hlsplaylist.c:69
Main libavformat public API header.
#define localtime_r
Definition: time_internal.h:46
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
#define lrint
Definition: tablegen.h:53
void ff_hls_write_end_list(AVIOContext *out)
Definition: hlsplaylist.c:189
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, int64_t video_keyframe_size, int64_t video_keyframe_pos, int iframe_mode)
Definition: hlsplaylist.c:132
FILE * out
Definition: movenc.c:54
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1023
void ff_hls_write_init_file(AVIOContext *out, const char *filename, int byterange_mode, int64_t size, int64_t pos)
Definition: hlsplaylist.c:122
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
Writes a formatted string to the context.