Skip to content

Commit aa2dab0

Browse files
committed
upipe-modules: add upipe_pad
A module to pad picture urefs with blank space.
1 parent b922746 commit aa2dab0

File tree

4 files changed

+346
-0
lines changed

4 files changed

+346
-0
lines changed

include/upipe-modules/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,5 @@ myinclude_HEADERS = \
9292
uref_graph_flow.h \
9393
uref_graph.h \
9494
upipe_graph.h \
95+
upipe_pad.h \
9596
$(NULL)

include/upipe-modules/upipe_pad.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Pad picture urefs with blank space.
3+
*
4+
* Copyright (C) 2020 Open Broadcast Systems Ltd.
5+
*
6+
* Authors: James Darnley
7+
*
8+
* This library is free software; you can redistribute it and/or
9+
* modify it under the terms of the GNU Lesser General Public
10+
* License as published by the Free Software Foundation; either
11+
* version 2.1 of the License, or (at your option) any later version.
12+
*
13+
* This library is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16+
* Lesser General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public
19+
* License along with this library; if not, write to the Free Software
20+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21+
*/
22+
23+
/** @file
24+
* @short Upipe module to pad picture urefs with blank space.
25+
*/
26+
27+
#ifndef _UPIPE_FILTERS_UPIPE_PAD_H_
28+
#define _UPIPE_FILTERS_UPIPE_PAD_H_
29+
30+
#include <upipe/ubase.h>
31+
32+
#ifdef __cplusplus
33+
extern "C" {
34+
#endif
35+
36+
/** @This is the signature of a pad pipe. */
37+
#define UPIPE_PAD_SIGNATURE UBASE_FOURCC('p','a','d',' ')
38+
39+
/** @This returns the pad pipe manager.
40+
*
41+
* @return a pointer to the pad pipe manager
42+
*/
43+
struct upipe_mgr *upipe_pad_mgr_alloc(void);
44+
45+
#ifdef __cplusplus
46+
}
47+
#endif
48+
#endif /* !_UPIPE_FILTERS_UPIPE_PAD_H_ */

lib/upipe-modules/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ libupipe_modules_la_SOURCES = \
8282
upipe_discard_blocking.c \
8383
upipe_audio_merge.c \
8484
upipe_graph.c \
85+
upipe_pad.c \
8586
$(NULL)
8687

8788
if HAVE_WRITEV

lib/upipe-modules/upipe_pad.c

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
/*
2+
* Pad picture urefs with blank space.
3+
*
4+
* Copyright (c) 2020 Open Broadcast Systems Ltd.
5+
*
6+
* Authors: James Darnley
7+
*
8+
* This library is free software; you can redistribute it and/or
9+
* modify it under the terms of the GNU Lesser General Public
10+
* License as published by the Free Software Foundation; either
11+
* version 2.1 of the License, or (at your option) any later version.
12+
*
13+
* This library is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16+
* Lesser General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public
19+
* License along with this library; if not, write to the Free Software
20+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21+
*/
22+
23+
/** @file
24+
* @short Upipe module to pad picture urefs with blank space.
25+
*/
26+
27+
#include <upipe/ubase.h>
28+
#include <upipe/upipe.h>
29+
#include <upipe/uprobe.h>
30+
#include <upipe/ubuf.h>
31+
#include <upipe/ubuf_pic.h>
32+
#include <upipe/uref.h>
33+
#include <upipe/uref_flow.h>
34+
#include <upipe/uref_pic.h>
35+
#include <upipe/uref_pic_flow.h>
36+
#include <upipe/upipe_helper_flow.h>
37+
#include <upipe/upipe_helper_input.h>
38+
#include <upipe/upipe_helper_output.h>
39+
#include <upipe/upipe_helper_ubuf_mgr.h>
40+
#include <upipe/upipe_helper_upipe.h>
41+
#include <upipe/upipe_helper_urefcount.h>
42+
43+
#include <upipe-modules/upipe_pad.h>
44+
45+
/** we only accept pictures */
46+
#define EXPECTED_FLOW_DEF "pic."
47+
48+
struct upipe_pad {
49+
/** refcount management structure */
50+
struct urefcount urefcount;
51+
52+
/** ubuf manager */
53+
struct ubuf_mgr *ubuf_mgr;
54+
/** flow format packet */
55+
struct uref *flow_format;
56+
/** ubuf manager request */
57+
struct urequest ubuf_mgr_request;
58+
59+
/** output pipe */
60+
struct upipe *output;
61+
/** flow_definition packet */
62+
struct uref *flow_def;
63+
/** output state */
64+
enum upipe_helper_output_state output_state;
65+
/** list of output requests */
66+
struct uchain request_list;
67+
68+
/** temporary uref storage (used during urequest) */
69+
struct uchain urefs;
70+
/** nb urefs in storage */
71+
unsigned int nb_urefs;
72+
/** max urefs in storage */
73+
unsigned int max_urefs;
74+
/** list of blockers (used during udeal) */
75+
struct uchain blockers;
76+
77+
/** public upipe structure */
78+
struct upipe upipe;
79+
80+
/* flow_def given at alloc describing how to pad the picture */
81+
uint64_t w, h, l, r, t, b;
82+
};
83+
84+
/** @hidden */
85+
static bool upipe_pad_handle(struct upipe *upipe, struct uref *uref, struct upump **upump_p);
86+
/** @hidden */
87+
static int upipe_pad_check(struct upipe *upipe, struct uref *flow_format);
88+
89+
UPIPE_HELPER_UPIPE(upipe_pad, upipe, UPIPE_PAD_SIGNATURE);
90+
UPIPE_HELPER_UREFCOUNT(upipe_pad, urefcount, upipe_pad_free);
91+
UPIPE_HELPER_FLOW(upipe_pad, EXPECTED_FLOW_DEF);
92+
UPIPE_HELPER_INPUT(upipe_pad, urefs, nb_urefs, max_urefs, blockers, upipe_pad_handle)
93+
UPIPE_HELPER_OUTPUT(upipe_pad, output, flow_def, output_state, request_list)
94+
UPIPE_HELPER_UBUF_MGR(upipe_pad, ubuf_mgr, flow_format, ubuf_mgr_request, upipe_pad_check,
95+
upipe_pad_register_output_request, upipe_pad_unregister_output_request)
96+
97+
/** @internal @This allocates a pad pipe.
98+
*
99+
* @param mgr common management structure
100+
* @param uprobe structure used to raise events
101+
* @param signature signature of the pipe allocator
102+
* @param args optional arguments
103+
* @return pointer to upipe or NULL in case of allocation error
104+
*/
105+
static struct upipe *upipe_pad_alloc(struct upipe_mgr *mgr,
106+
struct uprobe *uprobe,
107+
uint32_t signature, va_list args)
108+
{
109+
struct uref *flow_def;
110+
struct upipe *upipe = upipe_pad_alloc_flow(mgr, uprobe, signature, args, &flow_def);
111+
if (unlikely(upipe == NULL))
112+
return NULL;
113+
114+
struct upipe_pad *upipe_pad = upipe_pad_from_upipe(upipe);
115+
116+
upipe_pad_init_urefcount(upipe);
117+
upipe_pad_init_input(upipe);
118+
upipe_pad_init_output(upipe);
119+
upipe_pad_init_ubuf_mgr(upipe);
120+
121+
/* TODO: support more options than only the pad attributes. */
122+
123+
uint64_t l = 0, r = 0, t = 0, b = 0;
124+
if (!ubase_check(uref_pic_get_lpadding(flow_def, &l))
125+
|| !ubase_check(uref_pic_get_rpadding(flow_def, &r))
126+
|| !ubase_check(uref_pic_get_tpadding(flow_def, &t))
127+
|| !ubase_check(uref_pic_get_bpadding(flow_def, &b)))
128+
return NULL;
129+
upipe_pad->l = l; upipe_pad->r = r; upipe_pad->t = t; upipe_pad->b = b;
130+
upipe_pad->w = upipe_pad->h = 0;
131+
132+
uref_free(flow_def);
133+
upipe_throw_ready(upipe);
134+
return upipe;
135+
}
136+
137+
/** @internal @This frees a pad pipe.
138+
*
139+
* @param upipe description structure of the pipe
140+
*/
141+
static void upipe_pad_free(struct upipe *upipe)
142+
{
143+
upipe_throw_dead(upipe);
144+
upipe_pad_clean_urefcount(upipe);
145+
upipe_pad_clean_input(upipe);
146+
upipe_pad_clean_output(upipe);
147+
upipe_pad_clean_ubuf_mgr(upipe);
148+
upipe_pad_free_flow(upipe);
149+
}
150+
151+
/** @internal @This sets the input flow definition.
152+
*
153+
* @param upipe description structure of the pipe
154+
* @param flow_def flow definition packet
155+
* @return an error code
156+
*/
157+
static int upipe_pad_set_flow_def(struct upipe *upipe, struct uref *flow_def)
158+
{
159+
struct upipe_pad *upipe_pad = upipe_pad_from_upipe(upipe);
160+
if (flow_def == NULL)
161+
return UBASE_ERR_INVALID;
162+
UBASE_RETURN(uref_flow_match_def(flow_def, EXPECTED_FLOW_DEF));
163+
164+
uint64_t w, h;
165+
UBASE_RETURN(uref_pic_flow_get_hsize(flow_def, &w));
166+
UBASE_RETURN(uref_pic_flow_get_vsize(flow_def, &h));
167+
upipe_pad->w = w += upipe_pad->l + upipe_pad->r;
168+
upipe_pad->h = h += upipe_pad->t + upipe_pad->b;
169+
170+
struct uref *flow_def_dst = uref_dup(flow_def);
171+
UBASE_ALLOC_RETURN(flow_def_dst);
172+
UBASE_RETURN(uref_pic_flow_set_hsize(flow_def_dst, w));
173+
UBASE_RETURN(uref_pic_flow_set_vsize(flow_def_dst, h));
174+
175+
upipe_pad_require_ubuf_mgr(upipe, flow_def_dst);
176+
return UBASE_ERR_NONE;
177+
}
178+
179+
/** @internal @This handles data.
180+
*
181+
* @param upipe description structure of the pipe
182+
* @param uref uref structure describing the picture
183+
* @param upump_p reference to pump that generated the buffer
184+
* @return false if the input must be blocked
185+
*/
186+
static bool upipe_pad_handle(struct upipe *upipe, struct uref *uref, struct upump **upump_p)
187+
{
188+
struct upipe_pad *upipe_pad = upipe_pad_from_upipe(upipe);
189+
if (!upipe_pad->ubuf_mgr) {
190+
upipe_warn(upipe, "no ubuf_mgr, holding input uref");
191+
return false;
192+
}
193+
194+
struct ubuf *ubuf_dst = ubuf_pic_alloc(upipe_pad->ubuf_mgr, upipe_pad->w, upipe_pad->h);
195+
if (!ubuf_dst) {
196+
uref_free(uref);
197+
upipe_throw_error(upipe, UBASE_ERR_ALLOC);
198+
return true;
199+
}
200+
ubuf_pic_clear(ubuf_dst, 0, 0, -1, -1, 1);
201+
202+
uint64_t w = upipe_pad->w - upipe_pad->l - upipe_pad->r;
203+
uint64_t h = upipe_pad->h - upipe_pad->t - upipe_pad->b;
204+
UBASE_ERROR(upipe, ubuf_pic_blit(ubuf_dst, uref->ubuf, upipe_pad->l, upipe_pad->t,
205+
0, 0, w, h, 0, 0));
206+
207+
uref_attach_ubuf(uref, ubuf_dst);
208+
upipe_pad_output(upipe, uref, upump_p);
209+
return true;
210+
}
211+
212+
/** @internal @This receives a provided ubuf manager.
213+
*
214+
* @param upipe description structure of the pipe
215+
* @param flow_format amended flow format
216+
* @return an error code
217+
*/
218+
static int upipe_pad_check(struct upipe *upipe, struct uref *flow_format)
219+
{
220+
struct upipe_pad *upipe_pad = upipe_pad_from_upipe(upipe);
221+
if (flow_format != NULL)
222+
upipe_pad_store_flow_def(upipe, flow_format);
223+
if (upipe_pad->flow_def == NULL)
224+
return UBASE_ERR_NONE;
225+
226+
bool was_buffered = !upipe_pad_check_input(upipe);
227+
upipe_pad_output_input(upipe);
228+
upipe_pad_unblock_input(upipe);
229+
if (was_buffered && upipe_pad_check_input(upipe)) {
230+
/* All packets have been output, release again the pipe that has been
231+
* used in @ref upipe_pad_input. */
232+
upipe_release(upipe);
233+
}
234+
return UBASE_ERR_NONE;
235+
}
236+
237+
/** @internal @This receives incoming uref.
238+
*
239+
* @param upipe description structure of the pipe
240+
* @param uref uref structure describing the picture
241+
* @param upump_p reference to pump that generated the buffer
242+
*/
243+
static void upipe_pad_input(struct upipe *upipe, struct uref *uref,
244+
struct upump **upump_p)
245+
{
246+
if (!upipe_pad_check_input(upipe)) {
247+
upipe_pad_hold_input(upipe, uref);
248+
upipe_pad_block_input(upipe, upump_p);
249+
} else if (!upipe_pad_handle(upipe, uref, upump_p)) {
250+
upipe_pad_hold_input(upipe, uref);
251+
upipe_pad_block_input(upipe, upump_p);
252+
/* Increment upipe refcount to avoid disappearing before all packets
253+
* have been sent. */
254+
upipe_use(upipe);
255+
}
256+
}
257+
258+
/** @internal @This handles the pipe control commands.
259+
*
260+
* @param upipe description structure of the pipe
261+
* @param command control command to handle
262+
* @param args optional arguments
263+
* @return an error code
264+
*/
265+
static int upipe_pad_control(struct upipe *upipe, int command, va_list args)
266+
{
267+
UBASE_HANDLED_RETURN(upipe_pad_control_ubuf_mgr(upipe, command, args));
268+
UBASE_HANDLED_RETURN(upipe_pad_control_output(upipe, command, args));
269+
switch (command) {
270+
default:
271+
return UBASE_ERR_UNHANDLED;
272+
273+
case UPIPE_SET_FLOW_DEF: {
274+
struct uref *flow = va_arg(args, struct uref *);
275+
return upipe_pad_set_flow_def(upipe, flow);
276+
}
277+
}
278+
}
279+
280+
/** @internal @This is the static zoneplate source pipe manager. */
281+
static struct upipe_mgr upipe_pad_mgr = {
282+
.refcount = NULL,
283+
.signature = UPIPE_PAD_SIGNATURE,
284+
.upipe_alloc = upipe_pad_alloc,
285+
.upipe_input = upipe_pad_input,
286+
.upipe_control = upipe_pad_control,
287+
};
288+
289+
/** @This returns the zoneplate source pipe manager.
290+
*
291+
* @return a pointer to the zoneplate source pipe manager
292+
*/
293+
struct upipe_mgr *upipe_pad_mgr_alloc(void)
294+
{
295+
return &upipe_pad_mgr;
296+
}

0 commit comments

Comments
 (0)