没有SDL的LibVLC教程?

时间:2013-05-13 08:19:36

标签: c++ video vlc libvlc transcoding

我正在尝试逐帧地将视频写入* .yuv文件,并找到有关将视频渲染到SDL表面的this教程。

现在我不确定如何在没有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 ctxSDL_LockMutexSDL_LockSurface的情况下编写此功能?

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

1 个答案:

答案 0 :(得分:7)

我真的不知道libvlc,但是你可以根据这个特例去除SDL。

删除SDL

在此示例中,您必须将几个不同的函数传递给libvlc callback function ...

libvlc_video_set_callbacks(mp, lock, unlock, display, &ctx);

现在,要完全了解此锁定功能的作用,您需要了解一些多线程以及图像如何存储在内存中。

  • 本质上,为了确保没有任何内容访问libvlc在写入时所使用的内存区域,它会“锁定”一种称为互斥锁的内容。如果您尝试锁定已被其他内容锁定的互斥锁,则当前执行将一直等到它被解锁。

    如果你在半边写的时候访问了这些像素,你能想象它会有多可怕吗?它可能是半写的,然后你会用它来保存你的yuv文件。这将是灾难性的。

  • 锁定功能所做的第二件事是指定内存中vlc可用于加载图像帧的区域。此示例使用SDL_Surface,但如果您小心 ,则可以创建自己的

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


我将从上面的列表中按相反的顺序排列。在示例中,它们使用SDL_Surface但是如果您无法使用它,则必须在内存中创建自己的结构以存储像素数据(如果您想要提取它)。一种简单的方法是创建一个正确大小的char数组。我会使用ctx结构,因为它很方便:我知道你问过不使用它,但在这种情况下它非常有用,因为我们需要将多条信息传递给锁定函数。

struct ctx
{
    unsigned char *pixeldata;
};

现在,在主函数的某处,您需要在内存中创建区域。如果您知道视频大小和每像素使用的位数(bpp):这非常简单。但要非常小心,如果你没有正确地做到这一点:你可能最终会导致内存损坏。

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

确保在程序结束时正确删除...

delete[] ctx.pixeldata;

接下来是互斥体。这不是严格需要的,但是你可以遇到我上面提到的问题。如果您确实想使用互斥锁,则需要在libvlc_video_set_callbacks中指定解锁函数(如果您不想使用互斥锁,可以指定NULL解锁)。

问题是你将为此目的使用互斥锁(如果你想使用它,我建议你这样做)?如果您使用的是较新的C ++ 11标准,则可以使用std::mutex。如果你不是,那么你必须找到像boost threading library这样的东西,或者写一些类似你自己的东西。如果您使用的是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并删除示例中的显示代码。它在这个例子中为你处理内存,所以如果你不知道如何,它比编写你自己的安全代码容易一些。