Merge branch 'bug_355_seek_fixes'
authorghost <andreas.monzner@multimedia-labs.de>
Wed, 23 Dec 2009 15:22:45 +0000 (16:22 +0100)
committerghost <andreas.monzner@multimedia-labs.de>
Wed, 23 Dec 2009 15:22:45 +0000 (16:22 +0100)
1  2 
lib/dvb/tstools.cpp

diff --combined lib/dvb/tstools.cpp
@@@ -7,6 -7,7 +7,7 @@@
  #include <stdio.h>
  
  eDVBTSTools::eDVBTSTools()
+       :m_file_lock(true)
  {
        m_pid = -1;
        m_maxrange = 256*1024;
@@@ -47,6 -48,7 +48,7 @@@ int eDVBTSTools::openFile(const char *f
        
        m_samples_taken = 0;
  
+       eSingleLocker l(m_file_lock);
        if (m_file.open(filename, 1) < 0)
                return -1;
        return 0;
@@@ -54,6 -56,7 +56,7 @@@
  
  void eDVBTSTools::closeFile()
  {
+       eSingleLocker l(m_file_lock);
        m_file.close();
  }
  
@@@ -78,7 -81,8 +81,8 @@@ int eDVBTSTools::getPTS(off_t &offset, 
                return -1;
  
        offset -= offset % 188;
-       
+       eSingleLocker l(m_file_lock);
        if (m_file.lseek(offset, SEEK_SET) < 0)
        {
                eDebug("lseek failed");
                                        pts |= ((unsigned long long)(packet[ 9]&0xFF)) << 1;
                                        pts |= ((unsigned long long)(packet[10]&0x80)) >> 7;
                                        offset -= 188;
 -                                      eDebug("PCR  found at %llx: %16llx", offset, pts);
 +                                      eDebug("PCR %16llx found at %lld pid %02x (%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x)", pts, offset, pid, packet[0], packet[1], packet[2], packet[3], packet[4], packet[5], packet[6], packet[7], packet[8], packet[9], packet[10]);
                                        if (fixed && fixupPTS(offset, pts))
                                                return -1;
                                        return 0;
                } 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;
                        pts |= ((unsigned long long)(payload[13]&0xFE)) >> 1;
                        offset -= 188;
  
 -//                    eDebug("found pts %08llx at %08llx pid %02x stream: %02x", pts, offset, pid, payload[3]);
 -                      
 +                      eDebug("PTS %16llx found at %lld pid %02x stream: %02x", pts, offset, pid, payload[3]);
 +
                                /* convert to zero-based */
                        if (fixed && fixupPTS(offset, pts))
 -                                      return -1;
 +                              return -1;
                        return 0;
                }
        }
@@@ -271,13 -216,10 +275,13 @@@ int eDVBTSTools::fixupPTS(const off_t &
                        now -= pos;
                return 0;
        }
 +      eDebug("eDVBTSTools::fixupPTS failed!");
 +      return -1;
  }
  
  int eDVBTSTools::getOffset(off_t &offset, pts_t &pts, int marg)
  {
 +      eDebug("getOffset for pts 0x%llx", pts);
        if (m_use_streaminfo)
        {
                if (pts >= m_pts_end && marg > 0 && m_end_valid)
@@@ -417,7 -359,8 +421,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)
@@@ -502,8 -445,6 +507,8 @@@ void eDVBTSTools::takeSamples(
        m_samples_taken = 1;
        m_samples.clear();
        pts_t dummy;
 +      int retries=2;
 +
        if (calcLen(dummy) == -1)
                return;
        
                bytes_per_sample = 40*1024*1024;
  
        bytes_per_sample -= bytes_per_sample % 188;
 -      
 -      for (off_t offset = m_offset_begin; offset < m_offset_end; offset += bytes_per_sample)
 +
 +      eDebug("samples step %lld, pts begin %llx, pts end %llx, offs begin %lld, offs end %lld:",
 +              bytes_per_sample, m_pts_begin, m_pts_end, m_offset_begin, m_offset_end);
 +
 +      for (off_t offset = m_offset_begin; offset < m_offset_end;)
        {
                pts_t p;
 -              takeSample(offset, p);
 +              if (takeSample(offset, p) && retries--)
 +                      continue;
 +              retries = 2;
 +              offset += bytes_per_sample;
        }
        m_samples[0] = m_offset_begin;
        m_samples[m_pts_end - m_pts_begin] = m_offset_end;
 -      
 -//    eDebug("begin, end: %llx %llx", m_offset_begin, m_offset_end); 
  }
  
        /* returns 0 when a sample was taken. */
  int eDVBTSTools::takeSample(off_t off, pts_t &p)
  {
 +      off_t offset_org = off;
 +
        if (!eDVBTSTools::getPTS(off, p, 1))
        {
                        /* as we are happily mixing PTS and PCR values (no comment, please), we might
                        {
                                if ((l->second > off) || (u->second < off))
                                {
 -                                      eDebug("ignoring sample %llx %llx %llx (%lld %lld %lld)",
 +                                      eDebug("ignoring sample %lld %lld %lld (%llx %llx %llx)",
                                                l->second, off, u->second, l->first, p, u->first);
                                        return 1;
                                }
                        }
                }
  
 -              
 +              eDebug("adding sample %lld: pts 0x%llx -> pos %lld (diff %lld bytes)", offset_org, p, off, off-offset_org);
                m_samples[p] = off;
                return 0;
        }
 -      return 1;
 +      return -1;
  }
  
  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");
@@@ -722,23 -658,18 +728,23 @@@ int eDVBTSTools::findFrame(off_t &_offs
  
  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;
                
  //            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
                }
        }