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

📄 shmvideo.cxx

📁 softphone client for test
💻 CXX
字号:
/*
 * shmvideo.h
 *
 * This file contains the class hierarchy for both shared memory video
 * input and output devices.
 *
 * Copyright (c) 2003 Pai-Hsiang Hsiao
 * Copyright (c) 1998-2003 Equivalence Pty. Ltd.
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * $Log: shmvideo.cxx,v $
 * Revision 1.2  2003/06/12 21:34:13  shawn
 * makes code consistent with documentation
 *
 * Revision 1.1  2003/06/12 19:39:11  shawn
 * Added shared memory video input/output devices.  Video frames of these two
 * devices are stored in a named shared memory region and can be accessed by
 * other applications.
 *
 *
 */

#ifdef USE_SHM_VIDEO_DEVICES

#include "shmvideo.h"

static char *
ShmKeyFileName()
{
  return "/dev/null";
}

BOOL
ShmVideoOutputDevice::shmInit()
{
  semLock = sem_open(SEM_NAME_OF_OUTPUT_DEVICE,
		     O_RDWR, S_IRUSR|S_IWUSR, 0);

  if ((int)semLock != SEM_FAILED) {
    shmKey = ftok(ShmKeyFileName(), 0);
    if (shmKey >= 0) {
      shmId = shmget(shmKey, SHMVIDEO_BUFSIZE, 0666);
      if (shmId >= 0) {
        shmPtr = shmat(shmId, NULL, 0);
        if (shmPtr) {
          return TRUE;
        }
        else {
          PTRACE(1, "SHMV\t shmInit can not attach shared memory" << endl);
          shmctl(shmId, IPC_RMID, NULL);
          sem_close(semLock);
        }
      }
      else {
        PTRACE(1, "SHMV\t shmInit can not find the shared memory" << endl);
        sem_close(semLock);
      }
    }
    else {
      PTRACE(1, "SHMV\t shmInit can not create key for shared memory" << endl);
      sem_close(semLock);
    }
  }
  else {
    PTRACE(1, "SHMV\t shmInit can not create semaphore" << endl);
  }

  semLock = (sem_t *)SEM_FAILED;
  shmKey = -1;
  shmId = -1;
  shmPtr = NULL;

  return FALSE;
}

ShmVideoOutputDevice::ShmVideoOutputDevice()
{
  semLock = (sem_t *)SEM_FAILED;
  shmKey = -1;
  shmId = -1;
  shmPtr = NULL;

  PTRACE(6, "SHMV\t Constructor of ShmVideoOutputDevice");
}

BOOL
ShmVideoOutputDevice::Open(const PString & name,
			   BOOL /*startImmediate*/)
{
  PTRACE(1, "SHMV\t Open of ShmVideoOutputDevice");

  Close();

  if (shmInit() == TRUE) {
    deviceName = name;
    return TRUE;
  }
  else {
    return FALSE;
  }
}

BOOL
ShmVideoOutputDevice::IsOpen()
{
  if ((int)semLock != SEM_FAILED) {
    return TRUE;
  }
  else {
    return FALSE;
  }
}

BOOL
ShmVideoOutputDevice::Close()
{
  if ((int)semLock != SEM_FAILED) {
    shmdt(shmPtr);
    sem_close(semLock);
    shmPtr = NULL;
  }
  return TRUE;
}

PStringList
ShmVideoOutputDevice::GetDeviceNames() const
{
  PStringList list;
  list += "shm";
  return list;
}

BOOL
ShmVideoOutputDevice::EndFrame()
{
  long *ptr = (long *)shmPtr;

  if ((int)semLock == SEM_FAILED) {
    return FALSE;
  }

  if (bytesPerPixel != 3 && bytesPerPixel != 4) {
    PTRACE(1, "SHMV\t EndFrame() does not handle bytesPerPixel!={3,4}"<<endl);
    return FALSE;
  }

  if (frameWidth*frameHeight*bytesPerPixel > SHMVIDEO_FRAMESIZE) {
    return FALSE;
  }

  // write header info so the consumer knows what to expect
  ptr[0] = frameWidth;
  ptr[1] = frameHeight;
  ptr[2] = bytesPerPixel;

  PTRACE(1, "writing " << frameStore.GetSize() << " bytes" << endl);
  if (memcpy((char *)shmPtr+sizeof(long)*3,
             frameStore, frameStore.GetSize()) == NULL) {
    return FALSE;
  }

  sem_post(semLock);

  return TRUE;
}

///////////////////////////////////////////////////////////////////////////////

BOOL
ShmVideoInputDevice::shmInit()
{
  semLock = sem_open(SEM_NAME_OF_INPUT_DEVICE,
		     O_RDWR, S_IRUSR|S_IWUSR, 0);

  if ((int)semLock != SEM_FAILED) {
    shmKey = ftok(ShmKeyFileName(), 100);
    if (shmKey >= 0) {
      shmId = shmget(shmKey, SHMVIDEO_BUFSIZE, 0666);
      if (shmId >= 0) {
        shmPtr = shmat(shmId, NULL, 0);
        if (shmPtr) {
          return TRUE;
        }
        else {
          PTRACE(1, "SHMV\t shmInit can not attach shared memory" << endl);
          shmctl(shmId, IPC_RMID, NULL);
          sem_close(semLock);
        }
      }
      else {
        PTRACE(1, "SHMV\t shmInit can not find the shared memory" << endl);
        sem_close(semLock);
      }
    }
    else {
      PTRACE(1, "SHMV\t shmInit can not create key for shared memory" << endl);
      sem_close(semLock);
    }
  }
  else {
    PTRACE(1, "SHMV\t shmInit can not create semaphore" << endl);
  }

  semLock = (sem_t *)SEM_FAILED;
  shmKey = -1;
  shmId = -1;
  shmPtr = NULL;

  return FALSE;
}

ShmVideoInputDevice::ShmVideoInputDevice()
{
  semLock = (sem_t *)SEM_FAILED;
  shmKey = -1;
  shmId = -1;
  shmPtr = NULL;

  PTRACE(6, "SHMV\t Constructor of ShmVideoInputDevice");
}

BOOL
ShmVideoInputDevice::Open(const PString & name,
			  BOOL /*startImmediate*/)
{
  PTRACE(1, "SHMV\t Open of ShmVideoInputDevice");

  Close();

  if (shmInit() == TRUE) {
    deviceName = name;
    return TRUE;
  }
  else {
    return FALSE;
  }
}

BOOL
ShmVideoInputDevice::IsOpen()
{
  if ((int)semLock != SEM_FAILED) {
    return TRUE;
  }
  else {
    return FALSE;
  }
}

BOOL
ShmVideoInputDevice::Close()
{
  if ((int)semLock != SEM_FAILED) {
    shmdt(shmPtr);
    sem_close(semLock);
    shmPtr = NULL;
  }
  return TRUE;
}

PStringList
ShmVideoInputDevice::GetInputDeviceNames()
{
  PStringList list;
  list += "shm";
  return list;
}

BOOL
ShmVideoInputDevice::GetFrameSizeLimits(unsigned & minWidth,
					unsigned & minHeight,
					unsigned & maxWidth,
					unsigned & maxHeight) 
{
  minWidth  = 176;
  minHeight = 144;
  maxWidth  = 352;
  maxHeight =  288;

  return TRUE;
}

static void RGBtoYUV420PSameSize (const BYTE *, BYTE *, unsigned, BOOL, 
                                  int, int);


#define rgbtoyuv(r, g, b, y, u, v) \
  y=(BYTE)(((int)30*r  +(int)59*g +(int)11*b)/100); \
  u=(BYTE)(((int)-17*r  -(int)33*g +(int)50*b+12800)/100); \
  v=(BYTE)(((int)50*r  -(int)42*g -(int)8*b+12800)/100); \



static void RGBtoYUV420PSameSize (const BYTE * rgb,
                                  BYTE * yuv,
                                  unsigned rgbIncrement,
                                  BOOL flip, 
                                  int srcFrameWidth, int srcFrameHeight) 
{
  const unsigned planeSize = srcFrameWidth*srcFrameHeight;
  const unsigned halfWidth = srcFrameWidth >> 1;
  
  // get pointers to the data
  BYTE * yplane  = yuv;
  BYTE * uplane  = yuv + planeSize;
  BYTE * vplane  = yuv + planeSize + (planeSize >> 2);
  const BYTE * rgbIndex = rgb;

  for (int y = 0; y < (int) srcFrameHeight; y++) {
    BYTE * yline  = yplane + (y * srcFrameWidth);
    BYTE * uline  = uplane + ((y >> 1) * halfWidth);
    BYTE * vline  = vplane + ((y >> 1) * halfWidth);

    if (flip)
      rgbIndex = rgb + (srcFrameWidth*(srcFrameHeight-1-y)*rgbIncrement);

    for (int x = 0; x < (int) srcFrameWidth; x+=2) {
      rgbtoyuv(rgbIndex[0], rgbIndex[1], rgbIndex[2],*yline, *uline, *vline);
      rgbIndex += rgbIncrement;
      yline++;
      rgbtoyuv(rgbIndex[0], rgbIndex[1], rgbIndex[2],*yline, *uline, *vline);
      rgbIndex += rgbIncrement;
      yline++;
      uline++;
      vline++;
    }
  }
}

BOOL
ShmVideoInputDevice::GetFrameData(BYTE * buffer, PINDEX * bytesReturned)
{    
  WaitFinishPreviousFrame();

  GetFrameDataNoDelay(buffer, bytesReturned);
  
  *bytesReturned= videoFrameSize;

  return TRUE;
}

BOOL
ShmVideoInputDevice::GetFrameDataNoDelay (BYTE *frame, PINDEX *i)
{
  long *bufPtr = (long *)shmPtr;

  unsigned width = 0;
  unsigned height = 0;
  unsigned rgbIncrement = 4;

  GetFrameSize (width, height);

  bufPtr[0] = width;
  bufPtr[1] = height;

  if (semLock != (sem_t *)SEM_FAILED && sem_trywait(semLock) == 0) {
    if (bufPtr[0] == (long)width && bufPtr[1] == (long)height) {
      rgbIncrement = bufPtr[2];
      RGBtoYUV420PSameSize ((BYTE *)(bufPtr+3), frame, rgbIncrement, FALSE, 
			    width, height);
      return TRUE;
    }
  }

  return FALSE;
}

#endif

⌨️ 快捷键说明

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