From: Reinhard N. <rn...@gm...> - 2004-12-17 22:54:54
|
Hi, Michael Roitzsch wrote: >>I'd like to make some changes to input_vdr to omit using XINE_INTERNAL >>structures respectively structure elements. >> >>A major issue is accessing "port_ticket": >> >>this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, >>0); >> >>Is it necessary to acquire it before accessing the following functions: >> >>this->stream->video_out->get_overlay_manager(this->stream->video_out); >>this->stream->video_fifo->size(this->stream->video_fifo); >>this->stream->audio_fifo->size(this->stream->audio_fifo); >>this->stream->video_out->get_property(this->stream->video_out, >>VO_PROP_BUFS_IN_FIFO); >>this->stream->audio_out->get_property(this->stream->audio_out, >>AO_PROP_BUFS_IN_FIFO); > > You can access video_fifo and audio_fifo without the ticket. Only the *_out > pointer must not be dereferenced without the ticket. So I'll need it :-( >>Shall I rewrite it to _x_aquire_port_ticket(this->stream->xine, 0)? > > That would give anyone full access. The whole idea here is to limit the things > input and demuxer plugins are allowed to do in order to enforce a better > separation of the xine components. I would prefer an approach on a higher > level. Could you explain, what you actually want to do with the ticket? I'll show a little code fragment for each of these functions. Let's start with get_overlay_manager(): { video_overlay_manager_t *ovl; int redraw_needed = 1; while (redraw_needed) { this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 0); ovl = this->stream->video_out->get_overlay_manager(this->stream->video_out); redraw_needed = ovl->redraw_needed(ovl, 0); this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 0); // fprintf(stderr, "redraw_needed: %d\n", redraw_needed); usleep(1); } } This piece of code is used to wait until any pending OSD operations are processed. You may remember an email of mine where I wrote that hideing an OSD and grabbing an image immediately afterwards still gives returns an image which shows the OSD. With the above piece of code between hideing and grabbing the resulting image is fine. The next snipplet deals with get_property(): this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 0); while (1) { if (this->stream->video_fifo) vb = this->stream->video_fifo->size(this->stream->video_fifo); if (this->stream->audio_fifo) ab = this->stream->audio_fifo->size(this->stream->audio_fifo); if (this->stream->video_out) vf = this->stream->video_out->get_property(this->stream->video_out, VO_PROP_BUFS_IN_FIFO); if (this->stream->audio_out) af = this->stream->audio_out->get_property(this->stream->audio_out, AO_PROP_BUFS_IN_FIFO); if (vb <= 0 && ab <= 0 && vf <= 0 && af <= 0) break; if (data->msTimeout >= 0 && timercmp(&now, &then, >)) { timedOut++; break; } this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 0); usleep(100); this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 0); if (data->msTimeout >= 0) gettimeofday(&now, 0); } this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 0); I use this piece of code to wait a certain time for xine's input and output stages to drain (you may remember my emails about adding VO_PROP_BUFS_IN_FIFO and AO_PROP_BUFS_IN_FIFO). When the above loop returns, xine has either processed and shown on screen any PES packets sent from VDR so far or waiting has timed out. I use this code to synchronize VDR on xine. As xine has much larger buffers than a DVB device VDR cannot assume that after having sent the last byte to xine, xine is in the appropriate state e. g. to grab an image because it might still take several seconds until xine reaches this state. Therefore I've modified VDR to "flush" the device e. g. before grabing an image. BTW: I called it flush as it behaves like the well known fflush() but I know that a similarly named function in xine drops any unprocessed data. Flush's counterpart in xine then uses the above code to wait for the "flush" (= drain) to happen. >>Another issue is access to "first_frame_flag": >> >>this->stream->first_frame_flag = 2; >> >>This could be turned into _x_set_first_frame_flag(this->stream, 2). >> >>The last issue is "status": >> >>this->stream->status != XINE_STATUS_STOP >>this->stream->status != XINE_STATUS_QUIT >> >>This one could also be turned into a _x_get_stream_status() function. > > Again: I would like to know first, what you need these for. Let's first address the later two: if( (len-total) > 0 ) { int retries = 0; do { n = _x_read_abort (this->stream, this->fh, &buf[total], len-total); if (0 == n) lprintf("vdr: read 0, retries: %d\n", retries); } while (0 == n && this->stream->status != XINE_STATUS_STOP && this->stream->status != XINE_STATUS_QUIT && 200 > retries++); // 200 * 50ms if (n < 0) { _x_message(this->stream, XINE_MSG_READ_ERROR, NULL); return 0; } this->curpos += n; total += n; } return total; This code is part of vdr_plugin_read(). It tries to reread data for a certain time when the read didn't deliver any data. This was necessary as some time ago _x_read_abort() was changed to return with the number of bytes read so far when stream->demux_action_pending was true. But as this variable is used e. g. in __play_internal(), it was likely that vdr_plugin_read() returned 0 for example during attaching to VDR. And although VDR would have been able to send further data soon, this stopped demux_mpeg_pes as it couldn't read the number of bytes requested. The drawback of this loop was that xine was blocked for about 10 seconds e. g. when it disconnected from VDR while it was not sending any data. That's why I have added the status tests lately. And finally first_frame_flag: looking into __play_internal() and the video_out loop I've seen that this variable is used to skip dropping frames when a new stream starts replay. And as I noticed that starting replay was much smoother when xine connected to VDR than when a channel switch in VDR occurred, I decided to set this variable myself at that time. The result was a much smoother start of replay while switching channels in VDR, too. But as there are still some frame drops I assume there is a better solution than setting "first_frame_flag". But it's complicated to describe the interaction of VDR, vdr-xine and xine-lib/-ui. It would be helpful if you could setup a little VDR configuration and give vdr-xine a try. Looking at the output, you then could point me into the right direction for a different and better approach. Thanks a lot for your assistance. BTW: In the case you are already interested in VDR / vdr-xine Latest stable VDR: ftp://ftp.cadsoft.de/vdr/vdr-1.2.6.tar.bz2 Latest stable development VDR: ftp://ftp.cadsoft.de/vdr/Developer/vdr-1.3.16.tar.bz2 Latest vdr-xine: http://home.vr-web.de/~rnissl/vdr-xine-0.6.1.tgz Bye. -- Dipl.-Inform. (FH) Reinhard Nissl mailto:rn...@gm... |