FFmpeg浅尝辄止(四)——音频的解码和编码

音频和视频其实是一样的,在文件中寻找音频流,然后解压出来,得到音频帧的数据,同样也可以按照设定的编码格式进行压缩,我这里把音频的解码和编码做成了两个工程,也是直接上代码:

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. extern "C"  
  5. {  
  6. #include <libavcodec\avcodec.h>  
  7. #include <libavformat\avformat.h>  
  8. #include <libswscale\swscale.h>  
  9. }  
  10.   
  11. int main(char arg,char *argv[])  
  12. {  
  13.     char *filename = argv[1];  
  14.   
  15.     av_register_all();  //注册所有可解码类型  
  16.     AVFormatContext *pInFmtCtx=NULL;    //文件格式  
  17.     AVCodecContext *pInCodecCtx=NULL;   //编码格式   
  18.     if (av_open_input_file(&pInFmtCtx, filename, NULL, 0, NULL)!=0) //获取文件格式  
  19.         printf("av_open_input_file error\n");  
  20.     if (av_find_stream_info(pInFmtCtx) < 0)  //获取文件内音视频流的信息  
  21.         printf("av_find_stream_info error\n");  
  22.   
  23.     unsigned int j;  
  24.     // Find the first audio stream  
  25.   
  26.     int audioStream = -1;  
  27.     for (j=0; j<pInFmtCtx->nb_streams; j++)   //找到音频对应的stream  
  28.     {  
  29.         if (pInFmtCtx->streams[j]->codec->codec_type == CODEC_TYPE_AUDIO)  
  30.         {  
  31.             audioStream = j;  
  32.             break;  
  33.         }  
  34.     }  
  35.     if (audioStream == -1)  
  36.     {  
  37.         printf("input file has no audio stream\n");  
  38.         return 0; // Didn't find a audio stream  
  39.     }  
  40.     printf("audio stream num: %d\n",audioStream);  
  41.     pInCodecCtx = pInFmtCtx->streams[audioStream]->codec; //音频的编码上下文  
  42.     AVCodec *pInCodec = NULL;  
  43.   
  44.     pInCodec = avcodec_find_decoder(pInCodecCtx->codec_id); //根据编码ID找到用于解码的结构体  
  45.     if (pInCodec == NULL)  
  46.     {  
  47.         printf("error no Codec found\n");  
  48.         return -1 ; // Codec not found  
  49.     }  
  50.   
  51.     if(avcodec_open(pInCodecCtx, pInCodec)<0)//将两者结合以便在下面的解码函数中调用pInCodec中的对应解码函数  
  52.     {  
  53.         printf("error avcodec_open failed.\n");  
  54.         return -1; // Could not open codec  
  55.   
  56.     }  
  57.   
  58.     static AVPacket packet;  
  59.   
  60.     printf(" bit_rate = %d \r\n", pInCodecCtx->bit_rate);  
  61.     printf(" sample_rate = %d \r\n", pInCodecCtx->sample_rate);  
  62.     printf(" channels = %d \r\n", pInCodecCtx->channels);  
  63.     printf(" code_name = %s \r\n", pInCodecCtx->codec->name);  
  64.     printf(" block_align = %d\n",pInCodecCtx->block_align);  
  65.   
  66.     uint8_t *pktdata;  
  67.     int pktsize;  
  68.     int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*100;  
  69.     uint8_t * inbuf = (uint8_t *)malloc(out_size);  
  70.     FILE* pcm;  
  71.     pcm = fopen("result.pcm","wb");  
  72.     long start = clock();  
  73.     while (av_read_frame(pInFmtCtx, &packet) >= 0)//pInFmtCtx中调用对应格式的packet获取函数  
  74.     {  
  75.         if(packet.stream_index==audioStream)//如果是音频  
  76.         {  
  77.             pktdata = packet.data;  
  78.             pktsize = packet.size;  
  79.             while(pktsize>0)  
  80.             {  
  81.                 out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*100;  
  82.                 //解码  
  83.                 int len = avcodec_decode_audio2(pInCodecCtx, (short*)inbuf, &out_size, pktdata, pktsize);  
  84.                 if (len < 0)  
  85.                 {  
  86.                     printf("Error while decoding.\n");  
  87.                     break;  
  88.                 }  
  89.                 if(out_size > 0)  
  90.                 {  
  91.                     fwrite(inbuf,1,out_size,pcm);//pcm记录  
  92.                     fflush(pcm);  
  93.                 }  
  94.                 pktsize -= len;  
  95.                 pktdata += len;  
  96.             }  
  97.         }   
  98.         av_free_packet(&packet);  
  99.     }  
  100.     long end = clock();  
  101.     printf("cost time :%f\n",double(end-start)/(double)CLOCKS_PER_SEC);  
  102.     free(inbuf);  
  103.     fclose(pcm);  
  104.     if (pInCodecCtx!=NULL)  
  105.     {  
  106.         avcodec_close(pInCodecCtx);  
  107.     }  
  108.     av_close_input_file(pInFmtCtx);  
  109.   
  110.     return 0;  
  111. }  

解码后的文件保存为result.pcm中,现在用这个文件压缩出新的音频文件,代码如下:

[cpp]  view plain copy
  1. void main()  
  2. {  
  3.     int16_t *samples;  
  4.     uint8_t *audio_outbuf;  
  5.     int audio_outbuf_size;  
  6.     int audio_input_frame_size;  
  7.     double audio_pts;  
  8.       
  9.     const char* filename = "test.wav";  
  10.     FILE *fin = fopen("result.pcm""rb"); //音频源文件   
  11.     AVOutputFormat *fmt;  
  12.     AVFormatContext *oc;  
  13.     AVStream * audio_st;  
  14.     av_register_all();  
  15.     fmt = guess_format(NULL, filename, NULL);  
  16.     oc = av_alloc_format_context();  
  17.     oc->oformat = fmt;  
  18.     snprintf(oc->filename, sizeof(oc->filename), "%s", filename);  
  19.     audio_st = NULL;  
  20.   
  21.     if (fmt->audio_codec != CODEC_ID_NONE)  
  22.     {  
  23.         AVCodecContext *c;  
  24.         audio_st = av_new_stream(oc, 1);  
  25.         c = audio_st->codec;  
  26.         c->codec_id = fmt->audio_codec;  
  27.         c->codec_type = CODEC_TYPE_AUDIO;  
  28.         c->bit_rate = 128000;  
  29.         c->sample_rate = 44100;  
  30.         c->channels = 2;  
  31.     }  
  32.     if (av_set_parameters(oc, NULL) < 0)  
  33.     {  
  34.         return;  
  35.     }  
  36.     dump_format(oc, 0, filename, 1);  
  37.     if (audio_st)  
  38.     {  
  39.         AVCodecContext* c;  
  40.         AVCodec* codec;  
  41.         c = audio_st->codec;  
  42.         codec = avcodec_find_encoder(c->codec_id);  
  43.         avcodec_open(c, codec);  
  44.         audio_outbuf_size = 10000;  
  45.         audio_outbuf = (uint8_t*)av_malloc(audio_outbuf_size);  
  46.         if (c->frame_size <= 1)  
  47.         {  
  48.             audio_input_frame_size = audio_outbuf_size / c->channels;  
  49.             switch (audio_st->codec->codec_id)  
  50.             {  
  51.             case CODEC_ID_PCM_S16LE:  
  52.             case CODEC_ID_PCM_S16BE:  
  53.             case CODEC_ID_PCM_U16LE:  
  54.             case CODEC_ID_PCM_U16BE:  
  55.                 audio_input_frame_size >>= 1;  
  56.                 break;  
  57.             default:  
  58.                 break;  
  59.             }  
  60.         }  
  61.         else  
  62.         {  
  63.             audio_input_frame_size = c->frame_size;  
  64.         }  
  65.         samples = (int16_t*)av_malloc(audio_input_frame_size*2*c->channels);  
  66.     }  
  67.     if (!fmt->flags & AVFMT_NOFILE)  
  68.     {  
  69.         if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0)  
  70.         {  
  71.             return;  
  72.         }  
  73.     }  
  74.     av_write_header(oc);  
  75.     for (;;)  
  76.     {  
  77.         if (audio_st)  
  78.         {  
  79.             audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;  
  80.         }  
  81.         else  
  82.         {  
  83.             audio_pts = 0.0;  
  84.         }  
  85.         if (!audio_st || audio_pts >= 360.0)  
  86.         {  
  87.             break;  
  88.         }  
  89.         if (fread(samples, 1, audio_input_frame_size*2*audio_st->codec->channels, fin) <= 0)  
  90.         {  
  91.             break;  
  92.         }  
  93.         AVCodecContext* c;  
  94.         AVPacket pkt;  
  95.         av_init_packet(&pkt);  
  96.         c = audio_st->codec;  
  97.         pkt.size = avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, samples);  
  98.         pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, audio_st->time_base);  
  99.         pkt.flags |= PKT_FLAG_KEY;  
  100.         pkt.stream_index = audio_st->index;  
  101.         pkt.data = audio_outbuf;  
  102.         if (av_write_frame(oc, &pkt) != 0)  
  103.         {  
  104.             return;  
  105.         }  
  106.     }  
  107.     if (audio_st)  
  108.     {  
  109.         avcodec_close(audio_st->codec);  
  110.         av_free(samples);  
  111.         av_free(audio_outbuf);  
  112.     }  
  113.     av_write_trailer(oc);  
  114.     for (int i=0; i<oc->nb_streams; i++)  
  115.     {  
  116.         av_freep(&oc->streams[i]->codec);  
  117.         av_freep(&oc->streams[i]);  
  118.     }  
  119.     if (!(fmt->flags & AVFMT_NOFILE))  
  120.     {  
  121.         url_fclose(oc->pb);  
  122.     }  
  123.     av_free(oc);  
  124.     fclose(fin);  
  125. }  

对应的下载链接:

音频解码:http://download.csdn.net/detail/yang_xian521/4399219

音频编码:http://download.csdn.net/detail/yang_xian521/4399293

至此,我已经实现了视频的解码编码,音频的解码编码,相信有心人肯定可以在此基础上实现视频音频的同步压缩,不过要再看一些网上的资料,也是很轻松的。至于视频的显示播放,大多数是要结合SDL实现,由于我只是浅尝辄止,只实现了图片的显示和简单的视频播放,比起我之前推荐的几个链接是弱爆了的,就不写下去了,这个系列就到这里吧,希望能给像我一样的一些入门级选手点帮助。也欢迎大神来多多指教。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值