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