【C/C++】LibVLC库在逐帧提取的开发中回调设置帧格式


前言

提示:libvlc_video_set_format_callbacks

在LibVLC对视频媒体的逐帧提取开发中,void libvlc_video_set_format () 通常被开发者用来设置视频的格式,但是不同视频的格式是不同的,所以该函数是应用于用户已知媒体视频的格式,用户进行手动设置。接下来我将介绍由libvlc提供的void libvlc_video_set_format_callbacks () 回调设置视频的原始帧格式,该函数也可以帮助开发者在视频媒体播放前获取到帧格式。


提示:以下是本篇文章正文内容,下面案例可供参考

一、应用场景

当开发者需要对视频媒体的帧进行处理、保存帧图像、实现多屏播放等应用场景时,逐帧提取是一个关键的技术。libvlc帮我们实现了逐帧提取的相关API,理解这些API是实现上述场景的核心。

二、API介绍

您可在https://videolan.videolan.me/vlc/group__libvlc__media__player.html#ga612605f2e5c638d9f4ed59021d714bf0查看这些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;
    }
}

总结

如果用户需要对不同视频媒体进行逐帧提取时,用户需要重复设置不同的帧格式。因为保持相同的帧格式应用在不同的视频媒体上,往往会带来帧的横向或纵向的拉伸。而回调设置帧格式的方法很好的解决了开发者手动设置帧格式的繁琐和弊端。
希望您能仔细阅读,因为发现和指正文章中的不足之处,是对我莫大的提升,谢谢!

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值