[FFmpeg-devel] [PATCH 2/3] libavformat/hls: add support for SAMPLE-AES decryption in HLS demuxer

James Almer jamrial at gmail.com
Tue Jan 19 21:31:09 EET 2021


On 1/18/2021 2:39 PM, Nachiket Tarate wrote:
> +typedef struct AVParserContext {
> +    const uint8_t   *buf_in;
> +    const uint8_t   *buf_end;
> +    uint8_t         *buf_out;
> +    int             next_start_code_length;
> +} AVParserContext;

The AV prefix in structs names should not be used for an internal struct 
used in a single file.

[...]

> +/*
> + * Parse 'dec3' EC3SpecificBox
> + */
> +static int parse_dec3(AC3HeaderInfo **phdr, const uint8_t *buf, size_t size)
> +{
> +    GetBitContext gb;
> +    AC3HeaderInfo *hdr;
> +    int err;
> +
> +    int data_rate, fscod, acmod, lfeon;
> +
> +    if (!*phdr)
> +        *phdr = av_mallocz(sizeof(AC3HeaderInfo));

sizeof(AC3HeaderInfo) is not meant to be used outside of libavcodec. 
It's why avpriv_ac3_parse_header() resides in libavcodec and allocates 
it when used from libavformat.

Since parsing the dec3 atom is trivial, you can do it directly in 
ff_hls_parse_audio_setup_info and store the values in local independent 
variables (or even straight to st->codecpar) without the need for an 
AC3HeaderInfo struct.

> +    if (!*phdr)
> +        return AVERROR(ENOMEM);
> +    hdr = *phdr;
> +
> +    err = init_get_bits8(&gb, buf, size);
> +    if (err < 0)
> +        return AVERROR_INVALIDDATA;
> +
> +    data_rate = get_bits(&gb, 13);
> +    skip_bits(&gb, 3);
> +    fscod = get_bits(&gb, 2);
> +    skip_bits(&gb, 10);
> +    acmod = get_bits(&gb, 3);
> +    lfeon = get_bits(&gb, 1);
> +
> +    hdr->sample_rate = eac3_sample_rate_tab[fscod];
> +
> +    hdr->channel_layout = avpriv_ac3_channel_layout_tab[acmod];
> +    if (lfeon)
> +        hdr->channel_layout |= AV_CH_LOW_FREQUENCY;
> +
> +    hdr->channels = av_get_channel_layout_nb_channels(hdr->channel_layout);
> +
> +    hdr->bit_rate = data_rate*1000;
> +
> +    return 0;
> +}
> +
> +int ff_hls_parse_audio_setup_info(AVStream *st, HLSAudioSetupInfo *info)
> +{
> +    int ret = 0;
> +
> +    AC3HeaderInfo *ac3hdr = NULL;
> +
> +    st->codecpar->codec_tag = info->codec_tag;
> +
> +    if (st->codecpar->codec_id == AV_CODEC_ID_AAC)
> +        return 0;
> +
> +    st->codecpar->extradata = av_mallocz(info->setup_data_length + AV_INPUT_BUFFER_PADDING_SIZE);
> +
> +    if (!st->codecpar->extradata)
> +        return AVERROR(ENOMEM);
> +
> +    st->codecpar->extradata_size = info->setup_data_length;
> +
> +    if (st->codecpar->codec_id == AV_CODEC_ID_AC3)
> +        ret = avpriv_ac3_parse_header(&ac3hdr, info->setup_data, info->setup_data_length);

Are you sure this is correct? avpriv_ac3_parse_header() parses raw ac3 
and eac3 frame headers, and if eac3 here is supposedly stored as a dec3 
atom, wouldn't ac3 be the same using a dac3 atom?

> +    else if (st->codecpar->codec_id == AV_CODEC_ID_EAC3)
> +        ret = parse_dec3(&ac3hdr, info->setup_data, info->setup_data_length);
> +    else
> +        return -1;

AVERROR_INVALIDDATA. Is this function going to be called with other 
codec ids to trigger this path?

[...]

> @@ -2019,9 +2075,14 @@ static int hls_read_header(AVFormatContext *s)
>           * on us if they want to.
>           */
>          if (pls->is_id3_timestamped || (pls->n_renditions > 0 && pls->renditions[0]->type == AVMEDIA_TYPE_AUDIO)) {
> +            if (seg && seg->key_type == KEY_SAMPLE_AES && pls->audio_setup_info.setup_data_length > 0 &&
> +                pls->ctx->nb_streams == 1) {
> +                ff_hls_parse_audio_setup_info(pls->ctx->streams[0], &pls->audio_setup_info);

The return value is being ignored.

> +            } else {
>              ret = avformat_find_stream_info(pls->ctx, NULL);
>              if (ret < 0)
>                  goto fail;
> +            }
>          }
>  
>          pls->has_noheader_flag = !!(pls->ctx->ctx_flags & AVFMTCTX_NOHEADER);




More information about the ffmpeg-devel mailing list