FFMpeg杂音问题解决方案

最近在调试网上下载的android ffmpeg播放器的源代码。因为编译ffmpeg过程中,觉得很麻烦,因此就没有继续编译SDL库了。打算在Java层使用Bitmap显示视频帧,在C层使用OpenSLES播放音频帧。

 

     将网上的相关源代码整合到一块后,发现音视频解码,都没有错误。并且视频可以播放出来,但是声音声调不对,主要还有杂音。试了网上的一些方法也不行。最后自己尝试性地改了一个变量。杂音就消失了,但是声调还不对。

   网上的解码音频数据包,然后将解码后的原始数据push到音频缓冲区的源代码中有以下几行代码

   //音频数据解码

   len = avcodec_decode_audio4(aCodecCtx, frame, &got_frame, &packet); 

   //得到解码音频数据的大小

   data_size = av_samples_get_buffer_size(   NULL, aCodecCtx->channels,  
                                                                        frame->nb_samples,aCodecCtx->sample_fmt, 1);  

  //将解码的音频数据push到音频缓冲区
   memcpy(stream, (uint8_t*)(frame->data[0]), data_size]); 

 

  我将  memcpy(stream, (uint8_t*)(frame->data[0]), data_size]); 

  改为  memcpy(stream, (uint8_t*)(frame->data[0]), frame->linesize[0]);  后杂音就消失了。但是声音明显比正常的要快。

 

  这个时候,感觉再去网上找方法也没什么用了。必须老老实实地理解AVFrame结构体中,各个字段的具体意思和PCM的相关知识点。

 

      后来知道了杂音和声调不对的原因了。

 

      杂音是因为avcodec_decode_audio4(aCodecCtx, frame, &got_frame, &packet)解码后的两个声道的音频数据分别存放在frame->data[0]和frame->data[1]中,而 frame->linesize[0]和 frame->linesize[1] 分别是前两者的大小。(我用来调试的视频文件,音频部分是双声道的)。而data_size表示的是两个声道的音频数据的总和。  因此memcpy(stream, (uint8_t*)(frame->data[0]), data_size])将一大段错误的数据push到缓冲区了。

 

     声音明显比正常的要快的原因是,memcpy(stream, (uint8_t*)(frame->data[0]), frame->linesize[0])只是push了一个声道的音频数据,而创建OpenSLES的播放器是却设置成了双 声道。format_pcm.numChannels = aCodecCtx->channels(实际上为2)。两个通道播放一个通道的数据,自然变快了。为尽快播放出正常的声音,将播放器声道数设为1,此时听到了正常的音乐。

 

    当然最正确的方法是正确地将编码后的音频数据,转换为正确的PCM格式。这样就可以双声道播放了。

 

    小结一下:遇到不是程序本身存在的问题时。还需要从原理入手,学习相关的知识,这样才能够真正理解一段代码的工作流程和原理。

你可能感兴趣的:(vc++,ffmpeg,ffmpeg)