This example renders a scene and serves an interactive video stream over RTMP.
#include "example_shared.h"
#include "example_render_target_simple.h"
#include <fstream>
#include <iostream>
#include <vector>
{
public:
const mi::Uint8* get_data()
const {
return &m_buffer[0]; }
mi::Size get_data_size()
const {
return m_buffer.size(); }
Buffer( const std::vector<mi::Uint8>& content) { m_buffer = content; }
private:
std::vector<mi::Uint8> m_buffer;
};
{
public:
{
iresponse->set_header( "Content-Type", "application/x-shockwave-flash");
}
};
{
public:
Request_handler( const char* swf_file) : m_swf_file( swf_file) { }
{
std::ifstream file( m_swf_file, std::ios::in|std::ios::binary|std::ios::ate);
check_success( file);
std::ifstream::pos_type size = file.tellg();
std::vector<mi::Uint8> data(
static_cast<mi::Size>( size));
file.seekg( 0, std::ios::beg);
file.read( reinterpret_cast<char*>( &data[0]), size);
file.close();
connection->
enqueue( buffer.get());
return true;
}
private:
const char* m_swf_file;
};
{
public:
{
if( is_start) {
check_success( stream->
use_codec(
"screen video"));
check_success( codec->init( 512, 384, out) == 0);
}
else {
check_success( codec->close( out) == 0);
}
return true;
}
};
{
public:
bool handle(
{
if (send_queue_is_full)
return true;
{
canvas = m_cached_canvas.get();
if ( !canvas)
return true;
}
bool result = (codec->encode_canvas( canvas, out) == 0);
return result;
}
{
}
private:
};
{
public:
Render_event_handler(
{
{
m_render_context = scene->create_render_context( transaction.get(), "iray");
check_success( m_render_context.is_valid_interface());
scheduler_mode->set_c_str( "interactive");
m_render_context->set_option( "scheduler_mode", scheduler_mode.get());
interval->set_value( 0.1f);
m_render_context->set_option( "interactive_update_interval", interval.get());
}
transaction->commit();
}
{
{
new Render_target( image_api.get(), "Color", 512, 384));
check_success(
m_render_context->render( transaction.get(), render_target.get(), 0) >= 0);
m_frame_handler->update_canvas( canvas.get());
}
transaction->commit();
return true;
}
private:
};
{
public:
bool handle(
{
if( is_create) {
new Play_event_handler());
new Render_event_handler( m_neuray.get(), m_scope.get(),frame_event_handler.get()));
}
return true;
}
private:
};
{
public:
bool handle(
const char* ,
{
{
check_success( camera.is_valid_interface());
check_success( imap.is_valid_interface());
if ( pan_x) {
camera->set_offset_x( x - pan_x->get_value<
mi::Sint32>());
if( pan_xd) {
}
}
if( pan_y) {
camera->set_offset_y( y - pan_y->get_value<
mi::Sint32>());
}
if ( dir) {
bool going_right = dir->get_value<bool>();
going_right = !going_right;
}
}
transaction->commit();
return true;
}
private:
};
{
public:
bool handle(
{
if( is_create) {
new Stream_event_handler( m_neuray.get(), m_scope.get()));
new Call_event_handler( m_scope.get()));
}
return true;
}
private:
};
{
check_success( rc->add_mdl_path( mdl_path) == 0);
check_success( rc->add_mdl_path( ".") == 0);
}
void prepare_rendering(
{
check_success( database.is_valid_interface());
database->get_global_scope());
check_success( transaction.is_valid_interface());
check_success( import_api.is_valid_interface());
import_api->import_elements( transaction.get(), uri->get_c_str()));
check_success( import_result->get_error_number() == 0);
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");
transaction->commit();
}
void run_http_and_rtmp_server(
{
http_factory->create_server());
new Request_handler( swf_file));
http_server->install( request_handler.get());
new Response_handler());
http_server->install( response_handler.get());
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));
http_server->start( address);
database->get_global_scope());
new Connect_event_handler( neuray, scope.get()));
rtmp_server->install( connect_handler.get());
rtmp_server->start( "0.0.0.0:1935");
sleep_seconds( 30);
http_server->shutdown();
rtmp_server->shutdown();
}
int main( int argc, char* argv[])
{
if( argc != 5) {
std::cerr << "Usage: example_rtmp_server <swf_file> <scene_file> <mdl_path> <port>"
<< std::endl;
keep_console_open();
return EXIT_FAILURE;
}
const char* swf_file = argv[1];
const char* scene_file = argv[2];
const char* mdl_path = argv[3];
const char* port = argv[4];
check_success( neuray.is_valid_interface());
configuration( neuray.get(), mdl_path);
check_start_success( result);
prepare_rendering( neuray.get(), scene_file);
run_http_and_rtmp_server( neuray.get(), port, swf_file);
check_success( neuray->
shutdown() == 0);
neuray = 0;
check_success( unload());
keep_console_open();
return EXIT_SUCCESS;
}
This interface represents bool.
Definition: inumber.h:122
This interface is the base interface of all types.
Definition: idata.h:297
This interface represents mi::Float32.
Definition: inumber.h:221
This interface represents mi::Float64.
Definition: inumber.h:232
This interface represents maps, i.e., a key-value based data structure.
Definition: imap.h:41
This interface represents mi::Sint32.
Definition: inumber.h:199
A simple string class.
Definition: istring.h:22
Handle class template for interfaces, automatizing the lifetime control via reference counting.
Definition: handle.h:113
Mixin class template for deriving interface implementations.
Definition: interface_implement.h:41
Utility class to acquire a lock that is released by the destructor.
Definition: lock.h:61
Non-recursive lock class.
Definition: lock.h:49
The connection class represents a connection from a client to the server.
Definition: http.h:277
virtual IResponse * get_response()=0
Returns the response associated with the connection.
virtual bool enqueue(neuraylib::IBuffer *buffer)=0
Enqueues a buffer to be sent on the connection.
The factory can be used to instantiate the built-in HTTP classes.
Definition: http.h:922
This interface holds all the parameters of a response.
Definition: http.h:197
The camera defines the viewpoint from which the scene is rendered.
Definition: icamera.h:56
Abstract interface for a canvas represented by a rectangular array of tiles.
Definition: icanvas.h:89
This interface is used to interact with the distributed database.
Definition: idatabase.h:289
This interface provides various utilities related to canvases and buffers.
Definition: iimage_api.h:72
This interface is used to import files.
Definition: iimport_api.h:100
This is an object representing the Iray library.
Definition: ineuray.h:44
virtual Sint32 shutdown(bool blocking=true)=0
Shuts down the library.
virtual base::IInterface * get_api_component(const base::Uuid &uuid) const =0
Returns an API component from the Iray SDK API.
virtual Sint32 start(bool blocking=true)=0
Starts the operation of the Iray library.
This interface is used to load plugins and to query information about loaded plugins.
Definition: iplugin_configuration.h:24
This interface is used to query and change the rendering configuration.
Definition: irendering_configuration.h:109
The scene is the top-level element describing a subset of DB elements to be rendered.
Definition: iscene.h:44
A scope is the context which determines the visibility of database elements.
Definition: iscope.h:44
virtual ITransaction * create_transaction()=0
Creates a new transaction associated with this scope.
A buffer for video data representing a frame.
Definition: ivideo_plugin.h:33
The connection class represents a connection from a client to the server.
Definition: rtmp.h:212
virtual void register_stream_event_handler(IStream_event_handler *stream_event_handler)=0
Registers a stream event handler.
virtual void register_remote_call_handler(ICall_event_handler *call_handler, const char *procedure_name=0)=0
Registers a call event handler for the passed procedure name.
The factory can be used to instantiate the built-in RTMP server.
Definition: rtmp.h:547
Representing an RTMP stream.
Definition: rtmp.h:419
virtual bool use_codec(const char *name)=0
Tells the RTMP server which codec will be used on the stream.
virtual void register_render_event_handler(IRender_event_handler *render_event_handler)=0
Registers the render event handler.
virtual void register_play_event_handler(IPlay_event_handler *play_event_handler)=0
Registers the play event handler.
virtual void register_frame_event_handler(IFrame_event_handler *frame_event_handler)=0
Registers the frame event handler.
virtual neuraylib::IVideo_encoder * get_video_codec()=0
Returns the video codec for this stream.
#define MI_BASE_DLL_FILE_EXT
The operating system specific default filename extension for shared libraries (DLLs)
Definition: config.h:340
virtual const IInterface * get_interface(const Uuid &interface_id) const =0
Acquires a const interface from another.
virtual Uint32 retain() const =0
Increments the reference count.
Handle<Interface> make_handle_dup(Interface *iptr)
Converts passed-in interface pointer to a handle, without taking interface over.
Definition: handle.h:439
static const Dup_interface DUP_INTERFACE
Symbolic constant to trigger a special constructor in the Handle class.
Definition: handle.h:37
virtual Uint32 release() const =0
Decrements the reference count.
unsigned char Uint8
8-bit unsigned integer.
Definition: types.h:47
Uint64 Size
Unsigned integral type that is large enough to hold the size of all types.
Definition: types.h:112
double Float64
64-bit float.
Definition: types.h:52
signed int Sint32
32-bit signed integer.
Definition: types.h:46
Common namespace for APIs of NVIDIA Advanced Rendering Center GmbH.
Definition: neuraylib.h:179
/******************************************************************************
* Copyright 2024 NVIDIA Corporation. All rights reserved.
* Germany. All rights reserved
*****************************************************************************/
package {
import flash.events.MouseEvent;
import flash.events.NetStatusEvent;
import flash.events.SecurityErrorEvent;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import mx.core.Application;
import mx.core.UIComponent;
public class example_rtmp_server_actionscript extends UIComponent {
private var streamName:String = "example_rtmp_server";
public var connection:NetConnection = null;
private var video:Video = null;
private var mystream:NetStream = null;
private var client:Object = null;
private var mouseButton:Boolean = false;
private var mousePosX:int = 0;
private var mousePosY:int = 0;
public function example_rtmp_server_actionscript() {
super();
this.addEventListener(MouseEvent.MOUSE_DOWN, this.onMouseDown);
}
public function makeConnection(url:String):void {
if (connection != null) {
mystream = null;
connection.close();
} else {
connection = new NetConnection();
}
connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
var args:Object = new Object();
args["resolution_x"] = floor16(this.width).toString();
args["resolution_y"] = floor16(this.height).toString();
connection.connect(url,args);
}
private function floor16(val:int):int {
return int(val/16) * 16;
}
public function closeConnection():void {
if (connection != null) {
mystream = null;
connection.close();
}
}
private function netStatusHandler(event:NetStatusEvent):void {
switch (event.info.code) {
case "NetConnection.Connect.Success":
connectStream();
break;
case "NetStream.Play.StreamNotFound":
trace("Stream not found: " + streamName);
break;
}
}
private function securityErrorHandler(event:SecurityErrorEvent):void {
trace("securityErrorHandler: " + event);
}
private function connectStream():void {
mystream = new NetStream(connection);
mystream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
if (video == null) {
video = new Video(this.width,this.height);
video.smoothing = true;
}
video.attachNetStream(mystream);
addChild(video);
mystream.play(streamName);
}
public function onMouseDown(event: MouseEvent):void {
var x: int = event.stageX - (event.target as UIComponent).parent.x;
var y: int = event.stageY - (event.target as UIComponent).parent.y;
mousePosX = x;
mousePosY = y;
Application.application.addEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
Application.application.addEventListener(MouseEvent.MOUSE_MOVE, this.onMouseMove);
mouseButton = true;
}
public function onMouseUp(event: MouseEvent):void {
if (mouseButton) {
mouseButton = false;
Application.application.removeEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
Application.application.removeEventListener(MouseEvent.MOUSE_MOVE, this.onMouseMove);
}
}
public function onMouseMove(event: MouseEvent):void
{
var x: int = event.stageX - (event.target as UIComponent).parent.x;
var y: int = event.stageY - (event.target as UIComponent).parent.y;
if (mouseButton && connection && connection.connected && mystream) {
var diff_x:int = x-mousePosX;
var diff_y:int = y-mousePosY;
var args:Object = new Object();
if (diff_x != 0) args["pan_x"] = diff_x;
if (diff_y != 0) args["pan_y"] = -diff_y;
if (diff_x || diff_y) {
// For demonstration purposes also send a double..
args["pan_xd"] = (diff_x < 0) ? diff_x - 0.1 : diff_x + 0.1
// ..and some bool
args["going_right"] = diff_x > 0 ? true : false;
connection.call("moveCamera",null,args);
}
mousePosX = x;
mousePosY = y;
}
}
}
}