| | |
| | | |
| | | import com.anyun.h264.model.ResourceInfo; |
| | | import com.anyun.h264.model.WatermarkInfo; |
| | | import com.anyun.h264.util.FileUtil; |
| | | |
| | | import org.json.JSONException; |
| | | import org.json.JSONObject; |
| | |
| | | * 编码配置类 |
| | | */ |
| | | private static class EncodeConfig { |
| | | boolean useTFCard=true;//如果为true,则在tfcard 根目录建一个h264文件夹,在h264目录下以当前日期为名字的文件夹(比如20250123),然后h264文件就写入以当前日前为名字的目录下 |
| | | boolean enableFileOutput; //是否开启h264文件写入 |
| | | boolean enableNetworkTransmit; //开启h264,网络实时推流 |
| | | String ip; |
| | |
| | | config.port = 0; |
| | | config.simPhone = null; |
| | | config.cameraId = 1; // 默认使用第一个摄像头 |
| | | config.useTFCard = false; // 默认不使用TF卡 |
| | | return config; |
| | | } |
| | | |
| | |
| | | config.ip = json.optString("ip", null); |
| | | config.port = json.optInt("port", 0); |
| | | config.simPhone = json.optString("simPhone", null); |
| | | config.useTFCard = json.optBoolean("useTFCard", false); |
| | | |
| | | // 解析cameraId(如果未指定,默认为1) |
| | | if (json.has("cameraId")) { |
| | |
| | | } |
| | | |
| | | /** |
| | | * 获取输出文件目录(根据useTFCard配置) |
| | | * @param useTFCard 是否使用TF卡 |
| | | * @return 输出目录路径 |
| | | */ |
| | | private String getOutputFileDirectory(boolean useTFCard) { |
| | | if (useTFCard) { |
| | | // 使用TF卡:/sdcard/h264/当前日期/ |
| | | try { |
| | | String storagePath = FileUtil.getStoragePath(this, true); |
| | | if (storagePath == null || storagePath.trim().isEmpty()) { |
| | | Timber.w("TF card storage path not available, fallback to app directory"); |
| | | return outputFileDirectory; |
| | | } |
| | | |
| | | File externalStorage = new File(storagePath); |
| | | if (!externalStorage.exists()) { |
| | | Timber.w("TF card storage directory does not exist: %s, fallback to app directory", storagePath); |
| | | return outputFileDirectory; |
| | | } |
| | | |
| | | // 获取当前日期(格式:yyyyMMdd,如20250123) |
| | | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd", Locale.CHINA); |
| | | String dateDir = dateFormat.format(new Date()); |
| | | |
| | | // 构建路径:/sdcard/h264/20250123/ |
| | | File h264Dir = new File(externalStorage, "h264"); |
| | | File dateDirFile = new File(h264Dir, dateDir); |
| | | |
| | | // 创建目录(如果不存在) |
| | | if (!dateDirFile.exists()) { |
| | | boolean created = dateDirFile.mkdirs(); |
| | | if (!created && !dateDirFile.exists()) { |
| | | Timber.e("Failed to create TF card directory: %s, fallback to app directory", dateDirFile.getAbsolutePath()); |
| | | return outputFileDirectory; |
| | | } |
| | | } |
| | | |
| | | String tfCardPath = dateDirFile.getAbsolutePath(); |
| | | Timber.d("Using TF card directory: %s", tfCardPath); |
| | | return tfCardPath; |
| | | } catch (Exception e) { |
| | | Timber.e(e, "Error getting TF card directory, fallback to app directory"); |
| | | return outputFileDirectory; |
| | | } |
| | | } else { |
| | | // 使用应用外部存储目录 |
| | | return outputFileDirectory; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 启动编码(统一方法,支持文件写入和网络传输的组合) |
| | | * @param config 编码配置 |
| | | * @return 0-成功,1-失败 |
| | |
| | | Timber.e("Encode config cannot be null"); |
| | | return 1; |
| | | } |
| | | Timber.d("Starting encode mode, fileOutput: %b, networkTransmit: %b", |
| | | config.enableFileOutput, config.enableNetworkTransmit); |
| | | Timber.d("Starting encode mode, fileOutput: %b, networkTransmit: %b, useTFCard: %b", |
| | | config.enableFileOutput, config.enableNetworkTransmit, config.useTFCard); |
| | | |
| | | // 如果编码器已经在运行,只更新配置 |
| | | if (h264Encoder != null) { |
| | |
| | | int framerate = config != null && config.framerate > 0 ? config.framerate : DEFAULT_FRAME_RATE; |
| | | h264Encoder.setEncoderParams(width, height, framerate, DEFAULT_BITRATE); |
| | | |
| | | // 获取输出文件目录(根据useTFCard配置) |
| | | String outputDir = getOutputFileDirectory(config.useTFCard); |
| | | |
| | | // 设置输出文件目录(H264Encoder会自动管理文件创建,每分钟一个文件) |
| | | // 使用一个临时文件名来设置目录,H264Encoder会在初始化时创建第一个文件 |
| | | File tempFile = new File(outputFileDirectory, "temp.h264"); |
| | | File tempFile = new File(outputDir, "temp.h264"); |
| | | h264Encoder.setOutputFile(tempFile.getAbsolutePath()); |
| | | h264Encoder.setEnableFileOutput(config.enableFileOutput); |
| | | |