流程:
解复用->解码->yuv->交给纹理->交给渲染器->播放。
其中前三步使用ffmpeg实现,后三步用sdl实现。
#include
#include #include
#include
#include
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)
#define av_frame_alloc avcodec_alloc_frame
#define av_frame_free avcodec_free_frame
#endifint main(int argc, char *argv[]) {int ret &#61; -1;AVFormatContext *pFormatCtx &#61; NULL; int i, videoStream;AVCodecContext *pCodecCtxOrig &#61; NULL; AVCodecContext *pCodecCtx &#61; NULL;struct SwsContext *sws_ctx &#61; NULL;AVCodec *pCodec &#61; NULL; AVFrame *pFrame &#61; NULL;AVPacket packet;int frameFinished;float aspect_ratio;AVPicture *pict &#61; NULL;SDL_Rect rect;Uint32 pixformat; SDL_Window *win &#61; NULL;SDL_Renderer *renderer &#61; NULL;SDL_Texture *texture &#61; NULL;int w_width &#61; 640;int w_height &#61; 480;if(argc < 2) {SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Usage: command ");return ret;}if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not initialize SDL - %s\n", SDL_GetError());return ret;}av_register_all();if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!&#61;0){SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to open video file!");goto __FAIL; }if(avformat_find_stream_info(pFormatCtx, NULL)<0){SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to find stream infomation!");goto __FAIL; }av_dump_format(pFormatCtx, 0, argv[1], 0);videoStream&#61;-1;for(i&#61;0; i<pFormatCtx->nb_streams; i&#43;&#43;) {if(pFormatCtx->streams[i]->codec->codec_type&#61;&#61;AVMEDIA_TYPE_VIDEO) {videoStream&#61;i;break;}}if(videoStream&#61;&#61;-1){SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Din&#39;t find a video stream!");goto __FAIL;}pCodecCtxOrig&#61;pFormatCtx->streams[videoStream]->codec;pCodec&#61;avcodec_find_decoder(pCodecCtxOrig->codec_id);if(pCodec&#61;&#61;NULL) {SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unsupported codec!\n");goto __FAIL; }pCodecCtx &#61; avcodec_alloc_context3(pCodec);if(avcodec_copy_context(pCodecCtx, pCodecCtxOrig) !&#61; 0) {SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn&#39;t copy codec context");goto __FAIL;}if(avcodec_open2(pCodecCtx, pCodec, NULL)<0) {SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to open decoder!\n");goto __FAIL; }pFrame&#61;av_frame_alloc();w_width &#61; pCodecCtx->width;w_height &#61; pCodecCtx->height;win &#61; SDL_CreateWindow( "Media Player",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,w_width, w_height,SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); if(!win){SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create window by SDL"); goto __FAIL;}renderer &#61; SDL_CreateRenderer(win, -1, 0);if(!renderer){SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create Renderer by SDL"); goto __FAIL;}pixformat &#61; SDL_PIXELFORMAT_IYUV;texture &#61; SDL_CreateTexture(renderer,pixformat, SDL_TEXTUREACCESS_STREAMING,w_width, w_height);sws_ctx &#61; sws_getContext(pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt,pCodecCtx->width,pCodecCtx->height,AV_PIX_FMT_YUV420P,SWS_BILINEAR,NULL,NULL,NULL);pict &#61; (AVPicture*)malloc(sizeof(AVPicture));avpicture_alloc(pict, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);while(av_read_frame(pFormatCtx, &packet)>&#61;0) {if(packet.stream_index&#61;&#61;videoStream) {avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);if(frameFinished) {sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data,pFrame->linesize, 0, pCodecCtx->height,pict->data, pict->linesize);SDL_UpdateYUVTexture(texture, NULL, pict->data[0], pict->linesize[0],pict->data[1], pict->linesize[1],pict->data[2], pict->linesize[2]);rect.x &#61; 0;rect.y &#61; 0;rect.w &#61; pCodecCtx->width;rect.h &#61; pCodecCtx->height;SDL_RenderClear(renderer);SDL_RenderCopy(renderer, texture, NULL, &rect);SDL_RenderPresent(renderer);}}av_free_packet(&packet);}__QUIT:ret &#61; 0;__FAIL:if(pFrame){av_frame_free(&pFrame);}if(pCodecCtx){avcodec_close(pCodecCtx);}if(pCodecCtxOrig){avcodec_close(pCodecCtxOrig);}if(pFormatCtx){avformat_close_input(&pFormatCtx);}if(pict){avpicture_free(pict);free(pict);}if(win){SDL_DestroyWindow(win);}if(renderer){SDL_DestroyRenderer(renderer);}if(texture){SDL_DestroyTexture(texture);}SDL_Quit();return ret;
}