Ticket #11328: keep-first-keyframe-v2.patch

File keep-first-keyframe-v2.patch, 8.3 KB (added by jpoet, 14 years ago)

This version will handle the first packet being audio instead of video.

  • mythtv/libs/libmythtv/mpeg/mpegstreamdata.cpp

    diff --git a/mythtv/libs/libmythtv/mpeg/mpegstreamdata.cpp b/mythtv/libs/libmythtv/mpeg/mpegstreamdata.cpp
    index 489c547..fc50feb 100644
    a b const unsigned char MPEGStreamData::bit_sel[8] =  
    6565MPEGStreamData::MPEGStreamData(int desiredProgram, bool cacheTables)
    6666    : _sistandard("mpeg"),
    6767      _have_CRC_bug(false),
     68      _found_payload_start(false),
    6869      _si_time_offset_cnt(0),
    6970      _si_time_offset_indx(0),
    7071      _eit_helper(NULL), _eit_rate(0.0f),
    bool MPEGStreamData::ProcessTSPacket(const TSPacket& tspacket)  
    10541055    if (tspacket.Scrambled())
    10551056        return true;
    10561057
     1058    _found_payload_start |= (tspacket.HasPayload() && tspacket.PayloadStart());
     1059
    10571060    if (IsVideoPID(tspacket.PID()))
    10581061    {
    10591062        for (uint j = 0; j < _ts_av_listeners.size(); j++)
  • mythtv/libs/libmythtv/mpeg/mpegstreamdata.h

    diff --git a/mythtv/libs/libmythtv/mpeg/mpegstreamdata.h b/mythtv/libs/libmythtv/mpeg/mpegstreamdata.h
    index 94ad37d..3730426 100644
    a b class MTV_PUBLIC MPEGStreamData : public EITSource  
    307307    // Single program stuff, gets
    308308    int DesiredProgram(void) const          { return _desired_program; }
    309309    uint VideoPIDSingleProgram(void) const  { return _pid_video_single_program; }
     310    bool FoundPayloadStart(void) const { return _found_payload_start; }
     311    void ResetPayloadStart(void) { _found_payload_start = false; }
     312
    310313    QString GetRecordingType(void) const;
    311314
    312315    const ProgramAssociationTable* PATSingleProgram(void) const
    class MTV_PUBLIC MPEGStreamData : public EITSource  
    356359    QString                   _sistandard;
    357360
    358361    bool                      _have_CRC_bug;
     362    bool                      _found_payload_start;
    359363
    360364    mutable QMutex            _si_time_lock;
    361365    uint                      _si_time_offset_cnt;
  • mythtv/libs/libmythtv/recorders/dtvrecorder.cpp

    diff --git a/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp b/mythtv/libs/libmythtv/recorders/dtvrecorder.cpp
    index 0c30b10..0dcebaf 100644
    a b void DTVRecorder::InitStreamData(void)  
    277277void DTVRecorder::BufferedWrite(const TSPacket &tspacket)
    278278{
    279279    // delay until first GOP to avoid decoder crash on res change
    280     if (_wait_for_keyframe_option && _first_keyframe<0)
     280    if (!_buffer_packets && _wait_for_keyframe_option && _first_keyframe<0)
    281281        return;
    282282
    283283    if (curRecording && timeOfFirstDataIsSet.testAndSetRelaxed(0,1))
    static const uint frameRateMap[16] = {  
    403403 */
    404404bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)
    405405{
    406     bool haveBufferedData = !_payload_buffer.empty();
    407406    if (!tspacket->HasPayload()) // no payload to scan
    408         return !haveBufferedData;
     407        return _first_keyframe >= 0;
    409408
    410409    if (!ringBuffer)
    411         return !haveBufferedData;
     410        return _first_keyframe >= 0;
    412411
    413412    // if packet contains start of PES packet, start
    414413    // looking for first byte of MPEG start code (3 bytes 0 0 1)
    bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)  
    549548        _frames_seen_count++;
    550549        if (!_wait_for_keyframe_option || _first_keyframe>=0)
    551550            UpdateFramesWritten();
     551        else
     552        {
     553            /* Found a frame that is not a keyframe, and we want to
     554             * start on a keyframe */
     555            _payload_buffer.clear();
     556            _stream_data->ResetPayloadStart();
     557        }
    552558    }
    553559
    554560    if ((aspectRatio > 0) && (aspectRatio != m_videoAspect))
    bool DTVRecorder::FindMPEG2Keyframes(const TSPacket* tspacket)  
    572578        FrameRateChange(frameRate, _frames_written_count);
    573579    }
    574580
    575     return hasKeyFrame || (_payload_buffer.size() >= (188*50));
     581    return _first_keyframe >= 0;
    576582}
    577583
    578584void DTVRecorder::HandleTimestamps(int stream_id, int64_t pts, int64_t dts)
    void DTVRecorder::HandleKeyframe(uint64_t frameNum, int64_t extra)  
    762768 */
    763769bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
    764770{
     771    if (!tspacket->HasPayload()) // no payload to scan
     772        return _first_keyframe >= 0;
     773
    765774    if (!ringBuffer)
    766775    {
    767776        LOG(VB_GENERAL, LOG_ERR, LOC + "FindH264Keyframes: No ringbuffer");
    768         return false;
     777        return _first_keyframe >= 0;
    769778    }
    770779
    771     bool haveBufferedData = !_payload_buffer.empty();
    772     if (!tspacket->HasPayload()) // no payload to scan
    773         return !haveBufferedData;
    774 
    775780    const bool payloadStart = tspacket->PayloadStart();
    776781    if (payloadStart)
    777782    {
    bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)  
    790795
    791796    // scan for PES packets and H.264 NAL units
    792797    uint i = tspacket->AFCOffset();
    793     for (; i < TSPacket::kSize; i++)
     798    for (; i < TSPacket::kSize; ++i)
    794799    {
    795800        // special handling required when a new PES packet begins
    796801        if (payloadStart && !_pes_synced)
    bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)  
    879884                frameRate = m_h264_parser.frameRate();
    880885            }
    881886        }
    882     } // for (; i < TSPacket::kSize; i++)
     887    } // for (; i < TSPacket::kSize; ++i)
    883888
    884889    if (hasKeyFrame)
    885890    {
    bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)  
    892897        _frames_seen_count++;
    893898        if (!_wait_for_keyframe_option || _first_keyframe >= 0)
    894899            UpdateFramesWritten();
     900        else
     901        {
     902            /* Found a frame that is not a keyframe, and we want to
     903             * start on a keyframe */
     904            _payload_buffer.clear();
     905            _stream_data->ResetPayloadStart();
     906        }
    895907    }
    896908
    897909    if ((aspectRatio > 0) && (aspectRatio != m_videoAspect))
    bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)  
    909921
    910922    if (frameRate != 0 && frameRate != m_frameRate)
    911923    {
    912 
    913924        LOG(VB_RECORD, LOG_INFO, LOC +
    914925            QString("FindH264Keyframes: timescale: %1, tick: %2, framerate: %3")
    915926                      .arg( m_h264_parser.GetTimeScale() )
    bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)  
    919930        FrameRateChange(frameRate, _frames_written_count);
    920931    }
    921932
    922     return hasKeyFrame || (_payload_buffer.size() >= (188*50));
     933    return _seen_sps;
    923934}
    924935
    925936/** \fn DTVRecorder::HandleH264Keyframe(void)
    void DTVRecorder::HandlePAT(const ProgramAssociationTable *_pat)  
    11491160
    11501161    if (!pmtpid)
    11511162    {
    1152         LOG(VB_RECORD, LOG_ERR, LOC + "SetPAT(): "
    1153             "Ignoring PAT not containing our desired program...");
     1163        LOG(VB_RECORD, LOG_ERR, LOC +
     1164            QString("SetPAT(): Ignoring PAT not containing our desired "
     1165                    "program (%1)...").arg(progNum));
    11541166        return;
    11551167    }
    11561168
    bool DTVRecorder::ProcessVideoTSPacket(const TSPacket &tspacket)  
    12871299    // Check for keyframes and count frames
    12881300    if (streamType == StreamID::H264Video)
    12891301    {
    1290         _buffer_packets = !FindH264Keyframes(&tspacket);
    1291         if (_wait_for_keyframe_option && !_seen_sps)
    1292             return true;
     1302        _buffer_packets = !FindH264Keyframes(&tspacket) &&
     1303                          _stream_data->FoundPayloadStart();
    12931304    }
    12941305    else
    12951306    {
    1296         _buffer_packets = !FindMPEG2Keyframes(&tspacket);
     1307        _buffer_packets = !FindMPEG2Keyframes(&tspacket) &&
     1308                          _stream_data->FoundPayloadStart();
    12971309    }
    12981310
    12991311    return ProcessAVTSPacket(tspacket);
    bool DTVRecorder::ProcessAudioTSPacket(const TSPacket &tspacket)  
    13111323/// Common code for processing either audio or video packets
    13121324bool DTVRecorder::ProcessAVTSPacket(const TSPacket &tspacket)
    13131325{
     1326    // Sync recording start to first keyframe
     1327    if (!_buffer_packets && _wait_for_keyframe_option && _first_keyframe < 0)
     1328        return true;
     1329
    13141330    const uint pid = tspacket.PID();
    13151331
    13161332    if (pid != 0x1fff)
    bool DTVRecorder::ProcessAVTSPacket(const TSPacket &tspacket)  
    13281344                .arg(erate,5,'f',2));
    13291345    }
    13301346
    1331     // Sync recording start to first keyframe
    1332     if (_wait_for_keyframe_option && _first_keyframe < 0)
    1333         return true;
    1334 
    13351347    // Sync streams to the first Payload Unit Start Indicator
    13361348    // _after_ first keyframe iff _wait_for_keyframe_option is true
    13371349    if (!(_pid_status[pid] & kPayloadStartSeen) && tspacket.HasPayload())