int CDVDVideoCodecHybris::GetOutputPicture(void) {
  int rtn = 0;
  int ret = 0;
  int64_t timeout_us = 5000;
  int index;// = m_codec->dequeueOutputBuffer(bufferInfo, timeout_us);
  MediaCodecBufferInfo bufferInfo;
  ret = media_codec_dequeue_output_buffer(m_codec, &bufferInfo, timeout_us);
  index = bufferInfo.index;
  if (ret == OK)
  {
    if (m_drop)
    {
      media_codec_release_output_buffer(m_codec, index, 0);
      return 0;
    }

    // some devices will return a valid index
    // before signaling INFO_OUTPUT_BUFFERS_CHANGED which
    // is used to setup m_output, D'uh. setup m_output here.
#if 0
    if (m_output.empty())
    {
      m_output = m_codec->getOutputBuffers();
      FlushInternal();
    }
#endif
    int flags = bufferInfo.flags;
#if 0
    if (flags & CJNIMediaCodec::BUFFER_FLAG_SYNC_FRAME)
      CLog::Log(LOGDEBUG, "CDVDVideoCodecHybris:: BUFFER_FLAG_SYNC_FRAME");

    if (flags & CJNIMediaCodec::BUFFER_FLAG_CODEC_CONFIG)
      CLog::Log(LOGDEBUG, "CDVDVideoCodecHybris:: BUFFER_FLAG_CODEC_CONFIG");
#endif
    if (flags & 4 /*CJNIMediaCodec::BUFFER_FLAG_END_OF_STREAM*/)
    {
      CLog::Log(LOGDEBUG, "CDVDVideoCodecHybris:: BUFFER_FLAG_END_OF_STREAM");
      media_codec_release_output_buffer(m_codec, index, 0);
      return 0;
    }

    if (!m_render_sw)
    {
      size_t i = 0;
      for (; i < m_inflight.size(); ++i)
      {
        if (m_inflight[i]->GetIndex() == index)
          break;
      }
      if (i == m_inflight.size())
        m_inflight.push_back(
          new CDVDMediaCodecInfo(index, m_textureId, m_codec, m_surfaceTexture, m_frameAvailable)
        );
      m_videoBuffer.mediacodec = m_inflight[i]->Retain();
      m_videoBuffer.mediacodec->Validate(true);
    }
    else
    {
      int size = bufferInfo.size;
      int offset = bufferInfo.offset;

      if (size && media_codec_get_nth_output_buffer_capacity(m_codec, index))
      {
        uint8_t *src_ptr = (uint8_t*)media_codec_get_nth_output_buffer(m_codec, index);
        src_ptr += offset;

        int loop_end = 0;
        if (m_videoBuffer.format == RENDER_FMT_NV12)
          loop_end = 2;
        else if (m_videoBuffer.format == RENDER_FMT_YUV420P)
          loop_end = 3;

        for (int i = 0; i < loop_end; i++)
        {
          uint8_t *src = src_ptr + m_src_offset[i];
          int src_stride = m_src_stride[i];
          uint8_t *dst = m_videoBuffer.data[i];
          int dst_stride = m_videoBuffer.iLineSize[i];

          int height = m_videoBuffer.iHeight;
          if (i > 0)
            height = (m_videoBuffer.iHeight + 1) / 2;

          for (int j = 0; j < height; j++, src += src_stride, dst += dst_stride)
            memcpy(dst, src, dst_stride);
        }
      }
      media_codec_release_output_buffer(m_codec, index, 0);
    }

    int64_t pts = bufferInfo.presentation_time_us;
    m_videoBuffer.dts = DVD_NOPTS_VALUE;
//    m_videoBuffer.pts = DVD_NOPTS_VALUE;
  //  if (pts != AV_NOPTS_VALUE)
    //  m_videoBuffer.pts = pts;
#if 0
    if (pts != AV_NOPTS_VALUE)
      m_videoBuffer.pts = pts;
#endif
/*
    CLog::Log(LOGDEBUG, "CDVDVideoCodecHybris::GetOutputPicture "
        "index(%d), pts(%f)", index, m_videoBuffer.pts);
*/
    rtn = 1;
  }
  else if (ret == -3 /* == CJNIMediaCodec::INFO_OUTPUT_BUFFERS_CHANGED*/)
  {
//    m_output = m_codec->getOutputBuffers();
  }
  else if (ret == -2 /* CJNIMediaCodec::INFO_OUTPUT_FORMAT_CHANGED*/)
  {
    OutputFormatChanged();
  }
  else if (ret == -1/* CJNIMediaCodec::INFO_TRY_AGAIN_LATER*/)
  {
    // normal dequeueOutputBuffer timeout, ignore it.
    rtn = -1;
  }
  else
  {
    // we should never get here
    CLog::Log(LOGERROR, "CDVDVideoCodecHybris::GetOutputPicture unknown index(%d)", index);
  }

  return rtn;
}
int CDVDVideoCodecAndroidMediaCodec::GetOutputPicture(void)
{
  int rtn = 0;

  int64_t timeout_us = 50000;
  CJNIMediaCodecBufferInfo bufferInfo;
  int index = m_codec->dequeueOutputBuffer(bufferInfo, timeout_us);
  if (xbmc_jnienv()->ExceptionOccurred())
  {
    CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::GetOutputPicture ExceptionOccurred");
    xbmc_jnienv()->ExceptionDescribe();
    xbmc_jnienv()->ExceptionClear();
    return 0;
  }
  if (index >= 0)
  {
    if (m_drop)
    {
      m_codec->releaseOutputBuffer(index, false);
      if (xbmc_jnienv()->ExceptionOccurred())
        xbmc_jnienv()->ExceptionClear();
      return 0;
    }

    // some devices will return a valid index
    // before signaling INFO_OUTPUT_BUFFERS_CHANGED which
    // is used to setup m_output, D'uh. setup m_output here.
    if (m_output.empty())
    {
      m_output = m_codec->getOutputBuffers();
      FlushInternal();
    }

    int flags = bufferInfo.flags();
    if (flags & CJNIMediaCodec::BUFFER_FLAG_SYNC_FRAME)
      CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec:: BUFFER_FLAG_SYNC_FRAME");

    if (flags & CJNIMediaCodec::BUFFER_FLAG_CODEC_CONFIG)
      CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec:: BUFFER_FLAG_CODEC_CONFIG");

    if (flags & CJNIMediaCodec::BUFFER_FLAG_END_OF_STREAM)
    {
      CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec:: BUFFER_FLAG_END_OF_STREAM");
      m_codec->releaseOutputBuffer(index, false);
      if (xbmc_jnienv()->ExceptionOccurred())
        xbmc_jnienv()->ExceptionClear();
      return 0;
    }

    if (!m_render_sw)
    {
      m_videobuffer.mediacodec = m_inflight[index]->Retain();
      m_videobuffer.mediacodec->Validate(true);
    }
    else
    {
      int size = bufferInfo.size();
      int offset = bufferInfo.offset();

      if (!m_output[index].isDirect())
        CLog::Log(LOGWARNING, "CDVDVideoCodecAndroidMediaCodec:: m_output[index].isDirect == false");

      if (size && m_output[index].capacity())
      {
        uint8_t *src_ptr = (uint8_t*)xbmc_jnienv()->GetDirectBufferAddress(m_output[index].get_raw());
        src_ptr += offset;

        int loop_end = 0;
        if (m_videobuffer.format == RENDER_FMT_NV12)
          loop_end = 2;
        else if (m_videobuffer.format == RENDER_FMT_YUV420P)
          loop_end = 3;

        for (int i = 0; i < loop_end; i++)
        {
          uint8_t *src   = src_ptr + m_src_offset[i];
          int src_stride = m_src_stride[i];
          uint8_t *dst   = m_videobuffer.data[i];
          int dst_stride = m_videobuffer.iLineSize[i];

          int height = m_videobuffer.iHeight;
          if (i > 0)
            height = (m_videobuffer.iHeight + 1) / 2;

          if (src_stride == dst_stride)
            memcpy(dst, src, dst_stride * height);
          else
            for (int j = 0; j < height; j++, src += src_stride, dst += dst_stride)
              memcpy(dst, src, dst_stride);
        }
      }
      m_codec->releaseOutputBuffer(index, false);
    }

    int64_t pts= bufferInfo.presentationTimeUs();
    m_videobuffer.dts = DVD_NOPTS_VALUE;
    m_videobuffer.pts = DVD_NOPTS_VALUE;
    if (pts != AV_NOPTS_VALUE)
      m_videobuffer.pts = pts;

/*
    CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::GetOutputPicture "
      "index(%d), pts(%f)", index, m_videobuffer.pts);
*/
    // always, check/clear jni exceptions.
    if (xbmc_jnienv()->ExceptionOccurred())
      xbmc_jnienv()->ExceptionClear();

    rtn = 1;
  }
  else if (index == CJNIMediaCodec::INFO_OUTPUT_BUFFERS_CHANGED)
  {
    m_output = m_codec->getOutputBuffers();
    FlushInternal();
  }
  else if (index == CJNIMediaCodec::INFO_OUTPUT_FORMAT_CHANGED)
  {
    CJNIMediaFormat mediaformat = m_codec->getOutputFormat();
    ConfigureOutputFormat(&mediaformat);
  }
  else if (index == CJNIMediaCodec::INFO_TRY_AGAIN_LATER)
  {
    // normal dequeueOutputBuffer timeout, ignore it.
    rtn = -1;
  }
  else
  {
    // we should never get here
    CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::GetOutputPicture unknown index(%d)", index);
  }

  return rtn;
}
int RageFileObj::Flush()
{
	return FlushInternal();
}