Libvlc smem не вызывает функции обратного вызова - PullRequest
0 голосов
/ 22 октября 2019

Я пытаюсь передать поток mp4-файла в область памяти, и я подумал, что smem (поток в память) в libvlc - хорошая идея. Я использую заголовки libvlc и динамически подключаюсь к официальным библиотекам vlc. Модуль SEMM требует, чтобы вы определили некоторые обратные вызовы до и после рендеринга кадра видео, и именно здесь происходит фактическая передача видео в желаемое место в памяти. Чтобы проверить, работает он или нет, я добавил элемент «counter» в ParamStruct, и он будет считать каждый раз, когда входит в функцию VideoPrerender (). Но после установки точки останова после Sleep () и проверки через окно наблюдения VSCode переменная все еще была на нуле, поэтому она никогда не входила в эту функцию обратного вызова. Кроме того, это произошло:

Исключение, выданное в 0x00007FFB403FA839 в videodesktop.exe: исключение Microsoft C ++: _com_error в ячейке памяти 0x0000005CF75FF6A0.

каждые несколько секунд после "_libvlc_media_player_play (vlcMediaPlayer); "- строка с немного другим местом в памяти каждый раз.

Это мой код:

#include "vlccode.h"

#include <iostream>

struct RenderCallbackParamsStruct
{
    vlc_mutex_t Mutex;
    uint8_t *Buffer;
    decltype(vlc_mutex_lock) *_vlc_mutex_lock;
    decltype(vlc_mutex_unlock) *_vlc_mutex_unlock;
    size_t size;
    int counter;
};

void VideoPrerender(void *p_video_data, uint8_t **pp_pixel_buffer, size_t size)
{
    RenderCallbackParamsStruct *Params = (RenderCallbackParamsStruct *)p_video_data;
    Params->_vlc_mutex_lock(&Params->Mutex);

    *pp_pixel_buffer = (uint8_t *)p_video_data;
    Params->size = size;
    Params->counter++;
}

void VideoPostrender(void* p_video_data, uint8_t* p_pixel_buffer, int width, int height, int pixel_pitch, size_t size, int64_t pts)
{
    RenderCallbackParamsStruct *Params = (RenderCallbackParamsStruct *)p_video_data;



    // TODO: explain how data should be handled
    // TODO: Unlock the mutex
    Params->_vlc_mutex_unlock(&Params->Mutex);
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    char inputFileName[] = "D:\\Desktop\\Projects\\TEST\\videodesktop\\build\\WayOfKings.mp4";




    SetDllDirectoryA("VLC");
    HMODULE libvlc_dll = LoadLibraryA("libvlc.dll");
    HMODULE libvlccore_dll = LoadLibraryA("libvlccore.dll");

    // define all the needed libvlc functions
    decltype(libvlc_new) *_libvlc_new = (decltype(libvlc_new) *) GetProcAddress(libvlc_dll, "libvlc_new");
    decltype(libvlc_media_new_path) *_libvlc_media_new_path = (decltype(libvlc_media_new_path) *) GetProcAddress(libvlc_dll, "libvlc_media_new_path");
    decltype(libvlc_media_player_new) *_libvlc_media_player_new = (decltype(libvlc_media_player_new) *) GetProcAddress(libvlc_dll, "libvlc_media_player_new");
    decltype(libvlc_media_player_new_from_media) *_libvlc_media_player_new_from_media = (decltype(libvlc_media_player_new_from_media) *) GetProcAddress(libvlc_dll, "libvlc_media_player_new_from_media");
    decltype(libvlc_media_release) *_libvlc_media_release = (decltype(libvlc_media_release) *) GetProcAddress(libvlc_dll, "libvlc_media_release");
    decltype(libvlc_media_player_play) *_libvlc_media_player_play = (decltype(libvlc_media_player_play) *) GetProcAddress(libvlc_dll, "libvlc_media_player_play");
    decltype(libvlc_media_player_stop) *_libvlc_media_player_stop = (decltype(libvlc_media_player_stop) *) GetProcAddress(libvlc_dll, "libvlc_media_player_stop");
    decltype(libvlc_media_player_release) *_libvlc_media_player_release = (decltype(libvlc_media_player_release) *) GetProcAddress(libvlc_dll, "libvlc_media_player_release");
    decltype(libvlc_release) *_libvlc_release = (decltype(libvlc_release) *) GetProcAddress(libvlc_dll, "libvlc_release");
    decltype(vlc_mutex_init) *_vlc_mutex_init = (decltype(vlc_mutex_init) *) GetProcAddress(libvlccore_dll, "vlc_mutex_init");
    decltype(vlc_mutex_lock) *_vlc_mutex_lock = (decltype(vlc_mutex_lock) *) GetProcAddress(libvlccore_dll, "vlc_mutex_lock");
    decltype(vlc_mutex_unlock) *_vlc_mutex_unlock = (decltype(vlc_mutex_unlock) *) GetProcAddress(libvlccore_dll, "vlc_mutex_unlock");



    uint8_t *FrameBuffer = (uint8_t *)malloc(1920*1080*3);

    RenderCallbackParamsStruct RenderCallbackParams;
    RenderCallbackParams.Buffer = FrameBuffer;
    _vlc_mutex_init(&RenderCallbackParams.Mutex);
    RenderCallbackParams._vlc_mutex_lock = _vlc_mutex_lock;
    RenderCallbackParams._vlc_mutex_unlock = _vlc_mutex_unlock;
    RenderCallbackParams.counter = 0;

    char smem_options[256];
    sprintf(smem_options,
        "#transcode{vcodec=RV24}:smem{"
         "video-prerender-callback=%lld,"
         "video-postrender-callback=%lld,"
         "video-data=%lld,"
         "no-time-sync},",
      (long long int)(intptr_t)(void*)&VideoPrerender,
      (long long int)(intptr_t)(void*)&VideoPostrender,
      (long long int)(intptr_t)(void*)&RenderCallbackParams
      );

    const char *const vlc_args[] = 
    {
        "-I", "dummy", // Don't use any interface
        "--ignore-config",
        "--no-audio",
        "--verbose=2", // Be much more verbose than normal for debugging purpose
        "--sout", smem_options // Stream to memory
    };

    libvlc_instance_t *vlcInstance;
    libvlc_media_player_t *vlcMediaPlayer;
    libvlc_media_t *vlcMedia;

    /* Load the VLC engine */
    vlcInstance = _libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args);

    /* Create a new item */
    vlcMedia = _libvlc_media_new_path(vlcInstance, "WayOfKings.mp4");

    /* Create a media player playing environement */
    vlcMediaPlayer = _libvlc_media_player_new_from_media(vlcMedia);

    /* play the media_player */
    _libvlc_media_player_play(vlcMediaPlayer);

    Sleep(1000);

    // Breakpoint here

    _libvlc_media_player_stop(vlcMediaPlayer);

    /* Free the media_player */
    _libvlc_media_player_release(vlcMediaPlayer);

    _libvlc_release(vlcInstance);

    return 0;
}

По большей части я следовал официальному учебнику по смэму на vlcwiki: https://wiki.videolan.org/Stream_to_memory_(smem)_tutorial/ (но это касается только передачи аудио и очень поверхностно) и некоторые другие обсуждения, которые я нашел по stackoverflow.

Я ценю любые идеи, так как в сети почти нет обсуждений о smem.

...