AVIA treiber fragen

Sklaventreiber
Günther
Developer
Beiträge: 587
Registriert: Freitag 9. September 2005, 21:48

AVIA treiber fragen

Beitrag von Günther »

Carjay hat geschrieben:Du zitierst den falschen Puffer. Die DVR-Puffergröße ist innerhalb der DVB-API festgelegt auf: 10*188*1024
Ahhhhhhhhh, OK.
Ich wühle mich so langsam durch. ....
Der Puffer wird also hier festgelegt?

Code: Alles auswählen

avia_gt_dmx.c
static u8 queue_size_table[AVIA_GT_DMX_QUEUE_COUNT] = {
	10,			/* video	*/
	10,			/* audio	*/
	9,			/* teletext	*/
	9, 10, 11, 10, 10,	/* user 3..7	*/
	8, 8, 8, 8, 8, 8, 8, 8,	/* user 8..15	*/
	8, 8, 8, 7, 7, 7, 7, 7,	/* user 16..23	*/
	7, 7, 7, 7, 7, 7, 7,	/* user 24..30	*/
	8			/* message	*/
};
...
		q->size = (1 << queue_size_table[0]) * 64;
...
Oder ist das nur der dmx Buffer (wäre ja noch meiner Berechnung nur 1024*64 bytes) und nicht der dvr Buffer?

Die Module die über open/read usw. aufgerufen werden sind aber diese Treiber ?

Code: Alles auswählen

	.read		= dvb_dvr_read,
	.write		= dvb_dvr_write,
	.ioctl		= dvb_dvr_ioctl,
	.open		= dvb_dvr_open,
	.release	= dvb_dvr_release,
	.poll		= dvb_dvr_poll,
Kann es sein das der Treiber sich einen Buffer hält und die Applikation auch noch einen?
Ist dieses umkopieren unbedingt notwendig (bei 1MB/s sind das kurz überschlagen bestimmt 5-10 % Prozessorlast (bei 4 bytes pro lese/schreibbefehl)?
Könnte der Treiber nicht direkt weiter auf die Festplatte schreiben? (es gibt eine Source dvb2eth die sowas anscheinend für das Netzwerk macht, aber womöglich wird das gar nicht benutzt)?

Günther
mws
Developer
Beiträge: 331
Registriert: Freitag 7. Februar 2003, 22:17

Beitrag von mws »

hi,

es gibt im kernel 2.6.x eine möglichkeit genau so etwas zu machen.
man macht praktisch 2 filedescriptoren auf und verknüpft diese.
diese hätte eine - so denk ich mal - drastische verbesserung zur folge.
ansonsten hast du
demux -> buffer treiber (copy to user) -> buffer app (copy to kernel) -> writeToDisk

vom grunsatz her hat der demux einen buffer (queue) in dem er die empfangen ts pakete speichert, und du hast einen buffer im bereich der applikation, wo du hingehst und die empfangenen daten zwischenspeicherst.
cu
mws
AudioSlyer
Erleuchteter
Erleuchteter
Beiträge: 450
Registriert: Sonntag 28. Juli 2002, 01:18

Beitrag von AudioSlyer »

Kann das der grund sein warum manche eine extrem hohe Prozessorlast beim HDD streamen haben, das scheinen nur Nokia Avia600 User zu haben. Meine 500er rennt super.
Carjay
Developer
Beiträge: 122
Registriert: Sonntag 23. April 2006, 12:37

Beitrag von Carjay »

64 kiByte für Video und Audio-Queue bzw. 128 kiByte für beide zusammen (bei SPTS).

Der Demux kann kein DMA ins Host-RAM, sondern nur in sein eigenes und das ist nicht allzu groß (2 MiByte, davon geht aber noch etwas ab für andere Puffer).

Das mit dem 2.6er ist richtig, aber noch recht neu (ab 2.6.17).

Ich überlege momentan auch, wie sinnvoll ein eigenes dbox2-spezifisches Dateisystem wäre welches eine direkte Verbindung zum Demux-Treiber herstellen könnte (analog zu dvb2eth, welches wie Günther korrekt bemerkt hat, noch von niemandem richtig getestet wurde).

Dann könnte man vom Demux aus direkt die Puffer fürs Schreiben füllen und würde sich den Kopiervorgang sparen.

Muß mal nachdenken, wie die Implementierung genau aussehen könnte weil da auch noch andere Dinge wichtig sind (Verhalten nach einem Crash etc.)

Es wäre aber denke ich erstmal wichtiger, zu instrumentieren wo die Hotspots liegen.

Daß sich 500/600 unterscheiden kann ich nicht wirklich erklären. Muß man ebenfalls nachmessen.

Ich vermute mal, daß die Overflows daher rühren, daß der IDE-Treiber zu viel Zeit braucht und die Demux-Bottom Half (die die Daten kopiert) nicht rechtzeitig zum Zuge kommt. Aber ob das wirklich so ist wird man sehen.

Das Hin- und Herkopieren der Daten zwischen Kernel- und Userspace kostet sicherlich auch sehr viel Zeit.
AudioSlyer
Erleuchteter
Erleuchteter
Beiträge: 450
Registriert: Sonntag 28. Juli 2002, 01:18

Beitrag von AudioSlyer »

Danke ;)
Günther
Developer
Beiträge: 587
Registriert: Freitag 9. September 2005, 21:48

Beitrag von Günther »

Wahrscheinlich ist es nicht möglich wegen der Trennung user/kernel space , aber theorethisch könnte der DMX treiber der Applikation doch einen read-only pointer auf das aktuelle buffer segment geben, welches dann wiederum dem IDE-Treiber übergeben wird, der dürfte doch dann diesen Pointer wieder benutzen (?) und schon hätte man sich das Rumkopiere gespart. Wenn der IDE-Treiber gelesen hat wird dieses Segment wieder freigegeben.

Könnte ja auch ein ganz primitiver Segment-Ringbuffer sein ala (nicht getestet und kompiliert), aber da gibt es bestimmt auch schon was generisches in irgeneiner Lib die ich noch nicht kenne:

Code: Alles auswählen

/////////////////////////////////
// Defines
/////////////////////////////////

#define BUF_SEG     0x10000
#define BUF_SEG_NR  10

/////////////////////////////////
// Variables
/////////////////////////////////
static int seg_table[BUF_SEG_NR];
static int next_seg[BUF_SEG_NR];
static int prev_seg[BUF_SEG_NR];
static unsigend char buffer[MAX_BUFFER * BUF_SEG_NR];

static int buffer_write_seg =  0;
static int buffer_read_seg =   0;

static bool first_write = false;
/////////////////////////////////
// Prototypes
/////////////////////////////////
void            buffer_seg_init(void);
int             buffer_seg_get_seg(void);
int             buffer_seg_get_size(void);
unsigned char*  buffer_seg_get_next_write(void);
unsigned char*  buffer_seg_get_next_read(void);

//////////////////
// Note: After init the first call MUST be buffer_seg_get_next_write !!!!, otherwise the read does make an empty loop
// This is not handled in the routine to speed up everything!
//////////////

/////////////////////////////////
// Functions
/////////////////////////////////
void buffer_seg_init(void)
{
    for(int i = 0; i < BUF_SEG_NR; i++)
    {
        seg_table[i] = BUF_SEG * i;
        next_seg[i] = i+1;
        prev_seg[i] = i-1;
    }
    prev_seg[0] = BUF_SEG_NR-1;
    next_seg[BUF_SEG_NR-1] = 0;

    buffer_write_seg = 0;
    buffer_read_seg = 0;
}


/*********************************************************/
int buffer_seg_get_seg(void)
/*********************************************************/
{
    return BUF_SEG_NR;
}

/*********************************************************/
int buffer_seg_get_size(void)
/*********************************************************/
{
    return BUF_SEG;
}

/*********************************************************/
unsigned char* buffer_seg_get_next_write(void)
/*********************************************************/
{
    // first_write = true;
    // Check for buffer overflow????
    if(next_seg[buffer_write_seg] == buffer_read_seg)
    {
        // conflict with READ BUFFER, what do we want to do here?
        print("BUFFER OVERFLOW");
        buffer_write_seg = next_seg[buffer_write_seg]; // discard current segment to prevent memory conflicts?
    }

    buffer_write_seg = next_seg[buffer_write_seg];
    return &buffer[seg_table[buffer_write_seg]];
}

/*********************************************************/
unsigned char* buffer_seg_get_next_read(void)
/*********************************************************/
{
    //if(first_write == false) return NULL;
        
    if(next_seg[buffer_read_seg] == buffer_write_seg)
    {
        print("BUFFER UNDERFLOW");
        return NULL;
    }

    buffer_read_seg = next_seg[buffer_read_seg];
    return &buffer[seg_table[buffer_read_seg]];
}