2 Copyright (c) 2012, Broadcom Europe Ltd
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "core/mmal_component_private.h"
30 #include "core/mmal_port_private.h"
31 #include "mmal_logging.h"
33 #define PASSTHROUGH_PORTS_NUM 1
35 /*****************************************************************************/
36 typedef struct MMAL_COMPONENT_MODULE_T
38 MMAL_BOOL_T error; /**< Error state */
40 } MMAL_COMPONENT_MODULE_T;
42 typedef struct MMAL_PORT_MODULE_T
44 MMAL_QUEUE_T *queue; /**< queue for the buffers sent to the ports */
48 /*****************************************************************************/
50 /** Destroy a previously created component */
51 static MMAL_STATUS_T passthrough_component_destroy(MMAL_COMPONENT_T *component)
55 for(i = 0; i < component->input_num; i++)
56 if(component->input[i]->priv->module->queue)
57 mmal_queue_destroy(component->input[i]->priv->module->queue);
58 if(component->input_num)
59 mmal_ports_free(component->input, component->input_num);
61 for(i = 0; i < component->output_num; i++)
62 if(component->output[i]->priv->module->queue)
63 mmal_queue_destroy(component->output[i]->priv->module->queue);
64 if(component->output_num)
65 mmal_ports_free(component->output, component->output_num);
67 vcos_free(component->priv->module);
71 /** Enable processing on a port */
72 static MMAL_STATUS_T passthrough_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
74 MMAL_PARAM_UNUSED(port);
75 MMAL_PARAM_UNUSED(cb);
80 static MMAL_STATUS_T passthrough_port_flush(MMAL_PORT_T *port)
82 MMAL_PORT_MODULE_T *port_module = port->priv->module;
83 MMAL_BUFFER_HEADER_T *buffer;
85 /* Flush buffers that our component is holding on to */
86 buffer = mmal_queue_get(port_module->queue);
89 mmal_port_buffer_header_callback(port, buffer);
90 buffer = mmal_queue_get(port_module->queue);
96 /** Disable processing on a port */
97 static MMAL_STATUS_T passthrough_port_disable(MMAL_PORT_T *port)
99 /* We just need to flush our internal queue */
100 return passthrough_port_flush(port);
103 /** Send a buffer header to a port */
104 static MMAL_STATUS_T passthrough_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
106 MMAL_COMPONENT_T *component = port->component;
107 MMAL_COMPONENT_MODULE_T *module = component->priv->module;
108 MMAL_PORT_T **other_port, *in_port, *out_port;
109 MMAL_BUFFER_HEADER_T **other_buffer, *in = 0, *out = 0;
110 MMAL_STATUS_T status;
114 mmal_queue_put(port->priv->module->queue, buffer);
115 return MMAL_SUCCESS; /* Just do nothing */
118 in_port = port->component->input[port->index];
119 out_port = port->component->output[port->index];
121 if (port->type == MMAL_PORT_TYPE_INPUT)
123 other_port = &out_port;
129 other_port = &in_port;
134 /* Get a buffer header from the matching port */
135 *other_buffer = mmal_queue_get((*other_port)->priv->module->queue);
138 /* None available. Just queue the buffer header for now. */
139 mmal_queue_put(port->priv->module->queue, buffer);
143 /* Copy our input buffer header */
144 status = mmal_buffer_header_replicate(out, in);
145 if (status != MMAL_SUCCESS)
148 /* Consume the input buffer */
151 /* Send buffers back */
152 mmal_port_buffer_header_callback(in_port, in);
153 mmal_port_buffer_header_callback(out_port, out);
158 mmal_queue_put(in_port->priv->module->queue, in);
159 mmal_queue_put(out_port->priv->module->queue, out);
160 status = mmal_event_error_send(port->component, status);
161 if (status != MMAL_SUCCESS)
163 LOG_ERROR("unable to send an error event buffer (%i)", (int)status);
170 /** Set format on a port */
171 static MMAL_STATUS_T passthrough_port_format_commit(MMAL_PORT_T *port)
174 if (port->type == MMAL_PORT_TYPE_OUTPUT)
176 LOG_ERROR("output port is read-only");
180 return mmal_format_full_copy(port->component->output[port->index]->format, port->format);
183 static MMAL_STATUS_T passthrough_port_parameter_set(MMAL_PORT_T *port, const MMAL_PARAMETER_HEADER_T *param)
185 MMAL_COMPONENT_T *component = port->component;
186 MMAL_PORT_T *in = component->input[port->index], *out = component->input[port->index];
190 case MMAL_PARAMETER_BUFFER_REQUIREMENTS:
192 /* Propagate the requirements to the matching input and output the ports */
193 const MMAL_PARAMETER_BUFFER_REQUIREMENTS_T *req = (const MMAL_PARAMETER_BUFFER_REQUIREMENTS_T *)param;
194 uint32_t buffer_num_min = MMAL_MAX(port->buffer_num_min, req->buffer_num_min);
195 uint32_t buffer_num_recommended = MMAL_MAX(port->buffer_num_recommended, req->buffer_num_recommended);
196 uint32_t buffer_size_min = MMAL_MAX(port->buffer_size_min, req->buffer_size_min);
197 uint32_t buffer_size_recommended = MMAL_MAX(port->buffer_size_recommended, req->buffer_size_recommended);
199 in->buffer_num_min = buffer_num_min;
200 in->buffer_num_recommended = buffer_num_recommended;
201 in->buffer_size_min = buffer_size_min;
202 in->buffer_size_recommended = buffer_size_recommended;
203 out->buffer_num_min = buffer_num_min;
204 out->buffer_num_recommended = buffer_num_recommended;
205 out->buffer_size_min = buffer_size_min;
206 out->buffer_size_recommended = buffer_size_recommended;
215 /** Create an instance of a component */
216 static MMAL_STATUS_T mmal_component_create_passthrough(const char *name, MMAL_COMPONENT_T *component)
218 MMAL_COMPONENT_MODULE_T *module;
219 MMAL_STATUS_T status = MMAL_ENOMEM;
221 MMAL_PARAM_UNUSED(name);
223 /* Allocate the context for our module */
224 component->priv->module = module = vcos_malloc(sizeof(*module), "mmal module");
227 memset(module, 0, sizeof(*module));
229 component->priv->pf_destroy = passthrough_component_destroy;
231 /* Allocate and initialise all the ports for this component */
232 component->input = mmal_ports_alloc(component, PASSTHROUGH_PORTS_NUM,
233 MMAL_PORT_TYPE_INPUT, sizeof(MMAL_PORT_MODULE_T));
234 if(!component->input)
236 component->input_num = PASSTHROUGH_PORTS_NUM;
237 for(i = 0; i < component->input_num; i++)
239 component->input[i]->priv->pf_enable = passthrough_port_enable;
240 component->input[i]->priv->pf_disable = passthrough_port_disable;
241 component->input[i]->priv->pf_flush = passthrough_port_flush;
242 component->input[i]->priv->pf_send = passthrough_port_send;
243 component->input[i]->priv->pf_set_format = passthrough_port_format_commit;
244 component->input[i]->priv->pf_parameter_set = passthrough_port_parameter_set;
245 component->input[i]->buffer_num_min = 1;
246 component->input[i]->buffer_num_recommended = 0;
247 component->input[i]->priv->module->queue = mmal_queue_create();
248 if(!component->input[i]->priv->module->queue)
252 component->output = mmal_ports_alloc(component, PASSTHROUGH_PORTS_NUM,
253 MMAL_PORT_TYPE_OUTPUT, sizeof(MMAL_PORT_MODULE_T));
254 if(!component->output)
256 component->output_num = PASSTHROUGH_PORTS_NUM;
257 for(i = 0; i < component->output_num; i++)
259 component->output[i]->priv->pf_enable = passthrough_port_enable;
260 component->output[i]->priv->pf_disable = passthrough_port_disable;
261 component->output[i]->priv->pf_flush = passthrough_port_flush;
262 component->output[i]->priv->pf_send = passthrough_port_send;
263 component->output[i]->priv->pf_set_format = passthrough_port_format_commit;
264 component->output[i]->priv->pf_parameter_set = passthrough_port_parameter_set;
265 component->output[i]->buffer_num_min = 1;
266 component->output[i]->buffer_num_recommended = 0;
267 component->output[i]->capabilities = MMAL_PORT_CAPABILITY_PASSTHROUGH;
268 component->output[i]->priv->module->queue = mmal_queue_create();
269 if(!component->output[i]->priv->module->queue)
276 passthrough_component_destroy(component);
280 MMAL_CONSTRUCTOR(mmal_register_component_passthrough);
281 void mmal_register_component_passthrough(void)
283 mmal_component_supplier_register("passthrough", mmal_component_create_passthrough);