r105: This commit was manufactured by cvs2svn to create tag
[cinelerra_cv/mob.git] / hvirtual / cinelerra / device1394output.C
blob84beec48243c2317196c31b3d7053a8f245ea87e
1 #ifdef HAVE_FIREWIRE
6 #include "condition.h"
7 #include "device1394output.h"
8 #include "mutex.h"
9 #include "timer.h"
10 #include "vframe.h"
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <string.h>
15 #include <sys/ioctl.h>
16 #include <sys/mman.h>
17 #include <unistd.h>
20 #include "avc1394.h"
21 #include "avc1394_vcr.h"
22 #include "rom1394.h"
27 // Crazy DV internals
28 #define CIP_N_NTSC 2436
29 #define CIP_D_NTSC 38400
30 #define CIP_N_PAL 1
31 #define CIP_D_PAL 16
32 #define OUTPUT_SAMPLES 262144
33 #define BUFFER_TIMEOUT 500000
36 Device1394Output::Device1394Output()
37  : Thread(1, 0, 0)
39         buffer = 0;
40         buffer_size = 0;
41         total_buffers = 0;
42         current_inbuffer = 0;
43         current_outbuffer = 0;
44         done = 0;
45         audio_lock = 0;
46         video_lock = 0;
47         start_lock = 0;
48         buffer_lock = 0;
49         position_lock = 0;
50         video_encoder = 0;
51         audio_encoder = 0;
52         audio_buffer = 0;
53         audio_samples = 0;
54         output_fd = -1;
55 //      avc_handle = 0;
56         temp_frame = 0;
57         temp_frame2 = 0;
58         audio_position = 0;
59         interrupted = 0;
60         have_video = 0;
63 Device1394Output::~Device1394Output()
65         if(Thread::running())
66         {
67                 done = 1;
68                 start_lock->unlock();
69                 Thread::cancel();
70                 Thread::join();
71         }
73         if(buffer)
74         {
75                 for(int i = 0; i < total_buffers; i++)
76                 {
77                         if(buffer[i]) delete [] buffer[i];
78                 }
79                 delete [] buffer;
80                 delete [] buffer_size;
81                 delete [] buffer_valid;
82         }
84         if(audio_lock) delete audio_lock;
85         if(video_lock) delete video_lock;
86         if(start_lock) delete start_lock;
87         if(audio_buffer) delete [] audio_buffer;
89         if(output_fd >= 0)
90         {
91         output_queue.buffer = (output_mmap.nb_buffers + output_queue.buffer - 1) % output_mmap.nb_buffers;
93         if(ioctl(output_fd, VIDEO1394_TALK_WAIT_BUFFER, &output_queue) < 0) 
94                 {
95             fprintf(stderr, 
96                                 "Device1394::close_all: VIDEO1394_TALK_WAIT_BUFFER %s: %s",
97                                 output_queue,
98                                 strerror(errno));
99         }
100         munmap(output_buffer, output_mmap.nb_buffers * output_mmap.buf_size);
102         if(ioctl(output_fd, VIDEO1394_UNTALK_CHANNEL, &output_mmap.channel) < 0)
103                 {
104             perror("Device1394::close_all: VIDEO1394_UNTALK_CHANNEL");
105         }
107         close(output_fd);
109 //              if(avc_handle)
110 //                      raw1394_destroy_handle(avc_handle);
111         }
113         if(temp_frame) delete temp_frame;
114         if(temp_frame2) delete temp_frame2;
115         if(video_encoder) dv_delete(video_encoder);
116         if(audio_encoder) dv_delete(audio_encoder);
117         if(buffer_lock) delete buffer_lock;
118         if(position_lock) delete position_lock;
122 int Device1394Output::open(char *path,
123         int port,
124         int channel,
125         int length,
126         int channels, 
127         int bits, 
128         int samplerate,
129         int syt)
131         this->channels = channels;
132         this->bits = bits;
133         this->samplerate = samplerate;
134         this->total_buffers = length;
135         this->syt = syt;
137 //printf("Device1394::open_output 2 %s %d %d %d %d\n", path, port, channel, length, syt);
138         if(output_fd < 0)
139         {
140         output_fd = ::open(path, O_RDWR);
142                 if(output_fd <= 0)
143                 {
144                         fprintf(stderr, 
145                                 "Device1394Output::open path=%s: %s", 
146                                 path,
147                                 strerror(errno));
148                         return 1;
149                 }
150                 else
151                 {
152 //              avc_handle = raw1394_new_handle();
153 //                      if(avc_handle == 0)
154 //                              printf("Device1394::open_output avc_handle == 0\n");
155 // 
156 //                      struct raw1394_portinfo pinf[16];
157 //                      int numcards = raw1394_get_port_info(avc_handle, pinf, 16);
158 //                      if(numcards < 0)
159 //                              printf("Device1394::open_output raw1394_get_port_info failed\n");
160 //                      if(raw1394_set_port(avc_handle, out_config->firewire_port) < 0)
161 //                              printf("Device1394::open_output raw1394_set_port\n");
162 // 
163 //              int nodecount = raw1394_get_nodecount(avc_handle);
164 //                      int itemcount = 0;
165 //                      rom1394_directory rom1394_dir;
166 // 
167 //                      avc_id = -1;
168 //              for(int currentnode = 0; currentnode < nodecount; currentnode++) 
169 //                      {
170 //                      rom1394_get_directory(avc_handle, currentnode, &rom1394_dir);
171 // 
172 //                      if((rom1394_get_node_type(&rom1394_dir) == ROM1394_NODE_TYPE_AVC) &&
173 //                      avc1394_check_subunit_type(avc_handle, currentnode, AVC1394_SUBUNIT_TYPE_VCR)) 
174 //                              {
175 //                      itemcount++;
176 // // default the phyID to the first AVC node found
177 //                      if(itemcount == 1) avc_id = currentnode;
178 //                                      break;
179 //                      }
180 // 
181 //                      rom1394_free_directory(&rom1394_dir);
182 //              }
183 // 
184 //                      if(avc_id < 0)
185 //                              printf("Device1394::open_output no avc_id found.\n");
186 // 
187 //printf("Device1394::open_output 1 %p %d\n", avc_handle, avc_id);
188 //              avc1394_vcr_record(avc_handle, avc_id);
193                 output_mmap.channel = channel;
194                 output_queue.channel = channel;
195                 output_mmap.sync_tag = 0;
196                 output_mmap.nb_buffers = total_buffers;
197                 output_mmap.buf_size = 320 * 512;
198                 output_mmap.packet_size = 512;
199 // Shouldn't this be handled by the video1394 driver?
200 // dvgrab originally used 19000
201 // JVC DVL300 -> 30000
202                 output_mmap.syt_offset = syt;
203                 output_mmap.flags = VIDEO1394_VARIABLE_PACKET_SIZE;
206 // printf("Device1394Output::open %d %d %d %d %d %d %d\n", 
207 // output_mmap.channel, output_queue.channel, output_mmap.sync_tag, output_mmap.nb_buffers, output_mmap.buf_size, output_mmap.packet_size, output_mmap.syt_offset, output_mmap.flags);
208                 if(ioctl(output_fd, VIDEO1394_TALK_CHANNEL, &output_mmap) < 0)
209                         {
210                 perror("Device1394Output::open VIDEO1394_TALK_CHANNEL:");
211                 }
213                 output_buffer = (unsigned char*)mmap(0, 
214                                 output_mmap.nb_buffers * output_mmap.buf_size,
215                 PROT_READ | PROT_WRITE, 
216                                 MAP_SHARED, 
217                                 output_fd, 
218                                 0);
219                 if(output_buffer <= 0)
220                         {
221                 perror("Device1394Output::open mmap");
222                 }
224                         unused_buffers = output_mmap.nb_buffers;
225                 output_queue.buffer = 0;
226                 output_queue.packet_sizes = packet_sizes;
227                 continuity_counter = 0;
228                 cip_counter = 0;
230 // Create buffers
231                         buffer = new char*[total_buffers];
232                         for(int i = 0; i < length; i++)
233                                 buffer[i] = new char[DV_PAL_SIZE];
234                         buffer_size = new int[total_buffers];
235                         buffer_valid = new int[total_buffers];
236                         bzero(buffer_size, sizeof(int) * total_buffers);
237                         bzero(buffer_valid, sizeof(int) * total_buffers);
238                         bzero(buffer, sizeof(char*) * total_buffers);
239                         video_lock = new Condition(0);
240                         audio_lock = new Condition(0);
241                         start_lock = new Condition(0);
242                         buffer_lock = new Mutex;
243                         position_lock = new Mutex;
244                         encoder = dv_new();
245                         audio_buffer = new char[OUTPUT_SAMPLES * channels * bits / 8];
246                         Thread::start();
247         }
248         }
249         return 0;
252 void Device1394Output::run()
254         Thread::enable_cancel();
255         start_lock->lock();
256         Thread::disable_cancel();
258 //Timer timer;
259 // Write buffers continuously
260         while(!done)
261         {
262 // Get current buffer to play
263                 if(done) return;
264 //timer.update();
266 //printf("Device1394Output::run 1\n");
267                 buffer_lock->lock();
268 //printf("Device1394Output::run 10\n");
270                 char *out_buffer = buffer[current_outbuffer];
271                 int out_size = buffer_size[current_outbuffer];
277 // No video.  Put in a fake frame for audio only
278                 if(!have_video)
279                 {
280 #include "data/fake_ntsc_dv.h"
281                         out_size = sizeof(fake_ntsc_dv) - 4;
282                         out_buffer = (char*)fake_ntsc_dv + 4;
283                 }
284                 unsigned char *output = output_buffer + 
285                         output_queue.buffer * 
286                         output_mmap.buf_size;
287                 int is_pal = (out_size == DV_PAL_SIZE);
294 // Got a buffer
295                 if(out_buffer && out_size)
296                 {
297 // Calculate number of samples needed based on given pattern for 
298 // norm.
299                         int samples_per_frame = 2048;
301 // Encode audio
302                         if(audio_samples > samples_per_frame)
303                         {
305                                 int samples_written = dv_write_audio(encoder,
306                                         (unsigned char*)out_buffer,
307                                         (unsigned char*)audio_buffer,
308                                         samples_per_frame,
309                                         channels,
310                                         bits,
311                                         samplerate,
312                                         is_pal ? DV_PAL : DV_NTSC);
313                                 memcpy(audio_buffer, 
314                                         audio_buffer + samples_written * bits * channels / 8,
315                                         (audio_samples - samples_written) * bits * channels / 8);
316                                 audio_samples -= samples_written;
317                                 position_lock->lock();
318                                 audio_position += samples_written;
319                                 position_lock->unlock();
322                                 audio_lock->unlock();
323                         }
325 // Copy from current buffer to mmap buffer with firewire encryption
326                         encrypt((unsigned char*)output, 
327                                 (unsigned char*)out_buffer, 
328                                 out_size);
329                         buffer_valid[current_outbuffer] = 0;
330                 }
332 // Advance buffer number if possible
333                 increment_counter(&current_outbuffer);
335 // Reuse same buffer next time
336                 if(!buffer_valid[current_outbuffer])
337                 {
338                         decrement_counter(&current_outbuffer);
339                 }
340                 else
341 // Wait for user to reach current buffer before unlocking any more.
342                 {
343                         video_lock->unlock();
344                 }
347                 buffer_lock->unlock();
348 //printf("Device1394Output::run 100\n");
352                 if(out_size > 0)
353                 {
355 // Write mmap to device
356                         Thread::enable_cancel();
357                         unused_buffers--;
358                         if(ioctl(output_fd, VIDEO1394_TALK_QUEUE_BUFFER, &output_queue) < 0)
359                         {
360                         perror("Device1394Output::run VIDEO1394_TALK_QUEUE_BUFFER");
361                 }
363                 output_queue.buffer++;
364                         if(output_queue.buffer >= output_mmap.nb_buffers) 
365                                 output_queue.buffer = 0;
367                         if(unused_buffers <= 0)
368                         {
369                         if(ioctl(output_fd, VIDEO1394_TALK_WAIT_BUFFER, &output_queue) < 0) 
370                                 {
371                                 perror("Device1394::run VIDEO1394_TALK_WAIT_BUFFER");
372                         }
373                                 unused_buffers++;
374                         }
375                         Thread::disable_cancel();
376                 }
377                 else
378                 {
379 //                      Thread::enable_cancel();
380 //                      start_lock->lock();
381 //                      Thread::disable_cancel();
382                 }
384 //printf("Device1394Output::run %lld\n", timer.get_difference());
385         }
390 void Device1394Output::encrypt(unsigned char *output, 
391         unsigned char *data, 
392         int data_size)
394 // Encode in IEEE1394 video encryption
395         int is_pal = (data_size == DV_PAL_SIZE);
396         int output_size = 320;
397         int packets_per_frame = (is_pal ? 300 : 250);
398         int min_packet_size = output_mmap.packet_size;
399         unsigned long frame_size = packets_per_frame * 480;
400         unsigned long vdata = 0;
401         unsigned int *packet_sizes = this->packet_sizes;
403     if(cip_counter == 0) 
404         {
405         if(!is_pal) 
406                 {
407             cip_n = CIP_N_NTSC;
408             cip_d = CIP_D_NTSC;
409             f50_60 = 0x00;
410         }
411                 else 
412                 {
413             cip_n = CIP_N_PAL;
414             cip_d = CIP_D_PAL;
415             f50_60 = 0x80;
416         }
417         cip_counter = cip_n;
418     }
423         for(int i = 0; i < output_size && vdata < frame_size; i++)
424         {
425         unsigned char *p = output;
426         int want_sync = (cip_counter > cip_d);
428 /* Source node ID ! */
429         *p++ = 0x01; 
430 /* Packet size in quadlets (480 / 4) - this stays the same even for empty packets */
431         *p++ = 0x78; 
432         *p++ = 0x00;
433         *p++ = continuity_counter;
435 /* const */
436         *p++ = 0x80; 
437 /* high bit = 50/60 indicator */
438         *p++ = f50_60; 
440 /* timestamp - generated in driver */
441         *p++ = 0xff; 
442 /* timestamp */
443         *p++ = 0xff; 
445 /* video data */
446         if(!want_sync)
447                 {
448             continuity_counter++;
449             cip_counter += cip_n;
451             memcpy(p, data + vdata, 480);
452             p += 480;
453             vdata += 480;
454         }
455         else
456             cip_counter -= cip_d;
458         *packet_sizes++ = p - output;
459         output += min_packet_size;
460         }
461         *packet_sizes++ = 0;
467 void Device1394Output::write_frame(VFrame *input)
469         VFrame *ptr = 0;
470         int is_pal = (input->get_h() == 576);
471         int result = 0;
473 //printf("Device1394Output::write_frame 1\n");
475         if(output_fd <= 0) return;
476         if(interrupted) return;
478 // Encode frame to DV
479         if(input->get_color_model() != BC_COMPRESSED)
480         {
481                 if(!temp_frame) temp_frame = new VFrame;
482                 if(!encoder) encoder = dv_new();
483                 ptr = temp_frame;
485 // Exact resolution match.  Don't do colorspace conversion
486                 if(input->get_color_model() == BC_YUV422 &&
487                         input->get_w() == 720 &&
488                         (input->get_h() == 480 ||
489                         input->get_h() == 576))
490                 {
491                         int norm = is_pal ? DV_PAL : DV_NTSC;
492                         int data_size = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
493                         temp_frame->allocate_compressed_data(data_size);
494                         temp_frame->set_compressed_size(data_size);
496                         dv_write_video(encoder,
497                                 temp_frame->get_data(),
498                                 input->get_rows(),
499                                 BC_YUV422,
500                                 norm);
501                         ptr = temp_frame;
502                 }
503                 else
504 // Convert resolution and color model before compressing
505                 {
506                         if(!temp_frame2)
507                         {
508                                 int h = input->get_h();
509 // Default to NTSC if unknown
510                                 if(h != 480 && h != 576) h = 480;
512                                 temp_frame2 = new VFrame(0,
513                                         720,
514                                         h,
515                                         BC_YUV422);
516                                 
517                         }
519                         int norm = is_pal ? DV_PAL : DV_NTSC;
520                         int data_size = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
521                         temp_frame->allocate_compressed_data(data_size);
522                         temp_frame->set_compressed_size(data_size);
525                         cmodel_transfer(temp_frame2->get_rows(), /* Leave NULL if non existent */
526                                 input->get_rows(),
527                                 temp_frame2->get_y(), /* Leave NULL if non existent */
528                                 temp_frame2->get_u(),
529                                 temp_frame2->get_v(),
530                                 input->get_y(), /* Leave NULL if non existent */
531                                 input->get_u(),
532                                 input->get_v(),
533                                 0,        /* Dimensions to capture from input frame */
534                                 0, 
535                                 MIN(temp_frame2->get_w(), input->get_w()),
536                                 MIN(temp_frame2->get_h(), input->get_h()),
537                                 0,       /* Dimensions to project on output frame */
538                                 0, 
539                                 MIN(temp_frame2->get_w(), input->get_w()),
540                                 MIN(temp_frame2->get_h(), input->get_h()),
541                                 input->get_color_model(), 
542                                 BC_YUV422,
543                                 0,         /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
544                                 input->get_bytes_per_line(),       /* For planar use the luma rowspan */
545                                 temp_frame2->get_bytes_per_line());     /* For planar use the luma rowspan */
547                         dv_write_video(encoder,
548                                 temp_frame->get_data(),
549                                 temp_frame2->get_rows(),
550                                 BC_YUV422,
551                                 norm);
555                         ptr = temp_frame;
556                 }
557         }
558         else
559                 ptr = input;
571 // Take over buffer table
572         buffer_lock->lock();
573         have_video = 1;
574 // Wait for buffer to become available with timeout
575         while(buffer_valid[current_inbuffer] && !result && !interrupted)
576         {
577                 buffer_lock->unlock();
578                 result = video_lock->timed_lock(BUFFER_TIMEOUT);
579                 buffer_lock->lock();
580         }
584 // Write buffer if there's room
585         if(!buffer_valid[current_inbuffer])
586         {
587                 if(!buffer[current_inbuffer])
588                 {
589                         buffer[current_inbuffer] = new char[ptr->get_compressed_size()];
590                         buffer_size[current_inbuffer] = ptr->get_compressed_size();
591                 }
592                 memcpy(buffer[current_inbuffer], ptr->get_data(), ptr->get_compressed_size());
593                 buffer_valid[current_inbuffer] = 1;
594                 increment_counter(&current_inbuffer);
595         }
596         else
597 // Ignore it if there isn't room.
598         {
599                 ;
600         }
602         buffer_lock->unlock();
603         start_lock->unlock();
604 //printf("Device1394Output::write_frame 100\n");
607 void Device1394Output::write_samples(char *data, int samples)
609 //printf("Device1394Output::write_samples 1\n");
610         int result = 0;
611         int timeout = (int64_t)samples * 
612                 (int64_t)1000000 * 
613                 (int64_t)2 / 
614                 (int64_t)samplerate;
615         if(interrupted) return;
617 //printf("Device1394Output::write_samples 2\n");
619 // Check for maximum sample count exceeded
620         if(samples > OUTPUT_SAMPLES)
621         {
622                 printf("Device1394Output::write_samples samples=%d > OUTPUT_SAMPLES=%d\n",
623                         samples,
624                         OUTPUT_SAMPLES);
625                 return;
626         }
628 //printf("Device1394Output::write_samples 3\n");
629 // Take over buffer table
630         buffer_lock->lock();
631 // Wait for buffer to become available with timeout
632         while(audio_samples > OUTPUT_SAMPLES - samples && !result && !interrupted)
633         {
634                 buffer_lock->unlock();
635                 result = audio_lock->timed_lock(BUFFER_TIMEOUT);
636                 buffer_lock->lock();
637         }
639         if(!interrupted && audio_samples <= OUTPUT_SAMPLES - samples)
640         {
641 //printf("Device1394Output::write_samples 4 %d\n", audio_samples);
642                 memcpy(audio_buffer + audio_samples * channels * bits / 8,
643                         data,
644                         samples * channels * bits / 8);
645                 audio_samples += samples;
646         }
647         buffer_lock->unlock();
648         start_lock->unlock();
649 //printf("Device1394Output::write_samples 100\n");
652 long Device1394Output::get_audio_position()
654         position_lock->lock();
655         long result = audio_position;
656         position_lock->unlock();
657         return result;
660 void Device1394Output::interrupt()
662         interrupted = 1;
663 // Break write_samples out of a lock
664         video_lock->unlock();
665         audio_lock->unlock();
666 // Playback should stop when the object is deleted.
669 void Device1394Output::flush()
671         
674 void Device1394Output::increment_counter(int *counter)
676         (*counter)++;
677         if(*counter >= total_buffers) *counter = 0;
680 void Device1394Output::decrement_counter(int *counter)
682         (*counter)--;
683         if(*counter < 0) *counter = total_buffers - 1;
699 #endif // HAVE_FIREWIRE