Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

device1394input.C

Go to the documentation of this file.
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 // Driver crashes if it isn't stopped before cancelling the thread.
00043 // May still crash during the cancel though.
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 // Initialize grabbing
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 // Wait for frame to arrive
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 // Get a buffer to transfer to
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 // static FILE *test = 0;
00208 // if(!test) test = fopen("/tmp/test", "w");
00209 // fwrite(src, buffer_size, 1, test);
00210 
00211 // Export the video
00212                         if(dst)
00213                         {
00214                                 memcpy(dst, src, buffer_size);
00215                                 buffer_valid[current_inbuffer] = 1;
00216                                 video_lock->unlock();
00217                         }
00218 
00219 
00220 // Extract the audio
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 // do in-place _FAST_ && _SIMPLE_ upsampling to 48khz
00234 // i also think user should get a warning that his material is effectively 32khz
00235 // we take 16bit samples for both channels in one 32bit int
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 // Export the audio
00251                                 audio_lock->unlock();
00252                         }
00253 
00254 // Advance buffer
00255                         if(!is_overflow)
00256                                 increment_counter(&current_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 // Take over buffer table
00295         buffer_lock->lock("Device1394Input::read_video 1");
00296 // Wait for buffer with timeout
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 // Copy frame
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(&current_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 // Take over buffer table
00328         buffer_lock->lock("Device1394Input::read_audio 1");
00329 // Wait for buffer with timeout
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 //printf("Device1394Input::read_audio 1 %d %d\n", result, timeout);
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 //printf("Device1394Input::read_audio 100\n");
00347         buffer_lock->unlock();
00348         return result;
00349 }
00350 
00351 
00352 
00353 
00354 

Generated on Sun Jan 8 13:38:53 2006 for Cinelerra-svn by  doxygen 1.4.4