/* Get write pointer at most `cnt' bytes to `rb' from
   `src'.  Returns the actual number of bytes can insert. */
size_t ringbuffer_get_writepointer (ringbuffer_t * rb, uint8_t **src, size_t cnt)
{
	size_t free_cnt;
	size_t cnt2;
	size_t to_write;

	if ((free_cnt = ringbuffer_write_space (rb)) == 0)
		return 0;

	to_write = cnt > free_cnt ? free_cnt : cnt;

	cnt2 = rb->write_ptr + to_write;

	if (cnt2 > rb->size)
		return 0;
	else
		*src = &(rb->buf[rb->write_ptr]);

	return to_write;
}
/* The copying data writer.  Copy at most `cnt' bytes to `rb' from
 * `src'.  Returns the actual number of bytes copied.
 */
size_t ringbuffer_write (ringbuffer_t * rb, uint8_t *src, size_t cnt)
{
	size_t free_cnt;
	size_t cnt2;
	size_t to_write;
	size_t n1, n2;

	if ((free_cnt = ringbuffer_write_space (rb)) == 0)
		return 0;

	to_write = cnt > free_cnt ? free_cnt : cnt;

	cnt2 = rb->write_ptr + to_write;

	if (cnt2 > rb->size) {
		n1 = rb->size - rb->write_ptr;
		n2 = cnt2 & rb->size_mask;
	}
	else
	{
		n1 = to_write;
		n2 = 0;
	}

	memcpy (&(rb->buf[rb->write_ptr]), src, n1);
	rb->write_ptr += n1;
	rb->write_ptr &= rb->size_mask;

	if (n2)
	{
		memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2);
		rb->write_ptr += n2;
		rb->write_ptr &= rb->size_mask;
	}

	return to_write;
}
Beispiel #3
0
void * DMXThread(void * v_arg)
{
	pthread_t file_thread;
	struct filenames_t filename_data;
	char filename_extension[3];
	ringbuffer_data_t vec[2];
	ssize_t written;
	ssize_t todo = 0;
	ssize_t todo2;
	unsigned char buf[TS_SIZE];
	int     offset = 0;
	ssize_t r = 0;
	struct pollfd pfd = {*(int*)v_arg, POLLIN|POLLERR,0 };
	int pres;

	ringbuffer_t * ringbuf = ringbuffer_create(ringbuffersize);

	if (!ringbuf)
	{
		exit_flag = STREAM2FILE_STATUS_RECORDING_THREADS_FAILED;
		puts("[stream2file]: error allocating ringbuffer! (out of memory?)"); 
	}
	else
		fprintf(stderr, "[stream2file] allocated ringbuffer size: %ld\n", ringbuffer_write_space(ringbuf));

	filename_data.ringbuffer = ringbuf;

	if (v_arg == &dvrfd)
	{
		filename_data.extension = "ts";
	}
	else
	{
		for (int i = 0; i < MAXPIDS; i++)
			if (v_arg == (&(demuxfd[i])))
				sprintf(filename_extension, "%u", i);
		filename_data.extension = filename_extension;
	}

	if (pthread_create(&file_thread, 0, FileThread, &filename_data) != 0)
	{
		exit_flag = STREAM2FILE_STATUS_RECORDING_THREADS_FAILED;
		puts("[stream2file]: error creating file_thread! (out of memory?)"); 
	}

	if (v_arg == &dvrfd)
		while (exit_flag == STREAM2FILE_STATUS_RUNNING)
		{
			if ((pres=poll (&pfd, 1, 15000))>0)
			{
				if (!(pfd.revents&POLLIN))
				{
					printf ("[stream2file]: PANIC: error reading from demux, bailing out\n");
					exit_flag = STREAM2FILE_STATUS_READ_FAILURE;
				}
				r = read(*(int *)v_arg, &(buf[0]), TS_SIZE);
#ifdef HAVE_TRIPLEDRAGON
				if (r < 0)
				{
					perror("stream2file read DMX");
					exit_flag = STREAM2FILE_STATUS_READ_FAILURE;
					break;
				}
#endif
				if (r > 0)
				{
					offset = sync_byte_offset(&(buf[0]), r);
					if (offset != -1)
						break;
				}
			}
			else if (!pres)
			{
				printf ("[stream2file]: timeout from demux\n");
			}
		}
	else
		offset = 0;

	if (exit_flag == STREAM2FILE_STATUS_RUNNING)
	{
		written = ringbuffer_write(ringbuf, (char *)&(buf[offset]), r - offset);
		// TODO: Retry
		if (written != r - offset) {
			printf("PANIC: wrote less than requested to ringbuffer, written %d, requested %d\n", written, r - offset);
			exit_flag = STREAM2FILE_STATUS_BUFFER_OVERFLOW;
		}
		todo = IN_SIZE - (r - offset);
	}

	/* IN_SIZE > TS_SIZE => todo > 0 */

	while (exit_flag == STREAM2FILE_STATUS_RUNNING)
	{
		ringbuffer_get_write_vector(ringbuf, &(vec[0]));
		todo2 = todo - vec[0].len;
		if (todo2 < 0)
		{
			todo2 = 0;
		}
		else
		{
			if (((size_t)todo2) > vec[1].len)
			{
				printf("PANIC: not enough space in ringbuffer, available %d, needed %d\n", vec[0].len + vec[1].len, todo + todo2);
				exit_flag = STREAM2FILE_STATUS_BUFFER_OVERFLOW;
			}
			todo = vec[0].len;
		}

		while (exit_flag == STREAM2FILE_STATUS_RUNNING)
		{
			if ((pres=poll (&pfd, 1, 5000))>0)
			{
				if (!(pfd.revents&POLLIN))
				{
					printf ("PANIC: error reading from demux, bailing out\n");
					exit_flag = STREAM2FILE_STATUS_READ_FAILURE;
				}
				r = read(*(int *)v_arg, vec[0].buf, todo);
				if (r > 0)
				{
					ringbuffer_write_advance(ringbuf, r);
	
					if (todo == r)
					{
						if (todo2 == 0)
							goto next;
	
						todo = todo2;
						todo2 = 0;
						vec[0].buf = vec[1].buf;
					}
					else
					{
						vec[0].buf += r;
						todo -= r;
					}
				}
#ifdef HAVE_TRIPLEDRAGON
				if (r < 0 && errno != EAGAIN)
				{
					perror("[stream2file] read DMX");
					exit_flag = STREAM2FILE_STATUS_READ_FAILURE;
					break;
				}
#endif
			}
			else if (!pres){
				printf ("[stream2file]: timeout reading from demux\n");
				exit_flag = STREAM2FILE_STATUS_READ_FAILURE;
			}
		}
		next:
			todo = IN_SIZE;
	}

	if (v_arg == &dvrfd)
		close(*(int *)v_arg);
	else
		unsetPesFilter(*(int *)v_arg);

	pthread_join(file_thread, NULL);

	if (ringbuf)
		ringbuffer_free(ringbuf);

	if (v_arg == &dvrfd)
		while (demuxfd_count > 0)
			unsetPesFilter(demuxfd[--demuxfd_count]);

	DEC_BUSY_COUNT;

	if ((v_arg == &dvrfd) || (v_arg == (&(demuxfd[0]))))
	{
		CEventServer eventServer;
		eventServer.registerEvent2(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, "/tmp/neutrino.sock");
		stream2file_status2_t s;
		s.status = exit_flag;
		strncpy(s.filename,basename(myfilename),512);
		s.filename[511] = '\0';
		strncpy(s.dir,dirname(myfilename),100);
		s.dir[99] = '\0';
		eventServer.sendEvent(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, &s, sizeof(s));
		printf("[stream2file]: pthreads exit code: %i, dir: '%s', filename: '%s' myfilename: '%s'\n", exit_flag, s.dir, s.filename, myfilename);
	}

	pthread_exit(NULL);
}
Beispiel #4
0
void cRecord::DMXThread()
{
	pthread_t         file_thread;
	
	ringbuffer_data_t vec[2];
	ssize_t           written;
	ssize_t           todo = 0;
	ssize_t           todo2;
	unsigned char        buf[TS_SIZE];
	int                offset = 0;
	ssize_t            r = 0;
	struct pollfd       pfd;
	int                pres;

fprintf(stderr, "%s:%s >\n", __FILE__, __FUNCTION__);

        pfd.fd = dvrfd;
        pfd.events = POLLIN|POLLERR;
	pfd.revents = 0;
	
	ringbuffer_t * ringbuf = ringbuffer_create(ringbuffersize);

	if (!ringbuf)
	{
		exit_flag = STREAM2FILE_STATUS_WRITE_OPEN_FAILURE;
		fprintf(stderr, "[stream2file]: error allocating ringbuffer! (out of memory?)\n"); 
	}
	else
		fprintf(stderr, "[stream2file] allocated ringbuffer size: %ld\n", ringbuffer_write_space(ringbuf));

	ringbuffer = ringbuf;

	if (pthread_create(&file_thread, 0, execute_file_thread, this) != 0)
	{
		exit_flag = STREAM2FILE_STATUS_WRITE_OPEN_FAILURE;
		fprintf(stderr, "[stream2file]: error creating file_thread! (out of memory?)\n"); 
	}

	while (exit_flag == STREAM2FILE_STATUS_RUNNING)
	{
		if ((pres=poll (&pfd, 1, 15000))>0)
		{
			if (!(pfd.revents&POLLIN))
			{
				fprintf(stderr, "[stream2file]: PANIC: error reading from demux, bailing out\n");
				exit_flag = STREAM2FILE_STATUS_READ_FAILURE;
			}
			r = read(dvrfd, &(buf[0]), TS_SIZE);
			if (r > 0)
			{
				offset = sync_byte_offset(&(buf[0]), r);
				if (offset != -1)
					break;
			}
		}
		else if (!pres)
		{
			fprintf(stderr, "[stream2file]: timeout from demux\n");
		}
	}

	if (exit_flag == STREAM2FILE_STATUS_RUNNING)
	{
		written = ringbuffer_write(ringbuf, (char *)&(buf[offset]), r - offset);
		// TODO: Retry
		if (written != r - offset) {
			fprintf(stderr, "PANIC: wrote less than requested to ringbuffer, written %d, requested %d\n", written, r - offset);
			exit_flag = STREAM2FILE_STATUS_BUFFER_OVERFLOW;
		}
		todo = IN_SIZE - (r - offset);
	}

	/* IN_SIZE > TS_SIZE => todo > 0 */

	while (exit_flag == STREAM2FILE_STATUS_RUNNING)
	{
		ringbuffer_get_write_vector(ringbuf, &(vec[0]));
		todo2 = todo - vec[0].len;
		if (todo2 < 0)
		{
			todo2 = 0;
		}
		else
		{
			if (((size_t)todo2) > vec[1].len)
			{
				fprintf(stderr, "PANIC: not enough space in ringbuffer, available %d, needed %d\n", vec[0].len + vec[1].len, todo + todo2);
				exit_flag = STREAM2FILE_STATUS_BUFFER_OVERFLOW;
			}
			todo = vec[0].len;
		}

		while (exit_flag == STREAM2FILE_STATUS_RUNNING)
		{
			if ((pres=poll (&pfd, 1, 5000))>0)
			{
				if (!(pfd.revents&POLLIN))
				{
					fprintf(stderr, "PANIC: error reading from demux, bailing out\n");
					exit_flag = STREAM2FILE_STATUS_READ_FAILURE;
				}
				r = read(dvrfd, vec[0].buf, todo);
				if (r > 0)
				{
					ringbuffer_write_advance(ringbuf, r);
	
					if (todo == r)
					{
						if (todo2 == 0)
							goto next;
	
						todo = todo2;
						todo2 = 0;
						vec[0].buf = vec[1].buf;
					}
					else
					{
						vec[0].buf += r;
						todo -= r;
					}
				}
			}
			else if (!pres){
				fprintf(stderr, "[stream2file]: timeout reading from demux\n");
				exit_flag = STREAM2FILE_STATUS_READ_FAILURE;
			}
		}
		next:
			todo = IN_SIZE;
	}

	close(dvrfd);

	pthread_join(file_thread, NULL);

	if (ringbuf)
		ringbuffer_free(ringbuf);

	while (demuxfd_count > 0)
		unsetPesFilter(demuxfd[--demuxfd_count]);

#ifdef needed
//fixme: do we need it?
	CEventServer eventServer;
	eventServer.registerEvent2(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, "/tmp/neutrino.sock");
	stream2file_status2_t s;
	s.status = exit_flag;
	strncpy(s.filename,basename(myfilename),512);
	s.filename[511] = '\0';
	strncpy(s.dir,dirname(myfilename),100);
	s.dir[99] = '\0';
	eventServer.sendEvent(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, &s, sizeof(s));
	fprintf(stderr, "[stream2file]: pthreads exit code: %i, dir: '%s', filename: '%s' myfilename: '%s'\n", exit_flag, s.dir, s.filename, myfilename);
#endif

fprintf(stderr, "%s:%s <\n", __FILE__, __FUNCTION__);
	pthread_exit(NULL);
}
Beispiel #5
0
int JackClient::Process(jack_nframes_t nframes, void *self) {
    int j = 0;
    bool isEncoded = ((JackClient*) self)->m_Encoded;

    for(std::map<int, JackPort*>::iterator i = m_InputPortMap.begin();
        i != m_InputPortMap.end(); i++) {
        if(jack_port_connected(i->second->Port)) {
            sample_t *in = (sample_t *) jack_port_get_buffer(i->second->Port, nframes);
//                memcpy (i->second->Buf, in, sizeof (sample_t) * m_BufferSize); //m_BufferSize -> 2nd AudioCollector parameter
            //Buff attribué par SetInputBuf dans le construcAteur de AudioCollector
            if(isEncoded) {     //Added this to write in the buffer only if
                //the encoder is in action
                if(!j) {        //only streams the 1st Jack Input port
                    if(ringbuffer_write_space(((JackClient*) self)->first) >= (sizeof(sample_t) * nframes)) {
                        ringbuffer_write(((JackClient*) self)->first, (char *)in, (sizeof(sample_t) * nframes));
                    }
                    /*		    else
                                    {
                                      std::cerr << "-----------Pas suffisament de place dans audio_fred !!!" << std::endl;
                                    }*/
                    j++;
                }
            }
        }
    }

    int channels = ((JackClient*) self)->m_ringbufferchannels;


    bool output_available = false;
//m_ringbuffer created by ViewPort::add_audio
//1024*512 rounded up to the next power of two.
    if(((JackClient*) self)->m_ringbuffer) {
//        static int firsttime = 1 + ceil(4096/nframes); // XXX pre-buffer  TODO decrease this and compensate latency

        if(ringbuffer_read_space(((JackClient*) self)->m_ringbuffer) >=
           /*firsttime */ channels * nframes * sizeof(float)) {
//                firsttime=1;
            size_t rv = ringbuffer_read(((JackClient*) self)->m_ringbuffer,
                                        ((JackClient*) self)->m_inbuf,
                                        channels * nframes * sizeof(float));
            if(isEncoded) {     //Added this to write in the buffer only if
                //the encoder is in action
                if(ringbuffer_write_space(((JackClient*) self)->audio_mix_ring) >= rv) {
//                      unsigned char *aPtr = (unsigned char *)((JackClient*) self)->m_inbuf;
                    size_t rf = ringbuffer_write(((JackClient*) self)->audio_mix_ring, ((JackClient*) self)->m_inbuf, rv);
                    if(rf != rv)
                        std::cerr << "---" << rf << " : au lieu de :" << rv << " octets ecrits dans le ringbuffer !!" \
                                  << std::endl;
                } else {
                    std::cerr << "-----------Not enough room in audio_mix_ring !!!" << std::endl;
                }
            }
//reads m_ringbuffer and puts it in m_inbuf
//m_inbuf created in SetRingbufferPtr called by add_audio
//4096 * channels * sizeof(float)
            if(rv >= channels * nframes * sizeof(float)) {
                output_available = true;
            }
        }
#if 0
        else if(firsttime == 1)
            fprintf(stderr, "AUDIO BUFFER UNDERRUN: %i samples < %i\n", ringbuffer_read_space(((JackClient*) self)->m_ringbuffer) / sizeof(float) / channels, nframes);
#endif
    }

    j = 0;
    for(std::map<int, JackPort*>::iterator i = m_OutputPortMap.begin();
        i != m_OutputPortMap.end(); i++) {
        if(output_available && j < channels) {
            sample_t *out = (sample_t *) jack_port_get_buffer(i->second->Port, nframes);
            memset(out, 0, sizeof(jack_default_audio_sample_t) * nframes);
            deinterleave(((JackClient*) self)->m_inbuf, out, channels
                         , j, nframes);
//writes nframes of channels m_inbuf to out
//two times if stereo (shifted by the channel number)
#if 0                   // test-noise:
            int i;
            for(i = 0; i < nframes; i++) out[i] = (float) i / (float)nframes;
#endif
        } else { // no output availaible, clear
            sample_t *out = (sample_t *) jack_port_get_buffer(i->second->Port, nframes);
            memset(out, 0, sizeof(sample_t) * nframes);
        }
        j++;
    }

    m_BufferSize = nframes;

//      if(RunCallback&&RunContext)
//      {
//              // do the work
//              RunCallback(RunContext, nframes);
//      }

    return 0;
}