SDLとのビデオプレーヤーに基づいて(3)-SDL FFmpegのビデオディスプレイ
SDLについて
- SDL(Simple DirectMedia Layerを)は、C言語で書かれたクロスプラットフォームのマルチメディア開発ライブラリオープンソース、です。SDLは、同一または類似のコードが複数のプラットフォーム(Linuxでは、Windows版、Mac OS Xなど)アプリケーション間で開発することができますよう、開発者がいる限り使用することができるように、いくつかの制御画像、サウンド、入力および出力機能を提供します。SDLは、現在、マルチメディア・アプリケーション開発のゲーム、シミュレータ、メディアプレーヤーを使用します。
- 出力に等大幅に制御画像を構成するために必要なコードを簡素化し、基礎となるオペレーティング複合ビデオ及びオーディオ、ビデオおよびオーディオ処理困難簡略化、音を、カプセル化効果
- SDLは、そのクロスプラットフォームの特性を達成するためには、DirectXと他の低レベルのAPIと、完成したハードウェアの相互作用、同じ機能の中にパッケージ構造的に異なるオペレーティング・システム・ライブラリーと呼ばれています。
QTベースのビルド環境FFmpegの+ SDL
ビルド前にFFmpegのオペレーティング環境が経過し、プレゼンテーションは、もはやありません。
-
SDL取得
ます。http://www.libsdl.org/アドレスを取得し、SDL
自分のデバイスに応じて適切なバージョンを選択
-
プロジェクトでSDLの参照
プロジェクトの作成プロセスは、プロジェクトが後に必要な、Devのアーカイブ解凍を実行した場合にのみ、動的ライブラリの.dllファイル圧縮パッケージのDevダイナミックライブラリとアーカイブをダウンロードしただけで解凍し、唯一のSDLの導入の一部を説明し、ここで説明されていません私たちは、私たちのプロジェクトディレクトリに直接コピーし、含めるとlibフォルダのいずれかが必要です。
それは(前のffmpegの導入を含む).PROファイルに導入され
INCLUDEPATH += $$PWD/lib/ffmpeg/include\ $$PWD/lib/SDL2/include LIBS += $$PWD/lib/ffmpeg/lib/avcodec.lib\ $$PWD/lib/ffmpeg/lib/avdevice.lib\ $$PWD/lib/ffmpeg/lib/avfilter.lib\ $$PWD/lib/ffmpeg/lib/avformat.lib\ $$PWD/lib/ffmpeg/lib/avutil.lib\ $$PWD/lib/ffmpeg/lib/postproc.lib\ $$PWD/lib/ffmpeg/lib/swresample.lib\ $$PWD/lib/ffmpeg/lib/swscale.lib\ $$PWD/lib/SDL2/lib/SDL2.lib
我々はC ++プロジェクトをビルドすると、C ++のコンパイル時にコンパイラが使用され、そしてCは、FFMPEGライブラリですので、にextern「C」を追加することが必要。
extern "C" { #include <libavcodec\avcodec.h> #include <libavformat\avformat.h> #include <libswscale\swscale.h> #include <libswresample\swresample.h> #include "SDL.h" }
表示時間SDLとSDL関数やデータ構造を導入中とマルチスレッド
機能
- SDL_Init():初期化SDLシステム
- SDL_CreateWindow():ウィンドウを作成SDL_Window
- SDL_CreateRenderer():レンダラーSDL_Rendererを作成します。
- SDL_CreateTextureは():テクスチャSDL_Textureを作成します
- SDL_UpdateTexture():テクスチャデータを設定します。
- SDL_RenderCopy():将纹理的数据拷贝给渲染器
- SDL_RenderPresent():显示
- SDL_Delay():工具函数,用于延时。
- SDL_Quit():退出SDL系统
数据结构
- SDL_Window 代表了一个“窗口”
- SDL_Renderer 代表了一个“渲染器”
- SDL_Texture 代表了一个“纹理”
- SDL_Rect 一个简单的矩形结构
SDL事件
要想了解 SDL 的事件处理,我们必须要知道的一个原理是,SDL将所有事件都存放在一个队列中。所有对事件的操作,其实就是对队列的操作。
- SDL_PollEvent: 将队列头中的事件抛出来。
- SDL_WaitEvent: 当队列中有事件时,抛出事件。否则处于阻塞状态,释放 CPU。
- SDL_WaitEventTimeout: 与SDL_WaitEvent的区别时,当到达超时时间后,退出阻塞状态。
- SDL_PeekEvent: 从队列中取出事件,但该事件不从队列中删除。
- SDL_PushEvent: 向队列中插入事件。
SDL只提供了这样几个简单的API,下面们来介绍几个常见的事件:
- SDL_WindowEvent : Window窗口相关的事件。
- SDL_KeyboardEvent : 键盘相关的事件。
- SDL_MouseMotionEvent : 鼠标移动相关的事件。
- SDL_QuitEvent : 退出事件。
- SDL_UserEvent : 用户自定义事件。
SDL多线程
为什么引入多线程的概念呢,我们知道如果将耗时操作放到主线程中必将会导致界面的卡顿,所以我们在实际开发时需要将一些耗时操作放到子线程中进行,避免界面假死的同时充分发挥硬件的性能。
主要需要了解的函数如下:
- SDL线程创建:SDL_CreateThread
- SDL线程等待:SDL_WaitThead
- SDL互斥锁:SDL_CreateMutex / SDL_DestroyMutex
- SDL锁定互斥:SDL_LockMutex / SDL_UnlockMutex
- SDLの条件変数(セマフォ):SDL_CreateCond / SDL_DestoryCond
- SDLの条件変数(セマフォ)通知/待機:SDL_CondWait / SDL_CondSingal
SDLビデオ・ディスプレイ・ロジック
SDLビデオディスプレイ完全なコード
ここでコードを参照して以下トールコードをビデオ・ディスプレイに直接読み込ま純粋YUV形式のファイルであり、デカプセル化及びビデオ復号化操作をすることなく、これらの操作物を詳細に説明してきました。
#include <stdio.h>
extern "C"
{
#include "sdl/SDL.h"
};
const int bpp=12;
int screen_w=500,screen_h=500;
const int pixel_w=320,pixel_h=180;
unsigned char buffer[pixel_w*pixel_h*bpp/8];
//Refresh Event
#define REFRESH_EVENT (SDL_USEREVENT + 1)
//Break
#define BREAK_EVENT (SDL_USEREVENT + 2)
int thread_exit=0;
int refresh_video(void *opaque){
thread_exit=0;
while (thread_exit==0) {
SDL_Event event;
event.type = REFRESH_EVENT;
SDL_PushEvent(&event);
SDL_Delay(40);
}
thread_exit=0;
//Break
SDL_Event event;
event.type = BREAK_EVENT;
SDL_PushEvent(&event);
return 0;
}
int main(int argc, char* argv[])
{
if(SDL_Init(SDL_INIT_VIDEO)) {
printf( "Could not initialize SDL - %s\n", SDL_GetError());
return -1;
}
SDL_Window *screen;
//SDL 2.0 Support for multiple windows
screen = SDL_CreateWindow("Simplest Video Play SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
screen_w, screen_h,SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
if(!screen) {
printf("SDL: could not create window - exiting:%s\n",SDL_GetError());
return -1;
}
SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0);
Uint32 pixformat=0;
//IYUV: Y + U + V (3 planes)
//YV12: Y + V + U (3 planes)
pixformat= SDL_PIXELFORMAT_IYUV;
SDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer,pixformat, SDL_TEXTUREACCESS_STREAMING,pixel_w,pixel_h);
FILE *fp=NULL;
fp=fopen("test_yuv420p_320x180.yuv","rb+");
if(fp==NULL){
printf("cannot open this file\n");
return -1;
}
SDL_Rect sdlRect;
SDL_Thread *refresh_thread = SDL_CreateThread(refresh_video,NULL,NULL);
SDL_Event event;
while(1){
//Wait
SDL_WaitEvent(&event);
if(event.type==REFRESH_EVENT){
if (fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp) != pixel_w*pixel_h*bpp/8){
// Loop
fseek(fp, 0, SEEK_SET);
fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp);
}
SDL_UpdateTexture( sdlTexture, NULL, buffer, pixel_w);
//FIX: If window is resize
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 );
}else if(event.type==SDL_WINDOWEVENT){
//If Resize
SDL_GetWindowSize(screen,&screen_w,&screen_h);
}else if(event.type==SDL_QUIT){
thread_exit=1;
}else if(event.type==BREAK_EVENT){
break;
}
}
SDL_Quit();
return 0;
}
概要:前回の記事では、非カプセル化する方法を説明し、RGBやYUVフォーマットとしての暗号FFmpegは、によってビデオカプセル化フォーマットのための操作をデコード、この記事では、YUVフォーマットを再生するには、ビデオファイルの簡単な実装を説明し、どのように彼らはビデオが、そのような.AVI形式としてそれをファイル再生する機能を実現するために、直列に接続されるのですか?シンプルな実装がキューに格納された復号化されたビデオピクセルデータを話して後に得られる、SDLは、このキューからの再生のために読み込まれます。