<commit_before>/*
 * Vulkan Samples Kit
 *
 * Copyright (C) 2015 LunarG, Inc.
 *
 * 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.
 */

/*
VULKAN_SAMPLE_DESCRIPTION
samples utility functions
*/

#include <stdio.h>
#include <assert.h>
#include <cstdlib>
#include "util.hpp"
#include "SPIRV/GlslangToSpv.h"

using namespace std;

void extract_version(uint32_t version, uint32_t &major, uint32_t &minor, uint32_t &patch)
{
    major = version >> 22;
    minor = (version >> 12) & 0x3ff;
    patch = version & 0xfff;
}

string get_file_name(const string& s) {

    char sep = '/';

#ifdef _WIN32
    sep = '\\';
#endif

    //cout << "in get_file_name\n";
    size_t i = s.rfind(sep, s.length());
    if (i != string::npos) {
        return(s.substr(i+1, s.length() - i));
    }

    return("");
}

std::string get_base_data_dir()
{
    return std::string(VULKAN_SAMPLES_BASE_DIR) + "/data/";
}

std::string get_data_dir( std::string filename )
{
    std::string basedir = get_base_data_dir();
    // get the base filename
    std::string fname = get_file_name( filename );

    // get the prefix of the base filename, i.e. the part before the dash
    stringstream stream(fname);
    std::string prefix;
    getline(stream, prefix, '-');
    std::string ddir = basedir + prefix;
    return ddir;
}

bool memory_type_from_properties(struct sample_info &info, uint32_t typeBits, VkFlags requirements_mask, uint32_t *typeIndex)
{
     // Search memtypes to find first index with those properties
     for (uint32_t i = 0; i < 32; i++) {
         if ((typeBits & 1) == 1) {
             // Type is available, does it match user properties?
             if ((info.memory_properties.memoryTypes[i].propertyFlags & requirements_mask) == requirements_mask) {
                 *typeIndex = i;
                 return true;
             }
         }
         typeBits >>= 1;
     }
     // No memory types matched, return failure
     return false;
}

void set_image_layout(
        struct sample_info &info,
        VkImage image,
        VkImageAspectFlags aspectMask,
        VkImageLayout old_image_layout,
        VkImageLayout new_image_layout)
{
    /* DEPENDS on info.cmd and info.queue initialized */

    assert(info.cmd != VK_NULL_HANDLE);
    assert(info.queue != VK_NULL_HANDLE);

    VkImageMemoryBarrier image_memory_barrier = {};
    image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    image_memory_barrier.pNext = NULL;
    image_memory_barrier.srcAccessMask = 0;
    image_memory_barrier.dstAccessMask = 0;
    image_memory_barrier.oldLayout = old_image_layout;
    image_memory_barrier.newLayout = new_image_layout;
    image_memory_barrier.image = image;
    image_memory_barrier.subresourceRange.aspectMask = aspectMask;
    image_memory_barrier.subresourceRange.baseMipLevel = 0;
    image_memory_barrier.subresourceRange.levelCount = 1;
    image_memory_barrier.subresourceRange.layerCount = 0;

    if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
        /* Make sure anything that was copying from this image has completed */
        image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    }

    if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
        /* Make sure any Copy or CPU writes to image are flushed */
        image_memory_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
    }

    VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;

    VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
    VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;

    vkCmdPipelineBarrier(info.cmd, src_stages, dest_stages, 0, 1, (const void * const*)&pmemory_barrier);
}

bool read_ppm(char const*const filename, int& width, int& height, uint64_t rowPitch, unsigned char* dataPtr)
{
    // PPM format expected from http://netpbm.sourceforge.net/doc/ppm.html
    //  1. magic number
    //  2. whitespace
    //  3. width
    //  4. whitespace
    //  5. height
    //  6. whitespace
    //  7. max color value
    //  8. whitespace
    //  7. data

    // Comments are not supported, but are detected and we kick out
    // Only 8 bits per channel is supported
    // If dataPtr is nullptr, only width and height are returned

    // Read in values from the PPM file as characters to check for comments
    char magicStr[3] = {}, heightStr[6] = {}, widthStr[6] = {}, formatStr[6] = {};

    FILE *fPtr = fopen(filename,"rb");
    if (!fPtr) {
        printf("Bad filename in read_ppm: %s\n", filename);
        return false;
    }

    // Read the four values from file, accounting with any and all whitepace
    fscanf(fPtr, "%s %s %s %s ", magicStr, widthStr, heightStr, formatStr);

    // Kick out if comments present
    if (magicStr[0]  == '#' || widthStr[0] == '#' || heightStr[0]  == '#' || formatStr[0] == '#') {
        printf("Unhandled comment in PPM file\n");
        return false;
    }

    // Only one magic value is valid
    if (strncmp(magicStr, "P6", sizeof(magicStr))) {
        printf("Unhandled PPM magic number: %s\n", magicStr);
        return false;
    }

    width = atoi(widthStr);
    height = atoi(heightStr);

    // Ensure we got something sane for width/height
    static const int saneDimension = 32768; //??
    if (width <= 0 || width > saneDimension) {
        printf("Width seems wrong.  Update read_ppm if not: %u\n", width);
        return false;
    }
    if (height <= 0 || height > saneDimension) {
        printf("Height seems wrong.  Update read_ppm if not: %u\n", height);
        return false;
    }

    if (dataPtr == nullptr) {
        // If no destination pointer, caller only wanted dimensions
        return true;
    }

    // Now read the data
    for(int y = 0; y < height; y++)
    {
        unsigned char* rowPtr = dataPtr;
        for(int x = 0; x < width; x++)
        {
            fread(rowPtr, 3, 1, fPtr);
            rowPtr[3] = 255; /* Alpha of 1 */
            rowPtr += 4;
        }
        dataPtr += rowPitch;
    }
    fclose(fPtr);

    return true;
}

void init_resources(TBuiltInResource &Resources)
{
    Resources.maxLights = 32;
    Resources.maxClipPlanes = 6;
    Resources.maxTextureUnits = 32;
    Resources.maxTextureCoords = 32;
    Resources.maxVertexAttribs = 64;
    Resources.maxVertexUniformComponents = 4096;
    Resources.maxVaryingFloats = 64;
    Resources.maxVertexTextureImageUnits = 32;
    Resources.maxCombinedTextureImageUnits = 80;
    Resources.maxTextureImageUnits = 32;
    Resources.maxFragmentUniformComponents = 4096;
    Resources.maxDrawBuffers = 32;
    Resources.maxVertexUniformVectors = 128;
    Resources.maxVaryingVectors = 8;
    Resources.maxFragmentUniformVectors = 16;
    Resources.maxVertexOutputVectors = 16;
    Resources.maxFragmentInputVectors = 15;
    Resources.minProgramTexelOffset = -8;
    Resources.maxProgramTexelOffset = 7;
    Resources.maxClipDistances = 8;
    Resources.maxComputeWorkGroupCountX = 65535;
    Resources.maxComputeWorkGroupCountY = 65535;
    Resources.maxComputeWorkGroupCountZ = 65535;
    Resources.maxComputeWorkGroupSizeX = 1024;
    Resources.maxComputeWorkGroupSizeY = 1024;
    Resources.maxComputeWorkGroupSizeZ = 64;
    Resources.maxComputeUniformComponents = 1024;
    Resources.maxComputeTextureImageUnits = 16;
    Resources.maxComputeImageUniforms = 8;
    Resources.maxComputeAtomicCounters = 8;
    Resources.maxComputeAtomicCounterBuffers = 1;
    Resources.maxVaryingComponents = 60;
    Resources.maxVertexOutputComponents = 64;
    Resources.maxGeometryInputComponents = 64;
    Resources.maxGeometryOutputComponents = 128;
    Resources.maxFragmentInputComponents = 128;
    Resources.maxImageUnits = 8;
    Resources.maxCombinedImageUnitsAndFragmentOutputs = 8;
    Resources.maxCombinedShaderOutputResources = 8;
    Resources.maxImageSamples = 0;
    Resources.maxVertexImageUniforms = 0;
    Resources.maxTessControlImageUniforms = 0;
    Resources.maxTessEvaluationImageUniforms = 0;
    Resources.maxGeometryImageUniforms = 0;
    Resources.maxFragmentImageUniforms = 8;
    Resources.maxCombinedImageUniforms = 8;
    Resources.maxGeometryTextureImageUnits = 16;
    Resources.maxGeometryOutputVertices = 256;
    Resources.maxGeometryTotalOutputComponents = 1024;
    Resources.maxGeometryUniformComponents = 1024;
    Resources.maxGeometryVaryingComponents = 64;
    Resources.maxTessControlInputComponents = 128;
    Resources.maxTessControlOutputComponents = 128;
    Resources.maxTessControlTextureImageUnits = 16;
    Resources.maxTessControlUniformComponents = 1024;
    Resources.maxTessControlTotalOutputComponents = 4096;
    Resources.maxTessEvaluationInputComponents = 128;
    Resources.maxTessEvaluationOutputComponents = 128;
    Resources.maxTessEvaluationTextureImageUnits = 16;
    Resources.maxTessEvaluationUniformComponents = 1024;
    Resources.maxTessPatchComponents = 120;
    Resources.maxPatchVertices = 32;
    Resources.maxTessGenLevel = 64;
    Resources.maxViewports = 16;
    Resources.maxVertexAtomicCounters = 0;
    Resources.maxTessControlAtomicCounters = 0;
    Resources.maxTessEvaluationAtomicCounters = 0;
    Resources.maxGeometryAtomicCounters = 0;
    Resources.maxFragmentAtomicCounters = 8;
    Resources.maxCombinedAtomicCounters = 8;
    Resources.maxAtomicCounterBindings = 1;
    Resources.maxVertexAtomicCounterBuffers = 0;
    Resources.maxTessControlAtomicCounterBuffers = 0;
    Resources.maxTessEvaluationAtomicCounterBuffers = 0;
    Resources.maxGeometryAtomicCounterBuffers = 0;
    Resources.maxFragmentAtomicCounterBuffers = 1;
    Resources.maxCombinedAtomicCounterBuffers = 1;
    Resources.maxAtomicCounterBufferSize = 16384;
    Resources.maxTransformFeedbackBuffers = 4;
    Resources.maxTransformFeedbackInterleavedComponents = 64;
    Resources.maxCullDistances = 8;
    Resources.maxCombinedClipAndCullDistances = 8;
    Resources.maxSamples = 4;
    Resources.limits.nonInductiveForLoops = 1;
    Resources.limits.whileLoops = 1;
    Resources.limits.doWhileLoops = 1;
    Resources.limits.generalUniformIndexing = 1;
    Resources.limits.generalAttributeMatrixVectorIndexing = 1;
    Resources.limits.generalVaryingIndexing = 1;
    Resources.limits.generalSamplerIndexing = 1;
    Resources.limits.generalVariableIndexing = 1;
    Resources.limits.generalConstantMatrixVectorIndexing = 1;

}

EShLanguage FindLanguage(const VkShaderStageFlagBits shader_type)
{
    switch (shader_type) {
    case VK_SHADER_STAGE_VERTEX_BIT:
        return EShLangVertex;

    case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
        return EShLangTessControl;

    case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
        return EShLangTessEvaluation;

    case VK_SHADER_STAGE_GEOMETRY_BIT:
        return EShLangGeometry;

    case VK_SHADER_STAGE_FRAGMENT_BIT:
        return EShLangFragment;

    case VK_SHADER_STAGE_COMPUTE_BIT:
        return EShLangCompute;

    default:
        return EShLangVertex;
    }
}

void init_glslang()
{
    glslang::InitializeProcess();
}

void finalize_glslang()
{
    glslang::FinalizeProcess();
}

//
// Compile a given string containing GLSL into SPV for use by VK
// Return value of false means an error was encountered.
//
bool GLSLtoSPV(const VkShaderStageFlagBits shader_type,
               const char *pshader,
               std::vector<unsigned int> &spirv)
{
    glslang::TProgram& program = *new glslang::TProgram;
    const char *shaderStrings[1];
    TBuiltInResource Resources;
    init_resources(Resources);

    EShMessages messages = EShMsgDefault;

    EShLanguage stage = FindLanguage(shader_type);
    glslang::TShader* shader = new glslang::TShader(stage);

    shaderStrings[0] = pshader;
    shader->setStrings(shaderStrings, 1);

    if (! shader->parse(&Resources, 100, false, messages)) {
        puts(shader->getInfoLog());
        puts(shader->getInfoDebugLog());
        return false; // something didn't work
    }

    program.addShader(shader);

    //
    // Program-level processing...
    //

    if (! program.link(messages)) {
        puts(shader->getInfoLog());
        puts(shader->getInfoDebugLog());
        return false;
    }

    glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);

    return true;
}
void wait_seconds(int seconds)
{
#ifdef WIN32
    Sleep(seconds * 1000);
#else
    sleep(seconds);
#endif
}
<commit_msg>Fix dstAccessMasks for various image layouts<commit_after>/*
 * Vulkan Samples Kit
 *
 * Copyright (C) 2015 LunarG, Inc.
 *
 * 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.
 */

/*
VULKAN_SAMPLE_DESCRIPTION
samples utility functions
*/

#include <stdio.h>
#include <assert.h>
#include <cstdlib>
#include "util.hpp"
#include "SPIRV/GlslangToSpv.h"

using namespace std;

void extract_version(uint32_t version, uint32_t &major, uint32_t &minor, uint32_t &patch)
{
    major = version >> 22;
    minor = (version >> 12) & 0x3ff;
    patch = version & 0xfff;
}

string get_file_name(const string& s) {

    char sep = '/';

#ifdef _WIN32
    sep = '\\';
#endif

    //cout << "in get_file_name\n";
    size_t i = s.rfind(sep, s.length());
    if (i != string::npos) {
        return(s.substr(i+1, s.length() - i));
    }

    return("");
}

std::string get_base_data_dir()
{
    return std::string(VULKAN_SAMPLES_BASE_DIR) + "/data/";
}

std::string get_data_dir( std::string filename )
{
    std::string basedir = get_base_data_dir();
    // get the base filename
    std::string fname = get_file_name( filename );

    // get the prefix of the base filename, i.e. the part before the dash
    stringstream stream(fname);
    std::string prefix;
    getline(stream, prefix, '-');
    std::string ddir = basedir + prefix;
    return ddir;
}

bool memory_type_from_properties(struct sample_info &info, uint32_t typeBits, VkFlags requirements_mask, uint32_t *typeIndex)
{
     // Search memtypes to find first index with those properties
     for (uint32_t i = 0; i < 32; i++) {
         if ((typeBits & 1) == 1) {
             // Type is available, does it match user properties?
             if ((info.memory_properties.memoryTypes[i].propertyFlags & requirements_mask) == requirements_mask) {
                 *typeIndex = i;
                 return true;
             }
         }
         typeBits >>= 1;
     }
     // No memory types matched, return failure
     return false;
}

void set_image_layout(
        struct sample_info &info,
        VkImage image,
        VkImageAspectFlags aspectMask,
        VkImageLayout old_image_layout,
        VkImageLayout new_image_layout)
{
    /* DEPENDS on info.cmd and info.queue initialized */

    assert(info.cmd != VK_NULL_HANDLE);
    assert(info.queue != VK_NULL_HANDLE);

    VkImageMemoryBarrier image_memory_barrier = {};
    image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    image_memory_barrier.pNext = NULL;
    image_memory_barrier.srcAccessMask = 0;
    image_memory_barrier.dstAccessMask = 0;
    image_memory_barrier.oldLayout = old_image_layout;
    image_memory_barrier.newLayout = new_image_layout;
    image_memory_barrier.image = image;
    image_memory_barrier.subresourceRange.aspectMask = aspectMask;
    image_memory_barrier.subresourceRange.baseMipLevel = 0;
    image_memory_barrier.subresourceRange.levelCount = 1;
    image_memory_barrier.subresourceRange.layerCount = 0;

    if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
        /* Make sure anything that was copying from this image has completed */
        image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    }

    if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
        /* Make sure any Copy or CPU writes to image are flushed */
        image_memory_barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
        image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
    }

    if (new_image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
        image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
    }

    if (new_image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
        image_memory_barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
    }

    VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;

    VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
    VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;

    vkCmdPipelineBarrier(info.cmd, src_stages, dest_stages, 0, 1, (const void * const*)&pmemory_barrier);
}

bool read_ppm(char const*const filename, int& width, int& height, uint64_t rowPitch, unsigned char* dataPtr)
{
    // PPM format expected from http://netpbm.sourceforge.net/doc/ppm.html
    //  1. magic number
    //  2. whitespace
    //  3. width
    //  4. whitespace
    //  5. height
    //  6. whitespace
    //  7. max color value
    //  8. whitespace
    //  7. data

    // Comments are not supported, but are detected and we kick out
    // Only 8 bits per channel is supported
    // If dataPtr is nullptr, only width and height are returned

    // Read in values from the PPM file as characters to check for comments
    char magicStr[3] = {}, heightStr[6] = {}, widthStr[6] = {}, formatStr[6] = {};

    FILE *fPtr = fopen(filename,"rb");
    if (!fPtr) {
        printf("Bad filename in read_ppm: %s\n", filename);
        return false;
    }

    // Read the four values from file, accounting with any and all whitepace
    fscanf(fPtr, "%s %s %s %s ", magicStr, widthStr, heightStr, formatStr);

    // Kick out if comments present
    if (magicStr[0]  == '#' || widthStr[0] == '#' || heightStr[0]  == '#' || formatStr[0] == '#') {
        printf("Unhandled comment in PPM file\n");
        return false;
    }

    // Only one magic value is valid
    if (strncmp(magicStr, "P6", sizeof(magicStr))) {
        printf("Unhandled PPM magic number: %s\n", magicStr);
        return false;
    }

    width = atoi(widthStr);
    height = atoi(heightStr);

    // Ensure we got something sane for width/height
    static const int saneDimension = 32768; //??
    if (width <= 0 || width > saneDimension) {
        printf("Width seems wrong.  Update read_ppm if not: %u\n", width);
        return false;
    }
    if (height <= 0 || height > saneDimension) {
        printf("Height seems wrong.  Update read_ppm if not: %u\n", height);
        return false;
    }

    if (dataPtr == nullptr) {
        // If no destination pointer, caller only wanted dimensions
        return true;
    }

    // Now read the data
    for(int y = 0; y < height; y++)
    {
        unsigned char* rowPtr = dataPtr;
        for(int x = 0; x < width; x++)
        {
            fread(rowPtr, 3, 1, fPtr);
            rowPtr[3] = 255; /* Alpha of 1 */
            rowPtr += 4;
        }
        dataPtr += rowPitch;
    }
    fclose(fPtr);

    return true;
}

void init_resources(TBuiltInResource &Resources)
{
    Resources.maxLights = 32;
    Resources.maxClipPlanes = 6;
    Resources.maxTextureUnits = 32;
    Resources.maxTextureCoords = 32;
    Resources.maxVertexAttribs = 64;
    Resources.maxVertexUniformComponents = 4096;
    Resources.maxVaryingFloats = 64;
    Resources.maxVertexTextureImageUnits = 32;
    Resources.maxCombinedTextureImageUnits = 80;
    Resources.maxTextureImageUnits = 32;
    Resources.maxFragmentUniformComponents = 4096;
    Resources.maxDrawBuffers = 32;
    Resources.maxVertexUniformVectors = 128;
    Resources.maxVaryingVectors = 8;
    Resources.maxFragmentUniformVectors = 16;
    Resources.maxVertexOutputVectors = 16;
    Resources.maxFragmentInputVectors = 15;
    Resources.minProgramTexelOffset = -8;
    Resources.maxProgramTexelOffset = 7;
    Resources.maxClipDistances = 8;
    Resources.maxComputeWorkGroupCountX = 65535;
    Resources.maxComputeWorkGroupCountY = 65535;
    Resources.maxComputeWorkGroupCountZ = 65535;
    Resources.maxComputeWorkGroupSizeX = 1024;
    Resources.maxComputeWorkGroupSizeY = 1024;
    Resources.maxComputeWorkGroupSizeZ = 64;
    Resources.maxComputeUniformComponents = 1024;
    Resources.maxComputeTextureImageUnits = 16;
    Resources.maxComputeImageUniforms = 8;
    Resources.maxComputeAtomicCounters = 8;
    Resources.maxComputeAtomicCounterBuffers = 1;
    Resources.maxVaryingComponents = 60;
    Resources.maxVertexOutputComponents = 64;
    Resources.maxGeometryInputComponents = 64;
    Resources.maxGeometryOutputComponents = 128;
    Resources.maxFragmentInputComponents = 128;
    Resources.maxImageUnits = 8;
    Resources.maxCombinedImageUnitsAndFragmentOutputs = 8;
    Resources.maxCombinedShaderOutputResources = 8;
    Resources.maxImageSamples = 0;
    Resources.maxVertexImageUniforms = 0;
    Resources.maxTessControlImageUniforms = 0;
    Resources.maxTessEvaluationImageUniforms = 0;
    Resources.maxGeometryImageUniforms = 0;
    Resources.maxFragmentImageUniforms = 8;
    Resources.maxCombinedImageUniforms = 8;
    Resources.maxGeometryTextureImageUnits = 16;
    Resources.maxGeometryOutputVertices = 256;
    Resources.maxGeometryTotalOutputComponents = 1024;
    Resources.maxGeometryUniformComponents = 1024;
    Resources.maxGeometryVaryingComponents = 64;
    Resources.maxTessControlInputComponents = 128;
    Resources.maxTessControlOutputComponents = 128;
    Resources.maxTessControlTextureImageUnits = 16;
    Resources.maxTessControlUniformComponents = 1024;
    Resources.maxTessControlTotalOutputComponents = 4096;
    Resources.maxTessEvaluationInputComponents = 128;
    Resources.maxTessEvaluationOutputComponents = 128;
    Resources.maxTessEvaluationTextureImageUnits = 16;
    Resources.maxTessEvaluationUniformComponents = 1024;
    Resources.maxTessPatchComponents = 120;
    Resources.maxPatchVertices = 32;
    Resources.maxTessGenLevel = 64;
    Resources.maxViewports = 16;
    Resources.maxVertexAtomicCounters = 0;
    Resources.maxTessControlAtomicCounters = 0;
    Resources.maxTessEvaluationAtomicCounters = 0;
    Resources.maxGeometryAtomicCounters = 0;
    Resources.maxFragmentAtomicCounters = 8;
    Resources.maxCombinedAtomicCounters = 8;
    Resources.maxAtomicCounterBindings = 1;
    Resources.maxVertexAtomicCounterBuffers = 0;
    Resources.maxTessControlAtomicCounterBuffers = 0;
    Resources.maxTessEvaluationAtomicCounterBuffers = 0;
    Resources.maxGeometryAtomicCounterBuffers = 0;
    Resources.maxFragmentAtomicCounterBuffers = 1;
    Resources.maxCombinedAtomicCounterBuffers = 1;
    Resources.maxAtomicCounterBufferSize = 16384;
    Resources.maxTransformFeedbackBuffers = 4;
    Resources.maxTransformFeedbackInterleavedComponents = 64;
    Resources.maxCullDistances = 8;
    Resources.maxCombinedClipAndCullDistances = 8;
    Resources.maxSamples = 4;
    Resources.limits.nonInductiveForLoops = 1;
    Resources.limits.whileLoops = 1;
    Resources.limits.doWhileLoops = 1;
    Resources.limits.generalUniformIndexing = 1;
    Resources.limits.generalAttributeMatrixVectorIndexing = 1;
    Resources.limits.generalVaryingIndexing = 1;
    Resources.limits.generalSamplerIndexing = 1;
    Resources.limits.generalVariableIndexing = 1;
    Resources.limits.generalConstantMatrixVectorIndexing = 1;

}

EShLanguage FindLanguage(const VkShaderStageFlagBits shader_type)
{
    switch (shader_type) {
    case VK_SHADER_STAGE_VERTEX_BIT:
        return EShLangVertex;

    case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
        return EShLangTessControl;

    case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
        return EShLangTessEvaluation;

    case VK_SHADER_STAGE_GEOMETRY_BIT:
        return EShLangGeometry;

    case VK_SHADER_STAGE_FRAGMENT_BIT:
        return EShLangFragment;

    case VK_SHADER_STAGE_COMPUTE_BIT:
        return EShLangCompute;

    default:
        return EShLangVertex;
    }
}

void init_glslang()
{
    glslang::InitializeProcess();
}

void finalize_glslang()
{
    glslang::FinalizeProcess();
}

//
// Compile a given string containing GLSL into SPV for use by VK
// Return value of false means an error was encountered.
//
bool GLSLtoSPV(const VkShaderStageFlagBits shader_type,
               const char *pshader,
               std::vector<unsigned int> &spirv)
{
    glslang::TProgram& program = *new glslang::TProgram;
    const char *shaderStrings[1];
    TBuiltInResource Resources;
    init_resources(Resources);

    EShMessages messages = EShMsgDefault;

    EShLanguage stage = FindLanguage(shader_type);
    glslang::TShader* shader = new glslang::TShader(stage);

    shaderStrings[0] = pshader;
    shader->setStrings(shaderStrings, 1);

    if (! shader->parse(&Resources, 100, false, messages)) {
        puts(shader->getInfoLog());
        puts(shader->getInfoDebugLog());
        return false; // something didn't work
    }

    program.addShader(shader);

    //
    // Program-level processing...
    //

    if (! program.link(messages)) {
        puts(shader->getInfoLog());
        puts(shader->getInfoDebugLog());
        return false;
    }

    glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);

    return true;
}
void wait_seconds(int seconds)
{
#ifdef WIN32
    Sleep(seconds * 1000);
#else
    sleep(seconds);
#endif
}
<|endoftext|>


<commit_before>/// \file dtsc2mp4.cpp
/// Contains the code that will transform any valid DTSC input into valid MP4s.

#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <mist/json.h>
#include <mist/dtsc.h> //DTSC support
#include <mist/mp4.h> //MP4 support
#include <mist/config.h>

///\brief Holds everything unique to converters.
namespace Converters {
  struct keyPart{
    long long int trackID;
    long long int size;
    long long int time;
    long long int len;
    JSON::Value parts;
  };

  bool keyPartSort(keyPart i, keyPart j){
    return (i.time < j.time);
  }
  ///\brief Converts DTSC from file to MP4 on stdout.
  ///\return The return code for the converter.
  int DTSC2MP4(Util::Config & conf){
    DTSC::File input(conf.getString("filename"));
    //ftyp box
    /// \todo fill ftyp with non hardcoded values from file
    MP4::FTYP ftypBox;
    ftypBox.setMajorBrand(0x6D703431);//mp41
    ftypBox.setMinorVersion(0);
    ftypBox.setCompatibleBrands(0x69736f6d,0);
    ftypBox.setCompatibleBrands(0x69736f32,1);
    ftypBox.setCompatibleBrands(0x61766331,2);
    ftypBox.setCompatibleBrands(0x6D703431,3);
    std::cout << std::string(ftypBox.asBox(),ftypBox.boxedSize());

    uint64_t mdatSize = 0;
    //std::vector<uint64_t> stcoOffsets;
    //moov box
    MP4::MOOV moovBox;
      MP4::MVHD mvhdBox;
      mvhdBox.setVersion(0);
      mvhdBox.setCreationTime(0);
      mvhdBox.setModificationTime(0);
      mvhdBox.setTimeScale(1000);
      mvhdBox.setRate(0x10000);
      mvhdBox.setDuration(input.getMeta()["lastms"].asInt() + input.getMeta()["firstms"].asInt());
      mvhdBox.setTrackID(0);
      mvhdBox.setVolume(256);
      mvhdBox.setMatrix(0x00010000,0);
      mvhdBox.setMatrix(0,1);
      mvhdBox.setMatrix(0,2);
      mvhdBox.setMatrix(0,3);
      mvhdBox.setMatrix(0x00010000,4);
      mvhdBox.setMatrix(0,5);
      mvhdBox.setMatrix(0,6);
      mvhdBox.setMatrix(0,7);
      mvhdBox.setMatrix(0x40000000,8);
      moovBox.setContent(mvhdBox, 0);

      //calculate interleaving
      //putting all metadata in a huge vector
      std::vector <keyPart> keyParts;
      for (JSON::ObjIter trackIt = input.getMeta()["tracks"].ObjBegin(); trackIt != input.getMeta()["tracks"].ObjEnd(); trackIt++){
        for (unsigned int keyIt = 0; keyIt != trackIt->second["keys"].size(); keyIt++){
          keyPart temp;
          temp.trackID = trackIt->second["trackid"].asInt();
          temp.size = trackIt->second["keys"][keyIt]["size"].asInt();
          temp.time = trackIt->second["keys"][keyIt]["time"].asInt();
          temp.len = trackIt->second["keys"][keyIt]["len"].asInt();
          temp.parts = trackIt->second["keys"][keyIt]["parts"];
          keyParts.push_back(temp);
        }
      }
      //sort by time on keyframes for interleaving
      std::sort(keyParts.begin(), keyParts.end(), keyPartSort);

      //start arbitrary track addition for header
      int boxOffset = 1;
      input.getMeta()["tracks"]["audio0"] = input.getMeta()["audio"];
      input.getMeta()["tracks"]["audio0"]["type"] = "audio";
      input.getMeta()["tracks"]["audio0"]["trackid"] = 1;
      input.getMeta()["tracks"]["video0"] = input.getMeta()["video"];
      input.getMeta()["tracks"]["video0"]["keylen"] = input.getMeta()["keylen"];
      input.getMeta()["tracks"]["video0"]["trackid"] = 2;
      input.getMeta()["tracks"]["video0"]["type"] = "video";
      for (JSON::ObjIter it = input.getMeta()["tracks"].ObjBegin(); it != input.getMeta()["tracks"].ObjEnd(); it++){
        int timescale = 0;
        MP4::TRAK trakBox;
          MP4::TKHD tkhdBox;
          //std::cerr << it->second["trackid"].asInt() << std::endl;
          tkhdBox.setVersion(0);
          tkhdBox.setFlags(15);
          tkhdBox.setTrackID(it->second["trackid"].asInt());
          tkhdBox.setDuration(it->second["lastms"].asInt() + it->second["firsms"].asInt());

          if (it->second["type"].asString() == "video"){
            tkhdBox.setWidth(it->second["width"].asInt() << 16);
            tkhdBox.setHeight(it->second["height"].asInt() << 16);
            tkhdBox.setVolume(0);
          }else{
            tkhdBox.setVolume(256);
            tkhdBox.setAlternateGroup(1);
          }
          tkhdBox.setMatrix(0x00010000,0);
          tkhdBox.setMatrix(0,1);
          tkhdBox.setMatrix(0,2);
          tkhdBox.setMatrix(0,3);
          tkhdBox.setMatrix(0x00010000,4);
          tkhdBox.setMatrix(0,5);
          tkhdBox.setMatrix(0,6);
          tkhdBox.setMatrix(0,7);
          tkhdBox.setMatrix(0x40000000,8);
          trakBox.setContent(tkhdBox, 0);

          MP4::MDIA mdiaBox;
            MP4::MDHD mdhdBox(0);/// \todo fix constructor mdhd in lib
            mdhdBox.setCreationTime(0);
            mdhdBox.setModificationTime(0);
            //Calculating media time based on sampledelta. Probably cheating, but it works...
            int tmpParts = 0;
            for (JSON::ArrIter tmpIt = it->second["keys"].ArrBegin(); tmpIt != it->second["keys"].ArrEnd(); tmpIt++){
              tmpParts += (*tmpIt)["parts"].size();
            }
            timescale = ((double)(42 * tmpParts) / (it->second["lastms"].asInt() + it->second["firstms"].asInt())) *  1000;
            mdhdBox.setTimeScale(timescale);
            mdhdBox.setDuration(((it->second["lastms"].asInt() + it->second["firsms"].asInt()) * ((double)timescale / 1000)));
            mdiaBox.setContent(mdhdBox, 0);

            std::string tmpStr = it->second["type"].asString();
            MP4::HDLR hdlrBox;/// \todo fix constructor hdlr in lib
            if (tmpStr == "video"){
              hdlrBox.setHandlerType(0x76696465);//vide
            }else if (tmpStr == "audio"){
              hdlrBox.setHandlerType(0x736F756E);//soun
            }
            hdlrBox.setName(it->first);
            mdiaBox.setContent(hdlrBox, 1);

            MP4::MINF minfBox;
              if (tmpStr == "video"){
                MP4::VMHD vmhdBox;
                vmhdBox.setFlags(1);
                minfBox.setContent(vmhdBox,0);
              }else if (tmpStr == "audio"){
                MP4::SMHD smhdBox;
                minfBox.setContent(smhdBox,0);
              }
              MP4::DINF dinfBox;
                MP4::DREF drefBox;/// \todo fix constructor dref in lib
                  drefBox.setVersion(0);
                  MP4::URL urlBox;
                  urlBox.setFlags(1);
                  drefBox.setDataEntry(urlBox,0);
                dinfBox.setContent(drefBox,0);
              minfBox.setContent(dinfBox,1);

              MP4::STBL stblBox;
                MP4::STSD stsdBox;
                  stsdBox.setVersion(0);
                  if (tmpStr == "video"){//boxname = codec
                    MP4::VisualSampleEntry vse;
                    std::string tmpStr2 = it->second["codec"];
                    if (tmpStr2 == "H264"){
                      vse.setCodec("avc1");
                    }
                    vse.setDataReferenceIndex(1);
                    vse.setWidth(it->second["width"].asInt());
                    vse.setHeight(it->second["height"].asInt());
                      MP4::AVCC avccBox;
                      avccBox.setPayload(it->second["init"].asString());
                      vse.setCLAP(avccBox);
                    stsdBox.setEntry(vse,0);
                  }else if(tmpStr == "audio"){//boxname = codec
                    MP4::AudioSampleEntry ase;
                    std::string tmpStr2 = it->second["codec"];
                    if (tmpStr2 == "AAC"){
                      ase.setCodec("mp4a");
                      ase.setDataReferenceIndex(1);
                    }
                    ase.setSampleRate(it->second["rate"].asInt());
                    ase.setChannelCount(it->second["channels"].asInt());
                    ase.setSampleSize(it->second["size"].asInt());
                      MP4::ESDS esdsBox;
                      esdsBox.setESDescriptorTypeLength(32+it->second["init"].asString().size());
                      esdsBox.setESID(2);
                      esdsBox.setStreamPriority(0);
                      esdsBox.setDecoderConfigDescriptorTypeLength(18+it->second["init"].asString().size());
                      esdsBox.setByteObjectTypeID(0x40);
                      esdsBox.setStreamType(5);
                      esdsBox.setReservedFlag(1);
                      esdsBox.setBufferSize(1250000);
                      esdsBox.setMaximumBitRate(10000000);
                      esdsBox.setAverageBitRate(it->second["bps"].asInt() * 8);
                      esdsBox.setConfigDescriptorTypeLength(5);
                      esdsBox.setESHeaderStartCodes(it->second["init"].asString());
                      esdsBox.setSLConfigDescriptorTypeTag(0x6);
                      esdsBox.setSLConfigExtendedDescriptorTypeTag(0x808080);
                      esdsBox.setSLDescriptorTypeLength(1);
                      esdsBox.setSLValue(2);
                      ase.setCodecBox(esdsBox);
                    stsdBox.setEntry(ase,0);
                  }
                stblBox.setContent(stsdBox,0);

                /// \todo update following stts lines
                MP4::STTS sttsBox;//current version probably causes problems
                  sttsBox.setVersion(0);
                  MP4::STTSEntry newEntry;
                  newEntry.sampleCount = tmpParts;
                  //42, because of reasons.
                  newEntry.sampleDelta = 42;
                  sttsBox.setSTTSEntry(newEntry, 0);
                stblBox.setContent(sttsBox,1);

                if (it->second["type"] == "video"){
                  //STSS Box here
                  MP4::STSS stssBox;
                    stssBox.setVersion(0);
                    int tmpCount = 1;
                    for (int i = 0; i < it->second["keys"].size(); i++){
                      stssBox.setSampleNumber(tmpCount,i);
                      tmpCount += it->second["keys"][i]["parts"].size();
                    }
                  stblBox.setContent(stssBox,2);
                }

                int offset = (it->second["type"] == "video");

                MP4::STSC stscBox;//probably wrong
                stscBox.setVersion(0);
                uint32_t total = 0;
//                for (int i = 0; i < it->second["keys"].size(); i++){
                  MP4::STSCEntry stscEntry;
                  stscEntry.firstChunk = 1;
                  stscEntry.samplesPerChunk = 1;
                  stscEntry.sampleDescriptionIndex = 1;
                  stscBox.setSTSCEntry(stscEntry, 0);
 //               }
                stblBox.setContent(stscBox,2 + offset);

                MP4::STSZ stszBox;
                stszBox.setVersion(0);
                total = 0;
                for (int i = 0; i < it->second["keys"].size(); i++){
                  for (int o = 0; o < it->second["keys"][i]["parts"].size(); o++){
                    stszBox.setEntrySize(it->second["keys"][i]["parts"][o].asInt(), total);//in bytes in file
                    total++;
                  }
                }
                stblBox.setContent(stszBox,3 + offset);

                MP4::STCO stcoBox;
                stcoBox.setVersion(1);
                total = 0;
                uint64_t totalByteOffset = 0;
                //Inserting wrong values on purpose here, will be fixed later.
                //Current values are actual byte offset without header-sized offset
                for (unsigned int i = 0; i < keyParts.size(); i++){//for all keypart size
                  if(keyParts[i].trackID == it->second["trackid"].asInt()){//if keypart is of current trackID
                    for (unsigned int o = 0; o < keyParts[i].parts.size(); o++){//add all parts to STCO
                      stcoBox.setChunkOffset(totalByteOffset, total);
                      total++;
                      totalByteOffset += keyParts[i].parts[o].asInt();
                    }
                  }else{
                    totalByteOffset += keyParts[i].size;
                  }
                }
                //calculating the offset where the STCO box will be in the main MOOV box
                //needed for probable optimise
                /*stcoOffsets.push_back(
                  moovBox.payloadSize() +
                  trakBox.boxedSize() +
                  mdiaBox.boxedSize() +
                  minfBox.boxedSize() +
                  stblBox.boxedSize()
                );*/
                mdatSize = totalByteOffset;
                stblBox.setContent(stcoBox,4 + offset);
              minfBox.setContent(stblBox,2);
            mdiaBox.setContent(minfBox, 2);
          trakBox.setContent(mdiaBox, 1);
        moovBox.setContent(trakBox, boxOffset);
        boxOffset++;
      }
      //end arbitrary
      //initial offset length ftyp, length moov + 8
      unsigned long long int byteOffset = ftypBox.boxedSize() + moovBox.boxedSize() + 8;
      //update all STCO
      //std::map <int, MP4::STCO&> STCOFix;
      //for tracks
      for (unsigned int i = 1; i < moovBox.getContentCount(); i++){
        //10 lines to get the STCO box.
        MP4::TRAK checkTrakBox;
        MP4::MDIA checkMdiaBox;
        MP4::MINF checkMinfBox;
        MP4::STBL checkStblBox;
        checkTrakBox = ((MP4::TRAK&)moovBox.getContent(i));
        for (int j = 0; j < checkTrakBox.getContentCount(); j++){
          if (checkTrakBox.getContent(j).isType("mdia")){
            checkMdiaBox = ((MP4::MDIA&)checkTrakBox.getContent(j));
            break;
          }
        }
        for (int j = 0; j < checkMdiaBox.getContentCount(); j++){
          if (checkMdiaBox.getContent(j).isType("minf")){
            checkMinfBox = ((MP4::MINF&)checkMdiaBox.getContent(j));
            break;
          }
        }
        for (int j = 0; j < checkMinfBox.getContentCount(); j++){
          if (checkMinfBox.getContent(j).isType("stbl")){
            checkStblBox = ((MP4::STBL&)checkMinfBox.getContent(j));
            break;
          }
        }
        for (int j = 0; j < checkStblBox.getContentCount(); j++){
          if (checkStblBox.getContent(j).isType("stco")){
            std::cerr << "Part 1: " << ((MP4::TKHD&)(checkTrakBox.getContent(0))).getTrackID();
            std::cerr << " Part 2: " << ((MP4::STCO&)(checkStblBox.getContent(j))).getEntryCount() << std::endl;
            STCOFix.insert( std::pair<int, MP4::STCO&>(((MP4::TKHD&)(checkTrakBox.getContent(0))).getTrackID(),(MP4::STCO&)(checkStblBox.getContent(j))));
            break;
          }
        }
        /*MP4::Box temp = MP4::Box((moovBox.payload()+stcoOffsets[i]),false);
        MP4::STCO & checkStcoBox = *((MP4::STCO*)(&temp));
        std::cerr << checkStcoBox.toPrettyString() << std::endl;*/
        //got the STCO box, fixing values with MP4 header offset
        for (int j = 0; j < checkStcoBox.getEntryCount(); j++){
          checkStcoBox.setChunkOffset(checkStcoBox.getChunkOffset(j) + byteOffset, j);
        }
      }

    std::cout << std::string(moovBox.asBox(),moovBox.boxedSize());
    std::cerr << "Header Written" << std::endl;
    //end of header

    //mdat box making it interleaved
    printf("%c%c%c%cmdat", (mdatSize>>24) & 0x000000FF,(mdatSize>>16) & 0x000000FF,(mdatSize>>8) & 0x000000FF,mdatSize & 0x000000FF);
    std::map <long long unsigned int, std::deque<JSON::Value> > trackBuffer;
    long long unsigned int curKey = 0;//the key chunk we are currently searching for in keyParts
    long long unsigned int curPart = 0;//current part in current key

    //initialising JSON input
    std::set<int> selector;
    for (JSON::ObjIter trackIt = input.getMeta()["tracks"].ObjBegin(); trackIt != input.getMeta()["tracks"].ObjEnd(); trackIt++){
      selector.insert(trackIt->second["trackid"].asInt());
    }
    input.selectTracks(selector);
    input.seek_time(0);
    input.seekNext();

    while (input.getJSON()){
      //std::cerr << "DataSize: " << input.getJSON()["data"].asString().size() << std::endl;
      //mdat output here
      //output cleanout buffer first
      //while there are requested packets in the trackBuffer:...
      while (!trackBuffer[keyParts[curKey].trackID].empty()){
        //output requested packages
        if(keyParts[curKey].parts[curPart].asInt() != trackBuffer[keyParts[curKey].trackID].front()["data"].asString().size()){
          std::cerr << "Size discrepancy in buffer packet. Size: " << input.getJSON()["data"].asString().size() << " Expected:" << keyParts[curKey].parts[curPart].asInt() << std::endl;
        }
        std::cout << trackBuffer[keyParts[curKey].trackID].front()["data"].asString();
        trackBuffer[keyParts[curKey].trackID].pop_front();
        curPart++;
        if(curPart >= keyParts[curKey].parts.size()){
          curPart = 0;
          curKey++;
        }
      }
      //after that, try to put out the JSON data directly
      if(keyParts[curKey].trackID == input.getJSON()["trackid"].asInt()){
        //output JSON packet
        if(keyParts[curKey].parts[curPart].asInt() != input.getJSON()["data"].asString().size()){
          std::cerr << "Size discrepancy in JSON packet. Size: " << input.getJSON()["data"].asString().size() << " Expected:" << keyParts[curKey].parts[curPart].asInt() << std::endl;
        }
        std::cout << input.getJSON()["data"].asString();
        curPart++;
        if(curPart >= keyParts[curKey].parts.size()){
          curPart = 0;
          curKey++;
        }
      }else{
        //buffer for later
        trackBuffer[input.getJSON()["trackid"].asInt()].push_back(input.getJSON());
      }
      input.seekNext();
    }
    //output remaining buffer
    return 0;
  } //DTSC2MP4

} //Converter namespace

/// Entry point for DTSC2FLV, simply calls Converters::DTSC2FLV().
int main(int argc, char ** argv){
  Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
  conf.addOption("filename", JSON::fromString("{\"arg_num\":1, \"arg\":\"string\", \"help\":\"Filename of the input file to convert.\"}"));
  conf.parseArgs(argc, argv);
  return Converters::DTSC2MP4(conf);
} //main
<commit_msg>MP4 conversion now called from lib.<commit_after>/// \file dtsc2mp4.cpp
/// Contains the code that will transform any valid DTSC input into valid MP4s.

#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <mist/json.h>
#include <mist/dtsc.h> //DTSC support
#include <mist/mp4.h> //MP4 support
#include <mist/config.h>

///\brief Holds everything unique to converters.
namespace Converters {

  ///\brief Converts DTSC from file to MP4 on stdout.
  ///\return The return code for the converter.
  int DTSC2MP4(Util::Config & conf){
    DTSC::File input(conf.getString("filename"));//DTSC input
    MP4::DTSC2MP4Converter Conv;//DTSC to MP4 converter class will handle header creation and media parsing
    std::cout << Conv.DTSCMeta2MP4Header(input.getMeta());//Creating and outputting MP4 header from DTSC file

    //initialising JSON input
    std::set<int> selector;
    for (JSON::ObjIter trackIt = input.getMeta()["tracks"].ObjBegin(); trackIt != input.getMeta()["tracks"].ObjEnd(); trackIt++){
      selector.insert(trackIt->second["trackid"].asInt());
    }
    input.selectTracks(selector);
    input.seek_time(0);
    input.seekNext();

    //Parsing rest of file
    while (input.getJSON()){//as long as the file goes
      Conv.parseDTSC(input.getJSON());//parse 1 file DTSC packet
      if(Conv.sendReady()){//if the converter has a part to send out
        std::cout << Conv.sendString();//send out and clear Convverter buffer
      }
      input.seekNext();//get next DTSC packet
    }
    //output remaining buffer
    return 0;
  } //DTSC2MP4

} //Converter namespace

/// Entry point for DTSC2FLV, simply calls Converters::DTSC2FLV().
int main(int argc, char ** argv){
  Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
  conf.addOption("filename", JSON::fromString("{\"arg_num\":1, \"arg\":\"string\", \"help\":\"Filename of the input file to convert.\"}"));
  conf.parseArgs(argc, argv);
  return Converters::DTSC2MP4(conf);
} //main
<|endoftext|>


<commit_before>#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <map>
#include <mist/dtsc.h>
#include <mist/ogg.h>
#include <mist/theora.h>
#include <mist/vorbis.h>
#include <mist/config.h>
#include <mist/json.h>

namespace Converters{
  enum codecType {THEORA, VORBIS};

  class oggTrack{
    public:
      oggTrack() : lastTime(), parsedHeaders(false) { }
      codecType codec;
      std::string name;
      long long unsigned int dtscID;
      long long unsigned int lastTime;
      bool parsedHeaders;
      //Codec specific elements
      theora::header idHeader;//needed to determine keyframe
  };

  int OGG2DTSC(){
    std::string oggBuffer;
    OGG::Page oggPage;
    //netpacked
    //Read all of std::cin to oggBuffer

    JSON::Value DTSCOut;
    JSON::Value DTSCHeader;
    DTSCHeader.null();
    DTSCHeader["moreheader"] = 0ll;
    std::map<long unsigned int, oggTrack> trackData;
    long long int lastTrackID = 1;
    int headerSeen = 0;
    bool headerWritten = false;//important bool, used for outputting the simple DTSC header.
    bool allStreamsSeen = false; //other important bool used for error checking the EOS.
    //while stream busy
    while (std::cin.good()){
      for (unsigned int i = 0; (i < 1024) && (std::cin.good()); i++){//buffering
        oggBuffer += std::cin.get();
      }
      while (oggPage.read(oggBuffer)){//reading ogg to ogg::page
        //on succes, we handle one page
        long unsigned int sNum = oggPage.getBitstreamSerialNumber();
        if (oggPage.typeBOS()){//defines a new track
          std::cerr << "Begin "<< sNum << std::endl;
          if (memcmp(oggPage.getFullPayload()+1, "theora", 6) == 0){
            headerSeen += 1;
            headerWritten = false;
            trackData[sNum].codec = THEORA;
            std::cerr << "Snr " << sNum << "=theora" << std::endl;
          }else if(memcmp(oggPage.getFullPayload()+1, "vorbis", 6) == 0){
            headerSeen += 1;
            headerWritten = false;
            std::cerr << "Snr " << sNum << "=vorbis" << std::endl;
            trackData[sNum].codec = VORBIS;
          }else{
            std::cerr << "Unknown Codec, skipping" << std::endl;
            continue;
          }
          trackData[sNum].dtscID = lastTrackID++;
          std::stringstream tID;
          tID << "track" << trackData[sNum].dtscID;
          trackData[sNum].name = tID.str();
        }
        //if Serial number is available in mapping
        if(trackData.find(sNum)!=trackData.end()){
          int offset = 0;
          for (std::deque<unsigned int>::iterator it = oggPage.getSegmentTableDeque().begin(); it != oggPage.getSegmentTableDeque().end(); it++){
            if (trackData[sNum].parsedHeaders){
              //output DTSC packet
              DTSCOut.null();//clearing DTSC buffer
              DTSCOut["trackid"] = (long long)trackData[sNum].dtscID;
              long long unsigned int temp = oggPage.getGranulePosition();
              DTSCOut["granule"] = (long long)temp;
              DTSCOut["time"] = (long long)trackData[sNum].lastTime ++;
              DTSCOut["data"] = std::string(oggPage.getFullPayload()+offset, (*it)); //segment content put in JSON
              if (trackData[sNum].codec == THEORA){
                if (trackData[sNum].idHeader.parseGranuleLower(temp) == 0){ //granule mask equals zero when on keyframe
                  DTSCOut["keyframe"] = 1;
                }else{
                  DTSCOut["interframe"] = 1;
                }
              }
              // Ending packet
              if (oggPage.typeEOS()){//ending page
                DTSCOut["OggEOS"] = 1;
              }

              std::cout << DTSCOut.toNetPacked();
            }else{
              //switch on codec
              switch(trackData[sNum].codec){
                case THEORA:{
                  theora::header tHead;
                  if(tHead.read(oggPage.getFullPayload()+offset, (*it))){//if the current segment is a Theora header part
                    std::cerr << "Theora Header Segment " << tHead.getHeaderType() << std::endl;
                    //fillDTSC header
                    switch(tHead.getHeaderType()){
                      case 0:{ //identification header
                        std::cerr << "Theora ID header found" << std::endl;
                        trackData[sNum].idHeader = tHead;
                        DTSCHeader["tracks"][trackData[sNum].name]["height"] = (long long)tHead.getPICH();
                        DTSCHeader["tracks"][trackData[sNum].name]["width"] = (long long)tHead.getPICW();
                        DTSCHeader["tracks"][trackData[sNum].name]["IDHeader"] = std::string(oggPage.getFullPayload()+offset, (*it));
                        break;
                      }
                      case 1: //comment header
                        std::cerr << "Theora comment header found" << std::endl;
                        DTSCHeader["tracks"][trackData[sNum].name]["CommentHeader"] = std::string(oggPage.getFullPayload()+offset, (*it));
                        break;
                      case 2:{ //setup header, also the point to start writing the header
                        DTSCHeader["tracks"][trackData[sNum].name]["codec"] = "theora";
                        DTSCHeader["tracks"][trackData[sNum].name]["trackid"] = (long long)trackData[sNum].dtscID;
                        DTSCHeader["tracks"][trackData[sNum].name]["type"] = "video";
                        DTSCHeader["tracks"][trackData[sNum].name]["init"] = std::string(oggPage.getFullPayload()+offset, (*it));
                        headerSeen --;
                        trackData[sNum].parsedHeaders = true;
                        break;
                      }
                    }
                  }
                  break;
                }
                case VORBIS:{
                  vorbis::header vHead;
                    if(vHead.read(oggPage.getFullPayload()+offset, (*it))){//if the current segment is a Theora header part
                      switch(vHead.getHeaderType()){
                        case 1:{
                          std::cerr << "Vorbis ID header" << std::endl;
                          DTSCHeader["tracks"][trackData[sNum].name]["channels"] = (long long)vHead.getAudioChannels();
                          DTSCHeader["tracks"][trackData[sNum].name]["IDHeader"] = std::string(oggPage.getFullPayload()+offset, (*it));
                          break;
                        }
                        case 3:{
                          DTSCHeader["tracks"][trackData[sNum].name]["CommentHeader"] = std::string(oggPage.getFullPayload()+offset, (*it));
                          break;
                        }
                        case 5:{
                          std::cerr << "Vorbis init header" << std::endl;
                          DTSCHeader["tracks"][trackData[sNum].name]["codec"] = "vorbis";
                          DTSCHeader["tracks"][trackData[sNum].name]["trackid"] = (long long)trackData[sNum].dtscID;
                          DTSCHeader["tracks"][trackData[sNum].name]["type"] = "audio";
                          DTSCHeader["tracks"][trackData[sNum].name]["init"] = std::string(oggPage.getFullPayload()+offset, (*it));
                          headerSeen --;
                          trackData[sNum].parsedHeaders = true;
                          break;
                        }
                      }
                    }else{
                      //buffer vorbis
                    }
                  break;
                }
                default:
                  std::cerr << "Can not handle this codec" << std::endl;
                  break;
              }
            }
            offset += (*it);
          }

        }else{
          std::cerr <<"Error! Unknown bitstream number " << oggPage.getBitstreamSerialNumber() << std::endl;
        }
        //write header here
        if (headerSeen == 0 && headerWritten == false){
          std::cout << DTSCHeader.toNetPacked();
          headerWritten = true;
        }
        //write section buffer
        //write section
        if (oggPage.typeEOS()){//ending page
          std::cerr << oggPage.getBitstreamSerialNumber() << "  ending" << std::endl;
          //remove from trackdata
          trackData.erase(sNum);
        }
      }
    }
    return 0;
  }
}

int main(int argc, char ** argv){
  return Converters::OGG2DTSC();
}
<commit_msg>Ogg convert fully working now<commit_after>#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <map>
#include <mist/dtsc.h>
#include <mist/ogg.h>
#include <mist/theora.h>
#include <mist/vorbis.h>
#include <mist/config.h>
#include <mist/json.h>

namespace Converters{
  enum codecType {THEORA, VORBIS};

  class oggTrack{
    public:
      oggTrack() : lastTime(), parsedHeaders(false) { }
      codecType codec;
      std::string name;
      long long unsigned int dtscID;
      long long unsigned int lastTime;
      bool parsedHeaders;
      //Codec specific elements
      theora::header idHeader;//needed to determine keyframe
  };

  int OGG2DTSC(){
    std::string oggBuffer;
    OGG::Page oggPage;
    //netpacked
    //Read all of std::cin to oggBuffer

    JSON::Value DTSCOut;
    JSON::Value DTSCHeader;
    DTSCHeader.null();
    DTSCHeader["moreheader"] = 0ll;
    std::map<long unsigned int, oggTrack> trackData;
    long long int lastTrackID = 1;
    int headerSeen = 0;
    bool headerWritten = false;//important bool, used for outputting the simple DTSC header.
    bool allStreamsSeen = false; //other important bool used for error checking the EOS.
    //while stream busy
    while (std::cin.good()){
      for (unsigned int i = 0; (i < 1024) && (std::cin.good()); i++){//buffering
        oggBuffer += std::cin.get();
      }
      while (oggPage.read(oggBuffer)){//reading ogg to ogg::page
        //on succes, we handle one page
        long unsigned int sNum = oggPage.getBitstreamSerialNumber();
        if (oggPage.typeBOS()){//defines a new track
          std::cerr << "Begin "<< sNum << std::endl;
          if (memcmp(oggPage.getFullPayload()+1, "theora", 6) == 0){
            headerSeen += 1;
            headerWritten = false;
            trackData[sNum].codec = THEORA;
            std::cerr << "Snr " << sNum << "=theora" << std::endl;
          }else if(memcmp(oggPage.getFullPayload()+1, "vorbis", 6) == 0){
            headerSeen += 1;
            headerWritten = false;
            std::cerr << "Snr " << sNum << "=vorbis" << std::endl;
            trackData[sNum].codec = VORBIS;
          }else{
            std::cerr << "Unknown Codec, skipping" << std::endl;
            continue;
          }
          trackData[sNum].dtscID = lastTrackID++;
          std::stringstream tID;
          tID << "track" << trackData[sNum].dtscID;
          trackData[sNum].name = tID.str();
        }
        //if Serial number is available in mapping
        if(trackData.find(sNum)!=trackData.end()){
          int offset = 0;
          for (std::deque<unsigned int>::iterator it = oggPage.getSegmentTableDeque().begin(); it != oggPage.getSegmentTableDeque().end(); it++){
            if (trackData[sNum].parsedHeaders){
              //output DTSC packet
              DTSCOut.null();//clearing DTSC buffer
              DTSCOut["trackid"] = (long long)trackData[sNum].dtscID;
              long long unsigned int temp = oggPage.getGranulePosition();
              DTSCOut["granule"] = (long long)temp;
              DTSCOut["time"] = (long long)trackData[sNum].lastTime ++;
              DTSCOut["data"] = std::string(oggPage.getFullPayload()+offset, (*it)); //segment content put in JSON
              if (trackData[sNum].codec == THEORA){
                if (trackData[sNum].idHeader.parseGranuleLower(temp) == 0){ //granule mask equals zero when on keyframe
                  DTSCOut["keyframe"] = 1;
                }else{
                  DTSCOut["interframe"] = 1;
                }
              }
              // Ending packet
              if (oggPage.typeContinue()){//Continuing page
                DTSCOut["OggCont"] = 1;
              }
              if (oggPage.typeEOS()){//ending page
                DTSCOut["OggEOS"] = 1;
              }

              std::cout << DTSCOut.toNetPacked();
            }else{
              //switch on codec
              switch(trackData[sNum].codec){
                case THEORA:{
                  theora::header tHead;
                  if(tHead.read(oggPage.getFullPayload()+offset, (*it))){//if the current segment is a Theora header part
                    std::cerr << "Theora Header Segment " << tHead.getHeaderType() << std::endl;
                    //fillDTSC header
                    switch(tHead.getHeaderType()){
                      case 0:{ //identification header
                        std::cerr << "Theora ID header found" << std::endl;
                        trackData[sNum].idHeader = tHead;
                        DTSCHeader["tracks"][trackData[sNum].name]["height"] = (long long)tHead.getPICH();
                        DTSCHeader["tracks"][trackData[sNum].name]["width"] = (long long)tHead.getPICW();
                        DTSCHeader["tracks"][trackData[sNum].name]["IDHeader"] = std::string(oggPage.getFullPayload()+offset, (*it));
                        break;
                      }
                      case 1: //comment header
                        std::cerr << "Theora comment header found" << std::endl;
                        DTSCHeader["tracks"][trackData[sNum].name]["CommentHeader"] = std::string(oggPage.getFullPayload()+offset, (*it));
                        break;
                      case 2:{ //setup header, also the point to start writing the header
                        DTSCHeader["tracks"][trackData[sNum].name]["codec"] = "theora";
                        DTSCHeader["tracks"][trackData[sNum].name]["trackid"] = (long long)trackData[sNum].dtscID;
                        DTSCHeader["tracks"][trackData[sNum].name]["type"] = "video";
                        DTSCHeader["tracks"][trackData[sNum].name]["init"] = std::string(oggPage.getFullPayload()+offset, (*it));
                        headerSeen --;
                        trackData[sNum].parsedHeaders = true;
                        break;
                      }
                    }
                  }
                  break;
                }
                case VORBIS:{
                  vorbis::header vHead;
                    if(vHead.read(oggPage.getFullPayload()+offset, (*it))){//if the current segment is a Theora header part
                      switch(vHead.getHeaderType()){
                        case 1:{
                          std::cerr << "Vorbis ID header" << std::endl;
                          DTSCHeader["tracks"][trackData[sNum].name]["channels"] = (long long)vHead.getAudioChannels();
                          DTSCHeader["tracks"][trackData[sNum].name]["IDHeader"] = std::string(oggPage.getFullPayload()+offset, (*it));
                          break;
                        }
                        case 3:{
                          DTSCHeader["tracks"][trackData[sNum].name]["CommentHeader"] = std::string(oggPage.getFullPayload()+offset, (*it));
                          break;
                        }
                        case 5:{
                          std::cerr << "Vorbis init header" << std::endl;
                          DTSCHeader["tracks"][trackData[sNum].name]["codec"] = "vorbis";
                          DTSCHeader["tracks"][trackData[sNum].name]["trackid"] = (long long)trackData[sNum].dtscID;
                          DTSCHeader["tracks"][trackData[sNum].name]["type"] = "audio";
                          DTSCHeader["tracks"][trackData[sNum].name]["init"] = std::string(oggPage.getFullPayload()+offset, (*it));
                          headerSeen --;
                          trackData[sNum].parsedHeaders = true;
                          break;
                        }
                      }
                    }else{
                      //buffer vorbis
                    }
                  break;
                }
                default:
                  std::cerr << "Can not handle this codec" << std::endl;
                  break;
              }
            }
            offset += (*it);
          }

        }else{
          std::cerr <<"Error! Unknown bitstream number " << oggPage.getBitstreamSerialNumber() << std::endl;
        }
        //write header here
        if (headerSeen == 0 && headerWritten == false){
          std::cout << DTSCHeader.toNetPacked();
          headerWritten = true;
        }
        //write section buffer
        //write section
        if (oggPage.typeEOS()){//ending page
          std::cerr << oggPage.getBitstreamSerialNumber() << "  ending" << std::endl;
          //remove from trackdata
          trackData.erase(sNum);
        }
      }
    }
    return 0;
  }
}

int main(int argc, char ** argv){
  return Converters::OGG2DTSC();
}
<|endoftext|>


<commit_before>#include "core/GenomeTemplate.hpp"
#include "exception/MismatchedCountsException.hpp"

GenomeTemplate::GenomeTemplate() {}

GenomeTemplate::GenomeTemplate(
	std::vector<double> genes,
	std::vector<Locus*> loci
) {
	if (genes.size() != loci.size()) throw MismatchedCountsException();
	for (unsigned int i = 0; i < genes.size(); i++)
		this->genes.push_back(loci[i]->getGene(genes[i]));
}

GenomeTemplate::GenomeTemplate(std::vector<Gene*> genes) {
	for (unsigned int i = 0; i < genes.size(); i++)
		this->genes.push_back(genes[i]->copy());
}

GenomeTemplate GenomeTemplate::add(double gene, Locus* locus) {
	this->genes.push_back(locus->getGene(gene));
	return *this;
}

GenomeTemplate GenomeTemplate::add(std::tuple<double, Locus*> newGene) {
	this->add(std::get<0>(newGene), std::get<1>(newGene));
	return *this;
}

GenomeTemplate GenomeTemplate::add(
	std::vector<double> genes,
	std::vector<Locus*> loci
) {
	if (genes.size() != loci.size()) throw MismatchedCountsException();

	for (unsigned int i = 0; i < genes.size(); i++)
		this->add(genes[i], loci[i]);
	return *this;
}

GenomeTemplate GenomeTemplate::add(GenomeTemplate other) {
	this->add(other.getGenes());
	return *this;
}

GenomeTemplate GenomeTemplate::add(Gene* newGene) {
	this->genes.push_back(newGene->copy());
	return *this;
}

GenomeTemplate GenomeTemplate::add(std::vector<Gene*> newGenes) {
	for (unsigned int i = 0; i < newGenes.size(); i++)
		this->add(newGenes[i]);
	return *this;
}

GenomeTemplate GenomeTemplate::set(double value, unsigned int index) {
	this->genes[index]->setIndex(value);
	return *this;
}

GenomeTemplate GenomeTemplate::set(Locus * locus, unsigned int index) {
	Gene* gene = locus->getGene(this->genes[index]->getIndex());
	delete(this->genes[index]);
	this->genes[index] = gene;
	return *this;
}

GenomeTemplate GenomeTemplate::set(
	double value,
	Locus * locus,
	unsigned int index
) {
	delete(this->genes[index]);
	this->genes[index] = locus->getGene(value);
	return *this;
}

std::vector<Gene*> GenomeTemplate::getGenes() {
	return this->genes;
}

std::vector<Locus*> GenomeTemplate::getLoci() {
	std::vector<Locus*> loci;
	for (unsigned int i = 0; i < this->genes.size(); i++)
		loci.push_back(this->genes[i]->getLocus());
	return loci;
}

Gene* GenomeTemplate::getGene(unsigned int index) {
	return this->genes[index];
}

Locus* GenomeTemplate::getLocus(unsigned int index) {
	return this->genes[index]->getLocus();
}

unsigned int GenomeTemplate::genomeLength() {
	return this->genes.size();
}
<commit_msg>[GenomeTemplate]: Implemented missing function<commit_after>#include "core/GenomeTemplate.hpp"
#include "exception/MismatchedCountsException.hpp"

GenomeTemplate::GenomeTemplate() {}

GenomeTemplate::GenomeTemplate(
	std::vector<double> genes,
	std::vector<Locus*> loci
) {
	if (genes.size() != loci.size()) throw MismatchedCountsException();
	for (unsigned int i = 0; i < genes.size(); i++)
		this->genes.push_back(loci[i]->getGene(genes[i]));
}

GenomeTemplate::GenomeTemplate(std::vector<Gene*> genes) {
	for (unsigned int i = 0; i < genes.size(); i++)
		this->genes.push_back(genes[i]->copy());
}

GenomeTemplate GenomeTemplate::add(double gene, Locus* locus) {
	this->genes.push_back(locus->getGene(gene));
	return *this;
}

GenomeTemplate GenomeTemplate::add(std::tuple<double, Locus*> newGene) {
	this->add(std::get<0>(newGene), std::get<1>(newGene));
	return *this;
}

GenomeTemplate GenomeTemplate::add(
	std::vector<double> genes,
	std::vector<Locus*> loci
) {
	if (genes.size() != loci.size()) throw MismatchedCountsException();

	for (unsigned int i = 0; i < genes.size(); i++)
		this->add(genes[i], loci[i]);
	return *this;
}

GenomeTemplate GenomeTemplate::add(GenomeTemplate other) {
	this->add(other.getGenes());
	return *this;
}

GenomeTemplate GenomeTemplate::add(Gene* newGene) {
	this->genes.push_back(newGene->copy());
	return *this;
}

GenomeTemplate GenomeTemplate::add(std::vector<Gene*> newGenes) {
	for (unsigned int i = 0; i < newGenes.size(); i++)
		this->add(newGenes[i]);
	return *this;
}

GenomeTemplate GenomeTemplate::set(double value, unsigned int index) {
	this->genes[index]->setIndex(value);
	return *this;
}

GenomeTemplate GenomeTemplate::set(Locus * locus, unsigned int index) {
	Gene* gene = locus->getGene(this->genes[index]->getIndex());
	delete(this->genes[index]);
	this->genes[index] = gene;
	return *this;
}

GenomeTemplate GenomeTemplate::set(
	double value,
	Locus * locus,
	unsigned int index
) {
	delete(this->genes[index]);
	this->genes[index] = locus->getGene(value);
	return *this;
}

GenomeTemplate GenomeTemplate::set(Gene* gene, unsigned int index) {
	delete(this->genes[index]);
	this->genes[index] = gene;
	return *this;
}

std::vector<Gene*> GenomeTemplate::getGenes() {
	return this->genes;
}

std::vector<Locus*> GenomeTemplate::getLoci() {
	std::vector<Locus*> loci;
	for (unsigned int i = 0; i < this->genes.size(); i++)
		loci.push_back(this->genes[i]->getLocus());
	return loci;
}

Gene* GenomeTemplate::getGene(unsigned int index) {
	return this->genes[index];
}

Locus* GenomeTemplate::getLocus(unsigned int index) {
	return this->genes[index]->getLocus();
}

unsigned int GenomeTemplate::genomeLength() {
	return this->genes.size();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Boulanger Guillaume, Chathura Namalgamuwa
 * The file is distributed under the MIT license
 * The license is available in the LICENSE file or at https://github.com/boulangg/phoenix/blob/master/LICENSE
 */

#include <mm/VirtualArea.hpp>
#include <include/constant.h>
#include <algorithm>

VirtualArea::VirtualArea(uint64_t* addrStart, uint64_t* addrEnd, uint64_t flags,
		File* file, uint64_t offset, uint64_t fileSize) {
	this->addrStart = addrStart;
	this->addrEnd = addrEnd;
	this->flags = flags;
	this->file = file;
	this->offset = offset;
	this->fileSize = fileSize;
	uint64_t nbPages = (((uint64_t)addrEnd)+PAGE_SIZE-1)/PAGE_SIZE
			- ((uint64_t)addrStart)/PAGE_SIZE;
	if ((flags & FLAGS::VM_WRITE)
			&& !(flags & FLAGS::VM_SHARED) ) {
		physicalPages = new PhysicalMapping(nbPages);
	} else {
		physicalPages = nullptr;
	}
}

VirtualArea::VirtualArea(const VirtualArea& virtArea) {
	addrStart = virtArea.addrStart;
	addrEnd = virtArea.addrEnd;
	flags = virtArea.flags;
	file = virtArea.file;
	offset = virtArea.offset;
	fileSize = virtArea.fileSize;
	if (virtArea.physicalPages != nullptr) {
		physicalPages = new PhysicalMapping(*(virtArea.physicalPages));
	}
}

VirtualArea::~VirtualArea() {
	delete this->physicalPages;
}

size_t VirtualArea::getNbPages() {
	return (((uint64_t)addrEnd)+PAGE_SIZE-1)/PAGE_SIZE
			- ((uint64_t)addrStart)/PAGE_SIZE;
}

Page* VirtualArea::getPage(uint64_t index) {
	if (physicalPages != nullptr) {
		Page* page = physicalPages->getPage(index);
		if (page == nullptr) {
			page = PhysicalAllocator::allocZeroedPage();
			physicalPages->setPage(index, page);
			// Copy page if it comes from a file
			if (file != nullptr) {
				int64_t startPageOffset = (offset/PAGE_SIZE + index)*PAGE_SIZE;
				int64_t startOffsetLimit = (int64_t)offset-startPageOffset;
				int64_t startCpy = std::max(startOffsetLimit, (int64_t)0);

				int64_t endOffsetLimit = startOffsetLimit + fileSize;
				int64_t endCpy = std::min((int64_t)PAGE_SIZE, endOffsetLimit);

				int fileIndex = offset/PAGE_SIZE + index;
				Page* filePage = file->getPage(fileIndex);
				for (int64_t i = startCpy; i < endCpy; ++i) {
					((char*)(page->kernelMappAddr))[i] = ((char*)(filePage->kernelMappAddr))[i];
				}
			}
		}
		return page;
	} else {
		int fileIndex = offset/PAGE_SIZE + index;
		return file->getPage(fileIndex);
	}
}

bool VirtualArea::tryMergeArea(VirtualArea* area) {
	if (this->flags != area->flags) {
		return false;
	}
	if ((this->addrEnd != area->addrStart)
			& (this->file == area->file)){
		return false;
	}
	if (this->file == nullptr) {
		this->addrEnd = area->addrEnd;
		this->physicalPages->pushBack(area->physicalPages);
		return true;
	}
	if ((offset + (uint64_t)addrEnd - (uint64_t)addrStart) == area->offset) {
		this->addrEnd = area->addrEnd;
		return true;
	}
	return false;
}
<commit_msg>Fix missing initializer<commit_after>/*
 * Copyright (c) 2016 Boulanger Guillaume, Chathura Namalgamuwa
 * The file is distributed under the MIT license
 * The license is available in the LICENSE file or at https://github.com/boulangg/phoenix/blob/master/LICENSE
 */

#include <mm/VirtualArea.hpp>
#include <include/constant.h>
#include <algorithm>

VirtualArea::VirtualArea(uint64_t* addrStart, uint64_t* addrEnd, uint64_t flags,
		File* file, uint64_t offset, uint64_t fileSize) {
	this->addrStart = addrStart;
	this->addrEnd = addrEnd;
	this->flags = flags;
	this->file = file;
	this->offset = offset;
	this->fileSize = fileSize;
	uint64_t nbPages = (((uint64_t)addrEnd)+PAGE_SIZE-1)/PAGE_SIZE
			- ((uint64_t)addrStart)/PAGE_SIZE;
	if ((flags & FLAGS::VM_WRITE)
			&& !(flags & FLAGS::VM_SHARED) ) {
		physicalPages = new PhysicalMapping(nbPages);
	} else {
		physicalPages = nullptr;
	}
}

VirtualArea::VirtualArea(const VirtualArea& virtArea) {
	addrStart = virtArea.addrStart;
	addrEnd = virtArea.addrEnd;
	flags = virtArea.flags;
	file = virtArea.file;
	offset = virtArea.offset;
	fileSize = virtArea.fileSize;
	if (virtArea.physicalPages != nullptr) {
		physicalPages = new PhysicalMapping(*(virtArea.physicalPages));
	} else {
		physicalPages = nullptr;
	}
}

VirtualArea::~VirtualArea() {
	delete this->physicalPages;
}

size_t VirtualArea::getNbPages() {
	return (((uint64_t)addrEnd)+PAGE_SIZE-1)/PAGE_SIZE
			- ((uint64_t)addrStart)/PAGE_SIZE;
}

Page* VirtualArea::getPage(uint64_t index) {
	if (physicalPages != nullptr) {
		Page* page = physicalPages->getPage(index);
		if (page == nullptr) {
			page = PhysicalAllocator::allocZeroedPage();
			physicalPages->setPage(index, page);
			// Copy page if it comes from a file
			if (file != nullptr) {
				int64_t startPageOffset = (offset/PAGE_SIZE + index)*PAGE_SIZE;
				int64_t startOffsetLimit = (int64_t)offset-startPageOffset;
				int64_t startCpy = std::max(startOffsetLimit, (int64_t)0);

				int64_t endOffsetLimit = startOffsetLimit + fileSize;
				int64_t endCpy = std::min((int64_t)PAGE_SIZE, endOffsetLimit);

				int fileIndex = offset/PAGE_SIZE + index;
				Page* filePage = file->getPage(fileIndex);
				for (int64_t i = startCpy; i < endCpy; ++i) {
					((char*)(page->kernelMappAddr))[i] = ((char*)(filePage->kernelMappAddr))[i];
				}
			}
		}
		return page;
	} else {
		int fileIndex = offset/PAGE_SIZE + index;
		return file->getPage(fileIndex);
	}
}

bool VirtualArea::tryMergeArea(VirtualArea* area) {
	if (this->flags != area->flags) {
		return false;
	}
	if ((this->addrEnd != area->addrStart)
			& (this->file == area->file)){
		return false;
	}
	if (this->file == nullptr) {
		this->addrEnd = area->addrEnd;
		this->physicalPages->pushBack(area->physicalPages);
		return true;
	}
	if ((offset + (uint64_t)addrEnd - (uint64_t)addrStart) == area->offset) {
		this->addrEnd = area->addrEnd;
		return true;
	}
	return false;
}
<|endoftext|>


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

#include "acceln.h"
#include "embree2/rtcore_ray.h"
#include "algorithms/parallel_for.h"

namespace embree
{
  AccelN::AccelN () : N(0), M(0) {
    memset(accels,0,sizeof(accels));
  }

  AccelN::~AccelN()
  {
    for (size_t i=0; i<N; i++)
      delete accels[i];
  }

  void AccelN::add(Accel* accel)
  {
    assert(N<16);
    assert(accel);
    if (N<16) accels[N++] = accel;
  }

  void AccelN::intersect (void* ptr, RTCRay& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++)
      This->validAccels[i]->intersect(ray);
  }

  void AccelN::intersect4 (const void* valid, void* ptr, RTCRay4& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++)
      This->validAccels[i]->intersect4(valid,ray);
  }

  void AccelN::intersect8 (const void* valid, void* ptr, RTCRay8& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++)
      This->validAccels[i]->intersect8(valid,ray);
  }

  void AccelN::intersect16 (const void* valid, void* ptr, RTCRay16& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++)
      This->validAccels[i]->intersect16(valid,ray);
  }

  void AccelN::occluded (void* ptr, RTCRay& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++) {
      This->validAccels[i]->occluded(ray);
      if (ray.geomID == 0) break;
    }
  }

  void AccelN::occluded4 (const void* valid, void* ptr, RTCRay4& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++) {
      This->validAccels[i]->occluded4(valid,ray);
#if defined(__SSE2__)
      sseb valid0 = ((sseb*)valid)[0];
      sseb hit0   = ((ssei*)ray.geomID)[0] == ssei(0);
      if (all(valid0,hit0)) break;
#endif
    }
  }

  void AccelN::occluded8 (const void* valid, void* ptr, RTCRay8& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++) {
      This->validAccels[i]->occluded8(valid,ray);
#if defined(__SSE2__)
      sseb valid0 = ((sseb*)valid)[0];
      sseb hit0   = ((ssei*)ray.geomID)[0] == ssei(0);
      sseb valid1 = ((sseb*)valid)[1];
      sseb hit1   = ((ssei*)ray.geomID)[1] == ssei(0);
      if (all(valid0,hit0) && all(valid1,hit1)) break;
#endif
    }
  }

  void AccelN::occluded16 (const void* valid, void* ptr, RTCRay16& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++) {
      This->validAccels[i]->occluded16(valid,ray);
#if defined(__MIC__)
      mic_m valid0 = ((mic_m*)valid)[0];
      mic_m hit0   = ((mic_i*)ray.geomID)[0] == mic_i(0);
      if (all(valid0,hit0)) break;
#endif
    }
  }

  void AccelN::print(size_t ident)
  {
    for (size_t i=0; i<M; i++)
    {
      for (size_t j=0; j<ident; j++) std::cout << " ";
      std::cout << "accels[" << i << "]" << std::endl;
      validAccels[i]->intersectors.print(ident+2);
    }
  }

  void AccelN::immutable()
  {
    for (size_t i=0; i<N; i++)
      accels[i]->immutable();
  }

  void AccelN::build (size_t threadIndex, size_t threadCount)
  {
    /* build all acceleration structures in parallel */
    parallel_for (N, [&] (size_t i) {
        accels[i]->build(threadIndex,threadCount);
      });

    /* create list of non-empty acceleration structures */
    M = 0;
    for (size_t i=0; i<N; i++) {
      if (accels[i]->bounds.empty()) continue;
      validAccels[M++] = accels[i];
    }

    if (M == 1) {
      intersectors = validAccels[0]->intersectors;
    }
    else
    {
      intersectors.ptr = this;
      intersectors.intersector1 = Intersector1(&intersect,&occluded,"AccelN::intersector1");
      intersectors.intersector4 = Intersector4(&intersect4,&occluded4,"AccelN::intersector4");
      intersectors.intersector8 = Intersector8(&intersect8,&occluded8,"AccelN::intersector8");
      intersectors.intersector16= Intersector16(&intersect16,&occluded16,"AccelN::intersector16");
    }

    /*! calculate bounds */
    bounds = empty;
    for (size_t i=0; i<M; i++)
      bounds.extend(validAccels[i]->bounds);
  }

  void AccelN::select(bool filter4, bool filter8, bool filter16)
  {
    for (size_t i=0; i<N; i++)
      accels[i]->intersectors.select(filter4,filter8,filter16);
  }

  void AccelN::clear()
  {
    for (size_t i=0; i<N; i++)
      accels[i]->clear();
  }
}
<commit_msg>xeon phi bugfix, parallel loop over different accel types not supported<commit_after>// ======================================================================== //
// Copyright 2009-2015 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "acceln.h"
#include "embree2/rtcore_ray.h"
#include "algorithms/parallel_for.h"

namespace embree
{
  AccelN::AccelN () : N(0), M(0) {
    memset(accels,0,sizeof(accels));
  }

  AccelN::~AccelN()
  {
    for (size_t i=0; i<N; i++)
      delete accels[i];
  }

  void AccelN::add(Accel* accel)
  {
    assert(N<16);
    assert(accel);
    if (N<16) accels[N++] = accel;
  }

  void AccelN::intersect (void* ptr, RTCRay& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++)
      This->validAccels[i]->intersect(ray);
  }

  void AccelN::intersect4 (const void* valid, void* ptr, RTCRay4& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++)
      This->validAccels[i]->intersect4(valid,ray);
  }

  void AccelN::intersect8 (const void* valid, void* ptr, RTCRay8& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++)
      This->validAccels[i]->intersect8(valid,ray);
  }

  void AccelN::intersect16 (const void* valid, void* ptr, RTCRay16& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++)
      This->validAccels[i]->intersect16(valid,ray);
  }

  void AccelN::occluded (void* ptr, RTCRay& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++) {
      This->validAccels[i]->occluded(ray);
      if (ray.geomID == 0) break;
    }
  }

  void AccelN::occluded4 (const void* valid, void* ptr, RTCRay4& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++) {
      This->validAccels[i]->occluded4(valid,ray);
#if defined(__SSE2__)
      sseb valid0 = ((sseb*)valid)[0];
      sseb hit0   = ((ssei*)ray.geomID)[0] == ssei(0);
      if (all(valid0,hit0)) break;
#endif
    }
  }

  void AccelN::occluded8 (const void* valid, void* ptr, RTCRay8& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++) {
      This->validAccels[i]->occluded8(valid,ray);
#if defined(__SSE2__)
      sseb valid0 = ((sseb*)valid)[0];
      sseb hit0   = ((ssei*)ray.geomID)[0] == ssei(0);
      sseb valid1 = ((sseb*)valid)[1];
      sseb hit1   = ((ssei*)ray.geomID)[1] == ssei(0);
      if (all(valid0,hit0) && all(valid1,hit1)) break;
#endif
    }
  }

  void AccelN::occluded16 (const void* valid, void* ptr, RTCRay16& ray)
  {
    AccelN* This = (AccelN*)ptr;
    for (size_t i=0; i<This->M; i++) {
      This->validAccels[i]->occluded16(valid,ray);
#if defined(__MIC__)
      mic_m valid0 = ((mic_m*)valid)[0];
      mic_m hit0   = ((mic_i*)ray.geomID)[0] == mic_i(0);
      if (all(valid0,hit0)) break;
#endif
    }
  }

  void AccelN::print(size_t ident)
  {
    for (size_t i=0; i<M; i++)
    {
      for (size_t j=0; j<ident; j++) std::cout << " ";
      std::cout << "accels[" << i << "]" << std::endl;
      validAccels[i]->intersectors.print(ident+2);
    }
  }

  void AccelN::immutable()
  {
    for (size_t i=0; i<N; i++)
      accels[i]->immutable();
  }

  void AccelN::build (size_t threadIndex, size_t threadCount)
  {
    /* build all acceleration structures in parallel */
#if defined(__MIC__)
    for (size_t i=0; i<N; i++)
        accels[i]->build(threadIndex,threadCount);
#else
    parallel_for (N, [&] (size_t i) {
        accels[i]->build(threadIndex,threadCount);
      });
#endif

    /* create list of non-empty acceleration structures */
    M = 0;
    for (size_t i=0; i<N; i++) {
      if (accels[i]->bounds.empty()) continue;
      validAccels[M++] = accels[i];
    }

    if (M == 1) {
      intersectors = validAccels[0]->intersectors;
    }
    else
    {
      intersectors.ptr = this;
      intersectors.intersector1 = Intersector1(&intersect,&occluded,"AccelN::intersector1");
      intersectors.intersector4 = Intersector4(&intersect4,&occluded4,"AccelN::intersector4");
      intersectors.intersector8 = Intersector8(&intersect8,&occluded8,"AccelN::intersector8");
      intersectors.intersector16= Intersector16(&intersect16,&occluded16,"AccelN::intersector16");
    }

    /*! calculate bounds */
    bounds = empty;
    for (size_t i=0; i<M; i++)
      bounds.extend(validAccels[i]->bounds);
  }

  void AccelN::select(bool filter4, bool filter8, bool filter16)
  {
    for (size_t i=0; i<N; i++)
      accels[i]->intersectors.select(filter4,filter8,filter16);
  }

  void AccelN::clear()
  {
    for (size_t i=0; i<N; i++)
      accels[i]->clear();
  }
}
<|endoftext|>