<commit_before>// GRP.hpp
// Created by Sivaram Ambikasaran on September 2nd, 2014
// Modifications by Dan Foreman-Mackey

#ifndef __GRP_HPP__
#define __GRP_HPP__

#include <cmath>
#include <vector>
#include <Eigen/Dense>
#include <Eigen/Sparse>

class GRP {
private:
    // Number of unknowns.
    int N;

    // Rank of the separable part.
    int m;

    // The semi-separable matrix is of the form diag(d) + triu(U*V,1) + tril((U*V)',-1).
    Eigen::VectorXd alpha;
    Eigen::VectorXd beta;
    Eigen::VectorXd t;
    Eigen::MatrixXd gamma;

    // Diagonal entries of the matrix.
    Eigen::VectorXd d;

    // Determinant of the extended sparse matrix.
    double determinant;

    // Size of the extended sparse matrix.
    int M;

    // Number of non-zeros per block.
    int blocknnz;

    // Total number of non-zeros.
    int nnz;

    // Size of each block, will be 2m+1.
    int nBlockSize;

    // Starting index of each of the blocks.
    std::vector<double> nBlockStart;
    // Vector of triplets used to store the sparse matrix.
    std::vector<Eigen::Triplet<double> > triplets;
    // The extended sparse matrix.
    Eigen::SparseMatrix<double> Aex;

    // Stores the factorization.
    Eigen::SparseLU<Eigen::SparseMatrix<double>, Eigen::COLAMDOrdering<int> > factorize;

public:

    GRP(
        const int N,
        const int m,
        const Eigen::VectorXd alpha,
        const Eigen::VectorXd beta,
        const Eigen::VectorXd t,
        const Eigen::VectorXd d
    );
    GRP(
        const int N,
        const int m,
        double* alpha,
        double* beta,
        double* t,
        double* d
    );
    void assemble_Extended_Matrix();
    void factorize_Extended_Matrix();
    void obtain_Solution(
        const Eigen::VectorXd rhs,
        Eigen::VectorXd& solution,
        Eigen::VectorXd& solutionex
    );
    void obtain_Solution(
        double* rhs,
        double* solution
    );
    double obtain_Determinant();

    // Obtain error, i.e., ||Ax-b||_{\inf}
    double obtain_Error(const Eigen::VectorXd rhs, const Eigen::VectorXd& solex);
};

GRP::GRP (const int N, const int m, const Eigen::VectorXd alpha, const Eigen::VectorXd beta, const Eigen::VectorXd t, const Eigen::VectorXd d) {
    this->N     = N;
    this->m     = m;
    this->alpha = alpha;
    this->beta  = beta;
    this->t     = t;
    this->d     = d;
}

GRP::GRP (
    const int N,
    const int m,
    double* alpha,
    double* beta,
    double* t,
    double* d
) {
    this->N     = N;
    this->m     = m;
    this->alpha = Eigen::Map<Eigen::MatrixXd>(alpha, m, 1);
    this->beta  = Eigen::Map<Eigen::MatrixXd>(beta, m, 1);
    this->t     = Eigen::Map<Eigen::MatrixXd>(t, N, 1);
    this->d     = Eigen::Map<Eigen::MatrixXd>(d, N, 1);
}

void GRP::assemble_Extended_Matrix() {
    gamma = Eigen::MatrixXd(m,N-1);
    for (int i=0; i<m; ++i) {
        for (int j=0; j<N-1; ++j) {
            gamma(i,j)  =   exp(-beta(i)*fabs(t(j)-t(j+1)));
        }
    }
    //  Declare 2*m as a variable, since this will be used frequently.
    int twom = 2*m;

    //  Number of non-zeros per matrix block in the extended sparse matrix.
    //  This includes the '1' on the diagonal, the two negative identity
    //  matrices above and below the diagonal, the vectors u, u', v and v'.
    blocknnz = 6*m+1;

    //  Declare the blocksize, which is the repeating structure along the diagonal.
    nBlockSize = twom+1;

    //  Size of the extended sparse matrix.
    M = N*nBlockSize-twom;

    //  Number of non-zero entries in the matrix. The identity matrices on the
    //  supersuperdiagonals which were not included in the blocknnz has been
    //  accounted for here.
    //  This number is correct and has been checked with MATLAB.
    nnz = (N-1)*blocknnz+(N-2)*twom+1;

    //  Obtain the starting index of each of the block.
    for (int k=0; k<N; ++k) {
        nBlockStart.push_back(k*nBlockSize);
    }

    //  Assembles block by block except the identity matrices on the supersuperdiagonal.
    for (int nBlock=0; nBlock<N-1; ++nBlock) {
        //  The starting row and column for the blocks.
        //  Assemble the diagonal first.
        triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock], nBlockStart[nBlock], d(nBlock)));
        for (int k=0; k<m; ++k) {
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock]+k+1,nBlockStart[nBlock],gamma(k,nBlock)));
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock],nBlockStart[nBlock]+k+1,gamma(k,nBlock)));
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock]+m+k+1,nBlockStart[nBlock]+twom+1,alpha(k)));
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock]+twom+1,nBlockStart[nBlock]+m+k+1,alpha(k)));
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock]+k+1,nBlockStart[nBlock]+k+m+1,-1.0));
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock]+k+m+1,nBlockStart[nBlock]+k+1,-1.0));
        }
    }
    triplets.push_back(Eigen::Triplet<double>(M-1,M-1,d(N-1)));

    //  Assebmles the supersuperdiagonal identity blocks.
    for (int nBlock=0; nBlock<N-2; ++nBlock) {
        for (int k=0; k<m; ++k) {
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock]+k+m+1,nBlockStart[nBlock]+twom+k+2,gamma(k,nBlock+1)));
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock]+twom+k+2,nBlockStart[nBlock]+k+m+1,gamma(k,nBlock+1)));
        }
    }

    //  Set the size of the extended sparse matrix.
    Aex.resize(M,M);

    //  Assemble the matrix from triplets.
    Aex.setFromTriplets(triplets.begin(), triplets.end());
}

void GRP::factorize_Extended_Matrix() {
    //  Compute the sparse LU factorization of matrix `Aex'
    factorize.compute(Aex);
}

void GRP::obtain_Solution(const Eigen::VectorXd rhs, Eigen::VectorXd& solution, Eigen::VectorXd& solutionex) {
    //  Assemble the extended right hand side `rhsex'
    Eigen::VectorXd rhsex = Eigen::VectorXd::Zero(M);
    for (int nBlock=0; nBlock<N; ++nBlock) {
        rhsex(nBlockStart[nBlock]) = rhs(nBlock);
    }

    //  Obtain the solution
    solutionex = factorize.solve(rhsex);

    //  Desired solution vector
    solution = Eigen::VectorXd(N);
    for (int nBlock=0; nBlock<N; ++nBlock) {
        solution(nBlock) = solutionex(nBlockStart[nBlock]);
    }
}

void GRP::obtain_Solution(double* rhs, double* solution) {
    Eigen::Map<Eigen::VectorXd> rhs_(rhs, this->N, 1);
    Eigen::VectorXd solution_, solex;
    this->obtain_Solution(rhs_, solution_, solex);
    for (int i = 0; i < N; ++i) solution[i] = solution_[i];
}

double GRP::obtain_Error(const Eigen::VectorXd rhs, const Eigen::VectorXd& solex) {
    //  Assemble the extended right hand side `rhsex'
    Eigen::VectorXd rhsex = Eigen::VectorXd::Zero(M);
    for (int nBlock=0; nBlock<N; ++nBlock) {
        rhsex(nBlockStart[nBlock]) = rhs(nBlock);
    }
    double error = (Aex*solex-rhsex).cwiseAbs().maxCoeff();
    return error;
}

double GRP::obtain_Determinant() {
    //  Obtain determinant
    determinant = factorize.logAbsDeterminant();
    return determinant;
}

#endif /* defined(__GRP_HPP__) */
<commit_msg>adding licenses<commit_after>// GRP.hpp
// Created by Sivaram Ambikasaran on September 2nd, 2014
// Modifications by Dan Foreman-Mackey
//
// Original license:
//
// Copyright © 2014 New York University.
// All Rights Reserved.
//
// A license, solely to non-commercial parties, to use and copy this software and
// its documentation solely for your non-commercial purposes, without fee and
// without a signed licensing agreement, is hereby granted upon your download of
// the software, through which you agree to the following: 1) the above copyright
// notice, this paragraph and the following three paragraphs will prominently
// appear in all internal copies and modifications; 2) no rights to sublicense or
// further distribute this software for commercial purposes are granted; and 3) no
// rights to assign this license are granted. You may modify or otherwise generate
// derivatives of the software, provided that such derivatives are for
// non-commercial purposes only. The use of all such derivatives shall remain
// subject to the terms contained herein. Please contact The Office of Industrial
// Liaison, New York University, One Park Avenue, 6th Floor, New York, NY 10016,
// (212) 263-8178, for commercial licensing opportunities, or for further
// distribution, modification or license rights.
//
// Created by Sivaram Ambikasaran.
//
// IN NO EVENT SHALL NYU, OR ITS EMPLOYEES, OFFICERS, AGENTS OR TRUSTEES
// (“COLLECTIVELY “NYU PARTIES”) BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING LOST
// PROFITS, ARISING OUT OF ANY CLAIM RESULTING FROM YOUR USE OF THIS SOFTWARE
// AND ITS DOCUMENTATION, EVEN IF ANY OF NYU PARTIES HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH CLAIM OR DAMAGE.
//
// NYU SPECIFICALLY DISCLAIMS ANY WARRANTIES OF ANY KIND REGARDING THE SOFTWARE,
// INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, OR THE ACCURACY OR
// USEFULNESS, OR COMPLETENESS OF THE SOFTWARE. THE SOFTWARE AND ACCOMPANYING
// DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED COMPLETELY "AS IS".
// NYU HAS NO OBLIGATION TO PROVIDE FURTHER DOCUMENTATION, MAINTENANCE,
// SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
//
// Please cite Generalized Rybicki Press algorithm and the code, if you use the
// code, ESS, in your research.
//
// Citation for the article:
//
// @article{ambikasaran2014generalized,
//   title={Generalized Rybicki Press algorithm},
//   author={Ambikasaran, Sivaram},
//   journal={arXiv preprint arXiv:1409.7852},
//   year={2014}
// }
//
// Citation for the code:
//
// @MISC{ESSweb,
//   author = {Sivaram Ambikasaran},
//   title = {ESS},
//   howpublished = {https://github.com/sivaramambikasaran/ESS},
//   year = {2014}
//  }
//

#ifndef __GRP_HPP__
#define __GRP_HPP__

#include <cmath>
#include <vector>
#include <Eigen/Dense>
#include <Eigen/Sparse>

class GRP {
private:
    // Number of unknowns.
    int N;

    // Rank of the separable part.
    int m;

    // The semi-separable matrix is of the form diag(d) + triu(U*V,1) + tril((U*V)',-1).
    Eigen::VectorXd alpha;
    Eigen::VectorXd beta;
    Eigen::VectorXd t;
    Eigen::MatrixXd gamma;

    // Diagonal entries of the matrix.
    Eigen::VectorXd d;

    // Determinant of the extended sparse matrix.
    double determinant;

    // Size of the extended sparse matrix.
    int M;

    // Number of non-zeros per block.
    int blocknnz;

    // Total number of non-zeros.
    int nnz;

    // Size of each block, will be 2m+1.
    int nBlockSize;

    // Starting index of each of the blocks.
    std::vector<double> nBlockStart;
    // Vector of triplets used to store the sparse matrix.
    std::vector<Eigen::Triplet<double> > triplets;
    // The extended sparse matrix.
    Eigen::SparseMatrix<double> Aex;

    // Stores the factorization.
    Eigen::SparseLU<Eigen::SparseMatrix<double>, Eigen::COLAMDOrdering<int> > factorize;

public:

    GRP(
        const int N,
        const int m,
        const Eigen::VectorXd alpha,
        const Eigen::VectorXd beta,
        const Eigen::VectorXd t,
        const Eigen::VectorXd d
    );
    GRP(
        const int N,
        const int m,
        double* alpha,
        double* beta,
        double* t,
        double* d
    );
    void assemble_Extended_Matrix();
    void factorize_Extended_Matrix();
    void obtain_Solution(
        const Eigen::VectorXd rhs,
        Eigen::VectorXd& solution,
        Eigen::VectorXd& solutionex
    );
    void obtain_Solution(
        double* rhs,
        double* solution
    );
    double obtain_Determinant();

    // Obtain error, i.e., ||Ax-b||_{\inf}
    double obtain_Error(const Eigen::VectorXd rhs, const Eigen::VectorXd& solex);
};

GRP::GRP (const int N, const int m, const Eigen::VectorXd alpha, const Eigen::VectorXd beta, const Eigen::VectorXd t, const Eigen::VectorXd d) {
    this->N     = N;
    this->m     = m;
    this->alpha = alpha;
    this->beta  = beta;
    this->t     = t;
    this->d     = d;
}

GRP::GRP (
    const int N,
    const int m,
    double* alpha,
    double* beta,
    double* t,
    double* d
) {
    this->N     = N;
    this->m     = m;
    this->alpha = Eigen::Map<Eigen::MatrixXd>(alpha, m, 1);
    this->beta  = Eigen::Map<Eigen::MatrixXd>(beta, m, 1);
    this->t     = Eigen::Map<Eigen::MatrixXd>(t, N, 1);
    this->d     = Eigen::Map<Eigen::MatrixXd>(d, N, 1);
}

void GRP::assemble_Extended_Matrix() {
    gamma = Eigen::MatrixXd(m,N-1);
    for (int i=0; i<m; ++i) {
        for (int j=0; j<N-1; ++j) {
            gamma(i,j)  =   exp(-beta(i)*fabs(t(j)-t(j+1)));
        }
    }
    //  Declare 2*m as a variable, since this will be used frequently.
    int twom = 2*m;

    //  Number of non-zeros per matrix block in the extended sparse matrix.
    //  This includes the '1' on the diagonal, the two negative identity
    //  matrices above and below the diagonal, the vectors u, u', v and v'.
    blocknnz = 6*m+1;

    //  Declare the blocksize, which is the repeating structure along the diagonal.
    nBlockSize = twom+1;

    //  Size of the extended sparse matrix.
    M = N*nBlockSize-twom;

    //  Number of non-zero entries in the matrix. The identity matrices on the
    //  supersuperdiagonals which were not included in the blocknnz has been
    //  accounted for here.
    //  This number is correct and has been checked with MATLAB.
    nnz = (N-1)*blocknnz+(N-2)*twom+1;

    //  Obtain the starting index of each of the block.
    for (int k=0; k<N; ++k) {
        nBlockStart.push_back(k*nBlockSize);
    }

    //  Assembles block by block except the identity matrices on the supersuperdiagonal.
    for (int nBlock=0; nBlock<N-1; ++nBlock) {
        //  The starting row and column for the blocks.
        //  Assemble the diagonal first.
        triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock], nBlockStart[nBlock], d(nBlock)));
        for (int k=0; k<m; ++k) {
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock]+k+1,nBlockStart[nBlock],gamma(k,nBlock)));
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock],nBlockStart[nBlock]+k+1,gamma(k,nBlock)));
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock]+m+k+1,nBlockStart[nBlock]+twom+1,alpha(k)));
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock]+twom+1,nBlockStart[nBlock]+m+k+1,alpha(k)));
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock]+k+1,nBlockStart[nBlock]+k+m+1,-1.0));
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock]+k+m+1,nBlockStart[nBlock]+k+1,-1.0));
        }
    }
    triplets.push_back(Eigen::Triplet<double>(M-1,M-1,d(N-1)));

    //  Assebmles the supersuperdiagonal identity blocks.
    for (int nBlock=0; nBlock<N-2; ++nBlock) {
        for (int k=0; k<m; ++k) {
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock]+k+m+1,nBlockStart[nBlock]+twom+k+2,gamma(k,nBlock+1)));
            triplets.push_back(Eigen::Triplet<double>(nBlockStart[nBlock]+twom+k+2,nBlockStart[nBlock]+k+m+1,gamma(k,nBlock+1)));
        }
    }

    //  Set the size of the extended sparse matrix.
    Aex.resize(M,M);

    //  Assemble the matrix from triplets.
    Aex.setFromTriplets(triplets.begin(), triplets.end());
}

void GRP::factorize_Extended_Matrix() {
    //  Compute the sparse LU factorization of matrix `Aex'
    factorize.compute(Aex);
}

void GRP::obtain_Solution(const Eigen::VectorXd rhs, Eigen::VectorXd& solution, Eigen::VectorXd& solutionex) {
    //  Assemble the extended right hand side `rhsex'
    Eigen::VectorXd rhsex = Eigen::VectorXd::Zero(M);
    for (int nBlock=0; nBlock<N; ++nBlock) {
        rhsex(nBlockStart[nBlock]) = rhs(nBlock);
    }

    //  Obtain the solution
    solutionex = factorize.solve(rhsex);

    //  Desired solution vector
    solution = Eigen::VectorXd(N);
    for (int nBlock=0; nBlock<N; ++nBlock) {
        solution(nBlock) = solutionex(nBlockStart[nBlock]);
    }
}

void GRP::obtain_Solution(double* rhs, double* solution) {
    Eigen::Map<Eigen::VectorXd> rhs_(rhs, this->N, 1);
    Eigen::VectorXd solution_, solex;
    this->obtain_Solution(rhs_, solution_, solex);
    for (int i = 0; i < N; ++i) solution[i] = solution_[i];
}

double GRP::obtain_Error(const Eigen::VectorXd rhs, const Eigen::VectorXd& solex) {
    //  Assemble the extended right hand side `rhsex'
    Eigen::VectorXd rhsex = Eigen::VectorXd::Zero(M);
    for (int nBlock=0; nBlock<N; ++nBlock) {
        rhsex(nBlockStart[nBlock]) = rhs(nBlock);
    }
    double error = (Aex*solex-rhsex).cwiseAbs().maxCoeff();
    return error;
}

double GRP::obtain_Determinant() {
    //  Obtain determinant
    determinant = factorize.logAbsDeterminant();
    return determinant;
}

#endif /* defined(__GRP_HPP__) */
<|endoftext|>


<commit_before>/*
    avdeviceconfig.cpp  -  Kopete Video Device Configuration Panel

    Copyright (c) 2005 by Cludio da Silveira Pinheiro   <taupter@gmail.com>

    Kopete    (c) 2002-2003      by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * 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 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include "avdeviceconfig.h"
#include "avdeviceconfig_videoconfig.h"
#include "videodevice.h"

#include <qcheckbox.h>
#include <qlayout.h>
#include <qlabel.h>
#include <qhbuttongroup.h>
#include <qspinbox.h>
#include <qcombobox.h>
#include <qslider.h>

#include <kdebug.h>
#include <kplugininfo.h>
#include <klocale.h>
#include <kpushbutton.h>
#include <kgenericfactory.h>
#include <ktrader.h>
#include <kconfig.h>
#include <kcombobox.h>
#include <qimage.h>
#include <qpixmap.h>

#include <qtabwidget.h>

//#include "videodevice.h"
typedef KGenericFactory<AVDeviceConfig, QWidget> KopeteAVDeviceConfigFactory;
K_EXPORT_COMPONENT_FACTORY( kcm_kopete_avdeviceconfig, KopeteAVDeviceConfigFactory( "kcm_kopete_avdeviceconfig" ) )

AVDeviceConfig::AVDeviceConfig(QWidget *parent, const char *  name , const QStringList &args)
 : KCModule( KopeteAVDeviceConfigFactory::instance(), parent, args )
{
	(new QVBoxLayout(this))->setAutoAdd(true);
	mAVDeviceTabCtl = new QTabWidget(this, "mAVDeviceTabCtl");

// "Video" TAB ============================================================
	mPrfsVideoDevice = new AVDeviceConfig_VideoDevice(mAVDeviceTabCtl);
	connect(mPrfsVideoDevice->mDeviceKComboBox,               SIGNAL(activated(int)),    this, SLOT(slotDeviceKComboBoxChanged(int)));
	connect(mPrfsVideoDevice->mInputKComboBox,                SIGNAL(activated(int)),    this, SLOT(slotInputKComboBoxChanged(int)));
	connect(mPrfsVideoDevice->mStandardKComboBox,             SIGNAL(activated(int)),    this, SLOT(slotStandardKComboBoxChanged(int)));
	connect(mPrfsVideoDevice->mBrightSlider,                  SIGNAL(valueChanged(int)), this, SLOT(slotBrightSliderChanged(int)));
	connect(mPrfsVideoDevice->mContrastSlider,                SIGNAL(valueChanged(int)), this, SLOT(slotContrastSliderChanged(int)));
	connect(mPrfsVideoDevice->mSaturationSlider,              SIGNAL(valueChanged(int)), this, SLOT(slotSaturationSliderChanged(int)));
	connect(mPrfsVideoDevice->mHueSlider,                     SIGNAL(valueChanged(int)), this, SLOT(slotHueSliderChanged(int)));
	connect(mPrfsVideoDevice->mImageAutoAdjustBrightContrast, SIGNAL(toggled(bool)),     this, SLOT(slotImageAutoAdjustBrightContrastChanged(bool)));

	mPrfsVideoDevice->mVideoImageLabel->setPixmap(qpixmap);
	mAVDeviceTabCtl->addTab(mPrfsVideoDevice, i18n("&Video"));
	d = Kopete::AV::VideoDevice::self();
	d->scanDevices();
	d->selectDevice(0);
	d->open();
	d->initDevice();
	d->fillDeviceKcomboBox(mPrfsVideoDevice->mDeviceKComboBox);
	d->fillInputKComboBox(mPrfsVideoDevice->mInputKComboBox);
	d->selectInput(0);
	d->startCapturing();
	d->getFrame();
	d->getImage(&qimage);
	qpixmap.convertFromImage(qimage,0);
	mPrfsVideoDevice->mVideoImageLabel->setPixmap(qpixmap);
	connect(&qtimer, SIGNAL(timeout()), this, SLOT(slotUpdateImage()) );
	qtimer.start(500,FALSE);
}

AVDeviceConfig::~AVDeviceConfig()
{
	d->stopCapturing();
	d->close();
//	delete d;
}

/*!
    \fn VideoDeviceConfig::save()
 */
void AVDeviceConfig::save()
{
    /// @todo implement me
}

/*!
    \fn VideoDeviceConfig::load()
 */
void AVDeviceConfig::load()
{
    /// @todo implement me
}

void AVDeviceConfig::slotSettingsChanged(bool){
  emit changed(true);
}

void AVDeviceConfig::slotValueChanged(int){
  emit changed( true );
}

void AVDeviceConfig::slotDeviceKComboBoxChanged(int){
	int newdevice = mPrfsVideoDevice->mInputKComboBox->currentItem();
	if ((newdevice < d->m_videodevice.size())&&(newdevice!=d->currentDevice()))
	{
		d->selectDevice(newdevice);
		d->open();
		d->initDevice();
		d->fillDeviceKcomboBox(mPrfsVideoDevice->mDeviceKComboBox);
		d->fillInputKComboBox(mPrfsVideoDevice->mInputKComboBox);
		d->selectInput(0);
		d->startCapturing();
	}
	emit changed( true );
}

void AVDeviceConfig::slotInputKComboBoxChanged(int){
	d->selectInput(mPrfsVideoDevice->mInputKComboBox->currentItem());
	emit changed( true );
}

void AVDeviceConfig::slotStandardKComboBoxChanged(int){
  emit changed( true );
}

void AVDeviceConfig::slotBrightSliderChanged(int){
  emit changed( true );
}

void AVDeviceConfig::slotContrastSliderChanged(int){
  emit changed( true );
}

void AVDeviceConfig::slotSaturationSliderChanged(int){
  emit changed( true );
}

void AVDeviceConfig::slotHueSliderChanged(int){
  emit changed( true );
}

void AVDeviceConfig::slotImageAutoAdjustBrightContrastChanged(bool){
  emit changed( true );
}

void AVDeviceConfig::slotUpdateImage()
{
	d->getFrame();
	d->getImage(&qimage);
	qpixmap.convertFromImage(qimage,0);
//	bitBlt((QPaintDevice*)&m_video_image, 0, 0, (QPaintDevice*)&qpixmap, 0, Qt::CopyROP);
	mPrfsVideoDevice->mVideoImageLabel->setPixmap(qpixmap);
	kdDebug() << "kopete (avdeviceconfig_videoconfig): Image updated." << endl;
//	emit changed( true );
}
<commit_msg>Avoid some flickering on update of the image<commit_after>/*
    avdeviceconfig.cpp  -  Kopete Video Device Configuration Panel

    Copyright (c) 2005 by Cludio da Silveira Pinheiro   <taupter@gmail.com>

    Kopete    (c) 2002-2003      by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * 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 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include "avdeviceconfig.h"
#include "avdeviceconfig_videoconfig.h"
#include "videodevice.h"

#include <qcheckbox.h>
#include <qlayout.h>
#include <qlabel.h>
#include <qhbuttongroup.h>
#include <qspinbox.h>
#include <qcombobox.h>
#include <qslider.h>

#include <kdebug.h>
#include <kplugininfo.h>
#include <klocale.h>
#include <kpushbutton.h>
#include <kgenericfactory.h>
#include <ktrader.h>
#include <kconfig.h>
#include <kcombobox.h>
#include <qimage.h>
#include <qpixmap.h>

#include <qtabwidget.h>

//#include "videodevice.h"
typedef KGenericFactory<AVDeviceConfig, QWidget> KopeteAVDeviceConfigFactory;
K_EXPORT_COMPONENT_FACTORY( kcm_kopete_avdeviceconfig, KopeteAVDeviceConfigFactory( "kcm_kopete_avdeviceconfig" ) )

AVDeviceConfig::AVDeviceConfig(QWidget *parent, const char *  name , const QStringList &args)
 : KCModule( KopeteAVDeviceConfigFactory::instance(), parent, args )
{
	(new QVBoxLayout(this))->setAutoAdd(true);
	mAVDeviceTabCtl = new QTabWidget(this, "mAVDeviceTabCtl");

// "Video" TAB ============================================================
	mPrfsVideoDevice = new AVDeviceConfig_VideoDevice(mAVDeviceTabCtl);
	connect(mPrfsVideoDevice->mDeviceKComboBox,               SIGNAL(activated(int)),    this, SLOT(slotDeviceKComboBoxChanged(int)));
	connect(mPrfsVideoDevice->mInputKComboBox,                SIGNAL(activated(int)),    this, SLOT(slotInputKComboBoxChanged(int)));
	connect(mPrfsVideoDevice->mStandardKComboBox,             SIGNAL(activated(int)),    this, SLOT(slotStandardKComboBoxChanged(int)));
	connect(mPrfsVideoDevice->mBrightSlider,                  SIGNAL(valueChanged(int)), this, SLOT(slotBrightSliderChanged(int)));
	connect(mPrfsVideoDevice->mContrastSlider,                SIGNAL(valueChanged(int)), this, SLOT(slotContrastSliderChanged(int)));
	connect(mPrfsVideoDevice->mSaturationSlider,              SIGNAL(valueChanged(int)), this, SLOT(slotSaturationSliderChanged(int)));
	connect(mPrfsVideoDevice->mHueSlider,                     SIGNAL(valueChanged(int)), this, SLOT(slotHueSliderChanged(int)));
	connect(mPrfsVideoDevice->mImageAutoAdjustBrightContrast, SIGNAL(toggled(bool)),     this, SLOT(slotImageAutoAdjustBrightContrastChanged(bool)));

	mPrfsVideoDevice->mVideoImageLabel->setPixmap(qpixmap);
	mAVDeviceTabCtl->addTab(mPrfsVideoDevice, i18n("&Video"));
	d = Kopete::AV::VideoDevice::self();
	d->scanDevices();
	d->selectDevice(0);
	d->open();
	d->initDevice();
	d->fillDeviceKcomboBox(mPrfsVideoDevice->mDeviceKComboBox);
	d->fillInputKComboBox(mPrfsVideoDevice->mInputKComboBox);
	d->selectInput(0);
	d->startCapturing();
	d->getFrame();
	d->getImage(&qimage);
	qpixmap.convertFromImage(qimage,0);
	mPrfsVideoDevice->mVideoImageLabel->setPixmap(qpixmap);
	connect(&qtimer, SIGNAL(timeout()), this, SLOT(slotUpdateImage()) );
	qtimer.start(500,FALSE);
}

AVDeviceConfig::~AVDeviceConfig()
{
	d->stopCapturing();
	d->close();
//	delete d;
}

/*!
    \fn VideoDeviceConfig::save()
 */
void AVDeviceConfig::save()
{
    /// @todo implement me
}

/*!
    \fn VideoDeviceConfig::load()
 */
void AVDeviceConfig::load()
{
    /// @todo implement me
}

void AVDeviceConfig::slotSettingsChanged(bool){
  emit changed(true);
}

void AVDeviceConfig::slotValueChanged(int){
  emit changed( true );
}

void AVDeviceConfig::slotDeviceKComboBoxChanged(int){
	int newdevice = mPrfsVideoDevice->mInputKComboBox->currentItem();
	if ((newdevice < d->m_videodevice.size())&&(newdevice!=d->currentDevice()))
	{
		d->selectDevice(newdevice);
		d->open();
		d->initDevice();
		d->fillDeviceKcomboBox(mPrfsVideoDevice->mDeviceKComboBox);
		d->fillInputKComboBox(mPrfsVideoDevice->mInputKComboBox);
		d->selectInput(0);
		d->startCapturing();
	}
	emit changed( true );
}

void AVDeviceConfig::slotInputKComboBoxChanged(int){
	d->selectInput(mPrfsVideoDevice->mInputKComboBox->currentItem());
	emit changed( true );
}

void AVDeviceConfig::slotStandardKComboBoxChanged(int){
  emit changed( true );
}

void AVDeviceConfig::slotBrightSliderChanged(int){
  emit changed( true );
}

void AVDeviceConfig::slotContrastSliderChanged(int){
  emit changed( true );
}

void AVDeviceConfig::slotSaturationSliderChanged(int){
  emit changed( true );
}

void AVDeviceConfig::slotHueSliderChanged(int){
  emit changed( true );
}

void AVDeviceConfig::slotImageAutoAdjustBrightContrastChanged(bool){
  emit changed( true );
}

void AVDeviceConfig::slotUpdateImage()
{
	d->getFrame();
	d->getImage(&qimage);
	qpixmap.convertFromImage(qimage,0);
	bitBlt(mPrfsVideoDevice->mVideoImageLabel, 0, 0, &qimage, 0, Qt::CopyROP);
//	mPrfsVideoDevice->mVideoImageLabel->setPixmap(qpixmap);
	kdDebug() << "kopete (avdeviceconfig_videoconfig): Image updated." << endl;
//	emit changed( true );
}
<|endoftext|>


<commit_before>// -*- mode: C++; coding: utf-8 -*-
/*
 Recognition.cpp

 Copyright (c) 2011 AIST  All Rights Reserved.
 Eclipse Public License v1.0 (http://www.eclipse.org/legal/epl-v10.html)
*/
/*!
 * @file  Recognition.cpp
 * @brief 3D Recognition by Model
 * @date  \$Date::                            $
 */

#include "Recognition.h"
#include "execute3DRecognition.h"
#include "visionErrorCode.h"

// Module specification
// <rtc-template block="module_spec">
static const char *recognition_spec[] = {
  "implementation_id", "Recognition",
  "type_name", "Recognition",
  "description", "3D Recognition by Model",
  "version", "1.0.0",
  "vendor", "AIST.",
  "category", "3D Object Recognition",
  "activity_type", "PERIODIC",
  "kind", "DataFlowComponent",
  "max_instance", "0",
  "language", "C++",
  "lang_type", "compile",
  // Configuration variables
  "conf.default.RecogModelListPath", "modelList.txt",
  "conf.default.RecogParameterFilePath", "recogParameter.txt",
  "conf.default.DebugText", "0",
  "conf.default.DebugImage", "0",
  "conf.default.DebugDisplay", "0",
  // Widget
  "conf.__widget__.RecogModelListPath", "text",
  // Constraints
  ""
};

// </rtc-template>

/*!
 * @brief constructor
 * @param manager Maneger Object
 */
Recognition::Recognition(RTC::Manager* manager)
  // <rtc-template block="initializer">
  : RTC::DataFlowComponentBase(manager),
    m_stereo3DDataIn("Stereo3DIn", m_stereo3DData),
    m_stereo3DDataOut("Stereo3DOut", m_stereo3DData),
    m_RecognitionResultOut("RecognitionResultOut", m_RecognitionResult),
    m_RecognitionPort("Recognition"),
    m_Reconstruct3DPort("Reconstruct3D"),
    m_RecognitionResultViewerPort("RecognitionResultViewer")
    // </rtc-template>
{
  m_modelList.modelNum = 0;
  m_modelList.model = NULL;

  m_modelID = 0;
}

/*!
 * @brief destructor
 */
Recognition::~Recognition()
{
  // モデルファイル一覧のクリア
  if (m_modelList.model != NULL)
    {
      clearModelFileInfo(&m_modelList);
    }
}

RTC::ReturnCode_t Recognition::onInitialize()
{
  // Registration: InPort/OutPort/Service
  // <rtc-template block="registration">
  // Set InPort buffers
  addInPort("Stereo3DIn", m_stereo3DDataIn);

  // Set OutPort buffer
  addOutPort("Stereo3DOut", m_stereo3DDataOut);
  addOutPort("RecognitionResultOut", m_RecognitionResultOut);

  // Set service provider to Ports
  m_RecognitionPort.registerProvider("recogPort", "RecognitionService", m_Recognition);

  // Set service consumers to Ports
  m_Reconstruct3DPort.registerConsumer("Reconstruct3D", "Reconstruct3DService", m_Reconstruct3D);
  m_RecognitionResultViewerPort.registerConsumer("RecognitionResultViewer", "RecognitionResultViewerService", m_RecognitionResultViewer);

  // Set CORBA Service Ports
  addPort(m_RecognitionPort);
  addPort(m_Reconstruct3DPort);
  addPort(m_RecognitionResultViewerPort);

  // </rtc-template>

  // <rtc-template block="bind_config">
  // Bind variables and configuration variable
  bindParameter("RecogModelListPath", m_recogModelListPath, "modelList.txt");
  bindParameter("RecogParameterFilePath", m_recogParameterFilePath, "recogParameter.txt");
  bindParameter("DebugText", m_DebugText, "0");
  bindParameter("DebugImage", m_DebugImage, "0");
  bindParameter("DebugDisplay", m_DebugDisplay, "0");

  // </rtc-template>

  m_Recognition.setModelList(&m_modelList);

  // デバッグ用パラメータをメンバ変数に設定する。
  m_Recognition.setDebugParameter(m_DebugText, m_DebugImage, m_DebugDisplay);

  return RTC::RTC_OK;
}

/*
RTC::ReturnCode_t Recognition::onFinalize()
{
  return RTC::RTC_OK;
}
*/

/*
RTC::ReturnCode_t Recognition::onStartup(RTC::UniqueId ec_id)
{
  return RTC::RTC_OK;
}
*/

/*
RTC::ReturnCode_t Recognition::onShutdown(RTC::UniqueId ec_id)
{
  return RTC::RTC_OK;
}
*/

//
// Active 化した時点で Configuration を読み込む。
//
RTC::ReturnCode_t Recognition::onActivated(RTC::UniqueId ec_id)
{
  // モデルファイル一覧の読み込み。
  // モデル ID とモデルファイル名の組を読み込んで、保持しておく。
  int ret = loadModelListFile((char*) m_recogModelListPath.c_str(), &m_modelList);
#ifdef RECOGNITION_TEST
  printf( "Recognition::onActivated:RECOGNITION_TEST:m_recogModelListPath=%s\n", m_recogModelListPath.c_str());
#endif
  if (ret != 0)
    {
      m_Recognition.setModelList(NULL);
      fprintf(stderr, "Recognition::onActivated:モデルファイル一覧の読み込みに失敗しました。[%d]\n", ret);
      return RTC::BAD_PARAMETER;
    }

  m_Recognition.setModelList(&m_modelList);

  // 認識設定ファイルのパスを設定する。
  m_Recognition.setRecogParameterPath((char*) m_recogParameterFilePath.c_str());
#ifdef RECOGNITION_TEST
  printf( "Recognition::onActivated:RECOGNITION_TEST:m_recogParameterFilePath=%s\n", m_recogParameterFilePath.c_str());
#endif

  // 設定された認識設定ファイルをよみこむ。
  ret = m_Recognition.loadRecogParameter();
  if (ret != 0)
    {
      fprintf(stderr, "Recognition::onActivated:認識パラメータファイルの読み込みに失敗しました。[%d]\n", ret);
      return RTC::BAD_PARAMETER;
    }

  // デバッグ用パラメータを設定する。
  m_Recognition.setDebugParameter( m_DebugText, m_DebugImage, m_DebugDisplay );
#ifdef RECOGNITION_TEST
  printf( "Recognition::onActivated:RECOGNITION_TEST:m_DebugText=%d\n", m_DebugText);
  printf( "Recognition::onActivated:RECOGNITION_TEST:m_DebugImage=%d\n", m_DebugImage);
  printf( "Recognition::onActivated:RECOGNITION_TEST:m_DebugDisplay=%d\n", m_DebugDisplay);
#endif
  ret = m_Recognition.loadDebugParameter();
  if (ret != 0)
    {
      return RTC::BAD_PARAMETER;
    }

  return RTC::RTC_OK;
}

//
// Configuration で読み込んだデータをクリアする。
//
RTC::ReturnCode_t Recognition::onDeactivated(RTC::UniqueId ec_id)
{
  // モデルファイル一覧のクリア
  if (m_modelList.model != NULL)
    {
      clearModelFileInfo(&m_modelList);
    }

  return RTC::RTC_OK;
}

//
// 定期実行ルーチン
//
RTC::ReturnCode_t Recognition::onExecute(RTC::UniqueId ec_id)
{

  // 入力ポートに 3 次元距離計測データが送信されるのを待つ。
  if (m_stereo3DDataIn.isNew())
    {
      m_stereo3DDataIn.read();

      // 入力データから画像データをコピーする。
      Img::TimedMultiCameraImage* frame = &(m_stereo3DData.data.mimg);
      if (frame->data.image_seq.length() > 0)
        {
          printf("Image Accept: (%ld x %ld) x %ld\n",
		 frame->data.image_seq[0].image.width,
		 frame->data.image_seq[0].image.height,
		 frame->data.image_seq.length());
        }

      // 3 次元距離計測データをスルー出力する。
      m_stereo3DDataOut.write();

      Parameters param;
      int i;

      // 現在の認識設定値の取得
      m_Recognition.getCurrentRecogParameter(&param);

#ifdef RECOGNITION_TEST
      printf( "Recognition::onExecute:RECOGNITION_TEST:StereoPair=%d\n", param.pairing);
      printf( "Recognition::onExecute:RECOGNITION_TEST:OutputCandNum=%d\n", param.outputCandNum);
      printf( "Recognition::onExecute:RECOGNITION_TEST:EdgeDetectFunction=%d\n", param.feature2D.edgeDetectFunction);
      printf( "Recognition::onExecute:RECOGNITION_TEST:EdgeStrength=%f\n", param.feature2D.edgeStrength);
      printf( "Recognition::onExecute:RECOGNITION_TEST:MaxErrorOfLineFit=%f\n", param.feature2D.maxErrorofLineFit);
      printf( "Recognition::onExecute:RECOGNITION_TEST:MaxErrorOfConicFit=%f\n", param.feature2D.maxErrorofConicFit);
      printf( "Recognition::onExecute:RECOGNITION_TEST:OverlapRatioLine=%f\n", param.feature2D.overlapRatioLine);
      printf( "Recognition::onExecute:RECOGNITION_TEST:OverlapRatioCircle=%f\n", param.feature2D.overlapRatioCircle);
      printf( "Recognition::onExecute:RECOGNITION_TEST:HDMax(max_distance_end_points)=%f\n", param.feature2D.max_distance_end_points);
      printf( "Recognition::onExecute:RECOGNITION_TEST:IW_Condition=%d\n", param.paramEIW.Condition);
      printf( "Recognition::onExecute:RECOGNITION_TEST:IW_MinLength=%d\n", param.paramEIW.MinLength);
      printf( "Recognition::onExecute:RECOGNITION_TEST:IW_MinShortRadPrev=%f\n",param.paramEIW.MinShortRadPrev );
      printf( "Recognition::onExecute:RECOGNITION_TEST:IW_MinShortRadPost=%f\n", param.paramEIW.MinShortRadPost );
      printf( "Recognition::onExecute:RECOGNITION_TEST:IW_ThMeanError=%f\n", param.paramEIW.ThMeanError);
      printf( "Recognition::onExecute:RECOGNITION_TEST:IW_ThMaxError=%f\n", param.paramEIW.ThMaxError);
//      printf( "Recognition::onExecute:RECOGNITION_TEST:IW_OffsetMode=%d\n", param.paramEIW.OffsetMode);
      printf( "Recognition::onExecute:RECOGNITION_TEST:Amax=%f\n", param.stereo.amax);
      printf( "Recognition::onExecute:RECOGNITION_TEST:Amin=%f\n", param.stereo.amin);
      printf( "Recognition::onExecute:RECOGNITION_TEST:StereoError=%f\n", param.stereo.ethr);
      printf( "Recognition::onExecute:RECOGNITION_TEST:MinLengthLine2D=%f\n", param.feature2D.min_length_line);
      printf( "Recognition::onExecute:RECOGNITION_TEST:NoSearchFeatures=%d\n", param.feature2D.no_search_features);
      fflush(stdout);
#endif //RECOGNITION_TEST

      TimedRecognitionResult pos;
      // 認識を実行する。
      int ret = execute3DRecognition(m_stereo3DData.data.mimg,
                                     m_Recognition.getModelID(),
                                     m_Recognition.getModelFilePath(),
                                     param,
                                     pos);

      if ((ret != 0) && (ret != VISION_ILLEGAL_IMAGE_SIZE))
        // 画像サイズが 0 の場合は、候補数 0 を出力する。
        {
#ifdef _DEBUG
          fprintf(stderr, "Recognition failed.\n");
#endif
          // エラーの場合、候補数 1 でエラーを認識結果に出力する。
          m_RecognitionResult.data.length(RecogResultElementNum);
          for (i = 0; i < RecogResultElementNum; i++)
            {
              m_RecognitionResult.data[i] = 0.0;
            }
          m_RecognitionResult.data[eRRCameraID] = (double) m_stereo3DData.data.mimg.data.camera_set_id;
          m_RecognitionResult.data[eRRErrorCode] = (double) ret;
          m_RecognitionResult.tm = pos.tm;
          m_RecognitionResultOut.write();

          return RTC::RTC_OK;
        }

      // 認識結果を出力ポートに出力する。
      long dataNum = (long) (pos.data.length());
      m_RecognitionResult.data.length(dataNum);
      m_RecognitionResult.tm = pos.tm;

      for (i = 0; i < dataNum; i++)
        {
          m_RecognitionResult.data[i] = pos.data[i];
        }
      m_RecognitionResultOut.write();

      // 結果表示コンポーネントを呼び出して認識結果を表示する。
      if (::CORBA::is_nil(m_RecognitionResultViewer.getObject()) == false)
        {
          m_RecognitionResultViewer->display(m_stereo3DData.data.mimg, pos);
        }

    }

  // モデル ID がセットされていたら、画像送信要求を行う。
  if (m_Recognition.getModelIDUpdateFlag() == true)
    {
      if (::CORBA::is_nil(m_Reconstruct3D.getObject()) == false)
        {
          m_Reconstruct3D->reconstruct();
        }
      m_Recognition.resetModelIDUpdateFlag();
    }

  return RTC::RTC_OK;
}

/*
RTC::ReturnCode_t Recognition::onAborting(RTC::UniqueId ec_id)
{
  return RTC::RTC_OK;
}
*/

/*
RTC::ReturnCode_t Recognition::onError(RTC::UniqueId ec_id)
{
  return RTC::RTC_OK;
}
*/

/*
RTC::ReturnCode_t Recognition::onReset(RTC::UniqueId ec_id)
{
  return RTC::RTC_OK;
}
*/

/*
RTC::ReturnCode_t Recognition::onStateUpdate(RTC::UniqueId ec_id)
{
  return RTC::RTC_OK;
}
*/

/*
RTC::ReturnCode_t Recognition::onRateChanged(RTC::UniqueId ec_id)
{
  return RTC::RTC_OK;
}
*/

extern
  "C"
{

  void
  RecognitionInit(RTC::Manager* manager)
  {
    coil::Properties profile(recognition_spec);
    manager->registerFactory(profile,
			     RTC::Create < Recognition >,
			     RTC::Delete < Recognition >);
  }

}
<commit_msg>テスト用出力追加<commit_after>// -*- mode: C++; coding: utf-8 -*-
/*
 Recognition.cpp

 Copyright (c) 2011 AIST  All Rights Reserved.
 Eclipse Public License v1.0 (http://www.eclipse.org/legal/epl-v10.html)
*/
/*!
 * @file  Recognition.cpp
 * @brief 3D Recognition by Model
 * @date  \$Date::                            $
 */

#include "Recognition.h"
#include "execute3DRecognition.h"
#include "visionErrorCode.h"

// Module specification
// <rtc-template block="module_spec">
static const char *recognition_spec[] = {
  "implementation_id", "Recognition",
  "type_name", "Recognition",
  "description", "3D Recognition by Model",
  "version", "1.0.0",
  "vendor", "AIST.",
  "category", "3D Object Recognition",
  "activity_type", "PERIODIC",
  "kind", "DataFlowComponent",
  "max_instance", "0",
  "language", "C++",
  "lang_type", "compile",
  // Configuration variables
  "conf.default.RecogModelListPath", "modelList.txt",
  "conf.default.RecogParameterFilePath", "recogParameter.txt",
  "conf.default.DebugText", "0",
  "conf.default.DebugImage", "0",
  "conf.default.DebugDisplay", "0",
  // Widget
  "conf.__widget__.RecogModelListPath", "text",
  // Constraints
  ""
};

// </rtc-template>

/*!
 * @brief constructor
 * @param manager Maneger Object
 */
Recognition::Recognition(RTC::Manager* manager)
  // <rtc-template block="initializer">
  : RTC::DataFlowComponentBase(manager),
    m_stereo3DDataIn("Stereo3DIn", m_stereo3DData),
    m_stereo3DDataOut("Stereo3DOut", m_stereo3DData),
    m_RecognitionResultOut("RecognitionResultOut", m_RecognitionResult),
    m_RecognitionPort("Recognition"),
    m_Reconstruct3DPort("Reconstruct3D"),
    m_RecognitionResultViewerPort("RecognitionResultViewer")
    // </rtc-template>
{
  m_modelList.modelNum = 0;
  m_modelList.model = NULL;

  m_modelID = 0;
}

/*!
 * @brief destructor
 */
Recognition::~Recognition()
{
  // モデルファイル一覧のクリア
  if (m_modelList.model != NULL)
    {
      clearModelFileInfo(&m_modelList);
    }
}

RTC::ReturnCode_t Recognition::onInitialize()
{
  // Registration: InPort/OutPort/Service
  // <rtc-template block="registration">
  // Set InPort buffers
  addInPort("Stereo3DIn", m_stereo3DDataIn);

  // Set OutPort buffer
  addOutPort("Stereo3DOut", m_stereo3DDataOut);
  addOutPort("RecognitionResultOut", m_RecognitionResultOut);

  // Set service provider to Ports
  m_RecognitionPort.registerProvider("recogPort", "RecognitionService", m_Recognition);

  // Set service consumers to Ports
  m_Reconstruct3DPort.registerConsumer("Reconstruct3D", "Reconstruct3DService", m_Reconstruct3D);
  m_RecognitionResultViewerPort.registerConsumer("RecognitionResultViewer", "RecognitionResultViewerService", m_RecognitionResultViewer);

  // Set CORBA Service Ports
  addPort(m_RecognitionPort);
  addPort(m_Reconstruct3DPort);
  addPort(m_RecognitionResultViewerPort);

  // </rtc-template>

  // <rtc-template block="bind_config">
  // Bind variables and configuration variable
  bindParameter("RecogModelListPath", m_recogModelListPath, "modelList.txt");
  bindParameter("RecogParameterFilePath", m_recogParameterFilePath, "recogParameter.txt");
  bindParameter("DebugText", m_DebugText, "0");
  bindParameter("DebugImage", m_DebugImage, "0");
  bindParameter("DebugDisplay", m_DebugDisplay, "0");

  // </rtc-template>

  m_Recognition.setModelList(&m_modelList);

  // デバッグ用パラメータをメンバ変数に設定する。
  m_Recognition.setDebugParameter(m_DebugText, m_DebugImage, m_DebugDisplay);

  return RTC::RTC_OK;
}

/*
RTC::ReturnCode_t Recognition::onFinalize()
{
  return RTC::RTC_OK;
}
*/

/*
RTC::ReturnCode_t Recognition::onStartup(RTC::UniqueId ec_id)
{
  return RTC::RTC_OK;
}
*/

/*
RTC::ReturnCode_t Recognition::onShutdown(RTC::UniqueId ec_id)
{
  return RTC::RTC_OK;
}
*/

//
// Active 化した時点で Configuration を読み込む。
//
RTC::ReturnCode_t Recognition::onActivated(RTC::UniqueId ec_id)
{
  // モデルファイル一覧の読み込み。
  // モデル ID とモデルファイル名の組を読み込んで、保持しておく。
  int ret = loadModelListFile((char*) m_recogModelListPath.c_str(), &m_modelList);
#ifdef RECOGNITION_TEST
  printf( "Recognition::onActivated:RECOGNITION_TEST:m_recogModelListPath=%s\n", m_recogModelListPath.c_str());
#endif
  if (ret != 0)
    {
      m_Recognition.setModelList(NULL);
      fprintf(stderr, "Recognition::onActivated:モデルファイル一覧の読み込みに失敗しました。[%d]\n", ret);
      return RTC::BAD_PARAMETER;
    }

  m_Recognition.setModelList(&m_modelList);

  // 認識設定ファイルのパスを設定する。
  m_Recognition.setRecogParameterPath((char*) m_recogParameterFilePath.c_str());
#ifdef RECOGNITION_TEST
  printf( "Recognition::onActivated:RECOGNITION_TEST:m_recogParameterFilePath=%s\n", m_recogParameterFilePath.c_str());
#endif

  // 設定された認識設定ファイルをよみこむ。
  ret = m_Recognition.loadRecogParameter();
  if (ret != 0)
    {
      fprintf(stderr, "Recognition::onActivated:認識パラメータファイルの読み込みに失敗しました。[%d]\n", ret);
      return RTC::BAD_PARAMETER;
    }

  // デバッグ用パラメータを設定する。
  m_Recognition.setDebugParameter( m_DebugText, m_DebugImage, m_DebugDisplay );
#ifdef RECOGNITION_TEST
  printf( "Recognition::onActivated:RECOGNITION_TEST:m_DebugText=%d\n", m_DebugText);
  printf( "Recognition::onActivated:RECOGNITION_TEST:m_DebugImage=%d\n", m_DebugImage);
  printf( "Recognition::onActivated:RECOGNITION_TEST:m_DebugDisplay=%d\n", m_DebugDisplay);
#endif
  ret = m_Recognition.loadDebugParameter();
  if (ret != 0)
    {
      return RTC::BAD_PARAMETER;
    }

  return RTC::RTC_OK;
}

//
// Configuration で読み込んだデータをクリアする。
//
RTC::ReturnCode_t Recognition::onDeactivated(RTC::UniqueId ec_id)
{
  // モデルファイル一覧のクリア
  if (m_modelList.model != NULL)
    {
      clearModelFileInfo(&m_modelList);
    }

  return RTC::RTC_OK;
}

//
// 定期実行ルーチン
//
RTC::ReturnCode_t Recognition::onExecute(RTC::UniqueId ec_id)
{

  // 入力ポートに 3 次元距離計測データが送信されるのを待つ。
  if (m_stereo3DDataIn.isNew())
    {
      m_stereo3DDataIn.read();

      // 入力データから画像データをコピーする。
      Img::TimedMultiCameraImage* frame = &(m_stereo3DData.data.mimg);
      if (frame->data.image_seq.length() > 0)
        {
          printf("Image Accept: (%ld x %ld) x %ld\n",
		 frame->data.image_seq[0].image.width,
		 frame->data.image_seq[0].image.height,
		 frame->data.image_seq.length());
        }

      // 3 次元距離計測データをスルー出力する。
      m_stereo3DDataOut.write();

      Parameters param;
      int i;

      // 現在の認識設定値の取得
      m_Recognition.getCurrentRecogParameter(&param);

#ifdef RECOGNITION_TEST
      printf( "Recognition::onExecute:RECOGNITION_TEST:StereoPair=%d\n", param.pairing);
      printf( "Recognition::onExecute:RECOGNITION_TEST:OutputCandNum=%d\n", param.outputCandNum);
      printf( "Recognition::onExecute:RECOGNITION_TEST:EdgeDetectFunction=%d\n", param.feature2D.edgeDetectFunction);
      printf( "Recognition::onExecute:RECOGNITION_TEST:EdgeStrength=%f\n", param.feature2D.edgeStrength);
      printf( "Recognition::onExecute:RECOGNITION_TEST:MaxErrorOfLineFit=%f\n", param.feature2D.maxErrorofLineFit);
      printf( "Recognition::onExecute:RECOGNITION_TEST:MaxErrorOfConicFit=%f\n", param.feature2D.maxErrorofConicFit);
      printf( "Recognition::onExecute:RECOGNITION_TEST:OverlapRatioLine=%f\n", param.feature2D.overlapRatioLine);
      printf( "Recognition::onExecute:RECOGNITION_TEST:OverlapRatioCircle=%f\n", param.feature2D.overlapRatioCircle);
      printf( "Recognition::onExecute:RECOGNITION_TEST:HDMax(max_distance_end_points)=%f\n", param.feature2D.max_distance_end_points);
      printf( "Recognition::onExecute:RECOGNITION_TEST:IW_Condition=%d\n", param.paramEIW.Condition);
      printf( "Recognition::onExecute:RECOGNITION_TEST:IW_MinLength=%d\n", param.paramEIW.MinLength);
      printf( "Recognition::onExecute:RECOGNITION_TEST:IW_MinShortRadPrev=%f\n",param.paramEIW.MinShortRadPrev );
      printf( "Recognition::onExecute:RECOGNITION_TEST:IW_MinShortRadPost=%f\n", param.paramEIW.MinShortRadPost );
      printf( "Recognition::onExecute:RECOGNITION_TEST:IW_ThMeanError=%f\n", param.paramEIW.ThMeanError);
      printf( "Recognition::onExecute:RECOGNITION_TEST:IW_ThMaxError=%f\n", param.paramEIW.ThMaxError);
//      printf( "Recognition::onExecute:RECOGNITION_TEST:IW_OffsetMode=%d\n", param.paramEIW.OffsetMode);
      printf( "Recognition::onExecute:RECOGNITION_TEST:Amax=%f\n", param.stereo.amax);
      printf( "Recognition::onExecute:RECOGNITION_TEST:Amin=%f\n", param.stereo.amin);
      printf( "Recognition::onExecute:RECOGNITION_TEST:StereoError=%f\n", param.stereo.ethr);
      printf( "Recognition::onExecute:RECOGNITION_TEST:MinLengthLine2D=%f\n", param.feature2D.min_length_line);
      printf( "Recognition::onExecute:RECOGNITION_TEST:NoSearchFeatures=%d\n", param.feature2D.no_search_features);
      printf( "Recognition::onExecute:RECOGNITION_TEST:MaxDistanceSimilarLine=%f\n", param.feature2D.max_distance_similar_line);
      fflush(stdout);
#endif //RECOGNITION_TEST

      TimedRecognitionResult pos;
      // 認識を実行する。
      int ret = execute3DRecognition(m_stereo3DData.data.mimg,
                                     m_Recognition.getModelID(),
                                     m_Recognition.getModelFilePath(),
                                     param,
                                     pos);

      if ((ret != 0) && (ret != VISION_ILLEGAL_IMAGE_SIZE))
        // 画像サイズが 0 の場合は、候補数 0 を出力する。
        {
#ifdef _DEBUG
          fprintf(stderr, "Recognition failed.\n");
#endif
          // エラーの場合、候補数 1 でエラーを認識結果に出力する。
          m_RecognitionResult.data.length(RecogResultElementNum);
          for (i = 0; i < RecogResultElementNum; i++)
            {
              m_RecognitionResult.data[i] = 0.0;
            }
          m_RecognitionResult.data[eRRCameraID] = (double) m_stereo3DData.data.mimg.data.camera_set_id;
          m_RecognitionResult.data[eRRErrorCode] = (double) ret;
          m_RecognitionResult.tm = pos.tm;
          m_RecognitionResultOut.write();

          return RTC::RTC_OK;
        }

      // 認識結果を出力ポートに出力する。
      long dataNum = (long) (pos.data.length());
      m_RecognitionResult.data.length(dataNum);
      m_RecognitionResult.tm = pos.tm;

      for (i = 0; i < dataNum; i++)
        {
          m_RecognitionResult.data[i] = pos.data[i];
        }
      m_RecognitionResultOut.write();

      // 結果表示コンポーネントを呼び出して認識結果を表示する。
      if (::CORBA::is_nil(m_RecognitionResultViewer.getObject()) == false)
        {
          m_RecognitionResultViewer->display(m_stereo3DData.data.mimg, pos);
        }

    }

  // モデル ID がセットされていたら、画像送信要求を行う。
  if (m_Recognition.getModelIDUpdateFlag() == true)
    {
      if (::CORBA::is_nil(m_Reconstruct3D.getObject()) == false)
        {
          m_Reconstruct3D->reconstruct();
        }
      m_Recognition.resetModelIDUpdateFlag();
    }

  return RTC::RTC_OK;
}

/*
RTC::ReturnCode_t Recognition::onAborting(RTC::UniqueId ec_id)
{
  return RTC::RTC_OK;
}
*/

/*
RTC::ReturnCode_t Recognition::onError(RTC::UniqueId ec_id)
{
  return RTC::RTC_OK;
}
*/

/*
RTC::ReturnCode_t Recognition::onReset(RTC::UniqueId ec_id)
{
  return RTC::RTC_OK;
}
*/

/*
RTC::ReturnCode_t Recognition::onStateUpdate(RTC::UniqueId ec_id)
{
  return RTC::RTC_OK;
}
*/

/*
RTC::ReturnCode_t Recognition::onRateChanged(RTC::UniqueId ec_id)
{
  return RTC::RTC_OK;
}
*/

extern
  "C"
{

  void
  RecognitionInit(RTC::Manager* manager)
  {
    coil::Properties profile(recognition_spec);
    manager->registerFactory(profile,
			     RTC::Create < Recognition >,
			     RTC::Delete < Recognition >);
  }

}
<|endoftext|>


<commit_before>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

// A program with a main that is suitable for unittests, including those
// that also define microbenchmarks.  Based on whether the user specified
// the --benchmark_filter flag which specifies which benchmarks to run,
// we will either run benchmarks or run the gtest tests in the program.

#include <iostream>
#include <string>

#include "absl/strings/match.h"
#include "tensorflow/core/platform/platform.h"
#include "tensorflow/core/platform/stacktrace_handler.h"
#include "tensorflow/core/platform/test.h"
#include "tensorflow/core/platform/test_benchmark.h"

GTEST_API_ int main(int argc, char** argv) {
  std::cout << "Running main() from test_main.cc\n";

  tensorflow::testing::InstallStacktraceHandler();

  for (int i = 1; i < argc; i++) {
    if (absl::StartsWith(argv[i], "--benchmark_filter=")) {
      ::benchmark::Initialize(&argc, argv);

      // XXX: Must be called after benchmark's init because
      // InitGoogleTest eventually calls absl::ParseCommandLine() which would
      // complain that benchmark_filter flag is not known because that flag is
      // defined by the benchmark library via its own command-line flag
      // facility, which is not known to absl flags.
      // FIXME(vyng): Fix this mess once we make benchmark use absl flags
      testing::InitGoogleTest(&argc, argv);
      ::benchmark::RunSpecifiedBenchmarks();
      return 0;
    }
  }

  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Remove useless logging entry.<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

// A program with a main that is suitable for unittests, including those
// that also define microbenchmarks.  Based on whether the user specified
// the --benchmark_filter flag which specifies which benchmarks to run,
// we will either run benchmarks or run the gtest tests in the program.

#include <string>

#include "absl/strings/match.h"
#include "tensorflow/core/platform/platform.h"
#include "tensorflow/core/platform/stacktrace_handler.h"
#include "tensorflow/core/platform/test.h"
#include "tensorflow/core/platform/test_benchmark.h"

GTEST_API_ int main(int argc, char** argv) {
  tensorflow::testing::InstallStacktraceHandler();

  for (int i = 1; i < argc; i++) {
    if (absl::StartsWith(argv[i], "--benchmark_filter=")) {
      ::benchmark::Initialize(&argc, argv);

      // XXX: Must be called after benchmark's init because
      // InitGoogleTest eventually calls absl::ParseCommandLine() which would
      // complain that benchmark_filter flag is not known because that flag is
      // defined by the benchmark library via its own command-line flag
      // facility, which is not known to absl flags.
      // FIXME(vyng): Fix this mess once we make benchmark use absl flags
      testing::InitGoogleTest(&argc, argv);
      ::benchmark::RunSpecifiedBenchmarks();
      return 0;
    }
  }

  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2011 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 "receiver.h"

#include "encoded_frame.h"
#include "internal_defines.h"
#include "media_opt_util.h"
#include "tick_time_base.h"
#include "trace.h"
#include "video_coding.h"

#include <assert.h>

namespace webrtc {

VCMReceiver::VCMReceiver(VCMTiming& timing,
                         TickTimeBase* clock,
                         WebRtc_Word32 vcmId,
                         WebRtc_Word32 receiverId,
                         bool master)
:
_critSect(CriticalSectionWrapper::CreateCriticalSection()),
_vcmId(vcmId),
_clock(clock),
_receiverId(receiverId),
_master(master),
_jitterBuffer(_clock, vcmId, receiverId, master),
_timing(timing),
_renderWaitEvent(*new VCMEvent()),
_state(kPassive)
{
}

VCMReceiver::~VCMReceiver()
{
    _renderWaitEvent.Set();
    delete &_renderWaitEvent;
    delete _critSect;
}

void
VCMReceiver::Reset()
{
    CriticalSectionScoped cs(_critSect);
    if (!_jitterBuffer.Running())
    {
        _jitterBuffer.Start();
    }
    else
    {
        _jitterBuffer.Flush();
    }
    _renderWaitEvent.Reset();
    if (_master)
    {
        _state = kReceiving;
    }
    else
    {
        _state = kPassive;
    }
}

WebRtc_Word32
VCMReceiver::Initialize()
{
    CriticalSectionScoped cs(_critSect);
    Reset();
    if (!_master)
    {
        SetNackMode(kNoNack);
    }
    return VCM_OK;
}

void VCMReceiver::UpdateRtt(WebRtc_UWord32 rtt)
{
    _jitterBuffer.UpdateRtt(rtt);
}

WebRtc_Word32
VCMReceiver::InsertPacket(const VCMPacket& packet,
                          WebRtc_UWord16 frameWidth,
                          WebRtc_UWord16 frameHeight)
{
    // Find an empty frame
    VCMEncodedFrame *buffer = NULL;
    const WebRtc_Word32 error = _jitterBuffer.GetFrame(packet, buffer);
    if (error == VCM_OLD_PACKET_ERROR)
    {
        return VCM_OK;
    }
    else if (error < 0)
    {
        return error;
    }

    {
        CriticalSectionScoped cs(_critSect);

        if (frameWidth && frameHeight)
        {
            buffer->SetEncodedSize(static_cast<WebRtc_UWord32>(frameWidth),
                                   static_cast<WebRtc_UWord32>(frameHeight));
        }

        if (_master)
        {
            // Only trace the primary receiver to make it possible
            // to parse and plot the trace file.
            WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
                         VCMId(_vcmId, _receiverId),
                         "Packet seqNo %u of frame %u at %u",
                         packet.seqNum, packet.timestamp,
                         MaskWord64ToUWord32(_clock->MillisecondTimestamp()));
        }

        const WebRtc_Word64 nowMs = _clock->MillisecondTimestamp();

        WebRtc_Word64 renderTimeMs = _timing.RenderTimeMs(packet.timestamp, nowMs);

        if (renderTimeMs < 0)
        {
            // Render time error. Assume that this is due to some change in
            // the incoming video stream and reset the JB and the timing.
            _jitterBuffer.Flush();
            _timing.Reset(_clock->MillisecondTimestamp());
            return VCM_FLUSH_INDICATOR;
        }
        else if (renderTimeMs < nowMs - kMaxVideoDelayMs)
        {
            WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId),
                "This frame should have been rendered more than %u ms ago."
                "Flushing jitter buffer and resetting timing.", kMaxVideoDelayMs);
            _jitterBuffer.Flush();
            _timing.Reset(_clock->MillisecondTimestamp());
            return VCM_FLUSH_INDICATOR;
        }
        else if (_timing.TargetVideoDelay() > kMaxVideoDelayMs)
        {
            WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId),
                "More than %u ms target delay. Flushing jitter buffer and resetting timing.",
                kMaxVideoDelayMs);
            _jitterBuffer.Flush();
            _timing.Reset(_clock->MillisecondTimestamp());
            return VCM_FLUSH_INDICATOR;
        }

        // First packet received belonging to this frame.
        if (buffer->Length() == 0)
        {
            const WebRtc_Word64 nowMs = _clock->MillisecondTimestamp();
            if (_master)
            {
                // Only trace the primary receiver to make it possible to parse and plot the trace file.
                WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId),
                           "First packet of frame %u at %u", packet.timestamp,
                           MaskWord64ToUWord32(nowMs));
            }
            renderTimeMs = _timing.RenderTimeMs(packet.timestamp, nowMs);
            if (renderTimeMs >= 0)
            {
                buffer->SetRenderTime(renderTimeMs);
            }
            else
            {
                buffer->SetRenderTime(nowMs);
            }
        }

        // Insert packet into the jitter buffer
        // both media and empty packets
        const VCMFrameBufferEnum
        ret = _jitterBuffer.InsertPacket(buffer, packet);
        if (ret == kFlushIndicator) {
          return VCM_FLUSH_INDICATOR;
        } else if (ret < 0) {
          WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding,
                       VCMId(_vcmId, _receiverId),
                       "Error inserting packet seqNo=%u, timeStamp=%u",
                       packet.seqNum, packet.timestamp);
          return VCM_JITTER_BUFFER_ERROR;
        }
    }
    return VCM_OK;
}

VCMEncodedFrame*
VCMReceiver::FrameForDecoding(WebRtc_UWord16 maxWaitTimeMs, WebRtc_Word64& nextRenderTimeMs,
                              bool renderTiming, VCMReceiver* dualReceiver)
{
    // No need to enter the critical section here since the jitter buffer
    // is thread-safe.
    FrameType incomingFrameType = kVideoFrameDelta;
    nextRenderTimeMs = -1;
    const WebRtc_Word64 startTimeMs = _clock->MillisecondTimestamp();
    WebRtc_Word64 ret = _jitterBuffer.GetNextTimeStamp(maxWaitTimeMs,
                                                       incomingFrameType,
                                                       nextRenderTimeMs);
    if (ret < 0)
    {
        // No timestamp in jitter buffer at the moment
        return NULL;
    }
    const WebRtc_UWord32 timeStamp = static_cast<WebRtc_UWord32>(ret);

    // Update the timing
    _timing.SetRequiredDelay(_jitterBuffer.GetEstimatedJitterMS());
    _timing.UpdateCurrentDelay(timeStamp);

    const WebRtc_Word32 tempWaitTime = maxWaitTimeMs -
            static_cast<WebRtc_Word32>(_clock->MillisecondTimestamp() - startTimeMs);
    WebRtc_UWord16 newMaxWaitTime = static_cast<WebRtc_UWord16>(VCM_MAX(tempWaitTime, 0));

    VCMEncodedFrame* frame = NULL;

    if (renderTiming)
    {
        frame = FrameForDecoding(newMaxWaitTime, nextRenderTimeMs, dualReceiver);
    }
    else
    {
        frame = FrameForRendering(newMaxWaitTime, nextRenderTimeMs, dualReceiver);
    }

    if (frame != NULL)
    {
        bool retransmitted = false;
        const WebRtc_Word64 lastPacketTimeMs =
                _jitterBuffer.LastPacketTime(frame, retransmitted);
        if (lastPacketTimeMs >= 0 && !retransmitted)
        {
            // We don't want to include timestamps which have suffered from retransmission
            // here, since we compensate with extra retransmission delay within
            // the jitter estimate.
            _timing.IncomingTimestamp(timeStamp, lastPacketTimeMs);
        }
        if (dualReceiver != NULL)
        {
            dualReceiver->UpdateState(*frame);
        }
    }
    return frame;
}

VCMEncodedFrame*
VCMReceiver::FrameForDecoding(WebRtc_UWord16 maxWaitTimeMs,
                              WebRtc_Word64 nextRenderTimeMs,
                              VCMReceiver* dualReceiver)
{
    // How long can we wait until we must decode the next frame
    WebRtc_UWord32 waitTimeMs = _timing.MaxWaitingTime(nextRenderTimeMs,
                                          _clock->MillisecondTimestamp());

    // Try to get a complete frame from the jitter buffer
    VCMEncodedFrame* frame = _jitterBuffer.GetCompleteFrameForDecoding(0);

    if (frame == NULL && maxWaitTimeMs == 0 && waitTimeMs > 0)
    {
        // If we're not allowed to wait for frames to get complete we must
        // calculate if it's time to decode, and if it's not we will just return
        // for now.
        return NULL;
    }

    if (frame == NULL && VCM_MIN(waitTimeMs, maxWaitTimeMs) == 0)
    {
        // No time to wait for a complete frame,
        // check if we have an incomplete
        const bool dualReceiverEnabledAndPassive = (dualReceiver != NULL &&
                                     dualReceiver->State() == kPassive &&
                                     dualReceiver->NackMode() == kNackInfinite);
        if (dualReceiverEnabledAndPassive &&
            !_jitterBuffer.CompleteSequenceWithNextFrame())
        {
            // Jitter buffer state might get corrupt with this frame.
            dualReceiver->CopyJitterBufferStateFromReceiver(*this);
            frame = _jitterBuffer.GetFrameForDecoding();
            assert(frame);
        } else {
            frame = _jitterBuffer.GetFrameForDecoding();
        }
    }
    if (frame == NULL)
    {
        // Wait for a complete frame
        frame = _jitterBuffer.GetCompleteFrameForDecoding(maxWaitTimeMs);
    }
    if (frame == NULL)
    {
        // Get an incomplete frame
        if (_timing.MaxWaitingTime(nextRenderTimeMs,
                                   _clock->MillisecondTimestamp()) > 0)
        {
            // Still time to wait for a complete frame
            return NULL;
        }

        // No time left to wait, we must decode this frame now.
        const bool dualReceiverEnabledAndPassive = (dualReceiver != NULL &&
                                     dualReceiver->State() == kPassive &&
                                     dualReceiver->NackMode() == kNackInfinite);
        if (dualReceiverEnabledAndPassive &&
            !_jitterBuffer.CompleteSequenceWithNextFrame())
        {
            // Jitter buffer state might get corrupt with this frame.
            dualReceiver->CopyJitterBufferStateFromReceiver(*this);
        }

        frame = _jitterBuffer.GetFrameForDecoding();
    }
    return frame;
}

VCMEncodedFrame*
VCMReceiver::FrameForRendering(WebRtc_UWord16 maxWaitTimeMs,
                               WebRtc_Word64 nextRenderTimeMs,
                               VCMReceiver* dualReceiver)
{
    // How long MUST we wait until we must decode the next frame. This is different for the case
    // where we have a renderer which can render at a specified time. Here we must wait as long
    // as possible before giving the frame to the decoder, which will render the frame as soon
    // as it has been decoded.
    WebRtc_UWord32 waitTimeMs = _timing.MaxWaitingTime(nextRenderTimeMs,
                                                       _clock->MillisecondTimestamp());
    if (maxWaitTimeMs < waitTimeMs)
    {
        // If we're not allowed to wait until the frame is supposed to be rendered
        // we will have to return NULL for now.
        return NULL;
    }
    // Wait until it's time to render
    _renderWaitEvent.Wait(waitTimeMs);

    // Get a complete frame if possible
    VCMEncodedFrame* frame = _jitterBuffer.GetCompleteFrameForDecoding(0);

    if (frame == NULL)
    {
        // Get an incomplete frame
        const bool dualReceiverEnabledAndPassive = dualReceiver != NULL &&
                                                   dualReceiver->State() == kPassive &&
                                                   dualReceiver->NackMode() == kNackInfinite;
        if (dualReceiverEnabledAndPassive && !_jitterBuffer.CompleteSequenceWithNextFrame())
        {
            // Jitter buffer state might get corrupt with this frame.
            dualReceiver->CopyJitterBufferStateFromReceiver(*this);
        }

        frame = _jitterBuffer.GetFrameForDecoding();
    }
    return frame;
}

void
VCMReceiver::ReleaseFrame(VCMEncodedFrame* frame)
{
    _jitterBuffer.ReleaseFrame(frame);
}

WebRtc_Word32
VCMReceiver::ReceiveStatistics(WebRtc_UWord32& bitRate, WebRtc_UWord32& frameRate)
{
    const WebRtc_Word32 ret = _jitterBuffer.GetUpdate(frameRate, bitRate);
    bitRate /= 1000; // Should be in kbps
    return ret;
}

WebRtc_Word32
VCMReceiver::ReceivedFrameCount(VCMFrameCount& frameCount) const
{
    return _jitterBuffer.GetFrameStatistics(frameCount.numDeltaFrames,
                                            frameCount.numKeyFrames);
}

WebRtc_UWord32 VCMReceiver::DiscardedPackets() const {
  return _jitterBuffer.DiscardedPackets();
}

void
VCMReceiver::SetNackMode(VCMNackMode nackMode)
{
    CriticalSectionScoped cs(_critSect);
    // Default to always having NACK enabled in hybrid mode.
    _jitterBuffer.SetNackMode(nackMode, kLowRttNackMs, -1);
    if (!_master)
    {
        _state = kPassive; // The dual decoder defaults to passive
    }
}

VCMNackMode
VCMReceiver::NackMode() const
{
    CriticalSectionScoped cs(_critSect);
    return _jitterBuffer.GetNackMode();
}

VCMNackStatus
VCMReceiver::NackList(WebRtc_UWord16* nackList, WebRtc_UWord16& size)
{
    bool extended = false;
    WebRtc_UWord16 nackListSize = 0;
    WebRtc_UWord16* internalNackList = _jitterBuffer.GetNackList(nackListSize, extended);
    if (internalNackList == NULL && nackListSize == 0xffff)
    {
        // This combination is used to trigger key frame requests.
        size = 0;
        return kNackKeyFrameRequest;
    }
    if (nackListSize > size)
    {
        size = nackListSize;
        return kNackNeedMoreMemory;
    }
    if (internalNackList != NULL && nackListSize > 0) {
      memcpy(nackList, internalNackList, nackListSize * sizeof(WebRtc_UWord16));
    }
    size = nackListSize;
    return kNackOk;
}

// Decide whether we should change decoder state. This should be done if the dual decoder
// has caught up with the decoder decoding with packet losses.
bool
VCMReceiver::DualDecoderCaughtUp(VCMEncodedFrame* dualFrame, VCMReceiver& dualReceiver) const
{
    if (dualFrame == NULL)
    {
        return false;
    }
    if (_jitterBuffer.LastDecodedTimestamp() == dualFrame->TimeStamp())
    {
        dualReceiver.UpdateState(kWaitForPrimaryDecode);
        return true;
    }
    return false;
}

void
VCMReceiver::CopyJitterBufferStateFromReceiver(const VCMReceiver& receiver)
{
    _jitterBuffer.CopyFrom(receiver._jitterBuffer);
}

VCMReceiverState
VCMReceiver::State() const
{
    CriticalSectionScoped cs(_critSect);
    return _state;
}

void
VCMReceiver::UpdateState(VCMReceiverState newState)
{
    CriticalSectionScoped cs(_critSect);
    assert(!(_state == kPassive && newState == kWaitForPrimaryDecode));
//    assert(!(_state == kReceiving && newState == kPassive));
    _state = newState;
}

void
VCMReceiver::UpdateState(VCMEncodedFrame& frame)
{
    if (_jitterBuffer.GetNackMode() == kNoNack)
    {
        // Dual decoder mode has not been enabled.
        return;
    }
    // Update the dual receiver state
    if (frame.Complete() && frame.FrameType() == kVideoFrameKey)
    {
        UpdateState(kPassive);
    }
    if (State() == kWaitForPrimaryDecode &&
        frame.Complete() && !frame.MissingFrame())
    {
        UpdateState(kPassive);
    }
    if (frame.MissingFrame() || !frame.Complete())
    {
        // State was corrupted, enable dual receiver.
        UpdateState(kReceiving);
    }
}

}
<commit_msg>Fix potential VCMReceiver crash.<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 "modules/video_coding/main/source/receiver.h"

#include <assert.h>

#include "modules/video_coding/main/interface/video_coding.h"
#include "modules/video_coding/main/source/encoded_frame.h"
#include "modules/video_coding/main/source/internal_defines.h"
#include "modules/video_coding/main/source/media_opt_util.h"
#include "modules/video_coding/main/source/tick_time_base.h"
#include "system_wrappers/interface/trace.h"

namespace webrtc {

VCMReceiver::VCMReceiver(VCMTiming& timing,
                         TickTimeBase* clock,
                         WebRtc_Word32 vcmId,
                         WebRtc_Word32 receiverId,
                         bool master)
    : _critSect(CriticalSectionWrapper::CreateCriticalSection()),
      _vcmId(vcmId),
      _clock(clock),
      _receiverId(receiverId),
      _master(master),
      _jitterBuffer(_clock, vcmId, receiverId, master),
      _timing(timing),
      _renderWaitEvent(*new VCMEvent()),
      _state(kPassive) {}

VCMReceiver::~VCMReceiver()
{
    _renderWaitEvent.Set();
    delete &_renderWaitEvent;
    delete _critSect;
}

void
VCMReceiver::Reset()
{
    CriticalSectionScoped cs(_critSect);
    if (!_jitterBuffer.Running())
    {
        _jitterBuffer.Start();
    }
    else
    {
        _jitterBuffer.Flush();
    }
    _renderWaitEvent.Reset();
    if (_master)
    {
        _state = kReceiving;
    }
    else
    {
        _state = kPassive;
    }
}

WebRtc_Word32
VCMReceiver::Initialize()
{
    CriticalSectionScoped cs(_critSect);
    Reset();
    if (!_master)
    {
        SetNackMode(kNoNack);
    }
    return VCM_OK;
}

void VCMReceiver::UpdateRtt(WebRtc_UWord32 rtt)
{
    _jitterBuffer.UpdateRtt(rtt);
}

WebRtc_Word32
VCMReceiver::InsertPacket(const VCMPacket& packet,
                          WebRtc_UWord16 frameWidth,
                          WebRtc_UWord16 frameHeight)
{
    // Find an empty frame
    VCMEncodedFrame *buffer = NULL;
    const WebRtc_Word32 error = _jitterBuffer.GetFrame(packet, buffer);
    if (error == VCM_OLD_PACKET_ERROR)
    {
        return VCM_OK;
    }
    else if (error != VCM_OK)
    {
        return error;
    }
    assert(buffer);
    {
        CriticalSectionScoped cs(_critSect);

        if (frameWidth && frameHeight)
        {
            buffer->SetEncodedSize(static_cast<WebRtc_UWord32>(frameWidth),
                                   static_cast<WebRtc_UWord32>(frameHeight));
        }

        if (_master)
        {
            // Only trace the primary receiver to make it possible
            // to parse and plot the trace file.
            WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
                         VCMId(_vcmId, _receiverId),
                         "Packet seqNo %u of frame %u at %u",
                         packet.seqNum, packet.timestamp,
                         MaskWord64ToUWord32(_clock->MillisecondTimestamp()));
        }

        const WebRtc_Word64 nowMs = _clock->MillisecondTimestamp();

        WebRtc_Word64 renderTimeMs = _timing.RenderTimeMs(packet.timestamp, nowMs);

        if (renderTimeMs < 0)
        {
            // Render time error. Assume that this is due to some change in
            // the incoming video stream and reset the JB and the timing.
            _jitterBuffer.Flush();
            _timing.Reset(_clock->MillisecondTimestamp());
            return VCM_FLUSH_INDICATOR;
        }
        else if (renderTimeMs < nowMs - kMaxVideoDelayMs)
        {
            WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId),
                "This frame should have been rendered more than %u ms ago."
                "Flushing jitter buffer and resetting timing.", kMaxVideoDelayMs);
            _jitterBuffer.Flush();
            _timing.Reset(_clock->MillisecondTimestamp());
            return VCM_FLUSH_INDICATOR;
        }
        else if (_timing.TargetVideoDelay() > kMaxVideoDelayMs)
        {
            WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId),
                "More than %u ms target delay. Flushing jitter buffer and resetting timing.",
                kMaxVideoDelayMs);
            _jitterBuffer.Flush();
            _timing.Reset(_clock->MillisecondTimestamp());
            return VCM_FLUSH_INDICATOR;
        }

        // First packet received belonging to this frame.
        if (buffer->Length() == 0)
        {
            const WebRtc_Word64 nowMs = _clock->MillisecondTimestamp();
            if (_master)
            {
                // Only trace the primary receiver to make it possible to parse and plot the trace file.
                WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, VCMId(_vcmId, _receiverId),
                           "First packet of frame %u at %u", packet.timestamp,
                           MaskWord64ToUWord32(nowMs));
            }
            renderTimeMs = _timing.RenderTimeMs(packet.timestamp, nowMs);
            if (renderTimeMs >= 0)
            {
                buffer->SetRenderTime(renderTimeMs);
            }
            else
            {
                buffer->SetRenderTime(nowMs);
            }
        }

        // Insert packet into the jitter buffer
        // both media and empty packets
        const VCMFrameBufferEnum
        ret = _jitterBuffer.InsertPacket(buffer, packet);
        if (ret == kFlushIndicator) {
          return VCM_FLUSH_INDICATOR;
        } else if (ret < 0) {
          WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding,
                       VCMId(_vcmId, _receiverId),
                       "Error inserting packet seqNo=%u, timeStamp=%u",
                       packet.seqNum, packet.timestamp);
          return VCM_JITTER_BUFFER_ERROR;
        }
    }
    return VCM_OK;
}

VCMEncodedFrame* VCMReceiver::FrameForDecoding(WebRtc_UWord16 maxWaitTimeMs,
                                               WebRtc_Word64& nextRenderTimeMs,
                                               bool renderTiming,
                                               VCMReceiver* dualReceiver)
{
    // No need to enter the critical section here since the jitter buffer
    // is thread-safe.
    FrameType incomingFrameType = kVideoFrameDelta;
    nextRenderTimeMs = -1;
    const WebRtc_Word64 startTimeMs = _clock->MillisecondTimestamp();
    WebRtc_Word64 ret = _jitterBuffer.GetNextTimeStamp(maxWaitTimeMs,
                                                       incomingFrameType,
                                                       nextRenderTimeMs);
    if (ret < 0)
    {
        // No timestamp in jitter buffer at the moment
        return NULL;
    }
    const WebRtc_UWord32 timeStamp = static_cast<WebRtc_UWord32>(ret);

    // Update the timing
    _timing.SetRequiredDelay(_jitterBuffer.GetEstimatedJitterMS());
    _timing.UpdateCurrentDelay(timeStamp);

    const WebRtc_Word32 tempWaitTime = maxWaitTimeMs -
            static_cast<WebRtc_Word32>(_clock->MillisecondTimestamp() - startTimeMs);
    WebRtc_UWord16 newMaxWaitTime = static_cast<WebRtc_UWord16>(VCM_MAX(tempWaitTime, 0));

    VCMEncodedFrame* frame = NULL;

    if (renderTiming)
    {
        frame = FrameForDecoding(newMaxWaitTime, nextRenderTimeMs, dualReceiver);
    }
    else
    {
        frame = FrameForRendering(newMaxWaitTime, nextRenderTimeMs, dualReceiver);
    }

    if (frame != NULL)
    {
        bool retransmitted = false;
        const WebRtc_Word64 lastPacketTimeMs =
                _jitterBuffer.LastPacketTime(frame, retransmitted);
        if (lastPacketTimeMs >= 0 && !retransmitted)
        {
            // We don't want to include timestamps which have suffered from retransmission
            // here, since we compensate with extra retransmission delay within
            // the jitter estimate.
            _timing.IncomingTimestamp(timeStamp, lastPacketTimeMs);
        }
        if (dualReceiver != NULL)
        {
            dualReceiver->UpdateState(*frame);
        }
    }
    return frame;
}

VCMEncodedFrame*
VCMReceiver::FrameForDecoding(WebRtc_UWord16 maxWaitTimeMs,
                              WebRtc_Word64 nextRenderTimeMs,
                              VCMReceiver* dualReceiver)
{
    // How long can we wait until we must decode the next frame
    WebRtc_UWord32 waitTimeMs = _timing.MaxWaitingTime(nextRenderTimeMs,
                                          _clock->MillisecondTimestamp());

    // Try to get a complete frame from the jitter buffer
    VCMEncodedFrame* frame = _jitterBuffer.GetCompleteFrameForDecoding(0);

    if (frame == NULL && maxWaitTimeMs == 0 && waitTimeMs > 0)
    {
        // If we're not allowed to wait for frames to get complete we must
        // calculate if it's time to decode, and if it's not we will just return
        // for now.
        return NULL;
    }

    if (frame == NULL && VCM_MIN(waitTimeMs, maxWaitTimeMs) == 0)
    {
        // No time to wait for a complete frame,
        // check if we have an incomplete
        const bool dualReceiverEnabledAndPassive = (dualReceiver != NULL &&
                                     dualReceiver->State() == kPassive &&
                                     dualReceiver->NackMode() == kNackInfinite);
        if (dualReceiverEnabledAndPassive &&
            !_jitterBuffer.CompleteSequenceWithNextFrame())
        {
            // Jitter buffer state might get corrupt with this frame.
            dualReceiver->CopyJitterBufferStateFromReceiver(*this);
            frame = _jitterBuffer.GetFrameForDecoding();
            assert(frame);
        } else {
            frame = _jitterBuffer.GetFrameForDecoding();
        }
    }
    if (frame == NULL)
    {
        // Wait for a complete frame
        frame = _jitterBuffer.GetCompleteFrameForDecoding(maxWaitTimeMs);
    }
    if (frame == NULL)
    {
        // Get an incomplete frame
        if (_timing.MaxWaitingTime(nextRenderTimeMs,
                                   _clock->MillisecondTimestamp()) > 0)
        {
            // Still time to wait for a complete frame
            return NULL;
        }

        // No time left to wait, we must decode this frame now.
        const bool dualReceiverEnabledAndPassive = (dualReceiver != NULL &&
                                     dualReceiver->State() == kPassive &&
                                     dualReceiver->NackMode() == kNackInfinite);
        if (dualReceiverEnabledAndPassive &&
            !_jitterBuffer.CompleteSequenceWithNextFrame())
        {
            // Jitter buffer state might get corrupt with this frame.
            dualReceiver->CopyJitterBufferStateFromReceiver(*this);
        }

        frame = _jitterBuffer.GetFrameForDecoding();
    }
    return frame;
}

VCMEncodedFrame*
VCMReceiver::FrameForRendering(WebRtc_UWord16 maxWaitTimeMs,
                               WebRtc_Word64 nextRenderTimeMs,
                               VCMReceiver* dualReceiver)
{
    // How long MUST we wait until we must decode the next frame. This is different for the case
    // where we have a renderer which can render at a specified time. Here we must wait as long
    // as possible before giving the frame to the decoder, which will render the frame as soon
    // as it has been decoded.
    WebRtc_UWord32 waitTimeMs = _timing.MaxWaitingTime(nextRenderTimeMs,
                                                       _clock->MillisecondTimestamp());
    if (maxWaitTimeMs < waitTimeMs)
    {
        // If we're not allowed to wait until the frame is supposed to be rendered
        // we will have to return NULL for now.
        return NULL;
    }
    // Wait until it's time to render
    _renderWaitEvent.Wait(waitTimeMs);

    // Get a complete frame if possible
    VCMEncodedFrame* frame = _jitterBuffer.GetCompleteFrameForDecoding(0);

    if (frame == NULL)
    {
        // Get an incomplete frame
        const bool dualReceiverEnabledAndPassive = dualReceiver != NULL &&
                                                   dualReceiver->State() == kPassive &&
                                                   dualReceiver->NackMode() == kNackInfinite;
        if (dualReceiverEnabledAndPassive && !_jitterBuffer.CompleteSequenceWithNextFrame())
        {
            // Jitter buffer state might get corrupt with this frame.
            dualReceiver->CopyJitterBufferStateFromReceiver(*this);
        }

        frame = _jitterBuffer.GetFrameForDecoding();
    }
    return frame;
}

void
VCMReceiver::ReleaseFrame(VCMEncodedFrame* frame)
{
    _jitterBuffer.ReleaseFrame(frame);
}

WebRtc_Word32
VCMReceiver::ReceiveStatistics(WebRtc_UWord32& bitRate, WebRtc_UWord32& frameRate)
{
    const WebRtc_Word32 ret = _jitterBuffer.GetUpdate(frameRate, bitRate);
    bitRate /= 1000; // Should be in kbps
    return ret;
}

WebRtc_Word32
VCMReceiver::ReceivedFrameCount(VCMFrameCount& frameCount) const
{
    return _jitterBuffer.GetFrameStatistics(frameCount.numDeltaFrames,
                                            frameCount.numKeyFrames);
}

WebRtc_UWord32 VCMReceiver::DiscardedPackets() const {
  return _jitterBuffer.DiscardedPackets();
}

void
VCMReceiver::SetNackMode(VCMNackMode nackMode)
{
    CriticalSectionScoped cs(_critSect);
    // Default to always having NACK enabled in hybrid mode.
    _jitterBuffer.SetNackMode(nackMode, kLowRttNackMs, -1);
    if (!_master)
    {
        _state = kPassive; // The dual decoder defaults to passive
    }
}

VCMNackMode
VCMReceiver::NackMode() const
{
    CriticalSectionScoped cs(_critSect);
    return _jitterBuffer.GetNackMode();
}

VCMNackStatus
VCMReceiver::NackList(WebRtc_UWord16* nackList, WebRtc_UWord16& size)
{
    bool extended = false;
    WebRtc_UWord16 nackListSize = 0;
    WebRtc_UWord16* internalNackList = _jitterBuffer.GetNackList(nackListSize, extended);
    if (internalNackList == NULL && nackListSize == 0xffff)
    {
        // This combination is used to trigger key frame requests.
        size = 0;
        return kNackKeyFrameRequest;
    }
    if (nackListSize > size)
    {
        size = nackListSize;
        return kNackNeedMoreMemory;
    }
    if (internalNackList != NULL && nackListSize > 0) {
      memcpy(nackList, internalNackList, nackListSize * sizeof(WebRtc_UWord16));
    }
    size = nackListSize;
    return kNackOk;
}

// Decide whether we should change decoder state. This should be done if the dual decoder
// has caught up with the decoder decoding with packet losses.
bool
VCMReceiver::DualDecoderCaughtUp(VCMEncodedFrame* dualFrame, VCMReceiver& dualReceiver) const
{
    if (dualFrame == NULL)
    {
        return false;
    }
    if (_jitterBuffer.LastDecodedTimestamp() == dualFrame->TimeStamp())
    {
        dualReceiver.UpdateState(kWaitForPrimaryDecode);
        return true;
    }
    return false;
}

void
VCMReceiver::CopyJitterBufferStateFromReceiver(const VCMReceiver& receiver)
{
    _jitterBuffer.CopyFrom(receiver._jitterBuffer);
}

VCMReceiverState
VCMReceiver::State() const
{
    CriticalSectionScoped cs(_critSect);
    return _state;
}

void
VCMReceiver::UpdateState(VCMReceiverState newState)
{
    CriticalSectionScoped cs(_critSect);
    assert(!(_state == kPassive && newState == kWaitForPrimaryDecode));
//    assert(!(_state == kReceiving && newState == kPassive));
    _state = newState;
}

void
VCMReceiver::UpdateState(VCMEncodedFrame& frame)
{
    if (_jitterBuffer.GetNackMode() == kNoNack)
    {
        // Dual decoder mode has not been enabled.
        return;
    }
    // Update the dual receiver state
    if (frame.Complete() && frame.FrameType() == kVideoFrameKey)
    {
        UpdateState(kPassive);
    }
    if (State() == kWaitForPrimaryDecode &&
        frame.Complete() && !frame.MissingFrame())
    {
        UpdateState(kPassive);
    }
    if (frame.MissingFrame() || !frame.Complete())
    {
        // State was corrupted, enable dual receiver.
        UpdateState(kReceiving);
    }
}

}
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -std=c++11 -triple armv7-none-eabi -emit-llvm -o - %s | FileCheck %s

struct X {
  X();
  X(const X&);
  X(const char*);
  ~X();
};

struct Y {
  int i;
  X x;
};

// CHECK-LABEL: define i32 @_Z1fv()
int f() {
  // CHECK: [[LVALUE:%[a-z0-9.]+]] = alloca
  // CHECK-NEXT: [[I:%[a-z0-9]+]] = getelementptr inbounds {{.*}}, {{.*}}* [[LVALUE]], i32 0, i32 0
  // CHECK-NEXT: store i32 17, i32* [[I]]
  // CHECK-NEXT: [[X:%[a-z0-9]+]] = getelementptr inbounds {{.*}} [[LVALUE]], i32 0, i32 1
  // CHECK-NEXT: call %struct.X* @_ZN1XC1EPKc({{.*}}[[X]]
  // CHECK-NEXT: [[I:%[a-z0-9]+]] = getelementptr inbounds {{.*}} [[LVALUE]], i32 0, i32 0
  // CHECK-NEXT: [[RESULT:%[a-z0-9]+]] = load i32, i32*
  // CHECK-NEXT: call %struct.Y* @_ZN1YD1Ev
  // CHECK-NEXT: ret i32 [[RESULT]]
  return ((Y){17, "seventeen"}).i;
}

// CHECK-LABEL: define i32 @_Z1gv()
int g() {
  // CHECK: store [2 x i32]* @{{.*}}, [2 x i32]** [[V:%[a-z0-9.]+]]
  const int (&v)[2] = (int [2]) {1,2};

  // CHECK: [[A:%[a-z0-9.]+]] = load [2 x i32]*, [2 x i32]** [[V]]
  // CHECK-NEXT: [[A0ADDR:%[a-z0-9.]+]] = getelementptr inbounds [2 x i32], [2 x i32]* [[A]], i32 0, {{.*}} 0
  // CHECK-NEXT: [[A0:%[a-z0-9.]+]] = load i32, i32* [[A0ADDR]]
  // CHECK-NEXT: ret i32 [[A0]]
  return v[0];
}

struct Z { int i[3]; };
int *p = (Z){ {1, 2, 3} }.i;
// CHECK: define {{.*}}__cxx_global_var_init()
// CHECK: store i32* getelementptr inbounds (%struct.Z, %struct.Z* @.compoundliteral, i32 0, i32 0, i32 0), i32** @p

int *PR21912_1 = (int []){};
// CHECK-LABEL: define {{.*}}__cxx_global_var_init1()
// CHECK: store i32* getelementptr inbounds ([0 x i32], [0 x i32]* @.compoundliteral2, i32 0, i32 0), i32** @PR21912_1

union PR21912Ty {
  long long l;
  double d;
};
union PR21912Ty *PR21912_2 = (union PR21912Ty[]){{.d = 2.0}, {.l = 3}};
// CHECK-LABEL: define {{.*}}__cxx_global_var_init3()
// CHECK: store %union.PR21912Ty* getelementptr inbounds ([2 x %union.PR21912Ty], [2 x %union.PR21912Ty]* bitcast (<{ { double }, %union.PR21912Ty }>* @.compoundliteral4 to [2 x %union.PR21912Ty]*), i32 0, i32 0), %union.PR21912Ty** @PR21912_2
<commit_msg>Update test case for r234543.<commit_after>// RUN: %clang_cc1 -std=c++11 -triple armv7-none-eabi -emit-llvm -o - %s | FileCheck %s

struct X {
  X();
  X(const X&);
  X(const char*);
  ~X();
};

struct Y {
  int i;
  X x;
};

// CHECK-LABEL: define i32 @_Z1fv()
int f() {
  // CHECK: [[LVALUE:%[a-z0-9.]+]] = alloca
  // CHECK-NEXT: [[I:%[a-z0-9]+]] = getelementptr inbounds {{.*}}, {{.*}}* [[LVALUE]], i32 0, i32 0
  // CHECK-NEXT: store i32 17, i32* [[I]]
  // CHECK-NEXT: [[X:%[a-z0-9]+]] = getelementptr inbounds {{.*}} [[LVALUE]], i32 0, i32 1
  // CHECK-NEXT: call %struct.X* @_ZN1XC1EPKc({{.*}}[[X]]
  // CHECK-NEXT: [[I:%[a-z0-9]+]] = getelementptr inbounds {{.*}} [[LVALUE]], i32 0, i32 0
  // CHECK-NEXT: [[RESULT:%[a-z0-9]+]] = load i32, i32*
  // CHECK-NEXT: call %struct.Y* @_ZN1YD1Ev
  // CHECK-NEXT: ret i32 [[RESULT]]
  return ((Y){17, "seventeen"}).i;
}

// CHECK-LABEL: define i32 @_Z1gv()
int g() {
  // CHECK: store [2 x i32]* %{{[a-z0-9.]+}}, [2 x i32]** [[V:%[a-z0-9.]+]]
  const int (&v)[2] = (int [2]) {1,2};

  // CHECK: [[A:%[a-z0-9.]+]] = load [2 x i32]*, [2 x i32]** [[V]]
  // CHECK-NEXT: [[A0ADDR:%[a-z0-9.]+]] = getelementptr inbounds [2 x i32], [2 x i32]* [[A]], i32 0, {{.*}} 0
  // CHECK-NEXT: [[A0:%[a-z0-9.]+]] = load i32, i32* [[A0ADDR]]
  // CHECK-NEXT: ret i32 [[A0]]
  return v[0];
}

struct Z { int i[3]; };
int *p = (Z){ {1, 2, 3} }.i;
// CHECK: define {{.*}}__cxx_global_var_init()
// CHECK: store i32* getelementptr inbounds (%struct.Z, %struct.Z* @.compoundliteral, i32 0, i32 0, i32 0), i32** @p

int *PR21912_1 = (int []){};
// CHECK-LABEL: define {{.*}}__cxx_global_var_init1()
// CHECK: store i32* getelementptr inbounds ([0 x i32], [0 x i32]* @.compoundliteral2, i32 0, i32 0), i32** @PR21912_1

union PR21912Ty {
  long long l;
  double d;
};
union PR21912Ty *PR21912_2 = (union PR21912Ty[]){{.d = 2.0}, {.l = 3}};
// CHECK-LABEL: define {{.*}}__cxx_global_var_init3()
// CHECK: store %union.PR21912Ty* getelementptr inbounds ([2 x %union.PR21912Ty], [2 x %union.PR21912Ty]* bitcast (<{ { double }, %union.PR21912Ty }>* @.compoundliteral4 to [2 x %union.PR21912Ty]*), i32 0, i32 0), %union.PR21912Ty** @PR21912_2
<|endoftext|>