📄 vfakeio.cxx
字号:
BOOL PVideoInputDevice_FakeVideo::GetFrameData(BYTE * buffer, PINDEX * bytesReturned)
{
frameTimeError += msBetweenFrames;
PTime now;
PTimeInterval delay = now - previousFrameTime;
frameTimeError -= (int)delay.GetMilliSeconds();
previousFrameTime = now;
if (frameTimeError > 0) {
PTRACE(6, "FakeVideo\t Sleep for " << frameTimeError << " milli seconds");
PThread::Sleep(frameTimeError);
}
return GetFrameDataNoDelay(buffer, bytesReturned);
}
BOOL PVideoInputDevice_FakeVideo::GetFrameDataNoDelay(BYTE *destFrame, PINDEX * bytesReturned)
{
grabCount++;
// Make sure are NUM_PATTERNS cases here.
switch(channelNumber){
case eMovingBlocks :
GrabMovingBlocksTestFrame(destFrame);
break;
case eMovingLine :
GrabMovingLineTestFrame(destFrame);
break;
case eBouncingBoxes :
GrabBouncingBoxes(destFrame);
break;
case eBlankImage :
GrabBlankImage(destFrame);
break;
case eOriginalMovingBlocks :
GrabOriginalMovingBlocksFrame(destFrame);
break;
case eText :
GrabTextVideoFrame(destFrame);
break;
case eNTSCTest :
GrabNTSCTestFrame(destFrame);
break;
default :
return FALSE;
}
if (NULL != converter) {
if (!converter->Convert(destFrame, destFrame, bytesReturned))
return FALSE;
}
if (bytesReturned != NULL)
*bytesReturned = videoFrameSize;
return TRUE;
}
void PVideoInputDevice_FakeVideo::FillRect(BYTE * frame,
int xPos, int initialYPos,
int rectWidth, int rectHeight,
int r, int g, int b)
{
// PTRACE(0,"x,y is"<<xPos<<" "<<yPos<<" and size is "<<rectWidth<<" "<<rectHeight);
//This routine fills a region of the video image with data. It is used as the central
//point because one only has to add other image formats here.
if (bytesPerPixel > 2) {
for (int y = 0; y < rectHeight; y++) {
BYTE * ptr = frame + (initialYPos+y)*scanLineWidth + xPos*bytesPerPixel;
for (int x = 0; x < rectWidth; x++) {
*ptr++ = (BYTE)r;
*ptr++ = (BYTE)g;
*ptr++ = (BYTE)b;
if (bytesPerPixel > 3)
*ptr++ = 0;
}
}
return;
}
int yPos = initialYPos;
int offset = ( yPos * frameWidth ) + xPos;
int colourOffset = ( (yPos * frameWidth) >> 2) + (xPos >> 1);
int Y = ( 257 * r + 504 * g + 98 * b)/1000 + 16;
int Cb = (-148 * r - 291 * g + 439 * b)/1000 + 128;
int Cr = ( 439 * r - 368 * g - 71 * b)/1000 + 128;
unsigned char * Yptr = frame + offset;
unsigned char * CbPtr = frame + (frameWidth * frameHeight) + colourOffset;
unsigned char * CrPtr = frame + (frameWidth * frameHeight) + (frameWidth * frameHeight/4) + colourOffset;
int rr ;
int halfRectWidth = rectWidth >> 1;
int halfWidth = frameWidth >> 1;
for (rr = 0; rr < rectHeight;rr+=2) {
memset(Yptr, Y, rectWidth);
Yptr += frameWidth;
memset(Yptr, Y, rectWidth);
Yptr += frameWidth;
memset(CbPtr, Cb, halfRectWidth);
memset(CrPtr, Cr, halfRectWidth);
CbPtr += halfWidth;
CrPtr += halfWidth;
}
}
void PVideoInputDevice_FakeVideo::GrabBouncingBoxes(BYTE *resFrame)
{
FillRect(resFrame,
0, 0, frameWidth, frameHeight, //Fill the whole frame with the colour.
200,200,200); //a light grey colour.
double t= (grabCount%50) -25 ;
double h= t*t*frameHeight*0.85/625;
int yBox = (int)h;
yBox= (yBox>>1) * 2; //yBox is even.
int boxHeight= (int)(frameHeight*0.1);
boxHeight= (boxHeight >>1) * 2;
int boxWidth = (int)(frameWidth*0.1);
boxWidth = (boxWidth >>1) * 2;
FillRect(resFrame,
frameWidth >> 2, yBox, boxWidth, boxHeight,
255, 0, 0); // Red Box.
t= (grabCount%40) -20 ;
h= t*t*frameHeight*0.85/400 ;
yBox = (int)h;
yBox= (yBox>>1) * 2; //yBox is even.
FillRect(resFrame,
frameWidth>>1, yBox, boxWidth, boxHeight,
0, 255, 0); // Green
t= (grabCount%100) -50 ;
h= t*t*frameHeight*0.85/2500;
yBox = (int)h;
yBox= (yBox>>1) * 2; //yBox is even.
FillRect(resFrame,
(frameWidth>>1) + (frameWidth>>2), yBox, boxWidth, boxHeight,
0, 0, 255); // Blue
}
void PVideoInputDevice_FakeVideo::GrabNTSCTestFrame(BYTE *resFrame)
{
// Test image # 1
// A static image is generated, consisting of a series of coloured block.
// Sample NTSC test frame is found at http://www.displaymate.com/patterns.html
//
static int row1[7][3] = {
{ 204, 204, 204 }, // 80% grey
{ 255, 255, 0 }, // yellow
{ 0, 255, 255 }, // cyan
{ 0, 255, 0 }, // green
{ 255, 0, 255 }, // magenta
{ 255, 0, 0 }, // red
{ 0, 0, 255 }, // blue
};
static int row2[7][3] = {
{ 0, 0, 255 }, // blue
{ 19, 19, 19 }, // black
{ 255, 0, 255 }, // magenta
{ 19, 19, 19 }, // black
{ 0, 255, 255 }, // cyan
{ 19, 19, 19 }, // black
{ 204, 204, 204 }, // grey
};
static int row3a[4][3] = {
{ 8, 62, 89 }, // I
{ 255, 255, 255 }, // white
{ 58, 0, 126 }, // +Q
{ 19, 19, 19 }, // black
};
static int row3b[3][3] = {
{ 0, 0, 0 }, // 3.5
{ 19, 19, 19 }, // 7.5
{ 38, 38, 38 }, // 11.5
};
static int row3c[3] = { 19, 19, 19 };
int row1Height = (int)(0.66 * frameHeight);
int row2Height = (int)((0.75 * frameHeight) - row1Height);
row1Height = (row1Height>>1)*2; //Require that height is even.
row2Height = (row2Height>>1)*2;
int row3Height = frameHeight - row1Height - row2Height;
int columns[8];
PINDEX i;
for(i=0;i<7;i++) {
columns[i]= i*frameWidth/7;
columns[i]= (columns[i]>>1)*2; // require that columns[i] is even.
}
columns[7] = frameWidth;
// first row
for (i = 0; i < 6; i++)
FillRect(resFrame,
columns[i], 0, columns[i+1]-columns[i], row1Height, //x,y,w,h
row1[i][0], row1[i][1], row1[i][2]); // rgb
// second row
for (i = 0; i < 7; i++)
FillRect(resFrame,
columns[i], row1Height, columns[i+1]-columns[i], row2Height,
row2[i][0], row2[i][1], row2[i][2]);
// third row
int columnBot[5];
for (i=0; i<4; i++) {
columnBot[i]= i*columns[5]/4;
columnBot[i] = 2 * (columnBot[i]>>1);
}
columnBot[4]= columns[5];
for (i = 0; i < 4; i++)
FillRect(resFrame,
columnBot[i],row1Height + row2Height, columnBot[i+1]-columnBot[i], row3Height,
row3a[i][0], row3a[i][1], row3a[i][2]);
for (i=0; i<3; i++) {
columnBot[i] = columns[4]+(i*frameWidth)/(7*3);
columnBot[i] = 2 * (columnBot[i]>>1); //Force even.
}
columnBot[3]= columns[5];
for (i = 0; i < 3; i++)
FillRect(resFrame,
columnBot[i], row1Height + row2Height, columnBot[i+1] - columnBot[i], row3Height,
row3b[i][0], row3b[i][1], row3b[i][2]);
FillRect(resFrame,
columns[6], row1Height + row2Height, columns[7] - columns[6], row3Height,
row3c[0], row3c[1], row3c[2]);
}
void PVideoInputDevice_FakeVideo::GrabMovingBlocksTestFrame(BYTE * resFrame)
{
// Test image # 2
/*Brightness is set to alter, left to right.
Colour component alters top to bottom.
Image contains lots of high and low resolution areas.
*/
unsigned wi,hi, colourIndex,colNo, boxSize;
#define COL(b,x,y) ((b+x+y)%7)
static int background[7][3] = {
{ 254, 254, 254 }, // white
{ 255, 255, 0 }, // yellow
{ 0, 255, 255 }, // cyan
{ 0, 255, 0 }, // green
{ 255, 0, 255 }, // magenta
{ 255, 0, 0 }, // red
{ 0, 0, 255 }, // blue
};
int columns[9];
int heights[9];
int offset;
offset = (frameWidth >> 3) & 0xffe;
for(wi = 0; wi < 8; wi++)
columns[wi] = wi * offset;
columns[8] = frameWidth;
offset = (frameHeight >> 3) & 0xffe;
for(hi = 0; hi < 9; hi++)
heights[hi] = hi * offset;
heights[8] = frameHeight;
grabCount++;
colourIndex = time(NULL);//time in seconds since last epoch.
// Provides a difference if run on two ohphone sessions.
colNo = (colourIndex / 10) % 7; //Every 10 seconds, coloured background blocks move.
for(hi = 0; hi < 8; hi++) //Fill the background in.
for(wi = 0 ; wi < 8; wi++) {
FillRect(resFrame,
columns[wi], heights[hi], columns[wi + 1] - columns[wi], heights[hi + 1] - heights[hi],
background[COL(colNo, wi, hi)][0], background[COL(colNo, wi, hi)][1], background[COL(colNo, wi, hi)][2]);
}
//Draw a black box rapidly moving down the left of the window.
boxSize= frameHeight / 10;
hi = ((3 * colourIndex) % (frameHeight-boxSize)) & 0xffe; //Make certain hi is even.
FillRect(resFrame, 10, hi, boxSize, boxSize, 0, 0, 0); //Black Box.
//Draw four parallel black lines, which move up the middle of the window.
colourIndex = colourIndex / 3; //Every three seconds, lines move.
for(wi = 0; wi < 2; wi++)
columns[wi]= (((wi + 1) * frameWidth) / 3) & 0xffe;// Force columns to be even.
hi = colourIndex % ((frameHeight - 16) / 2);
hi = (frameHeight - 16) - (hi * 2); //hi is even, Lines move in opp. direction to box.
unsigned yi;
for(yi = 0; yi < 4; yi++)
FillRect(resFrame,
columns[0], hi+(yi * 4), columns[1] - columns[0], 2,
0, 0, 0);
}
void PVideoInputDevice_FakeVideo::GrabMovingLineTestFrame(BYTE *resFrame)
{
// Test image # 3
// Faster image generation. Same every times system runs.
// Colours cycle through. Have a vertical lines style of pattern.
// There is a horizontal bar which moves down the screen .
static int v=0;
int r,g,b;
v++;
r = (200+v) & 255;
g = (100+v) & 255;
b = (000+v) & 255;
FillRect(resFrame, 0, 0,frameWidth, frameHeight, r, g, b);
int hi = (v % (frameHeight-2) >> 1) *2;
FillRect(resFrame, 0, hi, frameWidth, 2, 0, 0, 0);
}
void PVideoInputDevice_FakeVideo::GrabBlankImage(BYTE *resFrame)
{
// Change colour every second, cycle is:
// black, red, green, yellow, blue, magenta, cyan, white
int mask = grabCount/frameRate;
FillRect(resFrame,
0, 0, frameWidth, frameHeight, //Fill the whole frame with the colour.
(mask&1) ? 255 : 0, // red
(mask&2) ? 255 : 0, // green
(mask&4) ? 255 : 0);//blue
}
void PVideoInputDevice_FakeVideo::GrabOriginalMovingBlocksFrame(BYTE *frame)
{
unsigned wi,hi,colourIndex,colourNumber;
int framesize = frameWidth*frameHeight;
static int gCount=0;
gCount++;
colourIndex = gCount/10;
colourNumber= (colourIndex/10)%7; //Every 10 seconds, coloured background blocks move.
for(hi=0; hi<frameHeight; hi++) //slow moving group of lines going upwards.
for(wi=0; wi<frameWidth; wi++)
if ( (wi>frameWidth/3)&&(wi<frameWidth*2/3)&&
( ((gCount+hi)%frameHeight)<16)&&
( (hi%4)<2) )
frame[(hi*frameWidth)+wi] = 16;
else
frame[(hi*frameWidth)+wi] = (BYTE)(((colourNumber+((wi*7)/frameWidth))%7)*35+26);
for(hi=1; hi<=frameHeight; hi++) //fast moving block going downwards.
for(wi=frameWidth/9; wi<(2*frameWidth/9); wi++)
if( (( (gCount*4)+hi)%frameHeight)<20)
frame[((frameHeight-hi)*frameWidth)+wi] = 16;
unsigned halfWidth = frameWidth/2;
unsigned halfHeight = frameHeight/2;
for(hi=1; hi<halfHeight; hi++)
for(wi=0; wi<halfWidth; wi++)
frame[framesize+(hi*halfWidth)+wi] = (BYTE)(((((hi*7)/halfHeight)+colourNumber)%7)*35+26);
}
void PVideoInputDevice_FakeVideo::GrabTextVideoFrame(BYTE *resFrame)
{
PINDEX i, j;
static PTime startTime;
grabCount++;
FillRect(resFrame,
0, 0, frameWidth, frameHeight, //Fill the whole frame with the colour.
200, 200, 200); //a light grey colour.
if (textLine[0].GetLength() < 2) {
PStringStream message;
message << PProcess::Current().GetUserName() << " on " <<
PProcess::Current().GetOSName() << ":" <<
PProcess::Current().GetOSHardware();
PINDEX nChars = message.GetLength();
PVideoFont::LetterData *ld;
for (j = 0; j < PVideoFont::MAX_L_HEIGHT; j++)
textLine[j] = "";
for (i = 0; i < (nChars + 2); i++){
if (i >= nChars)
ld = PVideoFont::GetLetterData(' ');
else
ld = PVideoFont::GetLetterData(message[i]);
if (ld == NULL)
continue;
for (j = 0; j < PVideoFont::MAX_L_HEIGHT; j++)
textLine[j] += ld->line[j] + PString(" ");
}
}
PINDEX boxSize = (frameHeight / (PVideoFont::MAX_L_HEIGHT * 2) ) & 0xffe;
int index = (int)((PTime() - startTime).GetMilliSeconds() / 300);
PINDEX maxI = (frameWidth / boxSize) - 2;
for (i = 0; i < maxI; i++)
for (j = 0; j < PVideoFont::MAX_L_HEIGHT; j++) {
PINDEX ii = (index + i) % textLine[0].GetLength();
if (textLine[j][ii] != ' ')
FillRect(resFrame,
(i + 1) * boxSize, (frameHeight / 3) + ((j + 1) * boxSize), //x,y start pos
boxSize, boxSize, //x,y dimension
250, 00, 00); //red box.
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/**This class defines a NULL video output device.
This will do precisely nothing with the output.
*/
class PVideoOutputDevice_NULLOutput : public PVideoOutputDevice
{
PCLASSINFO(PVideoOutputDevice_NULLOutput, PVideoOutputDevice);
public:
/** Create a new video output device.
*/
PVideoOutputDevice_NULLOutput();
/**Get a list of all of the drivers available.
*/
static PStringList GetOutputDeviceNames();
virtual PStringList GetDeviceNames() const
{ return GetOutputDeviceNames(); }
/**Open the device given the device name.
*/
virtual BOOL Open(
const PString & deviceName, /// Device name to open
BOOL startImmediate = TRUE /// Immediately start device
);
/**Start the video device I/O.
*/
BOOL Start();
/**Stop the video device I/O capture.
*/
BOOL Stop();
/**Close the device.
*/
virtual BOOL Close();
/**Determine if the device is currently open.
*/
virtual BOOL IsOpen();
/**Get the maximum frame size in bytes.
Note a particular device may be able to provide variable length
frames (eg motion JPEG) so will be the maximum size of all frames.
*/
virtual PINDEX GetMaxFrameBytes();
/**Set a section of the output frame buffer.
*/
virtual BOOL SetFrameData(
unsigned x,
unsigned y,
unsigned width,
unsigned height,
const BYTE * data,
BOOL endFrame = TRUE
);
/**Indicate frame may be displayed.
*/
virtual BOOL EndFrame();
};
PCREATE_VIDOUTPUT_PLUGIN(NULLOutput);
///////////////////////////////////////////////////////////////////////////////
// PVideoOutputDevice_NULLOutput
PVideoOutputDevice_NULLOutput::PVideoOutputDevice_NULLOutput()
{
deviceName = "NULL";
}
BOOL PVideoOutputDevice_NULLOutput::Open(const PString & /*deviceName*/,
BOOL /*startImmediate*/)
{
return TRUE;
}
BOOL PVideoOutputDevice_NULLOutput::Close()
{
return TRUE;
}
BOOL PVideoOutputDevice_NULLOutput::Start()
{
return TRUE;
}
BOOL PVideoOutputDevice_NULLOutput::Stop()
{
return TRUE;
}
BOOL PVideoOutputDevice_NULLOutput::IsOpen()
{
return TRUE;
}
PStringList PVideoOutputDevice_NULLOutput::GetOutputDeviceNames()
{
PStringList list;
list += "NULL";
return list;
}
PINDEX PVideoOutputDevice_NULLOutput::GetMaxFrameBytes()
{
return GetMaxFrameBytesConverted(CalculateFrameBytes(frameWidth, frameHeight, colourFormat));
}
BOOL PVideoOutputDevice_NULLOutput::SetFrameData(unsigned /*x*/, unsigned /*y*/,
unsigned /*width*/, unsigned /*height*/,
const BYTE * /*data*/,
BOOL /*endFrame*/)
{
return TRUE;
}
BOOL PVideoOutputDevice_NULLOutput::EndFrame()
{
return TRUE;
}
// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -