Esempio n. 1
0
bool cRecord::Start(int fd, unsigned short vpid, unsigned short * apids, int numpids) 
{ 
    fprintf(stderr, "%s:%s: fd %d, vpid 0x%02x\n", FILENAME, __FUNCTION__, fd, vpid); 
    
    fprintf(stderr, "apids: "); 
    for (int i = 0; i < numpids; i++)
       fprintf(stderr, "0x%02x ", apids[i]);
    fprintf(stderr, "\n");

    file_fd = fd;

    demuxfd_count = 1 + numpids;

//fixme: currently we only deal which what is called write_ts in earlier versions
//not splitting is possible, because we dont have the filename here...

    for (unsigned int i = 0; i < demuxfd_count; i++)
    {
	    unsigned short pid;

	    if (i == 0)
	       pid = vpid;
	    else
	       pid = apids[i-1];

	    if ((demuxfd[i] = setPesFilter(pid, DMX_OUT_TS_TAP)) < 0)
	    {
		    for (unsigned int j = 0; j < i; j++)
			    unsetPesFilter(demuxfd[j]);

                    fprintf(stderr, "error setting pes filter\n");
		    return false;
	    }
    }

    if ((dvrfd = open(DVRDEV, O_RDONLY|O_NONBLOCK)) < 0)
    {
	    while (demuxfd_count > 0)
		    unsetPesFilter(demuxfd[--demuxfd_count]);

            fprintf(stderr, "error opening dvr device\n");
	    return false;
    }
    
    fprintf(stderr, "dvrfd %d\n", dvrfd);
    
    exit_flag = STREAM2FILE_STATUS_RUNNING;

    if (pthread_create(&demux_thread[0], 0, execute_demux_thread, this) != 0)
    {
	    exit_flag = STREAM2FILE_STATUS_WRITE_OPEN_FAILURE; 
	    fprintf(stderr, "[stream2file]: error creating thread! (out of memory?)\n");
	    return false; 
    }
    
    time(&record_start_time);

    fprintf(stderr, "record start time: %lu \n", record_start_time);
    return true; 
}
Esempio n. 2
0
stream2file_error_msg_t start_recording(const char * const filename,
					const char * const info,
					const bool with_o_sync,
					const bool with_fdatasync,
					const unsigned long long splitsize,
					const unsigned int numpids,
					const unsigned short * const pids,
					const bool write_ts,
					const unsigned int ringbuffers)
{
	int fd;
	char buf[FILENAMEBUFFERSIZE];

	if (busy_count != 0)
	{
		if (exit_flag == STREAM2FILE_STATUS_RUNNING)
			return STREAM2FILE_BUSY;

		/* give threads a second to exit */
		sleep(1);

		puts("[stream2file] recording attempt 2");

		if (busy_count != 0)
			return STREAM2FILE_BUSY;
	}

	INC_BUSY_COUNT;

	strcpy(myfilename, filename);

	// write stream information (should wakeup the disk from standby, too)
	sprintf(buf, "%s.xml", filename);
	if ((fd = open(buf, O_SYNC | O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) >= 0)
	{
		write(fd, info, strlen(info));
		fdatasync(fd);
		close(fd);
	}
	else
	{
		DEC_BUSY_COUNT;
		return STREAM2FILE_INVALID_DIRECTORY;
	}

	if (splitsize < TS_SIZE)
	{
		limit = 1099511627776ULL; // 1024GB, virtually no splitting
	}
	else
		limit = splitsize;

	use_o_sync    = with_o_sync;
	use_fdatasync = with_fdatasync;

	if (ringbuffers < 20)
		ringbuffersize = IN_SIZE * 20;
	else
		ringbuffersize = IN_SIZE * ringbuffers;

	for (unsigned int i = 0; i < numpids; i++)
	{
		if (pids[i] > 0x1fff)
		{
			DEC_BUSY_COUNT;
			return STREAM2FILE_INVALID_PID;
		}
		
		if ((demuxfd[i] = setPesFilter(pids[i], write_ts ? DMX_OUT_TS_TAP : DMX_OUT_TAP)) < 0)
		{
			for (unsigned int j = 0; j < i; j++)
				unsetPesFilter(demuxfd[j]);

			DEC_BUSY_COUNT;
			return STREAM2FILE_PES_FILTER_FAILURE;
		}
	}
	
	demuxfd_count = numpids;

	if (write_ts)
	{
		if ((dvrfd = open(DVRDEV, O_RDONLY)) < 0)
		{
			while (demuxfd_count > 0)
				unsetPesFilter(demuxfd[--demuxfd_count]);

			DEC_BUSY_COUNT;
			return STREAM2FILE_DVR_OPEN_FAILURE;
		}
		exit_flag = STREAM2FILE_STATUS_RUNNING;
		pthread_create(&demux_thread[0], 0, DMXThread, &dvrfd);
	}
	else
	{
		exit_flag = STREAM2FILE_STATUS_RUNNING;
		for (unsigned int i = 0; i < numpids; i++)
		{
			INC_BUSY_COUNT;
			pthread_create(&demux_thread[i], 0, DMXThread, &demuxfd[i]);
		}
		DEC_BUSY_COUNT;
	}

	return STREAM2FILE_OK;
}
Esempio n. 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;
	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);

	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;
	}

	pthread_create(&file_thread, 0, FileThread, &filename_data);

	if (v_arg == &dvrfd)
		while (exit_flag == STREAM2FILE_STATUS_RUNNING)
		{
			if ((pres=poll (&pfd, 1, 15000))>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, &(buf[0]), TS_SIZE);
				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;

	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, 15000))>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;
					}
				}
			}
			else if (!pres){
				printf ("[stream2file]: timeout reading from demux\n");
				goto next;
			}
		}
		next:
			todo = IN_SIZE;
	}

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

	pthread_join(file_thread, NULL);

	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.dir,dirname(myfilename),100);
		eventServer.sendEvent(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, &s, sizeof(s));
		printf("[stream2file] pthreads exit code: %u\n", exit_flag);
	}

	pthread_exit(NULL);
}
Esempio n. 4
0
int
main (int argc, char ** argv) {

	int pid;
	int pids[MAXPIDS];
	char *fname;
	ssize_t written;
	int i;
	pthread_t rcst;
	int fd;

	if (argc < 4 ) {
		dprintf("Usage: streamfile file vpid apid [ pid3 pid4 ... ] (HEX-values without leading 0x!)\n");
		dprintf("file: filename without trailing '.ts'\n");
		return EXIT_FAILURE;
	}

	// set signal handler for clean termination
	signal(SIGTERM, clean_exit);

	buf = (unsigned char *) malloc(IN_SIZE);
	memset(buf, 0x00, IN_SIZE);

	if (buf == NULL) {
		perror("malloc buf");
		return EXIT_FAILURE;
	}

	i = 1;
	while (argv[i][0] == '-') {
		if (!strcmp(argv[i], "-s"))
			silent = 1;
		if (!strcmp(argv[i], "-l"))
			sscanf(argv[++i], "%d", &limit);
		i++;
	}
	if (limit <= 0)
		limit=2;

	fname = argv[i++];
	for (; i < argc; i++) {
		sscanf(argv[i], "%x", &pid);

		if (pid>0x1fff){
			printf ("invalid pid 0x%04x specified\n",pid);
			return EXIT_FAILURE;
		}
		
		pids[demuxfd_count] = pid;

		if ((demuxfd[demuxfd_count] = setPesFilter(pid)) < 0)
			break;

		dprintf("set filter for pid 0x%x\n", pid);

		demuxfd_count++;
	}

	// create and delete temp-file to wakeup the disk from standby
	sprintf(buf, "%s.tmp", fname);
	fd = open(buf, O_SYNC | O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, S_IRUSR | S_IWUSR);
	write(fd, buf, IN_SIZE);
	fdatasync(fd);
	close(fd);
	unlink(buf);

	if ((dvrfd = open(DVRDEV, O_RDONLY)) < 0) {
		free(buf);
		perror ("[streamfile]: open dvr");
		return EXIT_FAILURE;
	}

	ringbuf = ringbuffer_create (RINGBUFFERSIZE);
	pthread_create (&rcst, 0, FileThread, fname);
	
	/* write raw transport stream */
	int offset=0;

	ringbuffer_data_t vec[2];
	ssize_t r=0;
	ssize_t todo;
	ssize_t todo2;

	while (!exit_flag)
	{
		r = read(dvrfd, buf, IN_SIZE);
		if (r > 0)
		{
			offset = sync_byte_offset(buf, r);
			if (offset != -1)
				break;
		}
	}

	written = ringbuffer_write(ringbuf, buf + offset, r - offset);
	// TODO: Retry
	if (written != r - offset) {
		dprintf("PANIC: wrote less than requested to ringbuffer, written %d, requested %d\n", written, r - offset);
		exit_flag = 1;
	}
	todo = IN_SIZE - (r - offset);

	if (todo == 0)
		todo = IN_SIZE;

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

		while (!exit_flag)
		{
			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;
				}
			}
		}
	next:
		todo = IN_SIZE;
	}
	//sleep(1); // give FileThread some time to write remaining content of ringbuffer to file
	//	pthread_kill(rcst, SIGKILL);

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

	close(dvrfd);

	pthread_join(rcst,NULL);
	
	free(buf);

	ringbuffer_free(ringbuf);

	dprintf("End of main(). All filters are unset now.\n");
	return EXIT_SUCCESS;
}
Esempio n. 5
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);
}
Esempio n. 6
0
stream2file_error_msg_t start_recording(const char * const filename,
					const char * const info,
					int mode,
					const bool with_o_sync,
					const bool with_fdatasync,
					const unsigned long long splitsize,
					const unsigned int numpids,
					const unsigned short * const pids,
					const bool write_ts,
					const unsigned int ringbuffers,
					const bool with_gen_psi )
{
	int fd;
	char buf[FILENAMEBUFFERSIZE];

	if (busy_count != 0)
	{
		if (exit_flag == STREAM2FILE_STATUS_RUNNING)
			return STREAM2FILE_BUSY;

		/* give threads a second to exit */
		sleep(1);

		puts("[stream2file]: recording attempt 2");

		if (busy_count != 0)
			return STREAM2FILE_BUSY;
	}

	INC_BUSY_COUNT;
	strcpy(myfilename, filename);
	mymode = mode;

	// printf("start_recording: myfilename '%s' filename '%s'\n",myfilename,filename);
	// write stream information (should wakeup the disk from standby, too)
	sprintf(buf, "%s.xml", filename);
	if ((fd = open(buf, O_SYNC|O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, REC_FILE_PERMISSIONS)) >= 0)
	{
		write(fd, info, strlen(info));
		fdatasync(fd);
		close(fd);
	}
	else
	{
		if (errno == EEXIST)
			printf("[stream2file] INFO: %s already exists, not overwriting\n", buf);
		else
		{
			fprintf(stderr, "[stream2file] trying to create %s, error %d (%m)\n", buf, errno);
			DEC_BUSY_COUNT;
			return STREAM2FILE_INVALID_DIRECTORY;
		}
	}

	if (splitsize < TS_SIZE)
	{
		limit = 1099511627776ULL; // 1024GB, virtually no splitting
	}
	else
		limit = splitsize;

	use_o_sync    = with_o_sync;
	use_fdatasync = with_fdatasync;
	gen_psi       = with_gen_psi;

	if (ringbuffers > 4)
		ringbuffersize = ((1 << 19) << 4);
	else
		ringbuffersize = ((1 << 19) << ringbuffers);
	printf("[stream2file]: ringbuffersize %d write_ts %d numpids %d\n", ringbuffersize, write_ts, numpids);

	for (unsigned int i = 0; i < numpids; i++)
	{
		if (pids[i] > 0x1fff)
		{
			DEC_BUSY_COUNT;
			return STREAM2FILE_INVALID_PID;
		}
#ifndef HAVE_TRIPLEDRAGON
		demuxfd[i] = setPesFilter(pids[i], write_ts ? DMX_OUT_TS_TAP : DMX_OUT_TAP);
#else
		demuxfd[i] = setPesFilter(pids[i], OUT_MEMORY);
#endif
		if (demuxfd[i] < 0)
		{
			for (unsigned int j = 0; j < i; j++)
				unsetPesFilter(demuxfd[j]);

			DEC_BUSY_COUNT;
			return STREAM2FILE_PES_FILTER_FAILURE;
		}
	}
	
	demuxfd_count = numpids;

	if (write_ts)
	{
#ifdef HAVE_TRIPLEDRAGON
		if ((dvrfd = open(DMXDEV, O_RDWR|O_NONBLOCK)) != -1)
		{
			ioctl(dvrfd, DEMUX_SELECT_SOURCE, INPUT_FROM_CHANNEL0);
			ioctl(dvrfd, DEMUX_SET_BUFFER_SIZE, 230400);
			struct demux_bucket_para dbp;
			dbp.unloader.unloader_type = UNLOADER_TYPE_TRANSPORT;
			dbp.unloader.threshold     = 128; // one interrupt per 32kB
			if (ioctl(dvrfd, DEMUX_FILTER_BUCKET_SET, &dbp) < 0)
				perror("start_recording DEMUX_FILTER_BUCKET_SET");
		}
		else
#else
		if ((dvrfd = open(DVRDEV, O_RDONLY|O_NONBLOCK)) < 0)
#endif
		{
			while (demuxfd_count > 0)
				unsetPesFilter(demuxfd[--demuxfd_count]);

			DEC_BUSY_COUNT;
			return STREAM2FILE_DVR_OPEN_FAILURE;
		}
		exit_flag = STREAM2FILE_STATUS_RUNNING;

		if (pthread_create(&demux_thread[0], 0, DMXThread, &dvrfd) != 0)
		{
			DEC_BUSY_COUNT;
			exit_flag = STREAM2FILE_STATUS_RECORDING_THREADS_FAILED; 
			puts("[stream2file]: error creating thread! (out of memory?)");
			while (demuxfd_count > 0)
				unsetPesFilter(demuxfd[--demuxfd_count]);
			close(dvrfd);
			return STREAM2FILE_RECORDING_THREADS_FAILED; 
		}
#ifdef HAVE_TRIPLEDRAGON
		if (ioctl(dvrfd, DEMUX_START) < 0)
			perror("start_recording DEMUX_START");
#endif
	}
	else
	{
		exit_flag = STREAM2FILE_STATUS_RUNNING;
		for (unsigned int i = 0; i < numpids; i++)
		{
			if (pthread_create(&demux_thread[i], 0, DMXThread, &demuxfd[i]) == 0)
				INC_BUSY_COUNT;
			else
			{
				DEC_BUSY_COUNT;
				exit_flag = STREAM2FILE_STATUS_RECORDING_THREADS_FAILED; 
				puts("[stream2file]: error creating thread! (out of memory?)");
				return STREAM2FILE_RECORDING_THREADS_FAILED; 
			}
		}
		DEC_BUSY_COUNT;
	}

	/* this is set to 0 on program start and during stop_recording().
	   done this way, because stop_recording() is only called on a regular
	   stopped recording. */
	if (record_start_time == 0)
		time(&record_start_time);
	return STREAM2FILE_OK;
}