Quoting Mark Thompson (2017-05-14 23:24:11)
> ---
>  libavcodec/cbs.c             |    1 +
>  libavcodec/cbs_h264.h        |  396 +++++++++++++++
>  libavcodec/cbs_h2645.c       |  734 ++++++++++++++++++++++++++++
>  libavcodec/cbs_h264_syntax.c | 1099 
> ++++++++++++++++++++++++++++++++++++++++++
>  libavcodec/cbs_internal.h    |    3 +
>  5 files changed, 2233 insertions(+)
>  create mode 100644 libavcodec/cbs_h264.h
>  create mode 100644 libavcodec/cbs_h2645.c
>  create mode 100644 libavcodec/cbs_h264_syntax.c
> 
> diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
> index 002c11cc6..93556eb91 100644
> --- a/libavcodec/cbs.c
> +++ b/libavcodec/cbs.c
> @@ -27,6 +27,7 @@
>  
>  
>  static const CodedBitstreamType *cbs_type_table[] = {
> +    &ff_cbs_type_h264,
>  };
>  
>  int ff_cbs_init(CodedBitstreamContext *ctx,
> diff --git a/libavcodec/cbs_h264.h b/libavcodec/cbs_h264.h
> new file mode 100644
> index 000000000..8e8aae4da
> --- /dev/null
> +++ b/libavcodec/cbs_h264.h
> @@ -0,0 +1,396 @@
> +/*
> + * This file is part of Libav.
> + *
> + * Libav is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * Libav is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with Libav; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
> + */
> +
> +#ifndef AVCODEC_CBS_H264_H
> +#define AVCODEC_CBS_H264_H
> +
> +#include <stdint.h>
> +
> +
> +enum {
> +    H264_MAX_SPS = 32,
> +    H264_MAX_PPS = 256,
> +
> +    H264_MAX_REFS = 31,

31? You sure?

> +
> +    H264_MAX_CPB_CNT = 32,
> +
> +    H264_MAX_RPLM = H264_MAX_REFS + 1,
> +    H264_MAX_MMCO = H264_MAX_REFS * 2 + 3,
> +
> +    H264_MAX_SEI_PAYLOADS = 64,

Is this a spec-defined limit?

> +};

Would be nice to share those with the already existing values.
(would be even nicer to share a lot of this code, but I understand
that's a lot more work)

> +static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx,
> +                                       CodedBitstreamFragment *frag,
> +                                       const H2645Packet *packet)
> +{
> +    int err, i, start;
> +
> +    start = frag->nb_units;
> +    frag->nb_units += packet->nb_nals;
> +
> +    err = av_reallocp_array(&frag->units, frag->nb_units,
> +                            sizeof(*frag->units));

Same as the comment for the other patch. Also, it seems rather weird and
fragile that you're messing with the parent's internals directly
rather than through a function call. 

> +    if (err < 0)
> +        return err;
> +    memset(frag->units + start, 0,
> +           packet->nb_nals * sizeof(*frag->units));
> +
> +    for (i = 0; i < packet->nb_nals; i++) {
> +        CodedBitstreamUnit *unit = &frag->units[start + i];
> +        const H2645NAL *nal = &packet->nals[i];
> +
> +        unit->type = nal->type;
> +
> +        unit->data = av_malloc(nal->size);
> +        if (!unit->data)
> +            return AVERROR(ENOMEM);
> +        memcpy(unit->data, nal->data, nal->size);
> +        unit->data_size = nal->size;
> +    }
> +
> +    return 0;
> +}
> +
> +static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx,
> +                                    CodedBitstreamFragment *frag,
> +                                    int header)
> +{
> +    enum AVCodecID codec_id = ctx->codec->codec_id;
> +    H2645Packet packet = { 0 };
> +    int err;
> +
> +    if (frag->nb_units != 0)
> +        return AVERROR(EINVAL);

nit: I'm not a huge fan of such "is our caller being sane?" checks,
since if the caller is insane then you're screwed either way and it can
just hide bugs.

> +
> +    if (header && frag->data[0] && codec_id == AV_CODEC_ID_H264) {
> +        // AVCC header.
> +        CodedBitstreamH264Context *h264 = ctx->priv_data;
> +        uint8_t *data = frag->data;
> +        size_t size, start, end;
> +        int i, count;
> +
> +        h264->avcc = 1;
> +        if (data[0] != 1) {
> +            av_log(ctx, AV_LOG_ERROR, "Invalid AVCC header: "
> +                   "first byte %u.", *data);
> +            return AVERROR_INVALIDDATA;
> +        }
> +
> +        h264->nal_length_size = (data[4] & 3) + 1;
> +        count = data[5] & 0x1f;

Unchecked reads. I'd use the bytestream2 API.

> +
> +        start = end = 6;
> +        for (i = 0; i < count; i++) {
> +            size = AV_RB16(data + end) + 2;
> +            if (end + size > frag->data_size)
> +                return AVERROR_INVALIDDATA;
> +            end += size;
> +        }
> +        err = ff_h2645_packet_split(&packet, frag->data + start, end - start,
> +                                    ctx, 1, 2, AV_CODEC_ID_H264);
> +        if (err < 0) {
> +            av_log(ctx, AV_LOG_ERROR, "Failed to split AVCC SPSs.\n");
> +            return err;
> +        }
> +
> +        err = cbs_h2645_fragment_add_nals(ctx, frag, &packet);
> +        ff_h2645_packet_uninit(&packet);

You could store the packet in the context and call uninit only once at
the end. It doesn't need to (and shouldn't) be called after every split.

> +static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx,
> +                                  CodedBitstreamUnit *unit)
> +{
> +    BitstreamContext bc;
> +    int err;
> +
> +    err = bitstream_init(&bc, unit->data, 8 * unit->data_size);
> +    if (err < 0)
> +        return err;
> +
> +    switch (unit->type) {
> +    case H264_NAL_SPS:
> +        {
> +            H264RawSPS *sps;
> +
> +            sps = av_mallocz(sizeof(*sps));
> +            if (!sps)
> +                return AVERROR(ENOMEM);
> +            err = cbs_h264_read_sps(ctx, &bc, sps);
> +            if (err < 0) {
> +                av_free(sps);
> +                return err;
> +            }
> +
> +            cbs_h264_replace_sps(ctx, sps);

Should probably check the return value. Same below.


-- 
Anton Khirnov
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to