5 #include "audiodevice.h"
7 #include "iec61883output.h"
9 #include "playbackconfig.h"
12 #include "videodevice.h"
17 #include <sys/ioctl.h>
20 #include <sys/utsname.h>
27 #define CIP_N_NTSC 2436
28 #define CIP_D_NTSC 38400
31 #define OUTPUT_SAMPLES 262144
32 #define BUFFER_TIMEOUT 500000
35 IEC61883Output::IEC61883Output(AudioDevice *adevice)
39 this->adevice = adevice;
42 IEC61883Output::IEC61883Output(VideoDevice *vdevice)
46 this->vdevice = vdevice;
49 IEC61883Output::~IEC61883Output()
61 for(int i = 0; i < total_buffers; i++)
63 if(buffer[i]) delete [] buffer[i];
66 delete [] buffer_size;
67 delete [] buffer_valid;
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()
99 current_outbuffer = 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,
140 this->channels = channels;
142 this->samplerate = samplerate;
143 this->total_buffers = length;
146 // Set PAL mode based on frame height
147 if(vdevice) is_pal = (vdevice->out_h == 576);
154 handle = raw1394_new_handle_on_port(port);
157 frame = iec61883_dv_xmit_init(handle,
163 if(!iec61883_dv_xmit_start(frame, channel))
165 fd = raw1394_get_fd(handle);
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");
185 audio_buffer = new char[OUTPUT_SAMPLES * channels * bits / 8];
191 void IEC61883Output::run()
193 Thread::enable_cancel();
194 start_lock->lock("IEC61883Output::run");
195 Thread::disable_cancel();
205 if(select(fd + 1, &rfds, 0, 0, &tv) > 0)
206 raw1394_loop_iterate (handle);
212 int IEC61883Output::read_frame(unsigned char *data, int n, unsigned int dropped)
215 if(!out_buffer || out_position + 480 > out_size)
217 buffer_lock->lock("IEC61883Output read_frame 1");
219 out_buffer = buffer[current_outbuffer];
220 out_size = buffer_size[current_outbuffer];
224 // No video. Put in a fake frame for audio only
227 #include "data/fake_ntsc_dv.h"
228 out_size = sizeof(fake_ntsc_dv) - 4;
229 out_buffer = (char*)fake_ntsc_dv + 4;
239 // Calculate number of samples needed based on given pattern for
241 int samples_per_frame = 2048;
244 if(audio_samples > samples_per_frame)
246 int samples_written = dv_write_audio(encoder,
247 (unsigned char*)out_buffer,
248 (unsigned char*)audio_buffer,
253 is_pal ? DV_PAL : DV_NTSC);
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();
267 buffer_lock->unlock();
273 // Write next chunk of current frame
274 if(out_buffer && out_position + 480 <= out_size)
276 memcpy(data, out_buffer + out_position, 480);
281 if(out_position >= out_size)
283 buffer_lock->lock("IEC61883Output read_frame 2");
284 buffer_valid[current_outbuffer] = 0;
286 // Advance buffer number if possible
287 increment_counter(¤t_outbuffer);
289 // Reuse same buffer next time
290 if(!buffer_valid[current_outbuffer])
292 decrement_counter(¤t_outbuffer);
295 // Wait for user to reach current buffer before unlocking any more.
297 video_lock->unlock();
300 buffer_lock->unlock();
308 void IEC61883Output::write_frame(VFrame *input)
313 //printf("IEC61883Output::write_frame 1\n");
316 if(interrupted) return;
318 // Encode frame to DV
319 if(input->get_color_model() != BC_COMPRESSED)
321 if(!temp_frame) temp_frame = new VFrame;
322 if(!encoder) encoder = dv_new();
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))
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(),
344 // Convert resolution and color model before compressing
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,
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 */
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 */
373 0, /* Dimensions to capture from input frame */
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 */
379 MIN(temp_frame2->get_w(), input->get_w()),
380 MIN(temp_frame2->get_h(), input->get_h()),
381 input->get_color_model(),
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(),
411 // Take over buffer table
412 buffer_lock->lock("IEC61883Output::write_frame 1");
414 // Wait for buffer to become available with timeout
415 while(buffer_valid[current_inbuffer] && !result && !interrupted)
417 buffer_lock->unlock();
418 result = video_lock->timed_lock(BUFFER_TIMEOUT);
419 buffer_lock->lock("IEC61883Output::write_frame 2");
424 // Write buffer if there's room
425 if(!buffer_valid[current_inbuffer])
427 if(!buffer[current_inbuffer])
429 buffer[current_inbuffer] = new char[ptr->get_compressed_size()];
430 buffer_size[current_inbuffer] = ptr->get_compressed_size();
432 memcpy(buffer[current_inbuffer], ptr->get_data(), ptr->get_compressed_size());
433 buffer_valid[current_inbuffer] = 1;
434 increment_counter(¤t_inbuffer);
437 // Ignore it if there isn't room.
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");
451 int timeout = (int64_t)samples *
455 if(interrupted) return;
457 //printf("IEC61883Output::write_samples 2\n");
459 // Check for maximum sample count exceeded
460 if(samples > OUTPUT_SAMPLES)
462 printf("IEC61883Output::write_samples samples=%d > OUTPUT_SAMPLES=%d\n",
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)
474 buffer_lock->unlock();
475 result = audio_lock->timed_lock(BUFFER_TIMEOUT);
476 buffer_lock->lock("IEC61883Output::write_samples 2");
479 if(!interrupted && audio_samples <= OUTPUT_SAMPLES - samples)
481 //printf("IEC61883Output::write_samples 4 %d\n", audio_samples);
482 memcpy(audio_buffer + audio_samples * channels * bits / 8,
484 samples * channels * bits / 8);
485 audio_samples += samples;
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();
500 void IEC61883Output::interrupt()
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()
514 void IEC61883Output::increment_counter(int *counter)
517 if(*counter >= total_buffers) *counter = 0;
520 void IEC61883Output::decrement_counter(int *counter)
523 if(*counter < 0) *counter = total_buffers - 1;
536 #endif // HAVE_FIREWIRE
546 // c-file-style: "linux"