Code: Alles auswählen
Index: streamts.c
===================================================================
RCS file: /cvs/tuxbox/apps/dvb/tools/stream/streamts.c,v
retrieving revision 1.19
diff -U3 -r1.19 streamts.c
--- a/streamts.c 21 Jan 2006 22:23:51 -0000 1.19
+++ b/streamts.c 7 Apr 2007 10:35:08 -0000
@@ -49,6 +49,12 @@
#include <unistd.h>
#include <config.h>
#include <ctype.h>
+#include <pthread.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
#if HAVE_DVB_API_VERSION < 3
#include <ost/dmx.h>
@@ -77,7 +83,8 @@
#endif
/* conversion buffer sizes */
-#define IN_SIZE (TS_SIZE * 362)
+#define TS_COUNT (362 * 16)
+#define IN_SIZE (TS_SIZE * TS_COUNT)
#define IPACKS 2048
/* demux buffer size */
@@ -89,15 +96,19 @@
/* tcp packet data size */
#define PACKET_SIZE 1448
+
unsigned char * buf;
int dvrfd;
int demuxfd[MAXPIDS];
unsigned char demuxfd_count = 0;
-unsigned char exit_flag = 0;
+volatile unsigned char exit_flag = 0;
unsigned int writebuf_size = 0;
unsigned char writebuf[PACKET_SIZE];
+volatile unsigned int read_position = 0;
+volatile unsigned int write_position = 0;
+
static int
sync_byte_offset (const unsigned char * buf, const unsigned int len) {
@@ -214,6 +225,60 @@
}
+void* thread_stream_out( void* vbuffer )
+{
+ // char* buf = (char*)vbuffer;
+ unsigned int start;
+ unsigned int stop;
+ unsigned int todo;
+ unsigned int tmp;
+ ssize_t written;
+ fd_set fs;
+ struct timeval tv;
+
+ while( !exit_flag )
+ {
+ todo = read_position - write_position;
+ if( todo > 0 ) {
+ start = write_position % TS_COUNT;
+ stop = ( start + todo ) % TS_COUNT;
+ if( start > stop )
+ {
+ tmp = TS_COUNT - start;
+ if( tmp > 0 )
+ {
+ written = write(STDOUT_FILENO, &buf[ start * TS_SIZE ], tmp*TS_SIZE );
+ if( written == -1 )
+ {
+ exit_flag = 1;
+ }
+ }
+ start = 0;
+ }
+ tmp = stop - start;
+ if( tmp > 0 )
+ {
+ written = write(STDOUT_FILENO, &buf[ start * TS_SIZE ], tmp*TS_SIZE );
+ if( written == -1 )
+ {
+ exit_flag = 1;
+ }
+ }
+ write_position += todo;
+ }
+ else {
+ /* wait til data is available for reading */
+ FD_ZERO(&fs);
+ FD_SET( dvrfd, &fs );
+ tv.tv_sec = 0;
+ tv.tv_usec = 10;
+ select( 2 , &fs , NULL, NULL, &tv );
+ }
+ }
+ return NULL;
+}
+
+
#ifdef TRANSFORM
static int
dvr_to_ps (const int dvr_fd, const unsigned short audio_pid, const unsigned short video_pid, const unsigned char ps) {
@@ -349,6 +414,14 @@
}
+/*
+ * Thread to read dmux
+ */
+
+
+
+
+
int
main (int argc, char ** argv) {
@@ -356,10 +429,11 @@
int pids[MAXPIDS];
unsigned char *bp;
unsigned char mode;
- unsigned char tsfile[IN_SIZE];
+ unsigned char tsfile[1024]; /* Should be MAX_PATH */
int tsfilelen = 0;
int fileslice = 0;
int i = 0;
+ pthread_t write_thread;
if (argc != 2)
return EXIT_FAILURE;
@@ -467,8 +541,15 @@
/* write raw transport stream to stdout */
else
#endif
+ if ( mode == 2 )
+ {
+ pthread_create( &write_thread, NULL, thread_stream_out, (void*)buf );
+ }
+
+
if (mode == 2 || mode == 3) {
int offset;
+ int i;
ssize_t pos;
ssize_t r = 0;
@@ -478,8 +559,19 @@
pos = 0;
todo = IN_SIZE;
- while (todo)
+ if (mode == 2)
+ {
+ /* read from demux */
+ /* read 7 TS blocks at a time, and let the output writing thread catch up */
+ for( i = 0 ; i < TS_COUNT ; i+= 16 )
+ {
+ read(dvrfd, &buf[i*TS_SIZE], TS_SIZE*16);
+ read_position += 16;
+ }
+ }
+ else while (todo)
{
+
r = read(dvrfd, buf + pos, todo);
if (r > 0) {
pos += r;
@@ -487,33 +579,31 @@
}
else
{
- if (mode == 3)
+ if (r == -1)
+ {
+ free(buf);
+ return EXIT_FAILURE;
+ }
+ else
{
- if (r == -1)
- {
+ close(dvrfd);
+ sprintf(&tsfile[tsfilelen], ".%03d", ++fileslice);
+ if ((dvrfd = open(tsfile, O_RDONLY)) < 0) {
free(buf);
- return EXIT_FAILURE;
- }
- else
- {
- close(dvrfd);
- sprintf(&tsfile[tsfilelen], ".%03d", ++fileslice);
- if ((dvrfd = open(tsfile, O_RDONLY)) < 0) {
- free(buf);
- return EXIT_SUCCESS;
- }
+ return EXIT_SUCCESS;
}
}
}
+ packet_stdout(buf, IN_SIZE , NULL);
}
/* make sure to start with a ts header */
- offset = sync_byte_offset(buf, TS_SIZE);
+ // offset = sync_byte_offset(buf, TS_SIZE);
+
+ //if (offset == -1)
+ // continue;
+ // packet_stdout(buf + offset, r - offset, NULL);
- if (offset == -1)
- continue;
-
- packet_stdout(buf + offset, r - offset, NULL);
}
}
This makes streamts rock solid on DM500
BUT:
This version probably uses a bit to much memory for the circular buffer ( 5% of total DM500 memory ) so it should be tweaked lower,
When I started making this fix, it was on the assumtion that the DM500 network was slow, and the writing to network stalled the dmux reading. Thats wy I now write to the network in a seperate thread. But that assumption about the network beeing slow, might not be the case after all.
After playing with this I think that I can see an underlying problem with the DM500 demux, which I will nned to look into further. Here are som symptoms:
1) ngrab fails to records when bullz text s running
2) Streamts had problems subscribing to streams after channel change
3) Enigma recording over nfs is choppy
4) The fixed version of streamts is overwhelmed by HD streams. The old version would max out CPU load to 100%, the new version uses much less CPU, but still can't keep up with a full HD stream
Symptom 3,4 seems to indicate that there is a serious problem with write buffering from the dmux, besides the stream selection problem that still is a problem in stremts (1,2?). I will have to get into the kernel driver sources in order to learn more
Some more fiddling seems to indicate that setting the DMX_IMMEDIATE_START flag in setPesFilter() almost eliminates problem (2)