Mailing List archive

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

[linux-dvb] Re: WANTED : KaxTV testers



Le Mercredi 22 Décembre 2004 00:49, Jim Darby a écrit :
> Interesting new stuff.
>
> Firstly I did the commenting out of the EIT processing as Christophe
> suggested.
>
> No crashes! Fantastic. OK, I haven't run it for ages, but it's certainly
> looking good.
>
> Now I tried to perform my own CRC checking, but I can't seem to get it
> working. So, I did a quick check of the mailing list archives and from
> that I noticed that several people have commented that they have the
> crc32 kernel module loaded.
>
> I do NOT have this module loaded. Could this be the reason why the
> CRC-32 isn't being performed? Is this possible?
>
> How does the kernel module dvb-core know when to apply CRC-32 and not?
> Not all TS data uses it, just certain specific cases (such as it EIT).
>
> Thoughts anyone?
>
> Jim.

Having played a lot with eit parsing, i found on some TS some really buggy 
sections. Don't know if it's crc32 fault but at least i can sea some sections 
with totally wrong lengths (esp in short and extended event descriptors) 
causing buffer overflow. So, dvbEvents now always check length before 
attempting any buffer read. Seems to fix (but not yet heavily tested, just 
one shot : 2s autozap through chanlist for 1 hour with no crash).

Anyway, if you can't wait, there it's joined.
Look at stderr for : "EIT : buffer overflow !! Rejected". You got one buggy 
section that just make kaxtv laugthing.
And (hopefully:) merry christmas and happy new year !!

-- 
Christophe Thommeret
/***************************************************************************
                          dvbevents.cpp  -  description
                             -------------------
    begin                : Tue Dec 16 2003
    copyright            : (C) 2003 by Christophe Thommeret
    email                : hftom@free.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdio.h>
#include <unistd.h>

#include <qdatetime.h>

#include "dvbevents.h"



DVBevents::DVBevents( bool *ok, int card ) : DVBsection( ok, card )
{
	events.setAutoDelete( true );

	connect ( &cleanTimer, SIGNAL(timeout()), this, SLOT(setClean()) );
	clean = false;
	cleanTimer.start( 3000 );
	demuxOpened = false;
	isRunning = true;
	pf[0].fd = fdDemux;
	pf[0].events = POLLIN;
	start();
}



DVBevents::~DVBevents()
{
	isRunning = false;
	wait();
	events.clear();
	cleanTimer.stop();
}



void DVBevents::doClean( bool b )
{
	if ( b ) {
		if ( cleanTimer.isActive() ) return;
		cleanTimer.start( 3000 );
	}
	else {
		cleanTimer.stop();
		clean = false;
	}
}



bool DVBevents::shortEventDesc( unsigned char *buf, EventDesc *desc )
{
	QString name, text;
	int len, len2;
	ShortEvent *ev;

	if ( !safeLen( buf+6 ) ) return false;
	len = getBits(buf,40,8);
	if ( !safeLen( buf+6+len ) ) return false;
	name = getText( buf+6, len );
	if ( !safeLen( buf+6+len+1 ) ) return false;
	len2 = getBits(buf+6+len,0,8);
	if ( !safeLen( buf+7+len+len2 ) ) return false;
	text = getText( buf+7+len, len2);
	if ( desc->title=="" ) {
		desc->title=name;
		desc->subtitle=text;
		return true;
	}
	desc->shortEvents.append( new ShortEvent() );
	ev = desc->shortEvents.getLast();
	ev->name = name;
	ev->text = text;
	return true;
}



bool DVBevents::extEventDesc( unsigned char *buf, EventDesc *desc )
{
	int loop, len1, len2;
	unsigned char *b = buf;
	QString s;

	if ( !safeLen( b+7 ) ) return false;
	loop = getBits(b+6,0,8);
	b +=7;

	while ( loop>0 ) {
		if ( !safeLen( b+1 ) ) return false;
		len1 = getBits(b,0,8);
		if ( !safeLen( b+1+len1 ) ) return false;
		s = getText(b+1,len1);
		if ( !safeLen( b+1+len1+1 ) ) return false;
		len2 = getBits(b+1+len1,0,8);
		if ( !safeLen( buf+2+len1+len2 ) ) return false;
		if ( s!="" ) s = s+" : ";
		s = s+getText(b+2+len1,len2);
		desc->extEvents.append( new QString( s ) );
		b +=(2+len1+len2);
		loop -=(2+len1+len2);
	}
	if ( !safeLen( b+1 ) ) return false;
	len1 = getBits(b,0,8);
	if ( !safeLen( b+1+len1 ) ) return false;
	s = getText(b+1,len1);
	desc->extEvents.append( new QString( s ) );
	return true;
}



QDateTime DVBevents::getDateTime( unsigned char *buf )
{
	int hh, mm, ss;
	int i, j, m, D, Y, M, k, mjd;
	int sec;
	
	mjd = getBits(buf,0,16);
	i = (int)((mjd-15078.2)/365.25);
	j = (int)(i*365.25);
	m = (int)((mjd-14956.1-j)/30.6001);
	D = mjd-14956-j-(int)(m*30.6001);
	if ( m==14 || m==15 ) k = 1;
	else k = 0;
	Y = i+k+1900;
	M = m-1-k*12;

	hh = ((getBits(buf+2,0,4)*10)+getBits(buf+2,4,4))%24;
	mm = ((getBits(buf+2,8,4)*10)+getBits(buf+2,12,4))%60;
	ss = ((getBits(buf+2,16,4)*10)+getBits(buf+2,20,4))%60;

	QDateTime dt( QDate( (Y>=1970)?Y:1970, (M>0 && M<13)?M:1, (D>0 && D<32)?D:1 ), QTime( hh, mm, ss ) );
	QDateTime u( QDate( 1970, 1, 1 ), QTime( 0, 0, 0 ) );
	sec = u.secsTo( dt );
	u.setTime_t( sec );
	return u;
}



bool DVBevents::tableEIT( unsigned char* buffer )
{
	//fprintf( stderr, "Parsing EIT ...\n" );
	unsigned char* buf = buffer;
	unsigned int length, loop, sid, tid, eid, tsid, sn, lsn;
	int i, sec;
	EventDesc *desc=0, *itdesc=0;
	bool nodesc, process;
	QDateTime start, cur, dt;
	QPtrListIterator<EventDesc> it( events );

	tid = getBits(buf,0,8);
	length = getBits(buf,12,12);
	sid = getBits(buf,24,16);
	sn = getBits(buf,48,8);
	lsn = getBits(buf,56,8);
	tsid = getBits(buf,64,16);
	length -=11;
	buf +=14;

	while ( length>4 ) {
		nodesc=process=false;
		if ( !safeLen( buf+2 ) ) goto out;
		eid = getBits(buf,0,16);
		if ( !safeLen( buf+2+5 ) ) goto out;
		start = getDateTime( buf+2 );
		nodesc=process=true;
		it.toFirst();
		while ( (desc = it.current())!=0 ) {
			if ( desc->sid==sid && desc->tsid==tsid ) {
				if ( desc->startDateTime==start || desc->eid==eid ) {
					if ( desc->tid==0x4e && tid!=0x4e ) {
						process = false;
						nodesc = false;
						break;
					}
					else {
						desc->extEvents.clear();
						desc->shortEvents.clear();
						desc->title=desc->subtitle="";
						nodesc = false;
						break;
					}
				}
			}
			++it;
		}
		if ( nodesc ) desc = new EventDesc();
		if ( process ) {
			desc->sid = sid;
			desc->tid = tid;
			desc->tsid = tsid;
			desc->lsn = lsn;
			desc->sn = sn;
			desc->eid = eid;
			desc->duration = getTime( buf+7 );
			desc->startDateTime = start;
			desc->running = getBits(buf,80,3);
		}

		if ( desc->sn != sn ) {
			//fprintf( stderr, "... EIT rejected.\n" );
			return false;
		}
		if ( !safeLen( buf+12 ) ) goto out;
		loop = getBits(buf,84,12);
		buf +=12;
		length -=(12+loop);
		while ( loop>0 ) {
			if ( process ) {
				if ( !safeLen( buf+1 ) ) goto out;
				switch ( getBits(buf,0,8) ) {
					case 0x4D :
						if ( !shortEventDesc( buf, desc ) ) goto out;
						break;
					case 0x4E :
						if ( !extEventDesc( buf, desc ) ) goto out;
						break;
					default :
						break;
				}
			}
			if ( !safeLen( buf+2 ) ) goto out;
			loop -=( getBits(buf,8,8)+2 );
			buf +=( getBits(buf,8,8)+2 );
		}
		if ( nodesc ) {
			for ( i=0; i<(int)events.count(); i++ ) {
				itdesc = events.at(i);
				if ( desc->startDateTime<itdesc->startDateTime ) {
					events.insert( i, desc );
					break;
				}
				itdesc = 0;
			}
			if ( !itdesc ) events.append( desc );
		}
		if ( process ) ++(desc->sn);
		if ( desc->title.length()<3 ) events.remove( desc );
		else if ( nodesc ) {
			cur = QDateTime::currentDateTime();
			dt = desc->startDateTime;
			sec = desc->duration.hour()*3600+desc->duration.minute()*60+desc->duration.second();
			if ( dt.addSecs( sec )<cur ) events.remove( desc );
		}
	}
	//fprintf( stderr, "... EIT parsed. %d\n", events.count() );
	return true;
out:
	if ( nodesc ) delete desc;
	return false;
}



bool DVBevents::safeLen( unsigned char* buf )
{
	if ( !(buf>secbuf+4095) ) return true;
	fprintf( stderr, "EIT : buffer overflow !! Rejected\n" );
	return false;
}



bool DVBevents::go( bool all )
{
	int tid;

	if ( demuxOpened ) return true;
		
	if ( all ) tid = 0;
	else tid = 0x4e;
	if ( !setFilter( 0x12, tid, 100 ) ) return false;
	demuxOpened = true;
	return true;
}



void DVBevents::stop()
{
	if ( !demuxOpened ) return;
	
	demuxOpened = false;
	isRunning = false;
	wait();
	stopFilter();
	isRunning = true;
	start();
}



void DVBevents::setClean()
{
	clean = true;
}



void DVBevents::run()
{
	int n=0, sec;
	int skip=0;
	QDateTime dt, cur;
	QPtrListIterator<EventDesc> it( events );
	EventDesc *itdesc;

	while ( isRunning ) {
		if ( clean ) {
			it.toFirst();
			cur = QDateTime::currentDateTime();
			while ( (itdesc = it.current())!=0 ) {
				dt = itdesc->startDateTime;
				sec = itdesc->duration.hour()*3600+itdesc->duration.minute()*60+itdesc->duration.second();
				if ( dt.addSecs( sec )<cur ) events.remove( itdesc );
				++it;
			}
			clean = false;
			//fprintf(stderr,"%d events\n", events.count());
		}

		if ( !demuxOpened ) {
			usleep( 100000 );
			continue;
		}

		if ( poll(pf,1,100)>0 ){
			if ( pf[0].revents & POLLIN ){
				n = read( fdDemux, secbuf, 4096 );
				skip = 0;
			}
			else skip++;
		}
		else skip++;
		
		if (skip) continue;
		if ( n<4 ) continue;

		switch ( getBits(secbuf,0,8) ) {
			case 0x4E :
			case 0x4F :
			case 0x50 : case 0x51 : case 0x52 : case 0x53 : case 0x54 : case 0x55 :
			case 0x56 : case 0x57 : case 0x58 : case 0x59 : case 0x5A : case 0x5B :
			case 0x5C : case 0x5D : case 0x5E : case 0x5F :
			case 0x60 : case 0x61 : case 0x62 : case 0x63 : case 0x64 : case 0x65 :
			case 0x66 : case 0x67 : case 0x68 : case 0x69 : case 0x6A : case 0x6B :
			case 0x6C : case 0x6D : case 0x6E : case 0x6F :
				tableEIT( secbuf );
				break;
			default:
				break;
		}
	}
}
/***************************************************************************
                          dvbevents.h  -  description
                             -------------------
    begin                : Tue Dec 16 2003
    copyright            : (C) 2003 by Christophe Thommeret
    email                : hftom@free.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef DVBEVENTS_H
#define DVBEVENTS_H

#include <sys/poll.h>

#include <qtimer.h>

#include "dvbsection.h"
#include "channeldesc.h"



class DVBevents : public DVBsection
{
	Q_OBJECT
	
public:

	DVBevents( bool *ok, int card );
	~DVBevents();
	bool go( bool all=false );
	void stop();
	void doClean( bool b );

	QPtrList<EventDesc> events;

protected:

	virtual void run();
	bool tableEIT( unsigned char* buffer );
	bool shortEventDesc( unsigned char *buf, EventDesc *desc );
	bool extEventDesc( unsigned char *buf, EventDesc *desc );
	QDateTime getDateTime( unsigned char *buf );
	bool safeLen( unsigned char* buf );

	bool clean;
	QTimer cleanTimer;

private slots:

	void setClean();

private:

	unsigned char secbuf[4096];
	bool demuxOpened;
	struct pollfd pf[1];

signals:

	void newEvent( EventDesc* );

};

#endif

Home | Main Index | Thread Index