示例#1
0
// ##############################################################################################################
void jevois::Gadget::streamOff()
{
  JEVOIS_TRACE(2);
  
  // Note: we allow for several streamOff() without complaining, this happens, e.g., when destroying a Gadget that is
  // not currently streaming.

  LDEBUG("Turning off gadget stream");

  // Abort stream in case it was not already done, which will introduce some sleeping in our run() thread, thereby
  // helping us acquire our needed double lock:
  abortStream();

  JEVOIS_TIMED_LOCK(itsMtx);

  // Stop streaming over the USB link:
  int type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
  try { XIOCTL_QUIET(itsFd, VIDIOC_STREAMOFF, &type); } catch (...) { }
  
  // Nuke all our buffers:
  if (itsBuffers) { delete itsBuffers; itsBuffers = nullptr; }
  itsImageQueue.clear();
  itsDoneImgs.clear();

  LDEBUG("Gadget stream is off");
}
示例#2
0
// ##############################################################################################################
void jevois::Camera::streamOff()
{
  JEVOIS_TRACE(2);

  // Note: we allow for several streamOff() without complaining, this happens, e.g., when destroying a Camera that is
  // not currently streaming.
  
  LDEBUG("Turning off camera stream");

  // Abort stream in case it was not already done, which will introduce some sleeping in our run() thread, thereby
  // helping us acquire our needed double lock:
  abortStream();

  // We need a double lock here so that we can both turn off the stream and nuke our output image and done idx:
  std::unique_lock<std::timed_mutex> lk1(itsMtx, std::defer_lock);
  std::unique_lock<std::mutex> lk2(itsOutputMtx, std::defer_lock);
  std::lock(lk1, lk2);

  // Invalidate our output image:
  itsOutputImage.invalidate();

  // User may have called done() but our run() thread has not yet gotten to requeueing this image, if so requeue it here
  // as it seems to keep the driver happier:
  if (itsBuffers)
    for (size_t idx : itsDoneIdx) try { itsBuffers->qbuf(idx); } catch (...) { jevois::warnAndIgnoreException(); }
  itsDoneIdx.clear();
  
  // Stop streaming at the device level:
  int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  try { XIOCTL_QUIET(itsFd, VIDIOC_STREAMOFF, &type); } catch (...) { }

  // Nuke all the buffers:
  if (itsBuffers) { delete itsBuffers; itsBuffers = nullptr; }

  // Unblock any get() that is waiting on itsOutputCondVar, it will then throw now that streaming is off:
  lk2.unlock();
  itsOutputCondVar.notify_all();

  LDEBUG("Camera stream is off");
}
示例#3
0
bool audio::orchestra::api::Core::callbackEvent(AudioDeviceID _deviceId,
                                         const AudioBufferList *_inBufferList,
                                         const audio::Time& _inTime,
                                         const AudioBufferList *_outBufferList,
                                         const audio::Time& _outTime) {
	if (    m_state == audio::orchestra::state::stopped
	     || m_state == audio::orchestra::state::stopping) {
		return true;
	}
	if (m_state == audio::orchestra::state::closed) {
		ATA_ERROR("the stream is closed ... this shouldn't happen!");
		return false;
	}
	// Check if we were draining the stream and signal is finished.
	if (m_private->drainCounter > 3) {
		m_state = audio::orchestra::state::stopping;
		ATA_VERBOSE("Set state as stopping");
		if (m_private->internalDrain == true) {
			new std::thread(&audio::orchestra::api::Core::coreStopStream, this);
		} else {
			// external call to stopStream()
			m_private->condition.notify_one();
		}
		return true;
	}
	AudioDeviceID outputDevice = m_private->id[0];
	// Invoke user callback to get fresh output data UNLESS we are
	// draining stream or duplex mode AND the input/output devices are
	// different AND this function is called for the input device.
	if (m_private->drainCounter == 0 && (m_mode != audio::orchestra::mode_duplex || _deviceId == outputDevice)) {
		std::vector<enum audio::orchestra::status> status;
		if (    m_mode != audio::orchestra::mode_input
		     && m_private->xrun[0] == true) {
			status.push_back(audio::orchestra::status::underflow);
			m_private->xrun[0] = false;
		}
		if (    m_mode != audio::orchestra::mode_output
		     && m_private->xrun[1] == true) {
			status.push_back(audio::orchestra::status::overflow);
			m_private->xrun[1] = false;
		}
		int32_t cbReturnValue = m_callback(&m_userBuffer[1][0],
		                                   _inTime,
		                                   &m_userBuffer[0][0],
		                                   _outTime,
		                                   m_bufferSize,
		                                   status);
		if (cbReturnValue == 2) {
			m_state = audio::orchestra::state::stopping;
			ATA_VERBOSE("Set state as stopping");
			m_private->drainCounter = 2;
			abortStream();
			return true;
		} else if (cbReturnValue == 1) {
			m_private->drainCounter = 1;
			m_private->internalDrain = true;
		}
	}
	if (    m_mode == audio::orchestra::mode_output
	     || (    m_mode == audio::orchestra::mode_duplex
	          && _deviceId == outputDevice)) {
		if (m_private->drainCounter > 1) {
			// write zeros to the output stream
			if (m_private->nStreams[0] == 1) {
				memset(_outBufferList->mBuffers[m_private->iStream[0]].mData,
				       0,
				       _outBufferList->mBuffers[m_private->iStream[0]].mDataByteSize);
			} else {
				// fill multiple streams with zeros
				for (uint32_t i=0; i<m_private->nStreams[0]; i++) {
					memset(_outBufferList->mBuffers[m_private->iStream[0]+i].mData,
					       0,
					       _outBufferList->mBuffers[m_private->iStream[0]+i].mDataByteSize);
				}
			}
		} else if (m_private->nStreams[0] == 1) {
			if (m_doConvertBuffer[0]) {
				// convert directly to CoreAudio stream buffer
				convertBuffer((char*)_outBufferList->mBuffers[m_private->iStream[0]].mData,
				              &m_userBuffer[0][0],
				              m_convertInfo[0]);
			} else {
				// copy from user buffer
				memcpy(_outBufferList->mBuffers[m_private->iStream[0]].mData,
				       &m_userBuffer[0][0],
				       _outBufferList->mBuffers[m_private->iStream[0]].mDataByteSize);
			}
		} else {
			// fill multiple streams
			float *inBuffer = (float *) &m_userBuffer[0][0];
			if (m_doConvertBuffer[0]) {
				convertBuffer(m_deviceBuffer, &m_userBuffer[0][0], m_convertInfo[0]);
				inBuffer = (float *) m_deviceBuffer;
			}
			if (m_deviceInterleaved[0] == false) { // mono mode
				uint32_t bufferBytes = _outBufferList->mBuffers[m_private->iStream[0]].mDataByteSize;
				for (uint32_t i=0; i<m_nUserChannels[0]; i++) {
					memcpy(_outBufferList->mBuffers[m_private->iStream[0]+i].mData,
					       (void *)&inBuffer[i*m_bufferSize],
					       bufferBytes);
				}
			} else {
				// fill multiple multi-channel streams with interleaved data
				uint32_t streamChannels, channelsLeft, inJump, outJump, inOffset;
				float *out, *in;
				bool inInterleaved = true;
				uint32_t inChannels = m_nUserChannels[0];
				if (m_doConvertBuffer[0]) {
					inInterleaved = true; // device buffer will always be interleaved for nStreams > 1 and not mono mode
					inChannels = m_nDeviceChannels[0];
				}
				if (inInterleaved) {
					inOffset = 1;
				} else {
					inOffset = m_bufferSize;
				}
				channelsLeft = inChannels;
				for (uint32_t i=0; i<m_private->nStreams[0]; i++) {
					in = inBuffer;
					out = (float *) _outBufferList->mBuffers[m_private->iStream[0]+i].mData;
					streamChannels = _outBufferList->mBuffers[m_private->iStream[0]+i].mNumberChannels;
					outJump = 0;
					// Account for possible channel offset in first stream
					if (i == 0 && m_channelOffset[0] > 0) {
						streamChannels -= m_channelOffset[0];
						outJump = m_channelOffset[0];
						out += outJump;
					}
					// Account for possible unfilled channels at end of the last stream
					if (streamChannels > channelsLeft) {
						outJump = streamChannels - channelsLeft;
						streamChannels = channelsLeft;
					}
					// Determine input buffer offsets and skips
					if (inInterleaved) {
						inJump = inChannels;
						in += inChannels - channelsLeft;
					} else {
						inJump = 1;
						in += (inChannels - channelsLeft) * inOffset;
					}
					for (uint32_t i=0; i<m_bufferSize; i++) {
						for (uint32_t j=0; j<streamChannels; j++) {
							*out++ = in[j*inOffset];
						}
						out += outJump;
						in += inJump;
					}
					channelsLeft -= streamChannels;
				}
			}
		}
		if (m_private->drainCounter) {
			m_private->drainCounter++;
			goto unlock;
		}
	}
	AudioDeviceID inputDevice;
	inputDevice = m_private->id[1];
	if (    m_mode == audio::orchestra::mode_input
	     || (    m_mode == audio::orchestra::mode_duplex
	          && _deviceId == inputDevice)) {
		if (m_private->nStreams[1] == 1) {
			if (m_doConvertBuffer[1]) {
				// convert directly from CoreAudio stream buffer
				convertBuffer(&m_userBuffer[1][0],
				              (char *) _inBufferList->mBuffers[m_private->iStream[1]].mData,
				              m_convertInfo[1]);
			} else { // copy to user buffer
				memcpy(&m_userBuffer[1][0],
				       _inBufferList->mBuffers[m_private->iStream[1]].mData,
				       _inBufferList->mBuffers[m_private->iStream[1]].mDataByteSize);
			}
		} else { // read from multiple streams
			float *outBuffer = (float *) &m_userBuffer[1][0];
			if (m_doConvertBuffer[1]) {
				outBuffer = (float *) m_deviceBuffer;
			}
			if (m_deviceInterleaved[1] == false) {
				// mono mode
				uint32_t bufferBytes = _inBufferList->mBuffers[m_private->iStream[1]].mDataByteSize;
				for (uint32_t i=0; i<m_nUserChannels[1]; i++) {
					memcpy((void *)&outBuffer[i*m_bufferSize],
					       _inBufferList->mBuffers[m_private->iStream[1]+i].mData,
					       bufferBytes);
				}
			} else {
				// read from multiple multi-channel streams
				uint32_t streamChannels, channelsLeft, inJump, outJump, outOffset;
				float *out, *in;
				bool outInterleaved = true;
				uint32_t outChannels = m_nUserChannels[1];
				if (m_doConvertBuffer[1]) {
					outInterleaved = true; // device buffer will always be interleaved for nStreams > 1 and not mono mode
					outChannels = m_nDeviceChannels[1];
				}
				if (outInterleaved) {
					outOffset = 1;
				} else {
					outOffset = m_bufferSize;
				}
				channelsLeft = outChannels;
				for (uint32_t i=0; i<m_private->nStreams[1]; i++) {
					out = outBuffer;
					in = (float *) _inBufferList->mBuffers[m_private->iStream[1]+i].mData;
					streamChannels = _inBufferList->mBuffers[m_private->iStream[1]+i].mNumberChannels;
					inJump = 0;
					// Account for possible channel offset in first stream
					if (i == 0 && m_channelOffset[1] > 0) {
						streamChannels -= m_channelOffset[1];
						inJump = m_channelOffset[1];
						in += inJump;
					}
					// Account for possible unread channels at end of the last stream
					if (streamChannels > channelsLeft) {
						inJump = streamChannels - channelsLeft;
						streamChannels = channelsLeft;
					}
					// Determine output buffer offsets and skips
					if (outInterleaved) {
						outJump = outChannels;
						out += outChannels - channelsLeft;
					} else {
						outJump = 1;
						out += (outChannels - channelsLeft) * outOffset;
					}
					for (uint32_t i=0; i<m_bufferSize; i++) {
						for (uint32_t j=0; j<streamChannels; j++) {
							out[j*outOffset] = *in++;
						}
						out += outJump;
						in += inJump;
					}
					channelsLeft -= streamChannels;
				}
			}
			if (m_doConvertBuffer[1]) { // convert from our internal "device" buffer
				convertBuffer(&m_userBuffer[1][0],
				              m_deviceBuffer,
				              m_convertInfo[1]);
			}
		}
	}

unlock:
	//m_mutex.unlock();
	audio::orchestra::Api::tickStreamTime();
	return true;
}
示例#4
0
static void saxStartElement( message_info_t *data, const xmlChar *name, const xmlChar **attrs ){
	if ( data->ignore_depth == 0 ) {
		if ( data->bGeometry ) {
			// we have a handler
			data->pGeometry->saxStartElement( data, name, attrs );
		}
		else
		{
			if ( strcmp( (char *)name, "q3map_feedback" ) == 0 ) {
				// check the correct version
				// old q3map don't send a version attribute
				// the ones we support .. send Q3MAP_STREAM_VERSION
				if ( !attrs[0] || !attrs[1] || ( strcmp( (char*)attrs[0],"version" ) != 0 ) ) {
					Sys_FPrintf( SYS_ERR, "No stream version given in the feedback stream, this is an old q3map version.\n"
										  "Please turn off monitored compiling if you still wish to use this q3map executable\n" );
					abortStream( data );
					return;
				}
				else if ( strcmp( (char*)attrs[1],Q3MAP_STREAM_VERSION ) != 0 ) {
					Sys_FPrintf( SYS_ERR,
								 "This version of Radiant reads version %s debug streams, I got an incoming connection with version %s\n"
								 "Please make sure your versions of Radiant and q3map are matching.\n", Q3MAP_STREAM_VERSION, (char*)attrs[1] );
					abortStream( data );
					return;
				}
			}
			// we don't treat locally
			else if ( strcmp( (char *)name, "message" ) == 0 ) {
				data->msg_level = atoi( (char *)attrs[1] );
			}
			else if ( strcmp( (char *)name, "polyline" ) == 0 ) {
				// polyline has a particular status .. right now we only use it for leakfile ..
				data->bGeometry = true;
				data->pGeometry = &g_pointfile;
				data->pGeometry->saxStartElement( data, name, attrs );
			}
			else if ( strcmp( (char *)name, "select" ) == 0 ) {
				CSelectMsg *pSelect = new CSelectMsg();
				data->bGeometry = true;
				data->pGeometry = pSelect;
				data->pGeometry->saxStartElement( data, name, attrs );
			}
			else if ( strcmp( (char *)name, "pointmsg" ) == 0 ) {
				CPointMsg *pPoint = new CPointMsg();
				data->bGeometry = true;
				data->pGeometry = pPoint;
				data->pGeometry->saxStartElement( data, name, attrs );
			}
			else if ( strcmp( (char *)name, "windingmsg" ) == 0 ) {
				CWindingMsg *pWinding = new CWindingMsg();
				data->bGeometry = true;
				data->pGeometry = pWinding;
				data->pGeometry->saxStartElement( data, name, attrs );
			}
			else
			{
				Sys_FPrintf( SYS_WRN, "WARNING: ignoring unrecognized node in XML stream (%s)\n", name );
				// we don't recognize this node, jump over it
				// (NOTE: the ignore mechanism is a bit screwed, only works when starting an ignore at the highest level)
				data->ignore_depth = data->recurse;
			}
		}
	}
	data->recurse++;
}