乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

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

       gljin_cn 2016-09-30

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

       

      SDL簡介


      SDL(Simple DirectMedia Layer)是一套開放源代碼的跨平臺多媒體開發(fā)庫,使用C語言寫成。SDL提供了數(shù)種控制圖像、聲音、輸出入的函數(shù),讓開發(fā)者只要用相同或是相似的代碼就可以開發(fā)出跨多個平臺(Linux、Windows、Mac OS X等)的應(yīng)用軟件。目前SDL多用于開發(fā)游戲、模擬器、媒體播放器等多媒體應(yīng)用領(lǐng)域。用下面這張圖可以很明確地說明SDL的位置。


      SDL實際上并不限于視音頻的播放,它將功能分成下列數(shù)個子系統(tǒng)(subsystem):

      Video(圖像):圖像控制以及線程(thread)和事件管理(event)。
      Audio(聲音):聲音控制
      Joystick(搖桿):游戲搖桿控制
      CD-ROM(光盤驅(qū)動器):光盤媒體控制
      Window Management(視窗管理):與視窗程序設(shè)計集成
      Event(事件驅(qū)動):處理事件驅(qū)動

       

      在Windows下,SDL與DirectX的對應(yīng)關(guān)系如下。

       

      SDL

      DirectX

      SDL_Video、SDL_Image

      DirectDraw、Direct3D

      SDL_Audio、SDL_Mixer

      DirectSound

      SDL_Joystick、SDL_Base

      DirectInput

      SDL_Net

      DirectPlay

       

       

      SDL播放視頻的流程

      SDL播放視頻的技術(shù)在此前做的FFmpeg的示例程序中已經(jīng)多次用到。在這里重新總結(jié)一下流程。
       
      1.       初始化

      1)         初始化SDL
      2)         創(chuàng)建窗口(Window)
      3)         基于窗口創(chuàng)建渲染器(Render)
      4)         創(chuàng)建紋理(Texture)

      2.       循環(huán)顯示畫面

      1)       設(shè)置紋理的數(shù)據(jù)
      2)       紋理復(fù)制給渲染目標(biāo)
      3)       顯示

       
      下面詳細(xì)分析一下上文的流程。

      1.       初始化

      1)         初始化SDL

      使用SDL_Init()初始化SDL。該函數(shù)可以確定希望激活的子系統(tǒng)。SDL_Init()函數(shù)原型如下:

      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:不捕獲關(guān)鍵信號(這個沒研究過)
      SDL_INIT_EVERYTHING:包含上述所有選項

       

      有關(guān)SDL_Init()有一點需要注意:初始化的時候盡量做到“夠用就好”,而不要用SDL_INIT_EVERYTHING。因為有些情況下使用SDL_INIT_EVERYTHING會出現(xiàn)一些不可預(yù)知的問題。例如,在MFC應(yīng)用程序中播放純音頻,如果初始化SDL的時候使用SDL_INIT_EVERYTHING,那么就會出現(xiàn)聽不到聲音的情況。后來發(fā)現(xiàn),去掉了SDL_INIT_VIDEO之后,問題才得以解決。

       
      2)         創(chuàng)建窗口(Window)
      使用SDL_CreateWindow()創(chuàng)建一個用于視頻播放的窗口。SDL_CreateWindow()的原型如下。

      1. SDL_Window * SDLCALL SDL_CreateWindow(const char *title,  
      2.                                                       int x, int y, int w,  
      3.                                                       int h, Uint32 flags);  


      參數(shù)含義如下。
      title  :窗口標(biāo)題
      x       :窗口位置x坐標(biāo)。也可以設(shè)置為SDL_WINDOWPOS_CENTERED或SDL_WINDOWPOS_UNDEFINED。
      y       :窗口位置y坐標(biāo)。同上。
      w      :窗口的寬
      h       :窗口的高
      flags :支持下列標(biāo)識。包括了窗口的是否最大化、最小化,能否調(diào)整邊界等等屬性。
             ::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.
       返回創(chuàng)建完成的窗口的ID。如果創(chuàng)建失敗則返回0。
       
       
      3)         基于窗口創(chuàng)建渲染器(Render)
      使用SDL_CreateRenderer()基于窗口創(chuàng)建渲染器。SDL_CreateRenderer()原型如下。

      1. SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window * window,  
      2.                                                int index, Uint32 flags);  


      參數(shù)含義如下。
      window    : 渲染的目標(biāo)窗口。
      index         :打算初始化的渲染設(shè)備的索引。設(shè)置“-1”則初始化默認(rèn)的渲染設(shè)備。
      flags          :支持以下值(位于SDL_RendererFlags定義中)

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

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

      1. SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer,  
      2.                                                         Uint32 format,  
      3.                                                         int access, int w,  
      4.                                                         int h);  


      參數(shù)的含義如下。
      renderer:目標(biāo)渲染器。
      format      :紋理的格式。后面會詳述。
      access      :可以取以下值(定義位于SDL_TextureAccess中)

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

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

      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.     SDL_DEFINE_PIXELFOURCC('I', 'Y', 'U', 'V'),  
      96. SDL_PIXELFORMAT_YUY2 =      /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */  
      97.     SDL_DEFINE_PIXELFOURCC('Y', 'U', 'Y', '2'),  
      98. SDL_PIXELFORMAT_UYVY =      /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */  
      99.     SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y'),  
      100. SDL_PIXELFORMAT_YVYU =      /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */  
      101.     SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U')  


      這一看確實給人一種“眼花繚亂”的感覺。簡單分析一下其中的定義吧。例如ARGB8888的定義如下。

      1. SDL_PIXELFORMAT_ARGB8888 =  
      2.         SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB,  
      3.                                SDL_PACKEDLAYOUT_8888, 32, 4),  


      其中用了一個宏SDL_DEFINE_PIXELFORMAT用于將幾種屬性合并到一個格式中。下面我們看看一個格式都包含哪些屬性:
      SDL_PIXELTYPE_PACKED32:代表了像素分量的存儲方式。PACKED代表了像素的幾個分量是一起存儲的,內(nèi)存中存儲方式如下:R1|G1|B1,R2|G2|B2…;ARRAY則代表了像素的幾個分量是分開存儲的,內(nèi)存中存儲方式如下:R1|R2|R3…,G1|G2|G3…,B1|B2|B3…
      SDL_PACKEDORDER_ARGB:代表了PACKED存儲方式下像素分量的順序。注意,這里所說的順序涉及到了一個“大端”和“小端”的問題。這個問題在《最簡單的視音頻播放示例2:GDI播放YUV, RGB》中已經(jīng)敘述,不再重復(fù)記錄。對于Windows這樣的“小端”系統(tǒng),“ARGB”格式在內(nèi)存中的存儲順序是B|G|R|A。
      SDL_PACKEDLAYOUT_8888:說明了每個分量占據(jù)的比特數(shù)。例如ARGB格式每個分量分別占據(jù)了8bit。
      32:每個像素占用的比特數(shù)。例如ARGB格式占用了32bit(每個分量占據(jù)8bit)。
      4:每個像素占用的字節(jié)數(shù)。例如ARGB格式占用了4Byte(每個分量占據(jù)1Byte)。
       

      2.       循環(huán)顯示畫面

      1)       設(shè)置紋理的數(shù)據(jù)

      使用SDL_UpdateTexture()設(shè)置紋理的像素數(shù)據(jù)。SDL_UpdateTexture()的原型如下。

      1. int SDLCALL SDL_UpdateTexture(SDL_Texture * texture,  
      2.                                               const SDL_Rect * rect,  
      3.                                               const void *pixels, int pitch);  


      參數(shù)的含義如下。
      texture:目標(biāo)紋理。
      rect:更新像素的矩形區(qū)域。設(shè)置為NULL的時候更新整個區(qū)域。
      pixels:像素數(shù)據(jù)。
      pitch:一行像素數(shù)據(jù)的字節(jié)數(shù)。
      成功的話返回0,失敗的話返回-1。
       
      2)       紋理復(fù)制給渲染目標(biāo)
      使用SDL_RenderCopy()將紋理數(shù)據(jù)復(fù)制給渲染目標(biāo)。在使用SDL_RenderCopy()之前,可以使用SDL_RenderClear()先使用清空渲染目標(biāo)。實際上視頻播放的時候不使用SDL_RenderClear()也是可以的,因為視頻的后一幀會完全覆蓋前一幀。
      SDL_RenderClear()原型如下。

      1. int SDLCALL SDL_RenderClear(SDL_Renderer * renderer);  


      參數(shù)renderer用于指定渲染目標(biāo)。
      SDL_RenderCopy()原型如下。

      1. int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer,  
      2.                                            SDL_Texture * texture,  
      3.                                            const SDL_Rect * srcrect,  
      4.                                            const SDL_Rect * dstrect);  


      參數(shù)的含義如下。
      renderer:渲染目標(biāo)。
      texture:輸入紋理。
      srcrect:選擇輸入紋理的一塊矩形區(qū)域作為輸入。設(shè)置為NULL的時候整個紋理作為輸入。
      dstrect:選擇渲染目標(biāo)的一塊矩形區(qū)域作為輸出。設(shè)置為NULL的時候整個渲染目標(biāo)作為輸出。
      成功的話返回0,失敗的話返回-1。
       
      3)       顯示
      使用SDL_RenderPresent()顯示畫面。SDL_RenderPresent()原型如下。

      1. void SDLCALL SDL_RenderPresent(SDL_Renderer * renderer);  


       參數(shù)renderer用于指定渲染目標(biāo)。

      流程總結(jié)


      在《最簡單的基于FFMPEG+SDL的視頻播放器 ver2(采用SDL2.0)》中總結(jié)過SDL2播放視頻的流程,在這里簡單復(fù)制過來。
      使用SDL播放視頻的流程可以概括為下圖。


      SDL中幾個關(guān)鍵的結(jié)構(gòu)體之間的關(guān)系可以用下圖概述。


      簡單解釋一下各變量的作用:
      SDL_Window就是使用SDL的時候彈出的那個窗口。在SDL1.x版本中,只可以創(chuàng)建一個一個窗口。在SDL2.0版本中,可以創(chuàng)建多個窗口。
      SDL_Texture用于顯示YUV數(shù)據(jù)。一個SDL_Texture對應(yīng)一幀YUV數(shù)據(jù)。
      SDL_Renderer用于渲染SDL_Texture至SDL_Window。
      SDL_Rect用于確定SDL_Texture顯示的位置。

       

      代碼

      貼出源代碼。

       

      1. /** 
      2.  * 最簡單的SDL2播放視頻的例子(SDL2播放RGB/YUV) 
      3.  * Simplest Video Play SDL2 (SDL2 play RGB/YUV)  
      4.  * 
      5.  * 雷霄驊 Lei Xiaohua 
      6.  * leixiaohua1020@126.com 
      7.  * 中國傳媒大學(xué)/數(shù)字電視技術(shù) 
      8.  * Communication University of China / Digital TV Technology 
      9.  * http://blog.csdn.net/leixiaohua1020 
      10.  * 
      11.  * 本程序使用SDL2播放RGB/YUV視頻像素數(shù)據(jù)。SDL實際上是對底層繪圖 
      12.  * API(Direct3D,OpenGL)的封裝,使用起來明顯簡單于直接調(diào)用底層 
      13.  * API。 
      14.  * 
      15.  * 函數(shù)調(diào)用步驟如下:  
      16.  * 
      17.  * [初始化] 
      18.  * SDL_Init(): 初始化SDL。 
      19.  * SDL_CreateWindow(): 創(chuàng)建窗口(Window)。 
      20.  * SDL_CreateRenderer(): 基于窗口創(chuàng)建渲染器(Render)。 
      21.  * SDL_CreateTexture(): 創(chuàng)建紋理(Texture)。 
      22.  * 
      23.  * [循環(huán)渲染數(shù)據(jù)] 
      24.  * SDL_UpdateTexture(): 設(shè)置紋理的數(shù)據(jù)。 
      25.  * SDL_RenderCopy(): 紋理復(fù)制給渲染器。 
      26.  * SDL_RenderPresent(): 顯示。 
      27.  * 
      28.  * This software plays RGB/YUV raw video data using SDL2. 
      29.  * SDL is a wrapper of low-level API (Direct3D, OpenGL). 
      30.  * Use SDL is much easier than directly call these low-level API.   
      31.  * 
      32.  * The process is shown as follows: 
      33.  * 
      34.  * [Init] 
      35.  * SDL_Init(): Init SDL. 
      36.  * SDL_CreateWindow(): Create a Window. 
      37.  * SDL_CreateRenderer(): Create a Render. 
      38.  * SDL_CreateTexture(): Create a Texture. 
      39.  * 
      40.  * [Loop to Render data] 
      41.  * SDL_UpdateTexture(): Set Texture's data. 
      42.  * SDL_RenderCopy(): Copy Texture to Render. 
      43.  * SDL_RenderPresent(): Show. 
      44.  */  
      45.   
      46. #include <stdio.h>  
      47.   
      48. extern "C"  
      49. {  
      50. #include "sdl/SDL.h"  
      51. };  
      52.   
      53. //set '1' to choose a type of file to play  
      54. #define LOAD_BGRA    1  
      55. #define LOAD_RGB24   0  
      56. #define LOAD_BGR24   0  
      57. #define LOAD_YUV420P 0  
      58.   
      59. //Bit per Pixel  
      60. #if LOAD_BGRA  
      61. const int bpp=32;  
      62. #elif LOAD_RGB24|LOAD_BGR24  
      63. const int bpp=24;  
      64. #elif LOAD_YUV420P  
      65. const int bpp=12;  
      66. #endif  
      67.   
      68. int screen_w=500,screen_h=500;  
      69. const int pixel_w=320,pixel_h=180;  
      70.   
      71. unsigned char buffer[pixel_w*pixel_h*bpp/8];  
      72. //BPP=32  
      73. unsigned char buffer_convert[pixel_w*pixel_h*4];  
      74.   
      75. //Convert RGB24/BGR24 to RGB32/BGR32  
      76. //And change Endian if needed  
      77. void CONVERT_24to32(unsigned char *image_in,unsigned char *image_out,int w,int h){  
      78.     for(int i =0;i<h;i++)  
      79.         for(int j=0;j<w;j++){  
      80.             //Big Endian or Small Endian?  
      81.             //"ARGB" order:high bit -> low bit.  
      82.             //ARGB Format Big Endian (low address save high MSB, here is A) in memory : A|R|G|B  
      83.             //ARGB Format Little Endian (low address save low MSB, here is B) in memory : B|G|R|A  
      84.             if(SDL_BYTEORDER==SDL_LIL_ENDIAN){  
      85.                 //Little Endian (x86): R|G|B --> B|G|R|A  
      86.                 image_out[(i*w+j)*4+0]=image_in[(i*w+j)*3+2];  
      87.                 image_out[(i*w+j)*4+1]=image_in[(i*w+j)*3+1];  
      88.                 image_out[(i*w+j)*4+2]=image_in[(i*w+j)*3];  
      89.                 image_out[(i*w+j)*4+3]='0';  
      90.             }else{  
      91.                 //Big Endian: R|G|B --> A|R|G|B  
      92.                 image_out[(i*w+j)*4]='0';  
      93.                 memcpy(image_out+(i*w+j)*4+1,image_in+(i*w+j)*3,3);  
      94.             }  
      95.         }  
      96. }  
      97.   
      98.   
      99. //Refresh Event  
      100. #define REFRESH_EVENT  (SDL_USEREVENT + 1)  
      101.   
      102. int thread_exit=0;  
      103.   
      104. int refresh_video(void *opaque){  
      105.     while (thread_exit==0) {  
      106.         SDL_Event event;  
      107.         event.type = REFRESH_EVENT;  
      108.         SDL_PushEvent(&event);  
      109.         SDL_Delay(40);  
      110.     }  
      111.     return 0;  
      112. }  
      113.   
      114. int main(int argc, char* argv[])  
      115. {  
      116.     if(SDL_Init(SDL_INIT_VIDEO)) {    
      117.         printf( "Could not initialize SDL - %s\n", SDL_GetError());   
      118.         return -1;  
      119.     }   
      120.   
      121.     SDL_Window *screen;   
      122.     //SDL 2.0 Support for multiple windows  
      123.     screen = SDL_CreateWindow("Simplest Video Play SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,  
      124.         screen_w, screen_h,SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);  
      125.     if(!screen) {    
      126.         printf("SDL: could not create window - exiting:%s\n",SDL_GetError());    
      127.         return -1;  
      128.     }  
      129.     SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0);    
      130.   
      131.     Uint32 pixformat=0;  
      132. #if LOAD_BGRA  
      133.     //Note: ARGB8888 in "Little Endian" system stores as B|G|R|A  
      134.     pixformat= SDL_PIXELFORMAT_ARGB8888;    
      135. #elif LOAD_RGB24  
      136.     pixformat= SDL_PIXELFORMAT_RGB888;    
      137. #elif LOAD_BGR24  
      138.     pixformat= SDL_PIXELFORMAT_BGR888;    
      139. #elif LOAD_YUV420P  
      140.     //IYUV: Y + U + V  (3 planes)  
      141.     //YV12: Y + V + U  (3 planes)  
      142.     pixformat= SDL_PIXELFORMAT_IYUV;    
      143. #endif  
      144.   
      145.     SDL_Texture* sdlTexture = SDL_CreateTexture(sdlRenderer,pixformat, SDL_TEXTUREACCESS_STREAMING,pixel_w,pixel_h);  
      146.   
      147.   
      148.   
      149.     FILE *fp=NULL;  
      150. #if LOAD_BGRA  
      151.     fp=fopen("../test_bgra_320x180.rgb","rb+");  
      152. #elif LOAD_RGB24  
      153.     fp=fopen("../test_rgb24_320x180.rgb","rb+");  
      154. #elif LOAD_BGR24  
      155.     fp=fopen("../test_bgr24_320x180.rgb","rb+");  
      156. #elif LOAD_YUV420P  
      157.     fp=fopen("../test_yuv420p_320x180.yuv","rb+");  
      158. #endif  
      159.     if(fp==NULL){  
      160.         printf("cannot open this file\n");  
      161.         return -1;  
      162.     }  
      163.   
      164.     SDL_Rect sdlRect;    
      165.   
      166.     SDL_Thread *refresh_thread = SDL_CreateThread(refresh_video,NULL,NULL);  
      167.     SDL_Event event;  
      168.     while(1){  
      169.         //Wait  
      170.         SDL_WaitEvent(&event);  
      171.         if(event.type==REFRESH_EVENT){  
      172.             if (fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp) != pixel_w*pixel_h*bpp/8){  
      173.                 // Loop  
      174.                 fseek(fp, 0, SEEK_SET);  
      175.                 fread(buffer, 1, pixel_w*pixel_h*bpp/8, fp);  
      176.             }  
      177.   
      178. #if LOAD_BGRA  
      179.             //We don't need to change Endian  
      180.             //Because input BGRA pixel data(B|G|R|A) is same as ARGB8888 in Little Endian (B|G|R|A)  
      181.             SDL_UpdateTexture( sdlTexture, NULL, buffer, pixel_w*4);    
      182. #elif LOAD_RGB24|LOAD_BGR24  
      183.             //change 24bit to 32 bit  
      184.             //and in Windows we need to change Endian  
      185.             CONVERT_24to32(buffer,buffer_convert,pixel_w,pixel_h);  
      186.             SDL_UpdateTexture( sdlTexture, NULL, buffer_convert, pixel_w*4);    
      187. #elif LOAD_YUV420P  
      188.             SDL_UpdateTexture( sdlTexture, NULL, buffer, pixel_w);    
      189. #endif  
      190.             //FIX: If window is resize  
      191.             sdlRect.x = 0;    
      192.             sdlRect.y = 0;    
      193.             sdlRect.w = screen_w;    
      194.             sdlRect.h = screen_h;    
      195.               
      196.             SDL_RenderClear( sdlRenderer );     
      197.             SDL_RenderCopy( sdlRenderer, sdlTexture, NULL, &sdlRect);    
      198.             SDL_RenderPresent( sdlRenderer );    
      199.             //Delay 40ms  
      200.             SDL_Delay(40);  
      201.               
      202.         }else if(event.type==SDL_WINDOWEVENT){  
      203.             //If Resize  
      204.             SDL_GetWindowSize(screen,&screen_w,&screen_h);  
      205.         }else if(event.type==SDL_QUIT){  
      206.             break;  
      207.         }  
      208.     }  
      209.   
      210.     return 0;  
      211. }  



       

      運行結(jié)果

      程序的運行結(jié)果如下圖所示。

       

      下載


      代碼位于“Simplest Media Play”中
       
       

      SourceForge項目地址:https:///projects/simplestmediaplay/

      CSDN下載地址:http://download.csdn.net/detail/leixiaohua1020/8054395

       
       
      上述工程包含了使用各種API(Direct3D,OpenGL,GDI,DirectSound,SDL2)播放多媒體例子。其中音頻輸入為PCM采樣數(shù)據(jù)。輸出至系統(tǒng)的聲卡播放出來。視頻輸入為YUV/RGB像素數(shù)據(jù)。輸出至顯示器上的一個窗口播放出來。
      通過本工程的代碼初學(xué)者可以快速學(xué)習(xí)使用這幾個API播放視頻和音頻的技術(shù)。
      一共包括了如下幾個子工程:
      simplest_audio_play_directsound:         使用DirectSound播放PCM音頻采樣數(shù)據(jù)。
      simplest_audio_play_sdl2:                       使用SDL2播放PCM音頻采樣數(shù)據(jù)。
      simplest_video_play_direct3d:                使用Direct3D的Surface播放RGB/YUV視頻像素數(shù)據(jù)。
      simplest_video_play_direct3d_texture:使用Direct3D的Texture播放RGB視頻像素數(shù)據(jù)。
      simplest_video_play_gdi:                          使用GDI播放RGB/YUV視頻像素數(shù)據(jù)。
      simplest_video_play_opengl:                   使用OpenGL播放RGB/YUV視頻像素數(shù)據(jù)。
      simplest_video_play_opengl_texture:    使用OpenGL的Texture播放YUV視頻像素數(shù)據(jù)。
      simplest_video_play_sdl2:                        使用SDL2播放RGB/YUV視頻像素數(shù)據(jù)。

       

      from:http://blog.csdn.net/leixiaohua1020/article/details/40525591

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多