FFMPEG教程2_解码后在屏幕显示(使用2014年新SDK重新整理编译通过)

来源:互联网 发布:怎样进去网络黑市 编辑:程序博客网 时间:2024/05/21 06:30
#include "stdafx.h"#include <Windows.h>#pragma warning( disable : 4312 ) #pragma warning( disable : 4244 ) #pragma warning( disable : 4311 ) #ifdef  __cplusplus  extern "C" {  #endif  #include <libavcodec/avcodec.h>  #include <libavformat/avformat.h>  #include <libavutil/avutil.h>  #include <libswscale/swscale.h>  #include <SDL/SDL.h>  #include <SDL/SDL_video.h>      // SDL#include <SDL/SDL_thread.h>      // SDL#ifdef __cplusplus  }  #endif  #pragma comment( lib, "libgcc.a")  #pragma comment( lib, "libmingwex.a")  #pragma comment( lib, "libcoldname.a")  #pragma comment( lib, "libavcodec.a")  #pragma comment( lib, "libavformat.a")  #pragma comment( lib, "libavutil.a")  #pragma comment( lib, "libswscale.a")  #pragma comment( lib, "libz.a")  #pragma comment( lib, "libfaac.a")  #pragma comment( lib, "libgsm.a")  #pragma comment( lib, "libmp3lame.a")  #pragma comment( lib, "libogg.a")  #pragma comment( lib, "libspeex.a")  #pragma comment( lib, "libtheora.a")  #pragma comment( lib, "libvorbis.a")  #pragma comment( lib, "libvorbisenc.a")  #pragma comment( lib, "libx264.a")  #pragma comment( lib, "xvidcore.a") #pragma comment( lib, "wsock32.lib")  #pragma comment( lib, "vfw32.lib")   #pragma comment( lib, "sdl2main.lib")  #pragma comment( lib, "sdl2.lib")   #pragma   comment(lib, "winmm.lib ")#pragma  comment(lib,"Version.lib") #pragma  comment(lib,"imm32.lib") #define SFM_REFRESH_EVENT  (SDL_USEREVENT + 1)int thread_exit=0;int sfp_refresh_thread(void *opaque){while (thread_exit==0) {SDL_Event event;event.type = SFM_REFRESH_EVENT;SDL_PushEvent(&event);SDL_Delay(40);}return 0;}int _tmain(int argc, char *argv[]){//下面这个千万要注意,原来老代码不需要=NULL,//但是新SDK如果不初始化会在avformat_open_input非法退出//因此,将指针初始化为NULL是个好习惯!AVFormatContext *pFormatCtx = NULL;int             i, videoStream;AVCodecContext  *pCodecCtx = NULL;AVCodec         *pCodec = NULL;AVFrame         *pFrame = NULL; AVFrame         *pFrameRGB = NULL;AVPacket        packet;int             frameFinished;int             numBytes;uint8_t         *buffer;struct SwsContext *sws_ctx = NULL;SDL_Texture    *bmp = NULL;    SDL_Window     *screen = NULL;    SDL_Rect        rect;    SDL_Event       event;if(argc < 2) {printf("带参数执行,后面跟视频文件\n");return -1;}// 注册所有的解码格式av_register_all();avformat_network_init();      pFormatCtx = avformat_alloc_context();   if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());        exit(1);    }printf_s("打开视频文件:%s成功\n",argv[1]);//打开视频printf_s("打开视频文件:%s成功\n",argv[1]);    if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!=0)        return -1; // 打开视频文件失败    printf_s("打开视频文件:%s成功\n",argv[1]);// 检索流信息if(av_find_stream_info(pFormatCtx)<0)return -1; // 不能发现流信息资料//打印标准的转储信息 av_dump_format(pFormatCtx, 0, argv[1], 0);// 找到第一个视频videoStream=-1;for(i=0; i<(int)pFormatCtx->nb_streams; i++)if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {videoStream=i;break;}if(videoStream==-1)return -1; // 没有发现视频流//获得视频编解码器的上下文指针pCodecCtx=pFormatCtx->streams[videoStream]->codec;// 找到视频解码器pCodec=avcodec_find_decoder(pCodecCtx->codec_id);if(pCodec==NULL) {fprintf(stderr, "Unsupported codec!\n");return -1; //视频解码未发现}// 开放的编解码器if(avcodec_open(pCodecCtx, pCodec)<0)return -1; // 视频解码未发现//分配视频帧pFrame=avcodec_alloc_frame();// 分配一个AVFrame结构pFrameRGB=avcodec_alloc_frame();if(pFrameRGB==NULL)return -1; int screen_w = pCodecCtx->width;      int screen_h = pCodecCtx->height;      screen = SDL_CreateWindow("Simplest ffmpeg player's Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, screen_w, screen_h,SDL_WINDOW_OPENGL);  //screen = SDL_CreateWindow("My Game Window",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,pCodecCtx->width,  pCodecCtx->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);}//bmp = SDL_CreateTexture(renderer,SDL_PIXELFORMAT_YV12,SDL_TEXTUREACCESS_STREAMING,pCodecCtx->width,pCodecCtx->height);//如果使用这个SDL_PIXELFORMAT_YV12,显示颜色失真!bmp = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING,pCodecCtx->width,pCodecCtx->height);    //用于保存显示到SDL sws_ctx = sws_getContext(pCodecCtx->width,pCodecCtx->height, pCodecCtx->pix_fmt,pCodecCtx->width,pCodecCtx->height,PIX_FMT_YUV420P,SWS_BILINEAR,NULL,NULL,NULL);    ////确定所需的缓冲区大小和分配缓冲区,用于显示到SDL的numBytes = avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width,pCodecCtx->height);buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));// Assign appropriate parts of buffer to image planes in pFrameRGB // Note that pFrameRGB is an AVFrame, but AVFrame is a superset of AVPicture//分配适当的部分缓冲给在pFrameRGB中的图像平面,请注意,pFrameRGB 是一个AVFrame,但AVFrame却是AVPicture的超集,用于显示到SDLavpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);i=0;rect.x = 0;rect.y = 0;rect.w = pCodecCtx->width;rect.h = pCodecCtx->height;SDL_Thread *video_tid = SDL_CreateThread(sfp_refresh_thread,NULL,NULL);int iret;for(;;){SDL_WaitEvent(&event);if(event.type==SFM_REFRESH_EVENT){if(av_read_frame(pFormatCtx, &packet)>=0) {// 这是一个视频的包吗?if(packet.stream_index==videoStream) {// 解码视频帧iret = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished,&packet);if(iret < 0){printf("Decode Error.(解码错误)\n");return -1;}// 成功获得了视频帧?if(frameFinished) {// 将图像从原生格式转换成为目标格式sws_scale(sws_ctx,(uint8_t const * const *)pFrame->data,pFrame->linesize, 0,pCodecCtx->height, pFrameRGB->data,pFrameRGB->linesize);//送到SDL2.0中显示,和SDL1.0明显不同!SDL_UpdateTexture( bmp, &rect, pFrameRGB->data[0], pFrameRGB->linesize[0] );SDL_RenderClear( renderer );SDL_RenderCopy( renderer, bmp, &rect, &rect );SDL_RenderPresent( renderer );}}// 释放av_read_frame分配的包av_free_packet(&packet);}else{thread_exit = 1;break;}}}SDL_DestroyTexture(bmp);sws_freeContext(sws_ctx);  SDL_Quit();  // 释放RGB图像av_free(buffer);av_free(pFrameRGB);// 释放YUV帧av_free(pFrame);// 关闭解码器avcodec_close(pCodecCtx);// 关闭视频文件av_close_input_file(pFormatCtx);return 0;}

0 0
原创粉丝点击