@@ -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