Skip to content

Commit

Permalink
Merge pull request xbmc#7088 from popcornmix/dtspts
Browse files Browse the repository at this point in the history
[pi/players] Make use of new scheme to submit DTS timestamps
  • Loading branch information
popcornmix committed May 8, 2015
2 parents 25a3d5f + 9d59db1 commit e7446ab
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 80 deletions.
55 changes: 18 additions & 37 deletions xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ CMMALVideoBuffer::CMMALVideoBuffer(CMMALVideo *omv)
height = 0;
m_aspect_ratio = 0.0f;
m_changed_count = 0;
dts = DVD_NOPTS_VALUE;
}

CMMALVideoBuffer::~CMMALVideoBuffer()
Expand Down Expand Up @@ -256,37 +255,23 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf
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)
{
pthread_mutex_lock(&m_output_mutex);
m_droppedPics++;
pthread_mutex_unlock(&m_output_mutex);
if (g_advancedSettings.CanLogComponent(LOGVIDEO))
CLog::Log(LOGDEBUG, "%s::%s - dropping %p (drop:%d)", CLASSNAME, __func__, buffer, m_drop_state);
CLog::Log(LOGDEBUG, "%s::%s - dropping %p dts:%.3f pts:%.3f (drop:%d len:%d flags:%x)", CLASSNAME, __func__, buffer, buffer->dts*1e-6, buffer->pts*1e-6, m_drop_state, buffer->length, buffer->flags);
}
else
{
CMMALVideoBuffer *omvb = new CMMALVideoBuffer(this);
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);
CLASSNAME, __func__, buffer, omvb, buffer->length, buffer->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;
Expand Down Expand Up @@ -647,6 +632,10 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVide
if (status != MMAL_SUCCESS)
CLog::Log(LOGERROR, "%s::%s Failed to enable extra buffers on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status));

status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_VIDEO_INTERPOLATE_TIMESTAMPS, 0);
if (status != MMAL_SUCCESS)
CLog::Log(LOGERROR, "%s::%s Failed to disable interpolate timestamps mode on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status));

status = mmal_port_format_commit(m_dec_input);
if (status != MMAL_SUCCESS)
{
Expand Down Expand Up @@ -730,10 +719,9 @@ void CMMALVideo::Dispose()
done = true;
pthread_mutex_unlock(&m_output_mutex);
if (g_advancedSettings.CanLogComponent(LOGVIDEO))
CLog::Log(LOGDEBUG, "%s::%s dts_queue(%d) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, m_dts_queue.size(), m_output_ready.size(), m_output_busy, done);
CLog::Log(LOGDEBUG, "%s::%s ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, m_output_ready.size(), m_output_busy, done);
if (done)
{
assert(m_dts_queue.empty());
m_myself.reset();
}
}
Expand Down Expand Up @@ -769,8 +757,8 @@ void CMMALVideo::SetDropState(bool bDrop)
int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
{
//if (g_advancedSettings.CanLogComponent(LOGVIDEO))
// CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d dts:%.3f pts:%.3f dts_queue(%d) ready_queue(%d) busy_queue(%d)",
// CLASSNAME, __func__, pData, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, m_dts_queue.size(), m_output_ready.size(), m_output_busy);
// CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d dts:%.3f pts:%.3f ready_queue(%d) busy_queue(%d)",
// CLASSNAME, __func__, pData, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, m_output_ready.size(), m_output_busy);

unsigned int demuxer_bytes = 0;
uint8_t *demuxer_content = NULL;
Expand Down Expand Up @@ -840,6 +828,7 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
pts = 0;
buffer->pts = pts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : pts;
buffer->dts = dts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : dts;
if (buffer->dts != MMAL_TIME_UNKNOWN) buffer->pts = MMAL_TIME_UNKNOWN;
buffer->length = demuxer_bytes > buffer->alloc_size ? buffer->alloc_size : demuxer_bytes;
// set a flag so we can identify primary frames from generated frames (deinterlace)
buffer->flags = MMAL_BUFFER_HEADER_FLAG_USER0;
Expand All @@ -856,8 +845,8 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;

if (g_advancedSettings.CanLogComponent(LOGVIDEO))
CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d/%-6d dts:%.3f pts:%.3f flags:%x dts_queue(%d) ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d)",
CLASSNAME, __func__, buffer, buffer->length, demuxer_bytes, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, buffer->flags, m_dts_queue.size(), m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size);
CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d/%-6d dts:%.3f pts:%.3f flags:%x ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d)",
CLASSNAME, __func__, buffer, buffer->length, demuxer_bytes, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, buffer->flags, m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size);
assert((int)buffer->length > 0);
status = mmal_port_send_buffer(m_dec_input, buffer);
if (status != MMAL_SUCCESS)
Expand All @@ -874,12 +863,6 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
{
m_droppedPics += m_deint ? 2:1;
}
else
{
// only push if we are successful with feeding mmal
m_dts_queue.push(dts);
assert(m_dts_queue.size() < 5000);
}
pthread_mutex_unlock(&m_output_mutex);
if (m_changed_count_dec != m_changed_count)
{
Expand Down Expand Up @@ -943,8 +926,8 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
if (!ret)
{
if (g_advancedSettings.CanLogComponent(LOGVIDEO))
CLog::Log(LOGDEBUG, "%s::%s - Nothing to do: dts_queue(%d) ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d) preroll(%d)",
CLASSNAME, __func__, m_dts_queue.size(), m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size, m_preroll);
CLog::Log(LOGDEBUG, "%s::%s - Nothing to do: ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d) preroll(%d)",
CLASSNAME, __func__, m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size, m_preroll);
Sleep(10); // otherwise we busy spin
}
return ret;
Expand Down Expand Up @@ -974,8 +957,6 @@ void CMMALVideo::Reset(void)
bool old_drop_state = m_drop_state;
SetDropState(true);
pthread_mutex_lock(&m_output_mutex);
while(!m_dts_queue.empty())
m_dts_queue.pop();
while (!m_demux_queue.empty())
m_demux_queue.pop();
m_demux_queue_length = 0;
Expand Down Expand Up @@ -1009,8 +990,8 @@ void CMMALVideo::Recycle(MMAL_BUFFER_HEADER_T *buffer)
mmal_buffer_header_reset(buffer);
buffer->cmd = 0;
if (g_advancedSettings.CanLogComponent(LOGVIDEO))
CLog::Log(LOGDEBUG, "%s::%s Send buffer %p from pool to decoder output port %p dts_queue(%d) ready_queue(%d) busy_queue(%d)", CLASSNAME, __func__, buffer, m_dec_output,
m_dts_queue.size(), m_output_ready.size(), m_output_busy);
CLog::Log(LOGDEBUG, "%s::%s Send buffer %p from pool to decoder output port %p ready_queue(%d) busy_queue(%d)", CLASSNAME, __func__, buffer, m_dec_output,
m_output_ready.size(), m_output_busy);
status = mmal_port_send_buffer(m_dec_output, buffer);
if (status != MMAL_SUCCESS)
{
Expand All @@ -1037,7 +1018,7 @@ void CMMALVideo::ReleaseBuffer(CMMALVideoBuffer *buffer)
if (done)
m_myself.reset();
if (g_advancedSettings.CanLogComponent(LOGVIDEO))
CLog::Log(LOGDEBUG, "%s::%s %p (%p) dts_queue(%d) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, buffer, buffer->mmal_buffer, m_dts_queue.size(), m_output_ready.size(), m_output_busy, done);
CLog::Log(LOGDEBUG, "%s::%s %p (%p) ready_queue(%d) busy_queue(%d) done:%d", CLASSNAME, __func__, buffer, buffer->mmal_buffer, m_output_ready.size(), m_output_busy, done);
delete buffer;
}

Expand Down Expand Up @@ -1075,7 +1056,7 @@ bool CMMALVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
}

// timestamp is in microseconds
pDvdVideoPicture->dts = buffer->dts;
pDvdVideoPicture->dts = buffer->mmal_buffer->dts == MMAL_TIME_UNKNOWN || buffer->mmal_buffer->dts == 0 ? DVD_NOPTS_VALUE : buffer->mmal_buffer->dts;
pDvdVideoPicture->pts = buffer->mmal_buffer->pts == MMAL_TIME_UNKNOWN || buffer->mmal_buffer->pts == 0 ? DVD_NOPTS_VALUE : buffer->mmal_buffer->pts;

pDvdVideoPicture->MMALBuffer->Acquire();
Expand Down
2 changes: 0 additions & 2 deletions xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ class CMMALVideoBuffer
int width;
int height;
float m_aspect_ratio;
double dts;
uint32_t m_changed_count;
// reference counting
CMMALVideoBuffer* Acquire();
Expand Down Expand Up @@ -117,7 +116,6 @@ class CMMALVideo
const char *m_pFormatName;
MMALVideoPtr m_myself;

std::queue<double> m_dts_queue;
std::queue<mmal_demux_packet> m_demux_queue;
unsigned m_demux_queue_length;

Expand Down
28 changes: 9 additions & 19 deletions xbmc/cores/omxplayer/OMXPlayerVideo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ OMXPlayerVideo::OMXPlayerVideo(OMXClock *av_clock,
m_iCurrentPts = DVD_NOPTS_VALUE;
m_nextOverlay = DVD_NOPTS_VALUE;
m_flush = false;
m_history_valid_pts = 0;
}

OMXPlayerVideo::~OMXPlayerVideo()
Expand Down Expand Up @@ -313,14 +312,6 @@ void OMXPlayerVideo::Output(double pts, bool bDropPacket)
g_renderManager.FlipPage(CThread::m_bStop, time/DVD_TIME_BASE);
}

static unsigned count_bits(int32_t value)
{
unsigned bits = 0;
for(;value;++bits)
value &= value - 1;
return bits;
}

void OMXPlayerVideo::Process()
{
double frametime = (double)DVD_TIME_BASE / m_fFrameRate;
Expand Down Expand Up @@ -495,18 +486,20 @@ void OMXPlayerVideo::Process()
m_stalled = false;
}

// 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) | (pPacket->pts != DVD_NOPTS_VALUE);
double dts = pPacket->dts;
double pts = pPacket->pts;
if(count_bits(m_history_valid_pts & 0xffff) < 4)
pts = pPacket->dts;

if (dts != DVD_NOPTS_VALUE)
dts += m_iVideoDelay;

if (pts != DVD_NOPTS_VALUE)
pts += m_iVideoDelay;

m_omxVideo.Decode(pPacket->pData, pPacket->iSize, pts);
m_omxVideo.Decode(pPacket->pData, pPacket->iSize, dts, dts == DVD_NOPTS_VALUE ? pts : DVD_NOPTS_VALUE);

if (pts == DVD_NOPTS_VALUE)
pts = dts;

Output(pts, bRequestDrop);
if(pts != DVD_NOPTS_VALUE)
m_iCurrentPts = pts;
Expand Down Expand Up @@ -582,9 +575,6 @@ bool OMXPlayerVideo::OpenDecoder()
m_codecname = m_omxVideo.GetDecoderName();
}

// start from assuming all recent frames had valid pts
m_history_valid_pts = ~0;

return bVideoDecoderOpen;
}

Expand Down
1 change: 0 additions & 1 deletion xbmc/cores/omxplayer/OMXPlayerVideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ class OMXPlayerVideo : public CThread, public IDVDStreamPlayerVideo
RENDER_STEREO_MODE m_video_stereo_mode;
RENDER_STEREO_MODE m_display_stereo_mode;
bool m_StereoInvert;
uint32_t m_history_valid_pts;
DllBcmHost m_DllBcmHost;

CDVDOverlayContainer *m_pOverlayContainer;
Expand Down
25 changes: 5 additions & 20 deletions xbmc/cores/omxplayer/OMXVideo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,23 +606,6 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de
return false;
}

// broadcom omx entension:
// When enabled, the timestamp fifo mode will change the way incoming timestamps are associated with output images.
// In this mode the incoming timestamps get used without re-ordering on output images.
// recent firmware will actually automatically choose the timestamp stream with the least variance, so always enable
{
OMX_CONFIG_BOOLEANTYPE timeStampMode;
OMX_INIT_STRUCTURE(timeStampMode);
timeStampMode.bEnabled = OMX_TRUE;

omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamBrcmVideoTimestampFifo, &timeStampMode);
if (omx_err != OMX_ErrorNone)
{
CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexParamBrcmVideoTimestampFifo error (0%08x)\n", omx_err);
return false;
}
}

if(NaluFormatStartCodes(hints.codec, m_extradata, m_extrasize))
{
OMX_NALSTREAMFORMATTYPE nalStreamFormat;
Expand Down Expand Up @@ -762,7 +745,7 @@ bool COMXVideo::GetPlayerInfo(double &match, double &phase, double &pll)
}


int COMXVideo::Decode(uint8_t *pData, int iSize, double pts)
int COMXVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)
{
CSingleLock lock (m_critSection);
OMX_ERRORTYPE omx_err;
Expand All @@ -787,17 +770,19 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double pts)

omx_buffer->nFlags = 0;
omx_buffer->nOffset = 0;
omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts != DVD_NOPTS_VALUE ? pts : dts != DVD_NOPTS_VALUE ? dts : 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)
else if (pts == DVD_NOPTS_VALUE && dts == DVD_NOPTS_VALUE)
omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
else if (pts == DVD_NOPTS_VALUE)
omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_IS_DTS;

omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts);
omx_buffer->nFilledLen = std::min((OMX_U32)demuxer_bytes, omx_buffer->nAllocLen);
memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen);

Expand Down
2 changes: 1 addition & 1 deletion xbmc/cores/omxplayer/OMXVideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class COMXVideo
void Close(void);
unsigned int GetFreeSpace();
unsigned int GetSize();
int Decode(uint8_t *pData, int iSize, double pts);
int Decode(uint8_t *pData, int iSize, double dts, double pts);
void Reset(void);
void SetDropState(bool bDrop);
std::string GetDecoderName() { return m_video_codec_name; };
Expand Down

0 comments on commit e7446ab

Please sign in to comment.