Учебник по LibVLC без SDL?

Я пытаюсь записать видео кадр за кадром в файл * .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?

Как вы можете себе представить, я не очень опытный программист, поэтому, пожалуйста, будьте терпеливы со мной;)
Заранее спасибо!

5

Решение

Я действительно не знаю libvlc, но вот как вы могли бы удалить SDL на основе этого конкретного примера.

В этом примере есть несколько различных функций, которые вы должны передать функция обратного вызова libvlc

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

Теперь, чтобы полностью понять, что делает эта функция блокировки, вам нужно немного понять многопоточность и то, как изображение хранится в памяти.

  • По сути, чтобы удостовериться, что ничто не обращается к области памяти, которую использует libvlc во время записи в нее, она «блокирует» нечто, известное как мьютекс. Если вы попытаетесь заблокировать мьютекс, который уже заблокирован чем-то другим, текущее выполнение будет ждать, пока оно не будет разблокировано.

    Если вы получили доступ к этим пикселям, когда они были написаны наполовину, можете ли вы представить, как это ужасно? Он может быть наполовину написан, и вы сможете использовать его для сохранения в свой файл yuv. Это было бы довольно пагубно.

  • Второе, что делает функция блокировки, — это указание области памяти, которую 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_callbacks (вы можете указать NULL для разблокировки, если вы не хотите использовать мьютекс).

Проблема в том, какой мьютекс вы будете использовать для этой цели (если вы хотите использовать мьютекс, который я предлагаю вам сделать)? Если вы используете более новый стандарт C ++ 11, вы можете использовать станд :: мьютекс. Если нет, то вам нужно найти что-то еще, как увеличить поток библиотеки или напишите что-нибудь подобное. Если вы используете 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 и убрать код дисплея дальше по примеру. В этом примере он обрабатывает память для вас, так что это немного проще, чем писать собственный безопасный код, если вы не знаете, как.

7

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]