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

Quelle  media.c   Sprache: C

 

/*
 * media.c - libvlc media smoke test
 *
 */


/**********************************************************************
 *  Copyright (C) 2010 Pierre d'Herbemont.                            *
 *  This program is free software; you can redistribute and/or modify *
 *  it under the terms of the GNU General Public License as published *
 *  by the Free Software Foundation; version 2 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 General Public License for more details.              *
 *                                                                    *
 *  You should have received a copy of the GNU General Public License *
 *  along with this program; if not, you can get it from:             *
 *  http://www.gnu.org/copyleft/gpl.html                              *
 **********************************************************************/


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

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <vlc_threads.h>
#include <vlc_fs.h>
#include <vlc_input_item.h>
#include <vlc_preparser.h>

static void media_parse_ended(void *opaque, libvlc_parser_task *task,
                              libvlc_parser_status_t status)
{
    libvlc_media_t *media = libvlc_parser_task_get_media(task);
    assert(media != NULL);
    assert(libvlc_media_is_parsed(media) ==
           (status == libvlc_parser_status_done));

    vlc_sem_t *sem = opaque;
    vlc_sem_post (sem);
    libvlc_parser_task_release(task);
}

static void print_media(libvlc_media_t *media)
{
    static const libvlc_track_type_t types[] =
        { libvlc_track_audio, libvlc_track_video, libvlc_track_text,
          libvlc_track_unknown };
    size_t nb_tracks = 0;

    for (size_t i = 0; i < ARRAY_SIZE(types); ++i)
    {
        const libvlc_track_type_t type = types[i];
        libvlc_media_tracklist_t *tracklist =
            libvlc_media_get_tracklist(media, type);
        assert(tracklist);

        for (size_t j = 0; j < libvlc_media_tracklist_count(tracklist); ++j)
        {
            const libvlc_media_track_t *p_track =
                libvlc_media_tracklist_at(tracklist, j);

            assert(p_track);
            assert(p_track->i_type == type);
            nb_tracks ++;

            test_log("\ttrack(%zu/%d): codec: %4.4s/%4.4s, ", j, p_track->i_id,
                (const char *)&p_track->i_codec,
                (const char *)&p_track->i_original_fourcc);
            switch (p_track->i_type)
            {
            case libvlc_track_audio:
                printf("audio: channels: %u, rate: %u\n",
                       p_track->u.audio->i_channels, p_track->u.audio->i_rate);
                break;
            case libvlc_track_video:
                printf("video: %ux%u, sar: %u/%u, fps: %u/%u\n",
                       p_track->u.video->i_width, p_track->u.video->i_height,
                       p_track->u.video->i_sar_num, p_track->u.video->i_sar_den,
                       p_track->u.video->i_frame_rate_num, p_track->u.video->i_frame_rate_den);
                break;
            case libvlc_track_text:
                printf("text: %s\n", p_track->u.subtitle->psz_encoding);
                break;
            case libvlc_track_unknown:
                printf("unknown\n");
                break;
            default:
                vlc_assert_unreachable();
            }
        }
        libvlc_media_tracklist_delete(tracklist);
    }

    if (nb_tracks == 0)
        test_log("\tmedia doesn't have any tracks\n");

    for (enum libvlc_meta_t i = libvlc_meta_Title;
         i <= libvlc_meta_Compilation; ++i)
    {
        char *psz_meta = libvlc_media_get_meta(media, i);
        if (psz_meta != NULL)
            test_log("\tmeta(%d): '%s'\n", i, psz_meta);
        free(psz_meta);
    }
}

static libvlc_media_t *
test_media_preparsed_ext(libvlc_instance_t *vlc, const char *path,
                         const char *location,
                         libvlc_media_parse_flag_t parse_flags,
                         bool b_expected_parsed)
{
    test_log ("test_media_preparsed: %s, expected: %d\n", path ? path : location,
              b_expected_parsed);

    libvlc_media_t *media;
    if (path != NULL)
        media = libvlc_media_new_path(path);
    else
        media = libvlc_media_new_location(location);
    assert (media != NULL);

    vlc_sem_t sem;
    vlc_sem_init (&sem, 0);

    static const struct libvlc_parser_cbs cbs = {
        .version = 0,
        .on_parsed = media_parse_ended,
    };

    const struct libvlc_parser_cfg cfg = {
        .version = 0,
        .max_parser_threads = 1,
        .timeout = -1,
    };

    libvlc_parser_t *parser = libvlc_parser_new(vlc, &cfg);
    assert(parser != NULL);

    libvlc_parser_request_t req = {
        .version = 0,
        .media = media,
        .parse_flags = parse_flags,
    };

    libvlc_parser_task *task = libvlc_parser_task_new_parse(parser, &req, &cbs, &sem);
    assert(task != NULL);
    assert(libvlc_parser_submit(parser, task) == 0);

    // Wait for preparsed event
    vlc_sem_wait (&sem);

    // We are good, now check Elementary Stream info.
    assert (libvlc_media_is_parsed(media) == b_expected_parsed);
    if (b_expected_parsed)
        print_media(media);

    libvlc_parser_destroy(parser);

    return media;
}

static void test_media_preparsed(libvlc_instance_t *vlc, const char *path,
                                 const char *location,
                                 libvlc_media_parse_flag_t parse_flags,
                                 bool b_expected_parsed)
{
    libvlc_media_t *media = test_media_preparsed_ext(vlc, path, location,
                                                     parse_flags,
                                                     b_expected_parsed);
    libvlc_media_release (media);
}

static void test_media_tracks(libvlc_instance_t *vlc)
{
    const char *url =
        "mock://video_track_count=4;audio_track_count=42;"
        "video_width=100;video_height=50;"
        "audio_channels=2;audio_rate=48000;";
    libvlc_media_t *media =
        test_media_preparsed_ext(vlc, NULL, url,
                                 libvlc_media_parse,
                                 true);

    char buf[32];
    libvlc_media_tracklist_t *tracklist;

    tracklist = libvlc_media_get_tracklist(media, libvlc_track_video);
    assert(tracklist != NULL);
    assert(libvlc_media_tracklist_count(tracklist) == 4);
    for (size_t i = 0; i < libvlc_media_tracklist_count(tracklist); ++i)
    {
        libvlc_media_track_t *track = libvlc_media_tracklist_at(tracklist, i);
        assert(track->i_type == libvlc_track_video);
        assert(track->u.video != NULL);
        assert(track->u.video->i_width == 100);
        assert(track->u.video->i_height == 50);

        sprintf(buf, "video/%zu", i);
        assert(strcmp(track->psz_id, buf) == 0);
        assert(track->id_stable);
    }
    libvlc_media_tracklist_delete(tracklist);

    tracklist = libvlc_media_get_tracklist(media, libvlc_track_audio);
    assert(tracklist != NULL);
    assert(libvlc_media_tracklist_count(tracklist) == 42);
    for (size_t i = 0; i < libvlc_media_tracklist_count(tracklist); ++i)
    {
        libvlc_media_track_t *track = libvlc_media_tracklist_at(tracklist, i);
        assert(track->i_type == libvlc_track_audio);
        assert(track->u.audio != NULL);
        assert(track->u.audio->i_channels == 2);
        assert(track->u.audio->i_rate == 48000);

        sprintf(buf, "audio/%zu", i);
        assert(strcmp(track->psz_id, buf) == 0);
        assert(track->id_stable);
    }
    libvlc_media_tracklist_delete(tracklist);

    tracklist = libvlc_media_get_tracklist(media, libvlc_track_text);
    assert(tracklist != NULL);
    assert(libvlc_media_tracklist_count(tracklist) == 0);
    libvlc_media_tracklist_delete(tracklist);

    libvlc_media_release (media);
}

static void input_item_preparse_timeout( vlc_preparser_req *req,
                                         int status, void *user_data )
{
    (void)req;
    vlc_sem_t *p_sem = user_data;

    assert( status == VLC_ETIMEOUT );
    vlc_sem_post(p_sem);
}

static void input_item_preparse_cancel( vlc_preparser_req *req,
                                        int status, void *user_data )
{
    (void)req;
    vlc_sem_t *p_sem = user_data;

    assert( status == -EINTR );
    vlc_sem_post(p_sem);
}

static void test_input_metadata_timeout(libvlc_instance_t *vlc, int timeout,
                                        int wait_and_cancel)
{
    test_log ("test_input_metadata_timeout: timeout: %d, wait_and_cancel: %d ms\n",
         timeout, wait_and_cancel);

    int i_ret, p_pipe[2];
    i_ret = vlc_pipe(p_pipe);
    assert(i_ret == 0 && p_pipe[1] >= 0);

    char psz_fd_uri[strlen("fd://") + 11];
    sprintf(psz_fd_uri, "fd://%u", (unsigned) p_pipe[1]);
    input_item_t *p_item = input_item_NewFile(psz_fd_uri, "test timeout", 0,
                                              ITEM_LOCAL);
    assert(p_item != NULL);

    vlc_sem_t sem;
    vlc_sem_init (&sem, 0);
    const struct vlc_preparser_cbs cbs = {
        .on_ended = wait_and_cancel > 0 ? input_item_preparse_cancel
                                        : input_item_preparse_timeout,
    };

    int options = VLC_PREPARSER_TYPE_PARSE | VLC_PREPARSER_TYPE_FETCHMETA_LOCAL;

    const struct vlc_preparser_cfg cfg = {
        .types = options,
        .max_parser_threads = 1,
        .timeout = VLC_TICK_FROM_MS(timeout),
        .external_process = false,
    };
    vlc_preparser_t *parser = vlc_preparser_New(VLC_OBJECT(vlc->p_libvlc_int),
                                                &cfg);
    assert(parser != NULL);
    vlc_preparser_req *req =
        vlc_preparser_req_NewParse(parser, p_item, options, &cbs, &sem);
    assert(req != NULL);
    assert(vlc_preparser_Submit(parser, req) == VLC_SUCCESS);

    if (wait_and_cancel > 0)
    {
        vlc_tick_sleep( VLC_TICK_FROM_MS(wait_and_cancel) );
        size_t count = vlc_preparser_Cancel(parser, req);
        assert(count == 1);
    }
    vlc_sem_wait(&sem);

    vlc_preparser_req_Release(req);

    input_item_Release(p_item);
    vlc_preparser_Delete(parser);
    vlc_close(p_pipe[0]);
    vlc_close(p_pipe[1]);
}

static struct
{
    const char *file;
    libvlc_media_type_t type;
} test_media_subitems_list[] =
{
    { "directory", libvlc_media_type_directory, },
    { "file.jpg", libvlc_media_type_file },
    { "file.mkv", libvlc_media_type_file },
    { "file.mp3", libvlc_media_type_file },
    { "file.png", libvlc_media_type_file },
    { "file.ts", libvlc_media_type_file },
};

static void check_subitems(libvlc_media_t *m, bool *subitems_found)
{
#ifdef _WIN32
#define FILE_SEPARATOR   '\\'
#else
#define FILE_SEPARATOR   '/'
#endif
    assert (m);

    char *mrl = libvlc_media_get_mrl (m);
    assert (mrl);

    const char *file = strrchr (mrl, FILE_SEPARATOR);
    assert (file);
    file++;
    test_log ("subitem_added, file: %s\n", file);

    for (unsigned i = 0; i < ARRAY_SIZE(test_media_subitems_list); ++i)
    {
        if (strcmp (test_media_subitems_list[i].file, file) == 0)
        {
            assert (!subitems_found[i]);
            assert (libvlc_media_get_type(m) == test_media_subitems_list[i].type);
            subitems_found[i] = true;

            uint64_t value;
            int ret;

            ret = libvlc_media_get_filestat(m, libvlc_media_filestat_size, &value);
            assert(ret == 1);
            /* All files size are 0, directory size depends on the FS. */
            if (libvlc_media_get_type(m) != libvlc_media_type_directory)
                assert(value == 0);

            ret = libvlc_media_get_filestat(m, libvlc_media_filestat_mtime, &value);
            /* Epoch timestamp of the commit that added test/samples/subitems */
            assert(ret == 1 && value >= 1446796477);
        }
    }
    free (mrl);
#undef FILE_SEPARATOR
}

static void on_media_parsed(void *opaque, libvlc_media_t *media)
{
    (void) media;
    vlc_sem_t *sem = opaque;
    vlc_sem_post(sem);
}

static void on_media_subitems_changed(void *opaque, libvlc_media_t *media)
{
    (void) media;
    vlc_sem_t *sem = opaque;
    vlc_sem_post(sem);
}

static void test_media_subitems_media(libvlc_instance_t *vlc,
                                      libvlc_media_t *media, bool play,
                                      bool b_items_expected)
{
    libvlc_media_add_option(media, ":ignore-filetypes= ");
    libvlc_media_add_option(media, ":no-sub-autodetect-file");

    bool subitems_found[ARRAY_SIZE(test_media_subitems_list)] = { 0 };
    vlc_sem_t sem;
    vlc_sem_init (&sem, 0);

    if (play)
    {
        /* XXX: libvlc_media_parse won't work with fd, since it
         * won't be preparsed because fd:// is an unknown type, so play the
         * file to force parsing. */


        static const struct libvlc_media_player_cbs cbs = {
            .version = 0,
            .on_media_parsed = on_media_parsed,
            .on_media_subitems_changed = on_media_subitems_changed,
        };

        libvlc_media_player_t *mp =
            libvlc_media_player_new_from_media(vlc, media, &cbs, &sem);
        assert (mp);
        assert (libvlc_media_player_play (mp) != -1);

        vlc_sem_wait(&sem);
        vlc_sem_wait(&sem);

        libvlc_media_player_release (mp);
    }
    else
    {
        static const struct libvlc_parser_cbs cbs = {
            .version = 0,
            .on_parsed = media_parse_ended,
        };

        const struct libvlc_parser_cfg cfg = {
            .version = 0,
            .max_parser_threads = 1,
            .timeout = -1,
        };

        libvlc_parser_t *parser = libvlc_parser_new(vlc, &cfg);
        assert(parser != NULL);
        libvlc_parser_request_t req = {
            .version = 0,
            .media = media,
            .parse_flags = 0,
        };
        libvlc_parser_task *task = libvlc_parser_task_new_parse(parser, &req, &cbs, &sem);
        assert(task != NULL);
        assert(libvlc_parser_submit(parser, task) == 0);

        vlc_sem_wait (&sem);
        libvlc_parser_destroy(parser);
    }

    libvlc_media_list_t *subitems = libvlc_media_subitems(media);
    assert(subitems != NULL);
    for (int i = 0; i < libvlc_media_list_count(subitems); ++i)
    {
        libvlc_media_t *child = libvlc_media_list_item_at_index(subitems, i);
        assert(child != NULL);
        check_subitems(child, subitems_found);
        libvlc_media_release(child);
    }
    libvlc_media_list_release(subitems);

    if (!b_items_expected)
        return;

    for (unsigned i = 0; i < ARRAY_SIZE(test_media_subitems_list); ++i)
    {
        test_log ("test if %s was added\n", test_media_subitems_list[i].file);
        assert (subitems_found[i]);
    }
}

static void test_media_subitems(libvlc_instance_t *vlc)
{
    const char *subitems_path = SRCDIR"/samples/subitems";

    libvlc_media_t *media;

    test_log ("Testing media_subitems: path: '%s'\n", subitems_path);
    media = libvlc_media_new_path(subitems_path);
    assert (media != NULL);
    test_media_subitems_media(vlc, media, false, true);
    libvlc_media_release (media);

    char *subitems_realpath = realpath (subitems_path, NULL);
    assert (subitems_realpath != NULL);
    const char *schemes[] = { "file://", "dir://" };
    for (unsigned i = 0; i < ARRAY_SIZE(schemes); ++i)
    {
        char *location;
        assert (asprintf (&location, "%s%s", schemes[i], subitems_realpath) != -1);
        test_log ("Testing media_subitems: location: '%s'\n", location);
        media = libvlc_media_new_location(location);
        assert (media != NULL);
        test_media_subitems_media(vlc, media, false, true);
        free (location);
        libvlc_media_release (media);
    }
    free (subitems_realpath);

#ifdef HAVE_FSTATAT
    /* listing directory via a fd works only if fstatat() exists */
    int fd = open (subitems_path, O_RDONLY);
    test_log ("Testing media_subitems: fd: '%d'\n", fd);
    assert (fd >= 0);
    media = libvlc_media_new_fd(fd);
    assert (media != NULL);
    test_media_subitems_media(vlc, media, true, true);
    libvlc_media_release (media);
    vlc_close (fd);
#else
#warning not testing subitems list via a fd location
#endif

    test_log ("Testing media_subitems failure\n");
    media = libvlc_media_new_location("wrongfile://test");
    assert (media != NULL);
    test_media_subitems_media(vlc, media, false, false);
    libvlc_media_release (media);
}

int main(int i_argc, char *ppsz_argv[])
{
    test_init();

    libvlc_instance_t *vlc = libvlc_new (test_defaults_nargs,
                                         test_defaults_args);
    assert (vlc != NULL);

    char *psz_test_arg = i_argc > 1 ? ppsz_argv[1] : NULL;
    if (psz_test_arg != NULL)
    {
        alarm(0);
        const char *psz_test_url;
        const char *psz_test_path;
        if (strstr(psz_test_arg, "://") != NULL)
        {
            psz_test_url = psz_test_arg;
            psz_test_path = NULL;
        }
        else
        {
            psz_test_url = NULL;
            psz_test_path = psz_test_arg;
        }
        test_media_preparsed (vlc, psz_test_path, psz_test_url,
                              libvlc_media_parse,
                              true);
        libvlc_release(vlc);
        return 0;
    }

    test_media_preparsed (vlc, SRCDIR"/samples/image.jpg", NULL,
                          libvlc_media_parse,
                          true);

    test_media_subitems (vlc);
    test_media_tracks (vlc);

    /* Testing vlc_preparser_Submit timeout and vlc_preparser_Cancel. For
     * that, we need to create a local input_item_t based on a pipe. There is
     * no way to do that with a libvlc_media_t, that's why we don't use
     * libvlc_media_parse*() */


    test_input_metadata_timeout (vlc, 100, 0);
    test_input_metadata_timeout (vlc, 0, 100);

    libvlc_release (vlc);

    return 0;
}

Messung
CHZG
839710093

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© 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.