FFmpeg
Loading...
Searching...
No Matches
hls_sample_encryption.c
Go to the documentation of this file.
1/*
2 * Apple HTTP Live Streaming Sample Encryption/Decryption
3 *
4 * Copyright (c) 2021 Nachiket Tarate
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/**
24 * @file
25 * Apple HTTP Live Streaming Sample Encryption
26 * https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/HLS_Sample_Encryption
27 */
28
29#include "libavutil/aes.h"
31#include "libavutil/mem.h"
32
34
37#include "libavcodec/ac3tab.h"
39
40
41typedef struct NALUnit {
42 uint8_t *data;
43 int type;
44 int length;
46} NALUnit;
47
48typedef struct AudioFrame {
49 uint8_t *data;
50 int length;
53
54typedef struct CodecParserContext {
55 const uint8_t *buf_ptr;
56 const uint8_t *buf_end;
58
59static const int eac3_sample_rate_tab[] = { 48000, 44100, 32000, 0 };
60
61void ff_hls_senc_read_audio_setup_info(HLSAudioSetupInfo *info, const uint8_t *buf, size_t size)
62{
63 if (size < 8)
64 return;
65
66 info->codec_tag = AV_RL32(buf);
67
68 /* Always keep this list in sync with the one from hls_read_header() */
69 if (info->codec_tag == MKTAG('z','a','a','c'))
71 else if (info->codec_tag == MKTAG('z','a','c','3'))
73 else if (info->codec_tag == MKTAG('z','e','c','3'))
75 else
77
78 buf += 4;
79 info->priming = AV_RL16(buf);
80 buf += 2;
81 info->version = *buf++;
82 info->setup_data_length = *buf++;
83
84 if (info->setup_data_length > size - 8)
85 info->setup_data_length = size - 8;
86
88 return;
89
90 memcpy(info->setup_data, buf, info->setup_data_length);
92}
93
95{
96 int ret = 0;
97
98 st->codecpar->codec_tag = info->codec_tag;
99
101 return 0;
102
104 return AVERROR_INVALIDDATA;
105
106 if (st->codecpar->codec_id == AV_CODEC_ID_AC3) {
107 AC3HeaderInfo *ac3hdr = NULL;
108
109 ret = avpriv_ac3_parse_header(&ac3hdr, info->setup_data, info->setup_data_length);
110 if (ret < 0) {
111 av_free(ac3hdr);
112 return ret;
113 }
114
115 st->codecpar->sample_rate = ac3hdr->sample_rate;
118 st->codecpar->bit_rate = ac3hdr->bit_rate;
119
120 av_free(ac3hdr);
121 } else { /* Parse 'dec3' EC3SpecificBox */
122 GetBitContext gb;
123 uint64_t mask;
124 int data_rate, fscod, acmod, lfeon;
125
126 ret = init_get_bits8(&gb, info->setup_data, info->setup_data_length);
127 if (ret < 0)
128 return AVERROR_INVALIDDATA;
129
130 data_rate = get_bits(&gb, 13);
131 skip_bits(&gb, 3);
132 fscod = get_bits(&gb, 2);
133 skip_bits(&gb, 10);
134 acmod = get_bits(&gb, 3);
135 lfeon = get_bits(&gb, 1);
136
138
140 if (lfeon)
142
145
146 st->codecpar->bit_rate = data_rate*1000;
147 }
148
149 return 0;
150}
151
152/*
153 * Remove start code emulation prevention 0x03 bytes
154 */
155static void remove_scep_3_bytes(NALUnit *nalu)
156{
157 int i = 0;
158 int j = 0;
159
160 uint8_t *data = nalu->data;
161
162 while (i < nalu->length) {
163 if (nalu->length - i > 3 && AV_RB24(&data[i]) == 0x000003) {
164 data[j++] = data[i++];
165 data[j++] = data[i++];
166 i++;
167 } else {
168 data[j++] = data[i++];
169 }
170 }
171
172 nalu->length = j;
173}
174
176{
177 const uint8_t *nalu_start = ctx->buf_ptr;
178
179 if (ctx->buf_end - ctx->buf_ptr >= 4 && AV_RB32(ctx->buf_ptr) == 0x00000001)
180 nalu->start_code_length = 4;
181 else if (ctx->buf_end - ctx->buf_ptr >= 3 && AV_RB24(ctx->buf_ptr) == 0x000001)
182 nalu->start_code_length = 3;
183 else /* No start code at the beginning of the NAL unit */
184 return -1;
185
186 ctx->buf_ptr += nalu->start_code_length;
187
188 while (ctx->buf_ptr < ctx->buf_end) {
189 if (ctx->buf_end - ctx->buf_ptr >= 4 && AV_RB32(ctx->buf_ptr) == 0x00000001)
190 break;
191 else if (ctx->buf_end - ctx->buf_ptr >= 3 && AV_RB24(ctx->buf_ptr) == 0x000001)
192 break;
193 ctx->buf_ptr++;
194 }
195
196 nalu->data = (uint8_t *)nalu_start + nalu->start_code_length;
197 nalu->length = ctx->buf_ptr - nalu->data;
198 nalu->type = *nalu->data & 0x1F;
199
200 return 0;
201}
202
203static int decrypt_nal_unit(HLSCryptoContext *crypto_ctx, NALUnit *nalu)
204{
205 int ret = 0;
206 int rem_bytes;
207 uint8_t *data;
208 uint8_t iv[16];
209
210 ret = av_aes_init(crypto_ctx->aes_ctx, crypto_ctx->key, 16 * 8, 1);
211 if (ret < 0)
212 return ret;
213
214 /* Remove start code emulation prevention 0x03 bytes */
216
217 data = nalu->data + 32;
218 rem_bytes = nalu->length - 32;
219
220 memcpy(iv, crypto_ctx->iv, 16);
221
222 while (rem_bytes > 0) {
223 if (rem_bytes > 16) {
224 av_aes_crypt(crypto_ctx->aes_ctx, data, data, 1, iv, 1);
225 data += 16;
226 rem_bytes -= 16;
227 }
228 data += FFMIN(144, rem_bytes);
229 rem_bytes -= FFMIN(144, rem_bytes);
230 }
231
232 return 0;
233}
234
236{
237 int ret = 0;
239 NALUnit nalu;
240 uint8_t *data_ptr;
241 int move_nalu = 0;
242
243 memset(&ctx, 0, sizeof(ctx));
244 ctx.buf_ptr = pkt->data;
245 ctx.buf_end = pkt->data + pkt->size;
246
247 data_ptr = pkt->data;
248
249 while (ctx.buf_ptr < ctx.buf_end) {
250 memset(&nalu, 0, sizeof(nalu));
251 ret = get_next_nal_unit(&ctx, &nalu);
252 if (ret < 0)
253 return ret;
254 if ((nalu.type == 0x01 || nalu.type == 0x05) && nalu.length > 48) {
255 int encrypted_nalu_length = nalu.length;
256 ret = decrypt_nal_unit(crypto_ctx, &nalu);
257 if (ret < 0)
258 return ret;
259 move_nalu = nalu.length != encrypted_nalu_length;
260 }
261 if (move_nalu)
262 memmove(data_ptr, nalu.data - nalu.start_code_length, nalu.start_code_length + nalu.length);
263 data_ptr += nalu.start_code_length + nalu.length;
264 }
265
266 av_shrink_packet(pkt, data_ptr - pkt->data);
267
268 return 0;
269}
270
272{
273 int ret = 0;
274
275 AACADTSHeaderInfo *adts_hdr = NULL;
276
277 /* Find next sync word 0xFFF */
278 while (ctx->buf_ptr < ctx->buf_end - 1) {
279 if (*ctx->buf_ptr == 0xFF && (*(ctx->buf_ptr + 1) & 0xF0) == 0xF0)
280 break;
281 ctx->buf_ptr++;
282 }
283
284 if (ctx->buf_ptr >= ctx->buf_end - 1)
285 return -1;
286
287 frame->data = (uint8_t*)ctx->buf_ptr;
288
289 ret = avpriv_adts_header_parse (&adts_hdr, frame->data, ctx->buf_end - frame->data);
290 if (ret < 0)
291 return ret;
292
293 frame->header_length = adts_hdr->crc_absent ? AV_AAC_ADTS_HEADER_SIZE : AV_AAC_ADTS_HEADER_SIZE + 2;
294 frame->length = adts_hdr->frame_length;
295
296 av_free(adts_hdr);
297
298 return 0;
299}
300
302{
303 int ret = 0;
304
305 AC3HeaderInfo *hdr = NULL;
306
307 /* Find next sync word 0x0B77 */
308 while (ctx->buf_ptr < ctx->buf_end - 1) {
309 if (*ctx->buf_ptr == 0x0B && *(ctx->buf_ptr + 1) == 0x77)
310 break;
311 ctx->buf_ptr++;
312 }
313
314 if (ctx->buf_ptr >= ctx->buf_end - 1)
315 return -1;
316
317 frame->data = (uint8_t*)ctx->buf_ptr;
318 frame->header_length = 0;
319
320 ret = avpriv_ac3_parse_header(&hdr, frame->data, ctx->buf_end - frame->data);
321 if (ret < 0) {
322 av_free(hdr);
323 return ret;
324 }
325
326 frame->length = hdr->frame_size;
327
328 av_free(hdr);
329
330 return 0;
331}
332
342
344{
345 int ret = 0;
346 uint8_t *data;
347 int num_of_encrypted_blocks;
348
349 ret = av_aes_init(crypto_ctx->aes_ctx, crypto_ctx->key, 16 * 8, 1);
350 if (ret < 0)
351 return ret;
352
353 data = frame->data + frame->header_length + 16;
354
355 num_of_encrypted_blocks = (frame->length - frame->header_length - 16)/16;
356
357 av_aes_crypt(crypto_ctx->aes_ctx, data, data, num_of_encrypted_blocks, crypto_ctx->iv, 1);
358
359 return 0;
360}
361
363{
364 int ret = 0;
367
368 memset(&ctx, 0, sizeof(ctx));
369 ctx.buf_ptr = pkt->data;
370 ctx.buf_end = pkt->data + pkt->size;
371
372 while (ctx.buf_ptr < ctx.buf_end) {
373 memset(&frame, 0, sizeof(frame));
375 if (ret < 0)
376 return ret;
377 if (frame.length < frame.header_length ||
378 frame.length > ctx.buf_end - frame.data) {
380 "Sample-AES: declared frame length %d exceeds packet data\n",
381 frame.length);
382 return AVERROR_INVALIDDATA;
383 }
384 if (frame.length - frame.header_length > 31) {
385 ret = decrypt_sync_frame(codec_id, crypto_ctx, &frame);
386 if (ret < 0)
387 return ret;
388 }
389 ctx.buf_ptr += frame.length;
390 }
391
392 return 0;
393}
394
396{
398 return decrypt_video_frame(crypto_ctx, pkt);
400 return decrypt_audio_frame(codec_id, crypto_ctx, pkt);
401
402 return AVERROR_INVALIDDATA;
403}
const uint16_t ff_ac3_channel_layout_tab[8]
Map audio coding mode (acmod) to channel layout mask.
int avpriv_ac3_parse_header(AC3HeaderInfo **phdr, const uint8_t *buf, size_t size)
Definition ac3_parser.c:491
int avpriv_adts_header_parse(AACADTSHeaderInfo **phdr, const uint8_t *buf, size_t size)
Parse the ADTS frame header contained in the buffer, which is the first 54 bits.
Definition adts_parser.c:50
#define AV_AAC_ADTS_HEADER_SIZE
Definition adts_parser.h:25
static AVFormatContext * ctx
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
Public libavutil channel layout APIs header.
#define NULL
Definition coverity.c:32
static AVPacket * pkt
static AVFrame * frame
static void skip_bits(GetBitContext *s, int n)
Definition get_bits.h:383
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition get_bits.h:544
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition get_bits.h:337
#define AV_CH_LOW_FREQUENCY
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition codec_id.h:47
@ AV_CODEC_ID_EAC3
Definition codec_id.h:493
@ AV_CODEC_ID_H264
Definition codec_id.h:77
@ AV_CODEC_ID_NONE
Definition codec_id.h:48
@ AV_CODEC_ID_AAC
Definition codec_id.h:455
@ AV_CODEC_ID_AC3
Definition codec_id.h:456
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition defs.h:40
void av_shrink_packet(AVPacket *pkt, int size)
Reduce packet size, correctly zeroing padding.
Definition packet.c:113
int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt)
Initialize an AVAES context.
Definition aes.c:231
void av_aes_crypt(AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt)
Encrypt or decrypt a buffer using a previously initialized context.
Definition aes.c:171
void av_channel_layout_uninit(AVChannelLayout *channel_layout)
Free any allocated data in the channel layout and reset the channel count to 0.
int av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask)
Initialize a native channel layout from a bitmask indicating which channels are present.
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
static const int eac3_sample_rate_tab[]
int ff_hls_senc_decrypt_frame(enum AVCodecID codec_id, HLSCryptoContext *crypto_ctx, AVPacket *pkt)
static int decrypt_video_frame(HLSCryptoContext *crypto_ctx, AVPacket *pkt)
int ff_hls_senc_parse_audio_setup_info(AVStream *st, HLSAudioSetupInfo *info)
static void remove_scep_3_bytes(NALUnit *nalu)
static int get_next_adts_frame(CodecParserContext *ctx, AudioFrame *frame)
static int decrypt_sync_frame(enum AVCodecID codec_id, HLSCryptoContext *crypto_ctx, AudioFrame *frame)
static int decrypt_nal_unit(HLSCryptoContext *crypto_ctx, NALUnit *nalu)
static int decrypt_audio_frame(enum AVCodecID codec_id, HLSCryptoContext *crypto_ctx, AVPacket *pkt)
static int get_next_nal_unit(CodecParserContext *ctx, NALUnit *nalu)
void ff_hls_senc_read_audio_setup_info(HLSAudioSetupInfo *info, const uint8_t *buf, size_t size)
static int get_next_sync_frame(enum AVCodecID codec_id, CodecParserContext *ctx, AudioFrame *frame)
static int get_next_ac3_eac3_sync_frame(CodecParserContext *ctx, AudioFrame *frame)
Apple HTTP Live Streaming Sample Encryption https://developer.apple.com/library/ios/documentation/Aud...
#define HLS_MAX_AUDIO_SETUP_DATA_LEN
#define AV_RL32(p)
#define AV_RB32(p)
#define AV_RL16(p)
#define AV_RB24(x)
static const uint16_t mask[17]
Definition lzw.c:38
#define FFMIN(a, b)
Definition macros.h:49
#define MKTAG(a, b, c, d)
Definition macros.h:55
Memory handling functions.
const char data[16]
Definition mxf.c:149
uint32_t frame_length
Definition adts_header.h:44
Coded AC-3 header values up to the lfeon element, plus derived values.
AVChannelLayout ch_layout
The channel layout and number of channels.
Definition codec_par.h:207
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition codec_par.h:99
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition codec_par.h:61
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
int sample_rate
The number of audio samples per second.
Definition codec_par.h:213
This structure stores compressed data.
Definition packet.h:580
Stream structure.
Definition avformat.h:766
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:789
uint8_t setup_data[HLS_MAX_AUDIO_SETUP_DATA_LEN+AV_INPUT_BUFFER_PADDING_SIZE]
#define av_free(p)
#define av_log(a,...)
int size
enum AVCodecID codec_id