Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[vdr] Re: VDR developer version 1.1.6



Hi,

On Monday 05 August 2002 16:53, Klaus Schmidinger wrote:
> Andreas Schultz wrote:
> > ...
> >
> > > Actually PlayAudio() is intended for playing _additional_ audio data,
> > > like Dolby Digital. Since I was urged to first implement the cDevice
> > > plugin interface I had to postpone implementing PlayAudio().
> > > PlayVideo() is used for playing the "normal" A/V data. maybe I should
> > > rename PlayVideo() to something like PlayAV(), and PlayAudio() to
> > > PlayDolby()?
> >
> > That opens a whole new can of worms. Lets talk about that in a different
> > thread.
>
> What do you mean: the renaming or the definition? Apparently "normal" video
> and audio (as, e.g., recorded by VDR from a channel without Dolby Digital)
> closely belongs together and should be sent through a common channel (as is
> the case with the DVB driver). If a device needs to separate the audio and
> video data, it can do so. Dolby Digital on the other hand, as far as I can
> see, goes quite different ways. It may have to be piped into an external
> program, or sent to an SPDIF interface or whatever. Therefore I'd assume
> that having a channel where the player stuffs in the Dolby data, and which,
> on the other end, has a plugin-provided cAudio class that knows where to
> actually send the DD data should be a feasible way to do this. Or am I
> missing something important here?

YESSSSS (but you might not like it)!
I also want to send non-DD audio from recordings and live non-DD audio to some 
external destination. Basicly the cAudio plugin should _always_ and in all 
operation modes (even in live TV mode) receive the best quality audio 
available, if that happens to be only MPEG2 audio, than be it.

>
> > ...
> >
> > > > 2. Two fd' needs to be checked by the player
> > > > 3. PlayVideo does not gurantee that all data is beeing written to the
> > > > card and the buffer and timeout handling is done in the player class.
> > > > For the DXR3 that does not hold true. Buffering and _processing_
> > > > needs to be done in the device class. Therefore the buffer mechanism
> > > > in the player class can not longer work as intended.
> > >
> > > A call to PlayVideo() doesn't have to guarantee that all data is
> > > actually written. A device's PlayVideo() is free to consume as many
> > > bytes of the offered data as it can "swallow". It's even ok if it
> > > decides not to consume any data at this call. I don't see where the
> > > buffer mechanism in the player wouldn't work for such a device - but
> > > maybe I'm missing something important here.
> >
> > No you didn't, my explanation wasn't good enough. The buffering will of
> > course work and it is actualy not a real problem.
> >
> > The dxr3 has two properties that do not fit well with the current cDevice
> > interface. Both could IMHO be accomodated with some tweaks to the API.
> > The alternative with the current API would be to introduce additional
> > (non trivial) buffering in the device object, which in the spirit of
> > "keep it simple" i would really like to avoid!!
> >
> > On the video side, the card can only play a pure MPEG stream. All PS
> > and/or PES headers need to be stripped away. The easiest way to do that,
> > is when the device is always being feed with complete PS/PES packets and
> > when it can process those packets at its own pace. Otherwise a more
> > complicated reassembling of the incoming packets has to happen (which
> > means more buffers and more overhead).
> > VDR's current structure already guarantees that the first call to
> > PlayVideo() for a newly read packet will contain a complete PS/PES
> > packet. Subsequent calls for the same packet can be avoided by processing
> > the complete packet at once. However, we might not be able to actually
> > write the full packet to the card at once. The DXR3 device could now
> > simply block and return to the caller only once the full packet has been
> > written. But from the API and its usage I get the impression that
> > PlayVideo() was not supposed to block, right? Again blocking can be
> > avoided by using addional buffering in the device object.
>
> The idea is that the player reads the data from the disk and makes sure it
> has a decent "reserve" in case the disk is temporarily unavailable. It
> pushes the buffered data into the device in the same thread, so the device
> shouldn't block too long. However, I guess it should be ok if the device

There are actually two distinct and different buffers in cDvbPlayer. You have 
the ringbuffer, that builds the reserve you are speaking of, and you have the 
block of memory (usualy one frame) that you are trying to write to the 
device. I am refering _only_ to the later.

> takes "some" time to process the data. It just has to make sure it leaves
> the player enough time to read further data from the disk. I suggest you
> try processing the data that comes into your device through the PlayVideo()
> call and return once you have completely processed it. If that doesn't
> result in a smooth replay, either the machine is too slow or you'll have to
> implement an extra thread in your device that does the conversion. You
> shouldn't have to implement that much additional buffering, since I assume
> you'll be converting one frame at a time.

I do have to copy the entire frame then. This might not be much (in the great 
fabric of space and time) but i think we should avoid unneeded copies as much 
as possible.
The copying can be avoided (see below ...), if I can take posession of the 
frame that the player wants to send to the device and only inform the player 
about my progress. All this can be done without to much modification to the 
current code and without additional threads.

> > On the audio side, the card can only play PCM audio. The MPEG audio
> > stream needs to be decoded, which expands it size. This and the MPEG
> > audio decoder expecting full mpeg frames leads to excatly the same
> > problems and solutions as above.
> >
> > The simplest solution would be to allow PlayVideo() to block. Is that
> > acceptable? (IMHO it is not)
>
> See above. PlayVideo() doesn't have to return "immediately", but it must
> be fast enough to allow the player to keep up with reading the data.
>
> > The other solution, would be to make PlayVideo() always take possesion of
> > the complete packet (but do not memcpy() it) and have an additional
> > method do the actual non-blocking writting. This would mean, that the
> > buffer mechanism from cTransfer::Action() and cDvbPlayer::Action() would
> > be moved into the device object.
> >
> > What do you think?
>
> Wasn't it you who wanted the buffering done in the individual players?

Yes, but i'm not speaking about _that_ buffering.

> Moving it into the devices would, IMHO, not be the right way to go.

Again, not the full blown buffering, only the small piece of data that you try 
to send through PlayVideo().

> After all, the DVB cards don't need additional buffering (at least not
> in user space). If the DXR3 device needs to process the data before
> sending it to the hardware, it should do so in its own buffer and, if
> necessary, thread. But first I'd try if letting PlayVideo() return after
> processing all data works.

The semantics for PlayVideo I would prefer is:

class cDevice {
   ...
public:
    void PlayVideo(uint8_t buf, int length);
    int ProcessBuffer();
   ...
};

PlayVideo(...) will take the entire buffer and store a pointer to it internaly
ProcessBuffer(...) will send as much data as possible to the device, return 
values:
  > 0 mean there is still data in the buffer
  < 0 mean there is still data left, but the device is busy at the moment - 
     try again
   0 means all data has been written to the card,

values > 0 do not have to represent the actual amount of data beeing written

This will eventualy break the poll() on the devices, but i believe you can 
live without that quite happily. The DVB device buffers at least 300 ms worth 
of data (probably more). Checking the device on negative returns from 
ProcessBuffer() every 10ms will therefore still be sufficient.

> > ...
> >
> > > I guess what I could do is to introduce a cPlayer::Poll() function,
> > > which the player calls with its own file handle(s). That function in
> > > turn calls a virtual cDevice::Poll() function, which the derived device
> > > can re-implement to add its file handle(s). It then calls the Poll()
> > > function of the base cDevice class, which can then poll all
> > > participating file handles in one poll() call.
> > >
> > > Would that be something useful?
> >
> > What if the player has to wait on something that is not a file handle?
> > Ok, you might be doomed anyway in that case ....
>
> What if the world ends tomorrow? ;-)

It *does* end tomorrow, therefor you are required to make VDR perfect today! 
;-)


Andreas

-- 
Andreas Schultz <aschultz@cs.uni-magdeburg.de>
Student of computer science

"In accordance with plans for Linux OS world domination
      infiltration of governments is vital (:-))."




Home | Main Index | Thread Index