[英]Decode android's hardware encoded H264 camera feed using ffmpeg in real time
我正在尝试使用Android上的硬件H264
编码器从相机创建视频,并使用FFmpeg
音频(全部在Android手机本身上)
到目前为止,我已经完成的工作是将H264
视频打包为rtsp
数据包,并使用VLC(通过UDP
)对其进行解码,因此我知道视频的格式至少正确。 但是,我无法以可以理解的格式将视频数据传输到ffmpeg
。
我试过将相同的rtsp
数据包发送到本地主机上的端口5006(通过UDP),然后为ffmpeg
提供sdp
文件,该文件告诉它视频流进入哪个本地端口以及如何解码视频(如果我理解) rtsp
正确流式传输。 但是,这是行不通的,由于ffmpeg
只是坐在那里等待输入,因此我无法诊断原因。
出于延迟和可伸缩性的考虑,我不能仅将视频和音频发送到服务器并在服务器上进行复用,而必须在电话中以尽可能轻便的方式完成。
我猜我正在寻找有关如何实现此目标的建议。 最佳解决方案是通过管道将打包的H264
视频发送到ffmpeg
,但随后我无法将解码视频所需的sdp
文件参数发送给ffmpeg
。
我可以根据要求提供更多信息,例如ffmpeg
如何为Android编译,但我怀疑这是否必要。
哦,我启动ffmpeg
的方式是通过命令行,如果可能的话,我真的宁愿避免与jni混为一谈。
非常感谢您的帮助,谢谢。
您是否尝试过使用java.lang.Runtime?
String[] parameters = {"ffmpeg", "other", "args"};
Program program Runtime.getRuntime().exec(parameters);
InputStream in = program.getInputStream();
OutputStream out = program.getOutputStream();
InputStream err = program.getErrorStream();
然后,您写入stdout并从stdin和stderr中读取。 它不是管道,但应该比使用网络接口更好。
有点晚了,但是我认为这是一个很好的问题,而且还没有很好的答案。
如果要从Android设备流式传输摄像机和麦克风,则有两种主要选择:Java或NDK实现。
Java实现。
我只想提一下这个想法,但基本上,它是基于这些标准的H.264 Video 实时流协议2.0版和RTP有效负载格式在Java中实现RTSP服务器和RTP协议。 这项任务将非常漫长而艰巨。 但是,如果您正在做PhP,那么拥有一个适用于Android的RTSP Java库可能会很好。
NDK实现。
这是备选方案,包括各种解决方案。 主要思想是在我们的Android应用程序中使用功能强大的C或C ++库。 对于此实例,FFmpeg。 该库可以针对Android进行编译,并且可以支持各种架构。 这种方法的问题是您可能需要了解Android NDK,C和C ++才能完成此任务。
但是还有另一种选择。 您可以包装c库并使用FFmpeg。 但是如何?
例如,使用FFmpeg Android ,它已与x264,libass,fontconfig,freetype和fribidi一起编译,并支持各种体系结构。 但是,如果要实时流式传输,仍然很难编程,就需要处理文件描述符和输入/输出流。
从Java编程的角度来看,最好的选择是使用JavaCV 。 JavaCV使用来自常用计算机视觉库的包装器,这些包装器包括:( OpenCV , FFmpeg等),并提供实用程序类以使其功能更易于在Java平台(当然包括Android)上使用。
JavaCV还具有硬件加速的全屏图像显示( CanvasFrame
和GLCanvasFrame
),易于使用的方法以在多核上并行执行代码( Parallel
),相机和投影仪的用户友好型几何和颜色校准( GeometricCalibrator
, ProCamGeometricCalibrator
, ProCamColorCalibrator
),特征点的检测和匹配( ObjectFinder
),实现投影仪与相机系统直接图像对齐的一组类(主要是GNImageAligner
, ProjectiveTransformer
, ProjectiveColorTransformer
, ProCamTransformer
和ReflectanceInitializer
),斑点分析包( Blobs
),以及JavaCV
类中的其他功能。 其中一些类还具有OpenCL和OpenGL对应类,它们的名称以CL
结尾或以GL
开头,即: JavaCVCL
, GLCanvasFrame
等。
但是我们如何使用该解决方案?
在这里,我们有一个使用UDP进行流传输的基本实现。
String streamURL = "udp://ip_destination:port";
recorder = new FFmpegFrameRecorder(streamURL, frameWidth, frameHeight, 1);
recorder.setInterleaved(false);
// video options //
recorder.setFormat("mpegts");
recorder.setVideoOption("tune", "zerolatency");
recorder.setVideoOption("preset", "ultrafast");
recorder.setVideoBitrate(5 * 1024 * 1024);
recorder.setFrameRate(30);
recorder.setSampleRate(AUDIO_SAMPLE_RATE);
recorder.setVideoCodec(AV_CODEC_ID_H264);
recorder.setAudioCodec(AV_CODEC_ID_AAC);
代码的此部分显示如何初始化称为记录器的FFmpegFrameRecorder对象。 该对象将捕获并编码从摄像机获得的帧和从麦克风获得的样本。
如果要在同一Android应用中捕获预览,则需要实现CameraPreview类,该类将转换从Camera提供的原始数据,并将为FFmpegFrameRecorder创建Preview和Frame。
切记将ip_destination替换为要向其发送流的PC或设备的ip。 例如,端口可以是8080。
@Override
public Mat onCameraFrame(Mat mat)
{
if (audioRecordRunnable == null) {
startTime = System.currentTimeMillis();
return mat;
}
if (recording && mat != null) {
synchronized (semaphore) {
try {
Frame frame = converterToMat.convert(mat);
long t = 1000 * (System.currentTimeMillis() - startTime);
if (t > recorder.getTimestamp()) {
recorder.setTimestamp(t);
}
recorder.record(frame);
} catch (FFmpegFrameRecorder.Exception e) {
LogHelper.i(TAG, e.getMessage());
e.printStackTrace();
}
}
}
return mat;
}
此方法显示onCameraFrame
方法的实现,该方法从相机获取Mat(图片),并将其转换为Frame并由FFmpegFrameRecorder对象记录。
@Override
public void onSampleReady(ShortBuffer audioData)
{
if (recorder == null) return;
if (recording && audioData == null) return;
try {
long t = 1000 * (System.currentTimeMillis() - startTime);
if (t > recorder.getTimestamp()) {
recorder.setTimestamp(t);
}
LogHelper.e(TAG, "audioData: " + audioData);
recorder.recordSamples(audioData);
} catch (FFmpegFrameRecorder.Exception e) {
LogHelper.v(TAG, e.getMessage());
e.printStackTrace();
}
}
与音频相同, audioData
是一个ShortBuffer
对象,它将由FFmpegFrameRecorder记录。
在PC或设备目标中,您可以运行以下命令以获取流。
ffplay udp://ip_source:port
ip_source
是正在传输摄像头和麦克风流的智能手机的ip。 端口必须与8080相同。
我在github存储库中创建了一个解决方案: UDPAVStreamer 。
祝好运
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.