[FFmpeg-devel] [PATCH] avformat/hlsenc: added HLS encryption

Michael Niedermayer michaelni at gmx.at
Tue Dec 23 01:36:08 CET 2014


On Mon, Dec 22, 2014 at 01:54:17PM -0600, Christian Suloway wrote:
> Added HLS encryption with -hls_key_info_file <key_info_file> option.
> The first line of key_info_file specifies the key URI for the playlist.
> The second line specifies the path to the file containing the encryption
> key. An optional third line specifies an IV to use instead of the
> segment number. Changes to key_info_file will be reflected in segment
> encryption along with an entry in the playlist for the new key URI and
> IV.
> 
> Signed-off-by: Christian Suloway <csuloway at globaleagleent.com>
> ---
>  doc/muxers.texi      |   9 ++
>  libavformat/hlsenc.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 238 insertions(+), 6 deletions(-)
> 
> diff --git a/doc/muxers.texi b/doc/muxers.texi
> index a1264d2..f2ecf8b 100644
> --- a/doc/muxers.texi
> +++ b/doc/muxers.texi
> @@ -263,6 +263,15 @@ ffmpeg in.nut -hls_segment_filename 'file%03d.ts' out.m3u8
>  This example will produce the playlist, @file{out.m3u8}, and segment files:
>  @file{file000.ts}, @file{file001.ts}, @file{file002.ts}, etc.
>  
> + at item hls_key_info_file @var{file}
> +Use in the information in @var{file} for segment encryption. The first line of
> + at var{file} specifies the key URI for the playlist. The second line specifies
> +the path to the file containing the encryption key as a single packed array of
> +16 octets in binary format. The optional third line specifies a hexidecimal
> +string for the initialization vector (IV) to be used instead of the segment
> +number. Changes to @var{file} will result in segment encryption with the new
> +key/IV and an entry in the playlist for the new key URI/IV.
> +
>  @item hls_flags single_file
>  If this flag is set, the muxer will store all segments in a single MPEG-TS
>  file, and will use byte ranges in the playlist. HLS playlists generated with
> diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
> index f46e8d4..1dba60c 100644
> --- a/libavformat/hlsenc.c
> +++ b/libavformat/hlsenc.c
> @@ -37,12 +37,18 @@
>  #include "internal.h"
>  #include "os_support.h"
>  
> +#define BLOCKSIZE 16
> +
>  typedef struct HLSSegment {
>      char filename[1024];
>      double duration; /* in seconds */
>      int64_t pos;
>      int64_t size;
>  
> +    char *key_uri;
> +    char *iv_string;
> +    int attribute_iv;
> +
>      struct HLSSegment *next;
>  } HLSSegment;
>  
> @@ -86,9 +92,23 @@ typedef struct HLSContext {
>      char *format_options_str;
>      AVDictionary *format_options;
>  
> +    char *key_info_file;
> +    char *key_file;
> +    char *key_uri;
> +    char *key_string;
> +    char *iv_string;
> +    int attribute_iv;
> +
>      AVIOContext *pb;
>  } HLSContext;
>  
> +static void hls_free_segment(HLSSegment *en)
> +{
> +   av_freep(&en->key_uri);
> +   av_freep(&en->iv_string);
> +   av_freep(&en);
> +}
> +
>  static int hls_delete_old_segments(HLSContext *hls) {
>  
>      HLSSegment *segment, *previous_segment = NULL;
> @@ -145,7 +165,7 @@ static int hls_delete_old_segments(HLSContext *hls) {
>          av_free(path);
>          previous_segment = segment;
>          segment = previous_segment->next;
> -        av_free(previous_segment);
> +        hls_free_segment(previous_segment);
>      }
>  
>  fail:

> @@ -154,6 +174,134 @@ fail:
>      return ret;
>  }
>  
> +static int hls_encryption_start(HLSContext *hls)
> +{
> +
> +    int ret = 0, i;
> +    AVIOContext *pb = NULL, *dyn_buf = NULL;
> +    uint8_t buf[1024], *tmp = NULL, *key = NULL, *iv = NULL;
> +    char *p, *tstr, *saveptr = NULL, *key_string = NULL, *iv_string = NULL;
> +
> +    if ((ret = avio_open(&pb, hls->key_info_file, AVIO_FLAG_READ)) < 0) {
> +        av_log(hls, AV_LOG_ERROR, "error opening key info file %s\n",
> +                                  hls->key_info_file);
> +        goto fail;
> +    }
> +
> +    ret = avio_open_dyn_buf(&dyn_buf);
> +    if (ret < 0) {
> +        avio_closep(&pb);
> +        goto fail;
> +    }
> +
> +    while ((ret = avio_read(pb, buf, sizeof(buf))) > 0)
> +        avio_write(dyn_buf, buf, ret);
> +    avio_closep(&pb);
> +    if (ret != AVERROR_EOF && ret < 0) {
> +        avio_close_dyn_buf(dyn_buf, &tmp);
> +        goto fail;
> +    }
> +
> +    avio_w8(dyn_buf, 0);
> +    if ((ret = avio_close_dyn_buf(dyn_buf, &tmp)) < 0)
> +        goto fail;
> +
> +    p = tmp;
> +    if (!(tstr = av_strtok(p, "\n", &saveptr)) || !*tstr) {
> +        av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file %s\n",
> +                                  hls->key_info_file);
> +        ret = AVERROR(EINVAL);
> +        goto fail;
> +    }

this looks a bit odd,
see ff_get_line(), it probably allows to simplify this alot

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

If a bugfix only changes things apparently unrelated to the bug with no
further explanation, that is a good sign that the bugfix is wrong.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20141223/65903f07/attachment.asc>


More information about the ffmpeg-devel mailing list