nan20
Posts: 6
Joined: Sun Jan 03, 2016 10:01 am

Getting corrupted images for different resolution

Tue Jan 05, 2016 3:32 pm

Hi all ,

I am using the c++ API to interface with the pi camera , works fine but there is an issue with it , i get corrupted images when in my resolution width is not divisible by 32 or height is not divisible by 16. For example when i give my resolution as 752 by 160 with 752 not being divisible by 32 i get a corrupted image. Works fine for resolutions like - 160 by 160 , 768 by 160 , 640 by 480 etc .

Create camera component function in the API

Code: Select all

   MMAL_COMPONENT_T *Private_Impl::create_camera_component ( RASPIVID_STATE *state ) {
            MMAL_COMPONENT_T *camera = 0;
            MMAL_ES_FORMAT_T *format;
            MMAL_PORT_T  *video_port = NULL;

            MMAL_STATUS_T status;
            /* Create the component */
            status = mmal_component_create ( MMAL_COMPONENT_DEFAULT_CAMERA, &camera );

            if ( status != MMAL_SUCCESS ) {
                cerr<< ( "Failed to create camera component" );
                return 0;
            }

            if ( !camera->output_num ) {
                cerr<< ( "Camera doesn't have output ports" );
                mmal_component_destroy ( camera );
                return 0;
            }

            video_port = camera->output[MMAL_CAMERA_VIDEO_PORT];

            //  set up the camera configuration

            MMAL_PARAMETER_CAMERA_CONFIG_T cam_config;
            cam_config.hdr.id=MMAL_PARAMETER_CAMERA_CONFIG;
            cam_config.hdr.size=sizeof ( cam_config );
            cam_config.max_stills_w = state->width;
            cam_config.max_stills_h = state->height;
            cam_config.stills_yuv422 = 0;
            cam_config.one_shot_stills = 0;
            cam_config.max_preview_video_w = state->width;
            cam_config.max_preview_video_h = state->height;
            cam_config.num_preview_video_frames = 3;
            cam_config.stills_capture_circular_buffer_height = 0;
            cam_config.fast_preview_resume = 0;
            cam_config.use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC;
            mmal_port_parameter_set ( camera->control, &cam_config.hdr );

            // Set the encode format on the video  port

            format = video_port->format;
            format->encoding_variant =   convertFormat ( State.captureFtm );
            format->encoding = convertFormat ( State.captureFtm );
            format->es->video.width = VCOS_ALIGN_UP(state->width, 32);
            format->es->video.height = VCOS_ALIGN_UP(state->height, 16);
            format->es->video.crop.x = 0;
            format->es->video.crop.y = 0;
            format->es->video.crop.width = state->width;
            format->es->video.crop.height = state->height;
            format->es->video.frame_rate.num = state->framerate;
            format->es->video.frame_rate.den = VIDEO_FRAME_RATE_DEN;

            status = mmal_port_format_commit ( video_port );
            if ( status ) {
                cerr<< ( "camera video format couldn't be set" );
                mmal_component_destroy ( camera );
                return 0;
            }

            // PR : plug the callback to the video port
            status = mmal_port_enable ( video_port,video_buffer_callback );
            if ( status ) {
                cerr<< ( "camera video callback2 error" );
                mmal_component_destroy ( camera );
                return 0;
            }

            // Ensure there are enough buffers to avoid dropping frames
            if ( video_port->buffer_num < VIDEO_OUTPUT_BUFFERS_NUM )
                video_port->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM;



            //PR : create pool of message on video port
            MMAL_POOL_T *pool;
            video_port->buffer_size = video_port->buffer_size_recommended;
            video_port->buffer_num = video_port->buffer_num_recommended;
            pool = mmal_port_pool_create ( video_port, video_port->buffer_num, video_port->buffer_size );
            if ( !pool ) {
                cerr<< ( "Failed to create buffer header pool for video output port" );
            }
            state->video_pool = pool;


            /* Enable component */
            status = mmal_component_enable ( camera );

            if ( status ) {
                cerr<< ( "camera component couldn't be enabled" );
                mmal_component_destroy ( camera );
                return 0;
            }

            state->camera_component = camera;//this needs to be before set_all_parameters

            return camera;
        }


Is there any changes need to be made so that it works fine for all resolutions.

Thanks

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 9069
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: Getting corrupted images for different resolution

Tue Jan 05, 2016 4:09 pm

How are you interpreting the data? I think what you haven't grasped is the concept of stride or pitch of an image - eg https://msdn.microsoft.com/en-us/librar ... 85%29.aspx

Note in the code:
format->es->video.width = VCOS_ALIGN_UP(state->width, 32);
format->es->video.height = VCOS_ALIGN_UP(state->height, 16);
...
format->es->video.crop.width = state->width;
format->es->video.crop.height = state->height;
width and height set the overall dimensions (stride and plane height) of the overall buffer. crop.width and crop.height set the size of the active part of that image buffer.

If you felt really brave, there is a parameter of MMAL_PARAMETER_NO_IMAGE_PADDING that you can set on a port. That allows you to set stride to the same value as width, although the total buffer size has to be the same as with the padding as it is removed as a second pass over the image (it therefore has a performance hit too). The V4L2 driver uses this as I couldn't find a way to tell V4L2 about the padding.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

nan20
Posts: 6
Joined: Sun Jan 03, 2016 10:01 am

Re: Getting corrupted images for different resolution

Tue Jan 05, 2016 5:21 pm

6by9 wrote:How are you interpreting the data? I think what you haven't grasped is the concept of stride or pitch of an image - eg https://msdn.microsoft.com/en-us/librar ... 85%29.aspx

Note in the code:
format->es->video.width = VCOS_ALIGN_UP(state->width, 32);
format->es->video.height = VCOS_ALIGN_UP(state->height, 16);
...
format->es->video.crop.width = state->width;
format->es->video.crop.height = state->height;
width and height set the overall dimensions (stride and plane height) of the overall buffer. crop.width and crop.height set the size of the active part of that image buffer.

If you felt really brave, there is a parameter of MMAL_PARAMETER_NO_IMAGE_PADDING that you can set on a port. That allows you to set stride to the same value as width, although the total buffer size has to be the same as with the padding as it is removed as a second pass over the image (it therefore has a performance hit too). The V4L2 driver uses this as I couldn't find a way to tell V4L2 about the padding.

thanks for the reply , i am quite unaware about a lot of things in camera prog , kindly excuse me for that. So it is the extra padding bytes that effects the image , i want to understand from you format->es->video.width & format->es->video.height sets the height & width of the overall buffer which will include padding bytes , so they are being read from VCOS_ALIGN_UP(state->width, 32) & VCOS_ALIGN_UP(state->height, 16) ..what does VCOS_ALIGN_UP function basically do ?

If i have a resolution of 750 by 150 and i set my overall buffer size larger than that using format->es->video.width & format->es->video.height , and keep my buffer.crop.width & buffer.crop.height to my actual resolution (750 by 150) will that resolve it ? I mean can we play around these parameters and make it work for an odd resolution like 750 by 150.

Might have to look at MMAL_PARAMETER_NO_IMAGE_PADDING if this doesn't work. :)

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 9069
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: Getting corrupted images for different resolution

Tue Jan 05, 2016 5:53 pm

https://github.com/raspberrypi/userland ... pes.h#L204

Code: Select all

#define VCOS_ALIGN_DOWN(p,n) (((ptrdiff_t)(p)) & ~((n)-1))
#define VCOS_ALIGN_UP(p,n) VCOS_ALIGN_DOWN((ptrdiff_t)(p)+(n)-1,(n))
Actually defined in a more complex way than it could be, but in simple terms it aligns the value up to the next multiple of the second parameter.

If crop.width/height is 750,150, then width and height will be rounded up to 768,160. Only the first 750 pixels of each line of 768 will contain image data. The last 10 lines of the image will also be random.
If you are using I420, then the U plane will start at offset 768*160 = 122,880. The V plane will start at 768*160 + (768/2 * 160/2) = 153,600 bytes.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

nan20
Posts: 6
Joined: Sun Jan 03, 2016 10:01 am

Re: Getting corrupted images for different resolution

Tue Jan 05, 2016 5:59 pm

6by9 wrote:https://github.com/raspberrypi/userland ... pes.h#L204

Code: Select all

#define VCOS_ALIGN_DOWN(p,n) (((ptrdiff_t)(p)) & ~((n)-1))
#define VCOS_ALIGN_UP(p,n) VCOS_ALIGN_DOWN((ptrdiff_t)(p)+(n)-1,(n))
Actually defined in a more complex way than it could be, but in simple terms it aligns the value up to the next multiple of the second parameter.

If crop.width/height is 750,150, then width and height will be rounded up to 768,160. Only the first 750 pixels of each line of 768 will contain image data. The last 10 lines of the image will also be random.
If you are using I420, then the U plane will start at offset 768*160 = 122,880. The V plane will start at 768*160 + (768/2 * 160/2) = 153,600 bytes.
Thanks a bunch , i will try this and see how it works , i am using rgb color space.

Return to “Camera board”