void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { if (!(buffer->cmd == 0 && buffer->length > 0)) if (g_advancedSettings.CanLogComponent(LOGVIDEO)) CLog::Log(LOGDEBUG, "%s::%s port:%p buffer %p, len %d cmd:%x", CLASSNAME, __func__, port, buffer, buffer->length, buffer->cmd); bool kept = false; if (buffer->cmd == 0) { if (buffer->length > 0) { assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY)); double dts = DVD_NOPTS_VALUE; if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_USER0) { pthread_mutex_lock(&m_output_mutex); if (!m_dts_queue.empty()) { dts = m_dts_queue.front(); m_dts_queue.pop(); } else assert(0); pthread_mutex_unlock(&m_output_mutex); } if (m_drop_state) { if (g_advancedSettings.CanLogComponent(LOGVIDEO)) CLog::Log(LOGDEBUG, "%s::%s - dropping %p (drop:%d)", CLASSNAME, __func__, buffer, m_drop_state); } else { CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this); m_output_busy++; if (g_advancedSettings.CanLogComponent(LOGVIDEO)) CLog::Log(LOGDEBUG, "%s::%s - %p (%p) buffer_size(%u) dts:%.3f pts:%.3f flags:%x:%x frame:%d", CLASSNAME, __func__, buffer, omvb, buffer->length, dts*1e-6, buffer->pts*1e-6, buffer->flags, buffer->type->video.flags, omvb->m_changed_count); omvb->mmal_buffer = buffer; buffer->user_data = (void *)omvb; omvb->m_changed_count = m_changed_count; omvb->dts = dts; omvb->width = m_decoded_width; omvb->height = m_decoded_height; omvb->m_aspect_ratio = m_aspect_ratio; pthread_mutex_lock(&m_output_mutex); m_output_ready.push(omvb); pthread_mutex_unlock(&m_output_mutex); kept = true; } } } else if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) { PortSettingsChanged(port, buffer); } if (!kept) mmal_buffer_header_release(buffer); }
void CMMALVideo::dec_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { MMAL_STATUS_T status; if (buffer->cmd == MMAL_EVENT_ERROR) { status = (MMAL_STATUS_T)*(uint32_t *)buffer->data; CLog::Log(LOGERROR, "%s::%s Error (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); } else if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) { if (g_advancedSettings.CanLogComponent(LOGVIDEO)) CLog::Log(LOGDEBUG, "%s::%s format changed", CLASSNAME, __func__); PortSettingsChanged(port, buffer); } else CLog::Log(LOGERROR, "%s::%s other (cmd:%x data:%x)", CLASSNAME, __func__, buffer->cmd, *(uint32_t *)buffer->data); mmal_buffer_header_release(buffer); }
int COMXVideo::Decode(uint8_t *pData, int iSize, double dts, double pts) { OMX_ERRORTYPE omx_err; if (pData || iSize > 0) { unsigned int demuxer_bytes = (unsigned int)iSize; uint8_t *demuxer_content = pData; while(demuxer_bytes) { // 500ms timeout OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer(500); if(omx_buffer == NULL) { CLog::Log(LOGERROR, "OMXVideo::Decode timeout\n"); printf("COMXVideo::Decode timeout\n"); return false; } /* CLog::Log(DEBUG, "COMXVideo::Video VDec : pts %lld omx_buffer 0x%08x buffer 0x%08x number %d\n", pts, omx_buffer, omx_buffer->pBuffer, (int)omx_buffer->pAppPrivate); printf("VDec : pts %f omx_buffer 0x%08x buffer 0x%08x number %d\n", (float)pts / AV_TIME_BASE, omx_buffer, omx_buffer->pBuffer, (int)omx_buffer->pAppPrivate); */ omx_buffer->nFlags = 0; omx_buffer->nOffset = 0; // some packed bitstream AVI files set almost all pts values to DVD_NOPTS_VALUE, but have a scattering of real pts values. // the valid pts values match the dts values. // if a stream has had more than 4 valid pts values in the last 16, the use UNKNOWN, otherwise use dts m_history_valid_pts = (m_history_valid_pts << 1) | (pts != DVD_NOPTS_VALUE); if(pts == DVD_NOPTS_VALUE && count_bits(m_history_valid_pts & 0xffff) < 4) pts = dts; if(m_setStartTime) { // only send dts on first frame to get nearly correct starttime if(pts == DVD_NOPTS_VALUE) pts = dts; omx_buffer->nFlags |= OMX_BUFFERFLAG_STARTTIME; CLog::Log(LOGDEBUG, "OMXVideo::Decode VDec : setStartTime %f\n", (pts == DVD_NOPTS_VALUE ? 0.0 : pts) / DVD_TIME_BASE); m_setStartTime = false; } if(pts == DVD_NOPTS_VALUE) omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN; omx_buffer->nTimeStamp = ToOMXTime(pts == DVD_NOPTS_VALUE ? 0 : pts); omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes; memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); demuxer_bytes -= omx_buffer->nFilledLen; demuxer_content += omx_buffer->nFilledLen; if(demuxer_bytes == 0) omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; int nRetry = 0; while(true) { omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); if (omx_err == OMX_ErrorNone) { break; } else { CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); nRetry++; } if(nRetry == 5) { CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() finally failed\n", CLASSNAME, __func__); printf("%s::%s - OMX_EmptyThisBuffer() finaly failed\n", CLASSNAME, __func__); return false; } } omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, 0); if (omx_err == OMX_ErrorNone) { if(!PortSettingsChanged()) { CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged omx_err(0x%08x)\n", CLASSNAME, __func__, omx_err); } } omx_err = m_omx_decoder.WaitForEvent(OMX_EventParamOrConfigChanged, 0); if (omx_err == OMX_ErrorNone) { if(!PortSettingsChanged()) { CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged (EventParamOrConfigChanged) omx_err(0x%08x)\n", CLASSNAME, __func__, omx_err); } } } return true; } return false; }
int COMXVideo::Decode(uint8_t *pData, int iSize, double dts, double pts) { CSingleLock lock (m_critSection); OMX_ERRORTYPE omx_err; if( m_drop_state || !m_is_open ) return true; unsigned int demuxer_bytes = (unsigned int)iSize; uint8_t *demuxer_content = pData; if (demuxer_content && demuxer_bytes > 0) { OMX_U32 nFlags = 0; if(m_setStartTime) { nFlags |= OMX_BUFFERFLAG_STARTTIME; CLog::Log(LOGDEBUG, "OMXVideo::Decode VDec : setStartTime %f\n", (pts == DVD_NOPTS_VALUE ? 0.0 : pts) / DVD_TIME_BASE); m_setStartTime = false; } if (pts == DVD_NOPTS_VALUE && dts == DVD_NOPTS_VALUE) nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN; else if (pts == DVD_NOPTS_VALUE) nFlags |= OMX_BUFFERFLAG_TIME_IS_DTS; int loop = 0; while(demuxer_bytes) { // 500ms timeout OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer(500); if(omx_buffer == NULL) { CLog::Log(LOGERROR, "OMXVideo::Decode timeout\n"); printf("COMXVideo::Decode timeout\n"); return false; } omx_buffer->nFlags = nFlags; omx_buffer->nOffset = 0; omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts != DVD_NOPTS_VALUE ? pts : dts != DVD_NOPTS_VALUE ? dts : 0)); omx_buffer->nFilledLen = std::min((OMX_U32)demuxer_bytes, omx_buffer->nAllocLen); memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); demuxer_bytes -= omx_buffer->nFilledLen; demuxer_content += omx_buffer->nFilledLen; if(demuxer_bytes == 0) omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; 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); printf("%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); m_omx_decoder.DecoderEmptyBufferDone(m_omx_decoder.GetComponent(), omx_buffer); return false; } //CLog::Log(LOGINFO, "VideD: dts:%.0f pts:%.0f size:%d)\n", dts, pts, iSize); omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, 0); if (omx_err == OMX_ErrorNone) { if(!PortSettingsChanged()) { CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged omx_err(0x%08x)\n", CLASSNAME, __func__, omx_err); return false; } } omx_err = m_omx_decoder.WaitForEvent(OMX_EventParamOrConfigChanged, 0); if (omx_err == OMX_ErrorNone) { if(!PortSettingsChanged()) { CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged (EventParamOrConfigChanged) omx_err(0x%08x)\n", CLASSNAME, __func__, omx_err); } } } return true; } return false; }
int COMXVideo::Decode(uint8_t *pData, int iSize, double pts) { OMX_ERRORTYPE omx_err; if( m_drop_state ) return true; unsigned int demuxer_bytes = (unsigned int)iSize; uint8_t *demuxer_content = pData; if (demuxer_content && demuxer_bytes > 0) { while(demuxer_bytes) { // 500ms timeout OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer(500); if(omx_buffer == NULL) { CLog::Log(LOGERROR, "OMXVideo::Decode timeout\n"); return false; } omx_buffer->nFlags = 0; omx_buffer->nOffset = 0; if(m_setStartTime) { omx_buffer->nFlags |= OMX_BUFFERFLAG_STARTTIME; CLog::Log(LOGDEBUG, "OMXVideo::Decode VDec : setStartTime %f\n", (pts == DVD_NOPTS_VALUE ? 0.0 : pts) / DVD_TIME_BASE); m_setStartTime = false; } if(pts == DVD_NOPTS_VALUE) omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN; omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts); omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes; memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen); demuxer_bytes -= omx_buffer->nFilledLen; demuxer_content += omx_buffer->nFilledLen; if(demuxer_bytes == 0) omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; int nRetry = 0; while(true) { omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer); if (omx_err == OMX_ErrorNone) { //CLog::Log(LOGINFO, "VideD: dts:%.0f pts:%.0f size:%d)\n", dts, pts, iSize); break; } else { CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n", CLASSNAME, __func__, omx_err); nRetry++; } if(nRetry == 5) { CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() finally failed\n", CLASSNAME, __func__); return false; } } omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, 0); if (omx_err == OMX_ErrorNone) { if(!PortSettingsChanged()) { CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged omx_err(0x%08x)\n", CLASSNAME, __func__, omx_err); return false; } } omx_err = m_omx_decoder.WaitForEvent(OMX_EventParamOrConfigChanged, 0); if (omx_err == OMX_ErrorNone) { if(!PortSettingsChanged()) { CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged (EventParamOrConfigChanged) omx_err(0x%08x)\n", CLASSNAME, __func__, omx_err); } } } return true; } return false; }