我真的不知道 libvlc,但这里是您可以如何根据该特定示例删除 SDL。
删除 SDL
在此示例中,您必须将几个不同的函数传递给libvlc 回调函数......
libvlc_video_set_callbacks(mp, lock, unlock, display, &ctx);
现在,要完全理解这个锁函数在做什么,你需要了解一点多线程以及图像是如何存储在内存中的。
本质上,为了确保在写入时 libvlc 正在使用的内存区域没有任何访问,它“锁定”了称为互斥体的东西。如果您尝试锁定已被其他东西锁定的互斥锁,则当前执行将等待直到它被解锁。
如果你在写一半的时候访问这些像素,你能想象它会有多可怕吗?它可能写了一半,然后您将使用它保存到您的 yuv 文件中。这将是非常灾难性的。
lock 函数所做的第二件事是指定内存中的一个区域,vlc 可以使用它来加载图像帧。此示例为此使用了 SDL_Surface,但如果您小心的话,您可以创建自己的 SDL_Surface 。
所以,如果你只使用 libvlc,你会想找到这些东西的替代品。
我将从上面的列表中按相反的顺序进行。在示例中,他们使用 SDL_Surface 但是如果您无法使用它,则必须在内存中创建自己的结构来存储像素数据,如果您想提取它。一个简单的方法是创建一个正确大小的 char 数组。我将使用 ctx 结构,因为它很方便:我知道你问过不使用它,但在这种情况下它非常有用,因为我们需要将多条信息传递给 lock 函数。
struct ctx
{
unsigned char *pixeldata;
};
现在,在您的 main 函数的某个地方,您需要在内存中创建该区域。如果您知道视频大小以及每像素使用多少位 (bpp):这非常简单。但是要非常小心,如果您没有正确执行此操作:您最终可能会导致内存损坏。
ctx.pixeldata = new unsigned char[width * height * bpp];
确保在程序结束时正确删除它...
delete[] ctx.pixeldata;
接下来是互斥体。这不是绝对需要的,但是您可能会遇到我上面提到的问题。如果您确实想使用互斥锁,则需要在 libvlc_video_set_callbacks 中指定解锁函数(如果您不想使用互斥锁,可以指定 NULL 进行解锁)。
问题是您将为此目的使用什么互斥锁(如果您想使用一个,我建议您这样做)?如果您使用较新的 C++11 标准,则可以使用std::mutex。如果你不是,那么你将不得不找到其他东西,比如boost 线程库,或者自己写一些类似的东西。如果您使用的是 C++11,则将其添加到 ctx 结构中...
#include <mutex>
struct ctx
{
unsigned char *pixeldata;
std::mutex imagemutex;
};
现在来看看实际的锁定功能本身。
static void *lock(void *data, void **p_pixels)
{
struct ctx *ctx = data;
ctx->imagemutex.lock()
*p_pixels = ctx->pixeldata;
return NULL;
}
您的解锁功能将是这样的......
static void unlock(void *data, void *id, void *const *p_pixels)
{
struct ctx *ctx = data;
ctx->unlock();
assert(id == NULL);
}
每当您想安全地访问该像素数据时...
ctx->imagemutex.lock();
/* Access Data Here */
ctx->imagemutex.unlock();
使用 SDL
我想简单地添加一些关于 SDL 的内容。虽然它可用于将视频显示到屏幕上,但您不需要这样做。就个人而言,如果您不是那么有经验,我建议您继续使用 SDL 并在示例下方删除显示代码。在本例中,它会为您处理内存,因此如果您不知道如何编写安全代码,它比编写自己的安全代码要容易一些。