<div dir="ltr">I am trying to encode pcm data to mp3 format(exactly should be mono, s16p, 24k) But I always get  fltp as result. What I do wrong?<div><br></div><div>My code is below</div><div><br></div><div>```cpp</div><div>#include "encoder.h"<br>#include <string><br><br>#include <stdint.h><br>#include <stdio.h><br>#include <stdlib.h><br>#include <vector><br>#include <deque><br>#include <iostream><br><br>#include "encoder_err_code.h"<br><br>extern "C" {<br>    #include <libavutil/opt.h><br>    #include <libavcodec/avcodec.h><br>    #include <libavutil/channel_layout.h><br>    #include <libavutil/common.h><br>    #include <libavutil/frame.h><br>    #include <libavutil/samplefmt.h><br>    #include <libswresample/swresample.h><br>}<br><br>using namespace std;<br><br>const int PCM_SAMPLE_RATE = 24000;<br><br>class Encoder {<br>private:<br>    AVCodec *codec = nullptr;<br>    AVCodecContext *context = nullptr;<br>    AVFrame *frame = nullptr;<br>    AVPacket *pkt = nullptr;<br>    SwrContext *swrContext = nullptr;<br>    deque<uint8_t> pcmBuffer;<br><br>    int createCodec(const char* outputFormat) {<br>        // find codec by outputFormat<br>        AVCodecID avCodecId = AV_CODEC_ID_NONE;<br><br>        if (strcmp(outputFormat, "mp3") == 0) {<br>            avCodecId = AV_CODEC_ID_MP3;<br>        }<br><br>        if (AV_CODEC_ID_NONE == avCodecId) {<br>            return ENCODER_FORMAT_NOT_SUPPORT;<br>        } else {<br>            codec = avcodec_find_encoder(avCodecId);<br>        }<br><br>        if (!codec) {<br>            return ENCODER_CODEC_NOT_FOUND;<br>        }<br><br>        return ENCODER_SUCCESS;<br>    }<br><br>    int createContext(int sampleRate) {<br>        // check sampleRate support<br>        int ret = ENCODER_SAMPLE_RATE_NOT_SUPPORT;<br>        auto p = codec->supported_samplerates;<br>        while(*p) {<br>            if (*(p++) == sampleRate) {<br>                ret = ENCODER_SUCCESS;<br>                break;<br>            }<br>        }<br><br>        if(ret) {<br>            return ret;<br>        }<br><br>        // create context<br>        context = avcodec_alloc_context3(codec);<br><br>        if (!context) {<br>            return ENCODER_CODEC_CONTEXT_CREATE_ERROR;<br>        }<br><br>        // set output format<br>        context->audio_service_type = AV_AUDIO_SERVICE_TYPE_MAIN;<br>        context->sample_fmt = AV_SAMPLE_FMT_S16P;<br>        context->sample_rate = sampleRate;<br>        context->channel_layout = AV_CH_LAYOUT_MONO;<br>        context->channels = av_get_channel_layout_nb_channels(context->channel_layout);<br><br>        // check PCM sampleRate<br>        const enum AVSampleFormat *f = codec->sample_fmts;<br>        while( *f != AV_SAMPLE_FMT_NONE) {<br>            if (*f == context->sample_fmt) {<br>                break;<br>            }<br>            f++;<br>        }<br><br>        if (*f == AV_SAMPLE_FMT_NONE) {<br>            return ENCODER_SAMPLE_FMT_NOT_SUPPORT;<br>        }<br><br>        // check PCM layout<br>        auto l = codec->channel_layouts;<br>        while(l) {<br>            if (*l == context->channel_layout) {<br>                break;<br>            }<br>            l++;<br>        }<br><br>        if (!l) {<br>            return ENCODER_SAMPLE_LAYOUT_NOT_SUPPORT;<br>        }<br><br>        if (avcodec_open2(context, codec, nullptr) < 0 ) {<br>            return ENCODER_CODEC_OPEN_ERROR;<br>        }<br><br>        return ENCODER_SUCCESS;<br>    }<br>    <br>    int createSwrContext(int sampleRate){<br>        swrContext = swr_alloc();<br>        if (!swrContext) {<br>            return ENCODER_SWR_ALLOC_ERROR;<br>        }<br><br>        /* set options */<br>        av_opt_set_int(swrContext, "in_channel_layout",    AV_CH_LAYOUT_MONO, 0);<br>        av_opt_set_int(swrContext, "in_sample_rate",       PCM_SAMPLE_RATE, 0);<br>        av_opt_set_sample_fmt(swrContext, "in_sample_fmt", context->sample_fmt, 0);<br><br>        av_opt_set_int(swrContext, "out_channel_layout",    AV_CH_LAYOUT_MONO, 0);<br>        av_opt_set_int(swrContext, "out_sample_rate",       sampleRate, 0);<br>        av_opt_set_sample_fmt(swrContext, "out_sample_fmt", context->sample_fmt, 0);<br><br>        int ret = swr_init(swrContext);<br>        if (ret) {<br>            return ENCODER_SWR_INIT_ERROR;<br>        }<br>        return ENCODER_SUCCESS;<br>    }<br><br>    int createPacket(){<br>        pkt = av_packet_alloc();<br><br>        if (!pkt) {<br>            return ENCODER_PACKET_ALLOC_ERROR;<br>        }<br>        return ENCODER_SUCCESS;<br>    }<br><br>    int createFrame(){<br>        frame = av_frame_alloc();<br>        if (!frame) {<br>            return ENCODER_FRAME_ALLOC_ERROR;<br>        }<br>        frame->nb_samples     = context->frame_size;<br>        frame->format         = context->sample_fmt;<br>        frame->channel_layout = context->channel_layout;<br>        frame->channels       = context->channels;<br>        frame->linesize[0]    = context->frame_size*2;<br><br>        int ret = av_frame_get_buffer(frame, 0);<br>        if (ret < 0) {<br>            return ENCODER_FRAME_ALLOC_ERROR;<br>        }<br>        return ENCODER_SUCCESS;<br>    }<br><br>    int encode(AVFrame *frame, vector<uint8_t> &output){<br>        int ret;<br><br>        // send PCM rawData<br>        ret = avcodec_send_frame(context, frame);<br>        if (ret) {<br>            return ENCODER_FRAME_SEND_ERROR;<br>        }<br><br>        // read data<br>        while (ret >= 0) {<br>            ret = avcodec_receive_packet(context, pkt);<br>            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)<br>                return ENCODER_SUCCESS;<br>            else if (ret < 0) {<br>                return ENCODER_ENCODE_ERROR;<br>            }<br><br>            auto p = pkt->data;<br>            for (int i=0; i<pkt->size;i++) {<br>                output.emplace_back(*(p++));<br>            }<br>            av_packet_unref(pkt);<br>        }<br>        return ENCODER_SUCCESS;<br>    }<br><br>public:<br>    Encoder() {<br>        codec = nullptr;<br>        context = nullptr;<br>    }<br><br>    int init(const char* outputFormat, int sampleRate) {<br>        int ret;<br>        ret = createCodec(outputFormat);<br>        if (ret) {<br>            return ret;<br>        }<br><br>        ret = createContext(sampleRate);<br>        if (ret) {<br>            return ret;<br>        }<br>        <br>        ret = createSwrContext(sampleRate);<br>        if (ret) {<br>            return ret;<br>        }<br><br>        ret = createPacket();<br>        if (ret) {<br>            return ret;<br>        }<br><br>        ret = createFrame();<br>        if (ret) {<br>            return ret;<br>        }<br>        <br>        return ENCODER_SUCCESS;<br>    }<br><br>    int reSample(const char* inputPcm, int length) {<br>        // 代码参考 <a href="https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/resampling_audio.c">https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/resampling_audio.c</a><br>        const int srcRate = PCM_SAMPLE_RATE;<br>        const int dstRate = context->sample_rate;<br>        int srcSampleNum = length / 2;<br><br>        uint8_t **dstData = nullptr;<br>        int dstLineSize;<br><br>        // 计算重采样后的采样数目<br>        int dst_nb_samples = av_rescale_rnd(swr_get_delay(swrContext, srcRate) + srcSampleNum, dstRate, srcRate,<br>                                            AV_ROUND_UP);<br><br>        // 使用 API 申请空间用于存储重采样结果<br>        if (av_samples_alloc_array_and_samples(&dstData, &dstLineSize, 1, dst_nb_samples, context->sample_fmt, 0) < 0) {<br>            return ENCODER_SWR_ALLOC_ARRAY_ERROR;<br>        }<br><br>        // 转换采样率<br>        auto convertSampleNum = swr_convert(swrContext,<br>                dstData, dst_nb_samples,<br>                (const uint8_t **) (&inputPcm), srcSampleNum);<br>        if (convertSampleNum < 0) {<br>            av_freep(&dstData);<br>            return ENCODER_SWR_CONVERT_ERROR;<br>        }<br><br>        // 将结果转存到 pcmBuffer<br>        int dstBuffSize = av_samples_get_buffer_size(&dstLineSize, 1, convertSampleNum, context->sample_fmt, 1);<br>        if (dstBuffSize < 0) {<br>            av_freep(&dstData);<br>            return ENCODER_SWR_GET_ERROR;<br>        }<br><br>        for (int i = 0; i < dstBuffSize;i++) {<br>            pcmBuffer.emplace_back(*(dstData[0]+i));<br>        }<br><br>        return ENCODER_SUCCESS;<br>    }<br><br><br>    int process(const char* inputPcm, int length, bool isFinal, char** output, int* outputLength) {<br><br>        // 先进行重采样<br>        int ret = reSample(inputPcm, length);<br>        if (ret) {<br>            return ret;<br>        }<br><br>        // 编码,参考 <a href="https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/encode_audio.c">https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/encode_audio.c</a><br>        vector<uint8_t> buffer;<br>        while(true) {<br>            if (pcmBuffer.size() < context->frame_size*2)<br>                break;<br><br>            ret = av_frame_make_writable(frame);<br>            if (ret) {<br>                return ENCODER_FRAME_NOT_WRITEABLE;<br>            }<br><br>            // 从pcmBuffer 取出足够的数据填充一个 frame<br>            auto samples = frame->data[0];<br>            for (int i=0;i<context->frame_size*2;i++) {<br>                samples[i] = pcmBuffer.front();<br>                pcmBuffer.pop_front();<br>            }<br><br>            encode(frame, buffer);<br>        }<br><br>        // 最后的数据需要 flush<br>        if (isFinal) {<br>            encode(nullptr, buffer);<br>        }<br><br>        // 输出<br>        *output = (char*)malloc(buffer.size()*sizeof(char));<br>        if (*output) {<br>            *outputLength = buffer.size();<br>            memcpy(*output, buffer.data(), buffer.size());<br>            return ENCODER_SUCCESS;<br>        } else {<br>            return ENCODER_MEN_ALLOC_ERROR;<br>        }<br>    }<br><br>    virtual ~Encoder() {<br>        if (context) {<br>            avcodec_free_context(&context);<br>        }<br>        if (frame) {<br>            av_frame_free(&frame);<br>        }<br>        if (pkt) {<br>            av_packet_free(&pkt);<br>        }<br>        if (swrContext) {<br>            swr_free(&swrContext);<br>        }<br>    }<br>};<br><br>int createEncoder(const char* outputFormat, int sampleRate, void** encoderPtr) {<br>    int ret;<br>    auto encoder = new Encoder();<br>    ret = encoder->init(outputFormat, sampleRate);<br>    if (ret) {<br>        delete encoder;<br>        *encoderPtr = nullptr;<br>        return ret;<br>    } else {<br>        *encoderPtr = encoder;<br>        return ENCODER_SUCCESS;<br>    }<br>}<br><br>int destroyEncoder(void* encoder) {<br>    if (encoder != nullptr) {<br>        auto e = (Encoder *) encoder;<br>        delete e;<br>        return ENCODER_SUCCESS;<br>    }<br>}<br><br>// 该函数会 malloc 内存到 output,记得释放<br>int processEncoder(void* e, const char* inputPcm, int length, bool isFinal, char** output, int* outputLength) {<br>    auto encoder = (Encoder*)e;<br>    return encoder->process(inputPcm, length, isFinal, output, outputLength);<br>}<br></div><div>```</div></div>