Android LibVLC,在没有TextureView的情况下拍摄RTSP流的快照。

huangapple go评论78阅读模式
英文:

Android LibVLC, take snapshot of RTSP stream without TextureView

问题

考虑根据官方的建议方式,在Android上使用libVLC

我已经顺利完成了编译过程(但花了一些时间)。

我想要拍摄快照的功能,但我发现了一些非常旧(2-3年前)的帖子,其中提到这个功能仍然不可用(2016年),至少不是"开箱即用",根据这个帖子(2014年)。

快照功能在其他平台上是可用的。

还有一些解决方案,它们切换到TextureView。

但我更喜欢使用SurfaceView,因为TextureView会带来一些性能问题(根据这个帖子)。

而且,在官方的Android页面上有这样的说明:

在API 24及更高版本中,建议实现SurfaceView而不是TextureView。

2014年只有2个依赖于快照功能的帖子中提到的

  • 启用sout模块
  • 启用png编码器

当查看VideoLAN的"VLC-Android"仓库时,有一个文件负责构建libVLC。

在第396行,默认情况下似乎启用了sout模块。

在编译之前,我已经按照论坛中指出的方法在vlc/contrib/src/ffmpeg/rules.mak中启用了png编码器。

然而,在org.videolan.libvlc.MediaPlayer或org.videolan.libvlc.VLCVideoLayout中仍然没有与快照相关的功能。

问题是如何在Android上使用libVLC创建快照(保存到文件或缓冲区),而不使用TextureView?

更新1:

事实1:
找到了为什么在Android上不可用的原因。在VLC的核心源树中,在文件lib/video.c的第145行,有一个巨大的FIXME警告的快照功能:

/* FIXME: This is not atomic. All parameters should be passed at once
 * (obviously _not_ with var_*()). Also, the libvlc object should not be
 * used for the callbacks: that breaks badly if there are concurrent
 * media players in the instance. */
var_Create( p_vout, "snapshot-width", VLC_VAR_INTEGER );
var_SetInteger( p_vout, "snapshot-width", i_width);
var_Create( p_vout, "snapshot-height", VLC_VAR_INTEGER );
var_SetInteger( p_vout, "snapshot-height", i_height );
var_Create( p_vout, "snapshot-path", VLC_VAR_STRING );
var_SetString( p_vout, "snapshot-path", psz_filepath );
var_Create( p_vout, "snapshot-format", VLC_VAR_STRING );
var_SetString( p_vout, "snapshot-format", "png" );
var_TriggerCallback( p_vout, "video-snapshot" );
vlc_object_release( p_vout );

事实2:
我想采取另一种方向。如果快照功能不可用(而且不明智使用它),我考虑了一些紧急解决方案:

  1. VLC中有一个名为scene的视频过滤器。它可以将视频的静态图像生成到特定路径。我尝试使用这个,但视频过滤器不能在运行时更改。所以这个尝试失败了。

  2. 我还尝试从MediaPlayer中进行(通过Media.addOption),但是在Android上无法在MediaPlayer级别更改视频过滤器。

  3. 然后,我尝试将过滤器配置作为参数传递给libVLC初始化,最终成功了,但是每次需要截图时创建一个新的libVLC实例并不是一个有效的解决方案。

英文:

Consider using libVLC for Android, based on the official recommended way.

I went through the compilation process without problems (but took some time).

I'd like to have the snapshot functionality, but I've found some very old (2-3 years old) threads around which states that this feature is still not available (2016) at least "not out of the box' by this thread (2014).

Snapshot functionality is available on other platforms.

Also there are some solutions where they switch from SurfaceView to TextureView.

However I prefer sticking to SurfaceView as TextureView brings some performance drawbacks (according to this topic).

Also on an official android page it's stated:

In API 24 and higher, it's recommended to implement SurfaceView instead of TextureView.

In 2014 there were only 2 dependecies of the snapshot function based on the thread I've mentioned earlier:

  • enabling sout module
  • enabling png as encoder

When looking the "VLC-Android" repository of VideoLAN, there is a file responsible for building libVLC.

In line 396, sout module seems to be enabled by default.

Before compilation I've enabled png as encoder in vlc/contrib/src/ffmpeg/rules.mak as pointed out in the forum.

However there is still no function related to snapshot in either org.videolan.libvlc.MediaPlayer or in org.videolan.libvlc.VLCVideoLayout.

The question is how can I create a snapshot (either into file, or into buffer) on Android with libVLC, without using TextureView?

Update1:

Fact1:
Found the reason on why it's unavailable on Android. In VLC's core source tree, in file lib/video.c on line 145 there is the snapshot function with a massive FIXME warning:

/* FIXME: This is not atomic. All parameters should be passed at once
 * (obviously _not_ with var_*()). Also, the libvlc object should not be
 * used for the callbacks: that breaks badly if there are concurrent
 * media players in the instance. */
var_Create( p_vout, "snapshot-width", VLC_VAR_INTEGER );
var_SetInteger( p_vout, "snapshot-width", i_width);
var_Create( p_vout, "snapshot-height", VLC_VAR_INTEGER );
var_SetInteger( p_vout, "snapshot-height", i_height );
var_Create( p_vout, "snapshot-path", VLC_VAR_STRING );
var_SetString( p_vout, "snapshot-path", psz_filepath );
var_Create( p_vout, "snapshot-format", VLC_VAR_STRING );
var_SetString( p_vout, "snapshot-format", "png" );
var_TriggerCallback( p_vout, "video-snapshot" );
vlc_object_release( p_vout );  

Fact2:
I wanted to go to another direction with this. If snapshot function is not usable (and also not wise to use it), I thought of some emergency solutions:

  1. there is a video-filter in VLC named scene. This produce still images of the video to a specific path. I tried using this, but video-filters are not able to change at runtime. So this attempt failed.

  2. I also tried to do it from the MediaPlayer (via Media.addOption), but video filters are also not possible to change at MediaPlayer level on Android.

  3. I tried then to pass the filter config as an argument to libVLC initialization and finally it succeeded, however that won't be effective to create a new libVLC instance everytime when I need a screenshot.

答案1

得分: 2

以下是翻译好的内容:

  • 这是一个使用libvlc的跨平台缩略图生成示例:https://code.videolan.org/mfkl/libvlcsharp-samples/blob/master/PreviewThumbnailExtractor.Skia/Program.cs 由于在脚本中没有使用任何特定于操作系统的功能,所以在Android上进行编辑不需要太多工作。我猜应该也可以将其翻译成Java/Kotlin。

  • 有一个libvlc函数可以允许您拍摄快照。只需前往所需的时间并调用它:https://www.videolan.org/developers/vlc/doc/doxygen/html/group__libvlc__video.html#ga9b0a3870ce962aa0358050b2d5a59143

  • 在VLC Android中,medialibrary 现在管理缩略图。

  • LibVLC 4现在捆绑了一个缩略图生成器:https://github.com/videolan/vlc/blob/d40eb012b10cc355ea9ad7a13eaf494b8e826d78/include/vlc/libvlc_media.h#L845

祝好运。

英文:

A few ways to go about this...

Good luck.

huangapple
  • 本文由 发表于 2020年1月4日 01:19:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/59582719.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定