用ffmpeg把H264数据流解码成YUV420P

时间:2023-03-09 16:36:36
用ffmpeg把H264数据流解码成YUV420P

在网上找了很久这方面的内容,发现网上的代码都太旧了,所使用的函数旧到连最新版本的ffmpeg都已经不包含了,所以对于我这个初学者来说太坑拉。不过经过多次查找ffmpeg的头文件和结合网上的内容,终于成功可以解码拉。现在贴出来。

首先是初始化一些参数

  1. //下面初始化h264解码库
  2. avcodec_init();
  3. av_register_all();
  4. AVFrame *pFrame_ = NULL;
  5. AVCodecContext *codec_ = avcodec_alloc_context();
  6. /* find the video encoder */
  7. AVCodec *videoCodec = avcodec_find_decoder(CODEC_ID_H264);
  8. if (!videoCodec)
  9. {
  10. cout << "codec not found!" << endl;
  11. return -1;
  12. }
  13. //初始化参数,下面的参数应该由具体的业务决定
  14. codec_->time_base.num = 1;
  15. codec_->frame_number = 1; //每包一个视频帧
  16. codec_->codec_type = AVMEDIA_TYPE_VIDEO;
  17. codec_->bit_rate = 0;
  18. codec_->time_base.den = 30;//帧率
  19. codec_->width = 1280;//视频宽
  20. codec_->height = 720;//视频高
  21. if(avcodec_open(codec_, videoCodec) >= 0)
  22. pFrame_ = avcodec_alloc_frame();// Allocate video frame
  23. else
  24. return -1;

下面是具体的解码的代码

  1. AVPacket packet = {0};
  2. int frameFinished = dwBufsize;//这个是随便填入数字,没什么作用
  3. packet.data = pBuffer;//这里填入一个指向完整H264数据帧的指针
  4. packet.size = dwBufsize;//这个填入H264数据帧的大小
  5. //下面开始真正的解码
  6. avcodec_decode_video2(codec_, pFrame_, &frameFinished, &packet);
  7. if(frameFinished)//成功解码
  8. {
  9. int picSize = codec_->height * codec_->width;
  10. int newSize = picSize * 1.5;
  11. //申请内存
  12. unsigned char *buf = new unsigned char[newSize];
  13. int height = p->codec->height;
  14. int width = p->codec->width;
  15. //写入数据
  16. int a=0,i;
  17. for (i=0; i<height; i++)
  18. {
  19. memcpy(buf+a,pFrame_->data[0] + i * pFrame_->linesize[0], width);
  20. a+=width;
  21. }
  22. for (i=0; i<height/2; i++)
  23. {
  24. memcpy(buf+a,pFrame_->data[1] + i * pFrame_->linesize[1], width/2);
  25. a+=width/2;
  26. }
  27. for (i=0; i<height/2; i++)
  28. {
  29. memcpy(buf+a,pFrame_->data[2] + i * pFrame_->linesize[2], width/2);
  30. a+=width/2;
  31. }
  32. //===============
  33. //到这里,buf里面已经是yuv420p的数据了,可以对它做任何的处理拉!
  34. //===============
  35. delete [] buf;
  36. }

不过我发现这样解码很耗cpu资源,我的Core2  E7400 2.8G的处理器,解码1920X1080分辨率每秒30帧的视频时,CPU占用率能用到差不多50%。

 

PS:原来avcodec_decode_video2这个函数会修改codec_里面的参数的,也就是说如果原来里面填的分别率是1280X720,运行avcodec_decode_video2后codec_里面会变成实际视频的分辨率。