OMXClock::OMXClock() { m_dllAvFormat.Load(); m_video_clock = DVD_NOPTS_VALUE; m_audio_clock = DVD_NOPTS_VALUE; m_has_video = false; m_has_audio = false; m_play_speed = 1; m_pause = false; m_iCurrentPts = DVD_NOPTS_VALUE; m_systemFrequency = CurrentHostFrequency(); m_systemUsed = m_systemFrequency; m_pauseClock = 0; m_bReset = true; m_iDisc = 0; m_maxspeedadjust = 0.0; m_speedadjust = false; m_ismasterclock = true; m_ClockOffset = 0; m_fps = 25.0f; pthread_mutex_init(&m_lock, NULL); CheckSystemClock(); OMXReset(); }
void CVideoSyncDRM::EventHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data) { drmVBlank vbl; VblInfo *info = (VblInfo*)data; int crtc = g_Windowing.GetCrtc(); vbl.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT); if (crtc == 1) { vbl.request.type = (drmVBlankSeqType)(vbl.request.type | DRM_VBLANK_SECONDARY); } else if (crtc > 1) { vbl.request.type = (drmVBlankSeqType)(vbl.request.type | ((crtc << DRM_VBLANK_HIGH_CRTC_SHIFT) & DRM_VBLANK_HIGH_CRTC_MASK)); } vbl.request.sequence = 1; vbl.request.signal = (unsigned long)data; drmWaitVBlank(info->videoSync->m_fd, &vbl); uint64_t now = CurrentHostCounter(); float diff = (float)(now - info->start)/CurrentHostFrequency(); int vblanks = MathUtils::round_int(diff * info->videoSync->m_fps); info->start = now; info->videoSync->UpdateClock(vblanks, now); }
OMXClock::OMXClock() { m_dllAvFormat.Load(); m_video_clock = DVD_NOPTS_VALUE; m_audio_clock = DVD_NOPTS_VALUE; m_has_video = false; m_has_audio = false; m_play_speed = 1 * OMX_SLOMO_MULTIPLIER; // Adjusting initial speed for normal video playback, so it can accomodate the new slow motion range m_pause = false; m_iCurrentPts = DVD_NOPTS_VALUE; m_systemFrequency = CurrentHostFrequency(); m_systemUsed = m_systemFrequency; m_pauseClock = 0; m_bReset = true; m_iDisc = 0; m_maxspeedadjust = 0.0; m_speedadjust = false; m_ismasterclock = true; m_ClockOffset = 0; m_fps = 25.0f; pthread_mutex_init(&m_lock, NULL); CheckSystemClock(); OMXReset(); }
int CDVDVideoCodecVDA::Decode(BYTE* pData, int iSize, double dts, double pts) { CCocoaAutoPool pool; // if (pData) { OSStatus status; double sort_time; uint32_t avc_flags = 0; CFDataRef avc_demux; CFDictionaryRef avc_time; if (m_convert_bytestream) { // convert demuxer packet from bytestream (AnnexB) to bitstream ByteIOContext *pb; int demuxer_bytes; uint8_t *demuxer_content; if(m_dllAvFormat->url_open_dyn_buf(&pb) < 0) { return VC_ERROR; } demuxer_bytes = avc_parse_nal_units(m_dllAvFormat, pb, pData, iSize); demuxer_bytes = m_dllAvFormat->url_close_dyn_buf(pb, &demuxer_content); avc_demux = CFDataCreate(kCFAllocatorDefault, demuxer_content, demuxer_bytes); m_dllAvUtil->av_free(demuxer_content); } else { avc_demux = CFDataCreate(kCFAllocatorDefault, pData, iSize); } sort_time = (CurrentHostCounter() * 1000.0) / CurrentHostFrequency(); avc_time = CreateDictionaryWithDisplayTime(sort_time - m_sort_time_offset, dts, pts); if (m_DropPictures) avc_flags = kVDADecoderDecodeFlags_DontEmitFrame; status = m_dll->VDADecoderDecode((VDADecoder)m_vda_decoder, avc_flags, avc_demux, avc_time); CFRelease(avc_time); CFRelease(avc_demux); if (status != kVDADecoderNoErr) { CLog::Log(LOGNOTICE, "%s - VDADecoderDecode failed, status(%d)", __FUNCTION__, (int)status); return VC_ERROR; } } // TODO: queue depth is related to the number of reference frames in encoded h.264. // so we need to buffer until we get N ref frames + 1. if (m_queue_depth < 4) { return VC_BUFFER; } return VC_PICTURE | VC_BUFFER; }
void CDVDVideoCodecVDA::Reset(void) { CCocoaAutoPool pool; m_dll->VDADecoderFlush((VDADecoder)m_vda_decoder, 0); while (m_queue_depth) DisplayQueuePop(); m_sort_time_offset = (CurrentHostCounter() * 1000.0) / CurrentHostFrequency(); }
double AEDelayStatus::GetDelay() { double d = 0; if (tick) d = (double)(CurrentHostCounter() - tick) / CurrentHostFrequency(); if (d > maxcorrection) d = maxcorrection; return delay - d; }
void CVideoSyncD3D::Run(CEvent& stopEvent) { int64_t Now; int64_t LastVBlankTime; int NrVBlanks; double VBlankTime; int64_t systemFrequency = CurrentHostFrequency(); // init the vblanktime Now = CurrentHostCounter(); LastVBlankTime = Now; m_lastUpdateTime = Now - systemFrequency; while (!stopEvent.Signaled() && !m_displayLost && !m_displayReset) { // sleep until vblank Microsoft::WRL::ComPtr<IDXGIOutput> pOutput; DX::DeviceResources::Get()->GetOutput(&pOutput); HRESULT hr = pOutput->WaitForVBlank(); // calculate how many vblanks happened Now = CurrentHostCounter(); VBlankTime = (double)(Now - LastVBlankTime) / (double)systemFrequency; NrVBlanks = MathUtils::round_int(VBlankTime * m_fps); // update the vblank timestamp, update the clock and send a signal that we got a vblank UpdateClock(NrVBlanks, Now, m_refClock); // save the timestamp of this vblank so we can calculate how many vblanks happened next time LastVBlankTime = Now; if ((Now - m_lastUpdateTime) >= systemFrequency) { float fps = m_fps; if (fps != GetFps()) break; } // because we had a vblank, sleep until half the refreshrate period because i think WaitForVBlank block any rendering stuf // without sleeping we have freeze rendering int SleepTime = (int)((LastVBlankTime + (systemFrequency / MathUtils::round_int(m_fps) / 2) - Now) * 1000 / systemFrequency); if (SleepTime > 50) SleepTime = 50; //failsafe if (SleepTime > 0) ::Sleep(SleepTime); } m_lostEvent.Set(); while (!stopEvent.Signaled() && m_displayLost && !m_displayReset) { Sleep(10); } }
void CRenderSystemGLES::SetVSync(bool enable) { if (m_bVSync==enable && m_bVsyncInit == true) return; if (!m_bRenderCreated) return; if (enable) CLog::Log(LOGINFO, "GLES: Enabling VSYNC"); else CLog::Log(LOGINFO, "GLES: Disabling VSYNC"); m_iVSyncMode = 0; m_iVSyncErrors = 0; m_iSwapRate = 0; m_bVSync = enable; m_bVsyncInit = true; SetVSyncImpl(enable); if (!enable) return; if (g_advancedSettings.m_ForcedSwapTime != 0.0) { /* some hardware busy wait on swap/glfinish, so we must manually sleep to avoid 100% cpu */ double rate = g_graphicsContext.GetFPS(); if (rate <= 0.0 || rate > 1000.0) { CLog::Log(LOGWARNING, "Unable to determine a valid horizontal refresh rate, vsync workaround disabled %.2g", rate); m_iSwapRate = 0; } else { int64_t freq; freq = CurrentHostFrequency(); m_iSwapRate = (int64_t)((double)freq / rate); m_iSwapTime = (int64_t)(0.001 * g_advancedSettings.m_ForcedSwapTime * freq); m_iSwapStamp = 0; CLog::Log(LOGINFO, "GLES: Using artificial vsync sleep with rate %f", rate); if(!m_iVSyncMode) m_iVSyncMode = 1; } } if (!m_iVSyncMode) CLog::Log(LOGERROR, "GLES: Vertical Blank Syncing unsupported"); else CLog::Log(LOGINFO, "GLES: Selected vsync mode %d", m_iVSyncMode); }
CStopWatch::CStopWatch(bool useFrameTime /*=false*/) { m_timerPeriod = 0.0f; m_startTick = 0; m_isRunning = false; m_useFrameTime = useFrameTime; #ifdef TARGET_POSIX m_timerPeriod = 1.0f / 1000.0f; // we want seconds #else if (m_useFrameTime) m_timerPeriod = 1.0f / 1000.0f; //frametime is in milliseconds else m_timerPeriod = 1.0f / (float)CurrentHostFrequency(); #endif }
void CVideoSyncAndroid::FrameCallback(int64_t frameTimeNanos) { int NrVBlanks; double VBlankTime; int64_t nowtime = CurrentHostCounter(); //calculate how many vblanks happened VBlankTime = (double)(nowtime - m_LastVBlankTime) / (double)CurrentHostFrequency(); NrVBlanks = MathUtils::round_int(VBlankTime * m_fps); //save the timestamp of this vblank so we can calculate how many happened next time m_LastVBlankTime = nowtime; //update the vblank timestamp, update the clock and send a signal that we got a vblank UpdateClock(NrVBlanks, nowtime, m_refClock); }
CVideoReferenceClock::CVideoReferenceClock() : CThread("RefClock") { m_SystemFrequency = CurrentHostFrequency(); m_ClockSpeed = 1.0; m_TotalMissedVblanks = 0; m_UseVblank = false; m_CurrTime = 0; m_LastIntTime = 0; m_CurrTimeFract = 0.0; m_RefreshRate = 0.0; m_MissedVblanks = 0; m_VblankTime = 0; Start(); }
CVideoReferenceClock::CVideoReferenceClock() : CThread("RefClock") { m_SystemFrequency = CurrentHostFrequency(); m_ClockSpeed = 1.0; m_ClockOffset = 0; m_TotalMissedVblanks = 0; m_UseVblank = false; m_CurrTime = 0; m_LastIntTime = 0; m_CurrTimeFract = 0.0; m_fineadjust = 0.0; m_RefreshRate = 0.0; m_MissedVblanks = 0; m_VblankTime = 0; m_pVideoSync = nullptr; }
bool CRenderSystemGL::PresentRender(const CDirtyRegionList& dirty) { if (!m_bRenderCreated) return false; if (m_iVSyncMode != 0 && m_iSwapRate != 0) { int64_t curr, diff, freq; curr = CurrentHostCounter(); freq = CurrentHostFrequency(); if(m_iSwapStamp == 0) m_iSwapStamp = curr; /* calculate our next swap timestamp */ diff = curr - m_iSwapStamp; diff = m_iSwapRate - diff % m_iSwapRate; m_iSwapStamp = curr + diff; /* sleep as close as we can before, assume 1ms precision of sleep * * this should always awake so that we are guaranteed the given * * m_iSwapTime to do our swap */ diff = (diff - m_iSwapTime) * 1000 / freq; if (diff > 0) Sleep((DWORD)diff); } bool result = PresentRenderImpl(dirty); m_latencyCounter++; if (m_iVSyncMode && m_iSwapRate != 0) { int64_t curr, diff; curr = CurrentHostCounter(); diff = curr - m_iSwapStamp; m_iSwapStamp = curr; if (MathUtils::abs(diff - m_iSwapRate) < MathUtils::abs(diff)) CLog::Log(LOGDEBUG, "%s - missed requested swap",__FUNCTION__); } return result; }
CDVDClock::CDVDClock() { CSingleLock lock(m_systemsection); m_pauseClock = 0; m_bReset = true; m_iDisc = 0; m_maxspeedadjust = 0.0; m_systemAdjust = 0; m_speedAdjust = 0; m_startClock = 0; m_vSyncAdjust = 0; m_frameTime = DVD_TIME_BASE / 60.0; m_videoRefClock.reset(new CVideoReferenceClock()); m_lastSystemTime = m_videoRefClock->GetTime(); m_systemOffset = m_videoRefClock->GetTime(); m_systemFrequency = CurrentHostFrequency(); m_systemUsed = m_systemFrequency; }
void CVideoSyncDRM::EventHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data) { drmVBlank vbl; VblInfo *info = (VblInfo*)data; drmVBlankSeqType crtcSel = CrtcSel(); vbl.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT | crtcSel); vbl.request.sequence = 1; vbl.request.signal = (unsigned long)data; drmWaitVBlank(info->videoSync->m_fd, &vbl); uint64_t now = CurrentHostCounter(); float diff = (float)(now - info->start)/CurrentHostFrequency(); int vblanks = MathUtils::round_int(diff * info->videoSync->m_fps); info->start = now; info->videoSync->UpdateClock(vblanks, now); }
OMXPlayerAudio::OMXPlayerAudio(OMXClock *av_clock, CDVDMessageQueue& parent) : CThread("OMXPlayerAudio") , m_messageQueue("audio") , m_messageParent(parent) { m_av_clock = av_clock; m_pAudioCodec = NULL; m_speed = DVD_PLAYSPEED_NORMAL; m_started = false; m_stalled = false; m_audioClock = 0; m_buffer_empty = false; m_nChannels = 0; m_DecoderOpen = false; m_freq = CurrentHostFrequency(); m_send_eos = false; m_bad_state = false; m_hints_current.Clear(); m_av_clock->SetMasterClock(false); m_messageQueue.SetMaxDataSize(3 * 1024 * 1024); m_messageQueue.SetMaxTimeSize(8.0); m_use_passthrough = false; m_passthrough = false; m_use_hw_decode = false; m_hw_decode = false; m_silence = false; m_error = 0.0; m_errorbuff = 0.0; m_errorcount = 0; m_syncclock = false; m_integral = 0.0; m_skipdupcount = 0; m_prevskipped = false; m_flush = false; m_synctype = 0; }
OMXPlayerAudio::OMXPlayerAudio(OMXClock *av_clock, CDVDMessageQueue& parent) : CThread("COMXPlayerAudio") , m_messageQueue("audio") , m_messageParent(parent) { m_av_clock = av_clock; m_pAudioCodec = NULL; m_speed = DVD_PLAYSPEED_NORMAL; m_started = false; m_stalled = false; m_audioClock = 0; m_buffer_empty = false; m_nChannels = 0; m_DecoderOpen = false; m_freq = CurrentHostFrequency(); m_hints_current.Clear(); m_av_clock->SetMasterClock(false); m_messageQueue.SetMaxDataSize(3 * 1024 * 1024); m_messageQueue.SetMaxTimeSize(8.0); }
const CTextureArray& CGUITextureManager::Load(const std::string& strTextureName, bool checkBundleOnly /*= false */) { std::string strPath; static CTextureArray emptyTexture; int bundle = -1; int size = 0; if (!HasTexture(strTextureName, &strPath, &bundle, &size)) return emptyTexture; if (size) // we found the texture { for (int i = 0; i < (int)m_vecTextures.size(); ++i) { CTextureMap *pMap = m_vecTextures[i]; if (pMap->GetName() == strTextureName) { //CLog::Log(LOGDEBUG, "Total memusage %u", GetMemoryUsage()); return pMap->GetTexture(); } } // Whoops, not there. return emptyTexture; } for (ilistUnused i = m_unusedTextures.begin(); i != m_unusedTextures.end(); ++i) { CTextureMap* pMap = i->first; if (pMap->GetName() == strTextureName && i->second > 0) { m_vecTextures.push_back(pMap); m_unusedTextures.erase(i); return pMap->GetTexture(); } } if (checkBundleOnly && bundle == -1) return emptyTexture; //Lock here, we will do stuff that could break rendering CSingleLock lock(g_graphicsContext); #ifdef _DEBUG_TEXTURES int64_t start; start = CurrentHostCounter(); #endif if (StringUtils::EndsWithNoCase(strPath, ".gif")) { CTextureMap* pMap = nullptr; if (bundle >= 0) { CBaseTexture **pTextures; int nLoops = 0, width = 0, height = 0; int* Delay; int nImages = m_TexBundle[bundle].LoadAnim(strTextureName, &pTextures, width, height, nLoops, &Delay); if (!nImages) { CLog::Log(LOGERROR, "Texture manager unable to load bundled file: %s", strTextureName.c_str()); delete [] pTextures; delete [] Delay; return emptyTexture; } pMap = new CTextureMap(strTextureName, width, height, nLoops); for (int iImage = 0; iImage < nImages; ++iImage) { pMap->Add(pTextures[iImage], Delay[iImage]); } delete [] pTextures; delete [] Delay; } else { #if defined(HAS_GIFLIB) Gif gif; if(!gif.LoadGif(strPath.c_str())) { if (StringUtils::StartsWith(strPath, g_SkinInfo->Path())) CLog::Log(LOGERROR, "Texture manager unable to load file: %s", strPath.c_str()); return emptyTexture; } pMap = new CTextureMap(strTextureName, gif.Width(), gif.Height(), gif.GetNumLoops()); for (auto frame : gif.GetFrames()) { CTexture *glTexture = new CTexture(); if (glTexture) { glTexture->LoadFromMemory(gif.Width(), gif.Height(), gif.GetPitch(), XB_FMT_A8R8G8B8, false, frame->m_pImage); pMap->Add(glTexture, frame->m_delay); } } #endif//HAS_GIFLIB } if (pMap) { m_vecTextures.push_back(pMap); return pMap->GetTexture(); } } // of if (strPath.Right(4).ToLower()==".gif") CBaseTexture *pTexture = NULL; int width = 0, height = 0; if (bundle >= 0) { if (!m_TexBundle[bundle].LoadTexture(strTextureName, &pTexture, width, height)) { CLog::Log(LOGERROR, "Texture manager unable to load bundled file: %s", strTextureName.c_str()); return emptyTexture; } } else { pTexture = CBaseTexture::LoadFromFile(strPath); if (!pTexture) return emptyTexture; width = pTexture->GetWidth(); height = pTexture->GetHeight(); } if (!pTexture) return emptyTexture; CTextureMap* pMap = new CTextureMap(strTextureName, width, height, 0); pMap->Add(pTexture, 100); m_vecTextures.push_back(pMap); #ifdef _DEBUG_TEXTURES int64_t end, freq; end = CurrentHostCounter(); freq = CurrentHostFrequency(); char temp[200]; sprintf(temp, "Load %s: %.1fms%s\n", strPath.c_str(), 1000.f * (end - start) / freq, (bundle >= 0) ? " (bundled)" : ""); OutputDebugString(temp); #endif return pMap->GetTexture(); }
bool CDVDVideoCodecVDA::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) { if (g_guiSettings.GetBool("videoplayer.usevda") && !hints.software) { CCocoaAutoPool pool; int32_t width, height, profile, level; CFDataRef avcCData; uint8_t *extradata; // extra data for codec to use unsigned int extrasize; // size of extra data // width = hints.width; height = hints.height; level = hints.level; profile = hints.profile; extrasize = hints.extrasize; extradata = (uint8_t*)hints.extradata; if (Cocoa_GPUForDisplayIsNvidiaPureVideo3() && !CDVDCodecUtils::IsVP3CompatibleWidth(width)) { CLog::Log(LOGNOTICE, "%s - Nvidia 9400 GPU hardware limitation, cannot decode a width of %d", __FUNCTION__, width); return false; } switch (hints.codec) { case CODEC_ID_H264: // TODO: need to quality h264 encoding (profile, level and number of reference frame) // source must be H.264 with valid avcC atom data in extradata if (extrasize < 7 || extradata == NULL) { CLog::Log(LOGNOTICE, "%s - avcC atom too data small or missing", __FUNCTION__); return false; } // valid avcC atom data always starts with the value 1 (version) if ( *extradata != 1 ) { if (extradata[0] == 0 && extradata[1] == 0 && extradata[2] == 0 && extradata[3] == 1) { // video content is from x264 or from bytestream h264 (AnnexB format) // NAL reformating to bitstream format needed m_dllAvUtil = new DllAvUtil; m_dllAvFormat = new DllAvFormat; if (!m_dllAvUtil->Load() || !m_dllAvFormat->Load()) { return false; } ByteIOContext *pb; if (m_dllAvFormat->url_open_dyn_buf(&pb) < 0) { return false; } m_convert_bytestream = true; // create a valid avcC atom data from ffmpeg's extradata isom_write_avcc(m_dllAvUtil, m_dllAvFormat, pb, extradata, extrasize); // unhook from ffmpeg's extradata extradata = NULL; // extract the avcC atom data into extradata then write it into avcCData for VDADecoder extrasize = m_dllAvFormat->url_close_dyn_buf(pb, &extradata); // CFDataCreate makes a copy of extradata contents avcCData = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)extradata, extrasize); // done with the converted extradata, we MUST free using av_free m_dllAvUtil->av_free(extradata); } else { CLog::Log(LOGNOTICE, "%s - invalid avcC atom data", __FUNCTION__); return false; } } else { if (extradata[4] == 0xFE) { // video content is from so silly encoder that think 3 byte NAL sizes // are valid, setup to convert 3 byte NAL sizes to 4 byte. m_dllAvUtil = new DllAvUtil; m_dllAvFormat = new DllAvFormat; if (!m_dllAvUtil->Load() || !m_dllAvFormat->Load()) return false; extradata[4] = 0xFF; m_convert_3byteTo4byteNALSize = true; } // CFDataCreate makes a copy of extradata contents avcCData = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)extradata, extrasize); } m_format = 'avc1'; m_pFormatName = "vda-h264"; break; default: return false; break; } // input stream is qualified, now we can load dlls. m_dllSwScale = new DllSwScale; if (!m_dllSwScale->Load()) { CFRelease(avcCData); return false; } // setup the decoder configuration dict CFMutableDictionaryRef decoderConfiguration = CFDictionaryCreateMutable( kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFNumberRef avcWidth = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width); CFNumberRef avcHeight = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height); CFNumberRef avcFormat = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &m_format); CFDictionarySetValue(decoderConfiguration, m_dll->Get_kVDADecoderConfiguration_Height(), avcHeight); CFDictionarySetValue(decoderConfiguration, m_dll->Get_kVDADecoderConfiguration_Width(), avcWidth); CFDictionarySetValue(decoderConfiguration, m_dll->Get_kVDADecoderConfiguration_SourceFormat(), avcFormat); CFDictionarySetValue(decoderConfiguration, m_dll->Get_kVDADecoderConfiguration_avcCData(), avcCData); // release the retained object refs, decoderConfiguration owns them now CFRelease(avcWidth); CFRelease(avcHeight); CFRelease(avcFormat); CFRelease(avcCData); // setup the destination image buffer dict, vda will output this pict format CFMutableDictionaryRef destinationImageBufferAttributes = CFDictionaryCreateMutable( kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); OSType cvPixelFormatType = kCVPixelFormatType_422YpCbCr8; CFNumberRef pixelFormat = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &cvPixelFormatType); CFDictionarySetValue(destinationImageBufferAttributes, kCVPixelBufferPixelFormatTypeKey, pixelFormat); // create the VDADecoder object OSStatus status; try { status = m_dll->VDADecoderCreate(decoderConfiguration, destinationImageBufferAttributes, (VDADecoderOutputCallback *)VDADecoderCallback, this, (VDADecoder*)&m_vda_decoder); } catch (...) { CLog::Log(LOGERROR, "%s - exception",__FUNCTION__); status = kVDADecoderDecoderFailedErr; } CFRelease(decoderConfiguration); CFRelease(destinationImageBufferAttributes); if (status != kVDADecoderNoErr) { if (status == kVDADecoderDecoderFailedErr) CLog::Log(LOGNOTICE, "%s - VDADecoder Codec failed to open, currently in use by another process", __FUNCTION__); else CLog::Log(LOGNOTICE, "%s - VDADecoder Codec failed to open, status(%d), profile(%d), level(%d)", __FUNCTION__, (int)status, profile, level); return false; } // allocate a YV12 DVDVideoPicture buffer. // first make sure all properties are reset. memset(&m_videobuffer, 0, sizeof(DVDVideoPicture)); unsigned int iPixels = width * height; unsigned int iChromaPixels = iPixels/4; m_videobuffer.pts = DVD_NOPTS_VALUE; m_videobuffer.iFlags = DVP_FLAG_ALLOCATED; m_videobuffer.format = DVDVideoPicture::FMT_YUV420P; m_videobuffer.color_range = 0; m_videobuffer.color_matrix = 4; m_videobuffer.iWidth = width; m_videobuffer.iHeight = height; m_videobuffer.iDisplayWidth = width; m_videobuffer.iDisplayHeight = height; m_videobuffer.iLineSize[0] = width; //Y m_videobuffer.iLineSize[1] = width/2; //U m_videobuffer.iLineSize[2] = width/2; //V m_videobuffer.iLineSize[3] = 0; m_videobuffer.data[0] = (BYTE*)malloc(iPixels); //Y m_videobuffer.data[1] = (BYTE*)malloc(iChromaPixels); //U m_videobuffer.data[2] = (BYTE*)malloc(iChromaPixels); //V m_videobuffer.data[3] = NULL; // set all data to 0 for less artifacts.. hmm.. what is black in YUV?? memset(m_videobuffer.data[0], 0, iPixels); memset(m_videobuffer.data[1], 0, iChromaPixels); memset(m_videobuffer.data[2], 0, iChromaPixels); m_DropPictures = false; m_sort_time_offset = (CurrentHostCounter() * 1000.0) / CurrentHostFrequency(); return true; } return false; }
void CAESinkPULSE::GetDelay(AEDelayStatus& status) { if (!m_IsAllocated) { status.SetDelay(0); return; } pa_threaded_mainloop_lock(m_MainLoop); const pa_timing_info* pti = pa_stream_get_timing_info(m_Stream); // only incorporate local sink delay + internal PA transport delay double sink_delay = (pti->configured_sink_usec / 1000000.0); double transport_delay = pti->transport_usec / 1000000.0; uint64_t diff = CurrentHostCounter() - m_lastPackageStamp; unsigned int bytes_played = (unsigned int) ((double) diff * (double) m_BytesPerSecond / (double) CurrentHostFrequency() + 0.5); int buffer_delay = m_filled_bytes - bytes_played; if (buffer_delay < 0) buffer_delay = 0; pa_threaded_mainloop_unlock(m_MainLoop); double delay = buffer_delay / (double) m_BytesPerSecond + sink_delay + transport_delay; status.SetDelay(delay); }
int main(int argc, char * const argv[]) { int ret = CODEC_ERROR_NONE; std::string input_filename; if (argc > 1) { for (int i = 1; i < argc; i++) { if (strncasecmp(argv[i], "--input", 7) == 0) { // check the next arg with the proper value. int next = i + 1; if (next < argc) { input_filename = argv[next]; i++; } } else if (strncasecmp(argv[i], "-h", 2) == 0 || strncasecmp(argv[i], "--help", 6) == 0) { printf("Usage: %s [OPTIONS]...\n", argv[0]); printf("Arguments:\n"); printf(" --input <filename> \tInput video filename\n"); exit(0); } } } if (input_filename.empty()) { printf("no input file specified\n"); exit(0); } // install signal handlers signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); // initialize App contex. AVPacket avpkt; AppContext ctx; memset(&ctx, 0, sizeof(ctx)); player_para_init(&ctx); am_packet_init(&ctx.am_pkt); ctx.am_pkt.avpkt = &avpkt; av_init_packet(ctx.am_pkt.avpkt); // create the ffmepg file reader/demuxer ctx.demuxer = new FFmpegFileReader(input_filename.c_str()); if (!ctx.demuxer->Initialize()) { fprintf(stderr, "ERROR: Can't initialize FFmpegFileReader\n"); goto fail; } ctx.codec_context = ctx.demuxer->GetCodecContext(); ctx.format_context = ctx.demuxer->GetFormatContext(); if (!ctx.codec_context) { fprintf(stderr, "ERROR: Invalid FFmpegFileReader Codec Context\n"); goto fail; } dump_extradata(&ctx); printf("video width(%d), height(%d), extradata_size(%d)\n", (int)ctx.codec_context->width, (int)ctx.codec_context->height, ctx.codec_context->extradata_size); AVStream *pStream; pStream = ctx.format_context->streams[ctx.demuxer->GetVideoIndex()]; //ctx.vstream_info.video_pid = (unsigned short)ctx.codec_context->id; if (pStream->time_base.den) { ctx.vstream_info.start_time = pStream->start_time * pStream->time_base.num * PTS_FREQ / pStream->time_base.den; ctx.vstream_info.video_duration = ((float)pStream->time_base.num / pStream->time_base.den) * UNIT_FREQ; ctx.vstream_info.video_pts = ((float)pStream->time_base.num / pStream->time_base.den) * PTS_FREQ; } ctx.vstream_info.video_width = ctx.codec_context->width; ctx.vstream_info.video_height = ctx.codec_context->height; ctx.vstream_info.video_ratio = (float)pStream->sample_aspect_ratio.num / pStream->sample_aspect_ratio.den; if (ctx.codec_context->time_base.den) { ctx.vstream_info.video_codec_rate = (int64_t)UNIT_FREQ * ctx.codec_context->time_base.num / ctx.codec_context->time_base.den; } if (pStream->r_frame_rate.num) { ctx.vstream_info.video_rate = (int64_t)UNIT_FREQ * pStream->r_frame_rate.den / pStream->r_frame_rate.num; } log_print("time_base.num(%d), pStream->time_base.den(%d)\n", pStream->time_base.num, pStream->time_base.den); ctx.vstream_info.video_duration = ((float)pStream->time_base.num / pStream->time_base.den) * UNIT_FREQ; ctx.vstream_info.video_pts = ((float)pStream->time_base.num / pStream->time_base.den) * PTS_FREQ; printf("\n*********AMLOGIC CODEC PLAYER DEMO************\n\n"); osd_blank("/sys/class/graphics/fb0/blank", 1); osd_blank("/sys/class/graphics/fb1/blank", 1); //osd_blank("/sys/class/tsync/enable", 1); osd_blank("/sys/class/tsync/enable", 0); switch(ctx.codec_context->codec_id) { case CODEC_ID_H264: printf("CODEC_ID_H264\n"); ctx.vcodec.has_video = 1; ctx.vcodec.has_audio = 0; ctx.stream_type = STREAM_ES; //ctx.vcodec.video_pid = ctx.demuxer->GetVideoIndex(); ctx.vcodec.video_type = VFORMAT_H264; ctx.vcodec.stream_type = STREAM_TYPE_ES_VIDEO; //ctx.vcodec.noblock = !!p_para->buffering_enable; ctx.vcodec.am_sysinfo.format = VIDEO_DEC_FORMAT_H264; ctx.vcodec.am_sysinfo.width = ctx.vstream_info.video_width; ctx.vcodec.am_sysinfo.height = ctx.vstream_info.video_height; ctx.vcodec.am_sysinfo.rate = ctx.vstream_info.video_rate; ctx.vcodec.am_sysinfo.ratio = ctx.vstream_info.video_ratio; ctx.vcodec.am_sysinfo.param = (void*)(EXTERNAL_PTS | SYNC_OUTSIDE); break; case CODEC_ID_MPEG4: printf("CODEC_ID_MPEG4\n"); ctx.vcodec.video_type = VFORMAT_MPEG4; break; case CODEC_ID_MPEG2VIDEO: printf("CODEC_ID_MPEG2VIDEO\n"); ctx.vcodec.video_type = VFORMAT_MPEG12; break; default: fprintf(stderr, "ERROR: Invalid FFmpegFileReader Codec Format (not h264/mpeg4) = %d\n", ctx.codec_context->codec_id); goto fail; break; } ret = codec_init(&ctx.vcodec); if(ret != CODEC_ERROR_NONE) { printf("codec init failed, ret=-0x%x", -ret); return -1; } printf("video codec ok!\n"); ret = codec_init_cntl(&ctx.vcodec); if( ret != CODEC_ERROR_NONE ) { printf("codec_init_cntl error\n"); return -1; } codec_set_cntl_avthresh(&ctx.vcodec, AV_SYNC_THRESH); codec_set_cntl_syncthresh(&ctx.vcodec, ctx.vcodec.has_audio); { int frame_count, total = 0; int64_t bgn_us, end_us; ctx.am_pkt.codec = &ctx.vcodec; pre_header_feeding(&ctx, &ctx.am_pkt); ctx.demuxer->Read(ctx.am_pkt.avpkt); printf("byte_count(%d), dts(%llu), pts(%llu)\n", ctx.am_pkt.avpkt->size, ctx.am_pkt.avpkt->dts, ctx.am_pkt.avpkt->pts); if (!ctx.am_pkt.avpkt->size) { fprintf(stderr, "ERROR: Zero bytes read from input\n"); //goto fail; } ctx.am_pkt.type = CODEC_VIDEO; ctx.am_pkt.data = ctx.am_pkt.avpkt->data; ctx.am_pkt.data_size = ctx.am_pkt.avpkt->size; ctx.am_pkt.avpkt_newflag = 1; ctx.am_pkt.avpkt_isvalid = 1; frame_count = 0; bool done = false; struct buf_status vbuf; struct vdec_status vdec; float vlevel; while (!g_signal_abort && !done && (frame_count < 5000)) { h264_update_frame_header(&ctx.am_pkt); bgn_us = CurrentHostCounter() * 1000 / CurrentHostFrequency(); log_print("avpts(%lld), avdts(%lld)\n", ctx.am_pkt.avpkt->pts, ctx.am_pkt.avpkt->dts); ret = write_av_packet(&ctx, &ctx.am_pkt); end_us = CurrentHostCounter() * 1000 / CurrentHostFrequency(); frame_count++; //fprintf(stdout, "decode time(%llu) us\n", end_us-bgn_us); check_vcodec_state(&ctx.vcodec, &vdec, &vbuf); vlevel = 100.0 * (float)vbuf.data_len / vbuf.size; //log_print("buffering_states,vlevel=%d,vsize=%d,level=%f\n", vbuf.data_len, vbuf.size, vlevel); usleep(vlevel * 5000); ctx.demuxer->Read(ctx.am_pkt.avpkt); ctx.am_pkt.type = CODEC_VIDEO; ctx.am_pkt.data = ctx.am_pkt.avpkt->data; ctx.am_pkt.data_size = ctx.am_pkt.avpkt->size; ctx.am_pkt.avpkt_newflag = 1; ctx.am_pkt.avpkt_isvalid = 1; if (!ctx.am_pkt.data_size) done = true; total += ctx.am_pkt.data_size; } } fail: codec_close_cntl(&ctx.vcodec); codec_close(&ctx.vcodec); return 0; }
const CTextureArray& CGUITextureManager::Load(const std::string& strTextureName, bool checkBundleOnly /*= false */) { std::string strPath; static CTextureArray emptyTexture; int bundle = -1; int size = 0; if (!HasTexture(strTextureName, &strPath, &bundle, &size)) return emptyTexture; if (size) // we found the texture { for (int i = 0; i < (int)m_vecTextures.size(); ++i) { CTextureMap *pMap = m_vecTextures[i]; if (pMap->GetName() == strTextureName) { //CLog::Log(LOGDEBUG, "Total memusage %u", GetMemoryUsage()); return pMap->GetTexture(); } } // Whoops, not there. return emptyTexture; } for (ilistUnused i = m_unusedTextures.begin(); i != m_unusedTextures.end(); ++i) { CTextureMap* pMap = i->first; if (pMap->GetName() == strTextureName && i->second > 0) { m_vecTextures.push_back(pMap); m_unusedTextures.erase(i); return pMap->GetTexture(); } } if (checkBundleOnly && bundle == -1) return emptyTexture; //Lock here, we will do stuff that could break rendering CSingleLock lock(g_graphicsContext); #ifdef _DEBUG_TEXTURES int64_t start; start = CurrentHostCounter(); #endif if (bundle >= 0 && StringUtils::EndsWithNoCase(strPath, ".gif")) { CTextureMap* pMap = nullptr; CBaseTexture **pTextures = nullptr; int nLoops = 0, width = 0, height = 0; int* Delay = nullptr; int nImages = m_TexBundle[bundle].LoadAnim(strTextureName, &pTextures, width, height, nLoops, &Delay); if (!nImages) { CLog::Log(LOGERROR, "Texture manager unable to load bundled file: %s", strTextureName.c_str()); delete[] pTextures; delete[] Delay; return emptyTexture; } unsigned int maxWidth = 0; unsigned int maxHeight = 0; pMap = new CTextureMap(strTextureName, width, height, nLoops); for (int iImage = 0; iImage < nImages; ++iImage) { pMap->Add(pTextures[iImage], Delay[iImage]); maxWidth = std::max(maxWidth, pTextures[iImage]->GetWidth()); maxHeight = std::max(maxHeight, pTextures[iImage]->GetHeight()); } pMap->SetWidth((int)maxWidth); pMap->SetHeight((int)maxHeight); delete[] pTextures; delete[] Delay; if (pMap) { m_vecTextures.push_back(pMap); return pMap->GetTexture(); } } else if (StringUtils::EndsWithNoCase(strPath, ".gif") || StringUtils::EndsWithNoCase(strPath, ".apng")) { CTextureMap* pMap = nullptr; std::string mimeType; if (StringUtils::EndsWithNoCase(strPath, ".gif")) mimeType = "image/gif"; else if (StringUtils::EndsWithNoCase(strPath, ".apng")) mimeType = "image/apng"; XFILE::CFile file; XFILE::auto_buffer buf; CFFmpegImage anim(mimeType); pMap = new CTextureMap(strTextureName, 0, 0, 0); if (file.LoadFile(strPath, buf) <= 0 || !anim.Initialize((uint8_t*)buf.get(), buf.size()) || !pMap) { CLog::Log(LOGERROR, "Texture manager unable to load file: %s", CURL::GetRedacted(strPath).c_str()); file.Close(); return emptyTexture; } unsigned int maxWidth = 0; unsigned int maxHeight = 0; uint64_t maxMemoryUsage = 91238400;// 1920*1080*4*11 bytes, i.e, a total of approx. 12 full hd frames auto frame = anim.ReadFrame(); while (frame) { CTexture *glTexture = new CTexture(); if (glTexture) { glTexture->LoadFromMemory(anim.Width(), anim.Height(), frame->GetPitch(), XB_FMT_A8R8G8B8, true, frame->m_pImage); pMap->Add(glTexture, frame->m_delay); maxWidth = std::max(maxWidth, glTexture->GetWidth()); maxHeight = std::max(maxHeight, glTexture->GetHeight()); } if (pMap->GetMemoryUsage() <= maxMemoryUsage) { frame = anim.ReadFrame(); } else { CLog::Log(LOGDEBUG, "Memory limit (%" PRIu64 " bytes) exceeded, %i frames extracted from file : %s", (maxMemoryUsage/11)*12,pMap->GetTexture().size(), CURL::GetRedacted(strPath).c_str()); break; } } pMap->SetWidth((int)maxWidth); pMap->SetHeight((int)maxHeight); file.Close(); if (pMap) { m_vecTextures.push_back(pMap); return pMap->GetTexture(); } } CBaseTexture *pTexture = NULL; int width = 0, height = 0; if (bundle >= 0) { if (!m_TexBundle[bundle].LoadTexture(strTextureName, &pTexture, width, height)) { CLog::Log(LOGERROR, "Texture manager unable to load bundled file: %s", strTextureName.c_str()); return emptyTexture; } } else { pTexture = CBaseTexture::LoadFromFile(strPath); if (!pTexture) return emptyTexture; width = pTexture->GetWidth(); height = pTexture->GetHeight(); } if (!pTexture) return emptyTexture; CTextureMap* pMap = new CTextureMap(strTextureName, width, height, 0); pMap->Add(pTexture, 100); m_vecTextures.push_back(pMap); #ifdef _DEBUG_TEXTURES int64_t end, freq; end = CurrentHostCounter(); freq = CurrentHostFrequency(); char temp[200]; sprintf(temp, "Load %s: %.1fms%s\n", strPath.c_str(), 1000.f * (end - start) / freq, (bundle >= 0) ? " (bundled)" : ""); OutputDebugString(temp); #endif return pMap->GetTexture(); }
TEST(TestTimeUtils, CurrentHostFrequency) { std::cout << "CurrentHostFrequency(): " << testing::PrintToString(CurrentHostFrequency()) << std::endl; }
CGUIControlProfiler::CGUIControlProfiler(void) : m_ItemHead(NULL, NULL, NULL), m_pLastItem(NULL), m_iMaxFrameCount(200), m_iFrameCount(0) // m_bIsRunning(false), no isRunning because it is static { m_fPerfScale = 100000.0f / CurrentHostFrequency(); }