📄 shmvideo.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 + -