没有SDL的LibVLC教程?

use*_*364 5 c++ video vlc transcoding libvlc

我想写一帧视频帧到*.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 */
}
Run Code Online (Sandbox Code Playgroud)

我怎么能写没有这个功能struct ctx,SDL_LockMutexSDL_LockSurface

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

Adm*_*onB 7

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

删除SDL

在这个例子中,你必须通过一些不同的函数传递给libvlc回调函数 ......

libvlc_video_set_callbacks(mp, lock, unlock, display, &ctx);
Run Code Online (Sandbox Code Playgroud)

现在,要完全理解这个锁定函数正在做什么,您需要了解一些多线程以及图像如何存储在内存中.

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

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

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

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


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

struct ctx
{
    unsigned char *pixeldata;
};
Run Code Online (Sandbox Code Playgroud)

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

ctx.pixeldata = new unsigned char[width * height * bpp];
Run Code Online (Sandbox Code Playgroud)

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

delete[] ctx.pixeldata;
Run Code Online (Sandbox Code Playgroud)

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

问题是你将为此目的使用互斥锁(如果你想使用一个,我建议你这样做)?如果您使用的是较新的C++ 11标准,则可以使用std :: mutex.如果你不是,那么你将不得不找到像boost boost文件库那样的东西,或者写一些类似你自己的东西.如果您使用的是C++ 11,则需要将其添加到ctx结构中...

#include <mutex>

struct ctx
{
    unsigned char *pixeldata;
    std::mutex imagemutex;
};
Run Code Online (Sandbox Code Playgroud)

现在为实际的锁定功能本身.

static void *lock(void *data, void **p_pixels)
{
    struct ctx *ctx = data;

    ctx->imagemutex.lock()
    *p_pixels = ctx->pixeldata;

    return NULL;
}
Run Code Online (Sandbox Code Playgroud)

你的解锁功能会是这样的......

static void unlock(void *data, void *id, void *const *p_pixels)
{
    struct ctx *ctx = data;

    ctx->unlock();

    assert(id == NULL);
}
Run Code Online (Sandbox Code Playgroud)

无论何时您想要安全地访问该像素数据......

ctx->imagemutex.lock();
/* Access Data Here */
ctx->imagemutex.unlock();
Run Code Online (Sandbox Code Playgroud)

使用SDL

我想简单介绍一下SDL.虽然它可以用于将视频显示到屏幕,但您不需要.就个人而言,如果您没有经验,我建议您继续使用SDL并在示例中进一步删除显示代码.它在这个例子中为你处理内存,所以如果你不知道怎么做,它比编写你自己的安全代码容易一些.