Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/test/src/video_output/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 9 kB image not shown  

Quelle  inhibit.c   Sprache: C

 

/*****************************************************************************
 * inhibit.c: test for the video output screensaver inhibition
 *****************************************************************************
 * Copyright (C) 2026 VideoLabs
 *
 * Author: 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.
 *****************************************************************************/


/**
 * The vout window is created once per vout thread, and the vout is recycled
 * from one input to the next one. Check that switching to another media while
 * the playback is paused, which is what a playlist does when the user selects
 * another item, restores the inhibition of the screensaver.
 */


#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

/* Define a builtin module for mocked parts */
#define MODULE_NAME test_vout_inhibit
#undef VLC_DYNAMIC_PLUGIN

#include "../../libvlc/test.h"
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_codec.h>
#include <vlc_fourcc.h>
#include <vlc_frame.h>
#include <vlc_inhibit.h>
#include <vlc_interface.h>
#include <vlc_player.h>
#include <vlc_vout_display.h>
#include <vlc_window.h>

#include <limits.h>

#include "../lib/libvlc_internal.h"

const char vlc_module_name[] = MODULE_STRING;

static const char dec_dev_arg[] = "--dec-dev=" MODULE_STRING;

static const char source_800_600[] =
    "mock://video_track_count=1;length=100000000000;video_width=800;video_height=600";

static struct
{
    vlc_mutex_t lock;
    vlc_cond_t wait;

    /* Number of inhibiter instances created, used to check whether the
     * inhibiter was recycled or recreated. */

    size_t inhibit_count;
    /* Flags of the last inhibition request. */
    unsigned inhibit_flags;
    /* Number of display instances created, one per media
     * (decoder_UpdateVideoOutput) here. */

    size_t display_count;
    /* Number of pictures sent to the display. */
    size_t picture_count;
} ctx = {
    .lock = VLC_STATIC_MUTEX,
    .wait = VLC_STATIC_COND,
    .inhibit_count = 0,
    .inhibit_flags = VLC_INHIBIT_NONE,
    .display_count = 0,
    .picture_count = 0,
};

/* Wait for a state change from the vout, or abort the test if it never
 * happens. This simplify the writing of the test by helping writing it
 * in a synchronous way. */

#define WAIT_UNTIL(condition) do { \
    vlc_tick_t deadline_ = vlc_tick_now() + VLC_TICK_FROM_SEC(30); \
    vlc_mutex_lock(&ctx.lock); \
    while (!(condition)) \
        assert(vlc_cond_timedwait(&ctx.wait, &ctx.lock, deadline_) == 0 \
               && "timed out waiting for: " #condition); \
    vlc_mutex_unlock(&ctx.lock); \
} while (0)

/* Inhibit module implementation */

static void Inhibit(vlc_inhibit_t *ih, unsigned flags)
{
    msg_Info(ih, "inhibition flags: 0x%x", flags);

    vlc_mutex_lock(&ctx.lock);
    ctx.inhibit_flags = flags;
    vlc_cond_broadcast(&ctx.wait);
    vlc_mutex_unlock(&ctx.lock);
}

static int OpenInhibit(vlc_object_t *obj)
{
    vlc_inhibit_t *ih = (vlc_inhibit_t *)obj;
    ih->inhibit = Inhibit;

    vlc_mutex_lock(&ctx.lock);
    ctx.inhibit_count++;
    vlc_mutex_unlock(&ctx.lock);

    return VLC_SUCCESS;
}

/* Decoder mock implementation */

static int DecoderDecode(decoder_t *dec, vlc_frame_t *frame)
{
    int i_ret = VLC_SUCCESS;

    if (frame == NULL)
        return VLC_SUCCESS;

    i_ret = decoder_UpdateVideoOutput(dec, NULL);
    if (i_ret != VLC_SUCCESS)
        goto error;

    picture_t *pic = picture_NewFromFormat(&dec->fmt_out.video);
    if (pic == NULL)
    {
        i_ret = VLC_ENOMEM;
        goto error;
    }

    pic->date = frame->i_pts;
    pic->b_progressive = true;
    decoder_QueueVideo(dec, pic);

error:
    vlc_frame_Release(frame);
    return i_ret;
}

static int OpenDecoder(vlc_object_t *obj)
{
    decoder_t *dec = (decoder_t *)obj;

    es_format_Clean(&dec->fmt_out);
    es_format_Copy(&dec->fmt_out, dec->fmt_in);
    dec->fmt_out.i_codec
        = dec->fmt_out.video.i_chroma
        = VLC_CODEC_I420;
    dec->fmt_out.video.i_visible_width
        = dec->fmt_out.video.i_width
        = 800;
    dec->fmt_out.video.i_visible_height
        = dec->fmt_out.video.i_height
        = 600;

    dec->pf_decode = DecoderDecode;
    return VLC_SUCCESS;
}

/* Window mock implementation */

static int OpenWindow(vlc_window_t *wnd)
{
    static const struct vlc_window_operations ops =
    {

    };
    wnd->ops = &ops;
    return VLC_SUCCESS;
}

/* Display mock implementation */

static void Display(vout_display_t *vd, picture_t *picture)
{
    VLC_UNUSED(vd); VLC_UNUSED(picture);

    vlc_mutex_lock(&ctx.lock);
    ctx.picture_count++;
    vlc_cond_broadcast(&ctx.wait);
    vlc_mutex_unlock(&ctx.lock);
}

static int OpenDisplay(vout_display_t *vd, video_format_t *fmtp,
                       struct vlc_video_context *vctx)
{
    VLC_UNUSED(fmtp); VLC_UNUSED(vctx);

    static const struct vlc_display_operations ops =
    {
        .display = Display,
    };
    vd->ops = &ops;

    vlc_mutex_lock(&ctx.lock);
    ctx.display_count++;
    vlc_cond_broadcast(&ctx.wait);
    vlc_mutex_unlock(&ctx.lock);

    return VLC_SUCCESS;
}

/* Interface implementation, which actually starts the test */
static int OpenIntf(vlc_object_t *obj)
{
    intf_thread_t *intf = (intf_thread_t *)obj;

    var_Create(intf, "codec", VLC_VAR_STRING);
    var_SetString(intf, "codec", MODULE_STRING);

    var_Create(intf, "vout", VLC_VAR_STRING);
    var_SetString(intf, "vout", MODULE_STRING);

    var_Create(intf, "window", VLC_VAR_STRING);
    var_SetString(intf, "window", MODULE_STRING);

    input_item_t *media1 = input_item_New(source_800_600, "media1");
    assert(media1 != NULL);
    input_item_t *media2 = input_item_New(source_800_600, "media2");
    assert(media2 != NULL);

    vlc_player_t *player = vlc_player_New(&intf->obj, VLC_PLAYER_LOCK_NORMAL);
    assert(player != NULL);

    msg_Info(intf, "Starting the first media");
    vlc_player_Lock(player);
    vlc_player_SetCurrentMedia(player, media1);
    vlc_player_Start(player);
    vlc_player_Unlock(player);

    /* Enabling the window of the vout inhibits the screensaver. Wait for a
     * picture so that the decoder is known to be attached to the vout, which
     * is required for the pause below to reach it. */

    WAIT_UNTIL(ctx.picture_count > 0 && ctx.inhibit_flags == VLC_INHIBIT_VIDEO);

    vlc_mutex_lock(&ctx.lock);
    assert(ctx.display_count == 1);
    vlc_mutex_unlock(&ctx.lock);

    msg_Info(intf, "Pausing the first media");
    vlc_player_Lock(player);
    vlc_player_Pause(player);
    vlc_player_Unlock(player);

    /* Pausing the playback releases the inhibition. */
    WAIT_UNTIL(ctx.inhibit_flags == VLC_INHIBIT_NONE);

    /* Switch to another media without resuming first, like a playlist does
     * when the user selects another item while paused. The vout is recycled
     * with its window still enabled. */

    msg_Info(intf, "Switching to the second media while paused");
    vlc_player_Lock(player);
    vlc_player_SetCurrentMedia(player, media2);
    vlc_player_Unlock(player);

    /* The window is enabled again before the display of the second media is
     * created, so the inhibition state is settled once it shows up. */

    WAIT_UNTIL(ctx.display_count == 2);

    vlc_mutex_lock(&ctx.lock);
    /* The window, and thus the inhibiter, must have been reused. */
    assert(ctx.inhibit_count == 1);
    /* The second media is playing, the screensaver must be inhibited again. */
    assert(ctx.inhibit_flags == VLC_INHIBIT_VIDEO);
    vlc_mutex_unlock(&ctx.lock);

    vlc_player_Delete(player);
    input_item_Release(media2);
    input_item_Release(media1);

    var_Destroy(intf, "window");
    var_Destroy(intf, "vout");
    var_Destroy(intf, "codec");

    return VLC_SUCCESS;
}

/**
 * Inject the mocked modules as a static plugin:
 *  - decoder generating pictures for the video output
 *  - window and display to run a video output without any display server
 *  - inhibit to monitor the screensaver inhibition requests
 **/

vlc_module_begin()
    set_callback(OpenDecoder)
    set_capability("video decoder", INT_MAX)

    add_submodule()
        set_callback(OpenWindow)
        set_capability("vout window", INT_MAX)

    add_submodule()
        set_callback_display(OpenDisplay, 0)

    add_submodule()
        set_callback(OpenInhibit)
        set_capability("inhibit", INT_MAX)

    /* Interface module to start the test */
    add_submodule()
        set_callback(OpenIntf)
        set_capability("interface", 0)

vlc_module_end()

VLC_EXPORT const vlc_plugin_cb vlc_static_modules[] = {
    VLC_SYMBOL(vlc_entry),
    NULL
};

int main(int argc, char **argv)
{
    (void)argc; (void)argv;
    test_init();

    const char * const args[] = {
        "-vvv", "--aout=dummy", "--text-renderer=dummy",
        "--no-auto-preparse", "--no-hw-dec",
        "--no-spu", "--no-osd",
    };

    libvlc_instance_t *vlc = libvlc_new(ARRAY_SIZE(args), args);
    assert(vlc != NULL);

    libvlc_InternalAddIntf(vlc->p_libvlc_int, MODULE_STRING);
    libvlc_InternalPlay(vlc->p_libvlc_int);

    libvlc_release(vlc);
    return 0;
}

Messung
CHZG
839610093

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.