FFMPEG3.2SDK解码H264保存为YUV420文件

来源:互联网 发布:crm虚拟定位软件 编辑:程序博客网 时间:2024/05/29 16:30

 

直接上代码.

 

 

 

#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")

#include <windows.h>
#include <windef.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <math.h>

#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
#include "libswscale/swscale.h"

#define INBUF_SIZE 4096

bool H264_Init();
void H264_Release();
void ReadH264();
void pgm_save(unsigned char *buf,int wrap, int xsize,int ysize,char *filename);

static AVCodecContext * g_pCodecCtx = NULL;
static AVFrame * g_pavfFrame = NULL;
static AVFormatContext * pFormatCtx = NULL;
static AVCodec * pCodec = NULL;

uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE], *inbuf_ptr;

//main
int main(int arg,char* argv[]){

//SDK初始化

 H264_Init();

//解码

 ReadH264();

 return 0;

}

//ffmpge init .全局解码上下文应该可以通过FORMAT自动侦测的吧.这里写死了
bool H264_Init(){

 if(g_pCodecCtx){

  return true;

 }

 avcodec_init();

 av_register_all();

 pCodec = avcodec_find_decoder(CODEC_ID_H264);

 if(NULL!=pCodec){
  //printf("%s","ok");

  g_pCodecCtx=avcodec_alloc_context();
  g_pCodecCtx->time_base.num=1;
  g_pCodecCtx->time_base.den=25;
  g_pCodecCtx->bit_rate=0;
  g_pCodecCtx->frame_number=1;
  g_pCodecCtx->codec_type=CODEC_TYPE_VIDEO;
  g_pCodecCtx->width=1080;
  g_pCodecCtx->height=720;

  if(avcodec_open(g_pCodecCtx,pCodec)>=0){
  
   g_pavfFrame=avcodec_alloc_frame();

  }
 }

 return g_pavfFrame==NULL?true:false;
}


void H264_Release(){

 if(g_pavfFrame){

  av_free(g_pavfFrame);

  g_pavfFrame=NULL;

 }

 if(g_pCodecCtx){
 
  avcodec_close(g_pCodecCtx);

  av_free(g_pCodecCtx);

  g_pCodecCtx=NULL;

 }
};

 

//本来参考网上的资料,这个封装的方法实在不知道怎么用,就注释不用了.
/*
bool H264_Decode(const PBYTE pSrcData,const DWORD dwDataLen,PBYTE pDeData,int * pnWidth,int * pnHeight){

 bool nGot=false;

 avcodec_decode_video(g_pCodecCtx,g_pavfFrame,(int*)&nGot,(const unsigned char *)pSrcData,dwDataLen);

 if(nGot){
 
  *pnWidth=g_pCodecCtx->width;
  *pnHeight=g_pCodecCtx->height;

  assert(g_pCodecCtx->pix_fmt==PIX_FMT_YUV420P);

  for(int i=0,nDataLen=0;i<3;i++){
  
   int nShift=(i==0)?0:1;

   PBYTE pYUVData = (PBYTE)g_pavfFrame->data[i];

   for(int j=0;j<(g_pCodecCtx->height>>nShift);j++){
   
    memcpy(&pDeData[nDataLen],pYUVData,(g_pCodecCtx->width>>nShift));

    pYUVData+=g_pavfFrame->linesize[i];

    nDataLen+=(g_pCodecCtx->width>>nShift);

   }

  }
 
 }

 return nGot;

}
*/

void ReadH264(){

 

 AVPacket packet;
 
 uint8_t *buffer;

 AVFrame *pFrame;

 pFrame=avcodec_alloc_frame();

 int frameFinished;

 int numBytes;

 if(av_open_input_file(&pFormatCtx, "H264.264", NULL, 0, NULL)!=0){

  printf("%s","error");

 }
 if(av_find_stream_info(pFormatCtx)<0) {

  printf("%s","null stream"); // Couldn't find stream information</SPAN>
 }

 int videoStream=-1; 

 for(int i=0; i<(int)pFormatCtx->nb_streams; i++) 

  if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) { 

  videoStream=i; 

  break; 

 } 

  if(videoStream==-1)  {

   printf("%s","null video stream");  // Didn't find a video stream 

  }else{

   printf("%s","Have a video stream");

  }

  numBytes=avpicture_get_size(PIX_FMT_YUV420P, g_pCodecCtx->width,g_pCodecCtx->height); 

  buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
  
  //avpicture_fill((AVPicture *)g_pavfFrame, buffer, PIX_FMT_YUV420P, g_pCodecCtx->width, g_pCodecCtx->height);

  av_init_packet(&packet);

  FILE * fp = fopen("test.yuv","wb+");
  
  while(av_read_frame(pFormatCtx, &packet)>=0){
   
   if(packet.stream_index==videoStream){

    avcodec_decode_video(g_pCodecCtx,pFrame,&frameFinished,packet.data,packet.size);

    if(frameFinished){

     fflush(stdout);

     /* the picture is allocated by the decoder. no need to free it */
     pgm_save(pFrame->data[0], pFrame->linesize[0], g_pCodecCtx->width, g_pCodecCtx->height, "test.yuv");//Y
                        
     pgm_save(pFrame->data[1], pFrame->linesize[1], g_pCodecCtx->width/2, g_pCodecCtx->height/2, "test.yuv");       //U
     
     pgm_save(pFrame->data[2], pFrame->linesize[2], g_pCodecCtx->width/2, g_pCodecCtx->height/2, "test.yuv");  

    }


   }
   
  }

  //avcodec_decode_video

 

 // Get a pointer to the codec context for the video stream 

 //g_pCodecCtx=pFormatCtx->streams[videoStream]->codec;
 //pCodec=avcodec_find_decoder(g_pCodecCtx->codec_id);

}

//保存文件方法

void pgm_save(unsigned char *buf,int wrap, int xsize,int ysize,char *filename)
{
    FILE *f;
    int i;

 f=fopen(filename,"ab+");  

 for(i=0;i<ysize;i++)
 {
  fwrite(buf + i * wrap, 1, xsize, f );
 }
 fclose(f);
}