hlsenc.c
Go to the documentation of this file.
1 /*
2  * Apple HTTP Live Streaming segmenter
3  * Copyright (c) 2012, Luca Barbato
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include <float.h>
23 
24 #include "libavutil/mathematics.h"
25 #include "libavutil/parseutils.h"
26 #include "libavutil/avstring.h"
27 #include "libavutil/opt.h"
28 #include "libavutil/log.h"
29 
30 #include "avformat.h"
31 #include "internal.h"
32 
33 typedef struct ListEntry {
34  char name[1024];
35  int duration;
36  struct ListEntry *next;
37 } ListEntry;
38 
39 typedef struct HLSContext {
40  const AVClass *class; // Class for private options.
41  unsigned number;
42  int64_t sequence;
45  float time; // Set by a private option.
46  int size; // Set by a private option.
47  int wrap; // Set by a private option.
48  int64_t recording_time;
49  int has_video;
50  int64_t start_pts;
51  int64_t end_pts;
52  int64_t duration; ///< last segment duration computed so far, in seconds
56  char *basename;
58 } HLSContext;
59 
61 {
62  HLSContext *hls = s->priv_data;
63  AVFormatContext *oc;
64  int i;
65 
66  hls->avf = oc = avformat_alloc_context();
67  if (!oc)
68  return AVERROR(ENOMEM);
69 
70  oc->oformat = hls->oformat;
72 
73  for (i = 0; i < s->nb_streams; i++) {
74  AVStream *st;
75  if (!(st = avformat_new_stream(oc, NULL)))
76  return AVERROR(ENOMEM);
79  }
80 
81  return 0;
82 }
83 
84 static int append_entry(HLSContext *hls, uint64_t duration)
85 {
86  ListEntry *en = av_malloc(sizeof(*en));
87 
88  if (!en)
89  return AVERROR(ENOMEM);
90 
91  av_strlcpy(en->name, av_basename(hls->avf->filename), sizeof(en->name));
92 
93  en->duration = duration;
94  en->next = NULL;
95 
96  if (!hls->list)
97  hls->list = en;
98  else
99  hls->end_list->next = en;
100 
101  hls->end_list = en;
102 
103  if (hls->nb_entries >= hls->size) {
104  en = hls->list;
105  hls->list = en->next;
106  av_free(en);
107  } else
108  hls->nb_entries++;
109 
110  hls->sequence++;
111 
112  return 0;
113 }
114 
115 static void free_entries(HLSContext *hls)
116 {
117  ListEntry *p = hls->list, *en;
118 
119  while(p) {
120  en = p;
121  p = p->next;
122  av_free(en);
123  }
124 }
125 
126 static int hls_window(AVFormatContext *s, int last)
127 {
128  HLSContext *hls = s->priv_data;
129  ListEntry *en;
130  int target_duration = 0;
131  int ret = 0;
132 
133  if ((ret = avio_open2(&hls->pb, s->filename, AVIO_FLAG_WRITE,
134  &s->interrupt_callback, NULL)) < 0)
135  goto fail;
136 
137  for (en = hls->list; en; en = en->next) {
138  if (target_duration < en->duration)
139  target_duration = en->duration;
140  }
141 
142  avio_printf(hls->pb, "#EXTM3U\n");
143  avio_printf(hls->pb, "#EXT-X-VERSION:3\n");
144  avio_printf(hls->pb, "#EXT-X-TARGETDURATION:%d\n", target_duration);
145  avio_printf(hls->pb, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n",
146  FFMAX(0, hls->sequence - hls->size));
147 
148  for (en = hls->list; en; en = en->next) {
149  avio_printf(hls->pb, "#EXTINF:%d,\n", en->duration);
150  avio_printf(hls->pb, "%s\n", en->name);
151  }
152 
153  if (last)
154  avio_printf(hls->pb, "#EXT-X-ENDLIST\n");
155 
156 fail:
157  avio_closep(&hls->pb);
158  return ret;
159 }
160 
162 {
163  HLSContext *c = s->priv_data;
164  AVFormatContext *oc = c->avf;
165  int err = 0;
166 
167  if (c->wrap)
168  c->number %= c->wrap;
169 
170  if (av_get_frame_filename(oc->filename, sizeof(oc->filename),
171  c->basename, c->number++) < 0) {
172  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->basename);
173  return AVERROR(EINVAL);
174  }
175 
176  if ((err = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
177  &s->interrupt_callback, NULL)) < 0)
178  return err;
179 
180  if (oc->oformat->priv_class && oc->priv_data)
181  av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
182 
183  return 0;
184 }
185 
187 {
188  HLSContext *hls = s->priv_data;
189  int ret, i;
190  char *p;
191  const char *pattern = "%d.ts";
192  int basename_size = strlen(s->filename) + strlen(pattern) + 1;
193 
194  hls->number = 0;
195 
196  hls->recording_time = hls->time * AV_TIME_BASE;
197  hls->start_pts = AV_NOPTS_VALUE;
198 
199  for (i = 0; i < s->nb_streams; i++)
200  hls->has_video +=
202 
203  if (hls->has_video > 1)
205  "More than a single video stream present, "
206  "expect issues decoding it.\n");
207 
208  hls->oformat = av_guess_format("mpegts", NULL, NULL);
209 
210  if (!hls->oformat) {
212  goto fail;
213  }
214 
215  hls->basename = av_malloc(basename_size);
216 
217  if (!hls->basename) {
218  ret = AVERROR(ENOMEM);
219  goto fail;
220  }
221 
222  strcpy(hls->basename, s->filename);
223 
224  p = strrchr(hls->basename, '.');
225 
226  if (p)
227  *p = '\0';
228 
229  av_strlcat(hls->basename, pattern, basename_size);
230 
231  if ((ret = hls_mux_init(s)) < 0)
232  goto fail;
233 
234  if ((ret = hls_start(s)) < 0)
235  goto fail;
236 
237  if ((ret = avformat_write_header(hls->avf, NULL)) < 0)
238  return ret;
239 
240 
241 fail:
242  if (ret) {
243  av_free(hls->basename);
244  if (hls->avf)
246  }
247  return ret;
248 }
249 
251 {
252  HLSContext *hls = s->priv_data;
253  AVFormatContext *oc = hls->avf;
254  AVStream *st = s->streams[pkt->stream_index];
255  int64_t end_pts = hls->recording_time * hls->number;
256  int ret, is_ref_pkt = 0;
257 
258  if (hls->start_pts == AV_NOPTS_VALUE) {
259  hls->start_pts = pkt->pts;
260  hls->end_pts = pkt->pts;
261  }
262 
263  if ((hls->has_video && st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
264  pkt->pts != AV_NOPTS_VALUE) {
265  is_ref_pkt = 1;
266  hls->duration = av_rescale(pkt->pts - hls->end_pts,
267  st->time_base.num, st->time_base.den);
268  }
269 
270  if (is_ref_pkt &&
271  av_compare_ts(pkt->pts - hls->start_pts, st->time_base,
272  end_pts, AV_TIME_BASE_Q) >= 0 &&
273  pkt->flags & AV_PKT_FLAG_KEY) {
274 
275  ret = append_entry(hls, hls->duration);
276  if (ret)
277  return ret;
278 
279  hls->end_pts = pkt->pts;
280  hls->duration = 0;
281 
282  av_write_frame(oc, NULL); /* Flush any buffered data */
283  avio_close(oc->pb);
284 
285  ret = hls_start(s);
286 
287  if (ret)
288  return ret;
289 
290  oc = hls->avf;
291 
292  if ((ret = hls_window(s, 0)) < 0)
293  return ret;
294  }
295 
296  ret = ff_write_chained(oc, pkt->stream_index, pkt, s);
297 
298  return ret;
299 }
300 
302 {
303  HLSContext *hls = s->priv_data;
304  AVFormatContext *oc = hls->avf;
305 
306  av_write_trailer(oc);
307  avio_closep(&oc->pb);
309  av_free(hls->basename);
310  append_entry(hls, hls->duration);
311  hls_window(s, 1);
312 
313  free_entries(hls);
314  avio_close(hls->pb);
315  return 0;
316 }
317 
318 #define OFFSET(x) offsetof(HLSContext, x)
319 #define E AV_OPT_FLAG_ENCODING_PARAM
320 static const AVOption options[] = {
321  {"start_number", "set first number in the sequence", OFFSET(sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E},
322  {"hls_time", "set segment length in seconds", OFFSET(time), AV_OPT_TYPE_FLOAT, {.dbl = 2}, 0, FLT_MAX, E},
323  {"hls_list_size", "set maximum number of playlist entries", OFFSET(size), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E},
324  {"hls_wrap", "set number after which the index wraps", OFFSET(wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E},
325  { NULL },
326 };
327 
328 static const AVClass hls_class = {
329  .class_name = "hls muxer",
330  .item_name = av_default_item_name,
331  .option = options,
332  .version = LIBAVUTIL_VERSION_INT,
333 };
334 
335 
337  .name = "hls",
338  .long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
339  .extensions = "m3u8",
340  .priv_data_size = sizeof(HLSContext),
341  .audio_codec = AV_CODEC_ID_MP2,
342  .video_codec = AV_CODEC_ID_MPEG2VIDEO,
347  .priv_class = &hls_class,
348 };
float time
Definition: hlsenc.c:45
int wrap
Definition: hlsenc.c:47
const char * s
Definition: avisynth_c.h:668
Bytestream IO Context.
Definition: avio.h:68
char * basename
Definition: hlsenc.c:56
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1125
AVOption.
Definition: opt.h:251
struct ListEntry * next
Definition: hlsenc.c:36
static int hls_write_trailer(struct AVFormatContext *s)
Definition: hlsenc.c:301
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:383
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:504
av_default_item_name
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
static int write_packet(AVFormatContext *s, AVPacket *pkt)
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:709
int num
numerator
Definition: rational.h:44
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:333
#define wrap(func)
Definition: w64xmmtest.h:70
#define AVFMT_ALLOW_FLUSH
Format allows flushing.
Definition: avformat.h:361
static int append_entry(HLSContext *hls, uint64_t duration)
Definition: hlsenc.c:84
int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src)
Copy the settings of the source AVCodecContext into the destination AVCodecContext.
static int hls_window(AVFormatContext *s, int last)
Definition: hlsenc.c:126
initialize output if(nPeaks >3)%at least 3 peaks in spectrum for trying to find f0 nf0peaks
Format I/O context.
Definition: avformat.h:944
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:55
ListEntry * list
Definition: hlsenc.c:54
const char * av_basename(const char *path)
Thread safe basename.
Definition: avstring.c:233
AVOptions.
static AVPacket pkt
Definition: demuxing.c:56
int64_t end_pts
Definition: hlsenc.c:51
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
struct ListEntry ListEntry
AVStream ** streams
Definition: avformat.h:992
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
static int write_trailer(AVFormatContext *s)
struct AVOutputFormat * oformat
Definition: avformat.h:958
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
static const AVOption options[]
Definition: hlsenc.c:320
static int hls_write_header(AVFormatContext *s)
Definition: hlsenc.c:186
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
#define OFFSET(x)
Definition: hlsenc.c:318
AVIOContext * pb
Definition: hlsenc.c:57
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
int avio_close(AVIOContext *s)
Close the resource accessed by the AVIOContext s and free it.
Definition: aviobuf.c:821
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
int has_video
Definition: hlsenc.c:49
int64_t recording_time
Definition: hlsenc.c:48
#define FFMAX(a, b)
Definition: common.h:56
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:82
int size
int flags
A combination of AV_PKT_FLAG values.
int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
Compare 2 timestamps each in its own timebases.
Definition: mathematics.c:135
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
int size
Definition: hlsenc.c:46
unsigned int nb_streams
A list of all streams in the file.
Definition: avformat.h:991
unsigned number
Definition: hlsenc.c:41
static void free_entries(HLSContext *hls)
Definition: hlsenc.c:115
char filename[1024]
input or output filename
Definition: avformat.h:994
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:118
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:196
ret
Definition: avfilter.c:821
int64_t start_pts
Definition: hlsenc.c:50
Definition: hls.c:96
static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: hlsenc.c:250
const char * name
Definition: avformat.h:378
#define E
Definition: hlsenc.c:319
AVOutputFormat * av_guess_format(const char *short_name, const char *filename, const char *mime_type)
Return the output format in the list of registered output formats which best matches the provided par...
const AVClass * priv_class
AVClass for the private context.
Definition: avformat.h:406
preferred ID for MPEG-1/2 video decoding
LIBAVUTIL_VERSION_INT
Definition: eval.c:55
int av_get_frame_filename(char *buf, int buf_size, const char *path, int number)
Return in &#39;buf&#39; the path with &#39;d&#39; replaced by a number.
struct HLSContext HLSContext
Stream structure.
Definition: avformat.h:643
NULL
Definition: eval.c:55
enum AVMediaType codec_type
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:202
int64_t duration
last segment duration computed so far, in seconds
Definition: hlsenc.c:52
AVIOContext * pb
I/O context.
Definition: avformat.h:977
AVOutputFormat * oformat
Definition: hlsenc.c:43
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
Describe the class of an AVClass context structure.
Definition: log.h:50
synthesis window for stochastic i
int avio_open2(AVIOContext **s, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Create and initialize a AVIOContext for accessing the resource indicated by url.
Definition: aviobuf.c:804
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
int64_t sequence
Definition: hlsenc.c:42
char name[1024]
Definition: hlsenc.c:34
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer 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.Buffer references ownership and permissions
misc parsing utilities
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:92
static int flags
Definition: cpu.c:23
static int hls_mux_init(AVFormatContext *s)
Definition: hlsenc.c:60
int nb_entries
Definition: hlsenc.c:53
Main libavformat public API header.
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:345
static double c[64]
int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, AVFormatContext *src)
Write a packet to another muxer than the one the user originally intended.
int den
denominator
Definition: rational.h:45
ListEntry * end_list
Definition: hlsenc.c:55
static int hls_start(AVFormatContext *s)
Definition: hlsenc.c:161
void * priv_data
Format private data.
Definition: avformat.h:964
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:470
AVFormatContext * avf
Definition: hlsenc.c:44
AVOutputFormat ff_hls_muxer
Definition: hlsenc.c:336
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:769
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition: error.h:60
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:679
static const AVClass hls_class
Definition: hlsenc.c:328
This structure stores compressed data.
int avio_closep(AVIOContext **s)
Close the resource accessed by the AVIOContext *s, free it and set the pointer pointing to it to NULL...
Definition: aviobuf.c:839
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:252
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
int duration
Definition: hlsenc.c:35
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:190
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2