]> git.sesse.net Git - vlc/blob - modules/access/linsys/linsys_hdsdi.c
Qt: make SeekPoints handle jump to chapter requests
[vlc] / modules / access / linsys / linsys_hdsdi.c
1 /*****************************************************************************
2  * linsys_hdsdi.c: HDSDI capture for Linear Systems/Computer Modules cards
3  *****************************************************************************
4  * Copyright (C) 2010-2011 VideoLAN
5  *
6  * Authors: Christophe Massiot <massiot@via.ecp.fr>
7  *
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.
12  *
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.
17  *
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  *****************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include <poll.h>
31 #include <sys/mman.h>
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <errno.h>
37
38 #include <vlc_common.h>
39 #include <vlc_plugin.h>
40
41 #include <vlc_input.h>
42 #include <vlc_access.h>
43 #include <vlc_demux.h>
44
45 #include <vlc_fs.h>
46
47 #include "linsys_sdivideo.h"
48 #include "linsys_sdiaudio.h"
49
50 #undef HAVE_MMAP_SDIVIDEO
51 #undef HAVE_MMAP_SDIAUDIO
52
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"
62 #define NB_VBUFFERS             2
63 #define READ_TIMEOUT            80000
64 #define CLOCK_GAP               INT64_C(500000)
65 #define START_DATE              INT64_C(4294967296)
66
67 #define MAX_AUDIOS              4
68
69 /*****************************************************************************
70  * Module descriptor
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...)." )
88
89 static int  Open ( vlc_object_t * );
90 static void Close( vlc_object_t * );
91
92 vlc_module_begin()
93     set_description( _("HD-SDI Input") )
94     set_shortname( N_("HD-SDI") )
95     set_category( CAT_INPUT )
96     set_subcategory( SUBCAT_INPUT_ACCESS )
97
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 )
102
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 )
109
110     set_capability( "access_demux", 0 )
111     add_shortcut( "linsys-hdsdi" )
112     set_callbacks( Open, Close )
113 vlc_module_end()
114
115 /*****************************************************************************
116  * Local prototypes
117  *****************************************************************************/
118 typedef struct hdsdi_audio_t
119 {
120     int         i_channel; /* i_group * 2 + i_pair */
121
122     /* HDSDI parser */
123     int32_t     i_delay;
124
125     /* ES stuff */
126     int         i_id;
127     es_out_id_t *p_es;
128 } hdsdi_audio_t;
129
130 struct demux_sys_t
131 {
132     /* video device reader */
133     int          i_vfd;
134     unsigned int i_link;
135     unsigned int i_standard;
136 #ifdef HAVE_MMAP_SDIVIDEO
137     uint8_t      **pp_vbuffers;
138     unsigned int i_vbuffers, i_current_vbuffer;
139 #endif
140     unsigned int i_vbuffer_size;
141
142     /* audio device reader */
143     int          i_afd;
144     int          i_max_channel;
145     unsigned int i_sample_rate;
146 #ifdef HAVE_MMAP_SDIAUDIO
147     uint8_t      **pp_abuffers;
148     unsigned int i_abuffers, i_current_abuffer;
149 #endif
150     unsigned int i_abuffer_size;
151
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;
157     int          i_incr, i_aincr;
158
159     /* ES stuff */
160     int          i_id_video;
161     es_out_id_t  *p_es_video;
162     hdsdi_audio_t p_audios[MAX_AUDIOS];
163 };
164
165 static int Control( demux_t *, int, va_list );
166 static int Demux( demux_t * );
167
168 static int InitCapture( demux_t *p_demux );
169 static void CloseCapture( demux_t *p_demux );
170 static int Capture( demux_t *p_demux );
171
172 /*****************************************************************************
173  * DemuxOpen:
174  *****************************************************************************/
175 static int Open( vlc_object_t *p_this )
176 {
177     demux_t     *p_demux = (demux_t *)p_this;
178     demux_sys_t *p_sys;
179     char        *psz_parser;
180
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) )
186         return VLC_ENOMEM;
187
188     /* HDSDI AR */
189     char *psz_ar = var_InheritString( p_demux, "linsys-hdsdi-aspect-ratio" );
190     if ( psz_ar != NULL )
191     {
192         psz_parser = strchr( psz_ar, ':' );
193         if ( psz_parser )
194         {
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 );
199         }
200         else
201             p_sys->i_forced_aspect = 0;
202         free( psz_ar );
203     }
204
205     /* */
206     p_sys->i_id_video = var_InheritInteger( p_demux, "linsys-hdsdi-id-video" );
207
208     /* Audio ES */
209     char *psz_string = psz_parser = var_InheritString( p_demux,
210                                                        "linsys-hdsdi-audio" );
211     int i = 0;
212     p_sys->i_max_channel = -1;
213
214     while ( psz_parser != NULL && *psz_parser )
215     {
216         int i_id, i_group, i_pair;
217         char *psz_next = strchr( psz_parser, '=' );
218         if ( psz_next != NULL )
219         {
220             *psz_next = '\0';
221             i_id = strtol( psz_parser, NULL, 0 );
222             psz_parser = psz_next + 1;
223         }
224         else
225             i_id = 0;
226
227         psz_next = strchr( psz_parser, ':' );
228         if ( psz_next != NULL )
229         {
230             *psz_next = '\0';
231             psz_next++;
232         }
233
234         if ( sscanf( psz_parser, "%d,%d", &i_group, &i_pair ) == 2 )
235         {
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;
240             i++;
241         }
242         else
243             msg_Warn( p_demux, "malformed audio configuration (%s)",
244                       psz_parser );
245
246         psz_parser = psz_next;
247     }
248     free( psz_string );
249     for ( ; i < MAX_AUDIOS; i++ )
250         p_sys->p_audios[i].i_channel = -1;
251
252
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 );
255
256     p_sys->i_link = var_InheritInteger( p_demux, "linsys-hdsdi-link" );
257
258     if( InitCapture( p_demux ) != VLC_SUCCESS )
259     {
260         free( p_sys );
261         return VLC_EGENERIC;
262     }
263
264     return VLC_SUCCESS;
265 }
266
267 /*****************************************************************************
268  * DemuxClose:
269  *****************************************************************************/
270 static void Close( vlc_object_t *p_this )
271 {
272     demux_t     *p_demux = (demux_t *)p_this;
273     demux_sys_t *p_sys = p_demux->p_sys;
274
275     CloseCapture( p_demux );
276     free( p_sys );
277 }
278
279 /*****************************************************************************
280  * DemuxDemux:
281  *****************************************************************************/
282 static int Demux( demux_t *p_demux )
283 {
284     return ( Capture( p_demux ) == VLC_SUCCESS );
285 }
286
287 /*****************************************************************************
288  * Control:
289  *****************************************************************************/
290 static int Control( demux_t *p_demux, int i_query, va_list args )
291 {
292     bool *pb;
293     int64_t *pi64;
294
295     switch( i_query )
296     {
297         /* Special for access_demux */
298         case DEMUX_CAN_PAUSE:
299         case DEMUX_CAN_CONTROL_PACE:
300             /* TODO */
301             pb = (bool*)va_arg( args, bool * );
302             *pb = false;
303             return VLC_SUCCESS;
304
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;
308             return VLC_SUCCESS;
309
310         /* TODO implement others */
311         default:
312             return VLC_EGENERIC;
313     }
314 }
315
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])
323
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 )
327 {
328     const uint8_t *p_end = p_line + i_size;
329
330     while ( p_line < p_end )
331     {
332         *p_u++ = U;
333         *p_y++ = Y1;
334         *p_v++ = V;
335         *p_y++ = Y2;
336         p_line += 4;
337     }
338 }
339
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 )
343 {
344     const uint8_t *p_end = p_line + i_size;
345
346     while ( p_line < p_end )
347     {
348         uint16_t tmp;
349         tmp = 3 * *p_u;
350         tmp += U;
351         *p_u++ = tmp / 4;
352         *p_y++ = Y1;
353         tmp = 3 * *p_v;
354         tmp += V;
355         *p_v++ = tmp / 4;
356         *p_y++ = Y2;
357         p_line += 4;
358     }
359 }
360
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 )
364 {
365     const uint8_t *p_end = p_line + i_size;
366
367     while ( p_line < p_end )
368     {
369         uint16_t tmp;
370         tmp = *p_u;
371         tmp += 3 * U;
372         *p_u++ = tmp / 4;
373         *p_y++ = Y1;
374         tmp = *p_v;
375         tmp += 3 * V;
376         *p_v++ = tmp / 4;
377         *p_y++ = Y2;
378         p_line += 4;
379     }
380 }
381
382 #undef U
383 #undef Y1
384 #undef V
385 #undef Y2
386
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 )
389 {
390     for ( size_t i = 0; i < i_nb_samples; i++ )
391     {
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;
395     }
396 }
397
398 /*****************************************************************************
399  * Video & audio decoding
400  *****************************************************************************/
401 struct block_extension_t
402 {
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 */
407 };
408
409 static void StopDecode( demux_t *p_demux )
410 {
411     demux_sys_t *p_sys = p_demux->p_sys;
412
413     es_out_Del( p_demux->out, p_sys->p_es_video );
414
415     for ( int i = 0; i < MAX_AUDIOS; i++ )
416     {
417         hdsdi_audio_t *p_audio = &p_sys->p_audios[i];
418         if ( p_audio->i_channel != -1 && p_audio->p_es != NULL )
419         {
420             es_out_Del( p_demux->out, p_audio->p_es );
421             p_audio->p_es = NULL;
422         }
423     }
424 }
425
426 static int InitVideo( demux_t *p_demux )
427 {
428     demux_sys_t *p_sys = p_demux->p_sys;
429     es_format_t fmt;
430
431     msg_Dbg( p_demux, "found standard %d", p_sys->i_standard );
432     switch ( p_sys->i_standard )
433     {
434     case SDIVIDEO_CTL_BT_601_576I_50HZ:
435         /* PAL */
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;
441         break;
442
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;
449         break;
450
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;
457         break;
458
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;
468         break;
469
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;
476         break;
477
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;
484         break;
485
486     default:
487         msg_Err( p_demux, "unsupported standard %d", p_sys->i_standard );
488         return VLC_EGENERIC;
489     }
490
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);
495
496     /* Video ES */
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
504                                   / fmt.video.i_width;
505     fmt.video.i_sar_den         = VOUT_ASPECT_FACTOR;
506     p_sys->p_es_video           = es_out_Add( p_demux->out, &fmt );
507
508     return VLC_SUCCESS;
509 }
510
511 static int InitAudio( demux_t *p_demux )
512 {
513     demux_sys_t *p_sys = p_demux->p_sys;
514     es_format_t fmt;
515
516     for ( int i = 0; i < MAX_AUDIOS; i++ )
517     {
518         hdsdi_audio_t *p_audio = &p_sys->p_audios[i];
519
520         if ( p_audio->i_channel == -1 ) continue;
521
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 );
525
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 );
538     }
539
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;
543
544     return VLC_SUCCESS;
545 }
546
547 static int HandleVideo( demux_t *p_demux, const uint8_t *p_buffer )
548 {
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 ) )
552         return VLC_ENOMEM;
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;
559
560     for ( i_current_line = 0; i_current_line < p_sys->i_height;
561           i_current_line++ )
562     {
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 :
566             i_current_line;
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;
569
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) );
580        else if ( !b_field )
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) );
585        else
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) );
590     }
591
592     /* FIXME: progressive formats ? */
593     ext.b_progressive = false;
594     ext.i_nb_fields = 2;
595     ext.b_top_field_first = true;
596     ext.i_aspect = p_sys->i_forced_aspect ? p_sys->i_forced_aspect :
597                    p_sys->i_aspect;
598
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) );
602
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 );
605
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;
608     return VLC_SUCCESS;
609 }
610
611 static int HandleAudio( demux_t *p_demux, const uint8_t *p_buffer )
612 {
613     demux_sys_t *p_sys = p_demux->p_sys;
614
615     for ( int i = 0; i < MAX_AUDIOS; i++ )
616     {
617         hdsdi_audio_t *p_audio = &p_sys->p_audios[i];
618         if ( p_audio->i_channel != -1 && p_audio->p_es != NULL )
619         {
620             block_t *p_block = block_New( p_demux, p_sys->i_ablock_size );
621             if( unlikely( !p_block ) )
622                 return VLC_ENOMEM;
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 );
626
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 );
632         }
633     }
634     p_sys->i_next_adate += p_sys->i_aincr;
635     return VLC_SUCCESS;
636 }
637
638 /*****************************************************************************
639  * Low-level device stuff
640  *****************************************************************************/
641 #define MAXLEN 256
642
643 static ssize_t WriteULSysfs( const char *psz_fmt, unsigned int i_link,
644                              unsigned int i_buf )
645 {
646     char psz_file[MAXLEN], psz_data[MAXLEN];
647     int i_fd;
648     ssize_t i_ret;
649
650     snprintf( psz_file, sizeof(psz_file) -1, psz_fmt, i_link );
651
652     snprintf( psz_data, sizeof(psz_data) -1, "%u\n", i_buf );
653
654     if ( (i_fd = vlc_open( psz_file, O_WRONLY )) < 0 )
655         return i_fd;
656
657     i_ret = write( i_fd, psz_data, strlen(psz_data) + 1 );
658     close( i_fd );
659     return i_ret;
660 }
661
662 static int InitCapture( demux_t *p_demux )
663 {
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;
668 #endif
669     char psz_vdev[MAXLEN];
670
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 )
674     {
675         msg_Err( p_demux, "couldn't open device %s", psz_vdev );
676         return VLC_EGENERIC;
677     }
678
679     /* Wait for standard to settle down */
680     while ( !p_demux->b_die )
681     {
682         struct pollfd pfd[1];
683
684         pfd[0].fd = p_sys->i_vfd;
685         pfd[0].events = POLLIN | POLLPRI;
686
687         if ( poll( pfd, 1, READ_TIMEOUT ) < 0 )
688         {
689             msg_Warn( p_demux, "couldn't poll(): %m" );
690             close( p_sys->i_vfd );
691             return VLC_EGENERIC;
692         }
693
694         if ( pfd[0].revents & POLLPRI )
695         {
696             unsigned int i_val;
697
698             if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_RXGETEVENTS, &i_val ) < 0 )
699                 msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_RXGETEVENTS %m" );
700             else
701             {
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 )
711                 {
712                     msg_Warn( p_demux, "standard status change");
713                     break;
714                 }
715             }
716         }
717     }
718     if ( p_demux->b_die )
719     {
720         close( p_sys->i_vfd );
721         return VLC_EGENERIC;
722     }
723
724     if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_RXGETVIDSTATUS, &p_sys->i_standard )
725           < 0 )
726     {
727         msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_RXGETVIDSTATUS %m" );
728         close( p_sys->i_vfd );
729         return VLC_EGENERIC;
730     }
731     close( p_sys->i_vfd );
732
733     if ( InitVideo( p_demux ) != VLC_SUCCESS )
734         return VLC_EGENERIC;
735     p_sys->i_vbuffer_size = p_sys->i_height * p_sys->i_width * 2;
736
737     /* First open the audio for synchronization reasons */
738     if ( p_sys->i_max_channel != -1 )
739     {
740         unsigned int i_rate;
741         char psz_adev[MAXLEN];
742
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 )
746         {
747             msg_Err( p_demux, "couldn't open device %s", psz_adev );
748             return VLC_EGENERIC;
749         }
750
751         if ( ioctl( p_sys->i_afd, SDIAUDIO_IOC_RXGETAUDRATE, &i_rate ) < 0 )
752         {
753             msg_Warn( p_demux, "couldn't SDIAUDIO_IOC_RXGETAUDRATE %m" );
754             return VLC_EGENERIC;
755         }
756         switch ( i_rate )
757         {
758         case SDIAUDIO_CTL_ASYNC_48_KHZ:
759         case SDIAUDIO_CTL_SYNC_48_KHZ:
760             p_sys->i_sample_rate = 48000;
761             break;
762         case SDIAUDIO_CTL_ASYNC_44_1_KHZ:
763         case SDIAUDIO_CTL_SYNC_44_1_KHZ:
764             p_sys->i_sample_rate = 44100;
765             break;
766         case SDIAUDIO_CTL_ASYNC_32_KHZ:
767         case SDIAUDIO_CTL_SYNC_32_KHZ:
768             p_sys->i_sample_rate = 32000;
769             break;
770         case SDIAUDIO_CTL_ASYNC_96_KHZ:
771         case SDIAUDIO_CTL_SYNC_96_KHZ:
772             p_sys->i_sample_rate = 96000;
773             break;
774         case SDIAUDIO_CTL_ASYNC_FREE_RUNNING:
775         case SDIAUDIO_CTL_SYNC_FREE_RUNNING:
776         default:
777             msg_Err( p_demux, "unknown sample rate %u", i_rate );
778             return VLC_EGENERIC;
779         }
780         close( p_sys->i_afd );
781
782         if ( InitAudio( p_demux ) != VLC_SUCCESS )
783             return VLC_EGENERIC;
784         p_sys->i_abuffer_size = p_sys->i_ablock_size
785                                  * (1 + p_sys->i_max_channel);
786
787         /* Use 16-bit audio */
788         if ( WriteULSysfs( SDIAUDIO_SAMPLESIZE_FILE, p_sys->i_link,
789                            SDIAUDIO_CTL_AUDSAMP_SZ_16 ) < 0 )
790         {
791             msg_Err( p_demux, "couldn't write file " SDIAUDIO_SAMPLESIZE_FILE,
792                      p_sys->i_link );
793             return VLC_EGENERIC;
794         }
795
796         if ( WriteULSysfs( SDIAUDIO_CHANNELS_FILE, p_sys->i_link,
797                            (p_sys->i_max_channel + 1) * 2 ) < 0 )
798         {
799             msg_Err( p_demux, "couldn't write file " SDIAUDIO_CHANNELS_FILE,
800                      p_sys->i_link );
801             return VLC_EGENERIC;
802         }
803
804 #ifdef HAVE_MMAP_SDIAUDIO
805         if ( (p_sys->i_abuffers = ReadULSysfs( SDIAUDIO_BUFFERS_FILE,
806                                                p_sys->i_link )) < 0 )
807         {
808             msg_Err( p_demux, "couldn't read file " SDIAUDIO_BUFFERS_FILE,
809                      p_sys->i_link );
810             return VLC_EGENERIC;
811         }
812         p_sys->i_current_abuffer = 0;
813 #endif
814
815         if ( WriteULSysfs( SDIAUDIO_BUFSIZE_FILE, p_sys->i_link,
816                            p_sys->i_abuffer_size ) < 0 )
817         {
818             msg_Err( p_demux, "couldn't write file " SDIAUDIO_BUFSIZE_FILE,
819                      p_sys->i_link );
820             return VLC_EGENERIC;
821         }
822
823         if ( (p_sys->i_afd = open( psz_adev, O_RDONLY ) ) < 0 )
824         {
825             msg_Err( p_demux, "couldn't open device %s", psz_adev );
826             return VLC_EGENERIC;
827         }
828
829 #ifdef HAVE_MMAP_SDIAUDIO
830         i_bufmemsize = ((p_sys->i_abuffer_size + i_page_size - 1) / i_page_size)
831                          * i_page_size;
832         p_sys->pp_abuffers = malloc( p_sys->i_abuffers * sizeof(uint8_t *) );
833         if( unlikely( !p_sys->pp_abuffers ) )
834             return VLC_ENOMEM;
835         for ( unsigned int i = 0; i < p_sys->i_abuffers; i++ )
836         {
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 )
840             {
841                 msg_Err( p_demux, "couldn't mmap(%d): %m", i );
842                 return VLC_EGENERIC;
843             }
844         }
845 #endif
846     }
847
848     /* Use 8-bit video */
849     if ( WriteULSysfs( SDIVIDEO_MODE_FILE, p_sys->i_link,
850                        SDIVIDEO_CTL_MODE_UYVY ) < 0 )
851     {
852         msg_Err( p_demux, "couldn't write file " SDIVIDEO_MODE_FILE,
853                  p_sys->i_link );
854         return VLC_EGENERIC;
855     }
856
857     if ( WriteULSysfs( SDIVIDEO_BUFFERS_FILE, p_sys->i_link,
858                        NB_VBUFFERS ) < 0 )
859     {
860         msg_Err( p_demux, "couldn't write file " SDIVIDEO_BUFFERS_FILE,
861                  p_sys->i_link );
862         return VLC_EGENERIC;
863     }
864 #ifdef HAVE_MMAP_SDIVIDEO
865     p_sys->i_vbuffers = NB_VBUFFERS;
866 #endif
867
868     if ( WriteULSysfs( SDIVIDEO_BUFSIZE_FILE, p_sys->i_link,
869                        p_sys->i_vbuffer_size ) < 0 )
870     {
871         msg_Err( p_demux, "couldn't write file " SDIVIDEO_BUFSIZE_FILE,
872                  p_sys->i_link );
873         return VLC_EGENERIC;
874     }
875
876     if ( (p_sys->i_vfd = open( psz_vdev, O_RDONLY ) ) < 0 )
877     {
878         msg_Err( p_demux, "couldn't open device %s", psz_vdev );
879         return VLC_EGENERIC;
880     }
881
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)
885                      * i_page_size;
886     p_sys->pp_vbuffers = malloc( p_sys->i_vbuffers * sizeof(uint8_t *) );
887     if( unlikely( !p_sys->pp_vbuffers ) )
888         return VLC_ENOMEM;
889     for ( unsigned int i = 0; i < p_sys->i_vbuffers; i++ )
890     {
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 )
894         {
895             msg_Err( p_demux, "couldn't mmap(%d): %m", i );
896             return VLC_EGENERIC;
897         }
898     }
899 #endif
900
901     return VLC_SUCCESS;
902 }
903
904 static void CloseCapture( demux_t *p_demux )
905 {
906     demux_sys_t *p_sys = p_demux->p_sys;
907
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 );
913 #endif
914     close( p_sys->i_vfd );
915     if ( p_sys->i_max_channel != -1 )
916     {
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 );
921 #endif
922         close( p_sys->i_afd );
923     }
924 }
925
926 static int Capture( demux_t *p_demux )
927 {
928     demux_sys_t *p_sys = p_demux->p_sys;
929     struct pollfd pfd[2];
930
931     pfd[0].fd = p_sys->i_vfd;
932     pfd[0].events = POLLIN | POLLPRI;
933     if ( p_sys->i_max_channel != -1 )
934     {
935         pfd[1].fd = p_sys->i_afd;
936         pfd[1].events = POLLIN | POLLPRI;
937     }
938
939     if ( poll( pfd, 1 + (p_sys->i_max_channel != -1), READ_TIMEOUT ) < 0 )
940     {
941         msg_Warn( p_demux, "couldn't poll(): %m" );
942         return VLC_EGENERIC;
943     }
944
945     if ( pfd[0].revents & POLLPRI )
946     {
947         unsigned int i_val;
948
949         if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_RXGETEVENTS, &i_val ) < 0 )
950             msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_RXGETEVENTS %m" );
951         else
952         {
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");
963         }
964
965         p_sys->i_next_adate += CLOCK_GAP;
966         p_sys->i_next_vdate += CLOCK_GAP;
967     }
968
969     if ( p_sys->i_max_channel != -1 && pfd[1].revents & POLLPRI )
970     {
971         unsigned int i_val;
972
973         if ( ioctl( p_sys->i_afd, SDIAUDIO_IOC_RXGETEVENTS, &i_val ) < 0 )
974             msg_Warn( p_demux, "couldn't SDIAUDIO_IOC_RXGETEVENTS %m" );
975         else
976         {
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");
985         }
986
987         p_sys->i_next_adate += CLOCK_GAP;
988         p_sys->i_next_vdate += CLOCK_GAP;
989     }
990
991     if ( pfd[0].revents & POLLIN )
992     {
993 #ifdef HAVE_MMAP_SDIVIDEO
994         if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_DQBUF, p_sys->i_current_vbuffer )
995               < 0 )
996         {
997             msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_DQBUF %m" );
998             return VLC_EGENERIC;
999         }
1000
1001         if( HandleVideo( p_demux, p_sys->pp_vbuffers[p_sys->i_current_vbuffer] ) != VLC_SUCCESS )
1002             return VLC_ENOMEM;
1003
1004         if ( ioctl( p_sys->i_vfd, SDIVIDEO_IOC_QBUF, p_sys->i_current_vbuffer )
1005               < 0 )
1006         {
1007             msg_Warn( p_demux, "couldn't SDIVIDEO_IOC_QBUF %m" );
1008             return VLC_EGENERIC;
1009         }
1010
1011         p_sys->i_current_vbuffer++;
1012         p_sys->i_current_vbuffer %= p_sys->i_vbuffers;
1013 #else
1014         uint8_t *p_buffer = malloc( p_sys->i_vbuffer_size );
1015         if( unlikely( !p_buffer ) )
1016             return VLC_ENOMEM;
1017
1018         if ( read( p_sys->i_vfd, p_buffer, p_sys->i_vbuffer_size ) < 0 )
1019         {
1020             msg_Warn( p_demux, "couldn't read %m" );
1021             free( p_buffer );
1022             return VLC_EGENERIC;
1023         }
1024
1025         if( HandleVideo( p_demux, p_buffer ) != VLC_SUCCESS )
1026         {
1027             free( p_buffer );
1028             return VLC_ENOMEM;
1029         }
1030         free( p_buffer );
1031 #endif
1032     }
1033
1034     if ( p_sys->i_max_channel != -1 && pfd[1].revents & POLLIN )
1035     {
1036 #ifdef HAVE_MMAP_SDIAUDIO
1037         if ( ioctl( p_sys->i_afd, SDIAUDIO_IOC_DQBUF, p_sys->i_current_abuffer )
1038               < 0 )
1039         {
1040             msg_Warn( p_demux, "couldn't SDIAUDIO_IOC_DQBUF %m" );
1041             return VLC_EGENERIC;
1042         }
1043
1044         if( HandleAudio( p_demux, p_sys->pp_abuffers[p_sys->i_current_abuffer] ) != VLC_SUCCESS )
1045             return VLC_ENOMEM;
1046
1047         if ( ioctl( p_sys->i_afd, SDIAUDIO_IOC_QBUF, p_sys->i_current_abuffer )
1048               < 0 )
1049         {
1050             msg_Warn( p_demux, "couldn't SDIAUDIO_IOC_QBUF %m" );
1051             return VLC_EGENERIC;
1052         }
1053
1054         p_sys->i_current_abuffer++;
1055         p_sys->i_current_abuffer %= p_sys->i_abuffers;
1056 #else
1057         uint8_t *p_buffer = malloc( p_sys->i_abuffer_size );
1058         if( unlikely( !p_buffer ) )
1059             return VLC_ENOMEM;
1060
1061         if ( read( p_sys->i_afd, p_buffer, p_sys->i_abuffer_size ) < 0 )
1062         {
1063             msg_Warn( p_demux, "couldn't read %m" );
1064             free( p_buffer );
1065             return VLC_EGENERIC;
1066         }
1067
1068         if( HandleAudio( p_demux, p_buffer ) != VLC_SUCCESS )
1069         {
1070             free( p_buffer );
1071             return VLC_ENOMEM;
1072         }
1073         free( p_buffer );
1074 #endif
1075     }
1076
1077     return VLC_SUCCESS;
1078 }