f74830234632fcbcd0028672f79dc49ee1a062ab
[vlc.git] / test / src / input / demux-run.c
1 /**
2  * @file demux-run.c
3  */
4 /*****************************************************************************
5  * Copyright © 2016 Rémi Denis-Courmont
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * Rémi Denis-Courmont reserves the right to redistribute this file under
13  * the terms of the GNU Lesser General Public License as published by the
14  * the Free Software Foundation; either version 2.1 or the License, or
15  * (at his option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <limits.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36
37 #include <vlc_common.h>
38 #include <vlc_access.h>
39 #include <vlc_block.h>
40 #include <vlc_demux.h>
41 #include <vlc_es_out.h>
42 #include <vlc_url.h>
43 #include "../lib/libvlc_internal.h"
44
45 #include <vlc/vlc.h>
46
47 #include "demux-run.h"
48
49 struct test_es_out_t
50 {
51     struct es_out_t out;
52     struct es_out_id_t *ids;
53 };
54
55 struct es_out_id_t
56 {
57     struct es_out_id_t *next;
58 };
59
60 static es_out_id_t *EsOutAdd(es_out_t *out, const es_format_t *fmt)
61 {
62     struct test_es_out_t *ctx = (struct test_es_out_t *) out;
63
64     if (fmt->i_group < 0)
65         return NULL;
66
67     es_out_id_t *id = malloc(sizeof (*id));
68     if (unlikely(id == NULL))
69         return NULL;
70
71     id->next = ctx->ids;
72     ctx->ids = id;
73
74     debug("[%p] Added   ES\n", (void *)id);
75     return id;
76 }
77
78 static void EsOutCheckId(es_out_t *out, es_out_id_t *id)
79 {
80     struct test_es_out_t *ctx = (struct test_es_out_t *) out;
81
82     for (es_out_id_t *ids = ctx->ids; ids != NULL; ids = ids->next)
83         if (ids == id)
84             return;
85
86     abort();
87 }
88
89 static int EsOutSend(es_out_t *out, es_out_id_t *id, block_t *block)
90 {
91     //debug("[%p] Sent    ES: %zu\n", (void *)idd, block->i_buffer);
92     EsOutCheckId(out, id);
93     block_Release(block);
94     return VLC_SUCCESS;
95 }
96
97 static void EsOutDelete(es_out_t *out, es_out_id_t *id)
98 {
99     struct test_es_out_t *ctx = (struct test_es_out_t *) out;
100     es_out_id_t **pp = &ctx->ids;
101
102     while (*pp != id)
103     {
104         if (*pp == NULL)
105             abort();
106         pp = &((*pp)->next);
107     }
108
109     debug("[%p] Deleted ES\n", (void *)id);
110     *pp = id->next;
111     free(id);
112 }
113
114 static int EsOutControl(es_out_t *out, int query, va_list args)
115 {
116     switch (query)
117     {
118         case ES_OUT_SET_ES:
119             break;
120         case ES_OUT_RESTART_ES:
121             abort();
122         case ES_OUT_SET_ES_DEFAULT:
123         case ES_OUT_SET_ES_STATE:
124             break;
125         case ES_OUT_GET_ES_STATE:
126             EsOutCheckId(out, va_arg(args, es_out_id_t *));
127             *va_arg(args, bool *) = true;
128             break;
129         case ES_OUT_SET_ES_CAT_POLICY:
130             break;
131         case ES_OUT_SET_GROUP:
132             abort();
133         case ES_OUT_SET_PCR:
134         case ES_OUT_SET_GROUP_PCR:
135         case ES_OUT_RESET_PCR:
136         case ES_OUT_SET_ES_FMT:
137         case ES_OUT_SET_NEXT_DISPLAY_TIME:
138         case ES_OUT_SET_GROUP_META:
139         case ES_OUT_SET_GROUP_EPG:
140         case ES_OUT_DEL_GROUP:
141         case ES_OUT_SET_ES_SCRAMBLED_STATE:
142             break;
143         case ES_OUT_GET_EMPTY:
144             *va_arg(args, bool *) = true;
145             break;
146         case ES_OUT_SET_META:
147             break;
148         case ES_OUT_GET_PCR_SYSTEM:
149         case ES_OUT_MODIFY_PCR_SYSTEM:
150             abort();
151         default:
152             return VLC_EGENERIC;
153     }
154     return VLC_SUCCESS;
155 }
156
157 static void EsOutDestroy(es_out_t *out)
158 {
159     struct test_es_out_t *ctx = (struct test_es_out_t *)out;
160     es_out_id_t *id;
161
162     while ((id = ctx->ids) != NULL)
163     {
164         ctx->ids = id->next;
165         free(id);
166     }
167     free(ctx);
168 }
169
170 static es_out_t *test_es_out_create(vlc_object_t *parent)
171 {
172     struct test_es_out_t *ctx = malloc(sizeof (*ctx));
173     if (ctx == NULL)
174     {
175         fprintf(stderr, "Error: cannot create ES output.\n");
176         return NULL;
177     }
178
179     ctx->ids = NULL;
180
181     es_out_t *out = &ctx->out;
182     out->pf_add = EsOutAdd;
183     out->pf_send = EsOutSend;
184     out->pf_del = EsOutDelete;
185     out->pf_control = EsOutControl;
186     out->pf_destroy = EsOutDestroy;
187     out->p_sys = (void *)parent;
188
189     return out;
190 }
191
192 static int demux_process_stream(const struct vlc_run_args *args, stream_t *s)
193 {
194     const char *name = args->name;
195     if (name == NULL)
196         name = "any";
197
198     if (s == NULL)
199         return -1;
200
201     es_out_t *out = test_es_out_create(VLC_OBJECT(s));
202     if (out == NULL)
203         return -1;
204
205     demux_t *demux = demux_New(VLC_OBJECT(s), name, "", s, out);
206     if (demux == NULL)
207     {
208         es_out_Delete(out);
209         vlc_stream_Delete(s);
210         debug("Error: cannot create demultiplexer: %s\n", name);
211         return -1;
212     }
213
214     uintmax_t i = 0;
215     int val;
216
217     while ((val = demux_Demux(demux)) == VLC_DEMUXER_SUCCESS)
218          i++;
219
220     demux_Delete(demux);
221     es_out_Delete(out);
222
223     debug("Completed with %ju iteration(s).\n", i);
224
225     return val == VLC_DEMUXER_EOF ? 0 : -1;
226 }
227
228 int vlc_demux_process_url(const struct vlc_run_args *args, const char *url)
229 {
230     libvlc_instance_t *vlc = libvlc_create(args);
231     if (vlc == NULL)
232         return -1;
233
234     stream_t *s = vlc_access_NewMRL(VLC_OBJECT(vlc->p_libvlc_int), url);
235     if (s == NULL)
236         fprintf(stderr, "Error: cannot create input stream: %s\n", url);
237
238     int ret = demux_process_stream(args, s);
239     libvlc_release(vlc);
240     return ret;
241 }
242
243 int vlc_demux_process_path(const struct vlc_run_args *args, const char *path)
244 {
245     char *url = vlc_path2uri(path, NULL);
246     if (url == NULL)
247     {
248         fprintf(stderr, "Error: cannot convert path to URL: %s\n", path);
249         return -1;
250     }
251
252     int ret = vlc_demux_process_url(args, url);
253     free(url);
254     return ret;
255 }
256
257 int vlc_demux_process_memory(const struct vlc_run_args *args,
258                              const unsigned char *buf, size_t length)
259 {
260     libvlc_instance_t *vlc = libvlc_create(args);
261     if (vlc == NULL)
262         return -1;
263
264     stream_t *s = vlc_stream_MemoryNew(VLC_OBJECT(vlc->p_libvlc_int),
265                                        (void *)buf, length, true);
266     if (s == NULL)
267         fprintf(stderr, "Error: cannot create input stream\n");
268
269     int ret = demux_process_stream(args, s);
270     libvlc_release(vlc);
271     return ret;
272 }
273
274 #ifdef HAVE_STATIC_MODULES
275 # include <vlc_plugin.h>
276
277 typedef int (*vlc_plugin_cb)(int (*)(void *, void *, int, ...), void *);
278 extern vlc_plugin_cb vlc_static_modules[];
279
280 #define PLUGINS(f) \
281     f(console) \
282     f(filesystem) \
283     f(xml) \
284     f(aiff) \
285     f(asf) \
286     f(au) \
287     f(avi) \
288     f(caf) \
289     f(diracsys) \
290     f(es) \
291     f(flacsys) \
292     f(h26x) \
293     f(mjpeg) \
294     f(mkv) \
295     f(mp4) \
296     f(nsc) \
297     f(nsv) \
298     f(ps) \
299     f(pva) \
300     f(sap) \
301     f(smf) \
302     f(subtitle) \
303     PLUGIN_TS(f) \
304     f(tta) \
305     f(ttml) \
306     f(ty) \
307     f(voc) \
308     f(wav) \
309     f(xa) \
310     f(a52) \
311     f(dirac) \
312     f(dts) \
313     f(flac) \
314     f(h264) \
315     f(hevc) \
316     f(mlp) \
317     f(mpeg4audio) \
318     f(mpeg4video) \
319     f(mpegaudio) \
320     f(mpegvideo) \
321     f(vc1)
322 #ifdef HAVE_DVBPSI
323 # define PLUGIN_TS(f) f(ts)
324 #else
325 # define PLUGIN_TS(f)
326 #endif
327
328 #define DECL_PLUGIN(p) \
329     int vlc_entry__##p(int (*)(void *, void *, int, ...), void *);
330
331 #define FUNC_PLUGIN(p) \
332     vlc_entry__##p,
333
334 PLUGINS(DECL_PLUGIN)
335
336 __attribute__((visibility("default")))
337 vlc_plugin_cb vlc_static_modules[] = { PLUGINS(FUNC_PLUGIN) NULL };
338 #endif /* HAVE_STATIC_MODULES */