1 /*****************************************************************************
2 * linsys_sdi.c: SDI capture for Linear Systems/Computer Modules cards
3 *****************************************************************************
4 * Copyright (C) 2009-2011 VideoLAN
6 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
37 #include <vlc_common.h>
38 #include <vlc_plugin.h>
40 #include <vlc_input.h>
41 #include <vlc_access.h>
42 #include <vlc_demux.h>
46 #include "linsys_sdi.h"
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)
60 #define DEMUX_BUFFER_SIZE 1350000
62 #define SAMPLERATE_TOLERANCE 0.1
64 /*****************************************************************************
66 *****************************************************************************/
67 #define CACHING_TEXT N_("Caching value in ms")
68 #define CACHING_LONGTEXT N_( \
69 "Allows you to modify the default caching value for sdi capture " \
70 "streams. This value should be set in millisecond units." )
71 #define LINK_TEXT N_("Link #")
72 #define LINK_LONGTEXT N_( \
73 "Allows you to set the desired link of the board for the capture (starting at 0)." )
74 #define VIDEO_TEXT N_("Video ID")
75 #define VIDEO_LONGTEXT N_( \
76 "Allows you to set the ES ID of the video." )
77 #define VIDEO_ASPECT_TEXT N_("Aspect ratio")
78 #define VIDEO_ASPECT_LONGTEXT N_( \
79 "Allows you to force the aspect ratio of the video." )
80 #define AUDIO_TEXT N_("Audio configuration")
81 #define AUDIO_LONGTEXT N_( \
82 "Allows you to set audio configuration (id=group,pair:id=group,pair...)." )
83 #define TELX_TEXT N_("Teletext configuration")
84 #define TELX_LONGTEXT N_( \
85 "Allows you to set Teletext configuration (id=line1-lineN with both fields)." )
86 #define TELX_LANG_TEXT N_("Teletext language")
87 #define TELX_LANG_LONGTEXT N_( \
88 "Allows you to set Teletext language (page=lang/type,...)." )
90 static int Open ( vlc_object_t * );
91 static void Close( vlc_object_t * );
92 static int DemuxOpen ( vlc_object_t * );
93 static void DemuxClose( vlc_object_t * );
96 set_description( N_("SDI Input") )
97 set_shortname( N_("sdi") )
98 set_category( CAT_INPUT )
99 set_subcategory( SUBCAT_INPUT_ACCESS )
101 add_integer( "linsys-sdi-caching", DEFAULT_PTS_DELAY / 1000,
102 CACHING_TEXT, CACHING_LONGTEXT, true )
103 add_integer( "linsys-sdi-link", 0,
104 LINK_TEXT, LINK_LONGTEXT, true )
106 add_integer( "linsys-sdi-id-video", 0, VIDEO_TEXT, VIDEO_LONGTEXT, true )
107 add_string( "linsys-sdi-aspect-ratio", "", VIDEO_ASPECT_TEXT,
108 VIDEO_ASPECT_LONGTEXT, true )
109 add_string( "linsys-sdi-audio", "0=1,1", AUDIO_TEXT, AUDIO_LONGTEXT, true )
110 add_string( "linsys-sdi-telx", "", TELX_TEXT, TELX_LONGTEXT, true )
111 add_string( "linsys-sdi-telx-lang", "", TELX_LANG_TEXT, TELX_LANG_LONGTEXT,
114 set_capability( "access_demux", 0 )
115 add_shortcut( "linsys-sdi" )
116 set_callbacks( Open, Close )
119 set_description( N_("SDI Demux") )
120 set_capability( "demux", 0 )
121 set_callbacks( DemuxOpen, DemuxClose )
124 /*****************************************************************************
126 *****************************************************************************/
127 typedef struct sdi_audio_t
129 unsigned int i_group, i_pair;
134 uint8_t i_block_number;
136 unsigned int i_left_samples, i_right_samples, i_nb_samples, i_max_samples;
159 uint8_t **pp_buffers;
160 unsigned int i_buffers, i_current_buffer;
161 unsigned int i_buffer_size;
165 mtime_t i_last_state_change;
166 unsigned int i_anc_size, i_active_size, i_picture_size;
167 unsigned int i_line_offset, i_nb_lines;
170 unsigned int i_line_buffer;
171 unsigned int i_current_line;
172 uint8_t *p_line_buffer;
173 block_t *p_current_picture;
174 uint8_t *p_y, *p_u, *p_v;
175 uint8_t *p_wss_buffer;
176 uint8_t *p_telx_buffer;
178 /* picture decoding */
179 unsigned int i_frame_rate, i_frame_rate_base;
180 unsigned int i_width, i_height, i_aspect, i_forced_aspect;
181 unsigned int i_block_size;
182 unsigned int i_telx_line, i_telx_count;
183 char *psz_telx, *psz_telx_lang;
185 vbi_raw_decoder rd_wss, rd_telx;
191 es_out_id_t *p_es_video;
192 sdi_audio_t p_audios[MAX_AUDIOS];
193 es_out_id_t *p_es_telx;
196 static int Control( demux_t *, int, va_list );
197 static int DemuxControl( demux_t *, int, va_list );
198 static int Demux( demux_t * );
199 static int DemuxDemux( demux_t * );
201 static int InitWSS( demux_t *p_demux );
202 static int InitTelx( demux_t *p_demux );
204 static int HandleSDBuffer( demux_t *p_demux, uint8_t *p_buffer,
205 unsigned int i_buffer_size );
207 static int InitCapture( demux_t *p_demux );
208 static void CloseCapture( demux_t *p_demux );
209 static int Capture( demux_t *p_demux );
211 /*****************************************************************************
213 *****************************************************************************/
214 static int DemuxOpen( vlc_object_t *p_this )
216 demux_t *p_demux = (demux_t *)p_this;
220 /* Fill p_demux field */
221 p_demux->pf_demux = DemuxDemux;
222 p_demux->pf_control = DemuxControl;
223 p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );
224 if( unlikely(!p_sys ) )
227 p_sys->i_state = STATE_NOSYNC;
228 p_sys->i_last_state_change = mdate();
231 char *psz_ar = var_InheritString( p_demux, "linsys-sdi-aspect-ratio" );
232 if ( psz_ar != NULL )
234 psz_parser = strchr( psz_ar, ':' );
237 *psz_parser++ = '\0';
238 p_sys->i_forced_aspect = p_sys->i_aspect =
239 strtol( psz_ar, NULL, 0 ) * VOUT_ASPECT_FACTOR
240 / strtol( psz_parser, NULL, 0 );
243 p_sys->i_forced_aspect = 0;
248 p_sys->i_id_video = var_InheritInteger( p_demux, "linsys-sdi-id-video" );
251 char *psz_string = psz_parser = var_InheritString( p_demux,
252 "linsys-sdi-audio" );
255 while ( psz_parser != NULL && *psz_parser )
257 int i_id, i_group, i_pair;
258 char *psz_next = strchr( psz_parser, '=' );
259 if ( psz_next != NULL )
262 i_id = strtol( psz_parser, NULL, 0 );
263 psz_parser = psz_next + 1;
268 psz_next = strchr( psz_parser, ':' );
269 if ( psz_next != NULL )
275 if ( sscanf( psz_parser, "%d,%d", &i_group, &i_pair ) == 2 )
277 p_sys->p_audios[i].i_group = i_group;
278 p_sys->p_audios[i].i_pair = i_pair;
279 p_sys->p_audios[i].i_id = i_id;
283 msg_Warn( p_demux, "malformed audio configuration (%s)",
286 psz_parser = psz_next;
291 p_sys->psz_telx = var_InheritString( p_demux, "linsys-sdi-telx" );
293 p_sys->psz_telx_lang = var_InheritString( p_demux, "linsys-sdi-telx-lang" );
298 static int Open( vlc_object_t *p_this )
300 demux_t *p_demux = (demux_t *)p_this;
304 if ( (i_ret = DemuxOpen( p_this )) != VLC_SUCCESS )
307 /* Fill p_demux field */
308 p_demux->pf_demux = Demux;
309 p_demux->pf_control = Control;
310 p_sys = p_demux->p_sys;
312 /* Update default_pts to a suitable value for sdi access */
313 var_Create( p_demux, "linsys-sdi-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
315 p_sys->i_link = var_InheritInteger( p_demux, "linsys-sdi-link" );
317 if( InitCapture( p_demux ) != VLC_SUCCESS )
326 /*****************************************************************************
328 *****************************************************************************/
329 static void DemuxClose( vlc_object_t *p_this )
331 demux_t *p_demux = (demux_t *)p_this;
332 demux_sys_t *p_sys = p_demux->p_sys;
334 free( p_sys->psz_telx );
335 free( p_sys->psz_telx_lang );
339 static void Close( vlc_object_t *p_this )
341 demux_t *p_demux = (demux_t *)p_this;
343 CloseCapture( p_demux );
344 DemuxClose( p_this );
347 /*****************************************************************************
349 *****************************************************************************/
350 static int DemuxDemux( demux_t *p_demux )
352 block_t *p_block = stream_Block( p_demux->s, DEMUX_BUFFER_SIZE );
355 if ( p_block == NULL )
358 i_ret = HandleSDBuffer( p_demux, p_block->p_buffer, p_block->i_buffer );
359 block_Release( p_block );
361 return ( i_ret == VLC_SUCCESS );
364 static int Demux( demux_t *p_demux )
366 return ( Capture( p_demux ) == VLC_SUCCESS );
369 /*****************************************************************************
371 *****************************************************************************/
372 static int DemuxControl( demux_t *p_demux, int i_query, va_list args )
374 return demux_vaControlHelper( p_demux->s, -1, -1, 270000000, 1, i_query,
378 static int Control( demux_t *p_demux, int i_query, va_list args )
385 /* Special for access_demux */
386 case DEMUX_CAN_PAUSE:
387 case DEMUX_CAN_CONTROL_PACE:
389 pb = (bool*)va_arg( args, bool * );
393 case DEMUX_GET_PTS_DELAY:
394 pi64 = (int64_t*)va_arg( args, int64_t * );
395 *pi64 = (int64_t)var_GetInteger( p_demux, "linsys-sdi-caching" ) * 1000;
398 /* TODO implement others */
404 /*****************************************************************************
405 * Video, audio & VBI decoding
406 *****************************************************************************/
409 struct block_extension_t
411 bool b_progressive; /**< is it a progressive frame ? */
412 bool b_top_field_first; /**< which field is first */
413 unsigned int i_nb_fields; /**< # of displayed fields */
414 unsigned int i_aspect; /**< aspect ratio of frame */
417 static int NewFrame( demux_t *p_demux )
419 demux_sys_t *p_sys = p_demux->p_sys;
421 p_sys->p_current_picture = block_New( p_demux, p_sys->i_block_size );
422 if( unlikely( !p_sys->p_current_picture ) )
424 p_sys->p_y = p_sys->p_current_picture->p_buffer;
425 p_sys->p_u = p_sys->p_y + p_sys->i_width * p_sys->i_height;
426 p_sys->p_v = p_sys->p_u + p_sys->i_width * p_sys->i_height / 4;
428 for ( int i = 0; i < MAX_AUDIOS; i++ )
430 sdi_audio_t *p_audio = &p_sys->p_audios[i];
431 p_audio->i_left_samples = p_audio->i_right_samples = 0;
436 static int StartDecode( demux_t *p_demux )
438 demux_sys_t *p_sys = p_demux->p_sys;
442 p_sys->i_next_date = START_DATE;
443 p_sys->i_incr = 1000000 * p_sys->i_frame_rate_base / p_sys->i_frame_rate;
444 p_sys->i_block_size = p_sys->i_width * p_sys->i_height * 3 / 2
445 + sizeof(struct block_extension_t);
446 if( NewFrame( p_demux ) != VLC_SUCCESS )
450 es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_I420 );
451 fmt.i_id = p_sys->i_id_video;
452 fmt.video.i_frame_rate = p_sys->i_frame_rate;
453 fmt.video.i_frame_rate_base = p_sys->i_frame_rate_base;
454 fmt.video.i_width = p_sys->i_width;
455 fmt.video.i_height = p_sys->i_height;
456 int i_aspect = p_sys->i_forced_aspect ? p_sys->i_forced_aspect
458 fmt.video.i_sar_num = i_aspect * fmt.video.i_height
460 fmt.video.i_sar_den = VOUT_ASPECT_FACTOR;
461 p_sys->p_es_video = es_out_Add( p_demux->out, &fmt );
463 if ( p_sys->b_vbi && InitWSS( p_demux ) != VLC_SUCCESS )
467 psz_parser = p_sys->psz_telx;
468 if ( psz_parser != NULL && *psz_parser )
472 msg_Warn( p_demux, "VBI is unsupported on this input stream" );
477 char *psz_next = strchr( psz_parser, '=' );
478 if ( psz_next != NULL )
481 i_id = strtol( psz_parser, NULL, 0 );
482 psz_parser = psz_next + 1;
487 psz_next = strchr( psz_parser, '-' );
488 if ( psz_next != NULL )
491 p_sys->i_telx_line = strtol( psz_parser, NULL, 0 ) - 1;
492 if ( psz_next != NULL )
493 p_sys->i_telx_count = strtol( psz_next, NULL, 0 )
494 - p_sys->i_telx_line - 1 + 1;
496 p_sys->i_telx_count = 1;
498 if ( InitTelx( p_demux ) == VLC_SUCCESS )
501 uint8_t *p_dr = NULL;
503 msg_Dbg( p_demux, "capturing VBI lines %d-%d and %d-%d",
504 p_sys->i_telx_line + 1,
505 p_sys->i_telx_line + 1 + p_sys->i_telx_count - 1,
506 p_sys->i_telx_line + 1 + 313,
507 p_sys->i_telx_line + 1 + 313
508 + p_sys->i_telx_count - 1 );
510 es_format_Init( &fmt, SPU_ES, VLC_CODEC_TELETEXT );
513 /* Teletext language & type */
514 psz_parser = p_sys->psz_telx_lang;
516 while ( (psz_next = strchr( psz_parser, '=' )) != NULL )
520 if ( !psz_next[0] || !psz_next[1] || !psz_next[2] )
522 i_page = strtol( psz_parser, NULL, 0 );
524 p_dr = realloc( p_dr, i_dr_size );
525 p_dr[i_dr_size - 5] = *psz_next++;
526 p_dr[i_dr_size - 4] = *psz_next++;
527 p_dr[i_dr_size - 3] = *psz_next++;
528 if ( *psz_next == '/' )
531 p_dr[i_dr_size - 2] = strtol( psz_next, &psz_next, 0 )
534 else /* subtitle for hearing impaired */
535 p_dr[i_dr_size - 2] = 0x5 << 3;
536 p_dr[i_dr_size - 2] |= (i_page / 100) & 0x7;
537 p_dr[i_dr_size - 1] = i_page % 100;
539 if ( *psz_next == ',' )
541 psz_parser = psz_next;
544 fmt.i_extra = i_dr_size;
546 p_sys->p_es_telx = es_out_Add( p_demux->out, &fmt );
549 p_sys->i_telx_count = 0;
555 static void StopDecode( demux_t *p_demux )
557 demux_sys_t *p_sys = p_demux->p_sys;
559 if ( p_sys->i_state != STATE_SYNC )
562 free( p_sys->p_line_buffer );
564 block_Release( p_sys->p_current_picture );
565 p_sys->p_current_picture = NULL;
566 es_out_Del( p_demux->out, p_sys->p_es_video );
570 free( p_sys->p_wss_buffer );
571 p_sys->p_wss_buffer = NULL;
572 vbi_raw_decoder_destroy( &p_sys->rd_wss );
574 if ( p_sys->p_es_telx )
576 es_out_Del( p_demux->out, p_sys->p_es_telx );
577 free( p_sys->p_telx_buffer );
578 p_sys->p_telx_buffer = NULL;
579 vbi_raw_decoder_destroy( &p_sys->rd_telx );
583 for ( int i = 0; i < MAX_AUDIOS; i++ )
585 sdi_audio_t *p_audio = &p_sys->p_audios[i];
586 if ( p_audio->i_group && p_audio->p_es != NULL )
588 es_out_Del( p_demux->out, p_audio->p_es );
589 p_audio->p_es = NULL;
590 free( p_audio->p_buffer );
591 p_audio->p_buffer = NULL;
596 static void InitVideo( demux_t *p_demux )
598 demux_sys_t *p_sys = p_demux->p_sys;
599 int i_total_width = (p_sys->i_anc_size + p_sys->i_active_size) * 4 / 5;
600 p_sys->i_width = (p_sys->i_active_size - 5) * 4 / 10;
601 if ( p_sys->i_nb_lines == 625 )
604 p_sys->i_frame_rate = 25;
605 p_sys->i_frame_rate_base = 1;
606 p_sys->i_height = 576;
607 p_sys->i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;
610 else if ( p_sys->i_nb_lines == 525 )
613 p_sys->i_frame_rate = 30000;
614 p_sys->i_frame_rate_base = 1001;
615 p_sys->i_height = 480;
616 p_sys->i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;
619 else if ( p_sys->i_nb_lines == 1125 && i_total_width == 2640 )
621 /* 1080i50 or 1080p25 */
622 p_sys->i_frame_rate = 25;
623 p_sys->i_frame_rate_base = 1;
624 p_sys->i_height = 1080;
625 p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
628 else if ( p_sys->i_nb_lines == 1125 && i_total_width == 2200 )
630 /* 1080i60 or 1080p30 */
631 p_sys->i_frame_rate = 30000;
632 p_sys->i_frame_rate_base = 1001;
633 p_sys->i_height = 1080;
634 p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
637 else if ( p_sys->i_nb_lines == 750 && i_total_width == 1980 )
640 p_sys->i_frame_rate = 50;
641 p_sys->i_frame_rate_base = 1;
642 p_sys->i_height = 720;
643 p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
646 else if ( p_sys->i_nb_lines == 750 && i_total_width == 1650 )
649 p_sys->i_frame_rate = 60000;
650 p_sys->i_frame_rate_base = 1001;
651 p_sys->i_height = 720;
652 p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
657 msg_Warn( p_demux, "unable to determine video type" );
658 /* Put sensitive defaults */
659 p_sys->i_frame_rate = 25;
660 p_sys->i_frame_rate_base = 1;
661 p_sys->i_height = p_sys->i_nb_lines;
662 p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
665 p_sys->b_vbi = !p_sys->b_hd;
668 static void DecodeVideo( demux_t *p_demux )
670 demux_sys_t *p_sys = p_demux->p_sys;
671 struct block_extension_t ext;
673 /* FIXME: progressive formats ? */
674 ext.b_progressive = false;
676 ext.b_top_field_first = true;
677 ext.i_aspect = p_sys->i_forced_aspect ? p_sys->i_forced_aspect :
680 memcpy( &p_sys->p_current_picture->p_buffer[p_sys->i_block_size
681 - sizeof(struct block_extension_t)],
682 &ext, sizeof(struct block_extension_t) );
684 p_sys->p_current_picture->i_dts = p_sys->p_current_picture->i_pts
685 = p_sys->i_next_date;
686 es_out_Send( p_demux->out, p_sys->p_es_video, p_sys->p_current_picture );
689 static int InitWSS( demux_t *p_demux )
691 demux_sys_t *p_sys = p_demux->p_sys;
692 vbi_raw_decoder_init( &p_sys->rd_wss );
694 p_sys->rd_wss.scanning = 625;
695 p_sys->rd_wss.sampling_format = VBI_PIXFMT_UYVY;
696 p_sys->rd_wss.sampling_rate = 13.5e6;
697 p_sys->rd_wss.bytes_per_line = 720 * 2;
698 p_sys->rd_wss.offset = 9.5e-6 * 13.5e6;
700 p_sys->rd_wss.start[0] = 23;
701 p_sys->rd_wss.count[0] = 1;
702 p_sys->rd_wss.start[1] = 0;
703 p_sys->rd_wss.count[1] = 0;
705 p_sys->rd_wss.interlaced = FALSE;
706 p_sys->rd_wss.synchronous = TRUE;
708 if ( vbi_raw_decoder_add_services( &p_sys->rd_wss,
710 /* strict */ 2 ) == 0 )
712 msg_Warn( p_demux, "cannot initialize zvbi for WSS" );
713 vbi_raw_decoder_destroy ( &p_sys->rd_telx );
717 p_sys->p_wss_buffer = malloc( p_sys->i_width * 2 );
718 if( !p_sys->p_wss_buffer )
720 vbi_raw_decoder_destroy ( &p_sys->rd_telx );
726 static void DecodeWSS( demux_t *p_demux )
728 demux_sys_t *p_sys = p_demux->p_sys;
729 vbi_sliced p_sliced[1];
731 if ( vbi_raw_decode( &p_sys->rd_wss, p_sys->p_wss_buffer, p_sliced ) == 0 )
733 p_sys->i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;
737 unsigned int i_old_aspect = p_sys->i_aspect;
738 uint8_t *p = p_sliced[0].data;
739 int i_aspect, i_parity;
741 i_aspect = p[0] & 15;
743 i_parity ^= i_parity >> 2;
744 i_parity ^= i_parity >> 1;
747 if ( !(i_parity & 1) )
748 msg_Warn( p_demux, "WSS parity error" );
749 else if ( i_aspect == 7 )
750 p_sys->i_aspect = 16 * VOUT_ASPECT_FACTOR / 9;
752 p_sys->i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;
754 if ( p_sys->i_aspect != i_old_aspect )
755 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)",
756 i_aspect, (p[0] & 0x10) >> 4, (p[0] & 0x20) >> 5,
757 (p[0] & 0x40) >> 6, (p[0] & 0x80) >> 7, p[1] & 0x01,
758 (p[1] >> 1) & 3, (p[1] & 0x08) >> 3, (p[1] & 0x10) >> 4,
759 (p[1] & 0x20) >> 5 );
763 static int InitTelx( demux_t *p_demux )
765 demux_sys_t *p_sys = p_demux->p_sys;
766 vbi_raw_decoder_init( &p_sys->rd_telx );
768 p_sys->rd_telx.scanning = 625;
769 p_sys->rd_telx.sampling_format = VBI_PIXFMT_UYVY;
770 p_sys->rd_telx.sampling_rate = 13.5e6;
771 p_sys->rd_telx.bytes_per_line = 720 * 2;
772 p_sys->rd_telx.offset = 9.5e-6 * 13.5e6;
774 p_sys->rd_telx.start[0] = p_sys->i_telx_line + 1;
775 p_sys->rd_telx.count[0] = p_sys->i_telx_count;
776 p_sys->rd_telx.start[1] = p_sys->i_telx_line + 1 + 313;
777 p_sys->rd_telx.count[1] = p_sys->i_telx_count;
779 p_sys->rd_telx.interlaced = FALSE;
780 p_sys->rd_telx.synchronous = TRUE;
782 if ( vbi_raw_decoder_add_services( &p_sys->rd_telx, VBI_SLICED_TELETEXT_B,
785 msg_Warn( p_demux, "cannot initialize zvbi for Teletext" );
786 vbi_raw_decoder_destroy ( &p_sys->rd_telx );
790 p_sys->p_telx_buffer = malloc( p_sys->i_telx_count * p_sys->i_width * 4 );
791 if( !p_sys->p_telx_buffer )
793 vbi_raw_decoder_destroy ( &p_sys->rd_telx );
799 static int DecodeTelx( demux_t *p_demux )
801 demux_sys_t *p_sys = p_demux->p_sys;
802 vbi_sliced p_sliced[p_sys->i_telx_count * 2];
803 int i_nb_slices = vbi_raw_decode( &p_sys->rd_telx, p_sys->p_telx_buffer,
808 /* 3, 7, 11, 15, etc. */
809 int i_nb_slices_rounded = 3 + (i_nb_slices / 4) * 4;
812 block_t *p_block = block_New( p_demux,
813 1 + i_nb_slices_rounded * 46 );
814 if( unlikely( !p_block ) )
816 p_block->p_buffer[0] = 0x10; /* FIXME ? data_identifier */
817 p = p_block->p_buffer + 1;
819 for ( i = 0; i < i_nb_slices; i++ )
821 int i_line = p_sliced[i].line;
822 p[0] = 0x3; /* FIXME data_unit_id == subtitles */
823 p[1] = 0x2c; /* data_unit_length */
824 /* reserved | field_parity (kind of inverted) | line */
825 p[2] = 0xc0 | (i_line > 313 ? 0 : 0x20) | (i_line % 313);
826 p[3] = 0xe4; /* framing code */
827 for ( int j = 0; j < 42; j++ )
828 p[4 + j] = vbi_rev8( p_sliced[i].data[j] );
833 for ( ; i < i_nb_slices_rounded; i++ )
837 memset( p + 2, 0xff, 44 );
841 p_block->i_dts = p_block->i_pts = p_sys->i_next_date;
842 es_out_Send( p_demux->out, p_sys->p_es_telx, p_block );
847 static int InitAudio( demux_t *p_demux, sdi_audio_t *p_audio )
849 demux_sys_t *p_sys = p_demux->p_sys;
852 msg_Dbg( p_demux, "starting audio %u/%u rate:%u delay:%d", p_audio->i_group,
853 p_audio->i_pair, p_audio->i_rate, p_audio->i_delay );
855 es_format_Init( &fmt, AUDIO_ES, VLC_CODEC_S16L );
856 fmt.i_id = p_audio->i_id;
857 fmt.audio.i_channels = 2;
858 fmt.audio.i_physical_channels = 6;
859 fmt.audio.i_original_channels = 6;
860 fmt.audio.i_rate = p_audio->i_rate;
861 fmt.audio.i_bitspersample = 16;
862 fmt.audio.i_blockalign = fmt.audio.i_channels *
863 fmt.audio.i_bitspersample / 8;
864 fmt.i_bitrate = fmt.audio.i_channels * fmt.audio.i_rate *
865 fmt.audio.i_bitspersample;
866 p_audio->p_es = es_out_Add( p_demux->out, &fmt );
868 p_audio->i_nb_samples = p_audio->i_rate * p_sys->i_frame_rate_base
869 / p_sys->i_frame_rate;
870 p_audio->i_max_samples = (float)p_audio->i_nb_samples *
871 (1. + SAMPLERATE_TOLERANCE);
873 p_audio->p_buffer = malloc( p_audio->i_max_samples * sizeof(int16_t) * 2 );
874 p_audio->i_left_samples = p_audio->i_right_samples = 0;
875 p_audio->i_block_number = 0;
877 if( unlikely( !p_audio->p_buffer ) )
882 /* Fast and efficient linear resampling routine */
883 static void ResampleAudio( int16_t *p_out, int16_t *p_in,
884 unsigned int i_out, unsigned int i_in )
886 unsigned int i_remainder = 0;
887 float f_last_sample = (float)*p_in / 32768.0;
893 for ( unsigned int i = 1; i < i_in; i++ )
895 float f_in = (float)*p_in / 32768.0;
896 while ( i_remainder < i_out )
898 float f_out = f_last_sample;
899 f_out += (f_in - f_last_sample) * i_remainder / i_out;
900 if ( f_out >= 1.0 ) *p_out = 32767;
901 else if ( f_out < -1.0 ) *p_out = -32768;
902 else *p_out = f_out * 32768.0;
907 f_last_sample = f_in;
909 i_remainder -= i_out;
913 static int DecodeAudio( demux_t *p_demux, sdi_audio_t *p_audio )
915 demux_sys_t *p_sys = p_demux->p_sys;
919 if ( p_audio->p_buffer == NULL )
921 if ( !p_audio->i_left_samples && !p_audio->i_right_samples )
923 msg_Warn( p_demux, "no audio %u/%u", p_audio->i_group,
927 if ( p_audio->i_left_samples <
928 (float)p_audio->i_nb_samples * (1. - SAMPLERATE_TOLERANCE) ||
929 p_audio->i_left_samples >
930 (float)p_audio->i_nb_samples * (1. + SAMPLERATE_TOLERANCE) )
933 "left samplerate out of tolerance for audio %u/%u (%u vs. %u)",
934 p_audio->i_group, p_audio->i_pair,
935 p_audio->i_left_samples, p_audio->i_nb_samples );
938 if ( p_audio->i_right_samples <
939 (float)p_audio->i_nb_samples * (1. - SAMPLERATE_TOLERANCE) ||
940 p_audio->i_right_samples >
941 (float)p_audio->i_nb_samples * (1. + SAMPLERATE_TOLERANCE) )
944 "right samplerate out of tolerance for audio %u/%u (%u vs. %u)",
945 p_audio->i_group, p_audio->i_pair,
946 p_audio->i_right_samples, p_audio->i_nb_samples );
950 p_block = block_New( p_demux, p_audio->i_nb_samples * sizeof(int16_t) * 2 );
951 if( unlikely( !p_block ) )
953 p_block->i_dts = p_block->i_pts = p_sys->i_next_date
954 + (mtime_t)p_audio->i_delay * INT64_C(1000000) / p_audio->i_rate;
955 p_output = (int16_t *)p_block->p_buffer;
957 if ( p_audio->i_left_samples == p_audio->i_nb_samples &&
958 p_audio->i_right_samples == p_audio->i_nb_samples )
959 vlc_memcpy( p_output, p_audio->p_buffer,
960 p_audio->i_nb_samples * sizeof(int16_t) * 2 );
963 ResampleAudio( p_output, p_audio->p_buffer,
964 p_audio->i_nb_samples, p_audio->i_left_samples );
966 ResampleAudio( p_output + 1, p_audio->p_buffer + 1,
967 p_audio->i_nb_samples, p_audio->i_right_samples );
970 es_out_Send( p_demux->out, p_audio->p_es, p_block );
974 static int DecodeFrame( demux_t *p_demux )
976 demux_sys_t *p_sys = p_demux->p_sys;
980 DecodeWSS( p_demux );
982 if ( p_sys->i_height == 576 )
984 /* For PAL, erase first half of line 23, last half of line 623,
985 * and line 624 ; no need to erase chrominance */
986 vlc_memset( p_sys->p_y, 0, p_sys->i_width / 2 );
987 vlc_memset( p_sys->p_y + p_sys->i_width * 574 + p_sys->i_width / 2,
988 0, p_sys->i_width * 3 / 2 );
992 if ( p_sys->i_telx_count )
993 if ( DecodeTelx( p_demux ) != VLC_SUCCESS )
996 for ( int i = 0; i < MAX_AUDIOS; i++ )
998 if ( p_sys->p_audios[i].i_group && p_sys->p_audios[i].p_es != NULL )
999 if( DecodeAudio( p_demux, &p_sys->p_audios[i] ) != VLC_SUCCESS )
1000 return VLC_EGENERIC;
1003 DecodeVideo( p_demux );
1005 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_next_date );
1006 p_sys->i_next_date += p_sys->i_incr;
1008 if( NewFrame( p_demux ) != VLC_SUCCESS )
1014 /*****************************************************************************
1015 * SDI syntax parsing stuff
1016 *****************************************************************************/
1017 #define FIELD_1_VBLANK_EAV 0xB6
1018 #define FIELD_1_VBLANK_SAV 0xAB
1019 #define FIELD_1_ACTIVE_EAV 0x9D
1020 #define FIELD_1_ACTIVE_SAV 0x80
1021 #define FIELD_2_VBLANK_EAV 0xF1
1022 #define FIELD_2_VBLANK_SAV 0xEC
1023 #define FIELD_2_ACTIVE_EAV 0xDA
1024 #define FIELD_2_ACTIVE_SAV 0xC7
1026 static const uint8_t *FindReferenceCode( uint8_t i_code,
1027 const uint8_t *p_parser,
1028 const uint8_t *p_end )
1030 while ( p_parser <= p_end - 5 )
1032 if ( p_parser[0] == 0xff && p_parser[1] == 0x3 && p_parser[2] == 0x0
1033 && p_parser[3] == 0x0 && p_parser[4] == i_code )
1041 static const uint8_t *CountReference( unsigned int *pi_count, uint8_t i_code,
1042 const uint8_t *p_parser,
1043 const uint8_t *p_end )
1045 const uint8_t *p_tmp = FindReferenceCode( i_code, p_parser, p_end );
1046 if ( p_tmp == NULL )
1048 *pi_count += p_end - p_parser;
1051 *pi_count += p_tmp - p_parser;
1055 static const uint8_t *GetLine( demux_t *p_demux, const uint8_t **pp_parser,
1056 const uint8_t *p_end )
1058 demux_sys_t *p_sys = p_demux->p_sys;
1059 unsigned int i_total_size = p_sys->i_anc_size + p_sys->i_active_size;
1060 const uint8_t *p_tmp;
1062 if ( p_sys->i_line_buffer )
1064 unsigned int i_remaining = i_total_size - p_sys->i_line_buffer;
1065 vlc_memcpy( p_sys->p_line_buffer + p_sys->i_line_buffer,
1066 *pp_parser, i_remaining );
1067 *pp_parser += i_remaining;
1068 p_sys->i_line_buffer = 0;
1070 return p_sys->p_line_buffer;
1073 if ( p_end - *pp_parser < (int)i_total_size )
1075 vlc_memcpy( p_sys->p_line_buffer, *pp_parser,
1076 p_end - *pp_parser );
1077 p_sys->i_line_buffer = p_end - *pp_parser;
1082 *pp_parser += i_total_size;
1086 #define U (uint16_t)((p_line[0]) | ((p_line[1] & 0x3) << 8))
1087 #define Y1 (uint16_t)((p_line[1] >> 2) | ((p_line[2] & 0xf) << 6))
1088 #define V (uint16_t)((p_line[2] >> 4) | ((p_line[3] & 0x3f) << 4))
1089 #define Y2 (uint16_t)((p_line[3] >> 6) | (p_line[4] << 2))
1091 static void UnpackVBI( const uint8_t *p_line, unsigned int i_size,
1094 const uint8_t *p_end = p_line + i_size;
1096 while ( p_line < p_end )
1098 *p_dest++ = (U + 2) / 4;
1099 *p_dest++ = (Y1 + 2) / 4;
1100 *p_dest++ = (V + 2) / 4;
1101 *p_dest++ = (Y2 + 2) / 4;
1106 /* For lines 0 [4] or 1 [4] */
1107 static void Unpack01( const uint8_t *p_line, unsigned int i_size,
1108 uint8_t *p_y, uint8_t *p_u, uint8_t *p_v )
1110 const uint8_t *p_end = p_line + i_size;
1112 while ( p_line < p_end )
1114 *p_u++ = (U + 2) / 4;
1115 *p_y++ = (Y1 + 2) / 4;
1116 *p_v++ = (V + 2) / 4;
1117 *p_y++ = (Y2 + 2) / 4;
1122 /* For lines 2 [4] */
1123 static void Unpack2( const uint8_t *p_line, unsigned int i_size,
1124 uint8_t *p_y, uint8_t *p_u, uint8_t *p_v )
1126 const uint8_t *p_end = p_line + i_size;
1128 while ( p_line < p_end )
1134 *p_y++ = (Y1 + 2) / 4;
1138 *p_y++ = (Y2 + 2) / 4;
1143 /* For lines 3 [4] */
1144 static void Unpack3( const uint8_t *p_line, unsigned int i_size,
1145 uint8_t *p_y, uint8_t *p_u, uint8_t *p_v )
1147 const uint8_t *p_end = p_line + i_size;
1149 while ( p_line < p_end )
1153 tmp += 3 * (U + 2) / 4;
1155 *p_y++ = (Y1 + 2) / 4;
1157 tmp += 3 * (V + 2) / 4;
1159 *p_y++ = (Y2 + 2) / 4;
1169 #define A0 (uint16_t)((p_anc[0]) | ((p_anc[1] & 0x3) << 8))
1170 #define A1 (uint16_t)((p_anc[1] >> 2) | ((p_anc[2] & 0xf) << 6))
1171 #define A2 (uint16_t)((p_anc[2] >> 4) | ((p_anc[3] & 0x3f) << 4))
1172 #define A3 (uint16_t)((p_anc[3] >> 6) | (p_anc[4] << 2))
1174 static void UnpackAnc( const uint8_t *p_anc, unsigned int i_size,
1177 const uint8_t *p_end = p_anc + i_size;
1179 while ( p_anc <= p_end - 5 )
1194 static int HasAncillary( const uint8_t *p_anc )
1196 return ( (p_anc[0] == 0x0 && p_anc[1] == 0xfc && p_anc[2] == 0xff
1197 && (p_anc[3] & 0x3f) == 0x3f) );
1200 static void HandleAudioData( demux_t *p_demux, const uint16_t *p_anc,
1201 uint8_t i_data_count, uint8_t i_group,
1202 uint8_t i_block_number )
1204 demux_sys_t *p_sys = p_demux->p_sys;
1206 if ( i_data_count % 3 )
1208 msg_Warn( p_demux, "malformed audio data for group %u", i_group );
1212 for ( int i = 0; i < MAX_AUDIOS; i++ )
1214 sdi_audio_t *p_audio = &p_sys->p_audios[i];
1215 if ( p_audio->i_group == i_group )
1217 const uint16_t *x = p_anc;
1219 /* SMPTE 272M says that when parsing a frame, if an audio config
1220 * structure is present we will encounter it first. Otherwise
1221 * it is assumed to be 48 kHz. */
1222 if ( p_audio->p_es == NULL )
1224 p_audio->i_rate = 48000;
1225 p_audio->i_delay = 0;
1226 if( InitAudio( p_demux, p_audio ) != VLC_SUCCESS )
1230 if ( i_block_number )
1232 if ( p_audio->i_block_number + 1 != i_block_number )
1234 "audio data block discontinuity (%"PRIu8"->%"PRIu8") for group %"PRIu8,
1235 p_audio->i_block_number, i_block_number,
1237 if ( i_block_number == 0xff )
1238 p_audio->i_block_number = 0;
1240 p_audio->i_block_number = i_block_number;
1243 while ( x < p_anc + i_data_count )
1245 if ( ((*x & 0x4) && p_audio->i_pair == 2)
1246 || (!(*x & 0x4) && p_audio->i_pair == 1) )
1248 uint32_t i_tmp = (uint32_t)((x[0] & 0x1f1) >> 3)
1249 | ((x[1] & 0x1ff) << 6)
1250 | ((x[2] & 0x1f) << 15);
1253 i_sample = i_tmp | 0xfff00000;
1259 if ( p_audio->i_right_samples < p_audio->i_max_samples )
1260 p_audio->p_buffer[2 * p_audio->i_right_samples
1261 + 1] = (i_sample + 8) / 16;
1262 p_audio->i_right_samples++;
1266 if ( p_audio->i_left_samples < p_audio->i_max_samples )
1267 p_audio->p_buffer[2 * p_audio->i_left_samples]
1268 = (i_sample + 8) / 16;
1269 p_audio->i_left_samples++;
1278 static void HandleAudioConfig( demux_t *p_demux, const uint16_t *p_anc,
1279 uint8_t i_data_count, uint8_t i_group )
1281 demux_sys_t *p_sys = p_demux->p_sys;
1283 if ( i_data_count != 18 )
1285 msg_Warn( p_demux, "malformed audio config for group %u", i_group );
1289 for ( int i = 0; i < MAX_AUDIOS; i++ )
1291 sdi_audio_t *p_audio = &p_sys->p_audios[i];
1292 if ( p_audio->i_group == i_group && p_audio->p_es == NULL )
1294 unsigned int i_rate;
1296 if ( p_audio->i_pair == 2 )
1298 i_rate = (p_anc[2] & 0xe0) >> 5;
1299 if ( p_anc[7] & 0x1 )
1301 uint32_t i_tmp = ((p_anc[7] & 0x1fe) >> 1)
1302 | ((p_anc[8] & 0x1ff) << 8)
1303 | ((p_anc[9] & 0x1ff) << 17);
1304 if ( p_anc[9] & 0x80 )
1305 p_audio->i_delay = i_tmp | 0xfc000000;
1307 p_audio->i_delay = i_tmp;
1309 if ( p_anc[13] & 0x1 )
1310 msg_Warn( p_demux, "asymetric audio is not supported" );
1314 i_rate = (p_anc[2] & 0xe) >> 1;
1315 if ( p_anc[4] & 0x1 )
1317 uint32_t i_tmp = ((p_anc[4] & 0x1fe) >> 1)
1318 | ((p_anc[5] & 0x1ff) << 8)
1319 | ((p_anc[6] & 0x1ff) << 17);
1320 if ( p_anc[6] & 0x80 )
1321 p_audio->i_delay = i_tmp | 0xfc000000;
1323 p_audio->i_delay = i_tmp;
1325 if ( p_anc[10] & 0x1 )
1326 msg_Warn( p_demux, "asymetric audio is not supported" );
1331 case 0: p_audio->i_rate = 48000; break;
1332 case 1: p_audio->i_rate = 44100; break;
1333 case 2: p_audio->i_rate = 32000; break;
1335 msg_Warn( p_demux, "unknown rate for audio %u/%u (%u)",
1336 i_group, p_sys->p_audios[i].i_pair, i_rate );
1340 if( InitAudio( p_demux, p_audio ) != VLC_SUCCESS )
1347 * Ancillary packet structure:
1348 * byte 0: Ancillary Data Flag (0)
1349 * byte 1: Ancillary Data Flag (0x3ff)
1350 * byte 2: Ancillary Data Flag (0x3ff)
1351 * byte 3: Data ID (2 high order bits = parity)
1352 * byte 4: Data Block Number 1-255 or 0=unknown (if DID < 0x80)
1353 * or Secondary Data ID (if DID >= 0x80)
1354 * byte 5: Data Count (10 bits)
1355 * byte 6+DC: Checksum
1357 static void HandleAncillary( demux_t *p_demux, const uint16_t *p_anc,
1358 unsigned int i_size )
1360 uint8_t i_data_count;
1363 || p_anc[0] != 0x0 || p_anc[1] != 0x3ff || p_anc[2] != 0x3ff )
1366 i_data_count = p_anc[5] & 0xff;
1367 if ( i_size - 6 < i_data_count )
1369 msg_Warn( p_demux, "malformed ancillary packet (size %u > %u)",
1370 i_data_count, i_size - 6 );
1374 switch ( p_anc[3] ) /* Data ID */
1377 HandleAudioData( p_demux, p_anc + 6, i_data_count, 1, p_anc[4] & 0xff );
1380 HandleAudioData( p_demux, p_anc + 6, i_data_count, 2, p_anc[4] & 0xff );
1383 HandleAudioData( p_demux, p_anc + 6, i_data_count, 3, p_anc[4] & 0xff );
1386 HandleAudioData( p_demux, p_anc + 6, i_data_count, 4, p_anc[4] & 0xff );
1390 HandleAudioConfig( p_demux, p_anc + 6, i_data_count, 1 );
1393 HandleAudioConfig( p_demux, p_anc + 6, i_data_count, 2 );
1396 HandleAudioConfig( p_demux, p_anc + 6, i_data_count, 3 );
1399 HandleAudioConfig( p_demux, p_anc + 6, i_data_count, 4 );
1402 /* Extended data packets, same order */
1411 case 0x88: /* non-conforming ANC packet */
1414 while ( i_size >= 7 && (p_anc[0] != 0x0 || p_anc[1] != 0x3ff
1415 || p_anc[2] != 0x3ff) )
1421 HandleAncillary( p_demux, p_anc, i_size );
1425 return HandleAncillary( p_demux, p_anc + i_data_count + 7,
1426 i_size - i_data_count - 7 );
1430 static int HandleSDBuffer( demux_t *p_demux, uint8_t *p_buffer,
1431 unsigned int i_buffer_size )
1433 demux_sys_t *p_sys = p_demux->p_sys;
1434 const uint8_t *p_parser = p_buffer;
1435 const uint8_t *p_end = p_parser + i_buffer_size;
1436 const uint8_t *p_line;
1438 if ( p_sys->i_state != STATE_SYNC
1439 && p_sys->i_last_state_change < mdate() - RESYNC_TIMEOUT )
1441 p_sys->i_state = STATE_NOSYNC;
1442 p_sys->i_last_state_change = mdate();
1443 return VLC_EGENERIC;
1446 switch ( p_sys->i_state )
1450 p_parser = FindReferenceCode( FIELD_2_VBLANK_SAV, p_parser, p_end );
1451 if ( p_parser == NULL )
1453 p_sys->i_state = STATE_STARTSYNC;
1454 p_sys->i_last_state_change = mdate();
1456 case STATE_STARTSYNC:
1457 p_parser = FindReferenceCode( FIELD_1_VBLANK_EAV, p_parser, p_end );
1458 if ( p_parser == NULL )
1460 p_sys->i_anc_size = 0;
1461 p_sys->i_state = STATE_ANCSYNC;
1462 p_sys->i_last_state_change = mdate();
1465 p_parser = CountReference( &p_sys->i_anc_size,
1466 FIELD_1_VBLANK_SAV, p_parser, p_end );
1467 if ( p_parser == NULL )
1469 p_sys->i_active_size = 0;
1470 p_sys->i_state = STATE_LINESYNC;
1471 p_sys->i_last_state_change = mdate();
1473 case STATE_LINESYNC:
1474 p_parser = CountReference( &p_sys->i_active_size,
1475 FIELD_1_VBLANK_EAV, p_parser, p_end );
1476 if ( p_parser == NULL )
1478 p_sys->i_picture_size = p_sys->i_anc_size + p_sys->i_active_size;
1479 p_sys->i_state = STATE_ACTIVESYNC;
1480 p_sys->i_last_state_change = mdate();
1482 case STATE_ACTIVESYNC:
1483 p_parser = CountReference( &p_sys->i_picture_size,
1484 FIELD_1_ACTIVE_EAV, p_parser, p_end );
1485 if ( p_parser == NULL )
1487 p_sys->i_line_offset = p_sys->i_picture_size
1488 / (p_sys->i_anc_size + p_sys->i_active_size);
1489 p_sys->i_state = STATE_VBLANKSYNC;
1490 p_sys->i_last_state_change = mdate();
1492 case STATE_VBLANKSYNC:
1493 p_parser = CountReference( &p_sys->i_picture_size,
1494 FIELD_2_ACTIVE_EAV, p_parser, p_end );
1495 if ( p_parser == NULL )
1497 p_sys->i_state = STATE_PICSYNC;
1498 p_sys->i_last_state_change = mdate();
1501 p_parser = CountReference( &p_sys->i_picture_size,
1502 FIELD_1_VBLANK_EAV, p_parser, p_end );
1503 if ( p_parser == NULL )
1506 if ( p_sys->i_picture_size
1507 % (p_sys->i_anc_size + p_sys->i_active_size) )
1509 msg_Warn( p_demux, "wrong picture size (anc=%d active=%d total=%d offset=%d), syncing",
1510 p_sys->i_anc_size, p_sys->i_active_size,
1511 p_sys->i_picture_size, p_sys->i_line_offset + 1 );
1512 p_sys->i_state = STATE_NOSYNC;
1513 p_sys->i_last_state_change = mdate();
1517 p_sys->i_nb_lines = p_sys->i_picture_size
1518 / (p_sys->i_anc_size + p_sys->i_active_size);
1519 InitVideo( p_demux );
1521 "acquired sync, anc=%d active=%d lines=%d offset=%d",
1522 p_sys->i_anc_size, p_sys->i_active_size,
1523 p_sys->i_nb_lines, p_sys->i_line_offset + 1 );
1524 p_sys->i_state = STATE_SYNC;
1525 if( StartDecode( p_demux ) != VLC_SUCCESS )
1527 StopDecode( p_demux );
1530 p_sys->i_current_line = 0;
1531 p_sys->p_line_buffer = malloc( p_sys->i_anc_size
1532 + p_sys->i_active_size );
1533 if( !p_sys->p_line_buffer )
1535 StopDecode( p_demux );
1538 p_sys->i_line_buffer = 0;
1541 while ( (p_line = GetLine( p_demux, &p_parser, p_end )) != NULL )
1543 bool b_field = p_sys->b_hd ? false :
1544 (p_sys->i_current_line >= p_sys->i_nb_lines / 2);
1545 unsigned int i_field_height = p_sys->b_hd ? p_sys->i_height :
1546 p_sys->i_height / 2;
1547 unsigned int i_field_line = b_field ?
1548 p_sys->i_current_line - (p_sys->i_nb_lines + 1) / 2 :
1549 p_sys->i_current_line;
1550 bool b_vbi = i_field_line < p_sys->i_line_offset ||
1551 i_field_line >= p_sys->i_line_offset + i_field_height;
1552 unsigned int anc = p_sys->i_anc_size;
1554 if ( p_line[0] != 0xff || p_line[1] != 0x3
1555 || p_line[2] != 0x0 || p_line[3] != 0x0
1556 || p_line[anc+0] != 0xff || p_line[anc+1] != 0x3
1557 || p_line[anc+2] != 0x0 || p_line[anc+3] != 0x0
1558 || (!b_field && b_vbi &&
1559 (p_line[4] != FIELD_1_VBLANK_EAV ||
1560 p_line[anc+4] != FIELD_1_VBLANK_SAV))
1561 || (!b_field && !b_vbi &&
1562 (p_line[4] != FIELD_1_ACTIVE_EAV ||
1563 p_line[anc+4] != FIELD_1_ACTIVE_SAV))
1564 || (b_field && b_vbi &&
1565 (p_line[4] != FIELD_2_VBLANK_EAV ||
1566 p_line[anc+4] != FIELD_2_VBLANK_SAV))
1567 || (b_field && !b_vbi &&
1568 (p_line[4] != FIELD_2_ACTIVE_EAV ||
1569 p_line[anc+4] != FIELD_2_ACTIVE_SAV)) )
1571 msg_Warn( p_demux, "lost sync line:%u SAV:%x EAV:%x",
1572 p_sys->i_current_line + 1, p_line[4], p_line[anc+4] );
1573 StopDecode( p_demux );
1574 p_sys->i_state = STATE_NOSYNC;
1575 p_sys->i_last_state_change = mdate();
1579 if ( HasAncillary( p_line + 5 ) )
1582 unsigned int i_anc_words = (p_sys->i_anc_size - 5) * 4 / 5;
1583 uint16_t p_anc[i_anc_words];
1584 UnpackAnc( p_line + 5, p_sys->i_anc_size - 5, p_anc );
1585 HandleAncillary( p_demux, p_anc, i_anc_words );
1590 unsigned int i_active_field_line = i_field_line
1591 - p_sys->i_line_offset;
1592 unsigned int i_active_line = b_field
1593 + i_active_field_line * 2;
1594 if ( !(i_active_field_line % 2) && !b_field )
1595 Unpack01( p_line + anc + 5, p_sys->i_active_size - 5,
1596 p_sys->p_y + p_sys->i_width * i_active_line,
1597 p_sys->p_u + (p_sys->i_width / 2)
1598 * (i_active_line / 2),
1599 p_sys->p_v + (p_sys->i_width / 2)
1600 * (i_active_line / 2) );
1601 else if ( !(i_active_field_line % 2) )
1602 Unpack01( p_line + anc + 5, p_sys->i_active_size - 5,
1603 p_sys->p_y + p_sys->i_width * i_active_line,
1604 p_sys->p_u + (p_sys->i_width / 2)
1605 * (i_active_line / 2 + 1),
1606 p_sys->p_v + (p_sys->i_width / 2)
1607 * (i_active_line / 2 + 1) );
1608 else if ( !b_field )
1609 Unpack2( p_line + anc + 5, p_sys->i_active_size - 5,
1610 p_sys->p_y + p_sys->i_width * i_active_line,
1611 p_sys->p_u + (p_sys->i_width / 2)
1612 * (i_active_line / 2 - 1),
1613 p_sys->p_v + (p_sys->i_width / 2)
1614 * (i_active_line / 2 - 1) );
1616 Unpack3( p_line + anc + 5, p_sys->i_active_size - 5,
1617 p_sys->p_y + p_sys->i_width * i_active_line,
1618 p_sys->p_u + (p_sys->i_width / 2)
1619 * (i_active_line / 2),
1620 p_sys->p_v + (p_sys->i_width / 2)
1621 * (i_active_line / 2) );
1623 if ( p_sys->b_vbi && p_sys->i_height == 576
1624 && p_sys->i_current_line == p_sys->i_line_offset )
1626 /* Line 23 is half VBI, half active */
1627 UnpackVBI( p_line + anc + 5, p_sys->i_active_size - 5,
1628 p_sys->p_wss_buffer );
1631 else if ( p_sys->b_vbi && p_sys->i_telx_count &&
1632 i_field_line >= p_sys->i_telx_line &&
1633 i_field_line < p_sys->i_telx_line
1634 + p_sys->i_telx_count )
1636 UnpackVBI( p_line + anc + 5, p_sys->i_active_size - 5,
1637 &p_sys->p_telx_buffer[(i_field_line
1638 - p_sys->i_telx_line + b_field * p_sys->i_telx_count)
1639 * p_sys->i_width * 2] );
1641 else if ( b_vbi && HasAncillary( p_line + anc + 5 ) )
1644 unsigned int i_anc_words = (p_sys->i_active_size - 5) * 4 / 5;
1645 uint16_t p_anc[i_anc_words];
1646 UnpackAnc( p_line + 5, p_sys->i_active_size - 5,
1648 HandleAncillary( p_demux, p_anc, i_anc_words );
1651 p_sys->i_current_line++;
1652 if ( p_sys->i_current_line == p_sys->i_nb_lines )
1654 p_sys->i_current_line %= p_sys->i_nb_lines;
1655 if( DecodeFrame( p_demux ) != VLC_SUCCESS )
1656 return VLC_EGENERIC;
1665 /*****************************************************************************
1666 * Low-level device stuff
1667 *****************************************************************************/
1670 static int ReadULSysfs( const char *psz_fmt, unsigned int i_link )
1672 char psz_file[MAXLEN], psz_data[MAXLEN];
1676 unsigned int i_data;
1678 snprintf( psz_file, sizeof(psz_file) - 1, psz_fmt, i_link );
1680 if ( (i_fd = vlc_open( psz_file, O_RDONLY )) < 0 )
1683 i_ret = read( i_fd, psz_data, sizeof(psz_data) );
1689 i_data = strtoul( psz_data, &psz_tmp, 0 );
1690 if ( *psz_tmp != '\n' )
1696 static ssize_t WriteULSysfs( const char *psz_fmt, unsigned int i_link,
1697 unsigned int i_buf )
1699 char psz_file[MAXLEN], psz_data[MAXLEN];
1703 snprintf( psz_file, sizeof(psz_file) -1, psz_fmt, i_link );
1705 snprintf( psz_data, sizeof(psz_data) -1, "%u\n", i_buf );
1707 if ( (i_fd = vlc_open( psz_file, O_WRONLY )) < 0 )
1710 i_ret = write( i_fd, psz_data, strlen(psz_data) + 1 );
1715 static int InitCapture( demux_t *p_demux )
1717 demux_sys_t *p_sys = p_demux->p_sys;
1718 const int i_page_size = getpagesize();
1719 unsigned int i_bufmemsize;
1721 char psz_dev[MAXLEN];
1723 /* 10-bit mode or nothing */
1724 if ( WriteULSysfs( SDI_MODE_FILE, p_sys->i_link, SDI_CTL_MODE_10BIT ) < 0 )
1726 msg_Err( p_demux, "couldn't write file " SDI_MODE_FILE, p_sys->i_link );
1727 return VLC_EGENERIC;
1730 if ( (i_ret = ReadULSysfs( SDI_BUFFERS_FILE, p_sys->i_link )) < 0 )
1732 msg_Err( p_demux, "couldn't read file " SDI_BUFFERS_FILE,
1734 return VLC_EGENERIC;
1736 p_sys->i_buffers = i_ret;
1737 p_sys->i_current_buffer = 0;
1739 if ( (i_ret = ReadULSysfs( SDI_BUFSIZE_FILE, p_sys->i_link )) < 0 )
1741 msg_Err( p_demux, "couldn't read file " SDI_BUFSIZE_FILE,
1743 return VLC_EGENERIC;
1745 p_sys->i_buffer_size = i_ret;
1746 if ( p_sys->i_buffer_size % 20 )
1748 msg_Err( p_demux, "buffer size must be a multiple of 20" );
1749 return VLC_EGENERIC;
1752 snprintf( psz_dev, sizeof(psz_dev) - 1, SDI_DEVICE, p_sys->i_link );
1753 if ( (p_sys->i_fd = vlc_open( psz_dev, O_RDONLY ) ) < 0 )
1755 msg_Err( p_demux, "couldn't open device %s", psz_dev );
1756 return VLC_EGENERIC;
1759 i_bufmemsize = ((p_sys->i_buffer_size + i_page_size - 1) / i_page_size)
1761 p_sys->pp_buffers = malloc( p_sys->i_buffers * sizeof(uint8_t *) );
1762 if( !p_sys->pp_buffers )
1765 for ( unsigned int i = 0; i < p_sys->i_buffers; i++ )
1767 if ( (p_sys->pp_buffers[i] = mmap( NULL, p_sys->i_buffer_size,
1768 PROT_READ, MAP_SHARED, p_sys->i_fd,
1769 i * i_bufmemsize )) == MAP_FAILED )
1771 msg_Err( p_demux, "couldn't mmap(%d): %s", i, strerror(errno) );
1772 free( p_sys->pp_buffers );
1773 return VLC_EGENERIC;
1780 static void CloseCapture( demux_t *p_demux )
1782 demux_sys_t *p_sys = p_demux->p_sys;
1784 StopDecode( p_demux );
1785 for ( unsigned int i = 0; i < p_sys->i_buffers; i++ )
1786 munmap( p_sys->pp_buffers[i], p_sys->i_buffer_size );
1787 close( p_sys->i_fd );
1788 free( p_sys->pp_buffers );
1791 static int Capture( demux_t *p_demux )
1793 demux_sys_t *p_sys = p_demux->p_sys;
1796 pfd.fd = p_sys->i_fd;
1797 pfd.events = POLLIN | POLLPRI;
1799 if ( poll( &pfd, 1, READ_TIMEOUT ) < 0 )
1801 msg_Warn( p_demux, "couldn't poll(): %s", strerror(errno) );
1802 return VLC_EGENERIC;
1805 if ( pfd.revents & POLLPRI )
1809 if ( ioctl( p_sys->i_fd, SDI_IOC_RXGETEVENTS, &i_val ) < 0 )
1810 msg_Warn( p_demux, "couldn't SDI_IOC_RXGETEVENTS %s", strerror(errno) );
1813 if ( i_val & SDI_EVENT_RX_BUFFER )
1814 msg_Warn( p_demux, "driver receive buffer queue overrun" );
1815 if ( i_val & SDI_EVENT_RX_FIFO )
1816 msg_Warn( p_demux, "onboard receive FIFO overrun");
1817 if ( i_val & SDI_EVENT_RX_CARRIER )
1818 msg_Warn( p_demux, "carrier status change");
1821 p_sys->i_next_date += CLOCK_GAP;
1824 if ( pfd.revents & POLLIN )
1828 if ( ioctl( p_sys->i_fd, SDI_IOC_DQBUF, p_sys->i_current_buffer ) < 0 )
1830 msg_Warn( p_demux, "couldn't SDI_IOC_DQBUF %s", strerror(errno) );
1831 return VLC_EGENERIC;
1834 i_ret = HandleSDBuffer( p_demux,
1835 p_sys->pp_buffers[p_sys->i_current_buffer],
1836 p_sys->i_buffer_size );
1838 if ( ioctl( p_sys->i_fd, SDI_IOC_QBUF, p_sys->i_current_buffer ) < 0 )
1840 msg_Warn( p_demux, "couldn't SDI_IOC_QBUF %s", strerror(errno) );
1841 return VLC_EGENERIC;
1844 if ( i_ret == VLC_SUCCESS )
1846 p_sys->i_current_buffer++;
1847 p_sys->i_current_buffer %= p_sys->i_buffers;
1851 /* Reference codes do not start on a multiple of 5. This sometimes
1852 * happen. We really don't want to allow this. */
1853 msg_Warn( p_demux, "resetting board" );
1854 CloseCapture( p_demux );
1855 InitCapture( p_demux );