137 timerm cap

本文详细介绍了TMM0模块的初始化过程及中断处理机制,包括时钟配置、寄存器设置、捕获模式配置、中断使能与清除,以及脉冲输出模块初始化。通过具体代码示例,深入解析了定时器的工作原理和操作流程。
#include "bat32g137.h"
#include "userdefine.h"
#include "clk.h"
#include "tmm.h"

/***********************************************************************************************************************
* Function Name: TMM0_Init
* Description  : This function initializes the TMM0 module.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
void TMM0_Init(void)
{
	// 开启时钟
    CGC->PER1 |= CGC_PER1_TMMEN_Msk;     /* enables input clock supply */
	// 匹配后不清除定时器
    TMM->TMSTR |= _04_TMM_TM0_COUNT_CONTINUES;
	// 停止定时器
    TMM->TMSTR &= (uint8_t)~_01_TMM_TM0_COUNT_START;
	// D作为B的缓冲区 
	// C作为A的缓冲区
    TMM->TMMR |= _10_TMM_TMGRC0_BUFFER | _20_TMM_TMGRD0_BUFFER;
	// 时钟源是 FHOCO
    TMM->TMCR0 = _00_TMM_COUNTER_CLEAR_DISABLE | _00_TMM_INETNAL_CLOCK_FCLK_FHOCO;
	// 捕获模式 上升沿
    TMM->TMIORA0 = _40_TMM_TMGRB_CAPTURE | _00_TMM_TMGRB_CAPTURE_RISING | _04_TMM_TMGRA_CAPTURE | _00_TMM_TMGRA_CAPTURE_RISING;
    TMM->TMIORC0 |= _40_TMM_TMGRD_CAPTURE | _04_TMM_TMGRC_CAPTURE;
	// 开启对应的中断
    TMM->TMIER0 = _10_TMM_OVIE_ENABLE | _08_TMM_IMID_ENABLE | _02_TMM_IMIB_ENABLE | _01_TMM_IMIA_ENABLE;
    TMM->TMPOCR0 = _00_TMIOD_OUTPUT_ACTIVE_L | _00_TMIOC_OUTPUT_ACTIVE_L | _00_TMIOB_OUTPUT_ACTIVE_L;
	// 初始化IO为输入模式
 
import os import cv2 import numpy as np import psutil import time import argparse import json from datetime import datetime import logging import signal import sys import traceback import threading import subprocess import gc import queue import concurrent.futures import platform class VideoProcessor: def __init__(self, config): self.config = config self.canceled = False self.start_time = time.time() self.frame_counter = 0 self.progress = 0 self.status = "就绪" self.fps = 0.0 self.mem_usage = 0.0 self.cpu_percent = 0.0 self.system_mem_percent = 0.0 self.system_mem_used = 0.0 self.system_mem_available = 0.0 self.logger = logging.getLogger("VideoProcessor") self.resources = [] # 检测移动环境并应用优化配置 self.is_mobile = self.detect_mobile_environment() if self.is_mobile: self.logger.info("检测到移动环境,启用移动端优化配置") # 覆盖配置为移动端优化值 self.config.setdefault('output_resolution', [640, 360]) self.config.setdefault('queue_size', 3) self.config.setdefault('decoding_threads', 2) self.config.setdefault('use_gpu_processing', False) self.config.setdefault('enable_memory_monitor', False) self.config.setdefault('buffer_size', 1) self.config.setdefault('cuda_streams', 0) self.config.setdefault('reduce_latency', True) self.config.setdefault('mobile_optimized', True) self.config.setdefault('hardware_acceleration', 'mediacodec') self.config.setdefault('target_fps', 24) # 移动端特殊优化:防止后台被杀 self.setup_termux_optimizations() # 多线程队列 self.frame_queue = queue.Queue(maxsize=self.config.get('queue_size', 3)) self.processed_queue = queue.Queue(maxsize=self.config.get('queue_size', 3)) # 注册信号处理 signal.signal(signal.SIGINT, self.signal_handler) signal.signal(signal.SIGTERM, self.signal_handler) def setup_termux_optimizations(self): """设置Termux防杀后台优化""" try: # 防止后台被杀 self.logger.info("设置防止后台被杀优化") subprocess.run(["termux-wake-lock"], check=True) # 设置电池优化白名单 result = subprocess.run(["termux-battery-optimization", "-s"], capture_output=True, text=True) if "already" not in result.stdout: self.logger.info("电池优化白名单设置成功") else: self.logger.info("已在电池优化白名单中") # 设置后台服务保活 subprocess.run(["termux-job-scheduler", "-p", "1000", "-s", "python " + " ".join(sys.argv)], check=True) except Exception as e: self.logger.warning(f"Termux优化设置失败: {str(e)}") print("提示: 请确保已安装Termux:API应用并授予必要权限") def detect_mobile_environment(self): """精准检测移动环境""" try: # Android系统标志 if 'ANDROID_ROOT' in os.environ: return True # Termux特定路径检测 if os.path.exists("/data/data/com.termux/files/usr"): return True # 系统信息检测 uname = os.uname() system = platform.system().lower() if 'linux' in system and 'android' in uname.version.lower(): return True if system == 'darwin' and 'ios' in uname.machine.lower(): return True return False except Exception as e: self.logger.warning(f"移动环境检测失败: {str(e)}") return False def signal_handler(self, signum, frame): """处理中断信号""" self.logger.warning(f"接收到中断信号: {signum}, 正在停止...") self.cancel() sys.exit(1) def start_resource_monitor(self, interval=2): """启动简化的资源监控""" if not self.config.get('enable_memory_monitor', False) or self.is_mobile: return self.monitor_active = True self.monitor_thread = threading.Thread( target=self.monitor_resources, args=(interval,), daemon=True ) self.monitor_thread.start() self.logger.info("资源监控线程已启动") def stop_resource_monitor(self): """停止资源监控""" if hasattr(self, 'monitor_thread') and self.monitor_thread and self.monitor_thread.is_alive(): self.monitor_active = False self.monitor_thread.join(timeout=1.0) self.logger.info("资源监控线程已停止") def monitor_resources(self, interval=2): """简化的资源监控""" self.logger.info("资源监控开始") print("\n资源监控 | 时间戳 | CPU使用率 | 内存使用") print("-" * 50) while self.monitor_active: try: # CPU监控 cpu_percent = psutil.cpu_percent(interval=None) # 内存监控 mem = psutil.virtual_memory() mem_usage = f"{mem.used / (1024**2):.1f}MB/{mem.total / (1024**2):.1f}MB" timestamp = time.strftime('%H:%M:%S') print(f"{timestamp} | {cpu_percent:6.1f}% | {mem_usage}") self.logger.info(f"资源监控 | {timestamp} | CPU: {cpu_percent}% | 内存: {mem_usage}") time.sleep(interval) except Exception as e: self.logger.error(f"资源监控出错: {str(e)}") time.sleep(5) def open_video_with_acceleration(self, file_path): """移动端优化的视频打开方法""" # 移动端优先使用MediaCodec if self.is_mobile: try: self.logger.info("尝试使用Android MediaCodec硬件加速") cap = cv2.VideoCapture(file_path, cv2.CAP_ANDROID) if cap.isOpened(): # 设置移动端优化参数 cap.set(cv2.CAP_PROP_BUFFERSIZE, self.config.get('buffer_size', 1)) cap.set(cv2.CAP_PROP_FPS, self.config.get('target_fps', 24)) self.logger.info("MediaCodec加速成功") self.resources.append(cap) return cap except Exception as e: self.logger.warning(f"MediaCodec加速失败: {str(e)}") # 通用回退方案 self.logger.info("使用软件解码") cap = cv2.VideoCapture(file_path) if cap.isOpened(): self.resources.append(cap) return cap self.logger.error("无法打开视频文件") return None def update_system_stats(self): """更新系统资源统计""" self.cpu_percent = psutil.cpu_percent(interval=0.1) mem = psutil.virtual_memory() self.system_mem_percent = mem.percent self.system_mem_used = mem.used / (1024 ** 2) # MB self.system_mem_available = mem.available / (1024 ** 2) # MB def print_progress(self): """移动端友好的进度显示""" if self.is_mobile: # 简化移动端输出 progress_str = ( f"进度: {self.progress}% | " f"速度: {self.fps:.1f}fps | " f"内存: {self.mem_usage:.1f}MB" ) print(f"\r{progress_str}", end="") else: # 桌面端详细输出 elapsed = time.time() - self.start_time eta = (100 - self.progress) * elapsed / max(1, self.progress) if self.progress > 0 else 0 bar_length = 20 filled_length = int(bar_length * self.progress / 100) bar = '█' * filled_length + '-' * (bar_length - filled_length) progress_str = ( f"进度: |{bar}| {self.progress}% " f"| 速度: {self.fps:.1f}fps " f"| 用时: {elapsed:.1f}s " f"| 剩余: {eta:.1f}s " f"| CPU: {self.cpu_percent:.0f}% " f"| 内存: {self.mem_usage:.1f}MB" ) print(f"\r{progress_str}", end="") self.logger.info(progress_str) def capture_thread(self, cap, total_frames): """视频捕获线程 (生产者)""" frame_idx = 0 while cap.isOpened() and not self.canceled and frame_idx < total_frames: ret, frame = cap.read() if not ret: break # 放入队列,非阻塞方式防止死锁 try: self.frame_queue.put((frame_idx, frame), timeout=0.5) frame_idx += 1 except queue.Full: if self.canceled: break # 移动端更短的等待 time.sleep(0.001 if self.is_mobile else 0.01) # 发送结束信号 self.frame_queue.put((None, None)) self.logger.info(f"捕获线程完成,共捕获 {frame_idx} 帧") def processing_thread(self, output_resolution): """移动端优化的处理线程""" output_width, output_height = output_resolution while not self.canceled: try: # 获取帧,带超时防止死锁 frame_idx, frame = self.frame_queue.get(timeout=1.0) # 结束信号 if frame_idx is None: self.processed_queue.put((None, None)) self.frame_queue.task_done() break # 移动端专用轻量处理 if self.is_mobile: # 内存压力检测 - 跳过处理直接写入原始帧 mem = psutil.virtual_memory() if mem.percent > 85: self.logger.warning("内存压力过高,跳过帧处理") processed_frame = frame else: # 使用快速缩放算法 processed_frame = cv2.resize( frame, (output_width, output_height), interpolation=cv2.INTER_LINEAR ) # 可选: 轻量级图像增强 if self.config.get('mobile_enhance', False): processed_frame = self.mobile_enhance_frame(processed_frame) else: # 桌面端原有处理流程 if output_resolution: processed_frame = cv2.resize(frame, output_resolution) else: processed_frame = frame # 放入已处理队列 self.processed_queue.put((frame_idx, processed_frame), timeout=0.5) self.frame_queue.task_done() # 移动端内存管理 - 定期释放资源 if self.is_mobile and frame_idx % 10 == 0: gc.collect() except queue.Empty: if self.canceled: break except Exception as e: self.logger.error(f"处理线程出错: {str(e)}") self.logger.info("处理线程退出") def mobile_enhance_frame(self, frame): """移动端友好的帧增强""" try: # 使用快速直方图均衡化 lab = cv2.cvtColor(frame, cv2.COLOR_BGR2LAB) l, a, b = cv2.split(lab) clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(4, 4)) limg = clahe.apply(l) enhanced = cv2.merge((limg, a, b)) return cv2.cvtColor(enhanced, cv2.COLOR_LAB2BGR) except: return frame def writer_thread(self, out, total_frames): """移动端优化的写入线程""" frame_idx = 0 last_log_time = time.time() while not self.canceled and frame_idx < total_frames: try: # 获取已处理帧 idx, processed_frame = self.processed_queue.get(timeout=1.0) # 结束信号 if idx is None: break # 写入输出 if processed_frame is not None: out.write(processed_frame) # 更新计数 self.frame_counter += 1 frame_idx += 1 # 计算帧率 elapsed = time.time() - self.start_time self.fps = self.frame_counter / elapsed if elapsed > 0 else 0 # 更新内存使用 process = psutil.Process(os.getpid()) self.mem_usage = process.memory_info().rss / (1024 ** 2) # MB # 更新系统状态 self.update_system_stats() # 更新进度 self.progress = min(100, int(frame_idx * 100 / total_frames)) # 定期打印进度 current_time = time.time() if current_time - last_log_time > 1.0 or frame_idx % 20 == 0: self.print_progress() last_log_time = current_time # 移动端内存管理 if self.is_mobile: # 更频繁的垃圾回收 if frame_idx % 5 == 0: gc.collect() else: # 桌面端内存管理 if frame_idx % 100 == 0: gc.collect() self.processed_queue.task_done() except queue.Empty: if self.canceled: break except Exception as e: self.logger.error(f"写入线程出错: {str(e)}") self.logger.info(f"写入线程完成,共写入 {frame_idx} 帧") def run(self): try: self.status = "处理中..." self.logger.info("视频处理开始") self.start_time = time.time() # 启动资源监控 self.start_resource_monitor() # 打开主视频 self.logger.info("正在打开主视频...") main_cap = self.open_video_with_acceleration(self.config['main_video']) if not main_cap or not main_cap.isOpened(): self.status = "无法打开主视频文件!" self.logger.error(f"无法打开主视频文件: {self.config['main_video']}") return False # 获取主视频信息 main_fps = main_cap.get(cv2.CAP_PROP_FPS) main_width = int(main_cap.get(cv2.CAP_PROP_FRAME_WIDTH)) main_height = int(main_cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) main_total_frames = int(main_cap.get(cv2.CAP_PROP_FRAME_COUNT)) self.logger.info(f"主视频信息: {main_width}x{main_height}@{main_fps:.1f}fps, 总帧数: {main_total_frames}") # 打开副视频 self.logger.info("正在打开副视频...") sub_cap = self.open_video_with_acceleration(self.config['sub_video']) if not sub_cap or not sub_cap.isOpened(): self.status = "无法打开副视频文件!" self.logger.error(f"无法打开副视频文件: {self.config['sub_video']}") return False # 获取副视频信息 sub_fps = sub_cap.get(cv2.CAP_PROP_FPS) sub_width = int(sub_cap.get(cv2.CAP_PROP_FRAME_WIDTH)) sub_height = int(sub_cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) sub_total_frames = int(sub_cap.get(cv2.CAP_PROP_FRAME_COUNT)) self.logger.info(f"副视频信息: {sub_width}x{sub_height}@{sub_fps:.1f}fps, 总帧数: {sub_total_frames}") # 创建输出目录 output_dir = os.path.dirname(self.config['output_path']) if output_dir and not os.path.exists(output_dir): try: os.makedirs(output_dir) self.logger.info(f"已创建输出目录: {output_dir}") except Exception as e: self.status = f"无法创建输出目录: {output_dir}" self.logger.error(f"创建输出目录失败: {str(e)}") return False # 创建输出视频 output_width, output_height = self.config['output_resolution'] fourcc = cv2.VideoWriter_fourcc(*'mp4v') out = cv2.VideoWriter(self.config['output_path'], fourcc, main_fps, (output_width, output_height)) if out.isOpened(): self.resources.append(out) else: self.status = "无法创建输出视频文件!请检查分辨率设置。" self.logger.error(f"无法创建输出视频: {self.config['output_path']}, 分辨率: {output_width}x{output_height}") return False # 简化参数计算 segment_length_main = int(float(self.config['segment_a']) * main_fps) b1 = int(self.config['b1']) b2 = int(self.config['b2']) segment_length_sub = int(float(self.config['segment_c']) * sub_fps) d = int(self.config['d']) # 显示移动端优化信息 if self.is_mobile: print("\n移动端优化配置:") print(f"输出分辨率: {output_width}x{output_height}") print(f"队列大小: {self.frame_queue.maxsize}") print(f"目标帧率: {self.config.get('target_fps', 24)}") print(f"内存优化: 启用") if self.config.get('mobile_enhance', False): print("图像增强: 启用") self.logger.info("开始视频处理") self.logger.info(f"输出分辨率: {output_width}x{output_height}") # 启动多线程处理 with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor: # 启动捕获线程 capture_future = executor.submit( self.capture_thread, main_cap, main_total_frames ) # 启动处理线程 processing_future = executor.submit( self.processing_thread, (output_width, output_height) ) # 启动写入线程 writer_future = executor.submit( self.writer_thread, out, main_total_frames ) # 等待所有线程完成 concurrent.futures.wait( [capture_future, processing_future, writer_future], return_when=concurrent.futures.ALL_COMPLETED ) if not self.canceled: self.status = "处理完成" self.progress = 100 self.print_progress() print(f"\n\n处理完成!输出文件: {self.config['output_path']}") self.logger.info(f"处理完成! 总帧数: {self.frame_counter}, 耗时: {time.time() - self.start_time:.1f}秒") return True return False except Exception as e: error_msg = f"处理过程中发生错误: {str(e)}" if self.is_mobile: # 移动端友好的错误提示 if "out of memory" in error_msg.lower(): error_msg += "\n建议: 尝试降低分辨率或关闭增强功能" elif "not implemented" in error_msg.lower(): error_msg += "\n建议: 此功能在移动端不可用" self.status = error_msg error_trace = traceback.format_exc() self.logger.error(f"处理过程中发生错误: {str(e)}") self.logger.error(f"错误详情:\n{error_trace}") print(f"\n\n{error_msg}") return False finally: self.stop_resource_monitor() self.release_resources() # 释放Termux优化资源 if self.is_mobile: try: subprocess.run(["termux-wake-unlock"], check=True) self.logger.info("释放唤醒锁成功") except: pass def release_resources(self): """释放所有资源""" self.logger.info("正在释放资源...") for resource in self.resources: try: if hasattr(resource, 'release'): resource.release() elif hasattr(resource, 'close'): resource.close() except Exception as e: self.logger.warning(f"释放资源时出错: {str(e)}") self.resources = [] self.logger.info("资源已释放") def cancel(self): """取消处理""" self.canceled = True self.status = "正在取消..." self.logger.warning("用户请求取消处理") print("\n正在取消处理...") # 清空队列 while not self.frame_queue.empty(): try: self.frame_queue.get_nowait() self.frame_queue.task_done() except queue.Empty: break while not self.processed_queue.empty(): try: self.processed_queue.get_nowait() self.processed_queue.task_done() except queue.Empty: break self.stop_resource_monitor() self.release_resources() # 释放Termux优化资源 if self.is_mobile: try: subprocess.run(["termux-wake-unlock"], check=True) self.logger.info("释放唤醒锁成功") except: pass def get_video_info(file_path): """获取视频文件信息""" cap = None try: cap = cv2.VideoCapture(file_path) if cap.isOpened(): width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fps = cap.get(cv2.CAP_PROP_FPS) frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) duration = frame_count / fps if fps > 0 else 0 return { "width": width, "height": height, "fps": fps, "frame_count": frame_count, "duration": duration } return None except Exception as e: print(f"获取视频信息时出错: {str(e)}") return None finally: if cap and cap.isOpened(): cap.release() def validate_config(config): """验证配置参数""" # 检查文件存在 if not os.path.exists(config['main_video']): print(f"错误: 主视频文件不存在 - {config['main_video']}") return False if not os.path.exists(config['sub_video']): print(f"错误: 副视频文件不存在 - {config['sub_video']}") return False # 检查输出目录 output_dir = os.path.dirname(config['output_path']) if output_dir and not os.path.exists(output_dir): try: os.makedirs(output_dir) print(f"已创建输出目录: {output_dir}") except: print(f"错误: 无法创建输出目录 - {output_dir}") return False # 检查参数有效性 try: # 主视频参数 segment_a = float(config['segment_a']) if segment_a <= 0: print("错误: 分段长度必须大于0!") return False b1 = int(config['b1']) b2 = int(config['b2']) if b1 < 0 or b2 < 0: print("错误: 帧索引不能为负数!") return False if b1 > b2: print("错误: 替换开始帧(b1)必须小于或等于替换结束帧(b2)!") return False # 副视频参数 segment_c = float(config['segment_c']) if segment_c <= 0: print("错误: 分段长度必须大于0!") return False d = int(config['d']) if d < 0: print("错误: 帧索引不能为负数!") return False # 分辨率 width = int(config['output_resolution'][0]) height = int(config['output_resolution'][1]) if width <= 0 or height <= 0: print("错误: 分辨率必须大于0!") return False return True except ValueError: print("错误: 请输入有效的数字参数!") return False def save_config(config, file_path): """保存配置到文件""" try: with open(file_path, 'w') as f: json.dump(config, f, indent=2) print(f"配置已保存到: {file_path}") except Exception as e: print(f"保存配置时出错: {str(e)}") def load_config(file_path): """从文件加载配置""" try: with open(file_path, 'r') as f: config = json.load(f) # 确保配置中包含所有必要字段 required_keys = [ 'main_video', 'sub_video', 'output_path', 'main_segment_type', 'segment_a', 'b1', 'b2', 'sub_segment_type', 'segment_c', 'd', 'sub_option', 'output_resolution' ] for key in required_keys: if key not in config: print(f"警告: 配置文件中缺少 '{key}' 参数") return config except FileNotFoundError: print(f"错误: 配置文件不存在 - {file_path}") except Exception as e: print(f"加载配置时出错: {str(e)}") return None def create_default_config(): """移动端感知的默认配置""" # 检测是否为移动环境 is_mobile = VideoProcessor({}).detect_mobile_environment() if is_mobile: return { "main_video": "main.mp4", "sub_video": "sub.mp4", "output_path": "output/output.mp4", "main_segment_type": "秒", "segment_a": "1", "b1": "1", "b2": "1", "sub_segment_type": "帧", "segment_c": "1", "d": "1", "sub_option": "循环使用", "output_resolution": [640, 360], "hardware_acceleration": "mediacodec", "gpu_device_index": 0, "reduce_latency": True, "decoding_threads": 2, "use_gpu_processing": False, "cuda_streams": 0, "queue_size": 3, "buffer_size": 1, "target_fps": 24, "use_mjpeg": True, "enable_memory_monitor": False, "mobile_optimized": True, "mobile_enhance": False } else: return { "main_video": "main_video.mp4", "sub_video": "sub_video.mp4", "output_path": "output/output_video.mp4", "main_segment_type": "秒", "segment_a": "1", "b1": "1", "b2": "1", "sub_segment_type": "帧", "segment_c": "1", "d": "1", "sub_option": "循环使用", "output_resolution": [1280, 720], "hardware_acceleration": "auto", "gpu_device_index": 0, "reduce_latency": True, "decoding_threads": 4, "use_gpu_processing": True, "cuda_streams": 4, "queue_size": 30, "buffer_size": 3, "target_fps": 30, "use_mjpeg": True, "enable_memory_monitor": False, "mobile_optimized": True, "mobile_enhance": False } def setup_logging(): """配置日志系统""" log_dir = "logs" if not os.path.exists(log_dir): os.makedirs(log_dir) timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") log_file = os.path.join(log_dir, f"video_processor_{timestamp}.log") logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler(log_file), logging.StreamHandler() ] ) logger = logging.getLogger() logger.info(f"日志系统初始化完成, 日志文件: {log_file}") return logger, log_file def install_termux_dependencies(): """安装Termux所需的依赖""" print("正在安装Termux依赖...") commands = [ "pkg update -y && pkg upgrade -y", "pkg install python -y", "pkg install ffmpeg libjpeg-turbo -y", "pip install opencv-python-headless numpy psutil", "pkg install termux-api -y", # 新增Termux:API支持 # 清理缓存节省空间 "pkg clean -y", "rm -rf ~/.cache/pip" ] for cmd in commands: print(f"执行: {cmd}") try: subprocess.run(cmd, shell=True, check=True) except subprocess.CalledProcessError as e: print(f"安装失败: {e}") return False print("\n安装完成! 验证安装:") subprocess.run(["python", "-c", "import cv2; print(f'OpenCV版本: {cv2.__version__}')"]) print("请确保已安装Termux:API应用并授予必要权限") return True def verify_gpu_support(): """验证GPU支持情况""" print("\n验证GPU支持:") # 验证MediaCodec支持 print("\n1. MediaCodec支持:") result = subprocess.run(["ffmpeg", "-hwaccels"], capture_output=True, text=True) if "mediacodec" in result.stdout: print(" ✓ 支持MediaCodec硬件加速") else: print(" ✗ 不支持MediaCodec硬件加速") print("\n设置完成") def setup_termux_gpu_acceleration(): """设置Termux GPU加速环境""" print("="*50) print("Termux GPU加速视频处理设置") print("="*50) # 安装基础依赖 if not install_termux_dependencies(): print("依赖安装失败,无法继续设置") return # 验证GPU支持 verify_gpu_support() print("\nGPU加速环境设置完成!") print("现在可以使用以下命令进行硬件加速视频处理:") print("ffmpeg -hwaccel mediacodec -i input.mp4 -c:v h264_mediacodec output.mp4") # 创建示例批处理脚本 with open("gpu_batch_process.sh", "w") as f: f.write("""#!/bin/bash # GPU加速批处理脚本 for f in *.mp4; do echo "处理: $f" ffmpeg -hwaccel mediacodec -i "$f" -c:v h264_mediacodec "gpu_$f" done echo "所有视频处理完成!" """) print("\n已创建批处理脚本: gpu_batch_process.sh") print("使用命令运行: bash gpu_batch_process.sh") # 设置防后台杀死优化 print("\n设置防后台杀死优化:") try: subprocess.run(["termux-wake-lock"], check=True) print(" ✓ 防止后台被杀设置成功") result = subprocess.run(["termux-battery-optimization", "-s"], capture_output=True, text=True) if "already" not in result.stdout: print(" ✓ 电池优化白名单设置成功") else: print(" ✓ 已在电池优化白名单中") except Exception as e: print(f" ✗ 优化设置失败: {str(e)}") print("请确保已安装Termux:API应用并授予必要权限") def main(): # 设置日志 logger, log_file = setup_logging() # 创建参数解析器 parser = argparse.ArgumentParser(description="移动端视频帧替换工具", formatter_class=argparse.RawTextHelpFormatter) parser.add_argument("--config", help="配置文件路径", default="") parser.add_argument("--save-config", help="保存默认配置到文件", action="store_true") parser.add_argument("--batch", help="批量处理模式,指定批量配置文件", default="") parser.add_argument("--output-dir", help="批量处理输出目录", default="batch_output") parser.add_argument("--setup-termux", help="设置Termux GPU加速环境", action="store_true") parser.add_argument("--mobile-enhance", help="启用移动端图像增强", action="store_true") args = parser.parse_args() # Termux GPU加速设置 if args.setup_termux: setup_termux_gpu_acceleration() return # 保存默认配置 if args.save_config: config_file = args.config if args.config else "video_config.json" default_config = create_default_config() save_config(default_config, config_file) print(f"默认配置已保存到: {config_file}") return # 批量处理模式 if args.batch: if not os.path.exists(args.output_dir): os.makedirs(args.output_dir) print("批量处理模式在移动端不可用") return # 加载配置 config = None if args.config: config = load_config(args.config) # 如果没有提供配置或加载失败,使用默认配置 if not config: print("使用默认配置") config = create_default_config() # 命令行参数覆盖配置 if args.mobile_enhance: config['mobile_enhance'] = True # Termux环境特殊设置 is_mobile = VideoProcessor({}).detect_mobile_environment() if is_mobile: print("检测到Termux环境,应用移动端优化") # 设置环境变量 os.environ["OPENCV_VIDEOIO_PRIORITY"] = "MEDIACODEC" os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "video_codec=h264_mediacodec" os.environ["OPENCV_LOG_LEVEL"] = "ERROR" # 禁用非必要功能 config['enable_memory_monitor'] = False config['use_gpu_processing'] = False # 显示配置 logger.info("\n当前配置:") logger.info(f"主视频: {config['main_video']}") logger.info(f"副视频: {config['sub_video']}") logger.info(f"输出文件: {config['output_path']}") logger.info(f"输出分辨率: {config['output_resolution'][0]}x{config['output_resolution'][1]}") logger.info(f"硬件加速: {config.get('hardware_acceleration', 'auto')}") logger.info(f"移动端增强: {config.get('mobile_enhance', False)}") print("\n当前配置:") print(f"主视频: {config['main_video']}") print(f"副视频: {config['sub_video']}") print(f"输出文件: {config['output_path']}") print(f"输出分辨率: {config['output_resolution'][0]}x{config['output_resolution'][1]}") print(f"硬件加速: {config.get('hardware_acceleration', 'auto')}") print(f"移动端增强: {config.get('mobile_enhance', False)}\n") # 验证配置 if not validate_config(config): logger.error("配置验证失败") return # 显示视频信息 main_info = get_video_info(config['main_video']) if main_info: print("主视频信息:") print(f" 尺寸: {main_info['width']}x{main_info['height']}") print(f" 帧率: {main_info['fps']:.1f} fps") print(f" 时长: {main_info['duration']:.1f}秒") sub_info = get_video_info(config['sub_video']) if sub_info: print("\n副视频信息:") print(f" 尺寸: {sub_info['width']}x{sub_info['height']}") print(f" 帧率: {sub_info['fps']:.1f} fps") print(f" 时长: {sub_info['duration']:.1f}秒") # 确认开始处理 print("\n按 Enter 开始处理,或输入 'c' 取消...") user_input = input().strip().lower() if user_input == 'c': logger.info("用户取消处理") print("处理已取消") return # 创建并运行处理器 logger.info("开始视频处理") processor = VideoProcessor(config) processor.run() # 保存配置 timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") config_file = f"video_config_{timestamp}.json" save_config(config, config_file) logger.info(f"配置已保存: {config_file}") if __name__ == "__main__": main()
07-01
在移动端进行视频帧处理并启用硬件加速(如Android平台的MediaCodec)时,Python和OpenCV并不是最理想的选择。OpenCV主要依赖于CPU进行图像处理,并且其对移动端硬件加速的支持有限[^1]。 ### 视频帧处理与硬件加速方案 #### 1. 使用OpenCV进行视频帧处理 OpenCV可以在移动端(如Android或iOS)上运行,但通常用于轻量级的图像处理任务。对于视频流的逐帧处理,可以通过以下步骤实现: - **读取视频帧**:使用`cv2.VideoCapture`从文件或摄像头捕获视频流。 - **图像预处理**:应用滤波、边缘检测、颜色空间转换等操作。 - **显示或保存处理后的帧**:通过`cv2.imshow()`显示视频帧,或使用`cv2.VideoWriter`保存处理后的视频。 示例代码: ```python import cv2 # 打开视频文件 cap = cv2.VideoCapture("example.mp4") while cap.isOpened(): ret, frame = cap.read() if not ret: break # 转换为灰度图 gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 显示处理后的帧 cv2.imshow('Processed Video', gray_frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() ``` #### 2. 启用MediaCodec进行硬件加速 如果目标是启用MediaCodec来实现硬件加速解码/编码,则建议采用原生开发方式(如Java/Kotlin + NDK),因为OpenCV并不直接支持MediaCodec接口。以下是基本思路: - **使用MediaExtractor提取音视频数据**。 - **将视频帧传递给MediaCodec进行解码**。 - **利用OpenGL ES或Vulkan进行渲染加速**。 - **可选:使用NDK调用C++代码提升性能**。 在Python中难以直接访问MediaCodec API,因此推荐结合JNI或使用Pyjnius库调用Java方法以实现更底层的功能交互。 #### 3. 移动端资源优化策略 为了确保视频处理过程中的资源效率,可以采取以下措施: - **降低分辨率**:在不影响视觉质量的前提下减少视频尺寸。 - **控制帧率**:适当限制每秒处理帧数(FPS)以节省计算资源。 - **内存管理**:复用图像缓冲区并及时释放不再需要的对象。 - **异步处理**:将耗时操作移至后台线程执行,避免阻塞UI主线程。 ### 结论 尽管Python和OpenCV能够完成基础的视频帧处理任务,但在移动端启用MediaCodec硬件加速方面存在局限性。对于高性能需求的应用场景,建议转向基于Android SDK/NDK的开发模式,从而充分利用设备提供的GPU及编解码器能力。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值