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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#ifndef MITKDIFFUSIONIMAGETODIFFUSIONIMAGEFILTER_CPP
#define MITKDIFFUSIONIMAGETODIFFUSIONIMAGEFILTER_CPP

#include "mitkDWIHeadMotionCorrectionFilter.h"

#include "itkSplitDWImageFilter.h"
#include "itkB0ImageExtractionToSeparateImageFilter.h"

#include "mitkImageTimeSelector.h"

#include "mitkPyramidImageRegistrationMethod.h"
#include "mitkImageToDiffusionImageSource.h"

#include "mitkIOUtil.h"

template< typename DiffusionPixelType>
mitk::DWIHeadMotionCorrectionFilter<DiffusionPixelType>
::DWIHeadMotionCorrectionFilter()
{

}

template< typename DiffusionPixelType>
void mitk::DWIHeadMotionCorrectionFilter<DiffusionPixelType>
::GenerateData()
{
  typedef itk::SplitDWImageFilter< DiffusionPixelType, DiffusionPixelType> SplitFilterType;

  DiffusionImageType* input = const_cast<DiffusionImageType*>(this->GetInput(0));

  //
  //  (1) Extract the b-zero images to a 3d+t image, register them by NCorr metric and
  //     rigid registration : they will then be used are reference image for registering
  //     the gradient images
  //
  typedef itk::B0ImageExtractionToSeparateImageFilter< DiffusionPixelType, DiffusionPixelType> B0ExtractorType;
  typename B0ExtractorType::Pointer b0_extractor = B0ExtractorType::New();
  b0_extractor->SetInput( input->GetVectorImage() );
  b0_extractor->SetDirections( input->GetDirections() );
  b0_extractor->Update();

  mitk::Image::Pointer b0Image = mitk::Image::New();
  b0Image->InitializeByItk( b0_extractor->GetOutput() );
  b0Image->SetImportChannel( b0_extractor->GetOutput()->GetBufferPointer(),
                             mitk::Image::CopyMemory );

  // (2.1) Use the extractor to access the extracted b0 volumes
  mitk::ImageTimeSelector::Pointer t_selector =
      mitk::ImageTimeSelector::New();

  t_selector->SetInput( b0Image );
  t_selector->SetTimeNr(0);
  t_selector->Update();

  // first unweighted image as reference space for the registration
  mitk::Image::Pointer b0referenceImage = t_selector->GetOutput();

  mitk::PyramidImageRegistrationMethod::Pointer registrationMethod = mitk::PyramidImageRegistrationMethod::New();
  registrationMethod->SetFixedImage( b0referenceImage );
  registrationMethod->SetTransformToRigid();

  // the unweighted images are of same modality
  registrationMethod->SetCrossModalityOff();

  // Initialize the temporary output image
  mitk::Image::Pointer registeredB0Image = b0Image->Clone();
  const unsigned int numberOfb0Images = b0Image->GetTimeSteps();

  mitk::ImageTimeSelector::Pointer t_selector2 =
      mitk::ImageTimeSelector::New();

  t_selector2->SetInput( b0Image );

  for( unsigned int i=1; i<numberOfb0Images; i++)
  {

    t_selector2->SetTimeNr(i);
    t_selector2->Update();

    registrationMethod->SetMovingImage( t_selector2->GetOutput() );

    try
    {
      MITK_INFO << " === (" << i <<"/"<< numberOfb0Images-1 << ") :: Starting registration";
      registrationMethod->Update();
    }
    catch( const itk::ExceptionObject& e)
    {
      mitkThrow() << "Failed to register the b0 images, the PyramidRegistration threw an exception: \n" << e.what();
    }

    // import volume to the inter-results
    registeredB0Image->SetImportVolume( registrationMethod->GetResampledMovingImage()->GetData(),
                                       i, 0, mitk::Image::ReferenceMemory );

  }

  //
  // (2) Split the diffusion image into a 3d+t regular image, extract only the weighted images
  //
  typename SplitFilterType::Pointer split_filter = SplitFilterType::New();
  split_filter->SetInput (input->GetVectorImage() );
  split_filter->SetExtractAllAboveThreshold(20, input->GetB_ValueMap() );

  try
  {
    split_filter->Update();
  }
  catch( const itk::ExceptionObject &e)
  {
    mitkThrow() << " Caught exception from SplitImageFilter : " << e.what();
  }

  mitk::Image::Pointer splittedImage = mitk::Image::New();
  splittedImage->InitializeByItk( split_filter->GetOutput() );
  splittedImage->SetImportChannel( split_filter->GetOutput()->GetBufferPointer(),
                                   mitk::Image::CopyMemory );

  //
  // (3) Use again the time-selector to access the components separately in order
  //     to perform the registration of  Image -> unweighted reference
  //

  mitk::PyramidImageRegistrationMethod::Pointer weightedRegistrationMethod
      = mitk::PyramidImageRegistrationMethod::New();

  weightedRegistrationMethod->SetTransformToAffine();
  weightedRegistrationMethod->SetCrossModalityOn();
  //
  //   - (3.1) Create a reference image by averaging the aligned b0 images
  //
  //   !!!FIXME: For rapid prototyping using the first one
  //

  weightedRegistrationMethod->SetFixedImage( b0referenceImage );

  //
  //   - (3.2) Register all timesteps in the splitted image onto the first reference
  //
  unsigned int maxImageIdx = splittedImage->GetTimeSteps();
  mitk::TimeSlicedGeometry* tsg = splittedImage->GetTimeSlicedGeometry();
  tsg->ExpandToNumberOfTimeSteps( maxImageIdx+1 );

  mitk::Image::Pointer registeredWeighted = mitk::Image::New();
  registeredWeighted->Initialize( splittedImage->GetPixelType(0), *tsg );

  // insert the first unweighted reference as the first volume
  registeredWeighted->SetImportVolume( b0referenceImage->GetData(),
                                      0,0, mitk::Image::CopyMemory );

  // mitk::Image::Pointer registeredWeighted = splittedImage->Clone();
  // this time start at 0, we have only gradient images in the 3d+t file
  // the reference image comes form an other image
  mitk::ImageTimeSelector::Pointer t_selector_w =
      mitk::ImageTimeSelector::New();

  t_selector_w->SetInput( splittedImage );

  for( unsigned int i=0; i<maxImageIdx; i++)
  {
    t_selector_w->SetTimeNr(i);
    t_selector_w->Update();

    weightedRegistrationMethod->SetMovingImage( t_selector_w->GetOutput() );

    try
    {
      MITK_INFO << " === (" << i+1 <<"/"<< maxImageIdx << ") :: Starting registration";
      weightedRegistrationMethod->Update();
    }
    catch( const itk::ExceptionObject& e)
    {
      mitkThrow() << "Failed to register the b0 images, the PyramidRegistration threw an exception: \n" << e.what();
    }

    // allow expansion
    registeredWeighted->SetImportVolume( weightedRegistrationMethod->GetResampledMovingImage()->GetData(),
                                         i+1, 0, mitk::Image::CopyMemory);
  }

  //
  // (4) Cast the resulting image back to an diffusion weighted image
  //
  typename DiffusionImageType::GradientDirectionContainerType *gradients = input->GetDirections();
  typename DiffusionImageType::GradientDirectionContainerType::Pointer gradients_new =
      DiffusionImageType::GradientDirectionContainerType::New();
  typename DiffusionImageType::GradientDirectionType bzero_vector;
  bzero_vector.fill(0);

  // compose the direction vector
  //  - no direction for the first image
  //  - correct ordering of the directions based on the index list
  gradients_new->push_back( bzero_vector );

  typename SplitFilterType::IndexListType index_list = split_filter->GetIndexList();
  typename SplitFilterType::IndexListType::const_iterator lIter = index_list.begin();

  while( lIter != index_list.end() )
  {
    gradients_new->push_back( gradients->at( *lIter ) );
    ++lIter;
  }

  typename mitk::ImageToDiffusionImageSource< DiffusionPixelType >::Pointer caster =
      mitk::ImageToDiffusionImageSource< DiffusionPixelType >::New();

  caster->SetImage( registeredWeighted );
  caster->SetBValue( input->GetB_Value() );
  caster->SetGradientDirections( gradients_new.GetPointer() );

  try
  {
    caster->Update();
  }
  catch( const itk::ExceptionObject& e)
  {
    MITK_ERROR << "Casting back to diffusion image failed: ";
    mitkThrow() << "Subprocess failed with exception: " << e.what();
  }

  OutputImagePointerType output = caster->GetOutput();

  this->GetOutput()->SetVectorImage(output->GetVectorImage());
  this->GetOutput()->SetB_Value(output->GetB_Value());
  this->GetOutput()->SetDirections(output->GetDirections());
  this->GetOutput()->SetMeasurementFrame(output->GetMeasurementFrame());
  this->GetOutput()->InitializeFromVectorImage();

  this->GetOutput()->Modified();
}

#endif // MITKDIFFUSIONIMAGETODIFFUSIONIMAGEFILTER_CPP
<commit_msg>Added gradient correction step<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#ifndef MITKDIFFUSIONIMAGETODIFFUSIONIMAGEFILTER_CPP
#define MITKDIFFUSIONIMAGETODIFFUSIONIMAGEFILTER_CPP

#include "mitkDWIHeadMotionCorrectionFilter.h"

#include "itkSplitDWImageFilter.h"
#include "itkB0ImageExtractionToSeparateImageFilter.h"

#include "mitkImageTimeSelector.h"

#include "mitkPyramidImageRegistrationMethod.h"
#include "mitkImageToDiffusionImageSource.h"

#include "mitkDiffusionImageCorrectionFilter.h"

#include <vector>

#include "mitkIOUtil.h"

template< typename DiffusionPixelType>
mitk::DWIHeadMotionCorrectionFilter<DiffusionPixelType>
::DWIHeadMotionCorrectionFilter()
{

}

template< typename DiffusionPixelType>
void mitk::DWIHeadMotionCorrectionFilter<DiffusionPixelType>
::GenerateData()
{
  typedef itk::SplitDWImageFilter< DiffusionPixelType, DiffusionPixelType> SplitFilterType;

  DiffusionImageType* input = const_cast<DiffusionImageType*>(this->GetInput(0));

  //
  //  (1) Extract the b-zero images to a 3d+t image, register them by NCorr metric and
  //     rigid registration : they will then be used are reference image for registering
  //     the gradient images
  //
  typedef itk::B0ImageExtractionToSeparateImageFilter< DiffusionPixelType, DiffusionPixelType> B0ExtractorType;
  typename B0ExtractorType::Pointer b0_extractor = B0ExtractorType::New();
  b0_extractor->SetInput( input->GetVectorImage() );
  b0_extractor->SetDirections( input->GetDirections() );
  b0_extractor->Update();

  mitk::Image::Pointer b0Image = mitk::Image::New();
  b0Image->InitializeByItk( b0_extractor->GetOutput() );
  b0Image->SetImportChannel( b0_extractor->GetOutput()->GetBufferPointer(),
                             mitk::Image::CopyMemory );

  // (2.1) Use the extractor to access the extracted b0 volumes
  mitk::ImageTimeSelector::Pointer t_selector =
      mitk::ImageTimeSelector::New();

  t_selector->SetInput( b0Image );
  t_selector->SetTimeNr(0);
  t_selector->Update();

  // first unweighted image as reference space for the registration
  mitk::Image::Pointer b0referenceImage = t_selector->GetOutput();

  mitk::PyramidImageRegistrationMethod::Pointer registrationMethod = mitk::PyramidImageRegistrationMethod::New();
  registrationMethod->SetFixedImage( b0referenceImage );
  registrationMethod->SetTransformToRigid();

  // the unweighted images are of same modality
  registrationMethod->SetCrossModalityOff();

  // Initialize the temporary output image
  mitk::Image::Pointer registeredB0Image = b0Image->Clone();
  const unsigned int numberOfb0Images = b0Image->GetTimeSteps();

  mitk::ImageTimeSelector::Pointer t_selector2 =
      mitk::ImageTimeSelector::New();

  t_selector2->SetInput( b0Image );

  for( unsigned int i=1; i<numberOfb0Images; i++)
  {

    t_selector2->SetTimeNr(i);
    t_selector2->Update();

    registrationMethod->SetMovingImage( t_selector2->GetOutput() );

    try
    {
      MITK_INFO << " === (" << i <<"/"<< numberOfb0Images-1 << ") :: Starting registration";
      registrationMethod->Update();
    }
    catch( const itk::ExceptionObject& e)
    {
      mitkThrow() << "Failed to register the b0 images, the PyramidRegistration threw an exception: \n" << e.what();
    }

    // import volume to the inter-results
    registeredB0Image->SetImportVolume( registrationMethod->GetResampledMovingImage()->GetData(),
                                       i, 0, mitk::Image::ReferenceMemory );

  }

  //
  // (2) Split the diffusion image into a 3d+t regular image, extract only the weighted images
  //
  typename SplitFilterType::Pointer split_filter = SplitFilterType::New();
  split_filter->SetInput (input->GetVectorImage() );
  split_filter->SetExtractAllAboveThreshold(20, input->GetB_ValueMap() );

  try
  {
    split_filter->Update();
  }
  catch( const itk::ExceptionObject &e)
  {
    mitkThrow() << " Caught exception from SplitImageFilter : " << e.what();
  }

  mitk::Image::Pointer splittedImage = mitk::Image::New();
  splittedImage->InitializeByItk( split_filter->GetOutput() );
  splittedImage->SetImportChannel( split_filter->GetOutput()->GetBufferPointer(),
                                   mitk::Image::CopyMemory );

  //
  // (3) Use again the time-selector to access the components separately in order
  //     to perform the registration of  Image -> unweighted reference
  //

  mitk::PyramidImageRegistrationMethod::Pointer weightedRegistrationMethod
      = mitk::PyramidImageRegistrationMethod::New();

  weightedRegistrationMethod->SetTransformToAffine();
  weightedRegistrationMethod->SetCrossModalityOn();
  //
  //   - (3.1) Create a reference image by averaging the aligned b0 images
  //
  //   !!!FIXME: For rapid prototyping using the first one
  //

  weightedRegistrationMethod->SetFixedImage( b0referenceImage );

  //
  //   - (3.2) Register all timesteps in the splitted image onto the first reference
  //
  unsigned int maxImageIdx = splittedImage->GetTimeSteps();
  mitk::TimeSlicedGeometry* tsg = splittedImage->GetTimeSlicedGeometry();
  tsg->ExpandToNumberOfTimeSteps( maxImageIdx+1 );

  mitk::Image::Pointer registeredWeighted = mitk::Image::New();
  registeredWeighted->Initialize( splittedImage->GetPixelType(0), *tsg );

  // insert the first unweighted reference as the first volume
  registeredWeighted->SetImportVolume( b0referenceImage->GetData(),
                                      0,0, mitk::Image::CopyMemory );

  // mitk::Image::Pointer registeredWeighted = splittedImage->Clone();
  // this time start at 0, we have only gradient images in the 3d+t file
  // the reference image comes form an other image
  mitk::ImageTimeSelector::Pointer t_selector_w =
      mitk::ImageTimeSelector::New();

  t_selector_w->SetInput( splittedImage );

  // store the rotation parts of the transformations in a vector
  typedef mitk::PyramidImageRegistrationMethod::TransformMatrixType MatrixType;
  std::vector< MatrixType > estimated_transforms;

  for( unsigned int i=0; i<maxImageIdx; i++)
  {
    t_selector_w->SetTimeNr(i);
    t_selector_w->Update();

    weightedRegistrationMethod->SetMovingImage( t_selector_w->GetOutput() );

    try
    {
      MITK_INFO << " === (" << i+1 <<"/"<< maxImageIdx << ") :: Starting registration";
      weightedRegistrationMethod->Update();
    }
    catch( const itk::ExceptionObject& e)
    {
      mitkThrow() << "Failed to register the b0 images, the PyramidRegistration threw an exception: \n" << e.what();
    }

    // allow expansion
    registeredWeighted->SetImportVolume( weightedRegistrationMethod->GetResampledMovingImage()->GetData(),
                                         i+1, 0, mitk::Image::CopyMemory);

    estimated_transforms.push_back( weightedRegistrationMethod->GetLastRotationMatrix() );
  }

  //
  // (4) Cast the resulting image back to an diffusion weighted image
  //
  typename DiffusionImageType::GradientDirectionContainerType *gradients = input->GetDirections();
  typename DiffusionImageType::GradientDirectionContainerType::Pointer gradients_new =
      DiffusionImageType::GradientDirectionContainerType::New();
  typename DiffusionImageType::GradientDirectionType bzero_vector;
  bzero_vector.fill(0);

  // compose the direction vector
  //  - no direction for the first image
  //  - correct ordering of the directions based on the index list
  gradients_new->push_back( bzero_vector );

  typename SplitFilterType::IndexListType index_list = split_filter->GetIndexList();
  typename SplitFilterType::IndexListType::const_iterator lIter = index_list.begin();

  while( lIter != index_list.end() )
  {
    gradients_new->push_back( gradients->at( *lIter ) );
    ++lIter;
  }

  typename mitk::ImageToDiffusionImageSource< DiffusionPixelType >::Pointer caster =
      mitk::ImageToDiffusionImageSource< DiffusionPixelType >::New();

  caster->SetImage( registeredWeighted );
  caster->SetBValue( input->GetB_Value() );
  caster->SetGradientDirections( gradients_new.GetPointer() );

  try
  {
    caster->Update();
  }
  catch( const itk::ExceptionObject& e)
  {
    MITK_ERROR << "Casting back to diffusion image failed: ";
    mitkThrow() << "Subprocess failed with exception: " << e.what();
  }

  //
  // (5) Adapt the gradient directions according to the estimated transforms
  //
  typedef mitk::DiffusionImageCorrectionFilter< DiffusionPixelType > CorrectionFilterType;
  typename CorrectionFilterType::Pointer corrector = CorrectionFilterType::New();

  OutputImagePointerType output = caster->GetOutput();
  corrector->SetImage( output );
  corrector->CorrectDirections( estimated_transforms );

  //
  // (6) Pass the corrected image to the filters output port
  //
  this->GetOutput()->SetVectorImage(output->GetVectorImage());
  this->GetOutput()->SetB_Value(output->GetB_Value());
  this->GetOutput()->SetDirections(output->GetDirections());
  this->GetOutput()->SetMeasurementFrame(output->GetMeasurementFrame());
  this->GetOutput()->InitializeFromVectorImage();

  this->GetOutput()->Modified();
}

#endif // MITKDIFFUSIONIMAGETODIFFUSIONIMAGEFILTER_CPP
<|endoftext|>


<commit_before>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.

#include "../include/librealsense2/hpp/rs_sensor.hpp"
#include "../include/librealsense2/hpp/rs_processing.hpp"

#include "proc/synthetic-stream.h"
#include "context.h"
#include "environment.h"
#include "option.h"
#include "colorizer.h"
#include "disparity-transform.h"

namespace librealsense
{
    static color_map hue{ {
        { 255, 0, 0 },
        { 255, 255, 0 },
        { 0, 255, 0 },
        { 0, 255, 255 },
        { 0, 0, 255 },
        { 255, 0, 255 },
        { 255, 0, 0 },
        } };

    static color_map jet{ {
        { 0, 0, 255 },
        { 0, 255, 255 },
        { 255, 255, 0 },
        { 255, 0, 0 },
        { 50, 0, 0 },
        } };

    static color_map classic{ {
        { 30, 77, 203 },
        { 25, 60, 192 },
        { 45, 117, 220 },
        { 204, 108, 191 },
        { 196, 57, 178 },
        { 198, 33, 24 },
        } };

    static color_map grayscale{ {
        { 255, 255, 255 },
        { 0, 0, 0 },
        } };

    static color_map inv_grayscale{ {
        { 0, 0, 0 },
        { 255, 255, 255 },
        } };

    static color_map biomes{ {
        { 0, 0, 204 },
        { 204, 230, 255 },
        { 255, 255, 153 },
        { 170, 255, 128 },
        { 0, 153, 0 },
        { 230, 242, 255 },
        } };

    static color_map cold{ {
        { 230, 247, 255 },
        { 0, 92, 230 },
        { 0, 179, 179 },
        { 0, 51, 153 },
        { 0, 5, 15 }
        } };

    static color_map warm{ {
        { 255, 255, 230 },
        { 255, 204, 0 },
        { 255, 136, 77 },
        { 255, 51, 0 },
        { 128, 0, 0 },
        { 10, 0, 0 }
        } };

    static color_map quantized{ {
        { 255, 255, 255 },
        { 0, 0, 0 },
        }, 6 };

    static color_map pattern{ {
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        } };

    colorizer::colorizer()
        : colorizer("Depth Visualization")
    {}

    colorizer::colorizer(const char* name)
        : stream_filter_processing_block(name),
         _min(0.f), _max(6.f), _equalize(true),
         _target_stream_profile(), _histogram()
    {
        _histogram = std::vector<int>(MAX_DEPTH, 0);
        _hist_data = _histogram.data();
        _stream_filter.stream = RS2_STREAM_DEPTH;
        _stream_filter.format = RS2_FORMAT_Z16;

        _maps = { &jet, &classic, &grayscale, &inv_grayscale, &biomes, &cold, &warm, &quantized, &pattern, &hue };

        auto min_opt = std::make_shared<ptr_option<float>>(0.f, 16.f, 0.1f, 0.f, &_min, "Min range in meters");

        auto max_opt = std::make_shared<ptr_option<float>>(0.f, 16.f, 0.1f, 6.f, &_max, "Max range in meters");

        register_option(RS2_OPTION_MAX_DISTANCE,
            std::make_shared<max_distance_option>(
                max_opt,
                min_opt));

        register_option(RS2_OPTION_MIN_DISTANCE,
            std::make_shared<min_distance_option>(
                min_opt,
                max_opt));

        auto color_map = std::make_shared<ptr_option<int>>(0, (int)_maps.size() - 1, 1, 0, &_map_index, "Color map");
        color_map->set_description(0.f, "Jet");
        color_map->set_description(1.f, "Classic");
        color_map->set_description(2.f, "White to Black");
        color_map->set_description(3.f, "Black to White");
        color_map->set_description(4.f, "Bio");
        color_map->set_description(5.f, "Cold");
        color_map->set_description(6.f, "Warm");
        color_map->set_description(7.f, "Quantized");
        color_map->set_description(8.f, "Pattern");
        color_map->set_description(9.f, "Hue");
        register_option(RS2_OPTION_COLOR_SCHEME, color_map);

        auto preset_opt = std::make_shared<ptr_option<int>>(0, 3, 1, 0, &_preset, "Preset depth colorization");
        preset_opt->set_description(0.f, "Dynamic");
        preset_opt->set_description(1.f, "Fixed");
        preset_opt->set_description(2.f, "Near");
        preset_opt->set_description(3.f, "Far");

        preset_opt->on_set([this](float val)
        {
            if (fabs(val - 0.f) < 1e-6)
            {
                // Dynamic
                _equalize = true;
                _map_index = 0;
            }
            if (fabs(val - 1.f) < 1e-6)
            {
                // Fixed
                _equalize = false;
                _map_index = 0;
                _min = 0.f;
                _max = 6.f;
            }
            if (fabs(val - 2.f) < 1e-6)
            {
                // Near
                _equalize = false;
                _map_index = 1;
                _min = 0.3f;
                _max = 1.5f;
            }
            if (fabs(val - 3.f) < 1e-6)
            {
                // Far
                _equalize = false;
                _map_index = 0;
                _min = 1.f;
                _max = 16.f;
            }
        });
        register_option(RS2_OPTION_VISUAL_PRESET, preset_opt);

        auto hist_opt = std::make_shared<ptr_option<bool>>(false, true, true, true, &_equalize, "Perform histogram equalization");
        register_option(RS2_OPTION_HISTOGRAM_EQUALIZATION_ENABLED, hist_opt);
    }

    bool colorizer::should_process(const rs2::frame& frame)
    {
        if (!frame || frame.is<rs2::frameset>())
            return false;

        if (frame.get_profile().stream_type() != RS2_STREAM_DEPTH)
            return false;

        return true;
    }

    rs2::frame colorizer::process_frame(const rs2::frame_source& source, const rs2::frame& f)
    {
        if (f.get_profile().get() != _source_stream_profile.get())
        {
            _source_stream_profile = f.get_profile();
            _target_stream_profile = f.get_profile().clone(RS2_STREAM_DEPTH, f.get_profile().stream_index(), RS2_FORMAT_RGB8);

            auto info = disparity_info::update_info_from_frame(f);
            _depth_units = info.depth_units;
            _d2d_convert_factor = info.d2d_convert_factor;
        }

        auto make_equalized_histogram = [this](const rs2::video_frame& depth, rs2::video_frame rgb)
        {
            auto depth_format = depth.get_profile().format();
            const auto w = depth.get_width(), h = depth.get_height();
            auto rgb_data = reinterpret_cast<uint8_t*>(const_cast<void *>(rgb.get_data()));
            auto coloring_function = [&, this](float data) {
                auto hist_data = _hist_data[(int)data];
                auto pixels = (float)_hist_data[MAX_DEPTH - 1];
                return (hist_data / pixels);
            };

            if (depth_format == RS2_FORMAT_DISPARITY32)
            {
                auto depth_data = reinterpret_cast<const float*>(depth.get_data());
                update_histogram(_hist_data, depth_data, w, h);
                make_rgb_data<float>(depth_data, rgb_data, w, h, coloring_function);
            }
            else if (depth_format == RS2_FORMAT_Z16)
            {
                auto depth_data = reinterpret_cast<const uint16_t*>(depth.get_data());
                update_histogram(_hist_data, depth_data, w, h);
                make_rgb_data<uint16_t>(depth_data, rgb_data, w, h, coloring_function);
            }
        };

        auto make_value_cropped_frame = [this](const rs2::video_frame& depth, rs2::video_frame rgb)
        {
            auto depth_format = depth.get_profile().format();
            const auto w = depth.get_width(), h = depth.get_height();
            auto rgb_data = reinterpret_cast<uint8_t*>(const_cast<void *>(rgb.get_data()));

            if (depth_format == RS2_FORMAT_DISPARITY32)
            {
                auto depth_data = reinterpret_cast<const float*>(depth.get_data());
                // convert from depth min max to disparity min max
                // note: max min value is inverted in disparity domain
                auto __min = _min;
                if (__min < 1e-6f) { __min = 1e-6f; } // Min value set to prevent zero division. only when _min is zero.
                auto max = (_d2d_convert_factor / (__min)) * _depth_units + .5f;
                auto min = (_d2d_convert_factor / (_max)) * _depth_units + .5f;
                auto coloring_function = [&, this](float data) {
                    return (data - min) / (max - min);
                };
                make_rgb_data<float>(depth_data, rgb_data, w, h, coloring_function);
            }
            else if (depth_format == RS2_FORMAT_Z16)
            {
                auto depth_data = reinterpret_cast<const uint16_t*>(depth.get_data());
                auto min = _min;
                auto max = _max;
                auto coloring_function = [&, this](float data) {
                    return (data * _depth_units - min) / (max - min);
                };
                make_rgb_data<uint16_t>(depth_data, rgb_data, w, h, coloring_function);
            }
        };

        rs2::frame ret;

        auto vf = f.as<rs2::video_frame>();
        ret = source.allocate_video_frame(_target_stream_profile, f, 3, vf.get_width(), vf.get_height(), vf.get_width() * 3, RS2_EXTENSION_VIDEO_FRAME);

        if (_equalize)
            make_equalized_histogram(f, ret);
        else
            make_value_cropped_frame(f, ret);

        return ret;
    }
}
<commit_msg>DSO-8689 fix : division by 0<commit_after>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.

#include "../include/librealsense2/hpp/rs_sensor.hpp"
#include "../include/librealsense2/hpp/rs_processing.hpp"

#include "proc/synthetic-stream.h"
#include "context.h"
#include "environment.h"
#include "option.h"
#include "colorizer.h"
#include "disparity-transform.h"

namespace librealsense
{
    static color_map hue{ {
        { 255, 0, 0 },
        { 255, 255, 0 },
        { 0, 255, 0 },
        { 0, 255, 255 },
        { 0, 0, 255 },
        { 255, 0, 255 },
        { 255, 0, 0 },
        } };

    static color_map jet{ {
        { 0, 0, 255 },
        { 0, 255, 255 },
        { 255, 255, 0 },
        { 255, 0, 0 },
        { 50, 0, 0 },
        } };

    static color_map classic{ {
        { 30, 77, 203 },
        { 25, 60, 192 },
        { 45, 117, 220 },
        { 204, 108, 191 },
        { 196, 57, 178 },
        { 198, 33, 24 },
        } };

    static color_map grayscale{ {
        { 255, 255, 255 },
        { 0, 0, 0 },
        } };

    static color_map inv_grayscale{ {
        { 0, 0, 0 },
        { 255, 255, 255 },
        } };

    static color_map biomes{ {
        { 0, 0, 204 },
        { 204, 230, 255 },
        { 255, 255, 153 },
        { 170, 255, 128 },
        { 0, 153, 0 },
        { 230, 242, 255 },
        } };

    static color_map cold{ {
        { 230, 247, 255 },
        { 0, 92, 230 },
        { 0, 179, 179 },
        { 0, 51, 153 },
        { 0, 5, 15 }
        } };

    static color_map warm{ {
        { 255, 255, 230 },
        { 255, 204, 0 },
        { 255, 136, 77 },
        { 255, 51, 0 },
        { 128, 0, 0 },
        { 10, 0, 0 }
        } };

    static color_map quantized{ {
        { 255, 255, 255 },
        { 0, 0, 0 },
        }, 6 };

    static color_map pattern{ {
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        { 255, 255, 255 },
        { 0, 0, 0 },
        } };

    colorizer::colorizer()
        : colorizer("Depth Visualization")
    {}

    colorizer::colorizer(const char* name)
        : stream_filter_processing_block(name),
         _min(0.f), _max(6.f), _equalize(true),
         _target_stream_profile(), _histogram()
    {
        _histogram = std::vector<int>(MAX_DEPTH, 0);
        _hist_data = _histogram.data();
        _stream_filter.stream = RS2_STREAM_DEPTH;
        _stream_filter.format = RS2_FORMAT_Z16;

        _maps = { &jet, &classic, &grayscale, &inv_grayscale, &biomes, &cold, &warm, &quantized, &pattern, &hue };

        auto min_opt = std::make_shared<ptr_option<float>>(0.f, 16.f, 0.1f, 0.f, &_min, "Min range in meters");

        auto max_opt = std::make_shared<ptr_option<float>>(0.f, 16.f, 0.1f, 6.f, &_max, "Max range in meters");

        register_option(RS2_OPTION_MAX_DISTANCE,
            std::make_shared<max_distance_option>(
                max_opt,
                min_opt));

        register_option(RS2_OPTION_MIN_DISTANCE,
            std::make_shared<min_distance_option>(
                min_opt,
                max_opt));

        auto color_map = std::make_shared<ptr_option<int>>(0, (int)_maps.size() - 1, 1, 0, &_map_index, "Color map");
        color_map->set_description(0.f, "Jet");
        color_map->set_description(1.f, "Classic");
        color_map->set_description(2.f, "White to Black");
        color_map->set_description(3.f, "Black to White");
        color_map->set_description(4.f, "Bio");
        color_map->set_description(5.f, "Cold");
        color_map->set_description(6.f, "Warm");
        color_map->set_description(7.f, "Quantized");
        color_map->set_description(8.f, "Pattern");
        color_map->set_description(9.f, "Hue");
        register_option(RS2_OPTION_COLOR_SCHEME, color_map);

        auto preset_opt = std::make_shared<ptr_option<int>>(0, 3, 1, 0, &_preset, "Preset depth colorization");
        preset_opt->set_description(0.f, "Dynamic");
        preset_opt->set_description(1.f, "Fixed");
        preset_opt->set_description(2.f, "Near");
        preset_opt->set_description(3.f, "Far");

        preset_opt->on_set([this](float val)
        {
            if (fabs(val - 0.f) < 1e-6)
            {
                // Dynamic
                _equalize = true;
                _map_index = 0;
            }
            if (fabs(val - 1.f) < 1e-6)
            {
                // Fixed
                _equalize = false;
                _map_index = 0;
                _min = 0.f;
                _max = 6.f;
            }
            if (fabs(val - 2.f) < 1e-6)
            {
                // Near
                _equalize = false;
                _map_index = 1;
                _min = 0.3f;
                _max = 1.5f;
            }
            if (fabs(val - 3.f) < 1e-6)
            {
                // Far
                _equalize = false;
                _map_index = 0;
                _min = 1.f;
                _max = 16.f;
            }
        });
        register_option(RS2_OPTION_VISUAL_PRESET, preset_opt);

        auto hist_opt = std::make_shared<ptr_option<bool>>(false, true, true, true, &_equalize, "Perform histogram equalization");
        register_option(RS2_OPTION_HISTOGRAM_EQUALIZATION_ENABLED, hist_opt);
    }

    bool colorizer::should_process(const rs2::frame& frame)
    {
        if (!frame || frame.is<rs2::frameset>())
            return false;

        if (frame.get_profile().stream_type() != RS2_STREAM_DEPTH)
            return false;

        return true;
    }

    rs2::frame colorizer::process_frame(const rs2::frame_source& source, const rs2::frame& f)
    {
        if (f.get_profile().get() != _source_stream_profile.get())
        {
            _source_stream_profile = f.get_profile();
            _target_stream_profile = f.get_profile().clone(RS2_STREAM_DEPTH, f.get_profile().stream_index(), RS2_FORMAT_RGB8);

            auto info = disparity_info::update_info_from_frame(f);
            _depth_units = info.depth_units;
            _d2d_convert_factor = info.d2d_convert_factor;
        }

        auto make_equalized_histogram = [this](const rs2::video_frame& depth, rs2::video_frame rgb)
        {
            auto depth_format = depth.get_profile().format();
            const auto w = depth.get_width(), h = depth.get_height();
            auto rgb_data = reinterpret_cast<uint8_t*>(const_cast<void *>(rgb.get_data()));
            auto coloring_function = [&, this](float data) {
                auto hist_data = _hist_data[(int)data];
                auto pixels = (float)_hist_data[MAX_DEPTH - 1];
                return (hist_data / pixels);
            };

            if (depth_format == RS2_FORMAT_DISPARITY32)
            {
                auto depth_data = reinterpret_cast<const float*>(depth.get_data());
                update_histogram(_hist_data, depth_data, w, h);
                make_rgb_data<float>(depth_data, rgb_data, w, h, coloring_function);
            }
            else if (depth_format == RS2_FORMAT_Z16)
            {
                auto depth_data = reinterpret_cast<const uint16_t*>(depth.get_data());
                update_histogram(_hist_data, depth_data, w, h);
                make_rgb_data<uint16_t>(depth_data, rgb_data, w, h, coloring_function);
            }
        };

        auto make_value_cropped_frame = [this](const rs2::video_frame& depth, rs2::video_frame rgb)
        {
            auto depth_format = depth.get_profile().format();
            const auto w = depth.get_width(), h = depth.get_height();
            auto rgb_data = reinterpret_cast<uint8_t*>(const_cast<void *>(rgb.get_data()));

            if (depth_format == RS2_FORMAT_DISPARITY32)
            {
                auto depth_data = reinterpret_cast<const float*>(depth.get_data());
                // convert from depth min max to disparity min max
                // note: max min value is inverted in disparity domain
                auto __min = _min;
                if (__min < 1e-6f) { __min = 1e-6f; } // Min value set to prevent zero division. only when _min is zero.
                auto max = (_d2d_convert_factor / (__min)) * _depth_units + .5f;
                auto min = (_d2d_convert_factor / (_max)) * _depth_units + .5f;
                auto coloring_function = [&, this](float data) {
                    return (data - min) / (max - min);
                };
                make_rgb_data<float>(depth_data, rgb_data, w, h, coloring_function);
            }
            else if (depth_format == RS2_FORMAT_Z16)
            {
                auto depth_data = reinterpret_cast<const uint16_t*>(depth.get_data());
                auto min = _min;
                auto max = _max;
                auto coloring_function = [&, this](float data) {
                    if (max == min) return data * _depth_units;
                    return (data * _depth_units - min) / (max - min);
                };
                make_rgb_data<uint16_t>(depth_data, rgb_data, w, h, coloring_function);
            }
        };

        rs2::frame ret;

        auto vf = f.as<rs2::video_frame>();
        ret = source.allocate_video_frame(_target_stream_profile, f, 3, vf.get_width(), vf.get_height(), vf.get_width() * 3, RS2_EXTENSION_VIDEO_FRAME);

        if (_equalize)
            make_equalized_histogram(f, ret);
        else
            make_value_cropped_frame(f, ret);

        return ret;
    }
}
<|endoftext|>


<commit_before>/*
Copyright (C) 2011 by Ladislav Hrabcak

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.
*/

#include "benchmark.h"

#include "base/base.h"
#include "base/frame_context.h"
#include "base/canvas.h"
#include "scene.h"
#include "renderer.h"

#include <glm/gtc/matrix_transform.hpp>

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

benchmark::benchmark()
    : app()
    , _scene(new scene(this))
{
    _stats_str.resize(4096);
    memset(&_stats_str[0], 0, _stats_str.size());
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

benchmark::~benchmark() {}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void benchmark::start()
{
    char tmp[2048];

    sprintf(
        tmp,
        "%s - Generating scene with %u unique meshes and textures",
        get_wnd_name(),
        scene::MAX_BLOCK_COUNT);

    base::set_win_title(tmp);

    // start renderer thread
    _renderer.reset(new renderer(this, SRC_LOCATION));

    app::start();

    _scene->post_gpu_init();

    base::set_win_title(get_wnd_name());
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void benchmark::gpu_init()
{
    app::gpu_init();

    _scene->init_gpu_stuff(SRC_LOCATION);
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void benchmark::stop()
{
	_renderer->stop(SRC_LOCATION);
	app::stop();
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void benchmark::draw_frame()
{
	base::frame_context *ctx = 0;

	// wait for renderer
	while((ctx = _renderer->pop_frame_context_from_pool()) == 0 && !_shutdown)
        base::sleep_ms(0);

    if (_shutdown)
        return;

	assert(ctx != 0);

	app::begin_frame();

	app::create_perspective_matrix(ctx);
	app::update_camera(ctx);

    _scene->update(ctx);

    // prepare stats
    static base::stats_data stats;
    static int nframes = 0;
    static __int64 start_time = 0;
	static int nframes_total = 0;
	static float dtime_total = 0.0f;
	static int test_cycles = 0;

    if (start_time == 0 && ctx->_time != 0)
        start_time = ctx->_time;

    if (start_time != 0) {
        nframes++;
        stats += ctx->_stats;
        stats._cpu_time += ctx->_stats._cpu_time;
        stats._gpu_time += ctx->_stats._gpu_time;

        const __int64 freq = base::hptimer().freq();
        const __int64 dt = ((ctx->_time - start_time) * 1000000) / freq;

        if (dt > 1000000) {
            const float dtf = float(dt) * 0.000001f;
            const float fps = float(nframes) / dtf;
            const float r_nframes = 1.0f / float(nframes);

            sprintf(
                &_stats_str[0],
                "tex:      %.0f MB\n"
                "buf:      %.0f MB\n"
                "MVtx/s:   %.0f\n"
                "MVtx:     %.3f\n"
                "MTris/s:  %.0f\n"
                "MTris:    %.3f\n"
                "KDraw/s:  %.0f\n"
                "KDraw:    %.3f\n"
                "gpu:      %.3f ms\n"
                "cpu:      %.3f ms\n"
                "fps:      %.0f\n\n"
                "one mesh: %s\n"
                "vertex data: %s\n"
                "mesh size: %u\n"
                "textures: %ux%u BGRA8\n"
                "tex freq: %u\n"
                "GPU: %s\n\n"
                "%s",

                float(stats._texture_mem) / float(1024 * 1024),
                float(stats._buffer_mem) / float(1024 * 1024),
                float(stats._nvertices) * 0.000001 / dtf,
                float(stats._nvertices) * 0.000001 / float(nframes),
                float(stats._ntriangles) * 0.000001 / dtf,
                float(stats._ntriangles) * 0.000001 / float(nframes),
                float(stats._ndrawcalls) * 0.001 / dtf,
                float(stats._ndrawcalls) * 0.001 / nframes,
                stats._gpu_time * r_nframes,
                stats._cpu_time * r_nframes,
                fps,
                base::cfg().one_mesh ? "true" : "false",
                base::cfg().use_vbo ? "VERTEX BUFFER" : "TEXTURE BUFFER",
                base::cfg().mesh_size,
                base::cfg().tex_size, base::cfg().tex_size,
                base::cfg().tex_freq,
                _renderer->get_gpu_str(),
                get_test_name());

			if (test_cycles >= 1){
				_test_stats += stats;
				_test_stats._cpu_time += stats._cpu_time;
				_test_stats._gpu_time += stats._gpu_time;
				nframes_total += nframes;
				dtime_total += dtf;
			}

			if (base::cfg().test != -1 &&  test_cycles == 3){
				write_test_data_csv("test.csv", _test_stats, dtime_total, nframes_total);
				_shutdown = true;
			}

			start_time = ctx->_time;
			nframes = 0;
            stats = base::stats_data();
			test_cycles++;
        }

        //
        _canvas->fill_rect(
            ctx,
            glm::vec2(0),
            glm::vec2(256, 260),
            glm::vec4(0.0, 0.0, 0.0, 0.6));

        _canvas->draw_text(
            ctx,
            glm::vec2(3),
            &_stats_str[0],
            glm::vec4(1, 1, 1, 1),
            _fnt_mono.get());
    }

	_renderer->push_frame_context(ctx);
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void benchmark::gpu_draw_frame(base::frame_context * const ctx)
{
    glDisable(GL_BLEND);
    _scene->gpu_draw(ctx);

    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    base::canvas::render(ctx);
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void benchmark::key(const int key, const bool down)
{
	app::key(key, down);

}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

const char* benchmark::get_test_name() const
{
    return base::cfg().test != -1
        ? _scene->get_test_name(base::cfg().test)
        : "Interactive";
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

bool benchmark::write_test_data_csv(
	const char * file_name,
	const base::stats_data & stats,
	const float time,
	const int nframes)
{
	FILE * pFile;
	pFile = fopen(file_name, "r+");

	if (pFile == NULL){
		pFile = fopen(file_name, "w");
		if (pFile == NULL){
			return false;
		}

		fputs(
			"test_name,"
			"gpu_gl_name,"
			"use_vbo,"
			"tex_freq,"
			"mesh_size,"
			"one_mesh,"
			"frames,"
			"render_time,"
			"cpu_render_time (ms),"
			"gpu_render_time (ms),"
			"dc,"
			"ntri (Mtri),"
			"nverts (Mvtx),"
			"buf_mem (MB),"
			"tex_mem (MB)",
			pFile);
	}
	else{
		fseek(pFile, 0, SEEK_END);
	}

	fprintf(
		pFile,
		"\n%s,%s,%s,%i,%i,%s,%u,%f,%f,%f,%u,%u,%u,%u,%u",
		this->get_test_name(),
		_renderer->get_gpu_str(),
		base::cfg().use_vbo ? "true" : "false",
		base::cfg().tex_freq,
		base::cfg().mesh_size,
		base::cfg().one_mesh ? "true" : "false",
		nframes,
		time,
		stats._cpu_time,
		stats._gpu_time,
		stats._ndrawcalls,
		stats._ntriangles,
		stats._nvertices,
		stats._buffer_mem >> 20,
		stats._texture_mem >> 20);

	fclose(pFile);

	return true;
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=<commit_msg>tex mode<commit_after>/*
Copyright (C) 2011 by Ladislav Hrabcak

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.
*/

#include "benchmark.h"

#include "base/base.h"
#include "base/frame_context.h"
#include "base/canvas.h"
#include "scene.h"
#include "renderer.h"

#include <glm/gtc/matrix_transform.hpp>

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

benchmark::benchmark()
    : app()
    , _scene(new scene(this))
{
    _stats_str.resize(4096);
    memset(&_stats_str[0], 0, _stats_str.size());
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

benchmark::~benchmark() {}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void benchmark::start()
{
    char tmp[2048];

    sprintf(
        tmp,
        "%s - Generating scene with %u unique meshes and textures",
        get_wnd_name(),
        scene::MAX_BLOCK_COUNT);

    base::set_win_title(tmp);

    // start renderer thread
    _renderer.reset(new renderer(this, SRC_LOCATION));

    app::start();

    _scene->post_gpu_init();

    base::set_win_title(get_wnd_name());
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void benchmark::gpu_init()
{
    app::gpu_init();

    _scene->init_gpu_stuff(SRC_LOCATION);
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void benchmark::stop()
{
	_renderer->stop(SRC_LOCATION);
	app::stop();
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void benchmark::draw_frame()
{
	base::frame_context *ctx = 0;

	// wait for renderer
	while((ctx = _renderer->pop_frame_context_from_pool()) == 0 && !_shutdown)
        base::sleep_ms(0);

    if (_shutdown)
        return;

	assert(ctx != 0);

	app::begin_frame();

	app::create_perspective_matrix(ctx);
	app::update_camera(ctx);

    _scene->update(ctx);

    // prepare stats
    static base::stats_data stats;
    static int nframes = 0;
    static __int64 start_time = 0;
	static int nframes_total = 0;
	static float dtime_total = 0.0f;
	static int test_cycles = 0;

    if (start_time == 0 && ctx->_time != 0)
        start_time = ctx->_time;

    if (start_time != 0) {
        nframes++;
        stats += ctx->_stats;
        stats._cpu_time += ctx->_stats._cpu_time;
        stats._gpu_time += ctx->_stats._gpu_time;

        const __int64 freq = base::hptimer().freq();
        const __int64 dt = ((ctx->_time - start_time) * 1000000) / freq;

        if (dt > 1000000) {
            const float dtf = float(dt) * 0.000001f;
            const float fps = float(nframes) / dtf;
            const float r_nframes = 1.0f / float(nframes);

            sprintf(
                &_stats_str[0],
                "tex:      %.0f MB\n"
                "buf:      %.0f MB\n"
                "MVtx/s:   %.0f\n"
                "MVtx:     %.3f\n"
                "MTris/s:  %.0f\n"
                "MTris:    %.3f\n"
                "KDraw/s:  %.0f\n"
                "KDraw:    %.3f\n"
                "gpu:      %.3f ms\n"
                "cpu:      %.3f ms\n"
                "fps:      %.0f\n\n"
                "one mesh: %s\n"
                "vertex data: %s\n"
                "mesh size: %u\n"
                "textures: %ux%u BGRA8\n"
                "tex freq: %u\n"
                "GPU: %s\n\n"
                "%s",

                float(stats._texture_mem) / float(1024 * 1024),
                float(stats._buffer_mem) / float(1024 * 1024),
                float(stats._nvertices) * 0.000001 / dtf,
                float(stats._nvertices) * 0.000001 / float(nframes),
                float(stats._ntriangles) * 0.000001 / dtf,
                float(stats._ntriangles) * 0.000001 / float(nframes),
                float(stats._ndrawcalls) * 0.001 / dtf,
                float(stats._ndrawcalls) * 0.001 / nframes,
                stats._gpu_time * r_nframes,
                stats._cpu_time * r_nframes,
                fps,
                base::cfg().one_mesh ? "true" : "false",
                base::cfg().use_vbo ? "VERTEX BUFFER" : "TEXTURE BUFFER",
                base::cfg().mesh_size,
                base::cfg().tex_size, base::cfg().tex_size,
                base::cfg().tex_freq,
                _renderer->get_gpu_str(),
                get_test_name());

			if (test_cycles >= 1){
				_test_stats += stats;
				_test_stats._cpu_time += stats._cpu_time;
				_test_stats._gpu_time += stats._gpu_time;
				nframes_total += nframes;
				dtime_total += dtf;
			}

			if (base::cfg().test != -1 &&  test_cycles == 3){
				write_test_data_csv("test.csv", _test_stats, dtime_total, nframes_total);
				_shutdown = true;
			}

			start_time = ctx->_time;
			nframes = 0;
            stats = base::stats_data();
			test_cycles++;
        }

        //
        _canvas->fill_rect(
            ctx,
            glm::vec2(0),
            glm::vec2(256, 260),
            glm::vec4(0.0, 0.0, 0.0, 0.6));

        _canvas->draw_text(
            ctx,
            glm::vec2(3),
            &_stats_str[0],
            glm::vec4(1, 1, 1, 1),
            _fnt_mono.get());
    }

	_renderer->push_frame_context(ctx);
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void benchmark::gpu_draw_frame(base::frame_context * const ctx)
{
    glDisable(GL_BLEND);
    _scene->gpu_draw(ctx);

    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    base::canvas::render(ctx);
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void benchmark::key(const int key, const bool down)
{
	app::key(key, down);

}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

const char* benchmark::get_test_name() const
{
    return base::cfg().test != -1
        ? _scene->get_test_name(base::cfg().test)
        : "Interactive";
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

bool benchmark::write_test_data_csv(
	const char * file_name,
	const base::stats_data & stats,
	const float time,
	const int nframes)
{
	FILE * pFile;
	pFile = fopen(file_name, "r+");

	if (pFile == NULL){
		pFile = fopen(file_name, "w");
		if (pFile == NULL){
			return false;
		}

		fputs(
			"test_name,"
			"gpu_gl_name,"
			"use_vbo,"
			"tex_freq,"
			"tex_mode,"
			"mesh_size,"
			"one_mesh,"
			"frames,"
			"render_time,"
			"cpu_render_time (ms),"
			"gpu_render_time (ms),"
			"dc,"
			"ntri (Mtri),"
			"nverts (Mvtx),"
			"buf_mem (MB),"
			"tex_mem (MB)",
			pFile);
	}
	else{
		fseek(pFile, 0, SEEK_END);
	}

	fprintf(
		pFile,
		"\n%s,%s,%s,%i,%u,%i,%s,%u,%f,%f,%f,%u,%u,%u,%u,%u",
		this->get_test_name(),
		_renderer->get_gpu_str(),
		base::cfg().use_vbo ? "true" : "false",
		base::cfg().tex_freq,
		base::cfg().tex_mode,
		base::cfg().mesh_size,
		base::cfg().one_mesh ? "true" : "false",
		nframes,
		time,
		stats._cpu_time,
		stats._gpu_time,
		stats._ndrawcalls,
		stats._ntriangles,
		stats._nvertices,
		stats._buffer_mem >> 20,
		stats._texture_mem >> 20);

	fclose(pFile);

	return true;
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=<|endoftext|>


<commit_before>/*
* PK Key
* (C) 1999-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/internal/pk_algs.h>
#include <botan/oids.h>

#if defined(BOTAN_HAS_RSA)
  #include <botan/rsa.h>
#endif

#if defined(BOTAN_HAS_DSA)
  #include <botan/dsa.h>
#endif

#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
  #include <botan/dh.h>
#endif

#if defined(BOTAN_HAS_ECDSA)
  #include <botan/ecdsa.h>
#endif

#if defined(BOTAN_HAS_GOST_34_10_2001)
  #include <botan/gost_3410.h>
#endif

#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
  #include <botan/nr.h>
#endif

#if defined(BOTAN_HAS_RW)
  #include <botan/rw.h>
#endif

#if defined(BOTAN_HAS_ELGAMAL)
  #include <botan/elgamal.h>
#endif

namespace Botan {

Public_Key* make_public_key(const AlgorithmIdentifier& alg_id,
                            const MemoryRegion<byte>& key_bits)
   {
   const std::string alg_name = OIDS::lookup(alg_id.oid);
   if(alg_name == "")
      throw Decoding_Error("Unknown algorithm OID: " + alg_id.oid.as_string());

#if defined(BOTAN_HAS_RSA)
   if(alg_name == "RSA")
      return new RSA_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_RW)
   if(alg_name == "RW")
      return new RW_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_DSA)
   if(alg_name == "DSA")
      return new DSA_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
   if(alg_name == "DH")
      return new DH_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
   if(alg_name == "NR")
      return new NR_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_ELGAMAL)
   if(alg_name == "ElGamal")
      return new ElGamal_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_ECDSA)
   if(alg_name == "ECDSA")
      return new ECDSA_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_GOST_34_10_2001)
   if(alg_name == "GOST-34.10")
      return new GOST_3410_PublicKey(alg_id, key_bits);
#endif

   return 0;
   }

Private_Key* make_private_key(const AlgorithmIdentifier& alg_id,
                              const MemoryRegion<byte>& key_bits,
                              RandomNumberGenerator& rng)
   {
   const std::string alg_name = OIDS::lookup(alg_id.oid);
   if(alg_name == "")
      throw Decoding_Error("Unknown algorithm OID: " + alg_id.oid.as_string());

#if defined(BOTAN_HAS_RSA)
   if(alg_name == "RSA")
      return new RSA_PrivateKey(alg_id, key_bits, rng);
#endif

#if defined(BOTAN_HAS_RW)
   if(alg_name == "RW")
      return new RW_PrivateKey(alg_id, key_bits, rng);
#endif

#if defined(BOTAN_HAS_DSA)
   if(alg_name == "DSA")
      return new DSA_PrivateKey(alg_id, key_bits, rng);
#endif

#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
   if(alg_name == "DH")
      return new DH_PrivateKey(alg_id, key_bits, rng);
#endif

#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
   if(alg_name == "NR")
      return new NR_PrivateKey(alg_id, key_bits, rng);
#endif

#if defined(BOTAN_HAS_ELGAMAL)
   if(alg_name == "ElGamal")
      return new ElGamal_PrivateKey(alg_id, key_bits, rng);
#endif

#if defined(BOTAN_HAS_ECDSA)
   if(alg_name == "ECDSA")
      return new ECDSA_PrivateKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_GOST_34_10_2001)
   if(alg_name == "GOST-34.10")
      return new GOST_3410_PrivateKey(alg_id, key_bits);
#endif

   return 0;
   }

}
<commit_msg>Support ECDH key creation in the key factory function. Patch from Sean Cassidy, sent to the mailing list.<commit_after>/*
* PK Key
* (C) 1999-2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/internal/pk_algs.h>
#include <botan/oids.h>

#if defined(BOTAN_HAS_RSA)
  #include <botan/rsa.h>
#endif

#if defined(BOTAN_HAS_DSA)
  #include <botan/dsa.h>
#endif

#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
  #include <botan/dh.h>
#endif

#if defined(BOTAN_HAS_ECDSA)
  #include <botan/ecdsa.h>
#endif

#if defined(BOTAN_HAS_GOST_34_10_2001)
  #include <botan/gost_3410.h>
#endif

#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
  #include <botan/nr.h>
#endif

#if defined(BOTAN_HAS_RW)
  #include <botan/rw.h>
#endif

#if defined(BOTAN_HAS_ELGAMAL)
  #include <botan/elgamal.h>
#endif

#if defined(BOTAN_HAS_ECDH)
  #include <botan/ecdh.h>
#endif

namespace Botan {

Public_Key* make_public_key(const AlgorithmIdentifier& alg_id,
                            const MemoryRegion<byte>& key_bits)
   {
   const std::string alg_name = OIDS::lookup(alg_id.oid);
   if(alg_name == "")
      throw Decoding_Error("Unknown algorithm OID: " + alg_id.oid.as_string());

#if defined(BOTAN_HAS_RSA)
   if(alg_name == "RSA")
      return new RSA_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_RW)
   if(alg_name == "RW")
      return new RW_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_DSA)
   if(alg_name == "DSA")
      return new DSA_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
   if(alg_name == "DH")
      return new DH_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
   if(alg_name == "NR")
      return new NR_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_ELGAMAL)
   if(alg_name == "ElGamal")
      return new ElGamal_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_ECDSA)
   if(alg_name == "ECDSA")
      return new ECDSA_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_GOST_34_10_2001)
   if(alg_name == "GOST-34.10")
      return new GOST_3410_PublicKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_ECDH)
   if(alg_name == "ECDH")
      return new ECDH_PublicKey(alg_id, key_bits);
#endif

   return 0;
   }

Private_Key* make_private_key(const AlgorithmIdentifier& alg_id,
                              const MemoryRegion<byte>& key_bits,
                              RandomNumberGenerator& rng)
   {
   const std::string alg_name = OIDS::lookup(alg_id.oid);
   if(alg_name == "")
      throw Decoding_Error("Unknown algorithm OID: " + alg_id.oid.as_string());

#if defined(BOTAN_HAS_RSA)
   if(alg_name == "RSA")
      return new RSA_PrivateKey(alg_id, key_bits, rng);
#endif

#if defined(BOTAN_HAS_RW)
   if(alg_name == "RW")
      return new RW_PrivateKey(alg_id, key_bits, rng);
#endif

#if defined(BOTAN_HAS_DSA)
   if(alg_name == "DSA")
      return new DSA_PrivateKey(alg_id, key_bits, rng);
#endif

#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
   if(alg_name == "DH")
      return new DH_PrivateKey(alg_id, key_bits, rng);
#endif

#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
   if(alg_name == "NR")
      return new NR_PrivateKey(alg_id, key_bits, rng);
#endif

#if defined(BOTAN_HAS_ELGAMAL)
   if(alg_name == "ElGamal")
      return new ElGamal_PrivateKey(alg_id, key_bits, rng);
#endif

#if defined(BOTAN_HAS_ECDSA)
   if(alg_name == "ECDSA")
      return new ECDSA_PrivateKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_GOST_34_10_2001)
   if(alg_name == "GOST-34.10")
      return new GOST_3410_PrivateKey(alg_id, key_bits);
#endif

#if defined(BOTAN_HAS_ECDH)
   if(alg_name == "ECDH")
      return new ECDH_PrivateKey(alg_id, key_bits);
#endif

   return 0;
   }

}
<|endoftext|>


<commit_before>// Copyright (c) 2017 The Brave Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <utility>

#include "brave/common/extensions/shared_memory_bindings.h"

#include "base/memory/shared_memory.h"
#include "base/pickle.h"
#include "extensions/renderer/script_context.h"
#include "native_mate/arguments.h"
#include "native_mate/converter.h"
#include "native_mate/object_template_builder.h"
#include "native_mate/wrappable.h"
#include "url/gurl.h"
#include "v8/include/v8.h"

namespace mate {

v8::Local<v8::Value> Converter<base::SharedMemory*>::ToV8(
    v8::Isolate* isolate, base::SharedMemory* val) {
  if (!val) {
    return v8::Null(isolate);
  }

  if (!val->Map(sizeof(base::Pickle::Header)))
    return v8::Null(isolate);

  // Get the payload size
  base::Pickle::Header* pickle_header =
      reinterpret_cast<base::Pickle::Header*>(val->memory());

  // Now map in the rest of the block.
  int pickle_size =
      sizeof(base::Pickle::Header) + pickle_header->payload_size;
  val->Unmap();
  if (!val->Map(pickle_size))
    return v8::Null(isolate);

  base::Pickle pickle(reinterpret_cast<char*>(val->memory()),
                      pickle_size);

  base::PickleIterator iter(pickle);
  int length = 0;
  if (!iter.ReadInt(&length))
    return v8::Null(isolate);

  const char* body = NULL;
  if (!iter.ReadBytes(&body, length))
    return v8::Null(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::ValueDeserializer deserializer(
      isolate, reinterpret_cast<const uint8_t*>(body), length);
  deserializer.SetSupportsLegacyWireFormat(true);
  if (deserializer.ReadHeader(context).FromMaybe(false)) {
    v8::Local<v8::Value> data =
        deserializer.ReadValue(context).ToLocalChecked();
    return data;
  }

  return v8::Null(isolate);
}

bool Converter<base::SharedMemory*>::FromV8(v8::Isolate* isolate,
    v8::Local<v8::Value> val,
    base::SharedMemory** out) {
  brave::SharedMemoryWrapper* wrapper = nullptr;
  if (!ConvertFromV8(isolate, val, &wrapper) || !wrapper)
    return false;

  *out = wrapper->shared_memory();
  return true;
}

}  // namespace mate

namespace brave {

// static
mate::Handle<SharedMemoryWrapper> SharedMemoryWrapper::CreateFrom(
    v8::Isolate* isolate,
    const base::SharedMemoryHandle& shared_memory_handle) {
  return mate::CreateHandle(
      isolate, new SharedMemoryWrapper(isolate, shared_memory_handle));
}

// static
mate::Handle<SharedMemoryWrapper> SharedMemoryWrapper::CreateFrom(
    v8::Isolate* isolate, v8::Local<v8::Value> val) {
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::ValueSerializer serializer(isolate);
  serializer.WriteHeader();
  if (!serializer.WriteValue(
      context, val).FromMaybe(false)) {
    // error will be thrown by serializer
    return mate::Handle<SharedMemoryWrapper>();
  }

  std::pair<uint8_t*, size_t> buf = serializer.Release();

  base::Pickle pickle;
  pickle.WriteInt(buf.second);
  pickle.WriteBytes(buf.first, buf.second);

  // Create the shared memory object.
  base::SharedMemory shared_memory;

  base::SharedMemoryCreateOptions options;
  options.size = pickle.size();
  options.share_read_only = true;
  if (!shared_memory.Create(options) || !shared_memory.Map(pickle.size())) {
    free(buf.first);
    return mate::Handle<SharedMemoryWrapper>();
  }

  // Copy the pickle to shared memory.
  memcpy(shared_memory.memory(), pickle.data(), pickle.size());
  free(buf.first);

  base::SharedMemoryHandle readonly_handle;
  if (!shared_memory.ShareReadOnlyToProcess(base::GetCurrentProcessHandle(),
                                            &readonly_handle)) {
    return mate::Handle<SharedMemoryWrapper>();
  }

  return CreateFrom(isolate, readonly_handle);
}

SharedMemoryWrapper::SharedMemoryWrapper(v8::Isolate* isolate,
    const base::SharedMemoryHandle& shared_memory_handle)
        : shared_memory_(new base::SharedMemory(shared_memory_handle, true)),
          isolate_(isolate) {
  Init(isolate);
}

void SharedMemoryWrapper::Close() {
  if (shared_memory_.get()) {
    shared_memory_->Unmap();
    shared_memory_->Close();
  }
}

SharedMemoryWrapper::~SharedMemoryWrapper() {
  Close();
}

void SharedMemoryWrapper::BuildPrototype(v8::Isolate* isolate,
                                 v8::Local<v8::FunctionTemplate> prototype) {
  prototype->SetClassName(mate::StringToV8(isolate, "SharedMemoryWrapper"));
  mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
      .SetMethod("close", &SharedMemoryWrapper::Close)
      .SetMethod("memory", &SharedMemoryWrapper::shared_memory);
}

SharedMemoryBindings::SharedMemoryBindings(extensions::ScriptContext* context)
    : extensions::ObjectBackedNativeHandler(context) {
  RouteFunction("Create",
      base::Bind(&SharedMemoryBindings::Create, base::Unretained(this)));
}

SharedMemoryBindings::~SharedMemoryBindings() {
}

// static
v8::Local<v8::Object> SharedMemoryBindings::API(
    extensions::ScriptContext* context) {
  context->module_system()->RegisterNativeHandler(
    "muon_shared_memory", std::unique_ptr<extensions::NativeHandler>(
        new SharedMemoryBindings(context)));

  v8::Local<v8::Object> shared_memory_api = v8::Object::New(context->isolate());
  context->module_system()->SetNativeLazyField(
        shared_memory_api, "create", "muon_shared_memory", "Create");
  return shared_memory_api;
}

void SharedMemoryBindings::Create(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  if (args.Length() < 1) {
    context()->isolate()->ThrowException(v8::String::NewFromUtf8(
        context()->isolate(), "`data` is a required field"));
    return;
  }

  args.GetReturnValue().Set(
      SharedMemoryWrapper::CreateFrom(context()->isolate(), args[0]).ToV8());
}

}  // namespace brave
<commit_msg>Replace deprecated ShareReadOnlyToProcess<commit_after>// Copyright (c) 2017 The Brave Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <utility>

#include "brave/common/extensions/shared_memory_bindings.h"

#include "base/memory/shared_memory.h"
#include "base/pickle.h"
#include "extensions/renderer/script_context.h"
#include "native_mate/arguments.h"
#include "native_mate/converter.h"
#include "native_mate/object_template_builder.h"
#include "native_mate/wrappable.h"
#include "url/gurl.h"
#include "v8/include/v8.h"

namespace mate {

v8::Local<v8::Value> Converter<base::SharedMemory*>::ToV8(
    v8::Isolate* isolate, base::SharedMemory* val) {
  if (!val) {
    return v8::Null(isolate);
  }

  if (!val->Map(sizeof(base::Pickle::Header)))
    return v8::Null(isolate);

  // Get the payload size
  base::Pickle::Header* pickle_header =
      reinterpret_cast<base::Pickle::Header*>(val->memory());

  // Now map in the rest of the block.
  int pickle_size =
      sizeof(base::Pickle::Header) + pickle_header->payload_size;
  val->Unmap();
  if (!val->Map(pickle_size))
    return v8::Null(isolate);

  base::Pickle pickle(reinterpret_cast<char*>(val->memory()),
                      pickle_size);

  base::PickleIterator iter(pickle);
  int length = 0;
  if (!iter.ReadInt(&length))
    return v8::Null(isolate);

  const char* body = NULL;
  if (!iter.ReadBytes(&body, length))
    return v8::Null(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::ValueDeserializer deserializer(
      isolate, reinterpret_cast<const uint8_t*>(body), length);
  deserializer.SetSupportsLegacyWireFormat(true);
  if (deserializer.ReadHeader(context).FromMaybe(false)) {
    v8::Local<v8::Value> data =
        deserializer.ReadValue(context).ToLocalChecked();
    return data;
  }

  return v8::Null(isolate);
}

bool Converter<base::SharedMemory*>::FromV8(v8::Isolate* isolate,
    v8::Local<v8::Value> val,
    base::SharedMemory** out) {
  brave::SharedMemoryWrapper* wrapper = nullptr;
  if (!ConvertFromV8(isolate, val, &wrapper) || !wrapper)
    return false;

  *out = wrapper->shared_memory();
  return true;
}

}  // namespace mate

namespace brave {

// static
mate::Handle<SharedMemoryWrapper> SharedMemoryWrapper::CreateFrom(
    v8::Isolate* isolate,
    const base::SharedMemoryHandle& shared_memory_handle) {
  return mate::CreateHandle(
      isolate, new SharedMemoryWrapper(isolate, shared_memory_handle));
}

// static
mate::Handle<SharedMemoryWrapper> SharedMemoryWrapper::CreateFrom(
    v8::Isolate* isolate, v8::Local<v8::Value> val) {
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::ValueSerializer serializer(isolate);
  serializer.WriteHeader();
  if (!serializer.WriteValue(
      context, val).FromMaybe(false)) {
    // error will be thrown by serializer
    return mate::Handle<SharedMemoryWrapper>();
  }

  std::pair<uint8_t*, size_t> buf = serializer.Release();

  base::Pickle pickle;
  pickle.WriteInt(buf.second);
  pickle.WriteBytes(buf.first, buf.second);

  // Create the shared memory object.
  base::SharedMemory shared_memory;

  base::SharedMemoryCreateOptions options;
  options.size = pickle.size();
  options.share_read_only = true;
  if (!shared_memory.Create(options) || !shared_memory.Map(pickle.size())) {
    free(buf.first);
    return mate::Handle<SharedMemoryWrapper>();
  }

  // Copy the pickle to shared memory.
  memcpy(shared_memory.memory(), pickle.data(), pickle.size());
  free(buf.first);

  base::SharedMemoryHandle readonly_handle = shared_memory.GetReadOnlyHandle();
  if (!readonly_handle.IsValid()) {
    return mate::Handle<SharedMemoryWrapper>();
  }

  return CreateFrom(isolate, readonly_handle);
}

SharedMemoryWrapper::SharedMemoryWrapper(v8::Isolate* isolate,
    const base::SharedMemoryHandle& shared_memory_handle)
        : shared_memory_(new base::SharedMemory(shared_memory_handle, true)),
          isolate_(isolate) {
  Init(isolate);
}

void SharedMemoryWrapper::Close() {
  if (shared_memory_.get()) {
    shared_memory_->Unmap();
    shared_memory_->Close();
  }
}

SharedMemoryWrapper::~SharedMemoryWrapper() {
  Close();
}

void SharedMemoryWrapper::BuildPrototype(v8::Isolate* isolate,
                                 v8::Local<v8::FunctionTemplate> prototype) {
  prototype->SetClassName(mate::StringToV8(isolate, "SharedMemoryWrapper"));
  mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
      .SetMethod("close", &SharedMemoryWrapper::Close)
      .SetMethod("memory", &SharedMemoryWrapper::shared_memory);
}

SharedMemoryBindings::SharedMemoryBindings(extensions::ScriptContext* context)
    : extensions::ObjectBackedNativeHandler(context) {
  RouteFunction("Create",
      base::Bind(&SharedMemoryBindings::Create, base::Unretained(this)));
}

SharedMemoryBindings::~SharedMemoryBindings() {
}

// static
v8::Local<v8::Object> SharedMemoryBindings::API(
    extensions::ScriptContext* context) {
  context->module_system()->RegisterNativeHandler(
    "muon_shared_memory", std::unique_ptr<extensions::NativeHandler>(
        new SharedMemoryBindings(context)));

  v8::Local<v8::Object> shared_memory_api = v8::Object::New(context->isolate());
  context->module_system()->SetNativeLazyField(
        shared_memory_api, "create", "muon_shared_memory", "Create");
  return shared_memory_api;
}

void SharedMemoryBindings::Create(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  if (args.Length() < 1) {
    context()->isolate()->ThrowException(v8::String::NewFromUtf8(
        context()->isolate(), "`data` is a required field"));
    return;
  }

  args.GetReturnValue().Set(
      SharedMemoryWrapper::CreateFrom(context()->isolate(), args[0]).ToV8());
}

}  // namespace brave
<|endoftext|>