Linsys SDI: use single precision
[vlc.git] / modules / access / linsys / linsys_sdi.c
1 /*****************************************************************************
2  * linsys_sdi.c: SDI capture for Linear Systems/Computer Modules cards
3  *****************************************************************************
4  * Copyright (C) 2009-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 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.
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 Lesser General Public License for more details.
17  *
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  *****************************************************************************/
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 <fcntl.h>
35 #include <errno.h>
36
37 #include <vlc_common.h>
38 #include <vlc_plugin.h>
39
40 #include <vlc_input.h>
41 #include <vlc_access.h>
42 #include <vlc_demux.h>
43
44 #include <vlc_fs.h>
45
46 #include "linsys_sdi.h"
47
48 #undef ZVBI_DEBUG
49 #include <libzvbi.h>
50
51 #define SDI_DEVICE        "/dev/sdirx%u"
52 #define SDI_BUFFERS_FILE  "/sys/class/sdi/sdirx%u/buffers"
53 #define SDI_BUFSIZE_FILE  "/sys/class/sdi/sdirx%u/bufsize"
54 #define SDI_MODE_FILE     "/sys/class/sdi/sdirx%u/mode"
55 #define READ_TIMEOUT      80000
56 #define RESYNC_TIMEOUT    500000
57 #define CLOCK_GAP         INT64_C(500000)
58 #define START_DATE        INT64_C(4294967296)
59
60 #define DEMUX_BUFFER_SIZE 1350000
61 #define MAX_AUDIOS        4
62 #define SAMPLERATE_TOLERANCE 0.1f
63
64 /*****************************************************************************
65  * Module descriptor
66  *****************************************************************************/
67 #define LINK_TEXT N_("Link #")
68 #define LINK_LONGTEXT N_( \
69     "Allows you to set the desired link of the board for the capture (starting at 0)." )
70 #define VIDEO_TEXT N_("Video ID")
71 #define VIDEO_LONGTEXT N_( \
72     "Allows you to set the ES ID of the video." )
73 #define VIDEO_ASPECT_TEXT N_("Aspect ratio")
74 #define VIDEO_ASPECT_LONGTEXT N_( \
75     "Allows you to force the aspect ratio of the video." )
76 #define AUDIO_TEXT N_("Audio configuration")
77 #define AUDIO_LONGTEXT N_( \
78     "Allows you to set audio configuration (id=group,pair:id=group,pair...)." )
79 #define TELX_TEXT N_("Teletext configuration")
80 #define TELX_LONGTEXT N_( \
81     "Allows you to set Teletext configuration (id=line1-lineN with both fields)." )
82 #define TELX_LANG_TEXT N_("Teletext language")
83 #define TELX_LANG_LONGTEXT N_( \
84     "Allows you to set Teletext language (page=lang/type,...)." )
85
86 static int  Open ( vlc_object_t * );
87 static void Close( vlc_object_t * );
88 static int  DemuxOpen ( vlc_object_t * );
89 static void DemuxClose( vlc_object_t * );
90
91 vlc_module_begin()
92     set_description( N_("SDI Input") )
93     set_shortname( N_("SDI") )
94     set_category( CAT_INPUT )
95     set_subcategory( SUBCAT_INPUT_ACCESS )
96
97     add_integer( "linsys-sdi-link", 0,
98         LINK_TEXT, LINK_LONGTEXT, true )
99
100     add_integer( "linsys-sdi-id-video", 0, VIDEO_TEXT, VIDEO_LONGTEXT, true )
101     add_string( "linsys-sdi-aspect-ratio", "", VIDEO_ASPECT_TEXT,
102                 VIDEO_ASPECT_LONGTEXT, true )
103     add_string( "linsys-sdi-audio", "0=1,1", AUDIO_TEXT, AUDIO_LONGTEXT, true )
104     add_string( "linsys-sdi-telx", "", TELX_TEXT, TELX_LONGTEXT, true )
105     add_string( "linsys-sdi-telx-lang", "", TELX_LANG_TEXT, TELX_LANG_LONGTEXT,
106                 true )
107
108     set_capability( "access_demux", 0 )
109     add_shortcut( "linsys-sdi" )
110     set_callbacks( Open, Close )
111
112     add_submodule()
113         set_description( N_("SDI Demux") )
114         set_capability( "demux", 0 )
115         set_callbacks( DemuxOpen, DemuxClose )
116 vlc_module_end()
117
118 /*****************************************************************************
119  * Local prototypes
120  *****************************************************************************/
121 typedef struct sdi_audio_t
122 {
123     unsigned int i_group, i_pair;
124
125     /* SDI parser */
126     int32_t      i_delay;
127     unsigned int i_rate;
128     uint8_t      i_block_number;
129     int16_t      *p_buffer;
130     unsigned int i_left_samples, i_right_samples, i_nb_samples, i_max_samples;
131
132     /* ES stuff */
133     int          i_id;
134     es_out_id_t  *p_es;
135 } sdi_audio_t;
136
137 enum {
138     STATE_NOSYNC,
139     STATE_STARTSYNC,
140     STATE_ANCSYNC,
141     STATE_LINESYNC,
142     STATE_ACTIVESYNC,
143     STATE_VBLANKSYNC,
144     STATE_PICSYNC,
145     STATE_SYNC,
146 };
147
148 struct demux_sys_t
149 {
150     /* device reader */
151     int              i_fd;
152     unsigned int     i_link;
153     uint8_t          **pp_buffers;
154     unsigned int     i_buffers, i_current_buffer;
155     unsigned int     i_buffer_size;
156
157     /* SDI sync */
158     int              i_state;
159     mtime_t          i_last_state_change;
160     unsigned int     i_anc_size, i_active_size, i_picture_size;
161     unsigned int     i_line_offset, i_nb_lines;
162
163     /* SDI parser */
164     unsigned int     i_line_buffer;
165     unsigned int     i_current_line;
166     uint8_t          *p_line_buffer;
167     block_t          *p_current_picture;
168     uint8_t          *p_y, *p_u, *p_v;
169     uint8_t          *p_wss_buffer;
170     uint8_t          *p_telx_buffer;
171
172     /* picture decoding */
173     unsigned int     i_frame_rate, i_frame_rate_base;
174     unsigned int     i_width, i_height, i_aspect, i_forced_aspect;
175     unsigned int     i_block_size;
176     unsigned int     i_telx_line, i_telx_count;
177     char             *psz_telx, *psz_telx_lang;
178     bool             b_hd, b_vbi;
179     vbi_raw_decoder  rd_wss, rd_telx;
180     mtime_t          i_next_date;
181     int              i_incr;
182
183     /* ES stuff */
184     int              i_id_video;
185     es_out_id_t      *p_es_video;
186     sdi_audio_t      p_audios[MAX_AUDIOS];
187     es_out_id_t      *p_es_telx;
188 };
189
190 static int Control( demux_t *, int, va_list );
191 static int DemuxControl( demux_t *, int, va_list );
192 static int Demux( demux_t * );
193 static int DemuxDemux( demux_t * );
194
195 static int InitWSS( demux_t *p_demux );
196 static int InitTelx( demux_t *p_demux );
197
198 static int HandleSDBuffer( demux_t *p_demux, uint8_t *p_buffer,
199                            unsigned int i_buffer_size );
200
201 static int InitCapture( demux_t *p_demux );
202 static void CloseCapture( demux_t *p_demux );
203 static int Capture( demux_t *p_demux );
204
205 /*****************************************************************************
206  * DemuxOpen:
207  *****************************************************************************/
208 static int DemuxOpen( vlc_object_t *p_this )
209 {
210     demux_t     *p_demux = (demux_t *)p_this;
211     demux_sys_t *p_sys;
212     char        *psz_parser;
213
214     /* Fill p_demux field */
215     p_demux->pf_demux = DemuxDemux;
216     p_demux->pf_control = DemuxControl;
217     p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );
218     if( unlikely(!p_sys ) )
219         return VLC_ENOMEM;
220
221     p_sys->i_state = STATE_NOSYNC;
222     p_sys->i_last_state_change = mdate();
223
224     /* SDI AR */
225     char *psz_ar = var_InheritString( p_demux, "linsys-sdi-aspect-ratio" );
226     if ( psz_ar != NULL )
227     {
228         psz_parser = strchr( psz_ar, ':' );
229         if ( psz_parser )
230         {
231             *psz_parser++ = '\0';
232             p_sys->i_forced_aspect = p_sys->i_aspect =
233                  strtol( psz_ar, NULL, 0 ) * VOUT_ASPECT_FACTOR
234                  / strtol( psz_parser, NULL, 0 );
235         }
236         else
237             p_sys->i_forced_aspect = 0;
238         free( psz_ar );
239     }
240
241     /* */
242     p_sys->i_id_video = var_InheritInteger( p_demux, "linsys-sdi-id-video" );
243
244     /* Audio ES */
245     char *psz_string = psz_parser = var_InheritString( p_demux,
246                                                        "linsys-sdi-audio" );
247     int i = 0;
248
249     while ( psz_parser != NULL && *psz_parser )
250     {
251         int i_id, i_group, i_pair;
252         char *psz_next = strchr( psz_parser, '=' );
253         if ( psz_next != NULL )
254         {
255             *psz_next = '\0';
256             i_id = strtol( psz_parser, NULL, 0 );
257             psz_parser = psz_next + 1;
258         }
259         else
260             i_id = 0;
261
262         psz_next = strchr( psz_parser, ':' );
263         if ( psz_next != NULL )
264         {
265             *psz_next = '\0';
266             psz_next++;
267         }
268
269         if ( sscanf( psz_parser, "%d,%d", &i_group, &i_pair ) == 2 )
270         {
271             p_sys->p_audios[i].i_group = i_group;
272             p_sys->p_audios[i].i_pair = i_pair;
273             p_sys->p_audios[i].i_id = i_id;
274             i++;
275         }
276         else
277             msg_Warn( p_demux, "malformed audio configuration (%s)",
278                       psz_parser );
279
280         psz_parser = psz_next;
281     }
282     free( psz_string );
283
284     /* Teletext ES */
285     p_sys->psz_telx = var_InheritString( p_demux, "linsys-sdi-telx" );
286
287     p_sys->psz_telx_lang = var_InheritString( p_demux, "linsys-sdi-telx-lang" );
288
289     return VLC_SUCCESS;
290 }
291
292 static int Open( vlc_object_t *p_this )
293 {
294     demux_t     *p_demux = (demux_t *)p_this;
295     demux_sys_t *p_sys;
296     int         i_ret;
297
298     if ( (i_ret = DemuxOpen( p_this )) != VLC_SUCCESS )
299         return i_ret;
300
301     /* Fill p_demux field */
302     p_demux->pf_demux    = Demux;
303     p_demux->pf_control  = Control;
304     p_sys = p_demux->p_sys;
305
306     p_sys->i_link = var_InheritInteger( p_demux, "linsys-sdi-link" );
307
308     if( InitCapture( p_demux ) != VLC_SUCCESS )
309     {
310         free( p_sys );
311         return VLC_EGENERIC;
312     }
313
314     return VLC_SUCCESS;
315 }
316
317 /*****************************************************************************
318  * DemuxClose:
319  *****************************************************************************/
320 static void DemuxClose( vlc_object_t *p_this )
321 {
322     demux_t     *p_demux = (demux_t *)p_this;
323     demux_sys_t *p_sys   = p_demux->p_sys;
324
325     free( p_sys->psz_telx );
326     free( p_sys->psz_telx_lang );
327     free( p_sys );
328 }
329
330 static void Close( vlc_object_t *p_this )
331 {
332     demux_t     *p_demux = (demux_t *)p_this;
333
334     CloseCapture( p_demux );
335     DemuxClose( p_this );
336 }
337
338 /*****************************************************************************
339  * DemuxDemux:
340  *****************************************************************************/
341 static int DemuxDemux( demux_t *p_demux )
342 {
343     block_t *p_block = stream_Block( p_demux->s, DEMUX_BUFFER_SIZE );
344     int i_ret;
345
346     if ( p_block == NULL )
347         return 0;
348
349     i_ret = HandleSDBuffer( p_demux, p_block->p_buffer, p_block->i_buffer );
350     block_Release( p_block );
351
352     return ( i_ret == VLC_SUCCESS );
353 }
354
355 static int Demux( demux_t *p_demux )
356 {
357     return ( Capture( p_demux ) == VLC_SUCCESS );
358 }
359
360 /*****************************************************************************
361  * Control:
362  *****************************************************************************/
363 static int DemuxControl( demux_t *p_demux, int i_query, va_list args )
364 {
365     return demux_vaControlHelper( p_demux->s, -1, -1, 270000000, 1, i_query,
366                                    args );
367 }
368
369 static int Control( demux_t *p_demux, int i_query, va_list args )
370 {
371     bool *pb;
372     int64_t *pi64;
373
374     switch( i_query )
375     {
376         /* Special for access_demux */
377         case DEMUX_CAN_PAUSE:
378         case DEMUX_CAN_CONTROL_PACE:
379             /* TODO */
380             pb = (bool*)va_arg( args, bool * );
381             *pb = false;
382             return VLC_SUCCESS;
383
384         case DEMUX_GET_PTS_DELAY:
385             pi64 = (int64_t*)va_arg( args, int64_t * );
386             *pi64 = INT64_C(1000)
387                   * var_InheritInteger( p_demux, "live-caching" );
388             return VLC_SUCCESS;
389
390         /* TODO implement others */
391         default:
392             return VLC_EGENERIC;
393     }
394 }
395
396 /*****************************************************************************
397  * Video, audio & VBI decoding
398  *****************************************************************************/
399 #define WSS_LINE        23
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 int NewFrame( demux_t *p_demux )
410 {
411     demux_sys_t *p_sys = p_demux->p_sys;
412
413     p_sys->p_current_picture = block_Alloc( p_sys->i_block_size );
414     if( unlikely( !p_sys->p_current_picture ) )
415         return VLC_ENOMEM;
416     p_sys->p_y = p_sys->p_current_picture->p_buffer;
417     p_sys->p_u = p_sys->p_y + p_sys->i_width * p_sys->i_height;
418     p_sys->p_v = p_sys->p_u + p_sys->i_width * p_sys->i_height / 4;
419
420     for ( int i = 0; i < MAX_AUDIOS; i++ )
421     {
422         sdi_audio_t *p_audio = &p_sys->p_audios[i];
423         p_audio->i_left_samples = p_audio->i_right_samples = 0;
424     }
425     return VLC_SUCCESS;
426 }
427
428 static int StartDecode( demux_t *p_demux )
429 {
430     demux_sys_t *p_sys = p_demux->p_sys;
431     es_format_t fmt;
432     char *psz_parser;
433
434     p_sys->i_next_date = START_DATE;
435     p_sys->i_incr = 1000000 * p_sys->i_frame_rate_base / p_sys->i_frame_rate;
436     p_sys->i_block_size = p_sys->i_width * p_sys->i_height * 3 / 2
437                            + sizeof(struct block_extension_t);
438     if( NewFrame( p_demux ) != VLC_SUCCESS )
439         return VLC_ENOMEM;
440
441     /* Video ES */
442     es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_I420 );
443     fmt.i_id                    = p_sys->i_id_video;
444     fmt.video.i_frame_rate      = p_sys->i_frame_rate;
445     fmt.video.i_frame_rate_base = p_sys->i_frame_rate_base;
446     fmt.video.i_width           = p_sys->i_width;
447     fmt.video.i_height          = p_sys->i_height;
448     int i_aspect = p_sys->i_forced_aspect ? p_sys->i_forced_aspect
449                                           : p_sys->i_aspect;
450     fmt.video.i_sar_num = i_aspect * fmt.video.i_height
451                            / fmt.video.i_width;
452     fmt.video.i_sar_den = VOUT_ASPECT_FACTOR;
453     p_sys->p_es_video   = es_out_Add( p_demux->out, &fmt );
454
455     if ( p_sys->b_vbi && InitWSS( p_demux ) != VLC_SUCCESS )
456         p_sys->b_vbi = 0;
457
458     /* Teletext ES */
459     psz_parser = p_sys->psz_telx;
460     if ( psz_parser != NULL && *psz_parser )
461     {
462         if ( !p_sys->b_vbi )
463         {
464             msg_Warn( p_demux, "VBI is unsupported on this input stream" );
465         }
466         else
467         {
468             int i_id;
469             char *psz_next = strchr( psz_parser, '=' );
470             if ( psz_next != NULL )
471             {
472                 *psz_next = '\0';
473                 i_id = strtol( psz_parser, NULL, 0 );
474                 psz_parser = psz_next + 1;
475             }
476             else
477                 i_id = 0;
478
479             psz_next = strchr( psz_parser, '-' );
480             if ( psz_next != NULL )
481                 *psz_next++ = '\0';
482
483             p_sys->i_telx_line = strtol( psz_parser, NULL, 0 ) - 1;
484             if ( psz_next != NULL )
485                 p_sys->i_telx_count = strtol( psz_next, NULL, 0 )
486                                        - p_sys->i_telx_line - 1 + 1;
487             else
488                 p_sys->i_telx_count = 1;
489
490             if ( InitTelx( p_demux ) == VLC_SUCCESS )
491             {
492                 int i_dr_size = 0;
493                 uint8_t *p_dr = NULL;
494
495                 msg_Dbg( p_demux, "capturing VBI lines %d-%d and %d-%d",
496                          p_sys->i_telx_line + 1,
497                          p_sys->i_telx_line + 1 + p_sys->i_telx_count - 1,
498                          p_sys->i_telx_line + 1 + 313,
499                          p_sys->i_telx_line + 1 + 313
500                                                 + p_sys->i_telx_count - 1 );
501
502                 es_format_Init( &fmt, SPU_ES, VLC_CODEC_TELETEXT );
503                 fmt.i_id = i_id;
504
505                 /* Teletext language & type */
506                 psz_parser = p_sys->psz_telx_lang;
507
508                 while ( (psz_next = strchr( psz_parser, '=' )) != NULL )
509                 {
510                     int i_page;
511                     *psz_next++ = '\0';
512                     if ( !psz_next[0] || !psz_next[1] || !psz_next[2] )
513                         break;
514                     i_page = strtol( psz_parser, NULL, 0 );
515                     i_dr_size += 5;
516                     p_dr = realloc( p_dr, i_dr_size );
517                     p_dr[i_dr_size - 5] = *psz_next++;
518                     p_dr[i_dr_size - 4] = *psz_next++;
519                     p_dr[i_dr_size - 3] = *psz_next++;
520                     if ( *psz_next == '/' )
521                     {
522                         psz_next++;
523                         p_dr[i_dr_size - 2] = strtol( psz_next, &psz_next, 0 )
524                                                << 3;
525                     }
526                     else  /* subtitle for hearing impaired */
527                         p_dr[i_dr_size - 2] = 0x5 << 3;
528                     p_dr[i_dr_size - 2] |= (i_page / 100) & 0x7;
529                     p_dr[i_dr_size - 1] = i_page % 100;
530
531                     if ( *psz_next == ',' )
532                         psz_next++;
533                     psz_parser = psz_next;
534                 }
535
536                 fmt.i_extra = i_dr_size;
537                 fmt.p_extra = p_dr;
538                 p_sys->p_es_telx = es_out_Add( p_demux->out, &fmt );
539             }
540             else
541                 p_sys->i_telx_count = 0;
542         }
543     }
544     return VLC_SUCCESS;
545 }
546
547 static void StopDecode( demux_t *p_demux )
548 {
549     demux_sys_t *p_sys = p_demux->p_sys;
550
551     if ( p_sys->i_state != STATE_SYNC )
552         return;
553
554     free( p_sys->p_line_buffer );
555
556     block_Release( p_sys->p_current_picture );
557     p_sys->p_current_picture = NULL;
558     es_out_Del( p_demux->out, p_sys->p_es_video );
559
560     if ( p_sys->b_vbi )
561     {
562         free( p_sys->p_wss_buffer );
563         p_sys->p_wss_buffer = NULL;
564         vbi_raw_decoder_destroy( &p_sys->rd_wss );
565
566         if ( p_sys->p_es_telx )
567         {
568             es_out_Del( p_demux->out, p_sys->p_es_telx );
569             free( p_sys->p_telx_buffer );
570             p_sys->p_telx_buffer = NULL;
571             vbi_raw_decoder_destroy( &p_sys->rd_telx );
572         }
573     }
574
575     for ( int i = 0; i < MAX_AUDIOS; i++ )
576     {
577         sdi_audio_t *p_audio = &p_sys->p_audios[i];
578         if ( p_audio->i_group && p_audio->p_es != NULL )
579         {
580             es_out_Del( p_demux->out, p_audio->p_es );
581             p_audio->p_es = NULL;
582             free( p_audio->p_buffer );
583             p_audio->p_buffer = NULL;
584         }
585     }
586 }
587
588 static void InitVideo( demux_t *p_demux )
589 {
590     demux_sys_t *p_sys = p_demux->p_sys;
591     int i_total_width = (p_sys->i_anc_size + p_sys->i_active_size) * 4 / 5;
592     p_sys->i_width = (p_sys->i_active_size - 5) * 4 / 10;
593     if ( p_sys->i_nb_lines == 625 )
594     {
595         /* PAL */
596         p_sys->i_frame_rate      = 25;
597         p_sys->i_frame_rate_base = 1;
598         p_sys->i_height          = 576;
599         p_sys->i_aspect          = 4 * VOUT_ASPECT_FACTOR / 3;
600         p_sys->b_hd              = false;
601     }
602     else if ( p_sys->i_nb_lines == 525 )
603     {
604         /* NTSC */
605         p_sys->i_frame_rate      = 30000;
606         p_sys->i_frame_rate_base = 1001;
607         p_sys->i_height          = 480;
608         p_sys->i_aspect          = 4 * VOUT_ASPECT_FACTOR / 3;
609         p_sys->b_hd              = false;
610     }
611     else if ( p_sys->i_nb_lines == 1125 && i_total_width == 2640 )
612     {
613         /* 1080i50 or 1080p25 */
614         p_sys->i_frame_rate      = 25;
615         p_sys->i_frame_rate_base = 1;
616         p_sys->i_height          = 1080;
617         p_sys->i_aspect          = 16 * VOUT_ASPECT_FACTOR / 9;
618         p_sys->b_hd              = true;
619     }
620     else if ( p_sys->i_nb_lines == 1125 && i_total_width == 2200 )
621     {
622         /* 1080i60 or 1080p30 */
623         p_sys->i_frame_rate      = 30000;
624         p_sys->i_frame_rate_base = 1001;
625         p_sys->i_height          = 1080;
626         p_sys->i_aspect          = 16 * VOUT_ASPECT_FACTOR / 9;
627         p_sys->b_hd              = true;
628     }
629     else if ( p_sys->i_nb_lines == 750 && i_total_width == 1980 )
630     {
631         /* 720p50 */
632         p_sys->i_frame_rate      = 50;
633         p_sys->i_frame_rate_base = 1;
634         p_sys->i_height          = 720;
635         p_sys->i_aspect          = 16 * VOUT_ASPECT_FACTOR / 9;
636         p_sys->b_hd              = true;
637     }
638     else if ( p_sys->i_nb_lines == 750 && i_total_width == 1650 )
639     {
640         /* 720p60 */
641         p_sys->i_frame_rate      = 60000;
642         p_sys->i_frame_rate_base = 1001;
643         p_sys->i_height          = 720;
644         p_sys->i_aspect          = 16 * VOUT_ASPECT_FACTOR / 9;
645         p_sys->b_hd              = true;
646     }
647     else
648     {
649         msg_Warn( p_demux, "unable to determine video type" );
650         /* Put sensitive defaults */
651         p_sys->i_frame_rate      = 25;
652         p_sys->i_frame_rate_base = 1;
653         p_sys->i_height          = p_sys->i_nb_lines;
654         p_sys->i_aspect          = 16 * VOUT_ASPECT_FACTOR / 9;
655         p_sys->b_hd              = true;
656     }
657     p_sys->b_vbi = !p_sys->b_hd;
658 }
659
660 static void DecodeVideo( demux_t *p_demux )
661 {
662     demux_sys_t *p_sys = p_demux->p_sys;
663     struct block_extension_t ext;
664
665     /* FIXME: progressive formats ? */
666     ext.b_progressive     = false;
667     ext.i_nb_fields       = 2;
668     ext.b_top_field_first = true;
669     ext.i_aspect = p_sys->i_forced_aspect ? p_sys->i_forced_aspect :
670                    p_sys->i_aspect;
671
672     memcpy( &p_sys->p_current_picture->p_buffer[p_sys->i_block_size
673                                      - sizeof(struct block_extension_t)],
674             &ext, sizeof(struct block_extension_t) );
675
676     p_sys->p_current_picture->i_dts = p_sys->p_current_picture->i_pts
677         = p_sys->i_next_date;
678     es_out_Send( p_demux->out, p_sys->p_es_video, p_sys->p_current_picture );
679 }
680
681 static int InitWSS( demux_t *p_demux )
682 {
683     demux_sys_t *p_sys = p_demux->p_sys;
684     vbi_raw_decoder_init( &p_sys->rd_wss );
685
686     p_sys->rd_wss.scanning        = 625;
687     p_sys->rd_wss.sampling_format = VBI_PIXFMT_UYVY;
688     p_sys->rd_wss.sampling_rate   = 13.5e6;
689     p_sys->rd_wss.bytes_per_line  = 720 * 2;
690     p_sys->rd_wss.offset          = 9.5e-6 * 13.5e6;
691
692     p_sys->rd_wss.start[0] = 23;
693     p_sys->rd_wss.count[0] = 1;
694     p_sys->rd_wss.start[1] = 0;
695     p_sys->rd_wss.count[1] = 0;
696
697     p_sys->rd_wss.interlaced = FALSE;
698     p_sys->rd_wss.synchronous = TRUE;
699
700     if ( vbi_raw_decoder_add_services( &p_sys->rd_wss,
701                                        VBI_SLICED_WSS_625,
702                                        /* strict */ 2 ) == 0 )
703     {
704         msg_Warn( p_demux, "cannot initialize zvbi for WSS" );
705         vbi_raw_decoder_destroy ( &p_sys->rd_telx );
706         return VLC_EGENERIC;
707     }
708
709     p_sys->p_wss_buffer = malloc( p_sys->i_width * 2 );
710     if( !p_sys->p_wss_buffer )
711     {
712         vbi_raw_decoder_destroy ( &p_sys->rd_telx );
713         return VLC_ENOMEM;
714     }
715     return VLC_SUCCESS;
716 }
717
718 static void DecodeWSS( demux_t *p_demux )
719 {
720     demux_sys_t *p_sys = p_demux->p_sys;
721     vbi_sliced p_sliced[1];
722
723     if ( vbi_raw_decode( &p_sys->rd_wss, p_sys->p_wss_buffer, p_sliced ) == 0 )
724     {
725         p_sys->i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;
726     }
727     else
728     {
729         unsigned int i_old_aspect = p_sys->i_aspect;
730         uint8_t *p = p_sliced[0].data;
731         int i_aspect, i_parity;
732
733         i_aspect = p[0] & 15;
734         i_parity = i_aspect;
735         i_parity ^= i_parity >> 2;
736         i_parity ^= i_parity >> 1;
737         i_aspect &= 7;
738
739         if ( !(i_parity & 1) )
740             msg_Warn( p_demux, "WSS parity error" );
741         else if ( i_aspect == 7 )
742             p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
743         else
744             p_sys->i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;
745
746         if ( p_sys->i_aspect != i_old_aspect )
747             msg_Dbg( p_demux, "new WSS information (ra=%x md=%x cod=%x hlp=%x rvd=%x sub=%x pos=%x srd=%x c=%x cp=%x)",
748                      i_aspect, (p[0] & 0x10) >> 4, (p[0] & 0x20) >> 5,
749                      (p[0] & 0x40) >> 6, (p[0] & 0x80) >> 7, p[1] & 0x01,
750                      (p[1] >> 1) & 3, (p[1] & 0x08) >> 3, (p[1] & 0x10) >> 4,
751                      (p[1] & 0x20) >> 5 );
752     }
753 }
754
755 static int InitTelx( demux_t *p_demux )
756 {
757     demux_sys_t *p_sys = p_demux->p_sys;
758     vbi_raw_decoder_init( &p_sys->rd_telx );
759
760     p_sys->rd_telx.scanning        = 625;
761     p_sys->rd_telx.sampling_format = VBI_PIXFMT_UYVY;
762     p_sys->rd_telx.sampling_rate   = 13.5e6;
763     p_sys->rd_telx.bytes_per_line  = 720 * 2;
764     p_sys->rd_telx.offset          = 9.5e-6 * 13.5e6;
765
766     p_sys->rd_telx.start[0] = p_sys->i_telx_line + 1;
767     p_sys->rd_telx.count[0] = p_sys->i_telx_count;
768     p_sys->rd_telx.start[1] = p_sys->i_telx_line + 1 + 313;
769     p_sys->rd_telx.count[1] = p_sys->i_telx_count;
770
771     p_sys->rd_telx.interlaced = FALSE;
772     p_sys->rd_telx.synchronous = TRUE;
773
774     if ( vbi_raw_decoder_add_services( &p_sys->rd_telx, VBI_SLICED_TELETEXT_B,
775                                        0 ) == 0 )
776     {
777         msg_Warn( p_demux, "cannot initialize zvbi for Teletext" );
778         vbi_raw_decoder_destroy ( &p_sys->rd_telx );
779         return VLC_EGENERIC;
780     }
781
782     p_sys->p_telx_buffer = malloc( p_sys->i_telx_count * p_sys->i_width * 4 );
783     if( !p_sys->p_telx_buffer )
784     {
785         vbi_raw_decoder_destroy ( &p_sys->rd_telx );
786         return VLC_ENOMEM;
787     }
788     return VLC_SUCCESS;
789 }
790
791 static int DecodeTelx( demux_t *p_demux )
792 {
793     demux_sys_t *p_sys = p_demux->p_sys;
794     vbi_sliced p_sliced[p_sys->i_telx_count * 2];
795     int i_nb_slices = vbi_raw_decode( &p_sys->rd_telx, p_sys->p_telx_buffer,
796                                       p_sliced );
797
798     if ( i_nb_slices )
799     {
800         /* 3, 7, 11, 15, etc. */
801         int i_nb_slices_rounded = 3 + (i_nb_slices / 4) * 4;
802         int i;
803         uint8_t *p;
804         block_t *p_block = block_Alloc( 1 + i_nb_slices_rounded * 46 );
805         if( unlikely( !p_block ) )
806             return VLC_ENOMEM;
807         p_block->p_buffer[0] = 0x10; /* FIXME ? data_identifier */
808         p = p_block->p_buffer + 1;
809
810         for ( i = 0; i < i_nb_slices; i++ )
811         {
812             int i_line = p_sliced[i].line;
813             p[0] = 0x3; /* FIXME data_unit_id == subtitles */
814             p[1] = 0x2c; /* data_unit_length */
815             /* reserved | field_parity (kind of inverted) | line */
816             p[2] = 0xc0 | (i_line > 313 ? 0 : 0x20) | (i_line % 313);
817             p[3] = 0xe4; /* framing code */
818             for ( int j = 0; j < 42; j++ )
819                 p[4 + j] = vbi_rev8( p_sliced[i].data[j] );
820             p += 46;
821         }
822
823         /* Let's stuff */
824         for ( ; i < i_nb_slices_rounded; i++ )
825         {
826             p[0] = 0xff;
827             p[1] = 0x2c;
828             memset( p + 2, 0xff, 44 );
829             p += 46;
830         }
831
832         p_block->i_dts = p_block->i_pts = p_sys->i_next_date;
833         es_out_Send( p_demux->out, p_sys->p_es_telx, p_block );
834     }
835     return VLC_SUCCESS;
836 }
837
838 static int InitAudio( demux_t *p_demux, sdi_audio_t *p_audio )
839 {
840     demux_sys_t *p_sys = p_demux->p_sys;
841     es_format_t fmt;
842
843     msg_Dbg( p_demux, "starting audio %u/%u rate:%u delay:%d", p_audio->i_group,
844              p_audio->i_pair, p_audio->i_rate, p_audio->i_delay );
845
846     es_format_Init( &fmt, AUDIO_ES, VLC_CODEC_S16L );
847     fmt.i_id = p_audio->i_id;
848     fmt.audio.i_channels          = 2;
849     fmt.audio.i_original_channels =
850     fmt.audio.i_physical_channels = AOUT_CHANS_STEREO;
851     fmt.audio.i_rate              = p_audio->i_rate;
852     fmt.audio.i_bitspersample     = 16;
853     fmt.audio.i_blockalign        = fmt.audio.i_channels *
854                                     fmt.audio.i_bitspersample / 8;
855     fmt.i_bitrate                 = fmt.audio.i_channels * fmt.audio.i_rate *
856                                     fmt.audio.i_bitspersample;
857     p_audio->p_es                 = es_out_Add( p_demux->out, &fmt );
858
859     p_audio->i_nb_samples         = p_audio->i_rate * p_sys->i_frame_rate_base
860                                     / p_sys->i_frame_rate;
861     p_audio->i_max_samples        = (float)p_audio->i_nb_samples *
862                                     (1.f + SAMPLERATE_TOLERANCE);
863
864     p_audio->p_buffer             = malloc( p_audio->i_max_samples * sizeof(int16_t) * 2 );
865     p_audio->i_left_samples       = p_audio->i_right_samples = 0;
866     p_audio->i_block_number       = 0;
867
868     if( unlikely( !p_audio->p_buffer ) )
869         return VLC_ENOMEM;
870     return VLC_SUCCESS;
871 }
872
873 /* Fast and efficient linear resampling routine */
874 static void ResampleAudio( int16_t *p_out, int16_t *p_in,
875                            unsigned int i_out, unsigned int i_in )
876 {
877     unsigned int i_remainder = 0;
878     float f_last_sample = (float)*p_in / 32768.f;
879
880     *p_out = *p_in;
881     p_out += 2;
882     p_in += 2;
883
884     for ( unsigned int i = 1; i < i_in; i++ )
885     {
886         float f_in = (float)*p_in / 32768.f;
887         while ( i_remainder < i_out )
888         {
889             float f_out = f_last_sample;
890             f_out += (f_in - f_last_sample) * i_remainder / i_out;
891             if ( f_out >= 1.f ) *p_out = 32767;
892             else if ( f_out < -1.f ) *p_out = -32768;
893             else *p_out = f_out * 32768.f;
894             p_out += 2;
895             i_remainder += i_in;
896         }
897
898         f_last_sample = f_in;
899         p_in += 2;
900         i_remainder -= i_out;
901     }
902 }
903
904 static int DecodeAudio( demux_t *p_demux, sdi_audio_t *p_audio )
905 {
906     demux_sys_t *p_sys = p_demux->p_sys;
907     block_t *p_block;
908     int16_t *p_output;
909
910     if ( p_audio->p_buffer == NULL )
911         return VLC_EGENERIC;
912     if ( !p_audio->i_left_samples && !p_audio->i_right_samples )
913     {
914         msg_Warn( p_demux, "no audio %u/%u", p_audio->i_group,
915                   p_audio->i_pair );
916         return VLC_EGENERIC;
917     }
918     if ( p_audio->i_left_samples <
919             (float)p_audio->i_nb_samples * (1.f - SAMPLERATE_TOLERANCE) ||
920         p_audio->i_left_samples >
921             (float)p_audio->i_nb_samples * (1.f + SAMPLERATE_TOLERANCE) )
922     {
923         msg_Warn( p_demux,
924             "left samplerate out of tolerance for audio %u/%u (%u vs. %u)",
925             p_audio->i_group, p_audio->i_pair,
926             p_audio->i_left_samples, p_audio->i_nb_samples );
927         return VLC_EGENERIC;
928     }
929     if ( p_audio->i_right_samples <
930             (float)p_audio->i_nb_samples * (1.f - SAMPLERATE_TOLERANCE) ||
931         p_audio->i_right_samples >
932             (float)p_audio->i_nb_samples * (1.f + SAMPLERATE_TOLERANCE) )
933     {
934         msg_Warn( p_demux,
935             "right samplerate out of tolerance for audio %u/%u (%u vs. %u)",
936             p_audio->i_group, p_audio->i_pair,
937             p_audio->i_right_samples, p_audio->i_nb_samples );
938         return VLC_EGENERIC;
939     }
940
941     p_block = block_Alloc( p_audio->i_nb_samples * sizeof(int16_t) * 2 );
942     if( unlikely( !p_block ) )
943         return VLC_ENOMEM;
944     p_block->i_dts = p_block->i_pts = p_sys->i_next_date
945         + (mtime_t)p_audio->i_delay * INT64_C(1000000) / p_audio->i_rate;
946     p_output = (int16_t *)p_block->p_buffer;
947
948     if ( p_audio->i_left_samples == p_audio->i_nb_samples &&
949          p_audio->i_right_samples == p_audio->i_nb_samples )
950         memcpy( p_output, p_audio->p_buffer,
951                     p_audio->i_nb_samples * sizeof(int16_t) * 2 );
952     else
953     {
954         ResampleAudio( p_output, p_audio->p_buffer,
955                        p_audio->i_nb_samples, p_audio->i_left_samples );
956
957         ResampleAudio( p_output + 1, p_audio->p_buffer + 1,
958                        p_audio->i_nb_samples, p_audio->i_right_samples );
959     }
960
961     es_out_Send( p_demux->out, p_audio->p_es, p_block );
962     return VLC_SUCCESS;
963 }
964
965 static int DecodeFrame( demux_t *p_demux )
966 {
967     demux_sys_t *p_sys = p_demux->p_sys;
968
969     if ( p_sys->b_vbi )
970     {
971         DecodeWSS( p_demux );
972
973         if ( p_sys->i_height == 576 )
974         {
975             /* For PAL, erase first half of line 23, last half of line 623,
976              * and line 624 ; no need to erase chrominance */
977             memset( p_sys->p_y, 0, p_sys->i_width / 2 );
978             memset( p_sys->p_y + p_sys->i_width * 574 + p_sys->i_width / 2,
979                         0, p_sys->i_width * 3 / 2 );
980         }
981     }
982
983     if ( p_sys->i_telx_count )
984         if ( DecodeTelx( p_demux ) != VLC_SUCCESS )
985             return VLC_ENOMEM;
986
987     for ( int i = 0; i < MAX_AUDIOS; i++ )
988     {
989         if ( p_sys->p_audios[i].i_group && p_sys->p_audios[i].p_es != NULL )
990             if( DecodeAudio( p_demux, &p_sys->p_audios[i] ) != VLC_SUCCESS )
991                 return VLC_EGENERIC;
992     }
993
994     DecodeVideo( p_demux );
995
996     es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_next_date );
997     p_sys->i_next_date += p_sys->i_incr;
998
999     if( NewFrame( p_demux ) != VLC_SUCCESS )
1000         return VLC_ENOMEM;
1001
1002     return VLC_SUCCESS;
1003 }
1004
1005 /*****************************************************************************
1006  * SDI syntax parsing stuff
1007  *****************************************************************************/
1008 #define FIELD_1_VBLANK_EAV  0xB6
1009 #define FIELD_1_VBLANK_SAV  0xAB
1010 #define FIELD_1_ACTIVE_EAV  0x9D
1011 #define FIELD_1_ACTIVE_SAV  0x80
1012 #define FIELD_2_VBLANK_EAV  0xF1
1013 #define FIELD_2_VBLANK_SAV  0xEC
1014 #define FIELD_2_ACTIVE_EAV  0xDA
1015 #define FIELD_2_ACTIVE_SAV  0xC7
1016
1017 static const uint8_t *FindReferenceCode( uint8_t i_code,
1018                                          const uint8_t *p_parser,
1019                                          const uint8_t *p_end )
1020 {
1021     while ( p_parser <= p_end - 5 )
1022     {
1023         if ( p_parser[0] == 0xff && p_parser[1] == 0x3 && p_parser[2] == 0x0
1024               && p_parser[3] == 0x0 && p_parser[4] == i_code )
1025             return p_parser;
1026         p_parser += 5;
1027     }
1028
1029     return NULL;
1030 }
1031
1032 static const uint8_t *CountReference( unsigned int *pi_count, uint8_t i_code,
1033                                       const uint8_t *p_parser,
1034                                       const uint8_t *p_end )
1035 {
1036     const uint8_t *p_tmp = FindReferenceCode( i_code, p_parser, p_end );
1037     if ( p_tmp == NULL )
1038     {
1039         *pi_count += p_end - p_parser;
1040         return NULL;
1041     }
1042     *pi_count += p_tmp - p_parser;
1043     return p_tmp;
1044 }
1045
1046 static const uint8_t *GetLine( demux_t *p_demux, const uint8_t **pp_parser,
1047                                const uint8_t *p_end )
1048 {
1049     demux_sys_t *p_sys = p_demux->p_sys;
1050     unsigned int i_total_size = p_sys->i_anc_size + p_sys->i_active_size;
1051     const uint8_t *p_tmp;
1052
1053     if ( p_sys->i_line_buffer )
1054     {
1055         unsigned int i_remaining = i_total_size - p_sys->i_line_buffer;
1056         memcpy( p_sys->p_line_buffer + p_sys->i_line_buffer,
1057                                    *pp_parser, i_remaining );
1058         *pp_parser += i_remaining;
1059         p_sys->i_line_buffer = 0;
1060
1061         return p_sys->p_line_buffer;
1062     }
1063
1064     if ( p_end - *pp_parser < (int)i_total_size )
1065     {
1066         memcpy( p_sys->p_line_buffer, *pp_parser,
1067                                    p_end - *pp_parser );
1068         p_sys->i_line_buffer = p_end - *pp_parser;
1069         return NULL;
1070     }
1071
1072     p_tmp = *pp_parser;
1073     *pp_parser += i_total_size;
1074     return p_tmp;
1075 }
1076
1077 #define U   (uint16_t)((p_line[0]) | ((p_line[1] & 0x3) << 8))
1078 #define Y1  (uint16_t)((p_line[1] >> 2) | ((p_line[2] & 0xf) << 6))
1079 #define V   (uint16_t)((p_line[2] >> 4) | ((p_line[3] & 0x3f) << 4))
1080 #define Y2  (uint16_t)((p_line[3] >> 6) | (p_line[4] << 2))
1081
1082 static void UnpackVBI( const uint8_t *p_line, unsigned int i_size,
1083                        uint8_t *p_dest )
1084 {
1085     const uint8_t *p_end = p_line + i_size;
1086
1087     while ( p_line < p_end )
1088     {
1089         *p_dest++ = (U + 2) / 4;
1090         *p_dest++ = (Y1 + 2) / 4;
1091         *p_dest++ = (V + 2) / 4;
1092         *p_dest++ = (Y2 + 2) / 4;
1093         p_line += 5;
1094     }
1095 }
1096
1097 /* For lines 0 [4] or 1 [4] */
1098 static void Unpack01( const uint8_t *p_line, unsigned int i_size,
1099                       uint8_t *p_y, uint8_t *p_u, uint8_t *p_v )
1100 {
1101     const uint8_t *p_end = p_line + i_size;
1102
1103     while ( p_line < p_end )
1104     {
1105         *p_u++ = (U + 2) / 4;
1106         *p_y++ = (Y1 + 2) / 4;
1107         *p_v++ = (V + 2) / 4;
1108         *p_y++ = (Y2 + 2) / 4;
1109         p_line += 5;
1110     }
1111 }
1112
1113 /* For lines 2 [4] */
1114 static void Unpack2( const uint8_t *p_line, unsigned int i_size,
1115                      uint8_t *p_y, uint8_t *p_u, uint8_t *p_v )
1116 {
1117     const uint8_t *p_end = p_line + i_size;
1118
1119     while ( p_line < p_end )
1120     {
1121         uint16_t tmp;
1122         tmp = 3 * *p_u;
1123         tmp += (U + 2) / 4;
1124         *p_u++ = tmp / 4;
1125         *p_y++ = (Y1 + 2) / 4;
1126         tmp = 3 * *p_v;
1127         tmp += (V + 2) / 4;
1128         *p_v++ = tmp / 4;
1129         *p_y++ = (Y2 + 2) / 4;
1130         p_line += 5;
1131     }
1132 }
1133
1134 /* For lines 3 [4] */
1135 static void Unpack3( const uint8_t *p_line, unsigned int i_size,
1136                      uint8_t *p_y, uint8_t *p_u, uint8_t *p_v )
1137 {
1138     const uint8_t *p_end = p_line + i_size;
1139
1140     while ( p_line < p_end )
1141     {
1142         uint16_t tmp;
1143         tmp = *p_u;
1144         tmp += 3 * (U + 2) / 4;
1145         *p_u++ = tmp / 4;
1146         *p_y++ = (Y1 + 2) / 4;
1147         tmp = *p_v;
1148         tmp += 3 * (V + 2) / 4;
1149         *p_v++ = tmp / 4;
1150         *p_y++ = (Y2 + 2) / 4;
1151         p_line += 5;
1152     }
1153 }
1154
1155 #undef U
1156 #undef Y1
1157 #undef V
1158 #undef Y2
1159
1160 #define A0  (uint16_t)((p_anc[0]) | ((p_anc[1] & 0x3) << 8))
1161 #define A1  (uint16_t)((p_anc[1] >> 2) | ((p_anc[2] & 0xf) << 6))
1162 #define A2  (uint16_t)((p_anc[2] >> 4) | ((p_anc[3] & 0x3f) << 4))
1163 #define A3  (uint16_t)((p_anc[3] >> 6) | (p_anc[4] << 2))
1164
1165 static void UnpackAnc( const uint8_t *p_anc, unsigned int i_size,
1166                        uint16_t *p_dest )
1167 {
1168     const uint8_t *p_end = p_anc + i_size;
1169
1170     while ( p_anc <= p_end - 5 )
1171     {
1172         *p_dest++ = A0;
1173         *p_dest++ = A1;
1174         *p_dest++ = A2;
1175         *p_dest++ = A3;
1176         p_anc += 5;
1177     }
1178 }
1179
1180 #undef A0
1181 #undef A1
1182 #undef A2
1183 #undef A3
1184
1185 static int HasAncillary( const uint8_t *p_anc )
1186 {
1187     return ( (p_anc[0] == 0x0 && p_anc[1] == 0xfc && p_anc[2] == 0xff
1188                && (p_anc[3] & 0x3f) == 0x3f) );
1189 }
1190
1191 static void HandleAudioData( demux_t *p_demux, const uint16_t *p_anc,
1192                              uint8_t i_data_count, uint8_t i_group,
1193                              uint8_t i_block_number )
1194 {
1195     demux_sys_t *p_sys = p_demux->p_sys;
1196
1197     if ( i_data_count % 3 )
1198     {
1199         msg_Warn( p_demux, "malformed audio data for group %u", i_group );
1200         return;
1201     }
1202
1203     for ( int i = 0; i < MAX_AUDIOS; i++ )
1204     {
1205         sdi_audio_t *p_audio = &p_sys->p_audios[i];
1206         if ( p_audio->i_group == i_group )
1207         {
1208             const uint16_t *x = p_anc;
1209
1210             /* SMPTE 272M says that when parsing a frame, if an audio config
1211              * structure is present we will encounter it first. Otherwise
1212              * it is assumed to be 48 kHz. */
1213             if ( p_audio->p_es == NULL )
1214             {
1215                 p_audio->i_rate = 48000;
1216                 p_audio->i_delay = 0;
1217                 if( InitAudio( p_demux, p_audio ) != VLC_SUCCESS )
1218                     return;
1219             }
1220
1221             if ( i_block_number )
1222             {
1223                 if ( p_audio->i_block_number + 1 != i_block_number )
1224                     msg_Warn( p_demux,
1225                               "audio data block discontinuity (%"PRIu8"->%"PRIu8") for group %"PRIu8,
1226                               p_audio->i_block_number, i_block_number,
1227                               i_group );
1228                 if ( i_block_number == 0xff )
1229                     p_audio->i_block_number = 0;
1230                 else
1231                     p_audio->i_block_number = i_block_number;
1232             }
1233
1234             while ( x < p_anc + i_data_count )
1235             {
1236                 if ( ((*x & 0x4) && p_audio->i_pair == 2)
1237                       || (!(*x & 0x4) && p_audio->i_pair == 1) )
1238                 {
1239                     uint32_t i_tmp = (uint32_t)((x[0] & 0x1f1) >> 3)
1240                                                   | ((x[1] & 0x1ff) << 6)
1241                                                   | ((x[2] & 0x1f) << 15);
1242                     int32_t i_sample;
1243                     if ( x[2] & 0x10 )
1244                         i_sample = i_tmp | 0xfff00000;
1245                     else
1246                         i_sample = i_tmp;
1247
1248                     if ( x[0] & 0x2 )
1249                     {
1250                         if ( p_audio->i_right_samples < p_audio->i_max_samples )
1251                             p_audio->p_buffer[2 * p_audio->i_right_samples
1252                                                + 1] = (i_sample + 8) / 16;
1253                         p_audio->i_right_samples++;
1254                     }
1255                     else
1256                     {
1257                         if ( p_audio->i_left_samples < p_audio->i_max_samples )
1258                             p_audio->p_buffer[2 * p_audio->i_left_samples]
1259                                 = (i_sample + 8) / 16;
1260                         p_audio->i_left_samples++;
1261                     }
1262                 }
1263                 x += 3;
1264             }
1265         }
1266     }
1267 }
1268
1269 static void HandleAudioConfig( demux_t *p_demux, const uint16_t *p_anc,
1270                                uint8_t i_data_count, uint8_t i_group )
1271 {
1272     demux_sys_t *p_sys = p_demux->p_sys;
1273
1274     if ( i_data_count != 18 )
1275     {
1276         msg_Warn( p_demux, "malformed audio config for group %u", i_group );
1277         return;
1278     }
1279
1280     for ( int i = 0; i < MAX_AUDIOS; i++ )
1281     {
1282         sdi_audio_t *p_audio = &p_sys->p_audios[i];
1283         if ( p_audio->i_group == i_group && p_audio->p_es == NULL )
1284         {
1285             unsigned int i_rate;
1286
1287             if ( p_audio->i_pair == 2 )
1288             {
1289                 i_rate = (p_anc[2] & 0xe0) >> 5;
1290                 if ( p_anc[7] & 0x1 )
1291                 {
1292                     uint32_t i_tmp = ((p_anc[7] & 0x1fe) >> 1)
1293                                        | ((p_anc[8] & 0x1ff) << 8)
1294                                        | ((p_anc[9] & 0x1ff) << 17);
1295                     if ( p_anc[9] & 0x80 )
1296                         p_audio->i_delay = i_tmp | 0xfc000000;
1297                     else
1298                         p_audio->i_delay = i_tmp;
1299                 }
1300                 if ( p_anc[13] & 0x1 )
1301                     msg_Warn( p_demux, "asymetric audio is not supported" );
1302             }
1303             else
1304             {
1305                 i_rate = (p_anc[2] & 0xe) >> 1;
1306                 if ( p_anc[4] & 0x1 )
1307                 {
1308                     uint32_t i_tmp = ((p_anc[4] & 0x1fe) >> 1)
1309                                        | ((p_anc[5] & 0x1ff) << 8)
1310                                        | ((p_anc[6] & 0x1ff) << 17);
1311                     if ( p_anc[6] & 0x80 )
1312                         p_audio->i_delay = i_tmp | 0xfc000000;
1313                     else
1314                         p_audio->i_delay = i_tmp;
1315                 }
1316                 if ( p_anc[10] & 0x1 )
1317                     msg_Warn( p_demux, "asymetric audio is not supported" );
1318             }
1319
1320             switch ( i_rate )
1321             {
1322             case 0: p_audio->i_rate = 48000; break;
1323             case 1: p_audio->i_rate = 44100; break;
1324             case 2: p_audio->i_rate = 32000; break;
1325             default:
1326                 msg_Warn( p_demux, "unknown rate for audio %u/%u (%u)",
1327                           i_group, p_sys->p_audios[i].i_pair, i_rate );
1328                 continue;
1329             }
1330
1331             if( InitAudio( p_demux, p_audio ) != VLC_SUCCESS )
1332                 return;
1333         }
1334     }
1335 }
1336
1337 /*
1338  * Ancillary packet structure:
1339  *  byte 0: Ancillary Data Flag (0)
1340  *  byte 1: Ancillary Data Flag (0x3ff)
1341  *  byte 2: Ancillary Data Flag (0x3ff)
1342  *  byte 3: Data ID (2 high order bits = parity)
1343  *  byte 4: Data Block Number 1-255 or 0=unknown (if DID < 0x80)
1344  *       or Secondary Data ID (if DID >= 0x80)
1345  *  byte 5: Data Count (10 bits)
1346  *  byte 6+DC: Checksum
1347  */
1348 static void HandleAncillary( demux_t *p_demux, const uint16_t *p_anc,
1349                              unsigned int i_size )
1350 {
1351     uint8_t i_data_count;
1352
1353     if ( i_size < 7
1354           || p_anc[0] != 0x0 || p_anc[1] != 0x3ff || p_anc[2] != 0x3ff )
1355         return;
1356
1357     i_data_count = p_anc[5] & 0xff;
1358     if ( i_size - 6 < i_data_count )
1359     {
1360         msg_Warn( p_demux, "malformed ancillary packet (size %u > %u)",
1361                   i_data_count, i_size - 6 );
1362         return;
1363     }
1364
1365     switch ( p_anc[3] ) /* Data ID */
1366     {
1367     case 0x2ff:
1368         HandleAudioData( p_demux, p_anc + 6, i_data_count, 1, p_anc[4] & 0xff );
1369         break;
1370     case 0x1fd:
1371         HandleAudioData( p_demux, p_anc + 6, i_data_count, 2, p_anc[4] & 0xff );
1372         break;
1373     case 0x1fb:
1374         HandleAudioData( p_demux, p_anc + 6, i_data_count, 3, p_anc[4] & 0xff );
1375         break;
1376     case 0x2f9:
1377         HandleAudioData( p_demux, p_anc + 6, i_data_count, 4, p_anc[4] & 0xff );
1378         break;
1379
1380     case 0x1ef:
1381         HandleAudioConfig( p_demux, p_anc + 6, i_data_count, 1 );
1382         break;
1383     case 0x2ee:
1384         HandleAudioConfig( p_demux, p_anc + 6, i_data_count, 2 );
1385         break;
1386     case 0x2ed:
1387         HandleAudioConfig( p_demux, p_anc + 6, i_data_count, 3 );
1388         break;
1389     case 0x1ec:
1390         HandleAudioConfig( p_demux, p_anc + 6, i_data_count, 4 );
1391         break;
1392
1393     /* Extended data packets, same order */
1394     case 0x1fe:
1395     case 0x2fc:
1396     case 0x2fa:
1397     case 0x1f8:
1398
1399     default:
1400         break;
1401
1402     case 0x88: /* non-conforming ANC packet */
1403         p_anc += 7;
1404         i_size -= 7;
1405         while ( i_size >= 7 && (p_anc[0] != 0x0 || p_anc[1] != 0x3ff
1406                                  || p_anc[2] != 0x3ff) )
1407         {
1408             p_anc++;
1409             i_size--;
1410         }
1411         if ( i_size >= 7 )
1412             HandleAncillary( p_demux, p_anc, i_size );
1413         return;
1414     }
1415
1416     return HandleAncillary( p_demux, p_anc + i_data_count + 7,
1417                             i_size - i_data_count - 7 );
1418
1419 }
1420
1421 static int HandleSDBuffer( demux_t *p_demux, uint8_t *p_buffer,
1422                            unsigned int i_buffer_size )
1423 {
1424     demux_sys_t *p_sys = p_demux->p_sys;
1425     const uint8_t *p_parser = p_buffer;
1426     const uint8_t *p_end = p_parser + i_buffer_size;
1427     const uint8_t *p_line;
1428
1429     if ( p_sys->i_state != STATE_SYNC
1430           && p_sys->i_last_state_change < mdate() - RESYNC_TIMEOUT )
1431     {
1432         p_sys->i_state = STATE_NOSYNC;
1433         p_sys->i_last_state_change = mdate();
1434         return VLC_EGENERIC;
1435     }
1436
1437     switch ( p_sys->i_state )
1438     {
1439     case STATE_NOSYNC:
1440     default:
1441         p_parser = FindReferenceCode( FIELD_2_VBLANK_SAV, p_parser, p_end );
1442         if ( p_parser == NULL )
1443             break;
1444         p_sys->i_state = STATE_STARTSYNC;
1445         p_sys->i_last_state_change = mdate();
1446
1447     case STATE_STARTSYNC:
1448         p_parser = FindReferenceCode( FIELD_1_VBLANK_EAV, p_parser, p_end );
1449         if ( p_parser == NULL )
1450             break;
1451         p_sys->i_anc_size = 0;
1452         p_sys->i_state = STATE_ANCSYNC;
1453         p_sys->i_last_state_change = mdate();
1454
1455     case STATE_ANCSYNC:
1456         p_parser = CountReference( &p_sys->i_anc_size,
1457                                    FIELD_1_VBLANK_SAV, p_parser, p_end );
1458         if ( p_parser == NULL )
1459             break;
1460         p_sys->i_active_size = 0;
1461         p_sys->i_state = STATE_LINESYNC;
1462         p_sys->i_last_state_change = mdate();
1463
1464     case STATE_LINESYNC:
1465         p_parser = CountReference( &p_sys->i_active_size,
1466                                    FIELD_1_VBLANK_EAV, p_parser, p_end );
1467         if ( p_parser == NULL )
1468             break;
1469         p_sys->i_picture_size = p_sys->i_anc_size + p_sys->i_active_size;
1470         p_sys->i_state = STATE_ACTIVESYNC;
1471         p_sys->i_last_state_change = mdate();
1472
1473     case STATE_ACTIVESYNC:
1474         p_parser = CountReference( &p_sys->i_picture_size,
1475                                    FIELD_1_ACTIVE_EAV, p_parser, p_end );
1476         if ( p_parser == NULL )
1477             break;
1478         p_sys->i_line_offset = p_sys->i_picture_size
1479                              / (p_sys->i_anc_size + p_sys->i_active_size);
1480         p_sys->i_state = STATE_VBLANKSYNC;
1481         p_sys->i_last_state_change = mdate();
1482
1483     case STATE_VBLANKSYNC:
1484         p_parser = CountReference( &p_sys->i_picture_size,
1485                                    FIELD_2_ACTIVE_EAV, p_parser, p_end );
1486         if ( p_parser == NULL )
1487             break;
1488         p_sys->i_state = STATE_PICSYNC;
1489         p_sys->i_last_state_change = mdate();
1490
1491     case STATE_PICSYNC:
1492         p_parser = CountReference( &p_sys->i_picture_size,
1493                                    FIELD_1_VBLANK_EAV, p_parser, p_end );
1494         if ( p_parser == NULL )
1495             break;
1496
1497         if ( p_sys->i_picture_size
1498               % (p_sys->i_anc_size + p_sys->i_active_size) )
1499         {
1500             msg_Warn( p_demux, "wrong picture size (anc=%d active=%d total=%d offset=%d), syncing",
1501                  p_sys->i_anc_size, p_sys->i_active_size,
1502                  p_sys->i_picture_size, p_sys->i_line_offset + 1 );
1503             p_sys->i_state = STATE_NOSYNC;
1504             p_sys->i_last_state_change = mdate();
1505             break;
1506         }
1507
1508         p_sys->i_nb_lines = p_sys->i_picture_size
1509                              / (p_sys->i_anc_size + p_sys->i_active_size);
1510         InitVideo( p_demux );
1511         msg_Dbg( p_demux,
1512                  "acquired sync, anc=%d active=%d lines=%d offset=%d",
1513                  p_sys->i_anc_size, p_sys->i_active_size,
1514                  p_sys->i_nb_lines, p_sys->i_line_offset + 1 );
1515         p_sys->i_state = STATE_SYNC;
1516         if( StartDecode( p_demux ) != VLC_SUCCESS )
1517         {
1518             StopDecode( p_demux );
1519             return VLC_ENOMEM;
1520         }
1521         p_sys->i_current_line = 0;
1522         p_sys->p_line_buffer = malloc( p_sys->i_anc_size
1523                                         + p_sys->i_active_size );
1524         if( !p_sys->p_line_buffer )
1525         {
1526             StopDecode( p_demux );
1527             return VLC_ENOMEM;
1528         }
1529         p_sys->i_line_buffer = 0;
1530
1531     case STATE_SYNC:
1532         while ( (p_line = GetLine( p_demux, &p_parser, p_end )) != NULL )
1533         {
1534             bool b_field = p_sys->b_hd ? false :
1535                 (p_sys->i_current_line >= p_sys->i_nb_lines / 2);
1536             unsigned int i_field_height = p_sys->b_hd ? p_sys->i_height :
1537                 p_sys->i_height / 2;
1538             unsigned int i_field_line = b_field ?
1539                 p_sys->i_current_line - (p_sys->i_nb_lines + 1) / 2 :
1540                 p_sys->i_current_line;
1541             bool b_vbi = i_field_line < p_sys->i_line_offset ||
1542                 i_field_line >= p_sys->i_line_offset + i_field_height;
1543             unsigned int anc = p_sys->i_anc_size;
1544
1545             if ( p_line[0] != 0xff || p_line[1] != 0x3
1546                   || p_line[2] != 0x0 || p_line[3] != 0x0
1547                   || p_line[anc+0] != 0xff || p_line[anc+1] != 0x3
1548                   || p_line[anc+2] != 0x0 || p_line[anc+3] != 0x0
1549                   || (!b_field && b_vbi &&
1550                       (p_line[4] != FIELD_1_VBLANK_EAV ||
1551                        p_line[anc+4] != FIELD_1_VBLANK_SAV))
1552                   || (!b_field && !b_vbi &&
1553                       (p_line[4] != FIELD_1_ACTIVE_EAV ||
1554                        p_line[anc+4] != FIELD_1_ACTIVE_SAV))
1555                   || (b_field && b_vbi &&
1556                       (p_line[4] != FIELD_2_VBLANK_EAV ||
1557                        p_line[anc+4] != FIELD_2_VBLANK_SAV))
1558                   || (b_field && !b_vbi &&
1559                       (p_line[4] != FIELD_2_ACTIVE_EAV ||
1560                        p_line[anc+4] != FIELD_2_ACTIVE_SAV)) )
1561             {
1562                 msg_Warn( p_demux, "lost sync line:%u SAV:%x EAV:%x",
1563                           p_sys->i_current_line + 1, p_line[4], p_line[anc+4] );
1564                 StopDecode( p_demux );
1565                 p_sys->i_state = STATE_NOSYNC;
1566                 p_sys->i_last_state_change = mdate();
1567                 break;
1568             }
1569
1570             if ( HasAncillary( p_line + 5 ) )
1571             {
1572                 /* HANC */
1573                 unsigned int i_anc_words = (p_sys->i_anc_size - 5) * 4 / 5;
1574                 uint16_t p_anc[i_anc_words];
1575                 UnpackAnc( p_line + 5, p_sys->i_anc_size - 5, p_anc );
1576                 HandleAncillary( p_demux, p_anc, i_anc_words );
1577             }
1578
1579             if ( !b_vbi )
1580             {
1581                 unsigned int i_active_field_line = i_field_line
1582                                                     - p_sys->i_line_offset;
1583                 unsigned int i_active_line = b_field
1584                                               + i_active_field_line * 2;
1585                 if ( !(i_active_field_line % 2) && !b_field )
1586                     Unpack01( p_line + anc + 5, p_sys->i_active_size - 5,
1587                               p_sys->p_y + p_sys->i_width * i_active_line,
1588                               p_sys->p_u + (p_sys->i_width / 2)
1589                                * (i_active_line / 2),
1590                               p_sys->p_v + (p_sys->i_width / 2)
1591                                * (i_active_line / 2) );
1592                 else if ( !(i_active_field_line % 2) )
1593                     Unpack01( p_line + anc + 5, p_sys->i_active_size - 5,
1594                               p_sys->p_y + p_sys->i_width * i_active_line,
1595                               p_sys->p_u + (p_sys->i_width / 2)
1596                                * (i_active_line / 2 + 1),
1597                               p_sys->p_v + (p_sys->i_width / 2)
1598                                * (i_active_line / 2 + 1) );
1599                 else if ( !b_field )
1600                     Unpack2( p_line + anc + 5, p_sys->i_active_size - 5,
1601                              p_sys->p_y + p_sys->i_width * i_active_line,
1602                              p_sys->p_u + (p_sys->i_width / 2)
1603                               * (i_active_line / 2 - 1),
1604                              p_sys->p_v + (p_sys->i_width / 2)
1605                               * (i_active_line / 2 - 1) );
1606                 else
1607                     Unpack3( p_line + anc + 5, p_sys->i_active_size - 5,
1608                              p_sys->p_y + p_sys->i_width * i_active_line,
1609                              p_sys->p_u + (p_sys->i_width / 2)
1610                               * (i_active_line / 2),
1611                              p_sys->p_v + (p_sys->i_width / 2)
1612                               * (i_active_line / 2) );
1613
1614                 if ( p_sys->b_vbi && p_sys->i_height == 576
1615                       && p_sys->i_current_line == p_sys->i_line_offset )
1616                 {
1617                     /* Line 23 is half VBI, half active */
1618                     UnpackVBI( p_line + anc + 5, p_sys->i_active_size - 5,
1619                                p_sys->p_wss_buffer );
1620                 }
1621             }
1622             else if ( p_sys->b_vbi && p_sys->i_telx_count &&
1623                       i_field_line >= p_sys->i_telx_line &&
1624                       i_field_line < p_sys->i_telx_line
1625                                       + p_sys->i_telx_count )
1626             {
1627                 UnpackVBI( p_line + anc + 5, p_sys->i_active_size - 5,
1628                     &p_sys->p_telx_buffer[(i_field_line
1629                         - p_sys->i_telx_line + b_field * p_sys->i_telx_count)
1630                         * p_sys->i_width * 2] );
1631             }
1632             else if ( b_vbi && HasAncillary( p_line + anc + 5 ) )
1633             {
1634                 /* VANC */
1635                 unsigned int i_anc_words = (p_sys->i_active_size - 5) * 4 / 5;
1636                 uint16_t p_anc[i_anc_words];
1637                 UnpackAnc( p_line + 5, p_sys->i_active_size - 5,
1638                            p_anc );
1639                 HandleAncillary( p_demux, p_anc, i_anc_words );
1640             }
1641
1642             p_sys->i_current_line++;
1643             if ( p_sys->i_current_line == p_sys->i_nb_lines )
1644             {
1645                 p_sys->i_current_line %= p_sys->i_nb_lines;
1646                 if( DecodeFrame( p_demux ) != VLC_SUCCESS )
1647                     return VLC_EGENERIC;
1648             }
1649         }
1650         break;
1651     }
1652
1653     return VLC_SUCCESS;
1654 }
1655
1656 /*****************************************************************************
1657  * Low-level device stuff
1658  *****************************************************************************/
1659 #define MAXLEN 256
1660
1661 static int ReadULSysfs( const char *psz_fmt, unsigned int i_link )
1662 {
1663     char psz_file[MAXLEN], psz_data[MAXLEN];
1664     char *psz_tmp;
1665     int i_fd;
1666     ssize_t i_ret;
1667     unsigned int i_data;
1668
1669     snprintf( psz_file, sizeof(psz_file) - 1, psz_fmt, i_link );
1670
1671     if ( (i_fd = vlc_open( psz_file, O_RDONLY )) < 0 )
1672         return i_fd;
1673
1674     i_ret = read( i_fd, psz_data, sizeof(psz_data) );
1675     close( i_fd );
1676
1677     if ( i_ret < 0 )
1678         return i_ret;
1679
1680     i_data = strtoul( psz_data, &psz_tmp, 0 );
1681     if ( *psz_tmp != '\n' )
1682         return -1;
1683
1684     return i_data;
1685 }
1686
1687 static ssize_t WriteULSysfs( const char *psz_fmt, unsigned int i_link,
1688                              unsigned int i_buf )
1689 {
1690     char psz_file[MAXLEN], psz_data[MAXLEN];
1691     int i_fd;
1692     ssize_t i_ret;
1693
1694     snprintf( psz_file, sizeof(psz_file) -1, psz_fmt, i_link );
1695
1696     snprintf( psz_data, sizeof(psz_data) -1, "%u\n", i_buf );
1697
1698     if ( (i_fd = vlc_open( psz_file, O_WRONLY )) < 0 )
1699         return i_fd;
1700
1701     i_ret = write( i_fd, psz_data, strlen(psz_data) + 1 );
1702     close( i_fd );
1703     return i_ret;
1704 }
1705
1706 static int InitCapture( demux_t *p_demux )
1707 {
1708     demux_sys_t *p_sys = p_demux->p_sys;
1709     const int i_page_size = getpagesize();
1710     unsigned int i_bufmemsize;
1711     int i_ret;
1712     char psz_dev[MAXLEN];
1713
1714     /* 10-bit mode or nothing */
1715     if ( WriteULSysfs( SDI_MODE_FILE, p_sys->i_link, SDI_CTL_MODE_10BIT ) < 0 )
1716     {
1717         msg_Err( p_demux, "couldn't write file " SDI_MODE_FILE, p_sys->i_link );
1718         return VLC_EGENERIC;
1719     }
1720
1721     if ( (i_ret = ReadULSysfs( SDI_BUFFERS_FILE, p_sys->i_link )) < 0 )
1722     {
1723         msg_Err( p_demux, "couldn't read file " SDI_BUFFERS_FILE,
1724                  p_sys->i_link );
1725         return VLC_EGENERIC;
1726     }
1727     p_sys->i_buffers = i_ret;
1728     p_sys->i_current_buffer = 0;
1729
1730     if ( (i_ret = ReadULSysfs( SDI_BUFSIZE_FILE, p_sys->i_link )) < 0 )
1731     {
1732         msg_Err( p_demux, "couldn't read file " SDI_BUFSIZE_FILE,
1733                  p_sys->i_link );
1734         return VLC_EGENERIC;
1735     }
1736     p_sys->i_buffer_size = i_ret;
1737     if ( p_sys->i_buffer_size % 20 )
1738     {
1739         msg_Err( p_demux, "buffer size must be a multiple of 20" );
1740         return VLC_EGENERIC;
1741     }
1742
1743     snprintf( psz_dev, sizeof(psz_dev) - 1, SDI_DEVICE, p_sys->i_link );
1744     if ( (p_sys->i_fd = vlc_open( psz_dev, O_RDONLY ) ) < 0 )
1745     {
1746         msg_Err( p_demux, "couldn't open device %s", psz_dev );
1747         return VLC_EGENERIC;
1748     }
1749
1750     i_bufmemsize = ((p_sys->i_buffer_size + i_page_size - 1) / i_page_size)
1751                      * i_page_size;
1752     p_sys->pp_buffers = malloc( p_sys->i_buffers * sizeof(uint8_t *) );
1753     if( !p_sys->pp_buffers )
1754         return VLC_ENOMEM;
1755
1756     for ( unsigned int i = 0; i < p_sys->i_buffers; i++ )
1757     {
1758         if ( (p_sys->pp_buffers[i] = mmap( NULL, p_sys->i_buffer_size,
1759                                            PROT_READ, MAP_SHARED, p_sys->i_fd,
1760                                            i * i_bufmemsize )) == MAP_FAILED )
1761         {
1762             msg_Err( p_demux, "couldn't mmap(%d): %s", i,
1763                      vlc_strerror_c(errno) );
1764             free( p_sys->pp_buffers );
1765             return VLC_EGENERIC;
1766         }
1767     }
1768
1769     return VLC_SUCCESS;
1770 }
1771
1772 static void CloseCapture( demux_t *p_demux )
1773 {
1774     demux_sys_t *p_sys = p_demux->p_sys;
1775
1776     StopDecode( p_demux );
1777     for ( unsigned int i = 0; i < p_sys->i_buffers; i++ )
1778         munmap( p_sys->pp_buffers[i], p_sys->i_buffer_size );
1779     close( p_sys->i_fd );
1780     free( p_sys->pp_buffers );
1781 }
1782
1783 static int Capture( demux_t *p_demux )
1784 {
1785     demux_sys_t *p_sys = p_demux->p_sys;
1786     struct pollfd pfd;
1787
1788     pfd.fd = p_sys->i_fd;
1789     pfd.events = POLLIN | POLLPRI;
1790
1791     if ( poll( &pfd, 1, READ_TIMEOUT ) < 0 )
1792     {
1793         msg_Warn( p_demux, "couldn't poll(): %s", vlc_strerror_c(errno) );
1794         return VLC_EGENERIC;
1795     }
1796
1797     if ( pfd.revents & POLLPRI )
1798     {
1799         unsigned int i_val;
1800
1801         if ( ioctl( p_sys->i_fd, SDI_IOC_RXGETEVENTS, &i_val ) < 0 )
1802             msg_Warn( p_demux, "couldn't SDI_IOC_RXGETEVENTS: %s",
1803                       vlc_strerror_c(errno) );
1804         else
1805         {
1806             if ( i_val & SDI_EVENT_RX_BUFFER )
1807                 msg_Warn( p_demux, "driver receive buffer queue overrun" );
1808             if ( i_val & SDI_EVENT_RX_FIFO )
1809                 msg_Warn( p_demux, "onboard receive FIFO overrun");
1810             if ( i_val & SDI_EVENT_RX_CARRIER )
1811                 msg_Warn( p_demux, "carrier status change");
1812         }
1813
1814         p_sys->i_next_date += CLOCK_GAP;
1815     }
1816
1817     if ( pfd.revents & POLLIN )
1818     {
1819         int i_ret;
1820
1821         if ( ioctl( p_sys->i_fd, SDI_IOC_DQBUF, p_sys->i_current_buffer ) < 0 )
1822         {
1823             msg_Warn( p_demux, "couldn't SDI_IOC_DQBUF: %s",
1824                       vlc_strerror_c(errno) );
1825             return VLC_EGENERIC;
1826         }
1827
1828         i_ret = HandleSDBuffer( p_demux,
1829                                 p_sys->pp_buffers[p_sys->i_current_buffer],
1830                                 p_sys->i_buffer_size );
1831
1832         if ( ioctl( p_sys->i_fd, SDI_IOC_QBUF, p_sys->i_current_buffer ) < 0 )
1833         {
1834             msg_Warn( p_demux, "couldn't SDI_IOC_QBUF: %s",
1835                       vlc_strerror_c(errno) );
1836             return VLC_EGENERIC;
1837         }
1838
1839         if ( i_ret == VLC_SUCCESS )
1840         {
1841             p_sys->i_current_buffer++;
1842             p_sys->i_current_buffer %= p_sys->i_buffers;
1843         }
1844         else
1845         {
1846             /* Reference codes do not start on a multiple of 5. This sometimes
1847              * happen. We really don't want to allow this. */
1848             msg_Warn( p_demux, "resetting board" );
1849             CloseCapture( p_demux );
1850             InitCapture( p_demux );
1851         }
1852     }
1853
1854     return VLC_SUCCESS;
1855 }
1856