Ticket #4466: 4466-hack-v3.patch

File 4466-hack-v3.patch, 12.7 KB (added by danielk, 12 years ago)

Another hack attempt, based on e-mail from Martin Dauskard. This hasn't been tested with 2.6.24 yet..

  • libs/libmythtv/channel.h

     
    1515typedef QMap<int,int>         VidModV4L1;
    1616typedef QMap<int,v4l2_std_id> VidModV4L2;
    1717
     18extern QMutex            mpeg_recorder_ivtv_hack_lock;
     19extern QMap<QString,int> mpeg_recorder_ivtv_hack_chanfd;
     20extern QMap<QString,int> mpeg_recorder_ivtv_hack_readfd;
     21
    1822/** \class Channel
    1923 *  \brief Implements tuning for TV cards using the V4L driver API,
    2024 *         both versions 1 and 2.
  • libs/libmythtv/mpegrecorder.h

     
    88struct AVFormatContext;
    99struct AVPacket;
    1010
     11extern QMutex            mpeg_recorder_ivtv_hack_lock;
     12extern QMap<QString,int> mpeg_recorder_ivtv_hack_chanfd;
     13extern QMap<QString,int> mpeg_recorder_ivtv_hack_readfd;
     14
    1115class MpegRecorder : public RecorderBase
    1216{
    1317  public:
  • libs/libmythtv/mpegrecorder.cpp

     
    7878
    7979const unsigned int MpegRecorder::kBuildBufferMaxSize = 1024 * 1024;
    8080
     81QMutex            mpeg_recorder_ivtv_hack_lock;
     82QMap<QString,int> mpeg_recorder_ivtv_hack_chanfd;
     83QMap<QString,int> mpeg_recorder_ivtv_hack_readfd;
     84
    8185MpegRecorder::MpegRecorder(TVRec *rec) :
    8286    RecorderBase(rec),
    8387    // Debugging variables
     
    123127
    124128void MpegRecorder::TeardownAll(void)
    125129{
     130    QMutexLocker locker(&mpeg_recorder_ivtv_hack_lock);
     131    QString tmp = QDeepCopy<QString>(videodevice);
     132
    126133    if (chanfd >= 0)
    127134    {
    128135        close(chanfd);
    129136        chanfd = -1;
     137        mpeg_recorder_ivtv_hack_chanfd[tmp.ascii()] = -1;
    130138    }
     139
    131140    if (readfd >= 0)
    132141    {
    133142        close(readfd);
    134143        readfd = -1;
     144        mpeg_recorder_ivtv_hack_readfd[tmp.ascii()] = -1;
    135145    }
    136146}
    137147
     
    324334
    325335bool MpegRecorder::OpenV4L2DeviceAsInput(void)
    326336{
    327     chanfd = open(videodevice.ascii(), O_RDWR);
     337    {
     338        QMutexLocker locker(&mpeg_recorder_ivtv_hack_lock);
     339        chanfd = open(videodevice.ascii(), O_RDWR);
     340        QString tmp = QDeepCopy<QString>(videodevice);
     341        mpeg_recorder_ivtv_hack_chanfd[tmp.ascii()] = chanfd;
     342    }
     343
    328344    if (chanfd < 0)
    329345    {
    330346        VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't open video device. " + ENO);
     
    456472
    457473    SetVBIOptions(chanfd);
    458474
    459     readfd = open(videodevice.ascii(), O_RDWR | O_NONBLOCK);
     475    {
     476        QMutexLocker locker(&mpeg_recorder_ivtv_hack_lock);
     477        readfd = open(videodevice.ascii(), O_RDWR | O_NONBLOCK);
     478        QString tmp = QDeepCopy<QString>(videodevice);
     479        mpeg_recorder_ivtv_hack_readfd[tmp.ascii()] = readfd;
     480    }
     481
    460482    if (readfd < 0)
    461483    {
    462484        VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't open video device." + ENO);
     485        {
     486            QMutexLocker locker(&mpeg_recorder_ivtv_hack_lock);
     487            close(chanfd);
     488            chanfd = -1;
     489            QString tmp = QDeepCopy<QString>(videodevice);
     490            mpeg_recorder_ivtv_hack_chanfd[tmp.ascii()] = -1;
     491        }
    463492        return false;
    464493    }
    465494
  • libs/libmythtv/channel.cpp

     
    746746    return fmt;
    747747}
    748748
    749 bool Channel::SetInputAndFormat(int inputNum, QString newFmt)
     749static bool convertx_hack(
     750    const QString &loc_err_msg,
     751    int videofd, int inputNumV4L, int &ioctlval, bool &undo_convertx_hack)
    750752{
    751     InputMap::const_iterator it = inputs.find(inputNum);
    752     if (it == inputs.end() || (*it)->inputNumV4L < 0)
    753         return false;
     753    bool ok = true;
     754    undo_convertx_hack = false;
    754755
    755     int inputNumV4L = (*it)->inputNumV4L;
    756     bool usingv4l1 = !usingv4l2;
     756    // ConvertX (wis-go7007) requires streaming to be disabled
     757    // before an input switch, do this if initial switch failed.
     758    int  streamType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     759
     760    ioctlval = ioctl(videofd, VIDIOC_STREAMOFF, &streamType);
     761    if (ioctlval < 0)
     762    {
     763        VERBOSE(VB_IMPORTANT, loc_err_msg +
     764                "\n\t\t\twhile disabling streaming (v4l v2)" + ENO);
     765
     766        ok = false;
     767        ioctlval = 0;
     768    }
     769    else
     770    {
     771        undo_convertx_hack = true;
     772
     773        // Resend the input switch ioctl.
     774        ioctlval = ioctl(videofd, VIDIOC_S_INPUT, &inputNumV4L);
     775    }
     776
     777    return ok;
     778}
     779
     780static bool convertx_unhack(const QString &loc_err_msg, int videofd)
     781{
    757782    bool ok = true;
    758783
    759     QString msg =
    760         QString("SetInputAndFormat(%1, %2) ").arg(inputNum).arg(newFmt);
     784    // ConvertX (wis-go7007) requires streaming to be disabled
     785    // before an input switch, here we try to re-enable streaming.
     786    int  streamType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    761787
    762     if (usingv4l2)
     788    int ioctlval = ioctl(videofd, VIDIOC_STREAMON, &streamType);
     789    if (ioctlval < 0)
    763790    {
    764         VERBOSE(VB_CHANNEL, LOC + msg + "(v4l v2)");
     791        VERBOSE(VB_IMPORTANT, loc_err_msg +
     792                "\n\t\t\twhile reenabling ivtv streaming (v4l v2)" + ENO);
    765793
    766         int ioctlval = ioctl(videofd, VIDIOC_S_INPUT, &inputNumV4L);
     794        ok = false;
     795    }
    767796
    768         // ConvertX (wis-go7007) requires streaming to be disabled
    769         // before an input switch, do this if initial switch failed.
    770         bool streamingDisabled = false;
    771         int  streamType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    772         if ((ioctlval < 0) && (errno == EBUSY))
     797    return ok;
     798}
     799
     800static bool ivtv_hack(
     801    const QString &loc_err_msg,
     802    int videofd, int chanfd, int readfd,
     803    int inputNumV4L, int &ioctlval, bool &undo_ivtv_hack)
     804{
     805    bool ok = true;
     806    undo_ivtv_hack = false;
     807
     808    // The ivtv 0.10.6+ drivers require streaming to be disabled
     809    // on all open file descriptors before an input switch, do
     810    // this if initial switch failed.
     811    struct v4l2_encoder_cmd command;
     812    memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
     813    command.cmd   = V4L2_ENC_CMD_STOP;
     814    command.flags = V4L2_ENC_CMD_STOP_AT_GOP_END;
     815
     816    VERBOSE(VB_CHANNEL, "disabling streaming on videofd");
     817    ioctlval = ioctl(videofd, VIDIOC_ENCODER_CMD, &command);
     818    if (ioctlval < 0)
     819    {
     820        VERBOSE(VB_IMPORTANT, loc_err_msg +
     821                "\n\t\t\twhile disabling ivtv streaming 1 (v4l v2)" + ENO);
     822
     823        ok = false;
     824        ioctlval = 0;
     825    }
     826    else
     827    {
     828        memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
     829        command.cmd   = V4L2_ENC_CMD_STOP;
     830        command.flags = V4L2_ENC_CMD_STOP_AT_GOP_END;
     831
     832        VERBOSE(VB_CHANNEL, "disabling streaming on chanfd");
     833        ioctlval = ioctl(chanfd, VIDIOC_ENCODER_CMD, &command);
     834        if (ioctlval < 0)
    773835        {
    774             ioctlval = ioctl(videofd, VIDIOC_STREAMOFF, &streamType);
     836            VERBOSE(VB_IMPORTANT, loc_err_msg +
     837                    "\n\t\t\twhile disabling ivtv streaming 2 (v4l v2)" + ENO);
     838
     839            memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
     840            command.cmd = V4L2_ENC_CMD_START;
     841            ioctlval = ioctl(videofd, VIDIOC_ENCODER_CMD, &command);
     842
     843            ok = false;
     844            ioctlval = 0;
     845        }
     846        else
     847        {
     848            memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
     849            command.cmd   = V4L2_ENC_CMD_STOP;
     850            command.flags = V4L2_ENC_CMD_STOP_AT_GOP_END;
     851
     852            VERBOSE(VB_CHANNEL, "disabling streaming on readfd");
     853            ioctlval = ioctl(readfd, VIDIOC_ENCODER_CMD, &command);
    775854            if (ioctlval < 0)
    776855            {
    777                 VERBOSE(VB_IMPORTANT, LOC_ERR + msg +
    778                         "\n\t\t\twhile disabling streaming (v4l v2)" + ENO);
     856                VERBOSE(VB_IMPORTANT, loc_err_msg +
     857                        "\n\t\t\twhile disabling ivtv streaming 3 "
     858                        "(v4l v2)" + ENO);
    779859
     860                memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
     861                command.cmd = V4L2_ENC_CMD_START;
     862                ioctlval = ioctl(chanfd, VIDIOC_ENCODER_CMD, &command);
     863
     864                memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
     865                command.cmd = V4L2_ENC_CMD_START;
     866                ioctlval = ioctl(videofd, VIDIOC_ENCODER_CMD, &command);
     867
    780868                ok = false;
    781869                ioctlval = 0;
    782870            }
    783871            else
    784872            {
    785                 streamingDisabled = true;
     873                undo_ivtv_hack = true;
    786874
    787875                // Resend the input switch ioctl.
     876                VERBOSE(VB_CHANNEL, "resending input changing command");
    788877                ioctlval = ioctl(videofd, VIDIOC_S_INPUT, &inputNumV4L);
    789878            }
    790879        }
     880    }
    791881
     882    return ok;
     883}
     884
     885static bool ivtv_unhack(const QString &loc_err_msg,
     886                        int videofd, int chanfd, int readfd)
     887{
     888    bool ok = true;
     889
     890    // The ivtv 0.10.6+ drivers require streaming to be disabled
     891    // before an input switch, here we try to re-enable streaming.
     892    struct v4l2_encoder_cmd command;
     893    memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
     894    command.cmd = V4L2_ENC_CMD_START;
     895
     896    VERBOSE(VB_CHANNEL, "enabling streaming on readfd");
     897    int ioctlval = ioctl(readfd, VIDIOC_ENCODER_CMD, &command);
     898    if (ioctlval < 0)
     899    {
     900        VERBOSE(VB_IMPORTANT, loc_err_msg +
     901                "\n\t\t\twhile reenabling ivtv streaming 1 (v4l v2)" + ENO);
     902
     903        ok = false;
     904    }
     905
     906    VERBOSE(VB_CHANNEL, "enabling streaming on chanfd");
     907    ioctlval = ioctl(chanfd, VIDIOC_ENCODER_CMD, &command);
     908    if (ioctlval < 0)
     909    {
     910        VERBOSE(VB_IMPORTANT, loc_err_msg +
     911                "\n\t\t\twhile reenabling ivtv streaming 2 (v4l v2)" + ENO);
     912
     913        ok = false;
     914    }
     915
     916    VERBOSE(VB_CHANNEL, "enabling streaming on videofd");
     917    ioctlval = ioctl(videofd, VIDIOC_ENCODER_CMD, &command);
     918    if (ioctlval < 0)
     919    {
     920        VERBOSE(VB_IMPORTANT, loc_err_msg +
     921                "\n\t\t\twhile reenabling ivtv streaming 3 (v4l v2)" + ENO);
     922
     923        ok = false;
     924    }
     925
     926    return ok;
     927}
     928
     929bool Channel::SetInputAndFormat(int inputNum, QString newFmt)
     930{
     931    InputMap::const_iterator it = inputs.find(inputNum);
     932    if (it == inputs.end() || (*it)->inputNumV4L < 0)
     933        return false;
     934
     935    int inputNumV4L = (*it)->inputNumV4L;
     936    bool usingv4l1 = !usingv4l2;
     937    bool ok = true;
     938
     939    QString msg =
     940        QString("SetInputAndFormat(%1, %2) ").arg(inputNum).arg(newFmt);
     941
     942    if (usingv4l2)
     943    {
     944        VERBOSE(VB_CHANNEL, LOC + msg + "(v4l v2)");
     945
     946        VERBOSE(VB_CHANNEL, QString("sending input changing command (%1)")
     947                .arg(driver_name));
     948
     949        int ioctlval = ioctl(videofd, VIDIOC_S_INPUT, &inputNumV4L);
     950
     951        bool undo_convertx_hack = false;
     952        bool undo_ivtv_hack = false;
     953        if ((driver_name == "ivtv") && (ioctlval < 0) && (errno == EBUSY))
     954        {
     955            QMutexLocker locker(&mpeg_recorder_ivtv_hack_lock);
     956            QString tmp = QDeepCopy<QString>(device);
     957            ok = ivtv_hack(LOC_ERR + msg,
     958                           videofd,
     959                           mpeg_recorder_ivtv_hack_chanfd[tmp.ascii()],
     960                           mpeg_recorder_ivtv_hack_readfd[tmp.ascii()],
     961                           inputNumV4L,
     962                           ioctlval, undo_ivtv_hack);
     963        }
     964        else if ((ioctlval < 0) && (errno == EBUSY))
     965        {
     966            ok = convertx_hack(LOC_ERR + msg, videofd, inputNumV4L,
     967                               ioctlval, undo_convertx_hack);
     968        }
     969
    792970        if (ioctlval < 0)
    793971        {
    794972            VERBOSE(VB_IMPORTANT, LOC_ERR + msg +
     
    807985            ok = false;
    808986        }
    809987
    810         // ConvertX (wis-go7007) requires streaming to be disabled
    811         // before an input switch, here we try to re-enable streaming.
    812         if (streamingDisabled)
     988        if (undo_convertx_hack)
     989            ok &= convertx_unhack(LOC_ERR + msg, videofd);
     990        if (undo_ivtv_hack)
    813991        {
    814             ioctlval = ioctl(videofd, VIDIOC_STREAMON, &streamType);
    815             if (ioctlval < 0)
    816             {
    817                 VERBOSE(VB_IMPORTANT, LOC_ERR + msg +
    818                         "\n\t\t\twhile reenabling streaming (v4l v2)" + ENO);
    819 
    820                 ok = false;
    821             }
     992            QMutexLocker locker(&mpeg_recorder_ivtv_hack_lock);
     993            QString tmp = QDeepCopy<QString>(device);
     994            ok = ivtv_unhack(LOC_ERR + msg,
     995                             videofd,
     996                             mpeg_recorder_ivtv_hack_chanfd[tmp.ascii()],
     997                             mpeg_recorder_ivtv_hack_readfd[tmp.ascii()]);
    822998        }
    823999    }
    8241000