1. 程式人生 > >SDL2播放YUV

SDL2播放YUV

本文記錄SDL播放視訊的技術。在這裡使用的版本是SDL2。實際上SDL本身並不提供視音訊播放的功能,它只是封裝了視音訊播放的底層API。在Windows平臺下,SDL封裝了Direct3D這類的API用於播放視訊;封裝了DirectSound這類的API用於播放音訊。因為SDL的編寫目的就是簡化視音訊播放的開發難度,所以使用SDL播放視訊(YUV/RGB)和音訊(PCM)資料非常的容易。下文記錄一下使用SDL播放視訊資料的技術。

 

SDL簡介


SDL(Simple DirectMedia Layer)是一套開放原始碼的跨平臺多媒體開發庫,使用C語言寫成。SDL提供了數種控制影象、聲音、輸出入的函式,讓開發者只要用相同或是相似的程式碼就可以開發出跨多個平臺(Linux、Windows、Mac OS X等)的應用軟體。目前SDL多用於開發遊戲、模擬器、媒體播放器等多媒體應用領域。用下面這張圖可以很明確地說明SDL的位置。


SDL實際上並不限於視音訊的播放,它將功能分成下列數個子系統(subsystem):

Video(影象):影象控制以及執行緒(thread)和事件管理(event)。
Audio(聲音):聲音控制
Joystick(搖桿):遊戲搖桿控制
CD-ROM(光碟驅動器):光碟媒體控制
Window Management(視窗管理):與視窗程式設計整合
Event(事件驅動):處理事件驅動

 

在Windows下,SDL與DirectX的對應關係如下。

 

SDL

DirectX

SDL_Video、SDL_Image

DirectDraw、Direct3D

SDL_Audio、SDL_Mixer

DirectSound

SDL_Joystick、SDL_Base

DirectInput

SDL_Net

DirectPlay

 

 

SDL播放視訊的流程

SDL播放視訊的技術在此前做的FFmpeg的示例程式中已經多次用到。在這裡重新總結一下流程。
 
1.       初始化

1)         初始化SDL
2)         建立視窗(Window)
3)         基於視窗建立渲染器(Render)
4)         建立紋理(Texture)

2.       迴圈顯示畫面

1)       設定紋理的資料
2)       紋理複製給渲染目標
3)       顯示

 
下面詳細分析一下上文的流程。

1.       初始化

1)         初始化SDL

使用SDL_Init()初始化SDL。該函式可以確定希望啟用的子系統。SDL_Init()函式原型如下:

[cpp]  view plain copy 在CODE上檢視程式碼片 派生到我的程式碼片  
  1. int SDLCALL SDL_Init(Uint32 flags)  


其中,flags可以取下列值:

SDL_INIT_TIMER:定時器
SDL_INIT_AUDIO:音訊
SDL_INIT_VIDEO:視訊
SDL_INIT_JOYSTICK:搖桿
SDL_INIT_HAPTIC:觸控式螢幕
SDL_INIT_GAMECONTROLLER:遊戲控制器
SDL_INIT_EVENTS:事件
SDL_INIT_NOPARACHUTE:不捕獲關鍵訊號(這個沒研究過)
SDL_INIT_EVERYTHING:包含上述所有選項

 

有關SDL_Init()有一點需要注意:初始化的時候儘量做到“夠用就好”,而不要用SDL_INIT_EVERYTHING。因為有些情況下使用SDL_INIT_EVERYTHING會出現一些不可預知的問題。例如,在MFC應用程式中播放純音訊,如果初始化SDL的時候使用SDL_INIT_EVERYTHING,那麼就會出現聽不到聲音的情況。後來發現,去掉了SDL_INIT_VIDEO之後,問題才得以解決。

 
2)         建立視窗(Window)
使用SDL_CreateWindow()建立一個用於視訊播放的視窗。SDL_CreateWindow()的原型如下。

[cpp]  view plain copy 在CODE上檢視程式碼片 派生到我的程式碼片  
  1. SDL_Window * SDLCALL SDL_CreateWindow(const char *title,  
  2.                                                       int x, int y, int w,  
  3.                                                       int h, Uint32 flags);  


引數含義如下。
title  :視窗標題
x       :視窗位置x座標。也可以設定為SDL_WINDOWPOS_CENTERED或SDL_WINDOWPOS_UNDEFINED。
y       :視窗位置y座標。同上。
w      :視窗的寬
h       :視窗的高
flags :支援下列標識。包括了視窗的是否最大化、最小化,能否調整邊界等等屬性。
       ::SDL_WINDOW_FULLSCREEN,    ::SDL_WINDOW_OPENGL,
       ::SDL_WINDOW_HIDDEN,        ::SDL_WINDOW_BORDERLESS,
       ::SDL_WINDOW_RESIZABLE,     ::SDL_WINDOW_MAXIMIZED,
       ::SDL_WINDOW_MINIMIZED,     ::SDL_WINDOW_INPUT_GRABBED,
       ::SDL_WINDOW_ALLOW_HIGHDPI.
 返回建立完成的視窗的ID。如果建立失敗則返回0。
 
 
3)         基於視窗建立渲染器(Render)
使用SDL_CreateRenderer()基於視窗建立渲染器。SDL_CreateRenderer()原型如下。

[cpp]  view plain copy 在CODE上檢視程式碼片 派生到我的程式碼片  
  1. SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window * window,  
  2.                                                int index, Uint32 flags);  


引數含義如下。
window    : 渲染的目標視窗。
index         :打算初始化的渲染裝置的索引。設定“-1”則初始化預設的渲染裝置。
flags          :支援以下值(位於SDL_RendererFlags定義中)

    SDL_RENDERER_SOFTWARE :使用軟體渲染
    SDL_RENDERER_ACCELERATED :使用硬體加速
    SDL_RENDERER_PRESENTVSYNC:和顯示器的重新整理率同步
    SDL_RENDERER_TARGETTEXTURE :不太懂

返回建立完成的渲染器的ID。如果建立失敗則返回NULL。
 
4)         建立紋理(Texture)
使用SDL_CreateTexture()基於渲染器建立一個紋理。SDL_CreateTexture()的原型如下。

[cpp]  view plain copy 在CODE上檢視程式碼片 派生到我的程式碼片  
  1. SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer,  
  2.                                                         Uint32 format,  
  3.                                                         int access, int w,  
  4.                                                         int h);  


引數的含義如下。
renderer:目標渲染器。
format      :紋理的格式。後面會詳述。
access      :可以取以下值(定義位於SDL_TextureAccess中)

    SDL_TEXTUREACCESS_STATIC         :變化極少
    SDL_TEXTUREACCESS_STREAMING        :變化頻繁
    SDL_TEXTUREACCESS_TARGET       :暫時沒有理解

w               :紋理的寬
h                :紋理的高
建立成功則返回紋理的ID,失敗返回0。
 
在紋理的建立過程中,需要指定紋理的格式(即第二個引數)。SDL的中的格式很多,如下所列。
 

[cpp]  view plain copy 在CODE上檢視程式碼片 派生到我的程式碼片  
  1. SDL_PIXELFORMAT_UNKNOWN,  
  2. SDL_PIXELFORMAT_INDEX1LSB =  
  3.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_4321, 0,  
  4.                            1, 0),  
  5. SDL_PIXELFORMAT_INDEX1MSB =  
  6.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_1234, 0,  
  7.                            1, 0),  
  8. SDL_PIXELFORMAT_INDEX4LSB =  
  9.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_4321, 0,  
  10.                            4, 0),  
  11. SDL_PIXELFORMAT_INDEX4MSB =  
  12.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_1234, 0,  
  13.                            4, 0),  
  14. SDL_PIXELFORMAT_INDEX8 =  
  15.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX8, 0, 0, 8, 1),  
  16. SDL_PIXELFORMAT_RGB332 =  
  17.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED8, SDL_PACKEDORDER_XRGB,  
  18.                            SDL_PACKEDLAYOUT_332, 8, 1),  
  19. SDL_PIXELFORMAT_RGB444 =  
  20.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB,  
  21.                            SDL_PACKEDLAYOUT_4444, 12, 2),  
  22. SDL_PIXELFORMAT_RGB555 =  
  23.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB,  
  24.                            SDL_PACKEDLAYOUT_1555, 15, 2),  
  25. SDL_PIXELFORMAT_BGR555 =  
  26.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR,  
  27.                            SDL_PACKEDLAYOUT_1555, 15, 2),  
  28. SDL_PIXELFORMAT_ARGB4444 =  
  29.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ARGB,  
  30.                            SDL_PACKEDLAYOUT_4444, 16, 2),  
  31. SDL_PIXELFORMAT_RGBA4444 =  
  32.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_RGBA,  
  33.                            SDL_PACKEDLAYOUT_4444, 16, 2),  
  34. SDL_PIXELFORMAT_ABGR4444 =  
  35.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ABGR,  
  36.                            SDL_PACKEDLAYOUT_4444, 16, 2),  
  37. SDL_PIXELFORMAT_BGRA4444 =  
  38.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_BGRA,  
  39.                            SDL_PACKEDLAYOUT_4444, 16, 2),  
  40. SDL_PIXELFORMAT_ARGB1555 =  
  41.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ARGB,  
  42.                            SDL_PACKEDLAYOUT_1555, 16, 2),  
  43. SDL_PIXELFORMAT_RGBA5551 =  
  44.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_RGBA,  
  45.                            SDL_PACKEDLAYOUT_5551, 16, 2),  
  46. SDL_PIXELFORMAT_ABGR1555 =  
  47.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ABGR,  
  48.                            SDL_PACKEDLAYOUT_1555, 16, 2),  
  49. SDL_PIXELFORMAT_BGRA5551 =  
  50.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_BGRA,  
  51.                            SDL_PACKEDLAYOUT_5551, 16, 2),  
  52. SDL_PIXELFORMAT_RGB565 =  
  53.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB,  
  54.                            SDL_PACKEDLAYOUT_565, 16, 2),  
  55. SDL_PIXELFORMAT_BGR565 =  
  56.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR,  
  57.                            SDL_PACKEDLAYOUT_565, 16, 2),  
  58. SDL_PIXELFORMAT_RGB24 =  
  59.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8, SDL_ARRAYORDER_RGB, 0,  
  60.                            24, 3),  
  61. SDL_PIXELFORMAT_BGR24 =  
  62.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8, SDL_ARRAYORDER_BGR, 0,  
  63.                            24, 3),  
  64. SDL_PIXELFORMAT_RGB888 =  
  65.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XRGB,  
  66.                            SDL_PACKEDLAYOUT_8888, 24, 4),  
  67. SDL_PIXELFORMAT_RGBX8888 =  
  68.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_RGBX,  
  69.                            SDL_PACKEDLAYOUT_8888, 24, 4),  
  70. SDL_PIXELFORMAT_BGR888 =  
  71.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XBGR,  
  72.                            SDL_PACKEDLAYOUT_8888, 24, 4),  
  73. SDL_PIXELFORMAT_BGRX8888 =  
  74.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRX,  
  75.                            SDL_PACKEDLAYOUT_8888, 24, 4),  
  76. SDL_PIXELFORMAT_ARGB8888 =  
  77.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB,  
  78.                            SDL_PACKEDLAYOUT_8888, 32, 4),  
  79. SDL_PIXELFORMAT_RGBA8888 =  
  80.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_RGBA,  
  81.                            SDL_PACKEDLAYOUT_8888, 32, 4),  
  82. SDL_PIXELFORMAT_ABGR8888 =  
  83.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ABGR,  
  84.                            SDL_PACKEDLAYOUT_8888, 32, 4),  
  85. SDL_PIXELFORMAT_BGRA8888 =  
  86.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRA,  
  87.                            SDL_PACKEDLAYOUT_8888, 32, 4),  
  88. SDL_PIXELFORMAT_ARGB2101010 =  
  89.     SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB,  
  90.                            SDL_PACKEDLAYOUT_2101010, 32, 4),  
  91.   
  92. SDL_PIXELFORMAT_YV12 =      /**< Planar mode: Y + V + U  (3 planes) */  
  93.     SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2'),  
  94. SDL_PIXELFORMAT_IYUV =      /**< Planar mode: Y + U + V  (3 planes) */  
  95. 相關推薦

    8.基於SDL2播放YUV視訊

    參考資料: 1.雷博部落格 一.簡介 二、流程及函式 1)視訊播放流程 2)常用函式 3)程式碼 4)工程 前面講video解碼為YUV原始資料,接下來則需

    SDL2播放YUV

    本文記錄SDL播放視訊的技術。在這裡使用的版本是SDL2。實際上SDL本身並不提供視音訊播放的功能,它只是封裝了視音訊播放的底層API。在Windows平臺下,SDL封裝了Direct3D這類的API用於播放視訊;封裝了DirectSound這類的API用於播放音訊。因為SDL的編寫目的

    最簡單的視音頻播放演示樣例7:SDL2播放RGB/YUV

    pro big 更新 沒有 opaque support 解決 控制 mem =====================================================最簡單的視音頻播放演示樣例系列文章列表:最簡單的視音頻播放演示樣例1:總述最簡單的視音

    最簡單的視音訊播放示例7:SDL2播放RGB/YUV

    =====================================================最簡單的視音訊播放示例系列文章列表:=====================================================本文記錄SDL播放視訊的技術

    10.基於FFMPEG+SDL2播放video---音視訊同步(參考音訊時鐘)

    繼續FFMPEG學習之路。。。 參考資料: An ffmpeg and SDL Tutorial 文章目錄 1 綜述 2 音視訊同步 3 DTS 和 PTS 4 音訊時鐘 5 視訊PTS 6 同步 7 不

    9.基於FFMPEG+SDL2播放視訊(解碼執行緒和播放執行緒分開)

    參考資料: 1.雷博部落格 2. An ffmpeg and SDL Tutorial 繼續FFMPEG學習之路。。。 文章目錄 1 綜述 2 程式碼1(基礎程式碼) 3 程式碼2(播放執行緒和解碼執行緒分開) 3.1 幾個結構體

    6.基於FFMPEG+SDL2播放音訊

    參考資料: 1.雷博部落格 2. An ffmpeg and SDL Tutorial 前面瞭解了FFMPEG解碼MP3檔案為PCM,以及將PCM通過SDL2進行播放,下面就是將這兩者進行結合,使之能夠邊解碼邊播放。。。。 一、綜述 二、程式碼

    5.基於SDL2播放PCM音訊

    接上一篇<基於FFMPEG將音訊解碼為PCM>,接下來就是需要將PCM音訊進行播放,查閱資料是通過SDL進行音視訊的播放,因此這裡記錄一下SDL相關的筆記。。。 一.簡介 摘抄自百度百科: SDL(Simple DirectMedia Layer)是一套開

    最簡單的視音訊播放示例9:SDL2播放PCM

    最簡單的視音訊播放示例系列文章列表: ===================================================== 本文記錄SDL播放音訊的技術。在這裡使用的版本是SDL2。實際上SDL本身並不提供視音訊播放的功能,它只

    VLC播放YUV檔案

    副檔名需為.yuv,每秒5幀播放畫素格式為UYVY解析度為704x576的yuv檔案的步驟如下:  1、執行VLC  2、“媒體”-》“高階開啟檔案...”選單項調出“開啟媒體”對話方塊  3、新增檔案 4、選中“顯示更多選項”,在“編輯選項”中輸入:demux=

    android ffmpeg+OpenGL播放yuv+openSL 快放 慢放 視訊播放

    這裡是完整的音視訊播放器,功能如下(這裡有iOS版的): 視訊是通過opengl 播放yuv資料,音訊是opensl播放。 app執行流程如下圖: 紅色虛線內的是一個執行緒的執行,總共涉及到四個執行緒。 java層幾乎沒有播放器的內容,ffmpe

    使用SDL2播放音訊檔案出現斷斷續續的問題

    自己在雷神的部落格上找到了播放音訊檔案的示例程式。程式順利跑通。 自後自己在window進行編譯,編譯通過。可是在進行播放的時候,聲音老是斷斷續續地播放。我嘗試了好多次,實在是不知道原因。仔細翻閱了雷神相關的SDL部落格。才發現, 原來時SDL版本的問題。 我看的示例程式是

    android ffmpeg+OpenGL播放yuv+openSL 快放 慢放 視訊播放

    這裡是完整的音視訊播放器,功能如下(這裡有iOS版的): 視訊是通過opengl 播放yuv資料,音訊是opensl播放。 app執行流程如下圖: 紅色虛線內的是一個執行緒的執行,總共涉及到四個執行緒。 java層幾乎沒有播放器的內容,ffmpeg,opengl,opensl都

    SDL2播放FFmpeg解壓的視頻

    open dex n) end pac ios 文件中 h.264 second SDL2簡化了播放過程,這裏引入播放視頻。 1. 以我的《FFmpeg入門測試》為工程。 2. 到http://www.libsdl.org/index.php下載SDL2-devel

    播放yuv檔案遇到的問題及解決方法

        其實這也算是一個簡單的問題,可是自己老是忘記。播放yuv檔案,需要注意兩個地方的引數。 幀率不用管,一般是25或者30幀左右。其中注意yuv型別和解析度。自己犯錯的地方是就是這兩個引數。 一般來說,從攝像頭獲取的型別是Iyuv(I420),這個地方預設的是RGB3

    SDL2---編譯SDL庫、測試播放簡單畫素資料(YUV、RGB等)

    本篇博文整理自雷神(雷霄驊https://blog.csdn.net/leixiaohua1020/article/list/3)多篇博文,多謝分享,在此致敬! SDL簡介: SDL庫的作用說白了就是封裝了複雜的視音訊底層操作,簡化了視音訊處理的難度。 以下轉自WiKi:

    mac:使用VLC播放純視訊YUV檔案(命令列)

    有時候,我們需要播放一些純視訊檔案,判斷YUV資料是否可用。舉個例子,我們使用命令列播放/Users/lz目錄下的test_yuv420p_320x180.yuv檔案,命令如下: /Applications/VLC.app/Contents/MacOS/VLC --demux rawvide

    FFmpeg 4.0.2 + SDL2-2.0.8 實現H264解碼後播放

    一、初級版 功能:實現了簡易視訊播放器的功能,能解碼H264後播放 工具:FFmpeg 4.0.2 + SDL2-2.0.8 C++程式碼: /************************************* 功能:H264解碼為YUV序列,通過SDL播放 FFmpeg:

    FFmpeg把MP4檔案解碼為YUV,然後通過SDL播放

    #include <iostream> extern "C" { #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libswscale/swsca

    windows下使用FFmpeg生成YUV視訊檔案並播放(通過命令的方式)

    一、YUV的定義   YUV是一種顏色編碼方法。它跟我們常見的RGB格式區分開來,常使用在各個視訊處理元件中。其中"Y"代表明亮度,"U"和"V"代表其色度。視訊播放器把市面上流行的MP4等格式的視訊檔案解碼出來,得到的一般會是YUV格式的資料,然後得進行轉碼(比如通過op