⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vfw.cxx

📁 opal的ptlib c++源程序 可以从官方网站上下载
💻 CXX
📖 第 1 页 / 共 4 页
字号:
    PSyncPoint m_started;
    BITMAPINFO m_bitmap;
    bool       m_flipped;
    int        m_lastX;
    int        m_lastY;
};


#define DEFAULT_STYLE (WS_POPUP|WS_BORDER|WS_SYSMENU|WS_CAPTION)
#define DEFAULT_TITLE "Video Output"

static bool ParseWindowDeviceName(const PString & deviceName, DWORD * dwStylePtr = NULL, HWND * hWndParentPtr = NULL)
{
  if (deviceName.Find("MSWIN") != 0)
    return false;

  PINDEX pos = deviceName.Find("STYLE=");
  DWORD dwStyle = pos == P_MAX_INDEX ? DEFAULT_STYLE : strtoul(((const char *)deviceName)+pos+6, NULL, 0);
  if ((dwStyle&(WS_POPUP|WS_CHILD)) == 0) {
    PTRACE(1, "VidOut\tWindow must be WS_POPUP or WS_CHILD window.");
    return false;
  }

  HWND hWndParent = NULL;
  pos = deviceName.Find("PARENT=");
  if (pos != P_MAX_INDEX) {
    hWndParent = (HWND)strtoul(((const char *)deviceName)+pos+7, NULL, 0);
    if (!::IsWindow(hWndParent)) {
      PTRACE(2, "VidOut\tIllegal parent window " << hWndParent << " specified.");
      hWndParent = NULL;
    }
  }

  // Have parsed out style & parent, see if legal combination
  if (hWndParent == NULL && (dwStyle&WS_POPUP) == 0) {
    PTRACE(1, "VidOut\tWindow must be WS_POPUP if parent window not specified.");
    return false;
  }

  if (dwStylePtr != NULL)
    *dwStylePtr = dwStyle;

  if (hWndParentPtr != NULL)
    *hWndParentPtr = hWndParent;

  return true;
}


class PVideoOutputDevice_Window_PluginServiceDescriptor : public PDevicePluginServiceDescriptor
{
  public:
    virtual PObject *    CreateInstance(int /*userData*/) const { return PNEW PVideoOutputDevice_Window; }
    virtual PStringArray GetDeviceNames(int /*userData*/) const { return PVideoOutputDevice_Window::GetOutputDeviceNames(); }
    virtual bool         ValidateDeviceName(const PString & deviceName, int /*userData*/) const { return ParseWindowDeviceName(deviceName); }
} PVideoOutputDevice_Window_descriptor;

PCREATE_PLUGIN(Window, PVideoOutputDevice, &PVideoOutputDevice_Window_descriptor);


///////////////////////////////////////////////////////////////////////////////
// PVideoOutputDeviceRGB

PVideoOutputDevice_Window::PVideoOutputDevice_Window()
{
  m_hWnd = NULL;
  m_thread = NULL;
  m_flipped = PFalse;
  m_lastX = 0;
  m_lastY = 0;

  m_bitmap.bmiHeader.biSize = sizeof(m_bitmap.bmiHeader);
  m_bitmap.bmiHeader.biWidth = frameWidth;
  m_bitmap.bmiHeader.biHeight = -(int)frameHeight;
  m_bitmap.bmiHeader.biPlanes = 1;
  m_bitmap.bmiHeader.biBitCount = 32;
  m_bitmap.bmiHeader.biCompression = BI_RGB;
  m_bitmap.bmiHeader.biXPelsPerMeter = 0;
  m_bitmap.bmiHeader.biYPelsPerMeter = 0;
  m_bitmap.bmiHeader.biClrImportant = 0;
  m_bitmap.bmiHeader.biClrUsed = 0;
  m_bitmap.bmiHeader.biSizeImage = frameStore.GetSize();
}


PVideoOutputDevice_Window::~PVideoOutputDevice_Window()
{
  Close();
}


PStringArray PVideoOutputDevice_Window::GetOutputDeviceNames()
{
  return psprintf("MSWIN STYLE=0x%08X TITLE=\"%s\"", DEFAULT_STYLE, DEFAULT_TITLE);
}


PBoolean PVideoOutputDevice_Window::Open(const PString & name, PBoolean startImmediate)
{
  Close();

  m_openCloseMutex.Wait();

  deviceName = name;

  m_thread = PThread::Create(PCREATE_NOTIFIER(HandleDisplay), 0,
                             PThread::NoAutoDeleteThread, PThread::NormalPriority,
                             "VidOut:%x");

  m_openCloseMutex.Signal();
  m_started.Wait();

  PWaitAndSignal m(m_openCloseMutex);

  return startImmediate ? Start() : m_hWnd != NULL;
}


PBoolean PVideoOutputDevice_Window::IsOpen()
{
  return m_hWnd != NULL;
}


PBoolean PVideoOutputDevice_Window::Close()
{
  PWaitAndSignal m(m_openCloseMutex);

  if (m_hWnd == NULL)
      return PFalse;

  SendMessage(m_hWnd, WM_CLOSE, 0, 0);
  m_thread->WaitForTermination(3000);
  delete m_thread;
  m_thread = NULL;
  return PTrue;
}


PBoolean PVideoOutputDevice_Window::Start()
{
  PWaitAndSignal m(m_openCloseMutex);

  if (m_hWnd == NULL)
    return PFalse;
  
  ShowWindow(m_hWnd, SW_SHOW);
  return PTrue;
}


PBoolean PVideoOutputDevice_Window::Stop()
{
  PWaitAndSignal m(m_openCloseMutex);

  if (m_hWnd != NULL)
    return ShowWindow(m_hWnd, SW_HIDE);

  return PFalse;
}


PBoolean PVideoOutputDevice_Window::SetColourFormat(const PString & colourFormat)
{
  PWaitAndSignal m(mutex);

  if (((colourFormat *= "BGR24") || (colourFormat *= "BGR32")) &&
                PVideoOutputDeviceRGB::SetColourFormat(colourFormat)) {
    m_bitmap.bmiHeader.biBitCount = (WORD)(bytesPerPixel*8);
    m_bitmap.bmiHeader.biSizeImage = frameStore.GetSize();
    return PTrue;
  }

  return PFalse;
}


PBoolean PVideoOutputDevice_Window::GetVFlipState()
{
  return m_flipped;
}


PBoolean PVideoOutputDevice_Window::SetVFlipState(PBoolean newVFlip)
{
  m_flipped = newVFlip;
  m_bitmap.bmiHeader.biHeight = m_flipped ? frameHeight : -(int)frameHeight;
  return PTrue;
}


PBoolean PVideoOutputDevice_Window::SetFrameSize(unsigned width, unsigned height)
{
  {
    PWaitAndSignal m(mutex);

    if (width == frameWidth && height == frameHeight)
      return PTrue;

    if (!PVideoOutputDeviceRGB::SetFrameSize(width, height))
      return PFalse;

    m_bitmap.bmiHeader.biWidth = frameWidth;
    m_bitmap.bmiHeader.biHeight = m_flipped ? frameHeight : -(int)frameHeight;
    m_bitmap.bmiHeader.biSizeImage = frameStore.GetSize();
  }

  // Must be outside of mutex
  if (m_hWnd != NULL) {
    RECT rect;
    rect.top = 0;
    rect.left = 0;
    rect.bottom = frameHeight;
    rect.right = frameWidth;
    ::AdjustWindowRectEx(&rect, GetWindowLong(m_hWnd, GWL_STYLE), PFalse, 0L);
    ::SetWindowPos(m_hWnd, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, SWP_NOMOVE|SWP_NOZORDER);
  }

  return PTrue;
}


PBoolean PVideoOutputDevice_Window::FrameComplete()
{
  PWaitAndSignal m(mutex);

  if (m_hWnd == NULL)
    return PFalse;

  HDC hDC = GetDC(m_hWnd);
  Draw(hDC);
  ReleaseDC(m_hWnd, hDC);

  return PTrue;
}


PBoolean PVideoOutputDevice_Window::GetPosition(int & x, int & y) const
{
  x = m_lastX;
  y = m_lastY;
  return PTrue;
}


void PVideoOutputDevice_Window::Draw(HDC hDC)
{
  RECT rect;
  GetClientRect(m_hWnd, &rect);

  int result;
  if (frameWidth == (unsigned)rect.right && frameHeight == (unsigned)rect.bottom)
    result = SetDIBitsToDevice(hDC,
                               0, 0, frameWidth, frameHeight,
                               0, 0, 0, frameHeight,
                               frameStore.GetPointer(), &m_bitmap, DIB_RGB_COLORS);
  else
    result = StretchDIBits(hDC,
                           0, 0, rect.right, rect.bottom,
                           0, 0, frameWidth, frameHeight,
                           frameStore.GetPointer(), &m_bitmap, DIB_RGB_COLORS, SRCCOPY);

  if (result == 0) {
    lastError = ::GetLastError();
    PTRACE(2, "VidOut\tDrawing image failed, error=" << lastError);
  }
}


static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  if (uMsg == WM_CREATE)
    SetWindowLong(hWnd, 0, (LONG)((LPCREATESTRUCT)lParam)->lpCreateParams);

  PVideoOutputDevice_Window * vodw = (PVideoOutputDevice_Window *)GetWindowLong(hWnd, 0);
  if (vodw != NULL)
    return vodw->WndProc(uMsg, wParam, lParam);

  return DefWindowProc(hWnd, uMsg, wParam, lParam);
}


void PVideoOutputDevice_Window::HandleDisplay(PThread &, INT)
{
#ifndef _WIN32_WCE
  static const char wndClassName[] = "PVideoOutputDevice_Window";
#else
  static LPCWSTR wndClassName = L"PVideoOutputDevice_Window";
#endif

  static bool needRegistration = true;
  if (needRegistration) {
    needRegistration = false;

    WNDCLASS wndClass;
    memset(&wndClass, 0, sizeof(wndClass));
    wndClass.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
    wndClass.lpszClassName = wndClassName;
    wndClass.lpszClassName = wndClassName;
    wndClass.lpfnWndProc = ::WndProc;
    wndClass.cbWndExtra = sizeof(this);
    PAssertOS(RegisterClass(&wndClass));
  }

  DWORD dwStyle;
  HWND hParent;
  if (ParseWindowDeviceName(deviceName, &dwStyle, &hParent)) {
    PString title = DEFAULT_TITLE;

    PINDEX pos = deviceName.Find("TITLE=\"");
    if (pos != P_MAX_INDEX) {
      pos += 6;
      PINDEX quote = deviceName.FindLast('"');
      PString quotedTitle = deviceName(pos, quote > pos ? quote : P_MAX_INDEX);
      title = PString(PString::Literal, quotedTitle);
    }

    pos = deviceName.Find("X=");
    m_lastX = pos != P_MAX_INDEX ? atoi(&deviceName[pos+2]) : CW_USEDEFAULT;

    pos = deviceName.Find("Y=");
    m_lastY = pos != P_MAX_INDEX ? atoi(&deviceName[pos+2]) : CW_USEDEFAULT;

    PVarString windowTitle = title;
    m_hWnd = CreateWindow(wndClassName,
                          windowTitle, 
                          dwStyle,
                          m_lastX, m_lastY, frameWidth, frameHeight,
                          hParent, NULL, GetModuleHandle(NULL), this);
  }

  m_started.Signal();

  if (m_hWnd != NULL) {
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
      DispatchMessage(&msg);
  }
}


LRESULT PVideoOutputDevice_Window::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  PWaitAndSignal m(mutex);

  switch (uMsg) {
    case WM_PAINT :
      {
        PAINTSTRUCT paint;
        HDC hDC = BeginPaint(m_hWnd, &paint);
        Draw(hDC);
        EndPaint(m_hWnd, &paint);
        break;
      }

    case WM_MOVE :
      if (m_hWnd != NULL) {
        RECT rect;
        GetWindowRect(m_hWnd, &rect);
        m_lastX = rect.left;
        m_lastY = rect.top;
      }
      break;

    case WM_CLOSE :
      DestroyWindow(m_hWnd);
      m_hWnd = NULL;
      break;

    case WM_DESTROY:
      PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0, 0);
      break;
  }
  return DefWindowProc(m_hWnd, uMsg, wParam, lParam);
}

#endif // P_VIDEO



// End Of File ///////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -