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

device1394output.C

Go to the documentation of this file.
00001 #ifdef HAVE_FIREWIRE
00002 
00003 
00004 
00005 #include "audiodevice.h"
00006 #include "condition.h"
00007 #include "device1394output.h"
00008 #include "mutex.h"
00009 #include "playbackconfig.h"
00010 #include "bctimer.h"
00011 #include "vframe.h"
00012 #include "videodevice.h"
00013 
00014 #include <errno.h>
00015 #include <fcntl.h>
00016 #include <string.h>
00017 #include <sys/ioctl.h>
00018 #include <sys/mman.h>
00019 #include <unistd.h>
00020 #include <sys/utsname.h>
00021 
00022 
00023 
00024 
00025 
00026 // Crazy DV internals
00027 #define CIP_N_NTSC 2436
00028 #define CIP_D_NTSC 38400
00029 #define CIP_N_PAL 1
00030 #define CIP_D_PAL 16
00031 #define OUTPUT_SAMPLES 262144
00032 #define BUFFER_TIMEOUT 500000
00033 
00034 
00035 Device1394Output::Device1394Output(AudioDevice *adevice)
00036  : Thread(1, 0, 0)
00037 {
00038         reset();
00039         this->adevice = adevice;
00040 
00041         set_ioctls();
00042 }
00043 
00044 Device1394Output::Device1394Output(VideoDevice *vdevice)
00045  : Thread(1, 0, 0)
00046 {
00047         reset();
00048         this->vdevice = vdevice;
00049 
00050         set_ioctls();
00051 }
00052 
00053 Device1394Output::~Device1394Output()
00054 {
00055         if(Thread::running())
00056         {
00057                 done = 1;
00058                 start_lock->unlock();
00059                 Thread::cancel();
00060                 Thread::join();
00061         }
00062 
00063         if(buffer)
00064         {
00065                 for(int i = 0; i < total_buffers; i++)
00066                 {
00067                         if(buffer[i]) delete [] buffer[i];
00068                 }
00069                 delete [] buffer;
00070                 delete [] buffer_size;
00071                 delete [] buffer_valid;
00072         }
00073 
00074         if(audio_lock) delete audio_lock;
00075         if(video_lock) delete video_lock;
00076         if(start_lock) delete start_lock;
00077         if(audio_buffer) delete [] audio_buffer;
00078 
00079         if(output_fd >= 0)
00080         {
00081         output_queue.buffer = (output_mmap.nb_buffers + output_queue.buffer - 1) % output_mmap.nb_buffers;
00082 
00083                 if(get_dv1394())
00084                 {
00085                         if(ioctl(output_fd, DV1394_IOC_WAIT_FRAMES, status.init.n_frames - 1) < 0)
00086                         {
00087                                 fprintf(stderr,
00088                                         "Device1394Output::close_all: DV1394_WAIT_FRAMES %i: %s",
00089                                         output_mmap.nb_buffers,
00090                                         strerror(errno));
00091                         }
00092                         munmap(output_buffer, status.init.n_frames *
00093                                 (is_pal ? DV1394_PAL_FRAME_SIZE : DV1394_NTSC_FRAME_SIZE));
00094                         if(ioctl(output_fd, DV1394_IOC_SHUTDOWN, NULL) < 0)
00095                         {
00096                                 perror("Device1394Output::close_all: DV1394_SHUTDOWN");
00097                         }
00098                 }
00099                 else
00100                 {
00101                 if(ioctl(output_fd, video1394_talk_wait_buffer, &output_queue) < 0) 
00102                         {
00103                 fprintf(stderr, 
00104                                         "Device1394::close_all: VIDEO1394_TALK_WAIT_BUFFER %s: %s",
00105                                         output_queue,
00106                                         strerror(errno));
00107                 }
00108                 munmap(output_buffer, output_mmap.nb_buffers * output_mmap.buf_size);
00109 
00110                 if(ioctl(output_fd, video1394_untalk_channel, &output_mmap.channel) < 0)
00111                         {
00112                 perror("Device1394::close_all: VIDEO1394_UNTALK_CHANNEL");
00113                 }
00114                 }
00115 
00116         close(output_fd);
00117 
00118 //              if(avc_handle)
00119 //                      raw1394_destroy_handle(avc_handle);
00120         }
00121 
00122         if(temp_frame) delete temp_frame;
00123         if(temp_frame2) delete temp_frame2;
00124         if(video_encoder) dv_delete(video_encoder);
00125         if(audio_encoder) dv_delete(audio_encoder);
00126         if(buffer_lock) delete buffer_lock;
00127         if(position_lock) delete position_lock;
00128 }
00129 
00130 
00131 void Device1394Output::reset()
00132 {
00133         buffer = 0;
00134         buffer_size = 0;
00135         total_buffers = 0;
00136         current_inbuffer = 0;
00137         current_outbuffer = 0;
00138         done = 0;
00139         audio_lock = 0;
00140         video_lock = 0;
00141         start_lock = 0;
00142         buffer_lock = 0;
00143         position_lock = 0;
00144         video_encoder = 0;
00145         audio_encoder = 0;
00146         audio_buffer = 0;
00147         audio_samples = 0;
00148         output_fd = -1;
00149 //      avc_handle = 0;
00150         temp_frame = 0;
00151         temp_frame2 = 0;
00152         audio_position = 0;
00153         interrupted = 0;
00154         have_video = 0;
00155         adevice = 0;
00156         vdevice = 0;
00157         is_pal = 0;
00158 }
00159 
00160 int Device1394Output::get_dv1394()
00161 {
00162         if(adevice) return adevice->out_config->driver == AUDIO_DV1394;
00163         if(vdevice) return vdevice->out_config->driver == PLAYBACK_DV1394;
00164 }
00165 
00166 int Device1394Output::open(char *path,
00167         int port,
00168         int channel,
00169         int length,
00170         int channels, 
00171         int bits, 
00172         int samplerate,
00173         int syt)
00174 {
00175         this->channels = channels;
00176         this->bits = bits;
00177         this->samplerate = samplerate;
00178         this->total_buffers = length;
00179         this->syt = syt;
00180 
00181 // Set PAL mode based on frame height
00182         if(vdevice) is_pal = (vdevice->out_h == 576);
00183 
00184     struct dv1394_init setup = 
00185         {
00186        api_version: DV1394_API_VERSION,
00187        channel:     channel,
00188            n_frames:    length,
00189        format:      is_pal ? DV1394_PAL : DV1394_NTSC,
00190        cip_n:       0,
00191        cip_d:       0,
00192        syt_offset:  syt
00193     };
00194 
00195         
00196 
00197 //printf("Device1394::open_output 2 %s %d %d %d %d\n", path, port, channel, length, syt);
00198         if(output_fd < 0)
00199         {
00200         output_fd = ::open(path, O_RDWR);
00201 
00202                 if(output_fd <= 0)
00203                 {
00204                         fprintf(stderr, 
00205                                 "Device1394Output::open path=%s: %s\n", 
00206                                 path,
00207                                 strerror(errno));
00208                         return 1;
00209                 }
00210                 else
00211                 {
00212                 output_mmap.channel = channel;
00213                 output_queue.channel = channel;
00214                 output_mmap.sync_tag = 0;
00215                 output_mmap.nb_buffers = total_buffers;
00216                 output_mmap.buf_size = 320 * 512;
00217                 output_mmap.packet_size = 512;
00218 // Shouldn't this be handled by the video1394 driver?
00219 // dvgrab originally used 19000
00220 // JVC DVL300 -> 30000
00221                 output_mmap.syt_offset = syt;
00222                 output_mmap.flags = VIDEO1394_VARIABLE_PACKET_SIZE;
00223 
00224 
00225 
00226                         if(get_dv1394())
00227                         {
00228                                 if(ioctl(output_fd, DV1394_IOC_INIT, &setup) < 0)
00229                                 {
00230                                         perror("Device1394Output::open DV1394_INIT");
00231                                 }
00232 
00233                                 if(ioctl(output_fd, DV1394_IOC_GET_STATUS, &status) < 0)
00234                                 {
00235                                         perror("Device1394Output::open DV1394_GET_STATUS");
00236                                 }
00237 
00238                         output_buffer = (unsigned char*)mmap(0,
00239                         output_mmap.nb_buffers * (is_pal ? DV1394_PAL_FRAME_SIZE : DV1394_NTSC_FRAME_SIZE),
00240                         PROT_READ | PROT_WRITE,
00241                         MAP_SHARED,
00242                         output_fd,
00243                         0);
00244                         }
00245                         else
00246                         {
00247                         if(ioctl(output_fd, video1394_talk_channel, &output_mmap) < 0)
00248                                 {
00249                         perror("Device1394Output::open VIDEO1394_TALK_CHANNEL:");
00250                         }
00251 
00252                         output_buffer = (unsigned char*)mmap(0, 
00253                                         output_mmap.nb_buffers * output_mmap.buf_size,
00254                         PROT_READ | PROT_WRITE, 
00255                                         MAP_SHARED, 
00256                                         output_fd, 
00257                                         0);
00258                         }
00259 
00260                 if(output_buffer <= 0)
00261                         {
00262                 perror("Device1394Output::open mmap");
00263                 }
00264 
00265                         unused_buffers = output_mmap.nb_buffers;
00266                 output_queue.buffer = 0;
00267                 output_queue.packet_sizes = packet_sizes;
00268                 continuity_counter = 0;
00269                 cip_counter = 0;
00270 
00271 // Create buffers
00272                         buffer = new char*[total_buffers];
00273                         for(int i = 0; i < length; i++)
00274                                 buffer[i] = new char[get_dv1394() ?
00275                                         (is_pal ? DV1394_PAL_FRAME_SIZE : DV1394_NTSC_FRAME_SIZE) :
00276                                         DV_PAL_SIZE];
00277                         buffer_size = new int[total_buffers];
00278                         buffer_valid = new int[total_buffers];
00279                         bzero(buffer_size, sizeof(int) * total_buffers);
00280                         bzero(buffer_valid, sizeof(int) * total_buffers);
00281                         bzero(buffer, sizeof(char*) * total_buffers);
00282                         video_lock = new Condition(0, "Device1394Output::video_lock");
00283                         audio_lock = new Condition(0, "Device1394Output::audio_lock");
00284                         start_lock = new Condition(0, "Device1394Output::start_lock");
00285                         buffer_lock = new Mutex("Device1394Output::buffer_lock");
00286                         position_lock = new Mutex("Device1394Output::position_lock");
00287                         encoder = dv_new();
00288                         audio_buffer = new char[OUTPUT_SAMPLES * channels * bits / 8];
00289                         Thread::start();
00290         }
00291         }
00292         return 0;
00293 }
00294 
00295 void Device1394Output::run()
00296 {
00297         unsigned char *output;
00298         char *out_buffer;
00299         int out_size;
00300 
00301         Thread::enable_cancel();
00302         start_lock->lock("Device1394Output::run");
00303         Thread::disable_cancel();
00304 
00305 //Timer timer;
00306 // Write buffers continuously
00307         while(!done)
00308         {
00309 // Get current buffer to play
00310                 if(done) return;
00311 
00312                 buffer_lock->lock("Device1394Output::run 1");
00313 
00314                 out_buffer = buffer[current_outbuffer];
00315                 out_size = buffer_size[current_outbuffer];
00316 
00317 
00318 
00319 
00320 
00321 // No video.  Put in a fake frame for audio only
00322                 if(!have_video)
00323                 {
00324 #include "data/fake_ntsc_dv.h"
00325                         out_size = sizeof(fake_ntsc_dv) - 4;
00326                         out_buffer = (char*)fake_ntsc_dv + 4;
00327                 }
00328 
00329 
00330 
00331 
00332                 if(get_dv1394())
00333                 {
00334                         output = output_buffer + 
00335                                 out_size *
00336                                 status.first_clear_frame;
00337                 }
00338                 else
00339                 {
00340                         output = output_buffer + 
00341                                 output_queue.buffer * 
00342                                 output_mmap.buf_size;
00343                 }
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 // Got a buffer
00353                 if(out_buffer && out_size)
00354                 {
00355 // Calculate number of samples needed based on given pattern for 
00356 // norm.
00357                         int samples_per_frame = 2048;
00358 
00359 // Encode audio
00360                         if(audio_samples > samples_per_frame)
00361                         {
00362 
00363                                 int samples_written = dv_write_audio(encoder,
00364                                         (unsigned char*)out_buffer,
00365                                         (unsigned char*)audio_buffer,
00366                                         samples_per_frame,
00367                                         channels,
00368                                         bits,
00369                                         samplerate,
00370                                         is_pal ? DV_PAL : DV_NTSC);
00371                                 memcpy(audio_buffer, 
00372                                         audio_buffer + samples_written * bits * channels / 8,
00373                                         (audio_samples - samples_written) * bits * channels / 8);
00374                                 audio_samples -= samples_written;
00375                                 position_lock->lock("Device1394Output::run");
00376                                 audio_position += samples_written;
00377                                 position_lock->unlock();
00378 
00379 
00380                                 audio_lock->unlock();
00381                         }
00382 
00383 // Copy from current buffer to mmap buffer with firewire encryption
00384                         if(get_dv1394())
00385                         {
00386                                 memcpy(output, out_buffer, out_size);
00387                         }
00388                         else
00389                         {
00390                                 encrypt((unsigned char*)output, 
00391                                         (unsigned char*)out_buffer, 
00392                                         out_size);
00393                         }
00394                         buffer_valid[current_outbuffer] = 0;
00395                 }
00396 
00397 // Advance buffer number if possible
00398                 increment_counter(&current_outbuffer);
00399 
00400 // Reuse same buffer next time
00401                 if(!buffer_valid[current_outbuffer])
00402                 {
00403                         decrement_counter(&current_outbuffer);
00404                 }
00405                 else
00406 // Wait for user to reach current buffer before unlocking any more.
00407                 {
00408                         video_lock->unlock();
00409                 }
00410 
00411 
00412                 buffer_lock->unlock();
00413 //printf("Device1394Output::run 100\n");
00414 
00415 
00416 
00417                 if(out_size > 0)
00418                 {
00419 
00420 // Write mmap to device
00421                         Thread::enable_cancel();
00422                         unused_buffers--;
00423 
00424 
00425                         if(get_dv1394())
00426                         {
00427                                 if(ioctl(output_fd, DV1394_IOC_SUBMIT_FRAMES, 1) < 0)
00428                                 {
00429                                         perror("Device1394Output::run DV1394_SUBMIT_FRAMES");
00430                                 }
00431                                 if(ioctl(output_fd, DV1394_IOC_WAIT_FRAMES, 1) < 0)
00432                                 {
00433                                         perror("Device1394Output::run DV1394_WAIT_FRAMES");
00434                                 }
00435                                 if(ioctl(output_fd, DV1394_IOC_GET_STATUS, &status) < 0)
00436                                 {
00437                                         perror("Device1394Output::run DV1394_GET_STATUS");
00438                                 }
00439                         }
00440                         else
00441                         {
00442                                 if(ioctl(output_fd, video1394_talk_queue_buffer, &output_queue) < 0)
00443                                 {
00444                                 perror("Device1394Output::run VIDEO1394_TALK_QUEUE_BUFFER");
00445                         }
00446                         }
00447 
00448                 output_queue.buffer++;
00449                         if(output_queue.buffer >= output_mmap.nb_buffers) 
00450                                 output_queue.buffer = 0;
00451 
00452                         if(unused_buffers <= 0)
00453                         {
00454                                 if(!get_dv1394())
00455                                 {
00456                                 if(ioctl(output_fd, video1394_talk_wait_buffer, &output_queue) < 0) 
00457                                         {
00458                                         perror("Device1394::run VIDEO1394_TALK_WAIT_BUFFER");
00459                                 }
00460                                 }
00461                                 unused_buffers++;
00462                         }
00463 
00464 
00465                         Thread::disable_cancel();
00466                 }
00467                 else
00468                 {
00469 //                      Thread::enable_cancel();
00470 //                      start_lock->lock();
00471 //                      Thread::disable_cancel();
00472                 }
00473 
00474 //printf("Device1394Output::run %lld\n", timer.get_difference());
00475         }
00476 }
00477 
00478 
00479 
00480 void Device1394Output::encrypt(unsigned char *output, 
00481         unsigned char *data, 
00482         int data_size)
00483 {
00484 // Encode in IEEE1394 video encryption
00485         int output_size = 320;
00486         int packets_per_frame = (is_pal ? 300 : 250);
00487         int min_packet_size = output_mmap.packet_size;
00488         unsigned long frame_size = packets_per_frame * 480;
00489         unsigned long vdata = 0;
00490         unsigned int *packet_sizes = this->packet_sizes;
00491 
00492     if(cip_counter == 0) 
00493         {
00494         if(!is_pal) 
00495                 {
00496             cip_n = CIP_N_NTSC;
00497             cip_d = CIP_D_NTSC;
00498             f50_60 = 0x00;
00499         }
00500                 else 
00501                 {
00502             cip_n = CIP_N_PAL;
00503             cip_d = CIP_D_PAL;
00504             f50_60 = 0x80;
00505         }
00506         cip_counter = cip_n;
00507     }
00508 
00509 
00510 
00511 
00512         for(int i = 0; i < output_size && vdata < frame_size; i++)
00513         {
00514         unsigned char *p = output;
00515         int want_sync = (cip_counter > cip_d);
00516 
00517 /* Source node ID ! */
00518         *p++ = 0x01; 
00519 /* Packet size in quadlets (480 / 4) - this stays the same even for empty packets */
00520         *p++ = 0x78; 
00521         *p++ = 0x00;
00522         *p++ = continuity_counter;
00523 
00524 /* const */
00525         *p++ = 0x80; 
00526 /* high bit = 50/60 indicator */
00527         *p++ = f50_60; 
00528 
00529 /* timestamp - generated in driver */
00530         *p++ = 0xff; 
00531 /* timestamp */
00532         *p++ = 0xff; 
00533 
00534 /* video data */
00535         if(!want_sync)
00536                 {
00537             continuity_counter++;
00538             cip_counter += cip_n;
00539 
00540             memcpy(p, data + vdata, 480);
00541             p += 480;
00542             vdata += 480;
00543         }
00544         else
00545             cip_counter -= cip_d;
00546 
00547         *packet_sizes++ = p - output;
00548         output += min_packet_size;
00549         }
00550         *packet_sizes++ = 0;
00551 }
00552 
00553 
00554 
00555 
00556 void Device1394Output::write_frame(VFrame *input)
00557 {
00558         VFrame *ptr = 0;
00559         int result = 0;
00560 
00561 //printf("Device1394Output::write_frame 1\n");
00562 
00563         if(output_fd <= 0) return;
00564         if(interrupted) return;
00565 
00566 // Encode frame to DV
00567         if(input->get_color_model() != BC_COMPRESSED)
00568         {
00569                 if(!temp_frame) temp_frame = new VFrame;
00570                 if(!encoder) encoder = dv_new();
00571                 ptr = temp_frame;
00572 
00573 // Exact resolution match.  Don't do colorspace conversion
00574                 if(input->get_color_model() == BC_YUV422 &&
00575                         input->get_w() == 720 &&
00576                         (input->get_h() == 480 ||
00577                         input->get_h() == 576))
00578                 {
00579                         int norm = is_pal ? DV_PAL : DV_NTSC;
00580                         int data_size = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
00581                         temp_frame->allocate_compressed_data(data_size);
00582                         temp_frame->set_compressed_size(data_size);
00583 
00584                         dv_write_video(encoder,
00585                                 temp_frame->get_data(),
00586                                 input->get_rows(),
00587                                 BC_YUV422,
00588                                 norm);
00589                         ptr = temp_frame;
00590                 }
00591                 else
00592 // Convert resolution and color model before compressing
00593                 {
00594                         if(!temp_frame2)
00595                         {
00596                                 int h = input->get_h();
00597 // Default to NTSC if unknown
00598                                 if(h != 480 && h != 576) h = 480;
00599 
00600                                 temp_frame2 = new VFrame(0,
00601                                         720,
00602                                         h,
00603                                         BC_YUV422);
00604                                 
00605                         }
00606 
00607                         int norm = is_pal ? DV_PAL : DV_NTSC;
00608                         int data_size = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
00609                         temp_frame->allocate_compressed_data(data_size);
00610                         temp_frame->set_compressed_size(data_size);
00611 
00612 
00613                         cmodel_transfer(temp_frame2->get_rows(), /* Leave NULL if non existent */
00614                                 input->get_rows(),
00615                                 temp_frame2->get_y(), /* Leave NULL if non existent */
00616                                 temp_frame2->get_u(),
00617                                 temp_frame2->get_v(),
00618                                 input->get_y(), /* Leave NULL if non existent */
00619                                 input->get_u(),
00620                                 input->get_v(),
00621                                 0,        /* Dimensions to capture from input frame */
00622                                 0, 
00623                                 MIN(temp_frame2->get_w(), input->get_w()),
00624                                 MIN(temp_frame2->get_h(), input->get_h()),
00625                                 0,       /* Dimensions to project on output frame */
00626                                 0, 
00627                                 MIN(temp_frame2->get_w(), input->get_w()),
00628                                 MIN(temp_frame2->get_h(), input->get_h()),
00629                                 input->get_color_model(), 
00630                                 BC_YUV422,
00631                                 0,         /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
00632                                 input->get_bytes_per_line(),       /* For planar use the luma rowspan */
00633                                 temp_frame2->get_bytes_per_line());     /* For planar use the luma rowspan */
00634 
00635                         dv_write_video(encoder,
00636                                 temp_frame->get_data(),
00637                                 temp_frame2->get_rows(),
00638                                 BC_YUV422,
00639                                 norm);
00640 
00641 
00642 
00643                         ptr = temp_frame;
00644                 }
00645         }
00646         else
00647                 ptr = input;
00648 
00649 
00650 
00651 
00652 
00653 
00654 
00655 
00656 
00657 
00658 
00659 // Take over buffer table
00660         buffer_lock->lock("Device1394Output::write_frame 1");
00661         have_video = 1;
00662 // Wait for buffer to become available with timeout
00663         while(buffer_valid[current_inbuffer] && !result && !interrupted)
00664         {
00665                 buffer_lock->unlock();
00666                 result = video_lock->timed_lock(BUFFER_TIMEOUT);
00667                 buffer_lock->lock("Device1394Output::write_frame 2");
00668         }
00669 
00670 
00671 
00672 // Write buffer if there's room
00673         if(!buffer_valid[current_inbuffer])
00674         {
00675                 if(!buffer[current_inbuffer])
00676                 {
00677                         buffer[current_inbuffer] = new char[ptr->get_compressed_size()];
00678                         buffer_size[current_inbuffer] = ptr->get_compressed_size();
00679                 }
00680                 memcpy(buffer[current_inbuffer], ptr->get_data(), ptr->get_compressed_size());
00681                 buffer_valid[current_inbuffer] = 1;
00682                 increment_counter(&current_inbuffer);
00683         }
00684         else
00685 // Ignore it if there isn't room.
00686         {
00687                 ;
00688         }
00689 
00690         buffer_lock->unlock();
00691         start_lock->unlock();
00692 //printf("Device1394Output::write_frame 100\n");
00693 }
00694 
00695 void Device1394Output::write_samples(char *data, int samples)
00696 {
00697 //printf("Device1394Output::write_samples 1\n");
00698         int result = 0;
00699         int timeout = (int64_t)samples * 
00700                 (int64_t)1000000 * 
00701                 (int64_t)2 / 
00702                 (int64_t)samplerate;
00703         if(interrupted) return;
00704 
00705 //printf("Device1394Output::write_samples 2\n");
00706 
00707 // Check for maximum sample count exceeded
00708         if(samples > OUTPUT_SAMPLES)
00709         {
00710                 printf("Device1394Output::write_samples samples=%d > OUTPUT_SAMPLES=%d\n",
00711                         samples,
00712                         OUTPUT_SAMPLES);
00713                 return;
00714         }
00715 
00716 //printf("Device1394Output::write_samples 3\n");
00717 // Take over buffer table
00718         buffer_lock->lock("Device1394Output::write_samples 1");
00719 // Wait for buffer to become available with timeout
00720         while(audio_samples > OUTPUT_SAMPLES - samples && !result && !interrupted)
00721         {
00722                 buffer_lock->unlock();
00723                 result = audio_lock->timed_lock(BUFFER_TIMEOUT);
00724                 buffer_lock->lock("Device1394Output::write_samples 2");
00725         }
00726 
00727         if(!interrupted && audio_samples <= OUTPUT_SAMPLES - samples)
00728         {
00729 //printf("Device1394Output::write_samples 4 %d\n", audio_samples);
00730                 memcpy(audio_buffer + audio_samples * channels * bits / 8,
00731                         data,
00732                         samples * channels * bits / 8);
00733                 audio_samples += samples;
00734         }
00735         buffer_lock->unlock();
00736         start_lock->unlock();
00737 //printf("Device1394Output::write_samples 100\n");
00738 }
00739 
00740 long Device1394Output::get_audio_position()
00741 {
00742         position_lock->lock("Device1394Output::get_audio_position");
00743         long result = audio_position;
00744         position_lock->unlock();
00745         return result;
00746 }
00747 
00748 void Device1394Output::interrupt()
00749 {
00750         interrupted = 1;
00751 // Break write_samples out of a lock
00752         video_lock->unlock();
00753         audio_lock->unlock();
00754 // Playback should stop when the object is deleted.
00755 }
00756 
00757 void Device1394Output::flush()
00758 {
00759         
00760 }
00761 
00762 void Device1394Output::increment_counter(int *counter)
00763 {
00764         (*counter)++;
00765         if(*counter >= total_buffers) *counter = 0;
00766 }
00767 
00768 void Device1394Output::decrement_counter(int *counter)
00769 {
00770         (*counter)--;
00771         if(*counter < 0) *counter = total_buffers - 1;
00772 }
00773 
00774 void Device1394Output::set_ioctls()
00775 {
00776         // It would make sense to simply change the file that is included in
00777         // order to change the IOCTLs, but it isn't reasonable to think that
00778         // people will rebuild their software every time the update their
00779         // kernel, hence this fix.
00780 
00781         struct utsname buf;
00782 
00783         // Get the kernel version so we can set the right ioctls
00784         uname(&buf);
00785 
00786         char *ptr = strchr(buf.release, '.');
00787         int major = 2;
00788         int minor = 6;
00789         int point = 7;
00790         if(ptr)
00791         {
00792                 *ptr++ = 0;
00793                 major = atoi(buf.release);
00794                 char *ptr2 = strchr(ptr, '.');
00795                 if(ptr2)
00796                 {
00797                         *ptr2++ = 0;
00798                         minor = atoi(ptr);
00799                         point = atoi(ptr2);
00800                 }
00801         }
00802 
00803         if(major >= 2 && minor >= 6 && point >= 0 ||
00804                 major >= 2 && minor >= 4 && point >= 23)
00805         {
00806                 // video1394
00807                 video1394_listen_channel = VIDEO1394_IOC_LISTEN_CHANNEL;
00808                 video1394_unlisten_channel = VIDEO1394_IOC_UNLISTEN_CHANNEL;
00809                 video1394_listen_queue_buffer = VIDEO1394_IOC_LISTEN_QUEUE_BUFFER;
00810                 video1394_listen_wait_buffer = VIDEO1394_IOC_LISTEN_WAIT_BUFFER;
00811                 video1394_talk_channel = VIDEO1394_IOC_TALK_CHANNEL;
00812                 video1394_untalk_channel = VIDEO1394_IOC_UNTALK_CHANNEL;
00813                 video1394_talk_queue_buffer = VIDEO1394_IOC_TALK_QUEUE_BUFFER;
00814                 video1394_talk_wait_buffer = VIDEO1394_IOC_TALK_WAIT_BUFFER;
00815                 video1394_listen_poll_buffer = VIDEO1394_IOC_LISTEN_POLL_BUFFER;
00816 
00817                 // raw1394
00818                 // Nothing uses this right now, so I didn't include it.
00819         }
00820         else     // we are using an older kernel
00821         {
00822       // video1394
00823       video1394_listen_channel = VIDEO1394_LISTEN_CHANNEL;
00824       video1394_unlisten_channel = VIDEO1394_UNLISTEN_CHANNEL;
00825       video1394_listen_queue_buffer = VIDEO1394_LISTEN_QUEUE_BUFFER;
00826       video1394_listen_wait_buffer = VIDEO1394_LISTEN_WAIT_BUFFER;
00827       video1394_talk_channel = VIDEO1394_TALK_CHANNEL;
00828       video1394_untalk_channel = VIDEO1394_UNTALK_CHANNEL;
00829       video1394_talk_queue_buffer = VIDEO1394_TALK_QUEUE_BUFFER;
00830       video1394_talk_wait_buffer = VIDEO1394_TALK_WAIT_BUFFER;
00831       video1394_listen_poll_buffer = VIDEO1394_LISTEN_POLL_BUFFER;
00832         }
00833 }
00834 
00835 
00836 
00837 
00838 
00839 
00840 
00841 
00842 
00843 
00844 
00845 
00846 #endif // HAVE_FIREWIRE
00847 
00848 
00849 
00850 
00851 
00852 

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