在Linux上用FFmpeg得到视频的每一帧了,我想把每一帧在屏幕上显示出来

你是我的残梦 发布于 2014/05/22 15:34
阅读 3K+
收藏 0
#include "libavutil/imgutils.h" 
#include "libavutil/opt.h" 
#include "libavcodec/avcodec.h" 
#include "libavutil/mathematics.h" 
#include "libavutil/samplefmt.h" 
#include "libswscale/swscale.h"   
#include "SDL2/SDL.h"
#include "SDL2/SDL_thread.h"
   
#define INBUF_SIZE (4096) 
   
   
/* 
 * Video decoding example
 */ 
   
/*static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize,FILE *filename)
{
    FILE *f;
    int i;
 
    f=fopen(filename,"wb");
    fprintf(f,"P5\n%d%d\n%d\n",xsize,ysize,255);
    for(i=0;i<ysize;i++)
        fwrite(buf+i*wrap,ysize*xsize*3,1,f);
    fclose(f);
}*/
   
 //通过查找0x000001或者0x00000001找到下一个数据包的头部
static int _find_head(unsigned char*buffer, int len)
{
    int i;
 
    for(i=512;i<len;i++)
    {
        if(buffer[i] == 0 && buffer[i+1] == 0 && buffer[i+2] == 0&& buffer[i+3] == 1)
            break;
        if(buffer[i]== 0 && buffer[i+1] == 0 && buffer[i+2] == 1)
            break;
    }
    if (i ==len)
        return 0;
    if (i ==512)
        return 0;
    return i;
}
#define FILE_READING_BUFFER (1*1024*1024) 
static void build_avpkt(AVPacket *avpkt,FILE *fp)  
{  
     static unsigned char buffer[1*1024*1024];  
     static int readptr = 0;  
     static int writeptr = 0;  
     int len,toread;  
     int nexthead;  
     if(writeptr - readptr < 200 * 1024)  
     { 
          memmove(buffer, &buffer[readptr], writeptr - readptr); 
          writeptr -= readptr; 
          readptr = 0; 
          toread = FILE_READING_BUFFER - writeptr; 
          len =fread(&buffer[writeptr], 1, toread, fp); 
          writeptr += len; 
     } 
     nexthead = _find_head(&buffer[readptr], writeptr-readptr); 
     if(nexthead == 0)  
     { 
         printf("failed find next head...n"); 
         nexthead = writeptr - readptr; 
     } 
   
     avpkt->size = nexthead; 
     avpkt->data = &buffer[readptr]; 
     readptr += nexthead;   
}  
   
static void video_decode_example(const char*filename)  
{  
    AVCodec *codec; 
    AVCodecContext *c= NULL; 
    int frame, got_picture, len;  
    FILE *f, *fout;  
    AVFrame *picture; 
    uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; 
    char buf[1024];  
    AVPacket avpkt; 
    AVDictionary *opts; 
    //....SDL...
    SDL_Texture    *bmp = NULL; 
    SDL_Window     *screen = NULL; 
    SDL_Rect        rect; 
    SDL_Event       event;
   //..........
    av_init_packet(&avpkt); 
   
    /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */ 
    memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE); 
   
    printf("Video decoding\n"); 
    opts = NULL; 
    //av_dict_set(&opts, "b", "2.5M", 0); 
    /* find the mpeg1 video decoder */ 
    codec = avcodec_find_decoder(CODEC_ID_H264); 
    if(!codec) {  
        fprintf(stderr,"codec not found\n"); 
        exit(1); 
    } 
   
    c = avcodec_alloc_context3(codec); 
    picture= avcodec_alloc_frame(); 
   
    if(codec->capabilities&CODEC_CAP_TRUNCATED) 
        c->flags|= CODEC_FLAG_TRUNCATED;/* we do not send complete frames */ 
   
    /* For some codecs, such as msmpeg4 and mpeg4, width and height
       MUST be initialized there because this information is not
       available in the bitstream. */ 
   
    /* open it */ 
    if(avcodec_open2(c, codec, NULL) < 0) {  
        fprintf(stderr,"could not open codec\n"); 
        exit(1); 
    } 
   
    
     
    /* the codec gives us the frame size, in samples */ 
   
    f =fopen(filename,"rb");  
    if(!f) {  
        fprintf(stderr,"could not open %s\n", filename); 
        exit(1); 
    }
 //printf("%s",f); 
    AVFrame frameRGB;
    avpicture_alloc((AVPicture*)&frameRGB,PIX_FMT_RGB24,352,288);
    //------------SDL----------------
 /*if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) { 
  printf( "Could not initialize SDL - %s\n", SDL_GetError());
  exit(1);
 } */
 screen = SDL_CreateWindow("My Game Window", 
                              SDL_WINDOWPOS_UNDEFINED, 
                              SDL_WINDOWPOS_UNDEFINED, 
                              c->width,  c->height, 
                              SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL); 
    SDL_Renderer *renderer = SDL_CreateRenderer(screen, -1, 0); 
     
     
    if(!screen) { 
        fprintf(stderr, "SDL: could not set video mode - exiting\n"); 
        exit(1); 
    } 
    
    // Allocate a place to put our YUV image on that screen 
//    bmp = SDL_CreateYUVOverlay(pCodecCtx->width, 
//                               pCodecCtx->height, 
//                               SDL_YV12_OVERLAY, 
//                               screen); 
      bmp = SDL_CreateTexture(renderer,SDL_PIXELFORMAT_YV12,SDL_TEXTUREACCESS_STREAMING,c->width,c->height); 
//..........................*/
    frame = 0;
    struct SwsContext* scxt;
    for(;;) { 
        //avpkt.size = fread(inbuf, 1, INBUF_SIZE, f); 
        build_avpkt(&avpkt, f);
 
        if(avpkt.size == 0){  
            break; 
 }
     int i=0;
        while(avpkt.size > 0) {
     i++;
     char *outfilename = "ballrun-000%d.rgb";
    // fprintf(outfilename,i);
     fout=fopen(outfilename,"wb");
     //fprintf(fout,"P5%d\n%d\n",i,i,255); 
            len = avcodec_decode_video2(c, picture, &got_picture, &avpkt); 
            if(len < 0) {  
                fprintf(stderr,"Error while decoding frame %d\n", frame); 
                break; 
                //   exit(1); 
            } 
            if(got_picture) {  
                printf("saving frame %3d\n", frame); 
                fflush(stdout); 
      //将YUV420格式的图像转换成RGB格式所需要的转换上下文
                scxt =sws_getContext(picture->width,picture->height,PIX_FMT_YUV420P,picture->width,picture->height,PIX_FMT_RGB565,2,NULL,NULL,NULL);
                if(scxt != NULL)
                {
                    sws_scale(scxt,picture->data,picture->linesize,0,c->height,frameRGB.data,frameRGB.linesize);//图像格式转换
                    //RGB 
                    fwrite(picture->data[0],(c->width)*(c->height)*3,1,fout);
      /*SDL_LockYUVOverlay(bmp);
      bmp->pixels[0]=picture->data[0];
      bmp->pixels[2]=picture->data[1];
      bmp->pixels[1]=picture->data[2];    
      bmp->pitches[0]=picture->linesize[0];
      bmp->pitches[2]=picture->linesize[1];  
      bmp->pitches[1]=picture->linesize[2];
      SDL_UnlockYUVOverlay(bmp);
      rect.x = 0;   
      rect.y = 0;   
      rect.w = c->width;   
      rect.h = c->height;   
      SDL_DisplayYUVOverlay(bmp, &rect);
      SDL_Delay(40);*/
       ////iPitch 计算yuv一行数据占的字节数 
                SDL_UpdateTexture( bmp, &rect, picture->data[0], picture->linesize[0] ); 
                SDL_RenderClear( renderer ); 
                SDL_RenderCopy( renderer, bmp, &rect, &rect ); 
                SDL_RenderPresent( renderer ); 
        
                }
   SDL_Delay(50);
      //av_free_packet(&packet); 
        SDL_PollEvent(&event); 
        switch(event.type) { 
            case SDL_QUIT: 
                SDL_Quit(); 
                exit(0); 
                break; 
            default: 
                break; 
        }   
                /* the picture is allocated by the decoder. no need to
                   free it */ 
               /* sprintf(buf, outfilename, frame); 
                pgm_save(picture->data[0], picture->linesize[0], 
                         c->width, c->height, fout); 
                pgm_save(picture->data[1], picture->linesize[1], 
                         c->width/2, c->height/2, fout); 
                pgm_save(picture->data[2], picture->linesize[2], 
                         c->width/2, c->height/2, fout);*/
                frame++; 
            }
     SDL_DestroyTexture(bmp); 
            avpkt.size -= len; 
            avpkt.data += len;
     
        } 
    } 
   
    /* some codecs, such as MPEG, transmit the I and P frame with a
       latency of one frame. You must do the following to have a
       chance to get the last frame of the video */ 
    avpkt.data = NULL; 
    avpkt.size = 0; 
    len = avcodec_decode_video2(c, picture, &got_picture, &avpkt); 
    if(got_picture) {  
        printf("saving last frame %3d\n", frame); 
        fflush(stdout); 
     scxt =sws_getContext(picture->width,picture->height,PIX_FMT_YUV420P,picture->width,picture->height,PIX_FMT_RGB24,2,NULL,NULL,NULL);
                if(scxt != NULL)
                {
                    sws_scale(scxt,picture->data,picture->linesize,0,c->height,frameRGB.data,frameRGB.linesize);//图像格式转换
                    //RGB 
                    fwrite(picture->data[0],(c->width)*(c->height)*3,1,fout);
                }
        /* the picture is allocated by the decoder. no need to
           free it */ 
        //sprintf(buf, outfilename, frame); 
        //pgm_save(picture->data[0], picture->linesize[0], 
          //       c->width, c->height, fout); 
                 /* pgm_save(picture->data[0], picture->linesize[0],c->width, c->height, fout); 
   pgm_save(picture->data[1], picture->linesize[1],c->width/2, c->height/2, fout); 
    pgm_save(picture->data[2], picture->linesize[2],c->width/2, c->height/2, fout);*/ 
   
  frame++; 
    } 
   
    fclose(f); 
 fclose(fout); 
   
    avcodec_close(c); 
    av_free(c); 
    av_free(picture); 
    printf("n"); 
}  
   
   
int main(int argc,char *argv[])  
{  
     printf("hello world\n"); 
     avcodec_register_all(); 
    video_decode_example("ballrun.h264");
     return 0; 
}
为什么在编译的时候说找不到SDL_CreateWindow,
                              SDL_WINDOWPOS_UNDEFINED, 
                              SDL_WINDOWPOS_UNDEFINED,  
                              SDL_WINDOW_FULLSCREEN , SDL_WINDOW_OPENGL。。。这些东西呢?求帮忙解答一下,谢谢了 
加载中
返回顶部
顶部