void CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec(void)
{
  // setup a MediaFormat to match the video content,
  // used by codec during configure
  CJNIMediaFormat mediaformat = CJNIMediaFormat::createVideoFormat(
    m_mime.c_str(), m_hints.width, m_hints.height);
  // some android devices forget to default the demux input max size
  mediaformat.setInteger(CJNIMediaFormat::KEY_MAX_INPUT_SIZE, 0);

  // handle codec extradata
  if (m_hints.extrasize)
  {
    size_t size = m_hints.extrasize;
    void  *src_ptr = m_hints.extradata;
    if (m_bitstream)
    {
      size = m_bitstream->GetExtraSize();
      src_ptr = m_bitstream->GetExtraData();
    }
    // Allocate a byte buffer via allocateDirect in java instead of NewDirectByteBuffer,
    // since the latter doesn't allocate storage of its own, and we don't know how long
    // the codec uses the buffer.
    CJNIByteBuffer bytebuffer = CJNIByteBuffer::allocateDirect(size);
    void *dts_ptr = xbmc_jnienv()->GetDirectBufferAddress(bytebuffer.get_raw());
    memcpy(dts_ptr, src_ptr, size);
    // codec will automatically handle buffers as extradata
    // using entries with keys "csd-0", "csd-1", etc.
    mediaformat.setByteBuffer("csd-0", bytebuffer);
  }

  InitSurfaceTexture();

  // configure and start the codec.
  // use the MediaFormat that we have setup.
  // use a null MediaCrypto, our content is not encrypted.
  // use a null Surface, we will extract the video picture data manually.
  int flags = 0;
  CJNIMediaCrypto crypto(jni::jhobject(NULL));
  // our jni gets upset if we do this a different
  // way, do not mess with it.
  if (m_render_sw)
  {
    CJNISurface surface(jni::jhobject(NULL));
    m_codec->configure(mediaformat, surface, crypto, flags);
  }
  else
  {
    m_codec->configure(mediaformat, *m_surface, crypto, flags);
  }

  m_codec->start();

  // always, check/clear jni exceptions.
  if (xbmc_jnienv()->ExceptionOccurred())
    xbmc_jnienv()->ExceptionClear();
}
bool CDVDVideoCodecHybris::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) {
  int ret = 0;
  
  if (hints.software)
    return false;

  // stagefright crashes with null size. Trap this...
  if (!hints.width || !hints.height) {
    CLog::Log(LOGERROR, "%s::%s - %s\n", CLASSNAME, __func__,"null size, cannot handle");
    return false;
  }

  if(m_bitstream) {
    SAFE_DELETE(m_bitstream);
    m_bitstream = NULL;
  }

  CLog::Log(LOGDEBUG,
          "%s::%s - trying to open, codec(%d), profile(%d), level(%d)",
          CLASSNAME, __func__, hints.codec, hints.profile, hints.level);

  m_drop = false;
  m_hints = hints;

  switch(hints.codec) {
//    OMX_ON2_VIDEO_CodingMPEG2,      /**< AKA: H.262 */^M
    case AV_CODEC_ID_MPEG2VIDEO:
      m_mimeType = "video/mpeg2";
      m_name = "hyb-mpeg2";
      break;

//    OMX_ON2_VIDEO_CodingH263,       /**< H.263 */^M
    case AV_CODEC_ID_H263:
      m_name = "hyb-h263";
      m_mimeType = "video/3gpp";
      break;

//    OMX_ON2_VIDEO_CodingMPEG4,      /**< MPEG-4 */^M
    case AV_CODEC_ID_MPEG4:
      m_name = "hyb-mpeg4";
      m_mimeType = "video/mp4v-es";
      break;

//    OMX_ON2_VIDEO_CodingAVC,        /**< H.264/AVC */^M
    case AV_CODEC_ID_AVS:
    case AV_CODEC_ID_CAVS:
    case AV_CODEC_ID_H264:
      switch(hints.profile)
      {
        case FF_PROFILE_H264_HIGH_10:
        case FF_PROFILE_H264_HIGH_10_INTRA:
        case FF_PROFILE_H264_HIGH_422:
        case FF_PROFILE_H264_HIGH_422_INTRA:
        case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
        case FF_PROFILE_H264_HIGH_444_INTRA:
        case FF_PROFILE_H264_CAVLC_444:
          // Hi10P not supported
          return false;
      }

      m_name = "hyb-h264";
      m_mimeType = "video/avc";
      if (m_hints.extradata) {
        m_bitstream = new CBitstreamConverter;
        if (!m_bitstream->Open(m_hints.codec, (uint8_t*)m_hints.extradata, m_hints.extrasize, true)) {
          SAFE_DELETE(m_bitstream);
        }
      }
      break;

//    OMX_ON2_VIDEO_CodingVP6,^M
//    OMX_ON2_VIDEO_CodingVP8,        /**< VP8 */^M
    case AV_CODEC_ID_VP3:
    case AV_CODEC_ID_VP6:
    case AV_CODEC_ID_VP6F:
    case AV_CODEC_ID_VP8:
      //m_mimeType = "video/x-vp6";
      //m_mimeType = "video/x-vp7";
      m_mimeType = "video/x-vnd.on2.vp8";
      m_name = "hyb-vpX";
      break;

//    OMX_ON2_VIDEO_CodingWMV,        /**< Windows Media Video (WMV1,WMV2,WMV3)*/^M
    case AV_CODEC_ID_WMV3:
      m_mimeType = "video/wmv3";
      m_name = "hyb-wmv3";
      if (m_hints.extradata) {
        m_bitstream = new CBitstreamConverter;
        if (!m_bitstream->Open(m_hints.codec, (uint8_t*)m_hints.extradata, m_hints.extrasize, true)) {
          SAFE_DELETE(m_bitstream);
        }
      }
      break;
//    OMX_ON2_VIDEO_CodingVC1 = 0x01000000, /**< Windows Media Video (WMV1,WMV2,WMV3)*/^M
    case AV_CODEC_ID_VC1:
      m_mimeType = "video/vc1";
      m_name = "hyb-vc1";
      if (m_hints.extradata) {
        m_bitstream = new CBitstreamConverter;
        if (!m_bitstream->Open(m_hints.codec, (uint8_t*)m_hints.extradata, m_hints.extrasize, true)) {
          SAFE_DELETE(m_bitstream);
        }
      }
      break;

// mac_l1: 4K HEVC crashes after 10-20 secs... so exclude for now
//    OMX_RK_VIDEO_CodingHEVC,        /**< H.265/HEVC */^M
    case AV_CODEC_ID_HEVC:
      m_mimeType = "video/hevc";
      m_name = "hyb-h265";
      // check for hevc-hvcC and convert to h265-annex-b
      if (m_hints.extradata) {
        m_bitstream = new CBitstreamConverter;
        if (!m_bitstream->Open(m_hints.codec, (uint8_t*)m_hints.extradata, m_hints.extrasize, true)) {
          SAFE_DELETE(m_bitstream);
        }
      }
      break;

// mac_l1: better safe than sorry (although they might be supported by HW): 
// following are not supported in Androids XBMC/SPMC
//    OMX_ON2_VIDEO_CodingRV,         /**< all versions of Real Video */^M
//    OMX_ON2_VIDEO_CodingMJPEG,      /**< Motion JPEG */^M
//    OMX_ON2_VIDEO_CodingFLV1,       /**< Sorenson H.263 */^M
// following are not implemented in 
// frameworks/av/media/libstagefright/codecs/rkon2dec/RkOn2Decoder.cpp
// however, could work though...
//    OMX_ON2_VIDEO_CodingDIVX3,      /**< DIVX3 */^M
//    OMX_ON2_VIDEO_CodingVP9,        /**< VP9 */^M
    default:
      CLog::Log(LOGDEBUG, "%s::%s - Unsupported hints.codec(%d)", 
                CLASSNAME, __func__, hints.codec);
      return false;
      break;
  }

  m_format = media_format_create_video_format(m_mimeType.c_str(), 
                 hints.width, hints.height, 0, 0);
  if (m_format == NULL) {
    CLog::Log(LOGERROR, "%s::%s - Failed to create format object for %s", 
              CLASSNAME, __func__, m_mimeType.c_str());
    return false;
  }

  m_codec = media_codec_create_by_codec_type(m_mimeType.c_str());
  if (m_codec == NULL) {
    CLog::Log(LOGERROR, "%s::%s - Failed to create codec for %s", 
              CLASSNAME, __func__, m_mimeType.c_str());
    media_codec_release(m_codec);
    media_codec_delegate_destroy(m_codec);
    media_format_destroy(m_codec);
    return false;
  }

  if (hints.extrasize > 0) {
    size_t size = m_hints.extrasize;
    void *src_ptr = m_hints.extradata;
    if (m_bitstream)
    {
      size = m_bitstream->GetExtraSize();
      src_ptr = m_bitstream->GetExtraData();
    }
    media_format_set_byte_buffer(m_format, "csd-0", (uint8_t*)src_ptr, size);
  }

  // setup a YUV420P DVDVideoPicture buffer.
  // first make sure all properties are reset.
  memset(&m_videoBuffer, 0x00, sizeof(DVDVideoPicture));

  m_videoBuffer.dts = DVD_NOPTS_VALUE;
  m_videoBuffer.pts = DVD_NOPTS_VALUE;
  m_videoBuffer.color_range = 0;
  m_videoBuffer.color_matrix = 4;
  m_videoBuffer.iFlags = DVP_FLAG_ALLOCATED;
  m_videoBuffer.iWidth = m_hints.width;
  m_videoBuffer.iHeight = m_hints.height;
  // these will get reset to crop values later
  m_videoBuffer.iDisplayWidth = m_hints.width;
  m_videoBuffer.iDisplayHeight = m_hints.height;

  m_render_sw = false;

  InitSurfaceTexture();

  if( m_render_sw ) {
    if (media_codec_configure(m_codec, m_format, NULL, 0) != OK) {
      CLog::Log(LOGERROR, "%s::%s - Failed to configure codec for %s", 
                CLASSNAME, __func__, m_mimeType.c_str());
      return false;
    }
  } else {
    if (media_codec_configure(m_codec, m_format, m_surface, 0) != OK) {
      CLog::Log(LOGERROR, "%s::%s - Failed to configure codec w surface for %s",
                CLASSNAME, __func__, m_mimeType.c_str());
      return false;
    }
  }

  media_codec_start(m_codec);

  return true;
}