neuray API Programmer's Manual

Example for the HTTP server

[Previous] [Next] [Up]

This example imports a scene file, renders the scene, and serves the image via an HTTP server

New Topics

  • Running an HTTP server

Detailed Description

Running an HTTP server

This example provides a very simple HTTP server which just serves one particular image. The image is rendered in the same way as in the Example for Rendering. See HTTP server for a general introduction to the HTTP server.

This examples uses a simple request handler which always serves a fixed image, independent of the requested URL, etc. A response handler is installed to set the content type to 'image/jpeg'. Note that this is just done for illustration purposes. The content type could also be set directly by the request handler.

Example Source

Source Code Location: examples/example_http_server.cpp

‎/******************************************************************************
 * Copyright 1986, 2011 NVIDIA Corporation. All rights reserved.
 *****************************************************************************/

// examples/example_http_server.cpp
//
// Imports a scene file, renders the scene, and serves the image via the HTTP server

#include <iostream>

#include <mi/neuraylib.h>

// Include code shared by all examples.
#include "example_shared.h"
// Include an implementation of ITile, ICanvas, and IRender_target.
#include "example_render_target.h"

// Simple request handler which always sends the buffer passed in the constructor
class Request_handler : public mi::base::Interface_implement<mi::http::IRequest_handler>
{
public:
    // Constructor. Stores the passed buffer.
    Request_handler( mi::base::Handle< mi::IBuffer> buffer)
    {
        m_buffer = buffer;
    }

    // Send buffer contents over the connection.
    bool handle( mi::http::IConnection* connection)
    {
        connection->enqueue( m_buffer.get());
        return true;
    }
private:
    // The stored buffer
    mi::base::Handle< mi::IBuffer> m_buffer;
};

// Simple response handler which always sets the content type for JPG images
class Response_handler : public mi::base::Interface_implement<mi::http::IResponse_handler>
{
public:
    void handle( mi::http::IConnection* connection)
    {
        mi::http::IResponse* iresponse( connection->get_response());
        iresponse->set_header( "Content-Type", "image/jpeg");
    }
};

void configuration( mi::base::Handle< mi::neuraylib::INeuray> neuray, const char* shader_path)
{
    // Configure the neuray library. Here we set some paths needed by the renderer.
    mi::base::Handle< mi::neuraylib::IRendering_configuration> rendering_configuration(
        neuray->get_api_component<mi::neuraylib::IRendering_configuration>());
    check_success( rendering_configuration.is_valid_interface());
    check_success( rendering_configuration->add_shader_path( shader_path) == 0);

    // Load the FreeImage image plugin and the LLVM backend for MetaSL.
    mi::base::Handle< mi::neuraylib::IPlugin_configuration> plugin_configuration(
        neuray->get_api_component<mi::neuraylib::IPlugin_configuration>());
#ifndef MI_PLATFORM_WINDOWS
    check_success( plugin_configuration->load_plugin_library( "freeimage.so") == 0);
    check_success( plugin_configuration->load_plugin_library( "gen_llvm.so") == 0);
#else
    check_success( plugin_configuration->load_plugin_library( "freeimage.dll") == 0);
    check_success( plugin_configuration->load_plugin_library( "gen_llvm.dll") == 0);
#endif
}

mi::base::Handle< mi::IBuffer> rendering( mi::base::Handle< mi::neuraylib::INeuray> neuray,
                                         const char* scene_file)
{
    // Get the database, the global scope, which is the root for all transactions,
    // and create a transaction for importing the scene file and storing the scene.
    mi::base::Handle< mi::neuraylib::IDatabase> database(
        neuray->get_api_component<mi::neuraylib::IDatabase>());
    check_success( database.is_valid_interface());
    mi::base::Handle< mi::neuraylib::IScope> scope(
        database->get_global_scope());
    mi::base::Handle< mi::neuraylib::ITransaction> transaction(
        scope->create_transaction());
    check_success( transaction.is_valid_interface());

    // Import the scene file
    mi::base::Handle< mi::neuraylib::IImport_api> import_api(
        neuray->get_api_component<mi::neuraylib::IImport_api>());
    check_success( import_api.is_valid_interface());
    mi::base::Handle< const mi::IImport_result> import_result(
        import_api->import_elements( transaction.get(), scene_file));
    check_success( import_result->get_error_number() == 0);

    // Create the scene object
    mi::base::Handle< mi::neuraylib::IScene> scene(
        transaction->create<mi::neuraylib::IScene>( "Scene"));
    scene->set_rootgroup(       import_result->get_rootgroup());
    scene->set_options(         import_result->get_options());
    scene->set_camera_instance( import_result->get_camera_inst());
    transaction->store( scene.get(), "the_scene");

    // Create the render context using the default renderer
    scene = transaction->edit<mi::neuraylib::IScene>( "the_scene");
    mi::base::Handle< mi::neuraylib::IRender_context> render_context(
        scene->get_render_context( transaction.get(), "default"));
    scene = 0;

    // Create the render target and render the scene
    Render_target render_target( 512, 384);
    check_success( render_context->render( transaction.get(), &render_target, NULL) == 0);

    // Access the first canvas of the render target
    mi::base::Handle< mi::neuraylib::ICanvas> canvas( render_target.get_canvas( 0));

    // Convert content of the canvas to an JPG image
    mi::base::Handle< mi::neuraylib::IImage_api> image_api(
        neuray->get_api_component<mi::neuraylib::IImage_api>());
    mi::base::Handle< mi::IBuffer> buffer(
        image_api->create_buffer_from_canvas( canvas.get(), "jpg", "Rgb", "100"));

    // All transactions need to get committed or aborted, not really important in this example.
    transaction->commit();

    return buffer;
}

void run_http_server( mi::base::Handle< mi::neuraylib::INeuray> neuray,
                      mi::base::Handle< mi::IBuffer> buffer,
                      const char* port)
{
    // Create a server instance
    mi::base::Handle< mi::http::IFactory> http_factory(
        neuray->get_api_component<mi::http::IFactory>());
    mi::base::Handle< mi::http::IServer> http_server(
        http_factory->create_server());

    // Install our request and response handlers
    mi::base::Handle< mi::http::IRequest_handler> request_handler(
        new Request_handler( buffer));
    http_server->install( request_handler.get());
    mi::base::Handle< mi::http::IResponse_handler> response_handler(
        new Response_handler());
    http_server->install( response_handler.get());

    // Assemble server address
    const char* ip = "0.0.0.0:";
    char address[255];
    address[0] = '\0';
    strncat( address, ip, sizeof(address) - 1);
    strncat( address, port, sizeof(address) - 1 - strlen(address));

    // Run server for fixed time interval
    http_server->start( address);
    sleep_seconds( 30);
    http_server->shutdown();
}

// The example takes the following command line arguments:
//
//   example_rendering <scene_file> <shader_path> <port>
//
// scene_file       some scene file, e.g., main.mi
// shader_path      path to the shaders, e.g., neuray-<version>/shaders
// port             port for the HTTP server
//
int main( int argc, char* argv[])
{
    // Collect command line parameters
    if( argc != 4) {
        std::cerr << "Usage: example_rendering <scene_file> <shader_path> <port>" << std::endl;
        return EXIT_FAILURE;
    }
    const char* scene_file  = argv[1];
    const char* shader_path = argv[2];
    const char* port        = argv[3];

    // Access the neuray library
    mi::base::Handle< mi::neuraylib::INeuray> neuray( load_and_get_ineuray());
    check_success( neuray.is_valid_interface());

    // Configure the neuray library
    configuration ( neuray, shader_path);

    // Start the neuray library
    check_success( neuray->start( true) == 0);

    // Do the actual rendering
    mi::base::Handle< mi::IBuffer> buffer = rendering( neuray, scene_file);

    // Serve image via HTTP server on given port
    run_http_server( neuray, buffer, port);
    buffer = 0;

    // Shut down the neuray library
    check_success( neuray->shutdown() == 0);
    neuray = 0;

    // Unload the neuray library
    check_success( unload());

    return EXIT_SUCCESS;
}

[Previous] [Next] [Up]