]> git.sesse.net Git - vlc/blob - modules/access/fake.c
Round 2
[vlc] / modules / access / fake.c
1 /*****************************************************************************
2  * fake.c : Fake video input for VLC
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  * $Id$
6  *
7  * Author: Christophe Massiot <massiot@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc_access.h>
33 #include <vlc_demux.h>
34
35 /*****************************************************************************
36  * Module descriptior
37  *****************************************************************************/
38 static int  Open ( vlc_object_t * );
39 static void Close( vlc_object_t * );
40
41 #define CACHING_TEXT N_("Caching value in ms")
42 #define CACHING_LONGTEXT N_( \
43     "Caching value for fake streams. This " \
44     "value should be set in milliseconds." )
45 #define FPS_TEXT N_("Framerate")
46 #define FPS_LONGTEXT N_( \
47     "Number of frames per second (eg. 24, 25, 29.97, 30).")
48 #define ID_TEXT N_("ID")
49 #define ID_LONGTEXT N_( \
50     "Set the ID of the fake elementary stream for use in " \
51     "#duplicate{} constructs (default 0).")
52 #define DURATION_TEXT N_("Duration in ms")
53 #define DURATION_LONGTEXT N_( \
54     "Duration of the fake streaming before faking an " \
55     "end-of-file (default is 0, meaning that the stream is unlimited).")
56
57 vlc_module_begin();
58     set_shortname( _("Fake") );
59     set_description( _("Fake input") );
60     set_category( CAT_INPUT );
61     set_subcategory( SUBCAT_INPUT_ACCESS );
62
63     add_integer( "fake-caching", DEFAULT_PTS_DELAY / 1000, NULL,
64                  CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
65     add_float( "fake-fps", 25.0, NULL, FPS_TEXT, FPS_LONGTEXT, VLC_TRUE );
66     add_integer( "fake-id", 0, NULL, ID_TEXT, ID_LONGTEXT, VLC_TRUE );
67     add_integer( "fake-duration", 0, NULL, DURATION_TEXT, DURATION_LONGTEXT,
68                  VLC_TRUE );
69
70     add_shortcut( "fake" );
71     set_capability( "access_demux", 0 );
72     set_callbacks( Open, Close );
73 vlc_module_end();
74
75 /*****************************************************************************
76  * Access: local prototypes
77  *****************************************************************************/
78 static int Demux  ( demux_t * );
79 static int Control( demux_t *, int, va_list );
80
81 struct demux_sys_t
82 {
83     float f_fps;
84     mtime_t i_last_pts, i_duration, i_first_pts, i_end_pts, i_pause_pts;
85
86     es_out_id_t  *p_es_video;
87 };
88
89 /*****************************************************************************
90  * Open: opens fake device
91  *****************************************************************************/
92 static int Open( vlc_object_t *p_this )
93 {
94     demux_t     *p_demux = (demux_t*)p_this;
95     demux_sys_t *p_sys;
96     es_format_t fmt;
97
98     /* Only when selected */
99     if( *p_demux->psz_access == '\0' )
100         return VLC_EGENERIC;
101
102     /* Set up p_demux */
103     STANDARD_DEMUX_INIT; p_sys = p_demux->p_sys;
104     p_demux->info.i_update = 0;
105     p_demux->info.i_title = 0;
106     p_demux->info.i_seekpoint = 0;
107
108     p_sys->i_duration = var_CreateGetInteger( p_demux, "fake-duration" ) * 1000;
109     p_sys->f_fps = var_CreateGetFloat( p_demux, "fake-fps" );
110
111     /* Declare the elementary stream */
112     es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC('f','a','k','e') );
113     fmt.i_id = var_CreateGetInteger( p_demux, "fake-id" );
114     p_sys->p_es_video = es_out_Add( p_demux->out, &fmt );
115
116     /* Update default_pts to a suitable value for access */
117     var_Create( p_demux, "fake-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
118
119     return VLC_SUCCESS;
120 }
121
122 /*****************************************************************************
123  * Close: close device, free resources
124  *****************************************************************************/
125 static void Close( vlc_object_t *p_this )
126 {
127     demux_t     *p_demux = (demux_t *)p_this;
128     demux_sys_t *p_sys   = p_demux->p_sys;
129
130     free( p_sys );
131 }
132
133 /*****************************************************************************
134  * Control:
135  *****************************************************************************/
136 static int Control( demux_t *p_demux, int i_query, va_list args )
137 {
138     demux_sys_t *p_sys = p_demux->p_sys;
139     vlc_bool_t *pb, b;
140     int64_t    *pi64, i64;
141     double     *pf, f;
142
143     switch( i_query )
144     {
145         /* Special for access_demux */
146         case DEMUX_CAN_PAUSE:
147         case DEMUX_CAN_CONTROL_PACE:
148             pb = (vlc_bool_t *)va_arg( args, vlc_bool_t * );
149             *pb = VLC_TRUE;
150             return VLC_SUCCESS;
151
152         case DEMUX_SET_PAUSE_STATE:
153             b = (vlc_bool_t)va_arg( args, vlc_bool_t );
154             if ( b )
155             {
156                 p_sys->i_pause_pts = mdate();
157             }
158             else if ( p_sys->i_pause_pts )
159             {
160                 mtime_t i_pause_duration = mdate() - p_sys->i_pause_pts;
161                 p_sys->i_first_pts += i_pause_duration;
162                 p_sys->i_last_pts += i_pause_duration;
163                 if ( p_sys->i_duration )
164                     p_sys->i_end_pts += i_pause_duration;
165                 p_sys->i_pause_pts = 0;
166             }
167             return VLC_SUCCESS;
168
169         case DEMUX_GET_PTS_DELAY:
170             pi64 = (int64_t *)va_arg( args, int64_t * );
171             *pi64 = (int64_t)var_GetInteger( p_demux, "fake-caching" ) * 1000;
172             return VLC_SUCCESS;
173
174         case DEMUX_GET_POSITION:
175             pf = (double*)va_arg( args, double* );
176             if( p_sys->i_duration > 0 )
177             {
178                 *pf = (double)( p_sys->i_last_pts - p_sys->i_first_pts )
179                                 / (double)(p_sys->i_duration);
180             }
181             else
182             {
183                 *pf = 0;
184             }
185             return VLC_SUCCESS;
186
187         case DEMUX_SET_POSITION:
188             f = (double)va_arg( args, double );
189             i64 = f * (double)p_sys->i_duration;
190             p_sys->i_first_pts = p_sys->i_last_pts - i64;
191             p_sys->i_end_pts = p_sys->i_first_pts + p_sys->i_duration;
192             return VLC_SUCCESS;
193
194         case DEMUX_GET_TIME:
195             pi64 = (int64_t *)va_arg( args, int64_t * );
196             if ( p_sys->i_duration )
197                 *pi64 = p_sys->i_last_pts - p_sys->i_first_pts;
198             else
199                 *pi64 = p_sys->i_last_pts;
200             return VLC_SUCCESS;
201
202         case DEMUX_GET_LENGTH:
203             pi64 = (int64_t*)va_arg( args, int64_t * );
204             *pi64 = p_sys->i_duration;
205             return VLC_SUCCESS;
206
207         case DEMUX_SET_TIME:
208             i64 = (int64_t)va_arg( args, int64_t );
209             p_sys->i_first_pts = p_sys->i_last_pts - i64;
210             p_sys->i_end_pts = p_sys->i_first_pts + p_sys->i_duration;
211             return VLC_SUCCESS;
212
213         /* TODO implement others */
214         default:
215             return VLC_EGENERIC;
216     }
217
218     return VLC_EGENERIC;
219 }
220
221 /*****************************************************************************
222  * Demux:
223  *****************************************************************************/
224 static int Demux( demux_t *p_demux )
225 {
226     demux_sys_t *p_sys = p_demux->p_sys;
227     block_t *p_block = block_New( p_demux, 1 );
228
229     if ( !p_sys->i_last_pts )
230     {
231         p_sys->i_last_pts = p_sys->i_first_pts = mdate();
232         if ( p_sys->i_duration )
233             p_sys->i_end_pts = p_sys->i_first_pts + p_sys->i_duration;
234     }
235     else
236     {
237         p_sys->i_last_pts += (mtime_t)(1000000.0 / p_sys->f_fps);
238         if ( p_sys->i_duration && p_sys->i_last_pts > p_sys->i_end_pts )
239             return 0;
240         mwait( p_sys->i_last_pts );
241     }
242
243     p_block->i_flags |= BLOCK_FLAG_TYPE_I;
244     p_block->i_dts = p_block->i_pts = p_sys->i_last_pts;
245
246     es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts );
247     es_out_Send( p_demux->out, p_sys->p_es_video, p_block );
248
249     return 1;
250 }
251