开发中遇到个需求是循环播放某个h264视频文件,即后端不断提取
1)首先是视频文件直接提取流定长发送,但会造成花屏。
2)随后利用javacv一帧一帧提取字节数组发送,提取的帧是解码后的数据,内容量很大,不再属于h264编码,所以发送到前端无法解析。
3)读取视频文件,根据001、0001手动截取一帧帧视频流,注意001、0001是每一帧的开头,转发时也要发送出去前端可以解码展示,但是python程序捕获不到帧数据。
4)于是把小于50的信息帧数据跟后续的帧数据进行合并,在获取完整帧后再一起发送。(把视频文件每一帧的大小打印出来,发现有的帧才十几、三十几字节,这些帧要和后面的大帧合并发送,具体的值可以根据自己的实际情况进行估计)
- package com.mf.utils;
-
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.nio.ByteBuffer;
- import java.util.LinkedList;
- import java.util.function.Consumer;
-
- public class VideoHandler {
-
- private static int sleepTime = 40; //控制视频流发送的速度,避免出现视频播放加速的情况
-
- public static void extractFrame(InputStream inputStream, Consumer
callback) throws IOException { - LinkedList
cacheList = new LinkedList<>(); - ByteBuffer byteBuffer = ByteBuffer.allocate(2 * 1024 * 1024);
-
- while (true) {
- int value = inputStream.read();
- if (value == -1) break;
- cacheList.addLast(value);
- if (cacheList.size() < 4) {
- continue;
- }
- if (ishead(cacheList)) break;
- else {
- cacheList.removeFirst();
- }
- }
- cacheList.forEach(temp -> byteBuffer.put((byte) temp.intValue()));
-
- cacheList.clear();
-
- while (true) {
- int value = inputStream.read();
- if (value == -1) break;
- cacheList.addLast(value);
- if (cacheList.size() < 4) {
- continue;
- }
- if (ishead(cacheList)) {
- if(byteBuffer.position() < 50){
- cacheList.forEach(temp -> byteBuffer.put((byte) temp.intValue()));
- cacheList.clear();
- continue;
- }
-
- if (callback != null) {
- callback.accept(byteBuffer);
- }
-
- try {
- Thread.sleep(sleepTime);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
-
- byteBuffer.clear();
- cacheList.forEach(temp -> byteBuffer.put((byte) temp.intValue()));
- cacheList.clear();
- } else {
- byteBuffer.put((byte) cacheList.get(0).intValue());
- cacheList.removeFirst();
- }
- }
-
- cacheList.forEach(temp -> byteBuffer.put((byte) temp.intValue()));
- if (callback != null) {
- callback.accept(byteBuffer);
- }
- }
-
- private static boolean ishead(LinkedList
list) { - if (list.size() !=4) return false;
- int v1 = list.get(0);
- int v2 = list.get(1);
- int v3 = list.get(2);
- int v4 = list.get(3);
- if((v1 == 0 && v2==0 && v3==1) || (v1 == 0 && v2==0 && v3==0 && v4 ==1))
- return true;
- else return false;
- }
-
- public static void main(String[] args) {
- try (FileInputStream inputStream = new FileInputStream("D:\\tmp-data\\1694511149969.h264");){
- extractFrame(inputStream,buffer -> System.out.println(buffer.position()));
- }catch (Exception e){
- System.out.println(e.getMessage());
- }
- }
- }
-