ffmpeg tutorial2 解析

来源:互联网 发布:javaweb程序员简历 编辑:程序博客网 时间:2024/06/11 06:49
没有注释的地方见tutorial1

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>

//此处加入了SDL库,具体见www.libsdl.org.
#include <SDL.h>
#include <SDL_thread.h>

#ifdef __MINGW32__
#undef main /* Prevents SDL from overriding main() */
#endif

#include <stdio.h>

int main(int argc, char *argv[]) {
  AVFormatContext *pFormatCtx = NULL;
  int             i, videoStream;
  AVCodecContext  *pCodecCtx = NULL;
  AVCodec         *pCodec = NULL;
  AVFrame         *pFrame = NULL;
  AVPacket        packet;
  int             frameFinished;
  //float           aspect_ratio;

  AVDictionary    *optionsDict = NULL;
  struct SwsContext *sws_ctx = NULL;

/*
SDL_Overlay
http://www.libsdl.org/docs/html/sdloverlay.html
A SDL_Overlay is similar to a SDL_Surface except it stores a YUV overlay. All the fields are read only, except for pixels which should be locked before use.

SDL_Surface
http://www.libsdl.org/docs/html/sdlsurface.html
SDL_Surface's represent areas of "graphical" memory, memory that can be drawn to. The video framebuffer is returned as a SDL_Surface by SDL_SetVideoMode and SDL_GetVideoSurface. Most of the fields should be pretty obvious.

SDL_PollEvent
http://www.libsdl.org/docs/html/sdlevent.html
The SDL_Event union is the core to all event handling is SDL, its probably the most important structure after SDL_Surface. SDL_Event is a union of all event structures used in SDL, using it is a simple matter of knowing which union member relates to which event type.

SDL_Event
http://wiki.libsdl.org/moin.fcg/SDL_Rect?highlight=%28\bCategoryStruct\b%29|%28SGStructures%29|%28SDLStructTemplate%29
*/
  SDL_Overlay     *bmp = NULL;
  SDL_Surface     *screen = NULL;
  SDL_Rect        rect;
  SDL_Event       event;

  if(argc < 2) {
    fprintf(stderr, "Usage: test <file>\n");
    exit(1);
  }
  // Register all formats and codecs
  av_register_all();
 

/*

SDL_Init:
http://wiki.libsdl.org/moin.fcg/SDL_Init?highlight=%28\bCategoryAPI\b%29|%28SGFunctions%29|%28SDLFunctionTemplate%29

*/
  if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
    fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
    exit(1);
  }

  // Open video file
  if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!=0)
    return -1; // Couldn't open file
 
  // Retrieve stream information
  if(avformat_find_stream_info(pFormatCtx, NULL)<0)
    return -1; // Couldn't find stream information
 
  // Dump information about file onto standard error
  av_dump_format(pFormatCtx, 0, argv[1], 0);
 
  // Find the first video stream
  videoStream=-1;
  for(i=0; i<pFormatCtx->nb_streams; i++)
    if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
      videoStream=i;
      break;
    }
  if(videoStream==-1)
    return -1; // Didn't find a video stream
 
  // Get a pointer to the codec context for the video stream
  pCodecCtx=pFormatCtx->streams[videoStream]->codec;
 
  // Find the decoder for the video stream
  pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
  if(pCodec==NULL) {
    fprintf(stderr, "Unsupported codec!\n");
    return -1; // Codec not found
  }
 
  // Open codec
  if(avcodec_open2(pCodecCtx, pCodec, &optionsDict)<0)
    return -1; // Could not open codec
 
  // Allocate video frame
  pFrame=avcodec_alloc_frame();

/*
SDL_SetVideoMode
http://www.libsdl.org/docs/html/sdlsetvideomode.html
Set up a video mode with the specified width, height and bits-per-pixel.
*/
  // Make a screen to put our video
#ifndef __DARWIN__
        screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);
#else
        screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);
#endif
  if(!screen) {
    fprintf(stderr, "SDL: could not set video mode - exiting\n");
    exit(1);
  }
 
/*
SDL_CreateYUVOverlay
http://www.libsdl.org/docs/html/sdlcreateyuvoverlay.html
Create a YUV video overlay
*/
  // Allocate a place to put our YUV image on that screen
  bmp = SDL_CreateYUVOverlay(pCodecCtx->width,
                 pCodecCtx->height,
                 SDL_YV12_OVERLAY,
                 screen);
 
  sws_ctx =
    sws_getContext
    (
        pCodecCtx->width,
        pCodecCtx->height,
        pCodecCtx->pix_fmt,
        pCodecCtx->width,
        pCodecCtx->height,
        PIX_FMT_YUV420P,
        SWS_BILINEAR,
        NULL,
        NULL,
        NULL
    );

  // Read frames and save first five frames to disk
  i=0;
  while(av_read_frame(pFormatCtx, &packet)>=0) {
    // Is this a packet from the video stream?
    if(packet.stream_index==videoStream) {
      // Decode video frame
      avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished,
               &packet);
      
      // Did we get a video frame?
      if(frameFinished) {
        //Lock an overlay; you just to know use it when you write the SDL_Overlay
    SDL_LockYUVOverlay(bmp);

/*
AVPicture
http://ffmpeg.org/doxygen/trunk/structAVPicture.html
*/



    AVPicture pict;
    pict.data[0] = bmp->pixels[0];//pixels    Pointer to the actual pixel data
    pict.data[1] = bmp->pixels[2];
    pict.data[2] = bmp->pixels[1];

    pict.linesize[0] = bmp->pitches[0]; //pitch    Length of a surface scanline in bytes
    pict.linesize[1] = bmp->pitches[2];
    pict.linesize[2] = bmp->pitches[1];

    // Convert the image into YUV format that SDL uses
    sws_scale
    (
        sws_ctx,
        (uint8_t const * const *)pFrame->data,
        pFrame->linesize,
        0,
        pCodecCtx->height,
        pict.data,
        pict.linesize
    );
    //Unlock an overlay; you use it when you finish writing the SDL_Overlay
    SDL_UnlockYUVOverlay(bmp);
    
    rect.x = 0;
    rect.y = 0;
    rect.w = pCodecCtx->width;
    rect.h = pCodecCtx->height;
/*
SDL_DisplayYUVOverlay
http://www.libsdl.org/docs/html/sdldisplayyuvoverlay.html
Blit the overlay to the surface specified when it was created. The SDL_Rect structure, dstrect, specifies the position and size of the destination. If the dstrect is a larger or smaller than the overlay then the overlay will be scaled, this is optimized for 2x scaling.
*/
    SDL_DisplayYUVOverlay(bmp, &rect);
      
      }
    }
    
    // Free the packet that was allocated by av_read_frame
    av_free_packet(&packet);
/*
SDL_PollEvent
http://www.libsdl.org/docs/html/sdlpollevent.html
Polls for currently pending events, and returns 1 if there are any pending events, or 0 if there are none available.
If event is not NULL, the next event is removed from the queue and stored in that area.


*/
    SDL_PollEvent(&event);
    switch(event.type) {
    case SDL_QUIT:
      SDL_Quit();
      exit(0);
      break;
    case SDL_KEYDOWN:
      printf("you press key\n");
      break;
    default:
      break;
    }

  }
 
  // Free the YUV frame
  av_free(pFrame);
 
  // Close the codec
  avcodec_close(pCodecCtx);
 
  // Close the video file
  avformat_close_input(&pFormatCtx);
 
  return 0;
}