Converting 3gp (amr) to mp3 using ffmpeg api calls
Asked Answered
A

0

3

Converting 3gp (amr) to mp3 using ffmpeg api calls

I try to use libavformat (ffmpeg) to build my own function that converts 3gp audio files (recorded with an android mobile device) into mp3 files.

I use av_read_frame() to read a frame from the input file and use avcodec_decode_audio3() to decode the data into a buffer and use this buffer to encode the data into mp3 with avcodec_encode_audio. This seems to give me a correct result for converting wav to mp3 and mp3 to wav (Or decode one mp3 and encode to another mp3) but not for amr to mp3. My resulting mp3 file seems to has the right length but only consists of noise.

In another post I read that amr-decoder does not use the same sample format than mp3 does. AMR uses FLT and mp3 S16 or S32 und that I have to do resampling. So I call av_audio_resample_init() and audio_resample for each frame that has been decoded. But that does not solve my problem completely. Now I can hear my recorded voice and unsterstand what I was saying, but the quality is very low and there is still a lot of noise. I am not sure if I set the parameters of av_audio_resample correctly, especially the last 4 parameters (I think not) or if I miss something else.

ReSampleContext* reSampleContext = av_audio_resample_init(1, 1, 44100, 8000, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT, 0, 0, 0, 0.0);

while(1)
{
    if(av_read_frame(ic, &avpkt) < 0)
    {
        break;
    }

    out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
    int count;

    count = avcodec_decode_audio3(audio_stream->codec, (short *)decodedBuffer, &out_size, &avpkt);

    if(count < 0)
    {
        break;
    }

    if((audio_resample(reSampleContext, (short *)resampledBuffer, (short *)decodedBuffer, out_size / 4)) < 0)
    {
        fprintf(stderr, "Error\n");
        exit(1);
    }

    out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;

    pktOut.size = avcodec_encode_audio(c, outbuf, out_size, (short *)resampledBuffer);

    if(c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE)
    {
        pktOut.pts = av_rescale_q(c->coded_frame->pts, c->time_base, outStream->time_base);
        //av_res
    }

    pktOut.pts = AV_NOPTS_VALUE;
    pktOut.dts = AV_NOPTS_VALUE;

    pktOut.flags |= AV_PKT_FLAG_KEY;
    pktOut.stream_index = audio_stream->index;
    pktOut.data = outbuf;

    if(av_write_frame(oc, &pktOut) != 0)
    {
        fprintf(stderr, "Error while writing audio frame\n");
        exit(1);
    }
}
Applause answered 13/3, 2012 at 13:23 Comment(1)
Did you figure out a way around this?Innate

© 2022 - 2024 — McMap. All rights reserved.