Java 大华SDK问题

如题,Java如何通过官方SDK接口获取大华监控的实时视频流帧,有偿

一般大华的sdk有两种方式,一种是把窗口句柄直接传给sdk,画面直接显示,不用管解码显示,最为方便;另外一种是通过注册回调方法,返回数据流,sdk demo里面均有实现,见General_NetSDK_ChnEng_JAVA_Win64_IS_V3.052.0000002.0.R.201103中RealplayEx:

public void realplay(){
   lRealHandle= netSdk.CLIENT_RealPlayEx(loginHandle, 0, null, 0);
       if(lRealHandle.longValue()!=0){
           System.out.println("realplay success");
           netSdk.CLIENT_SetRealDataCallBackEx(lRealHandle, CbfRealDataCallBackEx.getInstance(),null, 31);
       }
}
/**
   * 实时监视数据回调函数--扩展(pBuffer内存由SDK内部申请释放)
   */
  private static class CbfRealDataCallBackEx implements NetSDKLib.fRealDataCallBackEx {
      private CbfRealDataCallBackEx() {
      }

      private static class CallBackHolder {
          private static CbfRealDataCallBackEx instance = new CbfRealDataCallBackEx();
      }

      public static CbfRealDataCallBackEx getInstance() {
          return CallBackHolder.instance;
      }

@Override
public void invoke(LLong lRealHandle, int dwDataType, Pointer pBuffer,
      int dwBufSize, int param, Pointer dwUser) {
   int bInput=0;
   if(0 != lRealHandle.longValue())
   {
      switch(dwDataType) {
      case 0:
         System.out.println("码流大小为" + dwBufSize + "\n" + "码流类型为原始音视频混合数据");             
         break;
      case 1:
         //标准视频数据
         
         break;
      case 2:
         //yuv 数据
         
         break;
      case 3:
         //pcm 音频数据
         
         break;
      case 4:
         //原始音频数据
         
         break;
      default:
         break;
      }  
   }
}
  }
pBuffer 和 dwBufSize

@Override public void invoke(NetSDKLib.LLong lRealHandle, int dwDataType, Pointer pBuffer, int dwBufSize, int param, Pointer dwUser) { if(0 != lRealHandle.longValue()) { switch(dwDataType) { case 0:

```

```// 原始数据 break; case 1: break; case 2: // yuv 数据 break; case 3: // pcm 音频数据 break; case 4: // 原始音频数据 break; default: // long before = device.getKEEP_ALIVE(); // boolean onLine = new Date().before(new Date(before + Contacts.KEEP_LIVE)); // if ( ! onLine ){ // boolean bRet = LoginModule.netsdk.CLIENT_StopRealPlayEx(lRealHandle); // if(bRet) { // device.getRecordVideo().isExit = true; // log.info("心跳停止,实时预览关闭"); // lRealHandle.setValue(0); // } // } // h264裸码流 if (dwDataType == 1004) { try { this.getOutputStream().write( pBuffer.getByteArray(0,dwBufSize),0,dwBufSize); this.getOutputStream().flush(); } catch (Exception e) { log.error( "管道 h264裸码流 写入失败{}",e.getMessage()); } // } else if (dwDataType == 1005) { // flv流 } break; } } } boolean isConnect = false;

/**
 * 管道流连接和推流操作
 * TODO: 尝试重新连接和推流操作
 */
public void connetAndPush(String rtmpPath, CameraContext device){
    isConnect = false;
    try {
        outputStream.connect(inputStream);
        new Thread(()->{
            while (!isConnect){
                try {

// Device device = AutoRegister.getDevice(lLoginID); // String rtmpPath = ConfigInfo.getRtpmUrl() + device.getUniCam().getCamId(); // RecordVideo.push(rtmpPath,inputStream,1); log.info("推流地址{}",rtmpPath); // 判断是否推流连接成功 isConnect = true; RecordVideo recordVideo = new RecordVideo(); device.setRecordVideo(recordVideo); recordVideo = recordVideo.fromSources(inputStream).to(rtmpPath,1); recordVideo.record();

                    byteArrayOS.close();
                    inputStream.close();
                    log.info("设备{}因断线,拉流推流关闭",device.getUniCam().getCamId());
                } catch (Exception e) {
                    isConnect = false;
                    log.error("连接失败,尝试重新连接{}",e.getMessage());
                }
            }
        }).start();
    } catch (Exception e) {
        log.error( "管道流连接失败{}",e.getMessage());
    }
}

public void startByteArrayReaderThread(){
    new Thread(() -> {
        try {
            while (keepRunning) {
                // 检查流里面的字节数
                if (byteArrayOS.size() > 0) {
                    byte[] buffer = null;
                    synchronized (byteArrayOS) {
                        buffer = byteArrayOS.toByteArray();
                        byteArrayOS.reset(); // 清除缓冲区
                    }
                    // 把提取到的数据发送给PipedOutputStream
                    outputStream.write(buffer, 0, buffer.length);
                } else {
                    // 没有数据可用,线程进入睡眠状态
                    // 每隔1秒查看ByteArrayOutputStream检查新数据
                    Thread.sleep(1000);
                }
            }
        }catch(Exception e) {
            // 记录错误或其他处理
            log.warn("管道流已关闭{}",e.getMessage());
        }
    }).start();
}

public OutputStream getOutputStream() {
    return byteArrayOS;
}
// 管道流通道
private final PipedOutputStream outputStream = new PipedOutputStream();
private boolean keepRunning = true;
private final ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream() {
    public void close() {
        keepRunning = false;
        try {
            super.close();
            outputStream.close();
        } catch(IOException e) {
            // 记录错误或其他处理
            log.error( "output流关闭失败 {}",e.getMessage());
        }
    }
};
private final PipedInputStream inputStream = new PipedInputStream(1024 << 2){
    public void close() {
        keepRunning = false;
        try    {
            super.close();
        } catch(IOException e) {
            // 记录错误或其他处理
            log.error( "output流关闭失败 写入失败{}",e.getMessage());
        }
    }
};

卧槽,乱码了?不知道咋整理。复制出来整理一下

可以参考一下这个博主写的思路实现https://blog.csdn.net/zb95731/article/details/114282803

但是我也卡住一个问题了,就是推流的延时很高10s左右去了,应该是个优化问题