<commit_before>
// hack, see http://stackoverflow.com/questions/12523122/what-is-glibcxx-use-nanosleep-all-about
#define _GLIBCXX_USE_NANOSLEEP 1
#include <chrono>
#include <thread>
#include <linux/i2c-dev.h>
//#include <linux/i2c.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <tinyxml.h>
#include <iostream>
#include <sstream>
#include <map>

#include "arro.pb.h"
#include "Trace.h"
#include "INodeContext.h"

/**
 * The PCA9685 PWM generator (used on the Esc Hat) has four main layers of structure:
 *
 * - a 25MHz internal clock
 * - a prescaler that emits 1 tick for every N ticks of the 25MHz clock
 * - a 12-bit counter triggered by the prescaler
 * - a set of comparison registers for each output channel
 *
 * The 12-bit counter resets to zero every 4096 ticks of the prescaler, and the number
 * of times that happens per second is the PWM frequency. See setPWMFreq().
 *
 * The output goes high when the 12-bit clock equals the value in the first comparison
 * register, and goes low when the 12-bit clock equals the value in the second comparison register.
 * See setPWM()
 *
 */
namespace Arro {
    class NodeEsc: public INodeDefinition {
    public:

        /**
         * Constructor
         *
         * \param d The Process node instance.
         * \param name Name of this node.
         * \param params List of parameters passed to this node.
         */
        NodeEsc(INodeContext* d, const std::string& name, StringMap& params, TiXmlElement*);
        virtual ~NodeEsc() {};

        // Copy and assignment is not supported.
        NodeEsc(const NodeEsc&) = delete;
        NodeEsc& operator=(const NodeEsc& other) = delete;

        virtual void finishConstruction();

        /**
         * Make the node execute a processing cycle.
         */
        void runCycle();

    private:
        class PWM {
        public:
            PWM(double freq, int address = 0x40, const char* filename = "/dev/i2c-1");
            // Esc(int address = 0x60, const char* filename = "/dev/i2c-1");
            virtual ~PWM() {};
            void setPulse(int ch, int val);

            /**
             * Read 1 byte from specified register.
             *
             * \param command Register to read from.
             */
            unsigned char i2c_readU8(unsigned char command);

            /**
             * Write 1 byte to register.
             *
             * \param command Register to write to.
             */
            void i2c_write8(unsigned char command, unsigned short value);

            /**
             * Sets a single PWM channel
             *
             * \param channel PWM channel
             * \param on  On?
             * \param off Offset?
             */
            void setPWM(int channel, int on, int off);

            /**
             * Sets the PWM frequency.
             *
             * \param freq Frequency.
             */
            void setPWMFreq(double freq);

        private:
            Trace m_trace;
            double m_prescaleval;
            char m_filename[40];
            int m_addr;           // The I2C address
            int m_file;
        };

        Trace m_trace;
        INodeContext* m_elemBlock;
        double m_speed;
        int m_Ch;
        int m_maxPulse;
        int m_minPulse;
        int m_zeroPulse;

        INodeContext::ItRef m_speedPad;

        static PWM* m_pPWM;
    };
}

using namespace std;
using namespace Arro;
using namespace arro;

// To stub out
#ifndef RPI
    #define i2c_smbus_write_byte_data(file, mode, data) 1
    #define i2c_smbus_read_byte_data(file, command) 1
#endif

// Registers/etc.
#define  __SUBADR1             0x02
#define  __SUBADR2             0x03
#define  __SUBADR3             0x04
#define  __MODE1               0x00
#define  __PRESCALE            0xFE
#define  __LED0_ON_L           0x06
#define  __LED0_ON_H           0x07
#define  __LED0_OFF_L          0x08
#define  __LED0_OFF_H          0x09
#define  __ALLLED_ON_L         0xFA
#define  __ALLLED_ON_H         0xFB
#define  __ALLLED_OFF_L        0xFC
#define  __ALLLED_OFF_H        0xFD

static RegisterMe<NodeEsc> registerMe("Esc");

unsigned char
NodeEsc::PWM::i2c_readU8(unsigned char command) {
    // Using I2C Read, equivalent of i2c_smbus_read_byte(file)
    // if (read(file, buf, 1) != 1) {
    __s32 ret  = i2c_smbus_read_byte_data(m_file, command);
    m_trace.println("---- i2c_read returned ", ret);
    if (ret == -1) {
        m_trace.fatal("Failed i2c_read errno", errno);
    } else {
        // buf[0] contains the read byte
    }
    return ret;
}

void
NodeEsc::PWM::i2c_write8(unsigned char command, unsigned short value) {
    // Using I2C Write, equivalent of
    // i2c_smbus_write_word_data(file, register, 0x6543)

    // unsigned char buf[10];
    // buf[0] = register;
    // buf[1] = value & 0x000000FF; // 0x43;
    // value = value >> 8;
    // buf[2] = value & 0x000000FF; // 0x65;
    // if (write(file, buf, 3) !=3) {

    __s32 ret = i2c_smbus_write_byte_data(m_file, command, value);
    m_trace.println("---- i2c_write8 Wrote", value);
    m_trace.println("to ", (int)command);
    if (ret == -1) {
        m_trace.fatal("Failed i2c_write8 errno", errno);
    }
}

void
NodeEsc::PWM::setPWM(int channel, int on, int off) {
    i2c_write8(__LED0_ON_L+4*channel, on & 0xFF);
    i2c_write8(__LED0_ON_H+4*channel, on >> 8);
    i2c_write8(__LED0_OFF_L+4*channel, off & 0xFF);
    i2c_write8(__LED0_OFF_H+4*channel, off >> 8);
}

void
NodeEsc::PWM::setPWMFreq(double freq) {
    m_prescaleval = 25000000.0;   // 25MHz
    m_prescaleval /= 4096.0;      // 12-bit
    m_prescaleval /= float(freq);
    m_prescaleval -= 1.0;

    m_trace.println("Setting PWM frequency to %d Hz", freq);
    m_trace.println("Estimated pre-scale: %d", m_prescaleval);

    int prescale = (int)(m_prescaleval + 0.5);
    m_trace.println("Final pre-scale", prescale);

    int oldmode = i2c_readU8(__MODE1);
    int newmode = (oldmode & 0x7F) | 0x10;  // sleep
    i2c_write8(__MODE1, newmode);           // go to sleep
    i2c_write8(__PRESCALE, prescale);
    i2c_write8(__MODE1, oldmode);
    //time.sleep(0.005)
    std::chrono::milliseconds timespan(5);
    std::this_thread::sleep_for(timespan);
    i2c_write8(__MODE1, oldmode | 0x80);
}

NodeEsc::PWM::PWM(double freq, int address, const char* filename):
    m_trace("Esc", true),
    m_prescaleval(0),
    m_addr(address){

// To stub out
#ifdef RPI
    if ((m_file = open(filename,O_RDWR)) < 0) {
        m_trace.fatal("Failed to open the bus errno", errno);
    }

    if (ioctl(m_file,I2C_SLAVE,m_addr) < 0) {
        m_trace.fatal("Failed to acquire bus access and/or talk to slave");
    }
#endif
    /* Reseting PCA9685 */
    i2c_smbus_write_byte_data(m_file, __MODE1, 0x00);

    setPWMFreq(freq);

}

void
NodeEsc::PWM::setPulse(int ch, int val) {
    setPWM(ch, 0, val);
}

NodeEsc::PWM* NodeEsc::m_pPWM = nullptr;

/*
def __init__(self, controller=None,
                   max_pulse=300,
                   min_pulse=490,
                   zero_pulse=350):

    self.controller = controller
    self.max_pulse = max_pulse
    self.min_pulse = min_pulse
    self.zero_pulse = zero_pulse

    #send zero pulse to calibrate ESC
    print("Init ESC")
    self.controller.set_pulse(self.max_pulse)
    time.sleep(0.01)
    self.controller.set_pulse(self.min_pulse)
    time.sleep(0.01)
    self.controller.set_pulse(self.zero_pulse)
    time.sleep(1)
*/

NodeEsc::NodeEsc(INodeContext* d, const string& /*name*/, StringMap& /* params */, TiXmlElement*):
    m_trace("NodeEsc", true),
    m_elemBlock(d),
    m_speed(0),
    m_Ch(0),
    m_speedPad{nullptr}
    {

    m_Ch = stod(d->getParameter("Channel"));
    int freq = stod(d->getParameter("Freq"));
    m_maxPulse = stod(d->getParameter("MaxPulse"));
    m_minPulse = stod(d->getParameter("MinPulse"));
    m_zeroPulse = stod(d->getParameter("ZeroPulse"));

    if(!m_pPWM) {
        m_pPWM = new PWM((float)freq);
    }

    // Init ESC
    m_trace.println("Init ESC");
    std::chrono::milliseconds timespan(10);
    m_pPWM->setPulse(m_Ch, m_maxPulse);
    std::this_thread::sleep_for(timespan);
    m_pPWM->setPulse(m_Ch, m_minPulse);
    std::this_thread::sleep_for(timespan);
    m_pPWM->setPulse(m_Ch, m_zeroPulse);
    std::chrono::milliseconds timespan1(1000);
    std::this_thread::sleep_for(timespan1);
}

void
NodeEsc::finishConstruction() {
    m_trace.println("finishConstruction");

    m_speedPad = m_elemBlock->begin(m_elemBlock->getInputPad("speed"), 0, INodeContext::DELTA);

}

void
NodeEsc::runCycle() {

    MessageBuf m1;
    if(m_speedPad->getNext(m1)) {
        Value* speed = new Value();
        speed->ParseFromString(m1->c_str());

        m_speed = speed->value();

        m_trace.println(string("NodeEsc speed = ") + to_string((long double)m_speed));

        m_pPWM->setPulse(m_Ch, m_speed);
    }
}
<commit_msg>Fix ESC speed control<commit_after>
// hack, see http://stackoverflow.com/questions/12523122/what-is-glibcxx-use-nanosleep-all-about
#define _GLIBCXX_USE_NANOSLEEP 1
#include <chrono>
#include <thread>
#include <linux/i2c-dev.h>
//#include <linux/i2c.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <tinyxml.h>
#include <iostream>
#include <sstream>
#include <map>

#include "arro.pb.h"
#include "Trace.h"
#include "INodeContext.h"

/**
 * The PCA9685 PWM generator (used on the Esc Hat) has four main layers of structure:
 *
 * - a 25MHz internal clock
 * - a prescaler that emits 1 tick for every N ticks of the 25MHz clock
 * - a 12-bit counter triggered by the prescaler
 * - a set of comparison registers for each output channel
 *
 * The 12-bit counter resets to zero every 4096 ticks of the prescaler, and the number
 * of times that happens per second is the PWM frequency. See setPWMFreq().
 *
 * The output goes high when the 12-bit clock equals the value in the first comparison
 * register, and goes low when the 12-bit clock equals the value in the second comparison register.
 * See setPWM()
 *
 */
namespace Arro {
    class NodeEsc: public INodeDefinition {
    public:

        /**
         * Constructor
         *
         * \param d The Process node instance.
         * \param name Name of this node.
         * \param params List of parameters passed to this node.
         */
        NodeEsc(INodeContext* d, const std::string& name, StringMap& params, TiXmlElement*);
        virtual ~NodeEsc() {};

        // Copy and assignment is not supported.
        NodeEsc(const NodeEsc&) = delete;
        NodeEsc& operator=(const NodeEsc& other) = delete;

        virtual void finishConstruction();

        /**
         * Make the node execute a processing cycle.
         */
        void runCycle();

    private:
        class PWM {
        public:
            PWM(double freq, int address = 0x40, const char* filename = "/dev/i2c-1");
            // Esc(int address = 0x60, const char* filename = "/dev/i2c-1");
            virtual ~PWM() {};
            void setPulse(int ch, int val);

            /**
             * Read 1 byte from specified register.
             *
             * \param command Register to read from.
             */
            unsigned char i2c_readU8(unsigned char command);

            /**
             * Write 1 byte to register.
             *
             * \param command Register to write to.
             */
            void i2c_write8(unsigned char command, unsigned short value);

            /**
             * Sets a single PWM channel
             *
             * \param channel PWM channel
             * \param on  On?
             * \param off Offset?
             */
            void setPWM(int channel, int on, int off);

            /**
             * Sets the PWM frequency.
             *
             * \param freq Frequency.
             */
            void setPWMFreq(double freq);

        private:
            Trace m_trace;
            double m_prescaleval;
            char m_filename[40];
            int m_addr;           // The I2C address
            int m_file;
        };

        Trace m_trace;
        INodeContext* m_elemBlock;
        int m_speed;
        int m_Ch;
        int m_maxPulse;
        int m_minPulse;
        int m_zeroPulse;

        INodeContext::ItRef m_speedPad;

        static PWM* m_pPWM;
    };
}

using namespace std;
using namespace Arro;
using namespace arro;

// To stub out
#ifndef RPI
    #define i2c_smbus_write_byte_data(file, mode, data) 1
    #define i2c_smbus_read_byte_data(file, command) 1
#endif

// Registers/etc.
#define  __SUBADR1             0x02
#define  __SUBADR2             0x03
#define  __SUBADR3             0x04
#define  __MODE1               0x00
#define  __PRESCALE            0xFE
#define  __LED0_ON_L           0x06
#define  __LED0_ON_H           0x07
#define  __LED0_OFF_L          0x08
#define  __LED0_OFF_H          0x09
#define  __ALLLED_ON_L         0xFA
#define  __ALLLED_ON_H         0xFB
#define  __ALLLED_OFF_L        0xFC
#define  __ALLLED_OFF_H        0xFD

static RegisterMe<NodeEsc> registerMe("Esc");

unsigned char
NodeEsc::PWM::i2c_readU8(unsigned char command) {
    // Using I2C Read, equivalent of i2c_smbus_read_byte(file)
    // if (read(file, buf, 1) != 1) {
    __s32 ret  = i2c_smbus_read_byte_data(m_file, command);
    m_trace.println("---- i2c_read returned ", ret);
    if (ret == -1) {
        m_trace.fatal("Failed i2c_read errno", errno);
    } else {
        // buf[0] contains the read byte
    }
    return ret;
}

void
NodeEsc::PWM::i2c_write8(unsigned char command, unsigned short value) {
    // Using I2C Write, equivalent of
    // i2c_smbus_write_word_data(file, register, 0x6543)

    // unsigned char buf[10];
    // buf[0] = register;
    // buf[1] = value & 0x000000FF; // 0x43;
    // value = value >> 8;
    // buf[2] = value & 0x000000FF; // 0x65;
    // if (write(file, buf, 3) !=3) {

    __s32 ret = i2c_smbus_write_byte_data(m_file, command, value);
    m_trace.println("---- i2c_write8 Wrote", value);
    m_trace.println("to ", (int)command);
    if (ret == -1) {
        m_trace.fatal("Failed i2c_write8 errno", errno);
    }
}

void
NodeEsc::PWM::setPWM(int channel, int on, int off) {
    i2c_write8(__LED0_ON_L+4*channel, on & 0xFF);
    i2c_write8(__LED0_ON_H+4*channel, on >> 8);
    i2c_write8(__LED0_OFF_L+4*channel, off & 0xFF);
    i2c_write8(__LED0_OFF_H+4*channel, off >> 8);
}

void
NodeEsc::PWM::setPWMFreq(double freq) {
    m_prescaleval = 25000000.0;   // 25MHz
    m_prescaleval /= 4096.0;      // 12-bit
    m_prescaleval /= float(freq);
    m_prescaleval -= 1.0;

    m_trace.println("Setting PWM frequency to %d Hz", freq);
    m_trace.println("Estimated pre-scale: %d", m_prescaleval);

    int prescale = (int)(m_prescaleval + 0.5);
    m_trace.println("Final pre-scale", prescale);

    int oldmode = i2c_readU8(__MODE1);
    int newmode = (oldmode & 0x7F) | 0x10;  // sleep
    i2c_write8(__MODE1, newmode);           // go to sleep
    i2c_write8(__PRESCALE, prescale);
    i2c_write8(__MODE1, oldmode);
    //time.sleep(0.005)
    std::chrono::milliseconds timespan(5);
    std::this_thread::sleep_for(timespan);
    i2c_write8(__MODE1, oldmode | 0x80);
}

NodeEsc::PWM::PWM(double freq, int address, const char* filename):
    m_trace("Esc", true),
    m_prescaleval(0),
    m_addr(address){

// To stub out
#ifdef RPI
    if ((m_file = open(filename,O_RDWR)) < 0) {
        m_trace.fatal("Failed to open the bus errno", errno);
    }

    if (ioctl(m_file,I2C_SLAVE,m_addr) < 0) {
        m_trace.fatal("Failed to acquire bus access and/or talk to slave");
    }
#endif
    /* Reseting PCA9685 */
    i2c_smbus_write_byte_data(m_file, __MODE1, 0x00);

    setPWMFreq(freq);

}

void
NodeEsc::PWM::setPulse(int ch, int val) {
    setPWM(ch, 0, val);
}

NodeEsc::PWM* NodeEsc::m_pPWM = nullptr;

/*
def __init__(self, controller=None,
                   max_pulse=300,
                   min_pulse=490,
                   zero_pulse=350):

    self.controller = controller
    self.max_pulse = max_pulse
    self.min_pulse = min_pulse
    self.zero_pulse = zero_pulse

    #send zero pulse to calibrate ESC
    print("Init ESC")
    self.controller.set_pulse(self.max_pulse)
    time.sleep(0.01)
    self.controller.set_pulse(self.min_pulse)
    time.sleep(0.01)
    self.controller.set_pulse(self.zero_pulse)
    time.sleep(1)
*/

NodeEsc::NodeEsc(INodeContext* d, const string& /*name*/, StringMap& /* params */, TiXmlElement*):
    m_trace("NodeEsc", true),
    m_elemBlock(d),
    m_speed(0),
    m_Ch(0),
    m_speedPad{nullptr}
{

    m_Ch = stod(d->getParameter("Channel"));
    int freq = stod(d->getParameter("Freq"));
    m_maxPulse = stod(d->getParameter("MaxPulse"));
    m_minPulse = stod(d->getParameter("MinPulse"));
    m_zeroPulse = stod(d->getParameter("ZeroPulse"));

    if(!m_pPWM) {
        m_pPWM = new PWM((float)freq);
    }

    // Init ESC
    m_trace.println("Init ESC");
    std::chrono::milliseconds timespan(10);
    m_pPWM->setPulse(m_Ch, m_maxPulse);
    std::this_thread::sleep_for(timespan);
    m_pPWM->setPulse(m_Ch, m_minPulse);
    std::this_thread::sleep_for(timespan);
    m_pPWM->setPulse(m_Ch, m_zeroPulse);
    std::chrono::milliseconds timespan1(1000);
    std::this_thread::sleep_for(timespan1);
}

void
NodeEsc::finishConstruction() {
    m_trace.println("finishConstruction");

    m_speedPad = m_elemBlock->begin(m_elemBlock->getInputPad("speed"), 0, INodeContext::DELTA);

}

void
NodeEsc::runCycle() {

    MessageBuf m1;
    if(m_speedPad->getNext(m1)) {
        Value* speed = new Value();
        speed->ParseFromString(m1->c_str());

        m_speed = speed->value();

        // Limit speed
        if(m_speed > 0) {
            m_speed = std::min(m_speed, 30);
        }
        else
        {
            m_speed = std::max(m_speed, -30);
        }
        m_speed += m_zeroPulse;

        m_trace.println(string("NodeEsc speed = ") + to_string(m_speed));

        m_pPWM->setPulse(m_Ch, m_speed);
    }
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2013 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/audio_device/android/audio_manager_jni.h"

#include <assert.h>

#include "webrtc/system_wrappers/interface/trace.h"

namespace {

class AttachThreadScoped {
 public:
  explicit AttachThreadScoped(JavaVM* jvm)
      : attached_(false), jvm_(jvm), env_(NULL) {
    jint ret_val = jvm->GetEnv(reinterpret_cast<void**>(&env_),
                               REQUIRED_JNI_VERSION);
    if (ret_val == JNI_EDETACHED) {
      // Attach the thread to the Java VM.
      ret_val = jvm_->AttachCurrentThread(&env_, NULL);
      attached_ = ret_val > 0;
      assert(attached_);
    }
  }
  ~AttachThreadScoped() {
    if (attached_ && (jvm_->DetachCurrentThread() < 0)) {
      assert(false);
    }
  }

  JNIEnv* env() { return env_; }

 private:
  bool attached_;
  JavaVM* jvm_;
  JNIEnv* env_;
};

}  // namespace

namespace webrtc {

static JavaVM* g_jvm_ = NULL;
static JNIEnv* g_jni_env_ = NULL;
static jobject g_context_ = NULL;
static jclass g_audio_manager_class_ = NULL;
static jobject g_audio_manager_ = NULL;

AudioManagerJni::AudioManagerJni()
    : low_latency_supported_(false),
      native_output_sample_rate_(0),
      native_buffer_size_(0) {
  if (!HasDeviceObjects()) {
    assert(false);
  }
  AttachThreadScoped ats(g_jvm_);
  JNIEnv* env = ats.env();
  assert(env && "Unsupported JNI version!");
  CreateInstance(env);
  // Pre-store device specific values.
  SetLowLatencySupported(env);
  SetNativeOutputSampleRate(env);
  SetNativeFrameSize(env);
}

void AudioManagerJni::SetAndroidAudioDeviceObjects(void* jvm, void* env,
                                                   void* context) {
  assert(jvm);
  assert(env);
  assert(context);

  // Store global Java VM variables to be accessed by API calls.
  g_jvm_ = reinterpret_cast<JavaVM*>(jvm);
  g_jni_env_ = reinterpret_cast<JNIEnv*>(env);
  g_context_ = g_jni_env_->NewGlobalRef(reinterpret_cast<jobject>(context));

  // FindClass must be made in this function since this function's contract
  // requires it to be called by a Java thread.
  // See
  // http://developer.android.com/training/articles/perf-jni.html#faq_FindClass
  // as to why this is necessary.
  // Get the AudioManagerAndroid class object.
  jclass javaAmClassLocal = g_jni_env_->FindClass(
      "org/webrtc/voiceengine/AudioManagerAndroid");
  assert(javaAmClassLocal);

  // Create a global reference such that the class object is not recycled by
  // the garbage collector.
  g_audio_manager_class_ = reinterpret_cast<jclass>(
      g_jni_env_->NewGlobalRef(javaAmClassLocal));
  assert(g_audio_manager_class_);
}

void AudioManagerJni::ClearAndroidAudioDeviceObjects() {
  g_jni_env_->DeleteGlobalRef(g_audio_manager_class_);
  g_audio_manager_class_ = NULL;
  g_jni_env_->DeleteGlobalRef(g_context_);
  g_context_ = NULL;
  g_jni_env_->DeleteGlobalRef(g_audio_manager_);
  g_audio_manager_ = NULL;
  g_jni_env_ = NULL;
  g_jvm_ = NULL;
}

void AudioManagerJni::SetLowLatencySupported(JNIEnv* env) {
  jmethodID id = LookUpMethodId(env, "isAudioLowLatencySupported", "()Z");
  low_latency_supported_ = env->CallBooleanMethod(g_audio_manager_, id);
}

void AudioManagerJni::SetNativeOutputSampleRate(JNIEnv* env) {
  jmethodID id = LookUpMethodId(env, "getNativeOutputSampleRate", "()I");
  native_output_sample_rate_ = env->CallIntMethod(g_audio_manager_, id);
}

void AudioManagerJni::SetNativeFrameSize(JNIEnv* env) {
  jmethodID id = LookUpMethodId(env,
                                "getAudioLowLatencyOutputFrameSize", "()I");
  native_buffer_size_ = env->CallIntMethod(g_audio_manager_, id);
}

bool AudioManagerJni::HasDeviceObjects() {
  return g_jvm_ && g_jni_env_ && g_context_ && g_audio_manager_class_;
}

jmethodID AudioManagerJni::LookUpMethodId(JNIEnv* env,
                                          const char* method_name,
                                          const char* method_signature) {
  jmethodID ret_val = env->GetMethodID(g_audio_manager_class_, method_name,
                                       method_signature);
  assert(ret_val);
  return ret_val;
}

void AudioManagerJni::CreateInstance(JNIEnv* env) {
  // Get the method ID for the constructor taking Context.
  jmethodID id = LookUpMethodId(env, "<init>", "(Landroid/content/Context;)V");
  g_audio_manager_ = env->NewObject(g_audio_manager_class_, id, g_context_);
  // Create a global reference so that the instance is accessible until no
  // longer needed.
  g_audio_manager_ = env->NewGlobalRef(g_audio_manager_);
  assert(g_audio_manager_);
}

}  // namespace webrtc
<commit_msg>Android OpenSL: Fixes faulty assertion in jni-code.<commit_after>/*
 *  Copyright (c) 2013 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/audio_device/android/audio_manager_jni.h"

#include <assert.h>

#include "webrtc/system_wrappers/interface/trace.h"

namespace {

class AttachThreadScoped {
 public:
  explicit AttachThreadScoped(JavaVM* jvm)
      : attached_(false), jvm_(jvm), env_(NULL) {
    jint ret_val = jvm->GetEnv(reinterpret_cast<void**>(&env_),
                               REQUIRED_JNI_VERSION);
    if (ret_val == JNI_EDETACHED) {
      // Attach the thread to the Java VM.
      ret_val = jvm_->AttachCurrentThread(&env_, NULL);
      attached_ = ret_val == JNI_OK;
      assert(attached_);
    }
  }
  ~AttachThreadScoped() {
    if (attached_ && (jvm_->DetachCurrentThread() < 0)) {
      assert(false);
    }
  }

  JNIEnv* env() { return env_; }

 private:
  bool attached_;
  JavaVM* jvm_;
  JNIEnv* env_;
};

}  // namespace

namespace webrtc {

static JavaVM* g_jvm_ = NULL;
static JNIEnv* g_jni_env_ = NULL;
static jobject g_context_ = NULL;
static jclass g_audio_manager_class_ = NULL;
static jobject g_audio_manager_ = NULL;

AudioManagerJni::AudioManagerJni()
    : low_latency_supported_(false),
      native_output_sample_rate_(0),
      native_buffer_size_(0) {
  if (!HasDeviceObjects()) {
    assert(false);
  }
  AttachThreadScoped ats(g_jvm_);
  JNIEnv* env = ats.env();
  assert(env && "Unsupported JNI version!");
  CreateInstance(env);
  // Pre-store device specific values.
  SetLowLatencySupported(env);
  SetNativeOutputSampleRate(env);
  SetNativeFrameSize(env);
}

void AudioManagerJni::SetAndroidAudioDeviceObjects(void* jvm, void* env,
                                                   void* context) {
  assert(jvm);
  assert(env);
  assert(context);

  // Store global Java VM variables to be accessed by API calls.
  g_jvm_ = reinterpret_cast<JavaVM*>(jvm);
  g_jni_env_ = reinterpret_cast<JNIEnv*>(env);
  g_context_ = g_jni_env_->NewGlobalRef(reinterpret_cast<jobject>(context));

  // FindClass must be made in this function since this function's contract
  // requires it to be called by a Java thread.
  // See
  // http://developer.android.com/training/articles/perf-jni.html#faq_FindClass
  // as to why this is necessary.
  // Get the AudioManagerAndroid class object.
  jclass javaAmClassLocal = g_jni_env_->FindClass(
      "org/webrtc/voiceengine/AudioManagerAndroid");
  assert(javaAmClassLocal);

  // Create a global reference such that the class object is not recycled by
  // the garbage collector.
  g_audio_manager_class_ = reinterpret_cast<jclass>(
      g_jni_env_->NewGlobalRef(javaAmClassLocal));
  assert(g_audio_manager_class_);
}

void AudioManagerJni::ClearAndroidAudioDeviceObjects() {
  g_jni_env_->DeleteGlobalRef(g_audio_manager_class_);
  g_audio_manager_class_ = NULL;
  g_jni_env_->DeleteGlobalRef(g_context_);
  g_context_ = NULL;
  g_jni_env_->DeleteGlobalRef(g_audio_manager_);
  g_audio_manager_ = NULL;
  g_jni_env_ = NULL;
  g_jvm_ = NULL;
}

void AudioManagerJni::SetLowLatencySupported(JNIEnv* env) {
  jmethodID id = LookUpMethodId(env, "isAudioLowLatencySupported", "()Z");
  low_latency_supported_ = env->CallBooleanMethod(g_audio_manager_, id);
}

void AudioManagerJni::SetNativeOutputSampleRate(JNIEnv* env) {
  jmethodID id = LookUpMethodId(env, "getNativeOutputSampleRate", "()I");
  native_output_sample_rate_ = env->CallIntMethod(g_audio_manager_, id);
}

void AudioManagerJni::SetNativeFrameSize(JNIEnv* env) {
  jmethodID id = LookUpMethodId(env,
                                "getAudioLowLatencyOutputFrameSize", "()I");
  native_buffer_size_ = env->CallIntMethod(g_audio_manager_, id);
}

bool AudioManagerJni::HasDeviceObjects() {
  return g_jvm_ && g_jni_env_ && g_context_ && g_audio_manager_class_;
}

jmethodID AudioManagerJni::LookUpMethodId(JNIEnv* env,
                                          const char* method_name,
                                          const char* method_signature) {
  jmethodID ret_val = env->GetMethodID(g_audio_manager_class_, method_name,
                                       method_signature);
  assert(ret_val);
  return ret_val;
}

void AudioManagerJni::CreateInstance(JNIEnv* env) {
  // Get the method ID for the constructor taking Context.
  jmethodID id = LookUpMethodId(env, "<init>", "(Landroid/content/Context;)V");
  g_audio_manager_ = env->NewObject(g_audio_manager_class_, id, g_context_);
  // Create a global reference so that the instance is accessible until no
  // longer needed.
  g_audio_manager_ = env->NewGlobalRef(g_audio_manager_);
  assert(g_audio_manager_);
}

}  // namespace webrtc
<|endoftext|>


<commit_before><commit_msg>Set ITS chi2 in the coverion from AliVTrack to AliESDtrack<commit_after><|endoftext|>


<commit_before>/*****************************************************************************\
 *                        ANALYSIS PERFORMANCE TOOLS                         *
 *                               libparaver-api                              *
 *                      API Library for libparaver-kernel                    *
 *****************************************************************************
 *     ___     This library is free software; you can redistribute it and/or *
 *    /  __         modify it under the terms of the GNU LGPL as published   *
 *   /  /  _____    by the Free Software Foundation; either version 2.1      *
 *  /  /  /     \   of the License, or (at your option) any later version.   *
 * (  (  ( B S C )                                                           *
 *  \  \  \_____/   This library is distributed in 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 LGPL 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 Street, Fifth Floor, Boston, MA 02110-1301 USA          *
 * The GNU LEsser General Public License is contained in the file COPYING.   *
 *                                 ---------                                 *
 *   Barcelona Supercomputing Center - Centro Nacional de Supercomputacion   *
\*****************************************************************************/

#include "workspace.h"

using std::string;
using std::vector;
using std::pair;

Workspace::Workspace()
{
}

Workspace::~Workspace()
{
}

string Workspace::getName() const
{
  return name;
}

WorkspaceValue::WorkspaceType Workspace::getType() const
{
  return myType;
}

vector<WorkspaceValue> Workspace::getAutoTypes() const
{
  return autoTypes;
}

vector<pair<string,string> > Workspace::getHintCFGs() const
{
  return hintCFGs;
}

pair<string,string> Workspace::getHintCFG( size_t whichHint ) const
{
  return hintCFGs[ whichHint ];
}

void Workspace::setName( string& whichName )
{
  name = whichName;
}

void Workspace::setType( WorkspaceValue::WorkspaceType whichType )
{
  myType = whichType;
  for( vector<WorkspaceValue>::iterator it = autoTypes.begin(); it != autoTypes.end(); ++it )
    it->myType = whichType;
}

void Workspace::setAutoTypes( vector<WorkspaceValue>& whichAutoTypes )
{
  autoTypes = whichAutoTypes;
}

void Workspace::addHintCFG( pair<string,string>& whichCFG )
{
  hintCFGs.push_back( whichCFG );
}

void Workspace::addHintCFG( size_t position, pair<string,string>& whichCFG )
{
  hintCFGs.insert( hintCFGs.begin() + position, whichCFG );
}

void Workspace::removeHintCFG( size_t whichHint )
{
  hintCFGs.erase( hintCFGs.begin() + whichHint );
}

void Workspace::modifyHintCFG( size_t position, pair<string,string>& whichCFG )
{
  hintCFGs[ position ] = whichCFG;
}

void Workspace::clearHintCFGs()
{
  hintCFGs.clear();
}

// load/save XML for import/export certain workspaces

void Workspace::loadXML( std::string &wsDir )
{
  // Read user defined
  std::ifstream ifs( wsDir );
  //ifs.open( wsDir );
  if( ifs.good() ) // due to xml_iarchive needs to be destroyed before fstream is closed
  {
    boost::archive::xml_iarchive ia( ifs );
    ia >> boost::serialization::make_nvp( "workspace", *this );
  }
  ifs.close();
}

void Workspace::saveXML( std::string &wsDir )
{
  std::ofstream ofs( wsDir );
  if( ofs.good() ) // due to xml_oarchive needs to be destroyed before fstream is closed
  {
    boost::archive::xml_oarchive oa( ofs );
    oa << boost::serialization::make_nvp( "workspace", *this );
  }
  ofs.close();
}
<commit_msg>Fixed compatibility constructor for fstream<commit_after>/*****************************************************************************\
 *                        ANALYSIS PERFORMANCE TOOLS                         *
 *                               libparaver-api                              *
 *                      API Library for libparaver-kernel                    *
 *****************************************************************************
 *     ___     This library is free software; you can redistribute it and/or *
 *    /  __         modify it under the terms of the GNU LGPL as published   *
 *   /  /  _____    by the Free Software Foundation; either version 2.1      *
 *  /  /  /     \   of the License, or (at your option) any later version.   *
 * (  (  ( B S C )                                                           *
 *  \  \  \_____/   This library is distributed in 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 LGPL 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 Street, Fifth Floor, Boston, MA 02110-1301 USA          *
 * The GNU LEsser General Public License is contained in the file COPYING.   *
 *                                 ---------                                 *
 *   Barcelona Supercomputing Center - Centro Nacional de Supercomputacion   *
\*****************************************************************************/

#include "workspace.h"

using std::string;
using std::vector;
using std::pair;

Workspace::Workspace()
{
}

Workspace::~Workspace()
{
}

string Workspace::getName() const
{
  return name;
}

WorkspaceValue::WorkspaceType Workspace::getType() const
{
  return myType;
}

vector<WorkspaceValue> Workspace::getAutoTypes() const
{
  return autoTypes;
}

vector<pair<string,string> > Workspace::getHintCFGs() const
{
  return hintCFGs;
}

pair<string,string> Workspace::getHintCFG( size_t whichHint ) const
{
  return hintCFGs[ whichHint ];
}

void Workspace::setName( string& whichName )
{
  name = whichName;
}

void Workspace::setType( WorkspaceValue::WorkspaceType whichType )
{
  myType = whichType;
  for( vector<WorkspaceValue>::iterator it = autoTypes.begin(); it != autoTypes.end(); ++it )
    it->myType = whichType;
}

void Workspace::setAutoTypes( vector<WorkspaceValue>& whichAutoTypes )
{
  autoTypes = whichAutoTypes;
}

void Workspace::addHintCFG( pair<string,string>& whichCFG )
{
  hintCFGs.push_back( whichCFG );
}

void Workspace::addHintCFG( size_t position, pair<string,string>& whichCFG )
{
  hintCFGs.insert( hintCFGs.begin() + position, whichCFG );
}

void Workspace::removeHintCFG( size_t whichHint )
{
  hintCFGs.erase( hintCFGs.begin() + whichHint );
}

void Workspace::modifyHintCFG( size_t position, pair<string,string>& whichCFG )
{
  hintCFGs[ position ] = whichCFG;
}

void Workspace::clearHintCFGs()
{
  hintCFGs.clear();
}

// load/save XML for import/export certain workspaces

void Workspace::loadXML( std::string &wsDir )
{
  // Read user defined
  std::ifstream ifs( wsDir.c_str() );
  //ifs.open( wsDir );
  if( ifs.good() ) // due to xml_iarchive needs to be destroyed before fstream is closed
  {
    boost::archive::xml_iarchive ia( ifs );
    ia >> boost::serialization::make_nvp( "workspace", *this );
  }
  ifs.close();
}

void Workspace::saveXML( std::string &wsDir )
{
  std::ofstream ofs( wsDir.c_str() );
  if( ofs.good() ) // due to xml_oarchive needs to be destroyed before fstream is closed
  {
    boost::archive::xml_oarchive oa( ofs );
    oa << boost::serialization::make_nvp( "workspace", *this );
  }
  ofs.close();
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * Copyright (C) 2011-2013 Michael Krufky
 *
 * Author: Michael Krufky <mkrufky@linuxtv.org>
 *
 * 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 Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <inttypes.h>
#include "string.h"

#include "stats.h"
#include "log.h"
#define CLASS_MODULE "stats"

#define DBG 0

#define dprintf(fmt, arg...) __dprintf(DBG_STATS, "(%s) "fmt, parent, ##arg)

stats::stats(const char *caller)
  : tei_count(0)
  , __timenow(0)
  , parent(caller)
  , streamtime_cb(NULL)
  , streamtime_priv(NULL)
  , statistics_cb(NULL)
  , statistics_priv(NULL)
{
	dprintf("(%s)", parent);
}

stats::~stats()
{
	dprintf("(%s)", parent);
	show(false);
}

#if 0
stats::stats(const stats&)
{
	dprintf("(%s, copy)", parent);
}

stats& stats::operator= (const stats& cSource)
{
	dprintf("(%s, operator=)", parent);

	if (this == &cSource)
		return *this;

	return *this;
}
#endif

static void parse_pcr(uint8_t *pcr, uint64_t *pcr_base, unsigned int *pcr_ext)
{
	*pcr_base = ((uint64_t)pcr[0] * 0x2000000) +
		    ((uint64_t)pcr[1] * 0x20000) +
		    ((uint64_t)pcr[2] * 0x200) +
		    ((uint64_t)pcr[3] * 0x02) +
		    ((uint64_t)(pcr[4] & 0x80) >> 7);

	*pcr_ext = ((pcr[4] & 0x01) * 0x100) + pcr[5];

	return;
}

static time_t walltime(void *p) { (void)p; return time(NULL); }

char *stats_scale_unit(char *b, size_t n, uint64_t x)
{
	memset(b, 0, n);

	if (x >= 1000000) {
		if ((x % 1000000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
		else
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
	} else if (x >= 1000) {
		if ((x % 1000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
		else
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
	} else
		snprintf(b, n, "    %3" PRIu64 "  ", x);
	return b;
}

void stats::show(bool per_sec)
{
	if (statistics_cb) {
		statistics_cb(statistics_priv, statistics, discontinuities, tei_count, per_sec);
		return;
	}
	for (stats_map::const_iterator iter = statistics.begin(); iter != statistics.end(); ++iter) {
		char a[16];
		char b[16];
		dprintf("pid %04x %5" PRIu64 " p%s  %sb%s  %sbit",
			iter->first, iter->second / 188, (per_sec) ? "/s" : "",
			stats_scale_unit(a, sizeof(a), iter->second), (per_sec) ? "/s" : "",
			stats_scale_unit(b, sizeof(b), iter->second * 8));
	}
	for (stats_map::const_iterator iter = discontinuities.begin(); iter != discontinuities.end(); ++iter)
		dprintf("pid %04x\t%" PRIu64 " continuity errors (%" PRIu64 "%%)", iter->first, iter->second, ((!iter->second) || (!statistics[iter->first])) ? 0 : (!statistics.count(iter->first)) ? 0 : (100 * iter->second / (statistics[iter->first] / 188)));

	if (tei_count) dprintf("tei count: %" PRIu64 " (%" PRIu64 "%%)", tei_count, (!statistics[0x2000]) ? 0 : (18800 * tei_count / statistics[0x2000]));
}

void stats::push_pid(int c, const uint16_t pid)
{
	streamtime_callback cb = (streamtime_cb) ? streamtime_cb : &walltime;
	time_t timenow = cb(streamtime_priv);

	if (timenow > __timenow) {
		show();
		clear_stats();
		__timenow = timenow;
	}

	__push_pid(c, pid);
}

pkt_stats_t *stats::parse(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	adaptation_field_t adapt;
	pkt_hdr_t hdr;

	return parse(p, pkt_stats, hdr, adapt);
}

pkt_stats_t *stats::parse(const uint8_t *p, pkt_stats_t *pkt_stats, pkt_hdr_t &hdr, adaptation_field_t &adapt)
{
	if (pkt_stats) {
		memset(pkt_stats, 0, sizeof(pkt_stats_t));

		const uint8_t *q = p;

		memset(&adapt, 0, sizeof(adapt));
		memset(&hdr, 0, sizeof(hdr));

		hdr.sync_byte          = q[0];
		hdr.tei                = (q[1] & 0x80) >> 7;
		hdr.payload_unit_start = (q[1] & 0x40) >> 6;
		hdr.transport_priority = (q[1] & 0x20) >> 5;
		hdr.pid                = ((q[1] & 0x1f) << 8) | q[2];
		hdr.scrambling         = (q[3] & 0xc0) >> 6;
		hdr.adaptation_flags   = (q[3] & 0x30) >> 4;
		hdr.continuity_ctr     = (q[3] & 0x0f);

		if (hdr.adaptation_flags & 0x02) {
			q += 4;
			adapt.field_length   = q[0];
			adapt.discontinuity  = (q[1] & 0x80) >> 7;
			adapt.random_access  = (q[1] & 0x40) >> 6; /* set to 1 if the PES pkt in this TS pkt starts an a/v sequence */
			adapt.es_priority    = (q[1] & 0x20) >> 5;
			adapt.pcr            = (q[1] & 0x10) >> 4;
			adapt.opcr           = (q[1] & 0x08) >> 3;
			adapt.splicing_point = (q[1] & 0x04) >> 2;
			adapt.tp_priv_data   = (q[1] & 0x02) >> 1;
			adapt.field_ext      = (q[1] & 0x01) >> 0;

			if (adapt.pcr) {
				memcpy(adapt.PCR, &q[2], 6);
				q += 6;
			}
			if (adapt.opcr) {
				memcpy(adapt.OPCR, &q[2], 6);
				q += 6;
			}
			if (adapt.splicing_point) {
				adapt.splicing_countdown = q[2];
				q ++;
			}
		}

		pkt_stats->sync_loss = (hdr.sync_byte != 0x47) ? true : false;
		if (!pkt_stats->sync_loss) {
			pkt_stats->tei = (hdr.tei) ? true : false;
			pkt_stats->pid = hdr.pid;
		} else
			pkt_stats->pid = (uint16_t) - 1;
	}
	return pkt_stats;
}

void stats::clear_stats()
{
	statistics.clear();
	discontinuities.clear();
	last_pcr_base.clear();
	tei_count = 0;
}

void stats::push_stats(pkt_stats_t *pkt_stats)
{
	if (pkt_stats->tei) {
		tei_count++;
		push_pid((uint16_t) - 1);
	} else
		push_pid(pkt_stats->pid);
}

void stats::push(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	adaptation_field_t adapt;
	pkt_hdr_t hdr;

	if (!pkt_stats) {
		__push(p);
		return;
	}

	memset(pkt_stats, 0, sizeof(pkt_stats_t));

	parse(p, pkt_stats, hdr, adapt);

	if (hdr.adaptation_flags & 0x01) {// payload present
		if (continuity.count(hdr.pid)) {
			uint8_t next = (continuity[hdr.pid] + 1) & 0x0f;
			if ((next != (hdr.continuity_ctr & 0x0f)) && (hdr.continuity_ctr + continuity[hdr.pid] > 0)) {
				if (!(hdr.adaptation_flags & 0x02) && (adapt.discontinuity)) {
					push_discontinuity(hdr.pid);
#if DBG
					dprintf("CONTINUITY ERROR pid: %04x cur: 0x%x prev 0x%x", hdr.pid, hdr.continuity_ctr, continuity[hdr.pid]);
#endif
				}
			}
		}
		continuity[hdr.pid] = hdr.continuity_ctr;
	}

	if (hdr.adaptation_flags & 0x02) {
		if (adapt.pcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.PCR, &pcr_base, &pcr_ext);
			dprintf("PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d", hdr.pid, pcr_base, pcr_ext);

			stats_map::const_iterator iter = last_pcr_base.find(hdr.pid);
#if DBG
			if ((iter != last_pcr_base.end()) && (pcr_base < iter->second))
				fprintf(stderr, "%s: PID: 0x%04x, %" PRIu64 " < %" PRIu64 " !!!\n",
					__func__, hdr.pid, pcr_base, iter->second);
#endif
			last_pcr_base[hdr.pid] = pcr_base;
		}
		if (adapt.opcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.OPCR, &pcr_base, &pcr_ext);
			dprintf("PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d", hdr.pid, pcr_base, pcr_ext);
		}
		if (adapt.splicing_point) {
			dprintf("PID: 0x%04x, splicing countdown: %d", hdr.pid, adapt.splicing_countdown);
		}
	}

	push_stats(pkt_stats);
}
<commit_msg>stats: fix warning: unused variable 'iter' [-Wunused-variable]<commit_after>/*****************************************************************************
 * Copyright (C) 2011-2013 Michael Krufky
 *
 * Author: Michael Krufky <mkrufky@linuxtv.org>
 *
 * 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 Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <inttypes.h>
#include "string.h"

#include "stats.h"
#include "log.h"
#define CLASS_MODULE "stats"

#define DBG 0

#define dprintf(fmt, arg...) __dprintf(DBG_STATS, "(%s) "fmt, parent, ##arg)

stats::stats(const char *caller)
  : tei_count(0)
  , __timenow(0)
  , parent(caller)
  , streamtime_cb(NULL)
  , streamtime_priv(NULL)
  , statistics_cb(NULL)
  , statistics_priv(NULL)
{
	dprintf("(%s)", parent);
}

stats::~stats()
{
	dprintf("(%s)", parent);
	show(false);
}

#if 0
stats::stats(const stats&)
{
	dprintf("(%s, copy)", parent);
}

stats& stats::operator= (const stats& cSource)
{
	dprintf("(%s, operator=)", parent);

	if (this == &cSource)
		return *this;

	return *this;
}
#endif

static void parse_pcr(uint8_t *pcr, uint64_t *pcr_base, unsigned int *pcr_ext)
{
	*pcr_base = ((uint64_t)pcr[0] * 0x2000000) +
		    ((uint64_t)pcr[1] * 0x20000) +
		    ((uint64_t)pcr[2] * 0x200) +
		    ((uint64_t)pcr[3] * 0x02) +
		    ((uint64_t)(pcr[4] & 0x80) >> 7);

	*pcr_ext = ((pcr[4] & 0x01) * 0x100) + pcr[5];

	return;
}

static time_t walltime(void *p) { (void)p; return time(NULL); }

char *stats_scale_unit(char *b, size_t n, uint64_t x)
{
	memset(b, 0, n);

	if (x >= 1000000) {
		if ((x % 1000000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
		else
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
	} else if (x >= 1000) {
		if ((x % 1000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
		else
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
	} else
		snprintf(b, n, "    %3" PRIu64 "  ", x);
	return b;
}

void stats::show(bool per_sec)
{
	if (statistics_cb) {
		statistics_cb(statistics_priv, statistics, discontinuities, tei_count, per_sec);
		return;
	}
	for (stats_map::const_iterator iter = statistics.begin(); iter != statistics.end(); ++iter) {
		char a[16];
		char b[16];
		dprintf("pid %04x %5" PRIu64 " p%s  %sb%s  %sbit",
			iter->first, iter->second / 188, (per_sec) ? "/s" : "",
			stats_scale_unit(a, sizeof(a), iter->second), (per_sec) ? "/s" : "",
			stats_scale_unit(b, sizeof(b), iter->second * 8));
	}
	for (stats_map::const_iterator iter = discontinuities.begin(); iter != discontinuities.end(); ++iter)
		dprintf("pid %04x\t%" PRIu64 " continuity errors (%" PRIu64 "%%)", iter->first, iter->second, ((!iter->second) || (!statistics[iter->first])) ? 0 : (!statistics.count(iter->first)) ? 0 : (100 * iter->second / (statistics[iter->first] / 188)));

	if (tei_count) dprintf("tei count: %" PRIu64 " (%" PRIu64 "%%)", tei_count, (!statistics[0x2000]) ? 0 : (18800 * tei_count / statistics[0x2000]));
}

void stats::push_pid(int c, const uint16_t pid)
{
	streamtime_callback cb = (streamtime_cb) ? streamtime_cb : &walltime;
	time_t timenow = cb(streamtime_priv);

	if (timenow > __timenow) {
		show();
		clear_stats();
		__timenow = timenow;
	}

	__push_pid(c, pid);
}

pkt_stats_t *stats::parse(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	adaptation_field_t adapt;
	pkt_hdr_t hdr;

	return parse(p, pkt_stats, hdr, adapt);
}

pkt_stats_t *stats::parse(const uint8_t *p, pkt_stats_t *pkt_stats, pkt_hdr_t &hdr, adaptation_field_t &adapt)
{
	if (pkt_stats) {
		memset(pkt_stats, 0, sizeof(pkt_stats_t));

		const uint8_t *q = p;

		memset(&adapt, 0, sizeof(adapt));
		memset(&hdr, 0, sizeof(hdr));

		hdr.sync_byte          = q[0];
		hdr.tei                = (q[1] & 0x80) >> 7;
		hdr.payload_unit_start = (q[1] & 0x40) >> 6;
		hdr.transport_priority = (q[1] & 0x20) >> 5;
		hdr.pid                = ((q[1] & 0x1f) << 8) | q[2];
		hdr.scrambling         = (q[3] & 0xc0) >> 6;
		hdr.adaptation_flags   = (q[3] & 0x30) >> 4;
		hdr.continuity_ctr     = (q[3] & 0x0f);

		if (hdr.adaptation_flags & 0x02) {
			q += 4;
			adapt.field_length   = q[0];
			adapt.discontinuity  = (q[1] & 0x80) >> 7;
			adapt.random_access  = (q[1] & 0x40) >> 6; /* set to 1 if the PES pkt in this TS pkt starts an a/v sequence */
			adapt.es_priority    = (q[1] & 0x20) >> 5;
			adapt.pcr            = (q[1] & 0x10) >> 4;
			adapt.opcr           = (q[1] & 0x08) >> 3;
			adapt.splicing_point = (q[1] & 0x04) >> 2;
			adapt.tp_priv_data   = (q[1] & 0x02) >> 1;
			adapt.field_ext      = (q[1] & 0x01) >> 0;

			if (adapt.pcr) {
				memcpy(adapt.PCR, &q[2], 6);
				q += 6;
			}
			if (adapt.opcr) {
				memcpy(adapt.OPCR, &q[2], 6);
				q += 6;
			}
			if (adapt.splicing_point) {
				adapt.splicing_countdown = q[2];
				q ++;
			}
		}

		pkt_stats->sync_loss = (hdr.sync_byte != 0x47) ? true : false;
		if (!pkt_stats->sync_loss) {
			pkt_stats->tei = (hdr.tei) ? true : false;
			pkt_stats->pid = hdr.pid;
		} else
			pkt_stats->pid = (uint16_t) - 1;
	}
	return pkt_stats;
}

void stats::clear_stats()
{
	statistics.clear();
	discontinuities.clear();
	last_pcr_base.clear();
	tei_count = 0;
}

void stats::push_stats(pkt_stats_t *pkt_stats)
{
	if (pkt_stats->tei) {
		tei_count++;
		push_pid((uint16_t) - 1);
	} else
		push_pid(pkt_stats->pid);
}

void stats::push(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	adaptation_field_t adapt;
	pkt_hdr_t hdr;

	if (!pkt_stats) {
		__push(p);
		return;
	}

	memset(pkt_stats, 0, sizeof(pkt_stats_t));

	parse(p, pkt_stats, hdr, adapt);

	if (hdr.adaptation_flags & 0x01) {// payload present
		if (continuity.count(hdr.pid)) {
			uint8_t next = (continuity[hdr.pid] + 1) & 0x0f;
			if ((next != (hdr.continuity_ctr & 0x0f)) && (hdr.continuity_ctr + continuity[hdr.pid] > 0)) {
				if (!(hdr.adaptation_flags & 0x02) && (adapt.discontinuity)) {
					push_discontinuity(hdr.pid);
#if DBG
					dprintf("CONTINUITY ERROR pid: %04x cur: 0x%x prev 0x%x", hdr.pid, hdr.continuity_ctr, continuity[hdr.pid]);
#endif
				}
			}
		}
		continuity[hdr.pid] = hdr.continuity_ctr;
	}

	if (hdr.adaptation_flags & 0x02) {
		if (adapt.pcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.PCR, &pcr_base, &pcr_ext);
			dprintf("PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d", hdr.pid, pcr_base, pcr_ext);

#if DBG
			stats_map::const_iterator iter = last_pcr_base.find(hdr.pid);
			if ((iter != last_pcr_base.end()) && (pcr_base < iter->second))
				fprintf(stderr, "%s: PID: 0x%04x, %" PRIu64 " < %" PRIu64 " !!!\n",
					__func__, hdr.pid, pcr_base, iter->second);
#endif
			last_pcr_base[hdr.pid] = pcr_base;
		}
		if (adapt.opcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.OPCR, &pcr_base, &pcr_ext);
			dprintf("PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d", hdr.pid, pcr_base, pcr_ext);
		}
		if (adapt.splicing_point) {
			dprintf("PID: 0x%04x, splicing countdown: %d", hdr.pid, adapt.splicing_countdown);
		}
	}

	push_stats(pkt_stats);
}
<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2012-2020 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. 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 OWNER 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.
 *
 *********************************************************************************/

#include <modules/basegl/processors/volumeraycaster.h>
#include <inviwo/core/io/serialization/serialization.h>
#include <inviwo/core/io/serialization/versionconverter.h>
#include <inviwo/core/interaction/events/keyboardevent.h>
#include <modules/opengl/volume/volumegl.h>
#include <modules/opengl/texture/textureunit.h>
#include <modules/opengl/texture/textureutils.h>
#include <modules/opengl/shader/shaderutils.h>
#include <modules/opengl/volume/volumeutils.h>
#include <inviwo/core/common/inviwoapplication.h>
#include <inviwo/core/util/rendercontext.h>
#include <inviwo/core/algorithm/boundingbox.h>

namespace inviwo {

const ProcessorInfo VolumeRaycaster::processorInfo_{
    "org.inviwo.VolumeRaycaster",  // Class identifier
    "Volume Raycaster",            // Display name
    "Volume Rendering",            // Category
    CodeState::Stable,             // Code state
    "GL, DVR, Raycasting"          // Tags
};

VolumeRaycaster::VolumeRaycaster()
    : Processor()
    , shader_("raycasting.frag", false)
    , volumePort_("volume")
    , entryPort_("entry")
    , exitPort_("exit")
    , backgroundPort_("bg")
    , outport_("outport")
    , channel_("channel", "Render Channel")
    , raycasting_("raycaster", "Raycasting")
    , isotfComposite_("isotfComposite", "TF & Isovalues", &volumePort_,
                      InvalidationLevel::InvalidResources)
    , camera_("camera", "Camera", util::boundingBox(volumePort_))
    , lighting_("lighting", "Lighting", &camera_)
    , positionIndicator_("positionindicator", "Position Indicator")
    , toggleShading_("toggleShading", "Toggle Shading", [this](Event* e) { toggleShading(e); },
                     IvwKey::L) {

    shader_.onReload([this]() { invalidate(InvalidationLevel::InvalidResources); });

    addPort(volumePort_, "VolumePortGroup");
    addPort(entryPort_, "ImagePortGroup1");
    addPort(exitPort_, "ImagePortGroup1");
    addPort(outport_, "ImagePortGroup1");
    addPort(backgroundPort_, "ImagePortGroup1");

    backgroundPort_.setOptional(true);

    channel_.addOption("Channel 1", "Channel 1", 0);
    channel_.setSerializationMode(PropertySerializationMode::All);
    channel_.setCurrentStateAsDefault();

    volumePort_.onChange([this]() {
        if (volumePort_.hasData()) {
            size_t channels = volumePort_.getData()->getDataFormat()->getComponents();

            if (channels == channel_.size()) return;

            std::vector<OptionPropertyIntOption> channelOptions;
            for (size_t i = 0; i < channels; i++) {
                channelOptions.emplace_back("Channel " + toString(i + 1),
                                            "Channel " + toString(i + 1), static_cast<int>(i));
            }
            channel_.replaceOptions(channelOptions);
            channel_.setCurrentStateAsDefault();
        }
    });
    backgroundPort_.onConnect([&]() { this->invalidate(InvalidationLevel::InvalidResources); });
    backgroundPort_.onDisconnect([&]() { this->invalidate(InvalidationLevel::InvalidResources); });

    // change the currently selected channel when a pre-computed gradient is selected
    raycasting_.gradientComputation_.onChange([this]() {
        if (channel_.size() == 4) {
            if (raycasting_.gradientComputation_.get() ==
                RaycastingProperty::GradientComputation::PrecomputedXYZ) {
                channel_.set(3);
            } else if (raycasting_.gradientComputation_.get() ==
                       RaycastingProperty::GradientComputation::PrecomputedYZW) {
                channel_.set(0);
            }
        }
    });

    addProperty(channel_);
    addProperty(raycasting_);
    addProperty(isotfComposite_);

    addProperty(camera_);
    addProperty(lighting_);
    addProperty(positionIndicator_);
    addProperty(toggleShading_);
}

const ProcessorInfo VolumeRaycaster::getProcessorInfo() const { return processorInfo_; }

void VolumeRaycaster::initializeResources() {
    utilgl::addDefines(shader_, raycasting_, isotfComposite_, camera_, lighting_,
                       positionIndicator_);
    utilgl::addShaderDefinesBGPort(shader_, backgroundPort_);
    shader_.build();
}

void VolumeRaycaster::process() {
    if (volumePort_.isChanged()) {
        auto newVolume = volumePort_.getData();

        if (newVolume->hasRepresentation<VolumeGL>()) {
            loadedVolume_ = newVolume;
        } else {
            dispatchPool([this, newVolume]() {
                RenderContext::getPtr()->activateLocalRenderContext();
                newVolume->getRep<kind::GL>();
                glFinish();
                dispatchFront([this, newVolume]() {
                    loadedVolume_ = newVolume;
                    invalidate(InvalidationLevel::InvalidOutput);
                });
            });
        }
    }

    if (!loadedVolume_) return;
    if (!loadedVolume_->hasRepresentation<VolumeGL>()) {
        LogWarn("No GL rep !!!");
        return;
    }

    utilgl::activateAndClearTarget(outport_);
    shader_.activate();

    TextureUnitContainer units;
    utilgl::bindAndSetUniforms(shader_, units, *loadedVolume_, "volume");
    utilgl::bindAndSetUniforms(shader_, units, isotfComposite_);
    utilgl::bindAndSetUniforms(shader_, units, entryPort_, ImageType::ColorDepthPicking);
    utilgl::bindAndSetUniforms(shader_, units, exitPort_, ImageType::ColorDepth);
    if (backgroundPort_.hasData()) {
        utilgl::bindAndSetUniforms(shader_, units, backgroundPort_, ImageType::ColorDepthPicking);
    }
    utilgl::setUniforms(shader_, outport_, camera_, lighting_, raycasting_, positionIndicator_,
                        channel_, isotfComposite_);

    utilgl::singleDrawImagePlaneRect();

    shader_.deactivate();
    utilgl::deactivateCurrentTarget();
}

void VolumeRaycaster::toggleShading(Event*) {
    if (lighting_.shadingMode_.get() == ShadingMode::None) {
        lighting_.shadingMode_.set(ShadingMode::Phong);
    } else {
        lighting_.shadingMode_.set(ShadingMode::None);
    }
}

// override to do member renaming.
void VolumeRaycaster::deserialize(Deserializer& d) {
    util::renamePort(d, {{&entryPort_, "entry-points"}, {&exitPort_, "exit-points"}});
    Processor::deserialize(d);
}

}  // namespace inviwo
<commit_msg>BaseGL: minor refactor<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2012-2020 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. 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 OWNER 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.
 *
 *********************************************************************************/

#include <modules/basegl/processors/volumeraycaster.h>
#include <inviwo/core/io/serialization/serialization.h>
#include <inviwo/core/io/serialization/versionconverter.h>
#include <inviwo/core/interaction/events/keyboardevent.h>
#include <modules/opengl/volume/volumegl.h>
#include <modules/opengl/texture/textureunit.h>
#include <modules/opengl/texture/textureutils.h>
#include <modules/opengl/shader/shaderutils.h>
#include <modules/opengl/volume/volumeutils.h>
#include <inviwo/core/common/inviwoapplication.h>
#include <inviwo/core/util/rendercontext.h>
#include <inviwo/core/algorithm/boundingbox.h>

namespace inviwo {

const ProcessorInfo VolumeRaycaster::processorInfo_{
    "org.inviwo.VolumeRaycaster",  // Class identifier
    "Volume Raycaster",            // Display name
    "Volume Rendering",            // Category
    CodeState::Stable,             // Code state
    "GL, DVR, Raycasting"          // Tags
};

VolumeRaycaster::VolumeRaycaster()
    : Processor()
    , shader_("raycasting.frag", false)
    , volumePort_("volume")
    , entryPort_("entry")
    , exitPort_("exit")
    , backgroundPort_("bg")
    , outport_("outport")
    , channel_("channel", "Render Channel", {{"Channel 1", "Channel 1", 0}}, 0)
    , raycasting_("raycaster", "Raycasting")
    , isotfComposite_("isotfComposite", "TF & Isovalues", &volumePort_,
                      InvalidationLevel::InvalidResources)
    , camera_("camera", "Camera", util::boundingBox(volumePort_))
    , lighting_("lighting", "Lighting", &camera_)
    , positionIndicator_("positionindicator", "Position Indicator")
    , toggleShading_(
          "toggleShading", "Toggle Shading", [this](Event* e) { toggleShading(e); }, IvwKey::L) {

    shader_.onReload([this]() { invalidate(InvalidationLevel::InvalidResources); });

    addPort(volumePort_, "VolumePortGroup");
    addPort(entryPort_, "ImagePortGroup1");
    addPort(exitPort_, "ImagePortGroup1");
    addPort(outport_, "ImagePortGroup1");
    addPort(backgroundPort_, "ImagePortGroup1");

    backgroundPort_.setOptional(true);

    channel_.setSerializationMode(PropertySerializationMode::All);

    volumePort_.onChange([this]() {
        if (volumePort_.hasData()) {
            size_t channels = volumePort_.getData()->getDataFormat()->getComponents();

            if (channels == channel_.size()) return;

            std::vector<OptionPropertyIntOption> channelOptions;
            for (size_t i = 0; i < channels; i++) {
                channelOptions.emplace_back("Channel " + toString(i + 1),
                                            "Channel " + toString(i + 1), static_cast<int>(i));
            }
            channel_.replaceOptions(channelOptions);
            channel_.setCurrentStateAsDefault();
        }
    });
    backgroundPort_.onConnect([&]() { this->invalidate(InvalidationLevel::InvalidResources); });
    backgroundPort_.onDisconnect([&]() { this->invalidate(InvalidationLevel::InvalidResources); });

    // change the currently selected channel when a pre-computed gradient is selected
    raycasting_.gradientComputation_.onChange([this]() {
        if (channel_.size() == 4) {
            if (raycasting_.gradientComputation_.get() ==
                RaycastingProperty::GradientComputation::PrecomputedXYZ) {
                channel_.set(3);
            } else if (raycasting_.gradientComputation_.get() ==
                       RaycastingProperty::GradientComputation::PrecomputedYZW) {
                channel_.set(0);
            }
        }
    });

    addProperty(channel_);
    addProperty(raycasting_);
    addProperty(isotfComposite_);

    addProperty(camera_);
    addProperty(lighting_);
    addProperty(positionIndicator_);
    addProperty(toggleShading_);
}

const ProcessorInfo VolumeRaycaster::getProcessorInfo() const { return processorInfo_; }

void VolumeRaycaster::initializeResources() {
    utilgl::addDefines(shader_, raycasting_, isotfComposite_, camera_, lighting_,
                       positionIndicator_);
    utilgl::addShaderDefinesBGPort(shader_, backgroundPort_);
    shader_.build();
}

void VolumeRaycaster::process() {
    if (volumePort_.isChanged()) {
        auto newVolume = volumePort_.getData();

        if (newVolume->hasRepresentation<VolumeGL>()) {
            loadedVolume_ = newVolume;
        } else {
            dispatchPool([this, newVolume]() {
                RenderContext::getPtr()->activateLocalRenderContext();
                newVolume->getRep<kind::GL>();
                glFinish();
                dispatchFront([this, newVolume]() {
                    loadedVolume_ = newVolume;
                    invalidate(InvalidationLevel::InvalidOutput);
                });
            });
        }
    }

    if (!loadedVolume_) return;
    if (!loadedVolume_->hasRepresentation<VolumeGL>()) {
        LogWarn("No GL rep !!!");
        return;
    }

    utilgl::activateAndClearTarget(outport_);
    shader_.activate();

    TextureUnitContainer units;
    utilgl::bindAndSetUniforms(shader_, units, *loadedVolume_, "volume");
    utilgl::bindAndSetUniforms(shader_, units, isotfComposite_);
    utilgl::bindAndSetUniforms(shader_, units, entryPort_, ImageType::ColorDepthPicking);
    utilgl::bindAndSetUniforms(shader_, units, exitPort_, ImageType::ColorDepth);
    if (backgroundPort_.hasData()) {
        utilgl::bindAndSetUniforms(shader_, units, backgroundPort_, ImageType::ColorDepthPicking);
    }
    utilgl::setUniforms(shader_, outport_, camera_, lighting_, raycasting_, positionIndicator_,
                        channel_, isotfComposite_);

    utilgl::singleDrawImagePlaneRect();

    shader_.deactivate();
    utilgl::deactivateCurrentTarget();
}

void VolumeRaycaster::toggleShading(Event*) {
    if (lighting_.shadingMode_.get() == ShadingMode::None) {
        lighting_.shadingMode_.set(ShadingMode::Phong);
    } else {
        lighting_.shadingMode_.set(ShadingMode::None);
    }
}

// override to do member renaming.
void VolumeRaycaster::deserialize(Deserializer& d) {
    util::renamePort(d, {{&entryPort_, "entry-points"}, {&exitPort_, "exit-points"}});
    Processor::deserialize(d);
}

}  // namespace inviwo
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/
#include "modules/common/math/linear_quadratic_regulator.h"
#include "modules/common/log.h"

#include "Eigen/Dense"

namespace apollo {
namespace common {
namespace math {

using Matrix = Eigen::MatrixXd;

void SolveLQRProblem(const Matrix &A, const Matrix &B, const Matrix &Q,
                     const Matrix &R, const double tolerance,
                     const uint max_num_iteration, Matrix *ptr_K) {
  if (A.rows() != A.cols() || B.rows() != A.rows() || Q.rows() != Q.cols() ||
      Q.rows() != A.rows() || R.rows() != R.cols() || R.rows() != B.cols()) {
    AERROR << "One or more matrices have incompatible dimensions.";
    return;
  }

  Matrix AT = A.transpose();
  Matrix BT = B.transpose();

  // Solves a discrete-time Algebraic Riccati equation (DARE)
  // Calculate Matrix Difference Riccati Equation, initialize P and Q
  Matrix P = Q;
  uint num_iteration = 0;
  double diff = 0.0;
  while (num_iteration++ < max_num_iteration) {
    Matrix P_next =
        AT * P * A - AT * P * B * (R + BT * P * B).inverse() * BT * P * A + Q;
    // check the difference between P and P_next
    diff = fabs((P_next - P).maxCoeff());
    P = P_next;

    if (diff < tolerance) {
      break;
    }
  }

  if (num_iteration >= max_num_iteration) {
    AWARN << "lqr_not_convergence, last_diff_is:" << diff;
  } else {
    ADEBUG << "Number of iterations until convergence: " << num_iteration
           << ", max difference: " << diff;
  }
  *ptr_K = (R + BT * P * B).inverse() * BT * P * A;
}

}  // namespace math
}  // namespace common
}  // namespace apollo
<commit_msg>common: minor restructured LQR solver<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/
#include "modules/common/math/linear_quadratic_regulator.h"
#include "modules/common/log.h"

#include "Eigen/Dense"

namespace apollo {
namespace common {
namespace math {

using Matrix = Eigen::MatrixXd;

void SolveLQRProblem(const Matrix &A, const Matrix &B, const Matrix &Q,
                     const Matrix &R, const double tolerance,
                     const uint max_num_iteration, Matrix *ptr_K) {
  if (A.rows() != A.cols() || B.rows() != A.rows() || Q.rows() != Q.cols() ||
      Q.rows() != A.rows() || R.rows() != R.cols() || R.rows() != B.cols()) {
    AERROR << "LQR solver: one or more matrices have incompatible dimensions.";
    return;
  }

  Matrix AT = A.transpose();
  Matrix BT = B.transpose();

  // Solves a discrete-time Algebraic Riccati equation (DARE)
  // Calculate Matrix Difference Riccati Equation, initialize P and Q
  Matrix P = Q;
  uint num_iteration = 0;
  double diff = std::numeric_limits<double>::max();
  while (num_iteration++ < max_num_iteration && diff > tolerance) {
    Matrix P_next =
        AT * P * A - AT * P * B * (R + BT * P * B).inverse() * BT * P * A + Q;
    // check the difference between P and P_next
    diff = fabs((P_next - P).maxCoeff());
    P = P_next;
  }

  if (num_iteration >= max_num_iteration) {
    AWARN << "LQR solver cannot converge to a solution, "
        "last consecutive result diff. is:" << diff;
  } else {
    ADEBUG << "LQR solver converged at iteration: " << num_iteration
           << ", max consecutive result diff.: " << diff;
  }
  *ptr_K = (R + BT * P * B).inverse() * BT * P * A;
}

}  // namespace math
}  // namespace common
}  // namespace apollo
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE "test_read_observer"

#ifdef BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#else
#include <boost/test/included/unit_test.hpp>
#endif

#include <mjolnir/core/BoundaryCondition.hpp>
#include <mjolnir/core/SimulatorTraits.hpp>
#include <mjolnir/input/read_observer.hpp>

BOOST_AUTO_TEST_CASE(read_observer)
{
    mjolnir::LoggerManager::set_default_logger("test_read_observer.log");

    using real_type = double;
    using traits_type = mjolnir::SimulatorTraits<real_type, mjolnir::UnlimitedBoundary>;
    {
        using namespace toml::literals;
        const toml::table v = toml::get<toml::table>(u8R"(
            [files]
            output.path   = "./"
            output.prefix = "test"
            output.format = "xyz"
        )"_toml);

        const auto obs = mjolnir::read_observer<traits_type>(v);
        BOOST_TEST(obs.observers().size() == 2u);
        BOOST_TEST(obs.observers().at(0)->prefix() == "./test");
        BOOST_TEST(obs.observers().at(1)->prefix() == "./test");

        const auto xyz = dynamic_cast<mjolnir::XYZObserver<traits_type>*>(
                             obs.observers().at(0).get());
        BOOST_TEST(static_cast<bool>(xyz));

        const auto ene = dynamic_cast<mjolnir::EnergyObserver<traits_type>*>(
                             obs.observers().at(1).get());
        BOOST_TEST(static_cast<bool>(ene));
    }
    {
        using namespace toml::literals;
        const toml::table v = toml::get<toml::table>(u8R"(
            [files]
            output.prefix = "test"
            output.format = "xyz"
        )"_toml);

        const auto obs = mjolnir::read_observer<traits_type>(v);
        BOOST_TEST(obs.observers().size() == 2u);
        BOOST_TEST(obs.observers().at(0)->prefix() == "./test");
        BOOST_TEST(obs.observers().at(1)->prefix() == "./test");

        const auto xyz = dynamic_cast<mjolnir::XYZObserver<traits_type>*>(
                             obs.observers().at(0).get());
        BOOST_TEST(static_cast<bool>(xyz));

        const auto ene = dynamic_cast<mjolnir::EnergyObserver<traits_type>*>(
                             obs.observers().at(1).get());
        BOOST_TEST(static_cast<bool>(ene));
    }

    // XXX
    // The following block tests read_observer successfully adds a path before
    // the prefix. But it requires the directory `test` under WORKING_DIRECTORY.
    // It strongly depends on the directory structure...
    // It is not good. We need to find a way to avoid this dependency.
    {
        using namespace toml::literals;
        const toml::table v = toml::get<toml::table>(u8R"(
            [files]
            output.path   = "./test"
            output.prefix = "test"
            output.format = "xyz"
        )"_toml);

        const auto obs = mjolnir::read_observer<traits_type>(v);

        BOOST_TEST(obs.observers().size() == 2u);
        BOOST_TEST(obs.observers().at(0)->prefix() == "./test/test");
        BOOST_TEST(obs.observers().at(1)->prefix() == "./test/test");

        const auto xyz = dynamic_cast<mjolnir::XYZObserver<traits_type>*>(
                             obs.observers().at(0).get());
        BOOST_TEST(static_cast<bool>(xyz));

        const auto ene = dynamic_cast<mjolnir::EnergyObserver<traits_type>*>(
                             obs.observers().at(1).get());
        BOOST_TEST(static_cast<bool>(ene));
    }
}

// check that read_observer returns XYZObserver or not
BOOST_AUTO_TEST_CASE(read_xyz_observer)
{
    mjolnir::LoggerManager::set_default_logger("test_read_observer.log");

    using real_type = double;
    using traits_type = mjolnir::SimulatorTraits<real_type, mjolnir::UnlimitedBoundary>;
    {
        using namespace toml::literals;
        const toml::table v = toml::get<toml::table>(u8R"(
            [files]
            output.path   = "./"
            output.prefix = "test"
            output.format = "xyz"
        )"_toml);

        const auto obs = mjolnir::read_observer<traits_type>(v);
        BOOST_TEST(obs.observers().size() == 2u);

        const auto xyz = dynamic_cast<mjolnir::XYZObserver<traits_type>*>(
                             obs.observers().at(0).get());
        BOOST_TEST(static_cast<bool>(xyz));

        const auto ene = dynamic_cast<mjolnir::EnergyObserver<traits_type>*>(
                             obs.observers().at(1).get());
        BOOST_TEST(static_cast<bool>(ene));
    }
}

// check that read_observer returns DCDObserver or not
BOOST_AUTO_TEST_CASE(read_dcd_observer)
{
    mjolnir::LoggerManager::set_default_logger("test_read_observer.log");

    using real_type = double;
    using traits_type = mjolnir::SimulatorTraits<real_type, mjolnir::UnlimitedBoundary>;
    {
        using namespace toml::literals;
        const toml::table v = toml::get<toml::table>(u8R"(
            [files]
            output.path   = "./"
            output.prefix = "test"
            output.format = "dcd"
        )"_toml);

        const auto obs = mjolnir::read_observer<traits_type>(v);
        BOOST_TEST(obs.observers().size() == 2u);

        const auto dcd = dynamic_cast<mjolnir::DCDObserver<traits_type>*>(
                             obs.observers().at(0).get());
        BOOST_TEST(static_cast<bool>(dcd));

        const auto ene = dynamic_cast<mjolnir::EnergyObserver<traits_type>*>(
                             obs.observers().at(1).get());
        BOOST_TEST(static_cast<bool>(ene));
    }
}

// check that read_observer returns TRRObserver or not
BOOST_AUTO_TEST_CASE(read_trr_observer)
{
    mjolnir::LoggerManager::set_default_logger("test_read_observer.log");

    using real_type = double;
    using traits_type = mjolnir::SimulatorTraits<real_type, mjolnir::UnlimitedBoundary>;
    {
        using namespace toml::literals;
        const toml::table v = toml::get<toml::table>(u8R"(
            [files]
            output.path   = "./"
            output.prefix = "test"
            output.format = "trr"
        )"_toml);

        const auto obs = mjolnir::read_observer<traits_type>(v);
        BOOST_TEST(obs.observers().size() == 2u);

        const auto trr = dynamic_cast<mjolnir::TRRObserver<traits_type>*>(
                             obs.observers().at(0).get());
        BOOST_TEST(static_cast<bool>(trr));

        const auto ene = dynamic_cast<mjolnir::EnergyObserver<traits_type>*>(
                             obs.observers().at(1).get());
        BOOST_TEST(static_cast<bool>(ene));
    }
}
<commit_msg>test: update test_read_observer for MsgPack<commit_after>#define BOOST_TEST_MODULE "test_read_observer"

#ifdef BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#else
#include <boost/test/included/unit_test.hpp>
#endif

#include <mjolnir/core/BoundaryCondition.hpp>
#include <mjolnir/core/SimulatorTraits.hpp>
#include <mjolnir/input/read_observer.hpp>

BOOST_AUTO_TEST_CASE(read_observer)
{
    mjolnir::LoggerManager::set_default_logger("test_read_observer.log");

    using real_type = double;
    using traits_type = mjolnir::SimulatorTraits<real_type, mjolnir::UnlimitedBoundary>;
    {
        using namespace toml::literals;
        const toml::table v = toml::get<toml::table>(u8R"(
            [files]
            output.path   = "./"
            output.prefix = "test"
            output.format = "xyz"
        )"_toml);

        const auto obs = mjolnir::read_observer<traits_type>(v);
        BOOST_TEST(obs.observers().size() == 3u);
        BOOST_TEST(obs.observers().at(0)->prefix() == "./test");
        BOOST_TEST(obs.observers().at(1)->prefix() == "./test");
        BOOST_TEST(obs.observers().at(2)->prefix() == "./test");

        bool has_xyz = false;
        bool has_ene = false;
        bool has_msg = false;
        for(const auto ptr : obs.observers())
        {
            const auto xyz = dynamic_cast<mjolnir::XYZObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(xyz))
            {
                has_xyz = true;
            }
            const auto ene = dynamic_cast<mjolnir::EnergyObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(ene))
            {
                has_ene = true;
            }
            const auto msg = dynamic_cast<mjolnir::MsgPackObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(msg))
            {
                has_msg = true;
            }
        }

        BOOST_TEST(has_xyz);
        BOOST_TEST(has_ene);
        BOOST_TEST(has_msg);
    }
    {
        using namespace toml::literals;
        const toml::table v = toml::get<toml::table>(u8R"(
            [files]
            output.prefix = "test"
            output.format = "xyz"
        )"_toml);

        const auto obs = mjolnir::read_observer<traits_type>(v);
        BOOST_TEST(obs.observers().size() == 3u);
        BOOST_TEST(obs.observers().at(0)->prefix() == "./test");
        BOOST_TEST(obs.observers().at(1)->prefix() == "./test");
        BOOST_TEST(obs.observers().at(2)->prefix() == "./test");

        bool has_xyz = false;
        bool has_ene = false;
        bool has_msg = false;
        for(const auto ptr : obs.observers())
        {
            const auto xyz = dynamic_cast<mjolnir::XYZObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(xyz))
            {
                has_xyz = true;
            }
            const auto ene = dynamic_cast<mjolnir::EnergyObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(ene))
            {
                has_ene = true;
            }
            const auto msg = dynamic_cast<mjolnir::MsgPackObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(msg))
            {
                has_msg = true;
            }
        }
        BOOST_TEST(has_xyz);
        BOOST_TEST(has_ene);
        BOOST_TEST(has_msg);
    }

    // XXX
    // The following block tests read_observer successfully adds a path before
    // the prefix. But it requires the directory `test` under WORKING_DIRECTORY.
    // It strongly depends on the directory structure...
    // It is not good. We need to find a way to avoid this dependency.
    {
        using namespace toml::literals;
        const toml::table v = toml::get<toml::table>(u8R"(
            [files]
            output.path   = "./test"
            output.prefix = "test"
            output.format = "xyz"
        )"_toml);

        const auto obs = mjolnir::read_observer<traits_type>(v);

        BOOST_TEST(obs.observers().size() == 3u);
        BOOST_TEST(obs.observers().at(0)->prefix() == "./test/test");
        BOOST_TEST(obs.observers().at(1)->prefix() == "./test/test");
        BOOST_TEST(obs.observers().at(2)->prefix() == "./test/test");

        bool has_xyz = false;
        bool has_ene = false;
        bool has_msg = false;
        for(const auto ptr : obs.observers())
        {
            const auto xyz = dynamic_cast<mjolnir::XYZObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(xyz))
            {
                has_xyz = true;
            }
            const auto ene = dynamic_cast<mjolnir::EnergyObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(ene))
            {
                has_ene = true;
            }
            const auto msg = dynamic_cast<mjolnir::MsgPackObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(msg))
            {
                has_msg = true;
            }
        }
        BOOST_TEST(has_xyz);
        BOOST_TEST(has_ene);
        BOOST_TEST(has_msg);
    }
}

// check that read_observer returns XYZObserver or not
BOOST_AUTO_TEST_CASE(read_xyz_observer)
{
    mjolnir::LoggerManager::set_default_logger("test_read_observer.log");

    using real_type = double;
    using traits_type = mjolnir::SimulatorTraits<real_type, mjolnir::UnlimitedBoundary>;
    {
        using namespace toml::literals;
        const toml::table v = toml::get<toml::table>(u8R"(
            [files]
            output.path   = "./"
            output.prefix = "test"
            output.format = "xyz"
        )"_toml);

        const auto obs = mjolnir::read_observer<traits_type>(v);
        BOOST_TEST(obs.observers().size() == 3u);

        bool has_xyz = false;
        bool has_ene = false;
        bool has_msg = false;
        for(const auto ptr : obs.observers())
        {
            const auto xyz = dynamic_cast<mjolnir::XYZObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(xyz))
            {
                has_xyz = true;
            }
            const auto ene = dynamic_cast<mjolnir::EnergyObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(ene))
            {
                has_ene = true;
            }
            const auto msg = dynamic_cast<mjolnir::MsgPackObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(msg))
            {
                has_msg = true;
            }
        }
        BOOST_TEST(has_xyz);
        BOOST_TEST(has_ene);
        BOOST_TEST(has_msg);
    }
}

// check that read_observer returns DCDObserver or not
BOOST_AUTO_TEST_CASE(read_dcd_observer)
{
    mjolnir::LoggerManager::set_default_logger("test_read_observer.log");

    using real_type = double;
    using traits_type = mjolnir::SimulatorTraits<real_type, mjolnir::UnlimitedBoundary>;
    {
        using namespace toml::literals;
        const toml::table v = toml::get<toml::table>(u8R"(
            [files]
            output.path   = "./"
            output.prefix = "test"
            output.format = "dcd"
        )"_toml);

        const auto obs = mjolnir::read_observer<traits_type>(v);
        BOOST_TEST(obs.observers().size() == 3u);

        bool has_dcd = false;
        bool has_ene = false;
        bool has_msg = false;
        for(const auto ptr : obs.observers())
        {
            const auto dcd = dynamic_cast<mjolnir::DCDObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(dcd))
            {
                has_dcd = true;
            }
            const auto ene = dynamic_cast<mjolnir::EnergyObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(ene))
            {
                has_ene = true;
            }
            const auto msg = dynamic_cast<mjolnir::MsgPackObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(msg))
            {
                has_msg = true;
            }
        }
        BOOST_TEST(has_dcd);
        BOOST_TEST(has_ene);
        BOOST_TEST(has_msg);
    }
}

// check that read_observer returns TRRObserver or not
BOOST_AUTO_TEST_CASE(read_trr_observer)
{
    mjolnir::LoggerManager::set_default_logger("test_read_observer.log");

    using real_type = double;
    using traits_type = mjolnir::SimulatorTraits<real_type, mjolnir::UnlimitedBoundary>;
    {
        using namespace toml::literals;
        const toml::table v = toml::get<toml::table>(u8R"(
            [files]
            output.path   = "./"
            output.prefix = "test"
            output.format = "trr"
        )"_toml);

        const auto obs = mjolnir::read_observer<traits_type>(v);
        BOOST_TEST(obs.observers().size() == 3u);

        bool has_trr = false;
        bool has_ene = false;
        bool has_msg = false;
        for(const auto ptr : obs.observers())
        {
            const auto trr = dynamic_cast<mjolnir::TRRObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(trr))
            {
                has_trr = true;
            }
            const auto ene = dynamic_cast<mjolnir::EnergyObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(ene))
            {
                has_ene = true;
            }
            const auto msg = dynamic_cast<mjolnir::MsgPackObserver<traits_type>*>(ptr.get());
            if(static_cast<bool>(msg))
            {
                has_msg = true;
            }
        }
        BOOST_TEST(has_trr);
        BOOST_TEST(has_ene);
        BOOST_TEST(has_msg);
    }
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "test/cpp/util/cli_credentials.h"

#include <gflags/gflags.h>

DEFINE_bool(
    enable_ssl, false,
    "Whether to use ssl/tls. Deprecated. Use --channel_creds_type=ssl.");
DEFINE_bool(use_auth, false,
            "Whether to create default google credentials. Deprecated. Use "
            "--channel_creds_type=google_default_credentials.");
DEFINE_string(
    access_token, "",
    "The access token that will be sent to the server to authenticate RPCs.");
DEFINE_string(
    ssl_target, "",
    "If not empty, treat the server host name as this for ssl/tls certificate "
    "validation.");
DEFINE_string(
    channel_creds_type, "",
    "The channel creds type: insecure, ssl, google_default_credentials or "
    "alts.");

namespace grpc {
namespace testing {

grpc::string CliCredentials::GetDefaultChannelCredsType() const {
  // Compatibility logic for --enable_ssl.
  if (FLAGS_enable_ssl) {
    fprintf(stderr,
            "warning: --enable_ssl is deprecated. Use "
            "--channel_creds_type=ssl.\n");
    return "ssl";
  }
  // Compatibility logic for --use_auth.
  if (FLAGS_access_token.empty() && FLAGS_use_auth) {
    fprintf(stderr,
            "warning: --use_auth is deprecated. Use "
            "--channel_creds_type=google_default_credentials.\n");
    return "google_default_credentials";
  }
  return "insecure";
}

std::shared_ptr<grpc::ChannelCredentials>
CliCredentials::GetChannelCredentials() const {
  if (FLAGS_channel_creds_type.compare("insecure") == 0) {
    return grpc::InsecureChannelCredentials();
  } else if (FLAGS_channel_creds_type.compare("ssl") == 0) {
    return grpc::SslCredentials(grpc::SslCredentialsOptions());
  } else if (FLAGS_channel_creds_type.compare("google_default_credentials") ==
             0) {
    return grpc::GoogleDefaultCredentials();
  } else if (FLAGS_channel_creds_type.compare("alts") == 0) {
    return grpc::experimental::AltsCredentials(
        grpc::experimental::AltsCredentialsOptions());
  }
  fprintf(stderr,
          "--channel_creds_type=%s invalid; must be insecure, ssl, "
          "google_default_credentials or alts.\n",
          FLAGS_channel_creds_type.c_str());
  return std::shared_ptr<grpc::ChannelCredentials>();
}

std::shared_ptr<grpc::CallCredentials> CliCredentials::GetCallCredentials()
    const {
  if (!FLAGS_access_token.empty()) {
    if (FLAGS_use_auth) {
      fprintf(stderr,
              "warning: use_auth is ignored when access_token is provided.");
    }
    return grpc::AccessTokenCredentials(FLAGS_access_token);
  }
  return std::shared_ptr<grpc::CallCredentials>();
}

std::shared_ptr<grpc::ChannelCredentials> CliCredentials::GetCredentials()
    const {
  if (FLAGS_channel_creds_type.empty()) {
    FLAGS_channel_creds_type = GetDefaultChannelCredsType();
  } else if (FLAGS_enable_ssl && FLAGS_channel_creds_type.compare("ssl") != 0) {
    fprintf(stderr,
            "warning: ignoring --enable_ssl because "
            "--channel_creds_type already set to %s.\n",
            FLAGS_channel_creds_type.c_str());
  } else if (FLAGS_use_auth && FLAGS_channel_creds_type.compare(
                                   "google_default_credentials") != 0) {
    fprintf(stderr,
            "warning: ignoring --use_auth because "
            "--channel_creds_type already set to %s.\n",
            FLAGS_channel_creds_type.c_str());
  }
  // Legacy transport upgrade logic for insecure requests.
  if (!FLAGS_access_token.empty() &&
      FLAGS_channel_creds_type.compare("insecure") == 0) {
    fprintf(stderr,
            "warning: --channel_creds_type=insecure upgraded to ssl because "
            "an access token was provided.\n");
    FLAGS_channel_creds_type = "ssl";
  }
  std::shared_ptr<grpc::ChannelCredentials> channel_creds =
      GetChannelCredentials();
  // Composite any call-type credentials on top of the base channel.
  std::shared_ptr<grpc::CallCredentials> call_creds = GetCallCredentials();
  return (channel_creds == nullptr || call_creds == nullptr)
             ? channel_creds
             : grpc::CompositeChannelCredentials(channel_creds, call_creds);
}

const grpc::string CliCredentials::GetCredentialUsage() const {
  return "    --enable_ssl             ; Set whether to use ssl (deprecated)\n"
         "    --use_auth               ; Set whether to create default google"
         " credentials\n"
         "    --access_token           ; Set the access token in metadata,"
         " overrides --use_auth\n"
         "    --ssl_target             ; Set server host for ssl validation\n"
         "    --channel_creds_type     ; Set to insecure, ssl, alts or\n"
         "                             ; google_default_credentials\n";
}

const grpc::string CliCredentials::GetSslTargetNameOverride() const {
  bool use_ssl =
      FLAGS_channel_creds_type.compare("ssl") == 0 ||
      FLAGS_channel_creds_type.compare("google_default_credentials") == 0;
  return use_ssl ? FLAGS_ssl_target : "";
}

}  // namespace testing
}  // namespace grpc
<commit_msg>Shorten flag value to gdc.<commit_after>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "test/cpp/util/cli_credentials.h"

#include <gflags/gflags.h>

DEFINE_bool(
    enable_ssl, false,
    "Whether to use ssl/tls. Deprecated. Use --channel_creds_type=ssl.");
DEFINE_bool(use_auth, false,
            "Whether to create default google credentials. Deprecated. Use "
            "--channel_creds_type=gdc.");
DEFINE_string(
    access_token, "",
    "The access token that will be sent to the server to authenticate RPCs.");
DEFINE_string(
    ssl_target, "",
    "If not empty, treat the server host name as this for ssl/tls certificate "
    "validation.");
DEFINE_string(
    channel_creds_type, "",
    "The channel creds type: insecure, ssl, gdc (Google Default Credentials) "
    "or alts.");

namespace grpc {
namespace testing {

grpc::string CliCredentials::GetDefaultChannelCredsType() const {
  // Compatibility logic for --enable_ssl.
  if (FLAGS_enable_ssl) {
    fprintf(stderr,
            "warning: --enable_ssl is deprecated. Use "
            "--channel_creds_type=ssl.\n");
    return "ssl";
  }
  // Compatibility logic for --use_auth.
  if (FLAGS_access_token.empty() && FLAGS_use_auth) {
    fprintf(stderr,
            "warning: --use_auth is deprecated. Use "
            "--channel_creds_type=gdc.\n");
    return "gdc";
  }
  return "insecure";
}

std::shared_ptr<grpc::ChannelCredentials>
CliCredentials::GetChannelCredentials() const {
  if (FLAGS_channel_creds_type.compare("insecure") == 0) {
    return grpc::InsecureChannelCredentials();
  } else if (FLAGS_channel_creds_type.compare("ssl") == 0) {
    return grpc::SslCredentials(grpc::SslCredentialsOptions());
  } else if (FLAGS_channel_creds_type.compare("gdc") == 0) {
    return grpc::GoogleDefaultCredentials();
  } else if (FLAGS_channel_creds_type.compare("alts") == 0) {
    return grpc::experimental::AltsCredentials(
        grpc::experimental::AltsCredentialsOptions());
  }
  fprintf(stderr,
          "--channel_creds_type=%s invalid; must be insecure, ssl, gdc or "
          "alts.\n",
          FLAGS_channel_creds_type.c_str());
  return std::shared_ptr<grpc::ChannelCredentials>();
}

std::shared_ptr<grpc::CallCredentials> CliCredentials::GetCallCredentials()
    const {
  if (!FLAGS_access_token.empty()) {
    if (FLAGS_use_auth) {
      fprintf(stderr,
              "warning: use_auth is ignored when access_token is provided.");
    }
    return grpc::AccessTokenCredentials(FLAGS_access_token);
  }
  return std::shared_ptr<grpc::CallCredentials>();
}

std::shared_ptr<grpc::ChannelCredentials> CliCredentials::GetCredentials()
    const {
  if (FLAGS_channel_creds_type.empty()) {
    FLAGS_channel_creds_type = GetDefaultChannelCredsType();
  } else if (FLAGS_enable_ssl && FLAGS_channel_creds_type.compare("ssl") != 0) {
    fprintf(stderr,
            "warning: ignoring --enable_ssl because "
            "--channel_creds_type already set to %s.\n",
            FLAGS_channel_creds_type.c_str());
  } else if (FLAGS_use_auth && FLAGS_channel_creds_type.compare("gdc") != 0) {
    fprintf(stderr,
            "warning: ignoring --use_auth because "
            "--channel_creds_type already set to %s.\n",
            FLAGS_channel_creds_type.c_str());
  }
  // Legacy transport upgrade logic for insecure requests.
  if (!FLAGS_access_token.empty() &&
      FLAGS_channel_creds_type.compare("insecure") == 0) {
    fprintf(stderr,
            "warning: --channel_creds_type=insecure upgraded to ssl because "
            "an access token was provided.\n");
    FLAGS_channel_creds_type = "ssl";
  }
  std::shared_ptr<grpc::ChannelCredentials> channel_creds =
      GetChannelCredentials();
  // Composite any call-type credentials on top of the base channel.
  std::shared_ptr<grpc::CallCredentials> call_creds = GetCallCredentials();
  return (channel_creds == nullptr || call_creds == nullptr)
             ? channel_creds
             : grpc::CompositeChannelCredentials(channel_creds, call_creds);
}

const grpc::string CliCredentials::GetCredentialUsage() const {
  return "    --enable_ssl             ; Set whether to use ssl (deprecated)\n"
         "    --use_auth               ; Set whether to create default google"
         " credentials\n"
         "    --access_token           ; Set the access token in metadata,"
         " overrides --use_auth\n"
         "    --ssl_target             ; Set server host for ssl validation\n"
         "    --channel_creds_type     ; Set to insecure, ssl, gdc, or alts\n";
}

const grpc::string CliCredentials::GetSslTargetNameOverride() const {
  bool use_ssl = FLAGS_channel_creds_type.compare("ssl") == 0 ||
                 FLAGS_channel_creds_type.compare("gdc") == 0;
  return use_ssl ? FLAGS_ssl_target : "";
}

}  // namespace testing
}  // namespace grpc
<|endoftext|>