40e612ee1b6485a5dc46ccb35fc1c06fe0f2c521
[vlc.git] / modules / stream_out / delay.c
1 /*****************************************************************************
2  * delay.c: delay a stream
3  *****************************************************************************
4  * Copyright © 2009-2011 VLC authors and 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 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <vlc_common.h>
31 #include <vlc_plugin.h>
32 #include <vlc_sout.h>
33 #include <vlc_block.h>
34
35 #define SOUT_CFG_PREFIX "sout-delay-"
36
37 typedef struct
38 {
39     void *id;
40     int i_id;
41     vlc_tick_t i_delay;
42 } sout_stream_sys_t;
43
44 static void *Add( sout_stream_t *p_stream, const es_format_t *p_fmt )
45 {
46     sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys;
47
48     if ( p_fmt->i_id == p_sys->i_id )
49     {
50         msg_Dbg( p_stream, "delaying ID %d by %"PRId64,
51                  p_sys->i_id, p_sys->i_delay );
52         p_sys->id = sout_StreamIdAdd( p_stream->p_next, p_fmt );
53         return p_sys->id;
54     }
55
56     return sout_StreamIdAdd( p_stream->p_next, p_fmt );
57 }
58
59 static void Del( sout_stream_t *p_stream, void *id )
60 {
61     sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys;
62
63     if ( id == p_sys->id )
64         p_sys->id = NULL;
65
66     sout_StreamIdDel( p_stream->p_next, id );
67 }
68
69 static int Send( sout_stream_t *p_stream, void *id, block_t *p_buffer )
70 {
71     sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys;
72
73     if ( id == p_sys->id )
74     {
75         block_t *p_block = p_buffer;
76         while ( p_block != NULL )
77         {
78             if ( p_block->i_pts != VLC_TICK_INVALID )
79                 p_block->i_pts += p_sys->i_delay;
80             if ( p_block->i_dts != VLC_TICK_INVALID )
81                 p_block->i_dts += p_sys->i_delay;
82             p_block = p_block->p_next;
83         }
84     }
85
86     return sout_StreamIdSend( p_stream->p_next, id, p_buffer );
87 }
88
89 static const struct sout_stream_operations ops = {
90     Add, Del, Send, NULL, NULL,
91 };
92
93 static const char *ppsz_sout_options[] = {
94     "id", "delay", NULL
95 };
96
97 /*****************************************************************************
98  * Open:
99  *****************************************************************************/
100 static int Open( vlc_object_t *p_this )
101 {
102     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
103     sout_stream_sys_t *p_sys;
104
105     p_sys = calloc( 1, sizeof( sout_stream_sys_t ) );
106     if( !p_sys )
107         return VLC_ENOMEM;
108
109
110     config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
111                    p_stream->p_cfg );
112
113     p_sys->i_id = var_GetInteger( p_stream, SOUT_CFG_PREFIX "id" );
114     p_sys->i_delay = VLC_TICK_FROM_MS(var_GetInteger( p_stream, SOUT_CFG_PREFIX "delay" ));
115
116     p_stream->ops = &ops;
117     p_stream->p_sys = p_sys;
118     return VLC_SUCCESS;
119 }
120
121 /*****************************************************************************
122  * Close:
123  *****************************************************************************/
124 static void Close( vlc_object_t * p_this )
125 {
126     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
127     sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys;
128
129     free( p_sys );
130 }
131
132 /*****************************************************************************
133  * Module descriptor
134  *****************************************************************************/
135 #define ID_TEXT N_("Elementary Stream ID")
136 #define ID_LONGTEXT N_( \
137     "Specify an identifier integer for this elementary stream" )
138
139 #define DELAY_TEXT N_("Delay of the ES (ms)")
140 #define DELAY_LONGTEXT N_( \
141     "Specify a delay (in ms) for this elementary stream. " \
142     "Positive means delay and negative means advance." )
143
144 vlc_module_begin()
145     set_shortname(N_("Delay"))
146     set_description(N_("Delay a stream"))
147     set_capability("sout filter", 50)
148     add_shortcut("delay")
149     set_category(CAT_SOUT)
150     set_subcategory(SUBCAT_SOUT_STREAM)
151     set_callbacks(Open, Close)
152     add_integer(SOUT_CFG_PREFIX "id", 0, ID_TEXT, ID_LONGTEXT,
153                 false)
154     add_integer(SOUT_CFG_PREFIX "delay", 0, DELAY_TEXT, DELAY_LONGTEXT,
155                 false)
156 vlc_module_end()