Esempio n. 1
0
bool COMXImage::Decode(unsigned width, unsigned height)
{
  std::string componentName = "";
  bool m_firstFrame = true;
  unsigned int demuxer_bytes = 0;
  const uint8_t *demuxer_content = NULL;
  OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  OMX_BUFFERHEADERTYPE *omx_buffer = NULL;

  OMX_INIT_STRUCTURE(m_decoded_format);

  CSingleLock lock(g_OMXSection);

  if(!m_image_buffer)
  {
    CLog::Log(LOGERROR, "%s::%s no input buffer\n", CLASSNAME, __func__);
    return false;
  }

  if(GetCompressionFormat() == OMX_IMAGE_CodingMax)
  {
    CLog::Log(LOGERROR, "%s::%s error unsupported image format\n", CLASSNAME, __func__);
    return false;
  }

  if(IsProgressive())
  {
    CLog::Log(LOGWARNING, "%s::%s progressive images not supported by decoder\n", CLASSNAME, __func__);
    return false;
  }

  if(!m_is_open)
  {
    CLog::Log(LOGERROR, "%s::%s error not opened\n", CLASSNAME, __func__);
    return false;
  }

  componentName = "OMX.broadcom.image_decode";
  if(!m_omx_decoder.Initialize((const std::string)componentName, OMX_IndexParamImageInit))
  {
    CLog::Log(LOGERROR, "%s::%s error m_omx_decoder.Initialize\n", CLASSNAME, __func__);
    return false;
  }

  componentName = "OMX.broadcom.resize";
  if(!m_omx_resize.Initialize((const std::string)componentName, OMX_IndexParamImageInit))
  {
    CLog::Log(LOGERROR, "%s::%s error m_omx_resize.Initialize\n", CLASSNAME, __func__);
    return false;
  }

  m_decoder_open = true;

  m_omx_tunnel_decode.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_resize, m_omx_resize.GetInputPort());

  omx_err = m_omx_tunnel_decode.Establish(false);
  if(omx_err != OMX_ErrorNone) 
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_decode.Establish\n", CLASSNAME, __func__);
    return false;
  }
 
  if(width == 0 || height == 0)
  {
#ifndef STANDALONE
    height = g_advancedSettings.m_imageRes;
    if (g_advancedSettings.m_fanartRes > g_advancedSettings.m_imageRes)
    { // a separate fanart resolution is specified - check if the image is exactly equal to this res
      if (m_width == (unsigned int)g_advancedSettings.m_fanartRes * 16/9 &&
          m_height == (unsigned int)g_advancedSettings.m_fanartRes)
      { // special case for fanart res
        height = g_advancedSettings.m_fanartRes;
      }
    }
    width = height * 16/9;
    if(!width || !height)
    {
      //width = g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution].iScreenWidth;
      //height = g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution].iScreenHeight;
      width = g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution].iWidth;
      height = g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution].iHeight;
    }
#else
    width = 2048;
    height = 2048;
#endif
  }

  OMX_PARAM_PORTDEFINITIONTYPE port_def;
  OMX_INIT_STRUCTURE(port_def);
  port_def.nPortIndex = m_omx_decoder.GetInputPort();

  omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_def);
  if(omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_decoder.GetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
    return false;
  }

  port_def.format.image.eCompressionFormat = GetCompressionFormat();
  port_def.format.image.eColorFormat = OMX_COLOR_FormatUnused;
  port_def.format.image.nFrameWidth = 0;
  port_def.format.image.nFrameHeight = 0;
  port_def.format.image.nStride = 0;
  port_def.format.image.nSliceHeight = 0;
  port_def.format.image.bFlagErrorConcealment = OMX_FALSE;

  omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &port_def);
  if(omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
    return false;
  }

  omx_err = m_omx_decoder.AllocInputBuffers();
  if(omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_decoder.AllocInputBuffers result(0x%x)", CLASSNAME, __func__, omx_err);
    return false;
  }

  omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting);
  if (omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetStateForComponent result(0x%x)\n", CLASSNAME, __func__, omx_err);
    return false;
  }

  OMX_INIT_STRUCTURE(port_def);
  port_def.nPortIndex = m_omx_resize.GetOutputPort();

  omx_err = m_omx_resize.GetParameter(OMX_IndexParamPortDefinition, &port_def);
  if(omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_resize.GetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
    return false;
  }

  port_def.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused;
  port_def.format.image.eColorFormat = OMX_COLOR_Format32bitARGB8888;

  port_def.format.image.nFrameWidth = (width + 15)&~15;
  port_def.format.image.nFrameHeight = (height + 15)&~15;

  port_def.format.image.nStride = 0;
  port_def.format.image.nSliceHeight = 0;
  port_def.format.image.bFlagErrorConcealment = OMX_FALSE;

  omx_err = m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def);
  if(omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
    return false;
  }

  omx_err = m_omx_resize.AllocOutputBuffers();
  if(omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_resize.AllocOutputBuffers result(0x%x)\n", CLASSNAME, __func__, omx_err);
    return false;
  }

  omx_err = m_omx_resize.SetStateForComponent(OMX_StateExecuting);
  if(omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetStateForComponent result(0x%x)\n", CLASSNAME, __func__, omx_err);
    return false;
  }

  demuxer_bytes   = GetImageSize();
  demuxer_content = GetImageBuffer();
  if(!demuxer_bytes || !demuxer_content)
    return false;

  m_firstFrame    = true;

  while(demuxer_bytes > 0)
  {
    omx_buffer = m_omx_decoder.GetInputBuffer(1000);
    if(omx_buffer == NULL)
      return false;

    omx_buffer->nOffset = omx_buffer->nFlags  = 0;

    omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes;
    memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen);

    demuxer_content += omx_buffer->nFilledLen;
    demuxer_bytes -= omx_buffer->nFilledLen;

    if(demuxer_bytes == 0)
      omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS;

    omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
    if (omx_err != OMX_ErrorNone)
    {
      CLog::Log(LOGERROR, "%s::%s OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
      break;
    }
    if(m_firstFrame)
    {
      m_firstFrame = false;

      m_omx_decoder.DisablePort(m_omx_decoder.GetOutputPort(), false);
      m_omx_resize.DisablePort(m_omx_resize.GetInputPort(), false);

      OMX_PARAM_PORTDEFINITIONTYPE port_image;
      OMX_INIT_STRUCTURE(port_image);

      port_image.nPortIndex = m_omx_decoder.GetOutputPort();
      m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_image);

      port_image.nPortIndex = m_omx_resize.GetInputPort();
      m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_image);

      m_omx_decoder.EnablePort(m_omx_decoder.GetOutputPort(), false);
      omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged);
      if(omx_err == OMX_ErrorStreamCorrupt)
      {
        CLog::Log(LOGERROR, "%s::%s image not unsupported\n", CLASSNAME, __func__);
        return false;
      }

      m_omx_resize.EnablePort(m_omx_resize.GetInputPort(), false);
      omx_err = m_omx_resize.WaitForEvent(OMX_EventPortSettingsChanged);
      if(omx_err == OMX_ErrorStreamCorrupt)
      {
        CLog::Log(LOGERROR, "%s::%s image not unsupported\n", CLASSNAME, __func__);
        return false;
      }
    }
  }

  omx_err = m_omx_decoder.WaitForEvent(OMX_EventBufferFlag, 1000);
  if(omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_decoder.WaitForEvent result(0x%x)\n", CLASSNAME, __func__, omx_err);
    return false;
  }

  m_decoded_buffer = m_omx_resize.GetOutputBuffer();

  if(!m_decoded_buffer)
  {
    CLog::Log(LOGERROR, "%s::%s no output buffer\n", CLASSNAME, __func__);
    return false;
  }

  omx_err = m_omx_resize.FillThisBuffer(m_decoded_buffer);

  omx_err = m_omx_resize.WaitForEvent(OMX_EventBufferFlag, 1000);
  if(omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_resize WaitForEvent result(0x%x)\n", CLASSNAME, __func__, omx_err);
    return false;
  }

  m_decoded_format.nPortIndex = m_omx_resize.GetOutputPort();
  omx_err = m_omx_resize.GetParameter(OMX_IndexParamPortDefinition, &m_decoded_format);
  if(omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_resize.GetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
    return false;
  }

  m_omx_tunnel_decode.Deestablish();

  return true;
}
bool COMXImage::Decode(unsigned width, unsigned height)
{
  CSingleLock lock(g_OMXSection);
  std::string componentName = "";
  unsigned int demuxer_bytes = 0;
  const uint8_t *demuxer_content = NULL;
  OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  OMX_BUFFERHEADERTYPE *omx_buffer = NULL;

  if(!m_image_buffer)
  {
    CLog::Log(LOGERROR, "%s::%s no input buffer\n", CLASSNAME, __func__);
    return false;
  }

  if(GetCompressionFormat() == OMX_IMAGE_CodingMax)
  {
    CLog::Log(LOGERROR, "%s::%s error unsupported image format\n", CLASSNAME, __func__);
    return false;
  }

  if(IsProgressive())
  {
    CLog::Log(LOGWARNING, "%s::%s progressive images not supported by decoder\n", CLASSNAME, __func__);
    return false;
  }

  if(!m_is_open)
  {
    CLog::Log(LOGERROR, "%s::%s error not opened\n", CLASSNAME, __func__);
    return false;
  }

  componentName = "OMX.broadcom.image_decode";
  if(!m_omx_decoder.Initialize((const std::string)componentName, OMX_IndexParamImageInit))
  {
    CLog::Log(LOGERROR, "%s::%s error m_omx_decoder.Initialize\n", CLASSNAME, __func__);
    return false;
  }

  componentName = "OMX.broadcom.resize";
  if(!m_omx_resize.Initialize((const std::string)componentName, OMX_IndexParamImageInit))
  {
    CLog::Log(LOGERROR, "%s::%s error m_omx_resize.Initialize\n", CLASSNAME, __func__);
    return false;
  }

  m_decoder_open = true;

  if(width == 0 || height == 0)
  {
    height = g_advancedSettings.m_imageRes;
    if (g_advancedSettings.m_fanartRes > g_advancedSettings.m_imageRes)
    { // a separate fanart resolution is specified - check if the image is exactly equal to this res
      if (m_width == (unsigned int)g_advancedSettings.m_fanartRes * 16/9 &&
          m_height == (unsigned int)g_advancedSettings.m_fanartRes)
      { // special case for fanart res
        height = g_advancedSettings.m_fanartRes;
      }
    }
    width = height * 16/9;
    if(!width || !height)
    {
      width = g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution].iWidth;
      height = g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution].iHeight;
    }
  }

  ClampLimits(width, height);

  // set input format
  OMX_IMAGE_PARAM_PORTFORMATTYPE imagePortFormat;
  OMX_INIT_STRUCTURE(imagePortFormat);
  imagePortFormat.nPortIndex = m_omx_decoder.GetInputPort();
  imagePortFormat.eCompressionFormat = OMX_IMAGE_CodingJPEG;

  omx_err = m_omx_decoder.SetParameter(OMX_IndexParamImagePortFormat, &imagePortFormat);
  if(omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetParameter OMX_IndexParamImagePortFormat result(0x%x)\n", CLASSNAME, __func__, omx_err);
    return false;
  }

  omx_err = m_omx_decoder.AllocInputBuffers();
  if(omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_decoder.AllocInputBuffers result(0x%x)", CLASSNAME, __func__, omx_err);
    return false;
  }

  omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting);
  if (omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetStateForComponent result(0x%x)\n", CLASSNAME, __func__, omx_err);
    return false;
  }

  demuxer_bytes   = GetImageSize();
  demuxer_content = GetImageBuffer();
  if(!demuxer_bytes || !demuxer_content)
    return false;

  while(demuxer_bytes > 0 || !m_decoded_buffer)
  {
    long timeout = 0;
    if (demuxer_bytes)
    {
       omx_buffer = m_omx_decoder.GetInputBuffer(1000);
       if(omx_buffer == NULL)
         return false;

       omx_buffer->nOffset = omx_buffer->nFlags  = 0;

       omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes;
       memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen);

       demuxer_content += omx_buffer->nFilledLen;
       demuxer_bytes -= omx_buffer->nFilledLen;

       if(demuxer_bytes == 0)
         omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS;

       omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
       if (omx_err != OMX_ErrorNone)
       {
         CLog::Log(LOGERROR, "%s::%s OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err);
         return false;
       }
    }
    else
    {
       // we've submitted all buffers so can wait now
       timeout = 1000;
    }
    omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, timeout);
    if(omx_err == OMX_ErrorNone)
    {
      if (!HandlePortSettingChange(width, height))
      {
        CLog::Log(LOGERROR, "%s::%s HandlePortSettingChange() failed\n", CLASSNAME, __func__);
        return false;
      }
    }
    // we treat it as an error if a real timeout occurred
    else  if (timeout)
    {
      CLog::Log(LOGERROR, "%s::%s HandlePortSettingChange() failed\n", CLASSNAME, __func__);
      return false;
    }
  }

  omx_err = m_omx_decoder.WaitForEvent(OMX_EventBufferFlag, 1000);
  if(omx_err != OMX_ErrorNone)
  {
    CLog::Log(LOGERROR, "%s::%s m_omx_decoder.WaitForEvent result(0x%x)\n", CLASSNAME, __func__, omx_err);
    return false;
  }

  m_omx_tunnel_decode.Deestablish();

  if(m_omx_decoder.BadState())
    return false;

  return true;
}