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
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 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 General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, 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 CACHING_TEXT N_("Caching value in ms")
73 #define CACHING_LONGTEXT N_( \
74 "Allows you to modify the default caching value for hdsdi capture " \
75 "streams. This value should be set in millisecond units." )
76 #define LINK_TEXT N_("Link #")
77 #define LINK_LONGTEXT N_( \
78 "Allows you to set the desired link of the board for the capture (starting at 0)." )
79 #define VIDEO_TEXT N_("Video ID")
80 #define VIDEO_LONGTEXT N_( \
81 "Allows you to set the ES ID of the video." )
82 #define VIDEO_ASPECT_TEXT N_("Aspect ratio")
83 #define VIDEO_ASPECT_LONGTEXT N_( \
84 "Allows you to force the aspect ratio of the video." )
85 #define AUDIO_TEXT N_("Audio configuration")
86 #define AUDIO_LONGTEXT N_( \
87 "Allows you to set audio configuration (id=group,pair:id=group,pair...)." )
89 static int Open ( vlc_object_t * );
90 static void Close( vlc_object_t * );
93 set_description( _("HD-SDI Input") )
94 set_shortname( N_("HD-SDI") )
95 set_category( CAT_INPUT )
96 set_subcategory( SUBCAT_INPUT_ACCESS )
98 add_integer( "linsys-hdsdi-caching", DEFAULT_PTS_DELAY / 1000,
99 CACHING_TEXT, CACHING_LONGTEXT, true )
100 add_integer( "linsys-hdsdi-link", 0,
101 LINK_TEXT, LINK_LONGTEXT, true )
103 add_integer( "linsys-hdsdi-id-video", 0,
104 VIDEO_TEXT, VIDEO_LONGTEXT, true )
105 add_string( "linsys-hdsdi-aspect-ratio", "",
106 VIDEO_ASPECT_TEXT, VIDEO_ASPECT_LONGTEXT, true )
107 add_string( "linsys-hdsdi-audio", "0=1,1",
108 AUDIO_TEXT, AUDIO_LONGTEXT, true )
110 set_capability( "access_demux", 0 )
111 add_shortcut( "linsys-hdsdi" )
112 set_callbacks( Open, Close )
115 /*****************************************************************************
117 *****************************************************************************/
118 typedef struct hdsdi_audio_t
120 int i_channel; /* i_group * 2 + i_pair */
132 /* video device reader */
135 unsigned int i_standard;
136 #ifdef HAVE_MMAP_SDIVIDEO
137 uint8_t **pp_vbuffers;
138 unsigned int i_vbuffers, i_current_vbuffer;
140 unsigned int i_vbuffer_size;
142 /* audio device reader */
145 unsigned int i_sample_rate;
146 #ifdef HAVE_MMAP_SDIAUDIO
147 uint8_t **pp_abuffers;
148 unsigned int i_abuffers, i_current_abuffer;
150 unsigned int i_abuffer_size;
152 /* picture decoding */
153 unsigned int i_frame_rate, i_frame_rate_base;
154 unsigned int i_width, i_height, i_aspect, i_forced_aspect;
155 unsigned int i_vblock_size, i_ablock_size;
156 mtime_t i_next_vdate, i_next_adate;
161 es_out_id_t *p_es_video;
162 hdsdi_audio_t p_audios[MAX_AUDIOS];
165 static int Control( demux_t *, int, va_list );
166 static int Demux( demux_t * );
168 static int InitCapture( demux_t *p_demux );
169 static void CloseCapture( demux_t *p_demux );
170 static int Capture( demux_t *p_demux );
172 /*****************************************************************************
174 *****************************************************************************/
175 static int Open( vlc_object_t *p_this )
177 demux_t *p_demux = (demux_t *)p_this;
181 /* Fill p_demux field */
182 p_demux->pf_demux = Demux;
183 p_demux->pf_control = Control;
184 p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );
185 if( unlikely(!p_sys) )
189 char *psz_ar = var_InheritString( p_demux, "linsys-hdsdi-aspect-ratio" );
190 if ( psz_ar != NULL )
192 psz_parser = strchr( psz_ar, ':' );
195 *psz_parser++ = '\0';
196 p_sys->i_forced_aspect = p_sys->i_aspect =
197 strtol( psz_ar, NULL, 0 ) * VOUT_ASPECT_FACTOR
198 / strtol( psz_parser, NULL, 0 );
201 p_sys->i_forced_aspect = 0;
206 p_sys->i_id_video = var_InheritInteger( p_demux, "linsys-hdsdi-id-video" );
209 char *psz_string = psz_parser = var_InheritString( p_demux,
210 "linsys-hdsdi-audio" );
212 p_sys->i_max_channel = -1;
214 while ( psz_parser != NULL && *psz_parser )
216 int i_id, i_group, i_pair;
217 char *psz_next = strchr( psz_parser, '=' );
218 if ( psz_next != NULL )
221 i_id = strtol( psz_parser, NULL, 0 );
222 psz_parser = psz_next + 1;
227 psz_next = strchr( psz_parser, ':' );
228 if ( psz_next != NULL )
234 if ( sscanf( psz_parser, "%d,%d", &i_group, &i_pair ) == 2 )
236 p_sys->p_audios[i].i_channel = (i_group - 1) * 2 + (i_pair - 1);
237 if ( p_sys->p_audios[i].i_channel > p_sys->i_max_channel )
238 p_sys->i_max_channel = p_sys->p_audios[i].i_channel;
239 p_sys->p_audios[i].i_id = i_id;
243 msg_Warn( p_demux, "malformed audio configuration (%s)",
246 psz_parser = psz_next;
249 for ( ; i < MAX_AUDIOS; i++ )
250 p_sys->p_audios[i].i_channel = -1;
253 /* Update default_pts to a suitable value for hdsdi access */
254 var_Create( p_demux, "linsys-hdsdi-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
256 p_sys->i_link = var_InheritInteger( p_demux, "linsys-hdsdi-link" );
258 if( InitCapture( p_demux ) != VLC_SUCCESS )
267 /*****************************************************************************
269 *****************************************************************************/
270 static void Close( vlc_object_t *p_this )
272 demux_t *p_demux = (demux_t *)p_this;
273 demux_sys_t *p_sys = p_demux->p_sys;
275 CloseCapture( p_demux );
279 /*****************************************************************************
281 *****************************************************************************/
282 static int Demux( demux_t *p_demux )
284 return ( Capture( p_demux ) == VLC_SUCCESS );
287 /*****************************************************************************
289 *****************************************************************************/
290 static int Control( demux_t *p_demux, int i_query, va_list args )
297 /* Special for access_demux */
298 case DEMUX_CAN_PAUSE:
299 case DEMUX_CAN_CONTROL_PACE:
301 pb = (bool*)va_arg( args, bool * );
305 case DEMUX_GET_PTS_DELAY:
306 pi64 = (int64_t*)va_arg( args, int64_t * );
307 *pi64 = (int64_t)var_GetInteger( p_demux, "linsys-hdsdi-caching" ) *1000;
310 /* TODO implement others */
316 /*****************************************************************************
317 * HDSDI syntax parsing stuff
318 *****************************************************************************/
319 #define U (uint16_t)(p_line[0])
320 #define Y1 (uint16_t)(p_line[1])
321 #define V (uint16_t)(p_line[2])
322 #define Y2 (uint16_t)(p_line[3])
324 /* For lines 0 [4] or 1 [4] */
325 static void Unpack01( const uint8_t *p_line, unsigned int i_size,
326 uint8_t *p_y, uint8_t *p_u, uint8_t *p_v )
328 const uint8_t *p_end = p_line + i_size;
330 while ( p_line < p_end )
340 /* For lines 2 [4] */
341 static void Unpack2( const uint8_t *p_line, unsigned int i_size,
342 uint8_t *p_y, uint8_t *p_u, uint8_t *p_v )
344 const uint8_t *p_end = p_line + i_size;
346 while ( p_line < p_end )
361 /* For lines 3 [4] */
362 static void Unpack3( const uint8_t *p_line, unsigned int i_size,
363 uint8_t *p_y, uint8_t *p_u, uint8_t *p_v )
365 const uint8_t *p_end = p_line + i_size;
367 while ( p_line < p_end )
387 static void SparseCopy( int16_t *p_dest, const int16_t *p_src,
388 size_t i_nb_samples, size_t i_offset, size_t i_stride )
390 for ( size_t i = 0; i < i_nb_samples; i++ )
392 p_dest[2 * i] = p_src[i_offset];
393 p_dest[2 * i + 1] = p_src[i_offset + 1];
394 i_offset += 2 * i_stride;
398 /*****************************************************************************
399 * Video & audio decoding
400 *****************************************************************************/
401 struct block_extension_t
403 bool b_progressive; /**< is it a progressive frame ? */
404 bool b_top_field_first; /**< which field is first */
405 unsigned int i_nb_fields; /**< # of displayed fields */
406 unsigned int i_aspect; /**< aspect ratio of frame */
409 static void StopDecode( demux_t *p_demux )
411 demux_sys_t *p_sys = p_demux->p_sys;
413 es_out_Del( p_demux->out, p_sys->p_es_video );
415 for ( int i = 0; i < MAX_AUDIOS; i++ )
417 hdsdi_audio_t *p_audio = &p_sys->p_audios[i];
418 if ( p_audio->i_channel != -1 && p_audio->p_es != NULL )
420 es_out_Del( p_demux->out, p_audio->p_es );
421 p_audio->p_es = NULL;
426 static int InitVideo( demux_t *p_demux )
428 demux_sys_t *p_sys = p_demux->p_sys;
431 msg_Dbg( p_demux, "found standard %d", p_sys->i_standard );
432 switch ( p_sys->i_standard )
434 case SDIVIDEO_CTL_BT_601_576I_50HZ:
436 p_sys->i_frame_rate = 25;
437 p_sys->i_frame_rate_base = 1;
438 p_sys->i_width = 720;
439 p_sys->i_height = 576;
440 p_sys->i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;
443 case SDIVIDEO_CTL_SMPTE_296M_720P_50HZ:
444 p_sys->i_frame_rate = 50;
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_296M_720P_60HZ:
452 p_sys->i_frame_rate = 60;
453 p_sys->i_frame_rate_base = 1;
454 p_sys->i_width = 1280;
455 p_sys->i_height = 720;
456 p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
459 case SDIVIDEO_CTL_SMPTE_295M_1080I_50HZ:
460 case SDIVIDEO_CTL_SMPTE_274M_1080I_50HZ:
461 case SDIVIDEO_CTL_SMPTE_274M_1080PSF_25HZ:
462 /* 1080i50 or 1080p25 */
463 p_sys->i_frame_rate = 25;
464 p_sys->i_frame_rate_base = 1;
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_59_94HZ:
471 p_sys->i_frame_rate = 30000;
472 p_sys->i_frame_rate_base = 1001;
473 p_sys->i_width = 1920;
474 p_sys->i_height = 1080;
475 p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
478 case SDIVIDEO_CTL_SMPTE_274M_1080I_60HZ:
479 p_sys->i_frame_rate = 30;
480 p_sys->i_frame_rate_base = 1;
481 p_sys->i_width = 1920;
482 p_sys->i_height = 1080;
483 p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
487 msg_Err( p_demux, "unsupported standard %d", p_sys->i_standard );
491 p_sys->i_next_vdate = START_DATE;
492 p_sys->i_incr = 1000000 * p_sys->i_frame_rate_base / p_sys->i_frame_rate;
493 p_sys->i_vblock_size = p_sys->i_width * p_sys->i_height * 3 / 2
494 + sizeof(struct block_extension_t);
497 es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC('I','4','2','0') );
498 fmt.i_id = p_sys->i_id_video;
499 fmt.video.i_frame_rate = p_sys->i_frame_rate;
500 fmt.video.i_frame_rate_base = p_sys->i_frame_rate_base;
501 fmt.video.i_width = fmt.video.i_visible_width = p_sys->i_width;
502 fmt.video.i_height = fmt.video.i_visible_height = p_sys->i_height;
503 fmt.video.i_sar_num = p_sys->i_aspect * fmt.video.i_height
505 fmt.video.i_sar_den = VOUT_ASPECT_FACTOR;
506 p_sys->p_es_video = es_out_Add( p_demux->out, &fmt );
511 static int InitAudio( demux_t *p_demux )
513 demux_sys_t *p_sys = p_demux->p_sys;
516 for ( int i = 0; i < MAX_AUDIOS; i++ )
518 hdsdi_audio_t *p_audio = &p_sys->p_audios[i];
520 if ( p_audio->i_channel == -1 ) continue;
522 msg_Dbg( p_demux, "starting audio %u/%u rate:%u delay:%d",
523 1 + p_audio->i_channel / 2, 1 + (p_audio->i_channel % 2),
524 p_sys->i_sample_rate, p_audio->i_delay );
526 es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC('a','r','a','w') );
527 fmt.i_id = p_audio->i_id;
528 fmt.audio.i_channels = 2;
529 fmt.audio.i_physical_channels = 6;
530 fmt.audio.i_original_channels = 6;
531 fmt.audio.i_rate = p_sys->i_sample_rate;
532 fmt.audio.i_bitspersample = 16;
533 fmt.audio.i_blockalign = fmt.audio.i_channels *
534 fmt.audio.i_bitspersample / 8;
535 fmt.i_bitrate = fmt.audio.i_channels * fmt.audio.i_rate *
536 fmt.audio.i_bitspersample;
537 p_audio->p_es = es_out_Add( p_demux->out, &fmt );
540 p_sys->i_next_adate = START_DATE;
541 p_sys->i_ablock_size = p_sys->i_sample_rate * 4 * p_sys->i_frame_rate_base / p_sys->i_frame_rate;
542 p_sys->i_aincr = 1000000. * p_sys->i_ablock_size / p_sys->i_sample_rate / 4;
547 static int HandleVideo( demux_t *p_demux, const uint8_t *p_buffer )
549 demux_sys_t *p_sys = p_demux->p_sys;
550 block_t *p_current_picture = block_New( p_demux, p_sys->i_vblock_size );
551 if( unlikely( !p_current_picture ) )
553 uint8_t *p_y = p_current_picture->p_buffer;
554 uint8_t *p_u = p_y + p_sys->i_width * p_sys->i_height;
555 uint8_t *p_v = p_u + p_sys->i_width * p_sys->i_height / 4;
556 unsigned int i_total_size = p_sys->i_width * 2;
557 unsigned int i_current_line;
558 struct block_extension_t ext;
560 for ( i_current_line = 0; i_current_line < p_sys->i_height;
563 bool b_field = (i_current_line >= p_sys->i_height / 2);
564 unsigned int i_field_line = b_field ?
565 i_current_line - (p_sys->i_height + 1) / 2 :
567 unsigned int i_real_line = b_field + i_field_line * 2;
568 const uint8_t *p_line = p_buffer + i_current_line * p_sys->i_width * 2;
570 if ( !(i_field_line % 2) && !b_field )
571 Unpack01( p_line, i_total_size,
572 p_y + p_sys->i_width * i_real_line,
573 p_u + (p_sys->i_width / 2) * (i_real_line / 2),
574 p_v + (p_sys->i_width / 2) * (i_real_line / 2) );
575 else if ( !(i_field_line % 2) )
576 Unpack01( p_line, i_total_size,
577 p_y + p_sys->i_width * i_real_line,
578 p_u + (p_sys->i_width / 2) * (i_real_line / 2 + 1),
579 p_v + (p_sys->i_width / 2) * (i_real_line / 2 + 1) );
581 Unpack2( p_line, i_total_size,
582 p_y + p_sys->i_width * i_real_line,
583 p_u + (p_sys->i_width / 2) * (i_real_line / 2 - 1),
584 p_v + (p_sys->i_width / 2) * (i_real_line / 2 - 1) );
586 Unpack3( p_line, i_total_size,
587 p_y + p_sys->i_width * i_real_line,
588 p_u + (p_sys->i_width / 2) * (i_real_line / 2),
589 p_v + (p_sys->i_width / 2) * (i_real_line / 2) );
592 /* FIXME: progressive formats ? */
593 ext.b_progressive = false;
595 ext.b_top_field_first = true;
596 ext.i_aspect = p_sys->i_forced_aspect ? p_sys->i_forced_aspect :
599 memcpy( &p_current_picture->p_buffer[p_sys->i_vblock_size
600 - sizeof(struct block_extension_t)],
601 &ext, sizeof(struct block_extension_t) );
603 p_current_picture->i_dts = p_current_picture->i_pts = p_sys->i_next_vdate;
604 es_out_Send( p_demux->out, p_sys->p_es_video, p_current_picture );
606 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_next_vdate );
607 p_sys->i_next_vdate += p_sys->i_incr;
611 static int HandleAudio( demux_t *p_demux, const uint8_t *p_buffer )
613 demux_sys_t *p_sys = p_demux->p_sys;
615 for ( int i = 0; i < MAX_AUDIOS; i++ )
617 hdsdi_audio_t *p_audio = &p_sys->p_audios[i];
618 if ( p_audio->i_channel != -1 && p_audio->p_es != NULL )
620 block_t *p_block = block_New( p_demux, p_sys->i_ablock_size );
621 if( unlikely( !p_block ) )
623 SparseCopy( (int16_t *)p_block->p_buffer, (const int16_t *)p_buffer,
624 p_sys->i_ablock_size / 4,
625 p_audio->i_channel * 2, p_sys->i_max_channel + 1 );
627 p_block->i_dts = p_block->i_pts
628 = p_sys->i_next_adate + (mtime_t)p_audio->i_delay
629 * INT64_C(1000000) / p_sys->i_sample_rate;
630 p_block->i_length = p_sys->i_aincr;
631 es_out_Send( p_demux->out, p_audio->p_es, p_block );
634 p_sys->i_next_adate += p_sys->i_aincr;
638 /*****************************************************************************
639 * Low-level device stuff
640 *****************************************************************************/
643 static ssize_t WriteULSysfs( const char *psz_fmt, unsigned int i_link,
646 char psz_file[MAXLEN], psz_data[MAXLEN];
650 snprintf( psz_file, sizeof(psz_file) -1, psz_fmt, i_link );
652 snprintf( psz_data, sizeof(psz_data) -1, "%u\n", i_buf );
654 if ( (i_fd = vlc_open( psz_file, O_WRONLY )) < 0 )
657 i_ret = write( i_fd, psz_data, strlen(psz_data) + 1 );
662 static int InitCapture( demux_t *p_demux )
664 demux_sys_t *p_sys = p_demux->p_sys;
665 #ifdef HAVE_MMAP_SDIVIDEO
666 const int i_page_size = getpagesize();
667 unsigned int i_bufmemsize;
669 char psz_vdev[MAXLEN];
671 snprintf( psz_vdev, sizeof(psz_vdev), SDIVIDEO_DEVICE, p_sys->i_link );
672 psz_vdev[sizeof(psz_vdev) - 1] = '\0';
673 if ( (p_sys->i_vfd = vlc_open( psz_vdev, O_RDONLY ) ) < 0 )
675 msg_Err( p_demux, "couldn't open device %s", psz_vdev );
679 /* Wait for standard to settle down */
680 while ( !p_demux->b_die )
682 struct pollfd pfd[1];
684 pfd[0].fd = p_sys->i_vfd;
685 pfd[0].events = POLLIN | POLLPRI;
687 if ( poll( pfd, 1, READ_TIMEOUT ) < 0 )
689 msg_Warn( p_demux, "couldn't poll(): %m" );
690 close( p_sys->i_vfd );
694 if ( pfd[0].revents & POLLPRI )
698 if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_RXGETEVENTS, &i_val ) < 0 )
699 msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_RXGETEVENTS %m" );
702 if ( i_val & SDIVIDEO_EVENT_RX_BUFFER )
703 msg_Warn( p_demux, "driver receive buffer queue overrun" );
704 if ( i_val & SDIVIDEO_EVENT_RX_FIFO )
705 msg_Warn( p_demux, "onboard receive FIFO overrun");
706 if ( i_val & SDIVIDEO_EVENT_RX_CARRIER )
707 msg_Warn( p_demux, "carrier status change");
708 if ( i_val & SDIVIDEO_EVENT_RX_DATA )
709 msg_Warn( p_demux, "data status change");
710 if ( i_val & SDIVIDEO_EVENT_RX_STD )
712 msg_Warn( p_demux, "standard status change");
718 if ( p_demux->b_die )
720 close( p_sys->i_vfd );
724 if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_RXGETVIDSTATUS, &p_sys->i_standard )
727 msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_RXGETVIDSTATUS %m" );
728 close( p_sys->i_vfd );
731 close( p_sys->i_vfd );
733 if ( InitVideo( p_demux ) != VLC_SUCCESS )
735 p_sys->i_vbuffer_size = p_sys->i_height * p_sys->i_width * 2;
737 /* First open the audio for synchronization reasons */
738 if ( p_sys->i_max_channel != -1 )
741 char psz_adev[MAXLEN];
743 snprintf( psz_adev, sizeof(psz_adev), SDIAUDIO_DEVICE, p_sys->i_link );
744 psz_adev[sizeof(psz_adev) - 1] = '\0';
745 if ( (p_sys->i_afd = vlc_open( psz_adev, O_RDONLY ) ) < 0 )
747 msg_Err( p_demux, "couldn't open device %s", psz_adev );
751 if ( ioctl( p_sys->i_afd, SDIAUDIO_IOC_RXGETAUDRATE, &i_rate ) < 0 )
753 msg_Warn( p_demux, "couldn't SDIAUDIO_IOC_RXGETAUDRATE %m" );
758 case SDIAUDIO_CTL_ASYNC_48_KHZ:
759 case SDIAUDIO_CTL_SYNC_48_KHZ:
760 p_sys->i_sample_rate = 48000;
762 case SDIAUDIO_CTL_ASYNC_44_1_KHZ:
763 case SDIAUDIO_CTL_SYNC_44_1_KHZ:
764 p_sys->i_sample_rate = 44100;
766 case SDIAUDIO_CTL_ASYNC_32_KHZ:
767 case SDIAUDIO_CTL_SYNC_32_KHZ:
768 p_sys->i_sample_rate = 32000;
770 case SDIAUDIO_CTL_ASYNC_96_KHZ:
771 case SDIAUDIO_CTL_SYNC_96_KHZ:
772 p_sys->i_sample_rate = 96000;
774 case SDIAUDIO_CTL_ASYNC_FREE_RUNNING:
775 case SDIAUDIO_CTL_SYNC_FREE_RUNNING:
777 msg_Err( p_demux, "unknown sample rate %u", i_rate );
780 close( p_sys->i_afd );
782 if ( InitAudio( p_demux ) != VLC_SUCCESS )
784 p_sys->i_abuffer_size = p_sys->i_ablock_size
785 * (1 + p_sys->i_max_channel);
787 /* Use 16-bit audio */
788 if ( WriteULSysfs( SDIAUDIO_SAMPLESIZE_FILE, p_sys->i_link,
789 SDIAUDIO_CTL_AUDSAMP_SZ_16 ) < 0 )
791 msg_Err( p_demux, "couldn't write file " SDIAUDIO_SAMPLESIZE_FILE,
796 if ( WriteULSysfs( SDIAUDIO_CHANNELS_FILE, p_sys->i_link,
797 (p_sys->i_max_channel + 1) * 2 ) < 0 )
799 msg_Err( p_demux, "couldn't write file " SDIAUDIO_CHANNELS_FILE,
804 #ifdef HAVE_MMAP_SDIAUDIO
805 if ( (p_sys->i_abuffers = ReadULSysfs( SDIAUDIO_BUFFERS_FILE,
806 p_sys->i_link )) < 0 )
808 msg_Err( p_demux, "couldn't read file " SDIAUDIO_BUFFERS_FILE,
812 p_sys->i_current_abuffer = 0;
815 if ( WriteULSysfs( SDIAUDIO_BUFSIZE_FILE, p_sys->i_link,
816 p_sys->i_abuffer_size ) < 0 )
818 msg_Err( p_demux, "couldn't write file " SDIAUDIO_BUFSIZE_FILE,
823 if ( (p_sys->i_afd = open( psz_adev, O_RDONLY ) ) < 0 )
825 msg_Err( p_demux, "couldn't open device %s", psz_adev );
829 #ifdef HAVE_MMAP_SDIAUDIO
830 i_bufmemsize = ((p_sys->i_abuffer_size + i_page_size - 1) / i_page_size)
832 p_sys->pp_abuffers = malloc( p_sys->i_abuffers * sizeof(uint8_t *) );
833 if( unlikely( !p_sys->pp_abuffers ) )
835 for ( unsigned int i = 0; i < p_sys->i_abuffers; i++ )
837 if ( (p_sys->pp_abuffers[i] = mmap( NULL, p_sys->i_abuffer_size,
838 PROT_READ, MAP_SHARED, p_sys->i_afd,
839 i * i_bufmemsize )) == MAP_FAILED )
841 msg_Err( p_demux, "couldn't mmap(%d): %m", i );
848 /* Use 8-bit video */
849 if ( WriteULSysfs( SDIVIDEO_MODE_FILE, p_sys->i_link,
850 SDIVIDEO_CTL_MODE_UYVY ) < 0 )
852 msg_Err( p_demux, "couldn't write file " SDIVIDEO_MODE_FILE,
857 if ( WriteULSysfs( SDIVIDEO_BUFFERS_FILE, p_sys->i_link,
860 msg_Err( p_demux, "couldn't write file " SDIVIDEO_BUFFERS_FILE,
864 #ifdef HAVE_MMAP_SDIVIDEO
865 p_sys->i_vbuffers = NB_VBUFFERS;
868 if ( WriteULSysfs( SDIVIDEO_BUFSIZE_FILE, p_sys->i_link,
869 p_sys->i_vbuffer_size ) < 0 )
871 msg_Err( p_demux, "couldn't write file " SDIVIDEO_BUFSIZE_FILE,
876 if ( (p_sys->i_vfd = open( psz_vdev, O_RDONLY ) ) < 0 )
878 msg_Err( p_demux, "couldn't open device %s", psz_vdev );
882 #ifdef HAVE_MMAP_SDIVIDEO
883 p_sys->i_current_vbuffer = 0;
884 i_bufmemsize = ((p_sys->i_vbuffer_size + i_page_size - 1) / i_page_size)
886 p_sys->pp_vbuffers = malloc( p_sys->i_vbuffers * sizeof(uint8_t *) );
887 if( unlikely( !p_sys->pp_vbuffers ) )
889 for ( unsigned int i = 0; i < p_sys->i_vbuffers; i++ )
891 if ( (p_sys->pp_vbuffers[i] = mmap( NULL, p_sys->i_vbuffer_size,
892 PROT_READ, MAP_SHARED, p_sys->i_vfd,
893 i * i_bufmemsize )) == MAP_FAILED )
895 msg_Err( p_demux, "couldn't mmap(%d): %m", i );
904 static void CloseCapture( demux_t *p_demux )
906 demux_sys_t *p_sys = p_demux->p_sys;
908 StopDecode( p_demux );
909 #ifdef HAVE_MMAP_SDIVIDEO
910 for ( unsigned int i = 0; i < p_sys->i_vbuffers; i++ )
911 munmap( p_sys->pp_vbuffers[i], p_sys->i_vbuffer_size );
912 free( p_sys->pp_vbuffers );
914 close( p_sys->i_vfd );
915 if ( p_sys->i_max_channel != -1 )
917 #ifdef HAVE_MMAP_SDIAUDIO
918 for ( unsigned int i = 0; i < p_sys->i_abuffers; i++ )
919 munmap( p_sys->pp_abuffers[i], p_sys->i_abuffer_size );
920 free( p_sys->pp_abuffers );
922 close( p_sys->i_afd );
926 static int Capture( demux_t *p_demux )
928 demux_sys_t *p_sys = p_demux->p_sys;
929 struct pollfd pfd[2];
931 pfd[0].fd = p_sys->i_vfd;
932 pfd[0].events = POLLIN | POLLPRI;
933 if ( p_sys->i_max_channel != -1 )
935 pfd[1].fd = p_sys->i_afd;
936 pfd[1].events = POLLIN | POLLPRI;
939 if ( poll( pfd, 1 + (p_sys->i_max_channel != -1), READ_TIMEOUT ) < 0 )
941 msg_Warn( p_demux, "couldn't poll(): %m" );
945 if ( pfd[0].revents & POLLPRI )
949 if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_RXGETEVENTS, &i_val ) < 0 )
950 msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_RXGETEVENTS %m" );
953 if ( i_val & SDIVIDEO_EVENT_RX_BUFFER )
954 msg_Warn( p_demux, "driver receive buffer queue overrun" );
955 if ( i_val & SDIVIDEO_EVENT_RX_FIFO )
956 msg_Warn( p_demux, "onboard receive FIFO overrun");
957 if ( i_val & SDIVIDEO_EVENT_RX_CARRIER )
958 msg_Warn( p_demux, "carrier status change");
959 if ( i_val & SDIVIDEO_EVENT_RX_DATA )
960 msg_Warn( p_demux, "data status change");
961 if ( i_val & SDIVIDEO_EVENT_RX_STD )
962 msg_Warn( p_demux, "standard status change");
965 p_sys->i_next_adate += CLOCK_GAP;
966 p_sys->i_next_vdate += CLOCK_GAP;
969 if ( p_sys->i_max_channel != -1 && pfd[1].revents & POLLPRI )
973 if ( ioctl( p_sys->i_afd, SDIAUDIO_IOC_RXGETEVENTS, &i_val ) < 0 )
974 msg_Warn( p_demux, "couldn't SDIAUDIO_IOC_RXGETEVENTS %m" );
977 if ( i_val & SDIAUDIO_EVENT_RX_BUFFER )
978 msg_Warn( p_demux, "driver receive buffer queue overrun" );
979 if ( i_val & SDIAUDIO_EVENT_RX_FIFO )
980 msg_Warn( p_demux, "onboard receive FIFO overrun");
981 if ( i_val & SDIAUDIO_EVENT_RX_CARRIER )
982 msg_Warn( p_demux, "carrier status change");
983 if ( i_val & SDIAUDIO_EVENT_RX_DATA )
984 msg_Warn( p_demux, "data status change");
987 p_sys->i_next_adate += CLOCK_GAP;
988 p_sys->i_next_vdate += CLOCK_GAP;
991 if ( pfd[0].revents & POLLIN )
993 #ifdef HAVE_MMAP_SDIVIDEO
994 if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_DQBUF, p_sys->i_current_vbuffer )
997 msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_DQBUF %m" );
1001 if( HandleVideo( p_demux, p_sys->pp_vbuffers[p_sys->i_current_vbuffer] ) != VLC_SUCCESS )
1004 if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_QBUF, p_sys->i_current_vbuffer )
1007 msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_QBUF %m" );
1008 return VLC_EGENERIC;
1011 p_sys->i_current_vbuffer++;
1012 p_sys->i_current_vbuffer %= p_sys->i_vbuffers;
1014 uint8_t *p_buffer = malloc( p_sys->i_vbuffer_size );
1015 if( unlikely( !p_buffer ) )
1018 if ( read( p_sys->i_vfd, p_buffer, p_sys->i_vbuffer_size ) < 0 )
1020 msg_Warn( p_demux, "couldn't read %m" );
1022 return VLC_EGENERIC;
1025 if( HandleVideo( p_demux, p_buffer ) != VLC_SUCCESS )
1034 if ( p_sys->i_max_channel != -1 && pfd[1].revents & POLLIN )
1036 #ifdef HAVE_MMAP_SDIAUDIO
1037 if ( ioctl( p_sys->i_afd, SDIAUDIO_IOC_DQBUF, p_sys->i_current_abuffer )
1040 msg_Warn( p_demux, "couldn't SDIAUDIO_IOC_DQBUF %m" );
1041 return VLC_EGENERIC;
1044 if( HandleAudio( p_demux, p_sys->pp_abuffers[p_sys->i_current_abuffer] ) != VLC_SUCCESS )
1047 if ( ioctl( p_sys->i_afd, SDIAUDIO_IOC_QBUF, p_sys->i_current_abuffer )
1050 msg_Warn( p_demux, "couldn't SDIAUDIO_IOC_QBUF %m" );
1051 return VLC_EGENERIC;
1054 p_sys->i_current_abuffer++;
1055 p_sys->i_current_abuffer %= p_sys->i_abuffers;
1057 uint8_t *p_buffer = malloc( p_sys->i_abuffer_size );
1058 if( unlikely( !p_buffer ) )
1061 if ( read( p_sys->i_afd, p_buffer, p_sys->i_abuffer_size ) < 0 )
1063 msg_Warn( p_demux, "couldn't read %m" );
1065 return VLC_EGENERIC;
1068 if( HandleAudio( p_demux, p_buffer ) != VLC_SUCCESS )