From 400a44e56bd35b57940abe1e016300d7dd0ef522 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Wed, 25 Jul 2018 17:28:02 +0100 Subject: [PATCH 1/5] hello_pi: encode: Use portdef for generating the test card It was using assumed knowledge of the padding instead. The requirements on video_encode have recently been reduced and the assumptions were therefore invalid and caused a segfault --- .../linux/apps/hello_pi/hello_encode/encode.c | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/host_applications/linux/apps/hello_pi/hello_encode/encode.c b/host_applications/linux/apps/hello_pi/hello_encode/encode.c index 7acb54b5f..23f83ee50 100644 --- a/host_applications/linux/apps/hello_pi/hello_encode/encode.c +++ b/host_applications/linux/apps/hello_pi/hello_encode/encode.c @@ -38,34 +38,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define NUMFRAMES 300 #define WIDTH 640 -#define PITCH ((WIDTH+31)&~31) #define HEIGHT ((WIDTH)*9/16) -#define HEIGHT16 ((HEIGHT+15)&~15) -#define SIZE ((WIDTH * HEIGHT16 * 3)/2) // generate an animated test card in YUV format static int -generate_test_card(void *buf, OMX_U32 * filledLen, int frame) +generate_test_card(void *buf, OMX_U32 * filledLen, int frame, OMX_PARAM_PORTDEFINITIONTYPE *def) { int i, j; - char *y = buf, *u = y + PITCH * HEIGHT16, *v = - u + (PITCH >> 1) * (HEIGHT16 >> 1); - - for (j = 0; j < HEIGHT / 2; j++) { - char *py = y + 2 * j * PITCH; - char *pu = u + j * (PITCH >> 1); - char *pv = v + j * (PITCH >> 1); - for (i = 0; i < WIDTH / 2; i++) { - int z = (((i + frame) >> 4) ^ ((j + frame) >> 4)) & 15; - py[0] = py[1] = py[PITCH] = py[PITCH + 1] = 0x80 + z * 0x8; - pu[0] = 0x00 + z * 0x10; - pv[0] = 0x80 + z * 0x30; - py += 2; - pu++; - pv++; + OMX_VIDEO_PORTDEFINITIONTYPE *vid = &def->format.video; + char *y = buf; + char *u = y + vid->nStride * vid->nSliceHeight; + char *v = u + (vid->nStride >> 1) * (vid->nSliceHeight >> 1); + + for (j = 0; j < vid->nFrameHeight / 2; j++) { + char *py = y + 2 * j * vid->nStride; + char *pu = u + j * (vid->nStride >> 1); + char *pv = v + j * (vid->nStride >> 1); + for (i = 0; i < vid->nFrameWidth / 2; i++) { + int z = (((i + frame) >> 4) ^ ((j + frame) >> 4)) & 15; + py[0] = py[1] = py[vid->nStride] = py[vid->nStride + 1] = 0x80 + z * 0x8; + pu[0] = 0x00 + z * 0x10; + pv[0] = 0x80 + z * 0x30; + py += 2; + pu++; + pv++; } } - *filledLen = SIZE; + *filledLen = (vid->nStride * vid->nSliceHeight * 3) >> 1; return 1; } @@ -148,7 +147,7 @@ video_encode_test(char *outputfilename) def.format.video.nFrameWidth = WIDTH; def.format.video.nFrameHeight = HEIGHT; def.format.video.xFramerate = 30 << 16; - def.format.video.nSliceHeight = def.format.video.nFrameHeight; + def.format.video.nSliceHeight = ALIGN_UP(def.format.video.nFrameHeight, 16); def.format.video.nStride = def.format.video.nFrameWidth; def.format.video.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar; From cf4fa331884216901778beee22a716e2dbcbac9d Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Wed, 25 Jul 2018 17:30:57 +0100 Subject: [PATCH 2/5] hello_pi: encode: Process the buffer before returning for filling. The code was calling ilclient_get_output_buffer to retrieve a filled buffer, and then immediately returning it via OMX_FillThisBuffer before looking at the contents. OMX_FillThisBuffer does not block, but relies on waiting for the FillBufferDone callback instead. The correct order of doing things is to call ilclient_get_output_buffer (which waits on FillBufferDone if necessary), process the buffer, and then call OMX_FillThisBuffer to pass it back to OMX for filling again. The recent improvements to video_encode mean that it is faster at processing buffers and would often have reset the buffer header before hello_encode had a chance to save the data. --- .../linux/apps/hello_pi/hello_encode/encode.c | 10 +++++----- host_applications/linux/apps/raspicam/RaspiStill.c | 6 +++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/host_applications/linux/apps/hello_pi/hello_encode/encode.c b/host_applications/linux/apps/hello_pi/hello_encode/encode.c index 23f83ee50..d851e2993 100644 --- a/host_applications/linux/apps/hello_pi/hello_encode/encode.c +++ b/host_applications/linux/apps/hello_pi/hello_encode/encode.c @@ -258,11 +258,6 @@ video_encode_test(char *outputfilename) out = ilclient_get_output_buffer(video_encode, 201, 1); - r = OMX_FillThisBuffer(ILC_GET_HANDLE(video_encode), out); - if (r != OMX_ErrorNone) { - printf("Error filling buffer: %x\n", r); - } - if (out != NULL) { if (out->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { int i; @@ -284,6 +279,11 @@ video_encode_test(char *outputfilename) printf("Not getting it :(\n"); } + r = OMX_FillThisBuffer(ILC_GET_HANDLE(video_encode), out); + if (r != OMX_ErrorNone) { + printf("Error filling buffer: %x\n", r); + } + } } while (framenumber < NUMFRAMES); diff --git a/host_applications/linux/apps/raspicam/RaspiStill.c b/host_applications/linux/apps/raspicam/RaspiStill.c index d980c75be..f4f7526dd 100644 --- a/host_applications/linux/apps/raspicam/RaspiStill.c +++ b/host_applications/linux/apps/raspicam/RaspiStill.c @@ -2065,7 +2065,11 @@ int main(int argc, const char **argv) state.camera_parameters.annotate_string, state.camera_parameters.annotate_text_size, state.camera_parameters.annotate_text_colour, - state.camera_parameters.annotate_bg_colour); + state.camera_parameters.annotate_bg_colour, + state.camera_parameters.annotate_justify, + state.camera_parameters.annotate_x, + state.camera_parameters.annotate_y + ); if (state.verbose) fprintf(stderr, "Starting capture %d\n", frame); From 847754bc326ac69c6abc5893c035133d71562b2d Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Wed, 25 Jul 2018 17:39:20 +0100 Subject: [PATCH 3/5] hello_pi: encode: Clean up indentation to use 3 spaces and no tabs --- .../linux/apps/hello_pi/hello_encode/encode.c | 124 +++++++++--------- 1 file changed, 60 insertions(+), 64 deletions(-) diff --git a/host_applications/linux/apps/hello_pi/hello_encode/encode.c b/host_applications/linux/apps/hello_pi/hello_encode/encode.c index d851e2993..0f2a95a5a 100644 --- a/host_applications/linux/apps/hello_pi/hello_encode/encode.c +++ b/host_applications/linux/apps/hello_pi/hello_encode/encode.c @@ -72,20 +72,20 @@ static void print_def(OMX_PARAM_PORTDEFINITIONTYPE def) { printf("Port %u: %s %u/%u %u %u %s,%s,%s %ux%u %ux%u @%u %u\n", - def.nPortIndex, - def.eDir == OMX_DirInput ? "in" : "out", - def.nBufferCountActual, - def.nBufferCountMin, - def.nBufferSize, - def.nBufferAlignment, - def.bEnabled ? "enabled" : "disabled", - def.bPopulated ? "populated" : "not pop.", - def.bBuffersContiguous ? "contig." : "not cont.", - def.format.video.nFrameWidth, - def.format.video.nFrameHeight, - def.format.video.nStride, - def.format.video.nSliceHeight, - def.format.video.xFramerate, def.format.video.eColorFormat); + def.nPortIndex, + def.eDir == OMX_DirInput ? "in" : "out", + def.nBufferCountActual, + def.nBufferCountMin, + def.nBufferSize, + def.nBufferAlignment, + def.bEnabled ? "enabled" : "disabled", + def.bPopulated ? "populated" : "not pop.", + def.bBuffersContiguous ? "contig." : "not cont.", + def.format.video.nFrameWidth, + def.format.video.nFrameHeight, + def.format.video.nStride, + def.format.video.nSliceHeight, + def.format.video.xFramerate, def.format.video.eColorFormat); } static int @@ -116,13 +116,13 @@ video_encode_test(char *outputfilename) // create video_encode r = ilclient_create_component(client, &video_encode, "video_encode", - ILCLIENT_DISABLE_ALL_PORTS | - ILCLIENT_ENABLE_INPUT_BUFFERS | - ILCLIENT_ENABLE_OUTPUT_BUFFERS); + ILCLIENT_DISABLE_ALL_PORTS | + ILCLIENT_ENABLE_INPUT_BUFFERS | + ILCLIENT_ENABLE_OUTPUT_BUFFERS); if (r != 0) { printf - ("ilclient_create_component() for video_encode failed with %x!\n", - r); + ("ilclient_create_component() for video_encode failed with %x!\n", + r); exit(1); } list[0] = video_encode; @@ -135,9 +135,9 @@ video_encode_test(char *outputfilename) if (OMX_GetParameter (ILC_GET_HANDLE(video_encode), OMX_IndexParamPortDefinition, - &def) != OMX_ErrorNone) { + &def) != OMX_ErrorNone) { printf("%s:%d: OMX_GetParameter() for video_encode port 200 failed!\n", - __FUNCTION__, __LINE__); + __FUNCTION__, __LINE__); exit(1); } @@ -154,11 +154,11 @@ video_encode_test(char *outputfilename) print_def(def); r = OMX_SetParameter(ILC_GET_HANDLE(video_encode), - OMX_IndexParamPortDefinition, &def); + OMX_IndexParamPortDefinition, &def); if (r != OMX_ErrorNone) { printf - ("%s:%d: OMX_SetParameter() for video_encode port 200 failed with %x!\n", - __FUNCTION__, __LINE__, r); + ("%s:%d: OMX_SetParameter() for video_encode port 200 failed with %x!\n", + __FUNCTION__, __LINE__, r); exit(1); } @@ -170,11 +170,11 @@ video_encode_test(char *outputfilename) printf("OMX_SetParameter for video_encode:201...\n"); r = OMX_SetParameter(ILC_GET_HANDLE(video_encode), - OMX_IndexParamVideoPortFormat, &format); + OMX_IndexParamVideoPortFormat, &format); if (r != OMX_ErrorNone) { printf - ("%s:%d: OMX_SetParameter() for video_encode port 201 failed with %x!\n", - __FUNCTION__, __LINE__, r); + ("%s:%d: OMX_SetParameter() for video_encode port 201 failed with %x!\n", + __FUNCTION__, __LINE__, r); exit(1); } @@ -216,8 +216,8 @@ video_encode_test(char *outputfilename) printf("encode to idle...\n"); if (ilclient_change_component_state(video_encode, OMX_StateIdle) == -1) { printf - ("%s:%d: ilclient_change_component_state(video_encode, OMX_StateIdle) failed", - __FUNCTION__, __LINE__); + ("%s:%d: ilclient_change_component_state(video_encode, OMX_StateIdle) failed", + __FUNCTION__, __LINE__); } printf("enabling port buffers for 200...\n"); @@ -245,45 +245,41 @@ video_encode_test(char *outputfilename) do { buf = ilclient_get_input_buffer(video_encode, 200, 1); if (buf == NULL) { - printf("Doh, no buffers for me!\n"); - } - else { - /* fill it */ - generate_test_card(buf->pBuffer, &buf->nFilledLen, framenumber++); - - if (OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_encode), buf) != - OMX_ErrorNone) { - printf("Error emptying buffer!\n"); - } - - out = ilclient_get_output_buffer(video_encode, 201, 1); - - if (out != NULL) { - if (out->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { - int i; - for (i = 0; i < out->nFilledLen; i++) - printf("%x ", out->pBuffer[i]); - printf("\n"); - } - - r = fwrite(out->pBuffer, 1, out->nFilledLen, outf); - if (r != out->nFilledLen) { - printf("fwrite: Error emptying buffer: %d!\n", r); - } - else { - printf("Writing frame %d/%d\n", framenumber, NUMFRAMES); - } - out->nFilledLen = 0; - } - else { - printf("Not getting it :(\n"); - } + printf("Doh, no buffers for me!\n"); + } else { + /* fill it */ + generate_test_card(buf->pBuffer, &buf->nFilledLen, framenumber++, &def); + + if (OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_encode), buf) != + OMX_ErrorNone) { + printf("Error emptying buffer!\n"); + } + + out = ilclient_get_output_buffer(video_encode, 201, 1); + + if (out != NULL) { + if (out->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + int i; + for (i = 0; i < out->nFilledLen; i++) + printf("%x ", out->pBuffer[i]); + printf("\n"); + } + + r = fwrite(out->pBuffer, 1, out->nFilledLen, outf); + if (r != out->nFilledLen) { + printf("fwrite: Error emptying buffer: %d!\n", r); + } else { + printf("Writing frame %d/%d, len %u\n", framenumber, NUMFRAMES, out->nFilledLen); + } + out->nFilledLen = 0; + } else { + printf("Not getting it :(\n"); + } r = OMX_FillThisBuffer(ILC_GET_HANDLE(video_encode), out); if (r != OMX_ErrorNone) { - printf("Error filling buffer: %x\n", r); + printf("Error sending buffer for filling: %x\n", r); } - } } while (framenumber < NUMFRAMES); From 14884587404f4b857d6c3f9cbfd5f7a544348a9c Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Tue, 24 Jul 2018 16:23:19 +0100 Subject: [PATCH 4/5] annotate: Add options to move the text and set justification Adds extra fields to the IL and MMAL parameters to set justification as centre/left/right, and add an x and y offset. Retains backwards compatibility --- interface/mmal/mmal_parameters_camera.h | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/interface/mmal/mmal_parameters_camera.h b/interface/mmal/mmal_parameters_camera.h index 8a8857107..577b7a2cd 100644 --- a/interface/mmal/mmal_parameters_camera.h +++ b/interface/mmal/mmal_parameters_camera.h @@ -782,6 +782,35 @@ typedef struct MMAL_PARAMETER_CAMERA_ANNOTATE_V3_T char text[MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V3]; } MMAL_PARAMETER_CAMERA_ANNOTATE_V3_T; +#define MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V4 256 +typedef struct MMAL_PARAMETER_CAMERA_ANNOTATE_V4_T +{ + MMAL_PARAMETER_HEADER_T hdr; + + MMAL_BOOL_T enable; + MMAL_BOOL_T show_shutter; + MMAL_BOOL_T show_analog_gain; + MMAL_BOOL_T show_lens; + MMAL_BOOL_T show_caf; + MMAL_BOOL_T show_motion; + MMAL_BOOL_T show_frame_num; + MMAL_BOOL_T enable_text_background; + MMAL_BOOL_T custom_background_colour; + uint8_t custom_background_Y; + uint8_t custom_background_U; + uint8_t custom_background_V; + uint8_t dummy1; + MMAL_BOOL_T custom_text_colour; + uint8_t custom_text_Y; + uint8_t custom_text_U; + uint8_t custom_text_V; + uint8_t text_size; + char text[MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V3]; + uint32_t justify; //0=centre, 1=left, 2=right + uint32_t x_offset; //Offset from the justification edge + uint32_t y_offset; +} MMAL_PARAMETER_CAMERA_ANNOTATE_V4_T; + typedef enum MMAL_STEREOSCOPIC_MODE_T { MMAL_STEREOSCOPIC_MODE_NONE = 0, MMAL_STEREOSCOPIC_MODE_SIDE_BY_SIDE = 1, From 9523c6055404ffa648716db022f403a2dca74112 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Wed, 25 Jul 2018 17:43:42 +0100 Subject: [PATCH 5/5] Raspicam: Update for justification and offset in annotation Camera annotation can now support left and right justification of the text, and setting an x and y offset. Update the raspicam apps to allow taking these via the command line. --- .../linux/apps/raspicam/RaspiCamControl.c | 29 ++++++++++++++----- .../linux/apps/raspicam/RaspiCamControl.h | 7 ++++- .../linux/apps/raspicam/RaspiVid.c | 12 ++++++-- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/host_applications/linux/apps/raspicam/RaspiCamControl.c b/host_applications/linux/apps/raspicam/RaspiCamControl.c index 8dd9b7b42..77351c436 100755 --- a/host_applications/linux/apps/raspicam/RaspiCamControl.c +++ b/host_applications/linux/apps/raspicam/RaspiCamControl.c @@ -203,7 +203,7 @@ static COMMAND_LIST cmdline_commands[] = {CommandStereoMode, "-stereo", "3d", "Select stereoscopic mode", 1}, {CommandStereoDecimate,"-decimate","dec", "Half width/height of stereo image"}, {CommandStereoSwap, "-3dswap", "3dswap", "Swap camera order for stereoscopic"}, - {CommandAnnotateExtras,"-annotateex","ae", "Set extra annotation parameters (text size, text colour(hex YUV), bg colour(hex YUV))", 2}, + {CommandAnnotateExtras,"-annotateex","ae", "Set extra annotation parameters (text size, text colour(hex YUV), bg colour(hex YUV), justify, x, y)", 2}, {CommandAnalogGain, "-analoggain", "ag", "Set the analog gain (floating point)", 1}, {CommandDigitalGain, "-digitalgain", "dg", "Set the digital gain (floating point)", 1}, }; @@ -772,9 +772,13 @@ int raspicamcontrol_parse_cmdline(RASPICAM_CAMERA_PARAMETERS *params, const char case CommandAnnotateExtras: { // 3 parameters - text size (6-80), text colour (Hex VVUUYY) and background colour (Hex VVUUYY) - sscanf(arg2, "%u,%X,%X", ¶ms->annotate_text_size, + sscanf(arg2, "%u,%X,%X,%u,%u,%u", ¶ms->annotate_text_size, ¶ms->annotate_text_colour, - ¶ms->annotate_bg_colour); + ¶ms->annotate_bg_colour, + ¶ms->annotate_justify, + ¶ms->annotate_x, + ¶ms->annotate_y + ); used=2; break; } @@ -1065,7 +1069,11 @@ int raspicamcontrol_set_all_parameters(MMAL_COMPONENT_T *camera, const RASPICAM_ result += raspicamcontrol_set_annotate(camera, params->enable_annotate, params->annotate_string, params->annotate_text_size, params->annotate_text_colour, - params->annotate_bg_colour); + params->annotate_bg_colour, + params->annotate_justify, + params->annotate_x, + params->annotate_y + ); result += raspicamcontrol_set_gains(camera, params->analog_gain, params->digital_gain); return result; @@ -1594,16 +1602,17 @@ int raspicamcontrol_set_stats_pass(MMAL_COMPONENT_T *camera, int stats_pass) * @return 0 if successful, non-zero if any parameters out of range */ int raspicamcontrol_set_annotate(MMAL_COMPONENT_T *camera, const int settings, const char *string, - const int text_size, const int text_colour, const int bg_colour) + const int text_size, const int text_colour, const int bg_colour, + const unsigned int justify, const unsigned int x, const unsigned int y) { - MMAL_PARAMETER_CAMERA_ANNOTATE_V3_T annotate = - {{MMAL_PARAMETER_ANNOTATE, sizeof(MMAL_PARAMETER_CAMERA_ANNOTATE_V3_T)}}; + MMAL_PARAMETER_CAMERA_ANNOTATE_V4_T annotate = + {{MMAL_PARAMETER_ANNOTATE, sizeof(MMAL_PARAMETER_CAMERA_ANNOTATE_V4_T)}}; if (settings) { time_t t = time(NULL); struct tm tm = *localtime(&t); - char tmp[MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V3]; + char tmp[MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V4]; int process_datetime = 1; annotate.enable = 1; @@ -1682,6 +1691,10 @@ int raspicamcontrol_set_annotate(MMAL_COMPONENT_T *camera, const int settings, c } else annotate.custom_background_colour = MMAL_FALSE; + + annotate.justify = justify; + annotate.x_offset = x; + annotate.y_offset = y; } else annotate.enable = 0; diff --git a/host_applications/linux/apps/raspicam/RaspiCamControl.h b/host_applications/linux/apps/raspicam/RaspiCamControl.h index 0286d9ff9..c06c539c2 100644 --- a/host_applications/linux/apps/raspicam/RaspiCamControl.h +++ b/host_applications/linux/apps/raspicam/RaspiCamControl.h @@ -163,6 +163,10 @@ typedef struct raspicam_camera_parameters_s int annotate_text_size; // Text size for annotation int annotate_text_colour; // Text colour for annotation int annotate_bg_colour; // Background colour for annotation + unsigned int annotate_justify; + unsigned int annotate_x; + unsigned int annotate_y; + MMAL_PARAMETER_STEREOSCOPIC_MODE_T stereo_mode; float analog_gain; // Analog gain float digital_gain; // Digital gain @@ -210,7 +214,8 @@ int raspicamcontrol_set_shutter_speed(MMAL_COMPONENT_T *camera, int speed_ms); int raspicamcontrol_set_DRC(MMAL_COMPONENT_T *camera, MMAL_PARAMETER_DRC_STRENGTH_T strength); int raspicamcontrol_set_stats_pass(MMAL_COMPONENT_T *camera, int stats_pass); int raspicamcontrol_set_annotate(MMAL_COMPONENT_T *camera, const int bitmask, const char *string, - const int text_size, const int text_colour, const int bg_colour); + const int text_size, const int text_colour, const int bg_colour, + const unsigned int justify, const unsigned int x, const unsigned int y); int raspicamcontrol_set_stereo_mode(MMAL_PORT_T *port, MMAL_PARAMETER_STEREOSCOPIC_MODE_T *stereo_mode); int raspicamcontrol_set_gains(MMAL_COMPONENT_T *camera, float analog, float digital); diff --git a/host_applications/linux/apps/raspicam/RaspiVid.c b/host_applications/linux/apps/raspicam/RaspiVid.c index 6340e13e6..0352cbde8 100755 --- a/host_applications/linux/apps/raspicam/RaspiVid.c +++ b/host_applications/linux/apps/raspicam/RaspiVid.c @@ -1258,7 +1258,11 @@ static void update_annotation_data(RASPIVID_STATE *state) raspicamcontrol_set_annotate(state->camera_component, state->camera_parameters.enable_annotate, text, state->camera_parameters.annotate_text_size, state->camera_parameters.annotate_text_colour, - state->camera_parameters.annotate_bg_colour); + state->camera_parameters.annotate_bg_colour, + state->camera_parameters.annotate_justify, + state->camera_parameters.annotate_x, + state->camera_parameters.annotate_y + ); free(text); } @@ -1267,7 +1271,11 @@ static void update_annotation_data(RASPIVID_STATE *state) raspicamcontrol_set_annotate(state->camera_component, state->camera_parameters.enable_annotate, state->camera_parameters.annotate_string, state->camera_parameters.annotate_text_size, state->camera_parameters.annotate_text_colour, - state->camera_parameters.annotate_bg_colour); + state->camera_parameters.annotate_bg_colour, + state->camera_parameters.annotate_justify, + state->camera_parameters.annotate_x, + state->camera_parameters.annotate_y + ); } }