<commit_before>/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdint>

#include "QMath.h"

struct Stats {
    int diff_8_bits = 0;
    int max_diff = 0;
    int min_diff = 0;
    int64_t total = 0;

    void log(int16_t golden, int16_t candidate) {
        int diff = candidate - golden;
        max_diff = std::max(max_diff, diff);
        min_diff = std::min(min_diff, diff);
        diff_8_bits += candidate != golden;
        total++;
    }

    void print() const {
        printf("8-bit diff: %d - %g%%\n", diff_8_bits, 100.0 * diff_8_bits / total);
        printf("differences min: %d max: %d\n", min_diff, max_diff);
        printf("total: %lld\n", total);
    }
};

static float golden_lerp(float t, int16_t a, int16_t b) {
    return (1.0f - t) * a + t * b;
}

template <int logPixelScale>
static int16_t saturating_lerp(float t, int16_t a, int16_t b) {
    const int16_t half = 1 << (logPixelScale - 1);
    Q15 qt(floor(t * 32768.f + 0.5f));
    Q15 qa(a << logPixelScale);
    Q15 qb(b << logPixelScale);

    Q15 answer = simulate_neon_vqrdmulhq_s16(qt, qb - qa) + qa;
    return (answer[0] + half) >> logPixelScale;
}

template <int logPixelScale>
static int16_t ssse3_lerp(float t, int16_t a, int16_t b) {
    const int16_t half = 1 << (logPixelScale - 1);
    Q15 qt(floor(t * 32768.f + 0.5f));
    Q15 qa(a << logPixelScale);
    Q15 qb(b << logPixelScale);

    Q15 answer = simulate_ssse3_mm_mulhrs_epi16(qt, qb - qa) + qa;
    return (answer[0] + half) >> logPixelScale;
}

// Change of parameters on t from [0, 1) to [-1, 1). This cuts the number if differences in half.
template <int logPixelScale>
static int16_t balanced_lerp(float t, int16_t a, int16_t b) {
    const int16_t half = 1 << logPixelScale;
    // t on [-1, 1).
    Q15 qt (floor(t * 65536.0f - 32768.0f + 0.5f));
    // need to pick logPixelScale to scale by addition 1/2.
    Q15 qw ((b - a) << logPixelScale);
    Q15 qm ((a + b) << logPixelScale);
    Q15 answer = simulate_ssse3_mm_mulhrs_epi16(qt, qw) + qm;
    // Extra shift to divide by 2.
    return (answer[0] + half) >> (logPixelScale + 1);
}

template <typename Lerp>
static Stats check_lerp(Lerp lerp) {
    Stats stats;
    for (float t = 0; t < 1.0f; t += 1.0f/32768.0f)
    for (int a = 255; a >= 0; a--)
    for (int b = 255; b >= 0; b--) {
        float l = golden_lerp(t, a, b);
        int16_t golden = floor(l + 0.5f);
        int16_t candidate = lerp(t, a, b);
        stats.log(golden, candidate);
    }
    return stats;
}

// Simulate a scaled intermediate value for bilerp.
template <typename Lerp>
static Stats check_scaled_lerp(Lerp lerp) {
    Stats stats;
    for (float t = 0; t < 1.0f; t += 1.0f/32768.0f)
    for (int a = 255; a >= 0; a--)
    for (int b = 255; b >= 0; b--) {
        int16_t scaledA = a << 6,
                scaledB = b << 6;

        float l = golden_lerp(t, scaledA, scaledB);
        int16_t golden = floor(l + 0.5f);
        int16_t candidate = lerp(t, scaledA, scaledB);
        stats.log(golden, candidate);
    }
    return stats;
}

int main() {
    Stats stats;

    printf("Using vqrdmulhq_s16...\n");
    stats = check_lerp(saturating_lerp<7>);
    stats.print();

    printf("\nUsing mm_mulhrs_epi16...\n");
    stats = check_lerp(ssse3_lerp<7>);
    stats.print();

    printf("\nScaled using vqrdmulhq_s16...\n");
    // Need one bit for rounding.
    stats = check_scaled_lerp(saturating_lerp<1>);
    stats.print();

    printf("\nScaled using mm_mulhrs_epi16...\n");
    // Need one bit for rounding.
    stats = check_scaled_lerp(ssse3_lerp<1>);
    stats.print();

    printf("\nInterval [-1, 1) mm_mulhrs_epi16...\n");
    stats = check_lerp(balanced_lerp<7>);
    stats.print();

    printf("Done.");
    return 0;
}

<commit_msg>use higher res to check [-1, 1)<commit_after>/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdint>

#include "QMath.h"

struct Stats {
    int diff_8_bits = 0;
    int max_diff = 0;
    int min_diff = 0;
    int64_t total = 0;

    void log(int16_t golden, int16_t candidate) {
        int diff = candidate - golden;
        max_diff = std::max(max_diff, diff);
        min_diff = std::min(min_diff, diff);
        diff_8_bits += candidate != golden;
        total++;
    }

    void print() const {
        printf("8-bit diff: %d - %g%%\n", diff_8_bits, 100.0 * diff_8_bits / total);
        printf("differences min: %d max: %d\n", min_diff, max_diff);
        printf("total: %lld\n", total);
    }
};

static float golden_lerp(float t, int16_t a, int16_t b) {
    return (1.0f - t) * a + t * b;
}

template <int logPixelScale>
static int16_t saturating_lerp(float t, int16_t a, int16_t b) {
    const int16_t half = 1 << (logPixelScale - 1);
    Q15 qt(floor(t * 32768.f + 0.5f));
    Q15 qa(a << logPixelScale);
    Q15 qb(b << logPixelScale);

    Q15 answer = simulate_neon_vqrdmulhq_s16(qt, qb - qa) + qa;
    return (answer[0] + half) >> logPixelScale;
}

template <int logPixelScale>
static int16_t ssse3_lerp(float t, int16_t a, int16_t b) {
    const int16_t half = 1 << (logPixelScale - 1);
    Q15 qt(floor(t * 32768.f + 0.5f));
    Q15 qa(a << logPixelScale);
    Q15 qb(b << logPixelScale);

    Q15 answer = simulate_ssse3_mm_mulhrs_epi16(qt, qb - qa) + qa;
    return (answer[0] + half) >> logPixelScale;
}

// Change of parameters on t from [0, 1) to [-1, 1). This cuts the number if differences in half.
template <int logPixelScale>
static int16_t balanced_lerp(float t, int16_t a, int16_t b) {
    const int16_t half = 1 << logPixelScale;
    // t on [-1, 1).
    Q15 qt (floor(t * 65536.0f - 32768.0f + 0.5f));
    // need to pick logPixelScale to scale by addition 1/2.
    Q15 qw ((b - a) << logPixelScale);
    Q15 qm ((a + b) << logPixelScale);
    Q15 answer = simulate_ssse3_mm_mulhrs_epi16(qt, qw) + qm;
    // Extra shift to divide by 2.
    return (answer[0] + half) >> (logPixelScale + 1);
}

template <typename Lerp>
static Stats check_lerp(Lerp lerp) {
    Stats stats;
    for (float t = 0; t < 1.0f - 1.0f / 65536.0f ; t += 1.0f/65536.0f)
    for (int a = 255; a >= 0; a--)
    for (int b = 255; b >= 0; b--) {
        float l = golden_lerp(t, a, b);
        int16_t golden = floor(l + 0.5f);
        int16_t candidate = lerp(t, a, b);
        stats.log(golden, candidate);
    }
    return stats;
}

int main() {
    Stats stats;

    printf("Using vqrdmulhq_s16...\n");
    stats = check_lerp(saturating_lerp<7>);
    stats.print();

    printf("\nUsing mm_mulhrs_epi16...\n");
    stats = check_lerp(ssse3_lerp<7>);
    stats.print();

    printf("\nInterval [-1, 1) mm_mulhrs_epi16...\n");
    stats = check_lerp(balanced_lerp<7>);
    stats.print();

    printf("Done.");
    return 0;
}

<|endoftext|>


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

#include "video/video_stream_decoder.h"

#include "modules/video_coding/include/video_coding.h"
#include "modules/video_coding/video_coding_impl.h"
#include "rtc_base/checks.h"
#include "video/receive_statistics_proxy.h"

namespace webrtc {

VideoStreamDecoder::VideoStreamDecoder(
    vcm::VideoReceiver* video_receiver,
    VCMPacketRequestCallback* vcm_packet_request_callback,
    bool enable_nack,
    bool /* enable_fec */,
    ReceiveStatisticsProxy* receive_statistics_proxy,
    rtc::VideoSinkInterface<VideoFrame>* incoming_video_stream)
    : video_receiver_(video_receiver),
      receive_stats_callback_(receive_statistics_proxy),
      incoming_video_stream_(incoming_video_stream) {
  RTC_DCHECK(video_receiver_);

  static const int kMaxPacketAgeToNack = 450;
  static const int kMaxNackListSize = 250;
  video_receiver_->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0);
  video_receiver_->RegisterReceiveCallback(this);

  VCMPacketRequestCallback* packet_request_callback =
      enable_nack ? vcm_packet_request_callback : nullptr;
  video_receiver_->RegisterPacketRequestCallback(packet_request_callback);
}

VideoStreamDecoder::~VideoStreamDecoder() {
  // Note: There's an assumption at this point that the decoder thread is
  // *not* running. If it was, then there could be a race for each of these
  // callbacks.

  // Unset all the callback pointers that we set in the ctor.
  video_receiver_->RegisterPacketRequestCallback(nullptr);
  video_receiver_->RegisterReceiveCallback(nullptr);
}

// Do not acquire the lock of |video_receiver_| in this function. Decode
// callback won't necessarily be called from the decoding thread. The decoding
// thread may have held the lock when calling VideoDecoder::Decode, Reset, or
// Release. Acquiring the same lock in the path of decode callback can deadlock.
int32_t VideoStreamDecoder::FrameToRender(VideoFrame& video_frame,
                                          absl::optional<uint8_t> qp,
                                          VideoContentType content_type) {
  receive_stats_callback_->OnDecodedFrame(video_frame, qp, content_type);
  incoming_video_stream_->OnFrame(video_frame);
  return 0;
}

int32_t VideoStreamDecoder::ReceivedDecodedReferenceFrame(
    const uint64_t picture_id) {
  RTC_NOTREACHED();
  return 0;
}

void VideoStreamDecoder::OnIncomingPayloadType(int payload_type) {
  receive_stats_callback_->OnIncomingPayloadType(payload_type);
}

void VideoStreamDecoder::OnDecoderImplementationName(
    const char* implementation_name) {
  receive_stats_callback_->OnDecoderImplementationName(implementation_name);
}

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

#include "video/video_stream_decoder.h"

#include "modules/video_coding/include/video_coding.h"
#include "modules/video_coding/video_coding_impl.h"
#include "rtc_base/checks.h"
#include "video/receive_statistics_proxy.h"

namespace webrtc {

VideoStreamDecoder::VideoStreamDecoder(
    vcm::VideoReceiver* video_receiver,
    VCMPacketRequestCallback* vcm_packet_request_callback,
    bool enable_nack,
    bool /* enable_fec */,
    ReceiveStatisticsProxy* receive_statistics_proxy,
    rtc::VideoSinkInterface<VideoFrame>* incoming_video_stream)
    : video_receiver_(video_receiver),
      receive_stats_callback_(receive_statistics_proxy),
      incoming_video_stream_(incoming_video_stream) {
  RTC_DCHECK(video_receiver_);

  video_receiver_->RegisterReceiveCallback(this);

  VCMPacketRequestCallback* packet_request_callback =
      enable_nack ? vcm_packet_request_callback : nullptr;
  video_receiver_->RegisterPacketRequestCallback(packet_request_callback);
}

VideoStreamDecoder::~VideoStreamDecoder() {
  // Note: There's an assumption at this point that the decoder thread is
  // *not* running. If it was, then there could be a race for each of these
  // callbacks.

  // Unset all the callback pointers that we set in the ctor.
  video_receiver_->RegisterPacketRequestCallback(nullptr);
  video_receiver_->RegisterReceiveCallback(nullptr);
}

// Do not acquire the lock of |video_receiver_| in this function. Decode
// callback won't necessarily be called from the decoding thread. The decoding
// thread may have held the lock when calling VideoDecoder::Decode, Reset, or
// Release. Acquiring the same lock in the path of decode callback can deadlock.
int32_t VideoStreamDecoder::FrameToRender(VideoFrame& video_frame,
                                          absl::optional<uint8_t> qp,
                                          VideoContentType content_type) {
  receive_stats_callback_->OnDecodedFrame(video_frame, qp, content_type);
  incoming_video_stream_->OnFrame(video_frame);
  return 0;
}

int32_t VideoStreamDecoder::ReceivedDecodedReferenceFrame(
    const uint64_t picture_id) {
  RTC_NOTREACHED();
  return 0;
}

void VideoStreamDecoder::OnIncomingPayloadType(int payload_type) {
  receive_stats_callback_->OnIncomingPayloadType(payload_type);
}

void VideoStreamDecoder::OnDecoderImplementationName(
    const char* implementation_name) {
  receive_stats_callback_->OnDecoderImplementationName(implementation_name);
}

}  // namespace webrtc
<|endoftext|>


<commit_before>#include <functional>

#include "arch/runtime/starter.hpp"
#include "serializer/config.hpp"
#include "unittest/mock_file.hpp"
#include "unittest/gtest.hpp"

namespace unittest {

// This test is completely vacuous, but should invite expansion in the future.

void run_CreateConstructDestroy() {
    // This serves more as a mock_file_t test than a serializer test.
    mock_file_opener_t file_opener;
    standard_serializer_t::create(&file_opener, standard_serializer_t::static_config_t());
    standard_serializer_t ser(standard_serializer_t::dynamic_config_t(),
                              &file_opener,
                              &get_global_perfmon_collection());
}

TEST(SerializerTest, CreateConstructDestroy) {
    run_in_thread_pool(run_CreateConstructDestroy, 4);
}

void run_AddDeleteRepeatedly(bool perform_index_write) {
    mock_file_opener_t file_opener;
    standard_serializer_t::create(&file_opener, standard_serializer_t::static_config_t());
    standard_serializer_t ser(standard_serializer_t::dynamic_config_t(),
                              &file_opener,
                              &get_global_perfmon_collection());

    scoped_malloc_t<ser_buffer_t> buf = ser.malloc();
    memset(buf->cache_data, 0, ser.get_block_size().value());

    scoped_ptr_t<file_account_t> account(ser.make_io_account(1));

    // We run enough create/delete operations to run ourselves through the young
    // extent queue and (with perform_index_write true) kick off a GC that reproduces
    // #1691.
    for (int i = 0; i < 200000; ++i) {
        const block_id_t block_id = i;
        std::vector<buf_write_info_t> infos;
        infos.push_back(buf_write_info_t(buf.get(), ser.get_block_size(), block_id));

        // Create the block
        struct : public iocallback_t, public cond_t {
            void on_io_complete() {
                pulse();
            }
        } cb;

        std::vector<counted_t<standard_block_token_t> > tokens
            = ser.block_writes(infos, account.get(), &cb);

        // Wait for it to be written (because we're nice).
        cb.wait();

        if (perform_index_write) {
            // Do an index write creating the block.
            {
                std::vector<index_write_op_t> write_ops;
                write_ops.push_back(index_write_op_t(block_id, tokens[0], repli_timestamp_t::distant_past));
                ser.index_write(write_ops, account.get());
            }
            // Now delete the only block token and delete the index reference.
            tokens.clear();
            {
                std::vector<index_write_op_t> write_ops;
                write_ops.push_back(index_write_op_t(block_id, counted_t<standard_block_token_t>()));
                ser.index_write(write_ops, account.get());
            }

        } else {
            // Now delete the only block token.
            tokens.clear();
        }
    }
}

TEST(SerializerTest, AddDeleteRepeatedly) {
    run_in_thread_pool(std::bind(run_AddDeleteRepeatedly, false), 4);
}

// This is a regression test for #1691.
TEST(SerializerTest, AddDeleteRepeatedlyWithIndex) {
    run_in_thread_pool(std::bind(run_AddDeleteRepeatedly, true), 4);
}

}  // namespace unittest
<commit_msg>Reduced number of iterations in run_AddDeleteRepeatedly to 2000.<commit_after>#include <functional>

#include "arch/runtime/starter.hpp"
#include "serializer/config.hpp"
#include "unittest/mock_file.hpp"
#include "unittest/gtest.hpp"

namespace unittest {

// This test is completely vacuous, but should invite expansion in the future.

void run_CreateConstructDestroy() {
    // This serves more as a mock_file_t test than a serializer test.
    mock_file_opener_t file_opener;
    standard_serializer_t::create(&file_opener, standard_serializer_t::static_config_t());
    standard_serializer_t ser(standard_serializer_t::dynamic_config_t(),
                              &file_opener,
                              &get_global_perfmon_collection());
}

TEST(SerializerTest, CreateConstructDestroy) {
    run_in_thread_pool(run_CreateConstructDestroy, 4);
}

void run_AddDeleteRepeatedly(bool perform_index_write) {
    mock_file_opener_t file_opener;
    standard_serializer_t::create(&file_opener, standard_serializer_t::static_config_t());
    standard_serializer_t ser(standard_serializer_t::dynamic_config_t(),
                              &file_opener,
                              &get_global_perfmon_collection());

    scoped_malloc_t<ser_buffer_t> buf = ser.malloc();
    memset(buf->cache_data, 0, ser.get_block_size().value());

    scoped_ptr_t<file_account_t> account(ser.make_io_account(1));

    // We run enough create/delete operations to run ourselves through the young
    // extent queue and (with perform_index_write true) kick off a GC that reproduces
    // #1691.
    for (int i = 0; i < 2000; ++i) {
        const block_id_t block_id = i;
        std::vector<buf_write_info_t> infos;
        infos.push_back(buf_write_info_t(buf.get(), ser.get_block_size(), block_id));

        // Create the block
        struct : public iocallback_t, public cond_t {
            void on_io_complete() {
                pulse();
            }
        } cb;

        std::vector<counted_t<standard_block_token_t> > tokens
            = ser.block_writes(infos, account.get(), &cb);

        // Wait for it to be written (because we're nice).
        cb.wait();

        if (perform_index_write) {
            // Do an index write creating the block.
            {
                std::vector<index_write_op_t> write_ops;
                write_ops.push_back(index_write_op_t(block_id, tokens[0], repli_timestamp_t::distant_past));
                ser.index_write(write_ops, account.get());
            }
            // Now delete the only block token and delete the index reference.
            tokens.clear();
            {
                std::vector<index_write_op_t> write_ops;
                write_ops.push_back(index_write_op_t(block_id, counted_t<standard_block_token_t>()));
                ser.index_write(write_ops, account.get());
            }

        } else {
            // Now delete the only block token.
            tokens.clear();
        }
    }
}

TEST(SerializerTest, AddDeleteRepeatedly) {
    run_in_thread_pool(std::bind(run_AddDeleteRepeatedly, false), 4);
}

// This is a regression test for #1691.
TEST(SerializerTest, AddDeleteRepeatedlyWithIndex) {
    run_in_thread_pool(std::bind(run_AddDeleteRepeatedly, true), 4);
}

}  // namespace unittest
<|endoftext|>


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

#include "webrtc/video_engine/vie_base_impl.h"

#include <sstream>
#include <string>

#include "webrtc/engine_configurations.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
#include "webrtc/modules/video_coding/main/interface/video_coding.h"
#include "webrtc/modules/video_processing/main/interface/video_processing.h"
#include "webrtc/modules/video_render/include/video_render.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/trace.h"
#include "webrtc/video_engine/include/vie_errors.h"
#include "webrtc/video_engine/vie_channel.h"
#include "webrtc/video_engine/vie_channel_manager.h"
#include "webrtc/video_engine/vie_defines.h"
#include "webrtc/video_engine/vie_encoder.h"
#include "webrtc/video_engine/vie_impl.h"
#include "webrtc/video_engine/vie_input_manager.h"
#include "webrtc/video_engine/vie_shared_data.h"

namespace webrtc {

ViEBase* ViEBase::GetInterface(VideoEngine* video_engine) {
  if (!video_engine) {
    return NULL;
  }
  VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
  ViEBaseImpl* vie_base_impl = vie_impl;
  (*vie_base_impl)++;  // Increase ref count.

  return vie_base_impl;
}

int ViEBaseImpl::Release() {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, shared_data_.instance_id(),
               "ViEBase::Release()");
  (*this)--;  // Decrease ref count.

  int32_t ref_count = GetCount();
  if (ref_count < 0) {
    WEBRTC_TRACE(kTraceWarning, kTraceVideo, shared_data_.instance_id(),
                 "ViEBase release too many times");
    shared_data_.SetLastError(kViEAPIDoesNotExist);
    return -1;
  }
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, shared_data_.instance_id(),
               "ViEBase reference count: %d", ref_count);
  return ref_count;
}

ViEBaseImpl::ViEBaseImpl(const Config& config)
    : shared_data_(config) {
  WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_.instance_id(),
               "ViEBaseImpl::ViEBaseImpl() Ctor");
}

ViEBaseImpl::~ViEBaseImpl() {
  WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_.instance_id(),
               "ViEBaseImpl::ViEBaseImpl() Dtor");
}

int ViEBaseImpl::Init() {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, shared_data_.instance_id(),
               "Init");
  return 0;
}

int ViEBaseImpl::SetVoiceEngine(VoiceEngine* voice_engine) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s", __FUNCTION__);
  if (shared_data_.channel_manager()->SetVoiceEngine(voice_engine) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::CreateChannel(int& video_channel) {  // NOLINT
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s", __FUNCTION__);
  if (shared_data_.channel_manager()->CreateChannel(&video_channel) == -1) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
                 "%s: Could not create channel", __FUNCTION__);
    video_channel = -1;
    shared_data_.SetLastError(kViEBaseChannelCreationFailed);
    return -1;
  }
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s: channel created: %d", __FUNCTION__, video_channel);
  return 0;
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               int original_channel) {
  return CreateChannel(video_channel, original_channel, true);
}

int ViEBaseImpl::CreateReceiveChannel(int& video_channel,  // NOLINT
                                      int original_channel) {
  return CreateChannel(video_channel, original_channel, false);
}

int ViEBaseImpl::DeleteChannel(const int video_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s(%d)", __FUNCTION__, video_channel);
  {
    ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
    ViEChannel* vie_channel = cs.Channel(video_channel);
    if (!vie_channel) {
      WEBRTC_TRACE(kTraceError, kTraceVideo,
                   ViEId(shared_data_.instance_id()),
                   "%s: channel %d doesn't exist", __FUNCTION__, video_channel);
      shared_data_.SetLastError(kViEBaseInvalidChannelId);
      return -1;
    }

    // Deregister the ViEEncoder if no other channel is using it.
    ViEEncoder* vie_encoder = cs.Encoder(video_channel);
    if (cs.ChannelUsingViEEncoder(video_channel) == false) {
      ViEInputManagerScoped is(*(shared_data_.input_manager()));
      ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
      if (provider) {
        provider->DeregisterFrameCallback(vie_encoder);
      }
    }
  }

  if (shared_data_.channel_manager()->DeleteChannel(video_channel) == -1) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
                 "%s: Could not delete channel %d", __FUNCTION__,
                 video_channel);
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s: channel deleted: %d", __FUNCTION__, video_channel);
  return 0;
}

int ViEBaseImpl::ConnectAudioChannel(const int video_channel,
                                     const int audio_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s(%d)", __FUNCTION__, video_channel);
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(video_channel)) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
                 "%s: channel %d doesn't exist", __FUNCTION__, video_channel);
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->ConnectVoiceChannel(video_channel,
                                                          audio_channel) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::DisconnectAudioChannel(const int video_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s(%d)", __FUNCTION__, video_channel);
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(video_channel)) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
                 "%s: channel %d doesn't exist", __FUNCTION__, video_channel);
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->DisconnectVoiceChannel(
      video_channel) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StartSend(const int video_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_.instance_id(), video_channel),
               "%s(channel: %d)", __FUNCTION__, video_channel);

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_.instance_id(), video_channel),
                 "%s: Channel %d does not exist", __FUNCTION__, video_channel);
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder != NULL);
  if (vie_encoder->Owner() != video_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_.instance_id(), video_channel),
                 "Can't start ssend on a receive only channel.");
    shared_data_.SetLastError(kViEBaseReceiveOnlyChannel);
    return -1;
  }

  // Pause and trigger a key frame.
  vie_encoder->Pause();
  int32_t error = vie_channel->StartSend();
  if (error != 0) {
    vie_encoder->Restart();
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_.instance_id(), video_channel),
                 "%s: Could not start sending on channel %d", __FUNCTION__,
                 video_channel);
    if (error == kViEBaseAlreadySending) {
      shared_data_.SetLastError(kViEBaseAlreadySending);
    }
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  vie_encoder->SendKeyFrame();
  vie_encoder->Restart();
  return 0;
}

int ViEBaseImpl::StopSend(const int video_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_.instance_id(), video_channel),
               "%s(channel: %d)", __FUNCTION__, video_channel);

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_.instance_id(), video_channel),
                 "%s: Channel %d does not exist", __FUNCTION__, video_channel);
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  int32_t error = vie_channel->StopSend();
  if (error != 0) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_.instance_id(), video_channel),
                 "%s: Could not stop sending on channel %d", __FUNCTION__,
                 video_channel);
    if (error == kViEBaseNotSending) {
      shared_data_.SetLastError(kViEBaseNotSending);
    } else {
      shared_data_.SetLastError(kViEBaseUnknownError);
    }
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StartReceive(const int video_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_.instance_id(), video_channel),
               "%s(channel: %d)", __FUNCTION__, video_channel);

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_.instance_id(), video_channel),
                 "%s: Channel %d does not exist", __FUNCTION__, video_channel);
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  if (vie_channel->StartReceive() != 0) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StopReceive(const int video_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_.instance_id(), video_channel),
               "%s(channel: %d)", __FUNCTION__, video_channel);

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_.instance_id(), video_channel),
                 "%s: Channel %d does not exist", __FUNCTION__, video_channel);
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  if (vie_channel->StopReceive() != 0) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::GetVersion(char version[1024]) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
               "GetVersion(version=?)");
  assert(kViEVersionMaxMessageSize == 1024);
  if (!version) {
    shared_data_.SetLastError(kViEBaseInvalidArgument);
    return -1;
  }

  // Add WebRTC Version.
  std::stringstream version_stream;
  version_stream << "VideoEngine 3.32.0" << std::endl;

  // Add build info.
  version_stream << "Build: svn:" << WEBRTC_SVNREVISION << " " << BUILDINFO
                 << std::endl;

#ifdef WEBRTC_EXTERNAL_TRANSPORT
  version_stream << "External transport build" << std::endl;
#endif
  int version_length = version_stream.tellp();
  assert(version_length < 1024);
  memcpy(version, version_stream.str().c_str(), version_length);
  version[version_length] = '\0';

  WEBRTC_TRACE(kTraceStateInfo, kTraceVideo,
               ViEId(shared_data_.instance_id()), "GetVersion() => %s",
               version);
  return 0;
}

int ViEBaseImpl::LastError() {
  return shared_data_.LastErrorInternal();
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               int original_channel, bool sender) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(original_channel)) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
                 "%s - original_channel does not exist.", __FUNCTION__,
                 shared_data_.instance_id());
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->CreateChannel(&video_channel,
                                                    original_channel,
                                                    sender) == -1) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
                 "%s: Could not create channel", __FUNCTION__);
    video_channel = -1;
    shared_data_.SetLastError(kViEBaseChannelCreationFailed);
    return -1;
  }
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s: channel created: %d", __FUNCTION__, video_channel);
  return 0;
}

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

#include "webrtc/video_engine/vie_base_impl.h"

#include <sstream>
#include <string>

#include "webrtc/engine_configurations.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
#include "webrtc/modules/video_coding/main/interface/video_coding.h"
#include "webrtc/modules/video_processing/main/interface/video_processing.h"
#include "webrtc/modules/video_render/include/video_render.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/trace.h"
#include "webrtc/video_engine/include/vie_errors.h"
#include "webrtc/video_engine/vie_channel.h"
#include "webrtc/video_engine/vie_channel_manager.h"
#include "webrtc/video_engine/vie_defines.h"
#include "webrtc/video_engine/vie_encoder.h"
#include "webrtc/video_engine/vie_impl.h"
#include "webrtc/video_engine/vie_input_manager.h"
#include "webrtc/video_engine/vie_shared_data.h"

namespace webrtc {

ViEBase* ViEBase::GetInterface(VideoEngine* video_engine) {
  if (!video_engine) {
    return NULL;
  }
  VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
  ViEBaseImpl* vie_base_impl = vie_impl;
  (*vie_base_impl)++;  // Increase ref count.

  return vie_base_impl;
}

int ViEBaseImpl::Release() {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, shared_data_.instance_id(),
               "ViEBase::Release()");
  (*this)--;  // Decrease ref count.

  int32_t ref_count = GetCount();
  if (ref_count < 0) {
    WEBRTC_TRACE(kTraceWarning, kTraceVideo, shared_data_.instance_id(),
                 "ViEBase release too many times");
    shared_data_.SetLastError(kViEAPIDoesNotExist);
    return -1;
  }
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, shared_data_.instance_id(),
               "ViEBase reference count: %d", ref_count);
  return ref_count;
}

ViEBaseImpl::ViEBaseImpl(const Config& config)
    : shared_data_(config) {
  WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_.instance_id(),
               "ViEBaseImpl::ViEBaseImpl() Ctor");
}

ViEBaseImpl::~ViEBaseImpl() {
  WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_.instance_id(),
               "ViEBaseImpl::ViEBaseImpl() Dtor");
}

int ViEBaseImpl::Init() {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, shared_data_.instance_id(),
               "Init");
  return 0;
}

int ViEBaseImpl::SetVoiceEngine(VoiceEngine* voice_engine) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s", __FUNCTION__);
  if (shared_data_.channel_manager()->SetVoiceEngine(voice_engine) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::CreateChannel(int& video_channel) {  // NOLINT
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s", __FUNCTION__);
  if (shared_data_.channel_manager()->CreateChannel(&video_channel) == -1) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
                 "%s: Could not create channel", __FUNCTION__);
    video_channel = -1;
    shared_data_.SetLastError(kViEBaseChannelCreationFailed);
    return -1;
  }
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s: channel created: %d", __FUNCTION__, video_channel);
  return 0;
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               int original_channel) {
  return CreateChannel(video_channel, original_channel, true);
}

int ViEBaseImpl::CreateReceiveChannel(int& video_channel,  // NOLINT
                                      int original_channel) {
  return CreateChannel(video_channel, original_channel, false);
}

int ViEBaseImpl::DeleteChannel(const int video_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s(%d)", __FUNCTION__, video_channel);
  {
    ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
    ViEChannel* vie_channel = cs.Channel(video_channel);
    if (!vie_channel) {
      WEBRTC_TRACE(kTraceError, kTraceVideo,
                   ViEId(shared_data_.instance_id()),
                   "%s: channel %d doesn't exist", __FUNCTION__, video_channel);
      shared_data_.SetLastError(kViEBaseInvalidChannelId);
      return -1;
    }

    // Deregister the ViEEncoder if no other channel is using it.
    ViEEncoder* vie_encoder = cs.Encoder(video_channel);
    if (cs.ChannelUsingViEEncoder(video_channel) == false) {
      ViEInputManagerScoped is(*(shared_data_.input_manager()));
      ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
      if (provider) {
        provider->DeregisterFrameCallback(vie_encoder);
      }
    }
  }

  if (shared_data_.channel_manager()->DeleteChannel(video_channel) == -1) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
                 "%s: Could not delete channel %d", __FUNCTION__,
                 video_channel);
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s: channel deleted: %d", __FUNCTION__, video_channel);
  return 0;
}

int ViEBaseImpl::ConnectAudioChannel(const int video_channel,
                                     const int audio_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s(%d)", __FUNCTION__, video_channel);
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(video_channel)) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
                 "%s: channel %d doesn't exist", __FUNCTION__, video_channel);
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->ConnectVoiceChannel(video_channel,
                                                          audio_channel) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::DisconnectAudioChannel(const int video_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s(%d)", __FUNCTION__, video_channel);
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(video_channel)) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
                 "%s: channel %d doesn't exist", __FUNCTION__, video_channel);
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->DisconnectVoiceChannel(
      video_channel) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StartSend(const int video_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_.instance_id(), video_channel),
               "%s(channel: %d)", __FUNCTION__, video_channel);

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_.instance_id(), video_channel),
                 "%s: Channel %d does not exist", __FUNCTION__, video_channel);
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder != NULL);
  if (vie_encoder->Owner() != video_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_.instance_id(), video_channel),
                 "Can't start ssend on a receive only channel.");
    shared_data_.SetLastError(kViEBaseReceiveOnlyChannel);
    return -1;
  }

  // Pause and trigger a key frame.
  vie_encoder->Pause();
  int32_t error = vie_channel->StartSend();
  if (error != 0) {
    vie_encoder->Restart();
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_.instance_id(), video_channel),
                 "%s: Could not start sending on channel %d", __FUNCTION__,
                 video_channel);
    if (error == kViEBaseAlreadySending) {
      shared_data_.SetLastError(kViEBaseAlreadySending);
    }
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  vie_encoder->SendKeyFrame();
  vie_encoder->Restart();
  return 0;
}

int ViEBaseImpl::StopSend(const int video_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_.instance_id(), video_channel),
               "%s(channel: %d)", __FUNCTION__, video_channel);

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_.instance_id(), video_channel),
                 "%s: Channel %d does not exist", __FUNCTION__, video_channel);
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  int32_t error = vie_channel->StopSend();
  if (error != 0) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_.instance_id(), video_channel),
                 "%s: Could not stop sending on channel %d", __FUNCTION__,
                 video_channel);
    if (error == kViEBaseNotSending) {
      shared_data_.SetLastError(kViEBaseNotSending);
    } else {
      shared_data_.SetLastError(kViEBaseUnknownError);
    }
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StartReceive(const int video_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_.instance_id(), video_channel),
               "%s(channel: %d)", __FUNCTION__, video_channel);

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_.instance_id(), video_channel),
                 "%s: Channel %d does not exist", __FUNCTION__, video_channel);
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  if (vie_channel->StartReceive() != 0) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StopReceive(const int video_channel) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
               ViEId(shared_data_.instance_id(), video_channel),
               "%s(channel: %d)", __FUNCTION__, video_channel);

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    WEBRTC_TRACE(kTraceError, kTraceVideo,
                 ViEId(shared_data_.instance_id(), video_channel),
                 "%s: Channel %d does not exist", __FUNCTION__, video_channel);
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  if (vie_channel->StopReceive() != 0) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::GetVersion(char version[1024]) {
  WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_.instance_id()),
               "GetVersion(version=?)");
  assert(kViEVersionMaxMessageSize == 1024);
  if (!version) {
    shared_data_.SetLastError(kViEBaseInvalidArgument);
    return -1;
  }

  // Add WebRTC Version.
  std::stringstream version_stream;
  version_stream << "VideoEngine 3.33.0" << std::endl;

  // Add build info.
  version_stream << "Build: svn:" << WEBRTC_SVNREVISION << " " << BUILDINFO
                 << std::endl;

#ifdef WEBRTC_EXTERNAL_TRANSPORT
  version_stream << "External transport build" << std::endl;
#endif
  int version_length = version_stream.tellp();
  assert(version_length < 1024);
  memcpy(version, version_stream.str().c_str(), version_length);
  version[version_length] = '\0';

  WEBRTC_TRACE(kTraceStateInfo, kTraceVideo,
               ViEId(shared_data_.instance_id()), "GetVersion() => %s",
               version);
  return 0;
}

int ViEBaseImpl::LastError() {
  return shared_data_.LastErrorInternal();
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               int original_channel, bool sender) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(original_channel)) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
                 "%s - original_channel does not exist.", __FUNCTION__,
                 shared_data_.instance_id());
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->CreateChannel(&video_channel,
                                                    original_channel,
                                                    sender) == -1) {
    WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
                 "%s: Could not create channel", __FUNCTION__);
    video_channel = -1;
    shared_data_.SetLastError(kViEBaseChannelCreationFailed);
    return -1;
  }
  WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(shared_data_.instance_id()),
               "%s: channel created: %d", __FUNCTION__, video_channel);
  return 0;
}

}  // namespace webrtc
<|endoftext|>


<commit_before>/*
 * DIPimage 3.0
 * This MEX-file implements the `viewslice` function
 *
 * (c)2018, Wouter Caarls.
 *
 * 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 "dip_matlab_interface.h"
#include "diplib/viewer/proxy.h"
#include "diplib/viewer/slice.h"

constexpr char const* ViewerClassName = "org.diplib.viewer.Viewer";
constexpr char const* MexFileName = "viewslice";
constexpr char const* JarFileName = "Viewer.jar";

void JavaAddPath( bool add = true ) {
   // The code below does:
   //    path = fullfile(fileparts(which('viewslice')),'Viewer.jar')
   mxArray* fname = mxCreateString( MexFileName );
   mxArray* path1;
   mexCallMATLAB( 1, &path1, 1, &fname, "which" );
   mxArray* path2;
   mexCallMATLAB( 1, &path2, 1, &path1, "fileparts" ); // Is this easier than implementing it in C++?
   mxArray* path;
   mxArray* args[ 2 ];
   args[ 0 ] = path2;
   args[ 1 ] = mxCreateString( JarFileName );
   mexCallMATLAB( 1, &path, 2, args, "fullfile" ); // Is this easier than implementing it in C++?
   // Add the found path to the Java Path:
   mexCallMATLABWithTrap( 0, nullptr, 1, &path, add ? "javaaddpath" : "javarmpath" ); // Ignore any errors generated
   //mexPrintf( add ? "Added to the Java path\n" : "Removed from the Java path\n" );
}

bool HasViewerClass() {
   static bool hasViewerClass = false;
   if( !hasViewerClass ) {
      //mexPrintf( "Testing for the Viewer java class\n" );
      mxArray* rhs[ 2 ];
      rhs[ 0 ] = mxCreateString( ViewerClassName );
      rhs[ 1 ] = mxCreateString( "class" );
      mxArray* lhs;
      mexCallMATLAB(1, &lhs, 2, rhs, "exist");
      dip::uint result = dml::GetUnsigned( lhs );
      if( result == 8 ) {
         hasViewerClass = true;
         //mexPrintf( "   - Tested true\n" );
      }
   }
   return hasViewerClass;
}

void EnsureViewerJarIsOnPath() {
   if( !HasViewerClass() ) {
      JavaAddPath();
      if( !HasViewerClass() ) {
         JavaAddPath( false );
         mexErrMsgTxt( "Cannot load library Viewer.jar.\nPossible sources of this error:\n"
                          " - Viewer.jar is not in the expected location.\n"
                          " - Viewer.jar is not compatible with this version of MATLAB.\n"
                          " - MATLAB's JVM is disabled." );
      }
   }
}

void mexFunction( int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[] ) {

   EnsureViewerJarIsOnPath();

   try {
      DML_MIN_ARGS( 1 );
      DML_MAX_ARGS( 2 );

      dip::Image image = dml::GetImage( prhs[ 0 ], dml::GetImageMode::SHARED_COPY );

      dip::String title;
      if( nrhs > 1 ) {
         title = dml::GetString( prhs[ 1 ] );
      }

      dip::viewer::WindowPtr wdw = dip::viewer::SliceViewer::Create( image, title );
      dip::viewer::ProxyManager::instance()->createWindow( wdw, false );

      mxArray* obj;
      mxArray* rhs[2];
      rhs[ 0 ] = mxCreateString( ViewerClassName );
      static_assert( sizeof( void* ) == 8, "viewslice requires a 64-bit environment" );
      rhs[ 1 ] = mxCreateUninitNumericMatrix( 1, 1, mxINT64_CLASS, mxREAL );
      *static_cast< void** >( mxGetData( rhs[ 1 ] )) = wdw.get();
      mexCallMATLAB( 1, &obj, 2, rhs, "javaObjectEDT" );

      if( nlhs > 0 ) {
         plhs[ 0 ] = obj;
      }

   } catch( const dip::Error& e ) {
      mexErrMsgTxt( e.what());
   }
}
<commit_msg>Replaced mxCreateUninitNumericMatrix() by mxCreateNumericMatrix() to support older Matlab versions<commit_after>/*
 * DIPimage 3.0
 * This MEX-file implements the `viewslice` function
 *
 * (c)2018, Wouter Caarls.
 *
 * 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 "dip_matlab_interface.h"
#include "diplib/viewer/proxy.h"
#include "diplib/viewer/slice.h"

constexpr char const* ViewerClassName = "org.diplib.viewer.Viewer";
constexpr char const* MexFileName = "viewslice";
constexpr char const* JarFileName = "Viewer.jar";

void JavaAddPath( bool add = true ) {
   // The code below does:
   //    path = fullfile(fileparts(which('viewslice')),'Viewer.jar')
   mxArray* fname = mxCreateString( MexFileName );
   mxArray* path1;
   mexCallMATLAB( 1, &path1, 1, &fname, "which" );
   mxArray* path2;
   mexCallMATLAB( 1, &path2, 1, &path1, "fileparts" ); // Is this easier than implementing it in C++?
   mxArray* path;
   mxArray* args[ 2 ];
   args[ 0 ] = path2;
   args[ 1 ] = mxCreateString( JarFileName );
   mexCallMATLAB( 1, &path, 2, args, "fullfile" ); // Is this easier than implementing it in C++?
   // Add the found path to the Java Path:
   mexCallMATLABWithTrap( 0, nullptr, 1, &path, add ? "javaaddpath" : "javarmpath" ); // Ignore any errors generated
   //mexPrintf( add ? "Added to the Java path\n" : "Removed from the Java path\n" );
}

bool HasViewerClass() {
   static bool hasViewerClass = false;
   if( !hasViewerClass ) {
      //mexPrintf( "Testing for the Viewer java class\n" );
      mxArray* rhs[ 2 ];
      rhs[ 0 ] = mxCreateString( ViewerClassName );
      rhs[ 1 ] = mxCreateString( "class" );
      mxArray* lhs;
      mexCallMATLAB(1, &lhs, 2, rhs, "exist");
      dip::uint result = dml::GetUnsigned( lhs );
      if( result == 8 ) {
         hasViewerClass = true;
         //mexPrintf( "   - Tested true\n" );
      }
   }
   return hasViewerClass;
}

void EnsureViewerJarIsOnPath() {
   if( !HasViewerClass() ) {
      JavaAddPath();
      if( !HasViewerClass() ) {
         JavaAddPath( false );
         mexErrMsgTxt( "Cannot load library Viewer.jar.\nPossible sources of this error:\n"
                          " - Viewer.jar is not in the expected location.\n"
                          " - Viewer.jar is not compatible with this version of MATLAB.\n"
                          " - MATLAB's JVM is disabled." );
      }
   }
}

void mexFunction( int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[] ) {

   EnsureViewerJarIsOnPath();

   try {
      DML_MIN_ARGS( 1 );
      DML_MAX_ARGS( 2 );

      dip::Image image = dml::GetImage( prhs[ 0 ], dml::GetImageMode::SHARED_COPY );

      dip::String title;
      if( nrhs > 1 ) {
         title = dml::GetString( prhs[ 1 ] );
      }

      dip::viewer::WindowPtr wdw = dip::viewer::SliceViewer::Create( image, title );
      dip::viewer::ProxyManager::instance()->createWindow( wdw, false );

      mxArray* obj;
      mxArray* rhs[2];
      rhs[ 0 ] = mxCreateString( ViewerClassName );
      static_assert( sizeof( void* ) == 8, "viewslice requires a 64-bit environment" );
      rhs[ 1 ] = mxCreateNumericMatrix( 1, 1, mxINT64_CLASS, mxREAL );
      *static_cast< void** >( mxGetData( rhs[ 1 ] )) = wdw.get();
      mexCallMATLAB( 1, &obj, 2, rhs, "javaObjectEDT" );

      if( nlhs > 0 ) {
         plhs[ 0 ] = obj;
      }

   } catch( const dip::Error& e ) {
      mexErrMsgTxt( e.what());
   }
}
<|endoftext|>


<commit_before>/**@file
	@brief Elements for Mobility Management messages, GSM 04.08 9.2.
*/
/*
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2010, 2014 Kestrel Signal Processing, Inc.
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

    This program 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.

*/

#define LOG_GROUP LogGroup::GSM		// Can set Log.Level.GSM for debugging

#include <time.h>
#include "GSML3MMElements.h"
#include <Logger.h>
#include <Timeval.h>

using namespace std;
using namespace GSM;

void L3CMServiceType::parseV(const L3Frame& src, size_t &rp)
{
	mType = (CMServiceTypeCode)src.readField(rp,4);
}

ostream& GSM::operator<<(ostream& os, CMServiceTypeCode code)
{
	switch (code) {
		case L3CMServiceType::MobileOriginatedCall: os << "MOC"; return os;
		case L3CMServiceType::EmergencyCall: os << "Emergency"; return os;
		case L3CMServiceType::ShortMessage: os << "SMS"; return os;
		case L3CMServiceType::SupplementaryService: os << "SS"; return os;
		case L3CMServiceType::VoiceCallGroup: os << "VGCS"; return os;
		case L3CMServiceType::VoiceBroadcast: os << "VBS"; return os;
		case L3CMServiceType::LocationService: os << "LCS"; return os;
		case L3CMServiceType::MobileTerminatedCall: os << "MTC"; return os;
		case L3CMServiceType::MobileTerminatedShortMessage: os << "MTSMS"; return os;
		case L3CMServiceType::LocationUpdateRequest: os << "LUR"; return os;
		case L3CMServiceType::HandoverCall: os << "Handover"; return os;
		case L3CMServiceType::UndefinedType: break;
		//default: os << "?" << (int)code << "?";
	}
	os << "invalid:" << (int)code;
	return os;
}

void L3CMServiceType::text(ostream& os) const
{
	os << mType;
}

void L3RejectCauseIE::writeV( L3Frame& dest, size_t &wp ) const
{
	dest.writeField(wp, mRejectCause, 8);
}

void L3RejectCauseIE::parseV(const L3Frame& src, size_t &rp)
{
        mRejectCause = (MMRejectCause) src.readField(rp,8);
}

void L3RejectCauseIE::text(ostream& os) const
{
	os <<"0x"<< hex << mRejectCause << dec;
}

void L3NetworkName::writeV(L3Frame& dest, size_t &wp) const
{
	unsigned sz = strlen(mName);
	// header byte
	if (mAlphabet == ALPHABET_UCS2) {
		// Ext: 1b, coding scheme: 001b (UCS2), CI, trailing spare bits: 000b (0)
		dest.writeField(wp,1,1);	// ext bit
		dest.writeField(wp,1,3);	// coding scheme USC2
		dest.writeField(wp,mCI,1);	// show country name?
		dest.writeField(wp,0,3);	// spare bits in last octet
		// the characters
		for (unsigned i=0; i<sz; i++) {
			dest.writeField(wp,mName[i],16);
		}
	} else {
		// Ext: 1b, coding scheme: 000b (GSM 03.38 coding scheme),
		int nameBits = sz*7;
		int nameBytes = nameBits/8;
		if (nameBits%8) nameBytes++;
		int msgBits = nameBytes*8;
		int spareBits = msgBits-nameBits;
		dest.writeField(wp,1,1);				// ext bit
		dest.writeField(wp,0,3);				// coding scheme USC2
		dest.writeField(wp,mCI,1);				// show country name?
		dest.writeField(wp,spareBits,3);		// spare bits in last octet
		// Temporary vector "chars" so we can do LSB8MSB() after encoding.
		BitVector2 chars(dest.segment(wp,msgBits));
		size_t twp = 0;
		// the characters: 7 bit, GSM 03.38 6.1.2.2, 6.2.1
		for (unsigned i=0; i<sz; i++) {
			chars.writeFieldReversed(twp,encodeGSMChar(mName[i]),7);
		}
		chars.writeField(twp,0,spareBits);
		chars.LSB8MSB();
		wp += twp;
	}
}

void L3NetworkName::text(std::ostream& os) const
{
	os << mName;
}

void L3TimeZoneAndTime::writeV(L3Frame& dest, size_t& wp) const
{
	// See GSM 03.40 9.2.3.11.

	// Convert from seconds since Jan 1, 1970 to calendar time.
	struct tm fields;
	const time_t seconds = mTime.sec();
	if (mType == LOCAL_TIME) {
		localtime_r(&seconds,&fields);
	} else {
		gmtime_r(&seconds,&fields);
	}
	// Write the fields in BCD format.
	// year
	unsigned year = fields.tm_year % 100;
	dest.writeField(wp, year % 10, 4);
	dest.writeField(wp, year / 10, 4);
	// month
	unsigned month = fields.tm_mon + 1;
	dest.writeField(wp, month % 10, 4);
	dest.writeField(wp, month / 10, 4);
	// day
	dest.writeField(wp, fields.tm_mday % 10, 4);
	dest.writeField(wp, fields.tm_mday / 10, 4);
	// hour
	dest.writeField(wp, fields.tm_hour % 10, 4);
	dest.writeField(wp, fields.tm_hour / 10, 4);
	// minute
	dest.writeField(wp, fields.tm_min % 10, 4);
	dest.writeField(wp, fields.tm_min / 10, 4);
	// second
	dest.writeField(wp, fields.tm_sec % 10, 4);
	dest.writeField(wp, fields.tm_sec / 10, 4);

	// time zone, in 1/4 steps with a sign bit
	int zone;
	if (mType == LOCAL_TIME) {
		zone = fields.tm_gmtoff;
	} else {
		// At least under Linux gmtime_r() does not return timezone
		// information for some reason and we have to use localtime_r()
		// to reptrieve this information.
		struct tm fields_local;
		localtime_r(&seconds,&fields_local);
		zone = fields_local.tm_gmtoff;
	}
	zone = zone / (15*60);
	unsigned zoneSign = (zone < 0);
	zone = abs(zone);
	dest.writeField(wp, zone % 10, 4);
	dest.writeField(wp, zoneSign, 1);
	dest.writeField(wp, zone / 10, 3);

	LOG(DEBUG) << "year=" << year << " month=" << month << " day=" << fields.tm_mday
	           << " hour=" << fields.tm_hour << " min=" << fields.tm_min << " sec=" << fields.tm_sec
	           << " zone=" << (zoneSign?"-":"+") << zone;
}

void L3TimeZoneAndTime::parseV(const L3Frame& src, size_t& rp)
{
	// See GSM 03.40 9.2.3.11.

	// Read it all into a localtime struct tm,
	// then covert to Unix seconds.
	struct tm fields;
	// year
	fields.tm_year = 2000 + src.readField(rp,4) + src.readField(rp,4)*10;
	// month
	fields.tm_mon = 1 + src.readField(rp,4) + src.readField(rp,4)*10;
	// day
	fields.tm_mday = src.readField(rp,4) + src.readField(rp,4)*10;
	// hour
	fields.tm_hour = src.readField(rp,4) + src.readField(rp,4)*10;
	// minute
	fields.tm_min = src.readField(rp,4) + src.readField(rp,4)*10;
	// second
	fields.tm_sec = src.readField(rp,4) + src.readField(rp,4)*10;
	// zone
	unsigned zone = src.readField(rp,4);
	unsigned zoneSign = src.readField(rp,1);
	zone += 10*src.readField(rp,4);
	if (zoneSign) zone = -zone;
	fields.tm_gmtoff = zone * 15 * 60;
	// convert
	mTime = Timeval(timegm(&fields),0);
}

void L3TimeZoneAndTime::text(ostream& os) const
{
	//char timeStr[26];
	const time_t seconds = mTime.sec();
        std::string timeStr("");
        Timeval::isoTime(seconds, timeStr, true);
	//ctime_r(&seconds,timeStr);
	//timeStr[24]='\0';
	os << timeStr << " (local)";
}

void L3RAND::writeV(L3Frame& dest, size_t &wp) const
{
	dest.writeField(wp,mRUpper,64);
	dest.writeField(wp,mRLower,64);
}

void L3RAND::text(ostream& os) const
{
	os << hex << "0x" << mRUpper << mRLower << dec;
}

void L3SRES::parseV(const L3Frame& src, size_t &rp)
{
	mValue = src.readField(rp,32);
}

void L3SRES::text(ostream& os) const
{
	os << hex << "0x" << mValue << dec;
}

// vim: ts=4 sw=4
<commit_msg>Fixes some SMS formatting issues discovered in smq. Unsure of the impact in openbts.<commit_after>/**@file
	@brief Elements for Mobility Management messages, GSM 04.08 9.2.
*/
/*
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2010, 2014 Kestrel Signal Processing, Inc.
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

    This program 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.

*/

#define LOG_GROUP LogGroup::GSM		// Can set Log.Level.GSM for debugging

#include <time.h>
#include "GSML3MMElements.h"
#include <Logger.h>
#include <Timeval.h>

using namespace std;
using namespace GSM;

void L3CMServiceType::parseV(const L3Frame& src, size_t &rp)
{
	mType = (CMServiceTypeCode)src.readField(rp,4);
}

ostream& GSM::operator<<(ostream& os, CMServiceTypeCode code)
{
	switch (code) {
		case L3CMServiceType::MobileOriginatedCall: os << "MOC"; return os;
		case L3CMServiceType::EmergencyCall: os << "Emergency"; return os;
		case L3CMServiceType::ShortMessage: os << "SMS"; return os;
		case L3CMServiceType::SupplementaryService: os << "SS"; return os;
		case L3CMServiceType::VoiceCallGroup: os << "VGCS"; return os;
		case L3CMServiceType::VoiceBroadcast: os << "VBS"; return os;
		case L3CMServiceType::LocationService: os << "LCS"; return os;
		case L3CMServiceType::MobileTerminatedCall: os << "MTC"; return os;
		case L3CMServiceType::MobileTerminatedShortMessage: os << "MTSMS"; return os;
		case L3CMServiceType::LocationUpdateRequest: os << "LUR"; return os;
		case L3CMServiceType::HandoverCall: os << "Handover"; return os;
		case L3CMServiceType::UndefinedType: break;
		//default: os << "?" << (int)code << "?";
	}
	os << "invalid:" << (int)code;
	return os;
}

void L3CMServiceType::text(ostream& os) const
{
	os << mType;
}

void L3RejectCauseIE::writeV( L3Frame& dest, size_t &wp ) const
{
	dest.writeField(wp, mRejectCause, 8);
}

void L3RejectCauseIE::parseV(const L3Frame& src, size_t &rp)
{
        mRejectCause = (MMRejectCause) src.readField(rp,8);
}

void L3RejectCauseIE::text(ostream& os) const
{
	os <<"0x"<< hex << mRejectCause << dec;
}

void L3NetworkName::writeV(L3Frame& dest, size_t &wp) const
{
	unsigned sz = strlen(mName);
	// header byte
	if (mAlphabet == ALPHABET_UCS2) {
		// Ext: 1b, coding scheme: 001b (UCS2), CI, trailing spare bits: 000b (0)
		dest.writeField(wp,1,1);	// ext bit
		dest.writeField(wp,1,3);	// coding scheme USC2
		dest.writeField(wp,mCI,1);	// show country name?
		dest.writeField(wp,0,3);	// spare bits in last octet
		// the characters
		for (unsigned i=0; i<sz; i++) {
			dest.writeField(wp,mName[i],16);
		}
	} else {
		// Ext: 1b, coding scheme: 000b (GSM 03.38 coding scheme),
		int nameBits = sz*7;
		int nameBytes = nameBits/8;
		if (nameBits%8) nameBytes++;
		int msgBits = nameBytes*8;
		int spareBits = msgBits-nameBits;
		dest.writeField(wp,1,1);				// ext bit
		dest.writeField(wp,0,3);				// coding scheme USC2
		dest.writeField(wp,mCI,1);				// show country name?
		dest.writeField(wp,spareBits,3);		// spare bits in last octet
		// Temporary vector "chars" so we can do LSB8MSB() after encoding.
		BitVector2 chars(dest.segment(wp,msgBits));
		size_t twp = 0;
		// the characters: 7 bit, GSM 03.38 6.1.2.2, 6.2.1
		for (unsigned i=0; i<sz; i++) {
			chars.writeFieldReversed(twp,encodeGSMChar(mName[i]),7);
		}
		chars.writeField(twp,0,spareBits);
		chars.LSB8MSB();
		wp += twp;
	}
}

void L3NetworkName::text(std::ostream& os) const
{
	os << mName;
}

void L3TimeZoneAndTime::writeV(L3Frame& dest, size_t& wp) const
{
	// See GSM 03.40 9.2.3.11.

	// Convert from seconds since Jan 1, 1970 to calendar time.
	struct tm fields;
	const time_t seconds = mTime.sec();
	if (mType == LOCAL_TIME) {
		localtime_r(&seconds,&fields);
	} else {
		gmtime_r(&seconds,&fields);
	}
	// Write the fields in BCD format.
	// year
	unsigned year = fields.tm_year % 100;
	dest.writeField(wp, year % 10, 4);
	dest.writeField(wp, year / 10, 4);
	// month
	unsigned month = fields.tm_mon + 1;
	dest.writeField(wp, month % 10, 4);
	dest.writeField(wp, month / 10, 4);
	// day
	dest.writeField(wp, fields.tm_mday % 10, 4);
	dest.writeField(wp, fields.tm_mday / 10, 4);
	// hour
	dest.writeField(wp, fields.tm_hour % 10, 4);
	dest.writeField(wp, fields.tm_hour / 10, 4);
	// minute
	dest.writeField(wp, fields.tm_min % 10, 4);
	dest.writeField(wp, fields.tm_min / 10, 4);
	// second
	dest.writeField(wp, fields.tm_sec % 10, 4);
	dest.writeField(wp, fields.tm_sec / 10, 4);

	// time zone, in 1/4 steps with a sign bit
	int zone;
	if (mType == LOCAL_TIME) {
		zone = fields.tm_gmtoff;
	} else {
		// At least under Linux gmtime_r() does not return timezone
		// information for some reason and we have to use localtime_r()
		// to reptrieve this information.
		struct tm fields_local;
		localtime_r(&seconds,&fields_local);
		zone = fields_local.tm_gmtoff;
	}
	zone = zone / (15*60);
	unsigned zoneSign = (zone < 0);
	zone = abs(zone);
	dest.writeField(wp, zone % 10, 4);
	dest.writeField(wp, zoneSign, 1);
	dest.writeField(wp, zone / 10, 3);

	LOG(DEBUG) << "year=" << year << " month=" << month << " day=" << fields.tm_mday
	           << " hour=" << fields.tm_hour << " min=" << fields.tm_min << " sec=" << fields.tm_sec
	           << " zone=" << (zoneSign?"-":"+") << zone;
}

void L3TimeZoneAndTime::parseV(const L3Frame& src, size_t& rp)
{
	// See GSM 03.40 9.2.3.11.

	// Read it all into a localtime struct tm,
	// then covert to Unix seconds.
	struct tm fields;
	// years since 1900
	fields.tm_year = 100 + src.readField(rp,4) + src.readField(rp,4)*10;
	// month
	fields.tm_mon = src.readField(rp,4) + src.readField(rp,4)*10;
	// day
	fields.tm_mday = src.readField(rp,4) + src.readField(rp,4)*10;
	// hour
	fields.tm_hour = src.readField(rp,4) + src.readField(rp,4)*10;
	// minute
	fields.tm_min = src.readField(rp,4) + src.readField(rp,4)*10;
	// second
	fields.tm_sec = src.readField(rp,4) + src.readField(rp,4)*10;
	// zone
	unsigned zone = src.readField(rp,4);
	unsigned zoneSign = src.readField(rp,1);
	zone += 10*src.readField(rp,3);
	if (zoneSign) zone = -zone;
	fields.tm_gmtoff = zone * 15 * 60;
	// convert
	mTime = Timeval(timegm(&fields),0);
}

void L3TimeZoneAndTime::text(ostream& os) const
{
	//char timeStr[26];
	const time_t seconds = mTime.sec();
        std::string timeStr("");
        Timeval::isoTime(seconds, timeStr, true);
	//ctime_r(&seconds,timeStr);
	//timeStr[24]='\0';
	os << timeStr << " (local)";
}

void L3RAND::writeV(L3Frame& dest, size_t &wp) const
{
	dest.writeField(wp,mRUpper,64);
	dest.writeField(wp,mRLower,64);
}

void L3RAND::text(ostream& os) const
{
	os << hex << "0x" << mRUpper << mRLower << dec;
}

void L3SRES::parseV(const L3Frame& src, size_t &rp)
{
	mValue = src.readField(rp,32);
}

void L3SRES::text(ostream& os) const
{
	os << hex << "0x" << mValue << dec;
}

// vim: ts=4 sw=4
<|endoftext|>


<commit_before>/**
* @version		GrPPI v0.3
* @copyright		Copyright (C) 2017 Universidad Carlos III de Madrid. All rights reserved.
* @license		GNU/GPL, see LICENSE.txt
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You have received a copy of the GNU General Public License in LICENSE.txt
* also available in <http://www.gnu.org/licenses/gpl.html>.
*
* See COPYRIGHT.txt for copyright notices and details.
*/
#include <atomic>
#include <utility>
#include <experimental/optional>

#include <gtest/gtest.h>

#include "farm.h"
#include "pipeline.h"
#include "dyn/dynamic_execution.h"

#include "supported_executions.h"

using namespace std;
using namespace grppi;
template <typename T>
using optional = std::experimental::optional<T>;

template <typename T>
class farm_pipeline_test : public ::testing::Test {
public:
  T execution_;
  dynamic_execution dyn_execution_{execution_};

  // Variables
  std::atomic<int> output;

  // Vectors
  vector<int> v{};
  vector<int> v2{};
  vector<int> v3{};
  vector<int> w{};

  // entry counter
  int idx_in = 0;
  int idx_out = 0;

  // Invocation counter
  std::atomic<int> invocations_in{0};
  std::atomic<int> invocations_op{0};
  std::atomic<int> invocations_op2{0};
  std::atomic<int> invocations_sk{0};

  void setup_empty() {}

  template <typename E>
  void run_empty(const E & e) {
    grppi::pipeline(e,
      [this]() -> optional<int>{
        invocations_in++;
        return {};
      },
      grppi::farm(4,
        grppi::pipeline(
          [this](int x) {
            invocations_op++;
            return x;
          },
          [this](int x) {
            invocations_op2++;
            return x;
          }
        )
      ),
      [](int x) {}
    );
  }

  void check_empty() {
    EXPECT_EQ(1, invocations_in); // Functor in was invoked once
    EXPECT_EQ(0, invocations_op); // Functor op was not invoked
    EXPECT_EQ(0, invocations_op2); // Functor op2 was not invoked
  }

  void setup_empty_sink() {}

  template <typename E>
  void run_empty_sink(const E & e) {
    grppi::pipeline (e,
      [this]() -> optional<int>{
        invocations_in++;
        return {};
      },
      grppi::farm(4,
        grppi::pipeline(
          [this](int x) {
            invocations_op++;
            return x;
          },
          [this](int x) {
            invocations_op2++;
            return x;
          }
        )
      ),
      [this](int x) {
        this->invocations_sk++;
      }
    );
  }

  void check_empty_sink() {
    EXPECT_EQ(1, invocations_in);
    EXPECT_EQ(0, invocations_op);
    EXPECT_EQ(0, invocations_op2);
    EXPECT_EQ(0, invocations_sk);
  }

  void setup_empty_ary() {}

  template <typename E>
  void run_empty_ary(const E & e) {
    grppi::pipeline(e,
      [this]() -> optional<tuple<int,int,int>> {
        invocations_in++;
        return {};
      },
      grppi::farm(4,
        grppi::pipeline(
          [this](tuple<int,int,int> x) {
            invocations_op++;
            return x;
          },
          [this](tuple<int,int,int> x) {
            invocations_op2++;
            return x;
          })
      ),
      [&](tuple<int,int,int> x){
        invocations_sk++;
      }
    );
  }

  void check_empty_ary() {
    EXPECT_EQ(1, invocations_in);
    EXPECT_EQ(0, invocations_op);
    EXPECT_EQ(0, invocations_op2);
    EXPECT_EQ(0, invocations_sk);
  }

  void setup_single_sink() {
    v = vector<int>{42};
    w = vector<int>{99};
  }

  template <typename E>
  void run_single_sink(const E & e) {
    grppi::pipeline(e,
      [this]() -> optional<int> {
        invocations_in++;
        if (idx_in < v.size() ) {
          idx_in++;
          return v[idx_in-1];
        }
        else return {};
      },
      grppi::farm(4,
        grppi::pipeline(
          [this](int x) {
            invocations_op++;
            return x*2;
          },
          [this](int x) {
            invocations_op2++;
            return x*2;
          }
        )
      ),
      [this](int x) {
        invocations_sk++;
        w[idx_out] = x;
        idx_out++;
      }
    );
  }

  void check_single_sink() {
    EXPECT_EQ(2, invocations_in); // Functor in was invoked once
    EXPECT_EQ(1, this->invocations_op); // one invocation of function op
    EXPECT_EQ(1, this->invocations_op2); // one invocation of function op
    EXPECT_EQ(1, this->invocations_sk); // one invocation of function sk
    EXPECT_EQ(168, this->w[0]);
  }

  void setup_single_ary_sink() {
    v = vector<int>{11};
    v2 = vector<int>{22};
    v3 = vector<int>{33};
    w = vector<int>{99};
  }

  template <typename E>
  void run_single_ary_sink(const E & e) {
    grppi::pipeline(e,
      [this]() -> optional<tuple<int,int,int>> {
        invocations_in++;
        if (idx_in < v.size()) {
          idx_in++;
          return make_tuple(v[idx_in-1], v2[idx_in-1], v3[idx_in-1]);
        }
        else return {};
      },
      grppi::farm(4,
        grppi::pipeline(
          [this](tuple<int,int,int> x) {
            invocations_op++;
            return get<0>(x) + get<1>(x) + get<2>(x);;
          },
          [this](int x){
            invocations_op2++;
            return x*2;
          }
        )
      ),
      [this](int x) {
        invocations_sk++;
        w[idx_out] = x;
        idx_out++;
      });
  }

  void check_single_ary_sink() {
    EXPECT_EQ(2, invocations_in); // Functor in was invoked twice
    EXPECT_EQ(1, this->invocations_op); // one invocation of function op
    EXPECT_EQ(1, this->invocations_op2); // one invocation of function op
    EXPECT_EQ(1, this->invocations_sk); // one invocation of function sk
    EXPECT_EQ(132, this->w[0]);
  }

  void setup_multiple_sink() {
    v = vector<int>{1,2,3,4,5};
    output = 0;
  }

  template <typename E>
  void run_multiple_sink(const E & e) {
    grppi::pipeline(e,
      [this]() -> optional<int> {
        invocations_in++;
        if (idx_in < v.size()) {
          idx_in++;
          return v[idx_in-1];
        } else return {};
      },
      grppi::farm(4,
        grppi::pipeline(
          [this](int x) {
            invocations_op++;
            return x * 2;
          },
          [this](int x) {
            invocations_op++;
            return x * 2;
          }
        )
      ),
      [this](int x) {
        invocations_sk++;
        output +=x;
      }
    );
  }

  void check_multiple_sink() {
    EXPECT_EQ(6, this->invocations_in); // six invocations of function in
    EXPECT_EQ(5, this->invocations_op); // five invocations of function op
    EXPECT_EQ(5, this->invocations_op2); // five invocations of function sk
    EXPECT_EQ(5, this->invocations_sk); // five invocations of function sk
    EXPECT_EQ(60, this->output);
  }

  void setup_multiple_ary_sink() {
    v = vector<int>{1,2,3,4,5};
    v2 = vector<int>{2,4,6,8,10};
    v3 = vector<int>{10,10,10,10,10};
    output = 0;
  }

  template <typename E>
  void run_multiple_ary_sink(const E & e) {
    grppi::pipeline(e,
      [this]() -> optional<tuple<int,int,int>> {
        invocations_in++;
        if (idx_in < v.size()) {
          idx_in++;
          return make_tuple(v[idx_in-1], v2[idx_in-1], v3[idx_in-1]);
      }
      else return {};
    },
    grppi::farm(4,
      grppi::pipeline(
        [this](tuple<int,int,int> x) {
          invocations_op++;
          return get<0>(x) + get<1>(x) + get<2>(x);
        },
        [this](int x){
          invocations_op2++;
          return x*2;
        }
      )
    ),
    [this](int x) {
      invocations_sk++;
      output += x;
    });
  }

  void check_multiple_ary_sink() {
    EXPECT_EQ(6, this->invocations_in); // six invocations of function in
    EXPECT_EQ(5, this->invocations_op); // five invocations of function op
    EXPECT_EQ(5, this->invocations_op2); // five invocations of function op
    EXPECT_EQ(5, this->invocations_sk); // five invocations of function sk
    EXPECT_EQ(190, this->output);
  }

};

// Test for execution policies defined in supported_executions.h
TYPED_TEST_CASE(farm_pipeline_test, executions);

TYPED_TEST(farm_pipeline_test, static_empty)
{
  this->setup_empty();
  this->run_empty(this->execution_);
  this->check_empty();
}
/*
TYPED_TEST(farm_pipeline_test, dyn_empty)
{
  this->setup_empty();
  this->run_empty(this->dyn_execution_);
  this->check_empty();
}

TYPED_TEST(farm_pipeline_test, static_empty_sink)
{
  this->setup_empty_sink();
  this->run_empty_sink(this->execution_);
  this->check_empty_sink();
}

TYPED_TEST(farm_pipeline_test, dyn_empty_sink)
{
  this->setup_empty_sink();
  this->run_empty_sink(this->dyn_execution_);
  this->check_empty_sink();
}

TYPED_TEST(farm_pipeline_test, static_empty_ary)
{
  this->setup_empty();
  this->run_empty_ary(this->execution_);
  this->check_empty();
}

TYPED_TEST(farm_pipeline_test, dyn_empty_ary)
{
  this->setup_empty();
  this->run_empty_ary(this->dyn_execution_);
  this->check_empty();
}

TYPED_TEST(farm_pipeline_test, static_single_sink)
{
  this->setup_single_sink();
  this->run_single_sink(this->execution_);
  this->check_single_sink();
}

TYPED_TEST(farm_pipeline_test, dyn_single_sink)
{
  this->setup_single_sink();
  this->run_single_sink(this->dyn_execution_);
  this->check_single_sink();
}

TYPED_TEST(farm_pipeline_test, static_single_ary_sink)
{
  this->setup_single_ary_sink();
  this->run_single_ary_sink(this->dyn_execution_);
  this->check_single_ary_sink();
}

TYPED_TEST(farm_pipeline_test, dyn_single_ary_sink)
{
  this->setup_single_ary_sink();
  this->run_single_ary_sink(this->dyn_execution_);
  this->check_single_ary_sink();
}

TYPED_TEST(farm_pipeline_test, static_multiple_sink)
{
  this->setup_multiple_sink();
  this->run_multiple_sink(this->execution_);
  this->check_multiple_sink();
}

TYPED_TEST(farm_pipeline_test, dyn_multiple_sink)
{
  this->setup_multiple_sink();
  this->run_multiple_sink(this->dyn_execution_);
  this->check_multiple_sink();
}

TYPED_TEST(farm_pipeline_test, static_multiple_ary_sink)
{
  this->setup_multiple_ary_sink();
  this->run_multiple_ary_sink(this->execution_);
  this->check_multiple_ary_sink();
}

TYPED_TEST(farm_pipeline_test, dyn_multiple_ary_sink)
{
  this->setup_multiple_ary_sink();
  this->run_multiple_ary_sink(this->dyn_execution_);
  this->check_multiple_ary_sink();
}*/
<commit_msg>Minor fixes<commit_after>/**
* @version		GrPPI v0.3
* @copyright		Copyright (C) 2017 Universidad Carlos III de Madrid. All rights reserved.
* @license		GNU/GPL, see LICENSE.txt
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You have received a copy of the GNU General Public License in LICENSE.txt
* also available in <http://www.gnu.org/licenses/gpl.html>.
*
* See COPYRIGHT.txt for copyright notices and details.
*/
#include <atomic>
#include <utility>
#include <experimental/optional>

#include <gtest/gtest.h>

#include "farm.h"
#include "pipeline.h"
#include "dyn/dynamic_execution.h"

#include "supported_executions.h"

using namespace std;
using namespace grppi;
template <typename T>
using optional = std::experimental::optional<T>;

template <typename T>
class farm_pipeline_test : public ::testing::Test {
public:
  T execution_;
  dynamic_execution dyn_execution_{execution_};

  // Variables
  std::atomic<int> output;

  // Vectors
  vector<int> v{};
  vector<int> v2{};
  vector<int> v3{};
  vector<int> w{};

  // entry counter
  int idx_in = 0;
  int idx_out = 0;

  // Invocation counter
  std::atomic<int> invocations_in{0};
  std::atomic<int> invocations_op{0};
  std::atomic<int> invocations_op2{0};
  std::atomic<int> invocations_sk{0};

  void setup_empty() {}

  template <typename E>
  void run_empty(const E & e) {
    grppi::pipeline(e,
      [this]() -> optional<int>{
        invocations_in++;
        return {};
      },
      grppi::farm(2,
        grppi::pipeline(
          [this](int x) {
            invocations_op++;
            return x;
          },
          [this](int x) {
            invocations_op2++;
            return x;
          }
        )
      ),
      [](int x) {}
    );
  }

  void check_empty() {
    EXPECT_EQ(1, invocations_in); // Functor in was invoked once
    EXPECT_EQ(0, invocations_op); // Functor op was not invoked
    EXPECT_EQ(0, invocations_op2); // Functor op2 was not invoked
  }

  void setup_empty_sink() {}

  template <typename E>
  void run_empty_sink(const E & e) {
    grppi::pipeline (e,
      [this]() -> optional<int>{
        invocations_in++;
        return {};
      },
      grppi::farm(2,
        grppi::pipeline(
          [this](int x) {
            invocations_op++;
            return x;
          },
          [this](int x) {
            invocations_op2++;
            return x;
          }
        )
      ),
      [this](int x) {
        this->invocations_sk++;
      }
    );
  }

  void check_empty_sink() {
    EXPECT_EQ(1, invocations_in);
    EXPECT_EQ(0, invocations_op);
    EXPECT_EQ(0, invocations_op2);
    EXPECT_EQ(0, invocations_sk);
  }

  void setup_empty_ary() {}

  template <typename E>
  void run_empty_ary(const E & e) {
    grppi::pipeline(e,
      [this]() -> optional<tuple<int,int,int>> {
        invocations_in++;
        return {};
      },
      grppi::farm(2,
        grppi::pipeline(
          [this](tuple<int,int,int> x) {
            invocations_op++;
            return x;
          },
          [this](tuple<int,int,int> x) {
            invocations_op2++;
            return x;
          })
      ),
      [&](tuple<int,int,int> x){
        invocations_sk++;
      }
    );
  }

  void check_empty_ary() {
    EXPECT_EQ(1, invocations_in);
    EXPECT_EQ(0, invocations_op);
    EXPECT_EQ(0, invocations_op2);
    EXPECT_EQ(0, invocations_sk);
  }

  void setup_single_sink() {
    v = vector<int>{42};
    w = vector<int>{99};
  }

  template <typename E>
  void run_single_sink(const E & e) {
    grppi::pipeline(e,
      [this]() -> optional<int> {
        invocations_in++;
        if (idx_in < v.size() ) {
          idx_in++;
          return v[idx_in-1];
        }
        else return {};
      },
      grppi::farm(2,
        grppi::pipeline(
          [this](int x) {
            invocations_op++;
            return x*2;
          },
          [this](int x) {
            invocations_op2++;
            return x*2;
          }
        )
      ),
      [this](int x) {
        invocations_sk++;
        w[idx_out] = x;
        idx_out++;
      }
    );
  }

  void check_single_sink() {
    EXPECT_EQ(2, invocations_in); // Functor in was invoked once
    EXPECT_EQ(1, this->invocations_op); // one invocation of function op
    EXPECT_EQ(1, this->invocations_op2); // one invocation of function op
    EXPECT_EQ(1, this->invocations_sk); // one invocation of function sk
    EXPECT_EQ(168, this->w[0]);
  }

  void setup_single_ary_sink() {
    v = vector<int>{11};
    v2 = vector<int>{22};
    v3 = vector<int>{33};
    w = vector<int>{99};
  }

  template <typename E>
  void run_single_ary_sink(const E & e) {
    grppi::pipeline(e,
      [this]() -> optional<tuple<int,int,int>> {
        invocations_in++;
        if (idx_in < v.size()) {
          idx_in++;
          return make_tuple(v[idx_in-1], v2[idx_in-1], v3[idx_in-1]);
        }
        else return {};
      },
      grppi::farm(2,
        grppi::pipeline(
          [this](tuple<int,int,int> x) {
            invocations_op++;
            return get<0>(x) + get<1>(x) + get<2>(x);;
          },
          [this](int x){
            invocations_op2++;
            return x*2;
          }
        )
      ),
      [this](int x) {
        invocations_sk++;
        w[idx_out] = x;
        idx_out++;
      });
  }

  void check_single_ary_sink() {
    EXPECT_EQ(2, invocations_in); // Functor in was invoked twice
    EXPECT_EQ(1, this->invocations_op); // one invocation of function op
    EXPECT_EQ(1, this->invocations_op2); // one invocation of function op
    EXPECT_EQ(1, this->invocations_sk); // one invocation of function sk
    EXPECT_EQ(132, this->w[0]);
  }

  void setup_multiple_sink() {
    v = vector<int>{1,2,3,4,5};
    output = 0;
  }

  template <typename E>
  void run_multiple_sink(const E & e) {
    grppi::pipeline(e,
      [this]() -> optional<int> {
        invocations_in++;
        if (idx_in < v.size()) {
          idx_in++;
          return v[idx_in-1];
        } else return {};
      },
      grppi::farm(2,
        grppi::pipeline(
          [this](int x) {
            invocations_op++;
            return x * 2;
          },
          [this](int x) {
            invocations_op2++;
            return x * 2;
          }
        )
      ),
      [this](int x) {
        invocations_sk++;
        output +=x;
      }
    );
  }

  void check_multiple_sink() {
    EXPECT_EQ(6, this->invocations_in); // six invocations of function in
    EXPECT_EQ(5, this->invocations_op); // five invocations of function op
    EXPECT_EQ(5, this->invocations_op2); // five invocations of function sk
    EXPECT_EQ(5, this->invocations_sk); // five invocations of function sk
    EXPECT_EQ(60, this->output);
  }

  void setup_multiple_ary_sink() {
    v = vector<int>{1,2,3,4,5};
    v2 = vector<int>{2,4,6,8,10};
    v3 = vector<int>{10,10,10,10,10};
    output = 0;
  }

  template <typename E>
  void run_multiple_ary_sink(const E & e) {
    grppi::pipeline(e,
      [this]() -> optional<tuple<int,int,int>> {
        invocations_in++;
        if (idx_in < v.size()) {
          idx_in++;
          return make_tuple(v[idx_in-1], v2[idx_in-1], v3[idx_in-1]);
      }
      else return {};
    },
    grppi::farm(2,
      grppi::pipeline(
        [this](tuple<int,int,int> x) {
          invocations_op++;
          return get<0>(x) + get<1>(x) + get<2>(x);
        },
        [this](int x){
          invocations_op2++;
          return x*2;
        }
      )
    ),
    [this](int x) {
      invocations_sk++;
      output += x;
    });
  }

  void check_multiple_ary_sink() {
    EXPECT_EQ(6, this->invocations_in); // six invocations of function in
    EXPECT_EQ(5, this->invocations_op); // five invocations of function op
    EXPECT_EQ(5, this->invocations_op2); // five invocations of function op
    EXPECT_EQ(5, this->invocations_sk); // five invocations of function sk
    EXPECT_EQ(190, this->output);
  }

};

// Test for execution policies defined in supported_executions.h
TYPED_TEST_CASE(farm_pipeline_test, executions);

TYPED_TEST(farm_pipeline_test, static_empty)
{
  this->setup_empty();
  this->run_empty(this->execution_);
  this->check_empty();
}

TYPED_TEST(farm_pipeline_test, dyn_empty)
{
  this->setup_empty();
  this->run_empty(this->dyn_execution_);
  this->check_empty();
}

TYPED_TEST(farm_pipeline_test, static_empty_sink)
{
  this->setup_empty_sink();
  this->run_empty_sink(this->execution_);
  this->check_empty_sink();
}

TYPED_TEST(farm_pipeline_test, dyn_empty_sink)
{
  this->setup_empty_sink();
  this->run_empty_sink(this->dyn_execution_);
  this->check_empty_sink();
}

TYPED_TEST(farm_pipeline_test, static_empty_ary)
{
  this->setup_empty();
  this->run_empty_ary(this->execution_);
  this->check_empty();
}

TYPED_TEST(farm_pipeline_test, dyn_empty_ary)
{
  this->setup_empty();
  this->run_empty_ary(this->dyn_execution_);
  this->check_empty();
}

TYPED_TEST(farm_pipeline_test, static_single_sink)
{
  this->setup_single_sink();
  this->run_single_sink(this->execution_);
  this->check_single_sink();
}

TYPED_TEST(farm_pipeline_test, dyn_single_sink)
{
  this->setup_single_sink();
  this->run_single_sink(this->dyn_execution_);
  this->check_single_sink();
}

TYPED_TEST(farm_pipeline_test, static_single_ary_sink)
{
  this->setup_single_ary_sink();
  this->run_single_ary_sink(this->dyn_execution_);
  this->check_single_ary_sink();
}

TYPED_TEST(farm_pipeline_test, dyn_single_ary_sink)
{
  this->setup_single_ary_sink();
  this->run_single_ary_sink(this->dyn_execution_);
  this->check_single_ary_sink();
}

TYPED_TEST(farm_pipeline_test, static_multiple_sink)
{
  this->setup_multiple_sink();
  this->run_multiple_sink(this->execution_);
  this->check_multiple_sink();
}

TYPED_TEST(farm_pipeline_test, dyn_multiple_sink)
{
  this->setup_multiple_sink();
  this->run_multiple_sink(this->dyn_execution_);
  this->check_multiple_sink();
}

TYPED_TEST(farm_pipeline_test, static_multiple_ary_sink)
{
  this->setup_multiple_ary_sink();
  this->run_multiple_ary_sink(this->execution_);
  this->check_multiple_ary_sink();
}

TYPED_TEST(farm_pipeline_test, dyn_multiple_ary_sink)
{
  this->setup_multiple_ary_sink();
  this->run_multiple_ary_sink(this->dyn_execution_);
  this->check_multiple_ary_sink();
}
<|endoftext|>


<commit_before>void readDigits(int nev=-1,int evStart=0)
{

  gSystem->Load("libITSUpgradeBase");
  gSystem->Load("libITSUpgradeSim");
  gROOT->SetStyle("Plain");
  const Int_t kMaxROCycleAccept=126;
  gAlice=NULL;
  AliRunLoader* runLoader = AliRunLoader::Open("galice.root");
  runLoader->LoadgAlice();

  gAlice = runLoader->GetAliRun();

  runLoader->LoadHeader();
  runLoader->LoadKinematics();
  runLoader->LoadSDigits();
  runLoader->LoadDigits();

  AliGeomManager::LoadGeometry("geometry.root");
  AliITSUGeomTGeo* gm = new AliITSUGeomTGeo(kTRUE,kTRUE);
  //
  Int_t nLayers = gm->GetNLayers();
  Int_t nChips = gm->GetNChips();
  Int_t nbins=100;
  Int_t xmin=0;
  Int_t xmax=50000;//00*1e-09;

  TH1D **hNelSDig = new TH1D*[nLayers], **hNelDig = new TH1D*[nLayers];
  //
  for(Int_t i=0; i< nLayers; i++ ) {
    hNelSDig[i] = new TH1D(Form("hNelSDig%i",i),Form("electron distribution in SDigits [ Layer %i] ",i),nbins,xmin,xmax);
    hNelSDig[i]->SetXTitle("N electrons");
    hNelDig[i] = new TH1D(Form("hNelDig%i",i),Form("electron distribution in Digits [ Layer %i] ",i),nbins,xmin,xmax);
    hNelDig[i]->SetXTitle("N electrons");
  }

  AliLoader *dl = runLoader->GetDetectorLoader("ITS");

  //SDIGITS INIT
  TTree * sDigTree = 0x0;
  TClonesArray *sDigArr= new TClonesArray("AliITSUSDigit");

  //DIGITS INIT
  TTree * digTree = 0x0;
  TClonesArray *digArr= new TClonesArray("AliITSUDigitPix");

  int nevTot = (Int_t)runLoader->GetNumberOfEvents();
  printf("N Events : %i \n",nevTot);
  evStart = evStart<nevTot ? evStart : nevTot-1;
  if (evStart<0) evStart = 0;
  //
  int lastEv = nev<0 ? nevTot : evStart+nev;
  if (lastEv > nevTot) lastEv = nevTot;
  //
  printf("N Events : %i \n",(Int_t)nevTot);

  for (Int_t iEvent = evStart; iEvent < lastEv; iEvent++) {
    printf("\n Event %i \n",iEvent);
    runLoader->GetEvent(iEvent);
    AliStack *stack = runLoader->Stack();
    sDigTree=dl->TreeS();
    digTree=dl->TreeD();
    //
    if (sDigTree) sDigTree->SetBranchAddress("ITS",&sDigArr);
    digTree->SetBranchAddress("ITSDigitsPix",&digArr);

    for (int imod=0;imod<nChips;imod++) {
      if (sDigTree) sDigTree->GetEntry(imod);
      digTree->GetEntry(imod);
      int detType = gm->GetChipChipTypeID(imod);
      AliITSUSegmentationPix* segm = (AliITSUSegmentationPix*)gm->GetSegmentationByID(detType);
      int lay,sta,ssta,mod,chip;
      int nsdig = sDigArr->GetEntries();
      int ndig  = digArr->GetEntries();
      if (ndig<1) continue;
      gm->GetChipId(imod, lay,sta,ssta,mod,chip);
      printf("\nChip %3d: (chip %2d in module:%d/substave:%1d/stave:%2d/Layer:%d) |NSDigits: %4d NDigits: %4d\n",imod,chip,mod,ssta,sta,lay,nsdig,ndig);
      //
      for (int isdig=0;isdig<nsdig;isdig++) {
	AliITSUSDigit *pSdig = (AliITSUSDigit*)sDigArr->At(isdig);
	int sdinfo = pSdig->GetUniqueID();
	UInt_t row,col;
	Int_t cycle;
	AliITSUSensMap::GetCell(sdinfo,segm->Npz(),segm->Npx(),kMaxROCycleAccept,col,row,cycle);
	printf("#%3d Sdigit col:%4d/row:%4d/cycle:%d generated by track %5d (%s)\t",isdig, col,row,cycle,
	       pSdig->GetTrack(0),stack->Particle(pSdig->GetTrack(0))->GetName());
	pSdig->Print();
	hNelSDig[lay]->Fill(pSdig->GetSignal());
      }
      //
      for (int idig=0;idig<ndig;idig++) {
	AliITSUDigitPix *pDig = (AliITSUDigitPix*)digArr->At(idig);
	printf("#%3d digit, col:%4d/row:%4d ROCycle:%d signal: %.2e,  generated by tracks ",idig,pDig->GetCoord1(),pDig->GetCoord2(),
	       pDig->GetROCycle(),pDig->GetSignalPix());
	for (int itr=0;itr<pDig->GetNTracks();itr++) if (pDig->GetTrack(itr)>=0) printf(" %5d",pDig->GetTrack(itr)); printf("\n");
	//
	hNelDig[lay]->Fill(pDig->GetSignalPix());
      }
      //
    }

  }//event loop

  TCanvas *cSd = new TCanvas("cSd","Summable Digits",1000,800);
  cSd->Divide(nLayers&0x1 ?  (nLayers/2+1) : nLayers/2,2);
  TCanvas *cD = new TCanvas("cD","Digits",1000,800);
  cD->Divide(nLayers&0x1 ?  (nLayers/2+1) : nLayers/2,2);

  for(Int_t ip =1; ip<=nLayers; ip++){
    cSd->cd(ip);
    hNelSDig[ip-1]->Draw();
    cD->cd(ip);
    hNelDig[ip-1]->Draw();
  }

}
<commit_msg>Fixing the names of promoted classes (one more macro)<commit_after>void readDigits(int nev=-1,int evStart=0)
{

  gSystem->Load("libITSUpgradeBase");
  gSystem->Load("libITSUpgradeSim");
  gROOT->SetStyle("Plain");
  const Int_t kMaxROCycleAccept=126;
  gAlice=NULL;
  AliRunLoader* runLoader = AliRunLoader::Open("galice.root");
  runLoader->LoadgAlice();

  gAlice = runLoader->GetAliRun();

  runLoader->LoadHeader();
  runLoader->LoadKinematics();
  runLoader->LoadSDigits();
  runLoader->LoadDigits();

  AliGeomManager::LoadGeometry("geometry.root");
  AliITSUGeomTGeo* gm = new AliITSUGeomTGeo(kTRUE,kTRUE);
  //
  Int_t nLayers = gm->GetNLayers();
  Int_t nChips = gm->GetNChips();
  Int_t nbins=100;
  Int_t xmin=0;
  Int_t xmax=50000;//00*1e-09;

  TH1D **hNelSDig = new TH1D*[nLayers], **hNelDig = new TH1D*[nLayers];
  //
  for(Int_t i=0; i< nLayers; i++ ) {
    hNelSDig[i] = new TH1D(Form("hNelSDig%i",i),Form("electron distribution in SDigits [ Layer %i] ",i),nbins,xmin,xmax);
    hNelSDig[i]->SetXTitle("N electrons");
    hNelDig[i] = new TH1D(Form("hNelDig%i",i),Form("electron distribution in Digits [ Layer %i] ",i),nbins,xmin,xmax);
    hNelDig[i]->SetXTitle("N electrons");
  }

  AliLoader *dl = runLoader->GetDetectorLoader("ITS");

  //SDIGITS INIT
  TTree * sDigTree = 0x0;
  TClonesArray *sDigArr= new TClonesArray("AliITSMFTSDigit");

  //DIGITS INIT
  TTree * digTree = 0x0;
  TClonesArray *digArr= new TClonesArray("AliITSMFTDigitPix");

  int nevTot = (Int_t)runLoader->GetNumberOfEvents();
  printf("N Events : %i \n",nevTot);
  evStart = evStart<nevTot ? evStart : nevTot-1;
  if (evStart<0) evStart = 0;
  //
  int lastEv = nev<0 ? nevTot : evStart+nev;
  if (lastEv > nevTot) lastEv = nevTot;
  //
  printf("N Events : %i \n",(Int_t)nevTot);

  for (Int_t iEvent = evStart; iEvent < lastEv; iEvent++) {
    printf("\n Event %i \n",iEvent);
    runLoader->GetEvent(iEvent);
    AliStack *stack = runLoader->Stack();
    sDigTree=dl->TreeS();
    digTree=dl->TreeD();
    //
    if (sDigTree) sDigTree->SetBranchAddress("ITS",&sDigArr);
    digTree->SetBranchAddress("ITSDigitsPix",&digArr);

    for (int imod=0;imod<nChips;imod++) {
      if (sDigTree) sDigTree->GetEntry(imod);
      digTree->GetEntry(imod);
      int detType = gm->GetChipChipTypeID(imod);
      AliITSMFTSegmentationPix* segm = (AliITSMFTSegmentationPix*)gm->GetSegmentationByID(detType);
      int lay,sta,ssta,mod,chip;
      int nsdig = sDigArr->GetEntries();
      int ndig  = digArr->GetEntries();
      if (ndig<1) continue;
      gm->GetChipId(imod, lay,sta,ssta,mod,chip);
      printf("\nChip %3d: (chip %2d in module:%d/substave:%1d/stave:%2d/Layer:%d) |NSDigits: %4d NDigits: %4d\n",imod,chip,mod,ssta,sta,lay,nsdig,ndig);
      //
      for (int isdig=0;isdig<nsdig;isdig++) {
	AliITSMFTSDigit *pSdig = (AliITSMFTSDigit*)sDigArr->At(isdig);
	int sdinfo = pSdig->GetUniqueID();
	UInt_t row,col;
	Int_t cycle;
	AliITSMFTSensMap::GetCell(sdinfo,segm->Npz(),segm->Npx(),kMaxROCycleAccept,col,row,cycle);
	printf("#%3d Sdigit col:%4d/row:%4d/cycle:%d generated by track %5d (%s)\t",isdig, col,row,cycle,
	       pSdig->GetTrack(0),stack->Particle(pSdig->GetTrack(0))->GetName());
	pSdig->Print();
	hNelSDig[lay]->Fill(pSdig->GetSignal());
      }
      //
      for (int idig=0;idig<ndig;idig++) {
	AliITSMFTDigitPix *pDig = (AliITSMFTDigitPix*)digArr->At(idig);
	printf("#%3d digit, col:%4d/row:%4d ROCycle:%d signal: %.2e,  generated by tracks ",idig,pDig->GetCoord1(),pDig->GetCoord2(),
	       pDig->GetROCycle(),pDig->GetSignalPix());
	for (int itr=0;itr<pDig->GetNTracks();itr++) if (pDig->GetTrack(itr)>=0) printf(" %5d",pDig->GetTrack(itr)); printf("\n");
	//
	hNelDig[lay]->Fill(pDig->GetSignalPix());
      }
      //
    }

  }//event loop

  TCanvas *cSd = new TCanvas("cSd","Summable Digits",1000,800);
  cSd->Divide(nLayers&0x1 ?  (nLayers/2+1) : nLayers/2,2);
  TCanvas *cD = new TCanvas("cD","Digits",1000,800);
  cD->Divide(nLayers&0x1 ?  (nLayers/2+1) : nLayers/2,2);

  for(Int_t ip =1; ip<=nLayers; ip++){
    cSd->cd(ip);
    hNelSDig[ip-1]->Draw();
    cD->cd(ip);
    hNelDig[ip-1]->Draw();
  }

}
<|endoftext|>