046217544dbe759fa35483f42a9b3e4732ccf94b
[vlc.git] / modules / stream_out / autodel.c
1 /*****************************************************************************
2  * autodel.c: monitor mux inputs and automatically add/delete streams
3  *****************************************************************************
4  * Copyright (C) 2006 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
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_sout.h>
34 #include <vlc_block.h>
35 #include <vlc_list.h>
36
37 typedef struct sout_stream_id_sys_t sout_stream_id_sys_t;
38 struct sout_stream_id_sys_t
39 {
40     sout_stream_id_sys_t *id;
41     es_format_t fmt;
42     vlc_tick_t i_last;
43     bool b_error;
44     struct vlc_list node;
45 };
46
47 typedef struct
48 {
49     struct vlc_list ids;
50 } sout_stream_sys_t;
51
52 static void *Add( sout_stream_t *p_stream, const es_format_t *p_fmt )
53 {
54     sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys;
55     sout_stream_id_sys_t *p_es = malloc( sizeof(sout_stream_id_sys_t) );
56     if( unlikely(p_es == NULL) )
57         return NULL;
58
59     es_format_Copy( &p_es->fmt, p_fmt );
60
61     p_es->id = NULL;
62     p_es->i_last = VLC_TICK_INVALID;
63     p_es->b_error = false;
64     vlc_list_append(&p_es->node, &p_sys->ids);
65     return p_es;
66 }
67
68 static void Del( sout_stream_t *p_stream, void *_p_es )
69 {
70     sout_stream_id_sys_t *p_es = (sout_stream_id_sys_t *)_p_es;
71
72     if( p_es->id != NULL )
73         sout_StreamIdDel( p_stream->p_next, p_es->id );
74
75     vlc_list_remove(&p_es->node);
76     es_format_Clean( &p_es->fmt );
77     free( p_es );
78 }
79
80 static int Send( sout_stream_t *p_stream, void *_p_es, block_t *p_buffer )
81 {
82     sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys;
83     sout_stream_id_sys_t *p_es = (sout_stream_id_sys_t *)_p_es;
84     vlc_tick_t i_current = vlc_tick_now();
85
86     p_es->i_last = p_buffer->i_dts;
87     if ( !p_es->id && !p_es->b_error )
88     {
89         p_es->id = sout_StreamIdAdd( p_stream->p_next, &p_es->fmt );
90         if ( p_es->id == NULL )
91         {
92             p_es->b_error = true;
93             msg_Err( p_stream, "couldn't create chain for id %d",
94                      p_es->fmt.i_id );
95         }
96     }
97
98     if ( !p_es->b_error )
99         sout_StreamIdSend( p_stream->p_next, p_es->id, p_buffer );
100     else
101         block_ChainRelease( p_buffer );
102
103     vlc_list_foreach (p_es, &p_sys->ids, node)
104         if (p_es->id != NULL
105          && (p_es->fmt.i_cat == VIDEO_ES || p_es->fmt.i_cat == AUDIO_ES)
106          && p_es->i_last < i_current)
107         {
108             sout_StreamIdDel(p_stream->p_next, p_es->id);
109             p_es->id = NULL;
110         }
111
112     return VLC_SUCCESS;
113 }
114
115 static const struct sout_stream_operations ops = {
116     Add, Del, Send, NULL, NULL,
117 };
118
119 static int Open( vlc_object_t *p_this )
120 {
121     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
122     sout_stream_sys_t *p_sys = vlc_obj_malloc(p_this, sizeof (*p_sys));
123
124     if (unlikely(p_sys == NULL))
125         return VLC_ENOMEM;
126
127     vlc_list_init(&p_sys->ids);
128     p_stream->ops = &ops;
129     p_stream->p_sys = p_sys;
130
131     return VLC_SUCCESS;
132 }
133
134 #define SOUT_CFG_PREFIX "sout-autodel-"
135
136 vlc_module_begin()
137     set_shortname(N_("Autodel"))
138     set_description(N_("Automatically add/delete input streams"))
139     set_capability("sout filter", 50)
140     add_shortcut("autodel")
141     set_callback(Open)
142 vlc_module_end()