<commit_before>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbGenericRSResampleImageFilter.h"
#include "otbBCOInterpolateImageFunction.h"

// Elevation handler
#include "otbWrapperElevationParametersHandler.h"

namespace otb
{

namespace Wrapper
{

class Superimpose : public Application
{
public:
  /** Standard class typedefs. */
  typedef Superimpose         Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(Superimpose, Application);

  typedef unsigned short int PixelType;

  typedef otb::BCOInterpolateImageFunction<UInt16VectorImageType>   InterpolatorType;
  typedef otb::GenericRSResampleImageFilter<UInt16VectorImageType,
                                            UInt16VectorImageType>  ResamplerType;

private:
  void DoInit()
  {
    SetName("Superimpose");
    SetDescription("Using available image metadata, project one image onto another one");

    // Documentation
    SetDocName("Superimpose sensor");
    SetDocLongDescription("This application performs the projection of an image into the geometry of another one.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");

    AddDocTag(Tags::Geometry);
    AddDocTag("Superimposition");

    AddParameter(ParameterType_InputImage,   "inr",   "Reference input");
    SetParameterDescription("inr","The input reference image.");
    AddParameter(ParameterType_InputImage,   "inm",   "The image to reproject");
    SetParameterDescription("inm","The image to reproject into the geometry of the reference input.");

    // Elevation
    ElevationParametersHandler::AddElevationParameters(this, "elev");

    AddParameter(ParameterType_Float,        "lms",   "Spacing of the deformation field");
    SetParameterDescription("lms","Generate a coarser deformation field with the given spacing");
    SetDefaultParameterFloat("lms", 4.);

    AddParameter(ParameterType_OutputImage,  "out",   "Output image");
    SetParameterDescription("out","Output reprojected image.");
    AddRAMParameter();

    MandatoryOff("lms");

    // Doc example parameter settings
    SetDocExampleParameterValue("inr", "QB_Toulouse_Ortho_PAN.tif");
    SetDocExampleParameterValue("inm", "QB_Toulouse_Ortho_XS.tif");
    SetDocExampleParameterValue("out", "SuperimposedXS_to_PAN.tif");
  }

  void DoUpdateParameters()
  {
    // Nothing to do here : all parameters are independent
  }

  void DoExecute()
  {
    // Get the inputs
    UInt16VectorImageType* refImage = GetParameterUInt16VectorImage("inr");
    UInt16VectorImageType* movingImage = GetParameterUInt16VectorImage("inm");

    // Resample filter
    m_Resampler    = ResamplerType::New();
    m_Interpolator = InterpolatorType::New();
    m_Resampler->SetInterpolator(m_Interpolator);

    // Setup the DEM Handler
    otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev");

    // Set up output image informations
    UInt16VectorImageType::SpacingType spacing = refImage->GetSpacing();
    UInt16VectorImageType::IndexType   start   = refImage->GetLargestPossibleRegion().GetIndex();
    UInt16VectorImageType::SizeType    size    = refImage->GetLargestPossibleRegion().GetSize();
    UInt16VectorImageType::PointType   origin  = refImage->GetOrigin();

    if(IsParameterEnabled("lms"))
      {
      float defScalarSpacing = GetParameterFloat("lms");
      std::cout<<"Generating coarse deformation field (spacing="<<defScalarSpacing<<")"<<std::endl;
      UInt16VectorImageType::SpacingType defSpacing;

      defSpacing[0] = defScalarSpacing;
      defSpacing[1] = defScalarSpacing;

      m_Resampler->SetDeformationFieldSpacing(defSpacing);
      }

    UInt16VectorImageType::PixelType defaultValue;
    itk::PixelBuilder<UInt16VectorImageType::PixelType>::Zero(defaultValue,
                                                              movingImage->GetNumberOfComponentsPerPixel());

    m_Resampler->SetInput(movingImage);
    m_Resampler->SetOutputOrigin(origin);
    m_Resampler->SetOutputSpacing(spacing);
    m_Resampler->SetOutputSize(size);
    m_Resampler->SetOutputStartIndex(start);
    m_Resampler->SetOutputKeywordList(refImage->GetImageKeywordlist());
    m_Resampler->SetOutputProjectionRef(refImage->GetProjectionRef());
    m_Resampler->SetEdgePaddingValue(defaultValue);

    // Set the output image
    SetParameterOutputImage("out", m_Resampler->GetOutput());
  }

  ResamplerType::Pointer           m_Resampler;
  InterpolatorType::Pointer        m_Interpolator;
};

} // end namespace Wrapper
} // end namespace otb

OTB_APPLICATION_EXPORT(otb::Wrapper::Superimpose)

<commit_msg>BUG: Mantis 619: fix Superimpose with ortho images<commit_after>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbGenericRSResampleImageFilter.h"
#include "otbBCOInterpolateImageFunction.h"

// Elevation handler
#include "otbWrapperElevationParametersHandler.h"

namespace otb
{

namespace Wrapper
{

class Superimpose : public Application
{
public:
  /** Standard class typedefs. */
  typedef Superimpose         Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(Superimpose, Application);

  typedef unsigned short int PixelType;

  typedef otb::BCOInterpolateImageFunction<FloatVectorImageType>   InterpolatorType;
  typedef otb::GenericRSResampleImageFilter<FloatVectorImageType,
                                            FloatVectorImageType>  ResamplerType;

private:
  void DoInit()
  {
    SetName("Superimpose");
    SetDescription("Using available image metadata, project one image onto another one");

    // Documentation
    SetDocName("Superimpose sensor");
    SetDocLongDescription("This application performs the projection of an image into the geometry of another one.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");

    AddDocTag(Tags::Geometry);
    AddDocTag("Superimposition");

    AddParameter(ParameterType_InputImage,   "inr",   "Reference input");
    SetParameterDescription("inr","The input reference image.");
    AddParameter(ParameterType_InputImage,   "inm",   "The image to reproject");
    SetParameterDescription("inm","The image to reproject into the geometry of the reference input.");

    // Elevation
    ElevationParametersHandler::AddElevationParameters(this, "elev");

    AddParameter(ParameterType_Float,        "lms",   "Spacing of the deformation field");
    SetParameterDescription("lms","Generate a coarser deformation field with the given spacing");
    SetDefaultParameterFloat("lms", 4.);

    AddParameter(ParameterType_OutputImage,  "out",   "Output image");
    SetParameterDescription("out","Output reprojected image.");
    AddRAMParameter();

    MandatoryOff("lms");

    // Doc example parameter settings
    SetDocExampleParameterValue("inr", "QB_Toulouse_Ortho_PAN.tif");
    SetDocExampleParameterValue("inm", "QB_Toulouse_Ortho_XS.tif");
    SetDocExampleParameterValue("out", "SuperimposedXS_to_PAN.tif");
  }

  void DoUpdateParameters()
  {
    // Nothing to do here : all parameters are independent
  }

  void DoExecute()
  {
    // Get the inputs
    FloatVectorImageType* refImage = GetParameterImage("inr");
    FloatVectorImageType* movingImage = GetParameterImage("inm");

    // Resample filter
    m_Resampler    = ResamplerType::New();
    m_Interpolator = InterpolatorType::New();
    m_Interpolator->SetRadius(2);
    m_Resampler->SetInterpolator(m_Interpolator);

    // Setup the DEM Handler
    otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev");

    // Set up output image informations
    FloatVectorImageType::SpacingType spacing = refImage->GetSpacing();
    FloatVectorImageType::IndexType   start   = refImage->GetLargestPossibleRegion().GetIndex();
    FloatVectorImageType::SizeType    size    = refImage->GetLargestPossibleRegion().GetSize();
    FloatVectorImageType::PointType   origin  = refImage->GetOrigin();

    if(IsParameterEnabled("lms"))
      {
      float defScalarSpacing = vcl_abs(GetParameterFloat("lms"));
      std::cout<<"Generating coarse deformation field (spacing="<<defScalarSpacing<<")"<<std::endl;
      FloatVectorImageType::SpacingType defSpacing;

      defSpacing[0] = defScalarSpacing;
      defSpacing[1] = defScalarSpacing;

      if (spacing[0]<0.0) defSpacing[0] *= -1.0;
      if (spacing[1]<0.0) defSpacing[1] *= -1.0;

      m_Resampler->SetDeformationFieldSpacing(defSpacing);
      }

    FloatVectorImageType::PixelType defaultValue;
    itk::PixelBuilder<FloatVectorImageType::PixelType>::Zero(defaultValue,
                                                              movingImage->GetNumberOfComponentsPerPixel());

    m_Resampler->SetInput(movingImage);
    m_Resampler->SetInputKeywordList(movingImage->GetImageKeywordlist());
    m_Resampler->SetInputProjectionRef(movingImage->GetProjectionRef());
    m_Resampler->SetOutputOrigin(origin);
    m_Resampler->SetOutputSpacing(spacing);
    m_Resampler->SetOutputSize(size);
    m_Resampler->SetOutputStartIndex(start);
    m_Resampler->SetOutputKeywordList(refImage->GetImageKeywordlist());
    m_Resampler->SetOutputProjectionRef(refImage->GetProjectionRef());
    m_Resampler->SetEdgePaddingValue(defaultValue);

    // Set the output image
    SetParameterOutputImage("out", m_Resampler->GetOutput());
  }

  ResamplerType::Pointer           m_Resampler;
  InterpolatorType::Pointer        m_Interpolator;
};

} // end namespace Wrapper
} // end namespace otb

OTB_APPLICATION_EXPORT(otb::Wrapper::Superimpose)

<|endoftext|>


<commit_before>#include <string>
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <assert.h>
#include <unistd.h>

#include "config.h"
#include "file_utils.hpp"
#include "NeighborJoining.hpp"
#include <ctime>
#include <time.h>
#include "log_utils.hpp"
#include "fnj_gengetopt.h"

#include "DataInputStream.hpp"
#include "DataOutputStream.hpp"
#include "TreeTextOutputStream.hpp"
#include "XmlOutputStream.hpp"
#include "Extrainfos.hpp"
#include "fileFormatSchema.hpp"
#include "PhylipDmInputStream.hpp"
#include "BinaryInputStream.hpp"

#ifdef WITH_LIBXML
#include "XmlInputStream.hpp"
#endif // WITH_LIBXML

using namespace std;

//
// Builds trees using the supplied distance methods.
// Each created tree is added to the tree2count map.
//

template<class T> void buildTrees(T &dm, tree2int_map &tree2count, std::vector<NJ_method> &methods, str2int_hashmap &name2id) {
	SequenceTree tree;
	for(size_t i=0; i<methods.size(); i++){
		computeNJTree(dm,tree,methods[i]);
		tree.makeCanonical(name2id);
		tree2int_map::iterator iter = tree2count.find(tree);
		if(iter!=tree2count.end())
			iter->second++;
		else
			tree2count[tree] = 1;
	}
}

int main (int argc, char **argv) {
    if(isatty(STDIN_FILENO) && argc==1) {
      cout<<"No input data or parameters. Use -h,--help for more information"<<endl;
      exit(EXIT_FAILURE);
    }
	gengetopt_args_info args_info;
	TRY_EXCEPTION();
	if (cmdline_parser (argc, argv, &args_info) != 0)
		exit(EXIT_FAILURE);
#ifndef WITH_LIBXML
	if ( args_info.input_format_arg == input_format_arg_xml ) {
		cerr << "The software was built with WITH_LIBXML=OFF. Please rebuild it if you want XML functionality." << endl;
		exit(EXIT_FAILURE);
	}
#endif // WITH_LIBXML
	if ( args_info.print_relaxng_input_given && args_info.print_relaxng_output_given ) {
		cerr << "error: --print-relaxng-input and --print-relaxng-output can not be used at the same time" << endl;
		exit(EXIT_FAILURE);
	}
	if ( args_info.print_relaxng_input_given ) {
		cout << fastphylo_distance_matrix_xml_relaxngstr << std::endl;
		exit(EXIT_SUCCESS);
	};
	if ( args_info.print_relaxng_output_given ) {
		cout << fastphylo_tree_count_xml_relaxngstr << std::endl;
		exit(EXIT_SUCCESS);
	};
	//----------------------------------------------
	// DISTANCE METHODS
	std::vector<NJ_method> methods;
	if( args_info.number_of_runs_given && args_info.input_format_arg == input_format_arg_xml ) {
		cerr << "error: --number-of-runs can not be used together with input format xml." << endl;
		exit(EXIT_FAILURE);
	}
	switch ( args_info.method_arg ) {
	case method_arg_NJ:
		methods.push_back(NJ);
		break;
	case method_arg_FNJ:
		methods.push_back(FNJ);
		break;
	case method_arg_BIONJ:
		methods.push_back(BIONJ);
		break;
	default:
		cerr << "error: method chosen not available" << endl;
		exit(EXIT_FAILURE);
	}
	bool printCounts = args_info.print_counts_flag;
	try {
		char * inputfilename = NULL;
		char * outputfilename = NULL;
		DataInputStream *istream;
		DataOutputStream *ostream;

		switch( args_info.inputs_num ) {
			case 0:
				break; /* inputfilename will be null and indicate stdin as input */
		case 1:
			inputfilename =  args_info.inputs[0];
			break;
		default: cerr << "Error: you can at most specify one input filename" << endl;
			exit(EXIT_FAILURE);
		}
		if( args_info.outfile_given )
			outputfilename = args_info.outfile_arg;
		switch ( args_info.input_format_arg ) {
			case input_format_arg_phylip:
				istream = new PhylipDmInputStream(inputfilename);
				break;
			case input_format_arg_binary: istream = new BinaryInputStream(inputfilename);
				break;
#ifdef WITH_LIBXML
			case input_format_arg_xml: istream = new XmlInputStream(inputfilename);
				break;
#endif // WITH_LIBXML
			default:
				exit(EXIT_FAILURE);
		}
		switch (args_info.output_format_arg) {
			case output_format_arg_newick:
				ostream = new TreeTextOutputStream(outputfilename);
				break;
			case output_format_arg_xml:
				ostream = new XmlOutputStream(outputfilename);
				break;
			default:
				exit(EXIT_FAILURE);
		}
		//printf("%d\n", args_info.input_format_arg);
		// THE DATA WE WILL PROCESS
		vector<Sequence> seqs;
		vector<std::string> names;
		vector<DNA_b128_String> b128seqs;
		Extrainfos extrainfos;
		bool latestReadSuccessful = true;
		vector<string> speciesnames;
		readstatus status;
		int run = 0;
		status = END_OF_RUN;

		while (status == END_OF_RUN && (args_info.input_format_arg == input_format_arg_xml || run<args_info.number_of_runs_arg)) {
			string runId("");
			run++;
			tree2int_map tree2count((size_t)(args_info.bootstraps_arg * 1.3));
			str2int_hashmap name2id;
			if (args_info.input_format_arg==input_format_arg_binary) {
				StrFloMatrix dm;
				for (int runNo=1; (status = istream->readDM(dm, names, runId, extrainfos))==DM_READ; runNo++) {
					if (args_info.analyze_run_number_given) {
						if (runNo<args_info.analyze_run_number_arg)
							continue;
						if (runNo>args_info.analyze_run_number_arg) {
							status=END_OF_RUN;
							break;
							}
						}
					for(size_t namei=0; namei<dm.getSize(); namei++)
						name2id[dm.getIdentifier(namei)] = namei;
					buildTrees(dm, tree2count, methods,name2id);
				}
			}
			else {
				StrDblMatrix dm;
				for (int runNo=1; (status = istream->readDM(dm, names, runId, extrainfos))==DM_READ; runNo++) {
					if (args_info.analyze_run_number_given) {
						if (runNo<args_info.analyze_run_number_arg)
							continue;
						if (runNo>args_info.analyze_run_number_arg) {
							status=END_OF_RUN;
							break;
							}
						}
					for(size_t namei=0; namei<dm.getSize(); namei++)
						name2id[dm.getIdentifier(namei)] = namei;
					buildTrees(dm, tree2count, methods,name2id);
				}
			}
			if (status==END_OF_RUN)
				ostream->print(tree2count,printCounts, runId, names, extrainfos);
			if (args_info.analyze_run_number_given)
				break;
		}//end run loop
		delete ostream;
		delete istream;
	}
	catch(...){
		throw;
	}
	CATCH_EXCEPTION();
	cmdline_parser_free(&args_info);
	return 0;
}
<commit_msg>Spiteful indent fix<commit_after>#include <string>
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <assert.h>
#include <unistd.h>

#include "config.h"
#include "file_utils.hpp"
#include "NeighborJoining.hpp"
#include <ctime>
#include <time.h>
#include "log_utils.hpp"
#include "fnj_gengetopt.h"

#include "DataInputStream.hpp"
#include "DataOutputStream.hpp"
#include "TreeTextOutputStream.hpp"
#include "XmlOutputStream.hpp"
#include "Extrainfos.hpp"
#include "fileFormatSchema.hpp"
#include "PhylipDmInputStream.hpp"
#include "BinaryInputStream.hpp"

#ifdef WITH_LIBXML
#include "XmlInputStream.hpp"
#endif // WITH_LIBXML

using namespace std;

//
// Builds trees using the supplied distance methods.
// Each created tree is added to the tree2count map.
//

template<class T> void buildTrees(T &dm, tree2int_map &tree2count, std::vector<NJ_method> &methods, str2int_hashmap &name2id) {
	SequenceTree tree;

	for(size_t i=0; i<methods.size(); i++){
		computeNJTree(dm,tree,methods[i]);
		tree.makeCanonical(name2id);
		tree2int_map::iterator iter = tree2count.find(tree);
		if(iter!=tree2count.end())
			iter->second++;
		else
			tree2count[tree] = 1;
	}
}

int main (int argc, char **argv) {
    if(isatty(STDIN_FILENO) && argc==1) {
      cout<<"No input data or parameters. Use -h,--help for more information"<<endl;
      exit(EXIT_FAILURE);
    }
	gengetopt_args_info args_info;
	TRY_EXCEPTION();
	if (cmdline_parser (argc, argv, &args_info) != 0)
		exit(EXIT_FAILURE);
#ifndef WITH_LIBXML
	if ( args_info.input_format_arg == input_format_arg_xml ) {
		cerr << "The software was built with WITH_LIBXML=OFF. Please rebuild it if you want XML functionality." << endl;
		exit(EXIT_FAILURE);
	}
#endif // WITH_LIBXML
	if ( args_info.print_relaxng_input_given && args_info.print_relaxng_output_given ) {
		cerr << "error: --print-relaxng-input and --print-relaxng-output can not be used at the same time" << endl;
		exit(EXIT_FAILURE);
	}
	if ( args_info.print_relaxng_input_given ) {
		cout << fastphylo_distance_matrix_xml_relaxngstr << std::endl;
		exit(EXIT_SUCCESS);
	};
	if ( args_info.print_relaxng_output_given ) {
		cout << fastphylo_tree_count_xml_relaxngstr << std::endl;
		exit(EXIT_SUCCESS);
	};
	//----------------------------------------------
	// DISTANCE METHODS
	std::vector<NJ_method> methods;
	if( args_info.number_of_runs_given && args_info.input_format_arg == input_format_arg_xml ) {
		cerr << "error: --number-of-runs can not be used together with input format xml." << endl;
		exit(EXIT_FAILURE);
	}
	switch ( args_info.method_arg ) {
	case method_arg_NJ:
		methods.push_back(NJ);
		break;
	case method_arg_FNJ:
		methods.push_back(FNJ);
		break;
	case method_arg_BIONJ:
		methods.push_back(BIONJ);
		break;
	default:
		cerr << "error: method chosen not available" << endl;
		exit(EXIT_FAILURE);
	}
	bool printCounts = args_info.print_counts_flag;
	try {
		char * inputfilename = NULL;
		char * outputfilename = NULL;
		DataInputStream *istream;
		DataOutputStream *ostream;

		switch( args_info.inputs_num ) {
			case 0:
				break; /* inputfilename will be null and indicate stdin as input */
		case 1:
			inputfilename =  args_info.inputs[0];
			break;
		default: cerr << "Error: you can at most specify one input filename" << endl;
			exit(EXIT_FAILURE);
		}
		if( args_info.outfile_given )
			outputfilename = args_info.outfile_arg;
		switch ( args_info.input_format_arg ) {
			case input_format_arg_phylip:
				istream = new PhylipDmInputStream(inputfilename);
				break;
			case input_format_arg_binary: istream = new BinaryInputStream(inputfilename);
				break;
#ifdef WITH_LIBXML
			case input_format_arg_xml: istream = new XmlInputStream(inputfilename);
				break;
#endif // WITH_LIBXML
			default:
				exit(EXIT_FAILURE);
		}
		switch (args_info.output_format_arg) {
			case output_format_arg_newick:
				ostream = new TreeTextOutputStream(outputfilename);
				break;
			case output_format_arg_xml:
				ostream = new XmlOutputStream(outputfilename);
				break;
			default:
				exit(EXIT_FAILURE);
		}
		//printf("%d\n", args_info.input_format_arg);
		// THE DATA WE WILL PROCESS
		vector<Sequence> seqs;
		vector<std::string> names;
		vector<DNA_b128_String> b128seqs;
		Extrainfos extrainfos;
		bool latestReadSuccessful = true;
		vector<string> speciesnames;
		readstatus status;
		int run = 0;
		status = END_OF_RUN;

		while (status == END_OF_RUN && (args_info.input_format_arg == input_format_arg_xml || run<args_info.number_of_runs_arg)) {
			string runId("");
			run++;
			tree2int_map tree2count((size_t)(args_info.bootstraps_arg * 1.3));
			str2int_hashmap name2id;
			if (args_info.input_format_arg==input_format_arg_binary) {
				StrFloMatrix dm;
				for (int runNo=1; (status = istream->readDM(dm, names, runId, extrainfos))==DM_READ; runNo++) {
					if (args_info.analyze_run_number_given) {
						if (runNo<args_info.analyze_run_number_arg)
							continue;
						if (runNo>args_info.analyze_run_number_arg) {
							status=END_OF_RUN;
							break;
							}
						}
					for(size_t namei=0; namei<dm.getSize(); namei++)
						name2id[dm.getIdentifier(namei)] = namei;
					buildTrees(dm, tree2count, methods,name2id);
				}
			}
			else {
				StrDblMatrix dm;
				for (int runNo=1; (status = istream->readDM(dm, names, runId, extrainfos))==DM_READ; runNo++) {
					if (args_info.analyze_run_number_given) {
						if (runNo<args_info.analyze_run_number_arg)
							continue;
						if (runNo>args_info.analyze_run_number_arg) {
							status=END_OF_RUN;
							break;
							}
						}
					for(size_t namei=0; namei<dm.getSize(); namei++) {
					     name2id[dm.getIdentifier(namei)] = namei;
					}
					buildTrees(dm, tree2count, methods,name2id);
				}
			}
			if (status==END_OF_RUN)
				ostream->print(tree2count,printCounts, runId, names, extrainfos);
			if (args_info.analyze_run_number_given)
				break;
		}//end run loop
		delete ostream;
		delete istream;
	}
	catch(...){
		throw;
	}
	CATCH_EXCEPTION();
	cmdline_parser_free(&args_info);
	return 0;
}
<|endoftext|>


<commit_before>/*
 * ExcaliburFrameDecoder.cpp
 *
 *  Created on: Jan 16th, 2017
 *      Author: Tim Nicholls, STFC Application Engineering Group
 */

#include "ExcaliburFrameDecoder.h"
#include "gettime.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <arpa/inet.h>

using namespace FrameReceiver;

ExcaliburFrameDecoder::ExcaliburFrameDecoder(LoggerPtr& logger,
        bool enable_packet_logging, unsigned int frame_timeout_ms) :
        FrameDecoder(logger, enable_packet_logging),
		current_frame_seen_(-1),
		current_frame_buffer_id_(-1),
		current_frame_buffer_(0),
		current_frame_header_(0),
		dropping_frame_data_(false),
		frame_timeout_ms_(frame_timeout_ms),
		frames_timedout_(0)
{
    current_packet_header_.reset(new uint8_t[sizeof(Excalibur::PacketHeader)]);
    dropped_frame_buffer_.reset(new uint8_t[Excalibur::total_frame_size]);

    if (enable_packet_logging_) {
        LOG4CXX_INFO(packet_logger_, "PktHdr: SourceAddress");
        LOG4CXX_INFO(packet_logger_, "PktHdr: |               SourcePort");
        LOG4CXX_INFO(packet_logger_, "PktHdr: |               |     DestinationPort");
        LOG4CXX_INFO(packet_logger_, "PktHdr: |               |     |      SubframeCounter  [4 Bytes]");
        LOG4CXX_INFO(packet_logger_, "PktHdr: |               |     |      |           PacketCounter&Flags [4 Bytes]");
        LOG4CXX_INFO(packet_logger_, "PktHdr: |               |     |      |           |");
        LOG4CXX_INFO(packet_logger_, "PktHdr: |-------------- |---- |----  |---------- |----------");
    }
}

ExcaliburFrameDecoder::~ExcaliburFrameDecoder()
{
}

const size_t ExcaliburFrameDecoder::get_frame_buffer_size(void) const
{
    return Excalibur::total_frame_size;
}

const size_t ExcaliburFrameDecoder::get_frame_header_size(void) const
{
    return sizeof(Excalibur::FrameHeader);
}

const size_t ExcaliburFrameDecoder::get_packet_header_size(void) const
{
    return sizeof(Excalibur::PacketHeader);
}

void* ExcaliburFrameDecoder::get_packet_header_buffer(void)
{
    return current_packet_header_.get();
}

void ExcaliburFrameDecoder::process_packet_header(size_t bytes_received, int port, struct sockaddr_in* from_addr)
{
    // Dump raw header if packet logging enabled
    if (enable_packet_logging_)
    {
        std::stringstream ss;
        uint8_t* hdr_ptr = reinterpret_cast<uint8_t*>(current_packet_header_.get());
        ss << "PktHdr: " << std::setw(15) << std::left << inet_ntoa(from_addr->sin_addr) << std::right << " "
           << std::setw(5) << ntohs(from_addr->sin_port) << " "
           << std::setw(5) << port << std::hex;
        for (unsigned int hdr_byte = 0; hdr_byte < sizeof(Excalibur::PacketHeader); hdr_byte++)
        {
            if (hdr_byte % 8 == 0) {
                ss << "  ";
            }
            ss << std::setw(2) << std::setfill('0') << (unsigned int)*hdr_ptr << " ";
            hdr_ptr++;
        }
        ss << std::dec;
        LOG4CXX_INFO(packet_logger_, ss.str());
    }

	uint32_t subframe_counter = get_subframe_counter();
	uint32_t packet_number = get_packet_number();
	bool start_of_frame_marker = get_start_of_frame_marker();
	bool end_of_frame_marker = get_end_of_frame_marker();

	uint32_t subframe_idx = subframe_counter % 2;
	uint32_t frame = subframe_counter / 2;

    LOG4CXX_DEBUG_LEVEL(3, logger_, "Got packet header:"
            << " packet: "   << packet_number << " subframe ctr: "<< subframe_counter << " idx:" << subframe_idx
			<< " SOF: " << (int)start_of_frame_marker << " EOF: " << (int)end_of_frame_marker
    );

    if (frame != current_frame_seen_)
    {
        current_frame_seen_ = frame;

    	if (frame_buffer_map_.count(current_frame_seen_) == 0)
    	{
    	    if (empty_buffer_queue_.empty())
            {
                current_frame_buffer_ = dropped_frame_buffer_.get();

    	        if (!dropping_frame_data_)
                {
                    LOG4CXX_ERROR(logger_, "First packet from frame " << current_frame_seen_ << " detected but no free buffers available. Dropping packet data for this frame");
                    dropping_frame_data_ = true;
                }
            }
    	    else
    	    {

                current_frame_buffer_id_ = empty_buffer_queue_.front();
                empty_buffer_queue_.pop();
                frame_buffer_map_[current_frame_seen_] = current_frame_buffer_id_;
                current_frame_buffer_ = buffer_manager_->get_buffer_address(current_frame_buffer_id_);

                if (!dropping_frame_data_)
                {
                    LOG4CXX_DEBUG_LEVEL(2, logger_, "First packet from frame " << current_frame_seen_ << " detected, allocating frame buffer ID " << current_frame_buffer_id_);
                }
                else
                {
                    dropping_frame_data_ = false;
                    LOG4CXX_DEBUG_LEVEL(2, logger_, "Free buffer now available for frame " << current_frame_seen_ << ", allocating frame buffer ID " << current_frame_buffer_id_);
                }
    	    }

    	    // Initialise frame header
            current_frame_header_ = reinterpret_cast<Excalibur::FrameHeader*>(current_frame_buffer_);
            current_frame_header_->frame_number = current_frame_seen_;
            current_frame_header_->frame_state = FrameDecoder::FrameReceiveStateIncomplete;
            current_frame_header_->packets_received = 0;
            current_frame_header_->sof_marker_count = 0;
            current_frame_header_->eof_marker_count = 0;
            memset(current_frame_header_->packet_state, 0, Excalibur::num_frame_packets);
            gettime(reinterpret_cast<struct timespec*>(&(current_frame_header_->frame_start_time)));

    	}
    	else
    	{
    		current_frame_buffer_id_ = frame_buffer_map_[current_frame_seen_];
        	current_frame_buffer_ = buffer_manager_->get_buffer_address(current_frame_buffer_id_);
        	current_frame_header_ = reinterpret_cast<Excalibur::FrameHeader*>(current_frame_buffer_);
    	}

    }

    // If SOF or EOF markers seen in packet header, increment appropriate field in frame header
    if (start_of_frame_marker) {
    	(current_frame_header_->sof_marker_count)++;
    }
    if (end_of_frame_marker) {
    	(current_frame_header_->eof_marker_count)++;
    }

    // Update packet_number state map in frame header
    current_frame_header_->packet_state[subframe_idx][packet_number] = 1;

}

void* ExcaliburFrameDecoder::get_next_payload_buffer(void) const
{

    uint8_t* next_receive_location =
            reinterpret_cast<uint8_t*>(current_frame_buffer_) +
            get_frame_header_size() +
            (Excalibur::subframe_size * (get_subframe_counter() % 2)) +
            (Excalibur::primary_packet_size * get_packet_number());

    return reinterpret_cast<void*>(next_receive_location);
}

size_t ExcaliburFrameDecoder::get_next_payload_size(void) const
{
   size_t next_receive_size = 0;

	if (get_packet_number() < Excalibur::num_primary_packets)
	{
		next_receive_size = Excalibur::primary_packet_size;
	}
	else
	{
		next_receive_size = Excalibur::tail_packet_size;
	}

    return next_receive_size;
}

FrameDecoder::FrameReceiveState ExcaliburFrameDecoder::process_packet(size_t bytes_received)
{

    FrameDecoder::FrameReceiveState frame_state = FrameDecoder::FrameReceiveStateIncomplete;

    // If this packet is the last in subframe (i.e. has on EOF marker in the header), extract the frame
    // number (which counts from 1) from the subframe trailer, update and/or validate in the frame buffer
    // header appropriately.
    if (get_end_of_frame_marker()) {

    	size_t payload_bytes_received = bytes_received - sizeof(Excalibur::PacketHeader);

    	Excalibur::SubframeTrailer* trailer = reinterpret_cast<Excalibur::SubframeTrailer*>(
    			(uint8_t*)get_next_payload_buffer() + payload_bytes_received - sizeof(Excalibur::SubframeTrailer));

    	uint32_t frame_number = static_cast<uint32_t>((trailer->frame_number & 0xFFFFFFFF) - 1);
    	LOG4CXX_DEBUG_LEVEL(3, logger_, "Subframe EOF trailer has frame number = " << frame_number);

    	uint32_t subframe_idx = get_subframe_counter() % 2;

    	if (subframe_idx == 0) {
    		current_frame_header_->frame_number = frame_number;
    	} else {
    		if (frame_number != current_frame_header_->frame_number) {
    			LOG4CXX_WARN(logger_, "Subframe EOF trailer frame number mismatch for frame " << current_frame_seen_
    					<< ": got " << frame_number << ", expected " << current_frame_header_->frame_number
    					);
    		}
    	}
    }

	current_frame_header_->packets_received++;

	if (current_frame_header_->packets_received == Excalibur::num_frame_packets)
	{

		// Check that the appropriate number of SOF and EOF markers (one each per subframe) have
		// been seen, otherwise log a warning

		if ((current_frame_header_->sof_marker_count != Excalibur::num_subframes) ||
			(current_frame_header_->eof_marker_count != Excalibur::num_subframes))
		{
			LOG4CXX_WARN(logger_, "Incorrect number of SOF (" << current_frame_header_->sof_marker_count
					<< ") or EOF (" << current_frame_header_->eof_marker_count
					<< "markers seen on completed frame " << current_frame_seen_
					);
		}

	    // Set frame state accordingly
		frame_state = FrameDecoder::FrameReceiveStateComplete;

		// Complete frame header
		current_frame_header_->frame_state = frame_state;

		if (!dropping_frame_data_)
		{
			// Erase frame from buffer map
			frame_buffer_map_.erase(current_frame_seen_);

			// Notify main thread that frame is ready
			ready_callback_(current_frame_buffer_id_, current_frame_seen_);

			// Reset current frame seen ID so that if next frame has same number (e.g. repeated
			// sends of single frame 0), it is detected properly
			current_frame_seen_ = -1;
		}
	}

	return frame_state;
}

void ExcaliburFrameDecoder::monitor_buffers(void)
{

    int frames_timedout = 0;
    struct timespec current_time;

    gettime(&current_time);

    // Loop over frame buffers currently in map and check their state
    std::map<uint32_t, int>::iterator buffer_map_iter = frame_buffer_map_.begin();
    while (buffer_map_iter != frame_buffer_map_.end())
    {
        uint32_t frame_num = buffer_map_iter->first;
        int      buffer_id = buffer_map_iter->second;
        void*    buffer_addr = buffer_manager_->get_buffer_address(buffer_id);
        Excalibur::FrameHeader* frame_header = reinterpret_cast<Excalibur::FrameHeader*>(buffer_addr);

        if (elapsed_ms(frame_header->frame_start_time, current_time) > frame_timeout_ms_)
        {
            LOG4CXX_DEBUG_LEVEL(1, logger_, "Frame " << frame_num << " in buffer " << buffer_id
                    << " addr 0x" << std::hex << buffer_addr << std::dec
                    << " timed out with " << frame_header->packets_received << " packets received");

            frame_header->frame_state = FrameReceiveStateTimedout;
            ready_callback_(buffer_id, frame_num);
            frames_timedout++;

            frame_buffer_map_.erase(buffer_map_iter++);
        }
        else
        {
            buffer_map_iter++;
        }
    }
    if (frames_timedout)
    {
        LOG4CXX_WARN(logger_, "Released " << frames_timedout << " timed out incomplete frames");
    }
    frames_timedout_ += frames_timedout;

    LOG4CXX_DEBUG_LEVEL(2, logger_, get_num_mapped_buffers() << " frame buffers in use, "
            << get_num_empty_buffers() << " empty buffers available, "
            << frames_timedout_ << " incomplete frames timed out");

}

uint32_t ExcaliburFrameDecoder::get_subframe_counter(void) const
{
    return reinterpret_cast<Excalibur::PacketHeader*>(current_packet_header_.get())->subframe_counter;
}

uint32_t ExcaliburFrameDecoder::get_packet_number(void) const
{
    return reinterpret_cast<Excalibur::PacketHeader*>(current_packet_header_.get())->packet_number_flags & Excalibur::packet_number_mask;
}

bool ExcaliburFrameDecoder::get_start_of_frame_marker(void) const
{
	uint32_t packet_number_flags = reinterpret_cast<Excalibur::PacketHeader*>(current_packet_header_.get())->packet_number_flags;
	return ((packet_number_flags & Excalibur::start_of_frame_mask) != 0);
}

bool ExcaliburFrameDecoder::get_end_of_frame_marker(void) const
{
	uint32_t packet_number_flags = reinterpret_cast<Excalibur::PacketHeader*>(current_packet_header_.get())->packet_number_flags;
	return ((packet_number_flags & Excalibur::end_of_frame_mask) != 0);
}

unsigned int ExcaliburFrameDecoder::elapsed_ms(struct timespec& start, struct timespec& end)
{

    double start_ns = ((double)start.tv_sec * 1000000000) + start.tv_nsec;
    double end_ns   = ((double)  end.tv_sec * 1000000000) +   end.tv_nsec;

    return (unsigned int)((end_ns - start_ns)/1000000);
}
<commit_msg>ExcaliburFrameDecoder now uses 'real' frame number in notifcations.<commit_after>/*
 * ExcaliburFrameDecoder.cpp
 *
 *  Created on: Jan 16th, 2017
 *      Author: Tim Nicholls, STFC Application Engineering Group
 */

#include "ExcaliburFrameDecoder.h"
#include "gettime.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <arpa/inet.h>

using namespace FrameReceiver;

ExcaliburFrameDecoder::ExcaliburFrameDecoder(LoggerPtr& logger,
        bool enable_packet_logging, unsigned int frame_timeout_ms) :
        FrameDecoder(logger, enable_packet_logging),
		current_frame_seen_(-1),
		current_frame_buffer_id_(-1),
		current_frame_buffer_(0),
		current_frame_header_(0),
		dropping_frame_data_(false),
		frame_timeout_ms_(frame_timeout_ms),
		frames_timedout_(0)
{
    current_packet_header_.reset(new uint8_t[sizeof(Excalibur::PacketHeader)]);
    dropped_frame_buffer_.reset(new uint8_t[Excalibur::total_frame_size]);

    if (enable_packet_logging_) {
        LOG4CXX_INFO(packet_logger_, "PktHdr: SourceAddress");
        LOG4CXX_INFO(packet_logger_, "PktHdr: |               SourcePort");
        LOG4CXX_INFO(packet_logger_, "PktHdr: |               |     DestinationPort");
        LOG4CXX_INFO(packet_logger_, "PktHdr: |               |     |      SubframeCounter  [4 Bytes]");
        LOG4CXX_INFO(packet_logger_, "PktHdr: |               |     |      |           PacketCounter&Flags [4 Bytes]");
        LOG4CXX_INFO(packet_logger_, "PktHdr: |               |     |      |           |");
        LOG4CXX_INFO(packet_logger_, "PktHdr: |-------------- |---- |----  |---------- |----------");
    }
}

ExcaliburFrameDecoder::~ExcaliburFrameDecoder()
{
}

const size_t ExcaliburFrameDecoder::get_frame_buffer_size(void) const
{
    return Excalibur::total_frame_size;
}

const size_t ExcaliburFrameDecoder::get_frame_header_size(void) const
{
    return sizeof(Excalibur::FrameHeader);
}

const size_t ExcaliburFrameDecoder::get_packet_header_size(void) const
{
    return sizeof(Excalibur::PacketHeader);
}

void* ExcaliburFrameDecoder::get_packet_header_buffer(void)
{
    return current_packet_header_.get();
}

void ExcaliburFrameDecoder::process_packet_header(size_t bytes_received, int port, struct sockaddr_in* from_addr)
{
    // Dump raw header if packet logging enabled
    if (enable_packet_logging_)
    {
        std::stringstream ss;
        uint8_t* hdr_ptr = reinterpret_cast<uint8_t*>(current_packet_header_.get());
        ss << "PktHdr: " << std::setw(15) << std::left << inet_ntoa(from_addr->sin_addr) << std::right << " "
           << std::setw(5) << ntohs(from_addr->sin_port) << " "
           << std::setw(5) << port << std::hex;
        for (unsigned int hdr_byte = 0; hdr_byte < sizeof(Excalibur::PacketHeader); hdr_byte++)
        {
            if (hdr_byte % 8 == 0) {
                ss << "  ";
            }
            ss << std::setw(2) << std::setfill('0') << (unsigned int)*hdr_ptr << " ";
            hdr_ptr++;
        }
        ss << std::dec;
        LOG4CXX_INFO(packet_logger_, ss.str());
    }

	uint32_t subframe_counter = get_subframe_counter();
	uint32_t packet_number = get_packet_number();
	bool start_of_frame_marker = get_start_of_frame_marker();
	bool end_of_frame_marker = get_end_of_frame_marker();

	uint32_t subframe_idx = subframe_counter % 2;
	uint32_t frame = subframe_counter / 2;

    LOG4CXX_DEBUG_LEVEL(3, logger_, "Got packet header:"
            << " packet: "   << packet_number << " subframe ctr: "<< subframe_counter << " idx:" << subframe_idx
			<< " SOF: " << (int)start_of_frame_marker << " EOF: " << (int)end_of_frame_marker
    );

    if (frame != current_frame_seen_)
    {
        current_frame_seen_ = frame;

    	if (frame_buffer_map_.count(current_frame_seen_) == 0)
    	{
    	    if (empty_buffer_queue_.empty())
            {
                current_frame_buffer_ = dropped_frame_buffer_.get();

    	        if (!dropping_frame_data_)
                {
                    LOG4CXX_ERROR(logger_, "First packet from frame " << current_frame_seen_ << " detected but no free buffers available. Dropping packet data for this frame");
                    dropping_frame_data_ = true;
                }
            }
    	    else
    	    {

                current_frame_buffer_id_ = empty_buffer_queue_.front();
                empty_buffer_queue_.pop();
                frame_buffer_map_[current_frame_seen_] = current_frame_buffer_id_;
                current_frame_buffer_ = buffer_manager_->get_buffer_address(current_frame_buffer_id_);

                if (!dropping_frame_data_)
                {
                    LOG4CXX_DEBUG_LEVEL(2, logger_, "First packet from frame " << current_frame_seen_ << " detected, allocating frame buffer ID " << current_frame_buffer_id_);
                }
                else
                {
                    dropping_frame_data_ = false;
                    LOG4CXX_DEBUG_LEVEL(2, logger_, "Free buffer now available for frame " << current_frame_seen_ << ", allocating frame buffer ID " << current_frame_buffer_id_);
                }
    	    }

    	    // Initialise frame header
            current_frame_header_ = reinterpret_cast<Excalibur::FrameHeader*>(current_frame_buffer_);
            current_frame_header_->frame_number = current_frame_seen_;
            current_frame_header_->frame_state = FrameDecoder::FrameReceiveStateIncomplete;
            current_frame_header_->packets_received = 0;
            current_frame_header_->sof_marker_count = 0;
            current_frame_header_->eof_marker_count = 0;
            memset(current_frame_header_->packet_state, 0, Excalibur::num_frame_packets);
            gettime(reinterpret_cast<struct timespec*>(&(current_frame_header_->frame_start_time)));

    	}
    	else
    	{
    		current_frame_buffer_id_ = frame_buffer_map_[current_frame_seen_];
        	current_frame_buffer_ = buffer_manager_->get_buffer_address(current_frame_buffer_id_);
        	current_frame_header_ = reinterpret_cast<Excalibur::FrameHeader*>(current_frame_buffer_);
    	}

    }

    // If SOF or EOF markers seen in packet header, increment appropriate field in frame header
    if (start_of_frame_marker) {
    	(current_frame_header_->sof_marker_count)++;
    }
    if (end_of_frame_marker) {
    	(current_frame_header_->eof_marker_count)++;
    }

    // Update packet_number state map in frame header
    current_frame_header_->packet_state[subframe_idx][packet_number] = 1;

}

void* ExcaliburFrameDecoder::get_next_payload_buffer(void) const
{

    uint8_t* next_receive_location =
            reinterpret_cast<uint8_t*>(current_frame_buffer_) +
            get_frame_header_size() +
            (Excalibur::subframe_size * (get_subframe_counter() % 2)) +
            (Excalibur::primary_packet_size * get_packet_number());

    return reinterpret_cast<void*>(next_receive_location);
}

size_t ExcaliburFrameDecoder::get_next_payload_size(void) const
{
   size_t next_receive_size = 0;

	if (get_packet_number() < Excalibur::num_primary_packets)
	{
		next_receive_size = Excalibur::primary_packet_size;
	}
	else
	{
		next_receive_size = Excalibur::tail_packet_size;
	}

    return next_receive_size;
}

FrameDecoder::FrameReceiveState ExcaliburFrameDecoder::process_packet(size_t bytes_received)
{

    FrameDecoder::FrameReceiveState frame_state = FrameDecoder::FrameReceiveStateIncomplete;

    // If this packet is the last in subframe (i.e. has on EOF marker in the header), extract the frame
    // number (which counts from 1) from the subframe trailer, update and/or validate in the frame buffer
    // header appropriately.
    if (get_end_of_frame_marker()) {

    	size_t payload_bytes_received = bytes_received - sizeof(Excalibur::PacketHeader);

    	Excalibur::SubframeTrailer* trailer = reinterpret_cast<Excalibur::SubframeTrailer*>(
    			(uint8_t*)get_next_payload_buffer() + payload_bytes_received - sizeof(Excalibur::SubframeTrailer));

    	uint32_t frame_number = static_cast<uint32_t>((trailer->frame_number & 0xFFFFFFFF) - 1);
    	LOG4CXX_DEBUG_LEVEL(3, logger_, "Subframe EOF trailer has frame number = " << frame_number);

    	uint32_t subframe_idx = get_subframe_counter() % 2;

    	if (subframe_idx == 0) {
    		current_frame_header_->frame_number = frame_number;
    	} else {
    		if (frame_number != current_frame_header_->frame_number) {
    			LOG4CXX_WARN(logger_, "Subframe EOF trailer frame number mismatch for frame " << current_frame_seen_
    					<< ": got " << frame_number << ", expected " << current_frame_header_->frame_number
    					);
    		}
    	}
    }

	current_frame_header_->packets_received++;

	if (current_frame_header_->packets_received == Excalibur::num_frame_packets)
	{

		// Check that the appropriate number of SOF and EOF markers (one each per subframe) have
		// been seen, otherwise log a warning

		if ((current_frame_header_->sof_marker_count != Excalibur::num_subframes) ||
			(current_frame_header_->eof_marker_count != Excalibur::num_subframes))
		{
			LOG4CXX_WARN(logger_, "Incorrect number of SOF (" << current_frame_header_->sof_marker_count
					<< ") or EOF (" << current_frame_header_->eof_marker_count
					<< "markers seen on completed frame " << current_frame_seen_
					);
		}

	    // Set frame state accordingly
		frame_state = FrameDecoder::FrameReceiveStateComplete;

		// Complete frame header
		current_frame_header_->frame_state = frame_state;

		if (!dropping_frame_data_)
		{
			// Erase frame from buffer map
			frame_buffer_map_.erase(current_frame_seen_);

			// Notify main thread that frame is ready
			ready_callback_(current_frame_buffer_id_, current_frame_header_->frame_number); //current_frame_seen_);

			// Reset current frame seen ID so that if next frame has same number (e.g. repeated
			// sends of single frame 0), it is detected properly
			current_frame_seen_ = -1;
		}
	}

	return frame_state;
}

void ExcaliburFrameDecoder::monitor_buffers(void)
{

    int frames_timedout = 0;
    struct timespec current_time;

    gettime(&current_time);

    // Loop over frame buffers currently in map and check their state
    std::map<uint32_t, int>::iterator buffer_map_iter = frame_buffer_map_.begin();
    while (buffer_map_iter != frame_buffer_map_.end())
    {
        uint32_t frame_num = buffer_map_iter->first;
        int      buffer_id = buffer_map_iter->second;
        void*    buffer_addr = buffer_manager_->get_buffer_address(buffer_id);
        Excalibur::FrameHeader* frame_header = reinterpret_cast<Excalibur::FrameHeader*>(buffer_addr);

        if (elapsed_ms(frame_header->frame_start_time, current_time) > frame_timeout_ms_)
        {
            LOG4CXX_DEBUG_LEVEL(1, logger_, "Frame " << frame_num << " in buffer " << buffer_id
                    << " addr 0x" << std::hex << buffer_addr << std::dec
                    << " timed out with " << frame_header->packets_received << " packets received");

            frame_header->frame_state = FrameReceiveStateTimedout;
            ready_callback_(buffer_id, frame_num);
            frames_timedout++;

            frame_buffer_map_.erase(buffer_map_iter++);
        }
        else
        {
            buffer_map_iter++;
        }
    }
    if (frames_timedout)
    {
        LOG4CXX_WARN(logger_, "Released " << frames_timedout << " timed out incomplete frames");
    }
    frames_timedout_ += frames_timedout;

    LOG4CXX_DEBUG_LEVEL(2, logger_, get_num_mapped_buffers() << " frame buffers in use, "
            << get_num_empty_buffers() << " empty buffers available, "
            << frames_timedout_ << " incomplete frames timed out");

}

uint32_t ExcaliburFrameDecoder::get_subframe_counter(void) const
{
    return reinterpret_cast<Excalibur::PacketHeader*>(current_packet_header_.get())->subframe_counter;
}

uint32_t ExcaliburFrameDecoder::get_packet_number(void) const
{
    return reinterpret_cast<Excalibur::PacketHeader*>(current_packet_header_.get())->packet_number_flags & Excalibur::packet_number_mask;
}

bool ExcaliburFrameDecoder::get_start_of_frame_marker(void) const
{
	uint32_t packet_number_flags = reinterpret_cast<Excalibur::PacketHeader*>(current_packet_header_.get())->packet_number_flags;
	return ((packet_number_flags & Excalibur::start_of_frame_mask) != 0);
}

bool ExcaliburFrameDecoder::get_end_of_frame_marker(void) const
{
	uint32_t packet_number_flags = reinterpret_cast<Excalibur::PacketHeader*>(current_packet_header_.get())->packet_number_flags;
	return ((packet_number_flags & Excalibur::end_of_frame_mask) != 0);
}

unsigned int ExcaliburFrameDecoder::elapsed_ms(struct timespec& start, struct timespec& end)
{

    double start_ns = ((double)start.tv_sec * 1000000000) + start.tv_nsec;
    double end_ns   = ((double)  end.tv_sec * 1000000000) +   end.tv_nsec;

    return (unsigned int)((end_ns - start_ns)/1000000);
}
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -triple x86_64-unknown-nacl -std=c++11 -verify %s
// expected-no-diagnostics

#include <stddef.h>
#include <stdarg.h>

static_assert(alignof(char) == 1, "alignof char is wrong");

static_assert(alignof(short) == 2, "sizeof short is wrong");
static_assert(alignof(short) == 2, "alignof short is wrong");

static_assert(alignof(int) == 4, "sizeof int is wrong");
static_assert(alignof(int) == 4, "alignof int is wrong");

static_assert(sizeof(long) == 4, "sizeof long is wrong");
static_assert(sizeof(long) == 4, "alignof long is wrong");

static_assert(sizeof(long long) == 8, "sizeof long long is wrong wrong");
static_assert(alignof(long long) == 8, "alignof long long is wrong wrong");

static_assert(sizeof(void*) == 4, "sizeof void * is wrong");
static_assert(alignof(void*) == 4, "alignof void * is wrong");

static_assert(sizeof(float) == 4, "sizeof float is wrong");
static_assert(alignof(float) == 4, "alignof float is wrong");

static_assert(sizeof(double) == 8, "sizeof double is wrong");
static_assert(alignof(double) == 8, "alignof double is wrong");

static_assert(sizeof(long double) == 8, "sizeof long double is wrong");
static_assert(alignof(long double) == 8, "alignof long double is wrong");

static_assert(sizeof(va_list) == 16, "sizeof va_list is wrong");
static_assert(alignof(va_list) == 4, "alignof va_list is wrong");

static_assert(sizeof(size_t) == 4, "sizeof size_t is wrong");
static_assert(alignof(size_t) == 4, "alignof size_t is wrong");
<commit_msg>Fix copy-paste errors in the test<commit_after>// RUN: %clang_cc1 -triple x86_64-unknown-nacl -std=c++11 -verify %s
// expected-no-diagnostics

#include <stddef.h>
#include <stdarg.h>

static_assert(alignof(char) == 1, "alignof char is wrong");

static_assert(sizeof(short) == 2, "sizeof short is wrong");
static_assert(alignof(short) == 2, "alignof short is wrong");

static_assert(sizeof(int) == 4, "sizeof int is wrong");
static_assert(alignof(int) == 4, "alignof int is wrong");

static_assert(sizeof(long) == 4, "sizeof long is wrong");
static_assert(alignof(long) == 4, "alignof long is wrong");

static_assert(sizeof(long long) == 8, "sizeof long long is wrong wrong");
static_assert(alignof(long long) == 8, "alignof long long is wrong wrong");

static_assert(sizeof(void*) == 4, "sizeof void * is wrong");
static_assert(alignof(void*) == 4, "alignof void * is wrong");

static_assert(sizeof(float) == 4, "sizeof float is wrong");
static_assert(alignof(float) == 4, "alignof float is wrong");

static_assert(sizeof(double) == 8, "sizeof double is wrong");
static_assert(alignof(double) == 8, "alignof double is wrong");

static_assert(sizeof(long double) == 8, "sizeof long double is wrong");
static_assert(alignof(long double) == 8, "alignof long double is wrong");

static_assert(sizeof(va_list) == 16, "sizeof va_list is wrong");
static_assert(alignof(va_list) == 4, "alignof va_list is wrong");

static_assert(sizeof(size_t) == 4, "sizeof size_t is wrong");
static_assert(alignof(size_t) == 4, "alignof size_t is wrong");
<|endoftext|>


<commit_before>/*
 * gVirtuS -- A GPGPU transparent virtualization component.
 *
 * Copyright (C) 2009-2011  The University of Napoli Parthenope at Naples.
 *
 * This file is part of gVirtuS.
 *
 * gVirtuS 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.
 *
 * gVirtuS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gVirtuS; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Written by: Giuseppe Coviello <giuseppe.coviello@uniparthenope.it>,
 *             Department of Applied Science
 */

#include <cufft.h>

#include "Frontend.h"

#include <iostream>

using namespace std;

extern "C" cufftResult cufftPlan1d(cufftHandle *plan, int nx, cufftType type,
        int batch) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(nx);
    in->Add(type);
    in->Add(batch);
    f->Execute("cufftPlan1d");
    //cout << hex << f->GetOutputBuffer() << endl;
    //cout << hex << f->GetOutputBuffer()->Get<uint64_t>();
    //*plan = (cufftHandle) f->GetOutputBuffer()->Get<uint64_t>();
    *plan = f->GetOutputBuffer()->Get<cufftHandle>();
    cout << "CCCC\n";
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftPlan2d(cufftHandle *plan, int nx, int ny,
        cufftType type) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(nx);
    in->Add(ny);
    in->Add(type);
    f->Execute("cufftPlan2d");
    *plan = f->GetOutputBuffer()->Get<cufftHandle>();
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftPlan3d(cufftHandle *plan, int nx, int ny, int nz,
        cufftType type) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(nx);
    in->Add(ny);
    in->Add(nz);
    in->Add(type);
    f->Execute("cufftPlan3d");
    *plan = (cufftHandle) f->GetOutputBuffer()->Get<uint64_t>();
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftPlanMany(cufftHandle *plan, int rank, int *n,
        int *inembed, int istride, int idist, int *onembed, int ostride,
        int odist, cufftType type, int batch) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(rank);
    in->Add(*n);
    in->Add(istride);
    in->Add(idist);
    in->Add(ostride);
    in->Add(odist);
    in->Add(type);
    in->Add(batch);
    f->Execute("cufftPlanMany");
    *plan = (cufftHandle) f->GetOutputBuffer()->Get<uint64_t>();
    *n = f->GetOutputBuffer()->Get<int>();
    return (cufftResult) f->GetExitCode();
}

/*
 * in Testing - Vincenzo Santopietro
 */
extern "C" cufftResult cufftCreate(cufftHandle *plan) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    f->Execute("cufftCreate");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftDestroy(cufftHandle plan) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    f->Execute("cufftDestroy");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecC2C(cufftHandle plan, cufftComplex *idata,
        cufftComplex *odata, int direction) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    in->Add(direction);
    f->Execute("cufftExecC2C");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecR2C(cufftHandle plan, cufftReal *idata,
        cufftComplex *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    f->Execute("cufftExecR2C");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecC2R(cufftHandle plan, cufftComplex *idata,
        cufftReal *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add((uint64_t) idata);
    in->Add((uint64_t) odata);
    f->Execute("cufftExecC2R");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecZ2Z(cufftHandle plan, cufftDoubleComplex *idata,
        cufftDoubleComplex *odata, int direction) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    in->Add(direction);
    f->Execute("cufftExecZ2z");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecD2Z(cufftHandle plan, cufftDoubleReal *idata,
        cufftDoubleComplex *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    f->Execute("cufftExecD2Z");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecZ2D(cufftHandle plan, cufftDoubleComplex *idata,
        cufftDoubleReal *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    f->Execute("cufftExecZ2D");
    return (cufftResult) f->GetExitCode();

}

extern "C" cufftResult cufftSetStream(cufftHandle plan, cudaStream_t stream) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add((uint64_t) stream);
    f->Execute("cufftSetStream");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftSetCompatibilityMode(cufftHandle plan,
        cufftCompatibility mode){
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(mode);
    f->Execute("cufftSetCompatibilityMode");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftXtMakePlanMany(cufftHandle plan, int rank, long long int *n, long long int *inembed, long long int istride, long long int idist, cudaDataType inputtype, long long int *onembed, long long int ostride, long long int odist, cudaDataType outputtype, long long int batch, size_t *workSize, cudaDataType executiontype) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    //plan = (cufftHandle) f->GetOutputBuffer()->Get<cufftHandle>();
    //n = (long long int * )f->GetOutputBuffer()->Get<long long int>();

    in->Add(plan);
    in->Add(rank);
    in->Add(*n);
    in->Add(*inembed);
    in->Add(istride);
    in->Add(idist);
    in->Add(inputtype);

    in->Add(*onembed);
    in->Add(ostride);
    in->Add(odist);
    in->Add(outputtype);

    in->Add(batch);
    in->Add(*workSize);
    in->Add(executiontype);
    f->Execute("cufftXtMakePlanMany");

    return (cufftResult) f->GetExitCode();
}
<commit_msg>Fixed cufftCreate and CufftPlan1d<commit_after>/*
 * gVirtuS -- A GPGPU transparent virtualization component.
 *
 * Copyright (C) 2009-2011  The University of Napoli Parthenope at Naples.
 *
 * This file is part of gVirtuS.
 *
 * gVirtuS 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.
 *
 * gVirtuS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gVirtuS; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Written by: Giuseppe Coviello <giuseppe.coviello@uniparthenope.it>,
 *             Department of Applied Science
 */

#include <cufft.h>

#include "Frontend.h"
#include "CufftFrontend.h"

using namespace std;

extern "C" cufftResult cufftPlan1d(cufftHandle *plan, int nx, cufftType type,
        int batch) {
    /*Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(nx);
    in->Add(type);
    in->Add(batch);
    f->Execute("cufftPlan1d");
    //cout << hex << f->GetOutputBuffer() << endl;
    //cout << hex << f->GetOutputBuffer()->Get<uint64_t>();
    //*plan = (cufftHandle) f->GetOutputBuffer()->Get<uint64_t>();
    *plan = f->GetOutputBuffer()->Get<cufftHandle>();
    return (cufftResult) f->GetExitCode();*/
    CufftFrontend::Prepare();
    CufftFrontend::AddHostPointerForArguments(plan);
    CufftFrontend::AddVariableForArguments(nx);
    CufftFrontend::AddVariableForArguments(type);
    CufftFrontend::AddVariableForArguments(batch);

    CufftFrontend::Execute("cufftPlan1d");
    if(CufftFrontend::Success())
        *plan = *(CufftFrontend::GetOutputHostPointer<cufftHandle>());
    cout << "plan : "<< *plan;
    return (cufftResult) CufftFrontend::GetExitCode();

}

extern "C" cufftResult cufftPlan2d(cufftHandle *plan, int nx, int ny,
        cufftType type) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(nx);
    in->Add(ny);
    in->Add(type);
    f->Execute("cufftPlan2d");
    *plan = f->GetOutputBuffer()->Get<cufftHandle>();
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftPlan3d(cufftHandle *plan, int nx, int ny, int nz,
        cufftType type) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(nx);
    in->Add(ny);
    in->Add(nz);
    in->Add(type);
    f->Execute("cufftPlan3d");
    *plan = (cufftHandle) f->GetOutputBuffer()->Get<uint64_t>();
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftPlanMany(cufftHandle *plan, int rank, int *n,
        int *inembed, int istride, int idist, int *onembed, int ostride,
        int odist, cufftType type, int batch) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(rank);
    in->Add(*n);
    in->Add(istride);
    in->Add(idist);
    in->Add(ostride);
    in->Add(odist);
    in->Add(type);
    in->Add(batch);
    f->Execute("cufftPlanMany");
    *plan = (cufftHandle) f->GetOutputBuffer()->Get<uint64_t>();
    *n = f->GetOutputBuffer()->Get<int>();
    return (cufftResult) f->GetExitCode();
}

/*
 * in Testing - Vincenzo Santopietro
 */
extern "C" cufftResult cufftCreate(cufftHandle *plan) {
    //Frontend *f = Frontend::GetFrontend();
    CufftFrontend::Prepare();
    CufftFrontend::AddHostPointerForArguments(plan);
    //f->GetFrontend();
    CufftFrontend::Execute("cufftCreate");
    if(CufftFrontend::Success())
        *plan = *(CufftFrontend::GetOutputHostPointer<cufftHandle>());
    printf("plan: %d",*plan);
    return (cufftResult) CufftFrontend::GetExitCode();//(cufftResult) CufftFrontend::GetExitCode();
}

extern "C" cufftResult cufftDestroy(cufftHandle plan) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    f->Execute("cufftDestroy");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecC2C(cufftHandle plan, cufftComplex *idata,
        cufftComplex *odata, int direction) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    in->Add(direction);
    f->Execute("cufftExecC2C");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecR2C(cufftHandle plan, cufftReal *idata,
        cufftComplex *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    f->Execute("cufftExecR2C");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecC2R(cufftHandle plan, cufftComplex *idata,
        cufftReal *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add((uint64_t) idata);
    in->Add((uint64_t) odata);
    f->Execute("cufftExecC2R");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecZ2Z(cufftHandle plan, cufftDoubleComplex *idata,
        cufftDoubleComplex *odata, int direction) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    in->Add(direction);
    f->Execute("cufftExecZ2z");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecD2Z(cufftHandle plan, cufftDoubleReal *idata,
        cufftDoubleComplex *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    f->Execute("cufftExecD2Z");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftExecZ2D(cufftHandle plan, cufftDoubleComplex *idata,
        cufftDoubleReal *odata) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(idata);
    in->Add(odata);
    f->Execute("cufftExecZ2D");
    return (cufftResult) f->GetExitCode();

}

extern "C" cufftResult cufftSetStream(cufftHandle plan, cudaStream_t stream) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add((uint64_t) stream);
    f->Execute("cufftSetStream");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftSetCompatibilityMode(cufftHandle plan,
        cufftCompatibility mode){
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *in = f->GetInputBuffer();
    in->Add(plan);
    in->Add(mode);
    f->Execute("cufftSetCompatibilityMode");
    return (cufftResult) f->GetExitCode();
}

extern "C" cufftResult cufftXtMakePlanMany(cufftHandle plan, int rank, long long int *n, long long int *inembed, long long int istride, long long int idist, cudaDataType inputtype, long long int *onembed, long long int ostride, long long int odist, cudaDataType outputtype, long long int batch, size_t *workSize, cudaDataType executiontype) {
    Frontend *f = Frontend::GetFrontend();
    f->Prepare();
    Buffer *input_buffer = f->GetInputBuffer();
    plan = (cufftHandle) f->GetOutputBuffer()->Get<cufftHandle>();
    n = (long long int * )f->GetOutputBuffer()->Get<long long int>();

    input_buffer->Add(plan);
    input_buffer->Add(rank);
    input_buffer->Add(*n);
    input_buffer->Add(*inembed);
    input_buffer->Add(istride);
    input_buffer->Add(idist);
    input_buffer->Add(inputtype);

    input_buffer->Add(*onembed);
    input_buffer->Add(ostride);
    input_buffer->Add(odist);
    input_buffer->Add(outputtype);

    input_buffer->Add(batch);
    input_buffer->Add(*workSize);
    input_buffer->Add(executiontype);
    f->Execute("cufftXtMakePlanMany");

    return (cufftResult) f->GetExitCode();
}
<|endoftext|>


<commit_before><commit_msg>fix OOXML validation error<commit_after><|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "generictilerenderer.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/aov/imagestack.h"
#include "renderer/kernel/aov/tilestack.h"
#include "renderer/kernel/rendering/ipixelrenderer.h"
#include "renderer/kernel/rendering/ishadingresultframebufferfactory.h"
#include "renderer/kernel/rendering/pixelcontext.h"
#include "renderer/kernel/rendering/shadingresultframebuffer.h"
#include "renderer/modeling/frame/frame.h"

// appleseed.foundation headers.
#include "foundation/image/canvasproperties.h"
#include "foundation/image/image.h"
#include "foundation/image/tile.h"
#include "foundation/math/aabb.h"
#include "foundation/math/filter.h"
#include "foundation/math/ordering.h"
#include "foundation/math/scalar.h"
#include "foundation/math/vector.h"
#include "foundation/platform/breakpoint.h"
#include "foundation/platform/types.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/iostreamop.h"
#include "foundation/utility/job.h"
#include "foundation/utility/statistics.h"
#include "foundation/utility/string.h"

// Standard headers.
#include <cassert>
#include <cmath>
#include <cstddef>
#include <memory>
#include <string>
#include <vector>

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Generic tile renderer.
    //

#ifndef NDEBUG

    // Define this symbol to break execution into the debugger
    // when a specific pixel is about to be rendered.
    // #define DEBUG_BREAK_AT_PIXEL Vector2i(0, 0)

#endif

    class GenericTileRenderer
      : public ITileRenderer
    {
      public:
        GenericTileRenderer(
            const Frame&                        frame,
            IPixelRendererFactory*              pixel_renderer_factory,
            IShadingResultFrameBufferFactory*   framebuffer_factory,
            const ParamArray&                   params,
            const bool                          primary)
          : m_pixel_renderer(pixel_renderer_factory->create(primary))
          , m_framebuffer_factory(framebuffer_factory)
        {
            compute_tile_margins(frame, primary);
            compute_pixel_ordering(frame);
        }

        virtual void release() OVERRIDE
        {
            delete this;
        }

        virtual void render_tile(
            const Frame&    frame,
            const size_t    tile_x,
            const size_t    tile_y,
            const size_t    pass_hash,
            AbortSwitch&    abort_switch) OVERRIDE
        {
            // Retrieve frame properties.
            const CanvasProperties& frame_properties = frame.image().properties();
            assert(tile_x < frame_properties.m_tile_count_x);
            assert(tile_y < frame_properties.m_tile_count_y);

            // Retrieve tile properties.
            Tile& tile = frame.image().tile(tile_x, tile_y);
            TileStack aov_tiles = frame.aov_images().tiles(tile_x, tile_y);
            const size_t tile_origin_x = frame_properties.m_tile_width * tile_x;
            const size_t tile_origin_y = frame_properties.m_tile_height * tile_y;

            // Compute the image space bounding box of the pixels to render.
            AABB2u tile_bbox;
            tile_bbox.min.x = tile_origin_x;
            tile_bbox.min.y = tile_origin_y;
            tile_bbox.max.x = tile_origin_x + tile.get_width() - 1;
            tile_bbox.max.y = tile_origin_y + tile.get_height() - 1;
            tile_bbox = AABB2u::intersect(tile_bbox, frame.get_crop_window());
            if (!tile_bbox.is_valid())
                return;

            // Transform the bounding box to local (tile) space.
            tile_bbox.min.x -= tile_origin_x;
            tile_bbox.min.y -= tile_origin_y;
            tile_bbox.max.x -= tile_origin_x;
            tile_bbox.max.y -= tile_origin_y;

            // Inform the pixel renderer that we are about to render a tile.
            m_pixel_renderer->on_tile_begin(frame, tile, aov_tiles);

            // Create the framebuffer into which we will accumulate the samples.
            ShadingResultFrameBuffer* framebuffer =
                m_framebuffer_factory->create(
                    frame,
                    tile_x,
                    tile_y,
                    tile_bbox);
            assert(framebuffer);

            // Seed the RNG with the tile index.
            m_rng = SamplingContext::RNGType(
                static_cast<uint32>(
                    tile_y * frame_properties.m_tile_count_x + tile_x));

            // Loop over tile pixels.
            const size_t tile_pixel_count = m_pixel_ordering.size();
            for (size_t i = 0; i < tile_pixel_count; ++i)
            {
                // Cancel any work done on this tile if rendering is aborted.
                if (abort_switch.is_aborted())
                    return;

                // Retrieve the coordinates of the pixel in the padded tile.
                const int tx = m_pixel_ordering[i].x;
                const int ty = m_pixel_ordering[i].y;

                // Skip pixels outside the intersection of the padded tile and the crop window.
                if (tx > static_cast<int>(tile_bbox.max.x) + m_margin_width ||
                    ty > static_cast<int>(tile_bbox.max.y) + m_margin_height)
                    continue;

                // Create a pixel context that identifies the pixel currently being rendered.
                const PixelContext pixel_context(
                    static_cast<int>(tile_origin_x) + tx,
                    static_cast<int>(tile_origin_y) + ty);

#ifdef DEBUG_BREAK_AT_PIXEL

                // Break in the debugger when this pixel is reached.
                if (pixel_context.get_pixel_coordinates() == DEBUG_BREAK_AT_PIXEL)
                    BREAKPOINT();

#endif

                // Render this pixel.
                m_pixel_renderer->render_pixel(
                    frame,
                    tile,
                    aov_tiles,
                    AABB2i(tile_bbox),
                    pixel_context,
                    pass_hash,
                    tx, ty,
                    m_rng,
                    *framebuffer);
            }

            // Develop the framebuffer to the tile.
            if (frame.is_premultiplied_alpha())
                framebuffer->develop_to_tile_premult_alpha(tile, aov_tiles);
            else framebuffer->develop_to_tile_straight_alpha(tile, aov_tiles);

            // Release the framebuffer.
            m_framebuffer_factory->destroy(framebuffer);

            // Inform the pixel renderer that we are done rendering the tile.
            m_pixel_renderer->on_tile_end(frame, tile, aov_tiles);
        }

        virtual StatisticsVector get_statistics() const OVERRIDE
        {
            return m_pixel_renderer->get_statistics();
        }

      protected:
        auto_release_ptr<IPixelRenderer>    m_pixel_renderer;
        IShadingResultFrameBufferFactory*   m_framebuffer_factory;
        int                                 m_margin_width;
        int                                 m_margin_height;
        vector<Vector<int16, 2> >           m_pixel_ordering;
        SamplingContext::RNGType            m_rng;

        void compute_tile_margins(const Frame& frame, const bool primary)
        {
            m_margin_width = truncate<int>(ceil(frame.get_filter().get_xradius() - 0.5));
            m_margin_height = truncate<int>(ceil(frame.get_filter().get_yradius() - 0.5));

            const CanvasProperties& properties = frame.image().properties();
            const size_t padded_tile_width = properties.m_tile_width + 2 * m_margin_width;
            const size_t padded_tile_height = properties.m_tile_height + 2 * m_margin_height;
            const size_t padded_pixel_count = padded_tile_width * padded_tile_height;
            const size_t pixel_count = properties.m_tile_width * properties.m_tile_height;
            const size_t overhead_pixel_count = padded_pixel_count - pixel_count;
            const double wasted_effort = static_cast<double>(overhead_pixel_count) / pixel_count * 100.0;
            const double MaxWastedEffort = 15.0;    // percents

            if (primary)
            {
                RENDERER_LOG(
                    wasted_effort > MaxWastedEffort ? LogMessage::Warning : LogMessage::Info,
                    "rendering effort wasted by tile borders: %s (tile dimensions: %sx%s, tile margins: %sx%s)",
                    pretty_percent(overhead_pixel_count, pixel_count).c_str(),
                    pretty_uint(properties.m_tile_width).c_str(),
                    pretty_uint(properties.m_tile_height).c_str(),
                    pretty_uint(2 * m_margin_width).c_str(),
                    pretty_uint(2 * m_margin_height).c_str());
            }
        }

        void compute_pixel_ordering(const Frame& frame)
        {
            // Compute the dimensions in pixels of the padded tile.
            const CanvasProperties& properties = frame.image().properties();
            const size_t padded_tile_width = properties.m_tile_width + 2 * m_margin_width;
            const size_t padded_tile_height = properties.m_tile_height + 2 * m_margin_height;
            const size_t pixel_count = padded_tile_width * padded_tile_height;

            // Generate the pixel ordering inside the padded tile.
            vector<size_t> ordering;
            ordering.reserve(pixel_count);
            hilbert_ordering(ordering, padded_tile_width, padded_tile_height);
            assert(ordering.size() == pixel_count);

            // Convert the pixel ordering to a 2D representation.
            m_pixel_ordering.resize(pixel_count);
            for (size_t i = 0; i < pixel_count; ++i)
            {
                const size_t x = ordering[i] % padded_tile_width;
                const size_t y = ordering[i] / padded_tile_width;
                assert(x < padded_tile_width);
                assert(y < padded_tile_height);
                m_pixel_ordering[i].x = static_cast<int16>(x) - m_margin_width;
                m_pixel_ordering[i].y = static_cast<int16>(y) - m_margin_height;
            }
        }
    };
}

//
// GenericTileRendererFactory class implementation.
//

GenericTileRendererFactory::GenericTileRendererFactory(
    const Frame&                        frame,
    IPixelRendererFactory*              pixel_renderer_factory,
    IShadingResultFrameBufferFactory*   framebuffer_factory,
    const ParamArray&                   params)
  : m_frame(frame)
  , m_pixel_renderer_factory(pixel_renderer_factory)
  , m_framebuffer_factory(framebuffer_factory)
  , m_params(params)
{
}

void GenericTileRendererFactory::release()
{
    delete this;
}

ITileRenderer* GenericTileRendererFactory::create(const bool primary)
{
    return
        new GenericTileRenderer(
            m_frame,
            m_pixel_renderer_factory,
            m_framebuffer_factory,
            m_params,
            primary);
}

}   // namespace renderer
<commit_msg>bug fix: some pixels were computed even though they were outside the crop window (they were not stored though).<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "generictilerenderer.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/aov/imagestack.h"
#include "renderer/kernel/aov/tilestack.h"
#include "renderer/kernel/rendering/ipixelrenderer.h"
#include "renderer/kernel/rendering/ishadingresultframebufferfactory.h"
#include "renderer/kernel/rendering/pixelcontext.h"
#include "renderer/kernel/rendering/shadingresultframebuffer.h"
#include "renderer/modeling/frame/frame.h"

// appleseed.foundation headers.
#include "foundation/image/canvasproperties.h"
#include "foundation/image/image.h"
#include "foundation/image/tile.h"
#include "foundation/math/aabb.h"
#include "foundation/math/filter.h"
#include "foundation/math/ordering.h"
#include "foundation/math/scalar.h"
#include "foundation/math/vector.h"
#include "foundation/platform/breakpoint.h"
#include "foundation/platform/types.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/iostreamop.h"
#include "foundation/utility/job.h"
#include "foundation/utility/statistics.h"
#include "foundation/utility/string.h"

// Standard headers.
#include <cassert>
#include <cmath>
#include <cstddef>
#include <memory>
#include <string>
#include <vector>

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Generic tile renderer.
    //

#ifndef NDEBUG

    // Define this symbol to break execution into the debugger
    // when a specific pixel is about to be rendered.
    // #define DEBUG_BREAK_AT_PIXEL Vector2i(0, 0)

#endif

    class GenericTileRenderer
      : public ITileRenderer
    {
      public:
        GenericTileRenderer(
            const Frame&                        frame,
            IPixelRendererFactory*              pixel_renderer_factory,
            IShadingResultFrameBufferFactory*   framebuffer_factory,
            const ParamArray&                   params,
            const bool                          primary)
          : m_pixel_renderer(pixel_renderer_factory->create(primary))
          , m_framebuffer_factory(framebuffer_factory)
        {
            compute_tile_margins(frame, primary);
            compute_pixel_ordering(frame);
        }

        virtual void release() OVERRIDE
        {
            delete this;
        }

        virtual void render_tile(
            const Frame&    frame,
            const size_t    tile_x,
            const size_t    tile_y,
            const size_t    pass_hash,
            AbortSwitch&    abort_switch) OVERRIDE
        {
            // Retrieve frame properties.
            const CanvasProperties& frame_properties = frame.image().properties();
            assert(tile_x < frame_properties.m_tile_count_x);
            assert(tile_y < frame_properties.m_tile_count_y);

            // Retrieve tile properties.
            Tile& tile = frame.image().tile(tile_x, tile_y);
            TileStack aov_tiles = frame.aov_images().tiles(tile_x, tile_y);
            const size_t tile_origin_x = frame_properties.m_tile_width * tile_x;
            const size_t tile_origin_y = frame_properties.m_tile_height * tile_y;

            // Compute the image space bounding box of the pixels to render.
            AABB2u tile_bbox;
            tile_bbox.min.x = tile_origin_x;
            tile_bbox.min.y = tile_origin_y;
            tile_bbox.max.x = tile_origin_x + tile.get_width() - 1;
            tile_bbox.max.y = tile_origin_y + tile.get_height() - 1;
            tile_bbox = AABB2u::intersect(tile_bbox, frame.get_crop_window());
            if (!tile_bbox.is_valid())
                return;

            // Transform the bounding box to local (tile) space.
            tile_bbox.min.x -= tile_origin_x;
            tile_bbox.min.y -= tile_origin_y;
            tile_bbox.max.x -= tile_origin_x;
            tile_bbox.max.y -= tile_origin_y;

            // Inform the pixel renderer that we are about to render a tile.
            m_pixel_renderer->on_tile_begin(frame, tile, aov_tiles);

            // Create the framebuffer into which we will accumulate the samples.
            ShadingResultFrameBuffer* framebuffer =
                m_framebuffer_factory->create(
                    frame,
                    tile_x,
                    tile_y,
                    tile_bbox);
            assert(framebuffer);

            // Seed the RNG with the tile index.
            m_rng = SamplingContext::RNGType(
                static_cast<uint32>(
                    tile_y * frame_properties.m_tile_count_x + tile_x));

            // Loop over tile pixels.
            const size_t tile_pixel_count = m_pixel_ordering.size();
            for (size_t i = 0; i < tile_pixel_count; ++i)
            {
                // Cancel any work done on this tile if rendering is aborted.
                if (abort_switch.is_aborted())
                    return;

                // Retrieve the coordinates of the pixel in the padded tile.
                const int tx = m_pixel_ordering[i].x;
                const int ty = m_pixel_ordering[i].y;

                // Skip pixels outside the intersection of the padded tile and the crop window.
                if (tx < static_cast<int>(tile_bbox.min.x) - m_margin_width  ||
                    ty < static_cast<int>(tile_bbox.min.y) - m_margin_height ||
                    tx > static_cast<int>(tile_bbox.max.x) + m_margin_width  ||
                    ty > static_cast<int>(tile_bbox.max.y) + m_margin_height)
                    continue;

                // Create a pixel context that identifies the pixel currently being rendered.
                const PixelContext pixel_context(
                    static_cast<int>(tile_origin_x) + tx,
                    static_cast<int>(tile_origin_y) + ty);

#ifdef DEBUG_BREAK_AT_PIXEL

                // Break in the debugger when this pixel is reached.
                if (pixel_context.get_pixel_coordinates() == DEBUG_BREAK_AT_PIXEL)
                    BREAKPOINT();

#endif

                // Render this pixel.
                m_pixel_renderer->render_pixel(
                    frame,
                    tile,
                    aov_tiles,
                    AABB2i(tile_bbox),
                    pixel_context,
                    pass_hash,
                    tx, ty,
                    m_rng,
                    *framebuffer);
            }

            // Develop the framebuffer to the tile.
            if (frame.is_premultiplied_alpha())
                framebuffer->develop_to_tile_premult_alpha(tile, aov_tiles);
            else framebuffer->develop_to_tile_straight_alpha(tile, aov_tiles);

            // Release the framebuffer.
            m_framebuffer_factory->destroy(framebuffer);

            // Inform the pixel renderer that we are done rendering the tile.
            m_pixel_renderer->on_tile_end(frame, tile, aov_tiles);
        }

        virtual StatisticsVector get_statistics() const OVERRIDE
        {
            return m_pixel_renderer->get_statistics();
        }

      protected:
        auto_release_ptr<IPixelRenderer>    m_pixel_renderer;
        IShadingResultFrameBufferFactory*   m_framebuffer_factory;
        int                                 m_margin_width;
        int                                 m_margin_height;
        vector<Vector<int16, 2> >           m_pixel_ordering;
        SamplingContext::RNGType            m_rng;

        void compute_tile_margins(const Frame& frame, const bool primary)
        {
            m_margin_width = truncate<int>(ceil(frame.get_filter().get_xradius() - 0.5));
            m_margin_height = truncate<int>(ceil(frame.get_filter().get_yradius() - 0.5));

            const CanvasProperties& properties = frame.image().properties();
            const size_t padded_tile_width = properties.m_tile_width + 2 * m_margin_width;
            const size_t padded_tile_height = properties.m_tile_height + 2 * m_margin_height;
            const size_t padded_pixel_count = padded_tile_width * padded_tile_height;
            const size_t pixel_count = properties.m_tile_width * properties.m_tile_height;
            const size_t overhead_pixel_count = padded_pixel_count - pixel_count;
            const double wasted_effort = static_cast<double>(overhead_pixel_count) / pixel_count * 100.0;
            const double MaxWastedEffort = 15.0;    // percents

            if (primary)
            {
                RENDERER_LOG(
                    wasted_effort > MaxWastedEffort ? LogMessage::Warning : LogMessage::Info,
                    "rendering effort wasted by tile borders: %s (tile dimensions: %sx%s, tile margins: %sx%s)",
                    pretty_percent(overhead_pixel_count, pixel_count).c_str(),
                    pretty_uint(properties.m_tile_width).c_str(),
                    pretty_uint(properties.m_tile_height).c_str(),
                    pretty_uint(2 * m_margin_width).c_str(),
                    pretty_uint(2 * m_margin_height).c_str());
            }
        }

        void compute_pixel_ordering(const Frame& frame)
        {
            // Compute the dimensions in pixels of the padded tile.
            const CanvasProperties& properties = frame.image().properties();
            const size_t padded_tile_width = properties.m_tile_width + 2 * m_margin_width;
            const size_t padded_tile_height = properties.m_tile_height + 2 * m_margin_height;
            const size_t pixel_count = padded_tile_width * padded_tile_height;

            // Generate the pixel ordering inside the padded tile.
            vector<size_t> ordering;
            ordering.reserve(pixel_count);
            hilbert_ordering(ordering, padded_tile_width, padded_tile_height);
            assert(ordering.size() == pixel_count);

            // Convert the pixel ordering to a 2D representation.
            m_pixel_ordering.resize(pixel_count);
            for (size_t i = 0; i < pixel_count; ++i)
            {
                const size_t x = ordering[i] % padded_tile_width;
                const size_t y = ordering[i] / padded_tile_width;
                assert(x < padded_tile_width);
                assert(y < padded_tile_height);
                m_pixel_ordering[i].x = static_cast<int16>(x) - m_margin_width;
                m_pixel_ordering[i].y = static_cast<int16>(y) - m_margin_height;
            }
        }
    };
}

//
// GenericTileRendererFactory class implementation.
//

GenericTileRendererFactory::GenericTileRendererFactory(
    const Frame&                        frame,
    IPixelRendererFactory*              pixel_renderer_factory,
    IShadingResultFrameBufferFactory*   framebuffer_factory,
    const ParamArray&                   params)
  : m_frame(frame)
  , m_pixel_renderer_factory(pixel_renderer_factory)
  , m_framebuffer_factory(framebuffer_factory)
  , m_params(params)
{
}

void GenericTileRendererFactory::release()
{
    delete this;
}

ITileRenderer* GenericTileRendererFactory::create(const bool primary)
{
    return
        new GenericTileRenderer(
            m_frame,
            m_pixel_renderer_factory,
            m_framebuffer_factory,
            m_params,
            primary);
}

}   // namespace renderer
<|endoftext|>