Skip to content

Commit

Permalink
infrared rgb HEVC streaming
Browse files Browse the repository at this point in the history
Related to #26
  • Loading branch information
bmegli committed Oct 30, 2020
1 parent c17c16d commit 8ac7dde
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 30 deletions.
23 changes: 14 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Realsense hardware video/depth encoding and streaming over custom [MLSP](https:/

This includes streaming:
- color (H.264, HEVC Main)
- infrared (H.264, HEVC Main)
- infrared/infrared-rgb (H.264, HEVC Main)
- depth (HEVC Main10)
- textured depth (HEVC Main10 + HEVC Main)

Expand Down Expand Up @@ -35,7 +35,7 @@ Requires Intel VAAPI compatible hardware encoder (QuickSync Video). For depth en

[Other technologies](https://github.com/bmegli/realsense-network-hardware-video-encoder/wiki/Hardware) may also work but were not tested.

Infrared textured depth encoding is implemented for D435, D455 and L515.
Infrared textured depth encoding is implemented for D415, D435, D455 and L515.
Color textured depth encoding is implemented for D415, D435, D455, L515.

## Dependencies
Expand Down Expand Up @@ -96,23 +96,28 @@ examples:
./realsense-nhve-h264 192.168.0.125 9766 color 640 360 30 50 /dev/dri/renderD128 500000```
Stream Realsense:
- color/infrared with HEVC Main
- color/infrared/infrared-rgb with HEVC Main
- depth with HEVC Main10
```bash
Usage:
./realsense-nhve-hevc <host> <port> <color/ir/depth> <width> <height> <framerate> <seconds> [device] [bitrate] [depth units] [json]
Usage: ./realsense-nhve-hevc <host> <port> <color/ir/ir-rgb/depth> <width> <height> <framerate> <seconds> [device] [bitrate] [depth units] [json]

examples:
./realsense-nhve-hevc 127.0.0.1 9766 color 640 360 30 5
./realsense-nhve-hevc 127.0.0.1 9766 infrared 640 360 30 5
./realsense-nhve-hevc 127.0.0.1 9766 ir 640 360 30 5
./realsense-nhve-hevc 127.0.0.1 9766 ir-rgb 640 360 30 5
./realsense-nhve-hevc 127.0.0.1 9766 depth 640 360 30 5
./realsense-nhve-hevc 127.0.0.1 9766 color 640 360 30 5 /dev/dri/renderD128
./realsense-nhve-hevc 127.0.0.1 9766 infrared 640 360 30 5 /dev/dri/renderD128
./realsense-nhve-hevc 127.0.0.1 9766 ir 640 360 30 5 /dev/dri/renderD128
./realsense-nhve-hevc 127.0.0.1 9766 ir-rgb 640 360 30 5 /dev/dri/renderD128
./realsense-nhve-hevc 127.0.0.1 9766 depth 640 360 30 5 /dev/dri/renderD128
./realsense-nhve-hevc 192.168.0.125 9766 color 640 360 30 50 /dev/dri/renderD128 500000
./realsense-nhve-hevc 192.168.0.125 9768 depth 848 480 30 50 /dev/dri/renderD128 2000000
./realsense-nhve-hevc 192.168.0.125 9768 depth 848 480 30 50 /dev/dri/renderD128 8000000 0.0001
./realsense-nhve-hevc 127.0.0.1 9768 depth 848 480 30 50 /dev/dri/renderD128 2000000
./realsense-nhve-hevc 192.168.0.100 9768 depth 848 480 30 500 /dev/dri/renderD128 2000000 0.0001
./realsense-nhve-hevc 192.168.0.100 9768 depth 848 480 30 500 /dev/dri/renderD128 2000000 0.00005
./realsense-nhve-hevc 192.168.0.100 9768 depth 848 480 30 500 /dev/dri/renderD128 2000000 0.000025
./realsense-nhve-hevc 192.168.0.100 9768 depth 848 480 30 500 /dev/dri/renderD128 2000000 0.0000125
./realsense-nhve-hevc 192.168.0.100 9768 depth 640 480 30 500 /dev/dri/renderD128 8000000 0.0000390625 my_config.json
```

Expand Down
5 changes: 3 additions & 2 deletions rnhve_h264.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ bool main_loop(const input_args& input, rs2::pipeline& realsense, nhve *streamer
const int frames = input.seconds * input.framerate;
int f;
nhve_frame frame = {0};
uint8_t *color_data = NULL; //data of dummy color plane for NV12 with Realsense Infrared
uint8_t *color_data = NULL; //data of dummy color plane for NV12 with Realsense infrared

for(f = 0; f < frames; ++f)
{
Expand Down Expand Up @@ -202,6 +202,7 @@ int hint_user_on_failure(char *argv[])
{
cerr << "unable to initalize, try to specify device e.g:" << endl << endl;
cerr << argv[0] << " 127.0.0.1 9766 color 640 360 30 5 /dev/dri/renderD128" << endl;
cerr << argv[0] << " 127.0.0.1 9766 infrared 640 360 30 5 /dev/dri/renderD128" << endl;
cerr << argv[0] << " 127.0.0.1 9766 ir 640 360 30 5 /dev/dri/renderD128" << endl;
cerr << argv[0] << " 127.0.0.1 9766 ir-rgb 640 360 30 5 /dev/dri/renderD128" << endl;
return -1;
}
50 changes: 31 additions & 19 deletions rnhve_hevc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Realsense Network Hardware Video Encoder
*
* Realsense hardware encoded UDP HEVC streaming
* - color/infrared (Main)
* - color/infrared/infrared rgb (Main)
* - depth (Main10)
*
* Copyright 2020 (C) Bartosz Meglicki <[email protected]>
Expand All @@ -28,7 +28,7 @@ using namespace std;

int hint_user_on_failure(char *argv[]);

enum StreamType {COLOR, INFRARED, DEPTH};
enum StreamType {COLOR, INFRARED, INFRARED_RGB, DEPTH};

//user supplied input
struct input_args
Expand Down Expand Up @@ -78,10 +78,10 @@ int main(int argc, char* argv[])

bool status = false;

if(user_input.stream == COLOR || user_input.stream == INFRARED)
status = main_loop_color_infrared(user_input, realsense, streamer);
if(user_input.stream == DEPTH)
status = main_loop_depth(user_input, realsense, streamer);
else //color, infrared, infrared rgb
status = main_loop_color_infrared(user_input, realsense, streamer);

nhve_close(streamer);

Expand All @@ -97,17 +97,17 @@ bool main_loop_color_infrared(const input_args& input, rs2::pipeline& realsense,
const int frames = input.seconds * input.framerate;
int f;
nhve_frame frame = {0};
uint8_t *color_data = NULL; //data of dummy color plane for NV12
uint8_t *color_data = NULL; //data of dummy color plane for NV12 with Realsense infrared

for(f = 0; f < frames; ++f)
{
rs2::frameset frameset = realsense.wait_for_frames();

rs2::video_frame video_frame = input.stream == COLOR ? frameset.get_color_frame() : frameset.get_infrared_frame(1);
rs2::video_frame video_frame = (input.stream == COLOR) ? frameset.get_color_frame() : frameset.get_infrared_frame(0);

if(!(input.stream == COLOR) && !color_data)
{ //prepare dummy color plane for NV12 format, half the size of Y
//we can't alloc it in advance, this is the first time we know realsense stride
if(input.stream == INFRARED && !color_data)
{ //prepare dummy color plane for NV12 format, half the size of Y
//we can't alloc it in advance, this is the first time we know realsense stride
int size = video_frame.get_stride_in_bytes()*video_frame.get_height()/2;
color_data = new uint8_t[size];
memset(color_data, 128, size);
Expand All @@ -116,8 +116,8 @@ bool main_loop_color_infrared(const input_args& input, rs2::pipeline& realsense,
frame.linesize[0] = video_frame.get_stride_in_bytes();
frame.data[0] = (uint8_t*) video_frame.get_data();

//if we are streaming infrared we have 2 planes (luminance and color)
frame.linesize[1] = (input.stream == COLOR) ? 0 : frame.linesize[0];
//if we are streaming infrared we have 2 planes (luminance and dummy color)
frame.linesize[1] = (input.stream == INFRARED) ? frame.linesize[0] : 0;
frame.data[1] = color_data; //dummy color plane for infrared

if(nhve_send(streamer, &frame, 0) != NHVE_OK)
Expand Down Expand Up @@ -212,10 +212,9 @@ void init_realsense(rs2::pipeline& pipe, input_args& input)
if(input.stream == COLOR)
cfg.enable_stream(RS2_STREAM_COLOR, input.width, input.height, RS2_FORMAT_YUYV, input.framerate);
else if(input.stream == INFRARED)
{// depth stream seems to be required for infrared to work
cfg.enable_stream(RS2_STREAM_DEPTH, input.width, input.height, RS2_FORMAT_Z16, input.framerate);
cfg.enable_stream(RS2_STREAM_INFRARED, input.width, input.height, RS2_FORMAT_Y8, input.framerate);
}
else if(input.stream == INFRARED_RGB)
cfg.enable_stream(RS2_STREAM_INFRARED, input.width, input.height, RS2_FORMAT_UYVY, input.framerate);
else if(input.stream == DEPTH)
cfg.enable_stream(RS2_STREAM_DEPTH, input.width, input.height, RS2_FORMAT_Z16, input.framerate);

Expand Down Expand Up @@ -315,13 +314,15 @@ int process_user_input(int argc, char* argv[], input_args* input, nhve_net_confi
{
if(argc < 8)
{
cerr << "Usage: " << argv[0] << " <host> <port> <color/ir/depth> <width> <height> <framerate> <seconds> [device] [bitrate] [depth units] [json]" << endl;
cerr << "Usage: " << argv[0] << " <host> <port> <color/ir/ir-rgb/depth> <width> <height> <framerate> <seconds> [device] [bitrate] [depth units] [json]" << endl;
cerr << endl << "examples: " << endl;
cerr << argv[0] << " 127.0.0.1 9766 color 640 360 30 5" << endl;
cerr << argv[0] << " 127.0.0.1 9766 infrared 640 360 30 5" << endl;
cerr << argv[0] << " 127.0.0.1 9766 ir 640 360 30 5" << endl;
cerr << argv[0] << " 127.0.0.1 9766 ir-rgb 640 360 30 5" << endl;
cerr << argv[0] << " 127.0.0.1 9766 depth 640 360 30 5" << endl;
cerr << argv[0] << " 127.0.0.1 9766 color 640 360 30 5 /dev/dri/renderD128" << endl;
cerr << argv[0] << " 127.0.0.1 9766 infrared 640 360 30 5 /dev/dri/renderD128" << endl;
cerr << argv[0] << " 127.0.0.1 9766 ir 640 360 30 5 /dev/dri/renderD128" << endl;
cerr << argv[0] << " 127.0.0.1 9766 ir-rgb 640 360 30 5 /dev/dri/renderD128" << endl;
cerr << argv[0] << " 127.0.0.1 9766 depth 640 360 30 5 /dev/dri/renderD128" << endl;
cerr << argv[0] << " 192.168.0.125 9766 color 640 360 30 50 /dev/dri/renderD128 500000" << endl;
cerr << argv[0] << " 127.0.0.1 9768 depth 848 480 30 50 /dev/dri/renderD128 2000000" << endl;
Expand All @@ -339,8 +340,13 @@ int process_user_input(int argc, char* argv[], input_args* input, nhve_net_confi

char c = argv[3][0]; //color, infrared, depth
if(c == 'c') input->stream = COLOR;
else if(c == 'i') input->stream = INFRARED;
else if(c == 'd') input->stream = DEPTH;
else if(c == 'i')
{
input->stream = INFRARED;
if(strlen(argv[3]) > 3 && argv[3][2] == '-')
input->stream = INFRARED_RGB;
}
else
{
cerr << "unknown stream: " << argv[3];
Expand All @@ -349,11 +355,14 @@ int process_user_input(int argc, char* argv[], input_args* input, nhve_net_confi

//native format of Realsense RGB sensor is YUYV (YUY2, YUYV422)
//see https://github.com/IntelRealSense/librealsense/issues/3042
//Realsense datasheet mentions uyvy format for IR rgb data
//see https://dev.intelrealsense.com/docs/intel-realsense-d400-series-product-family-datasheet

//on the other hand native format for VAAPI is nv12
//we will match:
//- Realsense RGB sensor YUYV with VAAPI YUYV422 (same format)
//- Realsense IR sensor Y8 with VAAPI NV12 (luminance plane with dummy color plane)
//- Realsense IR sensor rgb data UYVY with VAAPI uyvy422
//this way we always have optimal format at least on one side and hardware conversion on other

//for depth encoding we use 10 bit P010LE pixel format
Expand All @@ -368,6 +377,8 @@ int process_user_input(int argc, char* argv[], input_args* input, nhve_net_confi
hw_config->pixel_format = "yuyv422";
else if(input->stream == INFRARED)
hw_config->pixel_format = "nv12";
else if(input->stream == INFRARED_RGB)
hw_config->pixel_format = "uyvy422";
else //DEPTH
{
hw_config->pixel_format = "p010le";
Expand Down Expand Up @@ -421,7 +432,8 @@ int hint_user_on_failure(char *argv[])
{
cerr << "unable to initalize, try to specify device e.g:" << endl << endl;
cerr << argv[0] << " 127.0.0.1 9766 color 640 360 30 5 /dev/dri/renderD128" << endl;
cerr << argv[0] << " 127.0.0.1 9766 infrared 640 360 30 5 /dev/dri/renderD128" << endl;
cerr << argv[0] << " 127.0.0.1 9766 ir 640 360 30 5 /dev/dri/renderD128" << endl;
cerr << argv[0] << " 127.0.0.1 9766 ir-rgb 640 360 30 5 /dev/dri/renderD128" << endl;
cerr << argv[0] << " 127.0.0.1 9766 depth 640 360 30 5 /dev/dri/renderD128" << endl;
return -1;
}

0 comments on commit 8ac7dde

Please sign in to comment.