double OMXPlayerVideo::NextOverlay(double pts) { double delta_start, delta_stop, min_delta = DVD_NOPTS_VALUE; CSingleLock lock(*m_pOverlayContainer); VecOverlays* pVecOverlays = m_pOverlayContainer->GetOverlays(); VecOverlaysIter it = pVecOverlays->begin(); //Find the minimum time before a subtitle is added or removed while (it != pVecOverlays->end()) { CDVDOverlay* pOverlay = *it++; if(!pOverlay->bForced && !m_bRenderSubs) continue; double pts2 = pOverlay->bForced ? pts : pts - m_iSubtitleDelay; delta_start = pOverlay->iPTSStartTime - pts2; delta_stop = pOverlay->iPTSStopTime - pts2; // when currently on screen, we periodically update to allow (limited rate) ASS animation if (delta_start <= 0.0 && delta_stop > 0.0 && (min_delta == DVD_NOPTS_VALUE || DVD_MSEC_TO_TIME(100) < min_delta)) min_delta = DVD_MSEC_TO_TIME(100); else if (delta_start > 0.0 && (min_delta == DVD_NOPTS_VALUE || delta_start < min_delta)) min_delta = delta_start; else if (delta_stop > 0.0 && (min_delta == DVD_NOPTS_VALUE || delta_stop < min_delta)) min_delta = delta_stop; } return min_delta == DVD_NOPTS_VALUE ? pts+DVD_MSEC_TO_TIME(500) : pts+std::max(min_delta, DVD_MSEC_TO_TIME(100)); }
void CDVDPlayerSubtitle::GetCurrentSubtitle(CStdString& strSubtitle, double pts) { strSubtitle = ""; Process(pts); // TODO: move to separate thread? CSingleLock lock(*m_pOverlayContainer); VecOverlays* pOverlays = m_pOverlayContainer->GetOverlays(); if (pOverlays) { for(vector<CDVDOverlay*>::iterator it = pOverlays->begin();it != pOverlays->end();it++) { CDVDOverlay* pOverlay = *it; if (pOverlay->IsOverlayType(DVDOVERLAY_TYPE_TEXT) && (pOverlay->iPTSStartTime <= pts) && (pOverlay->iPTSStopTime >= pts || pOverlay->iPTSStopTime == 0LL)) { CDVDOverlayText::CElement* e = ((CDVDOverlayText*)pOverlay)->m_pHead; while (e) { if (e->IsElementType(CDVDOverlayText::ELEMENT_TYPE_TEXT)) { CDVDOverlayText::CElementText* t = (CDVDOverlayText::CElementText*)e; strSubtitle += t->m_text; strSubtitle += "\n"; } e = e->pNext; } } } } strSubtitle.TrimRight('\n'); }
void CDVDPlayerVideo::ProcessOverlays(DVDVideoPicture* pSource, YV12Image* pDest, double pts) { // remove any overlays that are out of time m_pOverlayContainer->CleanUp(min(pts, pts - m_iSubtitleDelay)); // rendering spu overlay types directly on video memory costs a lot of processing power. // thus we allocate a temp picture, copy the original to it (needed because the same picture can be used more than once). // then do all the rendering on that temp picture and finaly copy it to video memory. // In almost all cases this is 5 or more times faster!. bool bHasSpecialOverlay = m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_SPU) || m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_IMAGE); if (bHasSpecialOverlay) { if (m_pTempOverlayPicture && (m_pTempOverlayPicture->iWidth != pSource->iWidth || m_pTempOverlayPicture->iHeight != pSource->iHeight)) { CDVDCodecUtils::FreePicture(m_pTempOverlayPicture); m_pTempOverlayPicture = NULL; } if (!m_pTempOverlayPicture) m_pTempOverlayPicture = CDVDCodecUtils::AllocatePicture(pSource->iWidth, pSource->iHeight); } if (bHasSpecialOverlay && m_pTempOverlayPicture) CDVDCodecUtils::CopyPicture(m_pTempOverlayPicture, pSource); else CDVDCodecUtils::CopyPictureToOverlay(pDest, pSource); m_pOverlayContainer->Lock(); VecOverlays* pVecOverlays = m_pOverlayContainer->GetOverlays(); VecOverlaysIter it = pVecOverlays->begin(); //Check all overlays and render those that should be rendered, based on time and forced //Both forced and subs should check timeing, pts == 0 in the stillframe case while (it != pVecOverlays->end()) { CDVDOverlay* pOverlay = *it++; if(!pOverlay->bForced && !m_bRenderSubs) continue; if(pOverlay->iGroupId != pSource->iGroupId) continue; double pts2 = pOverlay->bForced ? pts : pts - m_iSubtitleDelay; if(pOverlay->iPTSStartTime <= pts2 && (pOverlay->iPTSStopTime >= pts2 || pOverlay->iPTSStopTime == 0LL) || pts == 0) { if (bHasSpecialOverlay && m_pTempOverlayPicture) CDVDOverlayRenderer::Render(m_pTempOverlayPicture, pOverlay, pts); else CDVDOverlayRenderer::Render(pDest, pOverlay, pts); } } m_pOverlayContainer->Unlock(); if (bHasSpecialOverlay && m_pTempOverlayPicture) { CDVDCodecUtils::CopyPictureToOverlay(pDest, m_pTempOverlayPicture); } }
void CVideoPlayerVideo::ProcessOverlays(const VideoPicture* pSource, double pts) { // remove any overlays that are out of time if (m_syncState == IDVDStreamPlayer::SYNC_INSYNC) m_pOverlayContainer->CleanUp(pts - m_iSubtitleDelay); VecOverlays overlays; { CSingleLock lock(*m_pOverlayContainer); VecOverlays* pVecOverlays = m_pOverlayContainer->GetOverlays(); VecOverlaysIter it = pVecOverlays->begin(); //Check all overlays and render those that should be rendered, based on time and forced //Both forced and subs should check timing while (it != pVecOverlays->end()) { CDVDOverlay* pOverlay = *it++; if(!pOverlay->bForced && !m_bRenderSubs) continue; double pts2 = pOverlay->bForced ? pts : pts - m_iSubtitleDelay; if((pOverlay->iPTSStartTime <= pts2 && (pOverlay->iPTSStopTime > pts2 || pOverlay->iPTSStopTime == 0LL))) { if(pOverlay->IsOverlayType(DVDOVERLAY_TYPE_GROUP)) overlays.insert(overlays.end(), static_cast<CDVDOverlayGroup*>(pOverlay)->m_overlays.begin() , static_cast<CDVDOverlayGroup*>(pOverlay)->m_overlays.end()); else overlays.push_back(pOverlay); } } for(it = overlays.begin(); it != overlays.end(); ++it) { double pts2 = (*it)->bForced ? pts : pts - m_iSubtitleDelay; m_renderManager.AddOverlay(*it, pts2); } } }
void OMXPlayerVideo::ProcessOverlays(int iGroupId, double pts) { // remove any overlays that are out of time if (m_started) m_pOverlayContainer->CleanUp(pts - m_iSubtitleDelay); VecOverlays overlays; CSingleLock lock(*m_pOverlayContainer); VecOverlays* pVecOverlays = m_pOverlayContainer->GetOverlays(); VecOverlaysIter it = pVecOverlays->begin(); //Check all overlays and render those that should be rendered, based on time and forced //Both forced and subs should check timeing, pts == 0 in the stillframe case while (it != pVecOverlays->end()) { CDVDOverlay* pOverlay = *it++; if(!pOverlay->bForced && !m_bRenderSubs) continue; if(pOverlay->iGroupId != iGroupId) continue; double pts2 = pOverlay->bForced ? pts : pts - m_iSubtitleDelay; if((pOverlay->iPTSStartTime <= pts2 && (pOverlay->iPTSStopTime > pts2 || pOverlay->iPTSStopTime == 0LL)) || pts == 0) { if(pOverlay->IsOverlayType(DVDOVERLAY_TYPE_GROUP)) overlays.insert(overlays.end(), static_cast<CDVDOverlayGroup*>(pOverlay)->m_overlays.begin() , static_cast<CDVDOverlayGroup*>(pOverlay)->m_overlays.end()); else overlays.push_back(pOverlay); } } for(it = overlays.begin(); it != overlays.end(); ++it) { double pts2 = (*it)->bForced ? pts : pts - m_iSubtitleDelay; g_renderManager.AddOverlay(*it, pts2); } }
void CDVDPlayerVideo::ProcessOverlays(DVDVideoPicture* pSource, double pts) { // remove any overlays that are out of time if (m_started) m_pOverlayContainer->CleanUp(pts - m_iSubtitleDelay); enum EOverlay { OVERLAY_AUTO // select mode auto , OVERLAY_GPU // render osd using gpu , OVERLAY_BUF // render osd on buffer } render = OVERLAY_AUTO; if(pSource->format == DVDVideoPicture::FMT_YUV420P) { if(g_Windowing.GetRenderQuirks() & RENDER_QUIRKS_MAJORMEMLEAK_OVERLAYRENDERER) { // for now use cpu for ssa overlays as it currently allocates and // frees textures for each frame this causes a hugh memory leak // on some mesa intel drivers if(m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_SPU) || m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_IMAGE) || m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_SSA) ) render = OVERLAY_BUF; } if(render == OVERLAY_BUF) { // rendering spu overlay types directly on video memory costs a lot of processing power. // thus we allocate a temp picture, copy the original to it (needed because the same picture can be used more than once). // then do all the rendering on that temp picture and finaly copy it to video memory. // In almost all cases this is 5 or more times faster!. if(m_pTempOverlayPicture && ( m_pTempOverlayPicture->iWidth != pSource->iWidth || m_pTempOverlayPicture->iHeight != pSource->iHeight)) { CDVDCodecUtils::FreePicture(m_pTempOverlayPicture); m_pTempOverlayPicture = NULL; } if(!m_pTempOverlayPicture) m_pTempOverlayPicture = CDVDCodecUtils::AllocatePicture(pSource->iWidth, pSource->iHeight); if(!m_pTempOverlayPicture) return; CDVDCodecUtils::CopyPicture(m_pTempOverlayPicture, pSource); memcpy(pSource->data , m_pTempOverlayPicture->data , sizeof(pSource->data)); memcpy(pSource->iLineSize, m_pTempOverlayPicture->iLineSize, sizeof(pSource->iLineSize)); } } if(render == OVERLAY_AUTO) render = OVERLAY_GPU; VecOverlays overlays; { CSingleLock lock(*m_pOverlayContainer); VecOverlays* pVecOverlays = m_pOverlayContainer->GetOverlays(); VecOverlaysIter it = pVecOverlays->begin(); //Check all overlays and render those that should be rendered, based on time and forced //Both forced and subs should check timeing, pts == 0 in the stillframe case while (it != pVecOverlays->end()) { CDVDOverlay* pOverlay = *it++; if(!pOverlay->bForced && !m_bRenderSubs) continue; if(pOverlay->iGroupId != pSource->iGroupId) continue; double pts2 = pOverlay->bForced ? pts : pts - m_iSubtitleDelay; if((pOverlay->iPTSStartTime <= pts2 && (pOverlay->iPTSStopTime > pts2 || pOverlay->iPTSStopTime == 0LL)) || pts == 0) { if(pOverlay->IsOverlayType(DVDOVERLAY_TYPE_GROUP)) overlays.insert(overlays.end(), static_cast<CDVDOverlayGroup*>(pOverlay)->m_overlays.begin() , static_cast<CDVDOverlayGroup*>(pOverlay)->m_overlays.end()); else overlays.push_back(pOverlay); } } for(it = overlays.begin(); it != overlays.end(); ++it) { double pts2 = (*it)->bForced ? pts : pts - m_iSubtitleDelay; if (render == OVERLAY_GPU) g_renderManager.AddOverlay(*it, pts2); if (render == OVERLAY_BUF) CDVDOverlayRenderer::Render(pSource, *it, pts2); } } }
void OMXPlayerVideo::ProcessOverlays(int iGroupId, double pts) { // remove any overlays that are out of time if (m_started) m_pOverlayContainer->CleanUp(pts - m_iSubtitleDelay); enum EOverlay { OVERLAY_AUTO // select mode auto , OVERLAY_GPU // render osd using gpu , OVERLAY_BUF // render osd on buffer } render = OVERLAY_AUTO; /* if(m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_SPU) || m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_IMAGE) || m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_SSA) ) render = OVERLAY_BUF; */ if(render == OVERLAY_BUF) { // rendering spu overlay types directly on video memory costs a lot of processing power. // thus we allocate a temp picture, copy the original to it (needed because the same picture can be used more than once). // then do all the rendering on that temp picture and finaly copy it to video memory. // In almost all cases this is 5 or more times faster!. if(m_pTempOverlayPicture && ( m_pTempOverlayPicture->iWidth != m_width || m_pTempOverlayPicture->iHeight != m_height)) { CDVDCodecUtils::FreePicture(m_pTempOverlayPicture); m_pTempOverlayPicture = NULL; } if(!m_pTempOverlayPicture) m_pTempOverlayPicture = CDVDCodecUtils::AllocatePicture(m_width, m_height); if(!m_pTempOverlayPicture) return; m_pTempOverlayPicture->format = RENDER_FMT_YUV420P; } if(render == OVERLAY_AUTO) render = OVERLAY_GPU; VecOverlays overlays; { CSingleLock lock(*m_pOverlayContainer); VecOverlays* pVecOverlays = m_pOverlayContainer->GetOverlays(); VecOverlaysIter it = pVecOverlays->begin(); //Check all overlays and render those that should be rendered, based on time and forced //Both forced and subs should check timeing, pts == 0 in the stillframe case while (it != pVecOverlays->end()) { CDVDOverlay* pOverlay = *it++; if(!pOverlay->bForced && !m_bRenderSubs) continue; if(pOverlay->iGroupId != iGroupId) continue; double pts2 = pOverlay->bForced ? pts : pts - m_iSubtitleDelay; if((pOverlay->iPTSStartTime <= pts2 && (pOverlay->iPTSStopTime > pts2 || pOverlay->iPTSStopTime == 0LL)) || pts == 0) { if(pOverlay->IsOverlayType(DVDOVERLAY_TYPE_GROUP)) overlays.insert(overlays.end(), static_cast<CDVDOverlayGroup*>(pOverlay)->m_overlays.begin() , static_cast<CDVDOverlayGroup*>(pOverlay)->m_overlays.end()); else overlays.push_back(pOverlay); } } for(it = overlays.begin(); it != overlays.end(); ++it) { double pts2 = (*it)->bForced ? pts : pts - m_iSubtitleDelay; if (render == OVERLAY_GPU) g_renderManager.AddOverlay(*it, pts2); /* printf("subtitle : DVDOVERLAY_TYPE_SPU %d DVDOVERLAY_TYPE_IMAGE %d DVDOVERLAY_TYPE_SSA %d\n", m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_SPU), m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_IMAGE), m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_SSA) ); */ if (render == OVERLAY_BUF) CDVDOverlayRenderer::Render(m_pTempOverlayPicture, *it, pts2); } } }
void CDVDPlayerVideo::ProcessOverlays(DVDVideoPicture* pSource, YV12Image* pDest, double pts) { // remove any overlays that are out of time m_pOverlayContainer->CleanUp(min(pts, pts - m_iSubtitleDelay)); enum EOverlay { OVERLAY_AUTO // select mode auto , OVERLAY_GPU // render osd using gpu , OVERLAY_VID // render osd directly on video memory , OVERLAY_BUF // render osd on buffer } render = OVERLAY_AUTO; if(render == OVERLAY_AUTO) { render = OVERLAY_GPU; #ifdef _LINUX // for now use cpu for ssa overlays as it currently allocates and // frees textures for each frame this causes a hugh memory leak // on some mesa intel drivers if(m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_SSA) && pSource->format == DVDVideoPicture::FMT_YUV420P) render = OVERLAY_VID; #endif if(render == OVERLAY_VID) { if( m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_SPU) || m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_IMAGE) || m_pOverlayContainer->ContainsOverlayType(DVDOVERLAY_TYPE_SSA) ) render = OVERLAY_BUF; } } if(pSource->format == DVDVideoPicture::FMT_YUV420P) { if(render == OVERLAY_BUF) { // rendering spu overlay types directly on video memory costs a lot of processing power. // thus we allocate a temp picture, copy the original to it (needed because the same picture can be used more than once). // then do all the rendering on that temp picture and finaly copy it to video memory. // In almost all cases this is 5 or more times faster!. if(m_pTempOverlayPicture && ( m_pTempOverlayPicture->iWidth != pSource->iWidth || m_pTempOverlayPicture->iHeight != pSource->iHeight)) { CDVDCodecUtils::FreePicture(m_pTempOverlayPicture); m_pTempOverlayPicture = NULL; } if(!m_pTempOverlayPicture) m_pTempOverlayPicture = CDVDCodecUtils::AllocatePicture(pSource->iWidth, pSource->iHeight); if(!m_pTempOverlayPicture) return; CDVDCodecUtils::CopyPicture(m_pTempOverlayPicture, pSource); } else { AutoCrop(pSource); CDVDCodecUtils::CopyPicture(pDest, pSource); } } m_pOverlayContainer->Lock(); VecOverlays* pVecOverlays = m_pOverlayContainer->GetOverlays(); VecOverlaysIter it = pVecOverlays->begin(); //Check all overlays and render those that should be rendered, based on time and forced //Both forced and subs should check timeing, pts == 0 in the stillframe case while (it != pVecOverlays->end()) { CDVDOverlay* pOverlay = *it++; if(!pOverlay->bForced && !m_bRenderSubs) continue; if(pOverlay->iGroupId != pSource->iGroupId) continue; double pts2 = pOverlay->bForced ? pts : pts - m_iSubtitleDelay; if((pOverlay->iPTSStartTime <= pts2 && (pOverlay->iPTSStopTime > pts2 || pOverlay->iPTSStopTime == 0LL)) || pts == 0) { if (render == OVERLAY_GPU) g_renderManager.AddOverlay(pOverlay, pts2); if(pSource->format == DVDVideoPicture::FMT_YUV420P) { if (render == OVERLAY_BUF) CDVDOverlayRenderer::Render(m_pTempOverlayPicture, pOverlay, pts2); else if(render == OVERLAY_VID) CDVDOverlayRenderer::Render(pDest, pOverlay, pts2); } } } m_pOverlayContainer->Unlock(); if(pSource->format == DVDVideoPicture::FMT_YUV420P) { if(render == OVERLAY_BUF) { AutoCrop(m_pTempOverlayPicture); CDVDCodecUtils::CopyPicture(pDest, m_pTempOverlayPicture); } } else if(pSource->format == DVDVideoPicture::FMT_NV12) { AutoCrop(pSource); CDVDCodecUtils::CopyNV12Picture(pDest, pSource); } else if(pSource->format == DVDVideoPicture::FMT_YUY2 || pSource->format == DVDVideoPicture::FMT_UYVY) { AutoCrop(pSource); CDVDCodecUtils::CopyYUV422PackedPicture(pDest, pSource); } #ifdef HAS_DX else if(pSource->format == DVDVideoPicture::FMT_DXVA) g_renderManager.AddProcessor(pSource->proc, pSource->proc_id); #endif #ifdef HAVE_LIBVDPAU else if(pSource->format == DVDVideoPicture::FMT_VDPAU) g_renderManager.AddProcessor(pSource->vdpau); #endif #ifdef HAVE_LIBVA else if(pSource->format == DVDVideoPicture::FMT_VAAPI) g_renderManager.AddProcessor(*pSource->vaapi); #endif }