| | |
| | | private static final String TAG = "H264EncodeService"; |
| | | |
| | | private H264Encoder h264Encoder; |
| | | private H264FileTransmitter h264FileTransmitter; // H264文件传输器 |
| | | private String outputFileDirectory; // H264文件输出目录 |
| | | |
| | | // 默认编码参数 |
| | |
| | | super.onDestroy(); |
| | | Log.d(TAG, "Service destroyed"); |
| | | |
| | | // 停止并释放编码器 |
| | | // 停止并释放编码器和文件传输器 |
| | | stopEncoder(); |
| | | stopFileTransmitter(); |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | /** |
| | | * 控制H264编码 |
| | | * @param action 操作类型:0-开启h264文件写入,1-停止h264编码并停止写入文件,2-开启网络推送h264(不写入文件),3-停止h264编码并停止网络推送 |
| | | * @param jsonConfig JSON格式的配置参数,包含:ip、port、width、height、framerate、simPhone |
| | | * 文件传输配置类 |
| | | */ |
| | | private static class FileTransmitConfig { |
| | | String ip; |
| | | int port; |
| | | int framerate; |
| | | String simPhone; |
| | | String filePath; // H264文件路径 |
| | | int protocolType; // 协议类型:1-UDP,2-TCP |
| | | |
| | | // 从JSON解析配置 |
| | | static FileTransmitConfig fromJson(String jsonConfig) throws JSONException { |
| | | FileTransmitConfig config = new FileTransmitConfig(); |
| | | if (jsonConfig == null || jsonConfig.trim().isEmpty()) { |
| | | throw new JSONException("File transmit config cannot be empty"); |
| | | } |
| | | |
| | | JSONObject json = new JSONObject(jsonConfig); |
| | | config.ip = json.optString("ip", null); |
| | | config.port = json.optInt("port", 0); |
| | | config.framerate = json.optInt("framerate", DEFAULT_FRAME_RATE); |
| | | config.simPhone = json.optString("simPhone", "013120122580"); |
| | | config.filePath = json.optString("filePath", null); |
| | | // 协议类型:默认TCP(2),1-UDP,2-TCP |
| | | config.protocolType = json.optInt("protocolType", JT1076ProtocolHelper.PROTOCOL_TYPE_TCP); |
| | | |
| | | return config; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 控制H264编码和文件传输 |
| | | * @param action 操作类型: |
| | | * 0-开启h264文件写入, |
| | | * 1-停止h264编码并停止写入文件, |
| | | * 2-开启网络推送h264(不写入文件), |
| | | * 3-停止h264编码并停止网络推送, |
| | | * 4-开始传输H264文件(从文件读取并网络推送), |
| | | * 5-停止H264文件传输 |
| | | * @param jsonConfig JSON格式的配置参数 |
| | | * action 0/2: 包含:ip、port、width、height、framerate、simPhone |
| | | * action 4: 包含:ip、port、framerate、simPhone、filePath、protocolType(可选,1-UDP,2-TCP,默认TCP) |
| | | * action 1/3/5: 此参数可为空或null |
| | | * @return 0-成功,1-失败 |
| | | */ |
| | | private synchronized int controlEncode(int action, String jsonConfig) { |
| | | Log.d(TAG, "controlEncode called with action: " + action + ", jsonConfig: " + jsonConfig); |
| | | |
| | | try { |
| | | EncodeConfig config = null; |
| | | |
| | | // 对于停止操作,不需要解析配置 |
| | | if (action != 1 && action != 3) { |
| | | try { |
| | | config = EncodeConfig.fromJson(jsonConfig); |
| | | Log.d(TAG, "Parsed config - width: " + config.width + ", height: " + config.height + |
| | | ", framerate: " + config.framerate + ", ip: " + config.ip + ", port: " + config.port + |
| | | ", simPhone: " + config.simPhone); |
| | | } catch (JSONException e) { |
| | | Log.e(TAG, "Failed to parse JSON config: " + jsonConfig, e); |
| | | return 1; // 失败 |
| | | } |
| | | } |
| | | |
| | | switch (action) { |
| | | case 0: // 开启h264文件写入 |
| | | return startFileEncode(config); |
| | | try { |
| | | EncodeConfig config0 = EncodeConfig.fromJson(jsonConfig); |
| | | return startFileEncode(config0); |
| | | } catch (JSONException e) { |
| | | Log.e(TAG, "Failed to parse JSON config: " + jsonConfig, e); |
| | | return 1; |
| | | } |
| | | |
| | | case 1: // 停止h264编码并停止写入文件 |
| | | return stopEncoder(); |
| | | |
| | | case 2: // 开启网络推送h264(不写入文件) |
| | | return startNetworkEncode(config); |
| | | try { |
| | | EncodeConfig config2 = EncodeConfig.fromJson(jsonConfig); |
| | | return startNetworkEncode(config2); |
| | | } catch (JSONException e) { |
| | | Log.e(TAG, "Failed to parse JSON config: " + jsonConfig, e); |
| | | return 1; |
| | | } |
| | | |
| | | case 3: // 停止h264编码并停止网络推送 |
| | | return stopEncoder(); |
| | | |
| | | case 4: // 开始传输H264文件 |
| | | try { |
| | | FileTransmitConfig config4 = FileTransmitConfig.fromJson(jsonConfig); |
| | | return startFileTransmit(config4); |
| | | } catch (JSONException e) { |
| | | Log.e(TAG, "Failed to parse JSON config: " + jsonConfig, e); |
| | | return 1; |
| | | } |
| | | |
| | | case 5: // 停止H264文件传输 |
| | | return stopFileTransmitter(); |
| | | |
| | | default: |
| | | Log.e(TAG, "Unknown action: " + action); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 启动文件传输模式(从H264文件读取并网络推送) |
| | | */ |
| | | private int startFileTransmit(FileTransmitConfig config) { |
| | | Log.d(TAG, "Starting file transmit mode"); |
| | | |
| | | // 如果文件传输器已经在运行,先停止 |
| | | if (h264FileTransmitter != null) { |
| | | Log.w(TAG, "File transmitter is already running, stopping it first"); |
| | | stopFileTransmitter(); |
| | | } |
| | | |
| | | // 检查必需的配置参数 |
| | | if (config == null || config.ip == null || config.ip.trim().isEmpty() || config.port <= 0) { |
| | | Log.e(TAG, "File transmit requires valid ip and port in config"); |
| | | return 1; // 失败 |
| | | } |
| | | |
| | | if (config.filePath == null || config.filePath.trim().isEmpty()) { |
| | | Log.e(TAG, "File transmit requires valid filePath in config"); |
| | | return 1; // 失败 |
| | | } |
| | | |
| | | try { |
| | | // 检查文件是否存在 |
| | | File file = new File(config.filePath); |
| | | if (!file.exists() || !file.isFile()) { |
| | | Log.e(TAG, "File does not exist: " + config.filePath); |
| | | return 1; // 失败 |
| | | } |
| | | |
| | | // 创建文件传输器 |
| | | h264FileTransmitter = new H264FileTransmitter(); |
| | | |
| | | // 设置服务器地址 |
| | | h264FileTransmitter.setServerAddress(config.ip, config.port); |
| | | |
| | | // 设置协议类型 |
| | | h264FileTransmitter.setProtocolType(config.protocolType); |
| | | |
| | | // 设置协议参数(SIM卡号和逻辑通道号) |
| | | String simPhone = config.simPhone != null && !config.simPhone.trim().isEmpty() |
| | | ? config.simPhone : "013120122580"; |
| | | h264FileTransmitter.setProtocolParams(simPhone, (byte)1); |
| | | |
| | | // 设置帧率(用于计算时间戳间隔) |
| | | int framerate = config.framerate > 0 ? config.framerate : DEFAULT_FRAME_RATE; |
| | | h264FileTransmitter.setFrameRate(framerate); |
| | | |
| | | // 设置进度回调(可选,用于日志输出) |
| | | h264FileTransmitter.setOnTransmitProgressCallback(new H264FileTransmitter.OnTransmitProgressCallback() { |
| | | @Override |
| | | public void onProgress(int currentFrame, int totalFrames) { |
| | | Log.d(TAG, "File transmit progress: frame " + currentFrame + |
| | | (totalFrames > 0 ? " of " + totalFrames : "")); |
| | | } |
| | | |
| | | @Override |
| | | public void onComplete() { |
| | | Log.d(TAG, "File transmit completed"); |
| | | } |
| | | |
| | | @Override |
| | | public void onError(String error) { |
| | | Log.e(TAG, "File transmit error: " + error); |
| | | } |
| | | }); |
| | | |
| | | // 初始化Socket连接 |
| | | if (!h264FileTransmitter.initialize()) { |
| | | Log.e(TAG, "Failed to initialize file transmitter socket"); |
| | | h264FileTransmitter = null; |
| | | return 1; // 失败 |
| | | } |
| | | |
| | | // 开始传输文件 |
| | | h264FileTransmitter.transmitFile(config.filePath); |
| | | |
| | | Log.d(TAG, "File transmit started successfully, file: " + config.filePath + |
| | | ", server: " + config.ip + ":" + config.port + |
| | | ", protocol: " + (config.protocolType == JT1076ProtocolHelper.PROTOCOL_TYPE_UDP ? "UDP" : "TCP") + |
| | | ", framerate: " + framerate); |
| | | return 0; // 成功 |
| | | |
| | | } catch (Exception e) { |
| | | Log.e(TAG, "Failed to start file transmit", e); |
| | | if (h264FileTransmitter != null) { |
| | | try { |
| | | h264FileTransmitter.stop(); |
| | | } catch (Exception ex) { |
| | | Log.e(TAG, "Error stopping file transmitter after failure", ex); |
| | | } |
| | | h264FileTransmitter = null; |
| | | } |
| | | return 1; // 失败 |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 停止文件传输器 |
| | | */ |
| | | private int stopFileTransmitter() { |
| | | Log.d(TAG, "Stopping file transmitter"); |
| | | |
| | | if (h264FileTransmitter != null) { |
| | | try { |
| | | h264FileTransmitter.stop(); |
| | | h264FileTransmitter = null; |
| | | Log.d(TAG, "File transmitter stopped successfully"); |
| | | return 0; // 成功 |
| | | } catch (Exception e) { |
| | | Log.e(TAG, "Error stopping file transmitter", e); |
| | | h264FileTransmitter = null; |
| | | return 1; // 失败 |
| | | } |
| | | } else { |
| | | Log.w(TAG, "File transmitter is not running"); |
| | | return 0; // 成功(没有运行的文件传输器,视为成功) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取资源列表(根据JT/T 1076-2016表23定义) |
| | | * @param startTime 开始时间(格式:YYMMDDHHmmss) |
| | | * @param endTime 结束时间(格式:YYMMDDHHmmss) |