Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OMX image_fx method OMX_ImageFilterDeInterlaceLineDouble broken #181

Closed
tp-m opened this issue May 16, 2013 · 8 comments
Closed

OMX image_fx method OMX_ImageFilterDeInterlaceLineDouble broken #181

tp-m opened this issue May 16, 2013 · 8 comments

Comments

@tp-m
Copy link

tp-m commented May 16, 2013

When configuring the OMX image_fx element to use the OMX_ImageFilterDeInterlaceLineDouble filter method, the image gets completely garbled (green/red noise mostly). Other methods such as OMX_ImageFilterDeInterlaceAdvanced or OMX_ImageFilterSolarize work just fine though.

I will attach a modified hello_video/video.c

@tp-m
Copy link
Author

tp-m commented May 16, 2013

// Video deocode demo using OpenMAX IL though the ilcient helper library
#include 
#include 
#include 
#include "bcm_host.h"
#include "ilclient.h"
static int video_decode_test(char *filename)
{
   OMX_VIDEO_PARAM_PORTFORMATTYPE format;
   OMX_TIME_CONFIG_CLOCKSTATETYPE cstate;
   COMPONENT_T *video_decode = NULL, *video_scheduler = NULL, *video_render = NULL, *clock = NULL;
   COMPONENT_T *list[6], *image_filter = NULL;
   TUNNEL_T tunnel[5];
   ILCLIENT_T *client;
   FILE *in;
   int status = 0;
   unsigned char *data = NULL;
   unsigned int data_len = 0;
   int find_start_codes = 0;
   int packet_size = 16<<10;   
   memset(list, 0, sizeof(list));
   memset(tunnel, 0, sizeof(tunnel));
   if((in = fopen(filename, "rb")) == NULL)
      return -2;
   if((client = ilclient_init()) == NULL)
   {
      fclose(in);
      return -3;
   }
   if(OMX_Init() != OMX_ErrorNone)
   {
      ilclient_destroy(client);
      fclose(in);
      return -4;
   }
   if(find_start_codes && (data = malloc(packet_size+4)) == NULL)
   {
      status = -16;
      if(OMX_Deinit() != OMX_ErrorNone)
         status = -17;
      ilclient_destroy(client);
      fclose(in);
      return status;
   }
   // create video_decode
   if(ilclient_create_component(client, &video_decode, "video_decode", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS) != 0)
      status = -14;
   list[0] = video_decode;
   // create video_render
   if(status == 0 && ilclient_create_component(client, &video_render, "video_render", ILCLIENT_DISABLE_ALL_PORTS) != 0)
      status = -14;
   list[1] = video_render;
   // create clock
   if(status == 0 && ilclient_create_component(client, &clock, "clock", ILCLIENT_DISABLE_ALL_PORTS) != 0)
      status = -14;
   list[2] = clock;
   memset(&cstate, 0, sizeof(cstate));
   cstate.nSize = sizeof(cstate);
   cstate.nVersion.nVersion = OMX_VERSION;
   cstate.eState = OMX_TIME_ClockStateWaitingForStartTime;
   cstate.nWaitMask = 1;
   if(clock != NULL && OMX_SetParameter(ILC_GET_HANDLE(clock), OMX_IndexConfigTimeClockState, &cstate) != OMX_ErrorNone)
      status = -13;
   // create video_scheduler
   if(status == 0 && ilclient_create_component(client, &video_scheduler, "video_scheduler", ILCLIENT_DISABLE_ALL_PORTS) != 0)
      status = -14;
   list[3] = video_scheduler;
   // create image_filter
   if(ilclient_create_component(client, &image_filter, "image_fx", ILCLIENT_DISABLE_ALL_PORTS) != 0)
      status = -14;
   list[4] = image_filter;
   set_tunnel(tunnel, video_decode, 131, image_filter, 190);
   set_tunnel(tunnel+1, image_filter, 191, video_scheduler, 10);
   set_tunnel(tunnel+2, video_scheduler, 11, video_render, 90);
   set_tunnel(tunnel+3, clock, 80, video_scheduler, 12);
   // setup clock tunnel first
   if(status == 0 && ilclient_setup_tunnel(tunnel+3, 0, 0) != 0)
      status = -15;
   else
      ilclient_change_component_state(clock, OMX_StateExecuting);
   if(status == 0)
      ilclient_change_component_state(video_decode, OMX_StateIdle);
   memset(&format, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
   format.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
   format.nVersion.nVersion = OMX_VERSION;
   format.nPortIndex = 130;
   format.eCompressionFormat = OMX_VIDEO_CodingAVC;
   if(status == 0 &&
      OMX_SetParameter(ILC_GET_HANDLE(video_decode), OMX_IndexParamVideoPortFormat, &format) == OMX_ErrorNone &&
      ilclient_enable_port_buffers(video_decode, 130, NULL, NULL, NULL) == 0)
   {
      OMX_BUFFERHEADERTYPE *buf;
      int port_settings_changed = 0;
      int first_packet = 1;
      ilclient_change_component_state(video_decode, OMX_StateExecuting);
      while((buf = ilclient_get_input_buffer(video_decode, 130, 1)) != NULL)
      {
         // feed data and wait until we get port settings changed
         unsigned char *dest = find_start_codes ? data + data_len : buf->pBuffer;
         data_len += fread(dest, 1, packet_size+(find_start_codes*4)-data_len, in);
         if(port_settings_changed == 0 &&
            ((data_len > 0 && ilclient_remove_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1) == 0) ||
             (data_len == 0 && ilclient_wait_for_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1,
                                                       ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 10000) == 0)))
         {
            port_settings_changed = 1;
            if(ilclient_setup_tunnel(tunnel, 0, 0) != 0)
            {
               status = -7;
               break;
            }
            {
                OMX_CONFIG_IMAGEFILTERTYPE filtertype;
                memset(&filtertype, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
                filtertype.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
                filtertype.nVersion.nVersion = OMX_VERSION;
                filtertype.nPortIndex = 191;
                filtertype.eImageFilter = OMX_ImageFilterDeInterlaceLineDouble; //Advanced; //OMX_ImageFilterNone;
                if (OMX_SetParameter(ILC_GET_HANDLE(image_filter), OMX_IndexConfigCommonImageFilter, &filtertype) != OMX_ErrorNone)
                {
                    status = -99;
                    break;
                }
            }
            ilclient_change_component_state(image_filter, OMX_StateExecuting);
            // now setup tunnel to video_scheduler
            if(ilclient_setup_tunnel(tunnel+1, 0, 1000) != 0)
            {
               status = -12;
               break;
            }
            ilclient_change_component_state(video_scheduler, OMX_StateExecuting);
            // now setup tunnel to video_render
            if(ilclient_setup_tunnel(tunnel+2, 0, 1000) != 0)
            {
               status = -12;
               break;
            }
            
            ilclient_change_component_state(video_render, OMX_StateExecuting);
         }
         if(!data_len)
            break;
         if(find_start_codes)
         {
            int i, start = -1, len = 0;
            int max_len = data_len > packet_size ? packet_size : data_len;
            for(i=2; i 2 && data[i-3] == 0)
                  {
                     len++;
                     start--;
                  }
                  break;
               }
            }
            if(start == 0)
            {
               // start code is next, so just send that
               buf->nFilledLen = len;
            }
            else if(start == -1)
            {
               // no start codes seen, send the first block
               buf->nFilledLen = max_len;
            }
            else
            {
               // start code in the middle of the buffer, send up to the code
               buf->nFilledLen = start;
            }
            memcpy(buf->pBuffer, data, buf->nFilledLen);
            memmove(data, data + buf->nFilledLen, data_len - buf->nFilledLen);
            data_len -= buf->nFilledLen;
         }
         else
         {
            buf->nFilledLen = data_len;
            data_len = 0;
         }
         buf->nOffset = 0;
         if(first_packet)
         {
            buf->nFlags = OMX_BUFFERFLAG_STARTTIME;
            first_packet = 0;
         }
         else
            buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
         if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone)
         {
            status = -6;
            break;
         }
         
      }
      buf->nFilledLen = 0;
      buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN | OMX_BUFFERFLAG_EOS;
      
      if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone)
         status = -20;
      
      // wait for EOS from render
      ilclient_wait_for_event(video_render, OMX_EventBufferFlag, 90, 0, OMX_BUFFERFLAG_EOS, 0,
                              ILCLIENT_BUFFER_FLAG_EOS, 10000);
      
      // need to flush the renderer to allow video_decode to disable its input port
      ilclient_flush_tunnels(tunnel, 0);
      ilclient_disable_port_buffers(video_decode, 130, NULL, NULL, NULL);
   }
   fclose(in);
   ilclient_disable_tunnel(tunnel);
   ilclient_disable_tunnel(tunnel+2);
   ilclient_disable_tunnel(tunnel+3);
   ilclient_teardown_tunnels(tunnel);
   ilclient_state_transition(list, OMX_StateIdle);
   ilclient_state_transition(list, OMX_StateLoaded);
   ilclient_cleanup_components(list);
   OMX_Deinit();
   ilclient_destroy(client);
   return status;
}
int main (int argc, char **argv)
{
   if (argc < 2) {
      printf("Usage: %s \n", argv[0]);
      exit(1);
   }
   bcm_host_init();
   return video_decode_test(argv[1]);
}

@julianscheel
Copy link

I can confirm this issue. Getting the same garbled issues.

@6by9
Copy link

6by9 commented Jun 3, 2014

Confirmed. The GPU is mismanaging buffers in this case and ends up not doing the conversion before deinterlacing. The output is just uninitialised memory.

I don't fully understand the algorithm, but think I understand the buffer handling so I'll look at fixing it up.

@6by9
Copy link

6by9 commented Jun 3, 2014

Firmware changes pushed internally that fix the buffer mismanagement. I now get an output image that looks reasonable, but I can't comment on the deinterlacing being correct.
Test firmware at https://github.com/6by9/RPiTest/blob/master/mmal_image_fx/start_x.elf if you want to experiment, but should be released in the next couple of days.

popcornmix pushed a commit that referenced this issue Jun 4, 2014
kernel: config: Add CONFIG_HID_XINMO
See: raspberrypi/linux#609

firmware: audio_render/audio_mixer: Support planar formats

firmware: bootcode: increase sdcard timeout to avoid observed boot failure under certain conditions

firmware: deinterlace_double - fix image locking
See: #181

firmware: Convert image_fx for use with MMAL and MMAL_ENCODING_OPAQUE
See: #278

firmware: RIL Camera: fix handling for stride>required stride
See: raspberrypi/userland#177
popcornmix pushed a commit to Hexxeh/rpi-firmware that referenced this issue Jun 4, 2014
kernel: config: Add CONFIG_HID_XINMO
See: raspberrypi/linux#609

firmware: audio_render/audio_mixer: Support planar formats

firmware: bootcode: increase sdcard timeout to avoid observed boot failure under certain conditions

firmware: deinterlace_double - fix image locking
See: raspberrypi/firmware#181

firmware: Convert image_fx for use with MMAL and MMAL_ENCODING_OPAQUE
See: raspberrypi/firmware#278

firmware: RIL Camera: fix handling for stride>required stride
See: raspberrypi/userland#177
@popcornmix
Copy link
Contributor

Firmware has been updated. Please run rpi-update and test.

@tp-m
Copy link
Author

tp-m commented Jun 4, 2014

Thanks a lot for the fix. I won't be able to test this until next week at the earliest, so please feel free to close if it works for you now.

@julianscheel
Copy link

I'm going to test it tomorrow

@julianscheel
Copy link

Works for me. Can be closed.

neuschaefer pushed a commit to neuschaefer/raspi-binary-firmware that referenced this issue Feb 27, 2017
kernel: config: Add CONFIG_HID_XINMO
See: raspberrypi/linux#609

firmware: audio_render/audio_mixer: Support planar formats

firmware: bootcode: increase sdcard timeout to avoid observed boot failure under certain conditions

firmware: deinterlace_double - fix image locking
See: raspberrypi#181

firmware: Convert image_fx for use with MMAL and MMAL_ENCODING_OPAQUE
See: raspberrypi#278

firmware: RIL Camera: fix handling for stride>required stride
See: raspberrypi/userland#177
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants