| 1 | /* |
| 2 | Copyright (c) 2012, Broadcom Europe Ltd |
| 3 | All rights reserved. |
| 4 | |
| 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. |
| 15 | |
| 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. |
| 26 | */ |
| 27 | |
| 28 | #include "mmal.h" |
| 29 | #include "core/mmal_component_private.h" |
| 30 | #include "core/mmal_port_private.h" |
| 31 | #include "util/mmal_graph.h" |
| 32 | #include "mmal_logging.h" |
| 33 | |
| 34 | #define AGGREGATOR_PREFIX "aggregator" |
| 35 | #define AGGREGATOR_PIPELINE_PREFIX "pipeline" |
| 36 | |
| 37 | typedef struct MMAL_GRAPH_USERDATA_T { |
| 38 | int dummy; |
| 39 | } MMAL_GRAPH_USERDATA_T; |
| 40 | |
| 41 | static MMAL_STATUS_T aggregator_parameter_set(MMAL_GRAPH_T *graph, |
| 42 | MMAL_PORT_T *port, const MMAL_PARAMETER_HEADER_T *param) |
| 43 | { |
| 44 | MMAL_PARAM_UNUSED(graph); |
| 45 | MMAL_PARAM_UNUSED(port); |
| 46 | MMAL_PARAM_UNUSED(param); |
| 47 | LOG_TRACE("graph %p, port %p, param %p" , graph, port, param); |
| 48 | return MMAL_ENOSYS; |
| 49 | } |
| 50 | |
| 51 | static MMAL_STATUS_T aggregator_parameter_get(MMAL_GRAPH_T *graph, |
| 52 | MMAL_PORT_T *port, MMAL_PARAMETER_HEADER_T *param) |
| 53 | { |
| 54 | MMAL_PARAM_UNUSED(graph); |
| 55 | MMAL_PARAM_UNUSED(port); |
| 56 | MMAL_PARAM_UNUSED(param); |
| 57 | LOG_TRACE("graph %p, port %p, param %p" , graph, port, param); |
| 58 | return MMAL_ENOSYS; |
| 59 | } |
| 60 | |
| 61 | /** Create an instance of a component */ |
| 62 | static MMAL_STATUS_T mmal_component_create_aggregator_pipeline(const char *full_name, |
| 63 | const char *component_names, MMAL_COMPONENT_T *component) |
| 64 | { |
| 65 | MMAL_GRAPH_T *graph = 0; |
| 66 | MMAL_COMPONENT_T *subcomponent[2] = {0}; |
| 67 | MMAL_STATUS_T status = MMAL_ENOMEM; |
| 68 | unsigned int length; |
| 69 | char *orig, *names; |
| 70 | |
| 71 | length = strlen(component_names); |
| 72 | names = orig = vcos_calloc(1, length + 1, "mmal aggregator" ); |
| 73 | if (!names) |
| 74 | goto error; |
| 75 | memcpy(names, component_names, length); |
| 76 | |
| 77 | /* We'll build the aggregator using a graph */ |
| 78 | status = mmal_graph_create(&graph, sizeof(MMAL_GRAPH_USERDATA_T)); |
| 79 | if (status != MMAL_SUCCESS) |
| 80 | goto error; |
| 81 | graph->pf_parameter_get = aggregator_parameter_get; |
| 82 | graph->pf_parameter_set = aggregator_parameter_set; |
| 83 | |
| 84 | /* Iterate through all the specified components */ |
| 85 | while (*names) |
| 86 | { |
| 87 | MMAL_CONNECTION_T *connection; |
| 88 | const char *name; |
| 89 | |
| 90 | /* Switch to a new connection */ |
| 91 | if (subcomponent[0]) |
| 92 | mmal_component_destroy(subcomponent[0]); |
| 93 | subcomponent[0] = subcomponent[1]; |
| 94 | subcomponent[1] = 0; |
| 95 | |
| 96 | /* Extract the name of the next component */ |
| 97 | for (name = names; *names && *names != ':'; names++); |
| 98 | |
| 99 | /* Replace the separator */ |
| 100 | if (*names) |
| 101 | *(names++) = 0; |
| 102 | |
| 103 | /* Skip empty strings */ |
| 104 | if (!*name) |
| 105 | continue; |
| 106 | |
| 107 | status = mmal_component_create(name, &subcomponent[1]); |
| 108 | if (status != MMAL_SUCCESS) |
| 109 | goto error; |
| 110 | |
| 111 | status = mmal_graph_add_component(graph, subcomponent[1]); |
| 112 | if (status != MMAL_SUCCESS) |
| 113 | goto error; |
| 114 | |
| 115 | /* Special case for dealing with the first component in the chain */ |
| 116 | if (!subcomponent[0]) |
| 117 | { |
| 118 | /* Add first input port if any */ |
| 119 | if (subcomponent[1]->input_num) |
| 120 | { |
| 121 | status = mmal_graph_add_port(graph, subcomponent[1]->input[0]); |
| 122 | if (status != MMAL_SUCCESS) |
| 123 | goto error; |
| 124 | } |
| 125 | continue; |
| 126 | } |
| 127 | |
| 128 | /* Create connection between the 2 ports */ |
| 129 | if (subcomponent[0]->output_num < 1 || subcomponent[1]->input_num < 1) |
| 130 | goto error; |
| 131 | status = mmal_connection_create(&connection, subcomponent[0]->output[0], |
| 132 | subcomponent[1]->input[0], 0); |
| 133 | if (status != MMAL_SUCCESS) |
| 134 | goto error; |
| 135 | |
| 136 | status = mmal_graph_add_connection(graph, connection); |
| 137 | /* Now the connection is added to the graph we don't care about it anymore */ |
| 138 | mmal_connection_destroy(connection); |
| 139 | if (status != MMAL_SUCCESS) |
| 140 | goto error; |
| 141 | } |
| 142 | |
| 143 | /* Add last output port if any */ |
| 144 | if (subcomponent[1] && subcomponent[1]->output_num && subcomponent[1]->output[0]) |
| 145 | { |
| 146 | status = mmal_graph_add_port(graph, subcomponent[1]->output[0]); |
| 147 | if (status != MMAL_SUCCESS) |
| 148 | goto error; |
| 149 | } |
| 150 | |
| 151 | /* Build the graph */ |
| 152 | component->priv->module = (struct MMAL_COMPONENT_MODULE_T *)graph; |
| 153 | status = mmal_graph_component_constructor(full_name, component); |
| 154 | if (status != MMAL_SUCCESS) |
| 155 | goto error; |
| 156 | |
| 157 | end: |
| 158 | if (subcomponent[0]) |
| 159 | mmal_component_destroy(subcomponent[0]); |
| 160 | if (subcomponent[1]) |
| 161 | mmal_component_destroy(subcomponent[1]); |
| 162 | vcos_free(orig); |
| 163 | return status; |
| 164 | |
| 165 | error: |
| 166 | if (graph) |
| 167 | mmal_graph_destroy(graph); |
| 168 | goto end; |
| 169 | } |
| 170 | |
| 171 | /** Create an instance of a component */ |
| 172 | static MMAL_STATUS_T mmal_component_create_aggregator(const char *name, MMAL_COMPONENT_T *component) |
| 173 | { |
| 174 | const char *stripped = name + sizeof(AGGREGATOR_PREFIX); |
| 175 | |
| 176 | /* Select the requested aggregator */ |
| 177 | if (!strncmp(stripped, AGGREGATOR_PIPELINE_PREFIX ":" , sizeof(AGGREGATOR_PIPELINE_PREFIX))) |
| 178 | return mmal_component_create_aggregator_pipeline(name, |
| 179 | stripped + sizeof(AGGREGATOR_PIPELINE_PREFIX), component); |
| 180 | |
| 181 | return MMAL_ENOSYS; |
| 182 | } |
| 183 | |
| 184 | MMAL_CONSTRUCTOR(mmal_register_component_aggregator); |
| 185 | void mmal_register_component_aggregator(void) |
| 186 | { |
| 187 | mmal_component_supplier_register(AGGREGATOR_PREFIX, mmal_component_create_aggregator); |
| 188 | } |
| 189 | |