日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

FFmpeg+SDL视频播放器

發(fā)布時(shí)間:2024/3/12 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 FFmpeg+SDL视频播放器 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本博客是摘自雷霄驊大神的課程《基于 FFmpeg + SDL 的視頻播放器的制作》課程 里的內(nèi)容,非常適合音視頻小白入門,在這里感謝雷神的指導(dǎo)!

目錄

  • FFmpeg和SDL的整合實(shí)現(xiàn)視頻播放
  • 進(jìn)階:脫離開(kāi)發(fā)環(huán)境的獨(dú)立播放器

FFmpeg和SDL的整合實(shí)現(xiàn)視頻播放

整合方式
? FFmpeg解碼器實(shí)現(xiàn)了:視頻文件->YUV
? SDL視頻顯示實(shí)現(xiàn)了:YUV->屏幕
? FFmpeg+SDL整合之后實(shí)現(xiàn)了:視頻文件->YUV->屏幕

/*** 最簡(jiǎn)單的基于FFmpeg的視頻播放器2(SDL升級(jí)版)* Simplest FFmpeg Player 2(SDL Update)** 雷霄驊 Lei Xiaohua* leixiaohua1020@126.com* 中國(guó)傳媒大學(xué)/數(shù)字電視技術(shù)* Communication University of China / Digital TV Technology* http://blog.csdn.net/leixiaohua1020** 本程序?qū)崿F(xiàn)了視頻文件的解碼和顯示(支持HEVC,H.264,MPEG2等)。* 是最簡(jiǎn)單的FFmpeg視頻解碼方面的教程。* 通過(guò)學(xué)習(xí)本例子可以了解FFmpeg的解碼流程。* 本版本中使用SDL消息機(jī)制刷新視頻畫面。* This software is a simplest video player based on FFmpeg.* Suitable for beginner of FFmpeg.**/#include <stdio.h>#define __STDC_CONSTANT_MACROSextern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" #include "libavutil/imgutils.h" #include "SDL.h" };//Refresh Event #define SFM_REFRESH_EVENT (SDL_USEREVENT + 1)#define SFM_BREAK_EVENT (SDL_USEREVENT + 2)int thread_exit = 0;int sfp_refresh_thread(void* opaque) {thread_exit = 0;while (!thread_exit) {SDL_Event event;event.type = SFM_REFRESH_EVENT;SDL_PushEvent(&event);SDL_Delay(40);}thread_exit = 0;//BreakSDL_Event event;event.type = SFM_BREAK_EVENT;SDL_PushEvent(&event);return 0; }int main(int argc, char* argv[]) {AVFormatContext* pFormatCtx;int i, videoindex;AVCodecContext* pCodecCtx;AVCodec* pCodec;AVFrame* pFrame, * pFrameYUV;uint8_t* out_buffer;AVPacket* packet;int ret, got_picture;//------------SDL----------------int screen_w, screen_h;SDL_Window* screen;SDL_Renderer* sdlRenderer;SDL_Texture* sdlTexture;SDL_Rect sdlRect;SDL_Thread* video_tid;SDL_Event event;struct SwsContext* img_convert_ctx;char filepath[] = "屌絲男士.mov";//av_register_all();avformat_network_init();pFormatCtx = avformat_alloc_context();if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0) {printf("Couldn't open input stream.\n");return -1;}if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {printf("Couldn't find stream information.\n");return -1;}videoindex = -1;for (i = 0; i < pFormatCtx->nb_streams; i++)if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {videoindex = i;break;}if (videoindex == -1) {printf("Didn't find a video stream.\n");return -1;}AVCodecParameters* codecParameters = pFormatCtx->streams[videoindex]->codecpar;pCodecCtx = avcodec_alloc_context3(nullptr);avcodec_parameters_to_context(pCodecCtx, codecParameters);//pCodecCtx = pFormatCtx->streams[videoindex]->codec;pCodec = (AVCodec*)avcodec_find_decoder(pCodecCtx->codec_id);if (pCodec == NULL) {printf("Codec not found.\n");return -1;}if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {printf("Could not open codec.\n");return -1;}packet = av_packet_alloc();pFrame = av_frame_alloc();pFrameYUV = av_frame_alloc();out_buffer = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1));av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1);img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) {printf("Could not initialize SDL - %s\n", SDL_GetError());return -1;}//SDL 2.0 Support for multiple windowsscreen_w = pCodecCtx->width;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);if (!screen) {printf("SDL: could not create window - exiting:%s\n", SDL_GetError());return -1;}sdlRenderer = SDL_CreateRenderer(screen, -1, 0);//IYUV: Y + U + V (3 planes)//YV12: Y + V + U (3 planes)sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height);sdlRect.x = 0;sdlRect.y = 0;sdlRect.w = screen_w;sdlRect.h = screen_h;packet = (AVPacket*)av_malloc(sizeof(AVPacket));video_tid = SDL_CreateThread(sfp_refresh_thread, NULL, NULL);//------------SDL End------------//Event Loopfor (;;) {//WaitSDL_WaitEvent(&event);if (event.type == SFM_REFRESH_EVENT) {//------------------------------if (av_read_frame(pFormatCtx, packet) >= 0) {if (packet->stream_index == videoindex) {if (avcodec_send_packet(pCodecCtx, packet) < 0) {printf("avcodec_send_packet failed!.\n");continue;}while (1) {ret = avcodec_receive_frame(pCodecCtx, pFrame);if (ret != 0)break;sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);//SDL---------------------------SDL_UpdateTexture(sdlTexture, NULL, pFrameYUV->data[0], pFrameYUV->linesize[0]);SDL_RenderClear(sdlRenderer);//SDL_RenderCopy( sdlRenderer, sdlTexture, &sdlRect, &sdlRect ); SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);SDL_RenderPresent(sdlRenderer);//SDL End-----------------------}}av_packet_unref(packet);}else {//Exit Threadthread_exit = 1;}}else if (event.type == SDL_QUIT) {thread_exit = 1;}else if (event.type == SFM_BREAK_EVENT) {break;}}sws_freeContext(img_convert_ctx);SDL_Quit();//--------------av_frame_free(&pFrameYUV);av_frame_free(&pFrame);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);return 0; }

進(jìn)階:脫離開(kāi)發(fā)環(huán)境的獨(dú)立播放器

因?yàn)閂S會(huì)生成可執(zhí)行文件(在Debug文件夾中),利用argv參數(shù)進(jìn)行視頻文件的選擇播放

main()函數(shù)的參數(shù)
? argc argv:全稱為ARGument Counter 和 ARGument Vector。其中argv存儲(chǔ)了來(lái)自于命令行的參數(shù);而argc存儲(chǔ)了參數(shù)的個(gè)數(shù)。
? 例如在命令行中輸入“ffmpeg -i test.mkv test.ts ”,則argc取值為4, 而argv[]數(shù)組取值如下:
argv[0]=“ffmpeg”
argv[1]=“-i”
argv[2]=“test.mkv”
argv[3]=“test.ts”
? 動(dòng)態(tài)鏈接庫(kù)(*.dll)
動(dòng)態(tài)鏈接庫(kù)不能被編譯進(jìn)應(yīng)用程序。因而使用應(yīng)用程序的時(shí)候必須在相同目錄下保存用到的動(dòng)態(tài)鏈接庫(kù)文件。

總結(jié)

以上是生活随笔為你收集整理的FFmpeg+SDL视频播放器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。