在流式传输 URL 时获取 Android VideoView 接收到的数据包
Getting Access on the Android VideoView received packets when Streaming a URL
VideoView 的本机代码是否允许在解码之前或之后访问接收到的视频数据包?我需要访问这些数据包以便将它们传输到另一台设备。最初的解决方案是修改 Android 本机代码。我发现的其他可能的解决方案是使用 GStreamer 或 FFmpeg 库。
我需要一些指导才能实现该目标。
假设 phone 已 root。
简短的回答是否定的,据我所知没有。
长答案是你没有提供足够的细节。您究竟需要访问哪些数据?您是在编写应用程序,还是正在修改您的 OS 以对其他应用程序执行此操作?
实际获取远程视频的代码在 MediaPlayer
中并且是原生的。参见MediaPlayer
中的以下方法:
private void setDataSource(/* snip */) throws /* snip */ {
/* snip */
else if (scheme != null) {
// handle non-file sources
nativeSetDataSource(
MediaHTTPService.createHttpServiceBinderIfNecessary(path),
path,
keys,
values);
return;
}
/* snip */
不幸的是,几乎所有相关的 MediaPlayer
代码都是 native
,如果不是,它是私有的(因此 subclassing 在这里不起作用)。
但是,根据您需要执行的操作,您可以覆盖 VideoView
方法 setVideoURI(Uri, Map<String, String>)
,即 public。在这里您可以获取 URI,然后通过您自己的 Web 服务或其他方式代理它。不过,这并不完全是您要问的。
或者,您可以考虑修改 MediaPlayer
所吸引的 Surface
。不过,大多数相关代码仍然是 native
。
我要提到的最后一种可能性(可能有数百种可能的方法)是修改 MediaHTTPService
class。这似乎被 MediaPlayer
使用,但我不能确定,因为如果使用它,它就会在本机代码中使用。
This answer recommends finding the native code at androidxref.com
编辑:
根据要求,这里有一些关于 "proxy server" 解决方案的更多细节。我不知道 Android.
的实施细节
基本上,当您获得 URL 在 VideoView
中播放时,您会将其传递到您自己的服务器。类似于 startProxyServer(videoUrl)
。这将启动一个服务器,该服务器下载并重新托管视频。要使其在本地运行,请启动一个侦听 localhost
的网络服务器。服务器只是在 videoUrl
下载视频,将其保存在本地,然后在 localhost:port/?video=${videoUrl}
.
托管它
所以在非常高级的伪代码中,服务器可能看起来像。
public void startProxyServer(String videoUrl) {
int PORT = 28641; // random port
File f = downloadFile(videoUrl);
saveFile(f, '/path/to/server/storage');
startWebServer('localhost', PORT);
}
所以现在您将 localhost:port/?video=${videoUrl}
作为 url 给 videoView
。此外,现在其他 videoView
个实例可以从同一本地主机 url.
下载
要让它与其他手机一起使用,您的服务器当然不能 运行 localhost
。
当然我没有实现这个,但这只是我能想到的一种解决方案。
VideoView 的本机代码是否允许在解码之前或之后访问接收到的视频数据包?我需要访问这些数据包以便将它们传输到另一台设备。最初的解决方案是修改 Android 本机代码。我发现的其他可能的解决方案是使用 GStreamer 或 FFmpeg 库。 我需要一些指导才能实现该目标。
假设 phone 已 root。
简短的回答是否定的,据我所知没有。
长答案是你没有提供足够的细节。您究竟需要访问哪些数据?您是在编写应用程序,还是正在修改您的 OS 以对其他应用程序执行此操作?
实际获取远程视频的代码在 MediaPlayer
中并且是原生的。参见MediaPlayer
中的以下方法:
private void setDataSource(/* snip */) throws /* snip */ {
/* snip */
else if (scheme != null) {
// handle non-file sources
nativeSetDataSource(
MediaHTTPService.createHttpServiceBinderIfNecessary(path),
path,
keys,
values);
return;
}
/* snip */
不幸的是,几乎所有相关的 MediaPlayer
代码都是 native
,如果不是,它是私有的(因此 subclassing 在这里不起作用)。
但是,根据您需要执行的操作,您可以覆盖 VideoView
方法 setVideoURI(Uri, Map<String, String>)
,即 public。在这里您可以获取 URI,然后通过您自己的 Web 服务或其他方式代理它。不过,这并不完全是您要问的。
或者,您可以考虑修改 MediaPlayer
所吸引的 Surface
。不过,大多数相关代码仍然是 native
。
我要提到的最后一种可能性(可能有数百种可能的方法)是修改 MediaHTTPService
class。这似乎被 MediaPlayer
使用,但我不能确定,因为如果使用它,它就会在本机代码中使用。
This answer recommends finding the native code at androidxref.com
编辑:
根据要求,这里有一些关于 "proxy server" 解决方案的更多细节。我不知道 Android.
的实施细节基本上,当您获得 URL 在 VideoView
中播放时,您会将其传递到您自己的服务器。类似于 startProxyServer(videoUrl)
。这将启动一个服务器,该服务器下载并重新托管视频。要使其在本地运行,请启动一个侦听 localhost
的网络服务器。服务器只是在 videoUrl
下载视频,将其保存在本地,然后在 localhost:port/?video=${videoUrl}
.
所以在非常高级的伪代码中,服务器可能看起来像。
public void startProxyServer(String videoUrl) {
int PORT = 28641; // random port
File f = downloadFile(videoUrl);
saveFile(f, '/path/to/server/storage');
startWebServer('localhost', PORT);
}
所以现在您将 localhost:port/?video=${videoUrl}
作为 url 给 videoView
。此外,现在其他 videoView
个实例可以从同一本地主机 url.
要让它与其他手机一起使用,您的服务器当然不能 运行 localhost
。
当然我没有实现这个,但这只是我能想到的一种解决方案。