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
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
00119
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
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
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
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
00219
00220
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
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
00306
00307 while(!done)
00308 {
00309
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
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
00353 if(out_buffer && out_size)
00354 {
00355
00356
00357 int samples_per_frame = 2048;
00358
00359
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
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
00398 increment_counter(¤t_outbuffer);
00399
00400
00401 if(!buffer_valid[current_outbuffer])
00402 {
00403 decrement_counter(¤t_outbuffer);
00404 }
00405 else
00406
00407 {
00408 video_lock->unlock();
00409 }
00410
00411
00412 buffer_lock->unlock();
00413
00414
00415
00416
00417 if(out_size > 0)
00418 {
00419
00420
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
00470
00471
00472 }
00473
00474
00475 }
00476 }
00477
00478
00479
00480 void Device1394Output::encrypt(unsigned char *output,
00481 unsigned char *data,
00482 int data_size)
00483 {
00484
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
00518 *p++ = 0x01;
00519
00520 *p++ = 0x78;
00521 *p++ = 0x00;
00522 *p++ = continuity_counter;
00523
00524
00525 *p++ = 0x80;
00526
00527 *p++ = f50_60;
00528
00529
00530 *p++ = 0xff;
00531
00532 *p++ = 0xff;
00533
00534
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
00562
00563 if(output_fd <= 0) return;
00564 if(interrupted) return;
00565
00566
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
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
00593 {
00594 if(!temp_frame2)
00595 {
00596 int h = input->get_h();
00597
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(),
00614 input->get_rows(),
00615 temp_frame2->get_y(),
00616 temp_frame2->get_u(),
00617 temp_frame2->get_v(),
00618 input->get_y(),
00619 input->get_u(),
00620 input->get_v(),
00621 0,
00622 0,
00623 MIN(temp_frame2->get_w(), input->get_w()),
00624 MIN(temp_frame2->get_h(), input->get_h()),
00625 0,
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,
00632 input->get_bytes_per_line(),
00633 temp_frame2->get_bytes_per_line());
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
00660 buffer_lock->lock("Device1394Output::write_frame 1");
00661 have_video = 1;
00662
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
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(¤t_inbuffer);
00683 }
00684 else
00685
00686 {
00687 ;
00688 }
00689
00690 buffer_lock->unlock();
00691 start_lock->unlock();
00692
00693 }
00694
00695 void Device1394Output::write_samples(char *data, int samples)
00696 {
00697
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
00706
00707
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
00717
00718 buffer_lock->lock("Device1394Output::write_samples 1");
00719
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
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
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
00752 video_lock->unlock();
00753 audio_lock->unlock();
00754
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
00777
00778
00779
00780
00781 struct utsname buf;
00782
00783
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
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
00818
00819 }
00820 else
00821 {
00822
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