Skip to content

Commit 6caa6d2

Browse files
committed
Add non-integer number of lines
1 parent a243d44 commit 6caa6d2

2 files changed

Lines changed: 49 additions & 28 deletions

File tree

src/include/sigutils/tvproc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct sigutils_tv_processor_params {
3636

3737
/* Geometry */
3838
SUSCOUNT frame_lines;
39+
SUFLOAT frame_spacing;
3940

4041
/* Filtering */
4142
SUBOOL enable_comb;
@@ -137,6 +138,7 @@ struct sigutils_tv_processor {
137138
SUFLOAT line_len_alpha;
138139

139140
/* Frame state */
141+
SUFLOAT field_line_due;
140142
SUSCOUNT field_x;
141143
SUFLOAT field_x_dec;
142144
SUSCOUNT field_y;

src/sigutils/tvproc.c

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -127,22 +127,23 @@ su_tv_processor_params_ntsc(
127127
struct sigutils_tv_processor_params *self,
128128
SUFLOAT samp_rate)
129129
{
130-
self->enable_sync = SU_TRUE;
131-
self->reverse = SU_FALSE;
132-
self->interlace = SU_TRUE;
133-
self->enable_agc = SU_TRUE;
134-
self->x_off = 0;
135-
self->dominance = SU_TRUE;
136-
self->frame_lines = 525;
137-
138-
self->enable_comb = SU_TRUE;
139-
self->comb_reverse = SU_FALSE;
140-
141-
self->hsync_len = SU_T2N_FLOAT(samp_rate, 4.749e-6);
142-
self->vsync_len = SU_T2N_FLOAT(samp_rate, 2.375e-6);
143-
self->line_len = SU_T2N_FLOAT(samp_rate, 63.556e-6);
130+
self->enable_sync = SU_TRUE;
131+
self->reverse = SU_FALSE;
132+
self->interlace = SU_TRUE;
133+
self->enable_agc = SU_TRUE;
134+
self->x_off = 0;
135+
self->dominance = SU_TRUE;
136+
self->frame_lines = 525;
137+
self->frame_spacing = 0.0;
138+
139+
self->enable_comb = SU_TRUE;
140+
self->comb_reverse = SU_FALSE;
141+
142+
self->hsync_len = SU_T2N_FLOAT(samp_rate, 4.749e-6);
143+
self->vsync_len = SU_T2N_FLOAT(samp_rate, 2.375e-6);
144+
self->line_len = SU_T2N_FLOAT(samp_rate, 63.556e-6);
144145
self->vsync_odd_trigger = 6; /* VSYNC counter to trigger vertical sync */
145-
146+
146147
self->t_tol = 1e-1; /* Timing error tolerance */
147148
self->l_tol = 1e-1; /* Level error tolerance */
148149
self->g_tol = 1e-1; /* Geometry adjustment tolerance */
@@ -166,20 +167,21 @@ su_tv_processor_params_pal(
166167
struct sigutils_tv_processor_params *self,
167168
SUFLOAT samp_rate)
168169
{
169-
self->enable_sync = SU_TRUE;
170-
self->reverse = SU_FALSE;
171-
self->interlace = SU_TRUE;
172-
self->enable_agc = SU_TRUE;
173-
self->x_off = 0;
174-
self->dominance = SU_TRUE;
175-
self->frame_lines = 625;
170+
self->enable_sync = SU_TRUE;
171+
self->reverse = SU_FALSE;
172+
self->interlace = SU_TRUE;
173+
self->enable_agc = SU_TRUE;
174+
self->x_off = 0;
175+
self->dominance = SU_TRUE;
176+
self->frame_lines = 625;
177+
self->frame_spacing = 0.0;
176178

177-
self->enable_comb = SU_TRUE;
179+
self->enable_comb = SU_TRUE;
178180
self->comb_reverse = SU_FALSE;
179181

180-
self->hsync_len = SU_T2N_FLOAT(samp_rate, 4e-6);
181-
self->vsync_len = SU_T2N_FLOAT(samp_rate, 2e-6);
182-
self->line_len = SU_T2N_FLOAT(samp_rate, 64e-6);
182+
self->hsync_len = SU_T2N_FLOAT(samp_rate, 4e-6);
183+
self->vsync_len = SU_T2N_FLOAT(samp_rate, 2e-6);
184+
self->line_len = SU_T2N_FLOAT(samp_rate, 64e-6);
183185
self->vsync_odd_trigger = 5; /* VSYNC counter to trigger vertical sync */
184186

185187
self->t_tol = 1e-1; /* Timing error tolerance */
@@ -211,7 +213,10 @@ SU_INSTANCER(
211213
new->width = SU_CEIL(params->line_len);
212214
new->height = params->frame_lines;
213215

214-
SU_ALLOCATE_MANY_FAIL(new->buffer, new->width *new->height, SUFLOAT);
216+
/*
217+
* Allocate extra line for fractional line numbers.
218+
*/
219+
SU_ALLOCATE_MANY_FAIL(new->buffer, new->width * (new->height + 1), SUFLOAT);
215220

216221
return new;
217222

@@ -274,12 +279,23 @@ SU_INSTANCER(su_tv_processor, const struct sigutils_tv_processor_params *params)
274279
SUINLINE
275280
SU_METHOD(su_tv_processor, void, swap_field)
276281
{
282+
SUBOOL spacing = SU_TRUE;
283+
277284
if (self->params.interlace) {
285+
spacing = self->field_parity;
278286
self->field_parity = !self->field_parity;
279287
self->field_lines = self->params.frame_lines / 2 + self->field_parity;
280288
} else {
281289
self->field_lines = self->params.frame_lines;
282290
}
291+
292+
if (spacing) {
293+
self->field_line_due += self->params.frame_spacing;
294+
if (self->field_line_due >= 1) {
295+
self->field_line_due -= 1.;
296+
++self->field_lines;
297+
}
298+
}
283299
}
284300

285301
SUINLINE
@@ -359,6 +375,9 @@ SU_METHOD(
359375
self->agc_lines = 0;
360376
}
361377

378+
/* Reset line due */
379+
self->field_line_due = 0.;
380+
362381
/* Reset pulse filter state */
363382
self->pulse_x = 0;
364383

@@ -423,7 +442,7 @@ SU_METHOD(
423442
self->hsync_slow_track_alpha = SU_SPLPF_ALPHA(params->hsync_slow_track_tau);
424443
self->hsync_fast_track_alpha = SU_SPLPF_ALPHA(params->hsync_fast_track_tau);
425444
self->line_len_alpha = SU_SPLPF_ALPHA(params->line_len_tau);
426-
445+
427446
ok = SU_TRUE;
428447

429448
fail:

0 commit comments

Comments
 (0)