Re: Re: being serious about the NG of zinf
Ed Sweetman <[email protected]>
| Newsgroups | gmane.comp.audio.zinf.devel |
|---|---|
| Message-ID | <[email protected]> |
Sam Varshavchik wrote: > Ed Sweetman writes: > >> Right now I'm opposed to using threads for the main player. >> Threads could possibly be used in the situation where we're streaming >> or playing from the internet. This is because of a couple reasons. We >> could have a large output buffer which may make reading from the >> stream be in longer intervals than ip allows for timeouts, thus losing >> our connection. Also, for streams, we may miss packets during our >> requests for more data. > > > With most desktop environment, X-Windows, or MS-Windows, sometimes > certain operations will lock the entire display, and any process that > requests any kind of a UI-related operation will be blocked. The most > common example would be resizing a desktop window. The entire display > will be locked so that the display manager can scribble over the entire > display with the rubberband outline of the resizing window. > > If your main application thread is multiplexing between pushing audio > out, and updating the display, the audio playback is going to come to a > screeching halt pretty quickly. Not nice. the gui can sit on a thread by itself via gdk_thread >> From a purely theoretical design, I think that audio playback needs a > > minimum of two threads. > > The first thread's only job would be to push audio out. No other I/O. > No dynamic memory allocation from the heap. It's going to be reading > from a reasonably sized memory buffer that the second thread will be > filling, and writing the data out to the audio device. Where possible, > it's going to be set to run as a high priority process. No other > syscalls or I/O interaction except for audio out. You want to minimize > any possibility of something else getting in the way. It's going to be > reading from the memory buffer, and periodically updating an output > counter that indicates how much audio was played so far. > > The second thread would be reading the audio source; be it a file or an > Internet stream, translating it to the native audio format, and > constantly filling the input buffer to the first thread. i'd have to disagree with this two thread model of the pipeline. A serial pipeline is more than adaquate to handle audio output (speed wise) and the maintainance of the two threads introduces a great amount of complexity and overhead compared to not using them. mplayer is serial and it manages to do both audio and video output without threading it's pipeline. > Everything else: all user interface and any other ancillary processing, > can go into the main application thread. When the main application > wants to start playing a file or a thread, the second thread gets > appropriately notified, then it begins reading the audio source and > filling the first thread's input buffer. Then, the main application's > remaining task is to periodically update the display based on the fist > thread's output counter. > > The main application would have a facility to signal the first thread to > pause and resume playback. Fast-Forward and Rewind is implemented by > signaling the first thread to pause, waiting until it indicates that > it's paused, then signaling the second thread to reset an refill the > input buffer from a different position in the audio stream; then > signaling the first thread to resume. First off you're already getting into why threading is to be avoided. Signals. Whenever you talk about threads you need to talk about signals and locking and such. This is part of the reason why the current player has so many problems, it's way too threaded. Serial pipelines do not suffer any of these problems. We simply tell the OS to stop playing by whatever method the api the plugin uses uses, then we clear our output buffer and input buffer. And begin reading again like nothing happened immediately (seeking in either direction) or whenever we want (pausing). If you're running an OS with a crappy schedular and are afraid some other process will eat into your timeslice with disk IO keeping your player from reading data in and thus, keeping the player from updating the soundcard with data in time, perhaps we can handle this by wrapping up the only the read() call in a thread. We dont have to care about locking anything or worrying about the player getting conflicting info by this asyncronous reading. The buffer will be able to handle adding data without affecting reading from it at the same exact time. I think that's perfectly acceptable instead of having a thread running all the time in parallel that we have to remote control. I like the wrapping of the input subsystem's read a lot. Sequential calls to read will be ignored so we dont create a bunch of threads waiting for hdd access, we only want one, and we can work asynchronously perfectly fine. Adding to the input buffer can be done without the reading being effected at all and since that's all the reading via input subsystem effects we're golden. Seeking of course is a non-issue. > The first thread needs to be aware of the particular buffering behavior > of the operating system's audio-out driver. When audio-out is paused, > the first thread needs to also flush the audio-out device, so that the > audio is muted immediately, then calculate its best estimate of how much > audio data was left buffered up, so if its signaled to resume playback > from the same point the playback will pick up exactly where it was > stopped; and all the time its output counters reflect its best estimate > on what's actually coming out of the speakers. One of my biggest > annoyances with some of the last versions of Freeamp is that it was > blissfully unaware of audio buffering by /dev/dsp. Each time you started > playing the track timer immediately jumped from 00:00 to 00:04 seconds, > then began counting off seconds normally, and once it reached the end of > the song it remained stuck on the final second for a little while until > /dev/dsp finished flushing everything out. It was even worse with > ESound. I think the current Zinf's much better in this regard, at least > I haven't noticed anything. Basically what you're annoyed at is the dependency of deciding what time it is by measuring how much data we've sent to the audio device or library output. First off this method is not really helpful if we allow the player to seek, so it probably wont be used as a method of telling what time it is. So then one might say, how do we decide when to update the time and how to handle filling the buffer at the same time. What we could do time the player on a loop that is run in the output plugin that queries the audio buffer waiting for a 2byte decrease from the max with initial time's starting at position given by the UI. That should be sufficient. Keep the comments/suggestions coming. I'm going to resist certain ideas that differ from the ones i started out with so be prepared.... I want to be convinced the ones i'm going to end up going along with are the best ones and i'm already convinced my own are pretty good so i'll be trying to push them and better ones should be able to trump those that aren't. I'm trying to adhere to certain guidelines i feel the next generation of zinf should follow. If you feel your idea is better at doing that than mine or the guidelines are wrong then tell me how before the idea and we can get right to the point. Compromising the integrity of the program is simply not going to be acceptable so if there are features that look like they're going to be simply impossible with the accepted described idea but only a niche group of people would require it then sorry, they're SOL. There is a scope to a program and undoubtedly some things will lay outside of it. eg. 100% accurate seeking and time reporting to name a couple. I'm much more concerned with keeping the code pure than doing things the way they're already done in other players. And another saying to give my programmer centric ways some backbone...It's better to do few things extremely well than a lot of things half assed. ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf