#!/usr/bin/env python3
"""
独立的视频流服务器
运行在单独的进程中，通过HTTP提供视频流服务
避免阻塞主API服务器线程
"""

import cv2
import time
import threading
import logging
import json
from flask import Flask, Response, request, jsonify
from flask_cors import CORS
import sys
import os

# 设置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = Flask(__name__)
CORS(app)

class VideoStreamServer:
    def __init__(self):
        self.streams = {}
        self.frame_cache = {}
        self.cache_locks = {}
        
    def create_stream(self, stream_id):
        """创建新的视频流"""
        if stream_id not in self.streams:
            self.streams[stream_id] = {
                'url': None,
                'active': False,
                'capture': None,
                'thread': None,
                'lock': threading.Lock(),
                'stop_event': threading.Event()
            }
            self.frame_cache[stream_id] = None
            self.cache_locks[stream_id] = threading.Lock()
    
    def _capture_worker(self, stream_id):
        """后台工作线程：持续捕获视频帧"""
        stream_info = self.streams[stream_id]
        logger.info(f"视频捕获线程启动: {stream_id}")
        
        while not stream_info['stop_event'].is_set():
            try:
                with stream_info['lock']:
                    if stream_info['capture'] is None:
                        break
                    ret, frame = stream_info['capture'].read()
                
                if ret and frame is not None:
                    # 编码为JPEG
                    ret_encode, buffer = cv2.imencode('.jpg', frame, [
                        cv2.IMWRITE_JPEG_QUALITY, 75,
                        cv2.IMWRITE_JPEG_OPTIMIZE, 1
                    ])
                    
                    if ret_encode:
                        with self.cache_locks[stream_id]:
                            self.frame_cache[stream_id] = buffer.tobytes()
                else:
                    time.sleep(0.1)
                    
            except Exception as e:
                logger.error(f"捕获{stream_id}帧异常: {e}")
                time.sleep(0.1)
            
            time.sleep(0.033)  # 约30fps
        
        logger.info(f"视频捕获线程结束: {stream_id}")
    
    def start_stream(self, stream_id, url):
        """启动视频流"""
        self.create_stream(stream_id)
        stream_info = self.streams[stream_id]
        
        if stream_info['active']:
            return True, "视频流已在运行"
        
        try:
            with stream_info['lock']:
                if stream_info['capture']:
                    stream_info['capture'].release()
                
                cap = cv2.VideoCapture(url, cv2.CAP_FFMPEG)
                cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
                cap.set(cv2.CAP_PROP_FPS, 30)
                cap.set(cv2.CAP_PROP_OPEN_TIMEOUT_MSEC, 5000)
                
                ret, test_frame = cap.read()
                if not ret:
                    cap.release()
                    return False, "无法连接视频流"
                
                stream_info['url'] = url
                stream_info['capture'] = cap
                stream_info['active'] = True
                stream_info['stop_event'].clear()
                
                # 启动后台线程
                stream_info['thread'] = threading.Thread(
                    target=self._capture_worker,
                    args=(stream_id,),
                    daemon=True
                )
                stream_info['thread'].start()
                
                return True, "视频流启动成功"
                
        except Exception as e:
            return False, f"启动失败: {str(e)}"
    
    def stop_stream(self, stream_id):
        """停止视频流"""
        if stream_id not in self.streams:
            return True, "流不存在"
        
        stream_info = self.streams[stream_id]
        stream_info['stop_event'].set()
        stream_info['active'] = False
        
        if stream_info['thread'] and stream_info['thread'].is_alive():
            stream_info['thread'].join(timeout=2.0)
        
        with stream_info['lock']:
            if stream_info['capture']:
                stream_info['capture'].release()
                stream_info['capture'] = None
        
        with self.cache_locks[stream_id]:
            self.frame_cache[stream_id] = None
        
        return True, "视频流已停止"
    
    def get_frame(self, stream_id):
        """获取最新帧"""
        if stream_id not in self.frame_cache:
            return None
        
        with self.cache_locks[stream_id]:
            return self.frame_cache[stream_id]
    
    def is_active(self, stream_id):
        """检查流是否活跃"""
        return stream_id in self.streams and self.streams[stream_id]['active']

# 全局视频服务器实例
video_server = VideoStreamServer()

@app.route('/start/<stream_id>')
def start_stream(stream_id):
    """启动视频流"""
    url = request.args.get('url')
    if not url:
        return jsonify({'success': False, 'message': '缺少URL参数'}), 400
    
    success, message = video_server.start_stream(stream_id, url)
    return jsonify({'success': success, 'message': message})

@app.route('/stop/<stream_id>')
def stop_stream(stream_id):
    """停止视频流"""
    success, message = video_server.stop_stream(stream_id)
    return jsonify({'success': success, 'message': message})

@app.route('/stream/<stream_id>')
def stream_video(stream_id):
    """视频流端点"""
    if not video_server.is_active(stream_id):
        return "Stream not active", 404
    
    def generate():
        while video_server.is_active(stream_id):
            frame_bytes = video_server.get_frame(stream_id)
            if frame_bytes:
                yield (b'--frame\r\n'
                       b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n')
            time.sleep(0.033)
    
    return Response(generate(), 
                   mimetype='multipart/x-mixed-replace; boundary=frame')

@app.route('/status')
def status():
    """获取所有流状态"""
    status_info = {}
    for stream_id, stream_info in video_server.streams.items():
        status_info[stream_id] = {
            'active': stream_info['active'],
            'url': stream_info['url']
        }
    return jsonify(status_info)

if __name__ == '__main__':
    print("启动独立视频流服务器...")
    print("监听端口: 5011")
    app.run(host='0.0.0.0', port=5011, debug=True, threaded=True)
