示例#1
0
// 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;
}
示例#5
0
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;
}