<commit_before>//  (C) Copyright Gennadiy Rozental 2011-2012.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : defines range generator
// ***************************************************************************

#ifndef BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER
#define BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_RANDOM_HPP_101512GER

// Boost.Test
#include <boost/test/data/config.hpp>

#ifndef BOOST_NO_CXX11_HDR_RANDOM

#include <boost/test/data/monomorphic/generate.hpp>
#include <boost/test/data/monomorphic/generators/keywords.hpp>

// STL
#include <random>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

namespace boost {
namespace unit_test {
namespace data {

namespace {
nfp::keyword<struct seed_t>         seed;
nfp::keyword<struct distrbution_t>  distribution;
nfp::keyword<struct engine_t>       engine;
} // local namespace

namespace monomorphic {

namespace ds_detail {
template<typename SampleType>
struct default_distribution {
    typedef typename mpl::if_<std::is_integral<SampleType>,
                              std::uniform_int_distribution<SampleType>,
                              std::uniform_real_distribution<SampleType> >::type type;
};

} // namespace ds_detail

// ************************************************************************** //
// **************                   random_t                   ************** //
// ************************************************************************** //

template<typename SampleType        = double,
         typename DistributionType  = typename ds_detail::default_distribution<SampleType>::type,
         typename EngineType        = std::default_random_engine>
class random_t {
public:
    typedef SampleType          data_type;
    typedef DistributionType    distr_type;
    typedef EngineType          engine_type;

    random_t()
    : m_distribution()
    , m_engine( std::random_device()() )
    {}
    explicit random_t( distr_type&& d )
    : m_distribution( std::forward<distr_type>(d) )
    , m_engine( std::random_device()() ){}
    random_t( engine_type&& e, distr_type&& d )
    : m_distribution( std::forward<distr_type>(d) )
    , m_engine( std::forward<engine_type>(e) ){}

    // Generator interface
    data::size_t        capacity() const    { return BOOST_TEST_DS_INFINITE_SIZE; }
    SampleType          next()
    {
        return m_distribution( m_engine );
    }
    template<typename SeedType>
    void seed( SeedType&& seed )            { m_engine.seed( std::forward<SeedType>( seed ) ); }

private:
    // Data members
    DistributionType    m_distribution;
    EngineType          m_engine;
};

//____________________________________________________________________________//

} // namespace monomorphic

inline monomorphic::generated_by<monomorphic::random_t<>>
random()
{
    return monomorphic::generated_by<monomorphic::random_t<>>( monomorphic::random_t<>() );
}

//____________________________________________________________________________//

template<typename SampleType>
inline monomorphic::generated_by<monomorphic::random_t<SampleType>>
random( SampleType begin, SampleType end )
{
    typedef monomorphic::random_t<SampleType> Gen;
    typedef typename Gen::distr_type distr_type;
    return monomorphic::generated_by<Gen>( Gen( distr_type(begin,end) ) );
}

//____________________________________________________________________________//

namespace ds_detail {
template<typename Params>
struct random_gen_type {
    typedef typename nfp::param_type<Params,decltype(distribution),std::uniform_real_distribution<>>::type distr_type;
    typedef typename nfp::param_type<Params,decltype(engine),std::default_random_engine>::type engine_type;
    typedef typename distr_type::result_type sample_type;

    typedef monomorphic::random_t<sample_type,distr_type,engine_type> type;
};

}

template<typename Params>
inline monomorphic::generated_by<typename ds_detail::random_gen_type<Params>::type>
random( Params const& params )
{
    typedef typename ds_detail::random_gen_type<Params>::type Gen;
    typedef typename Gen::distr_type distr_type;
    typedef typename Gen::engine_type engine_type;

    std::random_device rd;
    engine_type E;
//    engine_type E( rd );
    if( params.has(engine) )
        E = params[engine];

    distr_type D;
    if( params.has(distribution) )
        D = params[distribution];

    Gen G( std::move(E), std::move(D) );

    if( params.has(seed) )
        G.seed( params[seed] );

    return monomorphic::generated_by<Gen>( std::move(G) );
}

} // namespace data
} // namespace unit_test
} // namespace boost

#include <boost/test/detail/enable_warnings.hpp>

#endif // BOOST_NO_CXX11_HDR_RANDOM

#endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_RANDOM_HPP_101512GER
<commit_msg>Wrong gard<commit_after>//  (C) Copyright Gennadiy Rozental 2011-2012.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//  File        : $RCSfile$
//
//  Version     : $Revision$
//
//  Description : defines range generator
// ***************************************************************************

#ifndef BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_RANDOM_HPP_101512GER
#define BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_RANDOM_HPP_101512GER

// Boost.Test
#include <boost/test/data/config.hpp>

#ifndef BOOST_NO_CXX11_HDR_RANDOM

#include <boost/test/data/monomorphic/generate.hpp>
#include <boost/test/data/monomorphic/generators/keywords.hpp>

// STL
#include <random>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

namespace boost {
namespace unit_test {
namespace data {

namespace {
nfp::keyword<struct seed_t>         seed;
nfp::keyword<struct distrbution_t>  distribution;
nfp::keyword<struct engine_t>       engine;
} // local namespace

namespace monomorphic {

namespace ds_detail {
template<typename SampleType>
struct default_distribution {
    typedef typename mpl::if_<std::is_integral<SampleType>,
                              std::uniform_int_distribution<SampleType>,
                              std::uniform_real_distribution<SampleType> >::type type;
};

} // namespace ds_detail

// ************************************************************************** //
// **************                   random_t                   ************** //
// ************************************************************************** //

template<typename SampleType        = double,
         typename DistributionType  = typename ds_detail::default_distribution<SampleType>::type,
         typename EngineType        = std::default_random_engine>
class random_t {
public:
    typedef SampleType          data_type;
    typedef DistributionType    distr_type;
    typedef EngineType          engine_type;

    random_t()
    : m_distribution()
    , m_engine( std::random_device()() )
    {}
    explicit random_t( distr_type&& d )
    : m_distribution( std::forward<distr_type>(d) )
    , m_engine( std::random_device()() ){}
    random_t( engine_type&& e, distr_type&& d )
    : m_distribution( std::forward<distr_type>(d) )
    , m_engine( std::forward<engine_type>(e) ){}

    // Generator interface
    data::size_t        capacity() const    { return BOOST_TEST_DS_INFINITE_SIZE; }
    SampleType          next()
    {
        return m_distribution( m_engine );
    }
    template<typename SeedType>
    void seed( SeedType&& seed )            { m_engine.seed( std::forward<SeedType>( seed ) ); }

private:
    // Data members
    DistributionType    m_distribution;
    EngineType          m_engine;
};

//____________________________________________________________________________//

} // namespace monomorphic

inline monomorphic::generated_by<monomorphic::random_t<>>
random()
{
    return monomorphic::generated_by<monomorphic::random_t<>>( monomorphic::random_t<>() );
}

//____________________________________________________________________________//

template<typename SampleType>
inline monomorphic::generated_by<monomorphic::random_t<SampleType>>
random( SampleType begin, SampleType end )
{
    typedef monomorphic::random_t<SampleType> Gen;
    typedef typename Gen::distr_type distr_type;
    return monomorphic::generated_by<Gen>( Gen( distr_type(begin,end) ) );
}

//____________________________________________________________________________//

namespace ds_detail {
template<typename Params>
struct random_gen_type {
    typedef typename nfp::param_type<Params,decltype(distribution),std::uniform_real_distribution<>>::type distr_type;
    typedef typename nfp::param_type<Params,decltype(engine),std::default_random_engine>::type engine_type;
    typedef typename distr_type::result_type sample_type;

    typedef monomorphic::random_t<sample_type,distr_type,engine_type> type;
};

}

template<typename Params>
inline monomorphic::generated_by<typename ds_detail::random_gen_type<Params>::type>
random( Params const& params )
{
    typedef typename ds_detail::random_gen_type<Params>::type Gen;
    typedef typename Gen::distr_type distr_type;
    typedef typename Gen::engine_type engine_type;

    std::random_device rd;
    engine_type E;
//    engine_type E( rd );
    if( params.has(engine) )
        E = params[engine];

    distr_type D;
    if( params.has(distribution) )
        D = params[distribution];

    Gen G( std::move(E), std::move(D) );

    if( params.has(seed) )
        G.seed( params[seed] );

    return monomorphic::generated_by<Gen>( std::move(G) );
}

} // namespace data
} // namespace unit_test
} // namespace boost

#include <boost/test/detail/enable_warnings.hpp>

#endif // BOOST_NO_CXX11_HDR_RANDOM

#endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_RANDOM_HPP_101512GER
<|endoftext|>


<commit_before>/*
 * Global Presence - wraps calls to set and get presence for all accounts.
 *
 * Copyright (C) 2011 David Edmundson <kde@davidedmundson.co.uk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "global-presence.h"

#include "presence.h"

#include <TelepathyQt/AccountSet>
#include <TelepathyQt/Account>
#include <TelepathyQt/PendingReady>

#include "ktp-debug.h"

namespace KTp
{

GlobalPresence::GlobalPresence(QObject *parent)
    : QObject(parent),
      m_connectionStatus(Tp::ConnectionStatusDisconnected),
      m_changingPresence(false)
{
    Tp::Presence unknown;
    unknown.setStatus(Tp::ConnectionPresenceTypeUnknown, QLatin1String("unknown"), QString());

    m_requestedPresence = KTp::Presence(unknown);
    m_currentPresence = KTp::Presence(unknown);
}

void GlobalPresence::setAccountManager(const Tp::AccountManagerPtr &accountManager)
{
    if (! accountManager->isReady()) {
        qCWarning(KTP_COMMONINTERNALS) << "GlobalPresence used with unready account manager";
    }

    m_enabledAccounts = accountManager->enabledAccounts();
    m_onlineAccounts = accountManager->onlineAccounts();

    Q_FOREACH(const Tp::AccountPtr &account, m_enabledAccounts->accounts()) {
        onAccountAdded(account);
    }

    onCurrentPresenceChanged();
    onRequestedPresenceChanged();
    onChangingPresence();
    onConnectionStatusChanged();

    connect(m_enabledAccounts.data(), SIGNAL(accountAdded(Tp::AccountPtr)), SLOT(onAccountAdded(Tp::AccountPtr)));
}

void GlobalPresence::addAccountManager(const Tp::AccountManagerPtr &accountManager)
{
    m_accountManager = accountManager;
    connect(m_accountManager->becomeReady(), SIGNAL(finished(Tp::PendingOperation*)),
            this, SLOT(onAccountManagerReady(Tp::PendingOperation*)));
}

Tp::AccountManagerPtr GlobalPresence::accountManager() const
{
    return m_accountManager;
}

void GlobalPresence::onAccountManagerReady(Tp::PendingOperation* op)
{
    if (op->isError()) {
        qCDebug(KTP_COMMONINTERNALS) << op->errorName();
        qCDebug(KTP_COMMONINTERNALS) << op->errorMessage();

        //TODO: Create signal to send to client
        qCDebug(KTP_COMMONINTERNALS) << "Something unexpected happened to the core part of your Instant Messaging system "
                 << "and it couldn't be initialized. Try restarting the client.";

        return;
    }

    setAccountManager(m_accountManager);
    Q_EMIT(accountManagerReady());
}

Tp::ConnectionStatus GlobalPresence::connectionStatus() const
{
    return m_connectionStatus;
}

Presence GlobalPresence::currentPresence() const
{
    return m_currentPresence;
}

QString GlobalPresence::currentPresenceMessage() const
{
    KTp::Presence p = currentPresence();
    return p.statusMessage();
}

QIcon GlobalPresence::currentPresenceIcon() const
{
    return currentPresence().icon();
}

QString GlobalPresence::currentPresenceIconName() const
{
    return currentPresence().iconName();
}

QString GlobalPresence::currentPresenceName() const
{
    return currentPresence().displayString();
}

GlobalPresence::ConnectionPresenceType GlobalPresence::currentPresenceType() const
{
    KTp::Presence p = currentPresence();
    switch(p.type()) {
        case Tp::ConnectionPresenceTypeAvailable:
            return GlobalPresence::Available;
        case Tp::ConnectionPresenceTypeBusy:
            return GlobalPresence::Busy;
        case Tp::ConnectionPresenceTypeAway:
            return GlobalPresence::Away;
        case Tp::ConnectionPresenceTypeExtendedAway:
            return GlobalPresence::ExtendedAway;
        case Tp::ConnectionPresenceTypeHidden:
            return GlobalPresence::Hidden;
        case Tp::ConnectionPresenceTypeOffline:
            return GlobalPresence::Offline;
        default:
            return GlobalPresence::Unknown;
    }
}

Presence GlobalPresence::requestedPresence() const
{
    return m_requestedPresence;
}

QString GlobalPresence::requestedPresenceName() const
{
    return m_requestedPresence.displayString();
}

bool GlobalPresence::isChangingPresence() const
{
    return m_changingPresence;
}

void GlobalPresence::setPresence(const KTp::Presence &presence)
{
    if (m_enabledAccounts.isNull()) {
        qCWarning(KTP_COMMONINTERNALS) << "Requested presence change on empty accounts set";
        return;
    }

    Q_FOREACH(const Tp::AccountPtr &account, m_enabledAccounts->accounts()) {
        account->setRequestedPresence(presence);
    }
}

void GlobalPresence::setPresence(GlobalPresence::ConnectionPresenceType p, QString message)
{
    switch (p) {
    case GlobalPresence::Available:
        setPresence(Tp::Presence::available(message));
        break;
    case GlobalPresence::Busy:
        setPresence(Tp::Presence::busy(message));
        break;
    case GlobalPresence::Away:
        setPresence(Tp::Presence::away(message));
        break;
    case GlobalPresence::ExtendedAway:
        setPresence(Tp::Presence::xa(message));
        break;
    case GlobalPresence::Hidden:
        setPresence(Tp::Presence::hidden(message));
        break;
    case GlobalPresence::Offline:
        setPresence(Tp::Presence::offline(message));
        break;
    default:
        qCDebug(KTP_COMMONINTERNALS) << "You should not be here!";
    }
}

void GlobalPresence::onAccountAdded(const Tp::AccountPtr &account)
{
    connect(account.data(), SIGNAL(connectionStatusChanged(Tp::ConnectionStatus)), SLOT(onConnectionStatusChanged()));
    connect(account.data(), SIGNAL(changingPresence(bool)), SLOT(onChangingPresence()));
    connect(account.data(), SIGNAL(requestedPresenceChanged(Tp::Presence)), SLOT(onRequestedPresenceChanged()));
    connect(account.data(), SIGNAL(currentPresenceChanged(Tp::Presence)), SLOT(onCurrentPresenceChanged()));
}

void GlobalPresence::onCurrentPresenceChanged()
{
    /* basic idea of choosing global presence it to make it reflects the presence
     * over all accounts, usually this is used to indicates user the whole system
     * status.
     *
     * If there isn't any account, currentPresence should be offline, since there is nothing
     * online.
     * If there's only one account, then currentPresence should represent the presence
     * of this account.
     * If there're more than one accounts, the situation is more complicated.
     * There can be some accounts is still connecting (thus it's offline), and there can be
     * some accounts doesn't support the presence you're choosing. The user-chosen presence
     * priority will be higher than standard presence order.
     *
     * Example:
     * user choose to be online, 1 account online, 1 account offline, current presence
     * should be online, since online priority is higher than offline.
     * user chooses a presence supported by part of the account, current presence will be
     * the one chosen by user, to indicate there is at least one account supports it.
     * user choose a presence supported by no account, current presence will be chosen
     * from all accounts based on priority, and it also indicates there is no account support
     * the user-chosen presence.
     */
    Tp::Presence highestCurrentPresence = Tp::Presence::offline();
    Q_FOREACH(const Tp::AccountPtr &account, m_enabledAccounts->accounts()) {
        if (account->currentPresence().type() == m_requestedPresence.type()) {
            highestCurrentPresence = account->currentPresence();
            break;
        }

        if (Presence::sortPriority(account->currentPresence().type()) < Presence::sortPriority(highestCurrentPresence.type())) {
            highestCurrentPresence = account->currentPresence();
        }
    }

    qCDebug(KTP_COMMONINTERNALS) << "Current presence changed";

    if (highestCurrentPresence.type() != m_currentPresence.type() ||
            highestCurrentPresence.status() != m_currentPresence.status() ||
            highestCurrentPresence.statusMessage() != m_currentPresence.statusMessage()) {

        m_currentPresence = Presence(highestCurrentPresence);
        Q_EMIT currentPresenceChanged(m_currentPresence);
    }
}

void GlobalPresence::onRequestedPresenceChanged()
{
    Tp::Presence highestRequestedPresence = Tp::Presence::offline();
    Q_FOREACH(const Tp::AccountPtr &account, m_enabledAccounts->accounts()) {
        if (Presence::sortPriority(account->requestedPresence().type()) < Presence::sortPriority(highestRequestedPresence.type())) {
            highestRequestedPresence = account->requestedPresence();
        }
    }

    if (highestRequestedPresence.type() != m_requestedPresence.type() ||
            highestRequestedPresence.status() != m_requestedPresence.status() ||
            highestRequestedPresence.statusMessage() != m_requestedPresence.statusMessage()) {
        m_requestedPresence = Presence(highestRequestedPresence);
        // current presence priority is affected by requested presence
        onCurrentPresenceChanged();
        Q_EMIT requestedPresenceChanged(m_requestedPresence);
    }
}

void GlobalPresence::onChangingPresence()
{
    bool isChangingPresence = false;
    Q_FOREACH(const Tp::AccountPtr &account, m_enabledAccounts->accounts()) {
        if (account->isChangingPresence()) {
            isChangingPresence = true;
        }
    }

    if (isChangingPresence != m_changingPresence) {
        m_changingPresence = isChangingPresence;
        Q_EMIT changingPresence(m_changingPresence);
    }
}

void GlobalPresence::onConnectionStatusChanged()
{
    Tp::ConnectionStatus connectionStatus = Tp::ConnectionStatusDisconnected;

    Q_FOREACH(const Tp::AccountPtr &account, m_enabledAccounts->accounts()) {
        switch (account->connectionStatus()) {
        case Tp::ConnectionStatusConnecting:
            //connecting is the highest state, use this always
            connectionStatus = Tp::ConnectionStatusConnecting;
            break;
        case Tp::ConnectionStatusConnected:
            //only set to connected if we're not at connecting
            if (connectionStatus == Tp::ConnectionStatusDisconnected) {
                connectionStatus = Tp::ConnectionStatusConnected;
            }
            break;
        default:
            break;
        }
    }

    if (connectionStatus != m_connectionStatus) {
        m_connectionStatus = connectionStatus;
        Q_EMIT connectionStatusChanged(m_connectionStatus);
    }
}

bool GlobalPresence::hasEnabledAccounts() const
{
    if (m_enabledAccounts->accounts().isEmpty()) {
        return false;
    }

    return true;
}

void GlobalPresence::saveCurrentPresence()
{
    qCDebug(KTP_COMMONINTERNALS) << "Saving presence with message:" << m_currentPresence.statusMessage();
    m_savedPresence = m_currentPresence;
}

void GlobalPresence::restoreSavedPresence()
{
    qCDebug(KTP_COMMONINTERNALS) << m_savedPresence.statusMessage();
    setPresence(m_savedPresence);
}

Tp::AccountSetPtr GlobalPresence::onlineAccounts() const
{
    return m_onlineAccounts;
}

}

#include "global-presence.moc"
<commit_msg>Tp::Account::changingPresence is broken, compare requested and current presence instead<commit_after>/*
 * Global Presence - wraps calls to set and get presence for all accounts.
 *
 * Copyright (C) 2011 David Edmundson <kde@davidedmundson.co.uk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "global-presence.h"

#include "presence.h"

#include <TelepathyQt/AccountSet>
#include <TelepathyQt/Account>
#include <TelepathyQt/PendingReady>

#include "ktp-debug.h"

namespace KTp
{

GlobalPresence::GlobalPresence(QObject *parent)
    : QObject(parent),
      m_connectionStatus(Tp::ConnectionStatusDisconnected),
      m_changingPresence(false)
{
    Tp::Presence unknown;
    unknown.setStatus(Tp::ConnectionPresenceTypeUnknown, QLatin1String("unknown"), QString());

    m_requestedPresence = KTp::Presence(unknown);
    m_currentPresence = KTp::Presence(unknown);
}

void GlobalPresence::setAccountManager(const Tp::AccountManagerPtr &accountManager)
{
    if (! accountManager->isReady()) {
        qCWarning(KTP_COMMONINTERNALS) << "GlobalPresence used with unready account manager";
    }

    m_enabledAccounts = accountManager->enabledAccounts();
    m_onlineAccounts = accountManager->onlineAccounts();

    Q_FOREACH(const Tp::AccountPtr &account, m_enabledAccounts->accounts()) {
        onAccountAdded(account);
    }

    onCurrentPresenceChanged();
    onRequestedPresenceChanged();
    onChangingPresence();
    onConnectionStatusChanged();

    connect(m_enabledAccounts.data(), SIGNAL(accountAdded(Tp::AccountPtr)), SLOT(onAccountAdded(Tp::AccountPtr)));
}

void GlobalPresence::addAccountManager(const Tp::AccountManagerPtr &accountManager)
{
    m_accountManager = accountManager;
    connect(m_accountManager->becomeReady(), SIGNAL(finished(Tp::PendingOperation*)),
            this, SLOT(onAccountManagerReady(Tp::PendingOperation*)));
}

Tp::AccountManagerPtr GlobalPresence::accountManager() const
{
    return m_accountManager;
}

void GlobalPresence::onAccountManagerReady(Tp::PendingOperation* op)
{
    if (op->isError()) {
        qCDebug(KTP_COMMONINTERNALS) << op->errorName();
        qCDebug(KTP_COMMONINTERNALS) << op->errorMessage();

        //TODO: Create signal to send to client
        qCDebug(KTP_COMMONINTERNALS) << "Something unexpected happened to the core part of your Instant Messaging system "
                 << "and it couldn't be initialized. Try restarting the client.";

        return;
    }

    setAccountManager(m_accountManager);
    Q_EMIT(accountManagerReady());
}

Tp::ConnectionStatus GlobalPresence::connectionStatus() const
{
    return m_connectionStatus;
}

Presence GlobalPresence::currentPresence() const
{
    return m_currentPresence;
}

QString GlobalPresence::currentPresenceMessage() const
{
    KTp::Presence p = currentPresence();
    return p.statusMessage();
}

QIcon GlobalPresence::currentPresenceIcon() const
{
    return currentPresence().icon();
}

QString GlobalPresence::currentPresenceIconName() const
{
    return currentPresence().iconName();
}

QString GlobalPresence::currentPresenceName() const
{
    return currentPresence().displayString();
}

GlobalPresence::ConnectionPresenceType GlobalPresence::currentPresenceType() const
{
    KTp::Presence p = currentPresence();
    switch(p.type()) {
        case Tp::ConnectionPresenceTypeAvailable:
            return GlobalPresence::Available;
        case Tp::ConnectionPresenceTypeBusy:
            return GlobalPresence::Busy;
        case Tp::ConnectionPresenceTypeAway:
            return GlobalPresence::Away;
        case Tp::ConnectionPresenceTypeExtendedAway:
            return GlobalPresence::ExtendedAway;
        case Tp::ConnectionPresenceTypeHidden:
            return GlobalPresence::Hidden;
        case Tp::ConnectionPresenceTypeOffline:
            return GlobalPresence::Offline;
        default:
            return GlobalPresence::Unknown;
    }
}

Presence GlobalPresence::requestedPresence() const
{
    return m_requestedPresence;
}

QString GlobalPresence::requestedPresenceName() const
{
    return m_requestedPresence.displayString();
}

bool GlobalPresence::isChangingPresence() const
{
    return m_changingPresence;
}

void GlobalPresence::setPresence(const KTp::Presence &presence)
{
    if (m_enabledAccounts.isNull()) {
        qCWarning(KTP_COMMONINTERNALS) << "Requested presence change on empty accounts set";
        return;
    }

    Q_FOREACH(const Tp::AccountPtr &account, m_enabledAccounts->accounts()) {
        account->setRequestedPresence(presence);
    }
}

void GlobalPresence::setPresence(GlobalPresence::ConnectionPresenceType p, QString message)
{
    switch (p) {
    case GlobalPresence::Available:
        setPresence(Tp::Presence::available(message));
        break;
    case GlobalPresence::Busy:
        setPresence(Tp::Presence::busy(message));
        break;
    case GlobalPresence::Away:
        setPresence(Tp::Presence::away(message));
        break;
    case GlobalPresence::ExtendedAway:
        setPresence(Tp::Presence::xa(message));
        break;
    case GlobalPresence::Hidden:
        setPresence(Tp::Presence::hidden(message));
        break;
    case GlobalPresence::Offline:
        setPresence(Tp::Presence::offline(message));
        break;
    default:
        qCDebug(KTP_COMMONINTERNALS) << "You should not be here!";
    }
}

void GlobalPresence::onAccountAdded(const Tp::AccountPtr &account)
{
    connect(account.data(), SIGNAL(connectionStatusChanged(Tp::ConnectionStatus)), SLOT(onConnectionStatusChanged()));
    connect(account.data(), SIGNAL(requestedPresenceChanged(Tp::Presence)), SLOT(onRequestedPresenceChanged()));
    connect(account.data(), SIGNAL(currentPresenceChanged(Tp::Presence)), SLOT(onCurrentPresenceChanged()));
}

void GlobalPresence::onCurrentPresenceChanged()
{
    /* basic idea of choosing global presence it to make it reflects the presence
     * over all accounts, usually this is used to indicates user the whole system
     * status.
     *
     * If there isn't any account, currentPresence should be offline, since there is nothing
     * online.
     * If there's only one account, then currentPresence should represent the presence
     * of this account.
     * If there're more than one accounts, the situation is more complicated.
     * There can be some accounts is still connecting (thus it's offline), and there can be
     * some accounts doesn't support the presence you're choosing. The user-chosen presence
     * priority will be higher than standard presence order.
     *
     * Example:
     * user choose to be online, 1 account online, 1 account offline, current presence
     * should be online, since online priority is higher than offline.
     * user chooses a presence supported by part of the account, current presence will be
     * the one chosen by user, to indicate there is at least one account supports it.
     * user choose a presence supported by no account, current presence will be chosen
     * from all accounts based on priority, and it also indicates there is no account support
     * the user-chosen presence.
     */
    Tp::Presence highestCurrentPresence = Tp::Presence::offline();
    Q_FOREACH(const Tp::AccountPtr &account, m_enabledAccounts->accounts()) {
        if (account->currentPresence().type() == m_requestedPresence.type()) {
            highestCurrentPresence = account->currentPresence();
            break;
        }

        if (Presence::sortPriority(account->currentPresence().type()) < Presence::sortPriority(highestCurrentPresence.type())) {
            highestCurrentPresence = account->currentPresence();
        }
    }

    qCDebug(KTP_COMMONINTERNALS) << "Current presence changed";

    if (highestCurrentPresence.type() != m_currentPresence.type() ||
            highestCurrentPresence.status() != m_currentPresence.status() ||
            highestCurrentPresence.statusMessage() != m_currentPresence.statusMessage()) {

        m_currentPresence = Presence(highestCurrentPresence);
        Q_EMIT currentPresenceChanged(m_currentPresence);
    }

    onChangingPresence();
}

void GlobalPresence::onRequestedPresenceChanged()
{
    Tp::Presence highestRequestedPresence = Tp::Presence::offline();
    Q_FOREACH(const Tp::AccountPtr &account, m_enabledAccounts->accounts()) {
        if (Presence::sortPriority(account->requestedPresence().type()) < Presence::sortPriority(highestRequestedPresence.type())) {
            highestRequestedPresence = account->requestedPresence();
        }
    }

    if (highestRequestedPresence.type() != m_requestedPresence.type() ||
            highestRequestedPresence.status() != m_requestedPresence.status() ||
            highestRequestedPresence.statusMessage() != m_requestedPresence.statusMessage()) {
        m_requestedPresence = Presence(highestRequestedPresence);
        // current presence priority is affected by requested presence
        onCurrentPresenceChanged();
        Q_EMIT requestedPresenceChanged(m_requestedPresence);
    }

    onChangingPresence();
}

void GlobalPresence::onChangingPresence()
{
    bool isChangingPresence = false;
    Q_FOREACH(const Tp::AccountPtr &account, m_enabledAccounts->accounts()) {
        if (account->requestedPresence() != account->currentPresence()) {
            isChangingPresence = true;
        }
    }

    if (isChangingPresence != m_changingPresence) {
        m_changingPresence = isChangingPresence;
        Q_EMIT changingPresence(m_changingPresence);
    }
}

void GlobalPresence::onConnectionStatusChanged()
{
    Tp::ConnectionStatus connectionStatus = Tp::ConnectionStatusDisconnected;

    Q_FOREACH(const Tp::AccountPtr &account, m_enabledAccounts->accounts()) {
        switch (account->connectionStatus()) {
        case Tp::ConnectionStatusConnecting:
            //connecting is the highest state, use this always
            connectionStatus = Tp::ConnectionStatusConnecting;
            break;
        case Tp::ConnectionStatusConnected:
            //only set to connected if we're not at connecting
            if (connectionStatus == Tp::ConnectionStatusDisconnected) {
                connectionStatus = Tp::ConnectionStatusConnected;
            }
            break;
        default:
            break;
        }
    }

    if (connectionStatus != m_connectionStatus) {
        m_connectionStatus = connectionStatus;
        Q_EMIT connectionStatusChanged(m_connectionStatus);
    }
}

bool GlobalPresence::hasEnabledAccounts() const
{
    if (m_enabledAccounts->accounts().isEmpty()) {
        return false;
    }

    return true;
}

void GlobalPresence::saveCurrentPresence()
{
    qCDebug(KTP_COMMONINTERNALS) << "Saving presence with message:" << m_currentPresence.statusMessage();
    m_savedPresence = m_currentPresence;
}

void GlobalPresence::restoreSavedPresence()
{
    qCDebug(KTP_COMMONINTERNALS) << m_savedPresence.statusMessage();
    setPresence(m_savedPresence);
}

Tp::AccountSetPtr GlobalPresence::onlineAccounts() const
{
    return m_onlineAccounts;
}

}

#include "global-presence.moc"
<|endoftext|>


<commit_before>#pragma once

#include <openMVG/features/descriptor.hpp>
#include <openMVG/features/image_describer.hpp>
#include <openMVG/features/regions_factory.hpp>

extern "C" {
#include "nonFree/sift/vl/sift.h"
}

#include <cereal/cereal.hpp>

#include <iostream>
#include <numeric>

namespace openMVG {
namespace features {

struct SiftParams
{
  SiftParams(
    int first_octave = 0,
    int num_octaves = 6,
    int num_scales = 3,
    float edge_threshold = 10.0f,
    float peak_threshold = 0.04f,
    //
    std::size_t gridSize = 4,
    std::size_t maxTotalKeypoints = 1000,
    //
    bool root_sift = true
  ):
    _first_octave(first_octave),
    _num_octaves(num_octaves),
    _num_scales(num_scales),
    _edge_threshold(edge_threshold),
    _peak_threshold(peak_threshold),
    //
    _gridSize(gridSize),
    _maxTotalKeypoints(maxTotalKeypoints),
    //
    _root_sift(root_sift) {}

  template<class Archive>
  void serialize( Archive & ar )
  {
    ar(
      cereal::make_nvp("first_octave", _first_octave),
      cereal::make_nvp("num_octaves",_num_octaves),
      cereal::make_nvp("num_scales",_num_scales),
      cereal::make_nvp("edge_threshold",_edge_threshold),
      cereal::make_nvp("peak_threshold",_peak_threshold),
      //
      cereal::make_nvp("grid_size", _gridSize),
      cereal::make_nvp("max_total_keypoints", _maxTotalKeypoints),
      //
      cereal::make_nvp("root_sift",_root_sift));
  }

  // Parameters
  int _first_octave;      // Use original image, or perform an upscale if == -1
  int _num_octaves;       // Max octaves count
  int _num_scales;        // Scales per octave
  float _edge_threshold;  // Max ratio of Hessian eigenvalues
  float _peak_threshold;  // Min contrast
  //
  std::size_t _gridSize;
  std::size_t _maxTotalKeypoints;
  //
  bool _root_sift;        // see [1]

  bool setPreset(EDESCRIBER_PRESET preset)
  {
    switch(preset)
    {
    case LOW_PRESET:
    {
      _maxTotalKeypoints = 1000;
      _peak_threshold = 0.04f;
      _first_octave = 2;
      break;
    }
    case MEDIUM_PRESET:
    {
      _maxTotalKeypoints = 5000;
      _peak_threshold = 0.04f;
      _first_octave = 1;
      break;
    }
    case NORMAL_PRESET:
    {
      _maxTotalKeypoints = 10000;
      _peak_threshold = 0.04f;
      break;
    }
    case HIGH_PRESET:
    {
      _maxTotalKeypoints = 20000;
      _peak_threshold = 0.01f;
      break;
    }
    case ULTRA_PRESET:
    {
      _maxTotalKeypoints = 40000;
      _peak_threshold = 0.01f;
      _first_octave = -1;
      break;
    }
    default:
      return false;
    }
    return true;
  }

};

//convertSIFT
//////////////////////////////
template < typename TOut >
inline void convertSIFT(
  vl_sift_pix descr[128],
  Descriptor<TOut,128> & descriptor,
  bool brootSift = false
  );

template <>
inline void convertSIFT<float>(
  vl_sift_pix descr[128],
  Descriptor<float,128> &descriptor,
  bool brootSift)
{
  if(brootSift)
  {
    const float sum = std::accumulate(descr, descr + 128, 0.0f);
    for(int k = 0; k < 128; ++k)
      descriptor[k] = std::floor(512.f*sqrt(descr[k] / sum));
  }
  else
  {
    for(int k = 0; k < 128; ++k)
      descriptor[k] = std::floor(512.f*descr[k]);
  }
}

template <>
inline void convertSIFT<unsigned char>(
  vl_sift_pix descr[128],
  Descriptor<unsigned char,128> & descriptor,
  bool brootSift)
{
  if (brootSift)
  {
    // rootsift = sqrt( sift / sum(sift) );
    const float sum = std::accumulate(descr, descr+128, 0.0f);
    for (int k=0;k<128;++k)
      descriptor[k] = static_cast<unsigned char>(512.f*sqrt(descr[k]/sum));
  }
  else
  {
    for (int k=0;k<128;++k)
      descriptor[k] = static_cast<unsigned char>(512.f*descr[k]);
  }
}

/**
 * @brief Extract SIFT regions (in float or unsigned char).
 *
 * @param image
 * @param regions
 * @param params
 * @param bOrientation
 * @param mask
 * @return
 */
template < typename T >
bool extractSIFT(const image::Image<unsigned char>& image,
    std::unique_ptr<Regions> &regions,
    const SiftParams& params,
    bool bOrientation,
    const image::Image<unsigned char> * mask)
{
  const int w = image.Width(), h = image.Height();
  //Convert to float
  const image::Image<float> imageFloat(image.GetMat().cast<float>());

  // Configure VLFeat
  vl_constructor();

  VlSiftFilt *filt = vl_sift_new(w, h, params._num_octaves, params._num_scales, params._first_octave);
  if (params._edge_threshold >= 0)
    vl_sift_set_edge_thresh(filt, params._edge_threshold);
  if (params._peak_threshold >= 0)
    vl_sift_set_peak_thresh(filt, 255*params._peak_threshold/params._num_scales);

  Descriptor<vl_sift_pix, 128> vlFeatDescriptor;
  Descriptor<T, 128> descriptor;

  // Process SIFT computation
  vl_sift_process_first_octave(filt, imageFloat.data());

  typedef Scalar_Regions<SIOPointFeature,T,128> SIFT_Region_T;
  regions.reset( new SIFT_Region_T );

  // Build alias to cached data
  SIFT_Region_T * regionsCasted = dynamic_cast<SIFT_Region_T*>(regions.get());
  // reserve some memory for faster keypoint saving
  regionsCasted->Features().reserve(2000);
  regionsCasted->Descriptors().reserve(2000);

  while (true) {
    vl_sift_detect(filt);

    VlSiftKeypoint const *keys  = vl_sift_get_keypoints(filt);
    const int nkeys = vl_sift_get_nkeypoints(filt);

    // Update gradient before launching parallel extraction
    vl_sift_update_gradient(filt);

    std::cout << "TEST octave_width: " << filt->octave_width << std::endl;
    #ifdef OPENMVG_USE_OPENMP
    #pragma omp parallel for private(vlFeatDescriptor, descriptor)
    #endif
    for (int i = 0; i < nkeys; ++i) {

      // Feature masking
      if (mask)
      {
        const image::Image<unsigned char> & maskIma = *mask;
        if (maskIma(keys[i].y, keys[i].x) > 0)
          continue;
      }

      double angles [4] = {0.0, 0.0, 0.0, 0.0};
      int nangles = 1; // by default (1 upright feature)
      if (bOrientation)
      { // compute from 1 to 4 orientations
        nangles = vl_sift_calc_keypoint_orientations(filt, angles, keys+i);
      }

      for (int q=0 ; q < nangles ; ++q) {
        vl_sift_calc_keypoint_descriptor(filt, &vlFeatDescriptor[0], keys+i, angles[q]);
        const SIOPointFeature fp(keys[i].x, keys[i].y,
          keys[i].sigma, static_cast<float>(angles[q]));

        convertSIFT<T>(&vlFeatDescriptor[0], descriptor, params._root_sift);
        #ifdef OPENMVG_USE_OPENMP
        #pragma omp critical
        #endif
        {
          regionsCasted->Descriptors().push_back(descriptor);
          regionsCasted->Features().push_back(fp);
        }

      }
    }

    if (vl_sift_process_next_octave(filt))
      break; // Last octave
  }
  vl_sift_delete(filt);

  vl_destructor();

  const auto& features = regionsCasted->Features();
  const auto& descriptors = regionsCasted->Descriptors();
  {
    std::vector<std::size_t> indexSort(features.size());
    std::iota(indexSort.begin(), indexSort.end(), 0);
    std::sort(indexSort.begin(), indexSort.end(), [&](std::size_t a, std::size_t b){ return features[a].scale() > features[b].scale(); });

    std::vector<typename SIFT_Region_T::FeatureT> sortedFeatures(features.size());
    std::vector<typename SIFT_Region_T::DescriptorT> sortedDescriptors(features.size());
    for(std::size_t i: indexSort)
    {
      sortedFeatures[i] = features[indexSort[i]];
      sortedDescriptors[i] = descriptors[indexSort[i]];
    }
    regionsCasted->Features().swap(sortedFeatures);
    regionsCasted->Descriptors().swap(sortedDescriptors);
  }

  // Grid filtering of the keypoints to ensure a global repartition
  if(params._gridSize && params._maxTotalKeypoints)
  {
    // Only filter features if we have more features than the maxTotalKeypoints
    if(features.size() > params._maxTotalKeypoints)
    {
      std::cout << "Début filtrage" << std::endl;
      std::vector<typename SIFT_Region_T::FeatureT> filtered_keypoints;
      std::vector<typename SIFT_Region_T::FeatureT> rejected_keypoints;
      filtered_keypoints.reserve(std::min(features.size(), params._maxTotalKeypoints));
      rejected_keypoints.reserve(features.size());

      std::size_t sizeMat = params._gridSize*params._gridSize;
      std::size_t countFeatPerCell[sizeMat];
      for (int Indice = 0; Indice < sizeMat; Indice++) {
    	  countFeatPerCell[Indice] = 0;
      }
      const std::size_t keypointsPerCell = params._maxTotalKeypoints / sizeMat;
      const double regionWidth = w / double(params._gridSize);
      const double regionHeight = h / double(params._gridSize);

      //std::cout << "Grid filtering -- keypointsPerCell: " << keypointsPerCell
      //          << ", regionWidth: " << regionWidth
      //          << ", regionHeight: " << regionHeight << std::endl;

      for(auto& keypoint: features)
      {
        const std::size_t cellX = std::min(std::size_t(keypoint.x() / regionWidth), params._gridSize);
        const std::size_t cellY = std::min(std::size_t(keypoint.y() / regionHeight), params._gridSize);
        //std::cout << "- keypoint.pt.x: " << keypoint.pt.x << ", keypoint.pt.y: " << keypoint.pt.y << std::endl;
        //std::cout << "- cellX: " << cellX << ", cellY: " << cellY << std::endl;
        //std::cout << "- countFeatPerCell: " << countFeatPerCell << std::endl;
        //std::cout << "- gridSize: " << _params.gridSize << std::endl;

        const std::size_t count = countFeatPerCell[cellX*params._gridSize + cellY];
        countFeatPerCell[cellX*params._gridSize + cellY] = count + 1;
        if(count < keypointsPerCell)
          filtered_keypoints.push_back(keypoint);
        else
          rejected_keypoints.push_back(keypoint);
      }
      // If we don't have enough features (less than maxTotalKeypoints) after the grid filtering (empty regions in the grid for example).
      // We add the best other ones, without repartition constraint.
      if( filtered_keypoints.size() < params._maxTotalKeypoints )
      {
        const std::size_t remainingElements = std::min(rejected_keypoints.size(), params._maxTotalKeypoints - filtered_keypoints.size());
        std::cout << "Grid filtering -- Copy remaining points: " << remainingElements << std::endl;
        filtered_keypoints.insert(filtered_keypoints.end(), rejected_keypoints.begin(), rejected_keypoints.begin() + remainingElements);
      }

      regionsCasted->Features().swap(filtered_keypoints);

      for (int Indice = 0; Indice < sizeMat; Indice++) {
    	  countFeatPerCell[Indice] = 0;
      }

    }
  }

  return true;
}

} //namespace openMVG
} //namespace features

<commit_msg>[sift] fix merge, call vl_constructor only once<commit_after>#pragma once

#include <openMVG/features/descriptor.hpp>
#include <openMVG/features/image_describer.hpp>
#include <openMVG/features/regions_factory.hpp>

extern "C" {
#include "nonFree/sift/vl/sift.h"
}

#include <cereal/cereal.hpp>

#include <iostream>
#include <numeric>

namespace openMVG {
namespace features {

struct SiftParams
{
  SiftParams(
    int first_octave = 0,
    int num_octaves = 6,
    int num_scales = 3,
    float edge_threshold = 10.0f,
    float peak_threshold = 0.04f,
    //
    std::size_t gridSize = 4,
    std::size_t maxTotalKeypoints = 1000,
    //
    bool root_sift = true
  ):
    _first_octave(first_octave),
    _num_octaves(num_octaves),
    _num_scales(num_scales),
    _edge_threshold(edge_threshold),
    _peak_threshold(peak_threshold),
    //
    _gridSize(gridSize),
    _maxTotalKeypoints(maxTotalKeypoints),
    //
    _root_sift(root_sift) {}

  template<class Archive>
  void serialize( Archive & ar )
  {
    ar(
      cereal::make_nvp("first_octave", _first_octave),
      cereal::make_nvp("num_octaves",_num_octaves),
      cereal::make_nvp("num_scales",_num_scales),
      cereal::make_nvp("edge_threshold",_edge_threshold),
      cereal::make_nvp("peak_threshold",_peak_threshold),
      //
      cereal::make_nvp("grid_size", _gridSize),
      cereal::make_nvp("max_total_keypoints", _maxTotalKeypoints),
      //
      cereal::make_nvp("root_sift",_root_sift));
  }

  // Parameters
  int _first_octave;      // Use original image, or perform an upscale if == -1
  int _num_octaves;       // Max octaves count
  int _num_scales;        // Scales per octave
  float _edge_threshold;  // Max ratio of Hessian eigenvalues
  float _peak_threshold;  // Min contrast
  //
  std::size_t _gridSize;
  std::size_t _maxTotalKeypoints;
  //
  bool _root_sift;        // see [1]

  bool setPreset(EDESCRIBER_PRESET preset)
  {
    switch(preset)
    {
    case LOW_PRESET:
    {
      _maxTotalKeypoints = 1000;
      _peak_threshold = 0.04f;
      _first_octave = 2;
      break;
    }
    case MEDIUM_PRESET:
    {
      _maxTotalKeypoints = 5000;
      _peak_threshold = 0.04f;
      _first_octave = 1;
      break;
    }
    case NORMAL_PRESET:
    {
      _maxTotalKeypoints = 10000;
      _peak_threshold = 0.04f;
      break;
    }
    case HIGH_PRESET:
    {
      _maxTotalKeypoints = 20000;
      _peak_threshold = 0.01f;
      break;
    }
    case ULTRA_PRESET:
    {
      _maxTotalKeypoints = 40000;
      _peak_threshold = 0.01f;
      _first_octave = -1;
      break;
    }
    default:
      return false;
    }
    return true;
  }

};

//convertSIFT
//////////////////////////////
template < typename TOut >
inline void convertSIFT(
  vl_sift_pix descr[128],
  Descriptor<TOut,128> & descriptor,
  bool brootSift = false
  );

template <>
inline void convertSIFT<float>(
  vl_sift_pix descr[128],
  Descriptor<float,128> &descriptor,
  bool brootSift)
{
  if(brootSift)
  {
    const float sum = std::accumulate(descr, descr + 128, 0.0f);
    for(int k = 0; k < 128; ++k)
      descriptor[k] = std::floor(512.f*sqrt(descr[k] / sum));
  }
  else
  {
    for(int k = 0; k < 128; ++k)
      descriptor[k] = std::floor(512.f*descr[k]);
  }
}

template <>
inline void convertSIFT<unsigned char>(
  vl_sift_pix descr[128],
  Descriptor<unsigned char,128> & descriptor,
  bool brootSift)
{
  if (brootSift)
  {
    // rootsift = sqrt( sift / sum(sift) );
    const float sum = std::accumulate(descr, descr+128, 0.0f);
    for (int k=0;k<128;++k)
      descriptor[k] = static_cast<unsigned char>(512.f*sqrt(descr[k]/sum));
  }
  else
  {
    for (int k=0;k<128;++k)
      descriptor[k] = static_cast<unsigned char>(512.f*descr[k]);
  }
}

/**
 * @brief Extract SIFT regions (in float or unsigned char).
 *
 * @param image
 * @param regions
 * @param params
 * @param bOrientation
 * @param mask
 * @return
 */
template < typename T >
bool extractSIFT(const image::Image<unsigned char>& image,
    std::unique_ptr<Regions> &regions,
    const SiftParams& params,
    bool bOrientation,
    const image::Image<unsigned char> * mask)
{
  const int w = image.Width(), h = image.Height();
  //Convert to float
  const image::Image<float> imageFloat(image.GetMat().cast<float>());

  VlSiftFilt *filt = vl_sift_new(w, h, params._num_octaves, params._num_scales, params._first_octave);
  if (params._edge_threshold >= 0)
    vl_sift_set_edge_thresh(filt, params._edge_threshold);
  if (params._peak_threshold >= 0)
    vl_sift_set_peak_thresh(filt, 255*params._peak_threshold/params._num_scales);

  Descriptor<vl_sift_pix, 128> vlFeatDescriptor;
  Descriptor<T, 128> descriptor;

  // Process SIFT computation
  vl_sift_process_first_octave(filt, imageFloat.data());

  typedef Scalar_Regions<SIOPointFeature,T,128> SIFT_Region_T;
  regions.reset( new SIFT_Region_T );

  // Build alias to cached data
  SIFT_Region_T * regionsCasted = dynamic_cast<SIFT_Region_T*>(regions.get());
  // reserve some memory for faster keypoint saving
  regionsCasted->Features().reserve(2000);
  regionsCasted->Descriptors().reserve(2000);

  while (true) {
    vl_sift_detect(filt);

    VlSiftKeypoint const *keys  = vl_sift_get_keypoints(filt);
    const int nkeys = vl_sift_get_nkeypoints(filt);

    // Update gradient before launching parallel extraction
    vl_sift_update_gradient(filt);

    std::cout << "TEST octave_width: " << filt->octave_width << std::endl;
    #ifdef OPENMVG_USE_OPENMP
    #pragma omp parallel for private(vlFeatDescriptor, descriptor)
    #endif
    for (int i = 0; i < nkeys; ++i) {

      // Feature masking
      if (mask)
      {
        const image::Image<unsigned char> & maskIma = *mask;
        if (maskIma(keys[i].y, keys[i].x) > 0)
          continue;
      }

      double angles [4] = {0.0, 0.0, 0.0, 0.0};
      int nangles = 1; // by default (1 upright feature)
      if (bOrientation)
      { // compute from 1 to 4 orientations
        nangles = vl_sift_calc_keypoint_orientations(filt, angles, keys+i);
      }

      for (int q=0 ; q < nangles ; ++q) {
        vl_sift_calc_keypoint_descriptor(filt, &vlFeatDescriptor[0], keys+i, angles[q]);
        const SIOPointFeature fp(keys[i].x, keys[i].y,
          keys[i].sigma, static_cast<float>(angles[q]));

        convertSIFT<T>(&vlFeatDescriptor[0], descriptor, params._root_sift);
        #ifdef OPENMVG_USE_OPENMP
        #pragma omp critical
        #endif
        {
          regionsCasted->Descriptors().push_back(descriptor);
          regionsCasted->Features().push_back(fp);
        }

      }
    }

    if (vl_sift_process_next_octave(filt))
      break; // Last octave
  }
  vl_sift_delete(filt);

  const auto& features = regionsCasted->Features();
  const auto& descriptors = regionsCasted->Descriptors();
  {
    std::vector<std::size_t> indexSort(features.size());
    std::iota(indexSort.begin(), indexSort.end(), 0);
    std::sort(indexSort.begin(), indexSort.end(), [&](std::size_t a, std::size_t b){ return features[a].scale() > features[b].scale(); });

    std::vector<typename SIFT_Region_T::FeatureT> sortedFeatures(features.size());
    std::vector<typename SIFT_Region_T::DescriptorT> sortedDescriptors(features.size());
    for(std::size_t i: indexSort)
    {
      sortedFeatures[i] = features[indexSort[i]];
      sortedDescriptors[i] = descriptors[indexSort[i]];
    }
    regionsCasted->Features().swap(sortedFeatures);
    regionsCasted->Descriptors().swap(sortedDescriptors);
  }

  // Grid filtering of the keypoints to ensure a global repartition
  if(params._gridSize && params._maxTotalKeypoints)
  {
    // Only filter features if we have more features than the maxTotalKeypoints
    if(features.size() > params._maxTotalKeypoints)
    {
      std::cout << "Début filtrage" << std::endl;
      std::vector<typename SIFT_Region_T::FeatureT> filtered_keypoints;
      std::vector<typename SIFT_Region_T::FeatureT> rejected_keypoints;
      filtered_keypoints.reserve(std::min(features.size(), params._maxTotalKeypoints));
      rejected_keypoints.reserve(features.size());

      std::size_t sizeMat = params._gridSize*params._gridSize;
      std::size_t countFeatPerCell[sizeMat];
      for (int Indice = 0; Indice < sizeMat; Indice++) {
    	  countFeatPerCell[Indice] = 0;
      }
      const std::size_t keypointsPerCell = params._maxTotalKeypoints / sizeMat;
      const double regionWidth = w / double(params._gridSize);
      const double regionHeight = h / double(params._gridSize);

      //std::cout << "Grid filtering -- keypointsPerCell: " << keypointsPerCell
      //          << ", regionWidth: " << regionWidth
      //          << ", regionHeight: " << regionHeight << std::endl;

      for(auto& keypoint: features)
      {
        const std::size_t cellX = std::min(std::size_t(keypoint.x() / regionWidth), params._gridSize);
        const std::size_t cellY = std::min(std::size_t(keypoint.y() / regionHeight), params._gridSize);
        //std::cout << "- keypoint.pt.x: " << keypoint.pt.x << ", keypoint.pt.y: " << keypoint.pt.y << std::endl;
        //std::cout << "- cellX: " << cellX << ", cellY: " << cellY << std::endl;
        //std::cout << "- countFeatPerCell: " << countFeatPerCell << std::endl;
        //std::cout << "- gridSize: " << _params.gridSize << std::endl;

        const std::size_t count = countFeatPerCell[cellX*params._gridSize + cellY];
        countFeatPerCell[cellX*params._gridSize + cellY] = count + 1;
        if(count < keypointsPerCell)
          filtered_keypoints.push_back(keypoint);
        else
          rejected_keypoints.push_back(keypoint);
      }
      // If we don't have enough features (less than maxTotalKeypoints) after the grid filtering (empty regions in the grid for example).
      // We add the best other ones, without repartition constraint.
      if( filtered_keypoints.size() < params._maxTotalKeypoints )
      {
        const std::size_t remainingElements = std::min(rejected_keypoints.size(), params._maxTotalKeypoints - filtered_keypoints.size());
        std::cout << "Grid filtering -- Copy remaining points: " << remainingElements << std::endl;
        filtered_keypoints.insert(filtered_keypoints.end(), rejected_keypoints.begin(), rejected_keypoints.begin() + remainingElements);
      }

      regionsCasted->Features().swap(filtered_keypoints);

      for (int Indice = 0; Indice < sizeMat; Indice++) {
    	  countFeatPerCell[Indice] = 0;
      }

    }
  }

  return true;
}

} //namespace openMVG
} //namespace features

<|endoftext|>


<commit_before>//
//  yas_audio_route_node.cpp
//  Copyright (c) 2015 Yuki Yasoshima.
//

#include "yas_audio_route_node.h"
#include "yas_stl_utils.h"

using namespace yas;

#pragma mark - node_core

namespace yas
{
    class audio_route_node_core : public audio_node_core
    {
       public:
        audio_route_set routes;
    };
}

#pragma mark - impl

class audio_route_node::impl
{
   public:
    audio_route_set routes;

    void erase_route_if_either_matched(const audio_route &route)
    {
        erase_route_if([&route](const audio_route &route_of_set) {
            return route_of_set.source == route.source || route_of_set.destination == route.destination;
        });
    }

    void erase_route_if(std::function<bool(const audio_route &)> pred)
    {
        auto it = routes.begin();
        while (it != routes.end()) {
            auto &route_of_set = *it;

            if (pred(route_of_set)) {
                it = routes.erase(it);
            } else {
                ++it;
            }
        }
    }
};

#pragma mark - main

audio_route_node_sptr audio_route_node::create()
{
    return std::shared_ptr<audio_route_node>(new audio_route_node());
}

audio_route_node::audio_route_node() : audio_node(), _impl(std::make_unique<impl>())
{
}

UInt32 audio_route_node::input_bus_count() const
{
    return std::numeric_limits<UInt32>::max();
}

UInt32 audio_route_node::output_bus_count() const
{
    return std::numeric_limits<UInt32>::max();
}

const std::set<audio_route> &audio_route_node::routes() const
{
    return _impl->routes;
}

void audio_route_node::add_route(const audio_route &route)
{
    _impl->erase_route_if_either_matched(route);
    _impl->routes.insert(route);
    update_node_core();
}

void audio_route_node::add_route(audio_route &&route)
{
    _impl->erase_route_if_either_matched(route);
    _impl->routes.insert(std::move(route));
    update_node_core();
}

void audio_route_node::remove_route(const audio_route &route)
{
    _impl->routes.erase(route);
    update_node_core();
}

void audio_route_node::remove_route_for_source(const audio_route::point &src_pt)
{
    _impl->erase_route_if([&src_pt](const audio_route &route_of_set) { return route_of_set.source == src_pt; });
    update_node_core();
}

void audio_route_node::remove_route_for_destination(const audio_route::point &dst_pt)
{
    _impl->erase_route_if([&dst_pt](const audio_route &route_of_set) { return route_of_set.destination == dst_pt; });
    update_node_core();
}

void audio_route_node::set_routes(const std::set<audio_route> &routes)
{
    _impl->routes.clear();
    _impl->routes = routes;
    update_node_core();
}

void audio_route_node::set_routes(std::set<audio_route> &&routes)
{
    _impl->routes.clear();
    _impl->routes = std::move(routes);
    update_node_core();
}

void audio_route_node::clear_routes()
{
    _impl->routes.clear();
    update_node_core();
}

audio_node_core_sptr audio_route_node::make_node_core()
{
    return audio_node_core_sptr(new audio_route_node_core());
}

void audio_route_node::prepare_node_core(const audio_node_core_sptr &node_core)
{
    super_class::prepare_node_core(node_core);

    if (audio_route_node_core *route_node_core = dynamic_cast<audio_route_node_core *>(node_core.get())) {
        route_node_core->routes = _impl->routes;
    } else {
        throw std::runtime_error(std::string(__PRETTY_FUNCTION__) + " : failed dynamic cast to audio_route_node_core.");
    }
}

void audio_route_node::render(audio_pcm_buffer &dst_buffer, const UInt32 dst_bus_idx, const audio_time &when)
{
    super_class::render(dst_buffer, dst_bus_idx, when);

    if (auto core = node_core()) {
        audio_route_node_core *route_node_core = dynamic_cast<audio_route_node_core *>(core.get());
        auto &routes = route_node_core->routes;
        auto output_connection = core->output_connection(dst_bus_idx);
        auto input_connections = core->input_connections();
        const UInt32 dst_ch_count = dst_buffer.format().channel_count();

        for (const auto &pair : input_connections) {
            if (const auto &input_connection = pair.second) {
                if (auto node = input_connection->source_node()) {
                    const auto &src_format = input_connection->format();
                    const auto &src_bus_idx = pair.first;
                    const UInt32 src_ch_count = src_format.channel_count();
                    if (const auto result =
                            channel_map_from_routes(routes, src_bus_idx, src_ch_count, dst_bus_idx, dst_ch_count)) {
                        yas::audio_pcm_buffer src_buffer(src_format, dst_buffer, result.value());
                        node->render(src_buffer, src_bus_idx, when);
                    }
                }
            }
        }
    }
}
<commit_msg>update audio_route_node<commit_after>//
//  yas_audio_route_node.cpp
//  Copyright (c) 2015 Yuki Yasoshima.
//

#include "yas_audio_route_node.h"
#include "yas_stl_utils.h"

using namespace yas;

#pragma mark - node_core

namespace yas
{
    class audio_route_node_core : public audio_node_core
    {
       public:
        audio_route_set routes;
    };
}

#pragma mark - impl

class audio_route_node::impl
{
   public:
    audio_route_set routes;

    void erase_route_if_either_matched(const audio_route &route)
    {
        erase_route_if([&route](const audio_route &route_of_set) {
            return route_of_set.source == route.source || route_of_set.destination == route.destination;
        });
    }

    void erase_route_if(std::function<bool(const audio_route &)> pred)
    {
        erase_if(routes, pred);
    }
};

#pragma mark - main

audio_route_node_sptr audio_route_node::create()
{
    return std::shared_ptr<audio_route_node>(new audio_route_node());
}

audio_route_node::audio_route_node() : audio_node(), _impl(std::make_unique<impl>())
{
}

UInt32 audio_route_node::input_bus_count() const
{
    return std::numeric_limits<UInt32>::max();
}

UInt32 audio_route_node::output_bus_count() const
{
    return std::numeric_limits<UInt32>::max();
}

const std::set<audio_route> &audio_route_node::routes() const
{
    return _impl->routes;
}

void audio_route_node::add_route(const audio_route &route)
{
    _impl->erase_route_if_either_matched(route);
    _impl->routes.insert(route);
    update_node_core();
}

void audio_route_node::add_route(audio_route &&route)
{
    _impl->erase_route_if_either_matched(route);
    _impl->routes.insert(std::move(route));
    update_node_core();
}

void audio_route_node::remove_route(const audio_route &route)
{
    _impl->routes.erase(route);
    update_node_core();
}

void audio_route_node::remove_route_for_source(const audio_route::point &src_pt)
{
    _impl->erase_route_if([&src_pt](const audio_route &route_of_set) { return route_of_set.source == src_pt; });
    update_node_core();
}

void audio_route_node::remove_route_for_destination(const audio_route::point &dst_pt)
{
    _impl->erase_route_if([&dst_pt](const audio_route &route_of_set) { return route_of_set.destination == dst_pt; });
    update_node_core();
}

void audio_route_node::set_routes(const std::set<audio_route> &routes)
{
    _impl->routes.clear();
    _impl->routes = routes;
    update_node_core();
}

void audio_route_node::set_routes(std::set<audio_route> &&routes)
{
    _impl->routes.clear();
    _impl->routes = std::move(routes);
    update_node_core();
}

void audio_route_node::clear_routes()
{
    _impl->routes.clear();
    update_node_core();
}

audio_node_core_sptr audio_route_node::make_node_core()
{
    return audio_node_core_sptr(new audio_route_node_core());
}

void audio_route_node::prepare_node_core(const audio_node_core_sptr &node_core)
{
    super_class::prepare_node_core(node_core);

    if (audio_route_node_core *route_node_core = dynamic_cast<audio_route_node_core *>(node_core.get())) {
        route_node_core->routes = _impl->routes;
    } else {
        throw std::runtime_error(std::string(__PRETTY_FUNCTION__) + " : failed dynamic cast to audio_route_node_core.");
    }
}

void audio_route_node::render(audio_pcm_buffer &dst_buffer, const UInt32 dst_bus_idx, const audio_time &when)
{
    super_class::render(dst_buffer, dst_bus_idx, when);

    if (auto core = node_core()) {
        audio_route_node_core *route_node_core = dynamic_cast<audio_route_node_core *>(core.get());
        auto &routes = route_node_core->routes;
        auto output_connection = core->output_connection(dst_bus_idx);
        auto input_connections = core->input_connections();
        const UInt32 dst_ch_count = dst_buffer.format().channel_count();

        for (const auto &pair : input_connections) {
            if (const auto &input_connection = pair.second) {
                if (auto node = input_connection->source_node()) {
                    const auto &src_format = input_connection->format();
                    const auto &src_bus_idx = pair.first;
                    const UInt32 src_ch_count = src_format.channel_count();
                    if (const auto result =
                            channel_map_from_routes(routes, src_bus_idx, src_ch_count, dst_bus_idx, dst_ch_count)) {
                        yas::audio_pcm_buffer src_buffer(src_format, dst_buffer, result.value());
                        node->render(src_buffer, src_bus_idx, when);
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/* Author: DobroAlex
*
* Created on 12 июня 2017 г., 21:10
*/
/*Задание 1 .
Создать иерархию типов - корабль, пассажирский транспорт и пассажирский корабль.
*  Классы должны конструкторы, включая конструктор копирования, виртуальные деструкторы,
*  перегруженные функции вывода в поток и ввода в поток. */
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
using namespace std;
class Ship {
private:
	int draught;//водоизмещение
public:
	Ship() { // конструктор по умолчанию
		draught = 0;
	}
	Ship(int d) { // конструктор с параметром
		draught = d;
	}
	Ship(const Ship&s) { // конструктор копирования
		draught = s.draught;
	}
	virtual  ~Ship() { // виртуальный деструктор, может быть переопределен наследниками
		cout << "Bye, Ship" << endl;
		draught = 0;
	}
	friend ostream& operator << (ostream & out, const Ship& s);
	friend istream& operator >> (istream & out, Ship& s);
};
ostream& operator << (ostream & out, const Ship& s) {
	out << "Draught is " << s.draught << endl;
	return out;
}
istream& operator >> (istream & out, Ship& s) {
	cin >> s.draught;
	return out;
}
class Transp {
private:
	int pass; //число пассажиров
public:
	Transp() {  // конструктор по умолчанию
		pass = 0;
	}
	Transp(int p) {// конструктор с параметром
		pass = p;
	}
	Transp(const Transp & t) {// конструктор копирования
		pass = t.pass;
	}
	virtual  ~Transp() {// виртуальный деструктор, может быть переопределен наследниками
		cout << "bye,transp" << endl;
		pass = 0;
	}
	friend ostream& operator << (ostream & out, const Transp& s);
	friend istream& operator >> (istream & out, Transp& s);
};
ostream& operator << (ostream & out, const Transp& s) {
	out << "Num of passengers : " << s.pass << endl;
	return out;
}
istream& operator >> (istream & out, Transp& s) {
	out >> s.pass;
	return out;
}
class PasShip : virtual   public Ship, virtual     public Transp { // виртуальное наследование гарантирует отсутствие повторяющихся полей (ТУТ  НЕТ НЕОБХОДИМОСТИ ИСПОЛЬЗОВАТЬ)
	int num; //номер корабля
public:
	PasShip() {
		num = 0;
	}
	PasShip(int n, int d, int p) : Ship(d), Transp(p) { //передача параметров конструкторам родителй с явным вызовом
		num = n;
	}
	PasShip(const PasShip &p, const Ship & s, const Transp& t) : Ship(s), Transp(t) {  //передача параметров конструкторам копирования  родителй с явным вызовом
		num = p.num;
	}
	~PasShip() { //деструктор. Не виртуален, т.к не предпологается переопределение
		cout << "Bye, pasship\n";
		num = 0;
	}
	friend ostream& operator << (ostream & out, const PasShip& s);
	friend istream& operator >> (istream & out, PasShip& s);
};
ostream& operator << (ostream & out, const PasShip& s) {
	cout << "Num" << s.num << endl;
	return out;
}
istream& operator >> (istream & out, PasShip& s) {
	out >> s.num;
	return out;
}
int main(int argc, char** argv) {
	Ship A(100);
	cout << A;
	Transp B(200);
	cout << B;
	PasShip C(300, 400, 500);
	return 0;
}<commit_msg>Update Lab9Task1.cpp<commit_after>/* Author: DobroAlex
* Created on 12 июня 2017 г., 21:10
Создать иерархию типов - корабль, пассажирский транспорт и пассажирский корабль.
*  Классы должны конструкторы, включая конструктор копирования, виртуальные деструкторы,
*  перегруженные функции вывода в поток и ввода в поток. */
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
using namespace std;
class Ship {
private:
	int draught;//водоизмещение
public:
	Ship() { // конструктор по умолчанию
		draught = 0;
	}
	Ship(int d) { // конструктор с параметром
		draught = d;
	}
	Ship(const Ship&s) { // конструктор копирования
		draught = s.draught;
	}
	virtual  ~Ship() { // виртуальный деструктор, может быть переопределен наследниками
		cout << "Bye, Ship" << endl;
		draught = 0;
	}
	friend ostream& operator << (ostream & out, const Ship& s);
	friend istream& operator >> (istream & out, Ship& s);
};
ostream& operator << (ostream & out, const Ship& s) {
	out << "Draught is " << s.draught << endl;
	return out;
}
istream& operator >> (istream & out, Ship& s) {
	cin >> s.draught;
	return out;
}
class Transp {
private:
	int pass; //число пассажиров
public:
	Transp() {  // конструктор по умолчанию
		pass = 0;
	}
	Transp(int p) {// конструктор с параметром
		pass = p;
	}
	Transp(const Transp & t) {// конструктор копирования
		pass = t.pass;
	}
	virtual  ~Transp() {// виртуальный деструктор, может быть переопределен наследниками
		cout << "bye,transp" << endl;
		pass = 0;
	}
	friend ostream& operator << (ostream & out, const Transp& s);
	friend istream& operator >> (istream & out, Transp& s);
};
ostream& operator << (ostream & out, const Transp& s) {
	out << "Num of passengers : " << s.pass << endl;
	return out;
}
istream& operator >> (istream & out, Transp& s) {
	out >> s.pass;
	return out;
}
class PasShip : virtual   public Ship, virtual     public Transp { // виртуальное наследование гарантирует отсутствие повторяющихся полей (ТУТ  НЕТ НЕОБХОДИМОСТИ ИСПОЛЬЗОВАТЬ)
	int num; //номер корабля
public:
	PasShip() {
		num = 0;
	}
	PasShip(int n, int d, int p) : Ship(d), Transp(p) { //передача параметров конструкторам родителй с явным вызовом
		num = n;
	}
	PasShip(const PasShip &p, const Ship & s, const Transp& t) : Ship(s), Transp(t) {  //передача параметров конструкторам копирования  родителй с явным вызовом
		num = p.num;
	}
	~PasShip() { //деструктор. Не виртуален, т.к не предпологается переопределение
		cout << "Bye, pasship\n";
		num = 0;
	}
	friend ostream& operator << (ostream & out, const PasShip& s);
	friend istream& operator >> (istream & out, PasShip& s);
};
ostream& operator << (ostream & out, const PasShip& s) {
	cout << "Num" << s.num << endl;
	return out;
}
istream& operator >> (istream & out, PasShip& s) {
	out >> s.num;
	return out;
}
int main(int argc, char** argv) {
	Ship A(100);
	cout << A;
	Transp B(200);
	cout << B;
	PasShip C(300, 400, 500);
	return 0;
}
<|endoftext|>


<commit_before><commit_msg>include the IP we actually connected to when reporting the IPs of the tracker<commit_after><|endoftext|>


<commit_before><commit_msg>Write the code to hack bridge tree paths into simple cycles<commit_after><|endoftext|>


<commit_before><commit_msg>interpreter - cast()<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/base/video_frame.h"

namespace media {

// static
void VideoFrame::CreateFrame(VideoFrame::Format format,
                             size_t width,
                             size_t height,
                             base::TimeDelta timestamp,
                             base::TimeDelta duration,
                             scoped_refptr<VideoFrame>* frame_out) {
  DCHECK(width > 0 && height > 0);
  DCHECK(width * height < 100000000);
  DCHECK(frame_out);
  bool alloc_worked = false;
  scoped_refptr<VideoFrame> frame =
      new VideoFrame(VideoFrame::TYPE_SYSTEM_MEMORY, format, width, height);
  if (frame) {
    frame->SetTimestamp(timestamp);
    frame->SetDuration(duration);
    switch (format) {
      case VideoFrame::RGB555:
      case VideoFrame::RGB565:
        alloc_worked = frame->AllocateRGB(2u);
        break;
      case VideoFrame::RGB24:
        alloc_worked = frame->AllocateRGB(3u);
        break;
      case VideoFrame::RGB32:
      case VideoFrame::RGBA:
        alloc_worked = frame->AllocateRGB(4u);
        break;
      case VideoFrame::YV12:
      case VideoFrame::YV16:
        alloc_worked = frame->AllocateYUV();
        break;
      default:
        NOTREACHED();
        alloc_worked = false;
        break;
    }
  }
  *frame_out = alloc_worked ? frame : NULL;
}

// static
void VideoFrame::CreateEmptyFrame(scoped_refptr<VideoFrame>* frame_out) {
  *frame_out = new VideoFrame(VideoFrame::TYPE_SYSTEM_MEMORY,
                              VideoFrame::EMPTY, 0, 0);
}

// static
void VideoFrame::CreateBlackFrame(int width, int height,
                                  scoped_refptr<VideoFrame>* frame_out) {
  DCHECK_GT(width, 0);
  DCHECK_GT(height, 0);

  // Create our frame.
  scoped_refptr<VideoFrame> frame;
  const base::TimeDelta kZero;
  VideoFrame::CreateFrame(VideoFrame::YV12, width, height, kZero, kZero,
                          &frame);
  DCHECK(frame);

  // Now set the data to YUV(0,128,128).
  const uint8 kBlackY = 0x00;
  const uint8 kBlackUV = 0x80;

  // Fill the Y plane.
  uint8* y_plane = frame->data(VideoFrame::kYPlane);
  for (size_t i = 0; i < frame->height_; ++i) {
    memset(y_plane, kBlackY, frame->width_);
    y_plane += frame->stride(VideoFrame::kYPlane);
  }

  // Fill the U and V planes.
  uint8* u_plane = frame->data(VideoFrame::kUPlane);
  uint8* v_plane = frame->data(VideoFrame::kVPlane);
  for (size_t i = 0; i < (frame->height_ / 2); ++i) {
    memset(u_plane, kBlackUV, frame->width_ / 2);
    memset(v_plane, kBlackUV, frame->width_ / 2);
    u_plane += frame->stride(VideoFrame::kUPlane);
    v_plane += frame->stride(VideoFrame::kVPlane);
  }

  // Success!
  *frame_out = frame;
}

// static
void VideoFrame::CreatePrivateFrame(VideoFrame::BufferType type,
                                    VideoFrame::Format format,
                                    size_t width,
                                    size_t height,
                                    base::TimeDelta timestamp,
                                    base::TimeDelta duration,
                                    void* private_buffer,
                                    scoped_refptr<VideoFrame>* frame_out) {
  DCHECK(frame_out);
  scoped_refptr<VideoFrame> frame =
      new VideoFrame(type, format, width, height);
  if (frame) {
    frame->SetTimestamp(timestamp);
    frame->SetDuration(duration);
    frame->private_buffer_ = private_buffer;
  }
  *frame_out = frame;
}

static inline size_t RoundUp(size_t value, size_t alignment) {
  // Check that |alignment| is a power of 2.
  DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
  return ((value + (alignment - 1)) & ~(alignment-1));
}

bool VideoFrame::AllocateRGB(size_t bytes_per_pixel) {
  // Round up to align at a 64-bit (8 byte) boundary for each row.  This
  // is sufficient for MMX reads (movq).
  size_t bytes_per_row = RoundUp(width_ * bytes_per_pixel, 8);
  planes_ = VideoFrame::kNumRGBPlanes;
  strides_[VideoFrame::kRGBPlane] = bytes_per_row;
  data_[VideoFrame::kRGBPlane] = new uint8[bytes_per_row * height_];
  DCHECK(data_[VideoFrame::kRGBPlane]);
  DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7));
  COMPILE_ASSERT(0 == VideoFrame::kRGBPlane, RGB_data_must_be_index_0);
  return (NULL != data_[VideoFrame::kRGBPlane]);
}

bool VideoFrame::AllocateYUV() {
  DCHECK(format_ == VideoFrame::YV12 ||
         format_ == VideoFrame::YV16);
  // Align Y rows at 32-bit (4 byte) boundaries.  The stride for both YV12 and
  // YV16 is 1/2 of the stride of Y.  For YV12, every row of bytes for U and V
  // applies to two rows of Y (one byte of UV for 4 bytes of Y), so in the
  // case of YV12 the strides are identical for the same width surface, but the
  // number of bytes allocated for YV12 is 1/2 the amount for U & V as YV16.
  // We also round the height of the surface allocated to be an even number
  // to avoid any potential of faulting by code that attempts to access the Y
  // values of the final row, but assumes that the last row of U & V applies to
  // a full two rows of Y.
  size_t alloc_height = RoundUp(height_, 2);
  size_t y_bytes_per_row = RoundUp(width_, 4);
  size_t uv_stride = RoundUp(y_bytes_per_row / 2, 4);
  size_t y_bytes = alloc_height * y_bytes_per_row;
  size_t uv_bytes = alloc_height * uv_stride;
  if (format_ == VideoFrame::YV12) {
    uv_bytes /= 2;
  }
  uint8* data = new uint8[y_bytes + (uv_bytes * 2)];
  if (data) {
    planes_ = VideoFrame::kNumYUVPlanes;
    COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0);
    data_[VideoFrame::kYPlane] = data;
    data_[VideoFrame::kUPlane] = data + y_bytes;
    data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes;
    strides_[VideoFrame::kYPlane] = y_bytes_per_row;
    strides_[VideoFrame::kUPlane] = uv_stride;
    strides_[VideoFrame::kVPlane] = uv_stride;
    return true;
  }
  NOTREACHED();
  return false;
}

VideoFrame::VideoFrame(VideoFrame::BufferType type,
                       VideoFrame::Format format,
                       size_t width,
                       size_t height) {
  type_ = type;
  format_ = format;
  width_ = width;
  height_ = height;
  planes_ = 0;
  memset(&strides_, 0, sizeof(strides_));
  memset(&data_, 0, sizeof(data_));
  private_buffer_ = NULL;
}

VideoFrame::~VideoFrame() {
  // In multi-plane allocations, only a single block of memory is allocated
  // on the heap, and other |data| pointers point inside the same, single block
  // so just delete index 0.
  delete[] data_[0];
}

bool VideoFrame::IsEndOfStream() const {
  return format_ == VideoFrame::EMPTY;
}

}  // namespace media
<commit_msg>pad yuv additional 15 bytes to allow 16 pixels at a time to be processed without going off end of buffer. BUG=43970 TEST=play http://fbarchard0-w.ad.corp.google.com/mediatests/Etherworks-WebMadeMovies3BuildingABetterInternet799.ogg with scaling down (CTRL -).  Should not crash.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/base/video_frame.h"

namespace media {

// static
void VideoFrame::CreateFrame(VideoFrame::Format format,
                             size_t width,
                             size_t height,
                             base::TimeDelta timestamp,
                             base::TimeDelta duration,
                             scoped_refptr<VideoFrame>* frame_out) {
  DCHECK(width > 0 && height > 0);
  DCHECK(width * height < 100000000);
  DCHECK(frame_out);
  bool alloc_worked = false;
  scoped_refptr<VideoFrame> frame =
      new VideoFrame(VideoFrame::TYPE_SYSTEM_MEMORY, format, width, height);
  if (frame) {
    frame->SetTimestamp(timestamp);
    frame->SetDuration(duration);
    switch (format) {
      case VideoFrame::RGB555:
      case VideoFrame::RGB565:
        alloc_worked = frame->AllocateRGB(2u);
        break;
      case VideoFrame::RGB24:
        alloc_worked = frame->AllocateRGB(3u);
        break;
      case VideoFrame::RGB32:
      case VideoFrame::RGBA:
        alloc_worked = frame->AllocateRGB(4u);
        break;
      case VideoFrame::YV12:
      case VideoFrame::YV16:
        alloc_worked = frame->AllocateYUV();
        break;
      default:
        NOTREACHED();
        alloc_worked = false;
        break;
    }
  }
  *frame_out = alloc_worked ? frame : NULL;
}

// static
void VideoFrame::CreateEmptyFrame(scoped_refptr<VideoFrame>* frame_out) {
  *frame_out = new VideoFrame(VideoFrame::TYPE_SYSTEM_MEMORY,
                              VideoFrame::EMPTY, 0, 0);
}

// static
void VideoFrame::CreateBlackFrame(int width, int height,
                                  scoped_refptr<VideoFrame>* frame_out) {
  DCHECK_GT(width, 0);
  DCHECK_GT(height, 0);

  // Create our frame.
  scoped_refptr<VideoFrame> frame;
  const base::TimeDelta kZero;
  VideoFrame::CreateFrame(VideoFrame::YV12, width, height, kZero, kZero,
                          &frame);
  DCHECK(frame);

  // Now set the data to YUV(0,128,128).
  const uint8 kBlackY = 0x00;
  const uint8 kBlackUV = 0x80;

  // Fill the Y plane.
  uint8* y_plane = frame->data(VideoFrame::kYPlane);
  for (size_t i = 0; i < frame->height_; ++i) {
    memset(y_plane, kBlackY, frame->width_);
    y_plane += frame->stride(VideoFrame::kYPlane);
  }

  // Fill the U and V planes.
  uint8* u_plane = frame->data(VideoFrame::kUPlane);
  uint8* v_plane = frame->data(VideoFrame::kVPlane);
  for (size_t i = 0; i < (frame->height_ / 2); ++i) {
    memset(u_plane, kBlackUV, frame->width_ / 2);
    memset(v_plane, kBlackUV, frame->width_ / 2);
    u_plane += frame->stride(VideoFrame::kUPlane);
    v_plane += frame->stride(VideoFrame::kVPlane);
  }

  // Success!
  *frame_out = frame;
}

// static
void VideoFrame::CreatePrivateFrame(VideoFrame::BufferType type,
                                    VideoFrame::Format format,
                                    size_t width,
                                    size_t height,
                                    base::TimeDelta timestamp,
                                    base::TimeDelta duration,
                                    void* private_buffer,
                                    scoped_refptr<VideoFrame>* frame_out) {
  DCHECK(frame_out);
  scoped_refptr<VideoFrame> frame =
      new VideoFrame(type, format, width, height);
  if (frame) {
    frame->SetTimestamp(timestamp);
    frame->SetDuration(duration);
    frame->private_buffer_ = private_buffer;
  }
  *frame_out = frame;
}

static inline size_t RoundUp(size_t value, size_t alignment) {
  // Check that |alignment| is a power of 2.
  DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
  return ((value + (alignment - 1)) & ~(alignment-1));
}

bool VideoFrame::AllocateRGB(size_t bytes_per_pixel) {
  // Round up to align at a 64-bit (8 byte) boundary for each row.  This
  // is sufficient for MMX reads (movq).
  size_t bytes_per_row = RoundUp(width_ * bytes_per_pixel, 8);
  planes_ = VideoFrame::kNumRGBPlanes;
  strides_[VideoFrame::kRGBPlane] = bytes_per_row;
  data_[VideoFrame::kRGBPlane] = new uint8[bytes_per_row * height_];
  DCHECK(data_[VideoFrame::kRGBPlane]);
  DCHECK(!(reinterpret_cast<intptr_t>(data_[VideoFrame::kRGBPlane]) & 7));
  COMPILE_ASSERT(0 == VideoFrame::kRGBPlane, RGB_data_must_be_index_0);
  return (NULL != data_[VideoFrame::kRGBPlane]);
}

static const int kFramePadBytes = 15;  // allows faster SIMD YUV convert

bool VideoFrame::AllocateYUV() {
  DCHECK(format_ == VideoFrame::YV12 ||
         format_ == VideoFrame::YV16);
  // Align Y rows at 32-bit (4 byte) boundaries.  The stride for both YV12 and
  // YV16 is 1/2 of the stride of Y.  For YV12, every row of bytes for U and V
  // applies to two rows of Y (one byte of UV for 4 bytes of Y), so in the
  // case of YV12 the strides are identical for the same width surface, but the
  // number of bytes allocated for YV12 is 1/2 the amount for U & V as YV16.
  // We also round the height of the surface allocated to be an even number
  // to avoid any potential of faulting by code that attempts to access the Y
  // values of the final row, but assumes that the last row of U & V applies to
  // a full two rows of Y.
  size_t alloc_height = RoundUp(height_, 2);
  size_t y_bytes_per_row = RoundUp(width_, 4);
  size_t uv_stride = RoundUp(y_bytes_per_row / 2, 4);
  size_t y_bytes = alloc_height * y_bytes_per_row;
  size_t uv_bytes = alloc_height * uv_stride;
  if (format_ == VideoFrame::YV12) {
    uv_bytes /= 2;
  }
  uint8* data = new uint8[y_bytes + (uv_bytes * 2) + kFramePadBytes];
  if (data) {
    planes_ = VideoFrame::kNumYUVPlanes;
    COMPILE_ASSERT(0 == VideoFrame::kYPlane, y_plane_data_must_be_index_0);
    data_[VideoFrame::kYPlane] = data;
    data_[VideoFrame::kUPlane] = data + y_bytes;
    data_[VideoFrame::kVPlane] = data + y_bytes + uv_bytes;
    strides_[VideoFrame::kYPlane] = y_bytes_per_row;
    strides_[VideoFrame::kUPlane] = uv_stride;
    strides_[VideoFrame::kVPlane] = uv_stride;
    return true;
  }
  NOTREACHED();
  return false;
}

VideoFrame::VideoFrame(VideoFrame::BufferType type,
                       VideoFrame::Format format,
                       size_t width,
                       size_t height) {
  type_ = type;
  format_ = format;
  width_ = width;
  height_ = height;
  planes_ = 0;
  memset(&strides_, 0, sizeof(strides_));
  memset(&data_, 0, sizeof(data_));
  private_buffer_ = NULL;
}

VideoFrame::~VideoFrame() {
  // In multi-plane allocations, only a single block of memory is allocated
  // on the heap, and other |data| pointers point inside the same, single block
  // so just delete index 0.
  delete[] data_[0];
}

bool VideoFrame::IsEndOfStream() const {
  return format_ == VideoFrame::EMPTY;
}

}  // namespace media
<|endoftext|>