1 /*****************************************************************************
2 * cdg.c : cdg file demux module for vlc
3 *****************************************************************************
4 * Copyright (C) 2007 Laurent Aimar
6 * Authors: Laurent Aimar <fenrir # via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_demux.h>
35 /*****************************************************************************
37 *****************************************************************************/
38 static int Open ( vlc_object_t
* );
41 set_description( N_("CDG demuxer") )
42 set_category( CAT_INPUT
)
43 set_subcategory( SUBCAT_INPUT_DEMUX
)
44 set_capability( "demux", 3 )
45 set_callbacks( Open
, NULL
)
46 add_shortcut( "cdg", "subtitle" )
49 /*****************************************************************************
51 *****************************************************************************/
52 static int Demux ( demux_t
* );
53 static int Control( demux_t
*, int i_query
, va_list args
);
63 #define CDG_FRAME_SIZE (96)
64 #define CDG_FRAME_RATE (75)
65 #define CDG_FRAME_DELTA (CLOCK_FREQ / CDG_FRAME_RATE)
67 /*****************************************************************************
68 * Open: check file and initializes structures
69 *****************************************************************************/
70 static int Open( vlc_object_t
* p_this
)
72 demux_t
*p_demux
= (demux_t
*)p_this
;
74 /* Identify cdg file by extension, as there is no simple way to
76 if( !demux_IsPathExtension( p_demux
, ".cdg" ) && !demux_IsForced( p_demux
, "cdg" ) )
79 /* CDG file size has to be multiple of CDG_FRAME_SIZE (it works even
80 * if size is unknown ie 0) */
81 // if( (stream_Size( p_demux->s ) % CDG_FRAME_SIZE) != 0 )
83 // msg_Err( p_demux, "Reject CDG file based on its size" );
84 // return VLC_EGENERIC;
87 demux_sys_t
*p_sys
= vlc_obj_malloc( p_this
, sizeof (*p_sys
) );
88 if( unlikely(p_sys
== NULL
) )
91 es_format_Init( &p_sys
->fmt
, VIDEO_ES
, VLC_CODEC_CDG
);
92 p_sys
->fmt
.video
.i_width
= 300-2*6;
93 p_sys
->fmt
.video
.i_height
= 216-2*12 ;
94 p_sys
->fmt
.video
.i_visible_width
= p_sys
->fmt
.video
.i_width
;
95 p_sys
->fmt
.video
.i_visible_height
= p_sys
->fmt
.video
.i_height
;
97 p_sys
->p_es
= es_out_Add( p_demux
->out
, &p_sys
->fmt
);
98 if( unlikely(p_sys
->p_es
== NULL
) )
101 /* There is CDG_FRAME_RATE frames per second */
102 date_Init( &p_sys
->pts
, CDG_FRAME_RATE
, 1 );
103 date_Set( &p_sys
->pts
, VLC_TICK_0
);
105 p_demux
->pf_demux
= Demux
;
106 p_demux
->pf_control
= Control
;
107 p_demux
->p_sys
= p_sys
;
111 static vlc_tick_t
PosToDate( demux_t
*p_demux
)
113 return vlc_stream_Tell( p_demux
->s
) / CDG_FRAME_SIZE
* CDG_FRAME_DELTA
;
116 /*****************************************************************************
117 * Demux: read packet and send them to decoders
118 *****************************************************************************
119 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
120 *****************************************************************************/
121 static int Demux( demux_t
*p_demux
)
123 demux_sys_t
*p_sys
= p_demux
->p_sys
;
127 p_block
= vlc_stream_Block( p_demux
->s
, CDG_FRAME_SIZE
);
128 if( p_block
== NULL
)
130 msg_Dbg( p_demux
, "cannot read data, eof" );
131 return VLC_DEMUXER_EOF
;
134 i_date
= PosToDate( p_demux
);
135 if( i_date
>= date_Get( &p_sys
->pts
) + CDG_FRAME_DELTA
)
137 p_block
->i_dts
= p_block
->i_pts
= VLC_TICK_0
+ i_date
;
138 date_Set( &p_sys
->pts
, VLC_TICK_0
+ i_date
);
142 p_block
->i_dts
= VLC_TICK_0
+ i_date
;
143 p_block
->i_pts
= date_Get( &p_sys
->pts
);
146 es_out_SetPCR( p_demux
->out
, p_block
->i_pts
);
147 es_out_Send( p_demux
->out
, p_sys
->p_es
, p_block
);
148 return VLC_DEMUXER_SUCCESS
;
151 /*****************************************************************************
153 *****************************************************************************/
154 static int Control( demux_t
*p_demux
, int i_query
, va_list args
)
156 demux_sys_t
*p_sys
= p_demux
->p_sys
;
157 uint64_t i_old_offset
= vlc_stream_Tell( p_demux
->s
);
158 int i_ret
= demux_vaControlHelper( p_demux
->s
, 0, -1,
159 8*CDG_FRAME_SIZE
*CDG_FRAME_RATE
, CDG_FRAME_SIZE
,
161 if( !i_ret
&& ( i_query
== DEMUX_SET_POSITION
|| i_query
== DEMUX_SET_TIME
) )
163 date_Set( &p_sys
->pts
, PosToDate( p_demux
) );
164 if ( i_old_offset
> vlc_stream_Tell( p_demux
->s
) )
165 i_ret
= vlc_stream_Seek( p_demux
->s
, 0 );
167 i_ret
= vlc_stream_Seek( p_demux
->s
, i_old_offset
);