2017-04-06 23:02 GMT+08:00 Steven Liu <l...@chinaffmpeg.org>: > refer to: > https://git.libav.org/?p=libav.git;a=commitdiff;h= > 0a4b9d0ccd10b3c39105f99bd320f696f69a75a2 > add hls encrypt options looks like libav's libavformat/hlsenc.c > > Signed-off-by: Steven Liu <l...@chinaffmpeg.org> > --- > doc/muxers.texi | 16 +++++++ > libavformat/hlsenc.c | 122 ++++++++++++++++++++++++++++++ > ++++++++++++++++++--- > 2 files changed, 133 insertions(+), 5 deletions(-) > > diff --git a/doc/muxers.texi b/doc/muxers.texi > index 166c929369..db1c3db999 100644 > --- a/doc/muxers.texi > +++ b/doc/muxers.texi > @@ -597,6 +597,22 @@ ffmpeg -f lavfi -re -i testsrc -c:v h264 -hls_flags > delete_segments \ > -hls_key_info_file file.keyinfo out.m3u8 > @end example > > +@item -hls_enc @var{enc} > +Enable (1) or disable (0) the AES128 encryption. > +When enabled every segment generated is encrypted and the encryption key > +is saved as @var{playlist name}.key. > + > +@item -hls_enc_key @var{key} > +Hex-coded 16byte key to encrypt the segments, by default it > +is randomly generated. > + > +@item -hls_enc_key_url @var{keyurl} > +If set, @var{keyurl} is prepended instead of @var{baseurl} to the key > filename > +in the playlist. > + > +@item -hls_enc_iv @var{iv} > +Hex-coded 16byte initialization vector for every segment instead > +of the autogenerated ones. > > @item hls_flags @var{flags} > Possible values: > diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c > index e6c378df2e..f359bb9036 100644 > --- a/libavformat/hlsenc.c > +++ b/libavformat/hlsenc.c > @@ -26,10 +26,18 @@ > #include <unistd.h> > #endif > > +#if CONFIG_GCRYPT > +#include <gcrypt.h> > +#elif CONFIG_OPENSSL > +#include <openssl/rand.h> > +#endif > + > #include "libavutil/avassert.h" > #include "libavutil/mathematics.h" > #include "libavutil/parseutils.h" > #include "libavutil/avstring.h" > +#include "libavutil/intreadwrite.h" > +#include "libavutil/random_seed.h" > #include "libavutil/opt.h" > #include "libavutil/log.h" > #include "libavutil/time_internal.h" > @@ -139,6 +147,12 @@ typedef struct HLSContext { > char *subtitle_filename; > AVDictionary *format_options; > > + int encrypt; > + char *key; > + char *key_url; > + char *iv; > + char *key_basename; > + > char *key_info_file; > char key_file[LINE_BUFFER_SIZE + 1]; > char key_uri[LINE_BUFFER_SIZE + 1]; > @@ -349,6 +363,89 @@ fail: > return ret; > } > > +static int randomize(uint8_t *buf, int len) > +{ > +#if CONFIG_GCRYPT > + gcry_randomize(buf, len, GCRY_VERY_STRONG_RANDOM); > + return 0; > +#elif CONFIG_OPENSSL > + if (RAND_bytes(buf, len)) > + return 0; > +#else > + return AVERROR(ENOSYS); > +#endif > + return AVERROR(EINVAL); > +} > + > +static int do_encrypt(AVFormatContext *s) > +{ > + HLSContext *hls = s->priv_data; > + int ret; > + int len; > + AVIOContext *pb; > + uint8_t key[KEYSIZE]; > + > + len = strlen(hls->basename) + 4 + 1; > + hls->key_basename = av_mallocz(len); > + if (!hls->key_basename) > + return AVERROR(ENOMEM); > + > + av_strlcpy(hls->key_basename, s->filename, len); > + av_strlcat(hls->key_basename, ".key", len); > + > + if (hls->key_url) { > + strncpy(hls->key_file, hls->key_url, sizeof(hls->key_file)); > + strncpy(hls->key_uri, hls->key_url, sizeof(hls->key_uri)); > + } else { > + strncpy(hls->key_file, hls->key_basename, sizeof(hls->key_file)); > + strncpy(hls->key_uri, hls->key_basename, sizeof(hls->key_uri)); > + } > + > + if (!*hls->iv_string) { > + uint8_t iv[16] = { 0 }; > + char buf[33]; > + > + if (!hls->iv) { > + AV_WB64(iv + 8, hls->sequence); > + } else { > + memcpy(iv, hls->iv, sizeof(iv)); > + } > + ff_data_to_hex(buf, iv, sizeof(iv), 0); > + buf[32] = '\0'; > + memcpy(hls->iv_string, buf, sizeof(hls->iv_string)); > + } > + > + if (!*hls->key_uri) { > + av_log(hls, AV_LOG_ERROR, "no key URI specified in key info > file\n"); > + return AVERROR(EINVAL); > + } > + > + if (!*hls->key_file) { > + av_log(hls, AV_LOG_ERROR, "no key file specified in key info > file\n"); > + return AVERROR(EINVAL); > + } > + > + if (!*hls->key_string) { > + if (!hls->key) { > + if ((ret = randomize(key, sizeof(key))) < 0) { > + av_log(s, AV_LOG_ERROR, "Cannot generate a strong random > key\n"); > + return ret; > + } > + } else { > + memcpy(key, hls->key, sizeof(key)); > + } > + > + ff_data_to_hex(hls->key_string, key, sizeof(key), 0); > + if ((ret = s->io_open(s, &pb, hls->key_file, AVIO_FLAG_WRITE, > NULL)) < 0) > + return ret; > + avio_seek(pb, 0, SEEK_CUR); > + avio_write(pb, key, KEYSIZE); > + avio_close(pb); > + } > + return 0; > +} > + > + > static int hls_encryption_start(AVFormatContext *s) > { > HLSContext *hls = s->priv_data; > @@ -662,7 +759,7 @@ static int hls_append_segment(struct AVFormatContext > *s, HLSContext *hls, double > hls->discontinuity = 0; > } > > - if (hls->key_info_file) { > + if (hls->key_info_file || hls->encrypt) { > av_strlcpy(en->key_uri, hls->key_uri, sizeof(en->key_uri)); > av_strlcpy(en->iv_string, hls->iv_string, sizeof(en->iv_string)); > } > @@ -865,7 +962,7 @@ static int hls_window(AVFormatContext *s, int last) > hls->discontinuity_set = 1; > } > for (en = hls->segments; en; en = en->next) { > - if (hls->key_info_file && (!key_uri || strcmp(en->key_uri, > key_uri) || > + if ((hls->encrypt || hls->key_info_file) && (!key_uri || > strcmp(en->key_uri, key_uri) || > av_strcasecmp(en->iv_string, > iv_string))) { > avio_printf(out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", > en->key_uri); > if (*en->iv_string) > @@ -1031,9 +1128,18 @@ static int hls_start(AVFormatContext *s) > av_strlcat(oc->filename, ".tmp", sizeof(oc->filename)); > } > > - if (c->key_info_file) { > - if ((err = hls_encryption_start(s)) < 0) > - goto fail; > + if (c->key_info_file || c->encrypt) { > + if (c->key_info_file && c->encrypt) { > + av_log(s, AV_LOG_WARNING, "Cannot use both -hls_key_info_file > and -hls_enc," > + " will use -hls_key_info_file priority\n"); > + } > + if (c->key_info_file) { > + if ((err = hls_encryption_start(s)) < 0) > + goto fail; > + } else { > + if ((err = do_encrypt(s)) < 0) > + goto fail; > + } > if ((err = av_dict_set(&options, "encryption_key", c->key_string, > 0)) > < 0) > goto fail; > @@ -1300,6 +1406,7 @@ fail: > if (ret < 0) { > av_freep(&hls->basename); > av_freep(&hls->vtt_basename); > + av_freep(&hls->key_basename); > if (hls->avf) > avformat_free_context(hls->avf); > if (hls->vtt_avf) > @@ -1469,6 +1576,7 @@ static int hls_write_trailer(struct AVFormatContext > *s) > ff_format_io_close(s, &vtt_oc->pb); > } > av_freep(&hls->basename); > + av_freep(&hls->key_basename); > avformat_free_context(oc); > > hls->avf = NULL; > @@ -1503,6 +1611,10 @@ static const AVOption options[] = { > {"hls_segment_filename", "filename template for segment files", > OFFSET(segment_filename), AV_OPT_TYPE_STRING, {.str = NULL}, > 0, 0, E}, > {"hls_segment_size", "maximum size per segment file, (in bytes)", > OFFSET(max_seg_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, > INT_MAX, E}, > {"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}, > + {"hls_enc", "enable AES128 encryption support", OFFSET(encrypt), > AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E}, > + {"hls_enc_key", "hex-coded 16 byte key to encrypt the segments", > OFFSET(key), AV_OPT_TYPE_STRING, .flags = E}, > + {"hls_enc_key_url", "url to access the key to decrypt the > segments", OFFSET(key_url), AV_OPT_TYPE_STRING, {.str = NULL}, > 0, 0, E}, > + {"hls_enc_iv", "hex-coded 16 byte initialization vector", > OFFSET(iv), AV_OPT_TYPE_STRING, .flags = E}, > {"hls_subtitle_path", "set path of hls subtitles", > OFFSET(subtitle_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, > {"hls_flags", "set flags affecting HLS playlist and media file > generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, > "flags"}, > {"single_file", "generate a single media file indexed with byte > ranges", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SINGLE_FILE }, 0, UINT_MAX, E, > "flags"}, > -- > 2.11.0 (Apple Git-81) > > > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel >
pushed Thanks _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel