LibVLC教程,不带SDL

LibVLC tutorial without SDL?

本文关键字:SDL 不带 教程 LibVLC      更新时间:2023-10-16

我正在尝试逐帧写入视频到*。yuv文件,找到了这个关于将视频渲染成SDL表面的教程。

现在我不确定如何在没有SDL库的情况下使用此代码。例如,锁函数:

static void *lock(void *data, void **p_pixels)
{
    struct ctx *ctx = data;
    SDL_LockMutex(ctx->mutex);
    SDL_LockSurface(ctx->surf);
    *p_pixels = ctx->surf->pixels;
    return NULL; /* picture identifier, not needed here */
}

没有struct ctx, SDL_LockMutex, SDL_LockSurface怎么写这个函数?

你可以想象,我不是一个非常有经验的程序员,所以请耐心等待我;)
提前感谢!

我不太了解libvlc,但下面是基于这个特定示例删除SDL的方法。

<标题>删除SDL h1> 这个例子中,有几个不同的函数你必须传递给libvlc回调函数…
libvlc_video_set_callbacks(mp, lock, unlock, display, &ctx);

现在,为了完全理解这个锁函数在做什么,你需要了解一点多线程以及图像是如何存储在内存中的。

  • 本质上,为了确保libvlc在写入内存时没有任何东西访问它所使用的内存区域,它"锁定"了一个被称为互斥锁的东西。如果您试图锁定一个已经被其他对象锁定的互斥锁,则当前执行将等待直到它被解锁。

    如果你在它写了一半的时候访问这些像素,你能想象它会有多可怕吗?它可能只写了一半,然后您将使用它保存到您的yuv文件中。

  • lock函数做的第二件事是在内存中指定vlc可以用来加载图像帧的区域。这个例子使用了SDL_Surface,但是你也可以创建你自己的

所以,如果你只使用libvlc,你会想要找到一个替代这些东西。


我将按照上面列表的倒序排列。在这个例子中,他们使用SDL_Surface,但是如果你不能使用它,你将不得不在内存中创建自己的结构来存储像素数据,如果你想提取它。一个简单的方法是创建一个正确大小的字符数组。我将使用ctx结构体,因为它很方便:我知道您要求不要使用它,但它在这种情况下非常有用,因为我们需要将多条信息传递给锁函数。

struct ctx
{
    unsigned char *pixeldata;
};

现在,在主函数的某个地方,您需要在内存中创建该区域。如果您知道视频大小和每像素使用多少比特(bpp):这非常简单。但是要非常小心,如果你做得不对:你可能会导致内存损坏。

ctx.pixeldata = new unsigned char[width * height * bpp];

确保在程序结束时正确删除这个…

delete[] ctx.pixeldata;

下一个是互斥锁。这并不是严格需要的,但是你可能会遇到我上面提到的问题。如果你想使用互斥锁,你需要在libvlc_video_set_callback中指定一个unlock函数(如果你不想使用互斥锁,你可以为unlock指定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并删除示例后面的显示代码。在本例中,它为您处理内存,因此如果您不知道如何编写,它比您自己编写安全代码要容易一些。