コード例 #1
0
ファイル: fileringbuffer.cpp プロジェクト: gdenning/mythtv
bool FileRingBuffer::OpenFile(const QString &lfilename, uint retry_ms)
{
    LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("OpenFile(%1, %2 ms)")
            .arg(lfilename).arg(retry_ms));

    rwlock.lockForWrite();

    filename = lfilename;

    if (remotefile)
    {
        delete remotefile;
        remotefile = NULL;
    }

    if (fd2 >= 0)
    {
        close(fd2);
        fd2 = -1;
    }

    bool is_local = 
        (filename.left(4) != "/dev") &&
        ((filename.left(1) == "/") || QFile::exists(filename));

    if (is_local)
    {
        char buf[kReadTestSize];
        int lasterror = 0;

        MythTimer openTimer;
        openTimer.start();

        uint openAttempts = 0;
        do
        {
            openAttempts++;
            lasterror = 0;

            fd2 = open(filename.toLocal8Bit().constData(),
                       O_RDONLY|O_LARGEFILE|O_STREAMING|O_BINARY);

            if (fd2 < 0)
            {
                if (!check_permissions(filename))
                {
                    lasterror = 3;
                    break;
                }

                lasterror = 1;
                usleep(10 * 1000);
            }
            else
            {
                int ret = read(fd2, buf, kReadTestSize);
                if (ret != (int)kReadTestSize)
                {
                    lasterror = 2;
                    close(fd2);
                    fd2 = -1;
                    if (oldfile)
                        break; // if it's an old file it won't grow..
                    usleep(10 * 1000);
                }
                else
                {
                    if (0 == lseek(fd2, 0, SEEK_SET))
                    {
                        posix_fadvise(fd2, 0, 0,        POSIX_FADV_SEQUENTIAL);
                        posix_fadvise(fd2, 0, 128*1024, POSIX_FADV_WILLNEED);
                        lasterror = 0;
                        break;
                    }
                    lasterror = 4;
                    close(fd2);
                    fd2 = -1;
                }
            }
        }
        while ((uint)openTimer.elapsed() < retry_ms);

        switch (lasterror)
        {
            case 0:
            {
                QFileInfo fi(filename);
                oldfile = fi.lastModified()
                    .secsTo(QDateTime::currentDateTime()) > 60;
                QString extension = fi.completeSuffix().toLower();
                if (is_subtitle_possible(extension))
                    subtitlefilename = local_sub_filename(fi);
                break;
            }
            case 1:
                LOG(VB_GENERAL, LOG_ERR, LOC +
                        QString("OpenFile(): Could not open."));
                break;
            case 2:
                LOG(VB_GENERAL, LOG_ERR, LOC +
                        QString("OpenFile(): File too small (%1B).")
                        .arg(QFileInfo(filename).size()));
                break;
            case 3:
                LOG(VB_GENERAL, LOG_ERR, LOC +
                        "OpenFile(): Improper permissions.");
                break;
            case 4:
                LOG(VB_GENERAL, LOG_ERR, LOC +
                        "OpenFile(): Cannot seek in file.");
                break;
            default:
                break;
        }
        LOG(VB_FILE, LOG_INFO, 
            LOC + QString("OpenFile() made %1 attempts in %2 ms")
                .arg(openAttempts).arg(openTimer.elapsed()));

    }
    else
    {
        QString tmpSubName = filename;
        QString dirName  = ".";

        int dirPos = filename.lastIndexOf(QChar('/'));
        if (dirPos > 0)
        {
            tmpSubName = filename.mid(dirPos + 1);
            dirName = filename.left(dirPos);
        }

        QString baseName  = tmpSubName;
        QString extension = tmpSubName;
        QStringList auxFiles;

        int suffixPos = tmpSubName.lastIndexOf(QChar('.'));
        if (suffixPos > 0)
        {
            baseName = tmpSubName.left(suffixPos);
            extension = tmpSubName.right(suffixPos-1);
            if (is_subtitle_possible(extension))
            {
                QMutexLocker locker(&subExtLock);
                QStringList::const_iterator eit = subExt.begin();
                for (; eit != subExt.end(); ++eit)
                    auxFiles += baseName + *eit;
            }
        }

        remotefile = new RemoteFile(filename, false, true,
                                    retry_ms, &auxFiles);
        if (!remotefile->isOpen())
        {
            LOG(VB_GENERAL, LOG_ERR, LOC +
                    QString("RingBuffer::RingBuffer(): Failed to open remote "
                            "file (%1)").arg(filename));
            delete remotefile;
            remotefile = NULL;
        }
        else
        {
            QStringList aux = remotefile->GetAuxiliaryFiles();
            if (aux.size())
                subtitlefilename = dirName + "/" + aux[0];
        }
    }

    setswitchtonext = false;
    ateof = false;
    commserror = false;
    numfailures = 0;

    rawbitrate = 8000;
    CalcReadAheadThresh();

    bool ok = fd2 >= 0 || remotefile;

    rwlock.unlock();

    return ok;
}
コード例 #2
0
ファイル: bdringbuffer.cpp プロジェクト: DocOnDev/mythtv
bool BDRingBuffer::OpenFile(const QString &lfilename, uint retry_ms)
{
    filename = lfilename;

    VERBOSE(VB_IMPORTANT, LOC + QString("Opened BDRingBuffer device at %1")
            .arg(filename.toLatin1().data()));

    // Ask mythiowrapper to update this object on file open progress. Opening
    // a bluray disc can involve opening several hundred files which can take
    // several minutes when the disc structure is remote. The callback allows
    // us to 'kick' the main UI - as the 'please wait' widget is still visible
    // at this stage
    mythfile_open_register_callback(filename.toLatin1().data(), this,
                                    file_opened_callback);

    QMutexLocker locker(&m_infoLock);
    rwlock.lockForWrite();

    if (bdnav)
        close();

    QString keyfile = QString("%1/KEYDB.cfg").arg(GetConfDir());
    QByteArray keyarray = keyfile.toAscii();
    const char *keyfilepath = keyarray.data();

    bdnav = bd_open(filename.toLatin1().data(), keyfilepath);

    if (!bdnav)
    {
        rwlock.unlock();
        mythfile_open_register_callback(filename.toLatin1().data(), this, NULL);
        return false;
    }

    m_metaDiscLibrary = bd_get_meta(bdnav);

    if (m_metaDiscLibrary)
    {
        VERBOSE(VB_GENERAL, LOC + QString("Disc Title: %1 (%2)")
                    .arg(m_metaDiscLibrary->di_name)
                    .arg(m_metaDiscLibrary->language_code));
        VERBOSE(VB_GENERAL, LOC + QString("Alternative Title: %1")
                    .arg(m_metaDiscLibrary->di_alternative));
        VERBOSE(VB_GENERAL, LOC + QString("Disc Number: %1 of %2")
                    .arg(m_metaDiscLibrary->di_set_number)
                    .arg(m_metaDiscLibrary->di_num_sets));
    }

    // Check disc to see encryption status, menu and navigation types.
    m_topMenuSupported   = false;
    m_firstPlaySupported = false;
    const BLURAY_DISC_INFO *discinfo = bd_get_disc_info(bdnav);
    if (discinfo)
    {
        m_topMenuSupported   = discinfo->top_menu_supported;
        m_firstPlaySupported = discinfo->first_play_supported;

        VERBOSE(VB_PLAYBACK, LOC + QString("*** Blu-ray Disc Information ***"));
        VERBOSE(VB_PLAYBACK, LOC + QString("First Play Supported: %1")
                .arg(discinfo->first_play_supported ? "yes" : "no"));
        VERBOSE(VB_PLAYBACK, LOC + QString("Top Menu Supported: %1")
                .arg(discinfo->top_menu_supported ? "yes" : "no"));
        VERBOSE(VB_PLAYBACK, LOC + QString("Number of HDMV Titles: %1")
                .arg(discinfo->num_hdmv_titles));
        VERBOSE(VB_PLAYBACK, LOC + QString("Number of BD-J Titles: %1")
                .arg(discinfo->num_bdj_titles));
        VERBOSE(VB_PLAYBACK, LOC + QString("Number of Unsupported Titles: %1")
                .arg(discinfo->num_unsupported_titles));
        VERBOSE(VB_PLAYBACK, LOC + QString("AACS present on disc: %1")
                .arg(discinfo->aacs_detected ? "yes" : "no"));
        VERBOSE(VB_PLAYBACK, LOC + QString("libaacs used: %1")
                .arg(discinfo->libaacs_detected ? "yes" : "no"));
        VERBOSE(VB_PLAYBACK, LOC + QString("AACS handled: %1")
                .arg(discinfo->aacs_handled ? "yes" : "no"));
        VERBOSE(VB_PLAYBACK, LOC + QString("BD+ present on disc: %1")
                .arg(discinfo->bdplus_detected ? "yes" : "no"));
        VERBOSE(VB_PLAYBACK, LOC + QString("libbdplus used: %1")
                .arg(discinfo->libbdplus_detected ? "yes" : "no"));
        VERBOSE(VB_PLAYBACK, LOC + QString("BD+ handled: %1")
                .arg(discinfo->bdplus_handled ? "yes" : "no"));
    }

    // The following settings affect HDMV navigation
    // (default audio track selection,
    // parental controls, menu language, etc.  They are not yet used.

    // Set parental level "age" to 99 for now.  TODO: Add support for FE level
    bd_set_player_setting(bdnav, BLURAY_PLAYER_SETTING_PARENTAL, 99);

    // Set preferred language to FE guide language
    const char *langpref = gCoreContext->GetSetting(
        "ISO639Language0", "eng").toLatin1().data();
    QString QScountry  = gCoreContext->GetLocale()->GetCountryCode().toLower();
    const char *country = QScountry.toLatin1().data();
    bd_set_player_setting_str(
        bdnav, BLURAY_PLAYER_SETTING_AUDIO_LANG, langpref);

    // Set preferred presentation graphics language to the FE guide language
    bd_set_player_setting_str(bdnav, BLURAY_PLAYER_SETTING_PG_LANG, langpref);

    // Set preferred menu language to the FE guide language
    bd_set_player_setting_str(bdnav, BLURAY_PLAYER_SETTING_MENU_LANG, langpref);

    // Set player country code via MythLocale. (not a region setting)
    bd_set_player_setting_str(
        bdnav, BLURAY_PLAYER_SETTING_COUNTRY_CODE, country);

    int regioncode = 0;
    regioncode = gCoreContext->GetNumSetting("BlurayRegionCode");
    if (regioncode > 0)
        bd_set_player_setting(bdnav, BLURAY_PLAYER_SETTING_REGION_CODE, regioncode);

    VERBOSE(VB_IMPORTANT, LOC + QString("Using %1 as keyfile...")
            .arg(QString(keyfilepath)));

    // Return an index of relevant titles (excludes dupe clips + titles)
    VERBOSE(VB_GENERAL, LOC + QString("Retrieving title list (please wait)."));
    m_numTitles = bd_get_titles(bdnav, TITLES_RELEVANT);
    VERBOSE(VB_GENERAL, LOC + QString("Found %1 titles.").arg(m_numTitles));
    m_mainTitle = 0;
    m_currentTitleLength = 0;
    m_titlesize = 0;
    m_currentTime = 0;
    m_currentTitleInfo = NULL;
    m_currentTitleAngleCount = 0;

    // Mostly event-driven values below
    m_currentAngle = 0;
    m_currentTitle = 0;
    m_currentPlaylist = 0;
    m_currentPlayitem = 0;
    m_currentChapter = 0;
    m_currentAudioStream = 0;
    m_currentIGStream = 0;
    m_currentPGTextSTStream = 0;
    m_currentSecondaryAudioStream = 0;
    m_currentSecondaryVideoStream = 0;
    m_PGTextSTEnabled = false;
    m_secondaryAudioEnabled = false;
    m_secondaryVideoEnabled = false;
    m_secondaryVideoIsFullscreen = false;
    m_stillMode = BLURAY_STILL_NONE;
    m_stillTime = 0;
    m_inMenu = false;

    // First, attempt to initialize the disc in HDMV navigation mode.
    // If this fails, fall back to the traditional built-in title switching
    // mode.
    if (m_tryHDMVNavigation && m_firstPlaySupported && bd_play(bdnav))
    {
        VERBOSE(VB_IMPORTANT, LOC + QString("Using HDMV navigation mode."));
        m_isHDMVNavigation = true;

        // Register the Menu Overlay Callback
        bd_register_overlay_proc(bdnav, this, HandleOverlayCallback);
    }
    else
    {
        VERBOSE(VB_IMPORTANT, LOC + QString("Using title navigation mode."));

        // Loop through the relevant titles and find the longest
        uint64_t titleLength = 0;
        uint64_t margin      = 90000 << 4; // approx 30s
        BLURAY_TITLE_INFO *titleInfo = NULL;
        for( unsigned i = 0; i < m_numTitles; ++i)
        {
            titleInfo = GetTitleInfo(i);
            if (titleLength == 0 ||
                (titleInfo->duration > (titleLength + margin)))
            {
                m_mainTitle = titleInfo->idx;
                titleLength = titleInfo->duration;
            }
        }

        SwitchTitle(m_mainTitle);
    }

    readblocksize   = BD_BLOCK_SIZE * 62;
    setswitchtonext = false;
    ateof           = false;
    commserror      = false;
    numfailures     = 0;
    rawbitrate      = 8000;
    CalcReadAheadThresh();

    rwlock.unlock();

    mythfile_open_register_callback(filename.toLatin1().data(), this, NULL);
    return true;
}
コード例 #3
0
bool BDRingBuffer::OpenFile(const QString &lfilename, uint retry_ms)
{
    VERBOSE(VB_IMPORTANT, LOC + QString("Opened BDRingBuffer device at %1")
            .arg(lfilename.toLatin1().data()));

    rwlock.lockForWrite();

    if (bdnav)
    {
        if (m_currentTitleInfo)
            bd_free_title_info(m_currentTitleInfo);
        bd_close(bdnav);
        bdnav = NULL;
    }

    filename = lfilename;

    QString keyfile = QString("%1/KEYDB.cfg").arg(GetConfDir());
    QByteArray keyarray = keyfile.toAscii();
    const char *keyfilepath = keyarray.data();

    bdnav = bd_open(lfilename.toLatin1().data(), keyfilepath);

    if (!bdnav)
    {
        rwlock.unlock();
        return false;
    }

    // Check disc to see encryption status, menu and navigation types.
    const BLURAY_DISC_INFO *discinfo = bd_get_disc_info(bdnav);
    if (discinfo)
    {
        VERBOSE(VB_PLAYBACK, QString(
                    "*** Blu-ray Disc Information ***\n"
                    "First Play Supported: %1\n"
                    "Top Menu Supported: %2\n"
                    "Number of HDMV Titles: %3\n"
                    "Number of BD-J Titles: %4\n"
                    "Number of Unsupported Titles: %5\n"
                    "AACS present on disc: %6\n"
                    "libaacs used: %7\n"
                    "AACS handled: %8\n"
                    "BD+ present on disc: %9\n"
                    "libbdplus used: %10\n"
                    "BD+ handled: %11")
                .arg(discinfo->first_play_supported ? "yes" : "no")
                .arg(discinfo->top_menu_supported ? "yes" : "no")
                .arg(discinfo->num_hdmv_titles)
                .arg(discinfo->num_bdj_titles)
                .arg(discinfo->num_unsupported_titles)
                .arg(discinfo->aacs_detected ? "yes" : "no")
                .arg(discinfo->libaacs_detected ? "yes" : "no")
                .arg(discinfo->aacs_handled ? "yes" : "no")
                .arg(discinfo->bdplus_detected ? "yes" : "no")
                .arg(discinfo->libbdplus_detected ? "yes" : "no")
                .arg(discinfo->bdplus_handled ? "yes" : "no"));
    }

    // The following settings affect HDMV navigation
    // (default audio track selection,
    // parental controls, menu language, etc.  They are not yet used.

    // Set parental level "age" to 99 for now.  TODO: Add support for FE level
    bd_set_player_setting(bdnav, BLURAY_PLAYER_SETTING_PARENTAL, 99);

    // Set preferred language to FE guide language
    const char *langpref = gCoreContext->GetSetting(
        "ISO639Language0", "eng").toLatin1().data();
    QString QScountry  = gCoreContext->GetLocale()->GetCountryCode().toLower();
    const char *country = QScountry.toLatin1().data();
    bd_set_player_setting_str(
        bdnav, BLURAY_PLAYER_SETTING_AUDIO_LANG, langpref);

    // Set preferred presentation graphics language to the FE guide language
    bd_set_player_setting_str(bdnav, BLURAY_PLAYER_SETTING_PG_LANG, langpref);

    // Set preferred menu language to the FE guide language
    bd_set_player_setting_str(bdnav, BLURAY_PLAYER_SETTING_MENU_LANG, langpref);

    // Set player country code via MythLocale. (not a region setting)
    bd_set_player_setting_str(
        bdnav, BLURAY_PLAYER_SETTING_COUNTRY_CODE, country);

    int regioncode = 0;
    regioncode = gCoreContext->GetNumSetting("BlurayRegionCode");
    if (regioncode > 0)
        bd_set_player_setting(bdnav, BLURAY_PLAYER_SETTING_REGION_CODE, regioncode);

    VERBOSE(VB_IMPORTANT, LOC + QString("Using %1 as keyfile...")
            .arg(QString(keyfilepath)));

    // Return an index of relevant titles (excludes dupe clips + titles)
    m_numTitles = bd_get_titles(bdnav, TITLES_RELEVANT);
    m_mainTitle = 0;
    m_currentTitleLength = 0;
    m_titlesize = 0;
    m_currentTime = 0;
    m_currentTitleInfo = NULL;
    m_currentTitleAngleCount = 0;

    // Mostly event-driven values below
    m_currentAngle = 0;
    m_currentTitle = 0;
    m_currentPlaylist = 0;
    m_currentPlayitem = 0;
    m_currentChapter = 0;
    m_currentAudioStream = 0;
    m_currentIGStream = 0;
    m_currentPGTextSTStream = 0;
    m_currentSecondaryAudioStream = 0;
    m_currentSecondaryVideoStream = 0;
    m_PGTextSTEnabled = false;
    m_secondaryAudioEnabled = false;
    m_secondaryVideoEnabled = false;
    m_secondaryVideoIsFullscreen = false;
    m_still = 0;
    m_inMenu = false;

    VERBOSE(VB_IMPORTANT, LOC + QString("Found %1 relevant titles.")
            .arg(m_numTitles));

    // Loop through the relevant titles and find the longest
    uint64_t titleLength = 0;
    uint64_t margin      = 90000 << 4; // approx 30s
    BLURAY_TITLE_INFO *titleInfo = NULL;
    for( unsigned i = 0; i < m_numTitles; ++i)
    {
        titleInfo = bd_get_title_info(bdnav, i);
        if (titleLength == 0 ||
            (titleInfo->duration > (titleLength + margin)))
        {
            m_mainTitle = titleInfo->idx;
            titleLength = titleInfo->duration;
        }
    }

    bd_free_title_info(titleInfo);

    SwitchTitle(m_mainTitle);

#if 0
    // First, attempt to initialize the disc in HDMV navigation mode.
    // If this fails, fall back to the traditional built-in title switching
    // mode.
    if (bd_play(bdnav))
    {
        m_is_hdmv_navigation = true;

        // Initialize the HDMV event queue
        HandleBDEvents();

        // Register the Menu Overlay Callback
        bd_register_overlay_proc(bdnav, this, HandleOverlayCallback);
    }
#endif

    readblocksize   = BD_BLOCK_SIZE * 62;
    setswitchtonext = false;
    ateof           = false;
    commserror      = false;
    numfailures     = 0;
    rawbitrate      = 8000;
    CalcReadAheadThresh();

    rwlock.unlock();

    return true;
}