demux: es: fix swab usage
[vlc.git] / modules / demux / mock.c
blob03d282606bd96a7c511a1de11269c4e6f9ba3da3
1 /*****************************************************************************
2 * mock.c : mock demux module for vlc
3 *****************************************************************************
4 * Copyright (C) 2018 VLC authors and VideoLAN
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
25 #include <ctype.h>
26 #include <limits.h>
28 #include <vlc_common.h>
29 #include <vlc_plugin.h>
30 #include <vlc_aout.h>
31 #include <vlc_picture.h>
32 #include <vlc_demux.h>
33 #include <vlc_input.h>
34 #include <vlc_vector.h>
37 struct mock_track
39 es_format_t fmt;
40 es_out_id_t *id;
42 typedef struct VLC_VECTOR(struct mock_track *) mock_track_vector;
44 static ssize_t
45 var_InheritSsize(vlc_object_t *obj, const char *name)
47 int64_t value = var_InheritInteger(obj, name);
48 return value >= 0 ? value : -1;
51 static unsigned
52 var_InheritUnsigned(vlc_object_t *obj, const char *name)
54 int64_t value = var_InheritInteger(obj, name);
55 return value >= 0 && value < UINT_MAX ? value : UINT_MAX;
58 static vlc_fourcc_t
59 var_InheritFourcc(vlc_object_t *obj, const char *name)
61 char *var_value = var_InheritString(obj, name);
62 if (!var_value)
63 return 0;
65 size_t var_len = strlen(var_value);
66 if (var_len > 4)
68 free(var_value);
69 return 0;
72 /* Pad with spaces if the string len is less than 4 */
73 char value[] = " ";
74 strcpy(value, var_value);
75 if (var_len != 4)
76 value[var_len] = ' ';
77 free(var_value);
79 vlc_fourcc_t fourcc;
80 memcpy(&fourcc, value, 4);
81 return fourcc;
84 /* var_name, type, module_header_type, getter, default_value */
85 #define LIST_OPTIONS \
86 X(length, vlc_tick_t, add_integer, var_InheritInteger, VLC_TICK_FROM_MS(5000)) \
87 X(audio_track_count, ssize_t, add_integer, var_InheritSsize, 0) \
88 X(audio_channels, unsigned, add_integer, var_InheritUnsigned, 2) \
89 X(audio_format, vlc_fourcc_t, add_string, var_InheritFourcc, "u8") \
90 X(audio_rate, unsigned, add_integer, var_InheritUnsigned, 44100) \
91 X(audio_packetized, bool, add_bool, var_InheritBool, true) \
92 X(video_track_count, ssize_t, add_integer, var_InheritSsize, 0) \
93 X(video_chroma, vlc_fourcc_t, add_string, var_InheritFourcc, "I420") \
94 X(video_width, unsigned, add_integer, var_InheritUnsigned, 640) \
95 X(video_height, unsigned, add_integer, var_InheritUnsigned, 480) \
96 X(video_frame_rate, unsigned, add_integer, var_InheritUnsigned, 25) \
97 X(video_frame_rate_base, unsigned, add_integer, var_InheritUnsigned, 1) \
98 X(video_packetized, bool, add_bool, var_InheritBool, true) \
99 X(sub_track_count, ssize_t, add_integer, var_InheritSsize, 0) \
100 X(sub_packetized, bool, add_bool, var_InheritBool, true) \
101 X(title_count, ssize_t, add_integer, var_InheritSsize, 0 ) \
102 X(chapter_count, ssize_t, add_integer, var_InheritSsize, 0) \
103 X(null_names, bool, add_bool, var_InheritBool, false) \
104 X(program_count, ssize_t, add_integer, var_InheritSsize, 0) \
105 X(can_seek, bool, add_bool, var_InheritBool, true) \
106 X(can_pause, bool, add_bool, var_InheritBool, true) \
107 X(can_control_pace, bool, add_bool, var_InheritBool, true) \
108 X(can_control_rate, bool, add_bool, var_InheritBool, true) \
109 X(can_record, bool, add_bool, var_InheritBool, true) \
110 X(error, bool, add_bool, var_InheritBool, false) \
111 X(add_video_track_at, vlc_tick_t, add_integer, var_InheritInteger, VLC_TICK_INVALID ) \
112 X(add_audio_track_at, vlc_tick_t, add_integer, var_InheritInteger, VLC_TICK_INVALID ) \
113 X(add_spu_track_at, vlc_tick_t, add_integer, var_InheritInteger, VLC_TICK_INVALID ) \
115 struct demux_sys
117 mock_track_vector tracks;
118 vlc_tick_t pts;
119 vlc_tick_t step_length;
121 int current_title;
122 size_t chapter_gap;
124 #define X(var_name, type, module_header_type, getter, default_value) \
125 type var_name;
126 LIST_OPTIONS
127 #undef X
130 static input_title_t *
131 CreateTitle(demux_t *demux, size_t idx)
133 struct demux_sys *sys = demux->p_sys;
135 input_title_t *t = vlc_input_title_New();
136 if (!t)
137 return NULL;
139 t->i_length = sys->length;
140 if (!sys->null_names
141 && asprintf(&t->psz_name, "Mock Title %zu", idx) == -1)
143 t->psz_name = NULL;
144 vlc_input_title_Delete(t);
145 return NULL;
147 t->seekpoint = vlc_alloc(sys->chapter_count, sizeof(*t->seekpoint));
148 if (!t->seekpoint)
150 vlc_input_title_Delete(t);
151 return NULL;
154 for (ssize_t i = 0; i < sys->chapter_count; ++i)
156 t->seekpoint[i] = vlc_seekpoint_New();
157 if (!t->seekpoint[i])
159 vlc_input_title_Delete(t);
160 return NULL;
162 t->i_seekpoint++;
163 if (!sys->null_names
164 && asprintf(&t->seekpoint[i]->psz_name, "Mock Chapter %zu-%zu", idx, i)
165 == -1)
167 vlc_input_title_Delete(t);
168 return NULL;
170 t->seekpoint[i]->i_time_offset = i * sys->chapter_gap;
172 return t;
175 static int
176 Control(demux_t *demux, int query, va_list args)
178 struct demux_sys *sys = demux->p_sys;
180 switch (query)
182 case DEMUX_CAN_SEEK:
183 *va_arg(args, bool *) = sys->can_seek;
184 return VLC_SUCCESS;
185 case DEMUX_CAN_PAUSE:
186 *va_arg(args, bool *) = sys->can_pause;
187 return VLC_SUCCESS;
188 case DEMUX_CAN_CONTROL_PACE:
189 *va_arg(args, bool *) = sys->can_control_pace;
190 return VLC_SUCCESS;
191 case DEMUX_GET_PTS_DELAY:
192 *va_arg(args, vlc_tick_t *) = 0;
193 return VLC_SUCCESS;
194 case DEMUX_GET_META:
195 return VLC_EGENERIC;
196 case DEMUX_GET_SIGNAL:
197 return VLC_EGENERIC;
198 case DEMUX_SET_PAUSE_STATE:
199 return sys->can_pause ? VLC_SUCCESS : VLC_EGENERIC;
200 case DEMUX_SET_TITLE:
201 if (sys->title_count > 0)
203 int new_title = va_arg(args, int);
204 if (new_title >= sys->title_count)
205 return VLC_EGENERIC;
206 sys->current_title = new_title;
207 sys->pts = VLC_TICK_0;
208 return VLC_SUCCESS;
210 return VLC_EGENERIC;
211 case DEMUX_SET_SEEKPOINT:
212 if (sys->chapter_gap > 0)
214 const int seekpoint_idx = va_arg(args, int);
215 if (seekpoint_idx < sys->chapter_count)
217 sys->pts = seekpoint_idx * sys->chapter_gap;
218 return VLC_SUCCESS;
221 return VLC_EGENERIC;
222 case DEMUX_TEST_AND_CLEAR_FLAGS:
223 return VLC_EGENERIC;
224 case DEMUX_GET_TITLE:
225 if (sys->title_count > 0)
227 *va_arg(args, int *) = sys->current_title;
228 return VLC_SUCCESS;
230 return VLC_EGENERIC;
231 case DEMUX_GET_SEEKPOINT:
232 if (sys->chapter_gap > 0)
234 *va_arg(args, int *) = sys->pts / sys->chapter_gap;
235 return VLC_SUCCESS;
237 return VLC_EGENERIC;
238 case DEMUX_GET_POSITION:
239 *va_arg(args, double *) = sys->pts / (double) sys->length;
240 return VLC_SUCCESS;
241 case DEMUX_SET_POSITION:
242 if (!sys->can_seek)
243 return VLC_EGENERIC;
244 sys->pts = va_arg(args, double) * sys->length;
245 return VLC_SUCCESS;
246 case DEMUX_GET_LENGTH:
247 *va_arg(args, vlc_tick_t *) = sys->length;
248 return VLC_SUCCESS;
249 case DEMUX_GET_TIME:
250 *va_arg(args, vlc_tick_t *) = sys->pts;
251 return VLC_SUCCESS;
252 case DEMUX_SET_TIME:
253 if (!sys->can_seek)
254 return VLC_EGENERIC;
255 sys->pts = va_arg(args, vlc_tick_t);
256 return VLC_SUCCESS;
257 case DEMUX_GET_TITLE_INFO:
258 if (sys->title_count > 0)
260 input_title_t ***titles = va_arg(args, input_title_t ***);
261 *titles = vlc_alloc(sys->title_count, sizeof(*titles));
262 if (!*titles)
263 return VLC_ENOMEM;
264 for (ssize_t i = 0; i < sys->title_count; ++i)
266 (*titles)[i] = CreateTitle(demux, i);
267 if (!(*titles)[i])
269 while (i--)
270 vlc_input_title_Delete((*titles)[i - 1]);
271 free(*titles);
272 *titles = NULL;
273 return VLC_ENOMEM;
276 *va_arg(args, int *) = sys->title_count;
277 *va_arg(args, int *) = 0;
278 *va_arg(args, int *) = 0;
279 return VLC_SUCCESS;
281 return VLC_EGENERIC;
282 case DEMUX_SET_GROUP_DEFAULT:
283 return VLC_EGENERIC;
284 case DEMUX_SET_GROUP_ALL:
285 return VLC_EGENERIC;
286 case DEMUX_SET_GROUP_LIST:
287 return VLC_EGENERIC;
288 case DEMUX_SET_ES:
289 return VLC_EGENERIC;
290 case DEMUX_SET_NEXT_DEMUX_TIME:
291 return VLC_EGENERIC;
292 case DEMUX_GET_FPS:
293 return VLC_EGENERIC;
294 case DEMUX_HAS_UNSUPPORTED_META:
295 return VLC_EGENERIC;
296 case DEMUX_GET_ATTACHMENTS:
297 return VLC_EGENERIC;
298 case DEMUX_CAN_RECORD:
299 *va_arg(args, bool *) = sys->can_record;
300 return VLC_SUCCESS;
301 case DEMUX_SET_RECORD_STATE:
302 return sys->can_record ? VLC_SUCCESS : VLC_EGENERIC;
303 case DEMUX_CAN_CONTROL_RATE:
304 *va_arg(args, bool *) = sys->can_control_rate;
305 return VLC_SUCCESS;
306 case DEMUX_SET_RATE:
307 return sys->can_control_rate ? VLC_SUCCESS : VLC_EGENERIC;
308 case DEMUX_IS_PLAYLIST:
309 return VLC_EGENERIC;
310 case DEMUX_NAV_ACTIVATE:
311 return VLC_EGENERIC;
312 case DEMUX_NAV_UP:
313 return VLC_EGENERIC;
314 case DEMUX_NAV_DOWN:
315 return VLC_EGENERIC;
316 case DEMUX_NAV_LEFT:
317 return VLC_EGENERIC;
318 case DEMUX_NAV_RIGHT:
319 return VLC_EGENERIC;
320 case DEMUX_NAV_POPUP:
321 return VLC_EGENERIC;
322 case DEMUX_NAV_MENU:
323 return VLC_EGENERIC;
324 default:
325 return VLC_EGENERIC;
329 static block_t *
330 CreateAudioBlock(demux_t *demux, struct mock_track *track)
332 struct demux_sys *sys = demux->p_sys;
333 const int64_t samples =
334 samples_from_vlc_tick(sys->step_length, track->fmt.audio.i_rate);
335 const int64_t bytes = samples / track->fmt.audio.i_frame_length
336 * track->fmt.audio.i_bytes_per_frame;
337 block_t *b = block_Alloc(bytes);
338 if (!b)
339 return NULL;
340 memset(b->p_buffer, 0, b->i_buffer);
341 return b;
344 struct video_block
346 block_t b;
347 picture_t *pic;
350 static void
351 video_block_free_cb(block_t *b)
353 struct video_block *video = container_of(b, struct video_block, b);
354 picture_Release(video->pic);
355 free(video);
358 static block_t *
359 CreateVideoBlock(demux_t *demux, struct mock_track *track)
361 struct demux_sys *sys = demux->p_sys;
362 picture_t *pic = picture_NewFromFormat(&track->fmt.video);
363 if (!pic)
364 return NULL;
366 struct video_block *video = malloc(sizeof(*video));
367 if (!video)
369 picture_Release(pic);
370 return NULL;
372 video->pic = pic;
374 static const struct vlc_block_callbacks cbs =
376 .free = video_block_free_cb
379 size_t block_len = 0;
380 for (int i = 0; i < pic->i_planes; ++i)
381 block_len += pic->p[i].i_lines * pic->p[i].i_pitch;
382 memset(pic->p[0].p_pixels, (sys->pts / VLC_TICK_FROM_MS(10)) % 255,
383 block_len);
384 return block_Init(&video->b, &cbs, pic->p[0].p_pixels, block_len);
385 (void) demux;
388 static block_t *
389 CreateSubBlock(demux_t *demux, struct mock_track *track)
391 struct demux_sys *sys = demux->p_sys;
392 char *text;
393 if (asprintf(&text, "subtitle @ %"PRId64, sys->pts) == -1)
394 return NULL;
395 size_t len = strlen(text) + 1;
397 block_t *b = block_Alloc(len);
398 if (!b)
400 free(text);
401 return NULL;
404 memcpy(b->p_buffer, text, len);
405 b->i_buffer = len;
407 free(text);
408 return b;
409 (void) track;
412 static int
413 AppendMockTrack(demux_t *demux, const es_format_t *fmt, int group,
414 bool packetized)
416 struct demux_sys *sys = demux->p_sys;
417 struct mock_track *mock_track = malloc(sizeof(*mock_track));
418 if (!mock_track)
419 return VLC_EGENERIC;
420 mock_track->fmt = *fmt;
421 mock_track->fmt.i_group = group;
422 mock_track->fmt.b_packetized = packetized;
423 mock_track->id = es_out_Add(demux->out, & mock_track->fmt);
424 if (!mock_track->id)
426 free(mock_track);
427 return VLC_ENOMEM;
429 bool success = vlc_vector_push(&sys->tracks, mock_track);
430 assert(success); (void) success; /* checked by reserve() */
431 return VLC_SUCCESS;
434 static int
435 InitVideoTracks(demux_t *demux, int group, size_t count)
437 struct demux_sys *sys = demux->p_sys;
439 if (count == 0)
440 return VLC_SUCCESS;
442 const vlc_chroma_description_t *desc =
443 vlc_fourcc_GetChromaDescription(sys->video_chroma);
444 if (!desc || desc->plane_count == 0)
445 sys->video_chroma = 0;
447 const bool frame_rate_ok =
448 sys->video_frame_rate != 0 && sys->video_frame_rate != UINT_MAX &&
449 sys->video_frame_rate_base != 0 && sys->video_frame_rate_base != UINT_MAX;
450 const bool chroma_ok = sys->video_chroma != 0;
451 const bool size_ok = sys->video_width != UINT_MAX &&
452 sys->video_height != UINT_MAX;
454 if (sys->video_frame_rate == 0 || sys->video_frame_rate_base == 0
455 || sys->video_chroma == 0)
456 if (!frame_rate_ok || !chroma_ok || !size_ok)
458 if (!frame_rate_ok)
459 msg_Err(demux, "Invalid video frame rate");
460 if (!chroma_ok)
461 msg_Err(demux, "Invalid video chroma");
462 if (!size_ok)
463 msg_Err(demux, "Invalid video size");
464 return VLC_EGENERIC;
467 for (size_t i = 0; i < count; ++i)
469 es_format_t fmt;
470 es_format_Init(&fmt, VIDEO_ES, sys->video_chroma);
471 fmt.video.i_chroma = fmt.i_codec;
472 fmt.video.i_width = fmt.video.i_visible_width = sys->video_width;
473 fmt.video.i_height = fmt.video.i_visible_height = sys->video_height;
474 fmt.video.i_frame_rate = sys->video_frame_rate;
475 fmt.video.i_frame_rate_base = sys->video_frame_rate_base;
477 if (AppendMockTrack(demux, &fmt, group, sys->video_packetized))
478 return VLC_ENOMEM;
480 return VLC_SUCCESS;
483 static int
484 InitAudioTracks(demux_t *demux, int group, size_t count)
486 struct demux_sys *sys = demux->p_sys;
488 if (count == 0)
489 return VLC_SUCCESS;
491 const bool rate_ok = sys->audio_rate > 0 && sys->audio_rate != UINT_MAX;
492 const bool format_ok = aout_BitsPerSample(sys->audio_format) != 0;
493 const bool channels_ok = sys->audio_channels > 0 &&
494 sys->audio_channels <= AOUT_CHAN_MAX;
496 if (!rate_ok || !format_ok || !channels_ok)
498 if (!rate_ok)
499 msg_Err(demux, "Invalid audio rate");
500 if (!format_ok)
501 msg_Err(demux, "Invalid audio format");
502 if (!channels_ok)
503 msg_Err(demux, "Invalid audio channels");
504 return VLC_EGENERIC;
507 uint16_t physical_channels = 0;
508 switch (sys->audio_channels)
510 case 1: physical_channels = AOUT_CHAN_CENTER; break;
511 case 2: physical_channels = AOUT_CHANS_2_0; break;
512 case 3: physical_channels = AOUT_CHANS_2_1; break;
513 case 4: physical_channels = AOUT_CHANS_4_0; break;
514 case 5: physical_channels = AOUT_CHANS_4_1; break;
515 case 6: physical_channels = AOUT_CHANS_6_0; break;
516 case 7: physical_channels = AOUT_CHANS_7_0; break;
517 case 8: physical_channels = AOUT_CHANS_7_1; break;
518 case 9: physical_channels = AOUT_CHANS_8_1; break;
519 default: vlc_assert_unreachable();
522 for (size_t i = 0; i < count; ++i)
524 es_format_t fmt;
525 es_format_Init(&fmt, AUDIO_ES, sys->audio_format);
526 fmt.audio.i_format = fmt.i_codec;
527 fmt.audio.i_rate = sys->audio_rate;
528 fmt.audio.i_physical_channels = physical_channels;
529 aout_FormatPrepare(&fmt.audio);
531 if (AppendMockTrack(demux, &fmt, group, sys->audio_packetized))
532 return VLC_ENOMEM;
535 return VLC_SUCCESS;
538 static int
539 InitSubTracks(demux_t *demux, int group, size_t count)
541 struct demux_sys *sys = demux->p_sys;
543 if (count == 0)
544 return VLC_SUCCESS;
546 for (size_t i = 0; i < count; ++i)
548 es_format_t fmt;
549 es_format_Init(&fmt, SPU_ES, VLC_CODEC_SUBT);
551 if (AppendMockTrack(demux, &fmt, group, sys->sub_packetized))
552 return VLC_ENOMEM;
555 return VLC_SUCCESS;
558 static int
559 Demux(demux_t *demux)
561 struct demux_sys *sys = demux->p_sys;
563 if (sys->error)
564 return VLC_DEMUXER_EGENERIC;
566 struct mock_track *track;
567 vlc_vector_foreach(track, &sys->tracks)
569 block_t *block;
570 switch (track->fmt.i_cat)
572 case AUDIO_ES:
573 block = CreateAudioBlock(demux, track);
574 break;
575 case VIDEO_ES:
576 block = CreateVideoBlock(demux, track);
577 break;
578 case SPU_ES:
579 block = CreateSubBlock(demux, track);
580 break;
581 default:
582 vlc_assert_unreachable();
584 if (!block)
585 return VLC_DEMUXER_EGENERIC;
586 block->i_length = sys->step_length;
587 block->i_pts = block->i_dts = sys->pts;
588 int ret = es_out_Send(demux->out, track->id, block);
589 if (ret != VLC_SUCCESS)
590 return VLC_DEMUXER_EGENERIC;
592 es_out_SetPCR(demux->out, sys->pts);
593 sys->pts += sys->step_length;
594 if (sys->pts > sys->length)
595 sys->pts = sys->length;
597 if (sys->add_video_track_at != VLC_TICK_INVALID &&
598 sys->add_video_track_at <= sys->pts)
600 InitVideoTracks(demux, 0, 1);
601 sys->add_video_track_at = VLC_TICK_INVALID;
603 if (sys->add_audio_track_at != VLC_TICK_INVALID &&
604 sys->add_audio_track_at <= sys->pts)
606 InitAudioTracks(demux, 0, 1);
607 sys->add_audio_track_at = VLC_TICK_INVALID;
609 if (sys->add_spu_track_at != VLC_TICK_INVALID &&
610 sys->add_spu_track_at <= sys->pts)
612 InitSubTracks(demux, 0, 1);
613 sys->add_spu_track_at = VLC_TICK_INVALID;
616 return sys->pts == sys->length ? VLC_DEMUXER_EOF : VLC_DEMUXER_SUCCESS;
619 static void
620 Close(vlc_object_t *obj)
622 demux_t *demux = (demux_t*)obj;
623 struct demux_sys *sys = demux->p_sys;
625 struct mock_track *track;
626 vlc_vector_foreach(track, &sys->tracks)
628 es_out_Del(demux->out, track->id);
629 free(track);
631 vlc_vector_clear(&sys->tracks);
634 static int
635 Open(vlc_object_t *obj)
637 demux_t *demux = (demux_t*)obj;
639 if (demux->out == NULL)
640 return VLC_EGENERIC;
641 struct demux_sys *sys = vlc_obj_malloc(obj, sizeof(*sys));
642 if (!sys)
643 return VLC_ENOMEM;
645 demux->p_sys = sys;
647 if (var_LocationParse(obj, demux->psz_location, "mock-") != VLC_SUCCESS)
648 return VLC_ENOMEM;
650 #define X(var_name, type, module_header_type, getter, default_value) \
651 sys->var_name = getter(obj, "mock-"#var_name);
652 LIST_OPTIONS
653 #undef X
655 if (sys->chapter_count > 0 && sys->title_count == 0)
656 sys->title_count++;
658 const bool length_ok = sys->length >= 0;
659 const bool tracks_ok = sys->video_track_count >= 0 &&
660 sys->audio_track_count >= 0 &&
661 sys->sub_track_count >= 0;
662 const bool titles_ok = sys->title_count >= 0;
663 const bool chapters_ok = sys->chapter_count >= 0;
664 const bool programs_ok = sys->program_count >= 0;
666 if (!length_ok || !tracks_ok || !titles_ok || !chapters_ok || !programs_ok)
668 if (!length_ok)
669 msg_Err(demux, "Invalid length");
670 if (!tracks_ok)
671 msg_Err(demux, "Invalid track count");
672 if (!titles_ok)
673 msg_Err(demux, "Invalid title count");
674 if (!chapters_ok)
675 msg_Err(demux, "Invalid chapter count");
676 if (!programs_ok)
677 msg_Err(demux, "Invalid program count");
678 return VLC_EGENERIC;
681 if (sys->program_count == 0)
682 sys->program_count = 1;
683 size_t track_count = (sys->video_track_count + sys->audio_track_count +
684 sys->sub_track_count) * sys->program_count;
685 vlc_vector_init(&sys->tracks);
686 if (track_count > 0)
688 bool success = vlc_vector_reserve(&sys->tracks, track_count);
689 if (!success)
690 return VLC_ENOMEM;
693 int ret;
694 for (ssize_t i = 0; i < sys->program_count; ++i)
696 ret = InitVideoTracks(demux, i, sys->video_track_count);
697 if (ret != VLC_SUCCESS)
698 goto error;
700 ret = InitAudioTracks(demux, i, sys->audio_track_count);
701 if (ret != VLC_SUCCESS)
702 goto error;
704 ret = InitSubTracks(demux, i, sys->sub_track_count);
705 if (ret != VLC_SUCCESS)
706 goto error;
709 if (sys->video_track_count > 0)
710 sys->step_length = VLC_TICK_FROM_SEC(1) * sys->video_frame_rate_base
711 / sys->video_frame_rate;
712 else
713 sys->step_length = VLC_TICK_FROM_MS(100);
715 sys->pts = VLC_TICK_0;
716 sys->current_title = 0;
717 sys->chapter_gap = sys->chapter_count > 0 ?
718 (sys->length / sys->chapter_count) : 0;
720 demux->pf_control = Control;
721 demux->pf_demux = Demux;
723 return VLC_SUCCESS;
724 error:
725 Close(obj);
726 demux->p_sys = NULL;
727 return ret;
730 #define X(var_name, type, module_header_type, getter, default_value) \
731 module_header_type("mock-"#var_name, default_value, NULL, NULL, true) \
732 change_volatile() \
733 change_safe()
735 vlc_module_begin()
736 set_description("mock access demux")
737 set_capability("access", 0)
738 set_category(CAT_INPUT)
739 set_subcategory(SUBCAT_INPUT_ACCESS)
740 set_callbacks(Open, Close)
741 LIST_OPTIONS
742 add_shortcut("mock")
743 vlc_module_end()
745 #undef X