ffmpeg把pcm封装为wav

note

1.wav格式中,音频数据未经过压缩,直接封装即可

2.对于编码器的选择,应选择和pcm裸数据一致的编码器(本次实际不须编码)

version

#define LIBSWRESAMPLE_VERSION_MAJOR 2

#define LIBSWRESAMPLE_VERSION_MINOR 9

#define LIBSWRESAMPLE_VERSION_MICRO 100

#define LIBAVCODEC_VERSION_MINOR 31

#define LIBAVCODEC_VERSION_MICRO 102

code

复制代码
void CFfmpegOps::MuxPCMToWAV(const char* pcm_file, const char* wav_file)
{
    const AVOutputFormat* out_fmt = nullptr;
    AVFormatContext* fmt_ctx = nullptr;
    const AVCodec* codec = nullptr;
    AVCodecContext* codec_ctx = nullptr;
    AVStream* avstream = nullptr;
    AVPacket* avpacket = nullptr;
    AVFrame* avframe = nullptr;
    int ret = -1;
    FILE* in_fp = nullptr;
    int sample_fmt_is_planar = 0;
    size_t n = 0;
    int frame_data_bytes = 0;

    codec = avcodec_find_encoder(AV_CODEC_ID_PCM_F32LE);
    if (!codec)
    {
        printf("avcodec_find_encoder error\n");
        goto END;
    }

    codec_ctx = avcodec_alloc_context3(codec);
    if (!codec_ctx)
    {
        printf("avcodec_alloc_context3 error\n");
        goto END;
    }
    codec_ctx->sample_fmt = AV_SAMPLE_FMT_FLT;  // f32le
    codec_ctx->sample_rate = 44100;
    codec_ctx->channel_layout = AV_CH_LAYOUT_STEREO;
    codec_ctx->channels = av_get_channel_layout_nb_channels(codec_ctx->channel_layout);

    ret = avcodec_open2(codec_ctx, codec, nullptr);
    if (ret < 0)
    {
        printf("avcodec_open2 error(%s)\n", GetFfmpegERR(ret));
        goto END;
    }
    printf("frame_size:%d\n", codec_ctx->frame_size);

    avframe = av_frame_alloc();
    if (!avframe)
    {
        printf("av_frame_alloc error\n");
        goto END;
    }
    avframe->format = AV_SAMPLE_FMT_FLT;
    avframe->sample_rate = 44100;
    avframe->channel_layout = AV_CH_LAYOUT_STEREO;
    avframe->channels = av_get_channel_layout_nb_channels(avframe->channel_layout);
    avframe->nb_samples = 1024;

    ret = av_frame_get_buffer(avframe, 0);
    if (ret < 0)
    {
        printf("av_frame_get_buffer error(%s)\n", GetFfmpegERR(ret));
        goto END;
    }

    ret = av_samples_get_buffer_size(nullptr, 
                                    avframe->channels,
                                    avframe->nb_samples,
                                    (AVSampleFormat)(avframe->format),
                                    1);
    if (ret < 0)
    {
        printf("av_samples_get_buffer_size error(%s)\n", GetFfmpegERR(ret));
        goto END;
    }
    frame_data_bytes = ret;

    avpacket = av_packet_alloc();
    if (!avpacket)
    {
        printf("av_packet_alloc error\n");
        goto END;
    }

    in_fp = fopen(pcm_file, "rb");
    if (!in_fp)
    {
        printf("fopen error\n");
        goto END;
    }

    ret = avformat_alloc_output_context2(&fmt_ctx, nullptr, nullptr, wav_file);
    if (ret < 0)
    {
        printf("avformat_alloc_output_context2 error(%s)\n", GetFfmpegERR(ret));
        goto END;
    }
    out_fmt = fmt_ctx->oformat;

    avstream = avformat_new_stream(fmt_ctx, codec);
    if (!avstream)
    {
        printf("avformat_new_stream error\n");
        goto END;
    }

    ret = avcodec_parameters_from_context(avstream->codecpar, codec_ctx);
    if (ret < 0)
    {
        printf("avcodec_parameters_from_context error(%s)\n", GetFfmpegERR(ret));
        goto END;
    }

    ret = avio_open(&(fmt_ctx->pb), wav_file, AVIO_FLAG_READ_WRITE);
    if (ret < 0)
    {
        printf("avio_open error(%s)\n", GetFfmpegERR(ret));
        goto END;
    }

    ret = avformat_write_header(fmt_ctx, nullptr);
    if (ret < 0)
    {
        printf("avformat_write_header error(%s)\n", GetFfmpegERR(ret));
        goto END;
    }

    while (1)
    {
        if (feof(in_fp))
        {
            break;
        }

        sample_fmt_is_planar = av_sample_fmt_is_planar((AVSampleFormat)(avframe->format));
        if (sample_fmt_is_planar)
        {
            n = fread(avframe->data[0], sizeof(uint8_t), frame_data_bytes / 2, in_fp);
            if ((int)n != (frame_data_bytes / 2))
            {
                printf("n != (frame_data_bytes / 2)\n");
            }

            n = fread(avframe->data[1], sizeof(uint8_t), frame_data_bytes / 2, in_fp);
            if ((int)n != (frame_data_bytes / 2))
            {
                printf("n != (frame_data_bytes / 2)\n");
            }
        }
        else
        {
            n = fread(avframe->data[0], sizeof(uint8_t), frame_data_bytes, in_fp);
            if ((int)n != frame_data_bytes)
            {
                printf("n != (frame_data_bytes)\n");
            }
        }

        ret = avcodec_send_frame(codec_ctx, avframe);
        if (ret < 0)
        {
            if (ret == AVERROR(EAGAIN))
            {
                printf("read output first\n");
            }
            else
            {
                printf("avcodec_send_frame error(%s)\n", GetFfmpegERR(ret));
                break;
            }
        }

        while (1)
        {
            ret = avcodec_receive_packet(codec_ctx, avpacket);
            if (ret < 0)
            {
                if (ret == AVERROR(EAGAIN))
                {
                    printf("send input first\n");
                    break;
                }
                else
                {
                    printf("avcodec_receive_packet error(%s)\n", GetFfmpegERR(ret));
                    break;
                }
            }

            ret = av_write_frame(fmt_ctx, avpacket);
            if (ret < 0)
            {
                printf("av_write_frame error(%s)\n", GetFfmpegERR(ret));
                av_packet_unref(avpacket);
                goto END;
            }

            av_packet_unref(avpacket);
        }
    }

    ret = avcodec_send_frame(codec_ctx, nullptr);
    while (1)
    {
        ret = avcodec_receive_packet(codec_ctx, avpacket);
        if (ret < 0)
        {
            if (ret == AVERROR(EAGAIN))
            {
                printf("send input first\n");
                break;
            }
            else
            {
                printf("avcodec_receive_packet error(%s)\n", GetFfmpegERR(ret));
                break;
            }
        }

        ret = av_write_frame(fmt_ctx, avpacket);
        if (ret < 0)
        {
            printf("av_write_frame error(%s)\n", GetFfmpegERR(ret));
            av_packet_unref(avpacket);
            goto END;
        }

        av_packet_unref(avpacket);
    }

    ret = av_write_trailer(fmt_ctx);
    if (ret < 0)
    {
        printf("av_write_trailer error(%s)\n", GetFfmpegERR(ret));
        goto END;
    }

END:
    if (fmt_ctx)
    {
        avformat_free_context(fmt_ctx);
        fmt_ctx = nullptr;
    }
    if (in_fp)
    {
        fclose(in_fp);
        in_fp = nullptr;
    }
    if (avframe)
    {
        av_frame_free(&avframe);
        avframe = nullptr;
    }
    if (avpacket)
    {
        av_packet_free(&avpacket);
        avpacket = nullptr;
    }
    if (codec_ctx)
    {
        avcodec_free_context(&codec_ctx);
        codec_ctx = nullptr;
    }
}

performance

相关推荐
努力学习的小廉4 分钟前
我爱学算法之—— 二分查找(上)
开发语言·c++·算法
wqfhenanxc1 小时前
Mixing C++ and Rust for Fun and Profit 阅读笔记
c++·笔记·rust
R-G-B1 小时前
【MFC】 VS2022打开低版本的MFC,双击.rc文件,DIalog加载失败,页面弹窗fatal error RC***:cannot open*****
c++·mfc·vs打开较早版本mfc·双击.rc文件·dialog加载失败·fatal error rc·cannot open
敲上瘾1 小时前
基于Tcp协议的应用层协议定制
linux·运维·服务器·网络·c++·网络协议·tcp/ip
hunandede2 小时前
ffmpeg av_buffer_unref的逻辑实现; av_freep 和 av_freep函数的区别
ffmpeg
莹莹学编程—成长记2 小时前
string的模拟实现
服务器·c++·算法
喵先生!5 小时前
C++中的vector和list的区别与适用场景
开发语言·c++
xMathematics6 小时前
计算机图形学实践:结合Qt和OpenGL实现绘制彩色三角形
开发语言·c++·qt·计算机图形学·cmake·opengl
byte轻骑兵6 小时前
【HFP】蓝牙HFP协议中音频连接转移与拨号功能的深度解析
音视频·蓝牙技术·hfp
yuanManGan8 小时前
C++入门小馆: 深入了解STLlist
开发语言·c++