YUV Overlay in Windows via PB (DirectX) or SDL

Everything else that doesn't fall into one of the other PB categories.
inc.
Enthusiast
Enthusiast
Posts: 406
Joined: Thu May 06, 2004 4:28 pm
Location: Cologne/GER

YUV Overlay in Windows via PB (DirectX) or SDL

Post by inc. »

Hi,

Im writing a Videoplayback Appl. and want to display the videos YUV (Not RGB!) content.
Since I dont know how to do it via PB as PBs native OpenWidowedScreen() way only supports RGB Data I had to switch to SDL.

To possibilities:

1. Is it possible displaying YUV (YV12) Data by using OpenWidowedScreen()? Means is there a pointer to a DirectX Structure hidden which I can access and prepare for an YUV Playback?

If not ....

2. How can I let SDL display the YUV Overlay within an existing Window where the SDL window would act like a childwindow?

Thanks in advance
:-)
Check out OOP support for PB here!
inc.
Enthusiast
Enthusiast
Posts: 406
Joined: Thu May 06, 2004 4:28 pm
Location: Cologne/GER

Post by inc. »

After doing some search in here and the www I did figure it out by myself. Here's an example:

(EDIT: Is there an "official" port of ddraw.h available for Purebasic inkl. Structures, Constants, Macros etc ?)

Code: Select all

; User Setup

#Test_Width = 720
#Test_Height= 576

#ResizePicToWindow = #True

#UseOverlay = #True

#YV12 = #True ; // Else it will be a RGB32 example


; // DDraw.h constants

#DD_OK = 0
#DDSCL_NORMAL = $00000008
#DDSD_CAPS = $00000001
#DDSCAPS_OFFSCREENPLAIN = 64
#DDSD_PIXELFORMAT = 4096
#DDPF_FOURCC = 4
#DDOVER_SHOW = 16384
#DDSCAPS_OVERLAY = 128
#DDSCAPS_VIDEOMEMORY = 16384
#DDSD_HEIGHT = 2
#DDSD_WIDTH = 4
#DDPF_RGB = 64
#DDLOCK_WAIT = 1
#DDSCAPS_PRIMARYSURFACE = $00000200
#DDSCL_NOWINDOWCHANGES = $00000004
#DDPF_YUV = $00000200
#DDLOCK_WRITEONLY = $00000020
#DDBLT_WAIT = $01000000
#DDOVER_KEYDESTOVERRIDE = $00000800


; // Structures and Variables

Structure DDPIXELFORMAT
  dwSize.l
  dwFlags.l
  dwFourCC.l
  StructureUnion
    dwRGBBitCount.l
    dwYUVBitCount.l
    dwZBufferBitDepth.l
    dwAlphaBitDepth.l
  EndStructureUnion
  StructureUnion
    dwRBitMask.l
    dwYBitMask.l
  EndStructureUnion
  StructureUnion
    dwGBitMask.l
    dwUBitMask.l
  EndStructureUnion
  StructureUnion
    dwBBitMask.l
    dwVBitMask.l
  EndStructureUnion
  StructureUnion
    dwRGBAlphaBitMask.l
    dwYUVAlphaBitMask.l
  EndStructureUnion
EndStructure

Structure DDCOLORKEY
  dwColorSpaceLowValue.l
  dwColorSpaceHighValue.l
EndStructure

Structure DDSCAPS2
  dwCaps.l
  dwCaps2.l
  dwCaps3.l
  dwCaps4.l
EndStructure

Structure DDSURFACEDESC2
  dwSize.l;                                // size of the DDSURFACEDESC structure
  dwFlags.l;                               // determines what fields are valid
  dwHeight.l;                              // height of surface to be created
  dwWidth.l;                               // width of input surface
  StructureUnion
    lPitch.l;                           // distance to start of next line (return value only)
    dwLinearSize.l;                     // Formless late-allocated optimized surface size
  EndStructureUnion
  dwBackBufferCount.l;                     // number of back buffers requested
  StructureUnion
    dwMipMapCount.l;                    // number of mip-map levels requestde
    ;                                   // dwZBufferBitDepth removed, use ddpfPixelFormat one instead
    dwRefreshRate.l;                    // refresh rate (used when display mode is described)
    dwSrcVBHandle.l;                    // The source used in VB::Optimize
  EndStructureUnion
  dwAlphaBitDepth.l;                       // depth of alpha buffer requested
  dwReserved.l;                            // reserved
  lpSurface.l;                             // pointer to the associated surface memory
  StructureUnion
    ddckCKDestOverlay.DDCOLORKEY;       // color key for destination overlay use
    dwEmptyFaceColor.l;                 // Physical color for empty cubemap faces
  EndStructureUnion
  ddckCKDestBlt.DDCOLORKEY;                // color key for destination blt use
  ddckCKSrcOverlay.DDCOLORKEY;             // color key for source overlay use
  ddckCKSrcBlt.DDCOLORKEY;                 // color key for source blt use
  StructureUnion
    ddpfPixelFormat.DDPIXELFORMAT;      // pixel format description of the surface
    dwFVF.l;                            // vertex format description of vertex buffers
  EndStructureUnion
  ddscaps.DDSCAPS2;                        // direct draw surface capabilities
  dwTextureStage.l;                        // stage in multitexture cascade
EndStructure

EnableExplicit

Define *lpDD.IDirectDraw7
Define.IDirectDrawSurface7 *lpDDSPrimary, *lpDDSOffScr
Define ddsd.DDSURFACEDESC2
Define.RECT rctSour, rctDest
Define *lpClipper.IDirectDrawClipper
Define Event, hwnd, *lpSurf, x, y


; Our Window where the Imagecontent will be shown

hwnd = OpenWindow(0, 0, 0, #Test_Width, #Test_Height, "DirectDraw YV12 Test",#PB_Window_SizeGadget|#PB_Window_SystemMenu    )


; // Initializing DirectDraw

If OpenLibrary(0,"ddraw.dll")
  If Not CallFunction(0,"DirectDrawCreateEx",0 , @*lpDD, ?IID_IDirectDraw7, 0) = #DD_OK
    MessageRequester("Warning:","Couldn't init DirectDraw",0)
    End
  EndIf
Else
  MessageRequester("Warning:","Couldn't find ddraw.dll",0)
  End
EndIf
If Not *lpDD\SetCooperativeLevel(hwnd , #DDSCL_NORMAL|#DDSCL_NOWINDOWCHANGES) = #DD_OK
  Debug "Failed: SetCooperativeLevel" : End
EndIf


; // Setting up the primary surface

ddsd\dwSize = SizeOf(ddsd)
ddsd\dwFlags = #DDSD_CAPS
ddsd\ddscaps\dwCaps = #DDSCAPS_PRIMARYSURFACE
If Not *lpDD\CreateSurface(@ddsd, @*lpDDSPrimary, #Null) = #DD_OK
  Debug "Failed: PrimarySurface" : End
EndIf


; // ... and the overlay surface

ddsd\dwSize = SizeOf(ddsd);
ddsd\dwFlags = #DDSD_CAPS|#DDSD_HEIGHT|#DDSD_WIDTH|#DDSD_PIXELFORMAT
If #UseOverlay
  ddsd\ddscaps\dwCaps =#DDSCAPS_OVERLAY|#DDSCAPS_VIDEOMEMORY
Else
  ddsd\ddscaps\dwCaps =#DDSCAPS_OFFSCREENPLAIN|#DDSCAPS_VIDEOMEMORY
EndIf
ddsd\dwWidth = #Test_Width
ddsd\dwHeight = #Test_Height
ddsd\ddpfPixelFormat\dwSize = SizeOf(DDPIXELFORMAT)
If #YV12
  ddsd\ddpfPixelFormat\dwFlags  = #DDPF_FOURCC|#DDPF_YUV
  ddsd\ddpfPixelFormat\dwFourCC = PeekL(@"YV12")
  ddsd\ddpfPixelFormat\dwYUVBitCount = 8 
Else
  ddsd\ddpfPixelFormat\dwFlags=#DDPF_RGB
  ddsd\ddpfPixelFormat\dwRGBBitCount = 32
  ddsd\ddpfPixelFormat\dwRBitMask = $00FF0000
  ddsd\ddpfPixelFormat\dwGBitMask = $0000FF00
  ddsd\ddpfPixelFormat\dwBBitMask = $000000FF
EndIf
If Not *lpDD\CreateSurface(@ddsd, @*lpDDSOffScr, #Null) = #DD_OK
  Debug "Failed: YUV Surface" : End
EndIf


; // Set up the clipper to our mainwindow

If Not *lpDD\CreateClipper(0, @*lpClipper, #Null)= #DD_OK
  Debug "Failed: Clipper" : End
EndIf
If Not *lpClipper\SetHWnd(0, hwnd)= #DD_OK
  Debug "Failed: Clipper window" : End
EndIf


; // Copying/writing the image Data

If Not *lpDDSOffScr\Lock(#Null, @ddsd, #DDLOCK_WAIT, #Null) = #DD_OK
  Debug "Failed: Lock YUV Surface" : End
EndIf

*lpSurf = ddsd\lpSurface

Debug "surfaceWidth = "+Str(ddsd\dwWidth)
Debug "surfacepitch = "+Str(ddsd\lPitch)


If *lpSurf
  
  If #YV12 ;(Generate a cyan/blue YV12 Picture from scratch)
    ; // Y Data
    For y=0 To ddsd\dwHeight-1
      For x = 0 To ddsd\dwWidth-1
        If y < ddsd\dwHeight/2 
          If x < ddsd\dwWidth/2
            PokeB(*lpSurf+x, 127)
          Else
            PokeB(*lpSurf+x, 0)
          EndIf
        Else
          If x < ddsd\dwWidth/2
            PokeB(*lpSurf+x, 0)
          Else
            PokeB(*lpSurf+x, 127)
          EndIf
        EndIf
      Next x
      *lpSurf + ddsd\lPitch
    Next y
    
    ; // V
    For y=0 To (ddsd\dwHeight/2)-1
      For x = 0 To (ddsd\dwWidth/2)-1
        PokeB(*lpSurf+x, 0)
      Next x
      *lpSurf + ddsd\lPitch/2
    Next y
    
    ; // U
    For y=0 To (ddsd\dwHeight/2)-1
      For x = 0 To (ddsd\dwWidth/2)-1
        PokeB(*lpSurf+x,255)
      Next x
      *lpSurf + ddsd\lPitch/2
    Next y
    
    
  Else ;(Generate a red/green RGB Picture from scratch)
    For y=0 To ddsd\dwHeight-1 
      For x = 0 To ddsd\dwWidth-1 
        If y < ddsd\dwHeight/2
          If x < ddsd\dwWidth/2
            PokeL(*lpSurf+x*4, $00FF0000)
          Else
            PokeL(*lpSurf+x*4, $0000FF00)
          EndIf
        Else
          If x < ddsd\dwWidth/2
            PokeL(*lpSurf+x*4, $0000FF00)
          Else
            PokeL(*lpSurf+x*4, $00FF0000)
          EndIf
        EndIf 
      Next x
      *lpSurf + ddsd\lPitch
    Next y
    
  EndIf
  
Else
  Debug "Failed: No YUV Surface pointer" : End
EndIf

*lpDDSOffScr\Unlock(#Null)

Repeat
  Event = WaitWindowEvent()
  If Event = #WM_PAINT
    rctSour\left = 0
    rctSour\top = 0
    rctSour\right = ddsd\dwWidth
    rctSour\bottom = ddsd\dwHeight
    *lpDDSPrimary\SetClipper(*lpClipper)
    If #ResizePicToWindow
      GetClientRect_(hwnd,@rctDest)
    Else
      CopyMemory(@rctSour, @rctDest, SizeOf(RECT))
    EndIf
    ClientToScreen_(hwnd, @rctDest\left)
    ClientToScreen_(hwnd, @rctDest\right)
    *lpDDSPrimary\Blt(@rctDest, *lpDDSOffScr, @rctSour, #DDBLT_WAIT, #Null)
    *lpDDSPrimary\SetClipper(#Null)
  EndIf
Until Event = #PB_Event_CloseWindow

If *lpDD
  If *lpDDSPrimary
    *lpDDSPrimary\Release()
    *lpDDSPrimary = #Null
  EndIf
  If *lpDDSOffScr
    *lpDDSOffScr\Release()
    *lpDDSOffScr = #Null
  EndIf
  *lpDD\Release()
  *lpDD = #Null
EndIf

End


DataSection
IID_IDirectDraw7:
Data.l $15E65EC0
Data.w $3B9C, $11D2
Data.b $B9, $2F, $00, $60, $97, $97, $EA, $5B
EndDataSection
Check out OOP support for PB here!
Post Reply