2 * dvunit.c -- DV Transmission Unit Implementation
3 * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
4 * Author: Dan Dennedy <dan@dennedy.org>
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.
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.
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 Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #include <sys/ioctl.h>
30 #include <sys/types.h>
37 #include <libdv/dv1394.h>
38 #include <libraw1394/raw1394.h>
39 #include <libavc1394/avc1394_vcr.h>
44 #include "dvframepool.h"
49 #include "raw1394util.h"
53 /* Forward references */
54 static void dv_unit_status_communicate( dv_unit );
56 /** dv1394 device file names based upon devfs default names. */
58 static char *devices[4][4] = {
60 "/dev/ieee1394/dv/host0/NTSC/in",
61 "/dev/ieee1394/dv/host0/NTSC/out",
62 "/dev/ieee1394/dv/host0/PAL/in",
63 "/dev/ieee1394/dv/host0/PAL/out",
65 "/dev/ieee1394/dv/host1/NTSC/in",
66 "/dev/ieee1394/dv/host1/NTSC/out",
67 "/dev/ieee1394/dv/host1/PAL/in",
68 "/dev/ieee1394/dv/host1/PAL/out"
70 "/dev/ieee1394/dv/host2/NTSC/in",
71 "/dev/ieee1394/dv/host2/NTSC/out",
72 "/dev/ieee1394/dv/host2/PAL/in",
73 "/dev/ieee1394/dv/host2/PAL/out"
75 "/dev/ieee1394/dv/host3/NTSC/in",
76 "/dev/ieee1394/dv/host3/NTSC/out",
77 "/dev/ieee1394/dv/host3/PAL/in",
78 "/dev/ieee1394/dv/host3/PAL/out"
82 static int device_count[4] = {0,0,0,0};
84 /** Allocate a new DV transmission unit.
86 \param dv1394d_fd The file descriptor of a dv1394 device file to
88 \param guid The node GUID of the receiving device.
89 \param channel The channel to use for transmission.
90 \return A new dv_unit handle.
93 dv_unit dv_unit_init( octlet_t guid, int channel )
95 dv_unit unit = malloc( sizeof( dv_unit_t ) );
100 memset( unit, 0, sizeof( dv_unit_t ) );
102 unit->buffer_size = 25;
103 unit->is_terminated = 1;
104 unit->channel = channel;
105 unit->dv1394_fd = -1;
106 unit->n_frames = DV1394_MAX_FRAMES / 2;
109 /* get a raw1394 handle for plug control */
110 if ( ( node_id = raw1394_find_node( &(unit->raw1394), guid ) ) != -1 )
112 if ( dv_unit_online( unit ) == 1 )
113 dv1394d_log( LOG_DEBUG, "Added online unit with GUID %08x%08x",
114 (quadlet_t) (unit->guid>>32), (quadlet_t) (unit->guid & 0xffffffff) );
117 dv_unit_close( unit );
123 dv1394d_log( LOG_DEBUG, "Added offline unit with GUID %08x%08x",
124 (quadlet_t) (unit->guid>>32), (quadlet_t) (unit->guid & 0xffffffff) );
130 /** Allow stdin to feed the unit (redundant now that senddv has been dropped).
133 void dv_unit_allow_stdin( dv_unit unit, int flag )
135 unit->allow_stdin = flag;
138 /** Override the default buffer/pump size - this must be done prior to the pumps
142 void dv_unit_set_buffer_size( dv_unit unit, int size )
146 if ( unit->pump == NULL )
147 unit->buffer_size = size;
149 unit->buffer_size = dv_pump_resize( unit->pump, size );
153 int dv_unit_get_buffer_size( dv_unit unit )
155 return unit->buffer_size;
158 void dv_unit_set_n_frames( dv_unit unit, int size )
160 if ( size > 0 && size <= DV1394_MAX_FRAMES / 2 )
161 unit->n_frames = size;
164 int dv_unit_get_n_frames( dv_unit unit )
166 return unit->n_frames;
169 void dv_unit_set_n_fill( dv_unit unit, int size )
174 int dv_unit_get_n_fill( dv_unit unit )
179 /** Set the notifier info
182 void dv_unit_set_notifier( dv_unit this, dv1394_notifier notifier, char *root_dir )
184 this->notifier = notifier;
185 this->root_dir = root_dir;
186 dv_unit_status_communicate( this );
189 /** Communicate the current status to all threads waiting on the notifier.
192 static void dv_unit_status_communicate( dv_unit unit )
194 if ( unit != NULL && unit->notifier != NULL && unit->root_dir != NULL )
196 dv1394_status_t status;
197 if ( dv_unit_get_status( unit, &status ) == 0 )
198 if ( !( ( status.status == unit_playing || status.status == unit_paused ) &&
199 strcmp( status.clip, "" ) &&
200 !strcmp( status.tail_clip, "" ) &&
201 status.position == 0 &&
204 dv1394_notifier_put( unit->notifier, &status );
208 /** Load a clip into the unit clearing existing play list.
211 \param unit A dv_unit handle.
212 \param clip The absolute file name of the clip to load.
213 \param in The starting frame (-1 for 0)
214 \param out The ending frame (-1 for maximum)
217 dv_error_code dv_unit_load( dv_unit unit, const char *clip, long in, long out, int flush )
219 dv_player player = dv_unit_get_dv_player( unit );
220 dv_error_code error = dv_player_get_error( player );
221 if ( error == dv_pump_ok )
223 error = dv_player_replace_file( player, (char*) clip, in, out, flush );
224 dv1394d_log( LOG_DEBUG, "loaded clip %s", clip );
225 if ( unit->is_terminated )
226 dv_unit_status_communicate( unit );
231 dv_error_code dv_unit_insert( dv_unit unit, const char *clip, int index, long in, long out )
233 dv_player player = dv_unit_get_dv_player( unit );
234 dv_error_code error = dv_player_get_error( player );
235 if ( error == dv_pump_ok )
237 error = dv_player_insert_file( player, (char*) clip, index, in, out );
238 dv1394d_log( LOG_DEBUG, "inserted clip %s", clip );
239 if ( unit->is_terminated )
240 dv_unit_status_communicate( unit );
245 dv_error_code dv_unit_remove( dv_unit unit, int index )
247 dv_player player = dv_unit_get_dv_player( unit );
248 dv_error_code error = dv_player_get_error( player );
249 if ( error == dv_pump_ok )
251 error = dv_player_remove_clip( player, index );
252 dv1394d_log( LOG_DEBUG, "removed clip %d", index );
253 if ( unit->is_terminated )
254 dv_unit_status_communicate( unit );
259 dv_error_code dv_unit_clean( dv_unit unit )
261 dv_player player = dv_unit_get_dv_player( unit );
262 dv_error_code error = dv_player_get_error( player );
263 if ( error == dv_pump_ok )
265 error = dv_player_clean( player );
266 dv1394d_log( LOG_DEBUG, "Cleaned playlist" );
267 if ( unit->is_terminated )
268 dv_unit_status_communicate( unit );
273 dv_error_code dv_unit_move( dv_unit unit, int src, int dest )
275 dv_player player = dv_unit_get_dv_player( unit );
276 dv_error_code error = dv_player_get_error( player );
277 if ( error == dv_pump_ok )
279 error = dv_player_move_clip( player, src, dest );
280 dv1394d_log( LOG_DEBUG, "moved clip %d to %d", src, dest );
281 if ( unit->is_terminated )
282 dv_unit_status_communicate( unit );
287 /** Add a clip to the unit play list.
290 \param unit A dv_unit handle.
291 \param clip The absolute file name of the clip to load.
292 \param in The starting frame (-1 for 0)
293 \param out The ending frame (-1 for maximum)
296 dv_error_code dv_unit_append( dv_unit unit, const char *clip, long in, long out )
298 dv_player player = dv_unit_get_dv_player( unit );
299 dv_error_code error = dv_player_add_file( player, (char*) clip, in, out );
300 dv_unit_status_communicate( unit );
304 void *output_cleanup( void *arg )
307 if ( unit != NULL && unit->mmap != NULL )
309 unit->is_terminated = 1;
310 dv_unit_status_communicate( unit );
311 munmap( unit->mmap, unit->mmap_length );
312 /* this actually stops transmission as opposed to allowing the
313 last frame to loop in the OHCI DMA context. */
314 ioctl( unit->dv1394_fd, DV1394_SHUTDOWN, NULL );
320 /** The dv1394 transmission thread.
322 \param arg A dv_unit handle.
325 static void *output( void *arg )
328 dv_frame frames[ DV1394_MAX_FRAMES ];
329 int frames_dropped = 0; /* count of total frames dropped (repeated) */
330 struct dv1394_status status;
332 int n_fill = unit->n_fill;
333 int n_frames = unit->n_frames;
335 /* Determine the number of frames to wait for/fill on each iteration */
338 else if ( n_fill > unit->n_frames )
339 n_fill = n_frames / 2;
341 unit->mmap = mmap( NULL,unit->mmap_length,PROT_WRITE,MAP_SHARED,unit->dv1394_fd,0 );
342 if ( unit->mmap == MAP_FAILED || unit->mmap == NULL )
348 pthread_cleanup_push( output_cleanup, (void *)arg );
350 while ( dv_pump_get_available_output_count( unit->pump ) ||
351 !( dv_unit_has_terminated( unit ) || dv_pump_has_terminated( unit->pump) ) )
355 if ( ioctl( unit->dv1394_fd, DV1394_WAIT_FRAMES, n_fill ) < 0)
356 perror( "DV1394_WAIT_FRAMES" );
358 pthread_testcancel();
360 /* update the status for the next iteration and detect dropped frames */
361 if ( ioctl( unit->dv1394_fd, DV1394_GET_STATUS, &status ) >= 0)
363 pthread_testcancel();
366 printf( "dv1394 status: active=%02d, #clear=%02d, first clear=%02d\n",
367 status.active_frame, status.n_clear_frames, status.first_clear_frame);
370 /* report dropped frames */
371 if( status.dropped_frames > 0 )
373 frames_dropped += status.dropped_frames;
374 dv1394d_log( LOG_WARNING, "dv1394 repeated %d frames with %d available.",
375 status.dropped_frames, dv_pump_get_available_output_count( unit->pump ) );
378 available = dv_pump_get_output_block( unit->pump, (void **)frames, n_fill );
380 dv_unit_status_communicate( unit );
382 /* The only time we get 0 frames is when the unit is being stopped. */
383 if ( available != 0 )
385 int size = dv_frame_size( frames[ 0 ] );
386 int pos = status.first_clear_frame;
389 for ( index = 0; index < available; index ++ )
390 memcpy( unit->mmap + ( ( pos + index ) % n_frames ) * size, dv_frame_data( frames[ index ] ), size );
392 if ( ioctl( unit->dv1394_fd, DV1394_SUBMIT_FRAMES, available ) >= 0)
394 for ( index = 0; index < available - 1; index ++ )
396 dv_frame_clear_error( frames[ index ] );
397 dv_frame_id_clear( dv_frame_get_id( frames[ index ] ) );
399 dv_pump_return_output_block( unit->pump );
400 pthread_testcancel();
404 dv1394d_log( LOG_ERR, "failed to write frames to dv1394: %s.", strerror_r( errno, errstr, 63 ) );
405 dv_pump_terminate( unit->pump );
406 dv_pump_flush( unit->pump );
407 pthread_testcancel();
413 dv1394d_log( LOG_ERR, "failed to get dv1394 status: %s.", strerror_r( errno, errstr, 63 ) );
414 dv_pump_return_used_output( unit->pump );
418 if ( frames_dropped > 0 )
419 dv1394d_log( LOG_WARNING, "dv1394 repeated %d frames total during this transmission.", frames_dropped );
421 pthread_cleanup_pop( 1 );
426 /** Start playing the clip.
428 Start a dv-pump and commence dv1394 transmission.
431 \param unit A dv_unit handle.
432 \param speed An integer that specifies the playback rate as a
433 percentage multiplied by 100.
436 void dv_unit_play( dv_unit_t *unit, int speed )
438 dv_player player = dv_unit_get_dv_player( unit );
440 if ( unit->is_terminated == 1 && ( dv_player_get_total_frames( player ) > 0 || unit->allow_stdin ) )
443 dv_frame frame = NULL;
444 struct dv1394_init setup =
446 api_version: DV1394_API_VERSION,
447 channel: unit->channel,
448 /* this only sets the *requested* size of the ringbuffer,
450 n_frames: unit->n_frames,
451 /* we set the format later */
452 cip_n: unit->dv1394_cip_n,
453 cip_d: unit->dv1394_cip_d,
454 syt_offset: unit->dv1394_syt_offset
458 if ( unit->in == NULL )
460 if ( !unit->allow_stdin || dv_player_get_total_frames( player ) != 0 )
461 unit->in = dv_player_get_dv_input( player );
463 unit->in = dv_input_init( unit->pump );
467 dv_input_join_thread( unit->in );
468 pthread_join( unit->out, NULL );
471 unit->is_terminated = 0;
472 dv_pump_restart( unit->pump );
473 dv_input_start_thread( unit->in );
474 dv_player_set_speed( player, (double) speed/1000.0 );
476 /* first we read a little data to see if this is PAL or NTSC
477 so we can initialize dv1394 properly */
478 frame = dv_pump_get_available_output( unit->pump );
480 /* initialize dv1394 */
481 setup.format = dv_frame_is_pal(frame) ? DV1394_PAL : DV1394_NTSC;
483 retval = ioctl( unit->dv1394_fd, DV1394_INIT, &setup );
486 perror( "DV1394_INIT" );
490 unit->mmap_length = unit->n_frames * dv_frame_size( frame );
492 pthread_attr_init( &attr );
493 pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
494 pthread_attr_setinheritsched( &attr, PTHREAD_INHERIT_SCHED );
495 pthread_create( &unit->out, &attr, output, unit );
499 dv_player_set_speed( player, (double) speed/1000.0 );
501 dv_unit_status_communicate( unit );
506 Terminates the dv_pump and halts dv1394 transmission.
508 \param unit A dv_unit handle.
511 void dv_unit_terminate( dv_unit unit )
513 unit->is_terminated = 1;
514 if ( unit->pump != NULL )
516 dv_pump_terminate( unit->pump );
517 dv_pump_flush( unit->pump );
521 /** Query the status of unit playback.
523 \param unit A dv_unit handle.
524 \return 1 if the unit is not playing, 0 if playing.
527 int dv_unit_has_terminated( dv_unit unit )
529 return unit->is_terminated;
532 /** Get the dv_player from the dv_unit.
534 \param unit A dv_unit handle.
535 \return A dv_player handle.
538 dv_player dv_unit_get_dv_player( dv_unit unit )
542 if ( unit->pump == NULL )
544 unit->pump = dv_pump_init( unit->buffer_size );
545 if ( unit->pump != NULL )
546 unit->player = dv_player_init( unit->pump );
554 /** Transfer the currently loaded clip to another unit
557 int dv_unit_transfer( dv_unit dest_unit, dv_unit src_unit )
559 dv_player src_player = dv_unit_get_dv_player( src_unit );
560 dv_player dest_player = dv_unit_get_dv_player( dest_unit );
562 if( dest_player != NULL && src_player != NULL )
563 dv_player_replace_player( dest_player, src_player );
568 /** Get the guid associated to this unit.
571 octlet_t dv_unit_get_guid( dv_unit unit )
576 /** Get the node id associated to this unit.
579 int dv_unit_get_nodeid( dv_unit unit )
581 return (unit->node_id & 0x3f);
584 /** Get the channel associated to this unit.
587 int dv_unit_get_channel( dv_unit unit )
589 return (unit->channel);
592 /** Turn unit online.
595 int dv_unit_online( dv_unit unit )
600 if ( unit->raw1394 != NULL )
601 raw1394_close( unit->raw1394 );
603 node_id = raw1394_find_node( &(unit->raw1394), unit->guid );
606 unit->node_id = 0xffc0 | node_id;
607 port = dv_unit_get_port( unit );
609 unit->dv1394_fd = open( devices[ port ][ device_count[port] ], O_RDWR );
610 if ( unit->dv1394_fd < 0 )
612 dv1394d_log( LOG_ERR, "failed to open dv1394 device - %s\n", devices[ port ][ device_count[port] ] );
613 dv_unit_close( unit );
617 device_count[ port ] ++;
618 if ( establish_p2p_connection( unit->raw1394, unit->node_id, (unsigned int *) &(unit->channel) ) )
620 avc1394_vcr_record( unit->raw1394, unit->node_id );
622 dv_unit_status_communicate( unit );
631 /** Turn unit offline.
634 void dv_unit_offline( dv_unit unit )
636 if ( unit->online == 1 )
638 if ( unit->is_terminated == 0 )
639 dv_unit_terminate( unit );
641 if ( unit->raw1394 != NULL )
643 avc1394_vcr_stop( unit->raw1394, unit->node_id );
644 break_p2p_connection( unit->raw1394, unit->node_id, unit->channel );
646 if ( unit->dv1394_fd > -1 )
648 close( unit->dv1394_fd );
649 device_count[ dv_unit_get_port( unit ) ] --;
651 dv_unit_status_communicate( unit );
652 dv1394d_log( LOG_DEBUG, "Unit with GUID %08x%08x is now offline.",
653 (quadlet_t) (unit->guid>>32), (quadlet_t) (unit->guid & 0xffffffff) );
657 /** Determine if unit is offline.
660 int dv_unit_is_offline( dv_unit unit )
662 return (unit->online == 0);
665 /** Obtain the status for a given unit
668 int dv_unit_get_status( dv_unit unit, dv1394_status status )
672 memset( status, 0, sizeof( dv1394_status_t ) );
676 dv_player player = dv_unit_get_dv_player( unit );
680 if ( player != NULL )
682 dv_frame head = dv_pump_get_head( player->pump );
683 dv_frame tail = dv_pump_get_tail( player->pump );
685 status->speed = (int)( dv_player_get_speed( player ) * 1000.0 );
686 status->fps = dv_player_frames_per_second( player, 0 );
690 dv_frame_id id = dv_frame_get_id( head );
691 if ( id->resource != NULL )
693 const char *resource = id->resource;
694 if ( resource != NULL && unit->root_dir != NULL )
695 resource += strlen( unit->root_dir ) - ( unit->root_dir[ strlen( unit->root_dir ) - 1 ] == '/' );
696 strncpy( status->clip, resource, sizeof( status->clip ) );
700 char *title = dv_player_get_name( player, dv_player_get_clip_containing( player, 0 ), unit->root_dir );
702 strncpy( status->clip, title, sizeof( status->clip ) );
705 status->position = id->relative;
707 status->out = id->out;
708 status->length = id->length;
709 status->seek_flag = id->seek_flag;
713 char *title = dv_player_get_name( player, dv_player_get_clip_containing( player, 0 ), unit->root_dir );
715 strncpy( status->clip, title, sizeof( status->clip ) );
720 dv_frame_id id = dv_frame_get_id( tail );
721 const char *resource = id->resource;
722 if ( resource != NULL && unit->root_dir != NULL )
723 resource += strlen( unit->root_dir ) - ( unit->root_dir[ strlen( unit->root_dir ) - 1 ] == '/' );
724 if ( resource != NULL )
725 strncpy( status->tail_clip, resource, sizeof( status->clip ) );
726 status->tail_position = id->relative;
727 status->tail_in = id->in;
728 status->tail_out = id->out;
729 status->tail_length = id->length;
732 status->generation = player->generation;
733 status->clip_index = dv_unit_get_current_clip( unit );
736 if ( dv_unit_is_offline( unit ) )
737 status->status = unit_offline;
738 else if ( !strcmp( status->clip, "" ) )
739 status->status = unit_not_loaded;
740 else if ( dv_unit_has_terminated( unit ) )
741 status->status = unit_stopped;
742 else if ( status->speed == 0 )
743 status->status = unit_paused;
745 status->status = unit_playing;
749 status->status = unit_undefined;
752 status->unit = unit->unit;
757 /** Change position in the playlist.
760 void dv_unit_change_position( dv_unit unit, int clip, long position )
762 dv_player player = dv_unit_get_dv_player( unit );
763 dv_player_set_clip_position( player, clip, position );
764 dv_unit_status_communicate( unit );
770 void dv_unit_change_speed( dv_unit unit, int speed )
772 if ( dv_unit_has_terminated( unit ) )
773 dv_unit_change_position( unit, 0, 0 );
775 dv_unit_play( unit, speed );
778 int dv_unit_get_current_clip( dv_unit unit )
780 dv_player player = dv_unit_get_dv_player( unit );
781 unsigned long position = dv_player_get_position( player );
782 return dv_player_get_clip_containing( player, position );
785 /** Set a clip's in point
788 int dv_unit_set_clip_in( dv_unit unit, int index, long position )
791 dv_player player = dv_unit_get_dv_player( unit );
793 if ( player != NULL )
795 dv_unit_change_speed( unit, 0 );
796 if ( dv_player_set_in_point( player, index, (unsigned long) position ) == position )
797 dv_player_set_clip_position( player, index, position );
806 dv_unit_status_communicate( unit );
812 /** Set a clip's out point.
815 int dv_unit_set_clip_out( dv_unit unit, int index, long position )
818 dv_player player = dv_unit_get_dv_player( unit );
820 if ( player != NULL )
822 dv_unit_change_speed( unit, 0 );
823 if ( dv_player_set_out_point( player, index, position ) == position )
824 dv_player_set_clip_position( player, index, position );
833 dv_unit_status_communicate( unit );
838 /** Step by specified position.
841 void dv_unit_step( dv_unit unit, int offset )
843 dv_player player = dv_unit_get_dv_player( unit );
844 dv_player_change_position( player, dv_seek_relative, offset );
847 /** Set the unit's clip mode regarding in and out points.
850 void dv_unit_set_mode( dv_unit unit, dv_player_clip_mode mode )
852 dv_player player = dv_unit_get_dv_player( unit );
853 if ( player != NULL )
854 dv_player_set_clip_mode( player, mode );
855 dv_unit_status_communicate( unit );
858 /** Get the unit's clip mode regarding in and out points.
861 dv_player_clip_mode dv_unit_get_mode( dv_unit unit )
863 dv_player player = dv_unit_get_dv_player( unit );
864 return dv_player_get_clip_mode( player );
867 /** Set the unit's clip mode regarding eof handling.
870 void dv_unit_set_eof_action( dv_unit unit, dv_player_eof_action action )
872 dv_player player = dv_unit_get_dv_player( unit );
873 dv_player_set_eof_action( player, action );
874 dv_unit_status_communicate( unit );
877 /** Get the unit's clip mode regarding eof handling.
880 dv_player_eof_action dv_unit_get_eof_action( dv_unit unit )
882 dv_player player = dv_unit_get_dv_player( unit );
883 return dv_player_get_eof_action( player );
889 \param unit A dv_unit handle.
892 void dv_unit_close( dv_unit unit )
896 dv1394d_log( LOG_DEBUG, "closing unit..." );
897 dv_unit_offline( unit );
898 if ( unit->pump != NULL )
900 dv_pump_terminate( unit->pump );
901 dv_pump_flush( unit->pump );
902 dv_pump_return_used_output( unit->pump );
903 dv_input_join_thread( unit->in );
904 if ( !unit->is_terminated )
905 pthread_join( unit->out, NULL );
906 dv_pump_close( unit->pump );
909 raw1394_close( unit->raw1394 );
911 dv1394d_log( LOG_DEBUG, "... unit closed." );
915 /** Get the raw1394 port associated to this unit.
918 int dv_unit_get_port( dv_unit unit )
920 if ( unit->raw1394 != NULL )
921 return (int) raw1394_get_userdata( unit->raw1394 );
926 /** Set the dv1394 file descriptor for the unit.
929 void dv_unit_set_dv1394_fd( dv_unit unit, int fd )
931 unit->dv1394_fd = fd;
934 /** Get the dv1394 syt_offset (timestamp latency) property.
937 unsigned int dv_unit_get_syt_offset( dv_unit unit )
939 return unit->dv1394_syt_offset;
942 /** Get the dv1394 cip_n (timing numerator) property.
945 unsigned int dv_unit_get_cip_n( dv_unit unit )
947 return unit->dv1394_cip_n;
950 /** Get the dv1394 cip_d (timing denominator) property.
953 unsigned int dv_unit_get_cip_d( dv_unit unit )
955 return unit->dv1394_cip_d;
958 /** Set the dv1394 syt_offset (timestamp latency) property.
960 Stops and restarts the unit if playing.
963 void dv_unit_set_syt_offset( dv_unit unit, unsigned int syt_offset )
965 int restart = !unit->is_terminated;
966 int speed = (int)( dv_player_get_speed( dv_unit_get_dv_player(unit) ) * 1000.0 );
968 dv_unit_terminate( unit );
969 unit->dv1394_syt_offset = syt_offset;
971 dv_unit_play( unit, speed );
974 /** Set the dv1394 cip_n (timing numerator) property.
976 Stops and restarts the unit if playing.
979 void dv_unit_set_cip_n( dv_unit unit, unsigned int cip_n )
981 int restart = !unit->is_terminated;
982 int speed = (int)( dv_player_get_speed( dv_unit_get_dv_player(unit) ) * 1000.0 );
984 dv_unit_terminate( unit );
985 unit->dv1394_cip_n = cip_n;
987 dv_unit_play( unit, speed );
990 /** Set the dv1394 cip_d (timing denominator) property.
992 Stops and restarts the unit if playing.
995 void dv_unit_set_cip_d( dv_unit unit, unsigned int cip_d )
997 int restart = !unit->is_terminated;
998 int speed = (int)( dv_player_get_speed( dv_unit_get_dv_player(unit) ) * 1000.0 );
1000 dv_unit_terminate( unit );
1001 unit->dv1394_cip_d = cip_d;
1003 dv_unit_play( unit, speed );
1006 /** Terminate, but only the output thread and close dv1394.
1009 void dv_unit_suspend( dv_unit unit )
1011 if ( unit->is_terminated == 0 )
1013 unit->is_terminated = 1;
1014 unit->is_suspended = 1;
1015 dv_pump_terminate( unit->pump );
1016 dv_pump_flush( unit->pump );
1017 pthread_cancel( unit->out );
1019 if ( unit->dv1394_fd > -1 )
1021 close( unit->dv1394_fd );
1022 device_count[ dv_unit_get_port( unit ) ] --;
1024 unit->dv1394_fd = -1;
1025 dv_unit_status_communicate( unit );
1029 /** Restore unit on the bus, re-open dv1394, start playback if pump is running.
1032 void dv_unit_restore( dv_unit unit )
1037 if ( unit->raw1394 != NULL )
1038 raw1394_close( unit->raw1394 );
1040 node_id = raw1394_find_node( &(unit->raw1394), unit->guid );
1041 if ( node_id != -1 )
1043 unit->node_id = 0xffc0 | node_id;
1044 port = dv_unit_get_port( unit );
1046 unit->dv1394_fd = open( devices[ port ][ device_count[port] ], O_RDWR );
1047 if ( unit->dv1394_fd < 0 )
1049 dv1394d_log( LOG_ERR, "failed to open dv1394 device - %s\n", devices[ port ][ device_count[port] ] );
1050 dv_unit_close( unit );
1054 device_count[ port ] ++;
1055 break_p2p_connection( unit->raw1394, unit->node_id, unit->channel );
1056 if ( establish_p2p_connection( unit->raw1394, unit->node_id, (unsigned int *) &(unit->channel) ) )
1058 avc1394_vcr_record( unit->raw1394, unit->node_id );
1064 if ( unit->is_suspended == 1 )
1067 dv_frame frame = dv_pump_get_available_output( unit->pump );
1068 struct dv1394_init setup =
1070 api_version: DV1394_API_VERSION,
1071 channel: unit->channel,
1072 /* this only sets the *requested* size of the ringbuffer,
1074 n_frames: unit->n_frames,
1075 format: dv_frame_is_pal(frame) ? DV1394_PAL : DV1394_NTSC,
1076 cip_n: unit->dv1394_cip_n,
1077 cip_d: unit->dv1394_cip_d,
1078 syt_offset: unit->dv1394_syt_offset
1080 pthread_attr_t attr;
1082 dv_input_join_thread( unit->in );
1083 unit->is_terminated = 0;
1084 unit->is_suspended = 0;
1085 dv_pump_restart( unit->pump );
1086 dv_input_start_thread( unit->in );
1088 /* initialize dv1394 */
1089 retval = ioctl( unit->dv1394_fd, DV1394_INIT, &setup );
1093 pthread_attr_init( &attr );
1094 pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
1095 pthread_attr_setinheritsched( &attr, PTHREAD_INHERIT_SCHED );
1096 /* pthread_attr_setschedpolicy( &attr, SCHED_RR ); */
1097 pthread_create( &unit->out, &attr, output, unit );
1099 dv_unit_status_communicate( unit );