static int celt_header(AVFormatContext *s, int idx)

{

    struct ogg *ogg = s->priv_data;

    struct ogg_stream *os = ogg->streams + idx;

    AVStream *st = s->streams[idx];

    struct oggcelt_private *priv = os->private;

    uint8_t *p = os->buf + os->pstart;



    if (os->psize == 60 &&

        !memcmp(p, ff_celt_codec.magic, ff_celt_codec.magicsize)) {

        /* Main header */



        uint32_t version, sample_rate, nb_channels;

        uint32_t overlap, extra_headers;



        priv = av_malloc(sizeof(struct oggcelt_private));

        if (!priv)

            return AVERROR(ENOMEM);

        if (ff_alloc_extradata(st->codecpar, 2 * sizeof(uint32_t)) < 0) {

            av_free(priv);

            return AVERROR(ENOMEM);

        }

        version          = AV_RL32(p + 28);

        /* unused header size field skipped */

        sample_rate      = AV_RL32(p + 36);

        nb_channels      = AV_RL32(p + 40);

        overlap          = AV_RL32(p + 48);

        /* unused bytes per packet field skipped */

        extra_headers    = AV_RL32(p + 56);

        st->codecpar->codec_type     = AVMEDIA_TYPE_AUDIO;

        st->codecpar->codec_id       = AV_CODEC_ID_CELT;

        st->codecpar->sample_rate    = sample_rate;

        st->codecpar->channels       = nb_channels;

        if (sample_rate)

            avpriv_set_pts_info(st, 64, 1, sample_rate);

        priv->extra_headers_left  = 1 + extra_headers;

        av_free(os->private);

        os->private = priv;

        AV_WL32(st->codecpar->extradata + 0, overlap);

        AV_WL32(st->codecpar->extradata + 4, version);

        return 1;

    } else if (priv && priv->extra_headers_left) {

        /* Extra headers (vorbiscomment) */



        ff_vorbis_stream_comment(s, st, p, os->psize);

        priv->extra_headers_left--;

        return 1;

    } else {

        return 0;

    }

}
