You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
304 lines
8.2 KiB
304 lines
8.2 KiB
/*****************************************************************************
|
|
* imem.c: test for the imem libvlc code
|
|
*****************************************************************************
|
|
* Copyright (C) 2023 VideoLabs
|
|
*
|
|
* Authors: Alexandre Janniaux <ajanni@videolabs.io>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation; either version 2.1 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
|
*****************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
/* Define a builtin module for mocked parts */
|
|
#define MODULE_NAME test_imem
|
|
#undef VLC_DYNAMIC_PLUGIN
|
|
|
|
#include "./test.h"
|
|
#include <vlc_common.h>
|
|
#include <vlc_plugin.h>
|
|
#include <vlc_stream.h>
|
|
#include <vlc_threads.h>
|
|
#include <vlc_interrupt.h>
|
|
|
|
#include <vlc/libvlc_media.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include "media_player.h"
|
|
|
|
const char vlc_module_name[] = MODULE_STRING;
|
|
|
|
struct imem_root
|
|
{
|
|
/* root controlled semaphores */
|
|
vlc_sem_t available;
|
|
vlc_sem_t done;
|
|
vlc_sem_t opened;
|
|
vlc_sem_t read_blocking;
|
|
|
|
vlc_sem_t wait;
|
|
};
|
|
|
|
struct imem_access
|
|
{
|
|
struct imem_root *root;
|
|
vlc_sem_t wait;
|
|
};
|
|
|
|
static void AccessClose(void *opaque)
|
|
{
|
|
struct imem_access *sys = opaque;
|
|
fprintf(stderr, "test: Access: Close\n");
|
|
vlc_sem_post(&sys->root->done);
|
|
vlc_sem_post(&sys->root->available);
|
|
free(sys);
|
|
}
|
|
|
|
static int AccessOpen(void *opaque, void **datap, uint64_t *sizep)
|
|
{
|
|
(void)sizep;
|
|
struct imem_root *root = opaque;
|
|
vlc_sem_wait(&root->available);
|
|
fprintf(stderr, "test: Access: Opening new instance\n");
|
|
|
|
struct imem_access *sys = *datap = malloc(sizeof *sys);
|
|
if (sys == NULL)
|
|
return -ENOMEM;
|
|
|
|
sys->root = root;
|
|
vlc_sem_init(&sys->wait, 0);
|
|
vlc_sem_post(&sys->root->opened);
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
static ssize_t AccessRead(void *opaque, unsigned char *buf, size_t len)
|
|
{
|
|
(void)opaque;
|
|
assert(len < SSIZE_MAX);
|
|
memset(buf, 0xff, len);
|
|
return len;
|
|
}
|
|
|
|
static void SetFlag(void *opaque)
|
|
{
|
|
bool *flag = opaque;
|
|
*flag = true;
|
|
}
|
|
|
|
static ssize_t AccessReadBlocking(void *opaque, unsigned char *buf, size_t len)
|
|
{
|
|
(void)opaque; (void)buf;
|
|
struct imem_access *sys = opaque;
|
|
assert(len < SSIZE_MAX);
|
|
|
|
vlc_sem_post(&sys->root->read_blocking);
|
|
/* The interruption is used to detect when the input has been closed. */
|
|
bool was_interrupted = false;
|
|
vlc_interrupt_register(SetFlag, &was_interrupted);
|
|
fprintf(stderr, "test: Access: read() -> blocking\n");
|
|
vlc_sem_wait(&sys->root->wait);
|
|
fprintf(stderr, "test: Access: read() -> unblocked\n");
|
|
vlc_interrupt_unregister();
|
|
//assert(was_interrupted);
|
|
|
|
/* We notify that we don't have data to read right now. */
|
|
return 0;
|
|
}
|
|
|
|
static void UnblockRead(const libvlc_event_t *event, void *opaque)
|
|
{
|
|
(void)event;
|
|
fprintf(stderr, "test: Player: Unblock read\n");
|
|
struct imem_root *imem = opaque;
|
|
vlc_sem_post(&imem->wait);
|
|
}
|
|
|
|
static struct imem_root *imem_root_New(void)
|
|
{
|
|
|
|
struct imem_root *imem = malloc(sizeof *imem);
|
|
assert(imem != NULL);
|
|
|
|
vlc_sem_init(&imem->available, 1);
|
|
vlc_sem_init(&imem->done, 0);
|
|
vlc_sem_init(&imem->wait, 0);
|
|
vlc_sem_init(&imem->opened, 0);
|
|
vlc_sem_init(&imem->read_blocking, 0);
|
|
|
|
return imem;
|
|
}
|
|
|
|
static void test_media_callback(libvlc_instance_t *vlc)
|
|
{
|
|
struct imem_root *imem = imem_root_New();
|
|
|
|
fprintf(stderr, "test: 1/ checking that media can terminate\n");
|
|
libvlc_media_t *media = libvlc_media_new_callbacks(
|
|
AccessOpen,
|
|
AccessRead,
|
|
NULL,//AccessSeek,
|
|
AccessClose,
|
|
imem);
|
|
assert(media != NULL);
|
|
|
|
libvlc_media_player_t *player = libvlc_media_player_new(vlc);
|
|
assert(player != NULL);
|
|
|
|
struct mp_event_ctx wait_play;
|
|
mp_event_ctx_init(&wait_play);
|
|
libvlc_event_manager_t *mgr = libvlc_media_player_event_manager(player);
|
|
libvlc_event_attach(mgr, libvlc_MediaPlayerOpening, mp_event_ctx_on_event, &wait_play);
|
|
|
|
struct mp_event_ctx wait_stopped;
|
|
mp_event_ctx_init(&wait_stopped);
|
|
libvlc_event_attach(mgr, libvlc_MediaPlayerStopped, mp_event_ctx_on_event, &wait_stopped);
|
|
|
|
libvlc_media_player_set_media(player, media);
|
|
libvlc_media_player_play(player);
|
|
|
|
mp_event_ctx_wait(&wait_play);
|
|
libvlc_event_detach(mgr, libvlc_MediaPlayerOpening, mp_event_ctx_on_event, &wait_play);
|
|
|
|
// TODO: Wait event Opening
|
|
libvlc_media_player_stop_async(player);
|
|
|
|
mp_event_ctx_wait(&wait_stopped);
|
|
libvlc_event_detach(mgr, libvlc_MediaPlayerStopped, mp_event_ctx_on_event, &wait_stopped);
|
|
|
|
vlc_sem_wait(&imem->done);
|
|
libvlc_media_release(media);
|
|
libvlc_media_player_release(player);
|
|
|
|
free(imem);
|
|
}
|
|
|
|
static void test_media_callback_interrupt(libvlc_instance_t *vlc)
|
|
{
|
|
struct imem_root *imem = imem_root_New();
|
|
|
|
fprintf(stderr, "test: 2/ checking that we can terminate after the input\n");
|
|
libvlc_media_player_t *player = libvlc_media_player_new(vlc);
|
|
assert(player != NULL);
|
|
libvlc_event_manager_t *mgr = libvlc_media_player_event_manager(player);
|
|
assert(mgr != NULL);
|
|
|
|
libvlc_media_t *media = libvlc_media_new_callbacks(
|
|
AccessOpen,
|
|
AccessReadBlocking,
|
|
NULL,//AccessSeek,
|
|
AccessClose,
|
|
imem);
|
|
assert(media != NULL);
|
|
|
|
struct mp_event_ctx wait_play;
|
|
struct mp_event_ctx wait_stopped;
|
|
mp_event_ctx_init(&wait_play);
|
|
mp_event_ctx_init(&wait_stopped);
|
|
libvlc_event_attach(mgr, libvlc_MediaPlayerMediaStopping, UnblockRead, imem);
|
|
|
|
fprintf(stderr, "test: set initial media\n");
|
|
libvlc_media_player_set_media(player, media);
|
|
libvlc_media_player_play(player);
|
|
|
|
/* We want to be sure that the media has been opened. */
|
|
vlc_sem_wait(&imem->opened);
|
|
vlc_sem_wait(&imem->read_blocking);
|
|
|
|
libvlc_media_release(media);
|
|
media = libvlc_media_new_callbacks(
|
|
AccessOpen,
|
|
AccessReadBlocking,
|
|
NULL,
|
|
AccessClose,
|
|
imem);
|
|
assert(media != NULL);
|
|
fprintf(stderr, "test: changing to new media\n");
|
|
libvlc_media_player_set_media(player, media);
|
|
fprintf(stderr, "test: waiting for the new media\n");
|
|
|
|
/* Semaphore notifying that the first access has been closed. */
|
|
vlc_sem_wait(&imem->done);
|
|
assert(vlc_sem_trywait(&imem->read_blocking) == EAGAIN);
|
|
|
|
vlc_sem_wait(&imem->opened);
|
|
vlc_sem_wait(&imem->read_blocking);
|
|
|
|
fprintf(stderr, "test: checking that we get the media stopping event\n");
|
|
libvlc_media_player_stop_async(player);
|
|
|
|
vlc_sem_wait(&imem->done);
|
|
|
|
libvlc_media_release(media);
|
|
libvlc_media_player_release(player);
|
|
|
|
free(imem);
|
|
}
|
|
|
|
int main( int argc, char **argv )
|
|
{
|
|
(void)argc; (void)argv;
|
|
test_init();
|
|
|
|
const char * const vlc_argv[] = {
|
|
"-vvv", "--vout=dummy", "--aout=dummy", "--text-renderer=dummy",
|
|
"--demux="MODULE_STRING,
|
|
};
|
|
|
|
libvlc_instance_t *vlc = libvlc_new(ARRAY_SIZE(vlc_argv), vlc_argv);
|
|
assert(vlc != NULL);
|
|
|
|
test_media_callback(vlc);
|
|
test_media_callback_interrupt(vlc);
|
|
|
|
libvlc_release(vlc);
|
|
return 0;
|
|
}
|
|
|
|
static int DemuxDemux(demux_t *demux)
|
|
{
|
|
(void)demux;
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
static void DemuxClose(vlc_object_t *obj)
|
|
{
|
|
(void)obj;
|
|
}
|
|
|
|
static int DemuxOpen(vlc_object_t *obj)
|
|
{
|
|
demux_t *demux = (demux_t *)obj;
|
|
|
|
static const struct vlc_stream_operations ops =
|
|
{
|
|
.demux.demux = DemuxDemux,
|
|
};
|
|
demux->ops = &ops;
|
|
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
vlc_module_begin()
|
|
set_capability("demux", 0)
|
|
set_callbacks(DemuxOpen, DemuxClose)
|
|
vlc_module_end()
|
|
|
|
VLC_EXPORT const vlc_plugin_cb vlc_static_modules[] = {
|
|
VLC_SYMBOL(vlc_entry),
|
|
NULL
|
|
};
|
|
|