[FFmpeg-devel] [PATCH v2] avformat/oggenc: Add partial support for OggPCM muxing

Lynne dev at lynne.ee
Thu May 28 13:55:04 EEST 2020


May 28, 2020, 11:34 by oreo639 at outlook.com:

> This adds partial support for OggPCM muxing.
>
> +static inline uint32_t ogg_get_pcm_format_id(uint32_t codec_id)
>

use enum AVCodecID instead of uint32_t.
Also use that in ogg_pcm_codec for the codec IDs.



> +{
> +    int i;
> +
> +    for (i = 0; i < FF_ARRAY_ELEMS(ogg_pcm_codecs); i++)
>

Save 2 lines, use for (int i...



> +        if (ogg_pcm_codecs[i].codec_id == codec_id)
> +            return ogg_pcm_codecs[i].format_id;
> +
> +    return 0;
>

return AV_CODEC_ID_NONE;



> +}
> +
>  static void ogg_write_page(AVFormatContext *s, OGGPage *page, int extra_flags)
>  {
>  OGGStreamContext *oggstream = s->streams[page->stream_index]->priv_data;
> @@ -363,6 +393,39 @@ static int ogg_build_speex_headers(AVCodecParameters *par,
>  return 0;
>  }
>
> +#define OGGPCM_HEADER_SIZE 224
> +
> +static int ogg_build_pcm_headers(AVCodecParameters *par,
> +                                   OGGStreamContext *oggstream, int bitexact,
> +                                   AVDictionary **m)
>

Indentation seems wrong here.



> +{
> +    uint8_t *p;
> +
> +    // first packet: OggPCM header
> +    p = av_mallocz(OGGPCM_HEADER_SIZE);
> +    if (!p)
> +        return AVERROR(ENOMEM);
> +    oggstream->header[0] = p;
> +    oggstream->header_len[0] = OGGPCM_HEADER_SIZE;
> +    bytestream_put_buffer(&p, "PCM     ", 8); // Identifier
> +    bytestream_put_be16(&p, 0x00); // VMAJ
> +    bytestream_put_be16(&p, 0x00); // VMIN
> +    bytestream_put_be32(&p, ogg_get_pcm_format_id(par->codec_id)); // PCM fmt
> +    bytestream_put_be32(&p, par->sample_rate); // Sample rate
> +    bytestream_put_byte(&p, 0); // Significant bits (0 == Same as fmt)
>

That's not correct.
par->bits_per_raw_sample is what you want it set to.



> +    bytestream_put_byte(&p, par->channels); // Channels
> +    bytestream_put_be16(&p, 0); // Max frames per packet TODO:// Actually calculate max frames per packet
>

That's not really possible. PCM data packets can contain any number of samples.
Best you can do is place an upper bound for it, since an Ogg packet cannot be larger than
65xxx bytes.



> +    bytestream_put_be32(&p, 0); // Number of extra headers
> +
> +    // second packet: VorbisComment
> +    p = ogg_write_vorbiscomment(0, bitexact, &oggstream->header_len[1], m, 0, NULL, 0);
> +    if (!p)
> +        return AVERROR(ENOMEM);
> +    oggstream->header[1] = p;
> +
> +    return 0;
> +}
> +
>  #define OPUS_HEADER_SIZE 19
>
>  static int ogg_build_opus_headers(AVCodecParameters *par,
> @@ -487,18 +550,20 @@ static int ogg_init(AVFormatContext *s)
>  avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
>  }
>
> -        if (st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
> -            st->codecpar->codec_id != AV_CODEC_ID_THEORA &&
> -            st->codecpar->codec_id != AV_CODEC_ID_SPEEX  &&
> -            st->codecpar->codec_id != AV_CODEC_ID_FLAC   &&
> -            st->codecpar->codec_id != AV_CODEC_ID_OPUS   &&
> +        if (st->codecpar->codec_id != AV_CODEC_ID_VORBIS   &&
> +            st->codecpar->codec_id != AV_CODEC_ID_THEORA   &&
> +            st->codecpar->codec_id != AV_CODEC_ID_SPEEX    &&
> +            st->codecpar->codec_id != AV_CODEC_ID_FLAC     &&
> +            st->codecpar->codec_id != AV_CODEC_ID_OPUS     &&
> +            !ogg_get_pcm_format_id(st->codecpar->codec_id) &&
>  st->codecpar->codec_id != AV_CODEC_ID_VP8) {
>  av_log(s, AV_LOG_ERROR, "Unsupported codec id in stream %d\n", i);
>  return AVERROR(EINVAL);
>  }
>
>  if ((!st->codecpar->extradata || !st->codecpar->extradata_size) &&
> -            st->codecpar->codec_id != AV_CODEC_ID_VP8) {
> +            st->codecpar->codec_id != AV_CODEC_ID_VP8  &&
> +            !ogg_get_pcm_format_id(st->codecpar->codec_id)) {
>  av_log(s, AV_LOG_ERROR, "No extradata present\n");
>  return AVERROR_INVALIDDATA;
>  }
> @@ -553,6 +618,14 @@ static int ogg_init(AVFormatContext *s)
>  av_log(s, AV_LOG_ERROR, "Error writing VP8 headers\n");
>  return err;
>  }
> +        } else if (ogg_get_pcm_format_id(st->codecpar->codec_id)) {
> +            int err = ogg_build_pcm_headers(st->codecpar, oggstream,
> +                                              s->flags & AVFMT_FLAG_BITEXACT,
> +                                              &st->metadata);
>

Indent seems wrong here too.



More information about the ffmpeg-devel mailing list