• 2004-11-06

    从ffmpeg中提取mp3播放器

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://ffmpeg.blogbus.com/logs/480522.html

    mp3 和 mp2 的核心实现在 mpegaudiodec.c 里。

    如果不需要其它解码只要mpeg声音的解码的话,其接口相当简单。一个是初始化函数 decode_init,另一个是真正的帧解码函数 decode_frame.

    int decode_init(AVCodecContext * avctx)
    int decode_frame(AVCodecContext * avctx,void *data, int *data_size,uint8_t * buf, int buf_size)

    可以看得出来,用户只要定义一个 AVCodecContext 的变量,然后将指针传给这两个函数就可以了。另外特别值得注意的是 decode_init中第一行代码是
    MPADecodeContext *s = avctx->priv_data;

    由于AVCodecContext结构体的priv_data是一个数据空间的指针,如果没有分配空间那它是指向NULL的,所以你可以选择malloc一个空间,也可以定义一个全局变量MPADecodeContext MPDctx,然后将指针赋值给avctx->priv_data.我选择后者,对于管理内存,太麻烦,也不是俺的强项。

    decode_frame 的功能就是解码完一帧就返回,返回值表明使用了缓冲区中多少数据。当然如果传入的数据不够解码一帧也会返回,但是data_size为0。这里介绍一下decode_frame的后面几个参数,buf和buf_size是指传入的mpeg声音压缩码流的缓冲区地址和缓冲区大小,而data和是指解码出来的pcm数据要存放的地址,*data_size是解码出的pcm数据大小,一般为0或者1152x4. 除了data_size,decode_frame的另外四个参数都为输入型参数.

    据此,我们可以写一个main.c来实现一个播放器了。

    AVCodecContext t_avcc;
    MPADecodeContext t_mpadc;
    int main(int argc,char *argv[]){
         t_avcc.priv_data=&t_mpadc;

         decode_init(&t_avcc);

         此处加入打开mp3文件的指针file_mp3;

      while(!feof(file_mp3)){
        int len;
        unsigned char buf[4096],*buf_ptr;
        int buf_size;
        unsigned char data[1152*8];
        int data_size;
        /* 这个read函数不保证正确,凭感觉写的:(*/
        buf_size=read(buf,file_mp3,4096);
        while(buf_size>0){
          buf_ptr=buf;
          len=decode_frame(&t_avcc,data,&data_size,buf_ptr,buf_size);
          if(len<0)
            break;
          此处加入对data的处理代码,写入文件或者写到声卡,随便
          buf_optr+=len;
          buf_size-=len;
       }
      }
    }


    收藏到:Del.icio.us




    评论

  • 该代码只能解mp3 elementary stream, 代码里使用的file_mp3有点误导读者
  • ffdshow/ffmpeg工程组邀请版主加入,我们的QQ群:6939161,主页:http://www.chinavideo.org
  • 想请问一下如何使用ffmpeg解析出mp3文件中的id3 tag啊?谢谢!
  • 我只是不想使用太多的结构,呵呵。
  • "由于AVCodecContext结构体的priv_data是一个数据空间的指针,如果没有分配空间那它是指向NULL的,所以你可以选择malloc一个空间,也可以定义一个全局变量MPADecodeContext MPDctx,然后将指针赋值给avctx->priv_data.我选择后者,对于管理内存,太麻烦,也不是俺的强项。"



    你直接用 avcodec_open(AVCodecContext *avctx, AVCodec *codec)和

    int avcodec_close(AVCodecContext *avctx)不就完成了标准的wrapper了?

    我认为ffmpeg的IO接口实现的很不错,我们没有不使用的理由!