hlsenc: Fix the openssl support
[ffmpeg.git] / libavformat / hlsenc.c
1 /*
2  * Apple HTTP Live Streaming segmenter
3  * Copyright (c) 2012, Luca Barbato
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; 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 #include <stdint.h>
24
25 #include <config.h>
26
27 #if CONFIG_GCRYPT
28 #include <gcrypt.h>
29 #elif CONFIG_OPENSSL
30 #include <openssl/rand.h>
31 #endif
32
33 #include "libavutil/mathematics.h"
34 #include "libavutil/parseutils.h"
35 #include "libavutil/avstring.h"
36 #include "libavutil/intreadwrite.h"
37 #include "libavutil/opt.h"
38 #include "libavutil/random_seed.h"
39 #include "libavutil/log.h"
40
41 #include "avformat.h"
42 #include "internal.h"
43
44 typedef struct ListEntry {
45     char  name[1024];
46     int64_t duration;     // segment duration in AV_TIME_BASE units
47     struct ListEntry *next;
48 } ListEntry;
49
50 typedef struct HLSContext {
51     const AVClass *class;  // Class for private options.
52     unsigned number;
53     int64_t sequence;
54     int64_t start_sequence;
55     AVOutputFormat *oformat;
56     AVFormatContext *avf;
57     float time;            // Set by a private option.
58     int  size;             // Set by a private option.
59     int  wrap;             // Set by a private option.
60     int  version;          // Set by a private option.
61     int  allowcache;
62     int64_t recording_time;
63     int has_video;
64     // The following timestamps are in AV_TIME_BASE units.
65     int64_t start_pts;
66     int64_t end_pts;
67     int64_t duration;      // last segment duration computed so far.
68     int nb_entries;
69     ListEntry *list;
70     ListEntry *end_list;
71     char *basename;
72     char *baseurl;
73
74     int encrypt;           // Set by a private option.
75     char *key;             // Set by a private option.
76     int key_len;
77     char *key_url;         // Set by a private option.
78     char *iv;              // Set by a private option.
79     int iv_len;
80
81     char *key_basename;
82
83     AVDictionary *enc_opts;
84 } HLSContext;
85
86
87 static int randomize(uint8_t *buf, int len)
88 {
89 #if CONFIG_GCRYPT
90     gcry_randomize(buf, len, GCRY_VERY_STRONG_RANDOM);
91     return 0;
92 #elif CONFIG_OPENSSL
93     if (RAND_bytes(buf, len))
94         return 0;
95     return AVERROR(EIO);
96 #else
97     return AVERROR(ENOSYS);
98 #endif
99 }
100
101 static void free_encryption(AVFormatContext *s)
102 {
103     HLSContext *hls = s->priv_data;
104
105     av_dict_free(&hls->enc_opts);
106
107     av_freep(&hls->key_basename);
108 }
109
110 static int dict_set_bin(AVDictionary **dict, const char *key, uint8_t *buf)
111 {
112     char hex[33];
113
114     ff_data_to_hex(hex, buf, sizeof(buf), 0);
115     hex[32] = '\0';
116
117     return av_dict_set(dict, key, hex, 0);
118 }
119
120 static int setup_encryption(AVFormatContext *s)
121 {
122     HLSContext *hls = s->priv_data;
123     AVIOContext *out = NULL;
124     int len, ret;
125     uint8_t buf[16];
126     uint8_t *k;
127
128     len = strlen(hls->basename) + 4 + 1;
129     hls->key_basename = av_mallocz(len);
130     if (!hls->key_basename)
131         return AVERROR(ENOMEM);
132
133     av_strlcpy(hls->key_basename, hls->basename + 7, len);
134     av_strlcat(hls->key_basename, ".key", len);
135
136     if (hls->key) {
137         if (hls->key_len != 16) {
138             av_log(s, AV_LOG_ERROR,
139                    "Invalid key size %d, expected 16-bytes hex-coded key\n",
140                    hls->key_len);
141             return AVERROR(EINVAL);
142         }
143
144         if ((ret = dict_set_bin(&hls->enc_opts, "key", hls->key)) < 0)
145             return ret;
146         k = hls->key;
147     } else {
148         if ((ret = randomize(buf, sizeof(buf))) < 0) {
149             av_log(s, AV_LOG_ERROR, "Cannot generate a strong random key\n");
150             return ret;
151         }
152
153         if ((ret = dict_set_bin(&hls->enc_opts, "key", buf)) < 0)
154             return ret;
155         k = buf;
156     }
157
158     if (hls->iv) {
159         if (hls->iv_len != 16) {
160             av_log(s, AV_LOG_ERROR,
161                    "Invalid key size %d, expected 16-bytes hex-coded initialization vector\n",
162                    hls->iv_len);
163             return AVERROR(EINVAL);
164         }
165
166         if ((ret = dict_set_bin(&hls->enc_opts, "iv", hls->iv)) < 0)
167             return ret;
168     }
169
170     if ((ret = s->io_open(s, &out, hls->key_basename, AVIO_FLAG_WRITE, NULL)) < 0)
171         return ret;
172
173     avio_write(out, k, 16);
174
175     avio_close(out);
176
177     return 0;
178 }
179
180 static int hls_mux_init(AVFormatContext *s)
181 {
182     HLSContext *hls = s->priv_data;
183     AVFormatContext *oc;
184     int i;
185
186     hls->avf = oc = avformat_alloc_context();
187     if (!oc)
188         return AVERROR(ENOMEM);
189
190     oc->oformat            = hls->oformat;
191     oc->interrupt_callback = s->interrupt_callback;
192     oc->opaque             = s->opaque;
193     oc->io_open            = s->io_open;
194     oc->io_close           = s->io_close;
195
196     for (i = 0; i < s->nb_streams; i++) {
197         AVStream *st;
198         if (!(st = avformat_new_stream(oc, NULL)))
199             return AVERROR(ENOMEM);
200         avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar);
201         st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
202         st->time_base = s->streams[i]->time_base;
203     }
204
205     return 0;
206 }
207
208 static int append_entry(HLSContext *hls, int64_t duration)
209 {
210     ListEntry *en = av_malloc(sizeof(*en));
211
212     if (!en)
213         return AVERROR(ENOMEM);
214
215     av_strlcpy(en->name, av_basename(hls->avf->filename), sizeof(en->name));
216
217     en->duration = duration;
218     en->next     = NULL;
219
220     if (!hls->list)
221         hls->list = en;
222     else
223         hls->end_list->next = en;
224
225     hls->end_list = en;
226
227     if (hls->nb_entries >= hls->size) {
228         en = hls->list;
229         hls->list = en->next;
230         av_free(en);
231     } else
232         hls->nb_entries++;
233
234     hls->sequence++;
235
236     return 0;
237 }
238
239 static void free_entries(HLSContext *hls)
240 {
241     ListEntry *p = hls->list, *en;
242
243     while(p) {
244         en = p;
245         p = p->next;
246         av_free(en);
247     }
248 }
249
250 static int hls_window(AVFormatContext *s, int last)
251 {
252     HLSContext *hls = s->priv_data;
253     ListEntry *en;
254     int64_t target_duration = 0;
255     int ret = 0;
256     AVIOContext *out = NULL;
257     char temp_filename[1024];
258     int64_t sequence = FFMAX(hls->start_sequence, hls->sequence - hls->size);
259
260     snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", s->filename);
261     if ((ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL)) < 0)
262         goto fail;
263
264     for (en = hls->list; en; en = en->next) {
265         if (target_duration < en->duration)
266             target_duration = en->duration;
267     }
268
269     avio_printf(out, "#EXTM3U\n");
270     avio_printf(out, "#EXT-X-VERSION:%d\n", hls->version);
271     if (hls->allowcache == 0 || hls->allowcache == 1) {
272         avio_printf(out, "#EXT-X-ALLOW-CACHE:%s\n", hls->allowcache == 0 ? "NO" : "YES");
273     }
274     avio_printf(out, "#EXT-X-TARGETDURATION:%"PRId64"\n",
275                 av_rescale_rnd(target_duration, 1, AV_TIME_BASE,
276                                AV_ROUND_UP));
277     avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
278
279     av_log(s, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n",
280            sequence);
281
282     for (en = hls->list; en; en = en->next) {
283         if (hls->encrypt) {
284             char *key_url;
285
286             if (hls->key_url)
287                 key_url = hls->key_url;
288             else
289                 key_url = hls->baseurl;
290
291             avio_printf(out, "#EXT-X-KEY:METHOD=AES-128");
292             avio_printf(out, ",URI=\"");
293             if (key_url)
294                 avio_printf(out, "%s", key_url);
295             avio_printf(out, "%s\"", av_basename(hls->key_basename));
296             if (hls->iv)
297                 avio_printf(out, ",IV=\"0x%s\"", hls->iv);
298             avio_printf(out, "\n");
299         }
300
301         if (hls->version > 2)
302             avio_printf(out, "#EXTINF:%f\n",
303                         (double)en->duration / AV_TIME_BASE);
304         else
305             avio_printf(out, "#EXTINF:%"PRId64",\n",
306                         av_rescale(en->duration, 1, AV_TIME_BASE));
307         if (hls->baseurl)
308             avio_printf(out, "%s", hls->baseurl);
309         avio_printf(out, "%s\n", en->name);
310     }
311
312     if (last)
313         avio_printf(out, "#EXT-X-ENDLIST\n");
314
315 fail:
316     ff_format_io_close(s, &out);
317     if (ret >= 0)
318         ff_rename(temp_filename, s->filename);
319     return ret;
320 }
321
322 static int hls_start(AVFormatContext *s)
323 {
324     HLSContext *c = s->priv_data;
325     AVFormatContext *oc = c->avf;
326     int err = 0;
327     AVDictionary *opts = NULL;
328
329
330     if (av_get_frame_filename(oc->filename, sizeof(oc->filename),
331                               c->basename, c->wrap ? c->sequence % c->wrap : c->sequence) < 0)
332         return AVERROR(EINVAL);
333     c->number++;
334
335     if (c->encrypt) {
336         if ((err = av_dict_copy(&opts, c->enc_opts, 0)) < 0)
337             return err;
338         if (!c->iv) {
339             uint8_t iv[16] = { 0 };
340             char buf[33];
341
342             AV_WB64(iv + 8, c->sequence);
343             ff_data_to_hex(buf, iv, sizeof(iv), 0);
344             buf[32] = '\0';
345
346             if ((err = av_dict_set(&opts, "iv", buf, 0)) < 0)
347                 goto fail;
348         }
349     }
350
351     if ((err = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, &opts)) < 0)
352         return err;
353
354     if (oc->oformat->priv_class && oc->priv_data)
355         av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
356
357 fail:
358     av_dict_free(&opts);
359
360     return err;
361 }
362
363 static int hls_setup(AVFormatContext *s)
364 {
365     HLSContext *hls = s->priv_data;
366     const char *pattern = "%d.ts";
367     int basename_size = strlen(s->filename) + strlen(pattern) + 1;
368     char *p;
369
370     if (hls->encrypt)
371         basename_size += 7;
372
373     hls->basename = av_mallocz(basename_size);
374     if (!hls->basename)
375         return AVERROR(ENOMEM);
376
377     // TODO: support protocol nesting?
378     if (hls->encrypt)
379         strcpy(hls->basename, "crypto:");
380
381     av_strlcat(hls->basename, s->filename, basename_size);
382
383     p = strrchr(hls->basename, '.');
384
385     if (p)
386         *p = '\0';
387
388     if (hls->encrypt) {
389         int ret = setup_encryption(s);
390         if (ret < 0)
391             return ret;
392     }
393
394     av_strlcat(hls->basename, pattern, basename_size);
395
396     return 0;
397 }
398
399 static int hls_write_header(AVFormatContext *s)
400 {
401     HLSContext *hls = s->priv_data;
402     int ret, i;
403
404     hls->sequence       = hls->start_sequence;
405     hls->recording_time = hls->time * AV_TIME_BASE;
406     hls->start_pts      = AV_NOPTS_VALUE;
407
408     for (i = 0; i < s->nb_streams; i++)
409         hls->has_video +=
410             s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
411
412     if (hls->has_video > 1)
413         av_log(s, AV_LOG_WARNING,
414                "More than a single video stream present, "
415                "expect issues decoding it.\n");
416
417     hls->oformat = av_guess_format("mpegts", NULL, NULL);
418
419     if (!hls->oformat) {
420         ret = AVERROR_MUXER_NOT_FOUND;
421         goto fail;
422     }
423
424     if ((ret = hls_setup(s)) < 0)
425         goto fail;
426
427     if ((ret = hls_mux_init(s)) < 0)
428         goto fail;
429
430     if ((ret = hls_start(s)) < 0)
431         goto fail;
432
433     if ((ret = avformat_write_header(hls->avf, NULL)) < 0)
434         return ret;
435
436
437 fail:
438     if (ret) {
439         av_free(hls->basename);
440         if (hls->avf)
441             avformat_free_context(hls->avf);
442
443         free_encryption(s);
444     }
445     return ret;
446 }
447
448 static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
449 {
450     HLSContext *hls = s->priv_data;
451     AVFormatContext *oc = hls->avf;
452     AVStream *st = s->streams[pkt->stream_index];
453     int64_t end_pts = hls->recording_time * hls->number;
454     int64_t pts     = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q);
455     int ret, can_split = 1;
456
457     if (hls->start_pts == AV_NOPTS_VALUE) {
458         hls->start_pts = pts;
459         hls->end_pts   = pts;
460     }
461
462     if (hls->has_video) {
463         can_split = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
464                     pkt->flags & AV_PKT_FLAG_KEY;
465     }
466     if (pkt->pts == AV_NOPTS_VALUE)
467         can_split = 0;
468     else
469         hls->duration = pts - hls->end_pts;
470
471     if (can_split && pts - hls->start_pts >= end_pts) {
472         ret = append_entry(hls, hls->duration);
473         if (ret)
474             return ret;
475
476         hls->end_pts = pts;
477         hls->duration = 0;
478
479         av_write_frame(oc, NULL); /* Flush any buffered data */
480         ff_format_io_close(s, &oc->pb);
481
482         ret = hls_start(s);
483
484         if (ret)
485             return ret;
486
487         oc = hls->avf;
488
489         if ((ret = hls_window(s, 0)) < 0)
490             return ret;
491     }
492
493     ret = ff_write_chained(oc, pkt->stream_index, pkt, s);
494
495     return ret;
496 }
497
498 static int hls_write_trailer(struct AVFormatContext *s)
499 {
500     HLSContext *hls = s->priv_data;
501     AVFormatContext *oc = hls->avf;
502
503     av_write_trailer(oc);
504     ff_format_io_close(s, &oc->pb);
505     avformat_free_context(oc);
506     av_free(hls->basename);
507     append_entry(hls, hls->duration);
508     hls_window(s, 1);
509
510     free_entries(hls);
511     free_encryption(s);
512     return 0;
513 }
514
515 #define OFFSET(x) offsetof(HLSContext, x)
516 #define E AV_OPT_FLAG_ENCODING_PARAM
517 static const AVOption options[] = {
518     {"start_number",  "first number in the sequence",            OFFSET(start_sequence),AV_OPT_TYPE_INT64,  {.i64 = 0},     0, INT64_MAX, E},
519     {"hls_time",      "segment length in seconds",               OFFSET(time),    AV_OPT_TYPE_FLOAT,  {.dbl = 2},     0, FLT_MAX, E},
520     {"hls_list_size", "maximum number of playlist entries",      OFFSET(size),    AV_OPT_TYPE_INT,    {.i64 = 5},     0, INT_MAX, E},
521     {"hls_wrap",      "number after which the index wraps",      OFFSET(wrap),    AV_OPT_TYPE_INT,    {.i64 = 0},     0, INT_MAX, E},
522     {"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},
523     {"hls_base_url",  "url to prepend to each playlist entry",   OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,       E},
524     {"hls_version",   "protocol version",                        OFFSET(version), AV_OPT_TYPE_INT,    {.i64 = 3},     2, 3, E},
525     {"hls_enc",       "AES128 encryption support",               OFFSET(encrypt), AV_OPT_TYPE_INT,    {.i64 = 0},     0, 1, E},
526     {"hls_enc_key",   "use the specified hex-coded 16byte key to encrypt the segments",  OFFSET(key), AV_OPT_TYPE_BINARY, .flags = E},
527     {"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},
528     {"hls_enc_iv",     "use the specified hex-coded 16byte initialization vector",  OFFSET(iv), AV_OPT_TYPE_BINARY, .flags = E},
529     { NULL },
530 };
531
532 static const AVClass hls_class = {
533     .class_name = "hls muxer",
534     .item_name  = av_default_item_name,
535     .option     = options,
536     .version    = LIBAVUTIL_VERSION_INT,
537 };
538
539
540 AVOutputFormat ff_hls_muxer = {
541     .name           = "hls",
542     .long_name      = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
543     .extensions     = "m3u8",
544     .priv_data_size = sizeof(HLSContext),
545     .audio_codec    = AV_CODEC_ID_AAC,
546     .video_codec    = AV_CODEC_ID_H264,
547     .flags          = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH,
548     .write_header   = hls_write_header,
549     .write_packet   = hls_write_packet,
550     .write_trailer  = hls_write_trailer,
551     .priv_class     = &hls_class,
552 };