[Libav-user] Encoding FLOAT PCM to OGG using libav

Dmitry Adjiev adjiev.dmitry at gmail.com
Fri Aug 1 04:20:41 CEST 2014


Try libavfilter, please see transcoding.c again for sream conversions, btw
keep in mind your code may broke during porting from C to C++ or or vice
versa.
Just FYI: https://ffmpeg.org/pipermail/libav-user/2014-August/author.html


2014-08-01 1:33 GMT+04:00 wm4 <nfxjfg at googlemail.com>:

> On Thu, 31 Jul 2014 09:24:38 +0200
> Charles-Henri DUMALIN <dumalin.ch.maillist at gmail.com> wrote:
>
> > I am currently trying to convert a raw PCM Float buffer to an OGG encoded
> > file. I tried several library to do the encoding process and I finally
> > chose libavcodec.
> >
> > What I precisely want to do is get the float buffer ([-1;1]) provided by
> my
> > audio library and turn it to a char buffer of encoded ogg data.
> >
> > I managed to encode the float buffer to a buffer of encoded MP2 with this
> > (proof of concept) code:
> >
> > static int frameEncoded;
> >
> > FILE *file;
> >
> > int main(int argc, char *argv[])
> > {
> >     file = fopen("file.ogg", "w+");
> >
> >     long ret;
> >
> >     avcodec_register_all();
> >
> >     codec = avcodec_find_encoder(AV_CODEC_ID_MP2);
> >     if (!codec) {
> >         fprintf(stderr, "codec not found\n");
> >         exit(1);
> >     }
> >
> >     c = avcodec_alloc_context3(NULL);
> >
> >     c->bit_rate = 256000;
> >     c->sample_rate = 44100;
> >     c->channels = 2;
> >     c->sample_fmt = AV_SAMPLE_FMT_S16;
> >     c->channel_layout = AV_CH_LAYOUT_STEREO;
> >
> >     /* open it */
> >     if (avcodec_open2(c, codec, NULL) < 0) {
> >         fprintf(stderr, "Could not open codec\n");
> >         exit(1);
> >     }
> >
> >
> >     /* frame containing input raw audio */
> >     frame = av_frame_alloc();
> >     if (!frame) {
> >         fprintf(stderr, "Could not allocate audio frame\n");
> >         exit(1);
> >     }
> >
> >     frame->nb_samples     = c->frame_size;
> >     frame->format         = c->sample_fmt;
> >     frame->channel_layout = c->channel_layout;
> >
> >     /* the codec gives us the frame size, in samples,
> >      * we calculate the size of the samples buffer in bytes */
> >     int buffer_size = av_samples_get_buffer_size(NULL, c->channels,
> > c->frame_size,
> >                                                  c->sample_fmt, 0);
> >     if (buffer_size < 0) {
> >         fprintf(stderr, "Could not get sample buffer size\n");
> >         exit(1);
> >     }
> >     samples = av_malloc(buffer_size);
> >     if (!samples) {
> >         fprintf(stderr, "Could not allocate %d bytes for samples
> buffer\n",
> >                 buffer_size);
> >         exit(1);
> >     }
> >     /* setup the data pointers in the AVFrame */
> >     ret = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt,
> >                                    (const uint8_t*)samples, buffer_size,
> 0);
> >     if (ret < 0) {
> >         fprintf(stderr, "Could not setup audio frame\n");
> >         exit(1);
> >     }
> > }
> >
> > void  myLibraryCallback(float *inbuffer, unsigned int length)
> > {
> >     for(int j = 0; j < (2 * length); j++) {
> >         if(frameEncoded >= (c->frame_size *2)) {
> >             int avret, got_output;
> >
> >             av_init_packet(&pkt);
> >             pkt.data = NULL; // packet data will be allocated by the
> encoder
> >             pkt.size = 0;
> >
> >             avret = avcodec_encode_audio2(c, &pkt, frame, &got_output);
> >             if (avret < 0) {
> >                 fprintf(stderr, "Error encoding audio frame\n");
> >                 exit(1);
> >             }
> >             if (got_output) {
> >                 fwrite(pkt.data, 1, pkt.size, file);
> >                 av_free_packet(&pkt);
> >             }
> >
> >             frameEncoded = 0;
> >         }
> >
> >         samples[frameEncoded] = inbuffer[j] * SHRT_MAX;
> >         frameEncoded++;
> >     }
> > }
> >
> >
> > The code is really simple, I initialize libavencode the usual way, then
> my
> > audio library sends me processed PCM FLOAT [-1;1] interleaved at 44.1Khz
> > and the number of floats (usually 1024) in the inbuffer for each channel
> (2
> > for stereo). So usually, inbuffer contains 2048 floats.
> >
> > That was easy since I just needed here to convert my PCM to 16P, both
> > interleaved. Moreover it is possible to code a 16P sample on a single
> char.
> >
> > Now I would like to apply this to OGG which needs a sample format of
> > AV_SAMPLE_FMT_FLTP. Since my native format is AV_SAMPLE_FMT_FLT, it
> should
> > only be some desinterleaving. Which is really easy to do.
> >
> > The points I don't get are:
> >
> >    1. How can you send a float buffer on a char buffer ? Do we treat them
> >    as-is (float* floatSamples = (float*) samples) ? If so, what means the
> >    sample number avcodec gives you ? Is it the number of floats or chars
> ?
>
> The sample number is the number of floats per channel. So if you have a
> stereo non-interleaved (aka planar) float stream with 32 bytes per
> channel (aka plane in this case), ffmpeg will think of it as 8 samples.
>
> >    2. How can you send datas on two buffers (one for left, one for right)
> >    when avcodec_fill_audio_frame only takes a (uint8_t*) parameter and
> not a
> >    (uint8_t**) for multiple channels ? Does-it completely change the
> previous
> >    sample code ?
>
> I think avcodec_fill_audio_frame() should be considered legacy. The
> best way is to create an AVFrame with:
>
> frame = av_frame_alloc();
> frame.format = ...;
> ... set other parameters ...
> av_frame_get_buffer(frame, 32); // allocates frame data, using the params
>
> And then you copy in your source data.
>
> > I tried to find some answers myself and I made a LOT of experiments so
> far
> > but I failed on theses points. Since there is a huge lack of
> documentation
> > on these, I would be very grateful if you had answers.
> >
> > Thank you !
>
> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/libav-user
>



-- 
Regards,
Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20140801/69c88ef8/attachment.html>


More information about the Libav-user mailing list