sphere_mixed.cc

00001 /*
00002  *  Player - One Hell of a Robot Server
00003  *  Copyright (C) 2000  Brian Gerkey et al.
00004  *
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00147 // ONLY if you need something that was #define'd as a result of configure
00148 // (e.g., HAVE_CFMAKERAW), then #include <config.h>, like so:
00149 /*
00150 #if HAVE_CONFIG_H
00151   #include <config.h>
00152 #endif
00153 */
00154 #include "sphere_mixed.h"
00155 
00156 #define DEG2RAD(x) (((double)(x))*0.01745329251994)
00157 #define RAD2DEG(x) (((double)(x))*57.29577951308232)
00158 
00159 extern "C" {
00160 #include "setpwc_api.h"
00161 }
00162 
00163 #include <unistd.h>
00164 #include <string.h>
00165 #include <iostream>
00166 #include <stdint.h>
00167 #include <sys/time.h>
00168 #include <time.h>
00169 #include <assert.h>
00170 #include <math.h>
00171 using namespace std;
00172 
00173 const timespec NSLEEP_TIME = {0, 10000000}; // (0s, 10 ms) => max 100 fps
00174 
00176 // Now the driver
00177 
00178 // A factory creation function, declared outside of the class so that it
00179 // can be invoked without any object context (alternatively, you can
00180 // declare it static in the class).  In this function, we create and return
00181 // (as a generic Driver*) a pointer to a new instance of this driver.
00182 Driver*
00183 SphereDriver_Init(ConfigFile* cf, int section)
00184 {
00185   // Create and return a new instance of this driver
00186   return ((Driver*)(new SphereDriver(cf, section)));
00187 
00188 }
00189 
00190 // A driver registration function, again declared outside of the class so
00191 // that it can be invoked without object context.  In this function, we add
00192 // the driver into the given driver table, indicating which interface the
00193 // driver can support and how to create a driver instance.
00194 void SphereDriver_Register(DriverTable* table)
00195 {
00196   table->AddDriver("sphere", SphereDriver_Init);
00197 }
00198 
00200 // Constructor.  Retrieve options from the configuration file and do any
00201 // pre-Setup() setup.
00202 SphereDriver::SphereDriver(ConfigFile* cf, int section)
00203     : Driver(cf, section),
00204     mPanMin(0),
00205     mPanMax(1),
00206     mTiltMin(0),
00207     mTiltMax(1),
00208     mDevice(NULL),
00209     mFg(NULL),
00210     mFrame(NULL),
00211     mRGBFrame(NULL),
00212     mFrameNumber(0),
00213     mWidth(0),
00214     mHeight(0),
00215     mDepth(0)
00216 {
00217   // Create camera interface
00218   if (0 !=
00219     cf->ReadDeviceAddr(&(mCameraAddr),section,"provides",PLAYER_CAMERA_CODE,-1,NULL))
00220   {
00221     PLAYER_ERROR("Could not read camera ID ");
00222     SetError(-1);
00223     return;
00224   }
00225   if (0 != AddInterface(mCameraAddr))
00226   {
00227     PLAYER_ERROR("Could not add camera interface ");
00228     SetError(-1);
00229     return;
00230   }
00231 
00232   // Create Ptz interface
00233   if (0 !=
00234     cf->ReadDeviceAddr(&(mPtzAddr),section,"provides",PLAYER_PTZ_CODE,-1,NULL))
00235   {
00236     PLAYER_ERROR("Could not read ptz ID ");
00237     SetError(-1);
00238     return;
00239   }
00240   if (0 != AddInterface(mPtzAddr))
00241   {
00242     PLAYER_ERROR("Could not add ptz interface ID ");
00243     SetError(-1);
00244     return;
00245   }
00246 
00248   //ClearCommand(mPtzAddr);
00249 
00250   // Read options from the configuration file
00251   mSleep           =
00252     static_cast<int32_t>(rint(1e6/cf->ReadInt(section, "frequency", 100)));
00253 
00254   mDevice    = cf->ReadString(section, "port", "/dev/video0");
00255   mWidth     = cf->ReadTupleInt(section, "size", 0, 320);
00256   mHeight    = cf->ReadTupleInt(section, "size", 1, 240);
00257   mPalette   = cf->ReadString(section, "mode", "RGB888");
00258   mSave      = cf->ReadInt(section, "save", 0);
00259   mFrameRate = cf->ReadInt(section, "framerate", 10);
00260 
00261   // Not sure what a good default value is here
00262   mShutterSpeed          = cf->ReadInt(section, "shutter_speed", 64000);
00263   mCompressionPreference = cf->ReadInt(section, "compression_preference", 2);
00264   mAutomaticGain         = cf->ReadInt(section, "automatic_gain", 10000);
00265   mAutomaticWb           = cf->ReadString(section, "automatic_wb", "auto");
00266   mSharpness             = cf->ReadInt(section, "sharpness", -1);
00267   mBacklight             = cf->ReadInt(section, "backlight", 0);
00268   mFlicker               = cf->ReadInt(section, "flicker", 0);
00269   mNoiseReduction        = cf->ReadInt(section, "noise_reduction", 0);
00270   mDumpSettings          = cf->ReadInt(section, "dump_settings", 0);
00271   mDebug                 = cf->ReadInt(section, "debug", 0);
00272 
00273   return;
00274 }
00275 
00277 // Set up the device.  Return 0 if things go well, and -1 otherwise.
00278 int SphereDriver::Setup()
00279 {
00280   puts("Setting up sphere driver");
00281   mFg = fg_open(mDevice);
00282   if (mFg == NULL)
00283   {
00284     PLAYER_ERROR("Setup():  unable to open ");
00285     return -1;
00286   }
00287 
00288   fg_set_format(mFg, VIDEO_PALETTE_YUV420P);
00289   mFrame = frame_new(mWidth, mHeight, VIDEO_PALETTE_YUV420P );
00290 
00291   if (0 == strcasecmp(mPalette, "GREY"))
00292   {
00293     // We don't actually have a greyscale mode, but we can just return
00294     // the Y component of our YUV.
00295     mCameraData.format = PLAYER_CAMERA_FORMAT_MONO8;
00296     mDepth = 8;
00297   }
00298   else if (0 == strcasecmp(mPalette, "YUV420P"))
00299   {
00300   // What should we have here?
00301   //    mCameraData.format = PLAYER_CAMERA_FORMAT_YUV420P;
00302   //    mDepth = 24;
00303   }
00304   else if (0 == strcasecmp(mPalette, "RGB24P"))
00305   {
00306     mRGBFrame = frame_new(mWidth, mHeight, VIDEO_PALETTE_RGB24 );
00307     mCameraData.format = PLAYER_CAMERA_FORMAT_RGB;
00308     mDepth = 24;
00309   }
00310   else if (0 == strcasecmp(mPalette, "RGB888"))
00311   {
00312     mRGBFrame = frame_new(mWidth, mHeight, VIDEO_PALETTE_RGB24 );
00313     mCameraData.format = PLAYER_CAMERA_FORMAT_RGB888;
00314     mDepth = 24;
00315   }
00316   else
00317   {
00318     PLAYER_ERROR("Palette is not supported ");
00319     return 1;
00320   }
00321 
00322   fg_set_capture_window(mFg, 0, 0, mWidth, mHeight);
00323 
00324   // Setup the camera based on configuration options
00325   set_framerate(mFg->fd, mFrameRate);
00326   set_shutter_speed(mFg->fd, mShutterSpeed);
00327   set_compression_preference(mFg->fd, mCompressionPreference);
00328   set_automatic_gain_control(mFg->fd, mAutomaticGain);
00329   set_automatic_white_balance_mode(mFg->fd, const_cast<char*>(mAutomaticWb));
00330   set_sharpness(mFg->fd, mSharpness);
00331   set_backlight_compensation(mFg->fd, mBacklight);
00332   set_antiflicker_mode(mFg->fd, mFlicker);
00333   set_noise_reduction(mFg->fd, mNoiseReduction);
00334 
00335   int32_t min, max;
00336   get_pan_or_tilt_limits(mFg->fd, GET_PAN, &min, &max);
00337   mPanMin = DEG2RAD(min/100.0);
00338   mPanMax = DEG2RAD(max/100.0);
00339   get_pan_or_tilt_limits(mFg->fd, GET_TILT, &min, &max);
00340   mTiltMin = DEG2RAD(min/100.0);
00341   mTiltMax = DEG2RAD(max/100.0);
00342 
00343   if (mDebug)
00344   {
00345     printf("min, max:\n");
00346     printf("pan      %.3f %.3f\n", mPanMin, mPanMax);
00347     printf("tilt     %.3f %.3f\n", mTiltMin, mTiltMax);
00348   }
00349 
00350   reset_pan_tilt(mFg->fd, SET_PAN);
00351   reset_pan_tilt(mFg->fd, SET_TILT);
00352 
00353   if (FALSE!=mDumpSettings)
00354     dump_current_settings(mFg->fd);
00355 
00356   puts("Sphere driver ready");
00357 
00358   // Start the device thread; spawns a new thread and executes
00359   // SphereDriver::Main(), which contains the main loop for the driver.
00360   StartThread();
00361 
00362   return(0);
00363 }
00364 
00365 
00367 // Shutdown the device
00368 int SphereDriver::Shutdown()
00369 {
00370   puts("Shutting Sphere driver down");
00371 
00372   // Stop and join the driver thread
00373   StopThread();
00374 
00375   // Set to 0,0
00376   set_pan_and_tilt(mFg->fd, 0, 0);
00377 
00378   // Free resources
00379   if (mFrame != NULL)
00380     frame_release(mFrame);
00381   if (mRGBFrame != NULL)
00382     frame_release(mRGBFrame);
00383   if (mFg != NULL)
00384     fg_close(mFg);
00385 
00386   // Here you would shut the device down by, for example, closing a
00387   // serial port.
00388 
00389   puts("Sphere driver has been shutdown");
00390 
00391   return(0);
00392 }
00393 
00395 // Main function for device thread
00396 void SphereDriver::Main()
00397 {
00398 
00399   // The main loop; interact with the device here
00400   for(;;)
00401   {
00402     // test if we are supposed to cancel
00403     pthread_testcancel();
00404 
00405     // Go to sleep for a while (this is a polling loop)
00406     nanosleep(&NSLEEP_TIME, NULL);
00407 
00408     // Process incoming messages
00409     ProcessMessages();
00410 
00411     // Write outgoing data
00412     RefreshData();
00413 
00414   }
00415   return;
00416 }
00417 
00418 // Process an incoming message
00419 int SphereDriver::ProcessMessage(QueuePointer & resp_queue,
00420                                  player_msghdr* hdr,
00421                                  void* data)
00422 {
00423   assert(hdr);
00424   assert(data);
00425 
00426   if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD,
00427                            PLAYER_PTZ_CMD_STATE, mPtzAddr))
00428   {
00429     assert(hdr->size == sizeof(player_ptz_cmd_t));
00430     ProcessCommand(hdr, *reinterpret_cast<player_ptz_cmd_t *>(data));
00431     return(0);
00432   }
00433   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ,
00434                            PLAYER_PTZ_REQ_STATUS, mPtzAddr))
00435   {
00436     player_ptz_req_status_t ptz_status;
00437     int status;
00438 
00439     query_pan_tilt_status(mFg->fd, &status);
00440     ptz_status.status = (uint32_t) status;
00441 
00442     Publish(device_addr, resp_queue,
00443       PLAYER_MSGTYPE_RESP_ACK,
00444       PLAYER_PTZ_REQ_STATUS,
00445       (void*)&status
00446     );
00447     return(0);
00448   }
00449   else
00450   {
00451     PLAYER_ERROR1("SphereDriver received unknown message: %s", hdr->type);
00452   }
00453 
00454   return -1;
00455 }
00456 
00457 void SphereDriver::ProcessCommand(player_msghdr_t* hdr, player_ptz_cmd_t &data)
00458 {
00459   int16_t pan,tilt;
00460 
00461   pan       = (int16_t)rint(RAD2DEG(LimitPan(data.pan))*100);
00462   tilt      = (int16_t)rint(RAD2DEG(LimitTilt(data.tilt))*100);
00463 
00464   mPtzCmd.pan        = DEG2RAD(pan/100.0);
00465   mPtzCmd.tilt       = DEG2RAD(tilt/100.0);
00466 
00467   // we currently just store the command after checking the limits
00468   mPtzData.pan       = mPtzCmd.pan;
00469   mPtzData.tilt      = mPtzCmd.tilt;
00470 
00471   // we don't support these
00472   mPtzData.zoom      = -1;
00473   mPtzData.panspeed  = -1;
00474   mPtzData.tiltspeed = -1;
00475 
00476   // pan is inverted
00477   set_pan_and_tilt(mFg->fd, -pan, tilt);
00478 }
00479 
00480 void SphereDriver::RefreshData()
00481 {
00482   // Grab the next frame (blocking)
00483   fg_grab_frame(mFg, mFrame);
00484   size_t image_size;
00485 
00486   // Compute size of image
00487   image_size = mWidth * mHeight * mDepth / 8;
00488   // Set the image properties
00489   mCameraData.width  = mWidth;
00490   mCameraData.height = mHeight;
00491   mCameraData.bpp    = mDepth;
00492   mCameraData.compression = PLAYER_CAMERA_COMPRESS_RAW;
00493   mCameraData.image_count = image_size;
00494   mCameraData.image = new unsigned char [image_size];
00495 
00496 
00497   // Copy the image pixels
00498   if (0 == strcasecmp(mPalette, "GREY"))
00499   {
00500     memcpy(mCameraData.image, mFrame->data, image_size);
00501   }
00502   else if (0 == strcasecmp(mPalette, "YUV420P"))
00503   {
00504     // What should we do here?
00505     // memcpy(mCameraData.image, mRGBFrame->data, image_size);
00506   }
00507   else // RGB
00508   {
00509     // We have to do a conversion
00510     YUV422toRGB(static_cast<uint8_t*>(mFrame->data),
00511                 static_cast<uint8_t*>(mRGBFrame->data));
00512 
00513     assert(image_size <= (size_t) mRGBFrame->size);
00514     memcpy(mCameraData.image, mRGBFrame->data, image_size);
00515   }
00516 
00517   Publish(mCameraAddr, 
00518           PLAYER_MSGTYPE_DATA, PLAYER_CAMERA_DATA_STATE,
00519           reinterpret_cast<void*>(&mCameraData));
00520 
00521   Publish(mPtzAddr, 
00522           PLAYER_MSGTYPE_DATA, PLAYER_PTZ_DATA_STATE,
00523           reinterpret_cast<void*>(&mPtzData));
00524 
00525   // Save frames
00526   if (FALSE!=mSave)
00527   {
00528     char filename[256];
00529     snprintf(filename, sizeof(filename), "click-%04d.ppm", mFrameNumber++);
00530     frame_save(mFrame, filename);
00531   }
00532   delete [] mCameraData.image;
00533 
00534 }
00535 
00536 #define LIMIT(p) static_cast<uint8_t>((p < 0) ? 0 : ((p > 255) ? 255 : p))
00537 
00538 // These are the lookup tables for the YUV -> RGB conversion
00539 static const int32_t LUT_Y[256]   =
00540 {-4768, -4470, -4172, -3874, -3576, -3278, -2980, -2682, -2384, -2086, -1788,
00541 -1490, -1192, -894, -596, -298, 0, 298, 596, 894, 1192, 1490, 1788, 2086,
00542 2384, 2682, 2980, 3278, 3576, 3874, 4172, 4470, 4768, 5066, 5364, 5662, 5960,
00543 6258, 6556, 6854, 7152, 7450, 7748, 8046, 8344, 8642, 8940, 9238, 9535, 9833,
00544 10131, 10429, 10727, 11025, 11323, 11621, 11919, 12217, 12515, 12813, 13111,
00545 13409, 13707, 14005, 14303, 14601, 14899, 15197, 15495, 15793, 16091, 16389,
00546 16687, 16985, 17283, 17581, 17879, 18177, 18475, 18773, 19071, 19369, 19667,
00547 19965, 20263, 20561, 20859, 21157, 21455, 21753, 22051, 22349, 22647, 22945,
00548 23243, 23541, 23839, 24137, 24435, 24733, 25031, 25329, 25627, 25925, 26223,
00549 26521, 26819, 27117, 27415, 27713, 28010, 28308, 28606, 28904, 29202, 29500,
00550 29798, 30096, 30394, 30692, 30990, 31288, 31586, 31884, 32182, 32480, 32778,
00551 33076, 33374, 33672, 33970, 34268, 34566, 34864, 35162, 35460, 35758, 36056,
00552 36354, 36652, 36950, 37248, 37546, 37844, 38142, 38440, 38738, 39036, 39334,
00553 39632, 39930, 40228, 40526, 40824, 41122, 41420, 41718, 42016, 42314, 42612,
00554 42910, 43208, 43506, 43804, 44102, 44400, 44698, 44996, 45294, 45592, 45890,
00555 46188, 46486, 46783, 47081, 47379, 47677, 47975, 48273, 48571, 48869, 49167,
00556 49465, 49763, 50061, 50359, 50657, 50955, 51253, 51551, 51849, 52147, 52445,
00557 52743, 53041, 53339, 53637, 53935, 54233, 54531, 54829, 55127, 55425, 55723,
00558 56021, 56319, 56617, 56915, 57213, 57511, 57809, 58107, 58405, 58703, 59001,
00559 59299, 59597, 59895, 60193, 60491, 60789, 61087, 61385, 61683, 61981, 62279,
00560 62577, 62875, 63173, 63471, 63769, 64067, 64365, 64663, 64961, 65258, 65556,
00561 65854, 66152, 66450, 66748, 67046, 67344, 67642, 67940, 68238, 68536, 68834,
00562 69132, 69430, 69728, 70026, 70324, 70622, 70920};
00563 
00564 static const int32_t LUT_V_R[256] =
00565 {-52298, -51889, -51481, -51072, -50663, -50255, -49846, -49438, -49029,
00566 -48621, -48212, -47803, -47395, -46986, -46578, -46169, -45761, -45352,
00567 -44943, -44535, -44126, -43718, -43309, -42900, -42492, -42083, -41675,
00568 -41266, -40858, -40449, -40040, -39632, -39223, -38815, -38406, -37998,
00569 -37589, -37180, -36772, -36363, -35955, -35546, -35138, -34729, -34320,
00570 -33912, -33503, -33095, -32686, -32278, -31869, -31460, -31052, -30643,
00571 -30235, -29826, -29417, -29009, -28600, -28192, -27783, -27375, -26966,
00572 -26557, -26149, -25740, -25332, -24923, -24515, -24106, -23697, -23289,
00573 -22880, -22472, -22063, -21655, -21246, -20837, -20429, -20020, -19612,
00574 -19203, -18794, -18386, -17977, -17569, -17160, -16752, -16343, -15934,
00575 -15526, -15117, -14709, -14300, -13892, -13483, -13074, -12666, -12257,
00576 -11849, -11440, -11032, -10623, -10214, -9806, -9397, -8989, -8580, -8172,
00577 -7763, -7354, -6946, -6537, -6129, -5720, -5311, -4903, -4494, -4086, -3677,
00578 -3269, -2860, -2451, -2043, -1634, -1226, -817, -409, 0, 409, 817, 1226, 1634,
00579 2043, 2451, 2860, 3269, 3677, 4086, 4494, 4903, 5311, 5720, 6129, 6537, 6946,
00580 7354, 7763, 8172, 8580, 8989, 9397, 9806, 10214, 10623, 11032, 11440, 11849,
00581 12257, 12666, 13074, 13483, 13892, 14300, 14709, 15117, 15526, 15934, 16343,
00582 16752, 17160, 17569, 17977, 18386, 18794, 19203, 19612, 20020, 20429, 20837,
00583 21246, 21655, 22063, 22472, 22880, 23289, 23697, 24106, 24515, 24923, 25332,
00584 25740, 26149, 26557, 26966, 27375, 27783, 28192, 28600, 29009, 29417, 29826,
00585 30235, 30643, 31052, 31460, 31869, 32278, 32686, 33095, 33503, 33912, 34320,
00586 34729, 35138, 35546, 35955, 36363, 36772, 37180, 37589, 37998, 38406, 38815,
00587 39223, 39632, 40040, 40449, 40858, 41266, 41675, 42083, 42492, 42900, 43309,
00588 43718, 44126, 44535, 44943, 45352, 45761, 46169, 46578, 46986, 47395, 47803,
00589 48212, 48621, 49029, 49438, 49846, 50255, 50663, 51072, 51481};
00590 
00591 static const int32_t LUT_U_G[256] =
00592 {-12812, -12712, -12612, -12512, -12412, -12312, -12212, -12112, -12012,
00593 -11911, -11811, -11711, -11611, -11511, -11411, -11311, -11211, -11111,
00594 -11011, -10910, -10810, -10710, -10610, -10510, -10410, -10310, -10210,
00595 -10110, -10010, -9910, -9809, -9709, -9609, -9509, -9409, -9309, -9209, -9109,
00596 -9009, -8909, -8808, -8708, -8608, -8508, -8408, -8308, -8208, -8108, -8008,
00597 -7908, -7807, -7707, -7607, -7507, -7407, -7307, -7207, -7107, -7007, -6907,
00598 -6807, -6706, -6606, -6506, -6406, -6306, -6206, -6106, -6006, -5906, -5806,
00599 -5705, -5605, -5505, -5405, -5305, -5205, -5105, -5005, -4905, -4805, -4705,
00600 -4604, -4504, -4404, -4304, -4204, -4104, -4004, -3904, -3804, -3704, -3603,
00601 -3503, -3403, -3303, -3203, -3103, -3003, -2903, -2803, -2703, -2602, -2502,
00602 -2402, -2302, -2202, -2102, -2002, -1902, -1802, -1702, -1602, -1501, -1401,
00603 -1301, -1201, -1101, -1001, -901, -801, -701, -601, -500, -400, -300, -200,
00604 -100, 0, 100, 200, 300, 400, 500, 601, 701, 801, 901, 1001, 1101, 1201, 1301,
00605 1401, 1501, 1602, 1702, 1802, 1902, 2002, 2102, 2202, 2302, 2402, 2502, 2602,
00606 2703, 2803, 2903, 3003, 3103, 3203, 3303, 3403, 3503, 3603, 3704, 3804, 3904,
00607 4004, 4104, 4204, 4304, 4404, 4504, 4604, 4705, 4805, 4905, 5005, 5105, 5205,
00608 5305, 5405, 5505, 5605, 5705, 5806, 5906, 6006, 6106, 6206, 6306, 6406, 6506,
00609 6606, 6706, 6807, 6907, 7007, 7107, 7207, 7307, 7407, 7507, 7607, 7707, 7807,
00610 7908, 8008, 8108, 8208, 8308, 8408, 8508, 8608, 8708, 8808, 8909, 9009, 9109,
00611 9209, 9309, 9409, 9509, 9609, 9709, 9809, 9910, 10010, 10110, 10210, 10310,
00612 10410, 10510, 10610, 10710, 10810, 10910, 11011, 11111, 11211, 11311, 11411,
00613 11511, 11611, 11711, 11811, 11911, 12012, 12112, 12212, 12312, 12412, 12512,
00614 12612};
00615 
00616 static const int32_t LUT_V_G[256] =
00617 {-26640, -26432, -26224, -26016, -25808, -25600, -25392, -25183, -24975,
00618 -24767, -24559, -24351, -24143, -23935, -23727, -23518, -23310, -23102,
00619 -22894, -22686, -22478, -22270, -22062, -21853, -21645, -21437, -21229,
00620 -21021, -20813, -20605, -20397, -20188, -19980, -19772, -19564, -19356,
00621 -19148, -18940, -18732, -18523, -18315, -18107, -17899, -17691, -17483,
00622 -17275, -17066, -16858, -16650, -16442, -16234, -16026, -15818, -15610,
00623 -15401, -15193, -14985, -14777, -14569, -14361, -14153, -13945, -13736,
00624 -13528, -13320, -13112, -12904, -12696, -12488, -12280, -12071, -11863,
00625 -11655, -11447, -11239, -11031, -10823, -10615, -10406, -10198, -9990, -9782,
00626 -9574, -9366, -9158, -8950, -8741, -8533, -8325, -8117, -7909, -7701, -7493,
00627 -7284, -7076, -6868, -6660, -6452, -6244, -6036, -5828, -5619, -5411, -5203,
00628 -4995, -4787, -4579, -4371, -4163, -3954, -3746, -3538, -3330, -3122, -2914,
00629 -2706, -2498, -2289, -2081, -1873, -1665, -1457, -1249, -1041, -833, -624,
00630 -416, -208, 0, 208, 416, 624, 833, 1041, 1249, 1457, 1665, 1873, 2081, 2289,
00631 2498, 2706, 2914, 3122, 3330, 3538, 3746, 3954, 4163, 4371, 4579, 4787, 4995,
00632 5203, 5411, 5619, 5828, 6036, 6244, 6452, 6660, 6868, 7076, 7284, 7493, 7701,
00633 7909, 8117, 8325, 8533, 8741, 8950, 9158, 9366, 9574, 9782, 9990, 10198,
00634 10406, 10615, 10823, 11031, 11239, 11447, 11655, 11863, 12071, 12280, 12488,
00635 12696, 12904, 13112, 13320, 13528, 13736, 13945, 14153, 14361, 14569, 14777,
00636 14985, 15193, 15401, 15610, 15818, 16026, 16234, 16442, 16650, 16858, 17066,
00637 17275, 17483, 17691, 17899, 18107, 18315, 18523, 18732, 18940, 19148, 19356,
00638 19564, 19772, 19980, 20188, 20397, 20605, 20813, 21021, 21229, 21437, 21645,
00639 21853, 22062, 22270, 22478, 22686, 22894, 23102, 23310, 23518, 23727, 23935,
00640 24143, 24351, 24559, 24767, 24975, 25183, 25392, 25600, 25808, 26016, 26224};
00641 
00642 static const int32_t LUT_U_B[256] =
00643 {-66126, -65609, -65093, -64576, -64059, -63543, -63026, -62510, -61993,
00644 -61476, -60960, -60443, -59927, -59410, -58893, -58377, -57860, -57343,
00645 -56827, -56310, -55794, -55277, -54760, -54244, -53727, -53211, -52694,
00646 -52177, -51661, -51144, -50628, -50111, -49594, -49078, -48561, -48045,
00647 -47528, -47011, -46495, -45978, -45462, -44945, -44428, -43912, -43395,
00648 -42878, -42362, -41845, -41329, -40812, -40295, -39779, -39262, -38746,
00649 -38229, -37712, -37196, -36679, -36163, -35646, -35129, -34613, -34096,
00650 -33580, -33063, -32546, -32030, -31513, -30996, -30480, -29963, -29447,
00651 -28930, -28413, -27897, -27380, -26864, -26347, -25830, -25314, -24797,
00652 -24281, -23764, -23247, -22731, -22214, -21698, -21181, -20664, -20148,
00653 -19631, -19114, -18598, -18081, -17565, -17048, -16531, -16015, -15498,
00654 -14982, -14465, -13948, -13432, -12915, -12399, -11882, -11365, -10849,
00655 -10332, -9816, -9299, -8782, -8266, -7749, -7233, -6716, -6199, -5683, -5166,
00656 -4649, -4133, -3616, -3100, -2583, -2066, -1550, -1033, -517, 0, 517, 1033,
00657 1550, 2066, 2583, 3100, 3616, 4133, 4649, 5166, 5683, 6199, 6716, 7233, 7749,
00658 8266, 8782, 9299, 9816, 10332, 10849, 11365, 11882, 12399, 12915, 13432,
00659 13948, 14465, 14982, 15498, 16015, 16531, 17048, 17565, 18081, 18598, 19114,
00660 19631, 20148, 20664, 21181, 21698, 22214, 22731, 23247, 23764, 24281, 24797,
00661 25314, 25830, 26347, 26864, 27380, 27897, 28413, 28930, 29447, 29963, 30480,
00662 30996, 31513, 32030, 32546, 33063, 33580, 34096, 34613, 35129, 35646, 36163,
00663 36679, 37196, 37712, 38229, 38746, 39262, 39779, 40295, 40812, 41329, 41845,
00664 42362, 42878, 43395, 43912, 44428, 44945, 45462, 45978, 46495, 47011, 47528,
00665 48045, 48561, 49078, 49594, 50111, 50628, 51144, 51661, 52177, 52694, 53211,
00666 53727, 54244, 54760, 55277, 55794, 56310, 56827, 57343, 57860, 58377, 58893,
00667 59410, 59927, 60443, 60960, 61476, 61993, 62510, 63026, 63543, 64059, 64576,
00668 65093};
00669 
00670 
00671 
00686 void SphereDriver::YUV422toRGB(uint8_t* argInputData, uint8_t* argOutputData)
00687 {
00688 
00689   uint8_t* Y = argInputData;
00690   uint8_t* U = Y  + mHeight*mWidth;
00691   uint8_t* V = U  + mHeight*mWidth/4;
00692 
00693   uint8_t mode = 0;
00694   uint8_t* R;
00695   uint8_t* G;
00696   uint8_t* B;
00697 
00698   if (0 == strcasecmp(mPalette, "RGB24P"))
00699   {
00700     R = argOutputData;
00701     G = argOutputData + mHeight*mWidth;
00702     B = argOutputData + 2*mHeight*mWidth;
00703   }
00704   else // RGB888
00705   {
00706     R = argOutputData;
00707     G = argOutputData + 1;
00708     B = argOutputData + 2;
00709     mode = 1;
00710   }
00711 
00712   for (int32_t y=0;y < mHeight; ++y)
00713   {
00714     for (int32_t x=0;x<mWidth; ++x)
00715     {
00716       int32_t r,g,b;
00717       int32_t k=0,l=0;
00718 
00719       k = mWidth*y+x;
00720       // The /2 are grouped intentionally that way so the decimal
00721       // parts of each are truncated in that order.
00722       l = (mWidth/2)*(y/2) + x/2;
00723 
00724       r = LUT_Y[Y[k]]                 + LUT_V_R[V[l]];
00725       g = LUT_Y[Y[k]] - LUT_U_G[U[l]] - LUT_V_G[V[l]];
00726       b = LUT_Y[Y[k]] + LUT_U_B[U[l]];
00727 
00728       if (0==mode)
00729       {
00730         *R++ = LIMIT(r>>8);
00731         *G++ = LIMIT(g>>8);
00732         *B++ = LIMIT(b>>8);
00733       }
00734       else
00735       {
00736         *R = LIMIT(r>>8);
00737         *G = LIMIT(g>>8);
00738         *B = LIMIT(b>>8);
00739 
00740         R += 3;
00741         G += 3;
00742         B += 3;
00743       }
00744 
00745 /*
00746       // This all uses integer math.  It can be optimized using lookup tables
00747       // I'll leave that as an excercise for the user (or someone using
00748       // a slower machine).
00749 
00750       int32_t r,g,b;
00751       int32_t k=0,l=0;
00752 
00753       k = Y[mWidth*y+x] * 291 / 250;
00754       // The /2 are grouped intentionally that way so the decimal
00755       // parts of each are truncated in that order.
00756       l = (mWidth/2)*(y/2) + x/2;
00757 
00758       r = k +  V[l] * 399/250 - 223;
00759       g = k + (U[l] * 319 - V[l] * 813) / 1000 + 35;
00760       b = k +  U[l] * 1009/500 - 277;
00761 
00762 
00763       *R++ = LIMIT(r);
00764       *G++ = LIMIT(g);
00765       *B++ = LIMIT(b);
00766 
00767 */
00768 
00769 
00770 /*    // This was all for debugging purposes and runs slower due to
00771       // using all the doubles.  It's good for sanity checking though.
00772       double r,g,b;
00773 
00774       r = rint((Y[mWidth*y+x]-16.0)*1.164 +
00775                (V[(mWidth/2)*(y/2) + x/2]-128.0)*1.596);
00776       g = rint((Y[mWidth*y+x]-16.0)*1.164 -
00777                (U[(mWidth/2)*(y/2) + x/2]-128.0)*0.391 -
00778                (V[(mWidth/2)*(y/2) + x/2]-128.0)*0.813);
00779       b = rint((Y[mWidth*y+x]-16.0)*1.164 +
00780                (U[(mWidth/2)*(y/2) + x/2]-128.0)*2.018);
00781 
00782 
00783       *R++ = LIMIT(r);
00784       *G++ = LIMIT(g);
00785       *B++ = LIMIT(b);
00786 */
00787     }
00788   }
00789 
00790 #if 0
00791   if (0!=mDebug)
00792   {
00793     // Let's display the image locally to make sure it looks right.
00794     static CImg<uint8_t> cameraImage;
00795     cameraImage.width = mWidth;
00796     cameraImage.height = mHeight;
00797     cameraImage.depth = 1;//camera->depth;
00798     cameraImage.dim = mDepth/8;
00799     cameraImage.data = argOutputData;
00800     static CImgDisplay player_disp(cameraImage,"Player Image");
00801     player_disp.display(cameraImage);
00802   }
00803 #endif
00804 
00805 }
00806 
00807 #undef LIMIT
00808 
00809 #if 0
00811 // Extra stuff for building a shared object.
00812 
00813 /* need the extern to avoid C++ name-mangling  */
00814 extern "C" {
00815   int player_driver_init(DriverTable* table)
00816   {
00817     puts("Sphere driver initializing");
00818     SphereDriver_Register(table);
00819     puts("Sphere driver done");
00820     return(0);
00821   }
00822 }
00823 #endif

Last updated 12 September 2005 21:38:45