Page 1 of 1

Encoding vs encoding_variant

Posted: Mon Sep 10, 2018 9:01 am
by longo92
Hi, someone can tell me the differences on those parameters in mmal port?

Re: Encoding vs encoding_variant

Posted: Mon Sep 10, 2018 9:28 am
by 6by9
It's relevant if using encoding = MMAL_ENCODING_OPAQUE, or a compressed format, and there are options available.

The main example is on the camera component where you may wish to optimally connect output[2] to image_encode with "encoding = MMAL_ENCODING_OPAQUE", but want YUV422 data to encode. Set "encoding_variant = MMAL_ENCODING_I422" and you'd get that outcome, otherwise the camera component will default to YUV420.

There's a similar one with image_encode where the output port sets up whether the encoded data is meant to be YUV420 or YUV422, as the JPEG codec can subsample 422 down to 420 on the fly, or upsample 420 to 422. "encoding = MMAL_ENCODING_JPEG", "encoding_variant = MMAL_ENCODING_I422"

Re: Encoding vs encoding_variant

Posted: Mon Sep 10, 2018 10:13 am
by longo92
Thanks!! i have another question about MMAL_ZERO_COPY : is it used for passing only the buffer's pointer between components instead of the entire buffer data ? If i have a callaback on output port of a component where zero-copy is enabled can i access to buffer->data or it is allocated in gpu memory (resulting impossible to access) ?

Re: Encoding vs encoding_variant

Posted: Mon Sep 10, 2018 10:25 am
by 6by9
longo92 wrote:
Mon Sep 10, 2018 10:13 am
Thanks!! i have another question about MMAL_ZERO_COPY : is it used for passing only the buffer's pointer between components instead of the entire buffer data ? If i have a callaback on output port of a component where zero-copy is enabled can i access to buffer->data or it is allocated in gpu memory (resulting impossible to access) ?
Zero copy stems from the origins of the SoC as a multimedia co-processor with some arbitrary comms channel back to the host processor (ie the ARM), using the VCHIQ API.
That comms channel effectively enforced a copy of the buffer contents from GPU memory to ARM memory.

MMAL_PARAMETER_ZERO_COPY takes advantage of the fact that on the Pi the GPU and ARM share the same physical RAM.
The allocation is done from the GPU's memory allocation, but those addresses are then mapped into the ARM MMU. There is then a small amount of rejigging done so that the GPU gets the buffer handle it requires, and your userland app gets passed the ARM mapped address that allows you to read and write the buffer. Nothing extra needs to be done in your application, except that the buffer pool MUST be allocated using mmal_port_pool_create instead of mmal_pool_create.

Re: Encoding vs encoding_variant

Posted: Mon Sep 10, 2018 10:34 am
by longo92
Ok, i got it. So it gives you a small performance advantage when is used, right?
mmal_buffer_header_mem_lock/unlock performs the memory conversion from gpu to cpu?

Re: Encoding vs encoding_variant

Posted: Mon Sep 10, 2018 11:01 am
by 6by9
longo92 wrote:
Mon Sep 10, 2018 10:34 am
Ok, i got it. So it gives you a small performance advantage when is used, right?
It gives you a big performance increase as long as you can cope with having your buffers allocated in a particular manner.
When you pass the buffer back and forth you only need a cache flush or invalidate (depending on direction) rather than copying potentially multiple megabytes of data (1080P RGBA frame is 8MB).
longo92 wrote:
Mon Sep 10, 2018 10:34 am
mmal_buffer_header_mem_lock/unlock performs the memory conversion from gpu to cpu?
Er, the implementation of mmal_buffer_header_mem_lock
https://github.com/raspberrypi/userland ... fer.c#L157

Code: Select all

MMAL_STATUS_T mmal_buffer_header_mem_lock(MMAL_BUFFER_HEADER_T *header)
{
#ifdef __VIDEOCORE__
   uint8_t *data = mem_lock((MEM_HANDLE_T)header->data);
   if (!data)
      return MMAL_EINVAL;
   header->priv->payload_handle = (void *)header->data;
   header->data = data;
#else
   MMAL_PARAM_UNUSED(header);
#endif

   return MMAL_SUCCESS;
}
__VIDEOCORE__ is NOT defined on the ARM, so it's a nop. There is no need to call mmal_buffer_header_mem_lock/unlock on the ARM ever.
Please remember that the MMAL core code is common with the VideoCore GPU, and there the buffers are passed with buffer->data being an opaque handle, and hence mem_lock needs to be called to get the correct address pointer.

The magic is being done in https://github.com/raspberrypi/userland ... l_vc_shm.c
mmal_vc_shm_alloc is being called to allocate the buffer, so the allocation occurs via vcsm, and a list entry populated via mmal_vc_payload_list_get.
When the buffer is passed up from the GPU, mmal_vc_shm_lock gets called from https://github.com/raspberrypi/userland ... api.c#L511, and buffer->data now has the ARM address in it. Send the buffer back to a GPU port and mmal_vc_shm_unlock gets called at https://github.com/raspberrypi/userland ... api.c#L637 to restore the VideoCore buffer handle.
All totally opaque to the application.