Aktuelles
Digital Eliteboard - Das Digitale Technik Forum

Registriere dich noch heute kostenlos, um Mitglied zu werden! Sobald du angemeldet bist, kannst du auf unserer Seite aktiv teilnehmen, indem du deine eigenen Themen und Beiträge erstellst und dich über deinen eigenen Posteingang mit anderen Mitgliedern unterhalten kannst! Zudem bekommst du Zutritt zu Bereichen, welche für Gäste verwehrt bleiben

Registriere dich noch heute kostenlos, um Mitglied zu werden! Sobald du angemeldet bist, kannst du auf unserer Seite aktiv teilnehmen, indem du deine eigenen Themen und Beiträge erstellst und dich über deinen eigenen Posteingang mit anderen Mitgliedern unterhalten kannst! Zudem bekommst du Zutritt zu Bereichen, welche für Gäste verwehrt bleiben

Testkernel für User mit öfter auftrettenden zucken und aufhängen der Box

    Nobody is reading this thread right now.
AW: Testkernel für User mit öfter auftrettenden zucken und aufhängen der Box

die Probleme sind (bei mir zumindest) nur bei den 720p-Sendern, wobei sich ORF gerade noch in Grenzen hält, aber ARD/ZDF weit übers Ziel schießt (d.h. schlechtere Qualität mit höherer brutto Datenmenge)
die Frage: was und warum? sollten uns eigentlich die Deppen von ARD/ZDF beantworten, wenn sie es überhaupt begreifen, was sie da veranstalten und warum vor allem, lassen alles in 1080i produzieren wie auch einkaufen, strahlen dennoch in 720p aus, und wir sollten deren depperten Encoder studieren
wenn man die beiden arte HD Versionen vergleicht: Frankreich 1080i = keine Probleme vs. Deutschland 720p = massive Probleme
auch die Größe der Aufnahmen lässt vermuten, dass mit dem 720p Format etwas nicht stimmt: die Aufnahmen auf arte HD 1080i sind fast 30% kleiner als 720p (nicht jedoch die Qualität, im Gegenteil)
und wenn ich mir die Aufnahmen auf BBC ansehe, wo die Qualität noch besser ist: die sind dann noch um einiges mehr kleiner
 
AW: Testkernel für User mit öfter auftrettenden zucken und aufhängen der Box

und wie genau kann ich da jetzt was dran ändern ? wo soll ich da denn anfangen, wir haben ja auch pes filter echt aber glaube kaum das da der hund begraben liegt
 
AW: Testkernel für User mit öfter auftrettenden zucken und aufhängen der Box

könntest du mir bitte demix.cpp näher bringen ;)
 
AW: Testkernel für User mit öfter auftrettenden zucken und aufhängen der Box

em nö, wie soll ich das denn amchen ? ich kann dir das file posten aber das wars auch schon :P
Code:
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <aio.h>
#include <sys/sysinfo.h>
#include <sys/mman.h>

//#define SHOW_WRITE_TIME
static int determineBufferCount()
{
    struct sysinfo si;
    if (sysinfo(&si) != 0)
    {
        return 6; // Default to small
    }
    unsigned int megabytes = si.totalram >> 20;
    int result;
    if (megabytes > 200)
        result = 16; // old 20 , 512MB systems: Use 4MB IO buffers (et9x00, vuultimo, ...)
    else if (megabytes > 100)
        result = 16; // old 16, 256MB systems: Use 3MB demux buffers (dm8000, et5x00, vuduo, Argus)
    else
        result = 16; // Smaller boxes: Use 1.5MB buffer (dm7025)
    return result;
}

static int recordingBufferCount = determineBufferCount();

#include <linux/dvb/dmx.h>

#include "crc32.h"

#include <lib/base/eerror.h>
#include <lib/base/filepush.h>
#include <lib/dvb/idvb.h>
#include <lib/dvb/demux.h>
#include <lib/dvb/esection.h>
#include <lib/dvb/decoder.h>
#include <lib/dvb/pvrparse.h>

eDVBDemux::eDVBDemux(int adapter, int demux):
    adapter(adapter),
    demux(demux),
    source(-1),
    m_dvr_busy(0)
{
}

eDVBDemux::~eDVBDemux()
{
}

int eDVBDemux::openDemux(void)
{
    char filename[32];
    snprintf(filename, sizeof(filename), "/dev/dvb/adapter%d/demux%d", adapter, demux);
    return ::open(filename, O_RDWR);
}

int eDVBDemux::openDVR(int flags)
{
#ifdef HAVE_OLDPVR
    return ::open("/dev/misc/pvr", flags);
#else
    char filename[32];
    snprintf(filename, sizeof(filename), "/dev/dvb/adapter%d/dvr%d", adapter, demux);
    return ::open(filename, flags);
#endif
}

DEFINE_REF(eDVBDemux)

RESULT eDVBDemux::setSourceFrontend(int fenum)
{
    int fd = openDemux();
    if (fd < 0) return -1;
    int n = DMX_SOURCE_FRONT0 + fenum;
    int res = ::ioctl(fd, DMX_SET_SOURCE, &n);
    if (res)
        eDebug("DMX_SET_SOURCE failed! - %m");
    else
        source = fenum;
    ::close(fd);
    return res;
}

RESULT eDVBDemux::setSourcePVR(int pvrnum)
{
    int fd = openDemux();
    if (fd < 0) return -1;
    int n = DMX_SOURCE_DVR0 + pvrnum;
    int res = ::ioctl(fd, DMX_SET_SOURCE, &n);
    source = -1;
    ::close(fd);
    return res;
}

RESULT eDVBDemux::createSectionReader(eMainloop *context, ePtr<iDVBSectionReader> &reader)
{
    RESULT res;
    reader = new eDVBSectionReader(this, context, res);
    if (res)
        reader = 0;
    return res;
}

RESULT eDVBDemux::createPESReader(eMainloop *context, ePtr<iDVBPESReader> &reader)
{
    RESULT res;
    reader = new eDVBPESReader(this, context, res);
    if (res)
        reader = 0;
    return res;
}

RESULT eDVBDemux::createTSRecorder(ePtr<iDVBTSRecorder> &recorder, int packetsize, bool streaming)
{
    if (m_dvr_busy)
        return -EBUSY;
    recorder = new eDVBTSRecorder(this, packetsize, streaming);
    return 0;
}

RESULT eDVBDemux::getMPEGDecoder(ePtr<iTSMPEGDecoder> &decoder, int primary)
{
    decoder = new eTSMPEGDecoder(this, primary ? 0 : 1);
    return 0;
}

RESULT eDVBDemux::getSTC(pts_t &pts, int num)
{
    int fd = openDemux();
    
    if (fd < 0)
        return -ENODEV;

    struct dmx_stc stc;
    stc.num = num;
    stc.base = 1;
    
    if (ioctl(fd, DMX_GET_STC, &stc) < 0)
    {
        eDebug("DMX_GET_STC failed!");
        ::close(fd);
        return -1;
    }
    
    pts = stc.stc;
    
    eDebug("DMX_GET_STC - %lld", pts);
    
    ::close(fd);
    return 0;
}

RESULT eDVBDemux::flush()
{
    // FIXME: implement flushing the PVR queue here.
    
    m_event(evtFlush);
    return 0;
}

RESULT eDVBDemux::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &conn)
{
    conn = new eConnection(this, m_event.connect(event));
    return 0;
}

void eDVBSectionReader::data(int)
{
    __u8 data[4096]; // max. section size
    int r;
    r = ::read(fd, data, 4096);
    if(r < 0)
    {
        eWarning("ERROR reading section - %m\n");
        return;
    }
    if (checkcrc)
    {
        // this check should never happen unless the driver is crappy!
        unsigned int c;
        if ((c = crc32((unsigned)-1, data, r)))
        {
            eDebug("crc32 failed! is %x\n", c);
            return;
        }
    }
    if (active)
        read(data);
    else
        eDebug("data.. but not active");
}

eDVBSectionReader::eDVBSectionReader(eDVBDemux *demux, eMainloop *context, RESULT &res): demux(demux), active(0)
{
    fd = demux->openDemux();
    
    if (fd >= 0)
    {
        notifier=eSocketNotifier::create(context, fd, eSocketNotifier::Read, false);
        CONNECT(notifier->activated, eDVBSectionReader::data);
        res = 0;
    } else
    {
        perror("demux->openDemux failed");
        res = errno;
    }
}

DEFINE_REF(eDVBSectionReader)

eDVBSectionReader::~eDVBSectionReader()
{
    if (fd >= 0)
        ::close(fd);
}

RESULT eDVBSectionReader::setBufferSize(int size)
{
    int res=::ioctl(fd, DMX_SET_BUFFER_SIZE, size);
    if (res < 0)
        eDebug("eDVBSectionReader DMX_SET_BUFFER_SIZE failed(%m)");
    return res;
}

RESULT eDVBSectionReader::start(const eDVBSectionFilterMask &mask)
{
    RESULT res;
    if (fd < 0)
        return -ENODEV;

    notifier->start();

    dmx_sct_filter_params sct;
    sct.pid     = mask.pid;
    sct.timeout = 0;
    sct.flags   = DMX_IMMEDIATE_START;

    if (mask.flags & eDVBSectionFilterMask::rfCRC)
    {
        sct.flags |= DMX_CHECK_CRC;
        checkcrc = 1;
    } else
        checkcrc = 0;
    
    memcpy(sct.filter.filter, mask.data, DMX_FILTER_SIZE);
    memcpy(sct.filter.mask, mask.mask, DMX_FILTER_SIZE);
    memcpy(sct.filter.mode, mask.mode, DMX_FILTER_SIZE);
    setBufferSize(8192*8); // *8 = 65536

    res = ::ioctl(fd, DMX_SET_FILTER, &sct);
    if (!res)
    {
        active = 1;
    }
    return res;
}

RESULT eDVBSectionReader::stop()
{
    if (!active)
        return -1;

    active=0;
    ::ioctl(fd, DMX_STOP);
    notifier->stop();

    return 0;
}

RESULT eDVBSectionReader::connectRead(const Slot1<void,const __u8*> &r, ePtr<eConnection> &conn)
{
    conn = new eConnection(this, read.connect(r));
    return 0;
}

void eDVBPESReader::data(int)
{
    while (1)
    {
        __u8 buffer[16384]; //16384
        int r;
        r = ::read(m_fd, buffer, 16384); // 16384
        if (!r)
            return;
        if(r < 0)
        {
            if (errno == EAGAIN || errno == EINTR) /* ok */
                return;
            eWarning("ERROR reading PES (fd=%d) - %m", m_fd);
            return;
        }

        if (m_active)
            m_read(buffer, r);
        else
            eWarning("PES reader not active");
        if (r != 16384) // 16384
            break;
    }
}

eDVBPESReader::eDVBPESReader(eDVBDemux *demux, eMainloop *context, RESULT &res): m_demux(demux), m_active(0)
{
    m_fd = m_demux->openDemux();
    if (m_fd >= 0)
    {
        setBufferSize(64*1024); // 64*1024
        ::fcntl(m_fd, F_SETFL, O_NONBLOCK);
        m_notifier = eSocketNotifier::create(context, m_fd, eSocketNotifier::Read, false);
        CONNECT(m_notifier->activated, eDVBPESReader::data);
        res = 0;
    } else
    {
        perror("openDemux");
        res = errno;
    }
}

RESULT eDVBPESReader::setBufferSize(int size)
{
    int res = ::ioctl(m_fd, DMX_SET_BUFFER_SIZE, size);
    if (res < 0)
        eDebug("eDVBPESReader DMX_SET_BUFFER_SIZE failed(%m)");
    return res;
}

DEFINE_REF(eDVBPESReader)

eDVBPESReader::~eDVBPESReader()
{
    if (m_fd >= 0)
        ::close(m_fd);
}

RESULT eDVBPESReader::start(int pid)
{
    RESULT res;
    if (m_fd < 0)
        return -ENODEV;

    m_notifier->start();

    dmx_pes_filter_params flt;
    flt.pes_type = DMX_PES_OTHER;
    flt.pid     = pid;
    flt.input   = DMX_IN_FRONTEND;
    flt.output  = DMX_OUT_TAP;
    
    flt.flags   = DMX_IMMEDIATE_START;

    res = ::ioctl(m_fd, DMX_SET_PES_FILTER, &flt);
    
    if (res)
        eWarning("PES filter: DMX_SET_PES_FILTER - %m");
    if (!res)
        m_active = 1;
    return res;
}

RESULT eDVBPESReader::stop()
{
    if (!m_active)
        return -1;

    m_active=0;
    ::ioctl(m_fd, DMX_STOP);
    m_notifier->stop();

    return 0;
}

RESULT eDVBPESReader::connectRead(const Slot2<void,const __u8*,int> &r, ePtr<eConnection> &conn)
{
    conn = new eConnection(this, m_read.connect(r));
    return 0;
}

class eDVBRecordFileThread: public eFilePushThreadRecorder
{
public:
    eDVBRecordFileThread(int packetsize, int bufferCount);
    ~eDVBRecordFileThread();
    void setTimingPID(int pid, int type);
    void startSaveMetaInformation(const std::string &filename);
    void stopSaveMetaInformation();
    int getLastPTS(pts_t &pts);
    void setTargetFD(int fd) { m_fd_dest = fd; }
    void enableAccessPoints(bool enable) { m_ts_parser.enableAccessPoints(enable); }
protected:
    int asyncWrite(int len);
    /* override */ int writeData(int len);
    /* override */ void flush();

    struct AsyncIO
    {
        struct aiocb aio;
        unsigned char* buffer;
        AsyncIO()
        {
            memset(&aio, 0, sizeof(struct aiocb));
            buffer = NULL;
        }
        int wait();
        int start(int fd, off_t offset, size_t nbytes, void* buffer);
        int poll(); // returns 1 if busy, 0 if ready, <0 on error return
        int cancel(int fd); // returns <0 on error, 0 cancelled, >0 bytes written?
    };
    eMPEGStreamParserTS m_ts_parser;
    off_t m_current_offset;
    int m_fd_dest;
    typedef std::vector<AsyncIO> AsyncIOvector;
    unsigned char* m_allocated_buffer;
    AsyncIOvector m_aio;
    AsyncIOvector::iterator m_current_buffer;
    std::vector<int> m_buffer_use_histogram;
};

eDVBRecordFileThread::eDVBRecordFileThread(int packetsize, int bufferCount):
    eFilePushThreadRecorder(
        /* buffer */ (unsigned char*) ::mmap(NULL, bufferCount * packetsize * 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, /*ignored*/-1, 0),
        /*buffersize*/ packetsize * 1024),
     m_ts_parser(packetsize),
     m_current_offset(0),
     m_fd_dest(-1),
     m_aio(bufferCount),
     m_current_buffer(m_aio.begin()),
     m_buffer_use_histogram(bufferCount+1, 0)
{
    if (m_buffer == MAP_FAILED)
        eFatal("Failed to allocate filepush buffer, contact MiLo\n");
    // m_buffer actually points to a data block large enough to hold ALL buffers. m_buffer will
    // move around during writes, so we must remember where the "head" is.
    m_allocated_buffer = m_buffer;
    // m_buffersize is thus the size of a single buffer in the queue
    // Initialize the buffer pointers
    int index = 0;
    for (AsyncIOvector::iterator it = m_aio.begin(); it != m_aio.end(); ++it)
    {
        it->buffer = m_allocated_buffer + (index * m_buffersize);
        ++index;
    }
}

eDVBRecordFileThread::~eDVBRecordFileThread()
{
    ::munmap(m_allocated_buffer, m_aio.size() * m_buffersize);
}

void eDVBRecordFileThread::setTimingPID(int pid, int type)
{
    m_ts_parser.setPid(pid, type);
}

void eDVBRecordFileThread::startSaveMetaInformation(const std::string &filename)
{
    m_ts_parser.startSave(filename);
}

void eDVBRecordFileThread::stopSaveMetaInformation()
{
    m_ts_parser.stopSave();
}

int eDVBRecordFileThread::getLastPTS(pts_t &pts)
{
    return m_ts_parser.getLastPTS(pts);
}

int eDVBRecordFileThread::AsyncIO::wait()
{
    if (aio.aio_buf != NULL) // Only if we had a request outstanding
    {
        while (aio_error(&aio) == EINPROGRESS)
        {
            eDebug("[eDVBRecordFileThread] Waiting for I/O to complete");
            struct aiocb* paio = &aio;
            int r = aio_suspend(&paio, 1, NULL);
            if (r < 0)
            {
                eDebug("[eDVBRecordFileThread] aio_suspend failed: %m");
                return -1;
            }
        }
        int r = aio_return(&aio);
        aio.aio_buf = NULL;
        if (r < 0)
        {
            eDebug("[eDVBRecordFileThread] wait: aio_return returned failure: %m");
            return -1;
        }
    }
    return 0;
}

int eDVBRecordFileThread::AsyncIO::cancel(int fd)
{
    int r = poll();
    if (r <= 0)
        return r; // Either no need to cancel, or error return
    eDebug("[eDVBRecordFileThread] cancelling");
    return aio_cancel(fd, &aio);
}

int eDVBRecordFileThread::AsyncIO::poll()
{
    if (aio.aio_buf == NULL)
        return 0;
    if (aio_error(&aio) == EINPROGRESS)
    {
        return 1;
    }
    int r = aio_return(&aio);
    aio.aio_buf = NULL;
    if (r < 0)
    {
        eDebug("[eDVBRecordFileThread] poll: aio_return returned failure: %m");
        return -1;
    }
    return 0;
}

int eDVBRecordFileThread::AsyncIO::start(int fd, off_t offset, size_t nbytes, void* buffer)
{
    memset(&aio, 0, sizeof(struct aiocb)); // Documentation says "zero it before call".
    aio.aio_fildes = fd;
    aio.aio_nbytes = nbytes;
    aio.aio_offset = offset;   // Offset can be omitted with O_APPEND
    aio.aio_buf = buffer;
    return aio_write(&aio);
}

int eDVBRecordFileThread::asyncWrite(int len)
{
#ifdef SHOW_WRITE_TIME
    struct timeval starttime;
    struct timeval now;
    suseconds_t diff;
    gettimeofday(&starttime, NULL);
#endif

    m_ts_parser.parseData(m_current_offset, m_buffer, len);

#ifdef SHOW_WRITE_TIME
    gettimeofday(&now, NULL);
    diff = (1000000 * (now.tv_sec - starttime.tv_sec)) + now.tv_usec - starttime.tv_usec;
    eDebug("[eFilePushThreadRecorder] m_ts_parser.parseData: %9u us", (unsigned int)diff);
    gettimeofday(&starttime, NULL);
#endif
    
    int r = m_current_buffer->start(m_fd_dest, m_current_offset, len, m_buffer);
    if (r < 0)
    {
        eDebug("[eDVBRecordFileThread] aio_write failed: %m");
        return r;
    }
    m_current_offset += len;

#ifdef SHOW_WRITE_TIME
    gettimeofday(&now, NULL);
    diff = (1000000 * (now.tv_sec - starttime.tv_sec)) + now.tv_usec - starttime.tv_usec;
    eDebug("[eFilePushThreadRecorder] aio_write: %9u us", (unsigned int)diff);
#endif
    // Count how many buffers are still "busy". Move backwards from current,
    // because they can reasonably be expected to finish in that order.
    AsyncIOvector::iterator i = m_current_buffer;
    r = i->poll();
    int busy_count = 0;
    while (r > 0)
    {
        ++busy_count;
        if (i == m_aio.begin())
            i = m_aio.end();
        --i;
        if (i == m_current_buffer)
        {
            eDebug("[eFilePushThreadRecorder] Warning: All write buffers busy");
            break;
        }
        r = i->poll();
        if (r < 0)
            return r;
    }
    ++m_buffer_use_histogram[busy_count];

    ++m_current_buffer;
    if (m_current_buffer == m_aio.end())
        m_current_buffer = m_aio.begin();
    m_buffer = m_current_buffer->buffer;
    return len;
}

int eDVBRecordFileThread::writeData(int len)
{
    len = asyncWrite(len);
    if (len < 0)
        return len;
    // Wait for previous aio to complete on this buffer before returning
    int r = m_current_buffer->wait();
    if (r < 0)
        return -1;
    return len;
}

void eDVBRecordFileThread::flush()
{
    eDebug("[eDVBRecordFileThread] waiting for aio to complete");
    for (AsyncIOvector::iterator it = m_aio.begin(); it != m_aio.end(); ++it)
    {
        it->wait();
    }
    int bufferCount = m_aio.size();
    eDebug("[eDVBRecordFileThread] buffer usage histogram (%d buffers of %d kB)", bufferCount, m_buffersize>>10);
    for (int i=0; i <= bufferCount; ++i)
    {
        if (m_buffer_use_histogram[i] != 0) eDebug("     %2d: %6d", i, m_buffer_use_histogram[i]);
    }
    if (m_overflow_count)
    {
        eDebug("[eDVBRecordFileThread] Demux buffer overflows: %d", m_overflow_count);
    }
    if (m_fd_dest >= 0)
    {
        posix_fadvise(m_fd_dest, 0, 0, POSIX_FADV_DONTNEED);
    }
}

class eDVBRecordStreamThread: public eDVBRecordFileThread
{
public:
    eDVBRecordStreamThread(int packetsize):
        eDVBRecordFileThread(packetsize, /*bufferCount*/ 4)
    {
    }
protected:
    int writeData(int len)
    {
        len = asyncWrite(len);
        if (len < 0)
            return len;
        // Cancel aio on this buffer before returning, streams should not be held up. So we CANCEL
        // any request that hasn't finished on the second round.
        int r = m_current_buffer->cancel(m_fd_dest);
        switch (r)
        {
            //case 0: // that's one of these two:
            case AIO_CANCELED:
            case AIO_ALLDONE:
                break;
            case AIO_NOTCANCELED:
                eDebug("[eDVBRecordStreamThread] failed to cancel, killing all waiting IO");
                aio_cancel(m_fd_dest, NULL);
                // Poll all open requests, because they are all in error state now.
                for (AsyncIOvector::iterator it = m_aio.begin(); it != m_aio.end(); ++it)
                {
                    it->poll();
                }
                break;
            case -1:
                eDebug("[eDVBRecordStreamThread] failed: %m");
                return r;
        }
        // we want to have a consistent state, so wait for completion, just to be sure
        r = m_current_buffer->wait();
        if (r < 0)
        {
            eDebug("[eDVBRecordStreamThread] wait failed: %m");
            return -1;
        }
        return len;
    }
    void flush()
    {
        eDebug("[eDVBRecordStreamThread] cancelling aio");
        switch (aio_cancel(m_fd_dest, NULL))
        {
            case AIO_CANCELED:
                eDebug("[eDVBRecordStreamThread] ok");
                break;
            case AIO_NOTCANCELED:
                eDebug("[eDVBRecordStreamThread] not all cancelled");
                break;
            case AIO_ALLDONE:
                eDebug("[eDVBRecordStreamThread] all done");
                break;
            case -1:
                eDebug("[eDVBRecordStreamThread] failed: %m");
                break;
            default:
                eDebug("[eDVBRecordStreamThread] unexpected return code");
                break;
        }
        // Call inherited flush to clean up the rest.
        eDVBRecordFileThread::flush();
    }
};


DEFINE_REF(eDVBTSRecorder);

eDVBTSRecorder::eDVBTSRecorder(eDVBDemux *demux, int packetsize, bool streaming):
    m_demux(demux),
    m_running(0),
    m_target_fd(-1),
    m_thread(streaming ? new eDVBRecordStreamThread(packetsize) : new eDVBRecordFileThread(packetsize, recordingBufferCount)),
    m_packetsize(packetsize)
{
    CONNECT(m_thread->m_event, eDVBTSRecorder::filepushEvent);
}

eDVBTSRecorder::~eDVBTSRecorder()
{
    stop();
    delete m_thread;
}

RESULT eDVBTSRecorder::start()
{
    std::map<int,int>::iterator i(m_pids.begin());

    if (m_running)
        return -1;
    
    if (m_target_fd == -1)
        return -2;

    if (i == m_pids.end())
        return -3;

    char filename[128];
    snprintf(filename, 128, "/dev/dvb/adapter%d/demux%d", m_demux->adapter, m_demux->demux);

    m_source_fd = ::open(filename, O_RDONLY);
    
    if (m_source_fd < 0)
    {
        eDebug("FAILED to open demux (%s) in ts recoder (%m)", filename);
        return -3;
    }

    setBufferSize(1024*1024);

    dmx_pes_filter_params flt;
    flt.pes_type = DMX_PES_OTHER;
    flt.output  = DMX_OUT_TSDEMUX_TAP;
    flt.pid     = i->first;
    ++i;
    flt.input   = DMX_IN_FRONTEND;
    flt.flags   = 0;
    int res = ::ioctl(m_source_fd, DMX_SET_PES_FILTER, &flt);
    if (res)
    {
        eDebug("DMX_SET_PES_FILTER: %m");
        ::close(m_source_fd);
        m_source_fd = -1;
        return -3;
    }
    
    ::ioctl(m_source_fd, DMX_START);

    if (!m_target_filename.empty())
        m_thread->startSaveMetaInformation(m_target_filename);
    
    m_thread->start(m_source_fd);
    m_running = 1;

    while (i != m_pids.end()) {
        startPID(i->first);
        ++i;
    }

    return 0;
}

RESULT eDVBTSRecorder::setBufferSize(int size)
{
    int res = ::ioctl(m_source_fd, DMX_SET_BUFFER_SIZE, size);
    if (res < 0)
        eDebug("eDVBTSRecorder DMX_SET_BUFFER_SIZE failed(%m)");
    return res;
}

RESULT eDVBTSRecorder::addPID(int pid)
{
    if (m_pids.find(pid) != m_pids.end())
        return -1;
    
    m_pids.insert(std::pair<int,int>(pid, -1));
    if (m_running)
        startPID(pid);
    return 0;
}

RESULT eDVBTSRecorder::removePID(int pid)
{
    if (m_pids.find(pid) == m_pids.end())
        return -1;
        
    if (m_running)
        stopPID(pid);
    
    m_pids.erase(pid);
    return 0;
}

RESULT eDVBTSRecorder::setTimingPID(int pid, int type)
{
    m_thread->setTimingPID(pid, type);
    return 0;
}

RESULT eDVBTSRecorder::setTargetFD(int fd)
{
    m_target_fd = fd;
    m_thread->setTargetFD(fd);
    return 0;
}

RESULT eDVBTSRecorder::setTargetFilename(const std::string& filename)
{
    m_target_filename = filename;
    return 0;
}

RESULT eDVBTSRecorder::enableAccessPoints(bool enable)
{
    m_thread->enableAccessPoints(enable);
    return 0;
}

RESULT eDVBTSRecorder::setBoundary(off_t max)
{
    return -1; // not yet implemented
}

RESULT eDVBTSRecorder::stop()
{
    int state=3;

    for (std::map<int,int>::iterator i(m_pids.begin()); i != m_pids.end(); ++i)
        stopPID(i->first);

    if (!m_running)
        return -1;

    /* workaround for record thread stop */
    if (m_source_fd >= 0)
    {
        if (::ioctl(m_source_fd, DMX_STOP) < 0)
            perror("DMX_STOP");
        else
            state &= ~1;

        if (::close(m_source_fd) < 0)
            perror("close");
        else
            state &= ~2;
        m_source_fd = -1;
    }

    m_thread->stop();

    if (state & 3)
    {
        if (m_source_fd >= 0)
        {
            ::close(m_source_fd);
            m_source_fd = -1;
        }
    }

    m_running = 0;

    m_thread->stopSaveMetaInformation();
    return 0;
}

RESULT eDVBTSRecorder::getCurrentPCR(pts_t &pcr)
{
    if (!m_running)
        return 0;
    if (!m_thread)
        return 0;
        /* XXX: we need a lock here */

            /* we don't filter PCR data, so just use the last received PTS, which is not accurate, but better than nothing */
    return m_thread->getLastPTS(pcr);
}

RESULT eDVBTSRecorder::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &conn)
{
    conn = new eConnection(this, m_event.connect(event));
    return 0;
}

RESULT eDVBTSRecorder::startPID(int pid)
{
    while(true) {
        __u16 p = pid;
        if (::ioctl(m_source_fd, DMX_ADD_PID, &p) < 0) {
            perror("DMX_ADD_PID");
            if (errno == EAGAIN || errno == EINTR) {
                eDebug("retry!");
                continue;
            }
        } else
            m_pids[pid] = 1;
        break;
    }
    return 0;
}

void eDVBTSRecorder::stopPID(int pid)
{
    if (m_pids[pid] != -1)
    {
        while(true) {
            __u16 p = pid;
            if (::ioctl(m_source_fd, DMX_REMOVE_PID, &p) < 0) {
                perror("DMX_REMOVE_PID");
                if (errno == EAGAIN || errno == EINTR) {
                    eDebug("retry!");
                    continue;
                }
            }
            break;
        }
    }
    m_pids[pid] = -1;
}

void eDVBTSRecorder::filepushEvent(int event)
{
    switch (event)
    {
    case eFilePushThread::evtWriteError:
        m_event(eventWriteError);
        break;
    }
}
 
AW: Testkernel für User mit öfter auftrettenden zucken und aufhängen der Box

:D meinte eigentlich ne Erklärung, was es macht, weil ich außer das, dass es sich um eine C++ Datei handelt, damit nichts anfangen kann bzw. konnte
 
AW: Testkernel für User mit öfter auftrettenden zucken und aufhängen der Box

ja meinste denn ich ^^ ich kann dir das genauso wenig erklären, fackt ist das einige buffer gesetzt und verwendet werden für irgend was , was mit dem stream passiert, was genau, keine ahnung , hilft wohl nur probieren den ich glaub keiner kann dir das halbwegs verständlich irgend wie erklären ( zumindest von dennen die das verstehen sollten )
 
AW: Testkernel für User mit öfter auftrettenden zucken und aufhängen der Box

mich hat demix völlig verwirrt, hätte drauf kommen müssen, dass es sich um demux handelt, ich sollte die Dinge nicht so genau nehmen :P
 
AW: Testkernel für User mit öfter auftrettenden zucken und aufhängen der Box

axo ^^ ja klar die DEMUX ^^ hoppla sorry
 
AW: Testkernel für User mit öfter auftrettenden zucken und aufhängen der Box

Hallo, habe meinen ursprünglichen Post in den Thread "Aktuelles Duck-Trick RAMFS Release **Support Thread**" kopiert, da die Fragen eher dorthin passen.
Sorry für die Verwirrung.
 
Zuletzt bearbeitet:
AW: Testkernel für User mit öfter auftrettenden zucken und aufhängen der Box

Also ich hab ja von der Materie wenig Ahnung, kann aber sagen das ich immer mit extremen Rucklern zu kämpfen hatte bis ich den externen Kartenleser geholt habe. Einige Oscam versionen musste ich auch durchtesten und habe nun eigentlich gar keine Ruckler mehr. Eigentlich, weil sie nur noch auf bestimmten Programmen kommen, die ich aber nicht so oft bzw so lange sehe.

Soweit ich das nach mehreren Monaten testen sagen kann betrifft das "NatGeo Wild", "National Geographic" und vielleicht noch 1 oder 2 die ich so gut wie nie sehe. Die laufen eine ganze Weile ruckelfrei und dann fängt es irgenwann an und wird immer schlimmer bis man nur noch Geruckel hat.

Ich kann mir einfach nicht vorstellen, das das an dem Kernel liegt. Wobei, wie gesagt ich bin da weit von Experte entfernt. Ist auf diesen Sendern irgendwas anders als auf anderen? Ist der Empfang auf dem Transponder schlechter als auf anderen? Oder geht das doch über mein Vorstellungsvermögen?
 
AW: Testkernel für User mit öfter auftrettenden zucken und aufhängen der Box

naja der Kernel beinhalltet ja nicht nur diverse Treiber und schnittstellen für solche , er verwalltet ja auh den "virtuellen memory bereich" um es mal möglichst einfach zu sagen, in diesen bereich lagert das system später alle bilder zwischen und das hab ich geändert, da wir wenig speicher haben geht das nicht anders und um auch schnell genug alles zu verarbeiten liegts eben im ram ( stickword Bigphysarea ) es ist halt, finde ich, recht schwierig das gesunde mittelmass zu finden um auch dem system noch genug zu lassen später, und durch das ganze ramfs gedöhns brauchen wa für die installation eh etwas mehr ram um unser image in diesen zu kopieren um anschliessend den stick zu formatieren und das image wider zurück zu spielen, das alles zusammen macht den kahl eben fett ;) ob das nun damit zusammen hängt oder doch mit dem smartcard reader oder was auch immer kann ich dir aktuell auch noch nicht sagen, freezer hab ich von anbegin her nicht alledings benutz ich auch keine Karte im Vip, hab auch keine HDD dran da ich alles über Netzwerk mache , was der ausschlaggebende grund dafür sein könnte, ebenso kann es auch am usb port liegen, den benutz ich zwar, aber nur fürs system und nix weiter
 
AW: Testkernel für User mit öfter auftrettenden zucken und aufhängen der Box

Mich wundert jetzt halt das es mit dem externen Reader nur ein paar Programme bei mir betrifft. Alle anderen laufen vollkommen ohne Probleme und das seit Monaten. Auf Nation Geo wild und National Geographic kommen die Freezer aber und das jedesmal, man muss nur lange genug warten. Da denk ich mir als Laie halt das irgendwas an diesen Sendern anders sein muss als bei anderen. Vielleicht haben sie ein anderes Format und brauchen daher mehr Speicher oder so, keine Ahnung.

Danke nochmal für die ganze Mühe und Arbeit die du dir machst.
 
Zurück
Oben