Exemplo n.º 1
0
// Delete a connection with saved state
//
bool openavbAvdeccClearSavedState(const openavb_tl_data_cfg_t *pListener)
{
	AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);

	int i;

	// Delete the saved state matching the supplied one.
	// If the supplied saved state does not match any of the ones already saved, do nothing and return.
	for (i = 0; i < 1000; ++i) {
		const openavb_saved_state_t * pTest = openavbAvdeccGetSavedState(i);
		if (!pTest) {
			break;
		}

		if (strcmp(pTest->listener_friendly_name, pListener->friendly_name) == 0) {
			// We found the index for the item to delete.
			// Delete the item and save the updated file.
			openavbAvdeccDeleteSavedState(i);
			AVB_LOGF_DEBUG("Cleared saved state:  listener_id=\"%s\"", pListener->friendly_name);

			AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
			return true;
		}
	}

	AVB_LOGF_WARNING("Unable to find saved state to clear:  listener_id=\"%s\"", pListener->friendly_name);
	AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
	return false;
}
Exemplo n.º 2
0
// Each configuration name value pair for this mapping will result in this callback being called.
void openavbIntfMpeg2tsGstCfgCB(media_q_t *pMediaQ, const char *name, const char *value)
{
	AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL);

	if (pMediaQ)
	{
		pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo;
		if (!pPvtData)
		{
			AVB_LOG_ERROR("Private interface module data not allocated.");
			return;
		}

		char *pEnd;
		unsigned long tmp;
		bool nameOK = TRUE, valueOK = FALSE;

		if (strcmp(name, "intf_nv_gst_pipeline") == 0)
		{
			if (pPvtData->pPipelineStr)
				free(pPvtData->pPipelineStr);
			pPvtData->pPipelineStr = strdup(value);
			valueOK = (value != NULL && strlen(value) > 0);
		}
		else if (strcmp(name, "intf_nv_ignore_timestamp") == 0)
		{
			tmp = strtol(value, &pEnd, 10);
			if (*pEnd == '\0' && pEnd != value && (tmp == 0 || tmp == 1))
			{
				pPvtData->ignoreTimestamp = (tmp == 1);
				valueOK = TRUE;
			}
		}
		else
		{
			AVB_LOGF_WARNING("Unknown configuration item: %s", name);
			nameOK = FALSE;
		}

		if (nameOK && !valueOK)
		{
			AVB_LOGF_WARNING("Bad value for configuration item: %s = %s", name, value);
		}
	}

	AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL);
}
Exemplo n.º 3
0
static pcap_t* open_pcap_dev(const char* ifname, int frameSize, char* errbuf)
{
	pcap_t* handle = pcap_create(ifname, errbuf);
	if (handle) {
		int err;
		err = pcap_set_snaplen(handle, frameSize);
		if (err) AVB_LOGF_WARNING("Cannot set snap len %d", err);

		err = pcap_set_promisc(handle, 1);
		if (err) AVB_LOGF_WARNING("Cannot set promisc %d", err);

		err = pcap_set_immediate_mode(handle, 1);
		if (err) AVB_LOGF_WARNING("Cannot set immediate mode %d", err);

		// we need timeout (here 100ms) otherwise we could block for ever
		err = pcap_set_timeout(handle, 100);
		if (err) AVB_LOGF_WARNING("Cannot set timeout %d", err);

		err = pcap_set_tstamp_precision(handle, PCAP_TSTAMP_PRECISION_NANO);
		if (err) AVB_LOGF_WARNING("Cannot set tstamp nano precision %d", err);

		err = pcap_set_tstamp_type(handle, PCAP_TSTAMP_ADAPTER_UNSYNCED);
		if (err) AVB_LOGF_WARNING("Cannot set tstamp adapter unsynced %d", err);

		err = pcap_activate(handle);
		if (err) AVB_LOGF_WARNING("Cannot activate pcap %d", err);
	}
	return handle;
}
Exemplo n.º 4
0
static gboolean
bus_message(GstBus *bus, GstMessage *message, void *pv)
{
	switch (GST_MESSAGE_TYPE(message))
	{
		case GST_MESSAGE_ERROR:
		{
			GError *err = NULL;
			gchar *dbg_info = NULL;

			gst_message_parse_error(message, &err, &dbg_info);
			AVB_LOGF_ERROR("GStreamer ERROR message from element %s: %s",
			               GST_OBJECT_NAME(message->src),
			               err->message);
			AVB_LOGF_ERROR("Additional info: %s\n", (dbg_info) ? dbg_info : "none");
			g_error_free(err);
			g_free(dbg_info);
			break;
		}
		case GST_MESSAGE_WARNING:
		{
			GError *err = NULL;
			gchar *dbg_info = NULL;

			gst_message_parse_warning(message, &err, &dbg_info);
			AVB_LOGF_WARNING("GStreamer WARNING message from element %s: %s",
			                 GST_OBJECT_NAME(message->src),
			                 err->message);
			AVB_LOGF_WARNING("Additional info: %s\n", (dbg_info) ? dbg_info : "none");
			g_error_free(err);
			g_free(dbg_info);
			break;
		}
		case GST_MESSAGE_INFO:
		{
			GError *err = NULL;
			gchar *dbg_info = NULL;

			gst_message_parse_info(message, &err, &dbg_info);
			AVB_LOGF_ERROR("GStreamer INFO message from element %s: %s",
			               GST_OBJECT_NAME(message->src),
			               err->message);
			AVB_LOGF_ERROR("Additional info: %s\n", (dbg_info) ? dbg_info : "none");
			g_error_free(err);
			g_free(dbg_info);
			break;
		}
		case GST_MESSAGE_STATE_CHANGED:
		{
			GstState old_state, new_state;
			gst_message_parse_state_changed(message, &old_state, &new_state, NULL);
			AVB_LOGF_DEBUG("Element %s changed state from %s to %s",
			               GST_OBJECT_NAME(message->src),
			               gst_element_state_get_name(old_state),
			               gst_element_state_get_name(new_state));
			break;
		}
		case GST_MESSAGE_STREAM_STATUS:
		{
			// not so valuable
			break;
		}
		case GST_MESSAGE_EOS:
			AVB_LOG_INFO("EOS received");
			break;
		default:
			AVB_LOGF_INFO("GStreamer '%s' message from element %s",
			              gst_message_type_get_name(GST_MESSAGE_TYPE(message)),
			              GST_OBJECT_NAME(message->src));
			break;
	}

	return TRUE;
}
Exemplo n.º 5
0
bool openavbAvdeccMsgSrvrHndlInitIdentifyFromClient(int avdeccMsgHandle, char * friendly_name, U8 talker)
{
	AVB_TRACE_ENTRY(AVB_TRACE_AVDECC_MSG);
	openavb_tl_data_cfg_t * currentStream;

	avdecc_msg_state_t *pState = AvdeccMsgStateListGet(avdeccMsgHandle);
	if (pState) {
		// The handle was already specified.  Something has gone terribly wrong!
		AVB_LOGF_ERROR("avdeccMsgHandle %d already used", avdeccMsgHandle);
		AvdeccMsgStateListRemove(pState);
		free(pState);
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC_MSG);
		return false;
	}

	// Make sure the supplied string is nil-terminated.
	friendly_name[FRIENDLY_NAME_SIZE - 1] = '\0';

	// Create a structure to hold the client information.
	pState = (avdecc_msg_state_t *) calloc(1, sizeof(avdecc_msg_state_t));
	if (!pState) {
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC_MSG);
		return false;
	}
	pState->avdeccMsgHandle = avdeccMsgHandle;
	pState->bTalker = (talker != 0);
	pState->lastRequestedState = pState->lastReportedState = OPENAVB_AVDECC_MSG_UNKNOWN;

	// Find the state information matching this item.
	for (currentStream = streamList; currentStream != NULL; currentStream = currentStream->next) {
		if (strncmp(currentStream->friendly_name, friendly_name, FRIENDLY_NAME_SIZE) == 0)
		{
			break;
		}
	}
	if (!currentStream) {
		AVB_LOGF_WARNING("Ignoring unexpected client %d, friendly_name:  %s",
			avdeccMsgHandle, friendly_name);
		free(pState);
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC_MSG);
		return false;
	}

	// Keep track of this new state item.
	if (!AvdeccMsgStateListAdd(pState)) {
		AVB_LOGF_ERROR("Error saving client identity information %d", avdeccMsgHandle);
		free(pState);
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC_MSG);
		return false;
	}

	// Associate this Listener instance with the stream information.
	pState->stream = currentStream;
	currentStream->client = pState;

	AVB_LOGF_INFO("Client %d Detected, friendly_name:  %s",
		avdeccMsgHandle, friendly_name);

	// Enable ADP support, now that we have at least one Talker/Listener.
	openavbAdpHaveTL(true);

	AVB_TRACE_EXIT(AVB_TRACE_AVDECC_MSG);
	return true;
}
Exemplo n.º 6
0
// Called from openavbTLThreadFn() which is started from openavbTLRun()
void openavbTLRunListener(tl_state_t *pTLState)
{
	AVB_TRACE_ENTRY(AVB_TRACE_TL);

	if (!pTLState) {
		AVB_LOG_ERROR("Invalid TLState");
		AVB_TRACE_EXIT(AVB_TRACE_TL);
		return;
	}

	openavb_tl_cfg_t *pCfg = &pTLState->cfg;

	pTLState->pPvtListenerData = calloc(1, sizeof(listener_data_t));
	if (!pTLState->pPvtListenerData) {
		AVB_LOG_WARNING("Failed to allocate listener data.");
		return;
	}

	AVBStreamID_t streamID;
	memset(&streamID, 0, sizeof(streamID));
	memcpy(streamID.addr, pCfg->stream_addr.mac, ETH_ALEN);
	streamID.uniqueID = pCfg->stream_uid;

	AVB_LOGF_INFO("Attach "STREAMID_FORMAT, STREAMID_ARGS(&streamID));

	// Create Stats Mutex
	{
		MUTEX_ATTR_HANDLE(mta);
		MUTEX_ATTR_INIT(mta);
		MUTEX_ATTR_SET_TYPE(mta, MUTEX_ATTR_TYPE_DEFAULT);
		MUTEX_ATTR_SET_NAME(mta, "TLStatsMutex");
		MUTEX_CREATE_ERR();
		MUTEX_CREATE(pTLState->statsMutex, mta);
		MUTEX_LOG_ERR("Could not create/initialize 'TLStatsMutex' mutex");
	}

	// Tell endpoint to listen for our stream.
	// If there is a talker, we'll get callback (above.)
	pTLState->bConnected = openavbTLRunListenerInit(pTLState->endpointHandle, &streamID);

	if (pTLState->bConnected) {
		bool bServiceIPC;

		// Notify AVDECC Msg of the state change.
		openavbAvdeccMsgClntNotifyCurrentState(pTLState);

		// Do until we are stopped or lose connection to endpoint
		while (pTLState->bRunning && pTLState->bConnected) {

			// Listen for an RX frame (or just sleep if not streaming)
			bServiceIPC = listenerDoStream(pTLState);

			if (bServiceIPC) {
				// Look for messages from endpoint.  Don't block (timeout=0)
				if (!openavbEptClntService(pTLState->endpointHandle, 0)) {
					AVB_LOGF_WARNING("Lost connection to endpoint "STREAMID_FORMAT, STREAMID_ARGS(&streamID));
					pTLState->bConnected = FALSE;
					pTLState->endpointHandle = 0;
				}
			}
		}

		// Stop streaming
		listenerStopStream(pTLState);

		{
			MUTEX_CREATE_ERR();
			MUTEX_DESTROY(pTLState->statsMutex); // Destroy Stats Mutex
			MUTEX_LOG_ERR("Error destroying mutex");
		}

		// withdraw our listener attach
		if (pTLState->bConnected)
			openavbEptClntStopStream(pTLState->endpointHandle, &streamID);

		// Notify AVDECC Msg of the state change.
		openavbAvdeccMsgClntNotifyCurrentState(pTLState);
	}
	else {
		AVB_LOGF_WARNING("Failed to connect to endpoint "STREAMID_FORMAT, STREAMID_ARGS(&streamID));
	}

	if (pTLState->pPvtListenerData) {
		free(pTLState->pPvtListenerData);
		pTLState->pPvtListenerData = NULL;
	}

	AVB_TRACE_EXIT(AVB_TRACE_TL);
}
Exemplo n.º 7
0
// Called from openavbTLThreadFn() which is started from openavbTLRun() 
void openavbTLRunTalker(tl_state_t *pTLState)
{
	AVB_TRACE_ENTRY(AVB_TRACE_TL);

	if (!pTLState) {
		AVB_LOG_ERROR("Invalid TLState");
		AVB_TRACE_EXIT(AVB_TRACE_TL);
		return;
	}

	pTLState->pPvtTalkerData = calloc(1, sizeof(talker_data_t));
	if (!pTLState->pPvtTalkerData) {
		AVB_LOG_WARNING("Failed to allocate talker data.");
		return;
	}

	// Create Stats Mutex
	{
		MUTEX_ATTR_HANDLE(mta);
		MUTEX_ATTR_INIT(mta);
		MUTEX_ATTR_SET_TYPE(mta, MUTEX_ATTR_TYPE_DEFAULT);
		MUTEX_ATTR_SET_NAME(mta, "TLStatsMutex");
		MUTEX_CREATE_ERR();
		MUTEX_CREATE(pTLState->statsMutex, mta);
		MUTEX_LOG_ERR("Could not create/initialize 'TLStatsMutex' mutex");
	}

	/* If using endpoint register talker,
	   else register with tpsec */
	pTLState->bConnected = openavbTLRunTalkerInit(pTLState); 

	if (pTLState->bConnected) {
		bool bServiceIPC;

		// Do until we are stopped or loose connection to endpoint
		while (pTLState->bRunning && pTLState->bConnected) {

			// Talk (or just sleep if not streaming.)
			bServiceIPC = talkerDoStream(pTLState);

			// TalkerDoStream() returns TRUE once per second,
			// so that we can service our IPC at that low rate.
			if (bServiceIPC) {
				// Look for messages from endpoint.  Don't block (timeout=0)
				if (!openavbEptClntService(pTLState->endpointHandle, 0)) {
					AVB_LOGF_WARNING("Lost connection to endpoint, will retry "STREAMID_FORMAT, STREAMID_ARGS(&(((talker_data_t *)pTLState->pPvtTalkerData)->streamID)));
					pTLState->bConnected = FALSE;
					pTLState->endpointHandle = 0;
				}
			}
		}

		// Stop streaming
		talkerStopStream(pTLState);

		{
			MUTEX_CREATE_ERR();
			MUTEX_DESTROY(pTLState->statsMutex); // Destroy Stats Mutex
			MUTEX_LOG_ERR("Error destroying mutex");
		}

		// withdraw our talker registration
		if (pTLState->bConnected)
			openavbEptClntStopStream(pTLState->endpointHandle, &(((talker_data_t *)pTLState->pPvtTalkerData)->streamID));

		openavbTLRunTalkerFinish(pTLState);
	}
	else {
		AVB_LOGF_WARNING("Failed to connect to endpoint"STREAMID_FORMAT, STREAMID_ARGS(&(((talker_data_t *)pTLState->pPvtTalkerData)->streamID)));
	}

	if (pTLState->pPvtTalkerData) {
		free(pTLState->pPvtTalkerData);
		pTLState->pPvtTalkerData = NULL;
	}

	AVB_TRACE_EXIT(AVB_TRACE_TL);
}
Exemplo n.º 8
0
// Get a RX frame
U8* ringRawsockGetRxFrame(void *pvRawsock, U32 timeout, unsigned int *offset, unsigned int *len)
{
	AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL);
	ring_rawsock_t *rawsock = (ring_rawsock_t*)pvRawsock;
	if (!VALID_RX_RAWSOCK(rawsock)) {
		AVB_LOG_ERROR("Getting RX frame; invalid arguments");
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
		return NULL;
	}
	if (rawsock->buffersOut >= rawsock->frameCount) {
		AVB_LOG_ERROR("Too many RX buffers in use");
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
		return NULL;
	}

	// Get pointer to active buffer in ring
	volatile struct tpacket2_hdr *pHdr =
		(struct tpacket2_hdr*)(rawsock->pMem
							   + (rawsock->blockIndex * rawsock->blockSize)
							   + (rawsock->bufferIndex * rawsock->bufferSize));
	volatile U8 *pBuffer = (U8*)pHdr + rawsock->bufHdrSize;

	AVB_LOGF_VERBOSE("block=%d, buffer=%d, out=%d, pBuffer=%p, pHdr=%p",
					 rawsock->blockIndex, rawsock->bufferIndex, rawsock->buffersOut,
					 pBuffer, pHdr);

	// Check if buffer ready for user
	// In receive mode, we want TP_STATUS_USER flag set
	if ((pHdr->tp_status & TP_STATUS_USER) == 0)
	{
		struct timespec ts, *pts = NULL;
		struct pollfd pfd;

		// Use poll to wait for "ready to read" condition

		// Poll even if our timeout is 0 - to catch the case where
		// kernel is writing to the wrong slot (see below.)
		if (timeout != OPENAVB_RAWSOCK_BLOCK) {
			ts.tv_sec = timeout / MICROSECONDS_PER_SECOND;
			ts.tv_nsec = (timeout % MICROSECONDS_PER_SECOND) * NANOSECONDS_PER_USEC;
			pts = &ts;
		}

		pfd.fd = rawsock->sock;
		pfd.events = POLLIN;
		pfd.revents = 0;

		int ret = ppoll(&pfd, 1, pts, NULL);
		if (ret < 0) {
			if (errno != EINTR) {
				AVB_LOGF_ERROR("Getting RX frame; poll failed: %s", strerror(errno));
			}
			AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
			return NULL;
		}
		if ((pfd.revents & POLLIN) == 0) {
			// timeout
			AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
			return NULL;
		}

		if ((pHdr->tp_status & TP_STATUS_USER) == 0) {
			// Hmmm, this is unexpected.  poll indicated that the
			// socket was ready to read, but the slot in the TX ring
			// that we're looking for the kernel to fill isn't filled.

			// If there aren't any RX buffers held by the application,
			// we can try to fix this sticky situation...
			if (rawsock->buffersOut == 0) {
				// Scan forward through the RX ring, and look for a
				// buffer that's ready for us to read.  The kernel has
				// a bad habit of not starting at the beginning of the
				// ring when the listener process is restarted.
				int nSkipped = 0;
				while((pHdr->tp_status & TP_STATUS_USER) == 0) {
					// Move to next slot in ring.
					// (Increment buffer/block indexes)
					if (++(rawsock->bufferIndex) >= (rawsock->frameCount/rawsock->blockCount)) {
						rawsock->bufferIndex = 0;
						if (++(rawsock->blockIndex) >= rawsock->blockCount) {
							rawsock->blockIndex = 0;
						}
					}

					// Adjust pHdr, pBuffer to point to the new slot
					pHdr = (struct tpacket2_hdr*)(rawsock->pMem
												  + (rawsock->blockIndex * rawsock->blockSize)
												  + (rawsock->bufferIndex * rawsock->bufferSize));
					pBuffer = (U8*)pHdr + rawsock->bufHdrSize;

					// If we've scanned all the way around the ring, bail out.
					if (++nSkipped > rawsock->frameCount) {
						AVB_LOG_WARNING("Getting RX frame; no frame after poll");
						AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
						return NULL;
					}
				}

				// We found a slot that's ready.  Hopefully, we're good now.
				AVB_LOGF_WARNING("Getting RX frame; skipped %d empty slots (rawsock=%p)", nSkipped, rawsock);
			}
			else {
				AVB_LOG_WARNING("Getting RX frame; no frame after poll");
				AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
				return NULL;
			}
		}
	}

	AVB_LOGF_VERBOSE("Buffer status=0x%4.4lx", (unsigned long)pHdr->tp_status);
	if (pHdr->tp_status & TP_STATUS_COPY) {
		AVB_LOG_WARNING("Frame too big for receive buffer");
	}

	// Check the "losing" flag.  That indicates that the ring is full,
	// and the kernel had to toss some frames. There is no "winning" flag.
	if ((pHdr->tp_status & TP_STATUS_LOSING)) {
		if (!rawsock->bLosing) {
			AVB_LOG_WARNING("Getting RX frame; mmap buffers full");
			rawsock->bLosing = TRUE;
		}
	}
	else {
		rawsock->bLosing = FALSE;
	}

	// increment indexes for next time
	if (++(rawsock->bufferIndex) >= (rawsock->frameCount/rawsock->blockCount)) {
		rawsock->bufferIndex = 0;
		if (++(rawsock->blockIndex) >= rawsock->blockCount) {
			rawsock->blockIndex = 0;
		}
	}

	// Remember that the client has another buffer
	rawsock->buffersOut += 1;

	if (pHdr->tp_snaplen < pHdr->tp_len) {
#if (AVB_LOG_LEVEL >= AVB_LOG_LEVEL_VERBOSE)
		AVB_LOGF_WARNING("Getting RX frame; partial frame ignored (len %d, snaplen %d)", pHdr->tp_len, pHdr->tp_snaplen);
		AVB_LOG_BUFFER(AVB_LOG_LEVEL_VERBOSE, (const U8 *) pBuffer + (pHdr->tp_mac - rawsock->bufHdrSize), pHdr->tp_len, 16);
#else
		IF_LOG_INTERVAL(1000) AVB_LOGF_WARNING("Getting RX frame; partial frame ignored (len %d, snaplen %d)", pHdr->tp_len, pHdr->tp_snaplen);
#endif
		ringRawsockRelRxFrame(rawsock, (U8*)pBuffer);
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
		return NULL;
	}

	// Return pointer to the buffer and length
	*offset = pHdr->tp_mac - rawsock->bufHdrSize;
	*len = pHdr->tp_snaplen;
	AVB_LOGF_VERBOSE("Good RX frame (len %d, snaplen %d)", pHdr->tp_len, pHdr->tp_snaplen);

	AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
	return (U8*)pBuffer;
}
Exemplo n.º 9
0
// Get a buffer from the ring to use for TX
U8* ringRawsockGetTxFrame(void *pvRawsock, bool blocking, unsigned int *len)
{
	AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL);
	ring_rawsock_t *rawsock = (ring_rawsock_t*)pvRawsock;

	// Displays only warning when buffer busy after second try
	int bBufferBusyReported = 0;


	if (!VALID_TX_RAWSOCK(rawsock) || len == NULL) {
		AVB_LOG_ERROR("Getting TX frame; bad arguments");
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
		return NULL;
	}
	if (rawsock->buffersOut >= rawsock->frameCount) {
		AVB_LOG_ERROR("Getting TX frame; too many TX buffers in use");
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
		return NULL;
	}

	// Get pointer to next framebuf.
	volatile struct tpacket2_hdr *pHdr =
		(struct tpacket2_hdr*)(rawsock->pMem
							   + (rawsock->blockIndex * rawsock->blockSize)
							   + (rawsock->bufferIndex * rawsock->bufferSize));
	// And pointer to portion of buffer to be filled with frame
	volatile U8 *pBuffer = (U8*)pHdr + rawsock->bufHdrSize;

	AVB_LOGF_VERBOSE("block=%d, buffer=%d, out=%d, pBuffer=%p, pHdr=%p",
					 rawsock->blockIndex, rawsock->bufferIndex, rawsock->buffersOut,
					 pBuffer, pHdr);

	// Check if buffer ready for user
	// In send mode, we want to see TP_STATUS_AVAILABLE
	while (pHdr->tp_status != TP_STATUS_AVAILABLE)
	{
		switch (pHdr->tp_status) {
			case TP_STATUS_SEND_REQUEST:
			case TP_STATUS_SENDING:
				if (blocking) {
#if 0
// We should be able to poll on the socket to wait for the buffer to
// be ready, but it doesn't work (at least on 2.6.37).
// Keep this code, because it may work on newer kernels
					// poll until tx buffer is ready
					struct pollfd pfd;
					pfd.fd = rawsock->sock;
					pfd.events = POLLWRNORM;
					pfd.revents = 0;
					int ret = poll(&pfd, 1, -1);
					if (ret < 0 && errno != EINTR) {
						AVB_LOGF_DEBUG("getting TX frame; poll failed: %s", strerror(errno));
					}
#else
					// Can't poll, so sleep instead to avoid tight loop
					if(0 == bBufferBusyReported) {
						if(!rawsock->txOutOfBuffer) {
							// Display this info only once just to let know that something like this happened
							AVB_LOGF_INFO("Getting TX frame (sock=%d): TX buffer busy", rawsock->sock);
						}

						++rawsock->txOutOfBuffer;
						++rawsock->txOutOfBufferCyclic;
					} else if(1 == bBufferBusyReported) {
						//Display this warning if buffer was busy more than once because it might influence late/lost
						AVB_LOGF_WARNING("Getting TX frame (sock=%d): TX buffer busy after usleep(50) verify if there are any lost/late frames", rawsock->sock);
					}

					++bBufferBusyReported;

					usleep(50);
#endif
				}
				else {
					AVB_LOG_DEBUG("Non-blocking, return NULL");
					AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
					return NULL;
				}
				break;
			case TP_STATUS_WRONG_FORMAT:
			default:
				pHdr->tp_status = TP_STATUS_AVAILABLE;
				break;
		}
	}

	// Remind client how big the frame buffer is
	if (len)
		*len = rawsock->base.frameSize;

	// increment indexes to point to next buffer
	if (++(rawsock->bufferIndex) >= (rawsock->frameCount/rawsock->blockCount)) {
		rawsock->bufferIndex = 0;
		if (++(rawsock->blockIndex) >= rawsock->blockCount) {
			rawsock->blockIndex = 0;
		}
	}

	// increment the count of buffers held by client
	rawsock->buffersOut += 1;

	// warn if too many are out
	if (rawsock->buffersOut >= (rawsock->frameCount * 4)/5) {
		AVB_LOGF_WARNING("Getting TX frame; consider increasing buffers: count=%d, out=%d",
						 rawsock->frameCount, rawsock->buffersOut);
	}

	AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
	return (U8*)pBuffer;
}
Exemplo n.º 10
0
bool openavbReadTlDataIniFile(const char *fileName, openavb_tl_data_cfg_t *pCfg)
{
	AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);

	openavbIniCfgInit(pCfg);

	// Use the .INI file name as the default friendly name.
	strncpy(pCfg->friendly_name, fileName, FRIENDLY_NAME_SIZE - 1);
	char * pszComma = strchr(pCfg->friendly_name, ',');
	if (pszComma) {
		// Get rid of anything following the file name.
		*pszComma = '\0';
	}
	char * pszExtension = strrchr(pCfg->friendly_name, '.');
	if (pszExtension && strcasecmp(pszExtension, ".ini") == 0) {
		// Get rid of the .INI file extension.
		*pszExtension = '\0';
	}

	int result = ini_parse(fileName, openavbIniCfgCallback, pCfg);
	if (result < 0) {
		AVB_LOGF_ERROR("Couldn't parse INI file: %s", fileName);
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return FALSE;
	}
	if (result > 0) {
		AVB_LOGF_ERROR("Error in INI file: %s, line %d", fileName, result);
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return FALSE;
	}

	if (pCfg->current_sampling_rate != 0 && pCfg->audioRate != 0 &&
		pCfg->current_sampling_rate != pCfg->audioRate)
	{
		AVB_LOGF_ERROR("current_sampling_rate(%u) and intf_nv_audio_rate(%u) do not match.", pCfg->current_sampling_rate, pCfg->audioRate);
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return FALSE;
	}

	if (pCfg->current_sampling_rate == 0)
	{
		/* Make sure we have a default sampling rate. */
		if (pCfg->audioRate != 0) {
			pCfg->current_sampling_rate = pCfg->audioRate;
		} else if (pCfg->sampling_rates[0] != 0) {
			pCfg->current_sampling_rate = pCfg->sampling_rates[0];
		} else {
			pCfg->current_sampling_rate = AVB_AUDIO_RATE_48KHZ;
		}
		if (pCfg->audioRate == 0) {
			AVB_LOGF_WARNING("current_sampling_rate not specified in %s. Defaulting to %u", fileName, pCfg->current_sampling_rate);
		}
	}
	if (pCfg->sampling_rates_count == 0)
	{
		/* Set the list of sampling rates to the current sampling rate. */
		pCfg->sampling_rates[0] = pCfg->current_sampling_rate;
		pCfg->sampling_rates_count = 1;
		if (pCfg->audioRate == 0) {
			AVB_LOGF_WARNING("sampling_rates not specified in %s. Defaulting to %u", fileName, pCfg->current_sampling_rate);
		}
	} else {
		/* Make sure the current sampling rate is in the list of sampling rates. */
		U16 i;
		for (i = 0; i < pCfg->sampling_rates_count; ++i) {
			if (pCfg->sampling_rates[i] == pCfg->current_sampling_rate) break;
		}
		if (i >= pCfg->sampling_rates_count) {
			AVB_LOGF_ERROR("current_sampling_rate(%u) not in list of sampling_rates.", pCfg->current_sampling_rate);
			AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
			return FALSE;
		}
	}

	AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
	return TRUE;
}