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