#!/usr/bin/env python3
"""Frame-rate conversion cadence test. Usage: test-run.py <src24.mp4> <src30.mp4> <src60.mp4> <start_s> <dur_s>
Hashes decoded frames (160x90 gray, ffmpeg framemd5) of a source excerpt and of the same excerpt after ffmpeg's fps filter
(duplicate/drop), then maps every output frame back to the source frame with the same hash."""
import subprocess, sys, re, collections
src = {24: sys.argv[1], 30: sys.argv[2], 60: sys.argv[3]}
ss, dur = sys.argv[4], sys.argv[5]

def hashes(path, vf):
    out = subprocess.run(['ffmpeg','-v','error','-ss',ss,'-t',dur,'-i',path,'-an','-vf',vf,'-f','framemd5','-'],
                         capture_output=True, text=True, check=True).stdout
    return [l.split(',')[-1].strip() for l in out.splitlines() if l and not l.startswith('#')]

print('ffmpeg:', subprocess.run(['ffmpeg','-version'],capture_output=True,text=True).stdout.splitlines()[0])
print(f'excerpt: start {ss} s, duration {dur} s; frames compared as 160x90 gray md5 of decoded pictures\n')
rows = []
for S in (24, 30, 60):
    base = hashes(src[S], 'scale=160:90,format=gray')
    uniq = len(set(base)) == len(base)
    print(f'source {S} fps: {len(base)} frames, all hashes distinct: {uniq}')
    if not uniq:
        print('  CONTROL FAILED: duplicate source frames make mapping ambiguous; this source is not published'); continue
    idx = {h: i for i, h in enumerate(base)}
    for T in (24, 30, 60):
        out = hashes(src[S], f'fps={T},scale=160:90,format=gray')
        mapped = [idx.get(h, -1) for h in out]
        unknown = mapped.count(-1)
        holds = collections.Counter(mapped)
        kept = len(holds)
        dropped = len(base) - kept
        repeats = len(out) - kept
        pattern = ''
        seq = [holds[i] for i in range(len(base))]
        pattern = ','.join(str(x) for x in seq[:12])
        print(f'{S}->{T}: out frames {len(out)}, unmapped {unknown}, source frames kept {kept} of {len(base)}, '
              f'dropped {dropped} ({100*dropped/len(base):.2f}%), repeated output frames {repeats} ({100*repeats/len(out):.2f}%), '
              f'longest hold {max(seq)}, distinct hold lengths {sorted(set(seq))}, first 12 holds {pattern}')
