Merge branch 'ct' of git.pipapo.org:cinelerra-ct into ct
[cinelerra_cv/ct.git] / cinelerra / iec61883output.C
blobd60f90d99035a538aa2a51ba60b95835a80eb42e
1 #ifdef HAVE_FIREWIRE
5 #include "audiodevice.h"
6 #include "condition.h"
7 #include "iec61883output.h"
8 #include "mutex.h"
9 #include "playbackconfig.h"
10 #include "bctimer.h"
11 #include "vframe.h"
12 #include "videodevice.h"
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <string.h>
17 #include <sys/ioctl.h>
18 #include <sys/mman.h>
19 #include <unistd.h>
20 #include <sys/utsname.h>
26 // Crazy DV internals
27 #define CIP_N_NTSC 2436
28 #define CIP_D_NTSC 38400
29 #define CIP_N_PAL 1
30 #define CIP_D_PAL 16
31 #define OUTPUT_SAMPLES 262144
32 #define BUFFER_TIMEOUT 500000
35 IEC61883Output::IEC61883Output(AudioDevice *adevice)
36  : Thread(1, 0, 0)
38         reset();
39         this->adevice = adevice;
42 IEC61883Output::IEC61883Output(VideoDevice *vdevice)
43  : Thread(1, 0, 0)
45         reset();
46         this->vdevice = vdevice;
49 IEC61883Output::~IEC61883Output()
51         if(Thread::running())
52         {
53                 done = 1;
54                 start_lock->unlock();
55                 Thread::cancel();
56                 Thread::join();
57         }
59         if(buffer)
60         {
61                 for(int i = 0; i < total_buffers; i++)
62                 {
63                         if(buffer[i]) delete [] buffer[i];
64                 }
65                 delete [] buffer;
66                 delete [] buffer_size;
67                 delete [] buffer_valid;
68         }
70         if(audio_lock) delete audio_lock;
71         if(video_lock) delete video_lock;
72         if(start_lock) delete start_lock;
73         if(audio_buffer) delete [] audio_buffer;
75         if(temp_frame) delete temp_frame;
76         if(temp_frame2) delete temp_frame2;
77         if(video_encoder) dv_delete(video_encoder);
78         if(audio_encoder) dv_delete(audio_encoder);
79         if(buffer_lock) delete buffer_lock;
80         if(position_lock) delete position_lock;
81         if(frame) iec61883_dv_close(frame);
82         if(handle) raw1394_destroy_handle(handle);
86 void IEC61883Output::reset()
88         handle = 0;
89         fd = 0;
90         frame = 0;
91         out_position = 0;
92         out_buffer = 0;
93         out_size = 0;
95         buffer = 0;
96         buffer_size = 0;
97         total_buffers = 0;
98         current_inbuffer = 0;
99         current_outbuffer = 0;
100         done = 0;
101         audio_lock = 0;
102         video_lock = 0;
103         start_lock = 0;
104         buffer_lock = 0;
105         position_lock = 0;
106         video_encoder = 0;
107         audio_encoder = 0;
108         audio_buffer = 0;
109         audio_samples = 0;
110         temp_frame = 0;
111         temp_frame2 = 0;
112         audio_position = 0;
113         interrupted = 0;
114         have_video = 0;
115         adevice = 0;
116         vdevice = 0;
117         is_pal = 0;
122 static int read_frame_static(unsigned char *data, int n, unsigned int dropped, void *ptr)
124         IEC61883Output *output = (IEC61883Output*)ptr;
125         return output->read_frame(data, n, dropped);
132 int IEC61883Output::open(int port,
133         int channel,
134         int length,
135         int channels, 
136         int bits, 
137         int samplerate,
138         int syt)
140         this->channels = channels;
141         this->bits = bits;
142         this->samplerate = samplerate;
143         this->total_buffers = length;
144         this->syt = syt;
146 // Set PAL mode based on frame height
147         if(vdevice) is_pal = (vdevice->out_h == 576);
152         if(!handle)
153         {
154                 handle = raw1394_new_handle_on_port(port);
155                 if(handle)
156                 {
157                         frame = iec61883_dv_xmit_init(handle, 
158                                 is_pal, 
159                                 read_frame_static, 
160                                 (void *)this);
161                         if(frame)
162                         {
163                                 if(!iec61883_dv_xmit_start(frame, channel))
164                                 {
165                                         fd = raw1394_get_fd(handle);
166                                 }
167                         }
168                 }
170 // Create buffers
171                 buffer = new char*[total_buffers];
172                 for(int i = 0; i < length; i++)
173                         buffer[i] = new char[DV_PAL_SIZE];
174                 buffer_size = new int[total_buffers];
175                 buffer_valid = new int[total_buffers];
176                 bzero(buffer_size, sizeof(int) * total_buffers);
177                 bzero(buffer_valid, sizeof(int) * total_buffers);
178                 bzero(buffer, sizeof(char*) * total_buffers);
179                 video_lock = new Condition(0, "IEC61883Output::video_lock");
180                 audio_lock = new Condition(0, "IEC61883Output::audio_lock");
181                 start_lock = new Condition(0, "IEC61883Output::start_lock");
182                 buffer_lock = new Mutex("IEC61883Output::buffer_lock");
183                 position_lock = new Mutex("IEC61883Output::position_lock");
184                 encoder = dv_new();
185                 audio_buffer = new char[OUTPUT_SAMPLES * channels * bits / 8];
186                 Thread::start();
187         }
188         return 0;
191 void IEC61883Output::run()
193         Thread::enable_cancel();
194         start_lock->lock("IEC61883Output::run");
195         Thread::disable_cancel();
197         while(!done)
198         {
199                 struct timeval tv;
200                 fd_set rfds;
201                 FD_ZERO (&rfds);
202                 FD_SET (fd, &rfds);
203                 tv.tv_sec = 0;
204                 tv.tv_usec = 20000;
205                 if(select(fd + 1, &rfds, 0, 0, &tv) > 0)
206                         raw1394_loop_iterate (handle);
207         }
212 int IEC61883Output::read_frame(unsigned char *data, int n, unsigned int dropped)
214 // Next frame
215         if(!out_buffer || out_position + 480 > out_size)
216         {
217                 buffer_lock->lock("IEC61883Output read_frame 1");
219                 out_buffer = buffer[current_outbuffer];
220                 out_size = buffer_size[current_outbuffer];
221                 out_position = 0;
224 // No video.  Put in a fake frame for audio only
225                 if(!have_video)
226                 {
227 #include "data/fake_ntsc_dv.h"
228                         out_size = sizeof(fake_ntsc_dv) - 4;
229                         out_buffer = (char*)fake_ntsc_dv + 4;
230                 }
239 // Calculate number of samples needed based on given pattern for 
240 // norm.
241                 int samples_per_frame = 2048;
243 // Encode audio
244                 if(audio_samples > samples_per_frame)
245                 {
246                         int samples_written = dv_write_audio(encoder,
247                                 (unsigned char*)out_buffer,
248                                 (unsigned char*)audio_buffer,
249                                 samples_per_frame,
250                                 channels,
251                                 bits,
252                                 samplerate,
253                                 is_pal ? DV_PAL : DV_NTSC);
254                         memcpy(audio_buffer, 
255                                 audio_buffer + samples_written * bits * channels / 8,
256                                 (audio_samples - samples_written) * bits * channels / 8);
257                         audio_samples -= samples_written;
258                         position_lock->lock("IEC61883Output::run");
259                         audio_position += samples_written;
260                         position_lock->unlock();
263                         audio_lock->unlock();
264                 }
267                 buffer_lock->unlock();
268         }
273 // Write next chunk of current frame
274         if(out_buffer && out_position + 480 <= out_size)
275         {
276                 memcpy(data, out_buffer + out_position, 480);
277                 out_position += 480;
281                 if(out_position >= out_size)
282                 {
283                         buffer_lock->lock("IEC61883Output read_frame 2");
284                         buffer_valid[current_outbuffer] = 0;
286 // Advance buffer number if possible
287                         increment_counter(&current_outbuffer);
289 // Reuse same buffer next time
290                         if(!buffer_valid[current_outbuffer])
291                         {
292                                 decrement_counter(&current_outbuffer);
293                         }
294                         else
295 // Wait for user to reach current buffer before unlocking any more.
296                         {
297                                 video_lock->unlock();
298                         }
300                         buffer_lock->unlock();
301                 }
302         }
308 void IEC61883Output::write_frame(VFrame *input)
310         VFrame *ptr = 0;
311         int result = 0;
313 //printf("IEC61883Output::write_frame 1\n");
315         if(fd <= 0) return;
316         if(interrupted) return;
318 // Encode frame to DV
319         if(input->get_color_model() != BC_COMPRESSED)
320         {
321                 if(!temp_frame) temp_frame = new VFrame;
322                 if(!encoder) encoder = dv_new();
323                 ptr = temp_frame;
325 // Exact resolution match.  Don't do colorspace conversion
326                 if(input->get_color_model() == BC_YUV422 &&
327                         input->get_w() == 720 &&
328                         (input->get_h() == 480 ||
329                         input->get_h() == 576))
330                 {
331                         int norm = is_pal ? DV_PAL : DV_NTSC;
332                         int data_size = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
333                         temp_frame->allocate_compressed_data(data_size);
334                         temp_frame->set_compressed_size(data_size);
336                         dv_write_video(encoder,
337                                 temp_frame->get_data(),
338                                 input->get_rows(),
339                                 BC_YUV422,
340                                 norm);
341                         ptr = temp_frame;
342                 }
343                 else
344 // Convert resolution and color model before compressing
345                 {
346                         if(!temp_frame2)
347                         {
348                                 int h = input->get_h();
349 // Default to NTSC if unknown
350                                 if(h != 480 && h != 576) h = 480;
352                                 temp_frame2 = new VFrame(0,
353                                         720,
354                                         h,
355                                         BC_YUV422);
356                                 
357                         }
359                         int norm = is_pal ? DV_PAL : DV_NTSC;
360                         int data_size = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
361                         temp_frame->allocate_compressed_data(data_size);
362                         temp_frame->set_compressed_size(data_size);
365                         cmodel_transfer(temp_frame2->get_rows(), /* Leave NULL if non existent */
366                                 input->get_rows(),
367                                 temp_frame2->get_y(), /* Leave NULL if non existent */
368                                 temp_frame2->get_u(),
369                                 temp_frame2->get_v(),
370                                 input->get_y(), /* Leave NULL if non existent */
371                                 input->get_u(),
372                                 input->get_v(),
373                                 0,        /* Dimensions to capture from input frame */
374                                 0, 
375                                 MIN(temp_frame2->get_w(), input->get_w()),
376                                 MIN(temp_frame2->get_h(), input->get_h()),
377                                 0,       /* Dimensions to project on output frame */
378                                 0, 
379                                 MIN(temp_frame2->get_w(), input->get_w()),
380                                 MIN(temp_frame2->get_h(), input->get_h()),
381                                 input->get_color_model(), 
382                                 BC_YUV422,
383                                 0,         /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
384                                 input->get_bytes_per_line(),       /* For planar use the luma rowspan */
385                                 temp_frame2->get_bytes_per_line());     /* For planar use the luma rowspan */
387                         dv_write_video(encoder,
388                                 temp_frame->get_data(),
389                                 temp_frame2->get_rows(),
390                                 BC_YUV422,
391                                 norm);
395                         ptr = temp_frame;
396                 }
397         }
398         else
399                 ptr = input;
411 // Take over buffer table
412         buffer_lock->lock("IEC61883Output::write_frame 1");
413         have_video = 1;
414 // Wait for buffer to become available with timeout
415         while(buffer_valid[current_inbuffer] && !result && !interrupted)
416         {
417                 buffer_lock->unlock();
418                 result = video_lock->timed_lock(BUFFER_TIMEOUT);
419                 buffer_lock->lock("IEC61883Output::write_frame 2");
420         }
424 // Write buffer if there's room
425         if(!buffer_valid[current_inbuffer])
426         {
427                 if(!buffer[current_inbuffer])
428                 {
429                         buffer[current_inbuffer] = new char[ptr->get_compressed_size()];
430                         buffer_size[current_inbuffer] = ptr->get_compressed_size();
431                 }
432                 memcpy(buffer[current_inbuffer], ptr->get_data(), ptr->get_compressed_size());
433                 buffer_valid[current_inbuffer] = 1;
434                 increment_counter(&current_inbuffer);
435         }
436         else
437 // Ignore it if there isn't room.
438         {
439                 ;
440         }
442         buffer_lock->unlock();
443         start_lock->unlock();
444 //printf("IEC61883Output::write_frame 100\n");
447 void IEC61883Output::write_samples(char *data, int samples)
449 //printf("IEC61883Output::write_samples 1\n");
450         int result = 0;
451         int timeout = (int64_t)samples * 
452                 (int64_t)1000000 * 
453                 (int64_t)2 / 
454                 (int64_t)samplerate;
455         if(interrupted) return;
457 //printf("IEC61883Output::write_samples 2\n");
459 // Check for maximum sample count exceeded
460         if(samples > OUTPUT_SAMPLES)
461         {
462                 printf("IEC61883Output::write_samples samples=%d > OUTPUT_SAMPLES=%d\n",
463                         samples,
464                         OUTPUT_SAMPLES);
465                 return;
466         }
468 //printf("IEC61883Output::write_samples 3\n");
469 // Take over buffer table
470         buffer_lock->lock("IEC61883Output::write_samples 1");
471 // Wait for buffer to become available with timeout
472         while(audio_samples > OUTPUT_SAMPLES - samples && !result && !interrupted)
473         {
474                 buffer_lock->unlock();
475                 result = audio_lock->timed_lock(BUFFER_TIMEOUT);
476                 buffer_lock->lock("IEC61883Output::write_samples 2");
477         }
479         if(!interrupted && audio_samples <= OUTPUT_SAMPLES - samples)
480         {
481 //printf("IEC61883Output::write_samples 4 %d\n", audio_samples);
482                 memcpy(audio_buffer + audio_samples * channels * bits / 8,
483                         data,
484                         samples * channels * bits / 8);
485                 audio_samples += samples;
486         }
487         buffer_lock->unlock();
488         start_lock->unlock();
489 //printf("IEC61883Output::write_samples 100\n");
492 long IEC61883Output::get_audio_position()
494         position_lock->lock("IEC61883Output::get_audio_position");
495         long result = audio_position;
496         position_lock->unlock();
497         return result;
500 void IEC61883Output::interrupt()
502         interrupted = 1;
503 // Break write_samples out of a lock
504         video_lock->unlock();
505         audio_lock->unlock();
506 // Playback should stop when the object is deleted.
509 void IEC61883Output::flush()
511         
514 void IEC61883Output::increment_counter(int *counter)
516         (*counter)++;
517         if(*counter >= total_buffers) *counter = 0;
520 void IEC61883Output::decrement_counter(int *counter)
522         (*counter)--;
523         if(*counter < 0) *counter = total_buffers - 1;
536 #endif // HAVE_FIREWIRE
544 //      Local Variables:
545 //      mode: C++
546 //      c-file-style: "linux"
547 //      End: