我真的很想在Java fx项目上播放视频流。
-简短版本:
我正在将h264 / avcc风味视频从Android手机流式传输到台式计算机。但是,javafx没有显示流的简单解决方案。我正在尝试使用javacv / ffmpeg来使其正常工作。但是我从ffmpeg收到错误消息。
1)是否有更好的方法在javafx上显示流式视频?
2)您是否有Javacv ffmpegframegrabber的示例项目或良好教程?
3)我想我可能在mycode中缺少一些小细节,但是我不确定我会是什么。
-较长版本:
1)在android端,我正在使用mediarecorder获取视频。为了获取sps / pps信息,我记录并保存了一个小电影到设备,然后解析sps和pps数据。
2)接下来,在android上,我将纳尔分解成MTU req并通过udp连接将它们发送到我的桌面上
3)在我的桌面上,我重新组装了纳尔纳斯(如果它们丢失了数据,则将它们丢弃),并将其馈送到我提供给framegreabber构造函数的输入流中。
-代码和日志:
根据我所喂食的口味,错误会很长而且很多。这是两个单独的示例,通常会重复很长的时间
[h264 @ 0000020225907a40] non-existing PPS 0 referenced
[h264 @ 0000020225907a40] decode_slice_header error
[h264 @ 0000020225907a40] no frame!
[h264 @ 00000163d8637a40] illegal aspect ratio
[h264 @ 00000163d8637a40] pps_id 3412 out of range
[AVBSFContext @ 00000163e28a0e00] Invalid NAL unit 0, skipping.
!我知道的一个重要警告是,我尚未实现时间戳 我在喂ffmpeg时在android设备上创建的。我认为,尽管如此,它仍然应该显示失真的图像
因为我花了一整天的时间进行猜测,并尝试着掌握一些“风味”的数据。我只展示了每个nal的第一部分,我相信只要我的sps和pps是正确的,如果正确就至少会显示垃圾图像
sps: 67 80 80 1E E9 01 68 22 FD C0 36 85 09 A8
pps: 68 06 06 E2
下面是附件B样式。 这些都分别以00 00 01和00 00 00 01开头
Debug transfer 65 B8 40 0B E5 B8 7B 80 5B 85
Debug transfer 41 E2 20 7A 74 34 3B D6 BE FA
Debug transfer 41 E4 40 2F 01 E0 0C 06 EE 91
Debug transfer 41 E6 60 3E A1 20 5A 02 3C 6D
Debug transfer 41 E8 80 13 B0 B9 82 C3 03 F4
Debug transfer 41 EC C0 1B A3 0C 28 F1 B0 C8
Debug transfer 41 EE E0 1F CE 07 30 EE 05 06
Debug transfer 41 F1 00 08 ED 80 9C 20 09 73
Debug transfer 41 F3 20 09 E9 00 86 60 21 C3
VideoDecoderaddPacket type: 24
Debug transfer 67 80 80 1E E9 01 68 22 FD C0
Debug transfer 68 06 06 E2
Debug transfer 65 B8 20 00 9F 80 78 00 12 8A
Debug transfer 41 E2 20 09 F0 1E 40 7B 0C E0
Debug transfer 41 E4 40 09 F0 29 30 D6 00 AE
Debug transfer 41 E6 60 09 F1 48 31 80 99 40
[h264 @ 000001c771617a40] non-existing PPS 0 referenced
在这里,我尝试了Avcc样式。您可以看到第一行是sps pps的组合,后跟idr,然后重复出现非idr
Debug transfer 18 00 0E 67 80 80 1E E9 01 68
Debug transfer 00 02 4A 8F 65 B8 20 00 9F C5
Debug transfer 00 02 2F DA 41 E2 20 09 E8 0F
Debug transfer 00 02 2C 34 41 E4 40 09 F4 20
Debug transfer 00 02 4D 92 41 E6 60 09 FC 2B
Debug transfer 00 02 47 02 41 E8 80 09 F0 72
Debug transfer 00 02 52 50 41 EA A0 09 EC 0F
Debug transfer 00 02 58 8A 41 EC C0 09 FC 6F
Debug transfer 00 02 55 F9 41 EE E0 09 FC 6E
Debug transfer 00 02 4D 79 41 F1 00 09 F0 3E
Debug transfer 00 02 4D B6 41 F3 20 09 E8 64
以下类是我尝试获取javacv / ffmpeg来显示视频的地方。我认为这不是理想的解决方案,因此我正在研究canvas替代图像视图的方法。
public class ImageDecoder {
private final static String TAG = "ImageDecoder ";
private ImageDecoder(){
}
public static void streamImageToImageView(
final ImageView view,
final InputStream inputStream,
final String format,
final int frameRate,
final int bitrate,
final String preset,
final int numBuffers
)
{
System.out.println("Image Decoder Starting...");
try( final FrameGrabber grabber = new
FFmpegFrameGrabber(inputStream))
{
final Java2DFrameConverter converter = new Java2DFrameConverter();
grabber.setFrameNumber(frameRate);
grabber.setFormat(format);
grabber.setVideoBitrate(bitrate);
grabber.setVideoOption("preset", preset);
grabber.setNumBuffers(numBuffers);
System.out.println("Image Decoder waiting on grabber.start...");
grabber.start(); //---- this call is blocking the loop
System.out.println("Image Decoder Looping---------------------------
-------- hit stop");
while(!Thread.interrupted()){
//System.out.println("Image Decoder Looping");
final Frame frame = grabber.grab();
if (frame != null){
final BufferedImage bufferedImage =
converter.convert(frame);
if (bufferedImage != null){
Platform.runLater(() ->
view.setImage(SwingFXUtils.toFXImage(bufferedImage, null)));
}else{
System.out.println("no buf im");
}
}else{
System.out.println("no fr");
Thread.currentThread().interrupt();
}
}
}catch (Exception e){
System.out.print(TAG + e);
}
}
}
任何帮助将不胜感激。
答案 0 :(得分:0)
所以我有两个问题。
首先是我的sps pps解析方法有错误。注意第二和第三字节相同
第二个原因是我不小心使缓冲区过大,并创建了较大的0x00填充区域来模拟起始代码。
对我来说,这是一个很大的项目,我想帮助其他人。请访问我的网站,在该网站上我写了冗长的关于流媒体h264的多部分讨论。