Ticket #5443: hdpvr-0.13-recorder.patch

File hdpvr-0.13-recorder.patch, 47.3 KB (added by jppoet@…, 16 years ago)

Version 0.13

  • 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
    1215{
    1316  public:
    1417    MpegRecorder(TVRec*);
     
    3336    bool PauseAndWait(int timeout = 100);
    3437
    3538    bool IsRecording(void) { return recording; }
    36     bool IsErrored(void) { return errored; }
    3739
    38     long long GetFramesWritten(void) { return framesWritten; }
    39 
    4040    bool Open(void);
    4141    int GetVideoFd(void) { return chanfd; }
    4242
    43     long long GetKeyframePosition(long long desired);
     43    // TS
     44    virtual void SetStreamData(MPEGStreamData*);
     45    virtual MPEGStreamData *GetStreamData(void) { return _stream_data; }
    4446
    45     void SetNextRecording(const ProgramInfo*, RingBuffer*);
     47    // implements MPEGSingleProgramStreamListener
     48    void HandleSingleProgramPAT(ProgramAssociationTable *pat);
     49    void HandleSingleProgramPMT(ProgramMapTable *pmt);
    4650
    4751  private:
    48     bool SetupRecording(void);
    49     void FinishRecording(void);
    50     void HandleKeyframe(void);
    51 
    5252    void ProcessData(unsigned char *buffer, int len);
    5353
    5454    bool OpenMpegFileAsInput(void);
     
    6060    uint GetFilteredAudioSampleRate(void) const;
    6161    uint GetFilteredAudioLayer(void) const;
    6262    uint GetFilteredAudioBitRate(uint audio_layer) const;
     63    void ProcessPSdata(unsigned char *buffer, uint len);
     64    void ProcessTSdata(unsigned char * data, uint len, uint & leftover);
     65    bool ProcessTSPacket(const TSPacket &tspacket);
    6366
    6467    void ResetForNewFile(void);
    6568
     69    inline bool CheckCC(uint pid, uint cc);
     70
    6671    bool deviceIsMpegFile;
    6772    int bufferSize;
    6873
     
    7883    // State
    7984    bool recording;
    8085    bool encoding;
    81     bool errored;
    8286
    8387    // Pausing state
    8488    bool cleartimeonpause;
    8589
    86     // Number of frames written
    87     long long framesWritten;
    88 
    8990    // Encoding info
    9091    int width, height;
    9192    int bitrate, maxbitrate, streamtype, aspectratio;
     
    9798    int chanfd;
    9899    int readfd;
    99100
    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 
    112101    static const int   audRateL1[];
    113102    static const int   audRateL2[];
    114103    static const int   audRateL3[];
    115104    static const char *streamType[];
    116105    static const char *aspectRatio[];
    117106    static const unsigned int kBuildBufferMaxSize;
     107
     108    // TS
     109    MPEGStreamData *_stream_data;
     110    unsigned char   _stream_id[0x1fff];
     111    unsigned char   _pid_status[0x1fff];
     112    unsigned char   _continuity_counter[0x1fff];
     113    static const unsigned char kPayloadStartSeen = 0x2;
     114
     115    // Statistics
     116    mutable uint        _continuity_error_count;
     117    mutable uint        _stream_overflow_count;
     118    mutable uint        _bad_packet_count;
    118119};
     120
     121inline bool MpegRecorder::CheckCC(uint pid, uint new_cnt)
     122{
     123    bool ok = ((((_continuity_counter[pid] + 1) & 0xf) == new_cnt) ||
     124               (_continuity_counter[pid] == 0xFF));
     125
     126    _continuity_counter[pid] = new_cnt & 0xf;
     127
     128    return ok;
     129}
     130
    119131#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 = 1500 * 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        {
     
    809852{
    810853    if (!Open())
    811854    {
    812         errored = true;
    813         return;
     855        _error = true;
     856        return;
    814857    }
    815858
    816     if (!SetupRecording())
    817     {
    818         VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup recording.");
    819         errored = true;
    820         return;
     859    _start_code = 0xffffffff;
     860    _last_gop_seen = 0;
     861    _frames_written_count = 0;
     862
     863    if (driver == "hdpvr") {
     864        SetPositionMapType(MARK_GOP_BYFRAME);
     865
     866        if (_stream_data == NULL) {
     867            MPEGStreamData *sd = new MPEGStreamData(1, true);
     868            sd->Reset();
     869            sd->SetRecordingType(_recording_type);
     870            SetStreamData(sd);
     871        }
     872        else
     873            _stream_data->Reset(1);
     874
     875        // Make sure the first things in the file are a PAT & PMT
     876        _wait_for_keyframe_option = false;
     877        HandleSingleProgramPAT(_stream_data->PATSingleProgram());
     878        HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
     879        _wait_for_keyframe_option = true;
    821880    }
     881    else {
     882        SetPositionMapType(MARK_GOP_START);
     883    }
    822884
    823885    encoding = true;
    824886    recording = true;
     887
    825888    unsigned char *buffer = new unsigned char[bufferSize + 1];
    826     int ret;
     889    uint remainder = 0;
    827890
     891    int len;
     892
    828893    MythTimer elapsedTimer;
    829894    float elapsed;
    830895
     
    839904        if (PauseAndWait(100))
    840905            continue;
    841906
    842         if ((deviceIsMpegFile) && (framesWritten))
     907        if ((deviceIsMpegFile) && (GetFramesWritten()))
    843908        {
    844909            elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
    845             while ((framesWritten / elapsed) > 30)
     910            while ((GetFramesWritten() / elapsed) > 30)
    846911            {
    847912                usleep(50000);
    848913                elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
     
    852917        if (readfd < 0)
    853918            readfd = open(videodevice.ascii(), O_RDWR);
    854919
    855         tv.tv_sec = 5;
    856         tv.tv_usec = 0;
    857         FD_ZERO(&rdset);
    858         FD_SET(readfd, &rdset);
    859 
    860920#if defined(__FreeBSD__)
    861921        // HACK. FreeBSD PVR150/500 driver doesn't currently support select()
    862922#else
    863         switch (select(readfd + 1, &rdset, NULL, NULL, &tv))
    864         {
    865             case -1:
     923        // hdpvr driver does not like NONBLOCK mode with select
     924        if (driver != "hdpvr") {
     925            tv.tv_sec = 5;
     926            tv.tv_usec = 0;
     927            FD_ZERO(&rdset);
     928            FD_SET(readfd, &rdset);
     929
     930            switch (select(readfd + 1, &rdset, NULL, NULL, &tv))
     931            {
     932              case -1:
    866933                if (errno == EINTR)
    867934                    continue;
    868 
     935               
    869936                VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO);
    870937                continue;
    871 
    872             case 0:
     938               
     939              case 0:
    873940                VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - "
    874941                        "ivtv driver has stopped responding");
    875 
     942               
    876943                if (close(readfd) != 0)
    877944                {
    878945                    VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO);
    879946                }
    880 
     947               
    881948                readfd = -1; // Force PVR card to be reopened on next iteration
    882949                continue;
    883 
    884            default: break;
     950               
     951              default: break;
     952            }
    885953        }
    886954#endif
    887955
    888         ret = read(readfd, buffer, bufferSize);
     956        if (remainder)
     957            VERBOSE(VB_RECORD, LOC + QString("Remainder %1, Reading %2 bytes")
     958                    .arg(remainder).arg(bufferSize - remainder));
     959        len = read(readfd, &(buffer[remainder]), bufferSize - remainder);
    889960
    890         if ((ret == 0) &&
    891             (deviceIsMpegFile))
     961        if ((len == 0) && (deviceIsMpegFile))
    892962        {
    893963            close(readfd);
    894964            readfd = open(videodevice.ascii(), O_RDONLY);
    895965
    896966            if (readfd >= 0)
    897                 ret = read(readfd, buffer, bufferSize);
    898             if (ret <= 0)
     967                len = read(readfd, &(buffer[remainder]),
     968                           bufferSize - remainder);
     969            if (len <= 0)
    899970            {
    900971                encoding = false;
    901972                continue;
    902973            }
    903974        }
    904         else if (ret < 0 && errno != EAGAIN)
     975        else if (len < 0 && errno != EAGAIN)
    905976        {
    906977            VERBOSE(VB_IMPORTANT, LOC_ERR + QString("error reading from: %1")
    907978                    .arg(videodevice) + ENO);
    908 
    909979            continue;
    910980        }
    911         else if (ret > 0)
     981        else if (len > 0)
    912982        {
    913             ProcessData(buffer, ret);
     983            len += remainder;
     984
     985            if (driver == "hdpvr")
     986                ProcessTSdata(buffer, len, remainder);
     987            else
     988                ProcessPSdata(buffer, len);
    914989        }
    915990    }
    916991
    917992    FinishRecording();
     993    TeardownAll();
    918994
    919995    delete[] buffer;
    920996    recording = false;
    921997}
    922998
    923 bool MpegRecorder::SetupRecording(void)
     999void MpegRecorder::ProcessPSdata(unsigned char *buffer, uint len)
    9241000{
    925     leftovers = 0xFFFFFFFF;
    926     numgops = 0;
    927     lastseqstart = 0;
    928     return true;
     1001    FindPSKeyFrames(buffer, len);
    9291002}
    9301003
    931 void MpegRecorder::FinishRecording(void)
     1004void MpegRecorder::ProcessTSdata(unsigned char * buffer, uint len,
     1005                                 uint & remainder)
    9321006{
    933     ringBuffer->WriterFlush();
     1007    uint idx, pos;
     1008    int       synced_cnt = 0;
    9341009
    935     if (curRecording)
    936     {
    937         curRecording->SetFilesize(ringBuffer->GetRealFileSize());
    938         SavePositionMap(true);
    939     }
    940     positionMapLock.lock();
    941     positionMap.clear();
    942     positionMapDelta.clear();
    943     positionMapLock.unlock();
    944 }
     1010#if 0
     1011    VERBOSE(VB_RECORD, LOC + QString("idx: %1, end: %2, remainder: %3, len: %4")
     1012            .arg(TSPacket::SIZE - remainder)
     1013            .arg(end)
     1014            .arg(remainder)
     1015            .arg(len));
     1016#endif
     1017    for (idx = 0; idx < len; ) {
     1018        // Find header
     1019        for (pos = idx; pos < len; ++pos) {
     1020            if (buffer[pos] == SYNC_BYTE )
     1021                break;
     1022        }
    9451023
    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
     1024        if (pos == len) {
     1025            VERBOSE(VB_IMPORTANT, LOC_ERR + "No TS header.");
     1026            break;
     1027        }
    9511028
    952 void MpegRecorder::ProcessData(unsigned char *buffer, int len)
    953 {
    954     unsigned char *bufptr = buffer, *bufstart = buffer;
    955     unsigned int state = leftovers, v = 0;
    956     int leftlen = len;
     1029        if (pos > idx) {
     1030            VERBOSE(VB_IMPORTANT, LOC_ERR +
     1031                    QString("TS packet at %1 not in sync, after %2")
     1032                    .arg(pos).arg(synced_cnt));
     1033            synced_cnt = 0;
     1034        }
     1035        else
     1036            ++synced_cnt;
    9571037
    958     while (bufptr < buffer + len)
    959     {
    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;
     1038        if ((len - pos) < TSPacket::SIZE) {
     1039            remainder = len - pos;
     1040            memmove(buffer, &buffer[pos], remainder);
     1041            VERBOSE(VB_RECORD, LOC_ERR +
     1042                    QString("TS packet at %1 stradles end of buffer.")
     1043                    .arg(pos));
     1044            VERBOSE(VB_RECORD, LOC +
     1045                    QString("remainder: %1, idx: %2, pos: %3")
     1046                    .arg(remainder)
     1047                    .arg(idx)
     1048                    .arg(pos));
     1049            return;
     1050        }
    9701051
    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);
     1052        ProcessTSPacket(* reinterpret_cast<const TSPacket *>(buffer + pos));
    9781053
    979                     buildbuffersize = 4;
    980                     memcpy(buildbuffer, &state, 4);
     1054        // Next packet
     1055        idx = pos + TSPacket::SIZE;
     1056    }
    9811057
    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;
     1058    remainder = 0;
     1059    return;
     1060}
    9921061
    993                     if (buildbuffersize > 0)
    994                         ringBuffer->Write(buildbuffer, buildbuffersize);
     1062bool MpegRecorder::ProcessTSPacket(const TSPacket &tspacket)
     1063{
     1064    if (!_stream_data) {
     1065        VERBOSE(VB_RECORD, "ProcessTSPacket: !_stream_data");
     1066        return false;
     1067    }
    9951068
    996                     buildbuffersize = 0;
    997                 }
    998             }
     1069    if (tspacket.TransportError() || tspacket.ScramplingControl())
     1070        return false;
    9991071
    1000             if (state == SEQ_START)
    1001             {
    1002                 lastseqstart = lastpackheaderpos;
    1003             }
     1072    if (tspacket.HasAdaptationField())
     1073        _stream_data->HandleAdaptationFieldControl(&tspacket);
    10041074
    1005             if (state == GOP_START && lastseqstart == lastpackheaderpos)
    1006             {
    1007                 framesWritten = numgops * keyframedist;
    1008                 numgops++;
    1009                 HandleKeyframe();
    1010             }
     1075    if (tspacket.HasPayload())
     1076    {
     1077        const unsigned int lpid = tspacket.PID();
     1078
     1079        // Pass or reject packets based on PID, and parse info from them
     1080        if (lpid == _stream_data->VideoPIDSingleProgram())
     1081        {
     1082            _buffer_packets = !FindH264Keyframes(&tspacket);
     1083
     1084            if (!_seen_sps)
     1085                return true;
    10111086        }
    1012         else
    1013             state = ((state << 8) | v) & 0xFFFFFF;
    1014     }
     1087        else if (_stream_data->IsAudioPID(lpid))
     1088        {
     1089            _buffer_packets = !FindAudioKeyframes(&tspacket);
     1090        }
     1091        else if (GetStreamData()->IsListeningPID(lpid))
     1092            GetStreamData()->HandleTSTables(&tspacket);
     1093        else if (GetStreamData()->IsWritingPID(lpid))
     1094            BufferedWrite(tspacket);
    10151095
    1016     leftovers = state;
    1017 
    1018     if (buildbuffersize + leftlen > kBuildBufferMaxSize)
    1019     {
    1020         ringBuffer->Write(buildbuffer, buildbuffersize);
    1021         buildbuffersize = 0;
     1096        const uint pid = tspacket.PID();
     1097       
     1098        // Check continuity counter
     1099        if ((pid != 0x1fff) && !CheckCC(pid, tspacket.ContinuityCounter()))
     1100        {
     1101            VERBOSE(VB_RECORD, LOC +
     1102                    QString("PID 0x%1 discontinuity detected").arg(pid,0,16));
     1103            _continuity_error_count++;
     1104        }
     1105       
     1106        // Sync recording start to first keyframe
     1107        if (_wait_for_keyframe_option && _first_keyframe < 0)
     1108            return true;
     1109       
     1110        // Sync streams to the first Payload Unit Start Indicator
     1111        // _after_ first keyframe iff _wait_for_keyframe_option is true
     1112        if (!(_pid_status[pid] & kPayloadStartSeen) && tspacket.HasPayload())
     1113        {
     1114            if (!tspacket.PayloadStart())
     1115                return true; // not payload start - drop packet
     1116           
     1117            VERBOSE(VB_RECORD,
     1118                    QString("PID 0x%1 Found Payload Start").arg(pid,0,16));
     1119           
     1120            _pid_status[pid] |= kPayloadStartSeen;
     1121        }
     1122       
     1123        BufferedWrite(tspacket);
    10221124    }
    10231125
    1024     // copy remaining..
    1025     memcpy(buildbuffer + buildbuffersize, bufstart, leftlen);
    1026     buildbuffersize += leftlen;
     1126    return true;
    10271127}
    10281128
    10291129void MpegRecorder::StopRecording(void)
     
    10331133
    10341134void MpegRecorder::ResetForNewFile(void)
    10351135{
    1036     errored = false;
    1037     framesWritten = 0;
    1038     numgops = 0;
    1039     lastseqstart = lastpackheaderpos = 0;
     1136    DTVRecorder::ResetForNewFile();
    10401137
    1041     positionMap.clear();
    1042     positionMapDelta.clear();
     1138    bzero(_stream_id,  sizeof(_stream_id));
     1139    bzero(_pid_status, sizeof(_pid_status));
     1140    memset(_continuity_counter, 0xff, sizeof(_continuity_counter));
    10431141}
    10441142
    10451143void MpegRecorder::Reset(void)
    10461144{
     1145    VERBOSE(VB_RECORD, LOC + "Reset(void)");
    10471146    ResetForNewFile();
    10481147
    1049     leftovers = 0xFFFFFFFF;
    1050     buildbuffersize = 0;
     1148    _start_code = 0xffffffff;
    10511149
    1052     if (curRecording)
    1053         curRecording->ClearPositionMap(MARK_GOP_START);
     1150    if (curRecording) {
     1151        if (driver == "hdpvr") {
     1152            curRecording->ClearPositionMap(MARK_GOP_BYFRAME);
     1153        }
     1154        else {
     1155            curRecording->ClearPositionMap(MARK_GOP_START);
     1156        }
     1157    }
    10541158}
    10551159
    10561160void MpegRecorder::Pause(bool clear)
     
    10951199                command.cmd = V4L2_ENC_CMD_START;
    10961200                ioctl(readfd, VIDIOC_ENCODER_CMD, &command);
    10971201            }
     1202
     1203            if (_stream_data)
     1204                _stream_data->Reset(_stream_data->DesiredProgram());
    10981205        }
    10991206        paused = false;
    11001207    }
    11011208    return paused;
    11021209}
    11031210
    1104 long long MpegRecorder::GetKeyframePosition(long long desired)
     1211void MpegRecorder::SetStreamData(MPEGStreamData *data)
    11051212{
    1106     QMutexLocker locker(&positionMapLock);
    1107     long long ret = -1;
     1213    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin");
    11081214
    1109     if (positionMap.find(desired) != positionMap.end())
    1110         ret = positionMap[desired];
     1215    if (data == _stream_data)
     1216    {
     1217        VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0");
    11111218
    1112     return ret;
     1219        return;
     1220    }
     1221
     1222    MPEGStreamData *old_data = _stream_data;
     1223    _stream_data = data;
     1224    if (old_data)
     1225        delete old_data;
     1226
     1227    if (data)
     1228        data->AddMPEGSPListener(this);
     1229
     1230    data->SetDesiredProgram(1);
     1231
     1232    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1");
    11131233}
    11141234
    1115 // documented in recorderbase.h
    1116 void MpegRecorder::SetNextRecording(const ProgramInfo *progInf, RingBuffer *rb)
     1235void MpegRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat)
    11171236{
    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());
     1237    if (!pat)
     1238    {
     1239        VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPAT(NULL)");
     1240        return;
     1241    }
    11231242
    1124     // Then we set the next info
     1243    if (!ringBuffer)
     1244        return;
     1245
     1246    uint posA[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() };
     1247
     1248    uint next_cc = (pat->tsheader()->ContinuityCounter()+1)&0xf;
     1249    pat->tsheader()->SetContinuityCounter(next_cc);
     1250    DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(pat->tsheader())));
     1251
     1252    uint posB[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() };
     1253
     1254#if 0
     1255    if (posB[0] + posB[1] * TSPacket::SIZE >
     1256        posA[0] + posA[1] * TSPacket::SIZE)
    11251257    {
    1126         QMutexLocker locker(&nextRingBufferLock);
    1127         nextRecording = NULL;
    1128         if (progInf)
    1129             nextRecording = new ProgramInfo(*progInf);
    1130         nextRingBuffer = rb;
     1258        VERBOSE(VB_RECORD, LOC + "Wrote PAT @"
     1259                << posA[0] << " + " << (posA[1] * TSPacket::SIZE));
    11311260    }
     1261    else
     1262    {
     1263        VERBOSE(VB_RECORD, LOC + "Saw PAT but did not write to disk yet");
     1264    }
     1265#endif
    11321266}
    11331267
    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)
     1268void MpegRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt)
    11391269{
    1140     // Add key frame to position map
    1141     positionMapLock.lock();
    1142     if (!positionMap.contains(numgops))
     1270    if (!pmt) {
     1271        return;
     1272    }
     1273
     1274    // collect stream types for H.264 (MPEG-4 AVC) keyframe detection
     1275    for (uint i = 0; i < pmt->StreamCount(); i++)
     1276        _stream_id[pmt->StreamPID(i)] = pmt->StreamType(i);
     1277
     1278    if (!ringBuffer)
     1279        return;
     1280
     1281    unsigned char buf[8 * 1024];
     1282    uint next_cc = (pmt->tsheader()->ContinuityCounter()+1)&0xf;
     1283    pmt->tsheader()->SetContinuityCounter(next_cc);
     1284    uint size = pmt->WriteAsTSPackets(buf, next_cc);
     1285
     1286    uint posA[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() };
     1287
     1288    for (uint i = 0; i < size ; i += TSPacket::SIZE)
     1289        DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(&buf[i])));
     1290
     1291    uint posB[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() };
     1292
     1293#if 1
     1294    if (posB[0] + posB[1] * TSPacket::SIZE >
     1295        posA[0] + posA[1] * TSPacket::SIZE)
    11431296    {
    1144         positionMapDelta[numgops] = lastpackheaderpos;
    1145         positionMap[numgops]      = lastpackheaderpos;
     1297        VERBOSE(VB_RECORD, LOC + "Wrote PMT @"
     1298                << posA[0] << " + " << (posA[1] * TSPacket::SIZE));
    11461299    }
    1147     positionMapLock.unlock();
    1148 
    1149     // Perform ringbuffer switch if needed.
    1150     CheckForRingBufferSwitch();
     1300    else
     1301    {
     1302        VERBOSE(VB_RECORD, LOC + "Saw PMT but did not write to disk yet");
     1303    }
     1304#endif
    11511305}
    11521306