subtitle upgrades, textbox fixes/upgrades
[goodguy/history.git] / cinelerra-5.1 / cinelerra / iec61883output.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #ifdef HAVE_FIREWIRE
23
24
25
26 #include "audiodevice.h"
27 #include "condition.h"
28 #include "iec61883output.h"
29 #include "mutex.h"
30 #include "playbackconfig.h"
31 #include "bctimer.h"
32 #include "vframe.h"
33 #include "videodevice.h"
34
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <string.h>
38 #include <sys/ioctl.h>
39 #include <sys/mman.h>
40 #include <unistd.h>
41 #include <sys/utsname.h>
42
43
44
45
46
47 // Crazy DV internals
48 #define CIP_N_NTSC 2436
49 #define CIP_D_NTSC 38400
50 #define CIP_N_PAL 1
51 #define CIP_D_PAL 16
52 #define OUTPUT_SAMPLES 262144
53 #define BUFFER_TIMEOUT 500000
54
55
56 IEC61883Output::IEC61883Output(AudioDevice *adevice)
57  : Thread(1, 0, 0)
58 {
59         reset();
60         this->adevice = adevice;
61 }
62
63 IEC61883Output::IEC61883Output(VideoDevice *vdevice)
64  : Thread(1, 0, 0)
65 {
66         reset();
67         this->vdevice = vdevice;
68 }
69
70 IEC61883Output::~IEC61883Output()
71 {
72         if(Thread::running())
73         {
74                 done = 1;
75                 start_lock->unlock();
76                 Thread::cancel();
77         }
78         Thread::join();
79
80         if(buffer)
81         {
82                 for(int i = 0; i < total_buffers; i++)
83                 {
84                         if(buffer[i]) delete [] buffer[i];
85                 }
86                 delete [] buffer;
87                 delete [] buffer_size;
88                 delete [] buffer_valid;
89         }
90
91         if(audio_lock) delete audio_lock;
92         if(video_lock) delete video_lock;
93         if(start_lock) delete start_lock;
94         if(audio_buffer) delete [] audio_buffer;
95
96         if(temp_frame) delete temp_frame;
97         if(temp_frame2) delete temp_frame2;
98         if(video_encoder) dv_delete(video_encoder);
99         if(audio_encoder) dv_delete(audio_encoder);
100         if(buffer_lock) delete buffer_lock;
101         if(position_lock) delete position_lock;
102         if(frame) iec61883_dv_close(frame);
103         if(handle) raw1394_destroy_handle(handle);
104 }
105
106
107 void IEC61883Output::reset()
108 {
109         handle = 0;
110         fd = 0;
111         frame = 0;
112         out_position = 0;
113         out_buffer = 0;
114         out_size = 0;
115
116         buffer = 0;
117         buffer_size = 0;
118         total_buffers = 0;
119         current_inbuffer = 0;
120         current_outbuffer = 0;
121         done = 0;
122         audio_lock = 0;
123         video_lock = 0;
124         start_lock = 0;
125         buffer_lock = 0;
126         position_lock = 0;
127         video_encoder = 0;
128         audio_encoder = 0;
129         audio_buffer = 0;
130         audio_samples = 0;
131         temp_frame = 0;
132         temp_frame2 = 0;
133         audio_position = 0;
134         interrupted = 0;
135         have_video = 0;
136         adevice = 0;
137         vdevice = 0;
138         is_pal = 0;
139 }
140
141
142
143 static int read_frame_static(unsigned char *data, int n, unsigned int dropped, void *ptr)
144 {
145         IEC61883Output *output = (IEC61883Output*)ptr;
146         return output->read_frame(data, n, dropped);
147 }
148
149
150
151
152
153 int IEC61883Output::open(int port,
154         int channel,
155         int length,
156         int channels,
157         int bits,
158         int samplerate,
159         int syt)
160 {
161         this->channels = channels;
162         this->bits = bits;
163         this->samplerate = samplerate;
164         this->total_buffers = length;
165         this->syt = syt;
166
167 // Set PAL mode based on frame height
168         if(vdevice) is_pal = (vdevice->out_h == 576);
169
170
171
172
173         if(!handle)
174         {
175                 handle = raw1394_new_handle_on_port(port);
176                 if(handle)
177                 {
178                         frame = iec61883_dv_xmit_init(handle,
179                                 is_pal,
180                                 read_frame_static,
181                                 (void *)this);
182                         if(frame)
183                         {
184                                 if(!iec61883_dv_xmit_start(frame, channel))
185                                 {
186                                         fd = raw1394_get_fd(handle);
187                                 }
188                         }
189                 }
190
191 // Create buffers
192                 buffer = new char*[total_buffers];
193                 for(int i = 0; i < length; i++)
194                         buffer[i] = new char[DV_PAL_SIZE];
195                 buffer_size = new int[total_buffers];
196                 buffer_valid = new int[total_buffers];
197                 bzero(buffer_size, sizeof(int) * total_buffers);
198                 bzero(buffer_valid, sizeof(int) * total_buffers);
199                 bzero(buffer, sizeof(char*) * total_buffers);
200                 video_lock = new Condition(0, "IEC61883Output::video_lock");
201                 audio_lock = new Condition(0, "IEC61883Output::audio_lock");
202                 start_lock = new Condition(0, "IEC61883Output::start_lock");
203                 buffer_lock = new Mutex("IEC61883Output::buffer_lock");
204                 position_lock = new Mutex("IEC61883Output::position_lock");
205                 encoder = dv_new();
206                 audio_buffer = new char[OUTPUT_SAMPLES * channels * bits / 8];
207                 Thread::start();
208         }
209         return 0;
210 }
211
212 void IEC61883Output::run()
213 {
214         Thread::enable_cancel();
215         start_lock->lock("IEC61883Output::run");
216         Thread::disable_cancel();
217
218         while(!done)
219         {
220                 struct timeval tv;
221                 fd_set rfds;
222                 FD_ZERO (&rfds);
223                 FD_SET (fd, &rfds);
224                 tv.tv_sec = 0;
225                 tv.tv_usec = 20000;
226                 if(select(fd + 1, &rfds, 0, 0, &tv) > 0)
227                         raw1394_loop_iterate (handle);
228         }
229 }
230
231
232
233 int IEC61883Output::read_frame(unsigned char *data, int n, unsigned int dropped)
234 {
235 // Next frame
236         if(!out_buffer || out_position + 480 > out_size)
237         {
238                 buffer_lock->lock("IEC61883Output read_frame 1");
239
240                 out_buffer = buffer[current_outbuffer];
241                 out_size = buffer_size[current_outbuffer];
242                 out_position = 0;
243
244
245 // No video.  Put in a fake frame for audio only
246                 if(!have_video)
247                 {
248 #include "data/fake_ntsc_dv.h"
249                         out_size = sizeof(fake_ntsc_dv) - 4;
250                         out_buffer = (char*)fake_ntsc_dv + 4;
251                 }
252
253
254
255
256
257
258
259
260 // Calculate number of samples needed based on given pattern for
261 // norm.
262                 int samples_per_frame = 2048;
263
264 // Encode audio
265                 if(audio_samples > samples_per_frame)
266                 {
267                         int samples_written = dv_write_audio(encoder,
268                                 (unsigned char*)out_buffer,
269                                 (unsigned char*)audio_buffer,
270                                 samples_per_frame,
271                                 channels,
272                                 bits,
273                                 samplerate,
274                                 is_pal ? DV_PAL : DV_NTSC);
275                         memcpy(audio_buffer,
276                                 audio_buffer + samples_written * bits * channels / 8,
277                                 (audio_samples - samples_written) * bits * channels / 8);
278                         audio_samples -= samples_written;
279                         position_lock->lock("IEC61883Output::run");
280                         audio_position += samples_written;
281                         position_lock->unlock();
282
283
284                         audio_lock->unlock();
285                 }
286
287
288                 buffer_lock->unlock();
289         }
290
291
292
293
294 // Write next chunk of current frame
295         if(out_buffer && out_position + 480 <= out_size)
296         {
297                 memcpy(data, out_buffer + out_position, 480);
298                 out_position += 480;
299
300
301
302                 if(out_position >= out_size)
303                 {
304                         buffer_lock->lock("IEC61883Output read_frame 2");
305                         buffer_valid[current_outbuffer] = 0;
306
307 // Advance buffer number if possible
308                         increment_counter(&current_outbuffer);
309
310 // Reuse same buffer next time
311                         if(!buffer_valid[current_outbuffer])
312                         {
313                                 decrement_counter(&current_outbuffer);
314                         }
315                         else
316 // Wait for user to reach current buffer before unlocking any more.
317                         {
318                                 video_lock->unlock();
319                         }
320
321                         buffer_lock->unlock();
322                 }
323         }
324         return 0;
325 }
326
327
328
329
330 void IEC61883Output::write_frame(VFrame *input)
331 {
332         VFrame *ptr = 0;
333         int result = 0;
334
335 //printf("IEC61883Output::write_frame 1\n");
336
337         if(fd <= 0) return;
338         if(interrupted) return;
339
340 // Encode frame to DV
341         if(input->get_color_model() != BC_COMPRESSED)
342         {
343                 if(!temp_frame) temp_frame = new VFrame;
344                 if(!encoder) encoder = dv_new();
345                 ptr = temp_frame;
346
347 // Exact resolution match.  Don't do colorspace conversion
348                 if(input->get_color_model() == BC_YUV422 &&
349                         input->get_w() == 720 &&
350                         (input->get_h() == 480 ||
351                         input->get_h() == 576))
352                 {
353                         int norm = is_pal ? DV_PAL : DV_NTSC;
354                         int data_size = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
355                         temp_frame->allocate_compressed_data(data_size);
356                         temp_frame->set_compressed_size(data_size);
357
358                         dv_write_video(encoder,
359                                 temp_frame->get_data(),
360                                 input->get_rows(),
361                                 BC_YUV422,
362                                 norm);
363                         ptr = temp_frame;
364                 }
365                 else
366 // Convert resolution and color model before compressing
367                 {
368                         if(!temp_frame2)
369                         {
370                                 int h = input->get_h();
371 // Default to NTSC if unknown
372                                 if(h != 480 && h != 576) h = 480;
373
374                                 temp_frame2 = new VFrame(0,
375                                         -1,
376                                         720,
377                                         h,
378                                         BC_YUV422,
379                                         -1);
380
381                         }
382
383                         int norm = is_pal ? DV_PAL : DV_NTSC;
384                         int data_size = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
385                         temp_frame->allocate_compressed_data(data_size);
386                         temp_frame->set_compressed_size(data_size);
387
388
389                         BC_CModels::transfer(temp_frame2->get_rows(), /* Leave NULL if non existent */
390                                 input->get_rows(),
391                                 temp_frame2->get_y(), /* Leave NULL if non existent */
392                                 temp_frame2->get_u(),
393                                 temp_frame2->get_v(),
394                                 input->get_y(), /* Leave NULL if non existent */
395                                 input->get_u(),
396                                 input->get_v(),
397                                 0,        /* Dimensions to capture from input frame */
398                                 0,
399                                 MIN(temp_frame2->get_w(), input->get_w()),
400                                 MIN(temp_frame2->get_h(), input->get_h()),
401                                 0,       /* Dimensions to project on output frame */
402                                 0,
403                                 MIN(temp_frame2->get_w(), input->get_w()),
404                                 MIN(temp_frame2->get_h(), input->get_h()),
405                                 input->get_color_model(),
406                                 BC_YUV422,
407                                 0,         /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
408                                 input->get_bytes_per_line(),       /* For planar use the luma rowspan */
409                                 temp_frame2->get_bytes_per_line());     /* For planar use the luma rowspan */
410
411                         dv_write_video(encoder,
412                                 temp_frame->get_data(),
413                                 temp_frame2->get_rows(),
414                                 BC_YUV422,
415                                 norm);
416
417
418
419                         ptr = temp_frame;
420                 }
421         }
422         else
423                 ptr = input;
424
425
426
427
428
429
430
431
432
433
434
435 // Take over buffer table
436         buffer_lock->lock("IEC61883Output::write_frame 1");
437         have_video = 1;
438 // Wait for buffer to become available with timeout
439         while(buffer_valid[current_inbuffer] && !result && !interrupted)
440         {
441                 buffer_lock->unlock();
442                 result = video_lock->timed_lock(BUFFER_TIMEOUT);
443                 buffer_lock->lock("IEC61883Output::write_frame 2");
444         }
445
446
447
448 // Write buffer if there's room
449         if(!buffer_valid[current_inbuffer])
450         {
451                 if(!buffer[current_inbuffer])
452                 {
453                         buffer[current_inbuffer] = new char[ptr->get_compressed_size()];
454                         buffer_size[current_inbuffer] = ptr->get_compressed_size();
455                 }
456                 memcpy(buffer[current_inbuffer], ptr->get_data(), ptr->get_compressed_size());
457                 buffer_valid[current_inbuffer] = 1;
458                 increment_counter(&current_inbuffer);
459         }
460         else
461 // Ignore it if there isn't room.
462         {
463                 ;
464         }
465
466         buffer_lock->unlock();
467         start_lock->unlock();
468 //printf("IEC61883Output::write_frame 100\n");
469 }
470
471 void IEC61883Output::write_samples(char *data, int samples)
472 {
473 //printf("IEC61883Output::write_samples 1\n");
474         int result = 0;
475         //int timeout = (samples * 1000000LL * 2) / samplerate;
476         if(interrupted) return;
477
478 //printf("IEC61883Output::write_samples 2\n");
479
480 // Check for maximum sample count exceeded
481         if(samples > OUTPUT_SAMPLES)
482         {
483                 printf("IEC61883Output::write_samples samples=%d > OUTPUT_SAMPLES=%d\n",
484                         samples,
485                         OUTPUT_SAMPLES);
486                 return;
487         }
488
489 //printf("IEC61883Output::write_samples 3\n");
490 // Take over buffer table
491         buffer_lock->lock("IEC61883Output::write_samples 1");
492 // Wait for buffer to become available with timeout
493         while(audio_samples > OUTPUT_SAMPLES - samples && !result && !interrupted)
494         {
495                 buffer_lock->unlock();
496                 result = audio_lock->timed_lock(BUFFER_TIMEOUT);
497                 buffer_lock->lock("IEC61883Output::write_samples 2");
498         }
499
500         if(!interrupted && audio_samples <= OUTPUT_SAMPLES - samples)
501         {
502 //printf("IEC61883Output::write_samples 4 %d\n", audio_samples);
503                 memcpy(audio_buffer + audio_samples * channels * bits / 8,
504                         data,
505                         samples * channels * bits / 8);
506                 audio_samples += samples;
507         }
508         buffer_lock->unlock();
509         start_lock->unlock();
510 //printf("IEC61883Output::write_samples 100\n");
511 }
512
513 long IEC61883Output::get_audio_position()
514 {
515         position_lock->lock("IEC61883Output::get_audio_position");
516         long result = audio_position;
517         position_lock->unlock();
518         return result;
519 }
520
521 void IEC61883Output::interrupt()
522 {
523         interrupted = 1;
524 // Break write_samples out of a lock
525         video_lock->unlock();
526         audio_lock->unlock();
527 // Playback should stop when the object is deleted.
528 }
529
530 void IEC61883Output::flush()
531 {
532
533 }
534
535 void IEC61883Output::increment_counter(int *counter)
536 {
537         (*counter)++;
538         if(*counter >= total_buffers) *counter = 0;
539 }
540
541 void IEC61883Output::decrement_counter(int *counter)
542 {
543         (*counter)--;
544         if(*counter < 0) *counter = total_buffers - 1;
545 }
546
547
548
549
550
551
552
553
554
555
556
557 #endif // HAVE_FIREWIRE
558
559
560
561
562
563