# 本文公开核验脚本：仅验证随附原创文件及声明的有限条件。
import json, csv, hashlib, re, struct, subprocess, sys, zlib
from fractions import Fraction
from pathlib import Path
P = Path(__file__).resolve().parent
def read(name): return json.loads((P/name).read_text(encoding='utf-8-sig'))
def digest(name): return hashlib.sha256((P/name).read_bytes()).hexdigest()
def probe(name, *args):
    command = ['ffprobe','-v','error',*args,'-of','json',str(P/name)]
    run = subprocess.run(command,capture_output=True,text=True,encoding='utf-8',timeout=25)
    assert run.returncode == 0, run.stderr
    return json.loads(run.stdout)
def decode(name):
    command=['ffmpeg','-v','error','-xerror','-i',str(P/name),'-map','0:v?','-map','0:a?','-f','null','-']
    run=subprocess.run(command,capture_output=True,text=True,encoding='utf-8',timeout=25)
    assert run.returncode == 0, run.stderr
    assert not run.stderr.strip(), run.stderr
    return {'file':name,'exit_code':run.returncode,'stderr':run.stderr}
def packets(name, select='v:0'):
    return probe(name,'-select_streams',select,'-show_packets')['packets']
def streams(name): return probe(name,'-show_streams','-show_format')
def stamp(v,base): return Fraction(int(v))*Fraction(base)
def framehash(name):
    run=subprocess.run(['ffmpeg','-v','error','-i',str(P/name),'-map','0:V:0','-f','framemd5','-'],capture_output=True,text=True,encoding='utf-8',timeout=25)
    assert run.returncode==0,run.stderr
    return [x.split(',')[-1].strip() for x in run.stdout.splitlines() if x and not x.startswith('#')]
def emit(value): print(json.dumps(value,ensure_ascii=False,indent=2))

a=probe('programs.ts','-show_programs')['programs'];b=probe('selected.ts','-show_programs')['programs'];assert {q['program_id'] for q in a}=={101,202};assert len(b)==1 and b[0]['program_id']==202;assert len(b[0]['streams'])==2
emit({'source_programs':[{'program_id':q['program_id'],'streams':[{'index':s['index'],'pid':s['id'],'type':s['codec_type']} for s in q['streams']]} for q in a],'selected_programs':[{'program_id':q['program_id'],'stream_count':len(q['streams'])} for q in b],'decode':[decode('programs.ts'),decode('selected.ts')]})

