Avia Treiber haengt bei VDR Wiedergabe auf dbox2.

Sklaventreiber
cko
Neugieriger
Neugieriger
Beiträge: 3
Registriert: Samstag 14. Februar 2004, 21:20

Avia Treiber haengt bei VDR Wiedergabe auf dbox2.

Beitrag von cko »

Hallo,

ich versuche VDR (Klaus Schmidinger's Video Disk recorder, siehe
http://www.cadsoft.de/people/kls/vdr) Wiedergabe auf einer
Nokia Sat dbox2 zum Laufen zu kriegen.

Nachdem ich ein paar einfache Probleme ("find -type" busybox
Konfiguration fuer das VDR recordings menue, big endian bug
in VDR index file input) geloest habe, gibt's jetzt ein
Problem, bei dem ich ohne Hilfe nicht weiter komme.

VDR startet die Wiedergabe und beginnt nach dem setup mit
write calls auf das DVB device.
Ausnahmlos alle write calls bekommen errno=EAGAIN und der
Bildschirm bleibt schwarz.

Ich vermute, das EAGAIN wird von der routine avia_gt_dmx_queue_write
in driver/dvb/drivers/media/dvb/avia/avia_gt_dmx.c gemeldet.
Scheinbar wird die queue nie leer?

Ich vermute, dass der setup, den VDR macht (welcher natuerlich
auf PCs unter Linux mit DVB Karte einwandfrei funktioniert)
fuer diesen Treiber nicht ausreicht.

Die entscheidenden Stellen im VDR code findet man in dvbdevice.c.
Dort geschieht initial:

* in cDvbDevice::TurnOffLiveMode
ioctl(fd_audio, AUDIO_SET_MUTE, true);
ioctl(fd_video,VIDEO_SET_BLANK);
ioctl(fd_audio,AUDIO_STOP);
ioctl(fd_video,VIDEO_STOP);
* in cDvbDevice::SetPlayMode
ioctl(fd_video, VIDEO_SET_BLANK, true);
ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY);
ioctl(fd_audio, AUDIO_SET_AV_SYNC, PlayMode == pmAudioVideo);
ioctl(fd_audio, AUDIO_PLAY);
ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY);
ioctl(fd_video, VIDEO_PLAY);

Und dann beginnen die writes:
write(fd_video, Data, Length);

An der Stelle habe ich Testausschriebe eingebaut.

int cDvbDevice::PlayVideo(const uchar *Data, int Length)
{
int fd = (playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) ? fd_audio : fd_video;
int ret = -1;
if (fd >= 0)
ret = write(fd, Data, Length);
dsyslog("write(%d, %x, %d)=%d, errno=%d", fd, int(Data), Length, ret, errno);

return ret;
}

Die sehen alle ausnahmslos so aus:

Feb 15 15:29:02 dbox user.debug vdr[113]: write(5, 10292eb0, 54313)=-1, errno=11


Hat jemand einen Tip fuer mich?
Fehlt oben noch ein entscheidender ioctl, um das Ganze in Schwung
zu bringen?

Danke und Gruss,

Carsten.
obi
Senior Member
Beiträge: 1282
Registriert: Montag 12. November 2001, 00:00

Re: Avia Treiber haengt bei VDR Wiedergabe auf dbox2.

Beitrag von obi »

cko hat geschrieben:VDR startet die Wiedergabe und beginnt nach dem setup mit
write calls auf das DVB device.
was ist "das DVB device"?
cko hat geschrieben:Ausnahmlos alle write calls bekommen errno=EAGAIN und der
Bildschirm bleibt schwarz.

Ich vermute, das EAGAIN wird von der routine avia_gt_dmx_queue_write
in driver/dvb/drivers/media/dvb/avia/avia_gt_dmx.c gemeldet.
Scheinbar wird die queue nie leer?
ja
Ich vermute, dass der setup, den VDR macht (welcher natuerlich
auf PCs unter Linux mit DVB Karte einwandfrei funktioniert)
fuer diesen Treiber nicht ausreicht.
die alten dvb karten mit av7110 benutzen kein standardformat sondern "avpes". vdr schreibt also eine datei bestehend aus zusammengeschmissenem audio und video pes nach video0. vdr ist nebenbei zu doof, den treiber vorher zu fragen, ob er das versteht, weil kls ja denkt, dass es nur intel und av7110 karten gibt.

du hast die moeglichkeiten, TS nach dvr0 zu schreiben oder PES nach video0 und audio0 zu schreiben. was momentan passiert ist offenbar, dass du muell nach video0 schreibst, dazu av sync an hast aber nichts nach audio0 schreibst.
cko
Neugieriger
Neugieriger
Beiträge: 3
Registriert: Samstag 14. Februar 2004, 21:20

Beitrag von cko »

obi hat geschrieben: du hast die moeglichkeiten, TS nach dvr0 zu schreiben oder PES nach video0 und audio0 zu schreiben. was momentan passiert ist offenbar, dass du muell nach video0 schreibst, dazu av sync an hast aber nichts nach audio0 schreibst.
Danke fuer den Tip!
Das hat mir sehr viel weiter geholfen.
Ich habe jetzt also in vdr-1.2.6/dvbdevice.c cDvbDevice::PlayVideo
so erweitert, dass es die Pakete analysiert und Tonpakete nach fd_audio
sowie Bildpakete nach fd_video schreibt:

Code: Alles auswählen

int cDvbDevice::PlayVideo(const uchar *Data, int Length)
{
   int total_bytes = 0;
   for (int i = 0; i < Length - 6; i++)
      if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01)
      {
         const int packet_length = Data[i + 4] * 256 + Data[i + 5] + 6;
         if (packet_length > 0)
         {
            const uchar packet_id = Data[i + 3];
            int fd;
            switch (packet_id) 
            {
               case 0xBD: // dolby
               case 0xC0 ... 0xC1: // audio
                  fd = fd_audio;
               break;
               case 0xE0 ... 0xEF: // video
                  fd = fd_video;
               break;
               default:
                  esyslog("ERROR: unexpected packet id %02X.", packet_id);
                  fd = -1;
            }
            if (fd != -1)
            {
               int bytes_written = 0;
               while (bytes_written < packet_length)
               {
                  int l = write(fd, Data + bytes_written + i, packet_length - bytes_written);
                  if (l > 0) 
                     bytes_written += l;
                  else if (l == -1)
                  {
                     if (errno == EAGAIN)
                        usleep(1);
                     else
                     {
                        esyslog("ERROR: PlayVideo write returns %d.", errno);
                        return -1;
                     }
                  }
               }
               total_bytes += packet_length;
               i += packet_length - 1; // the loop increments, too!
            }
         }
      }
      else
         esyslog("ERROR: bad packet header %02X %02X %02X.", Data[i], Data[i + 1], Data[i +2]);

   return total_bytes;
}
Das funktioniert tatsaechlich.
Leider nur intermittierend.
Manchmal laufen Bild und Ton perfekt, manchmal nur das Bild ohne Ton und manchmal guter Ton mit ruckelndem Bild. Ein System konnte ich nicht erkennen. Selbst, wenn ich in aufeinanderfolgenden Tests direkt nach dem
booten die Wiedergabe gestartet habe, lief es mal perfekt, meist jedoch mit perfektem Video ohne Audio.

Hast Du noch nen Tip?

Danke und Gruss.

Carsten.
obi
Senior Member
Beiträge: 1282
Registriert: Montag 12. November 2001, 00:00

Beitrag von obi »

Code: Alles auswählen

const int packet_length = Data[i + 4] * 256 + Data[i + 5] + 6;
if (packet_length > 0)
ist immer wahr (>= 6)

spontan faellt mir eigentlich nur auf, dass video pakete keine gueltige laengenangabe enthalten muessen. stattdessen ist laenge==0 erlaubt, was so viel heisst wie "hoert da auf wo das naechste anfaengt".

dann koennte noch passieren, dass z.b. die video queue voll ist und du dich eine weile mit EAGAIN beschaeftigst, ohne daten in die audio queue schreiben zu koennen. so kommts vielleicht im audio decoder zum buffer underrun. der avia wird dann evtl. sync ausschalten oder ins stottern kommen oder was auch immer ;)

da waere es vielleicht sinnvoll, audio und video schon vorher in getrennten dateien zu haben, am besten neu verpackt, so dass immer gueltige laengenangaben auch beim video header vorhanden sind.

noch besser waere, die daten als TS zu schreiben, was enigma und neutrino auch machen. das kann vdr wohl (noch?) nicht.