bool V4L2Camera::enqueueRequestBuffers() {
  // Get a request from the queue (blocks this thread until one is available).
  std::shared_ptr<default_camera_hal::CaptureRequest> request =
      dequeueRequest();

  // Assume request validated before being added to the queue
  // (For now, always exactly 1 output buffer, no inputs).

  // Setting and getting settings are best effort here,
  // since there's no way to know through V4L2 exactly what
  // settings are used for a buffer unless we were to enqueue them
  // one at a time, which would be too slow.

  // Set the requested settings
  int res = metadata_->SetRequestSettings(request->settings);
  if (res) {
    HAL_LOGE("Failed to set settings.");
    completeRequest(request, res);
    return true;
  }

  // Replace the requested settings with a snapshot of
  // the used settings/state immediately before enqueue.
  res = metadata_->FillResultMetadata(&request->settings);
  if (res) {
    // Note: since request is a shared pointer, this may happen if another
    // thread has already decided to complete the request (e.g. via flushing),
    // since that locks the metadata (in that case, this failing is fine,
    // and completeRequest will simply do nothing).
    HAL_LOGE("Failed to fill result metadata.");
    completeRequest(request, res);
    return true;
  }

  // Actually enqueue the buffer for capture.
  res = device_->EnqueueRequest(request);
  if (res) {
    HAL_LOGE("Device failed to enqueue buffer.");
    completeRequest(request, res);
    return true;
  }

  // Make sure the stream is on (no effect if already on).
  res = device_->StreamOn();
  if (res) {
    HAL_LOGE("Device failed to turn on stream.");
    // Don't really want to send an error for only the request here,
    // since this is a full device error.
    // TODO: Should trigger full flush.
    return true;
  }

  std::unique_lock<std::mutex> lock(in_flight_lock_);
  in_flight_buffer_count_++;
  buffers_in_flight_.notify_one();
  return true;
}
Exemplo n.º 2
0
//--------------------------------------------------------------
// load chunks from request list
void ChunkWorld::chunkLoader()
{
  while (!m_shutdown)
  {
    m_chunkEvent->wait(1000.0);  // check shutdown every second

    // while there's work
    while (!m_shutdown)
    {
      ChunkObj* found = dequeueRequest();

      // process the request
      if (found != NULL)
        processRequest(found);
      else break;  // back to wait
    }
  }
}
Exemplo n.º 3
0
// This function must be called from the event loop. The only
// exception is documented in QHttpNetworkConnectionPrivate::queueRequest
// although it is called _q_startNextRequest, it will actually start multiple requests when possible
void QHttpNetworkConnectionPrivate::_q_startNextRequest()
{
    // If the QHttpNetworkConnection is currently paused then bail out immediately
    if (state == PausedState)
        return;

    //resend the necessary ones.
    for (int i = 0; i < channelCount; ++i) {
        if (channels[i].resendCurrent && (channels[i].state != QHttpNetworkConnectionChannel::ClosingState)) {
            channels[i].resendCurrent = false;
            channels[i].state = QHttpNetworkConnectionChannel::IdleState;

            // if this is not possible, error will be emitted and connection terminated
            if (!channels[i].resetUploadData())
                continue;
            channels[i].sendRequest();
        }
    }

    // dequeue new ones

    // return fast if there is nothing to do
    if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty())
        return;
    // try to get a free AND connected socket
    for (int i = 0; i < channelCount; ++i) {
        if (!channels[i].reply && !channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) {
            if (dequeueRequest(channels[i].socket))
                channels[i].sendRequest();
        }
    }

    // try to push more into all sockets
    // ### FIXME we should move this to the beginning of the function
    // as soon as QtWebkit is properly using the pipelining
    // (e.g. not for XMLHttpRequest or the first page load)
    // ### FIXME we should also divide the requests more even
    // on the connected sockets
    //tryToFillPipeline(socket);
    // return fast if there is nothing to pipeline
    if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty())
        return;
    for (int i = 0; i < channelCount; i++)
        if (channels[i].socket->state() == QAbstractSocket::ConnectedState)
            fillPipeline(channels[i].socket);

    // If there is not already any connected channels we need to connect a new one.
    // We do not pair the channel with the request until we know if it is 
    // connected or not. This is to reuse connected channels before we connect new once.
    int queuedRequest = highPriorityQueue.count() + lowPriorityQueue.count();
    for (int i = 0; i < channelCount; ++i) {
        if (channels[i].socket->state() == QAbstractSocket::ConnectingState)
            queuedRequest--;
        if ( queuedRequest <=0 )
            break;
        if (!channels[i].reply && !channels[i].isSocketBusy() && (channels[i].socket->state() == QAbstractSocket::UnconnectedState)) {
            channels[i].ensureConnection();
            queuedRequest--;
        }
    }
}
Exemplo n.º 4
0
//--------------------------------------------------------------
// update animation 
BOOL ChunkWorld::animate(
  double now,                       // current time (ms)
  double since)                     // milliseconds since last pass
{
  BOOL viewChanged = false;

  m_chunkLock->lock();

  // keep memory use under limits
  checkMemory();

  resetRequestList();

  // figure which chunk we are in
  int viewX = (int) floor(m_eyePt.x / CHUNK_SIZE);
  int viewZ = (int) floor(m_eyePt.z / CHUNK_SIZE);

  // for all coordinates in view list
  for (int i = m_viewListCount-1; i >= 0; i--)
  {
    ChunkOrigin* origin = &m_viewList[i];
    int chunkX = CHUNK_SIZE*(viewX + origin->x);
    int chunkZ = CHUNK_SIZE*(viewZ + origin->z);

    // find/create chunk
    ChunkObj* chunk = createChunk(chunkX, chunkZ);

    // if chunk within view
    if (chunk->withinFrustum())
    {
      switch (chunk->m_status)
      {
        case CHUNK_UNLOADED:
          // request the chunk (loads in memory)
          requestChunk(chunk);

          // request the neighbors
          loadNeighbors(chunk);
          break;

        case CHUNK_INMEMORY:
          // if all neighbors loaded, update chunk edges
          if (loadNeighbors(chunk))
          {
            updateEdges(chunk);

            // request the chunk (loads in display)
            requestChunk(chunk);
          }
          break;

        case CHUNK_INDISPLAY:
          // if we have an update, use it
          if (!chunk->m_active && chunk->m_hasUpdate)
          {
//            mgDebug("use update on (%d, %d)", chunk->m_originX, chunk->m_originZ);
            int oldSize = chunk->getDisplayMemUsed();
            chunk->useUpdate();
            int size = chunk->getDisplayMemUsed();
            m_displayMemUsed += size-oldSize;
            chunk->m_hasUpdate = false;
          }

          // if it needs an update, flag it
          if (!chunk->m_active && chunk->needsUpdate(m_eyePt))
          {
//            mgDebug("wants update on (%d, %d)", chunk->m_originX, chunk->m_originZ);
            chunk->m_status = CHUNK_NEEDSUPDATE;
            chunk->m_eyePt = m_eyePt;
            m_requestList.addToTail(chunk);
          }

          // if still in display, animate it, since we will draw it
          if (chunk->m_status == CHUNK_INDISPLAY ||
              chunk->m_status == CHUNK_NEEDSUPDATE)
            chunk->animate(now, since);
          break;

        case CHUNK_NEEDSUPDATE:
          // if needed update last pass, and not being processed, still needs update
          if (!chunk->m_active)
          {
//            mgDebug("still needs update on (%d, %d)", chunk->m_originX, chunk->m_originZ);
            m_requestList.addToTail(chunk);
            chunk->animate(now, since);
          }
          break;
      }

      // push to bottom of LRU list
      ChunkListNode* node = m_LRUList.find(chunk);
      if (node != NULL)
        m_LRUList.removeNode(node);
      m_LRUList.addToTail(chunk);
    }
  }

  if (m_chunksChanged)
  {
    viewChanged = true;
    m_chunksChanged = false;
  }

  m_chunkLock->unlock();

  // if we requested chunks, activate worker threads
  if (!m_requestList.isEmpty())
  {
    if (m_chunkThreads != NULL)
    {
      // signal the threads to look at requestList
      m_chunkEvent->signal();
    }
    else
    {
      // process one request in this thread (no worker threads)
      ChunkObj* found = dequeueRequest();
      if (found != NULL)
        processRequest(found);
    }
  }

  return viewChanged;
}