[xiph-cvs] cvs commit: vorbis-tools/ogg123 buffer.c buffer.h ogg123.c ogg123.h
Kenneth C. Arnold
kcarnold at xiph.org
Thu Jun 21 20:55:38 PDT 2001
kcarnold 01/06/21 20:55:37
Modified: ogg123 Tag: kcarnold_work buffer.c buffer.h ogg123.c
ogg123.h
Log:
My late night hacking. Two major things:
1. Buffer fill indication.
2. Overhaul to buffer semantics, including buffer flushing
capabilities and a few significant optimizations that should decrease
CPU usage noticably.
Revision Changes Path
No revision
No revision
1.7.2.1 +67 -10 vorbis-tools/ogg123/buffer.c
Index: buffer.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/buffer.c,v
retrieving revision 1.7
retrieving revision 1.7.2.1
diff -u -r1.7 -r1.7.2.1
--- buffer.c 2001/06/19 19:42:35 1.7
+++ buffer.c 2001/06/22 03:55:36 1.7.2.1
@@ -5,6 +5,8 @@
* that program is used in this buffer.
*/
+#define DEBUG_BUFFER
+
#include <sys/types.h>
#if HAVE_SMMAP
#include <sys/mman.h>
@@ -20,12 +22,28 @@
#include "ogg123.h"
#include "buffer.h"
+#ifdef DEBUG_BUFFER
+FILE *debugfile;
+#define DEBUG0(x) do { fprintf (debugfile, x "\n" ); } while (0)
+#define DEBUG1(x, y) do { fprintf (debugfile, x "\n" , y); } while (0)
+#else
+#define DEBUG0(x)
+#define DEBUG1(x, y)
+#endif
+
+void signal_handler (int sig)
+{
+}
+
/* Initialize the buffer structure. */
void buffer_init (buf_t *buf, long size)
{
+ DEBUG0("buffer init");
+ memset (buf, 0, sizeof(*buf));
buf->status = 0;
buf->reader = buf->writer = buf->buffer;
buf->end = buf->buffer + (size - 1);
+ buf->size = size;
}
/* Main write loop. No semaphores. No deadlock. No problem. I hope. */
@@ -34,24 +52,40 @@
devices_t *d1;
signal (SIGINT, SIG_IGN);
+ DEBUG0("r: writer_main");
while (! (buf->status & STAT_SHUTDOWN && buf->reader == buf->writer))
{
/* Writer just waits on reader to be done with buf_write.
* Reader must ensure that we don't deadlock. */
- write (buf->fds[1], "1", 1); /* This identifier could hold a lot
- * more detail in the future. */
+ if (buf->reader == buf->writer) {
+ /* this won't deadlock, right...? */
+ DEBUG0("alerting writer");
+ write (buf->fds[1], "1", sizeof(int)); /* This identifier could hold a lot
+ * more detail in the future. */
+ }
if (buf->status & STAT_FLUSH) {
+ flush:
+ DEBUG0("r: buffer flush");
buf->reader = buf->writer;
buf->status &= ~STAT_FLUSH;
+ DEBUG1("buf->status = %d", buf->status);
+ write (buf->fds[1], "F", sizeof(int));
}
+
+ while (buf->reader == buf->writer && !(buf->status & STAT_SHUTDOWN)
+ && !(buf->status & STAT_FLUSH))
+ DEBUG1("looping on buffer underflow, status is %d", buf->status);
- while (buf->reader == buf->writer && !(buf->status & STAT_SHUTDOWN));
+ if (buf->status & STAT_FLUSH)
+ goto flush; /* eeew... */
- if (buf->reader == buf->writer) break;
+ if (buf->reader == buf->writer)
+ break;
/* devices_write (buf->writer->data, buf->writer->len, d); */
+ DEBUG0("writing chunk");
{
d1 = d;
while (d1 != NULL) {
@@ -60,13 +94,17 @@
}
}
+ DEBUG0("incrementing pointer");
if (buf->writer == buf->end)
buf->writer = buf->buffer;
else
buf->writer++;
}
+ DEBUG0("r: shutting down buffer");
buf->status = 0;
- write (buf->fds[1], "2", 1);
+ write (buf->fds[1], "2", sizeof(int));
+ kill (buf->writerpid, SIGHUP);
+ DEBUG0("r: exiting");
_exit(0);
}
@@ -120,6 +158,11 @@
shmctl(shmid, IPC_RMID, 0);
#endif /* HAVE_SMMAP */
+#ifdef DEBUG_BUFFER
+ debugfile = fopen ("/tmp/bufferdebug", "w"); /* file can be a pipe */
+ setvbuf (debugfile, NULL, _IONBF, 0);
+#endif
+
buffer_init (buf, size);
/* Create a pipe for communication between the two processes. Unlike
@@ -132,12 +175,14 @@
exit (1);
}
- fcntl (buf->fds[1], F_SETFL, O_NONBLOCK);
/* write should never block; read should always block. */
+ fcntl (buf->fds[1], F_SETFL, O_NONBLOCK);
fflush (stdout);
/* buffer flushes stderr, but stderr is unbuffered (*duh*!) */
-
+
+ signal (SIGHUP, signal_handler);
+
childpid = fork();
if (childpid == -1)
@@ -151,8 +196,11 @@
writer_main (buf, d);
return NULL;
}
- else
+ else {
+ buf->writerpid = getpid();
+ buf->readerpid = childpid;
return buf;
+ }
}
void submit_chunk (buf_t *buf, chunk_t chunk)
@@ -163,6 +211,7 @@
FD_ZERO(&set);
FD_SET(buf->fds[0], &set);
+ DEBUG0("submit_chunk");
/* Wait wait, don't step on my sample! */
while (!((buf->reader != buf->end && buf->reader + 1 != buf->writer) ||
(buf->reader == buf->end && buf->writer != buf->buffer)))
@@ -171,24 +220,29 @@
int ret;
char t;
+ DEBUG0("w: looping on buffer overflow");
tv.tv_sec = 1;
tv.tv_usec = 0;
ret = select (buf->fds[0]+1, &set, NULL, NULL, &tv);
- while (ret-- > 0)
- read (buf->fds[0], &t, 1);
+ DEBUG1("w: select returned %d", ret);
+ if (ret > 0)
+ read (buf->fds[0], &t, sizeof(int));
}
+ DEBUG0("writing chunk");
*(buf->reader) = chunk;
/* do this atomically */
if (buf->reader == buf->end)
buf->reader = buf->buffer;
else
buf->reader++;
+ DEBUG0("submit_chunk exit");
}
void buffer_flush (buf_t *buf)
{
+ DEBUG0("flush buffer");
buf->status |= STAT_FLUSH;
}
@@ -196,9 +250,11 @@
{
struct timeval tv;
+ DEBUG0("shutdown buffer");
buf->status |= STAT_SHUTDOWN;
while (buf->status != 0)
{
+ DEBUG0("waiting on reader to quit");
tv.tv_sec = 1;
tv.tv_usec = 0;
select (0, NULL, NULL, NULL, &tv);
@@ -207,4 +263,5 @@
/* Deallocate the shared memory segment. */
shmdt(buf);
#endif /* HAVE_SMMAP */
+ DEBUG0("buffer done.");
}
1.2.2.1 +5 -0 vorbis-tools/ogg123/buffer.h
Index: buffer.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/buffer.h,v
retrieving revision 1.2
retrieving revision 1.2.2.1
diff -u -r1.2 -r1.2.2.1
--- buffer.h 2001/06/19 19:42:35 1.2
+++ buffer.h 2001/06/22 03:55:36 1.2.2.1
@@ -5,6 +5,8 @@
#include "ogg123.h"
+#include <sys/types.h>
+
typedef struct chunk_s
{
long len; /* Length of the chunk (for if we only got partial data) */
@@ -15,6 +17,9 @@
{
char status; /* Status. See STAT_* below. */
int fds[2]; /* Pipe file descriptors. */
+ long size; /* buffer size, for reference */
+ pid_t readerpid; /* PID of reader process */
+ pid_t writerpid; /* PID of writer process */
chunk_t *reader; /* Chunk the reader is busy with */
chunk_t *writer; /* Chunk the writer is busy with */
chunk_t *end; /* Last chunk in the buffer (for convenience) */
1.39.2.1 +56 -13 vorbis-tools/ogg123/ogg123.c
Index: ogg123.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123.c,v
retrieving revision 1.39
retrieving revision 1.39.2.1
diff -u -r1.39 -r1.39.2.1
--- ogg123.c 2001/06/19 19:42:35 1.39
+++ ogg123.c 2001/06/22 03:55:36 1.39.2.1
@@ -14,7 +14,7 @@
* *
********************************************************************
- last mod: $Id: ogg123.c,v 1.39 2001/06/19 19:42:35 kcarnold Exp $
+ last mod: $Id: ogg123.c,v 1.39.2.1 2001/06/22 03:55:36 kcarnold Exp $
********************************************************************/
@@ -122,6 +122,8 @@
opt.buffer_size = 0;
opt.delay = 1;
+ atexit (buffer_cleanup);
+ signal (SIGINT, signal_quit);
ao_initialize();
while (-1 != (ret = getopt_long(argc, argv, "b:d:hl:k:o:qvVz",
@@ -226,8 +228,10 @@
opt.outdevices = current;
}
- if (buffer != NULL)
+ if (buffer != NULL) {
buffer_shutdown(buffer);
+ buffer = NULL;
+ }
ao_shutdown();
@@ -263,7 +267,13 @@
old_sig = signal(SIGINT,signal_skipfile);
}
+void signal_quit(int ignored)
+{
+ exit(0);
+}
+
+
void play_file(ogg123_options_t opt)
{
/* Oh my gosh this is disgusting. Big cleanups here will include an
@@ -387,7 +397,7 @@
exit(1);
if (opt.quiet < 1) {
- if (eos && opt.verbose) fprintf (stderr, "\r \r\n");
+ if (eos && opt.verbose) fprintf (stderr, "\r \r\n");
for (i = 0; i < vc->comments; i++) {
char *cc = vc->user_comments[i]; /* current comment */
int i;
@@ -478,29 +488,43 @@
c_sec = u_pos - 60 * c_min;
r_min = (long) (u_time - u_pos) / (long) 60;
r_sec = (u_time - u_pos) - 60 * r_min;
- fprintf(stderr,
- "\rTime: %02li:%05.2f [%02li:%05.2f] of %02li:%05.2f, Bitrate: %.1f \r",
- c_min, c_sec, r_min, r_sec, t_min, t_sec,
- (float) ov_bitrate_instant(&vf) / 1000.0F);
+ if (buffer)
+ fprintf(stderr,
+ "\rTime: %02li:%05.2f [%02li:%05.2f] of %02li:%05.2f, Bitrate: %.1f, Buffer fill: %3.0f%% \r",
+ c_min, c_sec, r_min, r_sec, t_min, t_sec,
+ (double) ov_bitrate_instant(&vf) / 1000.0F,
+ buffer_full(buffer)*100.0F);
+ else
+ fprintf(stderr,
+ "\rTime: %02li:%05.2f [%02li:%05.2f] of %02li:%05.2f, Bitrate: %.1f \r",
+ c_min, c_sec, r_min, r_sec, t_min, t_sec,
+ (double) ov_bitrate_instant(&vf) / 1000.0F);
} else {
/* working around a bug in vorbisfile */
u_pos = (double) ov_pcm_tell(&vf) / (double) vi->rate;
c_min = (long) u_pos / (long) 60;
c_sec = u_pos - 60 * c_min;
- fprintf(stderr,
- "\rTime: %02li:%05.2f, Bitrate: %.1f \r",
- c_min, c_sec,
- (float) ov_bitrate_instant (&vf) / 1000.0F);
+ if (buffer)
+ fprintf(stderr,
+ "\rTime: %02li:%05.2f, Bitrate: %.1f, Buffer fill: %3.0f%% \r",
+ c_min, c_sec,
+ (float) ov_bitrate_instant (&vf) / 1000.0F,
+ buffer_full(buffer)*100.0F);
+ else
+ fprintf(stderr,
+ "\rTime: %02li:%05.2f, Bitrate: %.1f \r",
+ c_min, c_sec,
+ (float) ov_bitrate_instant (&vf) / 1000.0F);
}
}
}
}
}
-
+
alarm(0);
signal(SIGALRM,SIG_DFL);
signal(SIGINT,old_sig);
-
+
ov_clear(&vf);
if (opt.quiet < 1)
@@ -587,4 +611,23 @@
*buffer = fork_writer (opt->buffer_size, opt->outdevices);
return 0;
+}
+
+double buffer_full (buf_t* buf) {
+ chunk_t *reader = buf->reader; /* thread safety... */
+ int chunks;
+
+ if (reader > buf->writer)
+ chunks = (reader - buf->writer);
+ else
+ chunks = (buf->end - reader) + (buf->writer - buf->buffer);
+ return (double) chunks / buf->size;
+}
+
+void buffer_cleanup (void) {
+ if (buffer) {
+ buffer_flush (buffer);
+ buffer_shutdown (buffer);
+ buffer = NULL;
+ }
}
1.7.2.1 +4 -0 vorbis-tools/ogg123/ogg123.h
Index: ogg123.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123.h,v
retrieving revision 1.7
retrieving revision 1.7.2.1
diff -u -r1.7 -r1.7.2.1
--- ogg123.h 2001/06/19 17:15:32 1.7
+++ ogg123.h 2001/06/22 03:55:36 1.7.2.1
@@ -28,6 +28,7 @@
signed short int quiet; /* Be quiet (no title) */
double seekpos; /* Amount to seek by */
FILE *instream; /* Stream to read from. */
+ char *default_device; /* default device for playback */
devices_t *outdevices; /* Streams to write to. */
int buffer_size; /* Size of the buffer in chunks. */
int rate, channels; /* playback params for opening audio devices */
@@ -47,5 +48,8 @@
int get_tcp_socket(void); /* Will be going soon. */
FILE *http_open(char *server, int port, char *path); /* ditto */
int open_audio_devices(ogg123_options_t *opt, int rate, int channels, buf_t ** buffer);
+double buffer_full (buf_t* buffer);
+void buffer_cleanup (void);
+void signal_quit (int ignored);
#endif /* !defined(__OGG123_H) */
--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list