Dana
2025-12-01 ccf7a1f19b5c6276178c72609c88d057214c8239
app/src/main/java/com/anyun/h264/H264EncodeService.java
@@ -4,7 +4,7 @@
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import timber.log.Timber;
import com.anyun.h264.model.ResourceInfo;
@@ -56,22 +56,22 @@
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "H264EncodeService created");
        Timber.d("H264EncodeService created");
        
        // 初始化输出文件目录(使用应用外部存储目录)
        outputFileDirectory = getExternalFilesDir(null).getAbsolutePath();
        Log.d(TAG, "Output file directory: " + outputFileDirectory);
        Timber.d("Output file directory: %s", outputFileDirectory);
    }
    
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "Service bound");
        Timber.d("Service bound");
        return binder;
    }
    
    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "Service unbound");
        Timber.d("Service unbound");
        // 不自动停止编码器,让它在服务中保持运行
        return super.onUnbind(intent);
    }
@@ -79,7 +79,7 @@
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "Service destroyed");
        Timber.d("Service destroyed");
        
        // 停止并释放编码器和文件传输器
        stopEncoder();
@@ -170,7 +170,7 @@
     * @return 0-成功,1-失败
     */
    private synchronized int controlEncode(int action, String jsonConfig) {
        Log.d(TAG, "controlEncode called with action: " + action + ", jsonConfig: " + jsonConfig);
        Timber.d("controlEncode called with action: %d, jsonConfig: %s", action, jsonConfig);
        
        try {
            switch (action) {
@@ -179,7 +179,7 @@
                        EncodeConfig config0 = EncodeConfig.fromJson(jsonConfig);
                        return startFileEncode(config0);
                    } catch (JSONException e) {
                        Log.e(TAG, "Failed to parse JSON config: " + jsonConfig, e);
                        Timber.e(e, "Failed to parse JSON config: %s", jsonConfig);
                        return 1;
                    }
                    
@@ -191,7 +191,7 @@
                        EncodeConfig config2 = EncodeConfig.fromJson(jsonConfig);
                        return startNetworkEncode(config2);
                    } catch (JSONException e) {
                        Log.e(TAG, "Failed to parse JSON config: " + jsonConfig, e);
                        Timber.e(e, "Failed to parse JSON config: %s", jsonConfig);
                        return 1;
                    }
                    
@@ -203,7 +203,7 @@
                        FileTransmitConfig config4 = FileTransmitConfig.fromJson(jsonConfig);
                        return startFileTransmit(config4);
                    } catch (JSONException e) {
                        Log.e(TAG, "Failed to parse JSON config: " + jsonConfig, e);
                        Timber.e(e, "Failed to parse JSON config: %s", jsonConfig);
                        return 1;
                    }
                    
@@ -211,11 +211,11 @@
                    return stopFileTransmitter();
                    
                default:
                    Log.e(TAG, "Unknown action: " + action);
                    Timber.e("Unknown action: %d", action);
                    return 1; // 失败
            }
        } catch (Exception e) {
            Log.e(TAG, "Error in controlEncode", e);
            Timber.e(e, "Error in controlEncode");
            return 1; // 失败
        }
    }
@@ -224,11 +224,11 @@
     * 启动文件编码模式(只写入文件,不进行网络推送)
     */
    private int startFileEncode(EncodeConfig config) {
        Log.d(TAG, "Starting file encode mode");
        Timber.d("Starting file encode mode");
        
        // 如果编码器已经在运行,先停止
        if (h264Encoder != null) {
            Log.w(TAG, "Encoder is already running, stopping it first");
            Timber.w("Encoder is already running, stopping it first");
            stopEncoder();
        }
        
@@ -245,7 +245,7 @@
            long timeFile = System.currentTimeMillis();
            SimpleDateFormat bcdFormat = new SimpleDateFormat("yyMMddHHmmss");
            String str = bcdFormat.format(timeFile);
            Log.i(TAG,"文件名:"+str);
            Timber.i("文件名:%s", str);
            // 设置输出文件
            String fileName = "h264_" + timeFile+ ".h264";
            File outputFile = new File(outputFileDirectory, fileName);
@@ -259,16 +259,16 @@
            int[] resolution = {width, height};
            if (h264Encoder.initialize(DEFAULT_CAMERA_ID_RANGE, null, resolution, false)) {
                h264Encoder.start();
                Log.d(TAG, "File encode started successfully, output file: " + outputFile.getAbsolutePath() +
                        ", resolution: " + width + "x" + height + ", framerate: " + framerate);
                Timber.d("File encode started successfully, output file: %s, resolution: %dx%d, framerate: %d",
                        outputFile.getAbsolutePath(), width, height, framerate);
                return 0; // 成功
            } else {
                Log.e(TAG, "Failed to initialize encoder");
                Timber.e("Failed to initialize encoder");
                h264Encoder = null;
                return 1; // 失败
            }
        } catch (Exception e) {
            Log.e(TAG, "Failed to start file encode", e);
            Timber.e(e, "Failed to start file encode");
            h264Encoder = null;
            return 1; // 失败
        }
@@ -278,17 +278,17 @@
     * 启动网络推送模式(只进行网络推送,不写入文件)
     */
    private int startNetworkEncode(EncodeConfig config) {
        Log.d(TAG, "Starting network encode mode");
        Timber.d("Starting network encode mode");
        
        // 如果编码器已经在运行,先停止
        if (h264Encoder != null) {
            Log.w(TAG, "Encoder is already running, stopping it first");
            Timber.w("Encoder is already running, stopping it first");
            stopEncoder();
        }
        
        // 检查必需的配置参数
        if (config == null || config.ip == null || config.ip.trim().isEmpty() || config.port <= 0) {
            Log.e(TAG, "Network encode requires valid ip and port in config");
            Timber.e("Network encode requires valid ip and port in config");
            return 1; // 失败
        }
        
@@ -321,16 +321,16 @@
            int[] resolution = {width, height};
            if (h264Encoder.initialize(DEFAULT_CAMERA_ID_RANGE, null, resolution, false)) {
                h264Encoder.start();
                Log.d(TAG, "Network encode started successfully, server: " + config.ip + ":" + config.port +
                        ", resolution: " + width + "x" + height + ", framerate: " + framerate);
                Timber.d("Network encode started successfully, server: %s:%d, resolution: %dx%d, framerate: %d",
                        config.ip, config.port, width, height, framerate);
                return 0; // 成功
            } else {
                Log.e(TAG, "Failed to initialize encoder");
                Timber.e("Failed to initialize encoder");
                h264Encoder = null;
                return 1; // 失败
            }
        } catch (Exception e) {
            Log.e(TAG, "Failed to start network encode", e);
            Timber.e(e, "Failed to start network encode");
            h264Encoder = null;
            return 1; // 失败
        }
@@ -340,22 +340,22 @@
     * 停止编码器
     */
    private int stopEncoder() {
        Log.d(TAG, "Stopping encoder");
        Timber.d("Stopping encoder");
        
        if (h264Encoder != null) {
            try {
                h264Encoder.stop();
                h264Encoder.release();
                h264Encoder = null;
                Log.d(TAG, "Encoder stopped successfully");
                Timber.d("Encoder stopped successfully");
                return 0; // 成功
            } catch (Exception e) {
                Log.e(TAG, "Error stopping encoder", e);
                Timber.e(e, "Error stopping encoder");
                h264Encoder = null;
                return 1; // 失败
            }
        } else {
            Log.w(TAG, "Encoder is not running");
            Timber.w("Encoder is not running");
            return 0; // 成功(没有运行的编码器,视为成功)
        }
    }
@@ -364,22 +364,22 @@
     * 启动文件传输模式(从H264文件读取并网络推送)
     */
    private int startFileTransmit(FileTransmitConfig config) {
        Log.d(TAG, "Starting file transmit mode");
        Timber.d("Starting file transmit mode");
        
        // 如果文件传输器已经在运行,先停止
        if (h264FileTransmitter != null) {
            Log.w(TAG, "File transmitter is already running, stopping it first");
            Timber.w("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");
            Timber.e("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");
            Timber.e("File transmit requires valid filePath in config");
            return 1; // 失败
        }
        
@@ -387,7 +387,7 @@
            // 检查文件是否存在
            File file = new File(config.filePath);
            if (!file.exists() || !file.isFile()) {
                Log.e(TAG, "File does not exist: " + config.filePath);
                Timber.e("File does not exist: %s", config.filePath);
                return 1; // 失败
            }
            
@@ -413,24 +413,24 @@
            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 : ""));
                    Timber.d("File transmit progress: frame %d%s", currentFrame,
                            totalFrames > 0 ? " of " + totalFrames : "");
                }
                
                @Override
                public void onComplete() {
                    Log.d(TAG, "File transmit completed");
                    Timber.d("File transmit completed");
                }
                
                @Override
                public void onError(String error) {
                    Log.e(TAG, "File transmit error: " + error);
                    Timber.e("File transmit error: %s", error);
                }
            });
            
            // 初始化Socket连接
            if (!h264FileTransmitter.initialize()) {
                Log.e(TAG, "Failed to initialize file transmitter socket");
                Timber.e("Failed to initialize file transmitter socket");
                h264FileTransmitter = null;
                return 1; // 失败
            }
@@ -438,19 +438,18 @@
            // 开始传输文件
            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);
            Timber.d("File transmit started successfully, file: %s, server: %s:%d, protocol: %s, framerate: %d",
                    config.filePath, config.ip, config.port,
                    config.protocolType == JT1076ProtocolHelper.PROTOCOL_TYPE_UDP ? "UDP" : "TCP", framerate);
            return 0; // 成功
            
        } catch (Exception e) {
            Log.e(TAG, "Failed to start file transmit", e);
            Timber.e(e, "Failed to start file transmit");
            if (h264FileTransmitter != null) {
                try {
                    h264FileTransmitter.stop();
                } catch (Exception ex) {
                    Log.e(TAG, "Error stopping file transmitter after failure", ex);
                    Timber.e(ex, "Error stopping file transmitter after failure");
                }
                h264FileTransmitter = null;
            }
@@ -462,21 +461,21 @@
     * 停止文件传输器
     */
    private int stopFileTransmitter() {
        Log.d(TAG, "Stopping file transmitter");
        Timber.d("Stopping file transmitter");
        
        if (h264FileTransmitter != null) {
            try {
                h264FileTransmitter.stop();
                h264FileTransmitter = null;
                Log.d(TAG, "File transmitter stopped successfully");
                Timber.d("File transmitter stopped successfully");
                return 0; // 成功
            } catch (Exception e) {
                Log.e(TAG, "Error stopping file transmitter", e);
                Timber.e(e, "Error stopping file transmitter");
                h264FileTransmitter = null;
                return 1; // 失败
            }
        } else {
            Log.w(TAG, "File transmitter is not running");
            Timber.w("File transmitter is not running");
            return 0; // 成功(没有运行的文件传输器,视为成功)
        }
    }
@@ -488,7 +487,7 @@
     * @return 资源列表
     */
    private List<ResourceInfo> getResourceList(String startTime, String endTime) {
        Log.d(TAG, "getResourceList called, startTime: " + startTime + ", endTime: " + endTime);
        Timber.d("getResourceList called, startTime: %s, endTime: %s", startTime, endTime);
        
        List<ResourceInfo> resourceList = new ArrayList<>();
        
@@ -496,13 +495,13 @@
            // 扫描输出目录中的H264文件
            File dir = new File(outputFileDirectory);
            if (!dir.exists() || !dir.isDirectory()) {
                Log.w(TAG, "Output directory does not exist: " + outputFileDirectory);
                Timber.w("Output directory does not exist: %s", outputFileDirectory);
                return resourceList;
            }
            
            File[] files = dir.listFiles((dir1, name) -> name.toLowerCase().endsWith(".h264"));
            if (files == null || files.length == 0) {
                Log.d(TAG, "No H264 files found in directory");
                Timber.d("No H264 files found in directory");
                return resourceList;
            }
            
@@ -511,7 +510,7 @@
            Date endDate = parseTime(endTime);
            
            if (startDate == null || endDate == null) {
                Log.e(TAG, "Invalid time format, startTime: " + startTime + ", endTime: " + endTime);
                Timber.e("Invalid time format, startTime: %s, endTime: %s", startTime, endTime);
                return resourceList;
            }
            
@@ -523,11 +522,11 @@
                }
            }
            
            Log.d(TAG, "Found " + resourceList.size() + " resources in time range");
            Timber.d("Found %d resources in time range", resourceList.size());
            return resourceList;
            
        } catch (Exception e) {
            Log.e(TAG, "Error getting resource list", e);
            Timber.e(e, "Error getting resource list");
            return resourceList;
        }
    }
@@ -578,7 +577,7 @@
            return resourceInfo;
            
        } catch (Exception e) {
            Log.e(TAG, "Error creating resource info from file: " + file.getName(), e);
            Timber.e(e, "Error creating resource info from file: %s", file.getName());
            return null;
        }
    }
@@ -597,7 +596,7 @@
            SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss", Locale.CHINA);
            return format.parse(timeStr);
        } catch (ParseException e) {
            Log.e(TAG, "Failed to parse time: " + timeStr, e);
            Timber.e(e, "Failed to parse time: %s", timeStr);
            return null;
        }
    }