00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "jaus/extras/video/sharedimage.h"
00043 #include <string.h>
00044 #include <cstdio>
00045 #include <cstdlib>
00046
00047 using namespace JAUS;
00048
00049 const UInt JAUS_SHARED_IMAGE_HEADER_SIZE = ULONG_SIZE + UINT_SIZE*2 + USHORT_SIZE*2 + BYTE_SIZE;
00050
00051
00057 SharedImage::SharedImage()
00058 {
00059 mCameraID = 0;
00060 mWriteFlag = false;
00061 mpCallback = NULL;
00062 mpCallbackArgs = NULL;
00063 mExitFlag = false;
00064 }
00065
00071 SharedImage::~SharedImage()
00072 {
00073 CloseSharedImage();
00074 }
00075
00076
00088 int SharedImage::CreateSharedImage(const Address& src,
00089 const Byte cameraID,
00090 const unsigned int size)
00091 {
00092 CloseSharedImage();
00093
00094 if( src.IsValid() && !src.IsBroadcast() && size > JAUS_SHARED_IMAGE_HEADER_SIZE )
00095 {
00096 char sname[256];
00097 sprintf(sname, "SharedImage_%d.%d.%d.%d", src.mSubsystem,
00098 src.mNode,
00099 src.mComponent,
00100 cameraID);
00101 if( mImageBuffer.CreateMappedMemory(sname, size + JAUS_SHARED_IMAGE_HEADER_SIZE) ||
00102 mImageBuffer.OpenMappedMemory(sname, CxUtils::MappedMemory::ReadWriteAccess, size + JAUS_SHARED_IMAGE_HEADER_SIZE))
00103 {
00104 Time::Stamp tstamp;
00105 UInt number;
00106 UShort width = 0, height = 0;
00107 Byte channels = 0;
00108 tstamp = Time::GetUtcTimeMs();
00109 number = 0;
00110 mImageBuffer.Lock();
00111 mImageBuffer->SetWritePos(0);
00112 mImageBuffer->Write(tstamp);
00113 mImageBuffer->Write(number);
00114 mImageBuffer->Write(width);
00115 mImageBuffer->Write(height);
00116 mImageBuffer->Write(channels);
00117 mImageBuffer.Unlock();
00118
00119 mWriteFlag = true;
00120 mSourceID = src;
00121 mCameraID = cameraID;
00122 return OK;
00123 }
00124 }
00125
00126 CloseSharedImage();
00127 return FAILURE;
00128 }
00129
00130
00141 int SharedImage::OpenSharedImage(const Address& src, const Byte cameraID)
00142 {
00143 if(src.IsValid() && !src.IsBroadcast())
00144 {
00145 char sname[256];
00146 sprintf(sname, "SharedImage_%d.%d.%d.%d", src.mSubsystem,
00147 src.mNode,
00148 src.mComponent,
00149 cameraID);
00150 if( mImageBuffer.OpenMappedMemory(sname) )
00151 {
00152 mWriteFlag = false;
00153 mSourceID = src;
00154 mCameraID = cameraID;
00155 return OK;
00156 }
00157 }
00158
00159 return FAILURE;
00160 }
00161
00162
00168 int SharedImage::CloseSharedImage()
00169 {
00170 mExitFlag = true;
00171 for(unsigned int i = 0; i < 500; i++)
00172 {
00173 if(mCallbackThread.IsThreadActive() == false)
00174 {
00175 break;
00176 }
00177 CxUtils::SleepMs(1);
00178 }
00179 mCallbackThread.StopThread();
00180
00181 {
00182 Mutex::ScopedLock lock(&mCallbackMutex);
00183 mpCallback = NULL;
00184 mpCallbackArgs = NULL;
00185 }
00186
00187 if( mWriteFlag )
00188 {
00189 mImageBuffer.Lock();
00190 memset((void *)mImageBuffer.GetMemory(), 0, mImageBuffer->Size());
00191 mImageBuffer.Unlock();
00192 }
00193 mImageBuffer.CloseMappedMemory();
00194
00195 mWriteFlag = false;
00196 mExitFlag = false;
00197
00198 return OK;
00199 }
00200
00201
00214 int SharedImage::RegisterCallback(void (*func)(const Address& src,
00215 const Byte cameraID,
00216 const Image& img,
00217 const unsigned int frameNumber,
00218 void* args), void *fargs)
00219 {
00220 if( func )
00221 {
00222 mCallbackMutex.Lock();
00223 mpCallback = func;
00224 mpCallbackArgs = fargs;
00225 mCallbackMutex.Unlock();
00226
00227 if( mCallbackThread.IsThreadActive() == false )
00228 {
00229 mCallbackThread.CreateThread(&SharedImage::SharedImageUpdate, this);
00230 }
00231 return OK;
00232 }
00233 return FAILURE;
00234 }
00235
00236
00244 int SharedImage::ClearCallback()
00245 {
00246 mCallbackMutex.Lock();
00247 mpCallback = NULL;
00248 mpCallbackArgs = NULL;
00249 mCallbackMutex.Unlock();
00250
00251 return OK;
00252 }
00253
00254
00265 int SharedImage::SetFrame(const unsigned char* rawImage,
00266 const unsigned int width,
00267 const unsigned int height,
00268 const unsigned char channels,
00269 const unsigned int frameNumber)
00270 {
00271 int result = FAILURE;
00272
00273 if( mWriteFlag &&
00274 mImageBuffer.IsOpen() &&
00275 width*height*channels <= mImageBuffer->Size() - JAUS_SHARED_IMAGE_HEADER_SIZE)
00276 {
00277 Time::Stamp imgTimeStamp;
00278
00279 imgTimeStamp = Time::GetUtcTimeMs();
00280 mImageBuffer.Lock();
00281 mImageBuffer->SetWritePos(0);
00282 mImageBuffer->Write(imgTimeStamp);
00283 mImageBuffer->Write(frameNumber);
00284 mImageBuffer->Write(width);
00285 mImageBuffer->Write(height);
00286 mImageBuffer->Write(channels);
00287 mImageBuffer->Write(rawImage, width*height*channels );
00288 mImageBuffer.Unlock();
00289 result = OK;
00290 }
00291
00292 return result;
00293 }
00294
00295
00305 int SharedImage::GetFrame(Image& img) const
00306 {
00307 int result = FAILURE;
00308 Time::Stamp tstamp;
00309 UInt number;
00310 unsigned int width, height;
00311 Byte channels;
00312
00313 if( mImageBuffer.IsOpen() )
00314 {
00315 mImageBuffer.Lock();
00316 mImageBuffer->SetReadPos(0);
00317 if( mImageBuffer->Read( tstamp ) &&
00318 mImageBuffer->Read( number ) &&
00319 mImageBuffer->Read( width ) &&
00320 mImageBuffer->Read( height ) &&
00321 mImageBuffer->Read( channels ) )
00322 {
00323 if( width && height && channels &&
00324 mImageBuffer->Size() - JAUS_SHARED_IMAGE_HEADER_SIZE == (unsigned int)((unsigned int)(width)*height*channels))
00325 {
00326 result = img.Create(width, height, channels, mImageBuffer.GetMemory() + JAUS_SHARED_IMAGE_HEADER_SIZE );
00327 }
00328 }
00329 mImageBuffer.Unlock();
00330 }
00331
00332 return result;
00333 }
00334
00335
00352 int SharedImage::GetFrame(unsigned char*& image,
00353 unsigned int& size,
00354 unsigned int& width,
00355 unsigned int& height,
00356 unsigned char& channels,
00357 unsigned int& frameNumber) const
00358 {
00359 int result = FAILURE;
00360 Time::Stamp tstamp;
00361
00362 if( mImageBuffer.IsOpen() )
00363 {
00364 mImageBuffer.Lock();
00365 mImageBuffer->SetReadPos(0);
00366 if( mImageBuffer->Read( tstamp ) &&
00367 mImageBuffer->Read( frameNumber ) &&
00368 mImageBuffer->Read( width ) &&
00369 mImageBuffer->Read( height ) &&
00370 mImageBuffer->Read( channels ) )
00371 {
00372 if( width && height && channels )
00373 {
00374 if(size < width*height*channels || image == NULL)
00375 {
00376 if(image)
00377 {
00378 delete[] image;
00379 image = NULL;
00380 }
00381 size = width*height*channels;
00382 image = new unsigned char[size + 256];
00383 }
00384 result = mImageBuffer->Read(image, width*height*channels) == width*height*channels ? OK : FAILURE;
00385 }
00386 }
00387 mImageBuffer.Unlock();
00388 }
00389
00390 return result;
00391 }
00392
00393
00401 UInt SharedImage::GetFrameNumber() const
00402 {
00403 int result = FAILURE;
00404 UInt number = 0;
00405
00406 if( mImageBuffer.IsOpen() )
00407 {
00408 mImageBuffer.Lock();
00409 if( mImageBuffer->Read( number, UINT_SIZE ) )
00410 result = OK;
00411 mImageBuffer.Unlock();
00412 }
00413
00414 if( result )
00415 return number;
00416 return 0;
00417 }
00418
00419
00425 bool SharedImage::IsOpen() const
00426 {
00427 if( mImageBuffer.IsOpen() ||
00428 mCallbackThread.IsThreadActive() )
00429 {
00430 return true;
00431 }
00432 return false;
00433 }
00434
00435
00444 bool SharedImage::IsActive(const unsigned int timeout) const
00445 {
00446 if(mImageBuffer.IsOpen())
00447 {
00448 Time::Stamp imgTimeStamp = 0;
00449 mImageBuffer.Lock();
00450 mImageBuffer->SetReadPos(0);
00451 mImageBuffer->Read(imgTimeStamp);
00452 mImageBuffer.Unlock();
00453 Time::Stamp currentTime = Time::GetUtcTimeMs();
00454 if(currentTime > imgTimeStamp && currentTime - imgTimeStamp < timeout)
00455 {
00456 return true;
00457 }
00458 }
00459 return false;
00460 }
00461
00462
00469 void SharedImage::SharedImageUpdate(void *args)
00470 {
00471 SharedImage *img = (SharedImage*)args;
00472 UInt imgNumber = 0, prevImgNumber = 0;
00473 Time::Stamp imgTimeStamp = 0, currentTime = 0;
00474 unsigned int width, height;
00475 Byte channels;
00476
00477 bool haveCallback = true;
00478 while( img->mExitFlag == false && img && !img->mCallbackThread.QuitThreadFlag() && haveCallback)
00479 {
00480 if( img->mImageBuffer.IsOpen() )
00481 {
00482 bool haveImage = false;
00483 width = height = channels = 0;
00484 img->mImageBuffer.Lock();
00485 img->mImageBuffer->SetReadPos(0);
00486 if( img->mImageBuffer->Read(imgTimeStamp) &&
00487 img->mImageBuffer->Read(imgNumber) &&
00488 img->mImageBuffer->Read(width) &&
00489 img->mImageBuffer->Read(height) &&
00490 img->mImageBuffer->Read(channels) )
00491 {
00492 if(imgTimeStamp &&
00493 imgNumber != prevImgNumber &&
00494 width > 0 && height > 0 && channels >= 1 &&
00495 width*height*((unsigned int)channels) <= img->mImageBuffer->Size() - JAUS_SHARED_IMAGE_HEADER_SIZE)
00496 {
00497 if( img->mTempImage.Create(width,
00498 height,
00499 channels,
00500 img->mImageBuffer.GetMemory() + JAUS_SHARED_IMAGE_HEADER_SIZE))
00501 {
00502 haveImage = true;
00503 }
00504 }
00505 prevImgNumber = imgNumber;
00506 }
00507 img->mImageBuffer.Unlock();
00508
00509 if(haveImage && img->mExitFlag == false)
00510 {
00511 img->mCallbackMutex.Lock();
00512 if( img->mpCallback )
00513 {
00514 img->mpCallback(img->mSourceID, img->mCameraID, img->mTempImage, imgNumber, img->mpCallbackArgs);
00515 }
00516 else
00517 {
00518 haveCallback = false;
00519 }
00520 img->mCallbackMutex.Unlock();
00521 }
00522
00523 currentTime = Time::GetUtcTimeMs();
00524 if(imgTimeStamp == 0 || (imgTimeStamp < currentTime && currentTime - imgTimeStamp > 10000))
00525 {
00526 img->mImageBuffer.CloseMappedMemory();
00527
00528
00529 for(unsigned int i = 0; i < 1000; i++)
00530 {
00531 if( img->mCallbackThread.QuitThreadFlag() || img->mExitFlag)
00532 break;
00533
00534 CxUtils::SleepMs(1);
00535 }
00536 }
00537 }
00538 else
00539 {
00540
00541 img->OpenSharedImage(img->mSourceID, img->mCameraID);
00542 }
00543
00544 CxUtils::SleepMs(10);
00545 }
00546 }
00547
00548