Skip to content

Commit 29ed6cb

Browse files
committed
Merge branch 'vhs_decode' of github.com:oyvindln/vhs-decode into vhs_decode
2 parents 3bbe9ce + 13062d4 commit 29ed6cb

File tree

1 file changed

+82
-41
lines changed

1 file changed

+82
-41
lines changed

vhsdecode/field.py

Lines changed: 82 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -327,54 +327,94 @@ def get_line0_fallback(
327327
linelen / 2
328328
)
329329
line_offset = None
330-
phase_cnt = [0, 0, 0]
331-
for d in range(15, min(i, 30) + 1):
332-
pp = np.array(
333-
[
334-
(filtered_pulses[i - 2].start - filtered_pulses[i - d].start)
335-
/ measured_linelen,
336-
(
337-
filtered_pulses[i - 2].start
338-
- filtered_pulses[i - d + 1].start
339-
)
340-
/ measured_linelen,
341-
(
342-
filtered_pulses[i - 2].start
343-
- filtered_pulses[i - d + 2].start
344-
)
345-
/ measured_linelen,
346-
]
347-
)
348-
# PAL: for start of first field all values should be 1, for second field all should be 0
349-
# NTSC: for start of first field all values should be 0, for second field all should be 1
350-
pps = np.sum(np.mod(np.round(pp * 2), 2))
351-
if pps == 0:
352-
phase_cnt[0] += 1
353-
elif pps == 3:
354-
phase_cnt[1] += 1
355-
else:
356-
phase_cnt[2] += 1
357-
if sum(phase_cnt[0:2]) >= 5:
330+
# count "half lines" for detecting top/bottom field:
331+
half_lines = 0
332+
j = i
333+
while j < i + 9:
334+
dis = (filtered_pulses[j + 1].start - filtered_pulses[j].start) / linelen
335+
if (
336+
abs(dis-0.5) < 0.06
337+
and filtered_pulses[j].len < SHORT_PULSE_MAX
338+
and filtered_pulses[j + 1].len < SHORT_PULSE_MAX
339+
):
340+
half_lines += 1
341+
elif (
342+
abs(dis-1.0) < 0.06
343+
and filtered_pulses[j].len < SHORT_PULSE_MAX
344+
and filtered_pulses[j + 1].len < SHORT_PULSE_MAX
345+
):
358346
break
359-
phase = np.argmax(phase_cnt)
360-
if phase == 0:
361-
# we need to differ between 625 and 525 line
362-
if frame_lines == 625:
363-
first_field = 0
364-
line_offset = 5.0
365347
else:
366-
first_field = 1
367-
line_offset = 6.0
368-
first_field_confidence = phase_cnt[0] * 100 // sum(phase_cnt)
369-
elif phase == 1:
370-
# we need to differ between 625 and 525 line
348+
half_lines = 0
349+
break
350+
j += 1
351+
if half_lines == 4 and frame_lines == 625:
352+
first_field = 0
353+
first_field_confidence = 100
354+
line_offset = 5.0
355+
elif half_lines == 5:
371356
if frame_lines == 625:
372357
first_field = 1
358+
first_field_confidence = 100
373359
line_offset = 4.5
374360
else:
375361
first_field = 0
362+
first_field_confidence = 100
376363
line_offset = 5.5
377-
first_field_confidence = phase_cnt[1] * 100 // sum(phase_cnt)
364+
elif half_lines == 6 and frame_lines == 525:
365+
first_field = 1
366+
line_offset = 6.0
367+
368+
# if we couldn't detect field type based on half lines check phase
369+
if line_offset is None:
370+
phase_cnt = [0, 0, 0]
371+
for d in range(15, min(i, 30) + 1):
372+
pp = np.array(
373+
[
374+
(filtered_pulses[i - 2].start - filtered_pulses[i - d].start)
375+
/ measured_linelen,
376+
(
377+
filtered_pulses[i - 2].start
378+
- filtered_pulses[i - d + 1].start
379+
)
380+
/ measured_linelen,
381+
(
382+
filtered_pulses[i - 2].start
383+
- filtered_pulses[i - d + 2].start
384+
)
385+
/ measured_linelen,
386+
]
387+
)
388+
# PAL: for start of first field all values should be 1, for second field all should be 0
389+
# NTSC: for start of first field all values should be 0, for second field all should be 1
390+
pps = np.sum(np.mod(np.round(pp * 2), 2))
391+
if pps == 0:
392+
phase_cnt[0] += 1
393+
elif pps == 3:
394+
phase_cnt[1] += 1
395+
else:
396+
phase_cnt[2] += 1
397+
if sum(phase_cnt[0:2]) >= 5:
398+
break
399+
phase = np.argmax(phase_cnt)
400+
if phase == 0:
401+
# we need to differ between 625 and 525 line
402+
if frame_lines == 625:
403+
first_field = 0
404+
line_offset = 5.0
405+
else:
406+
first_field = 1
407+
line_offset = 6.0
408+
first_field_confidence = phase_cnt[0] * 100 // sum(phase_cnt)
409+
elif phase == 1:
410+
# we need to differ between 625 and 525 line
411+
if frame_lines == 625:
412+
first_field = 1
413+
line_offset = 4.5
414+
else:
415+
first_field = 0
416+
line_offset = 5.5
417+
first_field_confidence = phase_cnt[1] * 100 // sum(phase_cnt)
378418

379419
if line_offset is not None:
380420
# in case we cannot find a matching pulse, we can still use this prediction
@@ -761,7 +801,8 @@ def get_line0_fallback(
761801
"WARNING, line0 hsync not found in entire block, but vsync area found, using predicted position, result may be garbled."
762802
)
763803
line_0 = line_0_backup
764-
first_field_confidence -= 20
804+
first_field = first_field_backup
805+
first_field_confidence = first_field_confidence_backup - 20
765806

766807
if line_0 is not None:
767808
if DEBUG_PLOT:

0 commit comments

Comments
 (0)