X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=blobdiff_plain;f=lib%2Fdvb%2Ftstools.cpp;h=e93cfc0afb78f3379ecb28f43001d9d53c91d7d2;hp=d5ad24940714a3d4c048f48622d7c36ea1bc3272;hb=907bc063a13369ae1ab84f92f9ffe12d511de1ec;hpb=a302e0a778e1ea30b76956fd7469cf554eb0fc20 diff --git a/lib/dvb/tstools.cpp b/lib/dvb/tstools.cpp old mode 100644 new mode 100755 index d5ad249..379df9b --- a/lib/dvb/tstools.cpp +++ b/lib/dvb/tstools.cpp @@ -7,7 +7,6 @@ #include eDVBTSTools::eDVBTSTools() - :m_file_lock(true) { m_pid = -1; m_maxrange = 256*1024; @@ -23,19 +22,39 @@ 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; + + if (f->open(filename, 1) < 0) + return -1; + + setSource(src, nostreaminfo ? NULL : 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()) @@ -45,19 +64,14 @@ int eDVBTSTools::openFile(const char *filename, int nostreaminfo) // eDebug("no recorded stream information available"); m_use_streaminfo = 0; } - - m_samples_taken = 0; - eSingleLocker l(m_file_lock); - if (m_file.open(filename, 1) < 0) - return -1; - return 0; + m_samples_taken = 0; } void eDVBTSTools::closeFile() { - eSingleLocker l(m_file_lock); - m_file.close(); + if (m_source) + closeSource(); } void eDVBTSTools::setSyncPID(int pid) @@ -77,31 +91,24 @@ 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 || !m_source->valid()) return -1; offset -= offset % 188; - eSingleLocker l(m_file_lock); - if (m_file.lseek(offset, SEEK_SET) < 0) - { - eDebug("lseek failed"); - return -1; - } - int left = m_maxrange; while (left >= 188) { unsigned char packet[188]; - if (m_file.read(packet, 188) != 188) + if (m_source->read(offset, packet, 188) != 188) { eDebug("read error"); break; } left -= 188; offset += 188; - + if (packet[0] != 0x47) { eDebug("resync"); @@ -111,8 +118,8 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed) if (packet[i] == 0x47) break; ++i; + --offset; } - offset = m_file.lseek(i - 188, SEEK_CUR); continue; } @@ -205,6 +212,8 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed) break; case 0x71: // AC3 / DTS break; + case 0x72: // DTS - HD + break; default: eDebug("skip unknwn stream_id_extension %02x\n", payload[9+offs]); continue; @@ -404,7 +413,7 @@ int eDVBTSTools::getNextAccessPoint(pts_t &ts, const pts_t &start, int direction void eDVBTSTools::calcBegin() { - if (!m_file.valid()) + if (!m_source || !m_source->valid()) return; if (!(m_begin_valid || m_futile)) @@ -419,11 +428,10 @@ void eDVBTSTools::calcBegin() void eDVBTSTools::calcEnd() { - if (!m_file.valid()) + if (!m_source || !m_source->valid()) return; - eSingleLocker l(m_file_lock); - off_t end = m_file.lseek(0, SEEK_END); + off_t end = m_source->lseek(0, SEEK_END); if (llabs(end - m_last_filelength) > 1*1024*1024) { @@ -573,31 +581,28 @@ 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 || !m_source->valid()) { eDebug(" file not valid"); return -1; } - eSingleLocker l(m_file_lock); - if (m_file.lseek(0, SEEK_SET) < 0) - { - eDebug("seek failed"); - return -1; - } + off_t position=0; int left = 5*1024*1024; while (left >= 188) { unsigned char packet[188]; - if (m_file.read(packet, 188) != 188) + int ret = m_source->read(position, packet, 188); + if (ret != 188) { eDebug("read error"); break; } left -= 188; - + position += 188; + if (packet[0] != 0x47) { int i = 0; @@ -605,12 +610,11 @@ int eDVBTSTools::findPMT(int &pmt_pid, int &service_id) { if (packet[i] == 0x47) break; + --position; ++i; } - m_file.lseek(i - 188, SEEK_CUR); continue; } - int pid = ((packet[1] << 8) | packet[2]) & 0x1FFF; int pusi = !!(packet[1] & 0x40); @@ -644,11 +648,12 @@ 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) +int eDVBTSTools::findFrame(off_t &_iframe_offset, off_t &_new_offset, size_t &len, int &direction, int frame_types) { - off_t offset = _offset; + off_t offset = _iframe_offset; int nr_frames = 0; -// eDebug("trying to find iFrame at %llx", offset); + int is_mpeg = 0; +// eDebug("trying to find iFrame at %lld", offset); if (!m_use_streaminfo) { @@ -664,7 +669,13 @@ int eDVBTSTools::findFrame(off_t &_offset, size_t &len, int &direction, int fram while (1) { - if (m_streaminfo.getStructureEntry(offset, data, (direction == 0) ? 1 : 0)) + int res = -1; + if(direction<0) + res = m_streaminfo.getStructureEntry_prev(offset, data); + else + res = m_streaminfo.getStructureEntry_next(offset, data); + + if (res) { eDebug("getting structure info for origin offset failed."); return -1; @@ -677,10 +688,17 @@ int eDVBTSTools::findFrame(off_t &_offset, size_t &len, int &direction, int fram /* 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 */ + int is_start = 0; + if ((data & 0xE0FF) == 0x0009) /* H.264 NAL unit access delimiter with I-frame*/ + is_start =1; + else if ((data & 0xE07E) == 0x0046) /* H.265 NAL unit access delimiter with I-frame*/ + is_start = 1; + else if((data & 0x3800FF) == 0x080000) /* MPEG2 picture start code with I-frame */ + { + is_start =1; + is_mpeg =1; + } + int is_frame = ((data & 0xFF) == 0x0009) || ((data & 0x7E) == 0x0046) || ((data & 0xFF) == 0x00); /* H.264 UAD or H.265 UAD or MPEG2 start code */ if (is_frame) { @@ -689,7 +707,7 @@ int eDVBTSTools::findFrame(off_t &_offset, size_t &len, int &direction, int fram else ++nr_frames; } -// eDebug("%08llx@%llx -> %d, %d", data, offset, is_start, nr_frames); +// eDebug("%08llx@%llu -> %d, %d (I-frame)", data, offset, is_start, nr_frames); if (is_start) break; @@ -698,11 +716,29 @@ int eDVBTSTools::findFrame(off_t &_offset, size_t &len, int &direction, int fram else if (direction == +1) direction = 0; } - /* let's find the next frame after the given offset */ + off_t iframe_start = offset; off_t start = offset; +#if 0 + /* backtrack to find the previous sequence start, in case of MPEG2 */ + if ((data & 0xFF) == 0x00) { + do { + --start; + if (m_streaminfo.getStructureEntry(start, data, 0)) + { + eDebug("get previous failed"); + return -1; + } + } while (((data & 0xFF) != 9) && ((data & 0xFF) != 0x00) && ((data & 0xFF) != 0xB3)); /* sequence start or previous frame */ + if ((data & 0xFF) != 0xB3) + start = offset; /* Failed to find corresponding sequence start, so never mind */ + } + +#endif + + /* let's find the next frame after the given offset */ do { - if (m_streaminfo.getStructureEntry(offset, data, 1)) + if (m_streaminfo.getStructureEntry_next(offset, data)) { eDebug("get next failed"); return -1; @@ -712,29 +748,57 @@ int eDVBTSTools::findFrame(off_t &_offset, size_t &len, int &direction, int fram 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 */ +// eDebug("%08llx@%llu (next frame)", data, offset); + } while (((data & 0xFF) != 9) && ((data & 0x7E) != 0x46) && ((data & 0xFF) != 0x00)); /* next frame */ + if (is_mpeg) //MPEG2 picture start code with I-frame + { + off_t sequence_offset = start; + unsigned long long sequence_data; + int is_sequence =0; + int frame_length = (nr_frames<0) ? -nr_frames: nr_frames; + while(frame_length) + { +// --start; + if (m_streaminfo.getStructureEntry_prev(sequence_offset, sequence_data)) + { + eDebug("get previous failed"); + return -1; + } + if ((sequence_data & 0xFF) == 0xB3) /* sequence start or previous frame */ + is_sequence = 1; + if(((sequence_data & 0xFF) == 0x0009) || ((sequence_data & 0xFF) == 0x00)) /* H.264 UAD or MPEG2 start code */ + --frame_length; +// eDebug("[findFrame] %08llx@%llu -> %d, %d (sequence)", sequence_data, sequence_offset, is_sequence, frame_length); + if(is_sequence) /* get sequence frame */ + break; + } + start = sequence_offset; + } +#if 0 /* align to TS pkt start */ -// start = start - (start % 188); -// offset = offset - (offset % 188); + start = start - (start % 188); + offset = offset - (offset % 188); +#endif len = offset - start; - _offset = start; + _new_offset = start; + _iframe_offset = iframe_start; direction = nr_frames; -// eDebug("result: offset=%llx, len: %ld", offset, (int)len); +// eDebug("result: start=%lld, iframe= %lld, next=%lld, len: %ld",start, iframe_start ,offset, (long int)len); return 0; } int eDVBTSTools::findNextPicture(off_t &offset, size_t &len, int &distance, int frame_types) { int nr_frames, direction; -// eDebug("trying to move %d frames at %llx", distance, offset); +// eDebug("trying to move %d frames at %llu", distance, offset); frame_types = frametypeI; /* TODO: intelligent "allow IP frames when not crossing an I-Frame */ off_t new_offset = offset; size_t new_len = len; + off_t iframe_offset = new_offset; int first = 1; if (distance > 0) { @@ -748,7 +812,7 @@ int eDVBTSTools::findNextPicture(off_t &offset, size_t &len, int &distance, int while (distance > 0) { int dir = direction; - if (findFrame(new_offset, new_len, dir, frame_types)) + if (findFrame(iframe_offset, new_offset, new_len, dir, frame_types)) { // eDebug("findFrame failed!\n"); return -1; @@ -756,7 +820,7 @@ int eDVBTSTools::findNextPicture(off_t &offset, size_t &len, int &distance, int distance -= abs(dir); -// eDebug("we moved %d, %d to go frames (now at %llx)", dir, distance, new_offset); +// eDebug("we moved %d, %d to go frames (now at %llu)", dir, distance, new_offset); if (distance >= 0 || direction == 0) { @@ -764,7 +828,7 @@ int eDVBTSTools::findNextPicture(off_t &offset, size_t &len, int &distance, int offset = new_offset; len = new_len; nr_frames += abs(dir); - } + } else if (first) { first = 0; offset = new_offset; @@ -772,7 +836,6 @@ int eDVBTSTools::findNextPicture(off_t &offset, size_t &len, int &distance, int nr_frames += abs(dir) + distance; // never jump forward during rewind } } - distance = (direction < 0) ? -nr_frames : nr_frames; // eDebug("in total, we moved %d frames", nr_frames);