/*
* main.cxx
*
* PWLib application source file for vidtest
*
* Main program entry point.
*
* Copyright (c) 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/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Contributor(s): ______________________________________.
*
* $Log: main.cxx,v $
* Revision 1.11 2005/11/30 12:47:41 csoutheren
* Removed tabs, reformatted some code, and changed tags for Doxygen
*
* Revision 1.10 2005/08/09 09:08:11 rjongbloed
* Merged new video code from branch back to the trunk.
*
* Revision 1.9.4.1 2005/07/17 09:25:30 rjongbloed
* Major revisions of the PWLib video subsystem including:
* removal of F suffix on colour formats for vertical flipping, all done with existing bool
* working through use of RGB and BGR formats so now consistent
* cleaning up the plug in system to use virtuals instead of pointers to functions.
* rewrite of SDL to be a plug in compatible video output device.
* extensive enhancement of video test program
*
* Revision 1.9 2005/03/10 08:10:57 dereksmithies
* Use a more descriptive name for the manufacturer.
*
* Revision 1.8 2004/04/20 00:19:31 dereksmithies
* Add code to generate compile time error if SDL is not installed.
*
* Revision 1.7 2004/01/18 14:20:26 dereksmithies
* Opening of video devices for plugins works now.
*
* Revision 1.6 2003/12/14 10:01:25 rjongbloed
* Resolved issue with name space conflict os static and virtual forms of GetDeviceNames() function.
*
* Revision 1.5 2003/12/08 01:28:52 dereksmithies
* Compiles now with new video plugins.
*
* Revision 1.4 2003/11/04 03:21:26 dereksmithies
* Fix compile on windows OS.
*
* Revision 1.3 2003/04/29 00:57:21 dereks
* Add user interface, option setting for format/input/fake. Works on Linux.
*
* Revision 1.2 2003/04/28 14:30:21 craigs
* Started rearranging code
*
* Revision 1.1 2003/04/28 08:18:42 craigs
* Initial version
*
*/
#include "precompile.h"
#include "main.h"
#include "version.h"
PCREATE_PROCESS(VidTest);
#include <ptlib/video.h>
#include <ptclib/vsdl.h>
VidTest::VidTest()
: PProcess("PwLib Video Example", "vidtest", 1, 0, ReleaseCode, 0)
{
grabber = NULL;
display = NULL;
}
bool ParseSize(const PString & sizeString, unsigned & width, unsigned & height)
{
if (sizeString *= "qcif") {
width = PVideoDevice::QCIFWidth;
height = PVideoDevice::QCIFHeight;
return true;
}
if (sizeString *= "cif") {
width = PVideoDevice::CIFWidth;
height = PVideoDevice::CIFHeight;
return true;
}
if ((sizeString *= "cif4") || (sizeString *= "4cif")) {
width = PVideoDevice::CIF4Width;
height = PVideoDevice::CIF4Height;
return true;
}
return sscanf(sizeString, "%ix%i", &width, &height) == 2 && width > 0 && height > 0;
}
void VidTest::Main()
{
PArgList & args = GetArguments();
args.Parse("h-help."
"-input-driver:"
"I-input-device:"
"-input-format:"
"-input-channel:"
"-output-driver:"
"O-output-device:"
"F-colour-format:"
"S-frame-size:"
"R-frame-rate:"
#if PTRACING
"o-output:" "-no-output."
"t-trace." "-no-trace."
#endif
);
#if PTRACING
PTrace::Initialise(args.GetOptionCount('t'),
args.HasOption('o') ? (const char *)args.GetOptionString('o') : NULL,
PTrace::Blocks | PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine);
#endif
if (args.HasOption('h')) {
PError << "Available options are: " << endl
<< endl
<< "--help : print this help message.\n"
<< "--input-driver drv : video grabber driver.\n"
<< "--input-device dev : video grabber device.\n"
<< "--input-format fmt : video grabber format (\"pal\"/\"ntsc\")\n"
<< "--input-channel num : video grabber channel.\n"
<< "--output-driver drv : video display driver to use.\n"
<< "--output-device dev : video display device to use.\n"
<< "--colour-format fmt : video colour size (\"rgb24\", \"yuv420\", etc)\n"
<< "--frame-size size : video frame size (\"qcif\", \"cif\", WxH)\n"
<< "--frame-rate size : video frame rate (frames/second)\n"
#if PTRACING
<< "-o or --output file : file name for output of log messages\n"
<< "-t or --trace : degree of verbosity in error log (more times for more detail)\n"
#endif
<< endl
<< " e.g. ./vidtest --videodevice Philips\\ 680\\ webcam --videosize small " << endl << endl;
return;
}
PINDEX i;
PString inputDriverName = args.GetOptionString("input-driver");
if (!inputDriverName.IsEmpty()) {
grabber = PVideoInputDevice::CreateDevice(inputDriverName);
if (grabber == NULL) {
cerr << "Cannot use input driver name \"" << inputDriverName << "\", must be one of:\n";
PStringList drivers = PVideoInputDevice::GetDriverNames();
for (i = 0; i < drivers.GetSize(); i++)
cerr << " " << drivers[i] << '\n';
cerr << endl;
return;
}
}
PStringList devices = PVideoInputDevice::GetDriversDeviceNames(inputDriverName);
if (devices.IsEmpty()) {
cerr << "No video input devices present";
if (!inputDriverName.IsEmpty())
cerr << " for driver \"" << inputDriverName << '"';
cerr << endl;
return;
}
PString inputDeviceName = args.GetOptionString("input-device");
if (inputDeviceName.IsEmpty())
inputDeviceName = devices[0];
if (grabber == NULL)
grabber = PVideoInputDevice::CreateDeviceByName(inputDeviceName);
if (grabber == NULL || !grabber->Open(inputDeviceName, false)) {
cerr << "Cannot use input device name \"" << inputDeviceName << "\", must be one of:\n";
for (i = 0; i < devices.GetSize(); i++)
cerr << " " << devices[i] << '\n';
cerr << endl;
return;
}
cout << "Grabber ";
if (!inputDriverName.IsEmpty())
cout << "driver \"" << inputDriverName << "\" and ";
cout << "device \"" << grabber->GetDeviceName() << "\" opened." << endl;
if (args.HasOption("input-format")) {
PVideoDevice::VideoFormat format;
PCaselessString formatString = args.GetOptionString("input-format");
if (formatString == "PAL")
format = PVideoDevice::PAL;
else if (formatString == "NTSC")
format = PVideoDevice::NTSC;
else if (formatString == "SECAM")
format = PVideoDevice::SECAM;
else if (formatString == "Auto")
format = PVideoDevice::Auto;
else {
cerr << "Illegal video input format name \"" << formatString << '"' << endl;
return;
}
if (!grabber->SetVideoFormat(format)) {
cerr << "Video input device could not be set to format \"" << formatString << '"' << endl;
return;
}
}
cout << "Grabber input format set to " << grabber->GetVideoFormat() << endl;
if (args.HasOption("input-channel")) {
int videoInput = args.GetOptionString("input-channel").AsInteger();
if (!grabber->SetChannel(videoInput)) {
cerr << "Video input device could not be set to channel " << videoInput << endl;
return;
}
}
cout << "Grabber input channel set to " << grabber->GetChannel() << endl;
int frameRate;
if (args.HasOption("frame-rate"))
frameRate = args.GetOptionString("frame-rate").AsInteger();
else
frameRate = 15;
if (!grabber->SetFrameRate(frameRate)) {
cerr << "Video input device could not be set to frame rate " << frameRate << endl;
return;
}
cout << "Grabber frame rate set to " << grabber->GetFrameRate() << endl;
PString outputDriverName = args.GetOptionString("output-driver");
if (!outputDriverName.IsEmpty()) {
display = PVideoOutputDevice::CreateDevice(outputDriverName);
if (display == NULL) {
cerr << "Cannot use output driver name \"" << inputDriverName << "\", must be one of:\n";
PStringList drivers = PVideoOutputDevice::GetDriverNames();
for (i = 0; i < drivers.GetSize(); i++)
cerr << " " << drivers[i] << '\n';
cerr << endl;
return;
}
}
devices = PVideoOutputDevice::GetDriversDeviceNames(outputDriverName);
if (devices.IsEmpty()) {
cerr << "No video output devices present";
if (!outputDriverName.IsEmpty())
cerr << " for driver \"" << outputDriverName << '"';
cerr << endl;
return;
}
PString outputDeviceName = args.GetOptionString("output-device");
if (outputDeviceName.IsEmpty()) {
outputDeviceName = devices[0];
if (outputDeviceName == "NULL" && devices.GetSize() > 1)
outputDeviceName = devices[1];
}
if (display == NULL)
display = PVideoOutputDevice::CreateDeviceByName(outputDeviceName);
if (display == NULL || !display->Open(outputDeviceName, false)) {
cerr << "Cannot use output device name \"" << outputDeviceName << "\", must be one of:\n";
for (i = 0; i < devices.GetSize(); i++)
cerr << " " << devices[i] << '\n';
cerr << endl;
return;
}
cout << "Display ";
if (!outputDriverName.IsEmpty())
cout << "driver \"" << outputDriverName << "\" and ";
cout << "device \"" << display->GetDeviceName() << "\" opened." << endl;
unsigned width, height;
if (args.HasOption("frame-size")) {
PString sizeString = args.GetOptionString("frame-size");
if (!ParseSize(sizeString, width, height)) {
cerr << "Illegal video frame size \"" << sizeString << '"' << endl;
return;
}
}
else {
width = PVideoDevice::QCIFWidth;
height = PVideoDevice::QCIFHeight;
}
if (!grabber->SetFrameSizeConverter(width, height, FALSE)) {
cerr << "Video input device could not be set to size " << width << 'x' << height << endl;
return;
}
cout << "Grabber frame size set to " << grabber->GetFrameWidth() << 'x' << grabber->GetFrameHeight() << endl;
if (!display->SetFrameSizeConverter(width, height, FALSE)) {
cerr << "Video output device could not be set to size " << width << 'x' << height << endl;
return;
}
cout << "Display frame size set to " << display->GetFrameWidth() << 'x' << display->GetFrameHeight() << endl;
PCaselessString colourFormat = args.GetOptionString("colour-format", "RGB24").ToUpper();
if (!grabber->SetColourFormatConverter(colourFormat) ) {
cerr << "Video input device could not be set to colour format \"" << colourFormat << '"' << endl;
return;
}
cout << "Grabber colour format set to " << grabber->GetColourFormat() << " (";
if (colourFormat == grabber->GetColourFormat())
cout << "native";
else
cout << "converted to " << colourFormat;
cout << ')' << endl;
if (!display->SetColourFormatConverter(colourFormat)) {
cerr << "Video output device could not be set to colour format \"" << colourFormat << '"' << endl;
return;
}
cout << "Diaplay colour format set to " << display->GetColourFormat() << " (";
if (colourFormat == display->GetColourFormat())
cout << "native";
else
cout << "converted from " << colourFormat;
cout << ')' << endl;
PThread::Create(PCREATE_NOTIFIER(GrabAndDisplay), 0,
PThread::NoAutoDeleteThread, PThread::NormalPriority,
"GrabAndDisplay");
// command line
for (;;) {
// display the prompt
cout << "vidtest> " << flush;
PCaselessString cmd;
cin >> cmd;
if (cmd == "q" || cmd == "x" || cmd == "quit" || cmd == "exit")
break;
if (cmd == "fg") {
if (!grabber->SetVFlipState(!grabber->GetVFlipState()))
cout << "\nCould not toggle Vflip state of video input device" << endl;
continue;
}
if (cmd == "fd") {
if (!display->SetVFlipState(!display->GetVFlipState()))
cout << "\nCould not toggle Vflip state of video output device" << endl;
continue;
}
unsigned width, height;
if (ParseSize(cmd, width, height)) {
pauseGrabAndDisplay.Signal();
if (!grabber->SetFrameSizeConverter(width, height, FALSE))
cout << "Video input device could not be set to size " << width << 'x' << height << endl;
if (!display->SetFrameSizeConverter(width, height, FALSE))
cout << "Video output device could not be set to size " << width << 'x' << height << endl;
resumeGrabAndDisplay.Signal();
continue;
}
cout << "Select:\n"
" fg : Flip video input top to bottom\n"
" fd : Flip video output top to bottom\n"
" qcif : Set size of grab & display to qcif\n"
" cif : Set size of grab & display to cif\n"
" WxH : Set size of grab & display W by H\n"
" Q or X : Exit program\n" << endl;
} // end for
cout << "Exiting." << endl;
exitGrabAndDisplay.Signal();
}
void VidTest::GrabAndDisplay(PThread &, INT)
{
PBYTEArray frame;
unsigned frameCount = 0;
bool oldGrabberState = true;
bool oldDisplayState = true;
grabber->Start();
display->Start();
PTimeInterval startTick = PTimer::Tick();
while (!exitGrabAndDisplay.Wait(0)) {
bool grabberState = grabber->GetFrame(frame);
if (oldGrabberState != grabberState) {
oldGrabberState = grabberState;
cerr << "Frame grab " << (grabberState ? "restored." : "failed!") << endl;
}
bool displayState = display->SetFrameData(0, 0, grabber->GetFrameWidth(), grabber->GetFrameHeight(), frame);
if (oldDisplayState != displayState)
{
oldDisplayState = displayState;
cerr << "Frame display " << (displayState ? "restored." : "failed!") << endl;
}
if (pauseGrabAndDisplay.Wait(0)) {
pauseGrabAndDisplay.Acknowledge();
resumeGrabAndDisplay.Wait();
}
frameCount++;
}
PTimeInterval duration = PTimer::Tick() - startTick;
cout << frameCount << " frames over " << duration << " seconds at " << (frameCount*1000.0/duration.GetMilliSeconds()) << " fps." << endl;
exitGrabAndDisplay.Acknowledge();
}
// End of File ///////////////////////////////////////////////////////////////
syntax highlighted by Code2HTML, v. 0.9.1