00001 #include "condition.h"
00002 #include "device1394input.h"
00003 #include "ieee1394-ioctl.h"
00004 #include "mutex.h"
00005 #include "vframe.h"
00006 #include "video1394.h"
00007
00008 #include <errno.h>
00009 #include <fcntl.h>
00010 #include <sys/ioctl.h>
00011 #include <sys/mman.h>
00012 #include <stdio.h>
00013 #include <string.h>
00014 #include <unistd.h>
00015
00016 #define INPUT_SAMPLES 131072
00017 #define BUFFER_TIMEOUT 500000
00018
00019
00020 Device1394Input::Device1394Input()
00021 : Thread(1, 1, 0)
00022 {
00023 buffer = 0;
00024 buffer_valid = 0;
00025 input_buffer = 0;
00026 done = 0;
00027 total_buffers = 0;
00028 current_inbuffer = 0;
00029 current_outbuffer = 0;
00030 buffer_size = 0;
00031 audio_buffer = 0;
00032 audio_samples = 0;
00033 video_lock = 0;
00034 audio_lock = 0;
00035 buffer_lock = 0;
00036 decoder = 0;
00037 fd = -1;
00038 }
00039
00040 Device1394Input::~Device1394Input()
00041 {
00042
00043
00044
00045 if(Thread::running())
00046 {
00047 done = 1;
00048 Thread::cancel();
00049 Thread::join();
00050 }
00051
00052 if(buffer)
00053 {
00054 for(int i = 0; i < total_buffers; i++)
00055 delete [] buffer[i];
00056 delete [] buffer;
00057 delete [] buffer_valid;
00058 }
00059
00060 if(input_buffer)
00061 munmap(input_buffer, total_buffers * buffer_size);
00062
00063 if(audio_buffer)
00064 {
00065 delete [] audio_buffer;
00066 }
00067
00068 if(decoder)
00069 {
00070 dv_delete(decoder);
00071 }
00072
00073 if(video_lock) delete video_lock;
00074 if(audio_lock) delete audio_lock;
00075 if(buffer_lock) delete buffer_lock;
00076 if(fd > 0)
00077 {
00078 close(fd);
00079 }
00080 }
00081
00082 int Device1394Input::open(int port,
00083 int channel,
00084 int length,
00085 int channels,
00086 int samplerate,
00087 int bits,
00088 int w,
00089 int h)
00090 {
00091 int result = 0;
00092 this->channel = channel;
00093 this->length = length;
00094 this->channels = channels;
00095 this->samplerate = samplerate;
00096 this->bits = bits;
00097 this->w = w;
00098 this->h = h;
00099 is_pal = (h == 576);
00100 buffer_size = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
00101 total_buffers = length;
00102
00103
00104
00105 if(fd < 0)
00106 {
00107 #define PATH "/dev/dv1394"
00108 if((fd = ::open(PATH, O_RDWR)) < 0)
00109 {
00110 printf("Device1394Input::open %s: %s\n", PATH, strerror(errno));
00111 }
00112 else
00113 {
00114 #define CIP_N_NTSC 68000000
00115 #define CIP_D_NTSC 1068000000
00116
00117 #define CIP_N_PAL 1
00118 #define CIP_D_PAL 16
00119
00120 struct dv1394_init init =
00121 {
00122 api_version: DV1394_API_VERSION,
00123 channel: channel,
00124 n_frames: length,
00125 format: is_pal ? DV1394_PAL: DV1394_NTSC,
00126 cip_n: 0,
00127 cip_d: 0,
00128 syt_offset: 0
00129 };
00130 if(ioctl(fd, DV1394_IOC_INIT, &init) < 0)
00131 {
00132 printf("Device1394Input::open DV1394_IOC_INIT: %s\n", strerror(errno));
00133 }
00134
00135 input_buffer = (unsigned char*)mmap(0,
00136 length * buffer_size,
00137 PROT_READ | PROT_WRITE,
00138 MAP_SHARED,
00139 fd,
00140 0);
00141
00142 if(ioctl(fd, DV1394_IOC_START_RECEIVE, 0) < 0)
00143 {
00144 perror("Device1394Input::open DV1394_START_RECEIVE");
00145 }
00146 }
00147
00148
00149
00150 buffer = new char*[total_buffers];
00151 buffer_valid = new int[total_buffers];
00152 bzero(buffer_valid, sizeof(int) * total_buffers);
00153 for(int i = 0; i < total_buffers; i++)
00154 {
00155 buffer[i] = new char[DV_PAL_SIZE];
00156 }
00157
00158
00159 audio_buffer = new char[INPUT_SAMPLES * 2 * channels];
00160
00161 audio_lock = new Condition(0, "Device1394Input::audio_lock");
00162 video_lock = new Condition(0, "Device1394Input::video_lock");
00163 buffer_lock = new Mutex("Device1394Input::buffer_lock");
00164
00165 decoder = dv_new();
00166
00167 Thread::start();
00168 }
00169 return result;
00170 }
00171
00172 void Device1394Input::run()
00173 {
00174 while(!done)
00175 {
00176
00177 struct dv1394_status status;
00178
00179 Thread::enable_cancel();
00180 if(ioctl(fd, DV1394_IOC_WAIT_FRAMES, 1))
00181 {
00182 perror("Device1394Input::run DV1394_IOC_WAIT_FRAMES");
00183 sleep(1);
00184 }
00185 else
00186 if(ioctl(fd, DV1394_IOC_GET_STATUS, &status))
00187 {
00188 perror("Device1394Input::run DV1394_IOC_GET_STATUS");
00189 }
00190 Thread::disable_cancel();
00191
00192
00193
00194 buffer_lock->lock("Device1394Input::run 1");
00195
00196 for(int i = 0; i < status.n_clear_frames; i++)
00197 {
00198
00199 char *dst = 0;
00200 int is_overflow = 0;
00201 if(!buffer_valid[current_inbuffer])
00202 dst = buffer[current_inbuffer];
00203 else
00204 is_overflow = 1;
00205
00206 char *src = (char*)(input_buffer + buffer_size * status.first_clear_frame);
00207
00208
00209
00210
00211
00212 if(dst)
00213 {
00214 memcpy(dst, src, buffer_size);
00215 buffer_valid[current_inbuffer] = 1;
00216 video_lock->unlock();
00217 }
00218
00219
00220
00221 if(audio_samples < INPUT_SAMPLES - 2048)
00222 {
00223 int audio_result = dv_read_audio(decoder,
00224 (unsigned char*)audio_buffer +
00225 audio_samples * 2 * 2,
00226 (unsigned char*)src,
00227 buffer_size,
00228 channels,
00229 bits);
00230 int real_freq = decoder->decoder->audio->frequency;
00231 if (real_freq == 32000)
00232 {
00233
00234
00235
00236 int *twosample = (int*) (audio_buffer + audio_samples * 2 * 2);
00237 int from = audio_result - 1;
00238 int new_result = audio_result * 48000 / real_freq;
00239 for (int to = new_result - 1; to >=0; to--)
00240 {
00241 if ((to % 3) == 0 || (to % 3) == 1) from --;
00242 twosample[to] = twosample[from];
00243 }
00244 audio_result = new_result;
00245 }
00246
00247
00248 audio_samples += audio_result;
00249
00250
00251 audio_lock->unlock();
00252 }
00253
00254
00255 if(!is_overflow)
00256 increment_counter(¤t_inbuffer);
00257
00258
00259 Thread::enable_cancel();
00260 if(ioctl(fd, DV1394_IOC_RECEIVE_FRAMES, 1))
00261 {
00262 perror("Device1394Input::run DV1394_IOC_RECEIVE_FRAMES");
00263 }
00264
00265 if(ioctl(fd, DV1394_IOC_GET_STATUS, &status))
00266 {
00267 perror("Device1394Input::run DV1394_IOC_GET_STATUS");
00268 }
00269 Thread::disable_cancel();
00270 }
00271
00272 buffer_lock->unlock();
00273 }
00274 }
00275
00276 void Device1394Input::increment_counter(int *counter)
00277 {
00278 (*counter)++;
00279 if(*counter >= total_buffers) *counter = 0;
00280 }
00281
00282 void Device1394Input::decrement_counter(int *counter)
00283 {
00284 (*counter)--;
00285 if(*counter < 0) *counter = total_buffers - 1;
00286 }
00287
00288
00289
00290 int Device1394Input::read_video(VFrame *data)
00291 {
00292 int result = 0;
00293
00294
00295 buffer_lock->lock("Device1394Input::read_video 1");
00296
00297 while(!buffer_valid[current_outbuffer] && !result)
00298 {
00299 buffer_lock->unlock();
00300 result = video_lock->timed_lock(BUFFER_TIMEOUT, "Device1394Input::read_video 2");
00301 buffer_lock->lock("Device1394Input::read_video 3");
00302 }
00303
00304
00305 if(buffer_valid[current_outbuffer])
00306 {
00307 data->allocate_compressed_data(buffer_size);
00308 data->set_compressed_size(buffer_size);
00309 memcpy(data->get_data(), buffer[current_outbuffer], buffer_size);
00310 buffer_valid[current_outbuffer] = 0;
00311 increment_counter(¤t_outbuffer);
00312 }
00313
00314 buffer_lock->unlock();
00315 return result;
00316 }
00317
00318
00319
00320
00321 int Device1394Input::read_audio(char *data, int samples)
00322 {
00323 int result = 0;
00324 int timeout = (int64_t)samples * (int64_t)1000000 * (int64_t)2 / (int64_t)samplerate;
00325 if(timeout < 500000) timeout = 500000;
00326
00327
00328 buffer_lock->lock("Device1394Input::read_audio 1");
00329
00330 while(audio_samples < samples && !result)
00331 {
00332 buffer_lock->unlock();
00333 result = audio_lock->timed_lock(timeout, "Device1394Input::read_audio 2");
00334 buffer_lock->lock("Device1394Input::read_audio 3");
00335 }
00336
00337
00338 if(audio_samples >= samples)
00339 {
00340 memcpy(data, audio_buffer, samples * bits * channels / 8);
00341 memcpy(audio_buffer,
00342 audio_buffer + samples * bits * channels / 8,
00343 (audio_samples - samples) * bits * channels / 8);
00344 audio_samples -= samples;
00345 }
00346
00347 buffer_lock->unlock();
00348 return result;
00349 }
00350
00351
00352
00353
00354