Dana
2025-11-30 90f0e6d751e91206bacde671e950ec6f6d40ef64
1.h264文件以rtp sendPacket  添加到service ,未测试
2个文件已修改
233 ■■■■ 已修改文件
app/src/main/aidl/com/anyun/h264/IH264EncodeService.aidl 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/anyun/h264/H264EncodeService.java 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/aidl/com/anyun/h264/IH264EncodeService.aidl
@@ -8,11 +8,20 @@
 */
interface IH264EncodeService {
    /**
     * 控制H264编码
     * @param action 操作类型:0-开启h264文件写入,1-停止h264编码并停止写入文件,2-开启网络推送h264(不写入文件),3-停止h264编码并停止网络推送
     * @param jsonConfig JSON格式的配置参数,包含:ip(服务器IP)、port(服务器端口)、width(视频宽度)、height(视频高度)、framerate(帧率)、simPhone(SIM卡号)
     *                  示例:{"ip":"192.168.1.100","port":8888,"width":640,"height":480,"framerate":25,"simPhone":"013120122580"}
     *                  如果action为1或3(停止操作),此参数可为空或null
     * 控制H264编码和文件传输
     * @param action 操作类型:
     *               0-开启h264文件写入,
     *               1-停止h264编码并停止写入文件,
     *               2-开启网络推送h264(不写入文件),
     *               3-停止h264编码并停止网络推送,
     *               4-开始传输H264文件(从文件读取并网络推送),
     *               5-停止H264文件传输
     * @param jsonConfig JSON格式的配置参数
     *                  action 0/2: 包含:ip(服务器IP)、port(服务器端口)、width(视频宽度)、height(视频高度)、framerate(帧率)、simPhone(SIM卡号)
     *                          示例:{"ip":"192.168.1.100","port":8888,"width":640,"height":480,"framerate":25,"simPhone":"013120122580"}
     *                  action 4: 包含:ip(服务器IP)、port(服务器端口)、framerate(帧率)、simPhone(SIM卡号)、filePath(H264文件路径)、protocolType(协议类型,可选,1-UDP,2-TCP,默认TCP)
     *                          示例:{"ip":"192.168.1.100","port":8888,"framerate":25,"simPhone":"013120122580","filePath":"/sdcard/video.h264","protocolType":2}
     *                  action 1/3/5: 此参数可为空或null(停止操作不需要配置)
     * @return 0-成功,1-失败
     */
    int controlEncode(int action, String jsonConfig);
app/src/main/java/com/anyun/h264/H264EncodeService.java
@@ -27,6 +27,7 @@
    private static final String TAG = "H264EncodeService";
    
    private H264Encoder h264Encoder;
    private H264FileTransmitter h264FileTransmitter; // H264文件传输器
    private String outputFileDirectory; // H264文件输出目录
    
    // 默认编码参数
@@ -80,8 +81,9 @@
        super.onDestroy();
        Log.d(TAG, "Service destroyed");
        
        // 停止并释放编码器
        // 停止并释放编码器和文件传输器
        stopEncoder();
        stopFileTransmitter();
    }
    
    /**
@@ -122,42 +124,91 @@
    }
    
    /**
     * 控制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);
@@ -310,6 +361,127 @@
    }
    
    /**
     * 启动文件传输模式(从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)