X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=blobdiff_plain;f=lib%2Fdvb%2Ftstools.cpp;h=2c2618372dd0ab94105d5c5a68ed652321014bb1;hp=bd7ebce2843be12e4bef4d6a1f12262b47555215;hb=b64b791cb481944585fceaf5bcac9e2c699dbeb0;hpb=89a55fb89dbfb1d78255b48a50a8b4d28e83cdef diff --git a/lib/dvb/tstools.cpp b/lib/dvb/tstools.cpp index bd7ebce..2c26183 100644 --- a/lib/dvb/tstools.cpp +++ b/lib/dvb/tstools.cpp @@ -7,6 +7,7 @@ #include eDVBTSTools::eDVBTSTools() + :m_file_lock(true) { m_pid = -1; m_maxrange = 256*1024; @@ -32,7 +33,10 @@ int eDVBTSTools::openFile(const char *filename, int nostreaminfo) closeFile(); if (!nostreaminfo) - m_streaminfo.load((std::string(filename) + ".ap").c_str()); + { + eDebug("loading streaminfo for %s", filename); + m_streaminfo.load(filename); + } if (!m_streaminfo.empty()) m_use_streaminfo = 1; @@ -44,6 +48,7 @@ int eDVBTSTools::openFile(const char *filename, int nostreaminfo) m_samples_taken = 0; + eSingleLocker l(m_file_lock); if (m_file.open(filename, 1) < 0) return -1; return 0; @@ -51,6 +56,7 @@ int eDVBTSTools::openFile(const char *filename, int nostreaminfo) void eDVBTSTools::closeFile() { + eSingleLocker l(m_file_lock); m_file.close(); } @@ -68,13 +74,15 @@ void eDVBTSTools::setSearchRange(int maxrange) int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed) { if (m_use_streaminfo) - return m_streaminfo.getPTS(offset, pts); + if (!m_streaminfo.getPTS(offset, pts)) + return 0; if (!m_file.valid()) return -1; offset -= offset % 188; - + + eSingleLocker l(m_file_lock); if (m_file.lseek(offset, SEEK_SET) < 0) { eDebug("lseek failed"); @@ -141,9 +149,9 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed) payload = packet + 4; - if (m_pid >= 0) +/* if (m_pid >= 0) if (pid != m_pid) - continue; + continue; */ if (!pusi) continue; @@ -183,7 +191,8 @@ int eDVBTSTools::fixupPTS(const off_t &offset, pts_t &now) { if (m_use_streaminfo) { - return m_streaminfo.fixupPTS(offset, now); + if (!m_streaminfo.fixupPTS(offset, now)) + return 0; } else { /* for the simple case, we assume one epoch, with up to one wrap around in the middle. */ @@ -350,7 +359,8 @@ void eDVBTSTools::calcEnd() { if (!m_file.valid()) return; - + + eSingleLocker l(m_file_lock); off_t end = m_file.lseek(0, SEEK_END); if (llabs(end - m_last_filelength) > 1*1024*1024) @@ -499,6 +509,7 @@ int eDVBTSTools::findPMT(int &pmt_pid, int &service_id) return -1; } + eSingleLocker l(m_file_lock); if (m_file.lseek(0, SEEK_SET) < 0) { eDebug("seek failed"); @@ -562,3 +573,127 @@ int eDVBTSTools::findPMT(int &pmt_pid, int &service_id) return -1; } + +int eDVBTSTools::findFrame(off_t &_offset, size_t &len, int &direction, int frame_types) +{ + off_t offset = _offset; + int nr_frames = 0; +// eDebug("trying to find iFrame at %llx", offset); + + if (!m_use_streaminfo) + { +// eDebug("can't get next iframe without streaminfo"); + return -1; + } + + /* let's find the iframe before the given offset */ + unsigned long long data; + + if (direction < 0) + offset--; + + while (1) + { + if (m_streaminfo.getStructureEntry(offset, data, (direction == 0) ? 1 : 0)) + { + eDebug("getting structure info for origin offset failed."); + return -1; + } + if (offset == 0x7fffffffffffffffLL) /* eof */ + { + eDebug("reached eof"); + return -1; + } + /* data is usually the start code in the lower 8 bit, and the next byte <<8. we extract the picture type from there */ + /* we know that we aren't recording startcode 0x09 for mpeg2, so this is safe */ + /* TODO: check frame_types */ + int is_start = (data & 0xE0FF) == 0x0009; /* H.264 NAL unit access delimiter with I-frame*/ + is_start |= (data & 0x3800FF) == 0x080000; /* MPEG2 picture start code with I-frame */ + + int is_frame = ((data & 0xFF) == 0x0009) || ((data & 0xFF) == 0x00); /* H.264 UAD or MPEG2 start code */ + + if (is_frame) + { + if (direction < 0) + --nr_frames; + else + ++nr_frames; + } +// eDebug("%08llx@%llx -> %d, %d", data, offset, is_start, nr_frames); + if (is_start) + break; + + if (direction == -1) + --offset; /* move to previous entry */ + else if (direction == +1) + direction = 0; + } + /* let's find the next frame after the given offset */ + off_t start = offset; + + do { + if (m_streaminfo.getStructureEntry(offset, data, 1)) + { + eDebug("get next failed"); + return -1; + } + if (offset == 0x7fffffffffffffffLL) /* eof */ + { + eDebug("reached eof (while looking for end of iframe)"); + return -1; + } +// eDebug("%08llx@%llx (next)", data, offset); + } while (((data & 0xFF) != 9) && ((data & 0xFF) != 0x00)); /* next frame */ + + /* align to TS pkt start */ +// start = start - (start % 188); +// offset = offset - (offset % 188); + + len = offset - start; + _offset = start; + direction = nr_frames; +// eDebug("result: offset=%llx, len: %ld", offset, (int)len); + return 0; +} + +int eDVBTSTools::findNextPicture(off_t &offset, size_t &len, int &distance, int frame_types) +{ + int nr_frames = 0; +// 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; + + while (distance > 0) + { + int dir = direction; + if (findFrame(new_offset, new_len, dir, frame_types)) + { +// eDebug("findFrame failed!\n"); + return -1; + } + + distance -= abs(dir); + +// eDebug("we moved %d, %d to go frames (now at %llx)", dir, distance, new_offset); + + if (distance >= 0 || first) + { + first = 0; + offset = new_offset; + len = new_len; + nr_frames += abs(dir); + } + } + + distance = (direction < 0) ? -nr_frames : nr_frames; +// eDebug("in total, we moved %d frames", nr_frames); + + return 0; +}