<commit_before>/* ----------------------------------------------------------------------- *//**
 *
 * @file one_way_anova.cpp
 *
 * @brief One-way ANOVA functions
 *
 *//* ----------------------------------------------------------------------- */

#include <dbconnector/dbconnector.hpp>
#include <modules/prob/boost.hpp>
#include <modules/shared/HandleTraits.hpp>
#include <utils/Math.hpp>

#include "one_way_anova.hpp"

namespace madlib {

namespace modules {

namespace stats {

/**
 * @brief Transition state for one-way ANOVA functions
 *
 * Note: We assume that the DOUBLE PRECISION array is initialized by the
 * database with length 2, and all elemenets are 0. Handle::operator[] will
 * perform bounds checking.
 */
template <class Handle>
class OWATransitionState {
public:
    OWATransitionState(const AnyType &inArray)
      : mStorage(inArray.getAs<Handle>()) {

        rebind(utils::nextPowerOfTwo(static_cast<uint32_t>(mStorage[0])));
    }

    /**
     * @brief Convert to backend representation
     *
     * We define this function so that we can use TransitionState in the argument
     * list and as a return type.
     */
    inline operator AnyType() const {
        return mStorage;
    }

    /**
     * @brief Return the index (in the num, sum, and corrected_square_sum
     *     fields) of a group value
     *
     * If a value is not found, we add a new group to the transition state.
     * Since we do not want to reallocate too often, we reserve some buffer
     * space in the storage array. So we need to reallocate and copy memory only
     * whenever the number of groups hits a power of 2.
     */
    uint32_t idxOfGroup(const Allocator& inAllocator, uint32_t inValue);

private:
    static inline size_t arraySize(uint32_t inNumGroupsReserved) {
        return 1 + 5 * inNumGroupsReserved;
    }

    void rebind(uint32_t inNumGroupsReserved) {
        madlib_assert(mStorage.size() >= arraySize(inNumGroupsReserved),
            std::runtime_error("Out-of-bounds array access detected."));

        numGroups.rebind(&mStorage[0]);
        groupValues = &mStorage[1];
        posToIndices = &mStorage[1 + inNumGroupsReserved];
        num.rebind(&mStorage[1 + 2 * inNumGroupsReserved], inNumGroupsReserved);
        sum.rebind(&mStorage[1 + 3 * inNumGroupsReserved], inNumGroupsReserved);
        corrected_square_sum.rebind(
            &mStorage[1 + 4 * inNumGroupsReserved], inNumGroupsReserved);
    }

    Handle mStorage;

public:
    typename HandleTraits<Handle>::ReferenceToUInt32 numGroups;
    typename HandleTraits<Handle>::DoublePtr groupValues;
    typename HandleTraits<Handle>::DoublePtr posToIndices;
    typename HandleTraits<Handle>::ColumnVectorTransparentHandleMap num;
    typename HandleTraits<Handle>::ColumnVectorTransparentHandleMap sum;
    typename HandleTraits<Handle>::ColumnVectorTransparentHandleMap corrected_square_sum;
};

template <>
uint32_t
OWATransitionState<ArrayHandle<double> >::idxOfGroup(
    const Allocator&, uint32_t inValue) {

    std::ptrdiff_t pos = std::lower_bound(
        groupValues, groupValues + numGroups, inValue) - groupValues;

    if (static_cast<uint64_t>(pos) >= numGroups
        || groupValues[pos] != inValue) {
        // Did not find this group value. We have to start a new group.

        throw std::runtime_error("Could not find a grouping value during "
            "one-way ANOVA.");
    }
    return static_cast<uint32_t>(pos);
}

template <>
uint32_t
OWATransitionState<MutableArrayHandle<double> >::idxOfGroup(
    const Allocator& inAllocator, uint32_t inValue) {

    // FIXME: Think of using proper iterators. Add some safety. Overflow checks.
    // http://jira.madlib.net/browse/MADLIB-499
    std::ptrdiff_t pos = std::lower_bound(
        groupValues, groupValues + numGroups, inValue) - groupValues;

    if (static_cast<uint64_t>(pos) >= numGroups
        || groupValues[pos] != inValue) {
        // Did not find this group value. We have to start a new group.

        uint32_t numGroupsReserved = utils::nextPowerOfTwo(
            static_cast<uint32_t>(numGroups));
        if (numGroupsReserved > numGroups) {
            // We have enough reserve space allocated.
            std::copy(groupValues + pos, groupValues + numGroups,
                groupValues + pos + 1);
            groupValues[pos] = inValue;

            std::copy(posToIndices + pos, posToIndices + numGroups,
                posToIndices + pos + 1);
            posToIndices[pos] = numGroups++;
        } else {
            // We need to reallocate storage for the transition state
            // Save our current state, so we can subsequently restore it
            // with the new storage
            OWATransitionState oldSelf = *this;
            if (numGroupsReserved == 0)
                numGroupsReserved = 1;
            else {
                if (static_cast<uint64_t>(2) * numGroupsReserved >
                    std::numeric_limits<uint32_t>::max())
                    throw std::runtime_error("Too many groups.");

                numGroupsReserved = 2U * numGroupsReserved;
            }
            mStorage = inAllocator.allocateArray<double, dbal::AggregateContext,
                dbal::DoZero, dbal::ThrowBadAlloc>(arraySize(numGroupsReserved));
            rebind(numGroupsReserved);

            numGroups = oldSelf.numGroups + 1;
            std::copy(oldSelf.groupValues, oldSelf.groupValues + pos, groupValues);
            std::copy(oldSelf.groupValues + pos,
                oldSelf.groupValues + oldSelf.numGroups, groupValues + pos + 1);
            groupValues[pos] = inValue;

            std::copy(oldSelf.posToIndices, oldSelf.posToIndices + pos, posToIndices);
            std::copy(oldSelf.posToIndices + pos,
                oldSelf.posToIndices + oldSelf.numGroups, posToIndices + pos + 1);
            posToIndices[pos] = oldSelf.numGroups;

            num.segment(0, oldSelf.numGroups) << oldSelf.num;
            sum.segment(0, oldSelf.numGroups) << oldSelf.sum;
            corrected_square_sum.segment(0, oldSelf.numGroups) << oldSelf.corrected_square_sum;
        }
    }
    return static_cast<uint32_t>(posToIndices[pos]);
}

// FIXME: Same function used for t_test. Factor out.
// http://jira.madlib.net/browse/MADLIB-500
/**
 * @brief Update the corrected sum of squares
 *
 * For numerical stability, we should not compute the sample variance in the
 * naive way. The literature has many examples where this gives bad results
 * even with moderately sized inputs.
 *
 * See:
 *
 * B. P. Welford (1962). "Note on a method for calculating corrected sums of
 * squares and products". Technometrics 4(3):419–420.
 *
 * Chan, Tony F.; Golub, Gene H.; LeVeque, Randall J. (1979), "Updating
 * Formulae and a Pairwise Algorithm for Computing Sample Variances.", Technical
 * Report STAN-CS-79-773, Department of Computer Science, Stanford University.
 * ftp://reports.stanford.edu/pub/cstr/reports/cs/tr/79/773/CS-TR-79-773.pdf
 */
inline
void
updateCorrectedSumOfSquares(double &ioLeftWeight, double &ioLeftSum,
    double &ioLeftCorrectedSumSquares, double inRightWeight, double inRightSum,
    double inRightCorrectedSumSquares) {

    if (inRightWeight <= 0)
        return;

    // FIXME: Use compensated sums for numerical stability
    // http://jira.madlib.net/browse/MADLIB-500
    // See Ogita et al., "Accurate Sum and Dot Product", SIAM Journal on
    // Scientific Computing (SISC), 26(6):1955-1988, 2005.
    if (ioLeftWeight <= 0)
        ioLeftCorrectedSumSquares = inRightCorrectedSumSquares;
    else {
        double diff = inRightWeight / ioLeftWeight * ioLeftSum - inRightSum;
        ioLeftCorrectedSumSquares
               += inRightCorrectedSumSquares
                + ioLeftWeight / (inRightWeight * (ioLeftWeight + inRightWeight))
                    * diff * diff;
    }

    ioLeftSum += inRightSum;
    ioLeftWeight += inRightWeight;
}

/**
 * @brief Perform the transition step
 */
AnyType
one_way_anova_transition::run(AnyType &args) {
    OWATransitionState<MutableArrayHandle<double> > state = args[0];
    int32_t group = args[1].getAs<int32_t>();
    double value = args[2].getAs<double>();

    uint32_t idx = state.idxOfGroup(*this, group);
    updateCorrectedSumOfSquares(
        state.num(idx), state.sum(idx), state.corrected_square_sum(idx),
        1, value, 0);

    return state;
}

/**
 * @brief Perform the perliminary aggregation function: Merge transition states
 */
AnyType
one_way_anova_merge_states::run(AnyType &args) {
    OWATransitionState<MutableArrayHandle<double> > stateLeft = args[0];
    OWATransitionState<ArrayHandle<double> > stateRight = args[1];

    // Merge states together and return
    for (uint64_t posRight = 0; posRight < stateRight.numGroups; posRight++) {
        uint32_t value
            = static_cast<uint32_t>(stateRight.groupValues[posRight]);
        uint32_t idxRight = stateRight.idxOfGroup(*this, value);
        uint32_t idxLeft = stateLeft.idxOfGroup(*this, value);
        updateCorrectedSumOfSquares(
            stateLeft.num(idxLeft), stateLeft.sum(idxLeft),
                stateLeft.corrected_square_sum(idxLeft),
            stateRight.num(idxRight), stateRight.sum(idxRight),
                stateRight.corrected_square_sum(idxRight));
    }

    return stateLeft;
}

/**
 * @brief Perform the one-sided t-Test final step
 */
AnyType
one_way_anova_final::run(AnyType &args) {
    using boost::math::complement;

    OWATransitionState<ArrayHandle<double> > state = args[0];

    // If we haven't seen any data, just return Null. This is the standard
    // behavior of aggregate function on empty data sets (compare, e.g.,
    // how PostgreSQL handles sum or avg on empty inputs)
    if (state.numGroups == 0)
        return Null();

    double grand_mean = state.sum.sum() / state.num.sum();
    double sum_squares_between = 0;

    for (uint64_t idx = 0; idx < state.numGroups; idx++)
        sum_squares_between += state.num(idx)
                             * std::pow(state.sum(idx) / state.num(idx)
                                        - grand_mean, 2);

    double sum_squares_within = state.corrected_square_sum.sum();
    double df_between = state.numGroups - 1;
    double df_within = state.num.sum() - state.numGroups;
    double mean_square_between = sum_squares_between / df_between;
    double mean_square_within = sum_squares_within / df_within;
    double statistic = mean_square_between / mean_square_within;

    AnyType tuple;
    tuple
        << sum_squares_between
        << sum_squares_within
        << static_cast<int64_t>(df_between)
        << static_cast<int64_t>(df_within)
        << mean_square_between
        << mean_square_within
        << statistic
        << prob::cdf(
            complement(prob::fisher_f(df_between, df_within), statistic));
    return tuple;
}

} // namespace stats

} // namespace modules

} // namespace madlib
<commit_msg>One-way ANOVA: return NULL for p-values if d.f. <= 0 instead of raising error<commit_after>/* ----------------------------------------------------------------------- *//**
 *
 * @file one_way_anova.cpp
 *
 * @brief One-way ANOVA functions
 *
 *//* ----------------------------------------------------------------------- */

#include <dbconnector/dbconnector.hpp>
#include <modules/prob/boost.hpp>
#include <modules/shared/HandleTraits.hpp>
#include <utils/Math.hpp>

#include "one_way_anova.hpp"

namespace madlib {

namespace modules {

namespace stats {

/**
 * @brief Transition state for one-way ANOVA functions
 *
 * Note: We assume that the DOUBLE PRECISION array is initialized by the
 * database with length 2, and all elemenets are 0. Handle::operator[] will
 * perform bounds checking.
 */
template <class Handle>
class OWATransitionState {
public:
    OWATransitionState(const AnyType &inArray)
      : mStorage(inArray.getAs<Handle>()) {

        rebind(utils::nextPowerOfTwo(static_cast<uint32_t>(mStorage[0])));
    }

    /**
     * @brief Convert to backend representation
     *
     * We define this function so that we can use TransitionState in the argument
     * list and as a return type.
     */
    inline operator AnyType() const {
        return mStorage;
    }

    /**
     * @brief Return the index (in the num, sum, and corrected_square_sum
     *     fields) of a group value
     *
     * If a value is not found, we add a new group to the transition state.
     * Since we do not want to reallocate too often, we reserve some buffer
     * space in the storage array. So we need to reallocate and copy memory only
     * whenever the number of groups hits a power of 2.
     */
    uint32_t idxOfGroup(const Allocator& inAllocator, uint32_t inValue);

private:
    static inline size_t arraySize(uint32_t inNumGroupsReserved) {
        return 1 + 5 * inNumGroupsReserved;
    }

    void rebind(uint32_t inNumGroupsReserved) {
        madlib_assert(mStorage.size() >= arraySize(inNumGroupsReserved),
            std::runtime_error("Out-of-bounds array access detected."));

        numGroups.rebind(&mStorage[0]);
        groupValues = &mStorage[1];
        posToIndices = &mStorage[1 + inNumGroupsReserved];
        num.rebind(&mStorage[1 + 2 * inNumGroupsReserved], inNumGroupsReserved);
        sum.rebind(&mStorage[1 + 3 * inNumGroupsReserved], inNumGroupsReserved);
        corrected_square_sum.rebind(
            &mStorage[1 + 4 * inNumGroupsReserved], inNumGroupsReserved);
    }

    Handle mStorage;

public:
    typename HandleTraits<Handle>::ReferenceToUInt32 numGroups;
    typename HandleTraits<Handle>::DoublePtr groupValues;
    typename HandleTraits<Handle>::DoublePtr posToIndices;
    typename HandleTraits<Handle>::ColumnVectorTransparentHandleMap num;
    typename HandleTraits<Handle>::ColumnVectorTransparentHandleMap sum;
    typename HandleTraits<Handle>::ColumnVectorTransparentHandleMap corrected_square_sum;
};

template <>
uint32_t
OWATransitionState<ArrayHandle<double> >::idxOfGroup(
    const Allocator&, uint32_t inValue) {

    std::ptrdiff_t pos = std::lower_bound(
        groupValues, groupValues + numGroups, inValue) - groupValues;

    if (static_cast<uint64_t>(pos) >= numGroups
        || groupValues[pos] != inValue) {
        // Did not find this group value. We have to start a new group.

        throw std::runtime_error("Could not find a grouping value during "
            "one-way ANOVA.");
    }
    return static_cast<uint32_t>(pos);
}

template <>
uint32_t
OWATransitionState<MutableArrayHandle<double> >::idxOfGroup(
    const Allocator& inAllocator, uint32_t inValue) {

    // FIXME: Think of using proper iterators. Add some safety. Overflow checks.
    // http://jira.madlib.net/browse/MADLIB-499
    std::ptrdiff_t pos = std::lower_bound(
        groupValues, groupValues + numGroups, inValue) - groupValues;

    if (static_cast<uint64_t>(pos) >= numGroups
        || groupValues[pos] != inValue) {
        // Did not find this group value. We have to start a new group.

        uint32_t numGroupsReserved = utils::nextPowerOfTwo(
            static_cast<uint32_t>(numGroups));
        if (numGroupsReserved > numGroups) {
            // We have enough reserve space allocated.
            std::copy(groupValues + pos, groupValues + numGroups,
                groupValues + pos + 1);
            groupValues[pos] = inValue;

            std::copy(posToIndices + pos, posToIndices + numGroups,
                posToIndices + pos + 1);
            posToIndices[pos] = numGroups++;
        } else {
            // We need to reallocate storage for the transition state
            // Save our current state, so we can subsequently restore it
            // with the new storage
            OWATransitionState oldSelf = *this;
            if (numGroupsReserved == 0)
                numGroupsReserved = 1;
            else {
                if (static_cast<uint64_t>(2) * numGroupsReserved >
                    std::numeric_limits<uint32_t>::max())
                    throw std::runtime_error("Too many groups.");

                numGroupsReserved = 2U * numGroupsReserved;
            }
            mStorage = inAllocator.allocateArray<double, dbal::AggregateContext,
                dbal::DoZero, dbal::ThrowBadAlloc>(arraySize(numGroupsReserved));
            rebind(numGroupsReserved);

            numGroups = oldSelf.numGroups + 1;
            std::copy(oldSelf.groupValues, oldSelf.groupValues + pos, groupValues);
            std::copy(oldSelf.groupValues + pos,
                oldSelf.groupValues + oldSelf.numGroups, groupValues + pos + 1);
            groupValues[pos] = inValue;

            std::copy(oldSelf.posToIndices, oldSelf.posToIndices + pos, posToIndices);
            std::copy(oldSelf.posToIndices + pos,
                oldSelf.posToIndices + oldSelf.numGroups, posToIndices + pos + 1);
            posToIndices[pos] = oldSelf.numGroups;

            num.segment(0, oldSelf.numGroups) << oldSelf.num;
            sum.segment(0, oldSelf.numGroups) << oldSelf.sum;
            corrected_square_sum.segment(0, oldSelf.numGroups) << oldSelf.corrected_square_sum;
        }
    }
    return static_cast<uint32_t>(posToIndices[pos]);
}

// FIXME: Same function used for t_test. Factor out.
// http://jira.madlib.net/browse/MADLIB-500
/**
 * @brief Update the corrected sum of squares
 *
 * For numerical stability, we should not compute the sample variance in the
 * naive way. The literature has many examples where this gives bad results
 * even with moderately sized inputs.
 *
 * See:
 *
 * B. P. Welford (1962). "Note on a method for calculating corrected sums of
 * squares and products". Technometrics 4(3):419–420.
 *
 * Chan, Tony F.; Golub, Gene H.; LeVeque, Randall J. (1979), "Updating
 * Formulae and a Pairwise Algorithm for Computing Sample Variances.", Technical
 * Report STAN-CS-79-773, Department of Computer Science, Stanford University.
 * ftp://reports.stanford.edu/pub/cstr/reports/cs/tr/79/773/CS-TR-79-773.pdf
 */
inline
void
updateCorrectedSumOfSquares(double &ioLeftWeight, double &ioLeftSum,
    double &ioLeftCorrectedSumSquares, double inRightWeight, double inRightSum,
    double inRightCorrectedSumSquares) {

    if (inRightWeight <= 0)
        return;

    // FIXME: Use compensated sums for numerical stability
    // http://jira.madlib.net/browse/MADLIB-500
    // See Ogita et al., "Accurate Sum and Dot Product", SIAM Journal on
    // Scientific Computing (SISC), 26(6):1955-1988, 2005.
    if (ioLeftWeight <= 0)
        ioLeftCorrectedSumSquares = inRightCorrectedSumSquares;
    else {
        double diff = inRightWeight / ioLeftWeight * ioLeftSum - inRightSum;
        ioLeftCorrectedSumSquares
               += inRightCorrectedSumSquares
                + ioLeftWeight / (inRightWeight * (ioLeftWeight + inRightWeight))
                    * diff * diff;
    }

    ioLeftSum += inRightSum;
    ioLeftWeight += inRightWeight;
}

/**
 * @brief Perform the transition step
 */
AnyType
one_way_anova_transition::run(AnyType &args) {
    OWATransitionState<MutableArrayHandle<double> > state = args[0];
    int32_t group = args[1].getAs<int32_t>();
    double value = args[2].getAs<double>();

    uint32_t idx = state.idxOfGroup(*this, group);
    updateCorrectedSumOfSquares(
        state.num(idx), state.sum(idx), state.corrected_square_sum(idx),
        1, value, 0);

    return state;
}

/**
 * @brief Perform the perliminary aggregation function: Merge transition states
 */
AnyType
one_way_anova_merge_states::run(AnyType &args) {
    OWATransitionState<MutableArrayHandle<double> > stateLeft = args[0];
    OWATransitionState<ArrayHandle<double> > stateRight = args[1];

    // Merge states together and return
    for (uint64_t posRight = 0; posRight < stateRight.numGroups; posRight++) {
        uint32_t value
            = static_cast<uint32_t>(stateRight.groupValues[posRight]);
        uint32_t idxRight = stateRight.idxOfGroup(*this, value);
        uint32_t idxLeft = stateLeft.idxOfGroup(*this, value);
        updateCorrectedSumOfSquares(
            stateLeft.num(idxLeft), stateLeft.sum(idxLeft),
                stateLeft.corrected_square_sum(idxLeft),
            stateRight.num(idxRight), stateRight.sum(idxRight),
                stateRight.corrected_square_sum(idxRight));
    }

    return stateLeft;
}

/**
 * @brief Perform the one-sided t-Test final step
 */
AnyType
one_way_anova_final::run(AnyType &args) {
    using boost::math::complement;

    OWATransitionState<ArrayHandle<double> > state = args[0];

    // If we haven't seen any data, just return Null. This is the standard
    // behavior of aggregate function on empty data sets (compare, e.g.,
    // how PostgreSQL handles sum or avg on empty inputs)
    if (state.numGroups == 0)
        return Null();

    double grand_mean = state.sum.sum() / state.num.sum();
    double sum_squares_between = 0;

    for (uint64_t idx = 0; idx < state.numGroups; idx++)
        sum_squares_between += state.num(idx)
                             * std::pow(state.sum(idx) / state.num(idx)
                                        - grand_mean, 2);

    double sum_squares_within = state.corrected_square_sum.sum();
    double df_between = state.numGroups - 1;
    double df_within = state.num.sum() - state.numGroups;
    double mean_square_between = sum_squares_between / df_between;
    double mean_square_within = sum_squares_within / df_within;
    double statistic = mean_square_between / mean_square_within;

    AnyType tuple;
    tuple
        << sum_squares_between
        << sum_squares_within
        << static_cast<int64_t>(df_between)
        << static_cast<int64_t>(df_within)
        << mean_square_between
        << mean_square_within
        << statistic
        << ((df_between >= 1 && df_within >= 1)
            ? prob::cdf(
                complement(prob::fisher_f(df_between, df_within), statistic))
            : Null());
    return tuple;
}

} // namespace stats

} // namespace modules

} // namespace madlib
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/video_render//incoming_video_stream.h"

#include <assert.h>

#if defined(_WIN32)
#include <windows.h>
#elif defined(WEBRTC_LINUX)
#include <sys/time.h>
#include <time.h>
#else
#include <sys/time.h>
#endif

#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "webrtc/modules/video_render//video_render_frames.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
#include "webrtc/system_wrappers/interface/tick_util.h"
#include "webrtc/system_wrappers/interface/trace.h"

namespace webrtc {

IncomingVideoStream::IncomingVideoStream(const int32_t module_id,
                                         const uint32_t stream_id)
    : module_id_(module_id),
      stream_id_(stream_id),
      stream_critsect_(*CriticalSectionWrapper::CreateCriticalSection()),
      thread_critsect_(*CriticalSectionWrapper::CreateCriticalSection()),
      buffer_critsect_(*CriticalSectionWrapper::CreateCriticalSection()),
      incoming_render_thread_(),
      deliver_buffer_event_(*EventWrapper::Create()),
      running_(false),
      external_callback_(NULL),
      render_callback_(NULL),
      render_buffers_(*(new VideoRenderFrames)),
      callbackVideoType_(kVideoI420),
      callbackWidth_(0),
      callbackHeight_(0),
      incoming_rate_(0),
      last_rate_calculation_time_ms_(0),
      num_frames_since_last_calculation_(0),
      last_rendered_frame_(),
      temp_frame_(),
      start_image_(),
      timeout_image_(),
      timeout_time_(),
      mirror_frames_enabled_(false),
      mirroring_(),
      transformed_video_frame_() {
  WEBRTC_TRACE(kTraceMemory, kTraceVideoRenderer, module_id_,
               "%s created for stream %d", __FUNCTION__, stream_id);
}

IncomingVideoStream::~IncomingVideoStream() {
  WEBRTC_TRACE(kTraceMemory, kTraceVideoRenderer, module_id_,
               "%s deleted for stream %d", __FUNCTION__, stream_id_);

  Stop();

  // incoming_render_thread_ - Delete in stop
  delete &render_buffers_;
  delete &stream_critsect_;
  delete &buffer_critsect_;
  delete &thread_critsect_;
  delete &deliver_buffer_event_;
}

int32_t IncomingVideoStream::ChangeModuleId(const int32_t id) {
  CriticalSectionScoped cs(&stream_critsect_);
  module_id_ = id;
  return 0;
}

VideoRenderCallback* IncomingVideoStream::ModuleCallback() {
  CriticalSectionScoped cs(&stream_critsect_);
  return this;
}

int32_t IncomingVideoStream::RenderFrame(const uint32_t stream_id,
                                         I420VideoFrame& video_frame) {
  CriticalSectionScoped csS(&stream_critsect_);
  WEBRTC_TRACE(kTraceStream, kTraceVideoRenderer, module_id_,
               "%s for stream %d, render time: %u", __FUNCTION__, stream_id_,
               video_frame.render_time_ms());

  if (!running_) {
    WEBRTC_TRACE(kTraceStream, kTraceVideoRenderer, module_id_,
                 "%s: Not running", __FUNCTION__);
    return -1;
  }

  // Mirroring is not supported if the frame is backed by a texture.
  if (true == mirror_frames_enabled_ && video_frame.native_handle() == NULL) {
    transformed_video_frame_.CreateEmptyFrame(video_frame.width(),
                                              video_frame.height(),
                                              video_frame.stride(kYPlane),
                                              video_frame.stride(kUPlane),
                                              video_frame.stride(kVPlane));
    if (mirroring_.mirror_x_axis) {
      MirrorI420UpDown(&video_frame,
                       &transformed_video_frame_);
      video_frame.SwapFrame(&transformed_video_frame_);
    }
    if (mirroring_.mirror_y_axis) {
      MirrorI420LeftRight(&video_frame,
                          &transformed_video_frame_);
      video_frame.SwapFrame(&transformed_video_frame_);
    }
  }

  // Rate statistics.
  num_frames_since_last_calculation_++;
  int64_t now_ms = TickTime::MillisecondTimestamp();
  if (now_ms >= last_rate_calculation_time_ms_ + KFrameRatePeriodMs) {
    incoming_rate_ =
        static_cast<uint32_t>(1000 * num_frames_since_last_calculation_ /
                              (now_ms - last_rate_calculation_time_ms_));
    num_frames_since_last_calculation_ = 0;
    last_rate_calculation_time_ms_ = now_ms;
  }

  // Insert frame.
  CriticalSectionScoped csB(&buffer_critsect_);
  if (render_buffers_.AddFrame(&video_frame) == 1)
    deliver_buffer_event_.Set();

  return 0;
}

int32_t IncomingVideoStream::SetStartImage(
    const I420VideoFrame& video_frame) {
  CriticalSectionScoped csS(&thread_critsect_);
  return start_image_.CopyFrame(video_frame);
}

int32_t IncomingVideoStream::SetTimeoutImage(
    const I420VideoFrame& video_frame, const uint32_t timeout) {
  CriticalSectionScoped csS(&thread_critsect_);
  timeout_time_ = timeout;
  return timeout_image_.CopyFrame(video_frame);
}

int32_t IncomingVideoStream::SetRenderCallback(
    VideoRenderCallback* render_callback) {
  CriticalSectionScoped cs(&stream_critsect_);

  WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, module_id_,
               "%s(%x) for stream %d", __FUNCTION__, render_callback,
               stream_id_);
  render_callback_ = render_callback;
  return 0;
}

int32_t IncomingVideoStream::EnableMirroring(const bool enable,
                                             const bool mirror_x_axis,
                                             const bool mirror_y_axis) {
  CriticalSectionScoped cs(&stream_critsect_);
  mirror_frames_enabled_ = enable;
  mirroring_.mirror_x_axis = mirror_x_axis;
  mirroring_.mirror_y_axis = mirror_y_axis;

  return 0;
}

int32_t IncomingVideoStream::SetExpectedRenderDelay(
    int32_t delay_ms) {
  CriticalSectionScoped csS(&stream_critsect_);
  if (running_) {
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, module_id_,
                 "%s(%d) for stream %d", __FUNCTION__, delay_ms, stream_id_);
    return -1;
  }
  CriticalSectionScoped cs(&buffer_critsect_);
  return render_buffers_.SetRenderDelay(delay_ms);
}

int32_t IncomingVideoStream::SetExternalCallback(
    VideoRenderCallback* external_callback) {
  CriticalSectionScoped cs(&stream_critsect_);
  WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, module_id_,
               "%s(%x) for stream %d", __FUNCTION__, external_callback,
               stream_id_);
  external_callback_ = external_callback;
  callbackVideoType_ = kVideoI420;
  callbackWidth_ = 0;
  callbackHeight_ = 0;
  return 0;
}

int32_t IncomingVideoStream::Start() {
  CriticalSectionScoped csS(&stream_critsect_);
  WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, module_id_,
               "%s for stream %d", __FUNCTION__, stream_id_);
  if (running_) {
    WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, module_id_,
                 "%s: Already running", __FUNCTION__);
    return 0;
  }

  CriticalSectionScoped csT(&thread_critsect_);
  assert(incoming_render_thread_ == NULL);

  incoming_render_thread_ = ThreadWrapper::CreateThread(
      IncomingVideoStreamThreadFun, this, kRealtimePriority,
      "IncomingVideoStreamThread");
  if (!incoming_render_thread_) {
    WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, module_id_,
                 "%s: No thread", __FUNCTION__);
    return -1;
  }

  unsigned int t_id = 0;
  if (incoming_render_thread_->Start(t_id)) {
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, module_id_,
                 "%s: thread started: %u", __FUNCTION__, t_id);
  } else {
    WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, module_id_,
                 "%s: Could not start send thread", __FUNCTION__);
    return -1;
  }
  deliver_buffer_event_.StartTimer(false, KEventStartupTimeMS);

  running_ = true;
  return 0;
}

int32_t IncomingVideoStream::Stop() {
  CriticalSectionScoped cs_stream(&stream_critsect_);
  WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, module_id_,
               "%s for stream %d", __FUNCTION__, stream_id_);

  if (!running_) {
    WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, module_id_,
                 "%s: Not running", __FUNCTION__);
    return 0;
  }

  thread_critsect_.Enter();
  if (incoming_render_thread_) {
    ThreadWrapper* thread = incoming_render_thread_;
    incoming_render_thread_ = NULL;
    thread->SetNotAlive();
#ifndef WIN32_
    deliver_buffer_event_.StopTimer();
#endif
    thread_critsect_.Leave();
    if (thread->Stop()) {
      delete thread;
    } else {
      assert(false);
      WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, module_id_,
                   "%s: Not able to stop thread, leaking", __FUNCTION__);
    }
  } else {
    thread_critsect_.Leave();
  }
  running_ = false;
  return 0;
}

int32_t IncomingVideoStream::Reset() {
  CriticalSectionScoped cs_stream(&stream_critsect_);
  CriticalSectionScoped cs_buffer(&buffer_critsect_);
  render_buffers_.ReleaseAllFrames();
  return 0;
}

uint32_t IncomingVideoStream::StreamId() const {
  CriticalSectionScoped cs_stream(&stream_critsect_);
  return stream_id_;
}

uint32_t IncomingVideoStream::IncomingRate() const {
  CriticalSectionScoped cs(&stream_critsect_);
  return incoming_rate_;
}

bool IncomingVideoStream::IncomingVideoStreamThreadFun(void* obj) {
  return static_cast<IncomingVideoStream*>(obj)->IncomingVideoStreamProcess();
}

bool IncomingVideoStream::IncomingVideoStreamProcess() {
  if (kEventError != deliver_buffer_event_.Wait(KEventMaxWaitTimeMs)) {
    thread_critsect_.Enter();
    if (incoming_render_thread_ == NULL) {
      // Terminating
      thread_critsect_.Leave();
      return false;
    }

    I420VideoFrame* frame_to_render = NULL;

    // Get a new frame to render and the time for the frame after this one.
    buffer_critsect_.Enter();
    frame_to_render = render_buffers_.FrameToRender();
    uint32_t wait_time = render_buffers_.TimeToNextFrameRelease();
    buffer_critsect_.Leave();

    // Set timer for next frame to render.
    if (wait_time > KEventMaxWaitTimeMs) {
      wait_time = KEventMaxWaitTimeMs;
    }
    deliver_buffer_event_.StartTimer(false, wait_time);

    if (!frame_to_render) {
      if (render_callback_) {
        if (last_rendered_frame_.render_time_ms() == 0 &&
            !start_image_.IsZeroSize()) {
          // We have not rendered anything and have a start image.
          temp_frame_.CopyFrame(start_image_);
          render_callback_->RenderFrame(stream_id_, temp_frame_);
        } else if (!timeout_image_.IsZeroSize() &&
                   last_rendered_frame_.render_time_ms() + timeout_time_ <
                       TickTime::MillisecondTimestamp()) {
          // Render a timeout image.
          temp_frame_.CopyFrame(timeout_image_);
          render_callback_->RenderFrame(stream_id_, temp_frame_);
        }
      }

      // No frame.
      thread_critsect_.Leave();
      return true;
    }

    // Send frame for rendering.
    if (external_callback_) {
      WEBRTC_TRACE(kTraceStream, kTraceVideoRenderer, module_id_,
                   "%s: executing external renderer callback to deliver frame",
                   __FUNCTION__, frame_to_render->render_time_ms());
      external_callback_->RenderFrame(stream_id_, *frame_to_render);
    } else {
      if (render_callback_) {
        WEBRTC_TRACE(kTraceStream, kTraceVideoRenderer, module_id_,
                     "%s: Render frame, time: ", __FUNCTION__,
                     frame_to_render->render_time_ms());
        render_callback_->RenderFrame(stream_id_, *frame_to_render);
      }
    }

    // Release critsect before calling the module user.
    thread_critsect_.Leave();

    // We're done with this frame, delete it.
    if (frame_to_render) {
      CriticalSectionScoped cs(&buffer_critsect_);
      last_rendered_frame_.SwapFrame(frame_to_render);
      render_buffers_.ReturnFrame(frame_to_render);
    }
  }
  return true;
}

int32_t IncomingVideoStream::GetLastRenderedFrame(
    I420VideoFrame& video_frame) const {
  CriticalSectionScoped cs(&buffer_critsect_);
  return video_frame.CopyFrame(last_rendered_frame_);
}

}  // namespace webrtc
<commit_msg>Fix double backslashes in incoming_video_stream.cc<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/video_render/incoming_video_stream.h"

#include <assert.h>

#if defined(_WIN32)
#include <windows.h>
#elif defined(WEBRTC_LINUX)
#include <sys/time.h>
#include <time.h>
#else
#include <sys/time.h>
#endif

#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "webrtc/modules/video_render/video_render_frames.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
#include "webrtc/system_wrappers/interface/tick_util.h"
#include "webrtc/system_wrappers/interface/trace.h"

namespace webrtc {

IncomingVideoStream::IncomingVideoStream(const int32_t module_id,
                                         const uint32_t stream_id)
    : module_id_(module_id),
      stream_id_(stream_id),
      stream_critsect_(*CriticalSectionWrapper::CreateCriticalSection()),
      thread_critsect_(*CriticalSectionWrapper::CreateCriticalSection()),
      buffer_critsect_(*CriticalSectionWrapper::CreateCriticalSection()),
      incoming_render_thread_(),
      deliver_buffer_event_(*EventWrapper::Create()),
      running_(false),
      external_callback_(NULL),
      render_callback_(NULL),
      render_buffers_(*(new VideoRenderFrames)),
      callbackVideoType_(kVideoI420),
      callbackWidth_(0),
      callbackHeight_(0),
      incoming_rate_(0),
      last_rate_calculation_time_ms_(0),
      num_frames_since_last_calculation_(0),
      last_rendered_frame_(),
      temp_frame_(),
      start_image_(),
      timeout_image_(),
      timeout_time_(),
      mirror_frames_enabled_(false),
      mirroring_(),
      transformed_video_frame_() {
  WEBRTC_TRACE(kTraceMemory, kTraceVideoRenderer, module_id_,
               "%s created for stream %d", __FUNCTION__, stream_id);
}

IncomingVideoStream::~IncomingVideoStream() {
  WEBRTC_TRACE(kTraceMemory, kTraceVideoRenderer, module_id_,
               "%s deleted for stream %d", __FUNCTION__, stream_id_);

  Stop();

  // incoming_render_thread_ - Delete in stop
  delete &render_buffers_;
  delete &stream_critsect_;
  delete &buffer_critsect_;
  delete &thread_critsect_;
  delete &deliver_buffer_event_;
}

int32_t IncomingVideoStream::ChangeModuleId(const int32_t id) {
  CriticalSectionScoped cs(&stream_critsect_);
  module_id_ = id;
  return 0;
}

VideoRenderCallback* IncomingVideoStream::ModuleCallback() {
  CriticalSectionScoped cs(&stream_critsect_);
  return this;
}

int32_t IncomingVideoStream::RenderFrame(const uint32_t stream_id,
                                         I420VideoFrame& video_frame) {
  CriticalSectionScoped csS(&stream_critsect_);
  WEBRTC_TRACE(kTraceStream, kTraceVideoRenderer, module_id_,
               "%s for stream %d, render time: %u", __FUNCTION__, stream_id_,
               video_frame.render_time_ms());

  if (!running_) {
    WEBRTC_TRACE(kTraceStream, kTraceVideoRenderer, module_id_,
                 "%s: Not running", __FUNCTION__);
    return -1;
  }

  // Mirroring is not supported if the frame is backed by a texture.
  if (true == mirror_frames_enabled_ && video_frame.native_handle() == NULL) {
    transformed_video_frame_.CreateEmptyFrame(video_frame.width(),
                                              video_frame.height(),
                                              video_frame.stride(kYPlane),
                                              video_frame.stride(kUPlane),
                                              video_frame.stride(kVPlane));
    if (mirroring_.mirror_x_axis) {
      MirrorI420UpDown(&video_frame,
                       &transformed_video_frame_);
      video_frame.SwapFrame(&transformed_video_frame_);
    }
    if (mirroring_.mirror_y_axis) {
      MirrorI420LeftRight(&video_frame,
                          &transformed_video_frame_);
      video_frame.SwapFrame(&transformed_video_frame_);
    }
  }

  // Rate statistics.
  num_frames_since_last_calculation_++;
  int64_t now_ms = TickTime::MillisecondTimestamp();
  if (now_ms >= last_rate_calculation_time_ms_ + KFrameRatePeriodMs) {
    incoming_rate_ =
        static_cast<uint32_t>(1000 * num_frames_since_last_calculation_ /
                              (now_ms - last_rate_calculation_time_ms_));
    num_frames_since_last_calculation_ = 0;
    last_rate_calculation_time_ms_ = now_ms;
  }

  // Insert frame.
  CriticalSectionScoped csB(&buffer_critsect_);
  if (render_buffers_.AddFrame(&video_frame) == 1)
    deliver_buffer_event_.Set();

  return 0;
}

int32_t IncomingVideoStream::SetStartImage(
    const I420VideoFrame& video_frame) {
  CriticalSectionScoped csS(&thread_critsect_);
  return start_image_.CopyFrame(video_frame);
}

int32_t IncomingVideoStream::SetTimeoutImage(
    const I420VideoFrame& video_frame, const uint32_t timeout) {
  CriticalSectionScoped csS(&thread_critsect_);
  timeout_time_ = timeout;
  return timeout_image_.CopyFrame(video_frame);
}

int32_t IncomingVideoStream::SetRenderCallback(
    VideoRenderCallback* render_callback) {
  CriticalSectionScoped cs(&stream_critsect_);

  WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, module_id_,
               "%s(%x) for stream %d", __FUNCTION__, render_callback,
               stream_id_);
  render_callback_ = render_callback;
  return 0;
}

int32_t IncomingVideoStream::EnableMirroring(const bool enable,
                                             const bool mirror_x_axis,
                                             const bool mirror_y_axis) {
  CriticalSectionScoped cs(&stream_critsect_);
  mirror_frames_enabled_ = enable;
  mirroring_.mirror_x_axis = mirror_x_axis;
  mirroring_.mirror_y_axis = mirror_y_axis;

  return 0;
}

int32_t IncomingVideoStream::SetExpectedRenderDelay(
    int32_t delay_ms) {
  CriticalSectionScoped csS(&stream_critsect_);
  if (running_) {
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, module_id_,
                 "%s(%d) for stream %d", __FUNCTION__, delay_ms, stream_id_);
    return -1;
  }
  CriticalSectionScoped cs(&buffer_critsect_);
  return render_buffers_.SetRenderDelay(delay_ms);
}

int32_t IncomingVideoStream::SetExternalCallback(
    VideoRenderCallback* external_callback) {
  CriticalSectionScoped cs(&stream_critsect_);
  WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, module_id_,
               "%s(%x) for stream %d", __FUNCTION__, external_callback,
               stream_id_);
  external_callback_ = external_callback;
  callbackVideoType_ = kVideoI420;
  callbackWidth_ = 0;
  callbackHeight_ = 0;
  return 0;
}

int32_t IncomingVideoStream::Start() {
  CriticalSectionScoped csS(&stream_critsect_);
  WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, module_id_,
               "%s for stream %d", __FUNCTION__, stream_id_);
  if (running_) {
    WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, module_id_,
                 "%s: Already running", __FUNCTION__);
    return 0;
  }

  CriticalSectionScoped csT(&thread_critsect_);
  assert(incoming_render_thread_ == NULL);

  incoming_render_thread_ = ThreadWrapper::CreateThread(
      IncomingVideoStreamThreadFun, this, kRealtimePriority,
      "IncomingVideoStreamThread");
  if (!incoming_render_thread_) {
    WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, module_id_,
                 "%s: No thread", __FUNCTION__);
    return -1;
  }

  unsigned int t_id = 0;
  if (incoming_render_thread_->Start(t_id)) {
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, module_id_,
                 "%s: thread started: %u", __FUNCTION__, t_id);
  } else {
    WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, module_id_,
                 "%s: Could not start send thread", __FUNCTION__);
    return -1;
  }
  deliver_buffer_event_.StartTimer(false, KEventStartupTimeMS);

  running_ = true;
  return 0;
}

int32_t IncomingVideoStream::Stop() {
  CriticalSectionScoped cs_stream(&stream_critsect_);
  WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, module_id_,
               "%s for stream %d", __FUNCTION__, stream_id_);

  if (!running_) {
    WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, module_id_,
                 "%s: Not running", __FUNCTION__);
    return 0;
  }

  thread_critsect_.Enter();
  if (incoming_render_thread_) {
    ThreadWrapper* thread = incoming_render_thread_;
    incoming_render_thread_ = NULL;
    thread->SetNotAlive();
#ifndef WIN32_
    deliver_buffer_event_.StopTimer();
#endif
    thread_critsect_.Leave();
    if (thread->Stop()) {
      delete thread;
    } else {
      assert(false);
      WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, module_id_,
                   "%s: Not able to stop thread, leaking", __FUNCTION__);
    }
  } else {
    thread_critsect_.Leave();
  }
  running_ = false;
  return 0;
}

int32_t IncomingVideoStream::Reset() {
  CriticalSectionScoped cs_stream(&stream_critsect_);
  CriticalSectionScoped cs_buffer(&buffer_critsect_);
  render_buffers_.ReleaseAllFrames();
  return 0;
}

uint32_t IncomingVideoStream::StreamId() const {
  CriticalSectionScoped cs_stream(&stream_critsect_);
  return stream_id_;
}

uint32_t IncomingVideoStream::IncomingRate() const {
  CriticalSectionScoped cs(&stream_critsect_);
  return incoming_rate_;
}

bool IncomingVideoStream::IncomingVideoStreamThreadFun(void* obj) {
  return static_cast<IncomingVideoStream*>(obj)->IncomingVideoStreamProcess();
}

bool IncomingVideoStream::IncomingVideoStreamProcess() {
  if (kEventError != deliver_buffer_event_.Wait(KEventMaxWaitTimeMs)) {
    thread_critsect_.Enter();
    if (incoming_render_thread_ == NULL) {
      // Terminating
      thread_critsect_.Leave();
      return false;
    }

    I420VideoFrame* frame_to_render = NULL;

    // Get a new frame to render and the time for the frame after this one.
    buffer_critsect_.Enter();
    frame_to_render = render_buffers_.FrameToRender();
    uint32_t wait_time = render_buffers_.TimeToNextFrameRelease();
    buffer_critsect_.Leave();

    // Set timer for next frame to render.
    if (wait_time > KEventMaxWaitTimeMs) {
      wait_time = KEventMaxWaitTimeMs;
    }
    deliver_buffer_event_.StartTimer(false, wait_time);

    if (!frame_to_render) {
      if (render_callback_) {
        if (last_rendered_frame_.render_time_ms() == 0 &&
            !start_image_.IsZeroSize()) {
          // We have not rendered anything and have a start image.
          temp_frame_.CopyFrame(start_image_);
          render_callback_->RenderFrame(stream_id_, temp_frame_);
        } else if (!timeout_image_.IsZeroSize() &&
                   last_rendered_frame_.render_time_ms() + timeout_time_ <
                       TickTime::MillisecondTimestamp()) {
          // Render a timeout image.
          temp_frame_.CopyFrame(timeout_image_);
          render_callback_->RenderFrame(stream_id_, temp_frame_);
        }
      }

      // No frame.
      thread_critsect_.Leave();
      return true;
    }

    // Send frame for rendering.
    if (external_callback_) {
      WEBRTC_TRACE(kTraceStream, kTraceVideoRenderer, module_id_,
                   "%s: executing external renderer callback to deliver frame",
                   __FUNCTION__, frame_to_render->render_time_ms());
      external_callback_->RenderFrame(stream_id_, *frame_to_render);
    } else {
      if (render_callback_) {
        WEBRTC_TRACE(kTraceStream, kTraceVideoRenderer, module_id_,
                     "%s: Render frame, time: ", __FUNCTION__,
                     frame_to_render->render_time_ms());
        render_callback_->RenderFrame(stream_id_, *frame_to_render);
      }
    }

    // Release critsect before calling the module user.
    thread_critsect_.Leave();

    // We're done with this frame, delete it.
    if (frame_to_render) {
      CriticalSectionScoped cs(&buffer_critsect_);
      last_rendered_frame_.SwapFrame(frame_to_render);
      render_buffers_.ReturnFrame(frame_to_render);
    }
  }
  return true;
}

int32_t IncomingVideoStream::GetLastRenderedFrame(
    I420VideoFrame& video_frame) const {
  CriticalSectionScoped cs(&buffer_critsect_);
  return video_frame.CopyFrame(last_rendered_frame_);
}

}  // namespace webrtc
<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file SimpleEventRegistry.hxx
 * A simple implementation of an NMRANet event registry.
 *
 * @author Balazs Racz
 * @date 19 Octover 2013
 */

#ifndef _NMRANET_SimpleEventRegistry_hxx_
#define _NMRANET_SimpleEventRegistry_hxx_

#include "nmranet/NMRAnetEventRegistry.hxx"

class SimpleEventRegistry : public NMRAnetEventRegistry, public EventHandler {
 public:

};

#endif  // _NMRANET_SimpleEventRegistry_hxx_
<commit_msg>removes dead code.<commit_after><|endoftext|>


<commit_before>
// Copyright (c) 2015 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef OPENMVG_SFM_SFM_DATA_IO_PLY_HPP
#define OPENMVG_SFM_SFM_DATA_IO_PLY_HPP

#include "openMVG/sfm/sfm_data_io.hpp"

#include <fstream>
#include <iomanip>

namespace openMVG {
namespace sfm {

/// Save the structure and camera positions of a SfM_Data container as 3D points in a PLY ASCII file.
inline bool Save_PLY(
  const SfM_Data & sfm_data,
  const std::string & filename,
  ESfM_Data flags_part)
{
  const bool b_structure = (flags_part & STRUCTURE) == STRUCTURE;
  const bool b_control_points = (flags_part & CONTROL_POINTS) == CONTROL_POINTS;
  const bool b_extrinsics = (flags_part & EXTRINSICS) == EXTRINSICS;

  if (!(b_structure || b_extrinsics || b_control_points))
    return false; // No 3D points to display, so it would produce an empty PLY file

  // Create the stream and check its status
  std::ofstream stream(filename.c_str());
  if (!stream.is_open())
    return false;

  bool bOk = false;
  {
    // Count how many views having valid poses:
    IndexT view_with_pose_count = 0;
    IndexT view_with_pose_prior_count = 0;
    if (b_extrinsics)
    {
      for (const auto & view : sfm_data.GetViews())
      {
        view_with_pose_count += sfm_data.IsPoseAndIntrinsicDefined(view.second.get());
      }

      for (const auto & view : sfm_data.GetViews())
      {
        if (const sfm::ViewPriors *prior = dynamic_cast<sfm::ViewPriors*>(view.second.get()))
        {
            view_with_pose_prior_count += prior->b_use_pose_center_;
        }
      }
    }

    stream << std::fixed << std::setprecision (std::numeric_limits<double>::digits10 + 1);

    stream << "ply"
      << '\n' << "format ascii 1.0"
      << '\n' << "element vertex "
        // Vertex count: (#landmark + #GCP + #view_with_valid_pose)
        << (  (b_structure ? sfm_data.GetLandmarks().size() : 0)
            + (b_control_points ? sfm_data.GetControl_Points().size() : 0)
            + view_with_pose_count
            + view_with_pose_prior_count)
      << '\n' << "property double x"
      << '\n' << "property double y"
      << '\n' << "property double z"
      << '\n' << "property uchar red"
      << '\n' << "property uchar green"
      << '\n' << "property uchar blue"
      << '\n' << "end_header" << std::endl;

      if (b_extrinsics)
      {
        for (const auto & view : sfm_data.GetViews())
        {
          // Export pose as Green points
          if (sfm_data.IsPoseAndIntrinsicDefined(view.second.get()))
          {
            const geometry::Pose3 pose = sfm_data.GetPoseOrDie(view.second.get());
            stream
              << pose.center()(0) << ' '
              << pose.center()(1) << ' '
              << pose.center()(2) << ' '
              << "0 255 0\n";
          }

          // Export pose priors as Blue points
          if (const sfm::ViewPriors *prior = dynamic_cast<sfm::ViewPriors*>(view.second.get()))
          {
            if (prior->b_use_pose_center_) {
              stream
                << prior->pose_center_(0) << ' '
                << prior->pose_center_(1) << ' '
                << prior->pose_center_(2) << ' '
                << "0 0 255\n";
            }
          }
        }
      }

      if (b_structure)
      {
        // Export structure points as White points
        const Landmarks & landmarks = sfm_data.GetLandmarks();
        for ( const auto & iterLandmarks : landmarks )
        {
          stream
            << iterLandmarks.second.X(0) << ' '
            << iterLandmarks.second.X(1) << ' '
            << iterLandmarks.second.X(2) << ' '
            << "255 255 255\n";
        }
      }

      if (b_control_points)
      {
        // Export GCP as Red points
        const Landmarks & landmarks = sfm_data.GetControl_Points();
        for ( const auto & iterGCP : landmarks )
        {
          stream
            << iterGCP.second.X(0) << ' '
            << iterGCP.second.X(1) << ' '
            << iterGCP.second.X(2) << ' '
            << "255 0 0\n";
        }
      }

      stream.flush();
      bOk = stream.good();
      stream.close();
  }
  return bOk;
}

} // namespace sfm
} // namespace openMVG

#endif // OPENMVG_SFM_SFM_DATA_IO_PLY_HPP
<commit_msg>[sfm] Export binary PLY files #733<commit_after>
// Copyright (c) 2015 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef OPENMVG_SFM_SFM_DATA_IO_PLY_HPP
#define OPENMVG_SFM_SFM_DATA_IO_PLY_HPP

#include "openMVG/sfm/sfm_data_io.hpp"

#include <fstream>
#include <iomanip>

namespace openMVG {
namespace sfm {

/// Save the structure and camera positions of a SfM_Data container as 3D points in a PLY ASCII/BIN file.
inline bool Save_PLY
(
  const SfM_Data & sfm_data,
  const std::string & filename,
  ESfM_Data flags_part,
  bool b_write_in_ascii = false
)
{
  const bool b_structure = (flags_part & STRUCTURE) == STRUCTURE;
  const bool b_control_points = (flags_part & CONTROL_POINTS) == CONTROL_POINTS;
  const bool b_extrinsics = (flags_part & EXTRINSICS) == EXTRINSICS;

  if (!(b_structure || b_extrinsics || b_control_points))
    return false; // No 3D points to display, so it would produce an empty PLY file

  // Create the stream and check its status
  std::ofstream stream(filename.c_str(), std::ios::out | std::ios::binary);
  if (!stream.is_open())
    return false;

  bool bOk = false;
  {
    // Count how many views having valid poses:
    IndexT view_with_pose_count = 0;
    IndexT view_with_pose_prior_count = 0;
    if (b_extrinsics)
    {
      for (const auto & view : sfm_data.GetViews())
      {
        view_with_pose_count += sfm_data.IsPoseAndIntrinsicDefined(view.second.get());
      }

      for (const auto & view : sfm_data.GetViews())
      {
        if (const sfm::ViewPriors *prior = dynamic_cast<sfm::ViewPriors*>(view.second.get()))
        {
            view_with_pose_prior_count += prior->b_use_pose_center_;
        }
      }
    }

    stream << std::fixed << std::setprecision (std::numeric_limits<double>::digits10 + 1);

    using Vec3uc = Eigen::Matrix<unsigned char, 3, 1>;

    stream << "ply"
      << '\n' << "format "
              << (b_write_in_ascii ? "ascii 1.0" : "binary_little_endian 1.0")
      << '\n' << "comment generated by OpenMVG"
      << '\n' << "element vertex "
        // Vertex count: (#landmark + #GCP + #view_with_valid_pose)
        << (  (b_structure ? sfm_data.GetLandmarks().size() : 0)
            + (b_control_points ? sfm_data.GetControl_Points().size() : 0)
            + view_with_pose_count
            + view_with_pose_prior_count)
      << '\n' << "property double x"
      << '\n' << "property double y"
      << '\n' << "property double z"
      << '\n' << "property uchar red"
      << '\n' << "property uchar green"
      << '\n' << "property uchar blue"
      << '\n' << "end_header" << std::endl;

      if (b_extrinsics)
      {
        for (const auto & view : sfm_data.GetViews())
        {
          // Export pose as Green points
          if (sfm_data.IsPoseAndIntrinsicDefined(view.second.get()))
          {
            const geometry::Pose3 pose = sfm_data.GetPoseOrDie(view.second.get());
            if (b_write_in_ascii)
            {
              stream
                << pose.center()(0) << ' '
                << pose.center()(1) << ' '
                << pose.center()(2) << ' '
                << "0 255 0\n";
            }
            else
            {
              stream.write( reinterpret_cast<const char*> ( pose.center().data() ), sizeof( Vec3 ) );
              stream.write( reinterpret_cast<const char*> ( Vec3uc(0, 255, 0).data() ), sizeof( Vec3uc ) );
            }
          }

          // Export pose priors as Blue points
          if (const sfm::ViewPriors *prior = dynamic_cast<sfm::ViewPriors*>(view.second.get()))
          {
            if (prior->b_use_pose_center_)
            {
              if (b_write_in_ascii)
              {
                stream
                  << prior->pose_center_(0) << ' '
                  << prior->pose_center_(1) << ' '
                  << prior->pose_center_(2) << ' '
                  << "0 0 255\n";
              }
              else
              {
                stream.write( reinterpret_cast<const char*> ( prior->pose_center_.data() ), sizeof( Vec3 ) );
                stream.write( reinterpret_cast<const char*> ( Vec3uc(0, 0, 255).data() ), sizeof( Vec3uc ) );
              }
            }
          }
        }
      }

      if (b_structure)
      {
        // Export structure points as White points
        const Landmarks & landmarks = sfm_data.GetLandmarks();
        for ( const auto & iterLandmarks : landmarks )
        {
          if (b_write_in_ascii)
          {
            stream
              << iterLandmarks.second.X(0) << ' '
              << iterLandmarks.second.X(1) << ' '
              << iterLandmarks.second.X(2) << ' '
              << "255 255 255\n";
          }
          else
          {
            stream.write( reinterpret_cast<const char*> ( iterLandmarks.second.X.data() ), sizeof( Vec3 ) );
            stream.write( reinterpret_cast<const char*> ( Vec3uc(255, 255, 255).data() ), sizeof( Vec3uc ) );
          }
        }
      }

      if (b_control_points)
      {
        // Export GCP as Red points
        const Landmarks & landmarks = sfm_data.GetControl_Points();
        for ( const auto & iterGCP : landmarks )
        {
          if (b_write_in_ascii)
          {
            stream
              << iterGCP.second.X(0) << ' '
              << iterGCP.second.X(1) << ' '
              << iterGCP.second.X(2) << ' '
              << "255 0 0\n";
          }
          else
          {
            stream.write( reinterpret_cast<const char*> ( iterGCP.second.X.data() ), sizeof( Vec3 ) );
            stream.write( reinterpret_cast<const char*> ( Vec3uc(255, 255, 255).data() ), sizeof( Vec3uc ) );
          }
        }
      }

      stream.flush();
      bOk = stream.good();
      stream.close();
  }
  return bOk;
}

} // namespace sfm
} // namespace openMVG

#endif // OPENMVG_SFM_SFM_DATA_IO_PLY_HPP
<|endoftext|>


<commit_before>#include "config.h"

#include "file_io_type_pel.hpp"

#include "utils.hpp"
#include "xyz/openbmc_project/Common/error.hpp"

#include <stdint.h>
#include <systemd/sd-bus.h>
#include <unistd.h>

#include <exception>
#include <filesystem>
#include <iostream>
#include <sdbusplus/server.hpp>
#include <vector>
#include <xyz/openbmc_project/Logging/Entry/server.hpp>

#include "libpldm/base.h"
#include "oem/ibm/libpldm/file_io.h"

namespace pldm
{
namespace responder
{

int PelHandler::readIntoMemory(uint32_t offset, uint32_t& length,
                               uint64_t address)
{
    static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
    static constexpr auto logInterface = "org.open_power.Logging.PEL";

    auto& bus = pldm::utils::DBusHandler::getBus();

    try
    {
        auto service =
            pldm::utils::DBusHandler().getService(logObjPath, logInterface);
        auto method = bus.new_method_call(service.c_str(), logObjPath,
                                          logInterface, "GetPEL");
        method.append(fileHandle);
        auto reply = bus.call(method);
        sdbusplus::message::unix_fd fd{};
        reply.read(fd);
        auto rc = transferFileData(fd, true, offset, length, address);
        return rc;
    }
    catch (const std::exception& e)
    {
        std::cerr << "GetPEL D-Bus call failed, PEL id = " << fileHandle
                  << ", error = " << e.what() << "\n";
        return PLDM_ERROR;
    }

    return PLDM_SUCCESS;
}

int PelHandler::read(uint32_t offset, uint32_t& length, Response& response)
{
    static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
    static constexpr auto logInterface = "org.open_power.Logging.PEL";
    auto& bus = pldm::utils::DBusHandler::getBus();

    try
    {
        auto service =
            pldm::utils::DBusHandler().getService(logObjPath, logInterface);
        auto method = bus.new_method_call(service.c_str(), logObjPath,
                                          logInterface, "GetPEL");
        method.append(fileHandle);
        auto reply = bus.call(method);
        sdbusplus::message::unix_fd fd{};
        reply.read(fd);
        std::cerr << "GetPEL D-Bus call done\n";
        off_t fileSize = lseek(fd, 0, SEEK_END);
        if (fileSize == -1)
        {
            std::cerr << "file seek failed";
            return PLDM_ERROR;
        }
        if (offset >= fileSize)
        {
            std::cerr << "Offset exceeds file size, OFFSET=" << offset
                      << " FILE_SIZE=" << fileSize << std::endl;
            return PLDM_DATA_OUT_OF_RANGE;
        }
        if (offset + length > fileSize)
        {
            length = fileSize - offset;
        }
        auto rc = lseek(fd, offset, SEEK_SET);
        if (rc == -1)
        {
            std::cerr << "file seek failed";
            return PLDM_ERROR;
        }
        size_t currSize = response.size();
        response.resize(currSize + length);
        auto filePos = reinterpret_cast<char*>(response.data());
        filePos += currSize;
        rc = ::read(fd, filePos, length);
        if (rc == -1)
        {
            std::cerr << "file read failed";
            return PLDM_ERROR;
        }
        if (rc != length)
        {
            std::cerr << "mismatch between number of characters to read and "
                      << "the length read, LENGTH=" << length << " COUNT=" << rc
                      << std::endl;
            return PLDM_ERROR;
        }
    }
    catch (const std::exception& e)
    {
        std::cerr << "GetPEL D-Bus call failed";
        return PLDM_ERROR;
    }
    return PLDM_SUCCESS;
}

int PelHandler::writeFromMemory(uint32_t offset, uint32_t length,
                                uint64_t address)
{
    char tmpFile[] = "/tmp/pel.XXXXXX";
    int fd = mkstemp(tmpFile);
    if (fd == -1)
    {
        std::cerr << "failed to create a temporary pel, ERROR=" << errno
                  << "\n";
        return PLDM_ERROR;
    }
    close(fd);
    fs::path path(tmpFile);

    auto rc = transferFileData(path, false, offset, length, address);
    if (rc == PLDM_SUCCESS)
    {
        rc = storePel(path.string());
    }
    fs::remove(path);
    return rc;
}

int PelHandler::fileAck(uint8_t /*fileStatus*/)
{
    static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
    static constexpr auto logInterface = "org.open_power.Logging.PEL";
    auto& bus = pldm::utils::DBusHandler::getBus();

    try
    {
        auto service =
            pldm::utils::DBusHandler().getService(logObjPath, logInterface);
        auto method = bus.new_method_call(service.c_str(), logObjPath,
                                          logInterface, "HostAck");
        method.append(fileHandle);
        bus.call_noreply(method);
    }
    catch (const std::exception& e)
    {
        std::cerr << "HostAck D-Bus call failed";
        return PLDM_ERROR;
    }

    return PLDM_SUCCESS;
}

int PelHandler::storePel(std::string&& pelFileName)
{
    static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
    static constexpr auto logInterface = "xyz.openbmc_project.Logging.Create";

    auto& bus = pldm::utils::DBusHandler::getBus();

    try
    {
        auto service =
            pldm::utils::DBusHandler().getService(logObjPath, logInterface);
        using namespace sdbusplus::xyz::openbmc_project::Logging::server;
        std::map<std::string, std::string> addlData{};
        addlData.emplace("RAWPEL", std::move(pelFileName));
        auto severity =
            sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
                sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
                    Error);

        auto method = bus.new_method_call(service.c_str(), logObjPath,
                                          logInterface, "Create");
        method.append("xyz.openbmc_project.Host.Error.Event", severity,
                      addlData);
        bus.call_noreply(method);
    }
    catch (const std::exception& e)
    {
        std::cerr << "failed to make a d-bus call to PEL daemon, ERROR="
                  << e.what() << "\n";
        return PLDM_ERROR;
    }

    return PLDM_SUCCESS;
}

} // namespace responder
} // namespace pldm
<commit_msg>oem-ibm: remove debug log in PEL read handler<commit_after>#include "config.h"

#include "file_io_type_pel.hpp"

#include "utils.hpp"
#include "xyz/openbmc_project/Common/error.hpp"

#include <stdint.h>
#include <systemd/sd-bus.h>
#include <unistd.h>

#include <exception>
#include <filesystem>
#include <iostream>
#include <sdbusplus/server.hpp>
#include <vector>
#include <xyz/openbmc_project/Logging/Entry/server.hpp>

#include "libpldm/base.h"
#include "oem/ibm/libpldm/file_io.h"

namespace pldm
{
namespace responder
{

int PelHandler::readIntoMemory(uint32_t offset, uint32_t& length,
                               uint64_t address)
{
    static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
    static constexpr auto logInterface = "org.open_power.Logging.PEL";

    auto& bus = pldm::utils::DBusHandler::getBus();

    try
    {
        auto service =
            pldm::utils::DBusHandler().getService(logObjPath, logInterface);
        auto method = bus.new_method_call(service.c_str(), logObjPath,
                                          logInterface, "GetPEL");
        method.append(fileHandle);
        auto reply = bus.call(method);
        sdbusplus::message::unix_fd fd{};
        reply.read(fd);
        auto rc = transferFileData(fd, true, offset, length, address);
        return rc;
    }
    catch (const std::exception& e)
    {
        std::cerr << "GetPEL D-Bus call failed, PEL id = " << fileHandle
                  << ", error = " << e.what() << "\n";
        return PLDM_ERROR;
    }

    return PLDM_SUCCESS;
}

int PelHandler::read(uint32_t offset, uint32_t& length, Response& response)
{
    static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
    static constexpr auto logInterface = "org.open_power.Logging.PEL";
    auto& bus = pldm::utils::DBusHandler::getBus();

    try
    {
        auto service =
            pldm::utils::DBusHandler().getService(logObjPath, logInterface);
        auto method = bus.new_method_call(service.c_str(), logObjPath,
                                          logInterface, "GetPEL");
        method.append(fileHandle);
        auto reply = bus.call(method);
        sdbusplus::message::unix_fd fd{};
        reply.read(fd);

        off_t fileSize = lseek(fd, 0, SEEK_END);
        if (fileSize == -1)
        {
            std::cerr << "file seek failed";
            return PLDM_ERROR;
        }
        if (offset >= fileSize)
        {
            std::cerr << "Offset exceeds file size, OFFSET=" << offset
                      << " FILE_SIZE=" << fileSize << std::endl;
            return PLDM_DATA_OUT_OF_RANGE;
        }
        if (offset + length > fileSize)
        {
            length = fileSize - offset;
        }
        auto rc = lseek(fd, offset, SEEK_SET);
        if (rc == -1)
        {
            std::cerr << "file seek failed";
            return PLDM_ERROR;
        }
        size_t currSize = response.size();
        response.resize(currSize + length);
        auto filePos = reinterpret_cast<char*>(response.data());
        filePos += currSize;
        rc = ::read(fd, filePos, length);
        if (rc == -1)
        {
            std::cerr << "file read failed";
            return PLDM_ERROR;
        }
        if (rc != length)
        {
            std::cerr << "mismatch between number of characters to read and "
                      << "the length read, LENGTH=" << length << " COUNT=" << rc
                      << std::endl;
            return PLDM_ERROR;
        }
    }
    catch (const std::exception& e)
    {
        std::cerr << "GetPEL D-Bus call failed";
        return PLDM_ERROR;
    }
    return PLDM_SUCCESS;
}

int PelHandler::writeFromMemory(uint32_t offset, uint32_t length,
                                uint64_t address)
{
    char tmpFile[] = "/tmp/pel.XXXXXX";
    int fd = mkstemp(tmpFile);
    if (fd == -1)
    {
        std::cerr << "failed to create a temporary pel, ERROR=" << errno
                  << "\n";
        return PLDM_ERROR;
    }
    close(fd);
    fs::path path(tmpFile);

    auto rc = transferFileData(path, false, offset, length, address);
    if (rc == PLDM_SUCCESS)
    {
        rc = storePel(path.string());
    }
    fs::remove(path);
    return rc;
}

int PelHandler::fileAck(uint8_t /*fileStatus*/)
{
    static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
    static constexpr auto logInterface = "org.open_power.Logging.PEL";
    auto& bus = pldm::utils::DBusHandler::getBus();

    try
    {
        auto service =
            pldm::utils::DBusHandler().getService(logObjPath, logInterface);
        auto method = bus.new_method_call(service.c_str(), logObjPath,
                                          logInterface, "HostAck");
        method.append(fileHandle);
        bus.call_noreply(method);
    }
    catch (const std::exception& e)
    {
        std::cerr << "HostAck D-Bus call failed";
        return PLDM_ERROR;
    }

    return PLDM_SUCCESS;
}

int PelHandler::storePel(std::string&& pelFileName)
{
    static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
    static constexpr auto logInterface = "xyz.openbmc_project.Logging.Create";

    auto& bus = pldm::utils::DBusHandler::getBus();

    try
    {
        auto service =
            pldm::utils::DBusHandler().getService(logObjPath, logInterface);
        using namespace sdbusplus::xyz::openbmc_project::Logging::server;
        std::map<std::string, std::string> addlData{};
        addlData.emplace("RAWPEL", std::move(pelFileName));
        auto severity =
            sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
                sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
                    Error);

        auto method = bus.new_method_call(service.c_str(), logObjPath,
                                          logInterface, "Create");
        method.append("xyz.openbmc_project.Host.Error.Event", severity,
                      addlData);
        bus.call_noreply(method);
    }
    catch (const std::exception& e)
    {
        std::cerr << "failed to make a d-bus call to PEL daemon, ERROR="
                  << e.what() << "\n";
        return PLDM_ERROR;
    }

    return PLDM_SUCCESS;
}

} // namespace responder
} // namespace pldm
<|endoftext|>


<commit_before>#include "dx11_video.h"
#include "dx11_painter.h"
#include "dx11_shader.h"
#include "dx11_texture.h"
#include "dx11_render_target.h"
#include "dx11_material_constant_buffer.h"

#include <windows.h>
#include <windowsx.h>
#include <d3d11.h>
#include <DXGI1_2.h>
#include <DXGI.h>
#include "dx11_loader.h"
#include "halley/support/logger.h"
#include "halley/support/debug.h"

#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "Dxgi.lib")

using namespace Halley;

DX11Video::DX11Video(SystemAPI& system)
	: system(system)
{}

void DX11Video::init()
{
	loader = std::make_unique<DX11Loader>(*this);
}

void DX11Video::deInit()
{
	loader.reset();
	releaseD3D();
}

void DX11Video::initD3D(Window& window)
{
	if (initialised) {
		return;
	}

	IDXGIFactory* factory;
	CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&factory));
	IDXGIAdapter* adapter;
	factory->EnumAdapters(0, &adapter);
	if (adapter) {
		DXGI_ADAPTER_DESC desc;
		adapter->GetDesc(&desc);
		Logger::logInfo("Using display adapter for DX11: " + String(desc.Description));
	}

	ID3D11DeviceContext* dc;
	D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0 };
	uint32_t flags = 0;
	if (Debug::isDebug()) {
		flags |= D3D11_CREATE_DEVICE_DEBUG;
	} else {
		flags |= D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
	}
	auto result = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, flags, featureLevels, 3, D3D11_SDK_VERSION, &device, nullptr, &dc);
	if (result != S_OK) {
		throw Exception("Unable to initialise DX11", HalleyExceptions::VideoPlugin);
	}
	dc->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&deviceContext));
	if (!dc) {
		throw Exception("Unable to initialise DX11.1", HalleyExceptions::VideoPlugin);
	}

	ID3D10Multithread* mt;
	device->QueryInterface(__uuidof(ID3D10Multithread), reinterpret_cast<void**>(&mt));
	if (mt) {
		mt->SetMultithreadProtected(true);
	}

	initSwapChain(window);

	initialised = true;
}

void DX11Video::initSwapChain(Window& window)
{
	if (swapChain) {
		swapChain->Release();
		swapChain = nullptr;
	}

	auto size = window.getWindowRect().getSize();
	const bool usingCoreWindow = window.getNativeHandleType() == "CoreWindow";

	IDXGIDevice2* pDXGIDevice;
	device->QueryInterface(__uuidof(IDXGIDevice2), reinterpret_cast<void **>(&pDXGIDevice));
	IDXGIAdapter * pDXGIAdapter;
	pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void **>(&pDXGIAdapter));
	IDXGIFactory2 * pIDXGIFactory;
	pDXGIAdapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast<void **>(&pIDXGIFactory));

	DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
	ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC1));
	swapChainDesc.Width = size.x;
	swapChainDesc.Height = size.y;
	swapChainDesc.BufferCount = 1;
	swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	swapChainDesc.BufferCount = 2;
	swapChainDesc.SampleDesc.Count = 1;

	if (usingCoreWindow) {
#if WINVER >= 0x0A00
		swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
#else
		swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
#endif
		swapChainDesc.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH;
		swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;

		IUnknown* coreWindow = reinterpret_cast<IUnknown*>(window.getNativeHandle());
		auto result = pIDXGIFactory->CreateSwapChainForCoreWindow(device, coreWindow, &swapChainDesc, nullptr, &swapChain);
		if (result != S_OK) {
			throw Exception("Unable to create swap chain for CoreWindow", HalleyExceptions::VideoPlugin);
		}
	} else {
		auto hWnd = reinterpret_cast<HWND>(window.getNativeHandle());
		auto result = pIDXGIFactory->CreateSwapChainForHwnd(device, hWnd, &swapChainDesc, nullptr, nullptr, &swapChain);
		if (result != S_OK) {
			throw Exception("Unable to create swap chain for HWND", HalleyExceptions::VideoPlugin);
		}
	}

	swapChainSize = size;

	initBackBuffer();
}

void DX11Video::initBackBuffer()
{
	if (backbuffer) {
		backbuffer->Release();
		backbuffer = nullptr;
	}

	ID3D11Texture2D *pBackBuffer;
    swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<LPVOID*>(&pBackBuffer));
    device->CreateRenderTargetView(pBackBuffer, nullptr, &backbuffer);
    pBackBuffer->Release();
}

void DX11Video::resizeSwapChain(Vector2i size)
{
	if (backbuffer) {
		backbuffer->Release();
		backbuffer = nullptr;
	}

	HRESULT result = swapChain->ResizeBuffers(0, size.x, size.y, DXGI_FORMAT_UNKNOWN, 0);
	if (result != S_OK) {
		throw Exception("Unable to resize swap chain", HalleyExceptions::VideoPlugin);
	}

	swapChainSize = size;

	initBackBuffer();
}

void DX11Video::releaseD3D()
{
	if (!initialised) {
		return;
	}

	if (backbuffer) {
		backbuffer->Release();
		backbuffer = nullptr;
	}

	if (swapChain) {
		swapChain->Release();
		swapChain = nullptr;
	}

	device->Release();
	deviceContext->Release();
	initialised = false;
}

void DX11Video::startRender()
{
}

void DX11Video::finishRender()
{
    swapChain->Present(useVsync ? 1 : 0, 0);
}

void DX11Video::setWindow(WindowDefinition&& windowDescriptor)
{
	if (!window) {
		window = system.createWindow(windowDescriptor);
		initD3D(*window);
	} else {
		window->update(windowDescriptor);
	}
}

const Window& DX11Video::getWindow() const
{
	return *window;
}

bool DX11Video::hasWindow() const
{
	return !!window;
}

void DX11Video::setVsync(bool vsync)
{
	useVsync = vsync;
}

std::unique_ptr<Texture> DX11Video::createTexture(Vector2i size)
{
	return std::make_unique<DX11Texture>(*this, size);
}

std::unique_ptr<Shader> DX11Video::createShader(const ShaderDefinition& definition)
{
	return std::make_unique<DX11Shader>(*this, definition);
}

std::unique_ptr<TextureRenderTarget> DX11Video::createTextureRenderTarget()
{
	return std::make_unique<DX11TextureRenderTarget>(*this);
}

std::unique_ptr<ScreenRenderTarget> DX11Video::createScreenRenderTarget()
{
	auto view = Rect4i(Vector2i(), window->getWindowRect().getSize());
	if (swapChainSize != view.getSize()) {
		resizeSwapChain(view.getSize());
	}

	return std::make_unique<DX11ScreenRenderTarget>(*this, view, backbuffer);
}

std::unique_ptr<MaterialConstantBuffer> DX11Video::createConstantBuffer()
{
	return std::make_unique<DX11MaterialConstantBuffer>(*this);
}

std::unique_ptr<Painter> DX11Video::makePainter(Resources& resources)
{
	return std::make_unique<DX11Painter>(*this, resources);
}

String DX11Video::getShaderLanguage()
{
	return "hlsl";
}

ID3D11Device& DX11Video::getDevice()
{
	return *device;
}

ID3D11DeviceContext1& DX11Video::getDeviceContext()
{
	return *deviceContext;
}

SystemAPI& DX11Video::getSystem()
{
	return system;
}

void* DX11Video::getImplementationPointer(const String& id)
{
	if (id == "ID3D11Device") {
		return static_cast<IUnknown*>(device);
	}
	return nullptr;
}
<commit_msg>Fix UWP >_><commit_after>#include "dx11_video.h"
#include "dx11_painter.h"
#include "dx11_shader.h"
#include "dx11_texture.h"
#include "dx11_render_target.h"
#include "dx11_material_constant_buffer.h"

#include <windows.h>
#include <windowsx.h>
#include <d3d11.h>
#include <DXGI1_2.h>
#include <DXGI.h>
#include "dx11_loader.h"
#include "halley/support/logger.h"
#include "halley/support/debug.h"

#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "Dxgi.lib")

using namespace Halley;

DX11Video::DX11Video(SystemAPI& system)
	: system(system)
{}

void DX11Video::init()
{
	loader = std::make_unique<DX11Loader>(*this);
}

void DX11Video::deInit()
{
	loader.reset();
	releaseD3D();
}

void DX11Video::initD3D(Window& window)
{
	if (initialised) {
		return;
	}

#ifndef WINDOWS_STORE
	{
		IDXGIFactory* factory;
		CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&factory));
		IDXGIAdapter* adapter;
		factory->EnumAdapters(0, &adapter);
		if (adapter) {
			DXGI_ADAPTER_DESC desc;
			adapter->GetDesc(&desc);
			Logger::logInfo("Using display adapter for DX11: " + String(desc.Description));
		}
	}
#endif

	ID3D11DeviceContext* dc;
	D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0 };
	uint32_t flags = 0;
	if (Debug::isDebug()) {
		flags |= D3D11_CREATE_DEVICE_DEBUG;
	} else {
		flags |= D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
	}
	auto result = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, flags, featureLevels, 3, D3D11_SDK_VERSION, &device, nullptr, &dc);
	if (result != S_OK) {
		throw Exception("Unable to initialise DX11", HalleyExceptions::VideoPlugin);
	}
	dc->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&deviceContext));
	if (!dc) {
		throw Exception("Unable to initialise DX11.1", HalleyExceptions::VideoPlugin);
	}

	ID3D10Multithread* mt;
	device->QueryInterface(__uuidof(ID3D10Multithread), reinterpret_cast<void**>(&mt));
	if (mt) {
		mt->SetMultithreadProtected(true);
	}

	initSwapChain(window);

	initialised = true;
}

void DX11Video::initSwapChain(Window& window)
{
	if (swapChain) {
		swapChain->Release();
		swapChain = nullptr;
	}

	auto size = window.getWindowRect().getSize();
	const bool usingCoreWindow = window.getNativeHandleType() == "CoreWindow";

	IDXGIDevice2* pDXGIDevice;
	device->QueryInterface(__uuidof(IDXGIDevice2), reinterpret_cast<void **>(&pDXGIDevice));
	IDXGIAdapter * pDXGIAdapter;
	pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void **>(&pDXGIAdapter));
	IDXGIFactory2 * pIDXGIFactory;
	pDXGIAdapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast<void **>(&pIDXGIFactory));

	DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
	ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC1));
	swapChainDesc.Width = size.x;
	swapChainDesc.Height = size.y;
	swapChainDesc.BufferCount = 1;
	swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	swapChainDesc.BufferCount = 2;
	swapChainDesc.SampleDesc.Count = 1;

	if (usingCoreWindow) {
#if WINVER >= 0x0A00
		swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
#else
		swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
#endif
		swapChainDesc.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH;
		swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;

		IUnknown* coreWindow = reinterpret_cast<IUnknown*>(window.getNativeHandle());
		auto result = pIDXGIFactory->CreateSwapChainForCoreWindow(device, coreWindow, &swapChainDesc, nullptr, &swapChain);
		if (result != S_OK) {
			throw Exception("Unable to create swap chain for CoreWindow", HalleyExceptions::VideoPlugin);
		}
	} else {
		auto hWnd = reinterpret_cast<HWND>(window.getNativeHandle());
		auto result = pIDXGIFactory->CreateSwapChainForHwnd(device, hWnd, &swapChainDesc, nullptr, nullptr, &swapChain);
		if (result != S_OK) {
			throw Exception("Unable to create swap chain for HWND", HalleyExceptions::VideoPlugin);
		}
	}

	swapChainSize = size;

	initBackBuffer();
}

void DX11Video::initBackBuffer()
{
	if (backbuffer) {
		backbuffer->Release();
		backbuffer = nullptr;
	}

	ID3D11Texture2D *pBackBuffer;
    swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<LPVOID*>(&pBackBuffer));
    device->CreateRenderTargetView(pBackBuffer, nullptr, &backbuffer);
    pBackBuffer->Release();
}

void DX11Video::resizeSwapChain(Vector2i size)
{
	if (backbuffer) {
		backbuffer->Release();
		backbuffer = nullptr;
	}

	HRESULT result = swapChain->ResizeBuffers(0, size.x, size.y, DXGI_FORMAT_UNKNOWN, 0);
	if (result != S_OK) {
		throw Exception("Unable to resize swap chain", HalleyExceptions::VideoPlugin);
	}

	swapChainSize = size;

	initBackBuffer();
}

void DX11Video::releaseD3D()
{
	if (!initialised) {
		return;
	}

	if (backbuffer) {
		backbuffer->Release();
		backbuffer = nullptr;
	}

	if (swapChain) {
		swapChain->Release();
		swapChain = nullptr;
	}

	device->Release();
	deviceContext->Release();
	initialised = false;
}

void DX11Video::startRender()
{
}

void DX11Video::finishRender()
{
    swapChain->Present(useVsync ? 1 : 0, 0);
}

void DX11Video::setWindow(WindowDefinition&& windowDescriptor)
{
	if (!window) {
		window = system.createWindow(windowDescriptor);
		initD3D(*window);
	} else {
		window->update(windowDescriptor);
	}
}

const Window& DX11Video::getWindow() const
{
	return *window;
}

bool DX11Video::hasWindow() const
{
	return !!window;
}

void DX11Video::setVsync(bool vsync)
{
	useVsync = vsync;
}

std::unique_ptr<Texture> DX11Video::createTexture(Vector2i size)
{
	return std::make_unique<DX11Texture>(*this, size);
}

std::unique_ptr<Shader> DX11Video::createShader(const ShaderDefinition& definition)
{
	return std::make_unique<DX11Shader>(*this, definition);
}

std::unique_ptr<TextureRenderTarget> DX11Video::createTextureRenderTarget()
{
	return std::make_unique<DX11TextureRenderTarget>(*this);
}

std::unique_ptr<ScreenRenderTarget> DX11Video::createScreenRenderTarget()
{
	auto view = Rect4i(Vector2i(), window->getWindowRect().getSize());
	if (swapChainSize != view.getSize()) {
		resizeSwapChain(view.getSize());
	}

	return std::make_unique<DX11ScreenRenderTarget>(*this, view, backbuffer);
}

std::unique_ptr<MaterialConstantBuffer> DX11Video::createConstantBuffer()
{
	return std::make_unique<DX11MaterialConstantBuffer>(*this);
}

std::unique_ptr<Painter> DX11Video::makePainter(Resources& resources)
{
	return std::make_unique<DX11Painter>(*this, resources);
}

String DX11Video::getShaderLanguage()
{
	return "hlsl";
}

ID3D11Device& DX11Video::getDevice()
{
	return *device;
}

ID3D11DeviceContext1& DX11Video::getDeviceContext()
{
	return *deviceContext;
}

SystemAPI& DX11Video::getSystem()
{
	return system;
}

void* DX11Video::getImplementationPointer(const String& id)
{
	if (id == "ID3D11Device") {
		return static_cast<IUnknown*>(device);
	}
	return nullptr;
}
<|endoftext|>