X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=blobdiff_plain;f=lib%2Fdvb%2Ftstools.cpp;h=7739f60197e86ed385cbb7b556d8ef882af66153;hp=00a1da72a8e8e3fb328e21aaf2e3c28bfdb3b5a0;hb=2a0689a69ba995ec3adcf1cd6cc20146a6d4ef58;hpb=6987607629f68a8c47cbe9cf48f6a112b83468ec diff --git a/lib/dvb/tstools.cpp b/lib/dvb/tstools.cpp index 00a1da7..7739f60 100644 --- a/lib/dvb/tstools.cpp +++ b/lib/dvb/tstools.cpp @@ -22,19 +22,41 @@ eDVBTSTools::eDVBTSTools() m_futile = 0; } +void eDVBTSTools::closeSource() +{ + m_source = NULL; +} + eDVBTSTools::~eDVBTSTools() { - closeFile(); + closeSource(); } int eDVBTSTools::openFile(const char *filename, int nostreaminfo) { + eRawFile *f = new eRawFile(); + ePtr src = f; + + eSingleLocker l(f->getLock()); + + if (f->open(filename, 1) < 0) + return -1; + + setSource(src, filename); + + return 0; +} + +void eDVBTSTools::setSource(ePtr source, const char *stream_info_filename) +{ closeFile(); - - if (!nostreaminfo) + + m_source = source; + + if (stream_info_filename) { - eDebug("loading streaminfo for %s", filename); - m_streaminfo.load(filename); + eDebug("loading streaminfo for %s", stream_info_filename); + m_streaminfo.load(stream_info_filename); } if (!m_streaminfo.empty()) @@ -44,17 +66,16 @@ int eDVBTSTools::openFile(const char *filename, int nostreaminfo) // eDebug("no recorded stream information available"); m_use_streaminfo = 0; } - - m_samples_taken = 0; - if (m_file.open(filename, 1) < 0) - return -1; - return 0; + m_samples_taken = 0; } void eDVBTSTools::closeFile() { - m_file.close(); + if (m_source) { + eSingleLocker l(m_source->getLock()); + closeSource(); + } } void eDVBTSTools::setSyncPID(int pid) @@ -74,12 +95,16 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed) if (!m_streaminfo.getPTS(offset, pts)) return 0; - if (!m_file.valid()) + if (!m_source->valid()) return -1; offset -= offset % 188; - - if (m_file.lseek(offset, SEEK_SET) < 0) + + iDataSourcePositionRestorer r(m_source); + + eSingleLocker l(m_source->getLock()); + + if (m_source->lseek(offset, SEEK_SET) < 0) { eDebug("lseek failed"); return -1; @@ -90,7 +115,7 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed) while (left >= 188) { unsigned char packet[188]; - if (m_file.read(packet, 188) != 188) + if (m_source->read(packet, 188) != 188) { eDebug("read error"); break; @@ -108,7 +133,7 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed) break; ++i; } - offset = m_file.lseek(i - 188, SEEK_CUR); + offset = m_source->lseek(i - 188, SEEK_CUR); continue; } @@ -144,24 +169,83 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed) } else payload = packet + 4; - /* if (m_pid >= 0) if (pid != m_pid) continue; */ if (!pusi) continue; - - + /* somehow not a startcode. (this is invalid, since pusi was set.) ignore it. */ if (payload[0] || payload[1] || (payload[2] != 1)) continue; - + + if (payload[3] == 0xFD) + { // stream use extension mechanism defined in ISO 13818-1 Amendment 2 + if (payload[7] & 1) // PES extension flag + { + int offs = 0; + if (payload[7] & 0x80) // pts avail + offs += 5; + if (payload[7] & 0x40) // dts avail + offs += 5; + if (payload[7] & 0x20) // escr avail + offs += 6; + if (payload[7] & 0x10) // es rate + offs += 3; + if (payload[7] & 0x8) // dsm trickmode + offs += 1; + if (payload[7] & 0x4) // additional copy info + offs += 1; + if (payload[7] & 0x2) // crc + offs += 2; + if (payload[8] < offs) + continue; + uint8_t pef = payload[9+offs++]; // pes extension field + if (pef & 1) // pes extension flag 2 + { + if (pef & 0x80) // private data flag + offs += 16; + if (pef & 0x40) // pack header field flag + offs += 1; + if (pef & 0x20) // program packet sequence counter flag + offs += 2; + if (pef & 0x10) // P-STD buffer flag + offs += 2; + if (payload[8] < offs) + continue; + uint8_t stream_id_extension_len = payload[9+offs++] & 0x7F; + if (stream_id_extension_len >= 1) + { + if (payload[8] < (offs + stream_id_extension_len) ) + continue; + if (payload[9+offs] & 0x80) // stream_id_extension_bit (should not set) + continue; + switch (payload[9+offs]) + { + case 0x55 ... 0x5f: // VC-1 + break; + case 0x71: // AC3 / DTS + break; + default: + eDebug("skip unknwn stream_id_extension %02x\n", payload[9+offs]); + continue; + } + } + else + continue; + } + else + continue; + } + else + continue; + } /* drop non-audio, non-video packets because other streams can be non-compliant.*/ - if (((payload[3] & 0xE0) != 0xC0) && // audio - ((payload[3] & 0xF0) != 0xE0)) // video + else if (((payload[3] & 0xE0) != 0xC0) && // audio + ((payload[3] & 0xF0) != 0xE0)) // video continue; - + if (payload[7] & 0x80) /* PTS */ { pts = ((unsigned long long)(payload[ 9]&0xE)) << 29; @@ -341,7 +425,7 @@ int eDVBTSTools::getNextAccessPoint(pts_t &ts, const pts_t &start, int direction void eDVBTSTools::calcBegin() { - if (!m_file.valid()) + if (!m_source->valid()) return; if (!(m_begin_valid || m_futile)) @@ -356,10 +440,14 @@ void eDVBTSTools::calcBegin() void eDVBTSTools::calcEnd() { - if (!m_file.valid()) + if (!m_source->valid()) return; - - off_t end = m_file.lseek(0, SEEK_END); + + iDataSourcePositionRestorer r(m_source); + + eSingleLocker l(m_source->getLock()); + + off_t end = m_source->lseek(0, SEEK_END); if (llabs(end - m_last_filelength) > 1*1024*1024) { @@ -509,13 +597,17 @@ int eDVBTSTools::takeSample(off_t off, pts_t &p) int eDVBTSTools::findPMT(int &pmt_pid, int &service_id) { /* FIXME: this will be factored out soon! */ - if (!m_file.valid()) + if (!m_source->valid()) { eDebug(" file not valid"); return -1; } - if (m_file.lseek(0, SEEK_SET) < 0) + iDataSourcePositionRestorer r(m_source); + + eSingleLocker l(m_source->getLock()); + + if (m_source->lseek(0, SEEK_SET) < 0) { eDebug("seek failed"); return -1; @@ -526,7 +618,7 @@ int eDVBTSTools::findPMT(int &pmt_pid, int &service_id) while (left >= 188) { unsigned char packet[188]; - if (m_file.read(packet, 188) != 188) + if (m_source->read(packet, 188) != 188) { eDebug("read error"); break; @@ -542,7 +634,7 @@ int eDVBTSTools::findPMT(int &pmt_pid, int &service_id) break; ++i; } - m_file.lseek(i - 188, SEEK_CUR); + m_source->lseek(i - 188, SEEK_CUR); continue; } @@ -663,18 +755,23 @@ int eDVBTSTools::findFrame(off_t &_offset, size_t &len, int &direction, int fram int eDVBTSTools::findNextPicture(off_t &offset, size_t &len, int &distance, int frame_types) { - int nr_frames = 0; + int nr_frames, direction; // eDebug("trying to move %d frames at %llx", distance, offset); frame_types = frametypeI; /* TODO: intelligent "allow IP frames when not crossing an I-Frame */ - int direction = distance > 0 ? 0 : -1; - distance = abs(distance); - off_t new_offset = offset; size_t new_len = len; int first = 1; + if (distance > 0) { + direction = 0; + nr_frames = 0; + } else { + direction = -1; + nr_frames = -1; + distance = -distance+1; + } while (distance > 0) { int dir = direction; @@ -688,12 +785,18 @@ int eDVBTSTools::findNextPicture(off_t &offset, size_t &len, int &distance, int // eDebug("we moved %d, %d to go frames (now at %llx)", dir, distance, new_offset); - if (distance >= 0 || first) + if (distance >= 0 || direction == 0) { first = 0; offset = new_offset; len = new_len; nr_frames += abs(dir); + } + else if (first) { + first = 0; + offset = new_offset; + len = new_len; + nr_frames += abs(dir) + distance; // never jump forward during rewind } }