Ticket #5443: hdpvr-0.14-recorder.patch

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

Verison 0.14 (minor cleanups)

  • libs/libmythtv/dvbrecorder.cpp

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

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

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

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

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