c81802297d89efdb4f1c4d80d34762ae0f403c2e
[vlc.git] / modules / stream_out / display.c
1 /*****************************************************************************
2  * display.c: display stream output module
3  *****************************************************************************
4  * Copyright (C) 2001-2011 VLC authors and VideoLAN
5  *
6  * Authors: Laurent Aimar <fenrir@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 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_decoder.h>
34 #include <vlc_sout.h>
35 #include <vlc_block.h>
36
37 /*****************************************************************************
38  * Module descriptor
39  *****************************************************************************/
40 #define AUDIO_TEXT N_("Enable audio")
41 #define AUDIO_LONGTEXT N_( "Enable/disable audio rendering." )
42 #define VIDEO_TEXT N_("Enable video")
43 #define VIDEO_LONGTEXT N_( "Enable/disable video rendering." )
44 #define DELAY_TEXT N_("Delay (ms)")
45 #define DELAY_LONGTEXT N_( "Introduces a delay in the display of the stream." )
46
47 static int  Open ( vlc_object_t * );
48 static void Close( vlc_object_t * );
49
50 #define SOUT_CFG_PREFIX "sout-display-"
51
52 vlc_module_begin ()
53     set_shortname( N_("Display"))
54     set_description( N_("Display stream output") )
55     set_capability( "sout output", 50 )
56     add_shortcut( "display" )
57     set_category( CAT_SOUT )
58     set_subcategory( SUBCAT_SOUT_STREAM )
59
60     add_bool( SOUT_CFG_PREFIX "audio", true, AUDIO_TEXT,
61               AUDIO_LONGTEXT, true )
62     add_bool( SOUT_CFG_PREFIX "video", true, VIDEO_TEXT,
63               VIDEO_LONGTEXT, true )
64     add_integer( SOUT_CFG_PREFIX "delay", 100, DELAY_TEXT,
65                  DELAY_LONGTEXT, true )
66     set_callbacks( Open, Close )
67 vlc_module_end ()
68
69
70 /*****************************************************************************
71  * Exported prototypes
72  *****************************************************************************/
73 static const char *const ppsz_sout_options[] = {
74     "audio", "video", "delay", NULL
75 };
76
77 typedef struct
78 {
79     bool     b_audio;
80     bool     b_video;
81
82     vlc_tick_t     i_delay;
83     input_resource_t *p_resource;
84 } sout_stream_sys_t;
85
86 static void *Add( sout_stream_t *p_stream, const es_format_t *p_fmt )
87 {
88     sout_stream_sys_t *p_sys = p_stream->p_sys;
89
90     if( ( p_fmt->i_cat == AUDIO_ES && !p_sys->b_audio )||
91         ( p_fmt->i_cat == VIDEO_ES && !p_sys->b_video ) )
92     {
93         return NULL;
94     }
95
96     vlc_input_decoder_t *p_dec =
97         vlc_input_decoder_Create( VLC_OBJECT(p_stream), p_fmt,
98                                   p_sys->p_resource );
99     if( p_dec == NULL )
100     {
101         msg_Err( p_stream, "cannot create decoder for fcc=`%4.4s'",
102                  (char*)&p_fmt->i_codec );
103         return NULL;
104     }
105     return p_dec;
106 }
107
108 static void Del( sout_stream_t *p_stream, void *id )
109 {
110     (void) p_stream;
111     vlc_input_decoder_Delete( id );
112 }
113
114 static int Send( sout_stream_t *p_stream, void *id, block_t *p_buffer )
115 {
116     sout_stream_sys_t *p_sys = p_stream->p_sys;
117
118     while( p_buffer )
119     {
120         block_t *p_next = p_buffer->p_next;
121
122         p_buffer->p_next = NULL;
123
124         if( id != NULL && p_buffer->i_buffer > 0 )
125         {
126             if( p_buffer->i_dts == VLC_TICK_INVALID )
127                 p_buffer->i_dts = 0;
128             else
129                 p_buffer->i_dts += p_sys->i_delay;
130
131             if( p_buffer->i_pts == VLC_TICK_INVALID )
132                 p_buffer->i_pts = 0;
133             else
134                 p_buffer->i_pts += p_sys->i_delay;
135
136             vlc_input_decoder_Decode( id, p_buffer, false );
137         }
138
139         p_buffer = p_next;
140     }
141
142     return VLC_SUCCESS;
143 }
144
145 static int Control( sout_stream_t *p_stream, int i_query, va_list args )
146 {
147     switch (i_query)
148     {
149         case SOUT_STREAM_ID_SPU_HIGHLIGHT:
150         {
151             vlc_input_decoder_t *p_dec = va_arg(args, void *);
152             void *spu_hl = va_arg(args, void *);
153             return vlc_input_decoder_SetSpuHighlight( p_dec, spu_hl );
154         }
155
156         case SOUT_STREAM_IS_SYNCHRONOUS:
157             *va_arg(args, bool *) = true;
158             break;
159
160         default:
161            return VLC_EGENERIC;
162     }
163     (void) p_stream;
164     return VLC_SUCCESS;
165 }
166
167 static const struct sout_stream_operations ops = {
168     Add, Del, Send, Control, NULL,
169 };
170
171 /*****************************************************************************
172  * Open:
173  *****************************************************************************/
174 static int Open( vlc_object_t *p_this )
175 {
176     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
177     sout_stream_sys_t *p_sys;
178
179     p_sys = malloc( sizeof( sout_stream_sys_t ) );
180     if( p_sys == NULL )
181         return VLC_ENOMEM;
182
183     p_sys->p_resource = input_resource_New( p_this );
184     if( unlikely(p_sys->p_resource == NULL) )
185     {
186         free( p_sys );
187         return VLC_ENOMEM;
188     }
189
190     config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
191                    p_stream->p_cfg );
192
193     p_sys->b_audio = var_GetBool( p_stream, SOUT_CFG_PREFIX"audio" );
194     p_sys->b_video = var_GetBool( p_stream, SOUT_CFG_PREFIX "video" );
195     p_sys->i_delay = VLC_TICK_FROM_MS( var_GetInteger( p_stream, SOUT_CFG_PREFIX "delay" ) );
196
197     p_stream->ops = &ops;
198     p_stream->p_sys     = p_sys;
199     return VLC_SUCCESS;
200 }
201
202 /*****************************************************************************
203  * Close:
204  *****************************************************************************/
205 static void Close( vlc_object_t * p_this )
206 {
207     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
208     sout_stream_sys_t *p_sys = p_stream->p_sys;
209
210     input_resource_Release( p_sys->p_resource );
211     free( p_sys );
212 }