Ticket #11328: keep-first-keyframe-v4-v0.25.patch

File keep-first-keyframe-v4-v0.25.patch, 36.8 KB (added by jpoet, 7 years ago)
  • mythtv/libs/libmythtv/asirecorder.cpp

    diff --git a/mythtv/libs/libmythtv/asirecorder.cpp b/mythtv/libs/libmythtv/asirecorder.cpp
    index 830ac23..883d83b 100644
    a b void ASIRecorder::SetOption(const QString &name, int value) 
    6262        DTVRecorder::SetOption(name, value);
    6363}
    6464
     65void ASIRecorder::StartNewFile(void)
     66{
     67    // Make sure the first things in the file are a PAT & PMT
     68    HandleSingleProgramPAT(_stream_data->PATSingleProgram(), true);
     69    HandleSingleProgramPMT(_stream_data->PMTSingleProgram(), true);
     70}
     71
     72
    6573void ASIRecorder::run(void)
    6674{
    6775    if (!Open())
    void ASIRecorder::run(void) 
    99107    if (m_channel && (m_channel->GetSIStandard() == "dvb"))
    100108        _stream_data->AddListeningPID(DVB_TDT_PID);
    101109
    102     // Make sure the first things in the file are a PAT & PMT
    103     bool tmp = _wait_for_keyframe_option;
    104     _wait_for_keyframe_option = false;
    105     HandleSingleProgramPAT(_stream_data->PATSingleProgram());
    106     HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
    107     _wait_for_keyframe_option = tmp;
     110    StartNewFile();
    108111
    109112    _stream_data->AddAVListener(this);
    110113    _stream_data->AddWritingListener(this);
  • mythtv/libs/libmythtv/asirecorder.h

    diff --git a/mythtv/libs/libmythtv/asirecorder.h b/mythtv/libs/libmythtv/asirecorder.h
    index f29ccc5..06c5bc4 100644
    a b class ASIRecorder : public DTVRecorder 
    6868    bool Open(void);
    6969    bool IsOpen(void) const;
    7070    void Close(void);
     71    void StartNewFile(void);
    7172
    7273  private:
    7374    ASIChannel       *m_channel;
  • mythtv/libs/libmythtv/cetonrecorder.cpp

    diff --git a/mythtv/libs/libmythtv/cetonrecorder.cpp b/mythtv/libs/libmythtv/cetonrecorder.cpp
    index f7aacf4..b923770 100644
    a b void CetonRecorder::Close(void) 
    4646    LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- end");
    4747}
    4848
     49void CetonRecorder::StartNewFile(void)
     50{
     51    // Make sure the first things in the file are a PAT & PMT
     52    HandleSingleProgramPAT(_stream_data->PATSingleProgram(), true);
     53    HandleSingleProgramPMT(_stream_data->PMTSingleProgram(), true);
     54}
     55
    4956void CetonRecorder::run(void)
    5057{
    5158    LOG(VB_RECORD, LOG_INFO, LOC + "run -- begin");
    void CetonRecorder::run(void) 
    6572        recordingWait.wakeAll();
    6673    }
    6774
    68     // Make sure the first things in the file are a PAT & PMT
    69     bool tmp = _wait_for_keyframe_option;
    70     _wait_for_keyframe_option = false;
    71     HandleSingleProgramPAT(_stream_data->PATSingleProgram());
    72     HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
    73     _wait_for_keyframe_option = tmp;
     75    StartNewFile();
    7476
    7577    _stream_data->AddAVListener(this);
    7678    _stream_data->AddWritingListener(this);
  • mythtv/libs/libmythtv/cetonrecorder.h

    diff --git a/mythtv/libs/libmythtv/cetonrecorder.h b/mythtv/libs/libmythtv/cetonrecorder.h
    index fe2d176..8233d46 100644
    a b class CetonRecorder : public DTVRecorder 
    2626
    2727    bool Open(void);
    2828    void Close(void);
     29    void StartNewFile(void);
    2930
    3031    bool IsOpen(void) const { return _stream_handler; }
    3132
  • mythtv/libs/libmythtv/dtvrecorder.cpp

    diff --git a/mythtv/libs/libmythtv/dtvrecorder.cpp b/mythtv/libs/libmythtv/dtvrecorder.cpp
    index 9d7d89f..3ebd7ee 100644
    a b DTVRecorder::DTVRecorder(TVRec *rec) : 
    8585{
    8686    SetPositionMapType(MARK_GOP_BYFRAME);
    8787    _payload_buffer.reserve(TSPacket::kSize * (50 + 1));
     88
    8889    ResetForNewFile();
     90
     91    memset(_stream_id,  0, sizeof(_stream_id));
     92    memset(_pid_status, 0, sizeof(_pid_status));
     93    memset(_continuity_counter, 0xff, sizeof(_continuity_counter));
    8994}
    9095
    9196DTVRecorder::~DTVRecorder()
    void DTVRecorder::SetOptionsFromProfile(RecordingProfile *profile, 
    145150void DTVRecorder::FinishRecording(void)
    146151{
    147152    if (ringBuffer)
    148     {
    149         if (!_payload_buffer.empty())
    150         {
    151             ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size());
    152             _payload_buffer.clear();
    153         }
    154153        ringBuffer->WriterFlush();
    155     }
    156154
    157155    if (curRecording)
    158156    {
    void DTVRecorder::ResetForNewFile(void) 
    167165    LOG(VB_RECORD, LOG_INFO, LOC + "ResetForNewFile(void)");
    168166    QMutexLocker locker(&positionMapLock);
    169167
    170     // _first_keyframe, _seen_psp and m_h264_parser should
     168    // _seen_psp and m_h264_parser should
    171169    // not be reset here. This will only be called just as
    172170    // we're seeing the first packet of a new keyframe for
    173171    // writing to the new file and anything that makes the
    void DTVRecorder::ResetForNewFile(void) 
    176174    // -- Daniel Kristjansson 2011-02-26
    177175
    178176    _start_code                 = 0xffffffff;
    179     //_first_keyframe
     177    _first_keyframe             = -1;
    180178    _has_written_other_keyframe = false;
    181179    _last_keyframe_seen         = 0;
    182180    _last_gop_seen              = 0;
    void DTVRecorder::ResetForNewFile(void) 
    187185    //_recording
    188186    _error                      = QString();
    189187
    190     memset(_stream_id,  0, sizeof(_stream_id));
    191     memset(_pid_status, 0, sizeof(_pid_status));
    192     memset(_continuity_counter, 0xff, sizeof(_continuity_counter));
    193 
    194188    _progressive_sequence       = 0;
    195189    _repeat_pict                = 0;
    196190
    197     _pes_synced                 = false;
     191    //_pes_synced
    198192    //_seen_sps
    199193    positionMap.clear();
    200194    positionMapDelta.clear();
    201     _payload_buffer.clear();
    202195
    203196    locker.unlock();
    204197    ClearStatistics();
    void DTVRecorder::ClearStatistics(void) 
    209202    RecorderBase::ClearStatistics();
    210203
    211204    memset(_ts_count, 0, sizeof(_ts_count));
    212     for (int i = 0; i < 256; i++)
     205    for (int i = 0; i < 256; ++i)
    213206        _ts_last[i] = -1LL;
    214     for (int i = 0; i < 256; i++)
     207    for (int i = 0; i < 256; ++i)
    215208        _ts_first[i] = -1LL;
    216209    //_ts_first_dt -- doesn't need to be cleared only used if _ts_first>=0
    217210    _packet_count.fetchAndStoreRelaxed(0);
    void DTVRecorder::SetStreamData(void) 
    264257        _stream_data->SetDesiredProgram(_stream_data->DesiredProgram());
    265258}
    266259
    267 void DTVRecorder::BufferedWrite(const TSPacket &tspacket)
     260void DTVRecorder::BufferedWrite(const TSPacket &tspacket, bool insert)
    268261{
    269     // delay until first GOP to avoid decoder crash on res change
    270     if (_wait_for_keyframe_option && _first_keyframe<0)
    271         return;
    272 
    273     if (curRecording && timeOfFirstDataIsSet.testAndSetRelaxed(0,1))
     262    if (!insert)
    274263    {
    275         QMutexLocker locker(&statisticsLock);
    276         timeOfFirstData = mythCurrentDateTime();
    277         timeOfLatestData = mythCurrentDateTime();
    278         timeOfLatestDataTimer.start();
    279     }
     264        // delay until first GOP to avoid decoder crash on res change
     265        if (!_buffer_packets && _wait_for_keyframe_option &&
     266            _first_keyframe < 0)
     267            return;
    280268
    281     int val = timeOfLatestDataCount.fetchAndAddRelaxed(1);
    282     int thresh = timeOfLatestDataPacketInterval.fetchAndAddRelaxed(0);
    283     if (val > thresh)
    284     {
    285         QMutexLocker locker(&statisticsLock);
    286         uint elapsed = timeOfLatestDataTimer.restart();
    287         int interval = thresh;
    288         if (elapsed > kTimeOfLatestDataIntervalTarget + 250)
    289             interval = timeOfLatestDataPacketInterval
    290                 .fetchAndStoreRelaxed(thresh * 4 / 5);
    291         else if (elapsed + 250 < kTimeOfLatestDataIntervalTarget)
    292             interval = timeOfLatestDataPacketInterval
    293                 .fetchAndStoreRelaxed(thresh * 9 / 8);
    294 
    295         timeOfLatestDataCount.fetchAndStoreRelaxed(1);
    296         timeOfLatestData = mythCurrentDateTime();
    297 
    298         LOG(VB_RECORD, LOG_DEBUG, LOC + QString("Updating timeOfLatestData ") +
    299             QString("elapsed(%1) interval(%2)")
    300             .arg(elapsed).arg(interval));
    301     }
     269        if (curRecording && timeOfFirstDataIsSet.testAndSetRelaxed(0,1))
     270        {
     271            QMutexLocker locker(&statisticsLock);
     272            timeOfFirstData = mythCurrentDateTime();
     273            timeOfLatestData = mythCurrentDateTime();
     274            timeOfLatestDataTimer.start();
     275        }
    302276
    303     // Do we have to buffer the packet for exact keyframe detection?
    304     if (_buffer_packets)
    305     {
    306         int idx = _payload_buffer.size();
    307         _payload_buffer.resize(idx + TSPacket::kSize);
    308         memcpy(&_payload_buffer[idx], tspacket.data(), TSPacket::kSize);
    309         return;
    310     }
     277        int val = timeOfLatestDataCount.fetchAndAddRelaxed(1);
     278        int thresh = timeOfLatestDataPacketInterval.fetchAndAddRelaxed(0);
     279        if (val > thresh)
     280        {
     281            QMutexLocker locker(&statisticsLock);
     282            uint elapsed = timeOfLatestDataTimer.restart();
     283            int interval = thresh;
     284            if (elapsed > kTimeOfLatestDataIntervalTarget + 250)
     285                interval = timeOfLatestDataPacketInterval
     286                           .fetchAndStoreRelaxed(thresh * 4 / 5);
     287            else if (elapsed + 250 < kTimeOfLatestDataIntervalTarget)
     288                interval = timeOfLatestDataPacketInterval
     289                           .fetchAndStoreRelaxed(thresh * 9 / 8);
     290
     291            timeOfLatestDataCount.fetchAndStoreRelaxed(1);
     292            timeOfLatestData = mythCurrentDateTime();
     293
     294            LOG(VB_RECORD, LOG_DEBUG, LOC +
     295                QString("Updating timeOfLatestData elapsed(%1) interval(%2)")
     296                .arg(elapsed).arg(interval));
     297        }
    311298
    312     // We are free to write the packet, but if we have buffered packet[s]
    313     // we have to write them first...
    314     if (!_payload_buffer.empty())
    315     {
    316         if (ringBuffer)
    317             ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size());
    318         _payload_buffer.clear();
     299        // Do we have to buffer the packet for exact keyframe detection?
     300        if (_buffer_packets)
     301        {
     302            int idx = _payload_buffer.size();
     303            _payload_buffer.resize(idx + TSPacket::kSize);
     304            memcpy(&_payload_buffer[idx], tspacket.data(), TSPacket::kSize);
     305            return;
     306        }
     307
     308        // We are free to write the packet, but if we have buffered packet[s]
     309        // we have to write them first...
     310        if (!_payload_buffer.empty())
     311        {
     312            if (ringBuffer)
     313                ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size());
     314            _payload_buffer.clear();
     315        }
    319316    }
    320317
    321318    if (ringBuffer)
    static QDateTime ts_to_qdatetime( 
    361358}
    362359
    363360static const uint frameRateMap[16] = {
    364     0, 23796, 24000, 25000, 29970, 30000, 50000, 59940, 60000, 
    365     0, 0, 0, 0, 0, 0, 0 
     361    0, 23796, 24000, 25000, 29970, 30000, 50000, 59940, 60000,
     362    0, 0, 0, 0, 0, 0, 0
    366363};
    367364
    368365/** \fn DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
    static const uint frameRateMap[16] = { 
    393390 */
    394391bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
    395392{
    396     bool haveBufferedData = !_payload_buffer.empty();
    397393    if (!tspacket->HasPayload()) // no payload to scan
    398         return !haveBufferedData;
     394        return _first_keyframe >= 0;
    399395
    400396    if (!ringBuffer)
    401         return !haveBufferedData;
     397        return _first_keyframe >= 0;
    402398
    403399    // if packet contains start of PES packet, start
    404400    // looking for first byte of MPEG start code (3 bytes 0 0 1)
    bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket) 
    461457            }
    462458            else if (PESStreamID::MPEG2ExtensionStartCode == stream_id)
    463459            {
    464                 if (bytes_left >= 1) 
     460                if (bytes_left >= 1)
    465461                {
    466462                    ext_type = (bufptr[0] >> 4);
    467463                    switch(ext_type)
    bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket) 
    482478
    483479                            /* check if we must repeat the frame */
    484480                            _repeat_pict = 1;
    485                             if (repeat_first_field) 
     481                            if (repeat_first_field)
    486482                            {
    487483                                if (_progressive_sequence)
    488484                                {
    bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket) 
    491487                                    else
    492488                                        _repeat_pict = 3;
    493489                                }
    494                                 else if (progressive_frame) 
     490                                else if (progressive_frame)
    495491                                {
    496492                                    _repeat_pict = 2;
    497493                                }
    bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket) 
    527523    if (hasKeyFrame)
    528524    {
    529525        _last_keyframe_seen = _frames_seen_count;
    530         HandleKeyframe(_frames_written_count, TSPacket::kSize);
     526        HandleKeyframe(0);
    531527    }
    532528
    533529    if (hasFrame)
    534530    {
     531        _buffer_packets = false;  // We now know if it is a keyframe, or not
    535532        _frames_seen_count++;
    536         if (!_wait_for_keyframe_option || _first_keyframe>=0)
     533        if (!_wait_for_keyframe_option || _first_keyframe >= 0)
    537534            _frames_written_count++;
     535        else
     536        {
     537             /* Found a frame that is not a keyframe, and we want to
     538              * start on a keyframe */
     539            _payload_buffer.clear();
     540        }
    538541    }
    539542
    540543    if ((aspectRatio > 0) && (aspectRatio != m_videoAspect))
    bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket) 
    558561        FrameRateChange(frameRate, _frames_written_count);
    559562    }
    560563
    561     return hasKeyFrame || (_payload_buffer.size() >= (188*50));
     564    return _first_keyframe >= 0;
    562565}
    563566
    564567void DTVRecorder::HandleTimestamps(int stream_id, int64_t pts, int64_t dts)
    bool DTVRecorder::FindAudioKeyframes(const TSPacket*) 
    652655        if (1 == (_frames_seen_count & 0x7))
    653656        {
    654657            _last_keyframe_seen = _frames_seen_count;
    655             HandleKeyframe(_frames_written_count);
     658            HandleKeyframe(_payload_buffer.size());
    656659            hasKeyFrame = true;
    657660        }
    658661
    bool DTVRecorder::FindOtherKeyframes(const TSPacket *tspacket) 
    680683    _frames_written_count++;
    681684    _last_keyframe_seen = _frames_seen_count;
    682685
    683     HandleKeyframe(_frames_written_count);
     686    HandleKeyframe(_payload_buffer.size());
    684687
    685688    _has_written_other_keyframe = true;
    686689
    void DTVRecorder::SetNextRecording(const ProgramInfo *progInf, RingBuffer *rb) 
    716719 *  \brief This save the current frame to the position maps
    717720 *         and handles ringbuffer switching.
    718721 */
    719 void DTVRecorder::HandleKeyframe(uint64_t frameNum, int64_t extra)
     722void DTVRecorder::HandleKeyframe(int64_t extra)
    720723{
    721724    if (!ringBuffer)
    722725        return;
    723726
    724 #if 0
    725     unsigned long long frameNum = _frames_written_count;
    726 #endif
     727    // Perform ringbuffer switch if needed.
     728    CheckForRingBufferSwitch();
    727729
     730    uint64_t frameNum = _frames_written_count;
    728731    _first_keyframe = (_first_keyframe < 0) ? frameNum : _first_keyframe;
    729732
    730733    // Add key frame to position map
    731734    positionMapLock.lock();
    732735    if (!positionMap.contains(frameNum))
    733736    {
    734         long long startpos = ringBuffer->GetWritePosition();
    735         // FIXME: handle keyframes with start code spanning over two ts packets
    736         startpos += _payload_buffer.size() - extra;
     737        int64_t startpos = ringBuffer->GetWritePosition() + extra;
    737738
    738739        // Don't put negative offsets into the database, they get munged into
    739740        // MAX_INT64 - offset, which is an exceedingly large number, and
    void DTVRecorder::HandleKeyframe(uint64_t frameNum, int64_t extra) 
    745746        }
    746747    }
    747748    positionMapLock.unlock();
    748 
    749     // Perform ringbuffer switch if needed.
    750     CheckForRingBufferSwitch();
    751749}
    752750
    753751/** \fn DTVRecorder::FindH264Keyframes(const TSPacket*)
    void DTVRecorder::HandleKeyframe(uint64_t frameNum, int64_t extra) 
    757755 */
    758756bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
    759757{
     758    if (!tspacket->HasPayload()) // no payload to scan
     759        return _first_keyframe >= 0;
     760
    760761    if (!ringBuffer)
    761762    {
    762763        LOG(VB_GENERAL, LOG_ERR, LOC + "FindH264Keyframes: No ringbuffer");
    763         return false;
     764        return _first_keyframe >= 0;
    764765    }
    765766
    766     bool haveBufferedData = !_payload_buffer.empty();
    767     if (!tspacket->HasPayload()) // no payload to scan
    768         return !haveBufferedData;
    769 
    770767    const bool payloadStart = tspacket->PayloadStart();
    771768    if (payloadStart)
    772769    {
    bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket) 
    785782
    786783    // scan for PES packets and H.264 NAL units
    787784    uint i = tspacket->AFCOffset();
    788     for (; i < TSPacket::kSize; i++)
     785    for (; i < TSPacket::kSize; ++i)
    789786    {
    790787        // special handling required when a new PES packet begins
    791788        if (payloadStart && !_pes_synced)
    bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket) 
    836833            }
    837834
    838835            // we now know where the PES payload is
    839             // normally, we should have used 6, but use 5 because the for 
     836            // normally, we should have used 6, but use 5 because the for
    840837            // loop will bump i
    841838            i += 5 + pes_header_length;
    842839            _pes_synced = true;
    bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket) 
    853850
    854851        // scan for a NAL unit start code
    855852
    856         uint32_t bytes_used = m_h264_parser.addBytes(
    857             tspacket->data() + i, TSPacket::kSize - i,
    858             ringBuffer->GetWritePosition() + _payload_buffer.size()
    859             );
     853        uint32_t bytes_used = m_h264_parser.addBytes
     854                              (tspacket->data() + i, TSPacket::kSize - i,
     855                               ringBuffer->GetWritePosition());
    860856        i += (bytes_used - 1);
    861857
    862858        if (m_h264_parser.stateChanged())
    bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket) 
    874870                frameRate = m_h264_parser.frameRate();
    875871            }
    876872        }
    877     } // for (; i < TSPacket::kSize; i++)
     873    } // for (; i < TSPacket::kSize; ++i)
    878874
    879875    if (hasKeyFrame)
    880876    {
    bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket) 
    884880
    885881    if (hasFrame)
    886882    {
     883        _buffer_packets = false;  // We now know if this is a keyframe
    887884        _frames_seen_count++;
    888885        if (!_wait_for_keyframe_option || _first_keyframe >= 0)
    889886            _frames_written_count++;
     887        else
     888        {
     889            /* Found a frame that is not a keyframe, and we want to
     890             * start on a keyframe */
     891            _payload_buffer.clear();
     892        }
    890893    }
    891894
    892895    if ((aspectRatio > 0) && (aspectRatio != m_videoAspect))
    bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket) 
    904907
    905908    if (frameRate != 0 && frameRate != m_frameRate)
    906909    {
    907 
    908910        LOG(VB_RECORD, LOG_INFO, LOC +
    909911            QString("FindH264Keyframes: timescale: %1, tick: %2, framerate: %3")
    910                       .arg( m_h264_parser.GetTimeScale() ) 
     912                      .arg( m_h264_parser.GetTimeScale() )
    911913                      .arg( m_h264_parser.GetUnitsInTick() )
    912914                      .arg( frameRate ) );
    913915        m_frameRate = frameRate;
    914916        FrameRateChange(frameRate, _frames_written_count);
    915917    }
    916918
    917     return hasKeyFrame || (_payload_buffer.size() >= (188*50));
     919    return _seen_sps;
    918920}
    919921
    920922/** \fn DTVRecorder::HandleH264Keyframe(void)
    bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket) 
    923925 */
    924926void DTVRecorder::HandleH264Keyframe(void)
    925927{
    926     unsigned long long frameNum = _frames_written_count;
     928    // Perform ringbuffer switch if needed.
     929    CheckForRingBufferSwitch();
    927930
    928     _first_keyframe = (_first_keyframe < 0) ? frameNum : _first_keyframe;
     931    uint64_t startpos;
     932    uint64_t frameNum = _frames_written_count;
     933
     934    if (_first_keyframe < 0)
     935    {
     936        _first_keyframe = frameNum;
     937        startpos = 0;
     938    }
     939    else
     940        startpos = m_h264_parser.keyframeAUstreamOffset();
    929941
    930942    // Add key frame to position map
    931943    positionMapLock.lock();
    932944    if (!positionMap.contains(frameNum))
    933945    {
    934         positionMapDelta[frameNum] = m_h264_parser.keyframeAUstreamOffset();
    935         positionMap[frameNum]      = m_h264_parser.keyframeAUstreamOffset();
     946        positionMapDelta[frameNum] = startpos;
     947        positionMap[frameNum]      = startpos;
    936948    }
    937949    positionMapLock.unlock();
    938 
    939     // Perform ringbuffer switch if needed.
    940     CheckForRingBufferSwitch();
    941950}
    942951
    943952void DTVRecorder::FindPSKeyFrames(const uint8_t *buffer, uint len)
    void DTVRecorder::FindPSKeyFrames(const uint8_t *buffer, uint len) 
    10571066        if (hasKeyFrame)
    10581067        {
    10591068            _last_keyframe_seen = _frames_seen_count;
    1060             HandleKeyframe(_frames_written_count, bufptr - bufstart);
     1069            HandleKeyframe(_payload_buffer.size() - (bufptr - bufstart));
    10611070        }
    10621071
    10631072        if ((aspectRatio > 0) && (aspectRatio != m_videoAspect))
    void DTVRecorder::FindPSKeyFrames(const uint8_t *buffer, uint len) 
    10661075            AspectChange((AspectRatio)aspectRatio, _frames_written_count);
    10671076        }
    10681077
    1069         if (height && width && 
     1078        if (height && width &&
    10701079            (height != m_videoHeight || m_videoWidth != width))
    10711080        {
    10721081            m_videoHeight = height;
    void DTVRecorder::HandlePAT(const ProgramAssociationTable *_pat) 
    11411150
    11421151    if (!pmtpid)
    11431152    {
    1144         LOG(VB_RECORD, LOG_ERR, LOC + "SetPAT(): "
    1145             "Ignoring PAT not containing our desired program...");
     1153        LOG(VB_RECORD, LOG_ERR, LOC +
     1154            QString("SetPAT(): Ignoring PAT not containing our desired "
     1155                    "program (%1)...").arg(progNum));
    11461156        return;
    11471157    }
    11481158
    void DTVRecorder::HandlePAT(const ProgramAssociationTable *_pat) 
    11541164    delete oldpat;
    11551165
    11561166    // Listen for the other PMTs for faster channel switching
    1157     for (uint i = 0; _input_pat && (i < _input_pat->ProgramCount()); i++)
     1167    for (uint i = 0; _input_pat && (i < _input_pat->ProgramCount()); ++i)
    11581168    {
    11591169        uint pmt_pid = _input_pat->ProgramPID(i);
    11601170        if (!_stream_data->IsListeningPID(pmt_pid))
    void DTVRecorder::HandlePMT(uint progNum, const ProgramMapTable *_pmt) 
    11751185        QString sistandard = GetSIStandard();
    11761186
    11771187        bool has_no_av = true;
    1178         for (uint i = 0; i < _input_pmt->StreamCount() && has_no_av; i++)
     1188        for (uint i = 0; i < _input_pmt->StreamCount() && has_no_av; ++i)
    11791189        {
    11801190            has_no_av &= !_input_pmt->IsVideo(i, sistandard);
    11811191            has_no_av &= !_input_pmt->IsAudio(i, sistandard);
    void DTVRecorder::HandlePMT(uint progNum, const ProgramMapTable *_pmt) 
    11871197    }
    11881198}
    11891199
    1190 void DTVRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat)
     1200void DTVRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat,
     1201                                         bool insert)
    11911202{
    11921203    if (!pat)
    11931204    {
    void DTVRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat) 
    12021213    pat->tsheader()->SetContinuityCounter(next_cc);
    12031214    pat->GetAsTSPackets(_scratch, next_cc);
    12041215
    1205     for (uint i = 0; i < _scratch.size(); i++)
    1206         DTVRecorder::BufferedWrite(_scratch[i]);
     1216    for (uint i = 0; i < _scratch.size(); ++i)
     1217        DTVRecorder::BufferedWrite(_scratch[i], insert);
    12071218}
    12081219
    1209 void DTVRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt)
     1220void DTVRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt, bool insert)
    12101221{
    12111222    if (!pmt)
    12121223    {
    void DTVRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 
    12151226    }
    12161227
    12171228    // collect stream types for H.264 (MPEG-4 AVC) keyframe detection
    1218     for (uint i = 0; i < pmt->StreamCount(); i++)
     1229    for (uint i = 0; i < pmt->StreamCount(); ++i)
    12191230        _stream_id[pmt->StreamPID(i)] = pmt->StreamType(i);
    12201231
    12211232    if (!ringBuffer)
    void DTVRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 
    12251236    pmt->tsheader()->SetContinuityCounter(next_cc);
    12261237    pmt->GetAsTSPackets(_scratch, next_cc);
    12271238
    1228     for (uint i = 0; i < _scratch.size(); i++)
    1229         DTVRecorder::BufferedWrite(_scratch[i]);
     1239    for (uint i = 0; i < _scratch.size(); ++i)
     1240        DTVRecorder::BufferedWrite(_scratch[i], insert);
    12301241}
    12311242
    12321243bool DTVRecorder::ProcessTSPacket(const TSPacket &tspacket)
    bool DTVRecorder::ProcessTSPacket(const TSPacket &tspacket) 
    12521263    // Only create fake keyframe[s] if there are no audio/video streams
    12531264    if (_input_pmt && _has_no_av)
    12541265    {
    1255         _buffer_packets = !FindOtherKeyframes(&tspacket);
     1266        FindOtherKeyframes(&tspacket);
     1267        _buffer_packets = false;
    12561268    }
    12571269    else
    12581270    {
    bool DTVRecorder::ProcessVideoTSPacket(const TSPacket &tspacket) 
    12761288
    12771289    uint streamType = _stream_id[tspacket.PID()];
    12781290
    1279     // Check for keyframes and count frames
    1280     if (streamType == StreamID::H264Video)
     1291    if (tspacket.HasPayload() && tspacket.PayloadStart())
    12811292    {
    1282         _buffer_packets = !FindH264Keyframes(&tspacket);
    1283         if (_wait_for_keyframe_option && !_seen_sps)
    1284             return true;
     1293        // buffer packets until we know if this is a keyframe
     1294        _buffer_packets = true;
     1295#if 0
     1296        LOG(VB_RECORD, LOG_ERR, LOC + QString
     1297            ("ProcessVideoTSPacket PayloadStart @ %1 + %2 = %3")
     1298            .arg(ringBuffer->GetWritePosition())
     1299            .arg(_payload_buffer.size())
     1300            .arg(ringBuffer->GetWritePosition() + _payload_buffer.size()));
     1301#endif
    12851302    }
     1303
     1304    // Check for keyframes and count frames
     1305    if (streamType == StreamID::H264Video)
     1306        FindH264Keyframes(&tspacket);
     1307    else if (streamType != 0)
     1308        FindMPEG2Keyframes(&tspacket);
    12861309    else
    1287     {
    1288         _buffer_packets = !FindMPEG2Keyframes(&tspacket);
    1289     }
     1310        LOG(VB_RECORD, LOG_ERR, LOC +
     1311            "ProcessVideoTSPacket: unknown stream type!");
    12901312
    12911313    return ProcessAVTSPacket(tspacket);
    12921314}
    bool DTVRecorder::ProcessAudioTSPacket(const TSPacket &tspacket) 
    12961318    if (!ringBuffer)
    12971319        return true;
    12981320
    1299     _buffer_packets = !FindAudioKeyframes(&tspacket);
     1321    if (tspacket.HasPayload() && tspacket.PayloadStart())
     1322    {
     1323        // buffer packets until we know if this is a keyframe
     1324        _buffer_packets = true;
     1325#if 0
     1326        LOG(VB_RECORD, LOG_ERR, LOC + QString
     1327            ("ProcessAudioTSPacket PayloadStart @ %1 + %2 = %3")
     1328            .arg(ringBuffer->GetWritePosition())
     1329            .arg(_payload_buffer.size())
     1330            .arg(ringBuffer->GetWritePosition() + _payload_buffer.size()));
     1331#endif
     1332    }
     1333
     1334    FindAudioKeyframes(&tspacket);
    13001335    return ProcessAVTSPacket(tspacket);
    13011336}
    13021337
    13031338/// Common code for processing either audio or video packets
    13041339bool DTVRecorder::ProcessAVTSPacket(const TSPacket &tspacket)
    13051340{
     1341    // Sync recording start to first keyframe
     1342    if (!_buffer_packets && _wait_for_keyframe_option && _first_keyframe < 0)
     1343        return true;
     1344
    13061345    const uint pid = tspacket.PID();
    13071346
    13081347    if (pid != 0x1fff)
    bool DTVRecorder::ProcessAVTSPacket(const TSPacket &tspacket) 
    13201359                .arg(erate,5,'f',2));
    13211360    }
    13221361
    1323     // Sync recording start to first keyframe
    1324     if (_wait_for_keyframe_option && _first_keyframe < 0)
    1325         return true;
    1326 
    13271362    // Sync streams to the first Payload Unit Start Indicator
    13281363    // _after_ first keyframe iff _wait_for_keyframe_option is true
    13291364    if (!(_pid_status[pid] & kPayloadStartSeen) && tspacket.HasPayload())
  • mythtv/libs/libmythtv/dtvrecorder.h

    diff --git a/mythtv/libs/libmythtv/dtvrecorder.h b/mythtv/libs/libmythtv/dtvrecorder.h
    index e2749bf..5ecbf1b 100644
    a b class DTVRecorder : 
    6666    void HandleEncryptionStatus(uint /*pnum*/, bool /*encrypted*/) { }
    6767
    6868    // MPEG Single Program Stream Listener
    69     void HandleSingleProgramPAT(ProgramAssociationTable *pat);
    70     void HandleSingleProgramPMT(ProgramMapTable *pmt);
     69    void HandleSingleProgramPAT(ProgramAssociationTable *pat, bool insert);
     70    void HandleSingleProgramPMT(ProgramMapTable *pmt, bool insert);
    7171
    7272    // ATSC Main
    7373    void HandleSTT(const SystemTimeTable*) { UpdateCAMTimeOffset(); }
    class DTVRecorder : 
    9393    void FinishRecording(void);
    9494    void ResetForNewFile(void);
    9595
    96     void HandleKeyframe(uint64_t frameNum, int64_t extra = 0);
     96    void HandleKeyframe(int64_t extra);
    9797    void HandleTimestamps(int stream_id, int64_t pts, int64_t dts);
    9898
    99     void BufferedWrite(const TSPacket &tspacket);
     99    void BufferedWrite(const TSPacket &tspacket, bool insert = false);
    100100
    101101    // MPEG TS "audio only" support
    102102    bool FindAudioKeyframes(const TSPacket *tspacket);
  • mythtv/libs/libmythtv/dvbrecorder.cpp

    diff --git a/mythtv/libs/libmythtv/dvbrecorder.cpp b/mythtv/libs/libmythtv/dvbrecorder.cpp
    index c1b66d5..abd322a 100644
    a b void DVBRecorder::Close(void) 
    7272    LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- end");
    7373}
    7474
     75void DVBRecorder::StartNewFile(void)
     76{
     77    // Make sure the first things in the file are a PAT & PMT
     78    HandleSingleProgramPAT(_stream_data->PATSingleProgram(), true);
     79    HandleSingleProgramPMT(_stream_data->PMTSingleProgram(), true);
     80}
     81
    7582void DVBRecorder::run(void)
    7683{
    7784    if (!Open())
    void DVBRecorder::run(void) 
    9299    if (_channel && (_channel->GetSIStandard() == "dvb"))
    93100        _stream_data->AddListeningPID(DVB_TDT_PID);
    94101
    95     // Make sure the first things in the file are a PAT & PMT
    96     bool tmp = _wait_for_keyframe_option;
    97     _wait_for_keyframe_option = false;
    98     HandleSingleProgramPAT(_stream_data->PATSingleProgram());
    99     HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
    100     _wait_for_keyframe_option = tmp;
     102    StartNewFile();
    101103
    102104    _stream_data->AddAVListener(this);
    103105    _stream_data->AddWritingListener(this);
  • mythtv/libs/libmythtv/dvbrecorder.h

    diff --git a/mythtv/libs/libmythtv/dvbrecorder.h b/mythtv/libs/libmythtv/dvbrecorder.h
    index eb0b5f8..e82c2fe 100644
    a b class DVBRecorder : public DTVRecorder 
    2828    bool Open(void);
    2929    bool IsOpen(void) const;
    3030    void Close(void);
     31    void StartNewFile(void);
    3132
    3233  private:
    3334    bool PauseAndWait(int timeout = 100);
  • mythtv/libs/libmythtv/hdhrrecorder.cpp

    diff --git a/mythtv/libs/libmythtv/hdhrrecorder.cpp b/mythtv/libs/libmythtv/hdhrrecorder.cpp
    index 63e128b..08422dd 100644
    a b void HDHRRecorder::Close(void) 
    4747    LOG(VB_RECORD, LOG_INFO, LOC + "Close() -- end");
    4848}
    4949
     50void HDHRRecorder::StartNewFile(void)
     51{
     52    // Make sure the first things in the file are a PAT & PMT
     53    HandleSingleProgramPAT(_stream_data->PATSingleProgram(), true);
     54    HandleSingleProgramPMT(_stream_data->PMTSingleProgram(), true);
     55}
     56
    5057void HDHRRecorder::run(void)
    5158{
    5259    LOG(VB_RECORD, LOG_INFO, LOC + "run -- begin");
    void HDHRRecorder::run(void) 
    6673        recordingWait.wakeAll();
    6774    }
    6875
    69     // Make sure the first things in the file are a PAT & PMT
    70     bool tmp = _wait_for_keyframe_option;
    71     _wait_for_keyframe_option = false;
    72     HandleSingleProgramPAT(_stream_data->PATSingleProgram());
    73     HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
    74     _wait_for_keyframe_option = tmp;
     76    StartNewFile();
    7577
    7678    _stream_data->AddAVListener(this);
    7779    _stream_data->AddWritingListener(this);
  • mythtv/libs/libmythtv/hdhrrecorder.h

    diff --git a/mythtv/libs/libmythtv/hdhrrecorder.h b/mythtv/libs/libmythtv/hdhrrecorder.h
    index 44b3fc1..7523e37 100644
    a b class HDHRRecorder : public DTVRecorder 
    2626    bool Open(void);
    2727    bool IsOpen(void) const { return _stream_handler; }
    2828    void Close(void);
     29    void StartNewFile(void);
    2930
    3031    QString GetSIStandard(void) const;
    3132
  • mythtv/libs/libmythtv/iptvrecorder.cpp

    diff --git a/mythtv/libs/libmythtv/iptvrecorder.cpp b/mythtv/libs/libmythtv/iptvrecorder.cpp
    index 58cb956..f289e6c 100644
    a b void IPTVRecorder::StopRecording(void) 
    6969    request_recording = false;
    7070    unpauseWait.wakeAll();
    7171    pauseLock.unlock();
    72    
     72
    7373    // we can't hold the pause lock while we wait for the IPTV feeder to stop
    7474    _channel->GetFeeder()->Stop();
    7575}
    7676
     77void IPTVRecorder::StartNewFile(void)
     78{
     79    // Make sure the first things in the file are a PAT & PMT
     80    HandleSingleProgramPAT(_stream_data->PATSingleProgram(), true);
     81    HandleSingleProgramPMT(_stream_data->PMTSingleProgram(), true);
     82}
     83
    7784void IPTVRecorder::run(void)
    7885{
    7986    LOG(VB_RECORD, LOG_INFO, LOC + "run() -- begin");
    void IPTVRecorder::run(void) 
    9198        recordingWait.wakeAll();
    9299    }
    93100
     101    StartNewFile();
     102
    94103    // Go into main RTSP loop, feeding data to AddData
    95104    _channel->GetFeeder()->Run();
    96105
  • mythtv/libs/libmythtv/iptvrecorder.h

    diff --git a/mythtv/libs/libmythtv/iptvrecorder.h b/mythtv/libs/libmythtv/iptvrecorder.h
    index 1ed625f..a395664 100644
    a b class IPTVRecorder : public DTVRecorder, public TSDataListener 
    2929    bool Open(void);
    3030    void Close(void);
    3131    void StopRecording(void);
     32    void StartNewFile(void);
    3233
    3334    virtual void run(void);
    3435
  • mythtv/libs/libmythtv/mpeg/mpegstreamdata.cpp

    diff --git a/mythtv/libs/libmythtv/mpeg/mpegstreamdata.cpp b/mythtv/libs/libmythtv/mpeg/mpegstreamdata.cpp
    index 43bcbe8..d819776 100644
    a b void MPEGStreamData::ProcessPAT(const ProgramAssociationTable *pat) 
    836836        QMutexLocker locker(&_listener_lock);
    837837        ProgramAssociationTable *pat_sp = PATSingleProgram();
    838838        for (uint i = 0; i < _mpeg_sp_listeners.size(); i++)
    839             _mpeg_sp_listeners[i]->HandleSingleProgramPAT(pat_sp);
     839            _mpeg_sp_listeners[i]->HandleSingleProgramPAT(pat_sp, false);
    840840    }
    841841}
    842842
    void MPEGStreamData::ProcessPMT(const ProgramMapTable *pmt) 
    871871        QMutexLocker locker(&_listener_lock);
    872872        ProgramMapTable *pmt_sp = PMTSingleProgram();
    873873        for (uint i = 0; i < _mpeg_sp_listeners.size(); i++)
    874             _mpeg_sp_listeners[i]->HandleSingleProgramPMT(pmt_sp);
     874            _mpeg_sp_listeners[i]->HandleSingleProgramPMT(pmt_sp, false);
    875875    }
    876876}
    877877
    void MPEGStreamData::HandleTSTables(const TSPacket* tspacket) 
    982982            QMutexLocker locker(&_listener_lock);
    983983            ProgramAssociationTable *pat_sp = PATSingleProgram();
    984984            for (uint i = 0; i < _mpeg_sp_listeners.size(); i++)
    985                 _mpeg_sp_listeners[i]->HandleSingleProgramPAT(pat_sp);
     985                _mpeg_sp_listeners[i]->HandleSingleProgramPAT(pat_sp, false);
    986986        }
    987987        if (TableID::PMT == psip->TableID() &&
    988988            tspacket->PID() == _pid_pmt_single_program)
    void MPEGStreamData::HandleTSTables(const TSPacket* tspacket) 
    990990            QMutexLocker locker(&_listener_lock);
    991991            ProgramMapTable *pmt_sp = PMTSingleProgram();
    992992            for (uint i = 0; i < _mpeg_sp_listeners.size(); i++)
    993                 _mpeg_sp_listeners[i]->HandleSingleProgramPMT(pmt_sp);
     993                _mpeg_sp_listeners[i]->HandleSingleProgramPMT(pmt_sp, false);
    994994        }
    995995        DONE_WITH_PSIP_PACKET(); // already parsed this table, toss it.
    996996    }
  • mythtv/libs/libmythtv/mpeg/streamlisteners.h

    diff --git a/mythtv/libs/libmythtv/mpeg/streamlisteners.h b/mythtv/libs/libmythtv/mpeg/streamlisteners.h
    index bc9cb2d..9412d5d 100644
    a b class MPEGSingleProgramStreamListener 
    9595  protected:
    9696    virtual ~MPEGSingleProgramStreamListener() {}
    9797  public:
    98     virtual void HandleSingleProgramPAT(ProgramAssociationTable*) = 0;
    99     virtual void HandleSingleProgramPMT(ProgramMapTable*) = 0;
     98    virtual void HandleSingleProgramPAT(ProgramAssociationTable*,
     99                                        bool insert) = 0;
     100    virtual void HandleSingleProgramPMT(ProgramMapTable*, bool insert) = 0;
    100101};
    101102
    102103class ATSCMainStreamListener
  • mythtv/libs/libmythtv/mpegrecorder.cpp

    diff --git a/mythtv/libs/libmythtv/mpegrecorder.cpp b/mythtv/libs/libmythtv/mpegrecorder.cpp
    index ebb6e1a..66747f2 100644
    a b void MpegRecorder::run(void) 
    929929        _stream_data->AddWritingListener(this);
    930930
    931931        // Make sure the first things in the file are a PAT & PMT
    932         _wait_for_keyframe_option = false;
    933         HandleSingleProgramPAT(_stream_data->PATSingleProgram());
    934         HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
     932        HandleSingleProgramPAT(_stream_data->PATSingleProgram(), true);
     933        HandleSingleProgramPMT(_stream_data->PMTSingleProgram(), true);
    935934        _wait_for_keyframe_option = true;
    936935    }
    937936
    void MpegRecorder::RestartEncoding(void) 
    12561255        _stream_data->PMTSingleProgram())
    12571256    {
    12581257        _wait_for_keyframe_option = false;
    1259         HandleSingleProgramPAT(_stream_data->PATSingleProgram());
    1260         HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
     1258        HandleSingleProgramPAT(_stream_data->PATSingleProgram(), false);
     1259        HandleSingleProgramPMT(_stream_data->PMTSingleProgram(), false);
    12611260    }
    12621261
    12631262    if (driver == "hdpvr") // HD-PVR will sometimes reset to defaults