Revision: 8829
http://playerstage.svn.sourceforge.net/playerstage/?rev=8829&view=rev
Author: jpgr87
Date: 2010-07-23 02:36:37 +0000 (Fri, 23 Jul 2010)
Log Message:
-----------
Applied patch #3029974: Player SVN: extended camera interface
Modified Paths:
--------------
code/player/trunk/client_libs/libplayerc/dev_camera.c
code/player/trunk/client_libs/libplayerc/playerc.h
code/player/trunk/libplayerinterface/interfaces/040_camera.def
code/player/trunk/server/drivers/camera/compress/cameracompress.cc
code/player/trunk/server/drivers/camera/cvcam/cvcam.cc
code/player/trunk/server/drivers/camera/v4l2/camerav4l2.cc
Modified: code/player/trunk/client_libs/libplayerc/dev_camera.c
===================================================================
--- code/player/trunk/client_libs/libplayerc/dev_camera.c 2010-07-22
16:01:47 UTC (rev 8828)
+++ code/player/trunk/client_libs/libplayerc/dev_camera.c 2010-07-23
02:36:37 UTC (rev 8829)
@@ -49,6 +49,8 @@
#endif
#include <math.h>
+#include <stddef.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if !defined (WIN32)
@@ -60,6 +62,7 @@
#if defined (WIN32)
#define snprintf _snprintf
+ #define strdup _strdup
#endif
// Local declarations
@@ -123,7 +126,7 @@
if (device->image)
memcpy(device->image, data->image, device->image_count);
else
- PLAYERC_ERR1("failed to allocate memory for image, needed %ld bytes\n",
sizeof(device->image[0])*device->image_count);
+ PLAYERC_ERR1("failed to allocate memory for image, needed %u bytes\n",
sizeof(device->image[0])*device->image_count);
}
else
PLAYERC_WARN2("skipping camera message with unknown type/subtype: %s/%d\n",
@@ -150,11 +153,11 @@
// Copy uncompress image
device->image_count = dst_size;
- device->image = realloc(device->image,
sizeof(device->image[0])*device->image_count);
+ device->image = realloc(device->image, (sizeof device->image[0]) *
device->image_count);
if (device->image)
memcpy(device->image, dst, dst_size);
else
- PLAYERC_ERR1("failed to allocate memory for image, needed %ld bytes\n",
sizeof(device->image[0])*device->image_count);
+ PLAYERC_ERR1("failed to allocate memory for image, needed %u bytes\n",
(sizeof device->image[0]) * device->image_count);
free(dst);
// Pixels are now raw
@@ -214,3 +217,85 @@
return;
}
+
+// Set source channel.
+int
+playerc_camera_set_source(playerc_camera_t *device,
+ int source,
+ const char * norm)
+{
+ player_camera_source_t src;
+
+ memset(&src, 0, sizeof src);
+ src.norm_count = strlen(norm) + 1;
+ src.norm = strdup(norm);
+ if (!(src.norm)) return -1;
+ src.source = source;
+ if (playerc_client_request(device->info.client, &device->info,
+ PLAYER_CAMERA_REQ_SET_SOURCE,
+ (void*)(&src), NULL) < 0)
+ {
+ free(src.norm);
+ return -1;
+ }
+ // if the set suceeded copy them locally
+ snprintf(device->norm, sizeof device->norm, "%s", src.norm);
+ free(src.norm);
+ device->source = src.source;
+ return 0;
+}
+
+// Get the source channel.
+int
+playerc_camera_get_source(playerc_camera_t *device)
+{
+ player_camera_source_t * src;
+
+ if (playerc_client_request(device->info.client, &device->info,
+ PLAYER_CAMERA_REQ_GET_SOURCE,
+ NULL, (void**)&src) < 0)
+ return -1;
+ snprintf(device->norm, sizeof device->norm, "%s", src->norm);
+ device->source = src->source;
+ player_camera_source_t_free(src);
+ return 0;
+}
+
+// Force to get current image.
+int
+playerc_camera_get_image(playerc_camera_t *device)
+{
+ player_camera_data_t * data;
+
+ if (playerc_client_request(device->info.client, &device->info,
+ PLAYER_CAMERA_REQ_GET_IMAGE,
+ NULL, (void**)&data) < 0)
+ return -1;
+ device->width = data->width;
+ device->height = data->height;
+ device->bpp = data->bpp;
+ device->format = data->format;
+ device->fdiv = data->fdiv;
+ device->compression = data->compression;
+ device->image_count = data->image_count;
+ device->image = realloc(device->image, (sizeof device->image[0]) *
device->image_count);
+ if (device->image)
+ memcpy(device->image, data->image, device->image_count);
+ else
+ PLAYERC_ERR1("failed to allocate memory for image, needed %u bytes\n",
(sizeof device->image[0]) * device->image_count);
+ player_camera_data_t_free(data);
+ return 0;
+}
+
+// Copy image to some pre-allocated place.
+void
+playerc_camera_copy_image(playerc_camera_t * device, void * dst, size_t
dst_size)
+{
+ memcpy(dst, device->image, (dst_size <= (device->image_count)) ? dst_size :
(device->image_count));
+}
+// @brief Get given component of given pixel.
+unsigned
+playerc_camera_get_pixel_component(playerc_camera_t * device, unsigned int x,
unsigned int y, int component)
+{
+ return (unsigned)(device->image[(y * device->width * ((device->bpp)>>3)) +
(x * ((device->bpp)>>3)) + component]);
+}
Modified: code/player/trunk/client_libs/libplayerc/playerc.h
===================================================================
--- code/player/trunk/client_libs/libplayerc/playerc.h 2010-07-22 16:01:47 UTC
(rev 8828)
+++ code/player/trunk/client_libs/libplayerc/playerc.h 2010-07-23 02:36:37 UTC
(rev 8829)
@@ -1423,6 +1423,10 @@
*/
uint8_t *image;
+ /** Norm and source channel, filled by playerc_camera_get_source(). */
+ char norm[16];
+ int source;
+
} playerc_camera_t;
@@ -1444,6 +1448,21 @@
/** @brief Saves the image to disk as a .ppm */
PLAYERC_EXPORT void playerc_camera_save(playerc_camera_t *device, const char
*filename);
+/** @brief Set source channel. */
+PLAYERC_EXPORT int playerc_camera_set_source(playerc_camera_t *device, int
source, const char *norm);
+
+/** @brief Get source channel (sets norm and source fields in the current
proxy data). */
+PLAYERC_EXPORT int playerc_camera_get_source(playerc_camera_t *device);
+
+/** @brief Force to get current image. */
+PLAYERC_EXPORT int playerc_camera_get_image(playerc_camera_t *device);
+
+/** @brief Copy image to some pre-allocated place. */
+PLAYERC_EXPORT void playerc_camera_copy_image(playerc_camera_t * device, void
* dst, size_t dst_size);
+
+/** @brief Get given component of given pixel. */
+PLAYERC_EXPORT unsigned playerc_camera_get_pixel_component(playerc_camera_t *
device, unsigned int x, unsigned int y, int component);
+
/** @} */
/**************************************************************************/
Modified: code/player/trunk/libplayerinterface/interfaces/040_camera.def
===================================================================
--- code/player/trunk/libplayerinterface/interfaces/040_camera.def
2010-07-22 16:01:47 UTC (rev 8828)
+++ code/player/trunk/libplayerinterface/interfaces/040_camera.def
2010-07-23 02:36:37 UTC (rev 8829)
@@ -10,6 +10,13 @@
message { DATA, STATE, 1, player_camera_data_t };
+/** Request/reply subtype: get current source */
+message { REQ, GET_SOURCE, 1, player_camera_source_t };
+/** Request/reply subtype: set current source */
+message { REQ, SET_SOURCE, 2, player_camera_source_t };
+/** Request/reply subtype: get current image frame */
+message { REQ, GET_IMAGE, 3, player_camera_data_t };
+
/** Image format : 8-bit monochrome. */
#define PLAYER_CAMERA_FORMAT_MONO8 1
/** Image format : 16-bit monochrome (network byte order). */
@@ -49,3 +56,15 @@
to network byte ordering. */
uint8_t *image;
} player_camera_data_t;
+
+/** @brief Request/reply: Get/set current source.
+
+Send a @ref PLAYER_CAMEARA_REQ_SET_SOURCE request change image source
+(assuming your hardware supports it). */
+typedef struct player_camera_source
+{
+ /** Norm (one of "NTSC", "PAL", "SECAM", "UNKNOWN"). */
+ uint32_t norm_count;
+ char * norm;
+ int32_t source;
+} player_camera_source_t;
Modified: code/player/trunk/server/drivers/camera/compress/cameracompress.cc
===================================================================
--- code/player/trunk/server/drivers/camera/compress/cameracompress.cc
2010-07-22 16:01:47 UTC (rev 8828)
+++ code/player/trunk/server/drivers/camera/compress/cameracompress.cc
2010-07-23 02:36:37 UTC (rev 8829)
@@ -55,12 +55,12 @@
@par Configuration file options
-- check_timestamps (int)
+- check_timestamps (integer)
- Default: 0
- If non-zero, timestamps are checked so only new images are compressed
and published.
-- save (int)
+- save (integer)
- Default: 0
- If non-zero, uncompressed images are saved to disk (with a .jpeg extension)
@@ -68,6 +68,10 @@
- Default: 0.8
- Image quality for JPEG compression
+- request_only (integer)
+ - Default: 0
+ - If set to 1, data will be sent only at PLAYER_CAMEARA_REQ_GET_IMAGE
response.
+
@par Example
@verbatim
@@ -113,7 +117,7 @@
// Main function for device thread.
private: virtual void Main();
- private: void ProcessImage(player_camera_data_t & rawdata);
+ private: int ProcessImage(player_camera_data_t & rawdata);
// Input camera device
private:
@@ -131,9 +135,11 @@
private: double quality;
// Save image frames?
- private: int check_timestamps;
+
private: int save;
private: int frameno;
+ private: int check_timestamps;
+ private: int request_only;
};
@@ -166,6 +172,7 @@
this->check_timestamps = cf->ReadInt(section, "check_timestamps", 0);
this->save = cf->ReadInt(section, "save", 0);
this->quality = cf->ReadFloat(section, "image_quality", 0.8);
+ this->request_only = cf->ReadInt(section, "request_only", 0);
return;
}
@@ -208,20 +215,48 @@
int CameraCompress::ProcessMessage(QueuePointer & resp_queue, player_msghdr *
hdr,
void * data)
{
+ player_camera_data_t * imgData;
+ Message * msg;
+
assert(hdr);
-
- if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_DATA,
PLAYER_CAMERA_DATA_STATE, camera_id))
+ if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_DATA,
PLAYER_CAMERA_DATA_STATE, this->camera_id))
{
assert(data);
- player_camera_data_t * recv = reinterpret_cast<player_camera_data_t * >
(data);
+ imgData = reinterpret_cast<player_camera_data_t * >(data);
+ if (this->request_only) return 0;
if ((!(this->check_timestamps)) || (this->camera_time != hdr->timestamp))
{
this->camera_time = hdr->timestamp;
- ProcessImage(*recv);
+ if (!(this->ProcessImage(*imgData))) this->Publish(device_addr,
PLAYER_MSGTYPE_DATA, PLAYER_CAMERA_DATA_STATE, reinterpret_cast<void
*>(&(this->data)), 0, &this->camera_time);
+ // don't delete anything here! this->data.image is required and is
deleted somewhere else
}
return 0;
+ } else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
PLAYER_CAMERA_REQ_GET_IMAGE, this->device_addr))
+ {
+ msg = this->camera->Request(this->InQueue, PLAYER_MSGTYPE_REQ,
PLAYER_CAMERA_REQ_GET_IMAGE, NULL, 0, NULL);
+ if (!msg) return -1;
+ if ((msg->GetDataSize()) < (sizeof(player_camera_data_t)))
+ {
+ delete msg;
+ return -1;
+ }
+ imgData = reinterpret_cast<player_camera_data_t *>(msg->GetPayload());
+ if (!imgData)
+ {
+ delete msg;
+ return -1;
+ }
+ this->camera_time = hdr->timestamp;
+ if (!(this->ProcessImage(*imgData))) this->Publish(this->device_addr,
+ resp_queue,
+ PLAYER_MSGTYPE_RESP_ACK,
+
PLAYER_CAMERA_REQ_GET_IMAGE,
+ reinterpret_cast<void
*>(&(this->data)),
+ 0, &this->camera_time);
+ // don't delete anything here! this->data.image is required and is deleted
somewhere else
+ delete msg;
+ return 0;
}
-
return -1;
}
@@ -235,22 +270,21 @@
// Test if we are suppose to cancel this thread.
pthread_testcancel();
- ProcessMessages();
+ this->ProcessMessages();
}
- return;
}
-void CameraCompress::ProcessImage(player_camera_data_t & rawdata)
+int CameraCompress::ProcessImage(player_camera_data_t & rawdata)
{
char filename[256];
unsigned char * ptr, * ptr1;
- int i, l;
+ int i, l, ret;
+ FILE * fp;
unsigned char * buffer = NULL;
-
if ((rawdata.width <= 0) || (rawdata.height <= 0))
{
- if (!(this->data.image)) return;
+ if (!(this->data.image)) return -1;
} else if (rawdata.compression == PLAYER_CAMERA_COMPRESS_RAW)
{
switch (rawdata.bpp)
@@ -288,7 +322,7 @@
break;
default:
PLAYER_WARN("unsupported image depth (not good)");
- return;
+ return -1;
}
if (this->data.image) delete []this->data.image;
this->data.image = new unsigned char[(rawdata.width) * (rawdata.height) *
3];
@@ -303,6 +337,7 @@
this->data.height = (rawdata.height);
this->data.bpp = 24;
this->data.format = PLAYER_CAMERA_FORMAT_RGB888;
+ this->data.fdiv = (rawdata.fdiv);
this->data.compression = PLAYER_CAMERA_COMPRESS_JPEG;
this->data.image_count = (this->data.image_count);
} else
@@ -315,6 +350,7 @@
this->data.height = (rawdata.height);
this->data.bpp = (rawdata.bpp);
this->data.format = (rawdata.format);
+ this->data.fdiv = (rawdata.fdiv);
this->data.compression = (rawdata.compression);
this->data.image_count = (rawdata.image_count);
}
@@ -328,13 +364,13 @@
#else
snprintf(filename, sizeof(filename), "click-%04d.jpeg",this->frameno++);
#endif
- FILE *fp = fopen(filename, "w+");
- int ret = fwrite(this->data.image, 1, this->data.image_count, fp);
- if (ret < 0)
- PLAYER_ERROR("Failed to save frame");
- fclose(fp);
+ fp = fopen(filename, "w+");
+ if (fp)
+ {
+ ret = fwrite(this->data.image, 1, this->data.image_count, fp);
+ if (ret < 0) PLAYER_ERROR("Failed to save frame");
+ fclose(fp);
+ }
}
-
- Publish(device_addr, PLAYER_MSGTYPE_DATA, PLAYER_CAMERA_DATA_STATE, (void*)
&this->data, 0, &this->camera_time);
- // don't delete anything here! this->data.image is required and is deleted
somewhere else
+ return 0;
}
Modified: code/player/trunk/server/drivers/camera/cvcam/cvcam.cc
===================================================================
--- code/player/trunk/server/drivers/camera/cvcam/cvcam.cc 2010-07-22
16:01:47 UTC (rev 8828)
+++ code/player/trunk/server/drivers/camera/cvcam/cvcam.cc 2010-07-23
02:36:37 UTC (rev 8829)
@@ -103,9 +103,10 @@
// This method will be invoked on each incoming message
public: virtual int ProcessMessage(QueuePointer & resp_queue,
player_msghdr * hdr,
- void * data);
+ void * data);
private: virtual void Main();
+ private: int prepareData(player_camera_data_t * data);
private: CvCapture * capture;
private: int camindex;
@@ -163,12 +164,75 @@
this->capture = NULL;
}
+int CvCam::prepareData(player_camera_data_t * data)
+{
+ IplImage * frame;
+ int i;
+
+ assert(data);
+ frame = cvQueryFrame(this->capture);
+ if (!frame)
+ {
+ PLAYER_ERROR("No frame!");
+ return -1;
+ }
+ if (frame->depth != IPL_DEPTH_8U)
+ {
+ PLAYER_ERROR1("Unsupported depth %d", frame->depth);
+ return -1;
+ }
+ assert((frame->nChannels) > 0);
+ data->image_count = frame->width * frame->height * frame->nChannels;
+ assert(data->image_count > 0);
+ data->image = reinterpret_cast<unsigned char *>(malloc(data->image_count));
+ if (!(data->image))
+ {
+ PLAYER_ERROR("Out of memory");
+ return -1;
+ }
+ data->width = frame->width;
+ data->height = frame->height;
+ data->bpp = frame->nChannels * 8;
+ data->fdiv = 0;
+ switch (data->bpp)
+ {
+ case 8:
+ data->format = PLAYER_CAMERA_FORMAT_MONO8;
+ memcpy(data->image, frame->imageData, data->image_count);
+ break;
+ case 24:
+ data->format = PLAYER_CAMERA_FORMAT_RGB888;
+ for (i = 0; i < static_cast<int>(data->image_count); i +=
(frame->nChannels))
+ {
+ data->image[i] = frame->imageData[i + 2];
+ data->image[i + 1] = frame->imageData[i + 1];
+ data->image[i + 2] = frame->imageData[i];
+ }
+ break;
+ case 32:
+ data->format = PLAYER_CAMERA_FORMAT_RGB888;
+ for (i = 0; i < static_cast<int>(data->image_count); i +=
(frame->nChannels))
+ {
+ data->image[i] = frame->imageData[i + 2];
+ data->image[i + 1] = frame->imageData[i + 1];
+ data->image[i + 2] = frame->imageData[i];
+ data->image[i + 3] = frame->imageData[i + 3];
+ }
+ break;
+ default:
+ PLAYER_ERROR1("Unsupported image depth %d", data->bpp);
+ free(data->image);
+ data->image = NULL;
+ return -1;
+ }
+ data->compression = PLAYER_CAMERA_COMPRESS_RAW;
+ return 0;
+}
+
void CvCam::Main()
{
struct timespec tspec;
- IplImage * frame;
player_camera_data_t * data;
- int i;
if ((this->desired_width) > 0)
{
@@ -192,77 +256,46 @@
pthread_testcancel();
ProcessMessages();
+
pthread_testcancel();
- frame = cvQueryFrame(this->capture);
- if (!frame)
- {
- PLAYER_ERROR("No frame!");
- continue;
- }
- if (frame->depth != IPL_DEPTH_8U)
- {
- PLAYER_ERROR1("Unsupported depth %d", frame->depth);
- continue;
- }
data = reinterpret_cast<player_camera_data_t
*>(malloc(sizeof(player_camera_data_t)));
if (!data)
{
PLAYER_ERROR("Out of memory");
continue;
}
- assert((frame->nChannels) > 0);
- data->image_count = frame->width * frame->height * frame->nChannels;
- assert(data->image_count > 0);
- data->image = reinterpret_cast<unsigned char *>(malloc(data->image_count));
- if (!(data->image))
+ if (this->prepareData(data))
{
- PLAYER_ERROR("Out of memory");
+ free(data);
+ data = NULL;
+ pthread_testcancel();
continue;
}
- data->width = frame->width;
- data->height = frame->height;
- data->bpp = frame->nChannels * 8;
- data->fdiv = 0;
- switch (data->bpp)
- {
- case 8:
- data->format = PLAYER_CAMERA_FORMAT_MONO8;
- memcpy(data->image, frame->imageData, data->image_count);
- break;
- case 24:
- data->format = PLAYER_CAMERA_FORMAT_RGB888;
- for (i = 0; i < static_cast<int>(data->image_count); i +=
(frame->nChannels))
- {
- data->image[i] = frame->imageData[i + 2];
- data->image[i + 1] = frame->imageData[i + 1];
- data->image[i + 2] = frame->imageData[i];
- }
- break;
- case 32:
- data->format = PLAYER_CAMERA_FORMAT_RGB888;
- for (i = 0; i < static_cast<int>(data->image_count); i +=
(frame->nChannels))
- {
- data->image[i] = frame->imageData[i + 2];
- data->image[i + 1] = frame->imageData[i + 1];
- data->image[i + 2] = frame->imageData[i];
- data->image[i + 3] = frame->imageData[i + 3];
- }
- break;
- default:
- PLAYER_ERROR1("Unsupported image depth %d", data->bpp);
- data->bpp = 0;
- }
- assert(data->bpp > 0);
- data->compression = PLAYER_CAMERA_COMPRESS_RAW;
this->Publish(device_addr, PLAYER_MSGTYPE_DATA, PLAYER_CAMERA_DATA_STATE,
reinterpret_cast<void *>(data), 0, NULL, false);
// copy = false, don't dispose anything here
+ data = NULL;
pthread_testcancel();
}
}
int CvCam::ProcessMessage(QueuePointer & resp_queue, player_msghdr * hdr, void
* data)
{
+ player_camera_data_t imgData;
+
assert(hdr);
+ if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
+ PLAYER_CAMERA_REQ_GET_IMAGE,
+ this->device_addr))
+ {
+ if (this->prepareData(&imgData)) return -1;
+ this->Publish(this->device_addr,
+ resp_queue,
+ PLAYER_MSGTYPE_RESP_ACK,
+ PLAYER_CAMERA_REQ_GET_IMAGE,
+ reinterpret_cast<void *>(&imgData));
+ if (imgData.image) free(imgData.image);
+ return 0;
+ }
return -1;
}
Modified: code/player/trunk/server/drivers/camera/v4l2/camerav4l2.cc
===================================================================
--- code/player/trunk/server/drivers/camera/v4l2/camerav4l2.cc 2010-07-22
16:01:47 UTC (rev 8828)
+++ code/player/trunk/server/drivers/camera/v4l2/camerav4l2.cc 2010-07-23
02:36:37 UTC (rev 8829)
@@ -59,7 +59,7 @@
select which ones are used. You should define as many provided camera
interfaces as the number of sources is given here. Source channel
numbers are used as keys ('ch' prefixed) in 'provides' tuple.
- - If not given, channel 0 alone will be used by defauilt.
+ - If not given, channel 0 alone will be used by default.
- Note that switching between channels takes time. Framerate drops
dramatically whenever more than one channel is used.
@@ -89,8 +89,8 @@
- buffers (integer)
- Default: 2
- Number of buffers to use for grabbing. This reduces latency, but also
- potentially reduces throughput. Use this if you are reading slowly
- from the player driver and do not want to get stale frames.
+ potentially reduces throughput. Use this if you are reading slowly
+ from the player driver and do not want to get stale frames.
- sleep_nsec (integer)
- Default: 10000000 (=10ms which gives max 100 fps)
@@ -108,6 +108,10 @@
and they are counted. We can decide to stop waiting for stable image
after given number of frames was skipped.
+- request_only (integer)
+ - Default: 0
+ - If set to 1, data will be sent only at PLAYER_CAMEARA_REQ_GET_IMAGE
response.
+
- failsafe (integer)
- Default: 0
- If after few days of grabbing you experience unexpected failures you can
@@ -200,6 +204,7 @@
#include <libplayercore/playercore.h>
#define MAX_CHANNELS 10
+#define MAX_NORM_LEN 15
#define IS_JPEG(ptr) ((((ptr)[0]) == 0xff) && (((ptr)[1]) == 0xd8))
@@ -222,7 +227,9 @@
private:
// Main function for device thread.
virtual void Main();
+ int useSource();
int setSource();
+ int prepareData(player_camera_data_t * data, int sw);
int started;
const char * port;
@@ -231,9 +238,10 @@
int sources_count;
int sources[MAX_CHANNELS];
int current_source;
+ int next_source;
player_devaddr_t camera_addrs[MAX_CHANNELS];
void * fg;
- const char * norm;
+ char norm[MAX_NORM_LEN + 1];
int width;
int height;
int bpp;
@@ -241,6 +249,7 @@
double settle_time;
int skip_frames;
uint32_t format;
+ int request_only;
int failsafe;
int jpeg;
};
@@ -250,15 +259,17 @@
{
int i;
char key[24];
+ const char * str;
this->started = 0;
this->port = NULL;
this->mode = NULL;
this->buffers = 0;
this->sources_count = 0;
+ this->next_source = 0;
this->current_source = 0;
this->fg = NULL;
- this->norm = NULL;
+ this->norm[0] = 0;
this->width = 0;
this->height = 0;
this->bpp = 0;
@@ -266,6 +277,7 @@
this->settle_time = 0.0;
this->skip_frames = 0;
this->format = 0;
+ this->request_only = 0;
this->failsafe = 0;
this->jpeg = 0;
memset(this->sources, 0, sizeof this->sources);
@@ -375,7 +387,14 @@
return;
}
// NTSC, PAL or UNKNOWN
- this->norm = cf->ReadString(section, "norm", "NTSC");
+ str = cf->ReadString(section, "norm", "NTSC");
+ if (!str)
+ {
+ PLAYER_ERROR("NULL norm");
+ this->SetError(-1);
+ return;
+ }
+ snprintf(this->norm, sizeof this->norm, "%s", str);
if (!(strcmp(this->norm, "NTSC")))
{
this->width = 640;
@@ -413,6 +432,7 @@
}
this->settle_time = cf->ReadFloat(section, "settle_time", 0.5);
this->skip_frames = cf->ReadInt(section, "skip_frames", 10);
+ this->request_only = cf->ReadInt(section, "request_only", 0);
this->failsafe = cf->ReadInt(section, "failsafe", 0);
}
@@ -432,21 +452,12 @@
int dropped = 0;
double start_time, t;
struct timespec tspec;
- static int next_source = 0;
- if (!(this->fg)) return -1;
- if (this->started) stop_grab(this->fg);
- this->started = 0;
- if ((next_source < 0) || (next_source >= (this->sources_count))) return -1;
- if (set_channel(this->fg, this->sources[next_source], this->norm) < 0)
+ if (set_channel(this->fg, this->sources[this->current_source], this->norm) <
0)
{
- PLAYER_ERROR1("Cannot set channel %d", this->sources[next_source]);
+ PLAYER_ERROR1("Cannot set channel %d",
this->sources[this->current_source]);
return -1;
}
- this->current_source = next_source;
- next_source++;
- if (next_source >= (this->sources_count)) next_source = 0;
- if (((this->current_source) < 0) || ((this->current_source) >=
(this->sources_count))) return -1;
if (start_grab(this->fg) < 0)
{
PLAYER_ERROR1("Cannot start grab on channel %d",
this->sources[this->current_source]);
@@ -467,6 +478,23 @@
return 0;
}
+int CameraV4L2::useSource()
+{
+ if (!(this->fg)) return -1;
+ if (this->started) stop_grab(this->fg);
+ this->started = 0;
+ if ((this->sources_count) > 1)
+ {
+ if (((this->next_source) < 0) || ((this->next_source) >=
(this->sources_count))) return -1;
+ this->current_source = this->next_source;
+ (this->next_source)++;
+ if ((this->next_source) >= (this->sources_count)) this->next_source = 0;
+ }
+ if (((this->current_source) < 0) || ((this->current_source) >=
(this->sources_count))) return -1;
+ if (this->setSource() < 0) return -1;
+ return 0;
+}
+
////////////////////////////////////////////////////////////////////////////////
// Set up the device. Return 0 if things go well, and -1 otherwise.
int CameraV4L2::MainSetup()
@@ -474,7 +502,7 @@
assert((!(this->fg)) && (!(this->started)));
this->fg = open_fg(this->port, this->mode, this->width, this->height,
(this->bpp) / 8, this->buffers);
if (!(this->fg)) return -1;
- return this->setSource();
+ return this->useSource();
}
////////////////////////////////////////////////////////////////////////////////
@@ -495,9 +523,7 @@
void CameraV4L2::Main()
{
struct timespec tspec;
- const unsigned char * img;
player_camera_data_t * data = NULL;
- int i;
for (;;)
{
@@ -512,117 +538,229 @@
// Process any pending requests.
ProcessMessages();
- assert(this->fg);
- assert(this->started);
- // Grab the next frame (blocking)
- img = get_image(this->fg);
- if (this->failsafe)
- {
- if (!img)
- {
- PLAYER_ERROR("Cannot grab frame");
- pthread_testcancel();
- if (this->started) stop_grab(this->fg);
- this->started = 0;
- close_fg(this->fg);
- this->fg = NULL;
- tspec.tv_sec = 1;
- tspec.tv_nsec = 0;
- nanosleep(&tspec, NULL);
- pthread_testcancel();
- this->fg = open_fg(this->port, this->mode, this->width, this->height,
(this->bpp) / 8, this->buffers);
- assert(this->fg);
- this->setSource();
- assert(this->started);
- pthread_testcancel();
- continue;
- }
- } else
- {
- assert(img);
- }
data = reinterpret_cast<player_camera_data_t
*>(malloc(sizeof(player_camera_data_t)));
if (!data)
{
PLAYER_ERROR("Out of memory");
continue;
}
- memset(data, 0, sizeof *data);
- // Set the image properties
- data->width = this->width;
- data->height = this->height;
- data->bpp = this->bpp;
- data->format = this->format;
- data->fdiv = 0;
- data->image_count = 0;
- data->image = NULL;
- if (!(this->jpeg))
+ if (this->prepareData(data, !(this->request_only)))
{
- data->compression = PLAYER_CAMERA_COMPRESS_RAW;
- data->image_count = this->width * this->height * ((this->bpp) / 8);
- assert(data->image_count > 0);
- data->image = reinterpret_cast<uint8_t *>(malloc(data->image_count));
- if (!(data->image))
- {
- PLAYER_ERROR("Out of memory!");
- free(data);
- data = NULL;
- continue;
- }
- memcpy(data->image, img, data->image_count);
+ free(data);
+ data = NULL;
+ pthread_testcancel();
+ continue;
+ }
+ if (!(this->request_only))
+ {
+ Publish(this->camera_addrs[this->current_source],
+ PLAYER_MSGTYPE_DATA, PLAYER_CAMERA_DATA_STATE,
+ reinterpret_cast<void *>(data), 0, NULL, false);
+ // copy = false, don't dispose anything here!
} else
{
- data->compression = PLAYER_CAMERA_COMPRESS_JPEG;
- memcpy(&i, img, sizeof(int));
- data->image_count = i;
- assert(data->image_count > 1);
- if (!(IS_JPEG(img + sizeof(int))))
+ if (data->image)
{
- PLAYER_ERROR("Not a JPEG image...");
- free(data);
- data = NULL;
- continue;
+ free(data->image);
+ data->image = NULL;
}
- data->image = reinterpret_cast<uint8_t *>(malloc(data->image_count));
- if (!(data->image))
- {
- PLAYER_ERROR("Out of memory!");
- free(data);
- data = NULL;
- continue;
- }
- memcpy(data->image, img + sizeof(int), data->image_count);
+ free(data);
}
- assert(data->image_count > 0);
- assert(data->image);
- Publish(this->camera_addrs[this->current_source],
- PLAYER_MSGTYPE_DATA, PLAYER_CAMERA_DATA_STATE,
- reinterpret_cast<void *>(data), 0, NULL, false);
- // copy = false, don't dispose anything here!
data = NULL;
- if ((this->sources_count) > 1)
+ // Test if we are supposed to cancel this thread.
+ pthread_testcancel();
+ }
+}
+
+int CameraV4L2::prepareData(player_camera_data_t * data, int sw)
+{
+ const unsigned char * img;
+ struct timespec tspec;
+ int i = 0;
+
+ assert(data);
+ assert(this->fg);
+ if (!(this->started))
+ {
+ if (this->useSource()) return -1;
+ }
+ if (!(this->started)) return -1;
+ // Grab the next frame (blocking)
+ img = get_image(this->fg);
+ if (this->failsafe)
+ {
+ if (!img)
{
+ PLAYER_ERROR("Cannot grab frame");
pthread_testcancel();
- if (this->failsafe)
- {
- this->setSource();
- } else
- {
- assert(!(this->setSource()));
- }
+ if (this->started) stop_grab(this->fg);
+ this->started = 0;
+ close_fg(this->fg);
+ this->fg = NULL;
+ tspec.tv_sec = 1;
+ tspec.tv_nsec = 0;
+ nanosleep(&tspec, NULL);
+ pthread_testcancel();
+ this->fg = open_fg(this->port, this->mode, this->width, this->height,
(this->bpp) / 8, this->buffers);
+ assert(this->fg);
+ this->useSource();
+ assert(this->started);
+ return -1;
}
-
- // Test if we are supposed to cancel this thread.
+ } else
+ {
+ assert(img);
+ }
+ memset(data, 0, sizeof *data);
+ // Set the image properties
+ data->width = this->width;
+ data->height = this->height;
+ data->bpp = this->bpp;
+ data->format = this->format;
+ data->fdiv = 0;
+ data->image_count = 0;
+ data->image = NULL;
+ if (!(this->jpeg))
+ {
+ data->compression = PLAYER_CAMERA_COMPRESS_RAW;
+ data->image_count = this->width * this->height * ((this->bpp) / 8);
+ assert(data->image_count > 0);
+ data->image = reinterpret_cast<uint8_t *>(malloc(data->image_count));
+ if (!(data->image))
+ {
+ PLAYER_ERROR("Out of memory!");
+ return -1;
+ }
+ memcpy(data->image, img, data->image_count);
+ } else
+ {
+ data->compression = PLAYER_CAMERA_COMPRESS_JPEG;
+ memcpy(&i, img, sizeof(int));
+ data->image_count = i;
+ assert(data->image_count > 1);
+ if (!(IS_JPEG(img + sizeof(int))))
+ {
+ PLAYER_ERROR("Not a JPEG image...");
+ return -1;
+ }
+ data->image = reinterpret_cast<uint8_t *>(malloc(data->image_count));
+ if (!(data->image))
+ {
+ PLAYER_ERROR("Out of memory!");
+ return -1;
+ }
+ memcpy(data->image, img + sizeof(int), data->image_count);
+ }
+ assert(data->image_count > 0);
+ assert(data->image);
+ if (sw && ((this->sources_count) > 1))
+ {
pthread_testcancel();
+ if (this->failsafe)
+ {
+ this->useSource();
+ } else
+ {
+ assert(!(this->useSource()));
+ }
}
+ return 0;
}
int CameraV4L2::ProcessMessage(QueuePointer & resp_queue,
player_msghdr * hdr,
void * data)
{
+ player_camera_source_t source;
+ player_camera_source_t * src;
+ player_camera_data_t imgData;
+ char previousNorm[MAX_NORM_LEN + 1];
+ int previousSource;
+ int i;
+
assert(hdr);
+ if ((this->sources_count) == 1)
+ {
+ assert(!(this->current_source));
+ if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
+ PLAYER_CAMERA_REQ_GET_SOURCE,
+ this->camera_addrs[0]))
+ {
+ memset(&source, 0, sizeof source);
+ source.norm_count = strlen(this->norm) + 1;
+ source.norm = strdup(this->norm);
+ assert(source.norm);
+ source.source = this->sources[this->current_source];
+ this->Publish(this->camera_addrs[0],
+ resp_queue,
+ PLAYER_MSGTYPE_RESP_ACK,
+ PLAYER_CAMERA_REQ_GET_SOURCE,
+ reinterpret_cast<void *>(&source));
+ free(source.norm);
+ return 0;
+ } else if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
+ PLAYER_CAMERA_REQ_SET_SOURCE,
+ this->camera_addrs[0]))
+ {
+ assert(data);
+ src = reinterpret_cast<player_camera_source_t *>(data);
+ assert(src);
+ snprintf(previousNorm, sizeof previousNorm, "%s", this->norm);
+ previousSource = this->sources[this->current_source];
+ if ((src->norm_count) > 0) if (strlen(src->norm) > 0)
snprintf(this->norm, sizeof this->norm, "%s", src->norm);
+ this->sources[this->current_source] = src->source;
+ if (this->started) stop_grab(this->fg);
+ this->started = 0;
+ if (this->setSource())
+ {
+ this->Publish(this->camera_addrs[0],
+ resp_queue,
+ PLAYER_MSGTYPE_RESP_NACK,
+ PLAYER_CAMERA_REQ_SET_SOURCE,
+ data);
+ if (this->started) stop_grab(this->fg);
+ this->started = 0;
+ } else
+ {
+ this->Publish(this->camera_addrs[0],
+ resp_queue,
+ (this->started) ? PLAYER_MSGTYPE_RESP_ACK :
PLAYER_MSGTYPE_RESP_NACK,
+ PLAYER_CAMERA_REQ_SET_SOURCE,
+ data);
+ }
+ if (!(this->started))
+ {
+ snprintf(this->norm, sizeof this->norm, "%s", previousNorm);
+ this->sources[this->current_source] = previousSource;
+ if (this->setSource()) PLAYER_ERROR("Cannot switch back to previous
channel!");
+ }
+ return 0;
+ }
+ }
+ for (i = 0; i < (this->sources_count); i++)
+ {
+ if (Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
+ PLAYER_CAMERA_REQ_GET_IMAGE,
+ this->camera_addrs[i]))
+ {
+ if (this->current_source != i)
+ {
+ assert((this->current_source) > 1);
+ this->next_source = i;
+ if (this->useSource()) return -1;
+ }
+ assert((this->current_source) == i);
+ if (this->prepareData(&imgData, 0)) return -1;
+ this->Publish(this->camera_addrs[i],
+ resp_queue,
+ PLAYER_MSGTYPE_RESP_ACK,
+ PLAYER_CAMERA_REQ_GET_IMAGE,
+ reinterpret_cast<void *>(&imgData));
+ if (imgData.image) free(imgData.image);
+ return 0;
+ }
+ }
return -1;
}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit