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>
35 #include <sys/eventfd.h>
39 #include <vlc_common.h>
40 #include <vlc_plugin.h>
42 #include <vlc_input.h>
43 #include <vlc_access.h>
44 #include <vlc_demux.h>
48 #include "linsys_sdivideo.h"
49 #include "linsys_sdiaudio.h"
51 #undef HAVE_MMAP_SDIVIDEO
52 #undef HAVE_MMAP_SDIAUDIO
54 #define SDIVIDEO_DEVICE "/dev/sdivideorx%u"
55 #define SDIVIDEO_BUFFERS_FILE "/sys/class/sdivideo/sdivideorx%u/buffers"
56 #define SDIVIDEO_BUFSIZE_FILE "/sys/class/sdivideo/sdivideorx%u/bufsize"
57 #define SDIVIDEO_MODE_FILE "/sys/class/sdivideo/sdivideorx%u/mode"
58 #define SDIAUDIO_DEVICE "/dev/sdiaudiorx%u"
59 #define SDIAUDIO_BUFFERS_FILE "/sys/class/sdiaudio/sdiaudiorx%u/buffers"
60 #define SDIAUDIO_BUFSIZE_FILE "/sys/class/sdiaudio/sdiaudiorx%u/bufsize"
61 #define SDIAUDIO_SAMPLESIZE_FILE "/sys/class/sdiaudio/sdiaudiorx%u/sample_size"
62 #define SDIAUDIO_CHANNELS_FILE "/sys/class/sdiaudio/sdiaudiorx%u/channels"
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( N_("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
];
162 static int Control( demux_t
*, int, va_list );
163 static void *Demux( void * );
165 static int InitCapture( demux_t
*p_demux
);
166 static void CloseCapture( demux_t
*p_demux
);
167 static int Capture( demux_t
*p_demux
);
169 /*****************************************************************************
171 *****************************************************************************/
172 static int Open( vlc_object_t
*p_this
)
174 demux_t
*p_demux
= (demux_t
*)p_this
;
178 /* Fill p_demux field */
179 p_demux
->p_sys
= p_sys
= calloc( 1, sizeof( demux_sys_t
) );
180 if( unlikely(!p_sys
) )
184 unsigned int i_num
, i_den
;
185 if ( !var_InheritURational( p_demux
, &i_num
, &i_den
,
186 "linsys-hdsdi-aspect-ratio" ) && i_den
!= 0 )
187 p_sys
->i_forced_aspect
= p_sys
->i_aspect
=
188 i_num
* VOUT_ASPECT_FACTOR
/ i_den
;
190 p_sys
->i_forced_aspect
= 0;
193 p_sys
->i_id_video
= var_InheritInteger( p_demux
, "linsys-hdsdi-id-video" );
196 char *psz_string
= psz_parser
= var_InheritString( p_demux
,
197 "linsys-hdsdi-audio" );
199 p_sys
->i_max_channel
= -1;
201 while ( psz_parser
!= NULL
&& *psz_parser
)
203 int i_id
, i_group
, i_pair
;
204 char *psz_next
= strchr( psz_parser
, '=' );
205 if ( psz_next
!= NULL
)
208 i_id
= strtol( psz_parser
, NULL
, 0 );
209 psz_parser
= psz_next
+ 1;
214 psz_next
= strchr( psz_parser
, ':' );
215 if ( psz_next
!= NULL
)
221 if ( sscanf( psz_parser
, "%d,%d", &i_group
, &i_pair
) == 2 )
223 p_sys
->p_audios
[i
].i_channel
= (i_group
- 1) * 2 + (i_pair
- 1);
224 if ( p_sys
->p_audios
[i
].i_channel
> p_sys
->i_max_channel
)
225 p_sys
->i_max_channel
= p_sys
->p_audios
[i
].i_channel
;
226 p_sys
->p_audios
[i
].i_id
= i_id
;
230 msg_Warn( p_demux
, "malformed audio configuration (%s)",
233 psz_parser
= psz_next
;
236 for ( ; i
< MAX_AUDIOS
; i
++ )
237 p_sys
->p_audios
[i
].i_channel
= -1;
240 p_sys
->i_link
= var_InheritInteger( p_demux
, "linsys-hdsdi-link" );
242 p_sys
->evfd
= eventfd( 0, EFD_CLOEXEC
);
243 if( p_sys
->evfd
== -1 )
246 if( pthread_create( &p_sys
->thread
, NULL
, Demux
, p_demux
) )
248 vlc_close( p_sys
->evfd
);
252 p_demux
->pf_demux
= NULL
;
253 p_demux
->pf_control
= Control
;
260 /*****************************************************************************
262 *****************************************************************************/
263 static void Close( vlc_object_t
*p_this
)
265 demux_t
*p_demux
= (demux_t
*)p_this
;
266 demux_sys_t
*p_sys
= p_demux
->p_sys
;
268 write( p_sys
->evfd
, &(uint64_t){ 1 }, sizeof (uint64_t));
269 pthread_join( p_sys
->thread
, NULL
);
270 vlc_close( p_sys
->evfd
);
274 /*****************************************************************************
276 *****************************************************************************/
277 static void *Demux( void *opaque
)
279 demux_t
*p_demux
= opaque
;
281 if( InitCapture( p_demux
) != VLC_SUCCESS
)
284 while( Capture( p_demux
) == VLC_SUCCESS
);
286 CloseCapture( p_demux
);
290 /*****************************************************************************
292 *****************************************************************************/
293 static int Control( demux_t
*p_demux
, int i_query
, va_list args
)
300 /* Special for access_demux */
301 case DEMUX_CAN_PAUSE
:
302 case DEMUX_CAN_CONTROL_PACE
:
304 pb
= va_arg( args
, bool * );
308 case DEMUX_GET_PTS_DELAY
:
309 pi64
= va_arg( args
, int64_t * );
310 *pi64
= INT64_C(1000)
311 * var_InheritInteger( p_demux
, "live-caching" );
314 /* TODO implement others */
320 /*****************************************************************************
321 * HDSDI syntax parsing stuff
322 *****************************************************************************/
323 #define U (uint16_t)(p_line[0])
324 #define Y1 (uint16_t)(p_line[1])
325 #define V (uint16_t)(p_line[2])
326 #define Y2 (uint16_t)(p_line[3])
328 /* For lines 0 [4] or 1 [4] */
329 static void Unpack01( const uint8_t *p_line
, unsigned int i_size
,
330 uint8_t *p_y
, uint8_t *p_u
, uint8_t *p_v
)
332 const uint8_t *p_end
= p_line
+ i_size
;
334 while ( p_line
< p_end
)
344 /* For lines 2 [4] */
345 static void Unpack2( const uint8_t *p_line
, unsigned int i_size
,
346 uint8_t *p_y
, uint8_t *p_u
, uint8_t *p_v
)
348 const uint8_t *p_end
= p_line
+ i_size
;
350 while ( p_line
< p_end
)
365 /* For lines 3 [4] */
366 static void Unpack3( const uint8_t *p_line
, unsigned int i_size
,
367 uint8_t *p_y
, uint8_t *p_u
, uint8_t *p_v
)
369 const uint8_t *p_end
= p_line
+ i_size
;
371 while ( p_line
< p_end
)
391 static void SparseCopy( int16_t *p_dest
, const int16_t *p_src
,
392 size_t i_nb_samples
, size_t i_offset
, size_t i_stride
)
394 for ( size_t i
= 0; i
< i_nb_samples
; i
++ )
396 p_dest
[2 * i
] = p_src
[i_offset
];
397 p_dest
[2 * i
+ 1] = p_src
[i_offset
+ 1];
398 i_offset
+= 2 * i_stride
;
402 /*****************************************************************************
403 * Video & audio decoding
404 *****************************************************************************/
405 struct block_extension_t
407 bool b_progressive
; /**< is it a progressive frame ? */
408 bool b_top_field_first
; /**< which field is first */
409 unsigned int i_nb_fields
; /**< # of displayed fields */
410 unsigned int i_aspect
; /**< aspect ratio of frame */
413 static void StopDecode( demux_t
*p_demux
)
415 demux_sys_t
*p_sys
= p_demux
->p_sys
;
417 es_out_Del( p_demux
->out
, p_sys
->p_es_video
);
419 for ( int i
= 0; i
< MAX_AUDIOS
; i
++ )
421 hdsdi_audio_t
*p_audio
= &p_sys
->p_audios
[i
];
422 if ( p_audio
->i_channel
!= -1 && p_audio
->p_es
!= NULL
)
424 es_out_Del( p_demux
->out
, p_audio
->p_es
);
425 p_audio
->p_es
= NULL
;
430 static int InitVideo( demux_t
*p_demux
)
432 demux_sys_t
*p_sys
= p_demux
->p_sys
;
435 msg_Dbg( p_demux
, "found standard %d", p_sys
->i_standard
);
436 switch ( p_sys
->i_standard
)
438 case SDIVIDEO_CTL_BT_601_576I_50HZ
:
440 p_sys
->i_frame_rate
= 25;
441 p_sys
->i_frame_rate_base
= 1;
442 p_sys
->i_width
= 720;
443 p_sys
->i_height
= 576;
444 p_sys
->i_aspect
= 4 * VOUT_ASPECT_FACTOR
/ 3;
447 case SDIVIDEO_CTL_SMPTE_296M_720P_50HZ
:
448 p_sys
->i_frame_rate
= 50;
449 p_sys
->i_frame_rate_base
= 1;
450 p_sys
->i_width
= 1280;
451 p_sys
->i_height
= 720;
452 p_sys
->i_aspect
= 16 * VOUT_ASPECT_FACTOR
/ 9;
455 case SDIVIDEO_CTL_SMPTE_296M_720P_60HZ
:
456 p_sys
->i_frame_rate
= 60;
457 p_sys
->i_frame_rate_base
= 1;
458 p_sys
->i_width
= 1280;
459 p_sys
->i_height
= 720;
460 p_sys
->i_aspect
= 16 * VOUT_ASPECT_FACTOR
/ 9;
463 case SDIVIDEO_CTL_SMPTE_295M_1080I_50HZ
:
464 case SDIVIDEO_CTL_SMPTE_274M_1080I_50HZ
:
465 case SDIVIDEO_CTL_SMPTE_274M_1080PSF_25HZ
:
466 /* 1080i50 or 1080p25 */
467 p_sys
->i_frame_rate
= 25;
468 p_sys
->i_frame_rate_base
= 1;
469 p_sys
->i_width
= 1920;
470 p_sys
->i_height
= 1080;
471 p_sys
->i_aspect
= 16 * VOUT_ASPECT_FACTOR
/ 9;
474 case SDIVIDEO_CTL_SMPTE_274M_1080I_59_94HZ
:
475 p_sys
->i_frame_rate
= 30000;
476 p_sys
->i_frame_rate_base
= 1001;
477 p_sys
->i_width
= 1920;
478 p_sys
->i_height
= 1080;
479 p_sys
->i_aspect
= 16 * VOUT_ASPECT_FACTOR
/ 9;
482 case SDIVIDEO_CTL_SMPTE_274M_1080I_60HZ
:
483 p_sys
->i_frame_rate
= 30;
484 p_sys
->i_frame_rate_base
= 1;
485 p_sys
->i_width
= 1920;
486 p_sys
->i_height
= 1080;
487 p_sys
->i_aspect
= 16 * VOUT_ASPECT_FACTOR
/ 9;
491 msg_Err( p_demux
, "unsupported standard %d", p_sys
->i_standard
);
495 p_sys
->i_next_vdate
= START_DATE
;
496 p_sys
->i_incr
= 1000000 * p_sys
->i_frame_rate_base
/ p_sys
->i_frame_rate
;
497 p_sys
->i_vblock_size
= p_sys
->i_width
* p_sys
->i_height
* 3 / 2
498 + sizeof(struct block_extension_t
);
501 es_format_Init( &fmt
, VIDEO_ES
, VLC_CODEC_I420
);
502 fmt
.i_id
= p_sys
->i_id_video
;
503 fmt
.video
.i_frame_rate
= p_sys
->i_frame_rate
;
504 fmt
.video
.i_frame_rate_base
= p_sys
->i_frame_rate_base
;
505 fmt
.video
.i_width
= fmt
.video
.i_visible_width
= p_sys
->i_width
;
506 fmt
.video
.i_height
= fmt
.video
.i_visible_height
= p_sys
->i_height
;
507 fmt
.video
.i_sar_num
= p_sys
->i_aspect
* fmt
.video
.i_height
509 fmt
.video
.i_sar_den
= VOUT_ASPECT_FACTOR
;
510 p_sys
->p_es_video
= es_out_Add( p_demux
->out
, &fmt
);
515 static int InitAudio( demux_t
*p_demux
)
517 demux_sys_t
*p_sys
= p_demux
->p_sys
;
520 for ( int i
= 0; i
< MAX_AUDIOS
; i
++ )
522 hdsdi_audio_t
*p_audio
= &p_sys
->p_audios
[i
];
524 if ( p_audio
->i_channel
== -1 ) continue;
526 msg_Dbg( p_demux
, "starting audio %u/%u rate:%u delay:%d",
527 1 + p_audio
->i_channel
/ 2, 1 + (p_audio
->i_channel
% 2),
528 p_sys
->i_sample_rate
, p_audio
->i_delay
);
530 es_format_Init( &fmt
, AUDIO_ES
, VLC_CODEC_S16L
);
531 fmt
.i_id
= p_audio
->i_id
;
532 fmt
.audio
.i_channels
= 2;
533 fmt
.audio
.i_physical_channels
= AOUT_CHANS_STEREO
;
534 fmt
.audio
.i_rate
= p_sys
->i_sample_rate
;
535 fmt
.audio
.i_bitspersample
= 16;
536 fmt
.audio
.i_blockalign
= fmt
.audio
.i_channels
*
537 fmt
.audio
.i_bitspersample
/ 8;
538 fmt
.i_bitrate
= fmt
.audio
.i_channels
* fmt
.audio
.i_rate
*
539 fmt
.audio
.i_bitspersample
;
540 p_audio
->p_es
= es_out_Add( p_demux
->out
, &fmt
);
543 p_sys
->i_next_adate
= START_DATE
;
544 p_sys
->i_ablock_size
= p_sys
->i_sample_rate
* 4 * p_sys
->i_frame_rate_base
/ p_sys
->i_frame_rate
;
545 p_sys
->i_aincr
= 1000000. * p_sys
->i_ablock_size
/ p_sys
->i_sample_rate
/ 4;
550 static int HandleVideo( demux_t
*p_demux
, const uint8_t *p_buffer
)
552 demux_sys_t
*p_sys
= p_demux
->p_sys
;
553 block_t
*p_current_picture
= block_Alloc( p_sys
->i_vblock_size
);
554 if( unlikely( !p_current_picture
) )
556 uint8_t *p_y
= p_current_picture
->p_buffer
;
557 uint8_t *p_u
= p_y
+ p_sys
->i_width
* p_sys
->i_height
;
558 uint8_t *p_v
= p_u
+ p_sys
->i_width
* p_sys
->i_height
/ 4;
559 unsigned int i_total_size
= p_sys
->i_width
* 2;
560 unsigned int i_current_line
;
561 struct block_extension_t ext
;
563 for ( i_current_line
= 0; i_current_line
< p_sys
->i_height
;
566 bool b_field
= (i_current_line
>= p_sys
->i_height
/ 2);
567 unsigned int i_field_line
= b_field
?
568 i_current_line
- (p_sys
->i_height
+ 1) / 2 :
570 unsigned int i_real_line
= b_field
+ i_field_line
* 2;
571 const uint8_t *p_line
= p_buffer
+ i_current_line
* p_sys
->i_width
* 2;
573 if ( !(i_field_line
% 2) && !b_field
)
574 Unpack01( p_line
, i_total_size
,
575 p_y
+ p_sys
->i_width
* i_real_line
,
576 p_u
+ (p_sys
->i_width
/ 2) * (i_real_line
/ 2),
577 p_v
+ (p_sys
->i_width
/ 2) * (i_real_line
/ 2) );
578 else if ( !(i_field_line
% 2) )
579 Unpack01( p_line
, i_total_size
,
580 p_y
+ p_sys
->i_width
* i_real_line
,
581 p_u
+ (p_sys
->i_width
/ 2) * (i_real_line
/ 2 + 1),
582 p_v
+ (p_sys
->i_width
/ 2) * (i_real_line
/ 2 + 1) );
584 Unpack2( p_line
, i_total_size
,
585 p_y
+ p_sys
->i_width
* i_real_line
,
586 p_u
+ (p_sys
->i_width
/ 2) * (i_real_line
/ 2 - 1),
587 p_v
+ (p_sys
->i_width
/ 2) * (i_real_line
/ 2 - 1) );
589 Unpack3( p_line
, i_total_size
,
590 p_y
+ p_sys
->i_width
* i_real_line
,
591 p_u
+ (p_sys
->i_width
/ 2) * (i_real_line
/ 2),
592 p_v
+ (p_sys
->i_width
/ 2) * (i_real_line
/ 2) );
595 /* FIXME: progressive formats ? */
596 ext
.b_progressive
= false;
598 ext
.b_top_field_first
= true;
599 ext
.i_aspect
= p_sys
->i_forced_aspect
? p_sys
->i_forced_aspect
:
602 memcpy( &p_current_picture
->p_buffer
[p_sys
->i_vblock_size
603 - sizeof(struct block_extension_t
)],
604 &ext
, sizeof(struct block_extension_t
) );
606 p_current_picture
->i_dts
= p_current_picture
->i_pts
= p_sys
->i_next_vdate
;
607 es_out_Send( p_demux
->out
, p_sys
->p_es_video
, p_current_picture
);
609 es_out_SetPCR( p_demux
->out
, p_sys
->i_next_vdate
);
610 p_sys
->i_next_vdate
+= p_sys
->i_incr
;
614 static int HandleAudio( demux_t
*p_demux
, const uint8_t *p_buffer
)
616 demux_sys_t
*p_sys
= p_demux
->p_sys
;
618 for ( int i
= 0; i
< MAX_AUDIOS
; i
++ )
620 hdsdi_audio_t
*p_audio
= &p_sys
->p_audios
[i
];
621 if ( p_audio
->i_channel
!= -1 && p_audio
->p_es
!= NULL
)
623 block_t
*p_block
= block_Alloc( p_sys
->i_ablock_size
);
624 if( unlikely( !p_block
) )
626 SparseCopy( (int16_t *)p_block
->p_buffer
, (const int16_t *)p_buffer
,
627 p_sys
->i_ablock_size
/ 4,
628 p_audio
->i_channel
* 2, p_sys
->i_max_channel
+ 1 );
630 p_block
->i_dts
= p_block
->i_pts
631 = p_sys
->i_next_adate
+ (mtime_t
)p_audio
->i_delay
632 * INT64_C(1000000) / p_sys
->i_sample_rate
;
633 p_block
->i_length
= p_sys
->i_aincr
;
634 es_out_Send( p_demux
->out
, p_audio
->p_es
, p_block
);
637 p_sys
->i_next_adate
+= p_sys
->i_aincr
;
641 /*****************************************************************************
642 * Low-level device stuff
643 *****************************************************************************/
646 static ssize_t
WriteULSysfs( const char *psz_fmt
, unsigned int i_link
,
649 char psz_file
[MAXLEN
], psz_data
[MAXLEN
];
653 snprintf( psz_file
, sizeof(psz_file
) -1, psz_fmt
, i_link
);
655 snprintf( psz_data
, sizeof(psz_data
) -1, "%u\n", i_buf
);
657 if ( (i_fd
= vlc_open( psz_file
, O_WRONLY
)) < 0 )
660 i_ret
= write( i_fd
, psz_data
, strlen(psz_data
) + 1 );
665 static int InitCapture( demux_t
*p_demux
)
667 demux_sys_t
*p_sys
= p_demux
->p_sys
;
668 #ifdef HAVE_MMAP_SDIVIDEO
669 const int i_page_size
= getpagesize();
670 unsigned int i_bufmemsize
;
672 char psz_vdev
[MAXLEN
];
674 snprintf( psz_vdev
, sizeof(psz_vdev
), SDIVIDEO_DEVICE
, p_sys
->i_link
);
675 if ( (p_sys
->i_vfd
= vlc_open( psz_vdev
, O_RDONLY
) ) < 0 )
677 msg_Err( p_demux
, "couldn't open device %s", psz_vdev
);
681 /* Wait for standard to settle down */
682 struct pollfd pfd
[2];
684 pfd
[0].fd
= p_sys
->i_vfd
;
685 pfd
[0].events
= POLLPRI
;
686 pfd
[1].fd
= p_sys
->evfd
;
687 pfd
[1].events
= POLLIN
;
691 if( poll( pfd
, 2, -1 ) < 0 )
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: %s",
700 vlc_strerror_c(errno
) );
703 if ( i_val
& SDIVIDEO_EVENT_RX_BUFFER
)
704 msg_Warn( p_demux
, "driver receive buffer queue overrun" );
705 if ( i_val
& SDIVIDEO_EVENT_RX_FIFO
)
706 msg_Warn( p_demux
, "onboard receive FIFO overrun");
707 if ( i_val
& SDIVIDEO_EVENT_RX_CARRIER
)
708 msg_Warn( p_demux
, "carrier status change");
709 if ( i_val
& SDIVIDEO_EVENT_RX_DATA
)
710 msg_Warn( p_demux
, "data status change");
711 if ( i_val
& SDIVIDEO_EVENT_RX_STD
)
713 msg_Warn( p_demux
, "standard status change");
721 vlc_close( p_sys
->i_vfd
);
726 if ( ioctl( p_sys
->i_vfd
, SDIVIDEO_IOC_RXGETVIDSTATUS
, &p_sys
->i_standard
)
729 msg_Warn( p_demux
, "couldn't SDIVIDEO_IOC_RXGETVIDSTATUS: %s",
730 vlc_strerror_c(errno
) );
731 vlc_close( p_sys
->i_vfd
);
734 vlc_close( p_sys
->i_vfd
);
736 if ( InitVideo( p_demux
) != VLC_SUCCESS
)
738 p_sys
->i_vbuffer_size
= p_sys
->i_height
* p_sys
->i_width
* 2;
740 /* First open the audio for synchronization reasons */
741 if ( p_sys
->i_max_channel
!= -1 )
744 char psz_adev
[MAXLEN
];
746 snprintf( psz_adev
, sizeof(psz_adev
), SDIAUDIO_DEVICE
, p_sys
->i_link
);
747 if ( (p_sys
->i_afd
= vlc_open( psz_adev
, O_RDONLY
) ) < 0 )
749 msg_Err( p_demux
, "couldn't open device %s", psz_adev
);
753 if ( ioctl( p_sys
->i_afd
, SDIAUDIO_IOC_RXGETAUDRATE
, &i_rate
) < 0 )
755 msg_Warn( p_demux
, "couldn't SDIAUDIO_IOC_RXGETAUDRATE: %s",
756 vlc_strerror_c(errno
) );
761 case SDIAUDIO_CTL_ASYNC_48_KHZ
:
762 case SDIAUDIO_CTL_SYNC_48_KHZ
:
763 p_sys
->i_sample_rate
= 48000;
765 case SDIAUDIO_CTL_ASYNC_44_1_KHZ
:
766 case SDIAUDIO_CTL_SYNC_44_1_KHZ
:
767 p_sys
->i_sample_rate
= 44100;
769 case SDIAUDIO_CTL_ASYNC_32_KHZ
:
770 case SDIAUDIO_CTL_SYNC_32_KHZ
:
771 p_sys
->i_sample_rate
= 32000;
773 case SDIAUDIO_CTL_ASYNC_96_KHZ
:
774 case SDIAUDIO_CTL_SYNC_96_KHZ
:
775 p_sys
->i_sample_rate
= 96000;
777 case SDIAUDIO_CTL_ASYNC_FREE_RUNNING
:
778 case SDIAUDIO_CTL_SYNC_FREE_RUNNING
:
780 msg_Err( p_demux
, "unknown sample rate %u", i_rate
);
783 vlc_close( p_sys
->i_afd
);
785 if ( InitAudio( p_demux
) != VLC_SUCCESS
)
787 p_sys
->i_abuffer_size
= p_sys
->i_ablock_size
788 * (1 + p_sys
->i_max_channel
);
790 /* Use 16-bit audio */
791 if ( WriteULSysfs( SDIAUDIO_SAMPLESIZE_FILE
, p_sys
->i_link
,
792 SDIAUDIO_CTL_AUDSAMP_SZ_16
) < 0 )
794 msg_Err( p_demux
, "couldn't write file " SDIAUDIO_SAMPLESIZE_FILE
,
799 if ( WriteULSysfs( SDIAUDIO_CHANNELS_FILE
, p_sys
->i_link
,
800 (p_sys
->i_max_channel
+ 1) * 2 ) < 0 )
802 msg_Err( p_demux
, "couldn't write file " SDIAUDIO_CHANNELS_FILE
,
807 #ifdef HAVE_MMAP_SDIAUDIO
808 if ( (p_sys
->i_abuffers
= ReadULSysfs( SDIAUDIO_BUFFERS_FILE
,
809 p_sys
->i_link
)) < 0 )
811 msg_Err( p_demux
, "couldn't read file " SDIAUDIO_BUFFERS_FILE
,
815 p_sys
->i_current_abuffer
= 0;
818 if ( WriteULSysfs( SDIAUDIO_BUFSIZE_FILE
, p_sys
->i_link
,
819 p_sys
->i_abuffer_size
) < 0 )
821 msg_Err( p_demux
, "couldn't write file " SDIAUDIO_BUFSIZE_FILE
,
826 if ( (p_sys
->i_afd
= open( psz_adev
, O_RDONLY
) ) < 0 )
828 msg_Err( p_demux
, "couldn't open device %s", psz_adev
);
832 #ifdef HAVE_MMAP_SDIAUDIO
833 i_bufmemsize
= ((p_sys
->i_abuffer_size
+ i_page_size
- 1) / i_page_size
)
835 p_sys
->pp_abuffers
= vlc_alloc( p_sys
->i_abuffers
, sizeof(uint8_t *) );
836 if( unlikely( !p_sys
->pp_abuffers
) )
838 for ( unsigned int i
= 0; i
< p_sys
->i_abuffers
; i
++ )
840 if ( (p_sys
->pp_abuffers
[i
] = mmap( NULL
, p_sys
->i_abuffer_size
,
841 PROT_READ
, MAP_SHARED
, p_sys
->i_afd
,
842 i
* i_bufmemsize
)) == MAP_FAILED
)
844 msg_Err( p_demux
, "couldn't mmap(%d): %s", i
,
845 vlc_strerror_c(errno
) );
852 /* Use 8-bit video */
853 if ( WriteULSysfs( SDIVIDEO_MODE_FILE
, p_sys
->i_link
,
854 SDIVIDEO_CTL_MODE_UYVY
) < 0 )
856 msg_Err( p_demux
, "couldn't write file " SDIVIDEO_MODE_FILE
,
861 if ( WriteULSysfs( SDIVIDEO_BUFFERS_FILE
, p_sys
->i_link
,
864 msg_Err( p_demux
, "couldn't write file " SDIVIDEO_BUFFERS_FILE
,
868 #ifdef HAVE_MMAP_SDIVIDEO
869 p_sys
->i_vbuffers
= NB_VBUFFERS
;
872 if ( WriteULSysfs( SDIVIDEO_BUFSIZE_FILE
, p_sys
->i_link
,
873 p_sys
->i_vbuffer_size
) < 0 )
875 msg_Err( p_demux
, "couldn't write file " SDIVIDEO_BUFSIZE_FILE
,
880 if ( (p_sys
->i_vfd
= open( psz_vdev
, O_RDONLY
) ) < 0 )
882 msg_Err( p_demux
, "couldn't open device %s", psz_vdev
);
886 #ifdef HAVE_MMAP_SDIVIDEO
887 p_sys
->i_current_vbuffer
= 0;
888 i_bufmemsize
= ((p_sys
->i_vbuffer_size
+ i_page_size
- 1) / i_page_size
)
890 p_sys
->pp_vbuffers
= vlc_alloc( p_sys
->i_vbuffers
, sizeof(uint8_t *) );
891 if( unlikely( !p_sys
->pp_vbuffers
) )
893 for ( unsigned int i
= 0; i
< p_sys
->i_vbuffers
; i
++ )
895 if ( (p_sys
->pp_vbuffers
[i
] = mmap( NULL
, p_sys
->i_vbuffer_size
,
896 PROT_READ
, MAP_SHARED
, p_sys
->i_vfd
,
897 i
* i_bufmemsize
)) == MAP_FAILED
)
899 msg_Err( p_demux
, "couldn't mmap(%d): %s", i
,
900 vlc_strerror_c(errno
) );
909 static void CloseCapture( demux_t
*p_demux
)
911 demux_sys_t
*p_sys
= p_demux
->p_sys
;
913 StopDecode( p_demux
);
914 #ifdef HAVE_MMAP_SDIVIDEO
915 for ( unsigned int i
= 0; i
< p_sys
->i_vbuffers
; i
++ )
916 munmap( p_sys
->pp_vbuffers
[i
], p_sys
->i_vbuffer_size
);
917 free( p_sys
->pp_vbuffers
);
919 vlc_close( p_sys
->i_vfd
);
920 if ( p_sys
->i_max_channel
!= -1 )
922 #ifdef HAVE_MMAP_SDIAUDIO
923 for ( unsigned int i
= 0; i
< p_sys
->i_abuffers
; i
++ )
924 munmap( p_sys
->pp_abuffers
[i
], p_sys
->i_abuffer_size
);
925 free( p_sys
->pp_abuffers
);
927 vlc_close( p_sys
->i_afd
);
931 static int Capture( demux_t
*p_demux
)
933 demux_sys_t
*p_sys
= p_demux
->p_sys
;
934 struct pollfd pfd
[3];
936 pfd
[0].fd
= p_sys
->evfd
;
937 pfd
[0].events
= POLLIN
;
938 pfd
[1].fd
= p_sys
->i_vfd
;
939 pfd
[1].events
= POLLIN
| POLLPRI
;
940 if ( p_sys
->i_max_channel
!= -1 )
942 pfd
[2].fd
= p_sys
->i_afd
;
943 pfd
[2].events
= POLLIN
| POLLPRI
;
946 if( poll( pfd
, 2 + (p_sys
->i_max_channel
!= -1), -1 ) < 0 )
950 return VLC_EGENERIC
; /* Stop! */
952 if( pfd
[1].revents
& POLLPRI
)
956 if ( ioctl( p_sys
->i_vfd
, SDIVIDEO_IOC_RXGETEVENTS
, &i_val
) < 0 )
957 msg_Warn( p_demux
, "couldn't SDIVIDEO_IOC_RXGETEVENTS: %s",
958 vlc_strerror_c(errno
) );
961 if ( i_val
& SDIVIDEO_EVENT_RX_BUFFER
)
962 msg_Warn( p_demux
, "driver receive buffer queue overrun" );
963 if ( i_val
& SDIVIDEO_EVENT_RX_FIFO
)
964 msg_Warn( p_demux
, "onboard receive FIFO overrun");
965 if ( i_val
& SDIVIDEO_EVENT_RX_CARRIER
)
966 msg_Warn( p_demux
, "carrier status change");
967 if ( i_val
& SDIVIDEO_EVENT_RX_DATA
)
968 msg_Warn( p_demux
, "data status change");
969 if ( i_val
& SDIVIDEO_EVENT_RX_STD
)
970 msg_Warn( p_demux
, "standard status change");
973 p_sys
->i_next_adate
+= CLOCK_GAP
;
974 p_sys
->i_next_vdate
+= CLOCK_GAP
;
977 if( p_sys
->i_max_channel
!= -1 && (pfd
[2].revents
& POLLPRI
) )
981 if ( ioctl( p_sys
->i_afd
, SDIAUDIO_IOC_RXGETEVENTS
, &i_val
) < 0 )
982 msg_Warn( p_demux
, "couldn't SDIAUDIO_IOC_RXGETEVENTS: %s",
983 vlc_strerror_c(errno
) );
986 if ( i_val
& SDIAUDIO_EVENT_RX_BUFFER
)
987 msg_Warn( p_demux
, "driver receive buffer queue overrun" );
988 if ( i_val
& SDIAUDIO_EVENT_RX_FIFO
)
989 msg_Warn( p_demux
, "onboard receive FIFO overrun");
990 if ( i_val
& SDIAUDIO_EVENT_RX_CARRIER
)
991 msg_Warn( p_demux
, "carrier status change");
992 if ( i_val
& SDIAUDIO_EVENT_RX_DATA
)
993 msg_Warn( p_demux
, "data status change");
996 p_sys
->i_next_adate
+= CLOCK_GAP
;
997 p_sys
->i_next_vdate
+= CLOCK_GAP
;
1000 if( pfd
[1].revents
& POLLIN
)
1002 #ifdef HAVE_MMAP_SDIVIDEO
1003 if ( ioctl( p_sys
->i_vfd
, SDIVIDEO_IOC_DQBUF
, p_sys
->i_current_vbuffer
)
1006 msg_Warn( p_demux
, "couldn't SDIVIDEO_IOC_DQBUF: %s",
1007 vlc_strerror_c(errno
) );
1008 return VLC_EGENERIC
;
1011 if( HandleVideo( p_demux
, p_sys
->pp_vbuffers
[p_sys
->i_current_vbuffer
] ) != VLC_SUCCESS
)
1014 if ( ioctl( p_sys
->i_vfd
, SDIVIDEO_IOC_QBUF
, p_sys
->i_current_vbuffer
)
1017 msg_Warn( p_demux
, "couldn't SDIVIDEO_IOC_QBUF: %s",
1018 vlc_strerror_c(errno
) );
1019 return VLC_EGENERIC
;
1022 p_sys
->i_current_vbuffer
++;
1023 p_sys
->i_current_vbuffer
%= p_sys
->i_vbuffers
;
1025 uint8_t *p_buffer
= malloc( p_sys
->i_vbuffer_size
);
1026 if( unlikely( !p_buffer
) )
1029 if ( read( p_sys
->i_vfd
, p_buffer
, p_sys
->i_vbuffer_size
) < 0 )
1031 msg_Warn( p_demux
, "couldn't read: %s", vlc_strerror_c(errno
) );
1033 return VLC_EGENERIC
;
1036 if( HandleVideo( p_demux
, p_buffer
) != VLC_SUCCESS
)
1045 if( p_sys
->i_max_channel
!= -1 && (pfd
[2].revents
& POLLIN
) )
1047 #ifdef HAVE_MMAP_SDIAUDIO
1048 if ( ioctl( p_sys
->i_afd
, SDIAUDIO_IOC_DQBUF
, p_sys
->i_current_abuffer
)
1051 msg_Warn( p_demux
, "couldn't SDIAUDIO_IOC_DQBUF: %s",
1052 vlc_strerror_c(errno
) );
1053 return VLC_EGENERIC
;
1056 if( HandleAudio( p_demux
, p_sys
->pp_abuffers
[p_sys
->i_current_abuffer
] ) != VLC_SUCCESS
)
1059 if ( ioctl( p_sys
->i_afd
, SDIAUDIO_IOC_QBUF
, p_sys
->i_current_abuffer
)
1062 msg_Warn( p_demux
, "couldn't SDIAUDIO_IOC_QBUF: %s",
1063 vlc_strerror_c(errno
) );
1064 return VLC_EGENERIC
;
1067 p_sys
->i_current_abuffer
++;
1068 p_sys
->i_current_abuffer
%= p_sys
->i_abuffers
;
1070 uint8_t *p_buffer
= malloc( p_sys
->i_abuffer_size
);
1071 if( unlikely( !p_buffer
) )
1074 if ( read( p_sys
->i_afd
, p_buffer
, p_sys
->i_abuffer_size
) < 0 )
1076 msg_Warn( p_demux
, "couldn't read: %s", vlc_strerror_c(errno
) );
1078 return VLC_EGENERIC
;
1081 if( HandleAudio( p_demux
, p_buffer
) != VLC_SUCCESS
)