개발은 하는건가..

[MFC] DC 에 동영상 출력 시 가장 빠르게 출력 하기 위한 방법 본문

C, C++, MFC

[MFC] DC 에 동영상 출력 시 가장 빠르게 출력 하기 위한 방법

수동애비 2022. 4. 8. 14:45
반응형


동영상을 디코딩하여 나온 RGB raw 데이터를 DirectX 나 openGl 같은 것들을 사용하지 않고 DC 에서도 충분히 빠른 속도로 출력이 가능하다.
화면을 가득 채우는 FHD 해상도의 영상도 높지 않은 CPU 점유율을 소모하면서 30 프레임은 가능했다.
단, 조건은 영상을 디코딩 시 32bit BGRA 형태여야 한다. 그래야 출력 과정에서 RGB 데이터들을 다시 재배치하는 연산을 수행하지 않고 그대로 출력이되므로 속도가 빠르다.

RECT m_rcView = { 0, 0, 1280, 720 };   // 출력 영역 
BITMAPINFO*	m_pBitmapInfo = NULL;  // 비트맵 정보

void CVideoStreamDlg::DrawVideo(CDC *pDC, BYTE *pFrameData, UINT nWidth, UINT nHeight)
{		
    if (m_pBitmapInfo == NULL) {
    	// DC 에 draw 를 위한 BitmapInfo 생성
        m_pBitmapInfo = (BITMAPINFO*)(new BYTE[sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD)]);
        ZeroMemory(m_pBitmapInfo, sizeof(BITMAPINFO));

        m_pBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        m_pBitmapInfo->bmiHeader.biPlanes = 1;
        m_pBitmapInfo->bmiHeader.biCompression = BI_RGB;
        m_pBitmapInfo->bmiHeader.biClrImportant = 0;

        m_pBitmapInfo->bmiHeader.biWidth = nWidth;
        m_pBitmapInfo->bmiHeader.biHeight = -(int)nHeight;	// bitmap  상하 flip 를 위해 - 값으로 취한다.
        m_pBitmapInfo->bmiHeader.biBitCount = 32;        
    }

	// 영상 위에 추가적인 Drawing 시 속도 향상을 위해 memDC 이용 (CMemDC 는 MFC 클래스)
    CMemDC memDC(*pDC, m_rcView);
    pDC = &memDC.GetDC();

    pDC->SetStretchBltMode(HALFTONE);  // COLORONCOLOR  HALFTONE

	// pFrameData 의 RGB 데이터를 drawing
    ::StretchDIBits(pDC->GetSafeHdc(),
        m_rcView.left, m_rcView.top, m_rcView.Width(), m_rcView.Height(),	// Draw target rect
        0, 0, nWidth, nHeight,	// Src rect
        pFrameData,				// Bitmap data
        m_pBitmapInfo,			// BitmapInfo
        DIB_RGB_COLORS,
        SRCCOPY);

	// 영상 시간 표시를 위한 처리
    CString strStatus;
    LONGLONG llElapsed = GetTickCount64() - m_nFrameStartTs;
    int nHour, nMin, nSec, nMs;

    nHour = (int)(llElapsed / (1000 * 60 * 60));
    nMin = (int)(llElapsed / (1000 * 60)) % 60;
    nSec = (int)(llElapsed / 1000) % 60;
    nMs = (int)(llElapsed % 1000);

    strStatus.Format(_T("ElapsedTime=%02d:%02d:%02d.%03d), nHour, nMin, nSec, nMs);
    pDC->SetBkMode(TRANSPARENT);
    pDC->SetTextColor(RGB(0, 0, 0));
    pDC->TextOutW(m_rcView.left + 6, m_rcView.top + 6, strStatus);
    pDC->SetTextColor(RGB(255, 255, 255));
    pDC->TextOutW(m_rcView.left + 5, m_rcView.top + 5, strStatus);

}
Comments