1 /*****************************************************************************
2 * linsys_hdsdi.c: HDSDI capture for Linear Systems/Computer Modules cards
3 *****************************************************************************
4 * Copyright (C) 2010-2011 VideoLAN
6 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
38 #include <vlc_common.h>
39 #include <vlc_plugin.h>
41 #include <vlc_input.h>
42 #include <vlc_access.h>
43 #include <vlc_demux.h>
47 #include "linsys_sdivideo.h"
48 #include "linsys_sdiaudio.h"
50 #undef HAVE_MMAP_SDIVIDEO
51 #undef HAVE_MMAP_SDIAUDIO
53 #define SDIVIDEO_DEVICE "/dev/sdivideorx%u"
54 #define SDIVIDEO_BUFFERS_FILE "/sys/class/sdivideo/sdivideorx%u/buffers"
55 #define SDIVIDEO_BUFSIZE_FILE "/sys/class/sdivideo/sdivideorx%u/bufsize"
56 #define SDIVIDEO_MODE_FILE "/sys/class/sdivideo/sdivideorx%u/mode"
57 #define SDIAUDIO_DEVICE "/dev/sdiaudiorx%u"
58 #define SDIAUDIO_BUFFERS_FILE "/sys/class/sdiaudio/sdiaudiorx%u/buffers"
59 #define SDIAUDIO_BUFSIZE_FILE "/sys/class/sdiaudio/sdiaudiorx%u/bufsize"
60 #define SDIAUDIO_SAMPLESIZE_FILE "/sys/class/sdiaudio/sdiaudiorx%u/sample_size"
61 #define SDIAUDIO_CHANNELS_FILE "/sys/class/sdiaudio/sdiaudiorx%u/channels"
63 #define READ_TIMEOUT 80000
64 #define CLOCK_GAP INT64_C(500000)
65 #define START_DATE INT64_C(4294967296)
69 /*****************************************************************************
71 *****************************************************************************/
72 #define LINK_TEXT N_("Link #")
73 #define LINK_LONGTEXT N_( \
74 "Allows you to set the desired link of the board for the capture (starting at 0)." )
75 #define VIDEO_TEXT N_("Video ID")
76 #define VIDEO_LONGTEXT N_( \
77 "Allows you to set the ES ID of the video." )
78 #define VIDEO_ASPECT_TEXT N_("Aspect ratio")
79 #define VIDEO_ASPECT_LONGTEXT N_( \
80 "Allows you to force the aspect ratio of the video." )
81 #define AUDIO_TEXT N_("Audio configuration")
82 #define AUDIO_LONGTEXT N_( \
83 "Allows you to set audio configuration (id=group,pair:id=group,pair...)." )
85 static int Open ( vlc_object_t * );
86 static void Close( vlc_object_t * );
89 set_description( _("HD-SDI Input") )
90 set_shortname( N_("HD-SDI") )
91 set_category( CAT_INPUT )
92 set_subcategory( SUBCAT_INPUT_ACCESS )
94 add_integer( "linsys-hdsdi-link", 0,
95 LINK_TEXT, LINK_LONGTEXT, true )
97 add_integer( "linsys-hdsdi-id-video", 0,
98 VIDEO_TEXT, VIDEO_LONGTEXT, true )
99 add_string( "linsys-hdsdi-aspect-ratio", "",
100 VIDEO_ASPECT_TEXT, VIDEO_ASPECT_LONGTEXT, true )
101 add_string( "linsys-hdsdi-audio", "0=1,1",
102 AUDIO_TEXT, AUDIO_LONGTEXT, true )
104 set_capability( "access_demux", 0 )
105 add_shortcut( "linsys-hdsdi" )
106 set_callbacks( Open, Close )
109 /*****************************************************************************
111 *****************************************************************************/
112 typedef struct hdsdi_audio_t
114 int i_channel; /* i_group * 2 + i_pair */
126 /* video device reader */
129 unsigned int i_standard;
130 #ifdef HAVE_MMAP_SDIVIDEO
131 uint8_t **pp_vbuffers;
132 unsigned int i_vbuffers, i_current_vbuffer;
134 unsigned int i_vbuffer_size;
136 /* audio device reader */
139 unsigned int i_sample_rate;
140 #ifdef HAVE_MMAP_SDIAUDIO
141 uint8_t **pp_abuffers;
142 unsigned int i_abuffers, i_current_abuffer;
144 unsigned int i_abuffer_size;
146 /* picture decoding */
147 unsigned int i_frame_rate, i_frame_rate_base;
148 unsigned int i_width, i_height, i_aspect, i_forced_aspect;
149 unsigned int i_vblock_size, i_ablock_size;
150 mtime_t i_next_vdate, i_next_adate;
155 es_out_id_t *p_es_video;
156 hdsdi_audio_t p_audios[MAX_AUDIOS];
159 static int Control( demux_t *, int, va_list );
160 static int Demux( demux_t * );
162 static int InitCapture( demux_t *p_demux );
163 static void CloseCapture( demux_t *p_demux );
164 static int Capture( demux_t *p_demux );
166 /*****************************************************************************
168 *****************************************************************************/
169 static int Open( vlc_object_t *p_this )
171 demux_t *p_demux = (demux_t *)p_this;
175 /* Fill p_demux field */
176 p_demux->pf_demux = Demux;
177 p_demux->pf_control = Control;
178 p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );
179 if( unlikely(!p_sys) )
183 char *psz_ar = var_InheritString( p_demux, "linsys-hdsdi-aspect-ratio" );
184 if ( psz_ar != NULL )
186 psz_parser = strchr( psz_ar, ':' );
189 *psz_parser++ = '\0';
190 p_sys->i_forced_aspect = p_sys->i_aspect =
191 strtol( psz_ar, NULL, 0 ) * VOUT_ASPECT_FACTOR
192 / strtol( psz_parser, NULL, 0 );
195 p_sys->i_forced_aspect = 0;
200 p_sys->i_id_video = var_InheritInteger( p_demux, "linsys-hdsdi-id-video" );
203 char *psz_string = psz_parser = var_InheritString( p_demux,
204 "linsys-hdsdi-audio" );
206 p_sys->i_max_channel = -1;
208 while ( psz_parser != NULL && *psz_parser )
210 int i_id, i_group, i_pair;
211 char *psz_next = strchr( psz_parser, '=' );
212 if ( psz_next != NULL )
215 i_id = strtol( psz_parser, NULL, 0 );
216 psz_parser = psz_next + 1;
221 psz_next = strchr( psz_parser, ':' );
222 if ( psz_next != NULL )
228 if ( sscanf( psz_parser, "%d,%d", &i_group, &i_pair ) == 2 )
230 p_sys->p_audios[i].i_channel = (i_group - 1) * 2 + (i_pair - 1);
231 if ( p_sys->p_audios[i].i_channel > p_sys->i_max_channel )
232 p_sys->i_max_channel = p_sys->p_audios[i].i_channel;
233 p_sys->p_audios[i].i_id = i_id;
237 msg_Warn( p_demux, "malformed audio configuration (%s)",
240 psz_parser = psz_next;
243 for ( ; i < MAX_AUDIOS; i++ )
244 p_sys->p_audios[i].i_channel = -1;
247 p_sys->i_link = var_InheritInteger( p_demux, "linsys-hdsdi-link" );
249 if( InitCapture( p_demux ) != VLC_SUCCESS )
258 /*****************************************************************************
260 *****************************************************************************/
261 static void Close( vlc_object_t *p_this )
263 demux_t *p_demux = (demux_t *)p_this;
264 demux_sys_t *p_sys = p_demux->p_sys;
266 CloseCapture( p_demux );
270 /*****************************************************************************
272 *****************************************************************************/
273 static int Demux( demux_t *p_demux )
275 return ( Capture( p_demux ) == VLC_SUCCESS );
278 /*****************************************************************************
280 *****************************************************************************/
281 static int Control( demux_t *p_demux, int i_query, va_list args )
288 /* Special for access_demux */
289 case DEMUX_CAN_PAUSE:
290 case DEMUX_CAN_CONTROL_PACE:
292 pb = (bool*)va_arg( args, bool * );
296 case DEMUX_GET_PTS_DELAY:
297 pi64 = (int64_t*)va_arg( args, int64_t * );
298 *pi64 = INT64_C(1000)
299 * var_InheritInteger( p_demux, "live-caching" );
302 /* TODO implement others */
308 /*****************************************************************************
309 * HDSDI syntax parsing stuff
310 *****************************************************************************/
311 #define U (uint16_t)(p_line[0])
312 #define Y1 (uint16_t)(p_line[1])
313 #define V (uint16_t)(p_line[2])
314 #define Y2 (uint16_t)(p_line[3])
316 /* For lines 0 [4] or 1 [4] */
317 static void Unpack01( const uint8_t *p_line, unsigned int i_size,
318 uint8_t *p_y, uint8_t *p_u, uint8_t *p_v )
320 const uint8_t *p_end = p_line + i_size;
322 while ( p_line < p_end )
332 /* For lines 2 [4] */
333 static void Unpack2( const uint8_t *p_line, unsigned int i_size,
334 uint8_t *p_y, uint8_t *p_u, uint8_t *p_v )
336 const uint8_t *p_end = p_line + i_size;
338 while ( p_line < p_end )
353 /* For lines 3 [4] */
354 static void Unpack3( const uint8_t *p_line, unsigned int i_size,
355 uint8_t *p_y, uint8_t *p_u, uint8_t *p_v )
357 const uint8_t *p_end = p_line + i_size;
359 while ( p_line < p_end )
379 static void SparseCopy( int16_t *p_dest, const int16_t *p_src,
380 size_t i_nb_samples, size_t i_offset, size_t i_stride )
382 for ( size_t i = 0; i < i_nb_samples; i++ )
384 p_dest[2 * i] = p_src[i_offset];
385 p_dest[2 * i + 1] = p_src[i_offset + 1];
386 i_offset += 2 * i_stride;
390 /*****************************************************************************
391 * Video & audio decoding
392 *****************************************************************************/
393 struct block_extension_t
395 bool b_progressive; /**< is it a progressive frame ? */
396 bool b_top_field_first; /**< which field is first */
397 unsigned int i_nb_fields; /**< # of displayed fields */
398 unsigned int i_aspect; /**< aspect ratio of frame */
401 static void StopDecode( demux_t *p_demux )
403 demux_sys_t *p_sys = p_demux->p_sys;
405 es_out_Del( p_demux->out, p_sys->p_es_video );
407 for ( int i = 0; i < MAX_AUDIOS; i++ )
409 hdsdi_audio_t *p_audio = &p_sys->p_audios[i];
410 if ( p_audio->i_channel != -1 && p_audio->p_es != NULL )
412 es_out_Del( p_demux->out, p_audio->p_es );
413 p_audio->p_es = NULL;
418 static int InitVideo( demux_t *p_demux )
420 demux_sys_t *p_sys = p_demux->p_sys;
423 msg_Dbg( p_demux, "found standard %d", p_sys->i_standard );
424 switch ( p_sys->i_standard )
426 case SDIVIDEO_CTL_BT_601_576I_50HZ:
428 p_sys->i_frame_rate = 25;
429 p_sys->i_frame_rate_base = 1;
430 p_sys->i_width = 720;
431 p_sys->i_height = 576;
432 p_sys->i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;
435 case SDIVIDEO_CTL_SMPTE_296M_720P_50HZ:
436 p_sys->i_frame_rate = 50;
437 p_sys->i_frame_rate_base = 1;
438 p_sys->i_width = 1280;
439 p_sys->i_height = 720;
440 p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
443 case SDIVIDEO_CTL_SMPTE_296M_720P_60HZ:
444 p_sys->i_frame_rate = 60;
445 p_sys->i_frame_rate_base = 1;
446 p_sys->i_width = 1280;
447 p_sys->i_height = 720;
448 p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
451 case SDIVIDEO_CTL_SMPTE_295M_1080I_50HZ:
452 case SDIVIDEO_CTL_SMPTE_274M_1080I_50HZ:
453 case SDIVIDEO_CTL_SMPTE_274M_1080PSF_25HZ:
454 /* 1080i50 or 1080p25 */
455 p_sys->i_frame_rate = 25;
456 p_sys->i_frame_rate_base = 1;
457 p_sys->i_width = 1920;
458 p_sys->i_height = 1080;
459 p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
462 case SDIVIDEO_CTL_SMPTE_274M_1080I_59_94HZ:
463 p_sys->i_frame_rate = 30000;
464 p_sys->i_frame_rate_base = 1001;
465 p_sys->i_width = 1920;
466 p_sys->i_height = 1080;
467 p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
470 case SDIVIDEO_CTL_SMPTE_274M_1080I_60HZ:
471 p_sys->i_frame_rate = 30;
472 p_sys->i_frame_rate_base = 1;
473 p_sys->i_width = 1920;
474 p_sys->i_height = 1080;
475 p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
479 msg_Err( p_demux, "unsupported standard %d", p_sys->i_standard );
483 p_sys->i_next_vdate = START_DATE;
484 p_sys->i_incr = 1000000 * p_sys->i_frame_rate_base / p_sys->i_frame_rate;
485 p_sys->i_vblock_size = p_sys->i_width * p_sys->i_height * 3 / 2
486 + sizeof(struct block_extension_t);
489 es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC('I','4','2','0') );
490 fmt.i_id = p_sys->i_id_video;
491 fmt.video.i_frame_rate = p_sys->i_frame_rate;
492 fmt.video.i_frame_rate_base = p_sys->i_frame_rate_base;
493 fmt.video.i_width = fmt.video.i_visible_width = p_sys->i_width;
494 fmt.video.i_height = fmt.video.i_visible_height = p_sys->i_height;
495 fmt.video.i_sar_num = p_sys->i_aspect * fmt.video.i_height
497 fmt.video.i_sar_den = VOUT_ASPECT_FACTOR;
498 p_sys->p_es_video = es_out_Add( p_demux->out, &fmt );
503 static int InitAudio( demux_t *p_demux )
505 demux_sys_t *p_sys = p_demux->p_sys;
508 for ( int i = 0; i < MAX_AUDIOS; i++ )
510 hdsdi_audio_t *p_audio = &p_sys->p_audios[i];
512 if ( p_audio->i_channel == -1 ) continue;
514 msg_Dbg( p_demux, "starting audio %u/%u rate:%u delay:%d",
515 1 + p_audio->i_channel / 2, 1 + (p_audio->i_channel % 2),
516 p_sys->i_sample_rate, p_audio->i_delay );
518 es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC('a','r','a','w') );
519 fmt.i_id = p_audio->i_id;
520 fmt.audio.i_channels = 2;
521 fmt.audio.i_original_channels =
522 fmt.audio.i_physical_channels = AOUT_CHANS_STEREO;
523 fmt.audio.i_rate = p_sys->i_sample_rate;
524 fmt.audio.i_bitspersample = 16;
525 fmt.audio.i_blockalign = fmt.audio.i_channels *
526 fmt.audio.i_bitspersample / 8;
527 fmt.i_bitrate = fmt.audio.i_channels * fmt.audio.i_rate *
528 fmt.audio.i_bitspersample;
529 p_audio->p_es = es_out_Add( p_demux->out, &fmt );
532 p_sys->i_next_adate = START_DATE;
533 p_sys->i_ablock_size = p_sys->i_sample_rate * 4 * p_sys->i_frame_rate_base / p_sys->i_frame_rate;
534 p_sys->i_aincr = 1000000. * p_sys->i_ablock_size / p_sys->i_sample_rate / 4;
539 static int HandleVideo( demux_t *p_demux, const uint8_t *p_buffer )
541 demux_sys_t *p_sys = p_demux->p_sys;
542 block_t *p_current_picture = block_Alloc( p_sys->i_vblock_size );
543 if( unlikely( !p_current_picture ) )
545 uint8_t *p_y = p_current_picture->p_buffer;
546 uint8_t *p_u = p_y + p_sys->i_width * p_sys->i_height;
547 uint8_t *p_v = p_u + p_sys->i_width * p_sys->i_height / 4;
548 unsigned int i_total_size = p_sys->i_width * 2;
549 unsigned int i_current_line;
550 struct block_extension_t ext;
552 for ( i_current_line = 0; i_current_line < p_sys->i_height;
555 bool b_field = (i_current_line >= p_sys->i_height / 2);
556 unsigned int i_field_line = b_field ?
557 i_current_line - (p_sys->i_height + 1) / 2 :
559 unsigned int i_real_line = b_field + i_field_line * 2;
560 const uint8_t *p_line = p_buffer + i_current_line * p_sys->i_width * 2;
562 if ( !(i_field_line % 2) && !b_field )
563 Unpack01( p_line, i_total_size,
564 p_y + p_sys->i_width * i_real_line,
565 p_u + (p_sys->i_width / 2) * (i_real_line / 2),
566 p_v + (p_sys->i_width / 2) * (i_real_line / 2) );
567 else if ( !(i_field_line % 2) )
568 Unpack01( p_line, i_total_size,
569 p_y + p_sys->i_width * i_real_line,
570 p_u + (p_sys->i_width / 2) * (i_real_line / 2 + 1),
571 p_v + (p_sys->i_width / 2) * (i_real_line / 2 + 1) );
573 Unpack2( p_line, i_total_size,
574 p_y + p_sys->i_width * i_real_line,
575 p_u + (p_sys->i_width / 2) * (i_real_line / 2 - 1),
576 p_v + (p_sys->i_width / 2) * (i_real_line / 2 - 1) );
578 Unpack3( p_line, i_total_size,
579 p_y + p_sys->i_width * i_real_line,
580 p_u + (p_sys->i_width / 2) * (i_real_line / 2),
581 p_v + (p_sys->i_width / 2) * (i_real_line / 2) );
584 /* FIXME: progressive formats ? */
585 ext.b_progressive = false;
587 ext.b_top_field_first = true;
588 ext.i_aspect = p_sys->i_forced_aspect ? p_sys->i_forced_aspect :
591 memcpy( &p_current_picture->p_buffer[p_sys->i_vblock_size
592 - sizeof(struct block_extension_t)],
593 &ext, sizeof(struct block_extension_t) );
595 p_current_picture->i_dts = p_current_picture->i_pts = p_sys->i_next_vdate;
596 es_out_Send( p_demux->out, p_sys->p_es_video, p_current_picture );
598 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_next_vdate );
599 p_sys->i_next_vdate += p_sys->i_incr;
603 static int HandleAudio( demux_t *p_demux, const uint8_t *p_buffer )
605 demux_sys_t *p_sys = p_demux->p_sys;
607 for ( int i = 0; i < MAX_AUDIOS; i++ )
609 hdsdi_audio_t *p_audio = &p_sys->p_audios[i];
610 if ( p_audio->i_channel != -1 && p_audio->p_es != NULL )
612 block_t *p_block = block_Alloc( p_sys->i_ablock_size );
613 if( unlikely( !p_block ) )
615 SparseCopy( (int16_t *)p_block->p_buffer, (const int16_t *)p_buffer,
616 p_sys->i_ablock_size / 4,
617 p_audio->i_channel * 2, p_sys->i_max_channel + 1 );
619 p_block->i_dts = p_block->i_pts
620 = p_sys->i_next_adate + (mtime_t)p_audio->i_delay
621 * INT64_C(1000000) / p_sys->i_sample_rate;
622 p_block->i_length = p_sys->i_aincr;
623 es_out_Send( p_demux->out, p_audio->p_es, p_block );
626 p_sys->i_next_adate += p_sys->i_aincr;
630 /*****************************************************************************
631 * Low-level device stuff
632 *****************************************************************************/
635 static ssize_t WriteULSysfs( const char *psz_fmt, unsigned int i_link,
638 char psz_file[MAXLEN], psz_data[MAXLEN];
642 snprintf( psz_file, sizeof(psz_file) -1, psz_fmt, i_link );
644 snprintf( psz_data, sizeof(psz_data) -1, "%u\n", i_buf );
646 if ( (i_fd = vlc_open( psz_file, O_WRONLY )) < 0 )
649 i_ret = write( i_fd, psz_data, strlen(psz_data) + 1 );
654 static int InitCapture( demux_t *p_demux )
656 demux_sys_t *p_sys = p_demux->p_sys;
657 #ifdef HAVE_MMAP_SDIVIDEO
658 const int i_page_size = getpagesize();
659 unsigned int i_bufmemsize;
661 char psz_vdev[MAXLEN];
663 snprintf( psz_vdev, sizeof(psz_vdev), SDIVIDEO_DEVICE, p_sys->i_link );
664 if ( (p_sys->i_vfd = vlc_open( psz_vdev, O_RDONLY ) ) < 0 )
666 msg_Err( p_demux, "couldn't open device %s", psz_vdev );
670 /* Wait for standard to settle down */
671 while ( vlc_object_alive(p_demux) )
673 struct pollfd pfd[1];
675 pfd[0].fd = p_sys->i_vfd;
676 pfd[0].events = POLLPRI;
678 if( poll( pfd, 1, READ_TIMEOUT ) < 0 )
681 if ( pfd[0].revents & POLLPRI )
685 if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_RXGETEVENTS, &i_val ) < 0 )
686 msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_RXGETEVENTS: %s",
687 vlc_strerror_c(errno) );
690 if ( i_val & SDIVIDEO_EVENT_RX_BUFFER )
691 msg_Warn( p_demux, "driver receive buffer queue overrun" );
692 if ( i_val & SDIVIDEO_EVENT_RX_FIFO )
693 msg_Warn( p_demux, "onboard receive FIFO overrun");
694 if ( i_val & SDIVIDEO_EVENT_RX_CARRIER )
695 msg_Warn( p_demux, "carrier status change");
696 if ( i_val & SDIVIDEO_EVENT_RX_DATA )
697 msg_Warn( p_demux, "data status change");
698 if ( i_val & SDIVIDEO_EVENT_RX_STD )
700 msg_Warn( p_demux, "standard status change");
706 if ( !vlc_object_alive(p_demux) )
708 close( p_sys->i_vfd );
712 if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_RXGETVIDSTATUS, &p_sys->i_standard )
715 msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_RXGETVIDSTATUS: %s",
716 vlc_strerror_c(errno) );
717 close( p_sys->i_vfd );
720 close( p_sys->i_vfd );
722 if ( InitVideo( p_demux ) != VLC_SUCCESS )
724 p_sys->i_vbuffer_size = p_sys->i_height * p_sys->i_width * 2;
726 /* First open the audio for synchronization reasons */
727 if ( p_sys->i_max_channel != -1 )
730 char psz_adev[MAXLEN];
732 snprintf( psz_adev, sizeof(psz_adev), SDIAUDIO_DEVICE, p_sys->i_link );
733 if ( (p_sys->i_afd = vlc_open( psz_adev, O_RDONLY ) ) < 0 )
735 msg_Err( p_demux, "couldn't open device %s", psz_adev );
739 if ( ioctl( p_sys->i_afd, SDIAUDIO_IOC_RXGETAUDRATE, &i_rate ) < 0 )
741 msg_Warn( p_demux, "couldn't SDIAUDIO_IOC_RXGETAUDRATE: %s",
742 vlc_strerror_c(errno) );
747 case SDIAUDIO_CTL_ASYNC_48_KHZ:
748 case SDIAUDIO_CTL_SYNC_48_KHZ:
749 p_sys->i_sample_rate = 48000;
751 case SDIAUDIO_CTL_ASYNC_44_1_KHZ:
752 case SDIAUDIO_CTL_SYNC_44_1_KHZ:
753 p_sys->i_sample_rate = 44100;
755 case SDIAUDIO_CTL_ASYNC_32_KHZ:
756 case SDIAUDIO_CTL_SYNC_32_KHZ:
757 p_sys->i_sample_rate = 32000;
759 case SDIAUDIO_CTL_ASYNC_96_KHZ:
760 case SDIAUDIO_CTL_SYNC_96_KHZ:
761 p_sys->i_sample_rate = 96000;
763 case SDIAUDIO_CTL_ASYNC_FREE_RUNNING:
764 case SDIAUDIO_CTL_SYNC_FREE_RUNNING:
766 msg_Err( p_demux, "unknown sample rate %u", i_rate );
769 close( p_sys->i_afd );
771 if ( InitAudio( p_demux ) != VLC_SUCCESS )
773 p_sys->i_abuffer_size = p_sys->i_ablock_size
774 * (1 + p_sys->i_max_channel);
776 /* Use 16-bit audio */
777 if ( WriteULSysfs( SDIAUDIO_SAMPLESIZE_FILE, p_sys->i_link,
778 SDIAUDIO_CTL_AUDSAMP_SZ_16 ) < 0 )
780 msg_Err( p_demux, "couldn't write file " SDIAUDIO_SAMPLESIZE_FILE,
785 if ( WriteULSysfs( SDIAUDIO_CHANNELS_FILE, p_sys->i_link,
786 (p_sys->i_max_channel + 1) * 2 ) < 0 )
788 msg_Err( p_demux, "couldn't write file " SDIAUDIO_CHANNELS_FILE,
793 #ifdef HAVE_MMAP_SDIAUDIO
794 if ( (p_sys->i_abuffers = ReadULSysfs( SDIAUDIO_BUFFERS_FILE,
795 p_sys->i_link )) < 0 )
797 msg_Err( p_demux, "couldn't read file " SDIAUDIO_BUFFERS_FILE,
801 p_sys->i_current_abuffer = 0;
804 if ( WriteULSysfs( SDIAUDIO_BUFSIZE_FILE, p_sys->i_link,
805 p_sys->i_abuffer_size ) < 0 )
807 msg_Err( p_demux, "couldn't write file " SDIAUDIO_BUFSIZE_FILE,
812 if ( (p_sys->i_afd = open( psz_adev, O_RDONLY ) ) < 0 )
814 msg_Err( p_demux, "couldn't open device %s", psz_adev );
818 #ifdef HAVE_MMAP_SDIAUDIO
819 i_bufmemsize = ((p_sys->i_abuffer_size + i_page_size - 1) / i_page_size)
821 p_sys->pp_abuffers = malloc( p_sys->i_abuffers * sizeof(uint8_t *) );
822 if( unlikely( !p_sys->pp_abuffers ) )
824 for ( unsigned int i = 0; i < p_sys->i_abuffers; i++ )
826 if ( (p_sys->pp_abuffers[i] = mmap( NULL, p_sys->i_abuffer_size,
827 PROT_READ, MAP_SHARED, p_sys->i_afd,
828 i * i_bufmemsize )) == MAP_FAILED )
830 msg_Err( p_demux, "couldn't mmap(%d): %s", i,
831 vlc_strerror_c(errno) );
838 /* Use 8-bit video */
839 if ( WriteULSysfs( SDIVIDEO_MODE_FILE, p_sys->i_link,
840 SDIVIDEO_CTL_MODE_UYVY ) < 0 )
842 msg_Err( p_demux, "couldn't write file " SDIVIDEO_MODE_FILE,
847 if ( WriteULSysfs( SDIVIDEO_BUFFERS_FILE, p_sys->i_link,
850 msg_Err( p_demux, "couldn't write file " SDIVIDEO_BUFFERS_FILE,
854 #ifdef HAVE_MMAP_SDIVIDEO
855 p_sys->i_vbuffers = NB_VBUFFERS;
858 if ( WriteULSysfs( SDIVIDEO_BUFSIZE_FILE, p_sys->i_link,
859 p_sys->i_vbuffer_size ) < 0 )
861 msg_Err( p_demux, "couldn't write file " SDIVIDEO_BUFSIZE_FILE,
866 if ( (p_sys->i_vfd = open( psz_vdev, O_RDONLY ) ) < 0 )
868 msg_Err( p_demux, "couldn't open device %s", psz_vdev );
872 #ifdef HAVE_MMAP_SDIVIDEO
873 p_sys->i_current_vbuffer = 0;
874 i_bufmemsize = ((p_sys->i_vbuffer_size + i_page_size - 1) / i_page_size)
876 p_sys->pp_vbuffers = malloc( p_sys->i_vbuffers * sizeof(uint8_t *) );
877 if( unlikely( !p_sys->pp_vbuffers ) )
879 for ( unsigned int i = 0; i < p_sys->i_vbuffers; i++ )
881 if ( (p_sys->pp_vbuffers[i] = mmap( NULL, p_sys->i_vbuffer_size,
882 PROT_READ, MAP_SHARED, p_sys->i_vfd,
883 i * i_bufmemsize )) == MAP_FAILED )
885 msg_Err( p_demux, "couldn't mmap(%d): %s", i,
886 vlc_strerror_c(errno) );
895 static void CloseCapture( demux_t *p_demux )
897 demux_sys_t *p_sys = p_demux->p_sys;
899 StopDecode( p_demux );
900 #ifdef HAVE_MMAP_SDIVIDEO
901 for ( unsigned int i = 0; i < p_sys->i_vbuffers; i++ )
902 munmap( p_sys->pp_vbuffers[i], p_sys->i_vbuffer_size );
903 free( p_sys->pp_vbuffers );
905 close( p_sys->i_vfd );
906 if ( p_sys->i_max_channel != -1 )
908 #ifdef HAVE_MMAP_SDIAUDIO
909 for ( unsigned int i = 0; i < p_sys->i_abuffers; i++ )
910 munmap( p_sys->pp_abuffers[i], p_sys->i_abuffer_size );
911 free( p_sys->pp_abuffers );
913 close( p_sys->i_afd );
917 static int Capture( demux_t *p_demux )
919 demux_sys_t *p_sys = p_demux->p_sys;
920 struct pollfd pfd[2];
922 pfd[0].fd = p_sys->i_vfd;
923 pfd[0].events = POLLIN | POLLPRI;
924 if ( p_sys->i_max_channel != -1 )
926 pfd[1].fd = p_sys->i_afd;
927 pfd[1].events = POLLIN | POLLPRI;
930 if( poll( pfd, 1 + (p_sys->i_max_channel != -1), READ_TIMEOUT ) < 0 )
933 if ( pfd[0].revents & POLLPRI )
937 if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_RXGETEVENTS, &i_val ) < 0 )
938 msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_RXGETEVENTS: %s",
939 vlc_strerror_c(errno) );
942 if ( i_val & SDIVIDEO_EVENT_RX_BUFFER )
943 msg_Warn( p_demux, "driver receive buffer queue overrun" );
944 if ( i_val & SDIVIDEO_EVENT_RX_FIFO )
945 msg_Warn( p_demux, "onboard receive FIFO overrun");
946 if ( i_val & SDIVIDEO_EVENT_RX_CARRIER )
947 msg_Warn( p_demux, "carrier status change");
948 if ( i_val & SDIVIDEO_EVENT_RX_DATA )
949 msg_Warn( p_demux, "data status change");
950 if ( i_val & SDIVIDEO_EVENT_RX_STD )
951 msg_Warn( p_demux, "standard status change");
954 p_sys->i_next_adate += CLOCK_GAP;
955 p_sys->i_next_vdate += CLOCK_GAP;
958 if ( p_sys->i_max_channel != -1 && pfd[1].revents & POLLPRI )
962 if ( ioctl( p_sys->i_afd, SDIAUDIO_IOC_RXGETEVENTS, &i_val ) < 0 )
963 msg_Warn( p_demux, "couldn't SDIAUDIO_IOC_RXGETEVENTS: %s",
964 vlc_strerror_c(errno) );
967 if ( i_val & SDIAUDIO_EVENT_RX_BUFFER )
968 msg_Warn( p_demux, "driver receive buffer queue overrun" );
969 if ( i_val & SDIAUDIO_EVENT_RX_FIFO )
970 msg_Warn( p_demux, "onboard receive FIFO overrun");
971 if ( i_val & SDIAUDIO_EVENT_RX_CARRIER )
972 msg_Warn( p_demux, "carrier status change");
973 if ( i_val & SDIAUDIO_EVENT_RX_DATA )
974 msg_Warn( p_demux, "data status change");
977 p_sys->i_next_adate += CLOCK_GAP;
978 p_sys->i_next_vdate += CLOCK_GAP;
981 if ( pfd[0].revents & POLLIN )
983 #ifdef HAVE_MMAP_SDIVIDEO
984 if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_DQBUF, p_sys->i_current_vbuffer )
987 msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_DQBUF: %s",
988 vlc_strerror_c(errno) );
992 if( HandleVideo( p_demux, p_sys->pp_vbuffers[p_sys->i_current_vbuffer] ) != VLC_SUCCESS )
995 if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_QBUF, p_sys->i_current_vbuffer )
998 msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_QBUF: %s",
999 vlc_strerror_c(errno) );
1000 return VLC_EGENERIC;
1003 p_sys->i_current_vbuffer++;
1004 p_sys->i_current_vbuffer %= p_sys->i_vbuffers;
1006 uint8_t *p_buffer = malloc( p_sys->i_vbuffer_size );
1007 if( unlikely( !p_buffer ) )
1010 if ( read( p_sys->i_vfd, p_buffer, p_sys->i_vbuffer_size ) < 0 )
1012 msg_Warn( p_demux, "couldn't read: %s", vlc_strerror_c(errno) );
1014 return VLC_EGENERIC;
1017 if( HandleVideo( p_demux, p_buffer ) != VLC_SUCCESS )
1026 if ( p_sys->i_max_channel != -1 && pfd[1].revents & POLLIN )
1028 #ifdef HAVE_MMAP_SDIAUDIO
1029 if ( ioctl( p_sys->i_afd, SDIAUDIO_IOC_DQBUF, p_sys->i_current_abuffer )
1032 msg_Warn( p_demux, "couldn't SDIAUDIO_IOC_DQBUF: %s",
1033 vlc_strerror_c(errno) );
1034 return VLC_EGENERIC;
1037 if( HandleAudio( p_demux, p_sys->pp_abuffers[p_sys->i_current_abuffer] ) != VLC_SUCCESS )
1040 if ( ioctl( p_sys->i_afd, SDIAUDIO_IOC_QBUF, p_sys->i_current_abuffer )
1043 msg_Warn( p_demux, "couldn't SDIAUDIO_IOC_QBUF: %s",
1044 vlc_strerror_c(errno) );
1045 return VLC_EGENERIC;
1048 p_sys->i_current_abuffer++;
1049 p_sys->i_current_abuffer %= p_sys->i_abuffers;
1051 uint8_t *p_buffer = malloc( p_sys->i_abuffer_size );
1052 if( unlikely( !p_buffer ) )
1055 if ( read( p_sys->i_afd, p_buffer, p_sys->i_abuffer_size ) < 0 )
1057 msg_Warn( p_demux, "couldn't read: %s", vlc_strerror_c(errno) );
1059 return VLC_EGENERIC;
1062 if( HandleAudio( p_demux, p_buffer ) != VLC_SUCCESS )