Advertisement
zerodivisi0n

FFmpeg sample player

Feb 7th, 2012
7,520
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.10 KB | None | 0 0
  1. /**
  2.  * FFmpeg sample player
  3.  * Related to the article at http://habrahabr.ru/blogs/video/137793/
  4.  */
  5. #include <stdio.h>
  6.  
  7. #include <SDL.h>
  8.  
  9. #include <libavcodec/avcodec.h>
  10. #include <libavformat/avformat.h>
  11. #include <libswscale/swscale.h>
  12.  
  13. int main(int argc, char* argv[]) {
  14.     if (argc < 2) {
  15.         printf("Usage: %s filename\n", argv[0]);
  16.         return 0;
  17.     }
  18.    
  19.     // Register all available file formats and codecs
  20.     av_register_all();
  21.    
  22.     int err;
  23.     // Init SDL with video support
  24.     err = SDL_Init(SDL_INIT_VIDEO);
  25.     if (err < 0) {
  26.         fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
  27.         return -1;
  28.     }
  29.    
  30.     // Open video file
  31.     const char* filename = argv[1];
  32.     AVFormatContext* format_context = NULL;
  33.     err = avformat_open_input(&format_context, filename, NULL, NULL);
  34.     if (err < 0) {
  35.         fprintf(stderr, "ffmpeg: Unable to open input file\n");
  36.         return -1;
  37.     }
  38.    
  39.     // Retrieve stream information
  40.     err = avformat_find_stream_info(format_context, NULL);
  41.     if (err < 0) {
  42.         fprintf(stderr, "ffmpeg: Unable to find stream info\n");
  43.         return -1;
  44.     }
  45.    
  46.     // Dump information about file onto standard error
  47.     av_dump_format(format_context, 0, argv[1], 0);
  48.    
  49.     // Find the first video stream
  50.     int video_stream;
  51.     for (video_stream = 0; video_stream < format_context->nb_streams; ++video_stream) {
  52.         if (format_context->streams[video_stream]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
  53.             break;
  54.         }
  55.     }
  56.     if (video_stream == format_context->nb_streams) {
  57.         fprintf(stderr, "ffmpeg: Unable to find video stream\n");
  58.         return -1;
  59.     }
  60.    
  61.     AVCodecContext* codec_context = format_context->streams[video_stream]->codec;
  62.     AVCodec* codec = avcodec_find_decoder(codec_context->codec_id);
  63.     err = avcodec_open2(codec_context, codec, NULL);
  64.     if (err < 0) {
  65.         fprintf(stderr, "ffmpeg: Unable to open codec\n");
  66.         return -1;
  67.     }
  68.    
  69.     SDL_Surface* screen = SDL_SetVideoMode(codec_context->width, codec_context->height, 0, 0);
  70.     if (screen == NULL) {
  71.         fprintf(stderr, "Couldn't set video mode\n");
  72.         return -1;
  73.     }
  74.    
  75.     SDL_Overlay* bmp = SDL_CreateYUVOverlay(codec_context->width, codec_context->height,
  76.                                             SDL_YV12_OVERLAY, screen);
  77.  
  78.     struct SwsContext* img_convert_context;
  79.     img_convert_context = sws_getCachedContext(NULL,
  80.                                                 codec_context->width, codec_context->height,
  81.                                                 codec_context->pix_fmt,
  82.                                                 codec_context->width, codec_context->height,
  83.                                                 PIX_FMT_YUV420P, SWS_BICUBIC,
  84.                                                 NULL, NULL, NULL);
  85.     if (img_convert_context == NULL) {
  86.         fprintf(stderr, "Cannot initialize the conversion context\n");
  87.         return -1;
  88.     }
  89.  
  90.     AVFrame* frame = avcodec_alloc_frame();
  91.     AVPacket packet;
  92.     while (av_read_frame(format_context, &packet) >= 0) {
  93.         if (packet.stream_index == video_stream) {
  94.             // Video stream packet
  95.             int frame_finished;
  96.             avcodec_decode_video2(codec_context, frame, &frame_finished, &packet);
  97.            
  98.             if (frame_finished) {
  99.                 SDL_LockYUVOverlay(bmp);
  100.                
  101.                 // Convert frame to YV12 pixel format for display in SDL overlay
  102.                
  103.                 AVPicture pict;
  104.                 pict.data[0] = bmp->pixels[0];
  105.                 pict.data[1] = bmp->pixels[2];  // it's because YV12
  106.                 pict.data[2] = bmp->pixels[1];
  107.                
  108.                 pict.linesize[0] = bmp->pitches[0];
  109.                 pict.linesize[1] = bmp->pitches[2];
  110.                 pict.linesize[2] = bmp->pitches[1];
  111.                
  112.                 sws_scale(img_convert_context,
  113.                             frame->data, frame->linesize,
  114.                             0, codec_context->height,
  115.                             pict.data, pict.linesize);
  116.                
  117.                 SDL_UnlockYUVOverlay(bmp);
  118.                
  119.                 SDL_Rect rect;
  120.                 rect.x = 0;
  121.                 rect.y = 0;
  122.                 rect.w = codec_context->width;
  123.                 rect.h = codec_context->height;
  124.                 SDL_DisplayYUVOverlay(bmp, &rect);
  125.             }
  126.         }
  127.        
  128.         // Free the packet that was allocated by av_read_frame
  129.         av_free_packet(&packet);
  130.    
  131.         // Handling SDL events there
  132.         SDL_Event event;
  133.         if (SDL_PollEvent(&event)) {
  134.             if (event.type == SDL_QUIT) {
  135.                 break;
  136.             }
  137.         }
  138.     }
  139.    
  140.     sws_freeContext(img_convert_context);
  141.    
  142.     // Free the YUV frame
  143.     av_free(frame);
  144.    
  145.     // Close the codec
  146.     avcodec_close(codec_context);
  147.    
  148.     // Close the video file
  149.     avformat_close_input(&format_context);
  150.    
  151.     // Quit SDL
  152.     SDL_Quit();
  153.     return 0;
  154. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement