看了http://blog.csdn.net/leixiaohua1020/article/details/8652605后,想学习在windows下面使用ffmpeg库播放视频。
《100行代码实现最简单的基于FFMPEG+SDL的视频播放器》:
该文章里面是使用ffmpeg结合SDL1.2解码视频的。其中用到了SDL_CreateYUVOverlay,SDL_Overlay等函数在SDL2.0已经不存在了。
因此需要想新的办法。
这里需要给自己先补点知识:
SDL(Simple DirectMedia Layer): 是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。
经过多方的查询,参考了N多资料。解决了。
参考资料:
1. http://blog.csdn.net/ashqal/article/details/17640179
2. http://stackoverflow.com/questions/17579286/sdl2-0-alternative-for-sdl-overlay
3. http://wiki.libsdl.org/MigrationGuide
4. http://blog.csdn.net/leixiaohua1020/article/details/12747899
5. http://blog.csdn.net/leixiaohua1020/article/details/8652605
6. https://github.com/chelyaev/ffmpeg-tutorial
下面的代码,是我自己根据上面帖子里面代码修改的。
#include <stdio.h> #include <tchar.h> #include <io.h> #include <direct.h> extern "C" { // ffmpeg #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" // SDL #include "sdl/SDL.h" #include "sdl/SDL_thread.h" }; #pragma comment(lib,"avutil.lib") #pragma comment(lib,"avcodec.lib") #pragma comment(lib,"avformat.lib") #pragma comment(lib,"swscale.lib") #pragma comment(lib,"sdl2.lib") int _tmain(int argc, char *argv[]) { /////////////////////////////////////////////////////////////////////////////// // ffmpeg // Register all formats and codecs av_register_all(); // Open video file AVFormatContext *pFormatCtx = NULL; const char* filename = "cuc_ieschool.flv"; if( avformat_open_input(&pFormatCtx, filename, 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, filename, 0); // Find the first video stream int videoStream = -1; for(int 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 AVCodecContext * pCodecCtx = pFormatCtx->streams[videoStream]->codec; // Find the decoder for the video stream AVCodec* pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if( pCodec == NULL ) { fprintf(stderr, "Unsupported codec!\n"); return -1; // Codec not found } // Open codec AVDictionary* optionsDict = NULL; if( avcodec_open2(pCodecCtx, pCodec, &optionsDict) < 0 ) { return -1; // Could not open codec } // Allocate video frame AVFrame* pFrame = av_frame_alloc(); AVFrame* pFrameYUV = av_frame_alloc(); if( pFrameYUV == NULL ) { return -1; } struct SwsContext* sws_ctx = sws_getContext( pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL); int numBytes = avpicture_get_size( PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); uint8_t* buffer = (uint8_t *)av_malloc( numBytes*sizeof(uint8_t) ); avpicture_fill((AVPicture *)pFrameYUV, buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); // Read frames and save first five frames to disk SDL_Rect sdlRect; sdlRect.x = 0; sdlRect.y = 0; sdlRect.w = pCodecCtx->width; sdlRect.h = pCodecCtx->height; ////////////////////////////////////////////////////// // SDL if( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER )) { fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError()); exit(1); } SDL_Window* sdlWindow = SDL_CreateWindow("My Game Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, pCodecCtx->width, pCodecCtx->height, 0); if( !sdlWindow ) { fprintf(stderr, "SDL: could not set video mode - exiting\n"); exit(1); } SDL_Renderer* sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, 0); SDL_Texture* sdlTexture = SDL_CreateTexture( sdlRenderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height); AVPacket packet; SDL_Event event; while( av_read_frame(pFormatCtx, &packet) >= 0 ) { // Is this a packet from the video stream? if( packet.stream_index == videoStream ) { // Decode video frame int frameFinished; avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); // Did we get a video frame? if( frameFinished ) { sws_scale( sws_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize ); SDL_UpdateTexture( sdlTexture, &sdlRect, pFrameYUV->data[0], pFrameYUV->linesize[0] ); SDL_RenderClear( sdlRenderer ); SDL_RenderCopy( sdlRenderer, sdlTexture, &sdlRect, &sdlRect ); SDL_RenderPresent( sdlRenderer ); } SDL_Delay(50); } // Free the packet that was allocated by av_read_frame av_free_packet(&packet); SDL_PollEvent(&event); switch( event.type ) { case SDL_QUIT: SDL_Quit(); exit(0); break; default: break; } } SDL_DestroyTexture(sdlTexture); // Free the YUV frame av_free(pFrame); av_free(pFrameYUV); // Close the codec avcodec_close(pCodecCtx); // Close the video file avformat_close_input(&pFormatCtx); return 0; }
PS: 由于写这篇文章的时候,CSDN上传资源有问题,待可以上传的时候,我再上传。
步骤:
1.下载SDL2.0 地址:http://www.libsdl.org/
2.下载ffmpeg在Windows下的SDK 地址:http://ffmpeg.zeranoe.com/builds/
3.下载MinGW // 可以在CSDN下载绿色版 地址:http://download.csdn.net/detail/piano7heart/3651248
下面打算学习如何使用ffmpeg解码音频流。。。