首页 > 代码库 > ffmpeg+sdl教程----编写一个简单的播放器2(输出视频到屏幕)

ffmpeg+sdl教程----编写一个简单的播放器2(输出视频到屏幕)

来源:http://blog.csdn.net/mu399/article/details/5814859

下面完整代码,在vc2005下编译通过。可以看到,程序运行后视频播放出来了,但是由于没有加入播放延迟,视频简直跑疯了,为视频加入延迟将在教程五中实现,目前可以简单地让程序在播放完一帧后,sleep若干秒,改善一下运行状况。

[cpp] view plaincopy
  1. // ffmpegExe.cpp: 主项目文件。  
  2.   
  3. #include "stdafx.h"  
  4. #include "libavformat/avformat.h"  
  5. #include "libswscale/swscale.h"  
  6. //#include <windows.h>  
  7.   
  8. #include <stdlib.h>  
  9. #include <stdio.h>  
  10. #include <string.h>  
  11. #include <math.h>  
  12. #include <SDL/SDL.h>  
  13.   
  14. #ifdef main  
  15. #undef main  
  16. #endif  
  17.   
  18. #define SDL_AUDIO_BUFFER_SIZE 1024  
  19. static int sws_flags = SWS_BICUBIC;  
  20.   
  21. int main(int argc, char *argv[])  
  22. {  
  23.     AVFormatContext *pFormatCtx;  
  24.     int i, videoStream(-1);  
  25.     AVCodecContext *pCodecCtx;  
  26.     AVCodec *pCodec;  
  27.     AVFrame *pFrame;  
  28.     AVPacket packet;  
  29.     int frameFinished;  
  30.     float aspect_ratio;  
  31.     AVCodecContext *aCodecCtx;  
  32.     SDL_Overlay *bmp;  
  33.     SDL_Surface *screen;  
  34.     SDL_Rect rect;  
  35.     SDL_Event event;  
  36.     if(argc < 2)  
  37.     {  
  38.         fprintf(stderr, "Usage: test /n");  
  39.         exit(1);  
  40.     }  
  41.   
  42.     av_register_all();  
  43.     pFormatCtx = av_alloc_format_context();  
  44.     if (!pFormatCtx) {  
  45.         fprintf(stderr, "Memory error/n");  
  46.         exit(1);  
  47.     }  
  48.     if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)  
  49.         return -1; // Couldn‘t open file  
  50.     if(av_find_stream_info(pFormatCtx)<0)  
  51.         return -1; // Couldn‘t find stream information  
  52.     // Dump information about file onto standard error  
  53.     dump_format(pFormatCtx, 0, argv[1], 0);  
  54.   
  55.     // Find the first video stream  
  56.     for(i=0; i<pFormatCtx->nb_streams; i++)  
  57.     {  
  58.         if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO && videoStream<0)  
  59.         {  
  60.             videoStream=i;  
  61.         }  
  62.     }  
  63.     if(videoStream==-1)  
  64.       return -1; // Didn‘t find a video stream  
  65.   
  66.     // Get a pointer to the codec context for the video stream  
  67.   
  68.     pCodecCtx=pFormatCtx->streams[videoStream]->codec;  
  69.     pCodec=avcodec_find_decoder(pCodecCtx->codec_id);  
  70.     if(pCodec==NULL)  
  71.     {  
  72.         fprintf(stderr, "Unsupported codec!/n");  
  73.         return -1; // Codec not found  
  74.     }  
  75.     // Open codec  
  76.     if(avcodec_open(pCodecCtx, pCodec)<0)  
  77.         return -1; // Could not open codec  
  78.   
  79.     // Allocate video frame  
  80.     pFrame=avcodec_alloc_frame();  
  81.   
  82.     uint8_t *buffer;  
  83.     int numBytes;  
  84.     // Determine required buffer size and allocate buffer  
  85.     numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,  
  86.         pCodecCtx->height);  
  87.     buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));  
  88.   
  89.     if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER))  
  90.     {  
  91.         fprintf(stderr, "Could not initialize SDL - %s/n", SDL_GetError());  
  92.         exit(1);  
  93.     }  
  94.   
  95. #ifndef __DARWIN__  
  96.     screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);  
  97. #else  
  98.     screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);  
  99. #endif  
  100.     if(!screen)  
  101.     {  
  102.         fprintf(stderr, "SDL: could not set video mode - exiting/n");  
  103.         exit(1);  
  104.     }  
  105.   
  106.     bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,  
  107.         SDL_YV12_OVERLAY, screen);  
  108.   
  109.     static struct SwsContext *img_convert_ctx;  
  110.     if (img_convert_ctx == NULL)  
  111.     {  
  112.         img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,  
  113.                                          pCodecCtx->pix_fmt,  
  114.                                          pCodecCtx->width, pCodecCtx->height,  
  115.                                          PIX_FMT_YUV420P,  
  116.                                          sws_flags, NULL, NULL, NULL);  
  117.         if (img_convert_ctx == NULL)  
  118.         {  
  119.             fprintf(stderr, "Cannot initialize the conversion context/n");  
  120.             exit(1);  
  121.         }  
  122.     }  
  123.     i=0;  
  124.     while(av_read_frame(pFormatCtx, &packet)>=0)  
  125.     {  
  126.         // Is this a packet from the video stream?  
  127.         if(packet.stream_index==videoStream)  
  128.         {  
  129.             // Decode video frame  
  130.             avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,  
  131.                 packet.data, packet.size);  
  132.             // Did we get a video frame?  
  133.             if(frameFinished)  
  134.             {  
  135.                 // Convert the image from its native format to RGB  
  136.                 /*sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 
  137.                       0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);*/  
  138.                 // Save the frame to disk  
  139.                 /*if(++i<=5) 
  140.                     SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);*/  
  141.                 SDL_LockYUVOverlay(bmp);  
  142.                 AVPicture pict;  
  143.                 pict.data[0] = bmp->pixels[0];  
  144.                 pict.data[1] = bmp->pixels[2];  
  145.                 pict.data[2] = bmp->pixels[1];  
  146.   
  147.                 pict.linesize[0] = bmp->pitches[0];  
  148.                 pict.linesize[1] = bmp->pitches[2];  
  149.                 pict.linesize[2] = bmp->pitches[1];  
  150.   
  151.                 // Convert the image into YUV format that SDL uses  
  152.                 /*img_convert(&pict, PIX_FMT_YUV420P, 
  153.                     (AVPicture *)pFrame, pCodecCtx->pix_fmt, 
  154.                     pCodecCtx->width, pCodecCtx->height);*/  
  155.                 sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize,  
  156.                     0, pCodecCtx->height, pict.data, pict.linesize);  
  157.                 SDL_UnlockYUVOverlay(bmp);  
  158.                 rect.x = 0;  
  159.                 rect.y = 0;  
  160.                 rect.w = pCodecCtx->width;  
  161.                 rect.h = pCodecCtx->height;  
  162.                 SDL_DisplayYUVOverlay(bmp, &rect);  
  163.                 //Sleep(60);  
  164.             }  
  165.         }  
  166.   
  167.         // Free the packet that was allocated by av_read_frame  
  168.         av_free_packet(&packet);  
  169.   
  170.         SDL_PollEvent(&event);  
  171.         switch(event.type)  
  172.         {  
  173.         case SDL_QUIT:  
  174.             SDL_Quit();  
  175.             exit(0);  
  176.             break;  
  177.         default: break;  
  178.         }  
  179.     };  
  180.     // Free the RGB image  
  181.     av_free(buffer);  
  182.     //av_free(pFrameRGB);  
  183.     // Free the YUV frame  
  184.     av_free(pFrame);  
  185.     // Close the codec  
  186.     avcodec_close(pCodecCtx);  
  187.     // Close the video file  
  188.     av_close_input_file(pFormatCtx);  
  189.     return 0;  

ffmpeg+sdl教程----编写一个简单的播放器2(输出视频到屏幕)