| | |
| | | if (media.getM_screen() != null) { |
| | | resolutionArr[0] = media.getM_screen().getWidth(); |
| | | resolutionArr[1] = media.getM_screen().getHeight(); |
| | | Timber.d("设置分辨率: %dx%d", resolutionArr[0], resolutionArr[1]); |
| | | Timber.d("%s 设置分辨率: %dx%d", getCameraTag(), resolutionArr[0], resolutionArr[1]); |
| | | } |
| | | |
| | | try { |
| | |
| | | } |
| | | |
| | | cameraExists = true; |
| | | Timber.d("USB摄像头打开成功"); |
| | | Timber.d("%s USB摄像头打开成功", getCameraTag()); |
| | | |
| | | notifyCallback(1, 0, "推流线程已启动,等待推流状态就绪"); |
| | | } catch (Exception e) { |
| | | Timber.e(e, "Failed to start push"); |
| | | Timber.e(e, "%s Failed to start push", getCameraTag()); |
| | | notifyCallback(1, -3, "启动推流失败: " + e.getMessage()); |
| | | } |
| | | } |
| | |
| | | * 停止推流 |
| | | */ |
| | | public void stopPush() { |
| | | Timber.d("stopPush called"); |
| | | Timber.d("%s stopPush called", getCameraTag()); |
| | | stopPushThread(); |
| | | // stopAudioTransfer(); |
| | | stopWaterMaskSchedule(); |
| | |
| | | @Override |
| | | public void surfaceCreated(SurfaceHolder holder) { |
| | | try { |
| | | Timber.d("previewSurfaceView surfaceCreated, startPreviewAysnc"); |
| | | Timber.d("%s previewSurfaceView surfaceCreated, startPreviewAysnc", getCameraTag()); |
| | | if (alivcPusher != null) { |
| | | alivcPusher.startPreviewAysnc(previewSurfaceView); |
| | | |
| | |
| | | startPushThread(); |
| | | } |
| | | } catch (Exception e) { |
| | | Timber.e(e, "startPreviewAysnc in surfaceCreated failed"); |
| | | Timber.e(e, "%s startPreviewAysnc in surfaceCreated failed", getCameraTag()); |
| | | notifyCallback(1, -3, "预览启动失败: " + e.getMessage()); |
| | | } |
| | | } |
| | |
| | | // 设置监听器 |
| | | setupListeners(); |
| | | |
| | | Timber.d("AlivcPusher initialized successfully"); |
| | | Timber.d("%s AlivcPusher initialized successfully", getCameraTag()); |
| | | } catch (Exception e) { |
| | | Timber.e(e, "Failed to initialize AlivcPusher"); |
| | | Timber.e(e, "%s Failed to initialize AlivcPusher", getCameraTag()); |
| | | notifyCallback(1, -3, "初始化推流SDK失败: " + e.getMessage()); |
| | | } |
| | | } |
| | |
| | | alivcPusher.setLivePushInfoListener(new AlivcLivePushInfoListener() { |
| | | @Override |
| | | public void onPreviewStarted(AlivcLivePusher alivcLivePusher) { |
| | | Timber.d("onPreviewStarted"); |
| | | Timber.d("%s onPreviewStarted", getCameraTag()); |
| | | mainHandler.postDelayed(()->{ |
| | | // 预览就绪后再启动推流,避免 INIT 状态直接 startPush 报错 |
| | | if (alivcPusher != null && pushUrl != null && !pushUrl.isEmpty()) { |
| | | try { |
| | | AlivcLivePushStats s = alivcPusher.getCurrentStatus(); |
| | | Timber.i("onPreviewStarted, current status=%s", s != null ? s.name() : "null"); |
| | | Timber.d("开始推流: %s", pushUrl); |
| | | Timber.i("%s onPreviewStarted, current status=%s", getCameraTag(), s != null ? s.name() : "null"); |
| | | Timber.d("%s 开始推流: %s", getCameraTag(), pushUrl); |
| | | alivcPusher.startPushAysnc(pushUrl); |
| | | } catch (Exception e) { |
| | | Timber.e(e, "startPushAysnc failed"); |
| | | Timber.e(e, "%s startPushAysnc failed", getCameraTag()); |
| | | notifyCallback(1, -3, "启动推流失败: " + e.getMessage()); |
| | | } |
| | | } |
| | |
| | | |
| | | @Override |
| | | public void onPushStarted(AlivcLivePusher alivcLivePusher) { |
| | | Timber.d("onPushStarted"); |
| | | Timber.d("%s onPushStarted", getCameraTag()); |
| | | pushStarted = true; |
| | | // startAudioTransfer(); |
| | | notifyCallback(1, 0, "推流已开始,分辨率: " + resolutionArr[0] + "x" + resolutionArr[1]); |
| | |
| | | int ret = -1; |
| | | for (int i = 0; i < 3; i++) { |
| | | ret = usbCamera.prepareCamera(cameraIds, cameraName, resolutionArr, ay_encrypt); |
| | | Timber.d("USB摄像头第%d次打开结果: %d, 分辨率: %dx%d", i + 1, ret, resolutionArr[0], resolutionArr[1]); |
| | | Timber.d("%s USB摄像头第%d次打开结果: %d, 分辨率: %dx%d", getCameraTag(), i + 1, ret, resolutionArr[0], resolutionArr[1]); |
| | | if (ret == 0) { |
| | | break; |
| | | } |
| | |
| | | // 成功标准:prepareCamera 返回 0 |
| | | return ret == 0; |
| | | } catch (Exception e) { |
| | | Timber.e(e, "打开USB摄像头异常"); |
| | | Timber.e(e, "%s 打开USB摄像头异常", getCameraTag()); |
| | | return false; |
| | | } |
| | | } |
| | |
| | | isRunning = true; |
| | | pushThread = new PushThread(); |
| | | pushThread.start(); |
| | | Timber.d("Push thread started"); |
| | | Timber.d("%s Push thread started", getCameraTag()); |
| | | } |
| | | } |
| | | |
| | |
| | | @Override |
| | | public void run() { |
| | | super.run(); |
| | | Timber.d("PushThread started"); |
| | | Timber.d("%s PushThread started", getCameraTag()); |
| | | |
| | | try { |
| | | int width = resolutionArr[0]; |
| | |
| | | int bufferSize = width * height * 3 / 2; |
| | | byte[] buffer = new byte[bufferSize]; |
| | | |
| | | Timber.d("开始推送视频数据,分辨率: %dx%d", width, height); |
| | | Timber.d("%s 开始推送视频数据,分辨率: %dx%d", getCameraTag(), width, height); |
| | | |
| | | // 循环处理摄像头数据 |
| | | while (isRunning && cameraExists) { |
| | | // 处理摄像头数据 |
| | | int processResult = usbCamera.processCamera(); |
| | | if (processResult == -1) { |
| | | Timber.w("processCamera返回-1,摄像头可能断开"); |
| | | Timber.w("%s processCamera返回-1,摄像头可能断开", getCameraTag()); |
| | | cameraExists = false; |
| | | notifyCallback(1, -1, "USB摄像头断开"); |
| | | break; |
| | |
| | | 0 // rotation |
| | | ); |
| | | } catch (Exception e) { |
| | | Timber.e(e, "Error pushing frame"); |
| | | Timber.e(e, "%s Error pushing frame", getCameraTag()); |
| | | } |
| | | } else if (!pushStarted) { |
| | | // 等待 onPushStarted 后再喂帧,避免 SDK invalid state |
| | |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | Timber.e(e, "Error in push thread"); |
| | | Timber.e(e, "%s Error in push thread", getCameraTag()); |
| | | cameraExists = false; |
| | | notifyCallback(1, -1, "推流线程异常: " + e.getMessage()); |
| | | } finally { |
| | | Timber.d("PushThread ended"); |
| | | Timber.d("%s PushThread ended", getCameraTag()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取摄像头ID标签,用于日志 |
| | | * @return "[P1]" 或 "[P2]" |
| | | */ |
| | | private String getCameraTag() { |
| | | if (mediaArgu != null) { |
| | | int usbCameraId = mediaArgu.getUsbCameraId(); |
| | | return usbCameraId == 2 ? "[P2]" : "[P1]"; |
| | | } |
| | | return "[P1]"; // 默认 P1 |
| | | } |
| | | |
| | | /** |
| | | * 通知回调 |
| | | */ |
| | | private void notifyCallback(int type, int errCode, String message) { |