最も単純なFFMPEG + SDLベースのビデオプレーヤー:スプリットデコーダーとプレーヤー
Simplest Ffmpeg Sdl Based Video Player
================================================= = ==
FFmpegベースのビデオプレーヤーシリーズの最も単純なリスト:
最も単純なFFMPEG + SDLベースのビデオプレーヤー(SDL1.x)を実現するための100行のコード
最も単純なFFMPEG + SDLベースのビデオプレーヤーver2(SDL2.0を使用)
最も単純なFFmpegベースのデコーダー-純粋なバージョン(libavformatは含まれていません)
最も単純なFFMPEG + SDLベースのビデオプレーヤー:スプリットデコーダーとプレーヤー
最も単純なFFMPEGベースのHelloworldプログラム
================================================= = ==
この記事は、「シンプルなFFMPEG + SDLベースのビデオプレーヤー」の2つの例、FFmpegビデオデコーダーとSDLピクセルデータプレーヤーを補足するものです。これらの2つの部分は、ビデオプレーヤーから分割された2つの例です。 FFmpegビデオデコーダーはビデオデータのYUVデータへのデコードを実装し、SDLピクセルデータプレーヤーはYUVデータの表示を実装します。つまり、元のFFmpeg + SDLビデオプレーヤーは次のように実装されています。
ビデオデータ-> YUV->ディスプレイ
FFmpegビデオデコーダーは以下を実装します:
ビデオデータ-> YUV
SDLピクセルデータプレーヤーは以下を実装します。
YUV->ディスプレイFFmpegビデオデコーダー
ソースコード
[cpp] プレーンビュー コピー- / **
- *最も単純なFFmpegベースのビデオデコーダー
- * SimplestFFmpegDecoder
- *
- *サンダーレイシャオワ
- * root @ xxxxx
- *中国伝媒大学/デジタルTVテクノロジー
- * CommunicationUniversityofChina / DigitalTVTechnology
- * http://blog.csdn.net/leixiaohua1020
- *
- *
- *このプログラムは、ビデオファイルのYUVデータへのデコードを実装します。 libavcodecを使用し、
- * libavformat。これはFFmpegビデオデコードに関する最も簡単なチュートリアルです。
- *この例を学ぶことで、FFmpegのデコードプロセスを理解することができます。
- *このソフトウェアはFFmpegに基づく最も単純なデコーダーです。
- *ビデオをYUVpixeldataにデコードします。
- * Ituseslibavcodecandlibavformat。
- * FFmpegの初心者に適しています。
- *
- * /
- #include
- #define__STDC_CONSTANT_MACROS
- #ifdef_WIN32
- //ウィンドウズ
- 外部「C」
- {{
- #include'libavcodec / avcodec.h '
- #include'libavformat / avformat.h '
- #include'libswscale / swscale.h '
- #include'libavutil / imgutils.h '
- }
- #そうしないと
- // Linux .. ..
- #ifdef__cplusplus
- 外部「C」
- {{
- #endif
- #include
- #include
- #include
- #include
- #ifdef__cplusplus
- }
- #endif
- #endif
- intメイン(intargc、char* argv [])
- {{
- AVFormatContext * pFormatCtx
- inti、videoindex
- AVCodecContext * pCodecCtx
- AVCodec * pCodec
- AVFrame * pFrame、* pFrameYUV
- 署名なしchar* out_buffer
- AVPacket * packet
- inty_size
- intret、got_picture
- 構造体SwsContext * img_convert_ctx
- charfilepath [] ='Titanic.mkv'
- ファイル* fp_yuv = fopen('output.yuv'、'wb +')。
- av_register_all()
- avformat_network_init()
- pFormatCtx = avformat_alloc_context()
- もし(avformat_open_input(&pFormatCtx、filepath、NULL、NULL)!= 0){
- printf('inputstreamを開くことができませんでした。 n')。
- 戻る-1
- }
- もし(avformat_find_stream_info(pFormatCtx、NULL)<0){
- printf('ストリーム情報が見つかりませんでした。 n')。
- 戻る-1
- }
- videoindex = -1
- ために(i = 0inb_streamsi ++)
- もし(pFormatCtx-> streams [i]-> codec-> codec_type == AVMEDIA_TYPE_VIDEO){
- videoindex = i
- ブレーク
- }
- もし(videoindex ==-1){
- printf(「ビデオストリームを見つけられませんでした。 n」)。
- 戻る-1
- }
- pCodecCtx = pFormatCtx-> streams [videoindex]-> codec
- pCodec = avcodec_find_decoder(pCodecCtx-> codec_id)
- もし(pCodec == NULL){
- printf('Codecnotfound。 n')。
- 戻る-1
- }
- もし(avcodec_open2(pCodecCtx、pCodec、NULL)<0){
- printf('コードを開くことができませんでした。 n')。
- 戻る-1
- }
- pFrame = av_frame_alloc()
- pFrameYUV = av_frame_alloc()
- out_buffer =(unsignedchar*)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)
- パケット=(AVPacket *)av_malloc(のサイズ(AVPacket))
- // OutputInfo -----------------------------
- printf('---------------ファイル情報---------------- n')。
- av_dump_format(pFormatCtx、0、ファイルパス、0)
- printf('------------------------------------------------- n ')。
- 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)
- 一方(av_read_frame(pFormatCtx、パケット)> = 0){
- もし(パケット-> stream_index == videoindex){
- ret = avcodec_decode_video2(pCodecCtx、pFrame、&got_picture、packet)
- もし(正しい<0){
- printf('DecodeError。 n')。
- 戻る-1
- }
- もし(got_picture){
- sws_scale(img_convert_ctx、(const署名なしchar*const*)pFrame-> data、pFrame-> linesize、0、pCodecCtx-> height、
- pFrameYUV-> data、pFrameYUV-> linesize)
- y_size = pCodecCtx-> width * pCodecCtx-> height
- fwrite(pFrameYUV-> data [0]、1、y_size、fp_yuv)//そして
- fwrite(pFrameYUV-> data [1]、1、y_size / 4、fp_yuv)// U
- fwrite(pFrameYUV-> data [2]、1、y_size / 4、fp_yuv)// V
- printf('Succeedtodecode1frame! n')。
- }
- }
- av_free_packet(パケット)
- }
- // flushdecoder
- // FIX:FlushFramesremainedinCodec
- 一方(1){
- ret = avcodec_decode_video2(pCodecCtx、pFrame、&got_picture、packet)
- もし(正しい<0)
- ブレーク
- もし(!got_picture)
- ブレーク
- sws_scale(img_convert_ctx、(const署名なしchar*const*)pFrame-> data、pFrame-> linesize、0、pCodecCtx-> height、
- pFrameYUV-> data、pFrameYUV-> linesize)
- inty_size = pCodecCtx-> width * pCodecCtx-> height
- fwrite(pFrameYUV-> data [0]、1、y_size、fp_yuv)//そして
- fwrite(pFrameYUV-> data [1]、1、y_size / 4、fp_yuv)// U
- fwrite(pFrameYUV-> data [2]、1、y_size / 4、fp_yuv)// V
- printf('FlushDecoder:Succeedtodecode1frame! n')。
- }
- sws_freeContext(img_convert_ctx)
- fclose(fp_yuv)
- av_frame_free(&pFrameYUV)
- av_frame_free(&pFrame)
- avcodec_close(pCodecCtx)
- avformat_close_input(&pFormatCtx)
- 戻る0
- }
運転結果
プログラムの実行後、次のビデオファイルがデコードされます。デコードされたYUV420Pデータはファイルとして保存されます。 YUVプレーヤーを使用して幅と高さを設定した後、YUVコンテンツを表示できます。
SDLピクセルデータプレーヤー
ソースコード
[cpp] プレーンビュー コピー- / **
- * SDL2再生ビデオの最も簡単な例(SDL2再生RGB / YUV)
- * SimplestVideoPlaySDL2(SDL2playRGB / YUV)
- *
- *サンダーレイシャオワ
- * root @ xxxxx
- *中国伝媒大学/デジタルTVテクノロジー
- * CommunicationUniversityofChina / DigitalTVTechnology
- * http://blog.csdn.net/leixiaohua1020
- *
- *このプログラムはSDL2を使用してRGB / YUVビデオピクセルデータを再生します。 SDLは実際には基礎となる図面です
- * API(Direct3D、OpenGL)カプセル化、基礎となるものを呼び出すために直接使用する方が明らかに簡単です
- *火。
- *
- *関数呼び出しの手順は次のとおりです。
- *
- * [初期化]
- * SDL_Init():SDLを初期化します。
- * SDL_CreateWindow():ウィンドウ(Window)を作成します。
- * SDL_CreateRenderer():ウィンドウに基づいてレンダラーを作成します。
- * SDL_CreateTexture():テクスチャを作成します。
- *
- * [ループレンダリングデータ]
- * SDL_UpdateTexture():テクスチャデータを設定します。
- * SDL_RenderCopy():テクスチャがレンダラーにコピーされます。
- * SDL_RenderPresent():表示します。
- *
- *このソフトウェアはSDL2を使用してRGB / YUVrawvideodataを再生します。
- * SDLisawrapperoflow-levelAPI(Direct3D、OpenGL)。
- *これらの低レベルAPIを直接呼び出すよりもはるかに簡単なSDLismを使用してください。
- *
- *プロセスは次のとおりです。
- *
- *[初期化]
- * SDL_Init():InitSDL。
- * SDL_CreateWindow():CreateaWindow。
- * SDL_CreateRenderer():CreateaRender。
- * SDL_CreateTexture():CreateaTexture。
- *
- * [LooptoRenderdata]
- * SDL_UpdateTexture():SetTextureのデータ。
- * SDL_RenderCopy():CopyTexturetoRender。
- * SDL_RenderPresent():表示。
- * /
- #include
- 外部「C」
- {{
- #include'sdl / SDL.h '
- }
- constintbpp = 12
- intscreen_w = 500、screen_h = 500
- constintpixel_w = 320、pixel_h = 180
- 署名なしcharbuffer [pixel_w * pixel_h * bpp / 8]
- // RefreshEvent
- #defineREFRESH_EVENT(SDL_USEREVENT + 1)
- #defineBREAK_EVENT(SDL_USEREVENT + 2)
- intthread_exit = 0
- intrefresh_video(ボイド*不透明){
- thread_exit = 0
- 一方(!thread_exit){
- SDL_Eventevent
- event.type = REFRESH_EVENT
- SDL_PushEvent(&event)
- SDL_Delay(40)
- }
- thread_exit = 0
- //ブレーク
- SDL_Eventevent
- event.type = BREAK_EVENT
- SDL_PushEvent(&event)
- 戻る0
- }
- intメイン(intargc、char* argv [])
- {{
- もし(SDL_Init(SDL_INIT_VIDEO)){
- printf('SDLを初期化できませんでした-%s n'、SDL_GetError())
- 戻る-1
- }
- SDL_Window * screen
- //SDL2.0複数のウィンドウのサポート
- screen = SDL_CreateWindow(「SimplestVideoPlaySDL2」、SDL_WINDOWPOS_UNDEFINED、SDL_WINDOWPOS_UNDEFINED、
- screen_w、screen_h、SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE)
- もし(!画面){
- printf('SDL:couldnotcreatewindow-exiting:%s n'、SDL_GetError())
- 戻る-1
- }
- SDL_Renderer * sdlRenderer = SDL_CreateRenderer(screen、-1,0)
- Uint32pixformat = 0
- // IYUV:Y + U + V(3プレーン)
- // YV12:Y + V + U(3プレーン)
- pixformat = SDL_PIXELFORMAT_IYUV
- SDL_Texture * sdlTexture = SDL_CreateTexture(sdlRenderer、pixformat、SDL_TEXTUREACCESS_STREAMING、pixel_w、pixel_h)
- ファイル* fp = NULL
- fp = fopen('test_yuv420p_320x180.yuv'、'rb +')。
- もし(fp == NULL){
- printf('cannotopenthisfile n')。
- 戻る-1
- }
- SDL_RectsdlRect
- SDL_Thread * refresh_thread = SDL_CreateThread(refresh_video、NULL、NULL)
- SDL_Eventevent
- 一方(1){
- //待つ
- SDL_WaitEvent(&event)
- もし(event.type == REFRESH_EVENT){
- もし(fread(buffer、1、pixel_w * pixel_h * bpp / 8、fp)!= pixel_w * pixel_h * bpp / 8){
- //ループ
- fseek(fp、0、SEEK_SET)
- fread(buffer、1、pixel_w * pixel_h * bpp / 8、fp)
- }
- SDL_UpdateTexture(sdlTexture、NULL、buffer、pixel_w)
- //修正:Ifwindowisresize
- sdlRect.x = 0
- sdlRect.y = 0
- sdlRect.w = screen_w
- sdlRect.h = screen_h
- SDL_RenderClear(sdlRenderer)
- SDL_RenderCopy(sdlRenderer、sdlTexture、NULL、&sdlRect)
- SDL_RenderPresent(sdlRenderer)
- }そうしないともし(event.type == SDL_WINDOWEVENT){
- // IfResize
- SDL_GetWindowSize(screen、&screen_w、&screen_h)
- }そうしないともし(event.type == SDL_QUIT){
- thread_exit = 1
- }そうしないともし(event.type == BREAK_EVENT){
- ブレーク
- }
- }
- SDL_Quit()
- 戻る0
- }
運転結果
プログラムの実行後、以下に示すように、プログラムフォルダの下にあるYUV420Pファイルが読み取られます。次に、YUVコンテンツがポップアップウィンドウに描画されます。
ダウンロード
最もシンプルなFFmpegプレーヤー
プロジェクトのホームページ
ソースサイト: https://sourceforge.net/projects/simplestffmpegplayer/Github: https://github.com/leixiaohua1020/simplest_ffmpeg_player
オープンソース中国: http://git.oschina.net/leixiaohua1020/simplest_ffmpeg_player
CSDNダウンロードアドレス: http://download.csdn.net/detail/leixiaohua1020/8924321
これはFFmpegビデオデコードに関する最も簡単なチュートリアルです。
この例を研究することで、FFmpegのデコードプロセスについて学ぶことができます。
プロジェクトは6つのプロジェクトで構成されています。
simplest_ffmpeg_player:Standard Edition、FFmpeg学習の始まり。
simplest_ffmpeg_player_su:SU(SDL Update)バージョン、単純なSDLイベントが追加されました。
Simplest_ffmpeg_decoder:カプセル化フォーマットの処理を含むデコーダー。 libavcodecとlibavformatが使用されます。
Simplest_ffmpeg_decoder_pure:純粋なデコーダー。 libavcodecのみを使用してください(libavformatは使用しません)。
Simplest_video_play_sdl2:SDL2を使用してYUVを再生する例。
Simplest_ffmpeg_helloworld:FFmpegクラスライブラリに関する情報を出力します。