Я пытаюсь передать поток 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.