1 /*
2 Copyright (c) 2013, Broadcom Europe Ltd
3 Copyright (c) 2013, James Hughes
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 * Neither the name of the copyright holder nor the
14 names of its contributors may be used to endorse or promote products
15 derived from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <memory.h>
33
34 #include "interface/vcos/vcos.h"
35
36 #include "interface/mmal/mmal.h"
37 #include "interface/mmal/mmal_logging.h"
38 #include "interface/mmal/mmal_buffer.h"
39 #include "interface/mmal/util/mmal_util.h"
40 #include "interface/mmal/util/mmal_util_params.h"
41 #include "interface/mmal/util/mmal_default_components.h"
42 #include "interface/mmal/util/mmal_connection.h"
43
44 #include "RaspiPreview.h"
45 #include "RaspiCLI.h"
46
47 enum
48 {
49 CommandPreview,
50 CommandFullScreen,
51 CommandOpacity,
52 CommandDisablePreview
53 };
54
55 static COMMAND_LIST cmdline_commands[] =
56 {
57 { CommandPreview, "-preview", "p", "Preview window settings <'x,y,w,h'>", 1 },
58 { CommandFullScreen, "-fullscreen", "f", "Fullscreen preview mode", 0 },
59 { CommandOpacity, "-opacity", "op", "Preview window opacity (0-255)", 1},
60 { CommandDisablePreview,"-nopreview", "n", "Do not display a preview window", 0},
61 };
62
63 static int cmdline_commands_size = sizeof(cmdline_commands) / sizeof(cmdline_commands[0]);
64
65 /**
66 * Create the preview component, set up its ports
67 *
68 * @param state Pointer to state control struct
69 *
70 * @return MMAL_SUCCESS if all OK, something else otherwise
71 *
72 */
raspipreview_create(RASPIPREVIEW_PARAMETERS * state)73 MMAL_STATUS_T raspipreview_create(RASPIPREVIEW_PARAMETERS *state)
74 {
75 MMAL_COMPONENT_T *preview = 0;
76 MMAL_PORT_T *preview_port = NULL;
77 MMAL_STATUS_T status;
78
79 if (!state->wantPreview)
80 {
81 // No preview required, so create a null sink component to take its place
82 status = mmal_component_create("vc.null_sink", &preview);
83
84 if (status != MMAL_SUCCESS)
85 {
86 vcos_log_error("Unable to create null sink component");
87 goto error;
88 }
89 }
90 else
91 {
92 status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER,
93 &preview);
94
95 if (status != MMAL_SUCCESS)
96 {
97 vcos_log_error("Unable to create preview component");
98 goto error;
99 }
100
101 if (!preview->input_num)
102 {
103 status = MMAL_ENOSYS;
104 vcos_log_error("No input ports found on component");
105 goto error;
106 }
107
108 preview_port = preview->input[0];
109
110 MMAL_DISPLAYREGION_T param;
111 param.hdr.id = MMAL_PARAMETER_DISPLAYREGION;
112 param.hdr.size = sizeof(MMAL_DISPLAYREGION_T);
113
114 param.set = MMAL_DISPLAY_SET_LAYER;
115 param.layer = PREVIEW_LAYER;
116
117 param.set |= MMAL_DISPLAY_SET_ALPHA;
118 param.alpha = state->opacity;
119
120 if (state->wantFullScreenPreview)
121 {
122 param.set |= MMAL_DISPLAY_SET_FULLSCREEN;
123 param.fullscreen = 1;
124 }
125 else
126 {
127 param.set |= (MMAL_DISPLAY_SET_DEST_RECT | MMAL_DISPLAY_SET_FULLSCREEN);
128 param.fullscreen = 0;
129 param.dest_rect = state->previewWindow;
130 }
131
132 status = mmal_port_parameter_set(preview_port, ¶m.hdr);
133
134 if (status != MMAL_SUCCESS && status != MMAL_ENOSYS)
135 {
136 vcos_log_error("unable to set preview port parameters (%u)", status);
137 goto error;
138 }
139 }
140
141 /* Enable component */
142 status = mmal_component_enable(preview);
143
144 if (status != MMAL_SUCCESS)
145 {
146 vcos_log_error("Unable to enable preview/null sink component (%u)", status);
147 goto error;
148 }
149
150 state->preview_component = preview;
151
152 return status;
153
154 error:
155
156 if (preview)
157 mmal_component_destroy(preview);
158
159 return status;
160 }
161
162 /**
163 * Destroy the preview component
164 *
165 * @param state Pointer to state control struct
166 *
167 */
raspipreview_destroy(RASPIPREVIEW_PARAMETERS * state)168 void raspipreview_destroy(RASPIPREVIEW_PARAMETERS *state)
169 {
170 if (state->preview_component)
171 {
172 mmal_component_destroy(state->preview_component);
173 state->preview_component = NULL;
174 }
175 }
176
177 /**
178 * Assign set of default parameters to the passed in parameter block
179 *
180 * @param state Pointer to parameter block
181 *
182 */
raspipreview_set_defaults(RASPIPREVIEW_PARAMETERS * state)183 void raspipreview_set_defaults(RASPIPREVIEW_PARAMETERS *state)
184 {
185 state->wantPreview = 1;
186 state->wantFullScreenPreview = 1;
187 state->opacity = 255;
188 state->previewWindow.x = 0;
189 state->previewWindow.y = 0;
190 state->previewWindow.width = 1024;
191 state->previewWindow.height = 768;
192 state->preview_component = NULL;
193 }
194
195 /**
196 * Dump parameters as human readable to stdout
197 *
198 * @param state Pointer to parameter block
199 *
200 */
raspipreview_dump_parameters(RASPIPREVIEW_PARAMETERS * state)201 void raspipreview_dump_parameters(RASPIPREVIEW_PARAMETERS *state)
202 {
203 fprintf(stderr, "Preview %s, Full screen %s\n", state->wantPreview ? "Yes" : "No",
204 state->wantFullScreenPreview ? "Yes" : "No");
205
206 fprintf(stderr, "Preview window %d,%d,%d,%d\nOpacity %d\n", state->previewWindow.x,
207 state->previewWindow.y, state->previewWindow.width,
208 state->previewWindow.height, state->opacity);
209 };
210
211 /**
212 * Parse a possible command pair - command and parameter
213 * @param arg1 Command
214 * @param arg2 Parameter (could be NULL)
215 * @return How many parameters were used, 0,1,2
216 */
raspipreview_parse_cmdline(RASPIPREVIEW_PARAMETERS * params,const char * arg1,const char * arg2)217 int raspipreview_parse_cmdline(RASPIPREVIEW_PARAMETERS *params, const char *arg1, const char *arg2)
218 {
219 int command_id, used = 0, num_parameters;
220
221 if (!arg1)
222 return 0;
223
224 command_id = raspicli_get_command_id(cmdline_commands, cmdline_commands_size, arg1, &num_parameters);
225
226 // If invalid command, or we are missing a parameter, drop out
227 if (command_id==-1 || (command_id != -1 && num_parameters > 0 && arg2 == NULL))
228 return 0;
229
230 switch (command_id)
231 {
232 case CommandPreview: // Preview window
233 {
234 int tmp;
235
236 params->wantPreview = 1;
237
238 tmp = sscanf(arg2, "%d,%d,%d,%d",
239 ¶ms->previewWindow.x, ¶ms->previewWindow.y,
240 ¶ms->previewWindow.width, ¶ms->previewWindow.height);
241
242 // Failed to get any window parameters, so revert to full screen
243 if (tmp == 0)
244 params->wantFullScreenPreview = 1;
245 else
246 params->wantFullScreenPreview = 0;
247
248 used = 2;
249
250 break;
251 }
252
253 case CommandFullScreen: // Want full screen preview mode (overrides display rect)
254 params->wantPreview = 1;
255 params->wantFullScreenPreview = 1;
256
257 used = 1;
258 break;
259
260 case CommandOpacity: // Define preview window opacity
261 if (sscanf(arg2, "%u", ¶ms->opacity) != 1)
262 params->opacity = 255;
263 else
264 used = 2;
265 break;
266
267 case CommandDisablePreview: // Turn off preview output
268 params->wantPreview = 0;
269 used = 1;
270 break;
271 }
272
273 return used;
274 }
275
276 /**
277 * Display help for command line options
278 */
raspipreview_display_help()279 void raspipreview_display_help()
280 {
281 fprintf(stdout, "\nPreview parameter commands\n\n");
282 raspicli_display_help(cmdline_commands, cmdline_commands_size);
283 }
284