Ticket #5443: hdpvr-0.1-recorder.patch

File hdpvr-0.1-recorder.patch, 42.2 KB (added by jppoet@…, 17 years ago)

version 0.1

  • 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()
     
    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, int len);
     64    void ProcessTSdata(unsigned char * data, int len, uint & leftover);
     65    void ProcessTSPacket(const TSPacket &tspacket);
    6366
    6467    void ResetForNewFile(void);
    6568
     
    7881    // State
    7982    bool recording;
    8083    bool encoding;
    81     bool errored;
    8284
    8385    // Pausing state
    8486    bool cleartimeonpause;
    8587
    86     // Number of frames written
    87     long long framesWritten;
    88 
    8988    // Encoding info
    9089    int width, height;
    9190    int bitrate, maxbitrate, streamtype, aspectratio;
     
    9796    int chanfd;
    9897    int readfd;
    9998
    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 
    11299    static const int   audRateL1[];
    113100    static const int   audRateL2[];
    114101    static const int   audRateL3[];
    115102    static const char *streamType[];
    116103    static const char *aspectRatio[];
    117104    static const unsigned int kBuildBufferMaxSize;
     105
     106    // TS
     107    MPEGStreamData *_stream_data;
    118108};
    119109#endif
  • libs/libmythtv/cardutil.cpp

     
    14731473{
    14741474    bool ok;
    14751475    QStringList ret;
     1476
    14761477    int videofd = open(device.ascii(), O_RDWR);
    14771478    if (videofd < 0)
    14781479    {
     
    14801481                           "to probe its inputs.").arg(device);
    14811482        return ret;
    14821483    }
     1484
    14831485    InputNames list = CardUtil::probeV4LInputs(videofd, ok);
    14841486    close(videofd);
    14851487
  • libs/libmythtv/mpegrecorder.cpp

     
    4848const int MpegRecorder::audRateL1[] =
    4949{
    5050    32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0
    51 };
     51        };
    5252
    5353const int MpegRecorder::audRateL2[] =
    5454{
     
    7373    "Square", "4:3", "16:9", "2.21:1", 0
    7474};
    7575
    76 const unsigned int MpegRecorder::kBuildBufferMaxSize = 1024 * 1024;
    77 
    78 MpegRecorder::MpegRecorder(TVRec *rec) :
    79     RecorderBase(rec),
     76MpegRecorder::MpegRecorder(TVRec *rec) : DTVRecorder(rec),
    8077    // Debugging variables
    8178    deviceIsMpegFile(false),
    82     bufferSize(4096),
    8379    // Driver info
    8480    card(QString::null),      driver(QString::null),
    8581    version(0),               usingv4l2(false),
     
    8783    requires_special_pause(false),
    8884    // State
    8985    recording(false),         encoding(false),
    90     errored(false),
    9186    // Pausing state
    9287    cleartimeonpause(false),
    93     // Number of frames written
    94     framesWritten(0),
    9588    // Encoding info
    9689    width(720),               height(480),
    9790    bitrate(4500),            maxbitrate(6000),
     
    10295    audvolume(80),            language(0),
    10396    // Input file descriptors
    10497    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)
     98    // TS packet handling
     99    _stream_data(NULL)                                   
    112100{
    113101    SetPositionMapType(MARK_GOP_START);
    114102}
     
    116104MpegRecorder::~MpegRecorder()
    117105{
    118106    TeardownAll();
    119     delete [] buildbuffer;
    120107}
    121108
    122109void MpegRecorder::TeardownAll(void)
     
    332319
    333320    if (CardUtil::GetV4LInfo(chanfd, card, driver, version))
    334321    {
     322//      driver = "hdpvr";
     323
    335324        if (driver == "ivtv")
    336325        {
     326            bufferSize = 4096;
     327
    337328            usingv4l2     = (version >= IVTV_KERNEL_VERSION(0, 8, 0));
    338329            has_v4l2_vbi  = (version >= IVTV_KERNEL_VERSION(0, 3, 8));
    339330            has_buggy_vbi = true;
    340331            requires_special_pause =
    341332                (version >= IVTV_KERNEL_VERSION(0, 10, 0));
    342333        }
     334        else if (driver == "hdpvr")
     335        {
     336            bufferSize = 1500 * TSPacket::SIZE;
     337            usingv4l2 = true;
     338        }
    343339        else
    344340        {
    345             VERBOSE(VB_IMPORTANT, "\n\nNot ivtv driver??\n\n");
     341            VERBOSE(VB_IMPORTANT, "\n\nNot ivtv or hdpvr driver??\n\n");
    346342            usingv4l2 = has_v4l2_vbi = true;
    347343            has_buggy_vbi = requires_special_pause = false;
    348344        }
     
    354350
    355351    struct v4l2_format vfmt;
    356352    bzero(&vfmt, sizeof(vfmt));
    357 
     353   
    358354    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    359 
     355   
    360356    if (ioctl(chanfd, VIDIOC_G_FMT, &vfmt) < 0)
    361357    {
    362358        VERBOSE(VB_IMPORTANT, LOC_ERR + "Error getting format" + ENO);
    363359        return false;
    364360    }
     361       
     362    if (driver != "hdpvr") {
     363        vfmt.fmt.pix.width = width;
     364        vfmt.fmt.pix.height = height;
     365       
     366        if (ioctl(chanfd, VIDIOC_S_FMT, &vfmt) < 0)
     367        {
     368            VERBOSE(VB_IMPORTANT, LOC_ERR + "Error setting format" + ENO);
     369            return false;
     370        }
    365371
    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:
     372        // Set audio language mode
     373        bool do_audmode_set = true;
     374        struct v4l2_tuner vt;
     375        bzero(&vt, sizeof(struct v4l2_tuner));
     376        if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0)
     377        {
     378            VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get audio mode" + ENO);
     379            do_audmode_set = false;
     380        }
     381       
     382        switch (language)
     383        {
     384          case 0:
    388385            vt.audmode = V4L2_TUNER_MODE_LANG1;
    389386            break;
    390         case 1:
     387          case 1:
    391388            vt.audmode = V4L2_TUNER_MODE_LANG2;
    392389            break;
    393         case 2:
     390          case 2:
    394391            if (usingv4l2)
    395392                vt.audmode = V4L2_TUNER_MODE_LANG1_LANG2;
    396393            else
    397394                vt.audmode = V4L2_TUNER_MODE_STEREO;
    398395            break;
    399         default:
     396          default:
    400397            vt.audmode = V4L2_TUNER_MODE_LANG1;
    401     }
     398        }
    402399
    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     }
     400        int audio_layer = GetFilteredAudioLayer();
     401        if (do_audmode_set && (2 == language) && (1 == audio_layer))
     402        {
     403            VERBOSE(VB_GENERAL, "Dual audio mode incompatible with Layer I audio."
     404                    "\n\t\t\tFalling back to Main Language");
     405            vt.audmode = V4L2_TUNER_MODE_LANG1;
     406        }
    410407
    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     }
     408        if (do_audmode_set && ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0)
     409        {
     410            VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set audio mode" + ENO);
     411        }
    415412
    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     }
     413        // Get volume min/max values
     414        struct v4l2_queryctrl qctrl;
     415        qctrl.id = V4L2_CID_AUDIO_VOLUME;
     416        if (ioctl(chanfd, VIDIOC_QUERYCTRL, &qctrl) < 0)
     417        {
     418            VERBOSE(VB_IMPORTANT, LOC_WARN +
     419                    "Unable to get recording volume parameters(max/min)" + ENO +
     420                    "\n\t\t\tusing default range [0,65535].");
     421            qctrl.maximum = 65535;
     422            qctrl.minimum = 0;
     423        }
    427424
    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));
     425        // calculate volume in card units.
     426        int range = qctrl.maximum - qctrl.minimum;
     427        int value = (int) ((range * audvolume * 0.01f) + qctrl.minimum);
     428        int ctrl_volume = min(qctrl.maximum, max(qctrl.minimum, value));
    432429
    433     // Set recording volume
    434     struct v4l2_control ctrl;
    435     ctrl.id = V4L2_CID_AUDIO_VOLUME;
    436     ctrl.value = ctrl_volume;
     430        // Set recording volume
     431        struct v4l2_control ctrl;
     432        ctrl.id = V4L2_CID_AUDIO_VOLUME;
     433        ctrl.value = ctrl_volume;
    437434
    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.");
     435        if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0)
     436        {
     437            VERBOSE(VB_IMPORTANT, LOC_WARN +
     438                    "Unable to set recording volume" + ENO + "\n\t\t\t" +
     439                    "If you are using an AverMedia M179 card this is normal.");
     440        }
    443441    }
    444442
    445443    bool ok = true;
     
    457455
    458456    SetVBIOptions(chanfd);
    459457
    460     readfd = open(videodevice.ascii(), O_RDWR | O_NONBLOCK);
     458    // hdpvr driver does not like NONBLOCK mode with select
     459    if (driver == "hdpvr")
     460        readfd = open(videodevice.ascii(), O_RDWR);
     461    else
     462        readfd = open(videodevice.ascii(), O_RDWR | O_NONBLOCK);
     463
    461464    if (readfd < 0)
    462465    {
    463466        VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't open video device." + ENO);
     
    475478    {
    476479        switch (st)
    477480        {
    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;   
     481          case 2:  st = 2;  break;
     482          case 10:
     483          case 13:
     484          case 14: st = 10; break;
     485          case 11: st = 11; break;
     486          case 12: st = 12; break;
     487          default: st = 0;  break;   
    485488        }
    486489    }
     490    else if (driver == "hdpvr")
     491    {
     492        // FIX ME!  // I have no idea what to put here
     493        switch (st)
     494        {
     495          case 2:  st = 2;  break;
     496          case 10:
     497          case 13:
     498          case 14: st = 10; break;
     499          case 11: st = 11; break;
     500          case 12: st = 12; break;
     501          default: st = 0;  break;   
     502        }
     503    }
    487504
    488505    if (st != (uint) streamtype)
    489506    {
     
    502519
    503520    sr = (driver == "ivtv") ? 48000 : sr; // only 48kHz works properly.
    504521
     522    // hdpvr ?
     523
     524
    505525    if (sr != (uint) audsamplerate)
    506526    {
    507527        VERBOSE(VB_IMPORTANT, LOC_WARN +
     
    512532
    513533    switch (sr)
    514534    {
    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;
     535      case 32000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000;
     536      case 44100: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100;
     537      case 48000: return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
     538      default:    return V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
    519539    }
    520540}
    521541
     
    527547
    528548    layer = (driver == "ivtv") ? 2 : layer;
    529549
     550    // hdpvr?
     551
     552
    530553    if (layer != (uint) audtype)
    531554    {
    532555        VERBOSE(VB_IMPORTANT, LOC_WARN +
     
    587610{
    588611    switch (st)
    589612    {
    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;
     613      case 0:  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
     614      case 1:  return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
     615      case 2:  return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD;
     616      case 3:  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;  /* PES A/V    */
     617      case 5:  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;  /* PES V      */
     618      case 7:  return V4L2_MPEG_STREAM_TYPE_MPEG2_PS;  /* PES A      */
     619      case 10: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
     620      case 11: return V4L2_MPEG_STREAM_TYPE_MPEG1_VCD; /* VCD */
     621      case 12: return V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD;
     622      case 13: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; /* DVD-Special 1 */
     623      case 14: return V4L2_MPEG_STREAM_TYPE_MPEG2_DVD; /* DVD-Special 2 */
     624      default: return V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
    602625    }
    603626}
    604627
    605628bool MpegRecorder::SetV4L2DeviceOptions(int chanfd)
    606629{
    607     static const uint kNumControls = 7;
     630   static const uint kNumControls = 7;
    608631    struct v4l2_ext_controls ctrls;
    609632    struct v4l2_ext_control ext_ctrl[kNumControls];
    610633    QString control_description[kNumControls] =
     
    625648    uint audio_layer = GetFilteredAudioLayer();
    626649    uint audbitrate  = GetFilteredAudioBitRate(audio_layer);
    627650
    628     ext_ctrl[0].id    = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ;
    629     ext_ctrl[0].value = GetFilteredAudioSampleRate();
     651    if (driver != "hdpvr") {
     652        ext_ctrl[0].id    = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ;
     653        ext_ctrl[0].value = GetFilteredAudioSampleRate();
     654       
     655        ext_ctrl[1].id    = V4L2_CID_MPEG_VIDEO_ASPECT;
     656        ext_ctrl[1].value = aspectratio - 1;
     657       
     658        ext_ctrl[2].id    = V4L2_CID_MPEG_AUDIO_ENCODING;
     659        ext_ctrl[2].value = audio_layer - 1;
     660       
     661        ext_ctrl[3].id    = V4L2_CID_MPEG_AUDIO_L2_BITRATE;
     662        ext_ctrl[3].value = audbitrate - 1;
    630663
    631     ext_ctrl[1].id    = V4L2_CID_MPEG_VIDEO_ASPECT;
    632     ext_ctrl[1].value = aspectratio - 1;
     664        ext_ctrl[4].id    = V4L2_CID_MPEG_STREAM_TYPE;
     665        ext_ctrl[4].value = streamtype_ivtv_to_v4l2(GetFilteredStreamType());
     666    }
    633667
    634     ext_ctrl[2].id    = V4L2_CID_MPEG_AUDIO_ENCODING;
    635     ext_ctrl[2].value = audio_layer - 1;
     668    ext_ctrl[5].id    = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK;
     669    ext_ctrl[5].value = maxbitrate * 1000;
    636670
    637     ext_ctrl[3].id    = V4L2_CID_MPEG_AUDIO_L2_BITRATE;
    638     ext_ctrl[3].value = audbitrate - 1;
     671    ext_ctrl[6].id    = V4L2_CID_MPEG_VIDEO_BITRATE;
     672    ext_ctrl[6].value = (bitrate = min(bitrate, maxbitrate)) * 1000;
    639673
    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 
    649674    for (uint i = 0; i < kNumControls; i++)
    650675    {
    651676        int value = ext_ctrl[i].value;
    652677
     678        if (value != 0) {
     679            ctrls.ctrl_class  = V4L2_CTRL_CLASS_MPEG;
     680            ctrls.count       = 1;
     681            ctrls.controls    = ext_ctrl + i;
     682           
     683            if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
     684            {
     685                VERBOSE(VB_IMPORTANT, LOC_ERR +
     686                        QString("Could not set %1 to %2")
     687                        .arg(control_description[i]).arg(value) + ENO);
     688            }
     689        }
     690    }
     691
     692    if (driver != "hdpvr") {
     693        // Get controls
     694        ext_ctrl[0].id    = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
     695        ext_ctrl[0].value = 0;
     696       
    653697        ctrls.ctrl_class  = V4L2_CTRL_CLASS_MPEG;
    654698        ctrls.count       = 1;
    655         ctrls.controls    = ext_ctrl + i;
    656 
    657         if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
     699        ctrls.controls    = ext_ctrl;
     700       
     701        if (ioctl(chanfd, VIDIOC_G_EXT_CTRLS, &ctrls) < 0)
    658702        {
    659             VERBOSE(VB_IMPORTANT, LOC_ERR +
    660                     QString("Could not set %1 to %2")
    661                     .arg(control_description[i]).arg(value) + ENO);
     703            VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get "
     704                    "V4L2_CID_MPEG_VIDEO_GOP_SIZE, defaulting to 12" + ENO);
     705            ext_ctrl[0].value = 12;
    662706        }
     707       
     708        keyframedist = ext_ctrl[0].value;
    663709    }
    664710
    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 
    682711    return true;
    683712}
    684713
     
    687716    if (!vbimode)
    688717        return true;
    689718
     719    if (driver == "hdpvr")
     720        return true;
     721
    690722    if (has_buggy_vbi)
    691723    {
    692724        cout<<" *********************** WARNING ***********************"<<endl;
     
    717749
    718750        if (ioctl(chanfd, IVTV_IOC_G_VBI_MODE, &vbifmt) >= 0)
    719751        {
    720             VERBOSE(VB_RECORD, LOC + QString(
    721                         "VBI service:%1, packet size:%2, io size:%3")
     752            VERBOSE(VB_RECORD,
     753                    LOC + QString("VBI service:%1, packet size:%2, io size:%3")
    722754                    .arg(vbifmt.service_set).arg(vbifmt.packet_size)
    723755                    .arg(vbifmt.io_size));
    724756        }
     
    733765        bzero(&vbifmt, sizeof(struct v4l2_format));
    734766        vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
    735767        vbifmt.fmt.sliced.service_set |= (1 == vbimode) ?
    736             V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
     768               V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
    737769
    738770        if (ioctl(chanfd, VIDIOC_S_FMT, &vbifmt) < 0)
    739771        {
     
    809841{
    810842    if (!Open())
    811843    {
    812         errored = true;
    813         return;
     844        _error = true;
     845        return;
    814846    }
    815847
    816     if (!SetupRecording())
    817     {
    818         VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup recording.");
    819         errored = true;
    820         return;
     848    _start_code = 0xffffffff;
     849    _last_gop_seen = 0;
     850    _frames_written_count = 0;
     851
     852    if (driver == "hdpvr") {
     853        SetPositionMapType(MARK_GOP_BYFRAME);
     854
     855        if (_stream_data == NULL) {
     856            int progNum = 1;
     857            MPEGStreamData *sd = new MPEGStreamData(progNum, true);
     858            sd->SetCaching(true);
     859            SetStreamData(sd);
     860        }
    821861    }
     862    else {
     863        SetPositionMapType(MARK_GOP_START);
     864    }
    822865
    823866    encoding = true;
    824867    recording = true;
    825     unsigned char *buffer = new unsigned char[bufferSize + 1];
     868
     869    // Add an extra TSPacket::SIZE for "leftover_bytes"
     870    unsigned char *buffer = new unsigned char[bufferSize + TSPacket::SIZE + 1];
     871    unsigned char *bufstart = &buffer[TSPacket::SIZE];
     872    uint leftover_bytes = 0;
     873
    826874    int ret;
    827875
    828876    MythTimer elapsedTimer;
     
    839887        if (PauseAndWait(100))
    840888            continue;
    841889
    842         if ((deviceIsMpegFile) && (framesWritten))
     890        if ((deviceIsMpegFile) && (GetFramesWritten()))
    843891        {
    844892            elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
    845             while ((framesWritten / elapsed) > 30)
     893            while ((GetFramesWritten() / elapsed) > 30)
    846894            {
    847895                usleep(50000);
    848896                elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
     
    852900        if (readfd < 0)
    853901            readfd = open(videodevice.ascii(), O_RDWR);
    854902
    855         tv.tv_sec = 5;
    856         tv.tv_usec = 0;
    857         FD_ZERO(&rdset);
    858         FD_SET(readfd, &rdset);
    859 
    860903#if defined(__FreeBSD__)
    861904        // HACK. FreeBSD PVR150/500 driver doesn't currently support select()
    862905#else
    863         switch (select(readfd + 1, &rdset, NULL, NULL, &tv))
    864         {
    865             case -1:
     906        // hdpvr driver does not like NONBLOCK mode with select
     907        if (driver != "hdpvr") {
     908            tv.tv_sec = 5;
     909            tv.tv_usec = 0;
     910            FD_ZERO(&rdset);
     911            FD_SET(readfd, &rdset);
     912
     913            switch (select(readfd + 1, &rdset, NULL, NULL, &tv))
     914            {
     915              case -1:
    866916                if (errno == EINTR)
    867917                    continue;
    868 
     918               
    869919                VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO);
    870920                continue;
    871 
    872             case 0:
     921               
     922              case 0:
    873923                VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - "
    874924                        "ivtv driver has stopped responding");
    875 
     925               
    876926                if (close(readfd) != 0)
    877927                {
    878928                    VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO);
    879929                }
    880 
     930               
    881931                readfd = -1; // Force PVR card to be reopened on next iteration
    882932                continue;
    883 
    884            default: break;
     933               
     934              default: break;
     935            }
    885936        }
    886937#endif
    887938
    888         ret = read(readfd, buffer, bufferSize);
     939        ret = read(readfd, bufstart, bufferSize);
    889940
    890         if ((ret == 0) &&
    891             (deviceIsMpegFile))
     941        if ((ret == 0) && (deviceIsMpegFile))
    892942        {
    893943            close(readfd);
    894944            readfd = open(videodevice.ascii(), O_RDONLY);
    895945
    896946            if (readfd >= 0)
    897                 ret = read(readfd, buffer, bufferSize);
     947                ret = read(readfd, bufstart, bufferSize);
    898948            if (ret <= 0)
    899949            {
    900950                encoding = false;
     
    905955        {
    906956            VERBOSE(VB_IMPORTANT, LOC_ERR + QString("error reading from: %1")
    907957                    .arg(videodevice) + ENO);
    908 
    909958            continue;
    910959        }
    911960        else if (ret > 0)
    912961        {
    913             ProcessData(buffer, ret);
     962            if (driver == "hdpvr")
     963                ProcessTSdata(buffer, ret, leftover_bytes);
     964            else
     965                ProcessPSdata(bufstart, ret);
    914966        }
    915967    }
    916968
     
    920972    recording = false;
    921973}
    922974
    923 bool MpegRecorder::SetupRecording(void)
     975void MpegRecorder::ProcessPSdata(unsigned char *buffer, int len)
    924976{
    925     leftovers = 0xFFFFFFFF;
    926     numgops = 0;
    927     lastseqstart = 0;
    928     return true;
     977    FindPSKeyFrames(buffer, len);
    929978}
    930979
    931 void MpegRecorder::FinishRecording(void)
     980void MpegRecorder::ProcessTSdata(unsigned char * data, int len, uint & leftover)
    932981{
    933     ringBuffer->WriterFlush();
     982    uint idx, pos;
     983    uint last = TSPacket::SIZE + leftover + len;
    934984
    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 }
     985    for (idx = TSPacket::SIZE - leftover; idx < last; ) {
     986        // Find header
     987        for (pos = idx; pos < last; ++pos) {
     988            if (data[pos] == SYNC_BYTE )
     989                break;
     990        }
    945991
    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
     992        if (pos == last) {
     993            VERBOSE(VB_IMPORTANT, LOC_ERR + "No TS header.");
     994            break;
     995        }
    951996
    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;
     997        if (pos > idx) {
     998            VERBOSE(VB_IMPORTANT, LOC_ERR +
     999                    QString("TS packet at %1 not in sync.").arg(pos));
     1000        }
    9571001
    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;
     1002        if ((last - pos) < TSPacket::SIZE) {
     1003            VERBOSE(VB_RECORD, LOC_ERR +
     1004                    QString("TS packet at %1 stradles end of buffer.")
     1005                    .arg(pos));
     1006            leftover = last - pos;
     1007            memmove(&data[TSPacket::SIZE - leftover], &data[pos], leftover);
     1008            return;
     1009        }
    9701010
    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);
     1011        ProcessTSPacket(* reinterpret_cast<const TSPacket *>(data + pos));
    9781012
    979                     buildbuffersize = 4;
    980                     memcpy(buildbuffer, &state, 4);
     1013        // Next packet
     1014        idx = pos + TSPacket::SIZE;
     1015    }
    9811016
    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;
     1017    leftover = 0;
     1018    return;
     1019}
    9921020
    993                     if (buildbuffersize > 0)
    994                         ringBuffer->Write(buildbuffer, buildbuffersize);
     1021void MpegRecorder::ProcessTSPacket(const TSPacket &tspacket)
     1022{
     1023    if (!_stream_data)
     1024        return;
    9951025
    996                     buildbuffersize = 0;
    997                 }
    998             }
     1026    if (tspacket.TransportError() || tspacket.ScramplingControl())
     1027        return;
    9991028
    1000             if (state == SEQ_START)
    1001             {
    1002                 lastseqstart = lastpackheaderpos;
    1003             }
     1029    if (tspacket.HasAdaptationField())
     1030        _stream_data->HandleAdaptationFieldControl(&tspacket);
    10041031
    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     }
     1032    if (tspacket.HasPayload())
     1033    {
     1034        const unsigned int lpid = tspacket.PID();
    10151035
    1016     leftovers = state;
     1036        // Pass or reject packets based on PID, and parse info from them
     1037//        if (lpid == _stream_data->VideoPIDSingleProgram())
     1038        if (lpid == 4113)
     1039        {
     1040            _buffer_packets = !FindH264Keyframes(&tspacket);
    10171041
    1018     if (buildbuffersize + leftlen > kBuildBufferMaxSize)
    1019     {
    1020         ringBuffer->Write(buildbuffer, buildbuffersize);
    1021         buildbuffersize = 0;
     1042            if (_seen_sps)
     1043                BufferedWrite(tspacket);           
     1044        }
     1045//        else if (_stream_data->IsAudioPID(lpid))
     1046        else if (lpid == 4352)
     1047        {
     1048            _buffer_packets = !FindAudioKeyframes(&tspacket);
     1049            BufferedWrite(tspacket);
     1050        }
     1051        else {
     1052            BufferedWrite(tspacket);
     1053        }
    10221054    }
    1023 
    1024     // copy remaining..
    1025     memcpy(buildbuffer + buildbuffersize, bufstart, leftlen);
    1026     buildbuffersize += leftlen;
    10271055}
    10281056
    10291057void MpegRecorder::StopRecording(void)
     
    10331061
    10341062void MpegRecorder::ResetForNewFile(void)
    10351063{
    1036     errored = false;
    1037     framesWritten = 0;
    1038     numgops = 0;
    1039     lastseqstart = lastpackheaderpos = 0;
     1064    DTVRecorder::ResetForNewFile();
    10401065
    1041     positionMap.clear();
    1042     positionMapDelta.clear();
    10431066}
    10441067
    10451068void MpegRecorder::Reset(void)
    10461069{
     1070    VERBOSE(VB_RECORD, LOC + "Reset(void)");
    10471071    ResetForNewFile();
    10481072
    1049     leftovers = 0xFFFFFFFF;
    1050     buildbuffersize = 0;
     1073    _start_code = 0xffffffff;
    10511074
    1052     if (curRecording)
    1053         curRecording->ClearPositionMap(MARK_GOP_START);
     1075    if (curRecording) {
     1076        if (driver == "hdpvr") {
     1077            curRecording->ClearPositionMap(MARK_GOP_BYFRAME);
     1078        }
     1079        else {
     1080            curRecording->ClearPositionMap(MARK_GOP_START);
     1081        }
     1082    }
    10541083}
    10551084
    10561085void MpegRecorder::Pause(bool clear)
     
    10951124                command.cmd = V4L2_ENC_CMD_START;
    10961125                ioctl(readfd, VIDIOC_ENCODER_CMD, &command);
    10971126            }
     1127
     1128            if (_stream_data)
     1129                _stream_data->Reset(_stream_data->DesiredProgram());
    10981130        }
    10991131        paused = false;
    11001132    }
    11011133    return paused;
    11021134}
    11031135
    1104 long long MpegRecorder::GetKeyframePosition(long long desired)
     1136void MpegRecorder::SetStreamData(MPEGStreamData *data)
    11051137{
    1106     QMutexLocker locker(&positionMapLock);
    1107     long long ret = -1;
     1138    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin");
    11081139
    1109     if (positionMap.find(desired) != positionMap.end())
    1110         ret = positionMap[desired];
     1140    if (data == _stream_data)
     1141    {
     1142        VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0");
    11111143
    1112     return ret;
     1144        return;
     1145    }
     1146
     1147    MPEGStreamData *old_data = _stream_data;
     1148    _stream_data = data;
     1149    if (old_data)
     1150        delete old_data;
     1151
     1152    if (data)
     1153        data->AddMPEGSPListener(this);
     1154
     1155    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1");
    11131156}
    11141157
    1115 // documented in recorderbase.h
    1116 void MpegRecorder::SetNextRecording(const ProgramInfo *progInf, RingBuffer *rb)
     1158void MpegRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat)
    11171159{
    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());
     1160    if (!pat)
     1161        return;
    11231162
    1124     // Then we set the next info
    1125     {
    1126         QMutexLocker locker(&nextRingBufferLock);
    1127         nextRecording = NULL;
    1128         if (progInf)
    1129             nextRecording = new ProgramInfo(*progInf);
    1130         nextRingBuffer = rb;
    1131     }
     1163    int next = (pat->tsheader()->ContinuityCounter()+1)&0xf;
     1164    pat->tsheader()->SetContinuityCounter(next);
     1165    BufferedWrite(*(reinterpret_cast<const TSPacket*>(pat->tsheader())));
    11321166}
    11331167
    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)
     1168void MpegRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt)
    11391169{
    1140     // Add key frame to position map
    1141     positionMapLock.lock();
    1142     if (!positionMap.contains(numgops))
    1143     {
    1144         positionMapDelta[numgops] = lastpackheaderpos;
    1145         positionMap[numgops]      = lastpackheaderpos;
    1146     }
    1147     positionMapLock.unlock();
     1170    if (!pmt)
     1171        return;
    11481172
    1149     // Perform ringbuffer switch if needed.
    1150     CheckForRingBufferSwitch();
     1173    int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf;
     1174    pmt->tsheader()->SetContinuityCounter(next);
     1175    BufferedWrite(*(reinterpret_cast<const TSPacket*>(pmt->tsheader())));
    11511176}
    1152