int CDVDVideoCodecAndroidMediaCodec::Decode(uint8_t *pData, int iSize, double dts, double pts) { // Handle input, add demuxer packet to input queue, we must accept it or // it will be discarded as DVDPlayerVideo has no concept of "try again". // we must return VC_BUFFER or VC_PICTURE, default to VC_BUFFER. int rtn = VC_BUFFER; if (!m_opened) return rtn; if (m_hints.ptsinvalid) pts = DVD_NOPTS_VALUE; // must check for an output picture 1st, // otherwise, mediacodec can stall on some devices. if (GetOutputPicture() > 0) rtn |= VC_PICTURE; if (pData) { if (m_bitstream) { m_bitstream->Convert(pData, iSize); iSize = m_bitstream->GetConvertSize(); pData = m_bitstream->GetConvertBuffer(); } // queue demux pkt in case we cannot get an input buffer amc_demux demux_pkt; demux_pkt.dts = dts; demux_pkt.pts = pts; demux_pkt.iSize = iSize; demux_pkt.pData = (uint8_t*)malloc(iSize); memcpy(demux_pkt.pData, pData, iSize); m_demux.push(demux_pkt); // try to fetch an input buffer int64_t timeout_us = 5000; int index = m_codec->dequeueInputBuffer(timeout_us); if (xbmc_jnienv()->ExceptionOccurred()) { CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::Decode ExceptionOccurred"); xbmc_jnienv()->ExceptionDescribe(); xbmc_jnienv()->ExceptionClear(); return VC_ERROR; } if (index >= 0) { // docs lie, getInputBuffers should be good after // m_codec->start() but the internal refs are not // setup until much later on some devices. if (m_input.empty()) m_input = m_codec->getInputBuffers(); // we have an input buffer, fill it. int size = m_input[index].capacity(); // fetch the front demux packet amc_demux &demux_pkt = m_demux.front(); if (demux_pkt.iSize > size) { CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::Decode, iSize(%d) > size(%d)", iSize, size); demux_pkt.iSize = size; } // fetch a pointer to the ByteBuffer backing store void *dst_ptr = xbmc_jnienv()->GetDirectBufferAddress(m_input[index].get_raw()); if (dst_ptr) memcpy(dst_ptr, demux_pkt.pData, demux_pkt.iSize); free(demux_pkt.pData); m_demux.pop(); // Translate from dvdplayer dts/pts to MediaCodec pts, // pts WILL get re-ordered by MediaCodec if needed. // Do not try to pass pts as a unioned double/int64_t, // some android devices will diddle with presentationTimeUs // and you will get NaN back and DVDPlayerVideo will barf. int64_t presentationTimeUs = AV_NOPTS_VALUE; if (demux_pkt.pts != DVD_NOPTS_VALUE) presentationTimeUs = demux_pkt.pts; else if (demux_pkt.dts != DVD_NOPTS_VALUE) presentationTimeUs = demux_pkt.dts; /* CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec:: " "pts(%f), ipts(%lld), iSize(%d), GetDataSize(%d), loop_cnt(%d)", presentationTimeUs, pts_dtoi(presentationTimeUs), iSize, GetDataSize(), loop_cnt); */ int flags = 0; int offset = 0; m_codec->queueInputBuffer(index, offset, demux_pkt.iSize, presentationTimeUs, flags); // clear any jni exceptions, jni gets upset if we do not. if (xbmc_jnienv()->ExceptionOccurred()) { CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::Decode ExceptionOccurred"); xbmc_jnienv()->ExceptionClear(); } } } return rtn; }
int CDVDVideoCodecHybris::Decode(BYTE* pData, int iSize, double dts, double pts) { // Handle input, add demuxer packet to input queue, we must accept it or // it will be discarded as DVDPlayerVideo has no concept of "try again". // we must return VC_BUFFER or VC_PICTURE, default to VC_BUFFER. int rtn = VC_BUFFER; MediaCodecBufferInfo bufferInfo; if (m_hints.ptsinvalid) pts = DVD_NOPTS_VALUE; // must check for an output picture 1st, // otherwise, mediacodec can stall on some devices. if (GetOutputPicture() > 0) rtn |= VC_PICTURE; if (pData) { if (m_bitstream) { m_bitstream->Convert(pData, iSize); iSize = m_bitstream->GetConvertSize(); pData = m_bitstream->GetConvertBuffer(); } // queue demux pkt in case we cannot get an input buffer amc_demux demux_pkt; demux_pkt.dts = dts; demux_pkt.pts = pts; demux_pkt.iSize = iSize; demux_pkt.pData = (uint8_t*)malloc(iSize); memcpy(demux_pkt.pData, pData, iSize); m_demux.push(demux_pkt); // try to fetch an input buffer int64_t timeout_us = 5000; size_t index;// = m_codec->dequeueInputBuffer(timeout_us); int ret = media_codec_dequeue_input_buffer(m_codec, &index, timeout_us); if (ret == OK) { // we have an input buffer, fill it. int size = media_codec_get_nth_input_buffer_capacity(m_codec, index); // fetch the front demux packet amc_demux &demux_pkt = m_demux.front(); if (demux_pkt.iSize > size) { CLog::Log(LOGERROR, "CDVDVideoCodecHybris::Decode, iSize(%d) > size(%d)", iSize, size); demux_pkt.iSize = size; } // fetch a pointer to the ByteBuffer backing store void *dst_ptr = media_codec_get_nth_input_buffer(m_codec, index); if (dst_ptr) memcpy(dst_ptr, demux_pkt.pData, demux_pkt.iSize); free(demux_pkt.pData); m_demux.pop(); // Translate from dvdplayer dts/pts to MediaCodec pts, // pts WILL get re-ordered by MediaCodec if needed. // Do not try to pass pts as a unioned double/int64_t, // some android devices will diddle with presentationTimeUs // and you will get NaN back and DVDPlayerVideo will barf. int64_t presentationTimeUs = AV_NOPTS_VALUE; if (demux_pkt.pts != DVD_NOPTS_VALUE) presentationTimeUs = demux_pkt.pts; else if (demux_pkt.dts != DVD_NOPTS_VALUE) presentationTimeUs = demux_pkt.dts; /* CLog::Log(LOGDEBUG, "CDVDVideoCodecHybris:: " "pts(%f), ipts(%lld), iSize(%d), GetDataSize(%d), loop_cnt(%d)", presentationTimeUs, pts_dtoi(presentationTimeUs), iSize, GetDataSize(), loop_cnt); */ //m_codec->queueInputBuffer(index, offset, demux_pkt.iSize, presentationTimeUs, flags); bufferInfo.index = index; bufferInfo.offset = 0; bufferInfo.size = demux_pkt.iSize; bufferInfo.presentation_time_us = 0;//presentationTimeUs; bufferInfo.flags = 0; if(media_codec_queue_input_buffer(m_codec, &bufferInfo) != OK) { CLog::Log(LOGERROR, "CDVDVideoCodecHybris::Decode, failed to queue input buffer!"); } } } return rtn; }