// Should work with either the CPU or GPU version of a frame void VideoOutputNullVDPAU::DoneDisplayingFrame(VideoFrame *frame) { if (!frame || !BufferSizeCheck()) return; // is this a CPU frame for (uint i = 0; i < m_shadowBuffers->Size(); i++) { if (m_shadowBuffers->At(i) == frame) { frame = vbuffers.At(i); break; } } // is this a GPU frame for (uint i = 0; i < vbuffers.Size(); i++) { if (vbuffers.At(i) == frame) { m_lock.lock(); if (vbuffers.Contains(kVideoBuffer_used, frame)) DiscardFrame(frame); CheckFrameStates(); m_lock.unlock(); return; } } }
void MovieTexture_FFMpeg::DecoderThread() { #if defined(_WINDOWS) /* Windows likes to boost priority when processes come out of a wait state. We don't * want that, since it'll result in us having a small priority boost after each movie * frame, resulting in skips in the gameplay thread. */ if( !SetThreadPriorityBoost(GetCurrentThread(), TRUE) && GetLastError() != ERROR_CALL_NOT_IMPLEMENTED ) LOG->Warn( werr_ssprintf(GetLastError(), "SetThreadPriorityBoost failed") ); #endif CHECKPOINT; while( m_State != DECODER_QUIT ) { if( m_ImageWaiting == FRAME_NONE ) DecodeFrame(); /* If we still have no frame, we're at EOF and we didn't loop. */ if( m_ImageWaiting != FRAME_DECODED ) { usleep( 10000 ); continue; } const float fTime = CheckFrameTime(); if( fTime == -1 ) // skip frame { DiscardFrame(); } else if( fTime > 0 ) // not time to decode a new frame yet { /* This needs to be relatively short so that we wake up quickly * from being paused or for changes in m_Rate. */ usleep( 10000 ); } else // fTime == 0 { { /* The only reason m_BufferFinished might be non-zero right now (before * ConvertFrame()) is if we're quitting. */ int n = m_BufferFinished.GetValue(); ASSERT_M( n == 0 || m_State == DECODER_QUIT, ssprintf("%i, %i", n, m_State) ); } ConvertFrame(); /* We just went into FRAME_WAITING. Don't actually check; the main thread * will change us back to FRAME_NONE without locking, and poke m_BufferFinished. * Don't time out on this; if a new screen has started loading, this might not * return for a while. */ m_BufferFinished.Wait( false ); /* If the frame wasn't used, then we must be shutting down. */ ASSERT_M( m_ImageWaiting == FRAME_NONE || m_State == DECODER_QUIT, ssprintf("%i, %i", m_ImageWaiting, m_State) ); } } CHECKPOINT; }
void MovieTexture_FFMpeg::Update(float fDeltaTime) { /* We might need to decode more than one frame per update. However, there * have been bugs in ffmpeg that cause it to not handle EOF properly, which * could make this never return, so let's play it safe. */ int iMax = 4; while( --iMax ) { if( !m_bThreaded ) { /* If we don't have a frame decoded, decode one. */ if( m_ImageWaiting == FRAME_NONE ) DecodeFrame(); /* If we have a frame decoded, see if it's time to display it. */ if( m_ImageWaiting == FRAME_DECODED ) { float fTime = CheckFrameTime(); if( fTime > 0 ) return; else if( fTime == -1 ) DiscardFrame(); else ConvertFrame(); } } /* Note that if there's an image waiting, we *must* signal m_BufferFinished, or * the decoder thread may sit around waiting for it, even though Pause and Play * calls, causing the clock to keep running. */ if( m_ImageWaiting != FRAME_WAITING ) return; CHECKPOINT; UpdateFrame(); if( m_bThreaded ) m_BufferFinished.Post(); } LOG->MapLog( "ffmpeg_looping", "MovieTexture_FFMpeg::Update looping" ); }
bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) { if (ucontext == nullptr) { int ret = unw_getcontext(&context_); if (ret < 0) { BACK_LOGW("unw_getcontext failed %d", ret); return false; } } else { GetUnwContextFromUcontext(ucontext); } // The cursor structure is pretty large, do not put it on the stack. std::unique_ptr<unw_cursor_t> cursor(new unw_cursor_t); int ret = unw_init_local(cursor.get(), &context_); if (ret < 0) { BACK_LOGW("unw_init_local failed %d", ret); return false; } size_t num_frames = 0; do { unw_word_t pc; ret = unw_get_reg(cursor.get(), UNW_REG_IP, &pc); if (ret < 0) { BACK_LOGW("Failed to read IP %d", ret); break; } unw_word_t sp; ret = unw_get_reg(cursor.get(), UNW_REG_SP, &sp); if (ret < 0) { BACK_LOGW("Failed to read SP %d", ret); break; } frames_.resize(num_frames+1); backtrace_frame_data_t* frame = &frames_.at(num_frames); frame->num = num_frames; frame->pc = static_cast<uintptr_t>(pc); frame->sp = static_cast<uintptr_t>(sp); frame->stack_size = 0; FillInMap(frame->pc, &frame->map); // Check to see if we should skip this frame because it's coming // from within the library, and we are doing a local unwind. if (ucontext != nullptr || num_frames != 0 || !DiscardFrame(*frame)) { if (num_ignore_frames == 0) { // GetFunctionName is an expensive call, only do it if we are // keeping the frame. frame->func_name = GetFunctionName(frame->pc, &frame->func_offset); if (num_frames > 0) { // Set the stack size for the previous frame. backtrace_frame_data_t* prev = &frames_.at(num_frames-1); prev->stack_size = frame->sp - prev->sp; } num_frames++; } else { num_ignore_frames--; } } ret = unw_step (cursor.get()); } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES); return true; }
bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) { if (ucontext == nullptr) { int ret = unw_getcontext(&context_); if (ret < 0) { BACK_LOGW("unw_getcontext failed %d", ret); error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED; return false; } } else { GetUnwContextFromUcontext(ucontext); } // The cursor structure is pretty large, do not put it on the stack. std::unique_ptr<unw_cursor_t> cursor(new unw_cursor_t); int ret = unw_init_local(cursor.get(), &context_); if (ret < 0) { BACK_LOGW("unw_init_local failed %d", ret); error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED; return false; } initialized_ = true; size_t num_frames = 0; do { unw_word_t pc; ret = unw_get_reg(cursor.get(), UNW_REG_IP, &pc); if (ret < 0) { BACK_LOGW("Failed to read IP %d", ret); break; } unw_word_t sp; ret = unw_get_reg(cursor.get(), UNW_REG_SP, &sp); if (ret < 0) { BACK_LOGW("Failed to read SP %d", ret); break; } frames_.resize(num_frames+1); backtrace_frame_data_t* frame = &frames_.at(num_frames); frame->num = num_frames; frame->pc = static_cast<uintptr_t>(pc); frame->sp = static_cast<uintptr_t>(sp); frame->stack_size = 0; FillInMap(frame->pc, &frame->map); // Check to see if we should skip this frame because it's coming // from within the library, and we are doing a local unwind. if (ucontext != nullptr || num_frames != 0 || !DiscardFrame(*frame)) { if (num_ignore_frames == 0) { // GetFunctionName is an expensive call, only do it if we are // keeping the frame. frame->func_name = GetFunctionName(frame->pc, &frame->func_offset, &frame->map); if (num_frames > 0) { // Set the stack size for the previous frame. backtrace_frame_data_t* prev = &frames_.at(num_frames-1); prev->stack_size = frame->sp - prev->sp; } if (BacktraceMap::IsValid(frame->map)) { frame->rel_pc = frame->pc - frame->map.start + frame->map.load_bias; } else { frame->rel_pc = frame->pc; } num_frames++; } else { num_ignore_frames--; // Set the number of frames to zero to remove the frame added // above. By definition, if we still have frames to ignore // there should only be one frame in the vector. CHECK(num_frames == 0); frames_.resize(0); } } // If the pc is in a device map, then don't try to step. if (frame->map.flags & PROT_DEVICE_MAP) { break; } // Verify the sp is not in a device map too. backtrace_map_t map; FillInMap(frame->sp, &map); if (map.flags & PROT_DEVICE_MAP) { break; } ret = unw_step (cursor.get()); } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES); return true; }