C# ddraw实现视频流的显示

private DxVBLib.DDSURFACEDESC2 m_sDDOverlayDesc;
        private DxVBLib.DirectDrawSurface7 m_pDDOverlay;
        private int m_colortype;
        private DirectShowLib.BitmapInfoHeader m_bmpInfo;
        private int m_dwRawSize;
        private DxVBLib.DirectDrawSurface7 m_pDDPrimary;
        private int m_width;
        private int m_height;
        private DxVBLib.DirectX7 m_dx = new DxVBLib.DirectX7();
        private DxVBLib.DirectDraw7 m_pDD;
        private RECT m_WindowRect = new RECT();
        private RECT m_ClientRect = new RECT();
        private int m_hRenderWnd;
        private bool m_bPreview = false;

        public bool m_IsOpen = true;
        public VideoRenderer(int hWnd)
        {
            m_hRenderWnd = hWnd;
           
            m_bmpInfo = new DirectShowLib.BitmapInfoHeader();
            m_bmpInfo.Size = 0;
            SetDrawScale(0, 0);
            OpenDirectDraw();
        }
        /// <summary>
        /// 是否预览
        /// </summary>
        public bool IsPreview
        {
            set { m_bPreview = value;}
            get { return m_bPreview; }
        }
        public void CreateLiveWindow(int nChroma, int width, int height)
        {
            DirectShowLib.BitmapInfoHeader bmpFormat = new DirectShowLib.BitmapInfoHeader();

            bmpFormat.Width = width;
            bmpFormat.Height = height;
            bmpFormat.Planes = 1;

            m_width = width;
            m_height = height;
            if (nChroma == 0)
            {
                bmpFormat.BitCount = (short)32;
       bmpFormat.Compression = GetColorTypeValue("2YUY");
            }
            else if(nChroma == 1)
            {
                bmpFormat.BitCount = (short)16;
                bmpFormat.Compression = GetColorTypeValue("2YUY");
            }
            else if (nChroma == GetColorTypeValue("024I"))
            {
                bmpFormat.BitCount = (short)12;
                bmpFormat.Compression = GetColorTypeValue("024I");
            }
            else if (nChroma == GetColorTypeValue("21VY"))
            {
                bmpFormat.BitCount = (short)12;
                bmpFormat.Compression = GetColorTypeValue("21VY");
            }
            else
            {
                bmpFormat.BitCount = (short)32;
             }
            bmpFormat.ImageSize = bmpFormat.Width * bmpFormat.Height * bmpFormat.BitCount / 8;
       
            OpenVideoRender(bmpFormat);
        }
        public bool OpenDirectDraw()
        {
            bool bSuccess = false;
            m_pDD = m_dx.DirectDrawCreate("");
            if (m_pDD != null)
            {
                // Request normal cooperative level to put us in windowed mode
                m_pDD.SetCooperativeLevel(m_hRenderWnd, CONST_DDSCLFLAGS.DDSCL_NORMAL);

                bSuccess = true;
                // Create primary surface
                DDSURFACEDESC2 m_sDDPrimaryDesc = new DDSURFACEDESC2();
                m_sDDPrimaryDesc.lFlags = CONST_DDSURFACEDESCFLAGS.DDSD_CAPS;
                m_sDDPrimaryDesc.ddsCaps.lCaps = CONST_DDSURFACECAPSFLAGS.DDSCAPS_PRIMARYSURFACE;

                m_pDDPrimary = m_pDD.CreateSurface(ref m_sDDPrimaryDesc);
                if (m_pDDPrimary != null)
                {
                    DirectDrawClipper pDDClipper = null;
                    pDDClipper = m_pDD.CreateClipper(0);
                    if (pDDClipper == null)
                        return true;
                    pDDClipper.SetHWnd(m_hRenderWnd);
                    m_pDDPrimary.SetClipper(pDDClipper);
                }
            }

            return bSuccess;
        }
        public bool OpenVideoRender(DirectShowLib.BitmapInfoHeader pbmphInfo)
        {
            bool bSuccess = false;

            //CloseVideoRender();

            int dwWidth = pbmphInfo.Width;
            int dwHeight = pbmphInfo.Height;
            int dwBitCount = pbmphInfo.BitCount;
            int dwFourCC = pbmphInfo.Compression;
            m_colortype = dwFourCC;
            m_bmpInfo = pbmphInfo;
            m_dwRawSize = dwWidth * ((dwBitCount + 1) / 8);
            m_bmpInfo.ImageSize = m_dwRawSize * dwHeight;

            m_ClientRect.Left = 0;
            m_ClientRect.Top = 0;
            m_ClientRect.Right = dwWidth;
            m_ClientRect.Bottom = dwHeight;

            if (m_pDDPrimary != null)
            {
               
              
                DDCAPS sDDHalCaps = new DDCAPS();
                DDCAPS sDDHalCaps2 = new DDCAPS ();
                //m_pDD.GetCaps(ref sDDHalCaps,null);
                m_pDD.GetCaps(ref sDDHalCaps, ref sDDHalCaps2);
                m_sDDOverlayDesc = new DDSURFACEDESC2();
                m_sDDOverlayDesc.lFlags = CONST_DDSURFACEDESCFLAGS.DDSD_CAPS | CONST_DDSURFACEDESCFLAGS.DDSD_WIDTH | CONST_DDSURFACEDESCFLAGS.DDSD_HEIGHT;

                m_sDDOverlayDesc.lWidth = dwWidth;
                m_sDDOverlayDesc.lHeight = dwHeight;


                sDDHalCaps.lCaps = CONST_DDCAPS1FLAGS.DDCAPS_OVERLAY;

                m_sDDOverlayDesc.ddsCaps.lCaps = CONST_DDSURFACECAPSFLAGS.DDSCAPS_OFFSCREENPLAIN
                                                  | CONST_DDSURFACECAPSFLAGS.DDSCAPS_LIVEVIDEO
                                                  | CONST_DDSURFACECAPSFLAGS.DDSCAPS_VIDEOMEMORY
                                                  | CONST_DDSURFACECAPSFLAGS.DDSCAPS_NONLOCALVIDMEM
                                                  ;

                DDPIXELFORMAT ddPixelFormat = new DDPIXELFORMAT();

                if (dwFourCC != 0)//BI_RGB
                {
                    // FOURCC need HARDWARE support (VideoMem)
                    m_sDDOverlayDesc.lFlags |= CONST_DDSURFACEDESCFLAGS.DDSD_PIXELFORMAT;
                    m_sDDOverlayDesc.ddsCaps.lCaps &= ~CONST_DDSURFACECAPSFLAGS.DDSCAPS_NONLOCALVIDMEM;
                    m_sDDOverlayDesc.ddsCaps.lCaps |= CONST_DDSURFACECAPSFLAGS.DDSCAPS_HWCODEC;
                    ddPixelFormat.lFlags = CONST_DDPIXELFORMATFLAGS.DDPF_FOURCC;
                    ddPixelFormat.lFourCC = dwFourCC;
                    ddPixelFormat.lYUVBitCount = 16;//dwBitCount;
                    if (dwFourCC == GetColorTypeValue("VNUY") || dwFourCC == GetColorTypeValue("224V") || dwFourCC == GetColorTypeValue("2YUY")
                        || dwFourCC == GetColorTypeValue("YVYU") || dwFourCC == GetColorTypeValue("UYVY"))
                    {
                         ddPixelFormat.lFourCC      = GetColorTypeValue("2YUY");
                    }
                    else if (dwFourCC == GetColorTypeValue("024I") ||dwFourCC == GetColorTypeValue("21VY") ||dwFourCC == GetColorTypeValue("P14Y"))
                    {
                         ddPixelFormat.lFourCC = GetColorTypeValue("21VY");
                    }
                    //else if (dwFourCC == BI_BITFIELDS)//BI_BITFIELDS
                    //{
                    //    ddPixelFormat.lFourCC = GetColorTypeValue("21VY");
                    //}
               
                }
                else
                {
                    if ((m_sDDOverlayDesc.ddsCaps.lCaps & CONST_DDSURFACECAPSFLAGS.DDSCAPS_OVERLAY) == 0)
                    {
                        m_sDDOverlayDesc.ddsCaps.lCaps &= ~CONST_DDSURFACECAPSFLAGS.DDSCAPS_NONLOCALVIDMEM;
                    }
                    else
                    {
                        m_sDDOverlayDesc.ddsCaps.lCaps |= CONST_DDSURFACECAPSFLAGS.DDSCAPS_NONLOCALVIDMEM;
                    }

                    ddPixelFormat.lFlags = CONST_DDPIXELFORMATFLAGS.DDPF_RGB;
                    ddPixelFormat.lRGBBitCount = dwBitCount;
                    switch (dwBitCount)
                    {
                        case 16: // 16-bit RGB 5:6:5
                            break;
                        case 15: // 16-bit RGB 5:5:5
                            break;
                    }
                }

                m_sDDOverlayDesc.ddpfPixelFormat = ddPixelFormat;

                // Default is NonLocal VideoMem (AGP)
                m_pDDOverlay = m_pDD.CreateSurface(ref m_sDDOverlayDesc);
                if (bSuccess = (m_pDDOverlay != null)) { }
                else
                    return false;

                // try to Local VideoMem (Hardware)
                if (!bSuccess && ((m_sDDOverlayDesc.ddsCaps.lCaps & CONST_DDSURFACECAPSFLAGS.DDSCAPS_NONLOCALVIDMEM) == 0))
                {
                    m_sDDOverlayDesc.ddsCaps.lCaps &= ~CONST_DDSURFACECAPSFLAGS.DDSCAPS_NONLOCALVIDMEM;
                    m_pDDOverlay = m_pDD.CreateSurface(ref m_sDDOverlayDesc);
                }

                // try to SystemMem (Software)
                if (!bSuccess && ((m_sDDOverlayDesc.ddsCaps.lCaps & CONST_DDSURFACECAPSFLAGS.DDSCAPS_VIDEOMEMORY) == 0))
                {
                    m_sDDOverlayDesc.ddsCaps.lCaps &= ~CONST_DDSURFACECAPSFLAGS.DDSCAPS_VIDEOMEMORY;
                    m_sDDOverlayDesc.ddsCaps.lCaps |= CONST_DDSURFACECAPSFLAGS.DDSCAPS_SYSTEMMEMORY;
                    m_pDDOverlay = m_pDD.CreateSurface(ref m_sDDOverlayDesc);
                }
            }

            return bSuccess;
        }

        public unsafe void DrawVideo(byte* pFrame,int datalen)
        {
            RECT rcClient = new RECT();
            m_pDDOverlay.Lock(ref rcClient, ref m_sDDOverlayDesc, DxVBLib.CONST_DDLOCKFLAGS.DDLOCK_SURFACEMEMORYPTR | DxVBLib.CONST_DDLOCKFLAGS.DDLOCK_WAIT, 0);

            if (m_bmpInfo.Compression != 0)//BI_RGB
            {
                byte* dst = (byte*)m_sDDOverlayDesc.lpSurface;

                byte* lpY = (byte*)pFrame;
                byte* lpU = null;
                byte* lpV = null;
                if(m_colortype == GetColorTypeValue("024I"))
                {
                    lpU   = (byte*)pFrame + m_width * m_height;
                    lpV = (byte*)pFrame + m_width * m_height * 5 / 4; 
                }
                if (m_colortype == GetColorTypeValue("21VY"))//'21VY'
                {
                    lpV = (byte*)pFrame + m_width * m_height;
                    lpU = (byte*)pFrame + m_width * m_height * 5 / 4;
                }

                byte* lpSurf = (byte*)m_sDDOverlayDesc.lpSurface;
                uint i = 0;
                if (lpSurf != null)
                {
                    //   fill   Y   data  
                    lpY += 0;
                    for (i = 0; i < m_sDDOverlayDesc.lHeight; i++)
                    {
                        memcpy(lpSurf, lpY, m_sDDOverlayDesc.lWidth);
                        lpY += m_width;
                        lpSurf += m_sDDOverlayDesc.lPitch;
                    }

                    //fill V data
                    lpY += 0 * m_width / 4 + 0 / 2;
                    for (i = 0; i < m_sDDOverlayDesc.lHeight / 2; i++)
                    {
 
                        memcpy(lpSurf, lpV, m_sDDOverlayDesc.lWidth / 2);
                        lpV += m_width / 2;
                        lpSurf += m_sDDOverlayDesc.lPitch / 2;
                    }

                    //fill U data  
                    lpU += 0 * m_width / 4 + 0 / 2;
                    for (i = 0; i < m_sDDOverlayDesc.lHeight / 2; i++)
                    {
                        //printf("lpSurf = %p, lines=%d, copy V/n", lpSurf, m_sDDOverlayDesc.lHeight / 2);
                        memcpy(lpSurf, lpU, m_sDDOverlayDesc.lWidth / 2);
     
                        //printf("lpSurf = %p, copy V ok, line %d/n", lpSurf, i);
                        lpU += m_width / 2;
                        lpSurf += m_sDDOverlayDesc.lPitch / 2;
                    }
                }
            }
            else  // RGBA
            {

            }
            m_pDDOverlay.Unlock(ref m_ClientRect);
            UpdateDisplay();
        }

        void SetDrawScale(float fScaleHor, float fScaleVer)
        {
            RECT rcClient = new RECT ();
            m_dx.GetWindowRect(m_hRenderWnd, ref rcClient);
            if (m_bmpInfo.Size > 0)
            {
                m_bmpInfo.Width = rcClient.Right;
                m_bmpInfo.Height = rcClient.Bottom;
            }

            if (fScaleHor >= 0)
            {
                m_WindowRect.Right = (int)((float)m_bmpInfo.Width * fScaleHor);
            }
            else
            {
                // Fit for Window
                // Dst: Window Rect All
                m_WindowRect.Right = rcClient.Right;
            }

            if (fScaleVer > 0)
            {
                m_WindowRect.Bottom = (int)((float)m_bmpInfo.Height * fScaleVer);
            }
            else
            {
                // Fit for Window
                // Dst: Window Rect All
                m_WindowRect.Bottom = rcClient.Bottom;
            }

            // If window rect large than the displayed Bmp, replace it.


            if (rcClient.Right == m_WindowRect.Right)
            {
                m_WindowRect.Left = 0;
            }
            else
            {
                m_WindowRect.Left = (rcClient.Right - m_WindowRect.Right) >> 1;
            }

            if (rcClient.Bottom == m_WindowRect.Bottom)
            {
                m_WindowRect.Top = 0;
            }
            else
            {
                m_WindowRect.Top = (rcClient.Bottom - m_WindowRect.Bottom) >> 1;
            }

            UpdateDisplay();
        }

        #region C# 下内存拷贝(unsafe)
        unsafe void* memcpy(void* pvTo, void* pvFrom, int size)
        {
            byte* pbTo = (byte*)pvTo;         // 防止改变pvTo的地址
            byte* pbFrom = (byte*)pvFrom; // 防止改变pvFrom的地址
            while (size-- > 0)
                *pbTo++ = *pbFrom++;
            return pvTo;
        }
        #endregion
        #region 显示视频图像
        void UpdateDisplay()
        {
            //printf("-------------------- UpdateDisplay --------------------/n");
            if (m_pDDPrimary != null && m_pDDOverlay != null)
            {
                RECT rcWin = new RECT();
                m_dx.GetWindowRect(m_hRenderWnd, ref rcWin);   // Dst Window

                if ((m_sDDOverlayDesc.ddsCaps.lCaps & CONST_DDSURFACECAPSFLAGS.DDSCAPS_OVERLAY) != 0)
                {

                    m_pDDOverlay.UpdateOverlay(ref m_ClientRect, // src
                                         m_pDDPrimary,  // dest surface
                                         ref rcWin,  // dest rect
                                         CONST_DDOVERFLAGS.DDOVER_SHOW | CONST_DDOVERFLAGS.DDOVER_DDFX
                                         | CONST_DDOVERFLAGS.DDOVER_KEYDESTOVERRIDE);

                }
                else
                {
                    //DirectDrawSurface7 dDsurfaceSec = m_pDD.CreateSurfaceFromFile("c://3.bmp", ref m_sDDOverlayDesc);
                    m_pDDPrimary.Blt(ref rcWin, m_pDDOverlay, ref m_ClientRect, CONST_DDBLTFLAGS.DDBLT_ASYNC);
                }
                m_IsOpen = true;
            }

        }
        #endregion

 

 

//附上效果图

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值