ffmpeg库音频解码示例

 
#include <stdio.h>
#include <stdlib.h>
extern "C"{//
#include "avcodec.h"
#include "avformat.h"
}


int main(char arg,char *argv[])
{
    char *filename ="02.swf";
    
    av_register_all();//注册所有可解码类型
    AVFormatContext *pInFmtCtx=NULL;//文件格式
    AVCodecContext *pInCodecCtx=NULL;//编码格式
    if (av_open_input_file(&pInFmtCtx,filename,NULL, 0, NULL)!=0)//获取文件格式
        printf("av_open_input_file error\n");
    if(av_find_stream_info(pInFmtCtx) < 0)//获取文件内音视频流的信息
        printf("av_find_stream_info error\n");
    
    unsigned int j;
    // Find the first audio stream

    int    audioStream = -1;
    for(j=0; j<pInFmtCtx->nb_streams; j++)//找到音频对应的stream
        if(pInFmtCtx->streams[j]->codec->codec_type==CODEC_TYPE_AUDIO)
        {
            audioStream=j;
            break;
        }
        if(audioStream==-1)
        {
            printf("input file has no audio stream\n");
            return 0; // Didn't find a audio stream

        }
        printf("audio stream num: %d\n",audioStream);
        pInCodecCtx = pInFmtCtx->streams[audioStream]->codec;//音频的编码上下文
        AVCodec *pInCodec=NULL;
        /* FILE *file3 = fopen("codec_private_data_size.txt","w");
        for(int i = 0; i <200000; i++)
        {
        pInCodec = avcodec_find_decoder((CodecID)i);
        if (pInCodec!=NULL)
        {
        fprintf(file3,"%s %d\n",pInCodec->name,pInCodec->priv_data_size );
        }
        }
        fclose(file3);
        system("pause");
        */

        pInCodec = avcodec_find_decoder(pInCodecCtx->codec_id);//根据编码ID找到用于解码的结构体
        if(pInCodec==NULL)
        {
            printf("error no Codec found\n");
            return -1 ; // Codec not found
        }


        //使用test的代替pInCodecCtx也可以完成解码,可以看出只要获取以下几个重要信息就可以实现解码和重采样
        AVCodecContext *test = avcodec_alloc_context();
        test->bit_rate = pInCodecCtx->bit_rate;//重采样用
        test->sample_rate = pInCodecCtx->sample_rate;//重采样用
        test->channels = pInCodecCtx->channels;//重采样用
        test->extradata = pInCodecCtx->extradata;//若有则必有
        test->extradata_size = pInCodecCtx->extradata_size;//若有则必要
        test->codec_type = CODEC_TYPE_AUDIO;//不必要
        test->block_align = pInCodecCtx->block_align ;//必要

        
        if(avcodec_open(test, pInCodec)<0)//将两者结合以便在下面的解码函数中调用pInCodec中的对应解码函数
        {
            printf("error avcodec_open failed.\n");
            return -1; // Could not open codec

        }
        
        if(avcodec_open(pInCodecCtx, pInCodec)<0)
        {
            printf("error avcodec_open failed.\n");
            return -1; // Could not open codec

        }
        
        static AVPacket packet;
        
        printf(" bit_rate = %d \r\n", pInCodecCtx->bit_rate);
        printf(" sample_rate = %d \r\n", pInCodecCtx->sample_rate);
        printf(" channels = %d \r\n", pInCodecCtx->channels);
        printf(" code_name = %s \r\n", pInCodecCtx->codec->name);
        //printf("extra data size: %d :data%x %x %x %x\n",pInCodecCtx->extradata_size,pInCodecCtx->extradata[0]
        //     ,pInCodecCtx->extradata[1],pInCodecCtx->extradata[2],pInCodecCtx->extradata[3]);
        printf(" block_align = %d\n",pInCodecCtx->block_align);
        
        //system("pause");
        //

        uint8_t *pktdata;
        int pktsize;
        int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*100;
        uint8_t * inbuf = (uint8_t *)malloc(out_size);
        FILE* pcm,*packetinfo;
        packetinfo = fopen("packetinfo.txt","w");
        pcm = fopen("result.pcm","wb");
        long start = clock();
        while(av_read_frame(pInFmtCtx, &packet)>=0)//pInFmtCtx中调用对应格式的packet获取函数
        {
            //fprintf(packetinfo," packet { pts=%d; dts =%d;%x,%x,%x,%x; size=%d; stream_index=%d; pos=%d;}\n",

            // packet.pts,packet.dts,packet.data[0],packet.data[1],packet.data[2],packet.data[3],packet.size,packet.stream_index,packet.pos);

            if(packet.stream_index==audioStream)//如果是音频
            {
                pktdata = packet.data;
                pktsize = packet.size;
                while(pktsize>0)
                {
                    //fprintf(packetinfo,"packet data:%x %x %x %x %x\n",pktdata[0],pktdata[1],pktdata[2],pktdata[3],pktdata[4]);

                    //fprintf(packetinfo,"packet size:%d\n\n",pktsize);

                    out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*100;
                    //解码
                    int len = avcodec_decode_audio2(pInCodecCtx,(short*)inbuf,&out_size,pktdata,pktsize);
                    if (len<0)
                    {
                        printf("Error while decoding.\n");
                        break;
                    }
                    if(out_size>0)
                    {
                        fwrite(inbuf,1,out_size,pcm);//pcm记录
                        fflush(pcm);
                    }
                    pktsize -= len;
                    pktdata += len;
                }
            }
            av_free_packet(&packet);
        }
        long end = clock();
        printf("cost time :%f\n",double(end-start)/(double)CLOCKS_PER_SEC);
        free(inbuf);
        fclose(pcm);
        fclose(packetinfo);
        if (pInCodecCtx!=NULL)
        {
            avcodec_close(pInCodecCtx);
        }
        if (test!=NULL)
        {
            avcodec_close(test);
        }
        av_free(test);
        av_close_input_file(pInFmtCtx);
        return 0;
}

 

一个英文版的例子(有讲解)
ffmpeg的一些使用例子
mpeg and SDL Tutorial
ffmpeg编译相关
ffmpeg工作组(中文)

 

 

 

 

 

转自:

http://blog.chinaunix.net/u3/108358/showart_2132123.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要把音频解码后的AVFrame保存为PCM格式的音频文件,你可以使用FFmpeg提供的API进行处理。具体步骤如下: 1. 打开音频文件并获取音频流信息: ``` AVFormatContext *formatCtx = avformat_alloc_context(); if (avformat_open_input(&formatCtx, inputPath, NULL, NULL) != 0) { // 打开音频文件失败 return; } if (avformat_find_stream_info(formatCtx, NULL) < 0) { // 获取音频流信息失败 return; } int audioStreamIndex = -1; for (int i = 0; i < formatCtx->nb_streams; i++) { if (formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { audioStreamIndex = i; break; } } if (audioStreamIndex == -1) { // 找不到音频流 return; } AVCodecParameters *audioCodecParams = formatCtx->streams[audioStreamIndex]->codecpar; ``` 2. 获取音频解码器并打开解码器: ``` AVCodec *audioCodec = avcodec_find_decoder(audioCodecParams->codec_id); AVCodecContext *audioCodecCtx = avcodec_alloc_context3(audioCodec); avcodec_parameters_to_context(audioCodecCtx, audioCodecParams); if (avcodec_open2(audioCodecCtx, audioCodec, NULL) < 0) { // 打开音频解码器失败 return; } ``` 3. 循环读取音频帧并解码: ``` AVPacket pkt; av_init_packet(&pkt); AVFrame *frame = av_frame_alloc(); while (av_read_frame(formatCtx, &pkt) >= 0) { if (pkt.stream_index == audioStreamIndex) { int ret = avcodec_send_packet(audioCodecCtx, &pkt); if (ret < 0) { // 发送音频数据包到解码器失败 break; } while (ret >= 0) { ret = avcodec_receive_frame(audioCodecCtx, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { // 无法从解码器中接收更多音频帧 break; } else if (ret < 0) { // 解码音频帧失败 break; } // 将音频帧保存为PCM格式的文件 // 这里省略将AVFrame保存为PCM格式文件的代码 } } av_packet_unref(&pkt); } av_frame_free(&frame); ``` 4. 关闭解码器和音频文件: ``` avcodec_free_context(&audioCodecCtx); avformat_close_input(&formatCtx); ``` 在将AVFrame保存为PCM格式文件时,你需要将AVFrame中的音频数据读取出来,并将其保存为PCM格式的文件。具体的方法可以参考FFmpeg的文档和示例代码。另外,需要注意的是,在将音频帧保存为PCM格式的文件时,你还需要指定音频的采样率、采样格式、声道布局等参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值