[Libav-user] swr_convert questions

Ryan Routon ryanrouton at gmail.com
Sun Jul 13 11:58:27 CEST 2014


Hello All,

First of all this is my first post to the mailing list so hello all =)

Recently I have been working with fmpeg in order to render an mp4 using
still images via rgba values and a user selected audio file.  I have set up
the video portion which encodes perfectly. I have used the
avcodec_decode_audio4
<https://www.ffmpeg.org/doxygen/trunk/group__lavc__decoding.html#ga834bb1b062fbcc2de4cf7fb93f154a3e>
function
to pull frames from a user selected audio file.  Once I get the frame the
samples are then stored in AV_SAMPLE_FMT_FLTP, so at this point I either
have to manually cast the values as a short or use the sampler
functionality.  I did the first as a proof of concept but in order to make
the conversion as flexible as possible I opted for the sampler route.  I
set my sampler as follows:

        /* set options */

        av_opt_set_int       (swr_ctx, "in_channel_count",   frameIn->
channels,                 0);

        av_opt_set_int       (swr_ctx, "in_sample_rate",     frameIn->
sample_rate,              0);

        av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt",      (AVSampleFormat
)frameIn->format,   0);

        av_opt_set_int       (swr_ctx, "out_channel_count",  codecOut->
channels,                0);

        av_opt_set_int       (swr_ctx, "out_sample_rate",    codecOut->
sample_rate,             0);

        av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt",     codecOut->
sample_fmt,              0);


my target audio profile is as follows:


            (*codec)->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;

            c->bit_rate    = 64000;

            c->sample_rate = 22050;

            c->channels    = 2;

            c->channel_layout = AV_CH_LAYOUT_STEREO;


I has a hell of a time debugging random black box crashes in the
swr_convert file and it turned out to be that I was passing the uint8 ** by
value instead of reference so when there was more than one more channel it
would crash, but changing my parameter from ->data to &->data[0] solved
that.  So just in case that might help anyone having that particular
problem...



..Anyways, Now the sampler works great for a 1 channel file at the same
sample rate.  When I change the input file to a 2 channel or change the
sample rate i still hear the audio but it is very disjointed as if there
are gaps in the samples during the encoding process.


Here is the function, where the get_audio_frame() function uses the decode
4 function:


static int write_audio_frame_flip(AVFormatContext *oc, OutputStream *ost)

{

    AVCodecContext *c;

    AVPacket pkt = { 0 }; // data and size must be 0;

    AVFrame *frame;

    int ret;

    int got_packet;

    int dst_nb_samples;



    av_init_packet(&pkt);

    c = ost->st->codec;



    //Get decoded audio frame

    frame = get_audio_frame_flip(ost);



    if (frame)

    {

        SetSampler(c, frame);



        // convert samples from native format to destination codec format,
using the resampler

        if (swr_ctx)

        {

            if (ret < 0) {

                fprintf(stderr, "Could not allocate destination samples\n");

                return 0;

            }



            LOGD("Scaling frame->sample_rate=%d frame->nb_samples=%d
c->sample_rate=%d", frame->sample_rate, frame->nb_samples, c->sample_rate);



            // compute destination number of samples

            dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, frame->
sample_rate) + frame->nb_samples,

                                            c->sample_rate, frame->
sample_rate, AV_ROUND_UP);



            //convert the samples

            ret = swr_convert(swr_ctx, &ost->tmp_frame->data[0],
dst_nb_samples, (const uint8_t **)&frame->data[0], dst_nb_samples);



            if (ret < 0) {

                LOGD("Error while converting\n");

                return 0;

            }



            frame = ost->tmp_frame;



        } else {

            dst_nb_samples = frame->nb_samples;

        }



        frame->pts = av_rescale_q(samples_count, (AVRational){1, c->
sample_rate}, c->time_base);

        samples_count += dst_nb_samples;

    }



    ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);

    if (ret < 0) {

        fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str
(ret));

        return 0;

    }



    if (got_packet) {

        ret = write_frame(oc, &c->time_base, ost->st, &pkt);

        if (ret < 0) {

            fprintf(stderr, "Error while writing audio frame: %s\n",

                    av_err2str(ret));

            return 0;

        }

    }



    return (frame || got_packet) ? 0 : 1;

}


Thank you for any insight into what I might be doing wrong, this is all
very new to me and I am sure that I am misunderstanding some call or
concept.

Ryan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20140713/43576be0/attachment.html>


More information about the Libav-user mailing list