Ticket #5443: hdpvr-0.14-recorder.patch

File hdpvr-0.14-recorder.patch, 49.3 KB (added by jppoet@…, 4 years ago)

Verison 0.14 (minor cleanups)

  • libs/libmythtv/dvbrecorder.cpp

     
    120120 
    121121void DVBRecorder::TeardownAll(void) 
    122122{ 
    123     // Make SURE that the device read thread is cleaned up -- John Poet 
     123    // Make SURE that the device read thread is cleaned up 
    124124    StopRecording(); 
    125125 
    126126    if (IsOpen()) 
  • libs/libmythtv/dtvrecorder.h

     
    6565    bool FindH264Keyframes(const TSPacket* tspacket); 
    6666    void HandleH264Keyframe(void); 
    6767 
     68    // PS support (Hauppauge PVR-x50/PVR-500) 
     69    void HandlePSKeyframe(void); 
     70    bool FindPSKeyFrames(unsigned char *buffer, int len); 
     71 
    6872    // For handling other (non audio/video) packets 
    6973    bool FindOtherKeyframes(const TSPacket *tspacket); 
    7074 
     
    111115    unsigned long long _frames_seen_count; 
    112116    unsigned long long _frames_written_count; 
    113117 
     118    int keyframedist; 
     119 
    114120    // constants 
    115121    /// If the number of regular frames detected since the last 
    116122    /// detected keyframe exceeds this value, then we begin marking 
  • libs/libmythtv/dtvrecorder.cpp

     
    1414 
    1515extern "C" { 
    1616// from libavcodec 
    17 extern const uint8_t *ff_find_start_code(const uint8_t * restrict p, const uint8_t *end, uint32_t * restrict state); 
     17    extern const uint8_t *ff_find_start_code(const uint8_t * restrict p, const uint8_t *end, uint32_t * restrict state); 
    1818} 
    1919 
    2020#define LOC QString("DTVRec(%1): ").arg(tvrec->GetCaptureCardNum()) 
     
    2727 *         handle MPEG-2, MPEG-4, MPEG-4 AVC, DVB and ATSC streams. 
    2828 * 
    2929 *  \sa DBox2Recorder, DVBRecorder, FirewireRecorder, 
    30         HDHRRecoreder, IPTVRecorder 
    31  */ 
     30 HDHRRecoreder, IPTVRecorder 
     31*/ 
    3232 
    3333DTVRecorder::DTVRecorder(TVRec *rec) :  
    3434    RecorderBase(rec), 
     
    5454    // keyframe TS buffer 
    5555    _buffer_packets(false), 
    5656    // statistics 
    57     _frames_seen_count(0),          _frames_written_count(0) 
     57    _frames_seen_count(0),          _frames_written_count(0), 
     58    keyframedist(15) 
    5859{ 
    5960    SetPositionMapType(MARK_GOP_BYFRAME); 
     61    _payload_buffer.reserve(TSPacket::SIZE * (50 + 1)); 
    6062} 
    6163 
    6264DTVRecorder::~DTVRecorder() 
     
    108110{ 
    109111    if (ringBuffer) 
    110112    { 
    111         if (_payload_buffer.size()) 
     113        if (!_payload_buffer.empty()) 
    112114        { 
    113115            ringBuffer->Write(&_payload_buffer[0], _payload_buffer.size()); 
    114116            _payload_buffer.clear(); 
     
    430432 */ 
    431433bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket) 
    432434{ 
    433     if (!ringBuffer) 
     435    if (!ringBuffer) { 
     436        VERBOSE(VB_IMPORTANT, LOC_ERR + "FindH264Keyframes: No ringbuffer"); 
    434437        return false; 
     438    } 
    435439 
    436440    bool haveBufferedData = !_payload_buffer.empty(); 
    437441    if (!tspacket->HasPayload()) // no payload to scan 
     
    440444    const bool payloadStart = tspacket->PayloadStart(); 
    441445    if (payloadStart) 
    442446    { 
     447        //VERBOSE(VB_RECORD, LOC_ERR + "FindH264Keyframes: payloadStart"); 
    443448        // reset PES sync state 
    444449        _pes_synced = false; 
    445450        _start_code = 0xffffffff; 
     
    459464            if (i + 2 >= TSPacket::SIZE) 
    460465            { 
    461466                VERBOSE(VB_IMPORTANT, LOC_ERR + 
    462                     "PES packet start code may overflow to next TS packet, aborting keyframe search"); 
     467                        "PES packet start code may overflow to next TS " 
     468                        "packet, aborting keyframe search"); 
    463469                break; 
    464470            } 
    465471 
     
    469475                tspacket->data()[i++] != 0x01) 
    470476            { 
    471477                VERBOSE(VB_IMPORTANT, LOC_ERR + 
    472                     "PES start code not found in TS packet with PUSI set"); 
     478                        "PES start code not found in TS packet with PUSI set"); 
    473479                break; 
    474480            } 
    475481 
     
    477483            if (i + 5 >= TSPacket::SIZE) 
    478484            { 
    479485                VERBOSE(VB_IMPORTANT, LOC_ERR + 
    480                     "PES packet headers overflow to next TS packet, aborting keyframe search"); 
     486                        "PES packet headers overflow to next TS packet, " 
     487                        "aborting keyframe search"); 
    481488                break; 
    482489            } 
    483490 
     
    493500            if ((i + 6 + pes_header_length) >= TSPacket::SIZE) 
    494501            { 
    495502                VERBOSE(VB_IMPORTANT, LOC_ERR + 
    496                     "PES packet headers overflow to next TS packet, aborting keyframe search"); 
     503                        "PES packet headers overflow to next TS packet, " 
     504                        "aborting keyframe search"); 
    497505                break; 
    498506            } 
    499507 
    500             // we now know where the PES payload is 
    501             // normally, we should have used 6, but use 5 because the for loop will bump i 
     508            // we now know where the PES payload is. 
     509            // normally, we should have used 6, 
     510            //        but use 5 because the for loop will bump i 
    502511            i += 5 + pes_header_length; 
    503512            _pes_synced = true; 
    504513 
     
    511520            break; 
    512521 
    513522        // scan for a NAL unit start code 
    514         uint32_t bytes_used = _h264_kf_seq.AddBytes(tspacket->data() + i, 
    515                                                    TSPacket::SIZE - i, 
    516                                                    ringBuffer->GetWritePosition()); 
     523        uint32_t bytes_used =  
     524            _h264_kf_seq.AddBytes(tspacket->data() + i, 
     525                                  TSPacket::SIZE - i, 
     526                                  ringBuffer->GetWritePosition()); 
    517527        i += (bytes_used - 1); 
    518528 
    519529        // special handling when we've synced to a NAL unit 
     
    535545 
    536546    if (hasKeyFrame) 
    537547    { 
     548        //VERBOSE(VB_RECORD, LOC_ERR + "FindH264Keyframes: hasKeyFrame"); 
    538549        _last_keyframe_seen = _frames_seen_count; 
    539550        HandleH264Keyframe(); 
    540551    } 
    541552 
    542553    if (hasFrame) 
    543554    { 
     555        //VERBOSE(VB_RECORD, LOC_ERR + "FindH264Keyframes: hasFrame"); 
    544556        _frames_seen_count++; 
    545557        if (!_wait_for_keyframe_option || _first_keyframe >= 0) 
    546558            _frames_written_count++; 
     
    572584    CheckForRingBufferSwitch(); 
    573585} 
    574586 
     587/** \fn DTVRecorder::HandlePSKeyframe(void) 
     588 *  \brief This save the current frame to the position maps 
     589 *         and handles ringbuffer switching. 
     590 */ 
     591void DTVRecorder::HandlePSKeyframe(void) 
     592{ 
     593    if (!ringBuffer) 
     594        return; 
     595 
     596    unsigned long long frameNum = _last_gop_seen; 
     597 
     598    _first_keyframe = (_first_keyframe < 0) ? frameNum : _first_keyframe; 
     599 
     600    // Add key frame to position map 
     601    positionMapLock.lock(); 
     602    if (!positionMap.contains(frameNum)) 
     603    { 
     604        long long startpos = ringBuffer->GetWritePosition(); 
     605        // FIXME: handle keyframes with start code spanning over two ts packets 
     606        startpos += _payload_buffer.size(); 
     607//      VERBOSE(VB_RECORD, LOC + "mpHandleKeyframe frameNum: " << frameNum << ", startpos: " << startpos << " type " << positionMapType << "\n"); 
     608        positionMapDelta[frameNum] = startpos; 
     609        positionMap[frameNum]      = startpos; 
     610    } 
     611    positionMapLock.unlock(); 
     612 
     613    // Perform ringbuffer switch if needed. 
     614    CheckForRingBufferSwitch(); 
     615} 
     616 
     617 
     618bool DTVRecorder::FindPSKeyFrames(unsigned char *buffer, int len) 
     619{ 
     620    unsigned char *bufptr = buffer, *bufstart = buffer; 
     621    uint v = 0; 
     622    int leftlen = len; 
     623    bool hasKeyFrame = false; 
     624 
     625    while (bufptr < buffer + len) 
     626    { 
     627        v = *bufptr++; 
     628        if (_start_code == 0x000001) 
     629        { 
     630            _start_code = ((_start_code << 8) | v) & 0xFFFFFF; 
     631            const int stream_id = _start_code & 0x000000ff; 
     632 
     633            if (stream_id == PESStreamID::PackHeader) 
     634            { 
     635                _last_keyframe_seen = ringBuffer->GetWritePosition() + 
     636                                      _payload_buffer.size(); 
     637 
     638                int curpos = bufptr - bufstart - 4; 
     639                if (curpos < 0) 
     640                { 
     641                    // header was split 
     642                    if (_payload_buffer.size() + curpos > 0) 
     643                        ringBuffer->Write(&_payload_buffer[0], 
     644                                          _payload_buffer.size() + curpos); 
     645 
     646                    _payload_buffer.resize(4); 
     647                    memcpy(&_payload_buffer[0], &_start_code, 4); 
     648 
     649                    leftlen = leftlen - curpos + 4; 
     650                    bufstart = bufptr; 
     651                } 
     652                else 
     653                { 
     654                    // header was entirely in this packet 
     655                    int idx = _payload_buffer.size(); 
     656                    _payload_buffer.resize(idx + curpos); 
     657                    memcpy(&_payload_buffer[idx], bufstart, curpos); 
     658 
     659                    bufstart += curpos; 
     660                    leftlen -= curpos; 
     661 
     662                    if (_payload_buffer.size() > 0) 
     663                        ringBuffer->Write(&_payload_buffer[0], 
     664                                          _payload_buffer.size()); 
     665                    _payload_buffer.clear(); 
     666                } 
     667                _frames_seen_count++; 
     668            } 
     669            else if (stream_id == PESStreamID::SequenceStartCode) 
     670            { 
     671                _last_seq_seen = _last_keyframe_seen; 
     672            } 
     673            else if (stream_id == PESStreamID::GOPStartCode && 
     674                     _last_seq_seen == _last_keyframe_seen) 
     675            { 
     676                _frames_written_count = _last_gop_seen * keyframedist; 
     677                _last_gop_seen++; 
     678                HandlePSKeyframe(); 
     679            } 
     680        } 
     681        else 
     682            _start_code = ((_start_code << 8) | v) & 0xFFFFFF; 
     683    } 
     684 
     685    int idx = _payload_buffer.size(); 
     686    _payload_buffer.resize(idx + leftlen); 
     687    memcpy(&_payload_buffer[idx], bufstart, leftlen); 
     688 
     689    return hasKeyFrame; 
     690} 
     691 
     692 
    575693/* vim: set expandtab tabstop=4 shiftwidth=4: */ 
  • libs/libmythtv/mpegrecorder.h

     
    33#ifndef MPEGRECORDER_H_ 
    44#define MPEGRECORDER_H_ 
    55 
    6 #include "recorderbase.h" 
     6#include "dtvrecorder.h" 
     7#include "tspacket.h" 
     8#include "mpegstreamdata.h" 
    79 
    810struct AVFormatContext; 
    911struct AVPacket; 
    1012 
    11 class MpegRecorder : public RecorderBase 
     13class MpegRecorder : public DTVRecorder, 
     14                     public MPEGSingleProgramStreamListener, 
     15                     public TSPacketListener, 
     16                     public TSPacketListenerAV 
    1217{ 
    1318  public: 
    1419    MpegRecorder(TVRec*); 
     
    3338    bool PauseAndWait(int timeout = 100); 
    3439 
    3540    bool IsRecording(void) { return recording; } 
    36     bool IsErrored(void) { return errored; } 
    3741 
    38     long long GetFramesWritten(void) { return framesWritten; } 
    39  
    4042    bool Open(void); 
    4143    int GetVideoFd(void) { return chanfd; } 
    4244 
    43     long long GetKeyframePosition(long long desired); 
     45    // TS 
     46    virtual void SetStreamData(MPEGStreamData*); 
     47    virtual MPEGStreamData *GetStreamData(void) { return _stream_data; } 
    4448 
    45     void SetNextRecording(const ProgramInfo*, RingBuffer*); 
     49    // TSPacketListenerAV 
     50    bool ProcessVideoTSPacket(const TSPacket& tspacket); 
     51    bool ProcessAudioTSPacket(const TSPacket& tspacket); 
     52    bool ProcessAVTSPacket(const TSPacket &tspacket); 
    4653 
     54    // implements MPEGSingleProgramStreamListener 
     55    void HandleSingleProgramPAT(ProgramAssociationTable *pat); 
     56    void HandleSingleProgramPMT(ProgramMapTable *pmt); 
     57 
    4758  private: 
    48     bool SetupRecording(void); 
    49     void FinishRecording(void); 
    50     void HandleKeyframe(void); 
    51  
    5259    void ProcessData(unsigned char *buffer, int len); 
    5360 
    5461    bool OpenMpegFileAsInput(void); 
     
    6067    uint GetFilteredAudioSampleRate(void) const; 
    6168    uint GetFilteredAudioLayer(void) const; 
    6269    uint GetFilteredAudioBitRate(uint audio_layer) const; 
     70    void ProcessPSdata(unsigned char *buffer, uint len); 
    6371 
     72    // TSPacketListener 
     73    bool ProcessTSPacket(const TSPacket &tspacket); 
     74 
    6475    void ResetForNewFile(void); 
    6576 
     77    inline bool CheckCC(uint pid, uint cc); 
     78 
    6679    bool deviceIsMpegFile; 
    6780    int bufferSize; 
    6881 
     
    7891    // State 
    7992    bool recording; 
    8093    bool encoding; 
    81     bool errored; 
    8294 
    8395    // Pausing state 
    8496    bool cleartimeonpause; 
    8597 
    86     // Number of frames written 
    87     long long framesWritten; 
    88  
    8998    // Encoding info 
    9099    int width, height; 
    91100    int bitrate, maxbitrate, streamtype, aspectratio; 
     
    97106    int chanfd; 
    98107    int readfd; 
    99108 
    100     // Keyframe tracking inforamtion 
    101     int keyframedist; 
    102     bool gopset; 
    103     unsigned int leftovers; 
    104     long long lastpackheaderpos; 
    105     long long lastseqstart; 
    106     long long numgops; 
    107  
    108     // buffer used for ... 
    109     unsigned char *buildbuffer; 
    110     unsigned int buildbuffersize; 
    111  
    112109    static const int   audRateL1[]; 
    113110    static const int   audRateL2[]; 
    114111    static const int   audRateL3[]; 
    115112    static const char *streamType[]; 
    116113    static const char *aspectRatio[]; 
    117114    static const unsigned int kBuildBufferMaxSize; 
     115 
     116    // TS 
     117    MPEGStreamData *_stream_data; 
     118    unsigned char   _stream_id[0x1fff]; 
     119    unsigned char   _pid_status[0x1fff]; 
     120    unsigned char   _continuity_counter[0x1fff]; 
     121    static const unsigned char kPayloadStartSeen = 0x2; 
     122 
     123    // Statistics 
     124    mutable uint        _continuity_error_count; 
     125    mutable uint        _stream_overflow_count; 
     126    mutable uint        _bad_packet_count; 
    118127}; 
     128 
     129inline bool MpegRecorder::CheckCC(uint pid, uint new_cnt) 
     130{ 
     131    bool ok = ((((_continuity_counter[pid] + 1) & 0xf) == new_cnt) || 
     132               (_continuity_counter[pid] == 0xFF)); 
     133 
     134    _continuity_counter[pid] = new_cnt & 0xf; 
     135 
     136    return ok; 
     137} 
     138 
    119139#endif 
  • libs/libmythtv/mpegrecorder.cpp

     
    3434#include "util.h" 
    3535#include "cardutil.h" 
    3636 
     37// the audio and video PIDs are in the Program Map Table 
     38// the PID of the PMT are specified in the Program Association Table 
     39 
    3740// ivtv header 
    3841extern "C" { 
    3942#include "ivtv_myth.h" 
     
    4851const int MpegRecorder::audRateL1[] = 
    4952{ 
    5053    32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 
    51 }; 
     54        }; 
    5255 
    5356const int MpegRecorder::audRateL2[] = 
    5457{ 
     
    7376    "Square", "4:3", "16:9", "2.21:1", 0 
    7477}; 
    7578 
    76 const unsigned int MpegRecorder::kBuildBufferMaxSize = 1024 * 1024; 
    77  
    78 MpegRecorder::MpegRecorder(TVRec *rec) : 
    79     RecorderBase(rec), 
     79MpegRecorder::MpegRecorder(TVRec *rec) : DTVRecorder(rec), 
    8080    // Debugging variables 
    8181    deviceIsMpegFile(false), 
    82     bufferSize(4096), 
    8382    // Driver info 
    8483    card(QString::null),      driver(QString::null), 
    8584    version(0),               usingv4l2(false), 
     
    8786    requires_special_pause(false), 
    8887    // State 
    8988    recording(false),         encoding(false), 
    90     errored(false), 
    9189    // Pausing state 
    9290    cleartimeonpause(false), 
    93     // Number of frames written 
    94     framesWritten(0), 
    9591    // Encoding info 
    9692    width(720),               height(480), 
    9793    bitrate(4500),            maxbitrate(6000), 
     
    10298    audvolume(80),            language(0), 
    10399    // Input file descriptors 
    104100    chanfd(-1),               readfd(-1), 
    105     // Keyframe tracking inforamtion 
    106     keyframedist(15),         gopset(false), 
    107     leftovers(0),             lastpackheaderpos(0), 
    108     lastseqstart(0),          numgops(0), 
    109     // buffer used for ... 
    110     buildbuffer(new unsigned char[kBuildBufferMaxSize + 1]), 
    111     buildbuffersize(0) 
     101    // TS packet handling 
     102    _stream_data(NULL)                                    
    112103{ 
    113104    SetPositionMapType(MARK_GOP_START); 
    114105} 
     
    116107MpegRecorder::~MpegRecorder() 
    117108{ 
    118109    TeardownAll(); 
    119     delete [] buildbuffer; 
    120110} 
    121111 
    122112void MpegRecorder::TeardownAll(void) 
    123113{ 
     114    StopRecording(); 
     115 
    124116    if (chanfd >= 0) 
    125117    { 
    126118        close(chanfd); 
     
    131123        close(readfd); 
    132124        readfd = -1; 
    133125    } 
     126 
    134127} 
    135128 
    136129static int find_index(const int *audio_rate, int value) 
     
    332325 
    333326    if (CardUtil::GetV4LInfo(chanfd, card, driver, version)) 
    334327    { 
     328//      driver = "hdpvr"; 
     329 
    335330        if (driver == "ivtv") 
    336331        { 
     332            bufferSize = 4096; 
     333 
    337334            usingv4l2     = (version >= IVTV_KERNEL_VERSION(0, 8, 0)); 
    338335            has_v4l2_vbi  = (version >= IVTV_KERNEL_VERSION(0, 3, 8)); 
    339336            has_buggy_vbi = true; 
    340337            requires_special_pause = 
    341338                (version >= IVTV_KERNEL_VERSION(0, 10, 0)); 
    342339        } 
     340        else if (driver == "hdpvr") 
     341        { 
     342            bufferSize = 500 * TSPacket::SIZE; 
     343            usingv4l2 = true; 
     344            requires_special_pause = true; 
     345 
     346            bzero(_stream_id,  sizeof(_stream_id)); 
     347            bzero(_pid_status, sizeof(_pid_status)); 
     348            memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); 
     349        } 
    343350        else 
    344351        { 
    345             VERBOSE(VB_IMPORTANT, "\n\nNot ivtv driver??\n\n"); 
     352            VERBOSE(VB_IMPORTANT, "\n\nNot ivtv or hdpvr driver??\n\n"); 
    346353            usingv4l2 = has_v4l2_vbi = true; 
    347354            has_buggy_vbi = requires_special_pause = false; 
    348355        } 
     
    354361 
    355362    struct v4l2_format vfmt; 
    356363    bzero(&vfmt, sizeof(vfmt)); 
    357  
     364     
    358365    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
    359  
     366     
    360367    if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) < 0) 
    361368    { 
    362369        VERBOSE(VB_IMPORTANT, LOC_ERR + "Error getting format" + ENO); 
    363370        return false; 
    364371    } 
     372         
     373    if (driver != "hdpvr") { 
     374        vfmt.fmt.pix.width = width; 
     375        vfmt.fmt.pix.height = height; 
     376         
     377        if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0) 
     378        { 
     379            VERBOSE(VB_IMPORTANT, LOC_ERR + "Error setting format" + ENO); 
     380            return false; 
     381        } 
    365382 
    366     vfmt.fmt.pix.width = width; 
    367     vfmt.fmt.pix.height = height; 
    368  
    369     if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0) 
    370     { 
    371         VERBOSE(VB_IMPORTANT, LOC_ERR + "Error setting format" + ENO); 
    372         return false; 
    373     } 
    374  
    375     // Set audio language mode 
    376     bool do_audmode_set = true; 
    377     struct v4l2_tuner vt; 
    378     bzero(&vt, sizeof(struct v4l2_tuner)); 
    379     if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0) 
    380     { 
    381         VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get audio mode" + ENO); 
    382         do_audmode_set = false; 
    383     } 
    384  
    385     switch (language) 
    386     { 
    387         case 0: 
     383        // Set audio language mode 
     384        bool do_audmode_set = true; 
     385        struct v4l2_tuner vt; 
     386        bzero(&vt, sizeof(struct v4l2_tuner)); 
     387        if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0) 
     388        { 
     389            VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get audio mode" + ENO); 
     390            do_audmode_set = false; 
     391        } 
     392         
     393        switch (language) 
     394        { 
     395          case 0: 
    388396            vt.audmode = V4L2_TUNER_MODE_LANG1; 
    389397            break; 
    390         case 1: 
     398          case 1: 
    391399            vt.audmode = V4L2_TUNER_MODE_LANG2; 
    392400            break; 
    393         case 2: 
     401          case 2: 
    394402            if (usingv4l2) 
    395403                vt.audmode = V4L2_TUNER_MODE_LANG1_LANG2; 
    396404            else 
    397405                vt.audmode = V4L2_TUNER_MODE_STEREO; 
    398406            break; 
    399         default: 
     407          default: 
    400408            vt.audmode = V4L2_TUNER_MODE_LANG1; 
    401     } 
     409        } 
    402410 
    403     int audio_layer = GetFilteredAudioLayer(); 
    404     if (do_audmode_set && (2 == language) && (1 == audio_layer)) 
    405     { 
    406         VERBOSE(VB_GENERAL, "Dual audio mode incompatible with Layer I audio." 
    407                 "\n\t\t\tFalling back to Main Language"); 
    408         vt.audmode = V4L2_TUNER_MODE_LANG1; 
    409     } 
     411        int audio_layer = GetFilteredAudioLayer(); 
     412        if (do_audmode_set && (2 == language) && (1 == audio_layer)) 
     413        { 
     414            VERBOSE(VB_GENERAL, "Dual audio mode incompatible with Layer I audio." 
     415                    "\n\t\t\tFalling back to Main Language"); 
     416            vt.audmode = V4L2_TUNER_MODE_LANG1; 
     417        } 
    410418 
    411     if (do_audmode_set && ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0) 
    412     { 
    413         VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set audio mode" + ENO); 
    414     } 
     419        if (do_audmode_set && ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0) 
     420        { 
     421            VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set audio mode" + ENO); 
     422        } 
    415423 
    416     // Get volume min/max values 
    417     struct v4l2_queryctrl qctrl; 
    418     qctrl.id = V4L2_CID_AUDIO_VOLUME; 
    419     if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0) 
    420     { 
    421         VERBOSE(VB_IMPORTANT, LOC_WARN + 
    422                 "Unable to get recording volume parameters(max/min)" + ENO + 
    423                 "\n\t\t\tusing default range [0,65535]."); 
    424         qctrl.maximum = 65535; 
    425         qctrl.minimum = 0; 
    426     } 
     424        // Get volume min/max values 
     425        struct v4l2_queryctrl qctrl; 
     426        qctrl.id = V4L2_CID_AUDIO_VOLUME; 
     427        if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0) 
     428        { 
     429            VERBOSE(VB_IMPORTANT, LOC_WARN + 
     430                    "Unable to get recording volume parameters(max/min)" + ENO + 
     431                    "\n\t\t\tusing default range [0,65535]."); 
     432            qctrl.maximum = 65535; 
     433            qctrl.minimum = 0; 
     434        } 
    427435 
    428     // calculate volume in card units. 
    429     int range = qctrl.maximum - qctrl.minimum; 
    430     int value = (int) ((range * audvolume * 0.01f) + qctrl.minimum); 
    431     int ctrl_volume = min(qctrl.maximum, max(qctrl.minimum, value)); 
     436        // calculate volume in card units. 
     437        int range = qctrl.maximum - qctrl.minimum; 
     438        int value = (int) ((range * audvolume * 0.01f) + qctrl.minimum); 
     439        int ctrl_volume = min(qctrl.maximum, max(qctrl.minimum, value)); 
    432440 
    433     // Set recording volume 
    434     struct v4l2_control ctrl; 
    435     ctrl.id = V4L2_CID_AUDIO_VOLUME; 
    436     ctrl.value = ctrl_volume; 
     441        // Set recording volume 
     442        struct v4l2_control ctrl; 
     443        ctrl.id = V4L2_CID_AUDIO_VOLUME; 
     444        ctrl.value = ctrl_volume; 
    437445 
    438     if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0) 
    439     { 
    440         VERBOSE(VB_IMPORTANT, LOC_WARN + 
    441                 "Unable to set recording volume" + ENO + "\n\t\t\t" + 
    442                 "If you are using an AverMedia M179 card this is normal."); 
     446        if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0) 
     447        { 
     448            VERBOSE(VB_IMPORTANT, LOC_WARN + 
     449                    "Unable to set recording volume" + ENO + "\n\t\t\t" + 
     450                    "If you are using an AverMedia M179 card this is normal."); 
     451        } 
    443452    } 
    444453 
    445454    bool ok = true; 
     
    457466 
    458467    SetVBIOptions(chanfd); 
    459468 
    460     readfd = open(videodevice.ascii(), O_RDWR | O_NONBLOCK); 
     469    // hdpvr driver does not like NONBLOCK mode with select 
     470    if (driver == "hdpvr") 
     471        readfd = open(videodevice.ascii(), O_RDWR); 
     472    else 
     473        readfd = open(videodevice.ascii(), O_RDWR | O_NONBLOCK); 
     474 
    461475    if (readfd < 0) 
    462476    { 
    463477        VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't open video device." + ENO); 
     
    475489    { 
    476490        switch (st) 
    477491        { 
    478             case 2:  st = 2;  break; 
    479             case 10: 
    480             case 13: 
    481             case 14: st = 10; break; 
    482             case 11: st = 11; break; 
    483             case 12: st = 12; break; 
    484             default: st = 0;  break;    
     492          case 2:  st = 2;  break; 
     493          case 10: 
     494          case 13: 
     495          case 14: st = 10; break; 
     496          case 11: st = 11; break; 
     497          case 12: st = 12; break; 
     498          default: st = 0;  break;    
    485499        } 
    486500    } 
     501    else if (driver == "hdpvr") 
     502    { 
     503        // FIX ME!  // I have no idea what to put here 
     504        switch (st) 
     505        { 
     506          case 2:  st = 2;  break; 
     507          case 10: 
     508          case 13: 
     509          case 14: st = 10; break; 
     510          case 11: st = 11; break; 
     511          case 12: st = 12; break; 
     512          default: st = 0;  break;    
     513        } 
     514    } 
    487515 
    488516    if (st != (uint) streamtype) 
    489517    { 
     
    502530 
    503531    sr = (driver == "ivtv") ? 48000 : sr; // only 48kHz works properly. 
    504532 
     533    // hdpvr ? 
     534 
     535 
    505536    if (sr != (uint) audsamplerate) 
    506537    { 
    507538        VERBOSE(VB_IMPORTANT, LOC_WARN + 
     
    512543 
    513544    switch (sr) 
    514545    { 
    515         case 32000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000; 
    516         case 44100: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100; 
    517         case 48000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; 
    518         default:    return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; 
     546      case 32000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000; 
     547      case 44100: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100; 
     548      case 48000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; 
     549      default:    return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; 
    519550    } 
    520551} 
    521552 
     
    527558 
    528559    layer = (driver == "ivtv") ? 2 : layer; 
    529560 
     561    // hdpvr? 
     562 
     563 
    530564    if (layer != (uint) audtype) 
    531565    { 
    532566        VERBOSE(VB_IMPORTANT, LOC_WARN + 
     
    587621{ 
    588622    switch (st) 
    589623    { 
    590         case 0:  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS; 
    591         case 1:  return V4L2_MPEG_STREAM_TYPE_MPEG2_TS; 
    592         case 2:  return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD; 
    593         case 3:  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;  /* PES A/V    */ 
    594         case 5:  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;  /* PES V      */ 
    595         case 7:  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;  /* PES A      */ 
    596         case 10: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; 
    597         case 11: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD; /* VCD */ 
    598         case 12: return V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD; 
    599         case 13: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; /* DVD-Special 1 */ 
    600         case 14: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; /* DVD-Special 2 */ 
    601         default: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS; 
     624      case 0:  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS; 
     625      case 1:  return V4L2_MPEG_STREAM_TYPE_MPEG2_TS; 
     626      case 2:  return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD; 
     627      case 3:  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;  /* PES A/V    */ 
     628      case 5:  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;  /* PES V      */ 
     629      case 7:  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;  /* PES A      */ 
     630      case 10: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; 
     631      case 11: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD; /* VCD */ 
     632      case 12: return V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD; 
     633      case 13: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; /* DVD-Special 1 */ 
     634      case 14: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; /* DVD-Special 2 */ 
     635      default: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS; 
    602636    } 
    603637} 
    604638 
    605639bool MpegRecorder::SetV4L2DeviceOptions(int chanfd) 
    606640{ 
    607     static const uint kNumControls = 7; 
     641   static const uint kNumControls = 7; 
    608642    struct v4l2_ext_controls ctrls; 
    609643    struct v4l2_ext_control ext_ctrl[kNumControls]; 
    610644    QString control_description[kNumControls] = 
     
    625659    uint audio_layer = GetFilteredAudioLayer(); 
    626660    uint audbitrate  = GetFilteredAudioBitRate(audio_layer); 
    627661 
    628     ext_ctrl[0].id    = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ; 
    629     ext_ctrl[0].value = GetFilteredAudioSampleRate(); 
     662    if (driver != "hdpvr") { 
     663        ext_ctrl[0].id    = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ; 
     664        ext_ctrl[0].value = GetFilteredAudioSampleRate(); 
     665         
     666        ext_ctrl[1].id    = V4L2_CID_MPEG_VIDEO_ASPECT; 
     667        ext_ctrl[1].value = aspectratio - 1; 
     668         
     669        ext_ctrl[2].id    = V4L2_CID_MPEG_AUDIO_ENCODING; 
     670        ext_ctrl[2].value = audio_layer - 1; 
     671         
     672        ext_ctrl[3].id    = V4L2_CID_MPEG_AUDIO_L2_BITRATE; 
     673        ext_ctrl[3].value = audbitrate - 1; 
    630674 
    631     ext_ctrl[1].id    = V4L2_CID_MPEG_VIDEO_ASPECT; 
    632     ext_ctrl[1].value = aspectratio - 1; 
     675        ext_ctrl[4].id    = V4L2_CID_MPEG_STREAM_TYPE; 
     676        ext_ctrl[4].value = streamtype_ivtv_to_v4l2(GetFilteredStreamType()); 
     677    } 
    633678 
    634     ext_ctrl[2].id    = V4L2_CID_MPEG_AUDIO_ENCODING; 
    635     ext_ctrl[2].value = audio_layer - 1; 
     679    ext_ctrl[5].id    = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK; 
     680    ext_ctrl[5].value = maxbitrate * 1000; 
    636681 
    637     ext_ctrl[3].id    = V4L2_CID_MPEG_AUDIO_L2_BITRATE; 
    638     ext_ctrl[3].value = audbitrate - 1; 
     682    ext_ctrl[6].id    = V4L2_CID_MPEG_VIDEO_BITRATE; 
     683    ext_ctrl[6].value = (bitrate = min(bitrate, maxbitrate)) * 1000; 
    639684 
    640     ext_ctrl[4].id    = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK; 
    641     ext_ctrl[4].value = maxbitrate * 1000; 
    642  
    643     ext_ctrl[5].id    = V4L2_CID_MPEG_VIDEO_BITRATE; 
    644     ext_ctrl[5].value = (bitrate = min(bitrate, maxbitrate)) * 1000; 
    645  
    646     ext_ctrl[6].id    = V4L2_CID_MPEG_STREAM_TYPE; 
    647     ext_ctrl[6].value = streamtype_ivtv_to_v4l2(GetFilteredStreamType()); 
    648  
    649685    for (uint i = 0; i < kNumControls; i++) 
    650686    { 
    651687        int value = ext_ctrl[i].value; 
    652688 
     689        if (value != 0) { 
     690            ctrls.ctrl_class  = V4L2_CTRL_CLASS_MPEG; 
     691            ctrls.count       = 1; 
     692            ctrls.controls    = ext_ctrl + i; 
     693             
     694            if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0) 
     695            { 
     696                VERBOSE(VB_IMPORTANT, LOC_ERR + 
     697                        QString("Could not set %1 to %2") 
     698                        .arg(control_description[i]).arg(value) + ENO); 
     699            } 
     700        } 
     701    } 
     702 
     703    if (driver != "hdpvr") { 
     704        // Get controls 
     705        ext_ctrl[0].id    = V4L2_CID_MPEG_VIDEO_GOP_SIZE; 
     706        ext_ctrl[0].value = 0; 
     707         
    653708        ctrls.ctrl_class  = V4L2_CTRL_CLASS_MPEG; 
    654709        ctrls.count       = 1; 
    655         ctrls.controls    = ext_ctrl + i; 
    656  
    657         if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0) 
     710        ctrls.controls    = ext_ctrl; 
     711         
     712        if (ioctl(chanfd, VIDIOC_G_EXT_CTRLS, &ctrls) < 0) 
    658713        { 
    659             VERBOSE(VB_IMPORTANT, LOC_ERR + 
    660                     QString("Could not set %1 to %2") 
    661                     .arg(control_description[i]).arg(value) + ENO); 
     714            VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get " 
     715                    "V4L2_CID_MPEG_VIDEO_GOP_SIZE, defaulting to 12" + ENO); 
     716            ext_ctrl[0].value = 12; 
    662717        } 
     718         
     719        keyframedist = ext_ctrl[0].value; 
    663720    } 
    664721 
    665     // Get controls 
    666     ext_ctrl[0].id    = V4L2_CID_MPEG_VIDEO_GOP_SIZE; 
    667     ext_ctrl[0].value = 0; 
    668  
    669     ctrls.ctrl_class  = V4L2_CTRL_CLASS_MPEG; 
    670     ctrls.count       = 1; 
    671     ctrls.controls    = ext_ctrl; 
    672  
    673     if (ioctl(chanfd, VIDIOC_G_EXT_CTRLS, &ctrls) < 0) 
    674     { 
    675         VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get " 
    676                 "V4L2_CID_MPEG_VIDEO_GOP_SIZE, defaulting to 12" + ENO); 
    677         ext_ctrl[0].value = 12; 
    678     } 
    679  
    680     keyframedist = ext_ctrl[0].value; 
    681  
    682722    return true; 
    683723} 
    684724 
     
    687727    if (!vbimode) 
    688728        return true; 
    689729 
     730    if (driver == "hdpvr") 
     731        return true; 
     732 
    690733    if (has_buggy_vbi) 
    691734    { 
    692735        cout<<" *********************** WARNING ***********************"<<endl; 
     
    717760 
    718761        if (ioctl(chanfd, IVTV_IOC_G_VBI_MODE, &vbifmt) >= 0) 
    719762        { 
    720             VERBOSE(VB_RECORD, LOC + QString( 
    721                         "VBI service:%1, packet size:%2, io size:%3") 
     763            VERBOSE(VB_RECORD, 
     764                    LOC + QString("VBI service:%1, packet size:%2, io size:%3") 
    722765                    .arg(vbifmt.service_set).arg(vbifmt.packet_size) 
    723766                    .arg(vbifmt.io_size)); 
    724767        } 
     
    733776        bzero(&vbifmt, sizeof(struct v4l2_format)); 
    734777        vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; 
    735778        vbifmt.fmt.sliced.service_set |= (1 == vbimode) ? 
    736             V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; 
     779               V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; 
    737780 
    738781        if (ioctl(chanfd, VIDIOC_S_FMT, &vbifmt) < 0) 
    739782        { 
     
    805848        return OpenV4L2DeviceAsInput(); 
    806849} 
    807850 
     851void MpegRecorder::StopRecording(void) 
     852{ 
     853    encoding = false; 
     854} 
     855 
     856void MpegRecorder::ResetForNewFile(void) 
     857{ 
     858    DTVRecorder::ResetForNewFile(); 
     859 
     860    bzero(_stream_id,  sizeof(_stream_id)); 
     861    bzero(_pid_status, sizeof(_pid_status)); 
     862    memset(_continuity_counter, 0xff, sizeof(_continuity_counter)); 
     863} 
     864 
     865void MpegRecorder::Reset(void) 
     866{ 
     867    VERBOSE(VB_RECORD, LOC + "Reset(void)"); 
     868    ResetForNewFile(); 
     869 
     870    _start_code = 0xffffffff; 
     871 
     872    if (curRecording) { 
     873        if (driver == "hdpvr") { 
     874            curRecording->ClearPositionMap(MARK_GOP_BYFRAME); 
     875        } 
     876        else { 
     877            curRecording->ClearPositionMap(MARK_GOP_START); 
     878        } 
     879    } 
     880} 
     881 
     882void MpegRecorder::Pause(bool clear) 
     883{ 
     884    cleartimeonpause = clear; 
     885    paused = false; 
     886    request_pause = true; 
     887} 
     888 
     889bool MpegRecorder::PauseAndWait(int timeout) 
     890{ 
     891    if (request_pause) 
     892    { 
     893        if (!paused) 
     894        { 
     895            VERBOSE(VB_RECORD, "MpegRecorder::PauseAndWait pausing"); 
     896            if (requires_special_pause) 
     897            { 
     898                // Some ivtv drivers require streaming to be disabled before 
     899                // an input switch and other channel format setting. 
     900                struct v4l2_encoder_cmd command; 
     901                memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 
     902                command.cmd = V4L2_ENC_CMD_STOP; 
     903                ioctl(readfd, VIDIOC_ENCODER_CMD, &command); 
     904            } 
     905 
     906            paused = true; 
     907            pauseWait.wakeAll(); 
     908            if (tvrec) 
     909                tvrec->RecorderPaused(); 
     910        } 
     911        unpauseWait.wait(timeout); 
     912    } 
     913    if (!request_pause) 
     914    { 
     915        if (paused) 
     916        { 
     917            VERBOSE(VB_RECORD, "MpegRecorder::PauseAndWait un-pausing"); 
     918            if (requires_special_pause) 
     919            { 
     920                // Some ivtv drivers require streaming to be disabled before 
     921                // an input switch and other channel format setting. 
     922                struct v4l2_encoder_cmd command; 
     923                command.cmd = V4L2_ENC_CMD_START; 
     924                ioctl(readfd, VIDIOC_ENCODER_CMD, &command); 
     925            } 
     926 
     927            if (_stream_data) 
     928                _stream_data->Reset(_stream_data->DesiredProgram()); 
     929        } 
     930        paused = false; 
     931    } 
     932    return paused; 
     933} 
     934 
     935void MpegRecorder::SetStreamData(MPEGStreamData *data) 
     936{ 
     937    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin"); 
     938 
     939    if (data == _stream_data) 
     940    { 
     941        VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0"); 
     942 
     943        return; 
     944    } 
     945 
     946    MPEGStreamData *old_data = _stream_data; 
     947    _stream_data = data; 
     948    if (old_data) 
     949        delete old_data; 
     950 
     951    if (data) 
     952        data->AddMPEGSPListener(this); 
     953 
     954    data->SetDesiredProgram(1); 
     955 
     956    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1"); 
     957} 
     958 
    808959void MpegRecorder::StartRecording(void) 
    809960{ 
    810961    if (!Open()) 
    811962    { 
    812         errored = true; 
    813         return; 
     963        _error = true; 
     964        return; 
    814965    } 
    815966 
    816     if (!SetupRecording()) 
    817     { 
    818         VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup recording."); 
    819         errored = true; 
    820         return; 
     967    VERBOSE(VB_RECORD, "MpegRecorder::StartRecording"); 
     968 
     969    _start_code = 0xffffffff; 
     970    _last_gop_seen = 0; 
     971    _frames_written_count = 0; 
     972 
     973    if (driver == "hdpvr") { 
     974        SetPositionMapType(MARK_GOP_BYFRAME); 
     975 
     976        if (_stream_data == NULL) { 
     977            MPEGStreamData *sd = new MPEGStreamData(1, true); 
     978            sd->Reset(); 
     979            sd->SetRecordingType(_recording_type); 
     980            SetStreamData(sd); 
     981        } 
     982        else 
     983            _stream_data->Reset(1); 
     984 
     985        _stream_data->AddAVListener(this); 
     986        _stream_data->AddWritingListener(this); 
     987 
     988        // Make sure the first things in the file are a PAT & PMT 
     989        _wait_for_keyframe_option = false; 
     990        HandleSingleProgramPAT(_stream_data->PATSingleProgram()); 
     991        HandleSingleProgramPMT(_stream_data->PMTSingleProgram()); 
     992        _wait_for_keyframe_option = true; 
    821993    } 
     994    else { 
     995        SetPositionMapType(MARK_GOP_START); 
     996    } 
    822997 
    823998    encoding = true; 
    824999    recording = true; 
     1000 
    8251001    unsigned char *buffer = new unsigned char[bufferSize + 1]; 
    826     int ret; 
     1002    uint remainder = 0; 
    8271003 
     1004    int len; 
     1005 
    8281006    MythTimer elapsedTimer; 
    8291007    float elapsed; 
    8301008 
     
    8391017        if (PauseAndWait(100)) 
    8401018            continue; 
    8411019 
    842         if ((deviceIsMpegFile) && (framesWritten)) 
     1020        if ((deviceIsMpegFile) && (GetFramesWritten())) 
    8431021        { 
    8441022            elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; 
    845             while ((framesWritten / elapsed) > 30) 
     1023            while ((GetFramesWritten() / elapsed) > 30) 
    8461024            { 
    8471025                usleep(50000); 
    8481026                elapsed = (elapsedTimer.elapsed() / 1000.0) + 1; 
     
    8521030        if (readfd < 0) 
    8531031            readfd = open(videodevice.ascii(), O_RDWR); 
    8541032 
    855         tv.tv_sec = 5; 
    856         tv.tv_usec = 0; 
    857         FD_ZERO(&rdset); 
    858         FD_SET(readfd, &rdset); 
    859  
    8601033#if defined(__FreeBSD__) 
    8611034        // HACK. FreeBSD PVR150/500 driver doesn't currently support select() 
    8621035#else 
    863         switch (select(readfd + 1, &rdset, NULL, NULL, &tv)) 
    864         { 
    865             case -1: 
     1036        // hdpvr driver does not like NONBLOCK mode with select 
     1037        if (driver != "hdpvr") { 
     1038            tv.tv_sec = 5; 
     1039            tv.tv_usec = 0; 
     1040            FD_ZERO(&rdset); 
     1041            FD_SET(readfd, &rdset); 
     1042 
     1043            switch (select(readfd + 1, &rdset, NULL, NULL, &tv)) 
     1044            { 
     1045              case -1: 
    8661046                if (errno == EINTR) 
    8671047                    continue; 
    868  
     1048                 
    8691049                VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO); 
    8701050                continue; 
    871  
    872             case 0: 
     1051                 
     1052              case 0: 
    8731053                VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - " 
    8741054                        "ivtv driver has stopped responding"); 
    875  
     1055                 
    8761056                if (close(readfd) != 0) 
    8771057                { 
    8781058                    VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO); 
    8791059                } 
    880  
     1060                 
    8811061                readfd = -1; // Force PVR card to be reopened on next iteration 
    8821062                continue; 
    883  
    884            default: break; 
     1063                 
     1064              default: break; 
     1065            } 
    8851066        } 
    8861067#endif 
    8871068 
    888         ret = read(readfd, buffer, bufferSize); 
     1069        if (remainder) 
     1070            VERBOSE(VB_RECORD, LOC + QString("Remainder %1, Reading %2 bytes") 
     1071                    .arg(remainder).arg(bufferSize - remainder)); 
     1072        len = read(readfd, &(buffer[remainder]), bufferSize - remainder); 
    8891073 
    890         if ((ret == 0) && 
    891             (deviceIsMpegFile)) 
     1074        if ((len == 0) && (deviceIsMpegFile)) 
    8921075        { 
    8931076            close(readfd); 
    8941077            readfd = open(videodevice.ascii(), O_RDONLY); 
    8951078 
    8961079            if (readfd >= 0) 
    897                 ret = read(readfd, buffer, bufferSize); 
    898             if (ret <= 0) 
     1080                len = read(readfd, &(buffer[remainder]), 
     1081                           bufferSize - remainder); 
     1082            if (len <= 0) 
    8991083            { 
    9001084                encoding = false; 
    9011085                continue; 
    9021086            } 
    9031087        } 
    904         else if (ret < 0 && errno != EAGAIN) 
     1088        else if (len < 0 && errno != EAGAIN) 
    9051089        { 
    9061090            VERBOSE(VB_IMPORTANT, LOC_ERR + QString("error reading from: %1") 
    9071091                    .arg(videodevice) + ENO); 
    908  
    9091092            continue; 
    9101093        } 
    911         else if (ret > 0) 
     1094        else if (len > 0) 
    9121095        { 
    913             ProcessData(buffer, ret); 
     1096            len += remainder; 
     1097 
     1098            if (driver == "hdpvr") 
     1099                remainder = _stream_data->ProcessData(buffer, len); 
     1100            else 
     1101                ProcessPSdata(buffer, len); 
    9141102        } 
    9151103    } 
    9161104 
    9171105    FinishRecording(); 
     1106    TeardownAll(); 
    9181107 
    9191108    delete[] buffer; 
    9201109    recording = false; 
     1110 
     1111    VERBOSE(VB_RECORD, "MpegRecorder::StartRecording done"); 
    9211112} 
    9221113 
    923 bool MpegRecorder::SetupRecording(void) 
     1114void MpegRecorder::ProcessPSdata(unsigned char *buffer, uint len) 
    9241115{ 
    925     leftovers = 0xFFFFFFFF; 
    926     numgops = 0; 
    927     lastseqstart = 0; 
    928     return true; 
     1116    FindPSKeyFrames(buffer, len); 
    9291117} 
    9301118 
    931 void MpegRecorder::FinishRecording(void) 
     1119bool MpegRecorder::ProcessTSPacket(const TSPacket &tspacket) 
    9321120{ 
    933     ringBuffer->WriterFlush(); 
     1121    const uint pid = tspacket.PID(); 
    9341122 
    935     if (curRecording) 
     1123    // Check continuity counter 
     1124    if ((pid != 0x1fff) && !CheckCC(pid, tspacket.ContinuityCounter())) 
    9361125    { 
    937         curRecording->SetFilesize(ringBuffer->GetRealFileSize()); 
    938         SavePositionMap(true); 
     1126        VERBOSE(VB_RECORD, LOC + 
     1127                QString("PID 0x%1 discontinuity detected").arg(pid,0,16)); 
     1128        _continuity_error_count++; 
    9391129    } 
    940     positionMapLock.lock(); 
    941     positionMap.clear(); 
    942     positionMapDelta.clear(); 
    943     positionMapLock.unlock(); 
     1130 
     1131    // Only write the packet 
     1132    // if audio/video key-frames have been found 
     1133    if (_wait_for_keyframe_option && _first_keyframe < 0) 
     1134        return true; 
     1135     
     1136    _buffer_packets = true; 
     1137 
     1138    BufferedWrite(tspacket); 
     1139 
     1140    return true; 
    9441141} 
    9451142 
    946 #define PACK_HEADER   0x000001BA 
    947 #define GOP_START     0x000001B8 
    948 #define SEQ_START     0x000001B3 
    949 #define SLICE_MIN     0x00000101 
    950 #define SLICE_MAX     0x000001af 
    951  
    952 void MpegRecorder::ProcessData(unsigned char *buffer, int len) 
     1143bool MpegRecorder::ProcessVideoTSPacket(const TSPacket &tspacket) 
    9531144{ 
    954     unsigned char *bufptr = buffer, *bufstart = buffer; 
    955     unsigned int state = leftovers, v = 0; 
    956     int leftlen = len; 
     1145    uint streamType = _stream_id[tspacket.PID()]; 
    9571146 
    958     while (bufptr < buffer + len) 
     1147    // Check for keyframes and count frames 
     1148    if (streamType == StreamID::H264Video) 
    9591149    { 
    960         v = *bufptr++; 
    961         if (state == 0x000001) 
    962         { 
    963             state = ((state << 8) | v) & 0xFFFFFF; 
    964              
    965             if (state == PACK_HEADER) 
    966             { 
    967                 long long startpos = ringBuffer->GetWritePosition(); 
    968                 startpos += buildbuffersize + bufptr - bufstart - 4; 
    969                 lastpackheaderpos = startpos; 
     1150        _buffer_packets = !FindH264Keyframes(&tspacket); 
     1151        if (!_seen_sps) 
     1152            return true; 
     1153    } 
     1154    else 
     1155    { 
     1156        _buffer_packets = !FindMPEG2Keyframes(&tspacket); 
     1157    } 
    9701158 
    971                 int curpos = bufptr - bufstart - 4; 
    972                 if (curpos < 0) 
    973                 { 
    974                     // header was split 
    975                     buildbuffersize += curpos; 
    976                     if (buildbuffersize > 0) 
    977                         ringBuffer->Write(buildbuffer, buildbuffersize); 
     1159    return ProcessAVTSPacket(tspacket); 
     1160} 
    9781161 
    979                     buildbuffersize = 4; 
    980                     memcpy(buildbuffer, &state, 4); 
     1162bool MpegRecorder::ProcessAudioTSPacket(const TSPacket &tspacket) 
     1163{ 
     1164    _buffer_packets = !FindAudioKeyframes(&tspacket); 
     1165    return ProcessAVTSPacket(tspacket); 
     1166} 
    9811167 
    982                     leftlen = leftlen - curpos + 4; 
    983                     bufstart = bufptr; 
    984                 } 
    985                 else 
    986                 { 
    987                     // header was entirely in this packet 
    988                     memcpy(buildbuffer + buildbuffersize, bufstart, curpos); 
    989                     buildbuffersize += curpos; 
    990                     bufstart += curpos; 
    991                     leftlen -= curpos; 
     1168/// Common code for processing either audio or video packets 
     1169bool MpegRecorder::ProcessAVTSPacket(const TSPacket &tspacket) 
     1170{ 
     1171    const uint pid = tspacket.PID(); 
    9921172 
    993                     if (buildbuffersize > 0) 
    994                         ringBuffer->Write(buildbuffer, buildbuffersize); 
     1173    // Check continuity counter 
     1174    if ((pid != 0x1fff) && !CheckCC(pid, tspacket.ContinuityCounter())) 
     1175    { 
     1176        VERBOSE(VB_RECORD, LOC + 
     1177                QString("PID 0x%1 discontinuity detected").arg(pid,0,16)); 
     1178        _continuity_error_count++; 
     1179    } 
    9951180 
    996                     buildbuffersize = 0; 
    997                 } 
    998             } 
     1181    // Sync recording start to first keyframe 
     1182    if (_wait_for_keyframe_option && _first_keyframe < 0) 
     1183        return true; 
    9991184 
    1000             if (state == SEQ_START) 
    1001             { 
    1002                 lastseqstart = lastpackheaderpos; 
    1003             } 
     1185    // Sync streams to the first Payload Unit Start Indicator 
     1186    // _after_ first keyframe iff _wait_for_keyframe_option is true 
     1187    if (!(_pid_status[pid] & kPayloadStartSeen) && tspacket.HasPayload()) 
     1188    { 
     1189        if (!tspacket.PayloadStart()) 
     1190            return true; // not payload start - drop packet 
    10041191 
    1005             if (state == GOP_START && lastseqstart == lastpackheaderpos) 
    1006             { 
    1007                 framesWritten = numgops * keyframedist; 
    1008                 numgops++; 
    1009                 HandleKeyframe(); 
    1010             } 
    1011         } 
    1012         else 
    1013             state = ((state << 8) | v) & 0xFFFFFF; 
    1014     } 
     1192        VERBOSE(VB_RECORD, 
     1193                QString("PID 0x%1 Found Payload Start").arg(pid,0,16)); 
    10151194 
    1016     leftovers = state; 
    1017  
    1018     if (buildbuffersize + leftlen > kBuildBufferMaxSize) 
    1019     { 
    1020         ringBuffer->Write(buildbuffer, buildbuffersize); 
    1021         buildbuffersize = 0; 
     1195        _pid_status[pid] |= kPayloadStartSeen; 
    10221196    } 
    10231197 
    1024     // copy remaining.. 
    1025     memcpy(buildbuffer + buildbuffersize, bufstart, leftlen); 
    1026     buildbuffersize += leftlen; 
    1027 } 
     1198    BufferedWrite(tspacket); 
    10281199 
    1029 void MpegRecorder::StopRecording(void) 
    1030 { 
    1031     encoding = false; 
     1200    return true; 
    10321201} 
    10331202 
    1034 void MpegRecorder::ResetForNewFile(void) 
     1203 
     1204void MpegRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat) 
    10351205{ 
    1036     errored = false; 
    1037     framesWritten = 0; 
    1038     numgops = 0; 
    1039     lastseqstart = lastpackheaderpos = 0; 
     1206    if (!pat) 
     1207    { 
     1208        VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPAT(NULL)"); 
     1209        return; 
     1210    } 
    10401211 
    1041     positionMap.clear(); 
    1042     positionMapDelta.clear(); 
    1043 } 
     1212    if (!ringBuffer) 
     1213        return; 
    10441214 
    1045 void MpegRecorder::Reset(void) 
    1046 { 
    1047     ResetForNewFile(); 
     1215    uint posA[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 
    10481216 
    1049     leftovers = 0xFFFFFFFF; 
    1050     buildbuffersize = 0; 
     1217    uint next_cc = (pat->tsheader()->ContinuityCounter()+1)&0xf; 
     1218    pat->tsheader()->SetContinuityCounter(next_cc); 
     1219    DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(pat->tsheader()))); 
    10511220 
    1052     if (curRecording) 
    1053         curRecording->ClearPositionMap(MARK_GOP_START); 
    1054 } 
     1221    uint posB[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 
    10551222 
    1056 void MpegRecorder::Pause(bool clear) 
    1057 { 
    1058     cleartimeonpause = clear; 
    1059     paused = false; 
    1060     request_pause = true; 
    1061 } 
    1062  
    1063 bool MpegRecorder::PauseAndWait(int timeout) 
    1064 { 
    1065     if (request_pause) 
     1223#if 0 
     1224    if (posB[0] + posB[1] * TSPacket::SIZE >  
     1225        posA[0] + posA[1] * TSPacket::SIZE) 
    10661226    { 
    1067         if (!paused) 
    1068         { 
    1069             if (requires_special_pause) 
    1070             { 
    1071                 // Some ivtv drivers require streaming to be disabled before 
    1072                 // an input switch and other channel format setting. 
    1073                 struct v4l2_encoder_cmd command; 
    1074                 memset(&command, 0, sizeof(struct v4l2_encoder_cmd)); 
    1075                 command.cmd = V4L2_ENC_CMD_STOP; 
    1076                 ioctl(readfd, VIDIOC_ENCODER_CMD, &command); 
    1077             } 
    1078  
    1079             paused = true; 
    1080             pauseWait.wakeAll(); 
    1081             if (tvrec) 
    1082                 tvrec->RecorderPaused(); 
    1083         } 
    1084         unpauseWait.wait(timeout); 
     1227        VERBOSE(VB_RECORD, LOC + "Wrote PAT @" 
     1228                << posA[0] << " + " << (posA[1] * TSPacket::SIZE)); 
    10851229    } 
    1086     if (!request_pause) 
     1230    else 
    10871231    { 
    1088         if (paused) 
    1089         { 
    1090             if (requires_special_pause) 
    1091             { 
    1092                 // Some ivtv drivers require streaming to be disabled before 
    1093                 // an input switch and other channel format setting. 
    1094                 struct v4l2_encoder_cmd command; 
    1095                 command.cmd = V4L2_ENC_CMD_START; 
    1096                 ioctl(readfd, VIDIOC_ENCODER_CMD, &command); 
    1097             } 
    1098         } 
    1099         paused = false; 
     1232        VERBOSE(VB_RECORD, LOC + "Saw PAT but did not write to disk yet"); 
    11001233    } 
    1101     return paused; 
     1234#endif 
    11021235} 
    11031236 
    1104 long long MpegRecorder::GetKeyframePosition(long long desired) 
     1237void MpegRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 
    11051238{ 
    1106     QMutexLocker locker(&positionMapLock); 
    1107     long long ret = -1; 
     1239    if (!pmt) { 
     1240        return; 
     1241    } 
    11081242 
    1109     if (positionMap.find(desired) != positionMap.end()) 
    1110         ret = positionMap[desired]; 
     1243    // collect stream types for H.264 (MPEG-4 AVC) keyframe detection 
     1244    for (uint i = 0; i < pmt->StreamCount(); i++) 
     1245        _stream_id[pmt->StreamPID(i)] = pmt->StreamType(i); 
    11111246 
    1112     return ret; 
    1113 } 
     1247    if (!ringBuffer) 
     1248        return; 
    11141249 
    1115 // documented in recorderbase.h 
    1116 void MpegRecorder::SetNextRecording(const ProgramInfo *progInf, RingBuffer *rb) 
    1117 { 
    1118     // First we do some of the time consuming stuff we can do now 
    1119     SavePositionMap(true); 
    1120     ringBuffer->WriterFlush(); 
    1121         if (curRecording) 
    1122         curRecording->SetFilesize(ringBuffer->GetRealFileSize()); 
     1250    unsigned char buf[8 * 1024]; 
     1251    uint next_cc = (pmt->tsheader()->ContinuityCounter()+1)&0xf; 
     1252    pmt->tsheader()->SetContinuityCounter(next_cc); 
     1253    uint size = pmt->WriteAsTSPackets(buf, next_cc); 
    11231254 
    1124     // Then we set the next info 
     1255    uint posA[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 
     1256 
     1257    for (uint i = 0; i < size ; i += TSPacket::SIZE) 
     1258        DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(&buf[i]))); 
     1259 
     1260    uint posB[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() }; 
     1261 
     1262#if 0 
     1263    if (posB[0] + posB[1] * TSPacket::SIZE >  
     1264        posA[0] + posA[1] * TSPacket::SIZE) 
    11251265    { 
    1126         QMutexLocker locker(&nextRingBufferLock); 
    1127         nextRecording = NULL; 
    1128         if (progInf) 
    1129             nextRecording = new ProgramInfo(*progInf); 
    1130         nextRingBuffer = rb; 
     1266        VERBOSE(VB_RECORD, LOC + "Wrote PMT @" 
     1267                << posA[0] << " + " << (posA[1] * TSPacket::SIZE)); 
    11311268    } 
    1132 } 
    1133  
    1134 /** \fn MpegRecorder::HandleKeyframe(void) 
    1135  *  \brief This save the current frame to the position maps 
    1136  *         and handles ringbuffer switching. 
    1137  */ 
    1138 void MpegRecorder::HandleKeyframe(void) 
    1139 { 
    1140     // Add key frame to position map 
    1141     positionMapLock.lock(); 
    1142     if (!positionMap.contains(numgops)) 
     1269    else 
    11431270    { 
    1144         positionMapDelta[numgops] = lastpackheaderpos; 
    1145         positionMap[numgops]      = lastpackheaderpos; 
     1271        VERBOSE(VB_RECORD, LOC + "Saw PMT but did not write to disk yet"); 
    11461272    } 
    1147     positionMapLock.unlock(); 
    1148  
    1149     // Perform ringbuffer switch if needed. 
    1150     CheckForRingBufferSwitch(); 
     1273#endif 
    11511274} 
    11521275