00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "l1394_dcciso.h"
00019 #include "l1394_message.h"
00020
00021
00022 using std::endl;
00023
00024 namespace L1394{
00025 namespace internal{
00026
00027 DccIso::DccIso(const char *device)
00028 {
00029 if (mutex_array == 0) {
00030 mutex_array = new ThreadMutex*[16];
00031 for (int i = 0; i< 16; i++)
00032 mutex_array[i] = 0;
00033 }
00034 init(&video_mmap);
00035 this->device = device;
00036 fd = -1;
00037 old_buffer = 0;
00038 new_buffer = 0;
00039
00040 mutex = new ThreadMutex(ThreadMutex::RECURSIVE);
00041
00042 release_mode = true;
00043 is_init = false;
00044 map = 0;
00045
00046 frame_array = 0;
00047 unreleased_buffer = 0;
00048 }
00049
00050 DccIso::~DccIso()
00051 {
00052 makeClean();
00053 delete mutex;
00054 }
00055
00056 void DccIso::releaseBuffer(int i)
00057 {
00058 if (unreleased_buffer[i%video_mmap.nb_buffers] == 0) {
00059
00060 }
00061
00062 video1394_wait _vwait;
00063 _vwait.channel = video_mmap.channel;
00064 _vwait.buffer = i % video_mmap.nb_buffers;
00065 SMessage::getInstance()->debugStream() << "DccIso > IOCTRCL release Buffer : " << _vwait.buffer << endl;
00066 if (i >= 0) {
00067 if (ioctl(fd, VIDEO1394_LISTEN_QUEUE_BUFFER, &_vwait) == -1) {
00068
00069 }
00070 }
00071 SMessage::getInstance()->debugStream() << "DccIso < IOCTRCL release Buffer : " << _vwait.buffer << endl;
00072 }
00073
00074 Frame *DccIso::getFrame()
00075 {
00076 if (!is_init )
00077 return 0;
00078 if (release_mode) {
00079 releaseFrame(unreleased_buffer[old_buffer]);
00080 }
00081
00082 mutex->lock();
00083
00084 SMessage::getInstance()->debugStream() << "DccIso > Get Frame" << endl;
00085
00086 video1394_wait vwait;
00087 vwait.channel = video_mmap.channel;
00088 vwait.buffer = 0;
00089 vwait.filltime.tv_sec =1;
00090 vwait.filltime.tv_usec =0;
00091
00092 new_buffer = -1;
00093
00094
00095 for (int i = 0; i < video_mmap.nb_buffers; i++) {
00096 if ( (frame_array[(i+old_buffer+1) % video_mmap.nb_buffers] != 0) && (new_buffer == -1) ) {
00097 new_buffer = (i+old_buffer+1) % video_mmap.nb_buffers;
00098 }
00099 }
00100
00101
00102 if (new_buffer == -1) {
00103 SMessage::getInstance()->debugStream() << "DccIso > No Frame available. Return NULL" << endl;
00104 mutex->unlock();
00105 return NULL;
00106 }
00107
00108 SMessage::getInstance()->debugStream() << "DccIso > Frame Nr. " << new_buffer << " available" << endl;
00109
00110 vwait.buffer = new_buffer;
00111
00112 SMessage::getInstance()->debugStream() << "DccIso > IOCTRCL on buffer " << vwait.buffer << endl;
00113 if (ioctl(fd, VIDEO1394_LISTEN_WAIT_BUFFER, &vwait)<0) {
00114 SMessage::getInstance()->errorStream() << "VIDEO1394_LISTEN_WAIT_BUFFER failed" << endl;
00115 mutex->unlock();
00116 return 0;
00117 }
00118
00119 SMessage::getInstance()->debugStream() << "DccIso < IOCTRCL" << endl;
00120 if (vwait.buffer >0)
00121 SMessage::getInstance()->debugStream() << "DccIso > Buffer ready : " << vwait.buffer << endl;
00122
00123 unreleased_buffer[new_buffer] = frame_array[new_buffer];
00124 frame_array[new_buffer] = 0;
00125
00126 old_buffer = new_buffer;
00127
00128 SMessage::getInstance()->debugStream() << "DccIso < Get Frame" << endl;
00129
00130 mutex->unlock();
00131
00132 return unreleased_buffer[new_buffer];
00133 }
00134
00135 void DccIso::releaseFrame(Frame* buffer)
00136 {
00137 if (buffer == 0) {
00138 SMessage::getInstance()->warningStream() << "DccIso > Releasing Null ptr" << endl;
00139 return;
00140 }
00141
00142 mutex->lock();
00143
00144 int i = (unsigned char*)(buffer->getBuffer()) - map;
00145 i = i / video_mmap.buf_size;
00146
00147 releaseBuffer( i );
00148 frame_array[i] = buffer;
00149 unreleased_buffer[i] = 0;
00150 mutex->unlock();
00151 }
00152
00153 int DccIso::setParameter(const int buffercount, const int channel, const int buffersize)
00154 {
00155 mutex->lock();
00156 makeClean();
00157 old_buffer = buffercount-1;
00158 new_buffer = 0;
00159
00160 unreleased_buffer = new Frame*[buffercount];
00161 frame_array = new Frame*[buffercount];
00162
00163 if ( mutex_array[channel] ) {
00164 SMessage::getInstance()->errorStream() << "Channel " << channel << " already in use " << endl;
00165 mutex->unlock();
00166 return L1394_FAILED;
00167 }
00168 mutex_array[channel] = mutex;
00169
00170 video1394_wait vwait;
00171
00172 video_mmap.channel = channel;
00173 video_mmap.sync_tag = VIDEO1394_SYNC_FRAMES;
00174
00175 if (buffercount <1)
00176 video_mmap.nb_buffers = 1;
00177 else
00178 video_mmap.nb_buffers = buffercount;
00179
00180 video_mmap.buf_size = buffersize;
00181 video_mmap.flags = VIDEO1394_SYNC_FRAMES;
00182
00183
00184 vwait.buffer = 0;
00185 vwait.channel = channel;
00186
00187 fd = open(device.c_str(), O_RDWR);
00188 if(fd < 0) {
00189 SMessage::getInstance()->errorStream()<< "DccIso > Could not open device " << device<< endl;
00190 mutex->unlock();
00191 return L1394_FAILED;
00192 }
00193
00194 if(ioctl(fd, VIDEO1394_LISTEN_CHANNEL, &video_mmap) < 0) {
00195 SMessage::getInstance()->errorStream()<< "DccIso > Video listen failed. " << endl;
00196 mutex->unlock();
00197 return L1394_FAILED;
00198 }
00199
00200 for(int i = 0; i < video_mmap.nb_buffers; i++) {
00201 vwait.buffer = i;
00202 if(ioctl(fd, VIDEO1394_LISTEN_QUEUE_BUFFER, &vwait) == -1) {
00203 SMessage::getInstance()->errorStream() << "DccIso > Queueing Buffer failed" << endl;
00204 mutex->unlock();
00205 return L1394_FAILED;
00206 }
00207 }
00208
00209 if((map = (unsigned char*)mmap(0, video_mmap.nb_buffers * video_mmap.buf_size, PROT_READ, MAP_SHARED, fd, 0)) == (unsigned char*)-1)
00210 {
00211 SMessage::getInstance()->errorStream() << "DccIso > mmap failed " << endl;
00212 mutex->unlock();
00213 return L1394_FAILED;
00214 }
00215
00216 for (int i = 0; i<video_mmap.nb_buffers; i++)
00217 {
00218 frame_array[i] = new Frame( (char*) (map + (i*video_mmap.buf_size)) , buffersize);
00219
00220 unreleased_buffer[i] = 0;
00221 }
00222 is_init = true;
00223 mutex->unlock();
00224 return L1394_SUCCESS;
00225 }
00226
00227 int DccIso::startIsoListen() {
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 return L1394_SUCCESS;
00250 }
00251
00252
00253 int DccIso::stopIsoListen()
00254 {
00255 mutex->lock();
00256 if(ioctl(fd, VIDEO1394_UNLISTEN_CHANNEL, &video_mmap.channel) == -1)
00257 {
00258 SMessage::getInstance()->debugStream() << "DccIso > VIDEO1394_UNLISTEN_CHANNEL failed" << endl;
00259 mutex->unlock();
00260 return L1394_FAILED;
00261 }
00262 mutex->unlock();
00263 return L1394_SUCCESS;
00264 }
00265
00266
00267 void DccIso::makeClean() {
00268 for (int i = 0; i< video_mmap.nb_buffers; i++)
00269 {
00270 if (unreleased_buffer[i] != 0)
00271 releaseFrame(unreleased_buffer[i]);
00272 delete frame_array[i];
00273 }
00274
00275 if (map != (unsigned char*)-1)
00276 munmap(map, video_mmap.nb_buffers * video_mmap.buf_size);
00277
00278 mutex->lock();
00279 if(ioctl(fd, VIDEO1394_UNLISTEN_CHANNEL, &video_mmap.channel) == -1)
00280 SMessage::getInstance()->debugStream() << "DccIso > VIDEO1394_UNLISTEN_CHANNEL failed" << endl;
00281 mutex->unlock();
00282
00283 if (fd > 0)
00284 close(fd);
00285 fd = -1;
00286
00287 delete [] unreleased_buffer;
00288 unreleased_buffer = 0;
00289 delete [] frame_array;
00290 frame_array = 0;
00291 for (int i = 0; i<16; i++)
00292 if (mutex_array[i] == mutex)
00293 mutex_array[i] = 0;
00294 is_init = false;
00295 }
00296 void DccIso::init(video1394_mmap* map) {
00297 map->channel = -1;
00298 map->sync_tag = 1;
00299 map->nb_buffers= 0;
00300 map->buf_size = 0;
00301 map->packet_size = 0;
00302 map->fps = 0;
00303 map->flags = 0;
00304 map->syt_offset = 0;
00305 }
00306
00307 void DccIso::flushQueue() {
00308 mutex->lock();
00309 for ( int i = 0; i< video_mmap.nb_buffers; i++)
00310 if (frame_array[i])
00311 releaseFrame(frame_array[i]);
00312 mutex->unlock();
00313 }
00314 ThreadMutex** DccIso::mutex_array = 0;
00315 }
00316 }