• 7.SwrContext音频重采样使用


    头文件位于#include <libswresample/swresample.h>
     
    SwrContext常用函数如下所示
    SwrContext *swr_alloc(void); //创建一个SwrContext,并设置为默认参数
     
    struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,nt64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, int log_offset, void *log_ctx);
    //如果第一个参数指向为NULL,则创建一个新的SwrContext,否则对其进行参数配置。
    //@param s 要创建的SwrContext ,如果指向NULL,则分配一个新的SwrContext
    //@param out_ch_layout output channel layout (AV_CH_LAYOUT_*)
    //@param out_sample_fmt output sample format (AV_SAMPLE_FMT_*).
    //@param out_sample_rate output sample rate (frequency in Hz)
    //@param in_ch_layout input channel layout (AV_CH_LAYOUT_*)
    //@param in_sample_fmt input sample format (AV_SAMPLE_FMT_*).
    //@param in_sample_rate input sample rate (frequency in Hz)
    //@param log_offset logging level offset(日志相关,为NULL即可)
    //@param log_ctx parent logging context(日志相关,为NULL即可) int64_t av_get_default_channel_layout(int nb_channels); //通过当前通道数返回对应AV_CH_LAYOUT_*枚举值,比如参数为2(2通道),那么返回AV_CH_LAYOUT_STEREO(立体声) int av_get_channel_layout_nb_channels(uint64_t channel_layout); //通过AV_CH_LAYOUT_*获取当前有多少通道 int swr_init(struct SwrContext *s); // 初始化上下文,初始化之前需要配置好SwrContext //如果初始化好后,还需要修改转换的参数,则调用swr_alloc_set_opts(),然后swr_init()重新初始化

    void swr_free(struct SwrContext **s); // 释放上下文空间,并且设置*s为NULL int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in , int in_count); //音频重采样转换 // s : 初始化好的SwrContext //out : 输出缓冲区,对于packet,都存在out[0]中,对于planar,比如AV_CH_LAYOUT_STEREO,那么out[0]存L,out[1]存R //out_count : 输出缓冲区每通道样本数据数量(对于音频,每个通道数据长度都相同),注意这里不是以字节为单位. //in :输入缓冲区,这里填入frame->data即可 //in_count :输入缓冲区每通道数据数量,这里填入frame->nb_samples即可 //返回值:转换成功后每个通道的输出样本数,出错则为负值

     音频解码并重采样示例

    void debugErr(QString prefix, int err)  //根据错误编号获取错误信息并打印
    {
        char errbuf[512]={0};
    
        av_strerror(err,errbuf,sizeof(errbuf));
    
        cout<<prefix<<":"<<errbuf<<endl;
    }
    
    void runAudioPlay()
    {
        int ret;     
        avformat_network_init(); //初始化网络库 (可以打开rtsp rtmp http 协议的流媒体视频)
        AVFormatContext *pFmtCtx=NULL;
    ret
    = avformat_open_input(&pFmtCtx,filePath,NULL, NULL) ; //打开音视频文件并创建AVFormatContext结构体以及初始化. if (ret!= 0) { debugErr("avformat_open_input",ret); return ; } ret = avformat_find_stream_info(pFmtCtx, NULL); //初始化流信息 if (ret!= 0) { debugErr("avformat_find_stream_info",ret); return ; } int audioindex=-1; audioindex = av_find_best_stream(pFmtCtx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); qDebug()<<"audioindex:"<<audioindex; AVCodec *acodec = avcodec_find_decoder(pFmtCtx->streams[audioindex]->codecpar->codec_id);//获取codec AVCodecContext *acodecCtx = avcodec_alloc_context3(acodec); //构造AVCodecContext ,并将vcodec填入AVCodecContext中 avcodec_parameters_to_context(acodecCtx, pFmtCtx->streams[audioindex]->codecpar); //初始化AVCodecContext ret = avcodec_open2(acodecCtx, NULL,NULL);
    //打开解码器,由于之前调用avcodec_alloc_context3(acodec)初始化了解码器,那么codec(第2个参数)可以填NULL if (ret!= 0) { debugErr("avcodec_open2",ret); return ; } SwrContext *swrctx =NULL; swrctx=swr_alloc_set_opts(swrctx, av_get_default_channel_layout(2),AV_SAMPLE_FMT_S16,44100, acodecCtx->channel_layout, acodecCtx->sample_fmt,acodecCtx->sample_rate, NULL,NULL);
           swr_init(swrctx);
    while(1) { ret = av_read_frame(pFmtCtx, packet); if (ret!= 0) { debugErr("av_read_frame",ret); break ; } //解码一帧数据 ret = avcodec_send_packet(acodecCtx, packet); av_packet_unref(packet); if (ret != 0) { debugErr("avcodec_send_packet",ret); continue ; } if(packet->stream_index==audioindex) //判断是音频流 { while( avcodec_receive_frame(acodecCtx, frame) == 0) { uint8_t *data[2] = { 0 }; int byteCnt=frame->nb_samples * 2 * 2; unsigned char *pcm = new uint8_t[byteCnt]; //frame->nb_samples*2*2表示分配样本数据量*两通道*每通道2字节大小 data[0] = pcm; //输出格式为AV_SAMPLE_FMT_S16(packet类型),所以转换后的LR两通道都存在data[0]中 ret = swr_convert(swrctx, data, frame->nb_samples, //输出 (const uint8_t**)frame->data,frame->nb_samples ); //输入 //将重采样后的data数据发送到输出设备,进行播放 ... ... delete[] pcm; //最后delete pcm } } } //释放 av_frame_free(&frame); av_packet_free(&packet); swr_free(&swrctx); avcodec_free_context(&acodecCtx); avformat_close_input(&pFmtCtx); }

  • 相关阅读:
    什么是SQLCLR与使用
    SQL Server中使用正则表达式
    YUV格式
    Android官方开发文档Training系列课程中文版:手势处理之ViewGroup的事件管理
    Android中利用5.0系统屏幕录制UI漏洞骗取应用录制屏幕授权
    Android解析编译之后的所有文件(so,dex,xml,arsc)格式
    PageRank 算法--从原理到实现
    机器人视觉初级系列
    深入解析 iOS 开源项目
    微信热补丁 Tinker 的实践演进之路
  • 原文地址:https://www.cnblogs.com/lifexy/p/13647846.html
Copyright © 2020-2023  润新知