Skip to content

Commit af73f50

Browse files
quariumcmassiot
authored andcommitted
upipe_interlace: add lowpass filter
1 parent c939d71 commit af73f50

2 files changed

Lines changed: 106 additions & 1 deletion

File tree

include/upipe-modules/upipe_interlace.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ enum upipe_interlace_command {
3333
UPIPE_INTERLACE_SET_DROP,
3434
/** get the configured value for field drop (bool *) */
3535
UPIPE_INTERLACE_GET_DROP,
36+
/** set low pass filter (bool) */
37+
UPIPE_INTERLACE_SET_LOWPASS,
38+
/** get the configured value for low pass filter (bool *) */
39+
UPIPE_INTERLACE_GET_LOWPASS,
3640
};
3741

3842
/** @This converts @ref upipe_interlace_command to a string.
@@ -47,6 +51,8 @@ static inline const char *upipe_interlace_command_str(int command)
4751
UBASE_CASE_TO_STR(UPIPE_INTERLACE_GET_TFF);
4852
UBASE_CASE_TO_STR(UPIPE_INTERLACE_SET_DROP);
4953
UBASE_CASE_TO_STR(UPIPE_INTERLACE_GET_DROP);
54+
UBASE_CASE_TO_STR(UPIPE_INTERLACE_SET_LOWPASS);
55+
UBASE_CASE_TO_STR(UPIPE_INTERLACE_GET_LOWPASS);
5056
case UPIPE_INTERLACE_SENTINEL: break;
5157
}
5258
return NULL;
@@ -116,6 +122,31 @@ static inline int upipe_interlace_get_drop(struct upipe *upipe, bool *drop)
116122
UPIPE_INTERLACE_SIGNATURE, drop);
117123
}
118124

125+
/** @This sets low pass filter.
126+
*
127+
* @param upipe description structure of the pipe
128+
* @param lowpass true to enable low pass filter
129+
* @return an error code
130+
*/
131+
static inline int upipe_interlace_set_lowpass(struct upipe *upipe, bool lowpass)
132+
{
133+
return upipe_control(upipe, UPIPE_INTERLACE_SET_LOWPASS,
134+
UPIPE_INTERLACE_SIGNATURE, lowpass ? 1 : 0);
135+
}
136+
137+
/** @This gets the configured value for low pass filter.
138+
*
139+
* @param upipe description structure of the pipe
140+
* @param lowpass filled with the configured value
141+
* @return an error code
142+
*/
143+
static inline int upipe_interlace_get_lowpass(struct upipe *upipe,
144+
bool *lowpass)
145+
{
146+
return upipe_control(upipe, UPIPE_INTERLACE_GET_LOWPASS,
147+
UPIPE_INTERLACE_SIGNATURE, lowpass);
148+
}
149+
119150
/** @This returns the management structure for all interlace pipes.
120151
*
121152
* @return pointer to manager

lib/upipe-modules/upipe_interlace.c

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ struct upipe_interlace {
7070
bool tff;
7171
/** drop field? */
7272
bool drop;
73+
/** low pass filtering? */
74+
bool lowpass;
7375
/** last input frame */
7476
struct uref *uref_last;
7577
/** current input width */
@@ -120,6 +122,7 @@ static struct upipe *upipe_interlace_alloc(struct upipe_mgr *mgr,
120122
upipe_interlace->uref_last = NULL;
121123
upipe_interlace->tff = true;
122124
upipe_interlace->drop = true;
125+
upipe_interlace->lowpass = false;
123126

124127
upipe_throw_ready(upipe);
125128

@@ -145,6 +148,37 @@ static void upipe_interlace_free(struct upipe *upipe)
145148
upipe_interlace_free_void(upipe);
146149
}
147150

151+
/** @internal @This copies a line in the output buffer.
152+
*
153+
* @param upipe description structure of the pipe
154+
* @param in pointer to the line to copy
155+
* @param above pointer to the line above for filtering
156+
* @param below pointer to the line below for filtering
157+
* @param width number of pixel to copy
158+
* @param mpixel size of a pixel in byte
159+
* @param out pointer to the destination buffer
160+
*/
161+
static void upipe_interlace_line(struct upipe *upipe, const uint8_t *in,
162+
const uint8_t *above, const uint8_t *below,
163+
uint64_t width, uint8_t mpixel, uint8_t *out)
164+
{
165+
struct upipe_interlace *upipe_interlace = upipe_interlace_from_upipe(upipe);
166+
167+
if (!upipe_interlace->lowpass || mpixel > 2) {
168+
memcpy(out, in, width * mpixel);
169+
} else if (mpixel == 1) {
170+
for (uint64_t i = 0; i < width; i++)
171+
out[i] = (1 + (in[i] << 1) + above[i] + below[i]) >> 2;
172+
} else {
173+
const uint16_t *in16 = (const uint16_t *)in;
174+
const uint16_t *above16 = (const uint16_t *)above;
175+
const uint16_t *below16 = (const uint16_t *)below;
176+
uint16_t *out16 = (uint16_t *)out;
177+
for (uint64_t i = 0; i < width; i++)
178+
out16[i] = (1 + (in16[i] << 1) + above16[i] + below16[i]) >> 2;
179+
}
180+
}
181+
148182
/** @internal @This processes a picture plane
149183
*
150184
* @param upipe description structure of the pipe
@@ -229,7 +263,10 @@ static int upipe_interlace_plane(struct upipe *upipe, struct uref *top,
229263
uint64_t lines = upipe_interlace->height / t_vsub;
230264
uint64_t width = upipe_interlace->width / t_hsub;
231265
for (uint64_t l = 0; l < lines; l++) {
232-
memcpy(out, (l % 2 ? b_in : t_in), width * t_size);
266+
const uint8_t *in = l % 2 ? b_in : t_in;
267+
const uint8_t *above = l ? in - t_stride : in;
268+
const uint8_t *below = l + 1 < lines ? in + t_stride : in;
269+
upipe_interlace_line(upipe, in, above, below, width, t_size, out);
233270
t_in += t_stride;
234271
b_in += b_stride;
235272
out += out_stride;
@@ -542,6 +579,33 @@ static int _upipe_interlace_get_drop(struct upipe *upipe, bool *drop)
542579
return UBASE_ERR_NONE;
543580
}
544581

582+
/** @internal @This sets low pass filter.
583+
*
584+
* @param upipe description structure of the pipe
585+
* @param lowpass true to enable low pass filter
586+
* @return an error code
587+
*/
588+
static int _upipe_interlace_set_lowpass(struct upipe *upipe, bool lowpass)
589+
{
590+
struct upipe_interlace *upipe_interlace = upipe_interlace_from_upipe(upipe);
591+
upipe_interlace->lowpass = lowpass;
592+
return UBASE_ERR_NONE;
593+
}
594+
595+
/** @internal @This get the configured value for low pass filter.
596+
*
597+
* @param upipe description structure of the pipe
598+
* @param lowpass filled with the configured value
599+
* @return an error code
600+
*/
601+
static int _upipe_interlace_get_lowpass(struct upipe *upipe, bool *lowpass)
602+
{
603+
struct upipe_interlace *upipe_interlace = upipe_interlace_from_upipe(upipe);
604+
if (lowpass)
605+
*lowpass = upipe_interlace->lowpass;
606+
return UBASE_ERR_NONE;
607+
}
608+
545609
/** @internal @This processes control commands on the pipe.
546610
*
547611
* @param upipe description structure of the pipe
@@ -596,6 +660,16 @@ static int upipe_interlace_control(struct upipe *upipe, int command,
596660
bool *drop = va_arg(args, bool *);
597661
return _upipe_interlace_get_drop(upipe, drop);
598662
}
663+
case UPIPE_INTERLACE_SET_LOWPASS: {
664+
UBASE_SIGNATURE_CHECK(args, UPIPE_INTERLACE_SIGNATURE);
665+
int lowpass = va_arg(args, int);
666+
return _upipe_interlace_set_lowpass(upipe, lowpass != 0);
667+
}
668+
case UPIPE_INTERLACE_GET_LOWPASS: {
669+
UBASE_SIGNATURE_CHECK(args, UPIPE_INTERLACE_SIGNATURE);
670+
bool *lowpass = va_arg(args, bool *);
671+
return _upipe_interlace_get_lowpass(upipe, lowpass);
672+
}
599673
}
600674

601675
return UBASE_ERR_UNHANDLED;

0 commit comments

Comments
 (0)