4. Use ffmpeg to decode the H264 data stream into YUV420P

I have been looking for this content on the Internet for a long time, and found that the code on the Internet is too old, and the functions used are so old that even the latest version of ffmpeg does not contain it, so it is too boring for a beginner like me. However, after many searches for ffmpeg's header files and combined with online content, I finally succeeded in decoding and pulling. Post it now.

The first is to initialize some parameters

[cpp] view plaincopy  
  1. //Initialize the h264 decoding library below  
  2. avcodec_init();  
  3. av_register_all ();  
  4.   
  5. AVFrame *pFrame_ = NULL;  
  6.   
  7. AVCodecContext *codec_ = avcodec_alloc_context();  
  8.   
  9. /* find the video encoder */  
  10. AVCodec *videoCodec = avcodec_find_decoder(CODEC_ID_H264);  
  11.   
  12. if (!videoCodec)   
  13. {  
  14.     cout << "codec not found!" << endl;  
  15.     return -1;  
  16. }  
  17.   
  18. //Initialization parameters, the following parameters should be determined by the specific business  
  19. codec_->time_base.num = 1;  
  20. codec_->frame_number = 1;  //One video frame per packet  
  21. codec_->codec_type = AVMEDIA_TYPE_VIDEO;  
  22. codec_->bit_rate = 0;  
  23. codec_->time_base.den = 30; //frame rate  
  24. codec_->width = 1280; //Video width  
  25. codec_->height = 720; //Video height  
  26.   
  27. if(avcodec_open(codec_, videoCodec) >= 0)  
  28.     pFrame_ = avcodec_alloc_frame();// Allocate video frame  
  29. else  
  30.     return -1;  

The following is the specific decoding code

[cpp] view plaincopy  
  1. AVPacket packet = {0};  
  2. int  frameFinished = dwBufsize; //This is to fill in the numbers casually, it has no effect  
  3.   
  4. packet.data = pBuffer; //fill in here a pointer to a complete H264 data frame  
  5. packet.size = dwBufsize; //This fills in the size of the H264 data frame  
  6.   
  7. //begin the real decoding below  
  8. avcodec_decode_video2(codec_, pFrame_, &frameFinished, &packet);  
  9. if (frameFinished) //Successful decoding  
  10. {  
  11.     int picSize = codec_->height * codec_->width;  
  12.     int newSize = picSize * 1.5;  
  13.   
  14.     //申请内存  
  15.     unsigned char *buf = new unsigned char[newSize];  
  16.   
  17.     int height = p->codec->height;  
  18.     int width = p->codec->width;  
  19.   
  20.   
  21.     //写入数据  
  22.     int a=0,i;   
  23.     for (i=0; i<height; i++)   
  24.     {   
  25.         memcpy(buf+a,pFrame_->data[0] + i * pFrame_->linesize[0], width);   
  26.         a+=width;   
  27.     }   
  28.     for (i=0; i<height/2; i++)   
  29.     {   
  30.         memcpy(buf+a,pFrame_->data[1] + i * pFrame_->linesize[1], width/2);   
  31.         a+=width/2;   
  32.     }   
  33.     for (i=0; i<height/2; i++)   
  34.     {   
  35.         memcpy(buf+a,pFrame_->data[2] + i * pFrame_->linesize[2], width/2);   
  36.         a+=width/2;   
  37.     }  
  38.   
  39.     //===============  
  40.     //到这里,buf里面已经是yuv420p的数据了,可以对它做任何的处理拉!  
  41.     //===============  
  42.     delete [] buf;  
  43. }  


However, I found that decoding in this way consumes CPU resources. My Core2 E7400 2.8G processor can use about 50% of the CPU usage when decoding 30 frames per second video at 1920X1080 resolution.


PS: The original avcodec_decode_video2 function will modify the parameters in codec_, that is to say, if the original resolution is 1280X720, after running avcodec_decode_video2, codec_ will become the actual video resolution.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325857811&siteId=291194637