文章目录
前言
提示:libvlc_video_set_format_callbacks
在LibVLC对视频媒体的逐帧提取开发中,void libvlc_video_set_format () 通常被开发者用来设置视频的格式,但是不同视频的格式是不同的,所以该函数是应用于用户已知媒体视频的格式,用户进行手动设置。接下来我将介绍由libvlc提供的void libvlc_video_set_format_callbacks () 回调设置视频的原始帧格式,该函数也可以帮助开发者在视频媒体播放前获取到帧格式。
提示:以下是本篇文章正文内容,下面案例可供参考
一、应用场景
当开发者需要对视频媒体的帧进行处理、保存帧图像、实现多屏播放等应用场景时,逐帧提取是一个关键的技术。libvlc帮我们实现了逐帧提取的相关API,理解这些API是实现上述场景的核心。
二、API介绍
1. libvlc_video_set_callbacks ()
void libvlc_video_set_callbacks ( // 设置回调,将解码后的帧渲染并存储到内存中的自定义区域。
libvlc_media_player_t * mp,
libvlc_video_lock_cb lock,
libvlc_video_unlock_cb unlock,
libvlc_video_display_cb display,
void * opaque
)
2. libvlc_video_set_format ()
void libvlc_video_set_format ( // 配置帧的解码格式
libvlc_media_player_t * mp,
const char * chroma,
unsigned width,
unsigned height,
unsigned pitch
)
3. libvlc_video_set_format_callbacks ()
版本:LibVLC 2.0.0 or later
libvlc_video_set_format_callbacks ( // 设置回调,配置帧的解码格式
libvlc_media_player_t * mp,
libvlc_video_format_cb setup,
libvlc_video_cleanup_cb cleanup
)
二、逐帧提取
1. 开发者设置帧格式
因为我看到很多的平台都由相关的 libvlc_video_set_format () 使用介绍,所以在此我不再赘述。如果有需要,可以参考https://jishuin.proginn.com/p/763bfbd2afc3。
2. 回调设置帧格式
代码如下(示例):
因为本人是在Qt + VLC的开发环境下,所以会使用部分Qt的工具,如果你是纯C++开发者,你可以用C++相应的工具替换它们。
本人的开发环境:Linux、Qt、C++
#include <QDebug>
#include <QMutex>
#include <QThread>
struct Context {
QMutex mutex;
int width;
int height;
uchar * pixels;
};
static Context *g_pContxt = nullptr;
static void *lock(void */*opaque*/, void **planes)
{
g_pContxt->mutex.lock();
*planes = g_pContxt->pixels;
return NULL;
}
static void unlock(void */*opaque*/, void */*picture*/, void *const *planes)
{
unsigned char *data = (unsigned char *)*planes; // planes即为帧数据
/*
处理帧数据data
*/
g_pContxt->mutex.unlock();
}
static void display(void *opaque, void *picture)
{
(void)opaque;
}
static unsigned setup(void** /*opaque*/, char* chroma, unsigned *width, unsigned *height, unsigned *pitches, unsigned *lines)
{
qDebug() << "chroma:" << QString(chroma) << "width:" << *width << ", height:" << *height;
/* 开辟存放图像数据的内存块 */
if (g_pContxt)
{
if (g_pContxt->pixels)
{
delete[] g_pContxt->pixels;
g_pContxt->pixels = NULL;
}
delete g_pContxt;
g_pContxt = NULL;
}
int w = *width;
int h = *height;
g_pContxt = new Context;
g_pContxt->pixels = new uchar[w * h * 4]; // 申请大小也为4通道的像素
memset(g_pContxt->pixels, 0, g_pContxt->width * g_pContxt->height * 4);
memcpy(chroma, "RV32", 4);
g_pContxt->width = w;
g_pContxt->height = h;
*pitches= w * 4;
*lines= h;
return 1;
}
int main()
{
const char *fileName= "1.mp4"; // 设置你自己的媒体文件路径名
libvlc_instance_t *m_pVlcInst = libvlc_new(0, NULL);
libvlc_media_t *pMedia = libvlc_media_new_path(m_pVlcInst, fileName); // 媒体
libvlc_media_player_t *m_pVlcPlayer = libvlc_media_player_new_from_media(pMedia);
libvlc_media_release(pMedia); // 释放媒体对象
pMedia = nullptr;
/* 设置逐帧提取 */
libvlc_video_set_callbacks(m_pVlcPlayer, lock, unlock, display, NULL); // 设置帧回调,用来抓取解码后的帧
libvlc_video_set_format_callbacks(m_pVlcPlayer, setup, NULL); // 设置格式回调,用来设置解码后的帧格式
/* 播放和停止媒体 */
libvlc_media_player_play(m_pVlcPlayer);
QThread::sleep(100);
libvlc_media_player_stop(m_pVlcPlayer);
/* 释放资源 */
libvlc_media_player_release(m_pVlcPlayer);
m_pVlcPlayer = nullptr;
libvlc_release(m_pVlcInst);
m_pVlcInst = nullptr;
if (g_pContxt)
{
if (g_pContxt->pixels)
{
delete[] g_pContxt->pixels;
g_pContxt->pixels = nullptr;
}
delete g_pContxt;
g_pContxt = nullptr;
}
}
总结
如果用户需要对不同视频媒体进行逐帧提取时,用户需要重复设置不同的帧格式。因为保持相同的帧格式应用在不同的视频媒体上,往往会带来帧的横向或纵向的拉伸。而回调设置帧格式的方法很好的解决了开发者手动设置帧格式的繁琐和弊端。
希望您能仔细阅读,因为发现和指正文章中的不足之处,是对我莫大的提升,谢谢!