SDLとのビデオプレーヤーに基づいて(3)-SDL FFmpegのビデオディスプレイ

SDLとのビデオプレーヤーに基づいて(3)-SDL FFmpegのビデオディスプレイ

SDLについて

  • SDL(Simple DirectMedia Layerを)は、C言語で書かれたクロスプラットフォームのマルチメディア開発ライブラリオープンソース、です。SDLは、同一または類似のコードが複数のプラットフォーム(Linuxでは、Windows版、Mac OS Xなど)アプリケーション間で開発することができますよう、開発者がいる限り使用することができるように、いくつかの制御画像、サウンド、入力および出力機能を提供します。SDLは、現在、マルチメディア・アプリケーション開発のゲーム、シミュレータ、メディアプレーヤーを使用します。
  • 出力に等大幅に制御画像を構成するために必要なコードを簡素化し、基礎となるオペレーティング複合ビデオ及びオーディオ、ビデオおよびオーディオ処理困難簡略化、音を、カプセル化効果
  • SDLは、そのクロスプラットフォームの特性を達成するためには、DirectXと他の低レベルのAPIと、完成したハードウェアの相互作用、同じ機能の中にパッケージ構造的に異なるオペレーティング・システム・ライブラリーと呼ばれています。

ここに画像を挿入説明

QTベースのビルド環境FFmpegの+ SDL

ビルド前にFFmpegのオペレーティング環境が経過し、プレゼンテーションは、もはやありません。

  1. SDL取得

    ます。http://www.libsdl.org/アドレスを取得し、SDL

    ここに画像を挿入説明

    自分のデバイスに応じて適切なバージョンを選択

  2. プロジェクトで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関数やデータ構造を導入中とマルチスレッド

機能
  1. SDL_Init():初期化SDLシステム
  2. SDL_CreateWindow():ウィンドウを作成SDL_Window
  3. SDL_CreateRenderer():レンダラーSDL_Rendererを作成します。
  4. SDL_CreateTextureは():テクスチャSDL_Textureを作成します
  5. SDL_UpdateTexture():テクスチャデータを設定します。
  6. SDL_RenderCopy():将纹理的数据拷贝给渲染器
  7. SDL_RenderPresent():显示
  8. SDL_Delay():工具函数,用于延时。
  9. SDL_Quit():退出SDL系统
数据结构

ここに画像を挿入説明

  1. SDL_Window 代表了一个“窗口”
  2. SDL_Renderer 代表了一个“渲染器”
  3. SDL_Texture 代表了一个“纹理”
  4. 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は、このキューからの再生のために読み込まれます。

公開された24元の記事 ウォンの賞賛5 ビュー3930

おすすめ

転載: blog.csdn.net/qq_41345281/article/details/104237900
おすすめ