LibVLC for android 解码视频并获取每一帧

本文介绍了如何在Android上使用LibVLC库解码视频并获取每一帧,通过libvlc_video_set_format()和libvlc_video_set_callbacks()设置格式和回调,通过JNI层与JAVA层交互,实现视频帧的处理。然而,这种方法存在解码效率和显示效率问题,可能导致CPU负载增加和额外的内存拷贝操作。
摘要由CSDN通过智能技术生成

一、背景

      最近有一个需求,使用android系统的设备,从IP摄像头(RTSP SERVER)获取到的视频中的每一帧进行处理(人脸检测),直接使用ffmpeg进行实现比较简单,但是苦于对ffmpeg不太熟悉,获取到的视频延迟较高,只好转战看看LibVLC能否获得更好的效果。

        两篇文章帮助较大,在此感谢:

        https://zhuanlan.zhihu.com/p/30595614

        https://www.cnblogs.com/enigma19971/p/6269014.html

二、主要思路

     主要思路是利用libVLC 现有的API:libvlc_video_set_format()  、libvlc_video_set_callbacks() 对libvlc解码后的帧进行截取,然后把设置callback的接口通过JNI暴露给JAVA层。这两个函数都在libvlc_media_player.h中有具体的说明。下面分别进行分析。

三、 具体实现

3.1 Lib层
3.1.1 libvlc_video_set_format() :

以下截取自"libvlc_media_player.h"

/**
 * Set decoded video chroma and dimensions.
 * This only works in combination with libvlc_video_set_callbacks(),
 * and is mutually exclusive with libvlc_video_set_format_callbacks().
 *
 * \param mp the media player
 * \param chroma a four-characters string identifying the chroma
 *               (e.g. "RV32" or "YUYV")
 * \param width pixel width
 * \param height pixel height
 * \param pitch line pitch (in bytes)
 * \version LibVLC 1.1.1 or later
 * \bug All pixel planes are expected to have the same pitch.
 * To use the YCbCr color space with chrominance subsampling,
 * consider using libvlc_video_set_format_callbacks() instead.
 */
LIBVLC_API
void libvlc_video_set_format( libvlc_media_player_t *mp, const char *chroma,
                              unsigned width, unsigned height,
                              unsigned pitch );

该函数的作用是设置你希望的输出帧的格式和尺寸,libvlc会非常卖力地帮你解码,然后转换成你希望的格式。

· chroma为视频输出帧格式的选择,可以是常用的YUYV、NV12、RGBA等各种格式;

· width、height为你希望输出的帧的长宽;

· pitch 直接的翻译是“场”,它的值是 帧宽度 × 每个像素所占的字节数,当然每个像素的字节数是由你选择的帧格式决定的,比如RGBA一个像素4个字节,YUYV一个像素1.5个字节。具体自己问google。


3.1.2 libvlc_video_set_callbacks():

以下截取自"

libvlc库中,VideoFrame是处理视频流的核心数据结构,它封装了每一帧的像素数据。以下是获取并处理VideoFrame的一般步骤: 1. **初始化 VLC 播放器**: 首先,你需要创建一个VLC播放器实例,并开启解码器以便接收VideoFrames。 ```c++ vlclibvlc_instance_t *instance = libvlc_new(0, NULL); vlclibvlc_media_player_t *player = libvlc_media_player_new_from_instance(instance); ``` 2. **创建媒体源并播放**: 加载你要播放的媒体文件,然后开始播放。 ```c++ vlclibvlc_media_t *media = libvlc_media_new_path(instance, "path_to_your_video"); if (libvlc_media_player_play(player) < 0) { // 错误处理 } ``` 3. **注册回调函数**: 为了接收到VideoFrames,需要设置一个`video_display`回调函数。这个函数会在每帧解码完成后被调用。 ```c++ void video_display(void *data, struct libvlc_event_args *args) { vlcvideoframe_t *frame = data; // 处理帧数据... } libvlc_media_player_set_callbacks(player, &video_display, NULL, NULL); ``` 4. **读取和处理帧**: 当`video_display`回调被触发时,你可以从`frame`指针中提取数据,例如像素数据或颜色空间等信息。 ```c++ // 获取帧宽度、高度和像素数据 int width = frame->width; int height = frame->height; unsigned char *pixels = vlccolor_get_buffer(frame, VLC_VIDEO_FORMAT_I420); // 进行图像处理,如缩放、转换格式等 // ... vlccolor_release_buffer(frame, pixels); ``` 5. **释放资源**: 当不再需要VideoFrame时,记得释放它以及相关的VLC资源。 ```c++ vlcvideoframe_release(frame); libvlc_media_player_stop(player); libvlc_release(player); libvlc_release(instance); ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值