Skip to content

Commit ef34cfc

Browse files
committed
Merge pull request #221 from xlz/stream-parsers
Improve RGB and depth stream parsers
2 parents 2e72fa9 + f0945e7 commit ef34cfc

9 files changed

+112
-59
lines changed

examples/protonect/include/libfreenect2/depth_packet_processor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ namespace libfreenect2
4040
struct LIBFREENECT2_API DepthPacket
4141
{
4242
uint32_t sequence;
43+
uint32_t timestamp;
4344
unsigned char *buffer;
4445
size_t buffer_length;
4546
};

examples/protonect/include/libfreenect2/frame_listener.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#define FRAME_LISTENER_HPP_
2929

3030
#include <cstddef>
31+
#include <stdint.h>
3132
#include <libfreenect2/config.h>
3233

3334
namespace libfreenect2
@@ -42,6 +43,8 @@ struct LIBFREENECT2_API Frame
4243
Depth = 4
4344
};
4445

46+
uint32_t timestamp;
47+
uint32_t sequence;
4548
size_t width, height, bytes_per_pixel;
4649
unsigned char* data;
4750

examples/protonect/include/libfreenect2/rgb_packet_processor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ struct LIBFREENECT2_API RgbPacket
4141
{
4242
uint32_t sequence;
4343

44+
uint32_t timestamp;
4445
unsigned char *jpeg_buffer;
4546
size_t jpeg_buffer_length;
4647
};

examples/protonect/src/cpu_depth_packet_processor.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,11 @@ void CpuDepthPacketProcessor::process(const DepthPacket &packet)
743743

744744
impl_->startTiming();
745745

746+
impl_->ir_frame->timestamp = packet.timestamp;
747+
impl_->depth_frame->timestamp = packet.timestamp;
748+
impl_->ir_frame->sequence = packet.sequence;
749+
impl_->depth_frame->sequence = packet.sequence;
750+
746751
cv::Mat m = cv::Mat::zeros(424, 512, CV_32FC(9)), m_filtered = cv::Mat::zeros(424, 512, CV_32FC(9)), m_max_edge_test = cv::Mat::ones(424, 512, CV_8UC1);
747752

748753
float *m_ptr = m.ptr<float>();

examples/protonect/src/depth_packet_stream_parser.cpp

Lines changed: 23 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#include <libfreenect2/depth_packet_stream_parser.h>
2828
#include <iostream>
2929
#include <memory.h>
30-
#include <algorithm>
3130

3231
namespace libfreenect2
3332
{
@@ -43,8 +42,8 @@ DepthPacketStreamParser::DepthPacketStreamParser() :
4342
buffer_.front().length = buffer_.front().capacity;
4443
buffer_.back().length = buffer_.back().capacity;
4544

46-
work_buffer_.data = new unsigned char[single_image * 2];
47-
work_buffer_.capacity = single_image * 2;
45+
work_buffer_.data = new unsigned char[single_image];
46+
work_buffer_.capacity = single_image;
4847
work_buffer_.length = 0;
4948
}
5049

@@ -59,43 +58,38 @@ void DepthPacketStreamParser::setPacketProcessor(libfreenect2::BaseDepthPacketPr
5958

6059
void DepthPacketStreamParser::onDataReceived(unsigned char* buffer, size_t in_length)
6160
{
62-
// TODO: simplify this crap (so code, such unreadable, wow ;)
6361
Buffer &wb = work_buffer_;
6462

65-
size_t in_offset = 0;
66-
67-
while(in_offset < in_length)
63+
if(in_length == 0)
64+
{
65+
//synchronize to subpacket boundary
66+
wb.length = 0;
67+
}
68+
else
6869
{
69-
unsigned char *ptr_in = buffer + in_offset, *ptr_out = wb.data + wb.length;
7070
DepthSubPacketFooter *footer = 0;
7171
bool footer_found = false;
7272

73-
size_t max_length = std::min<size_t>(wb.capacity - wb.length, in_length - 8);
74-
75-
for(; in_offset < max_length; ++in_offset)
73+
if(wb.length + in_length == wb.capacity + sizeof(DepthSubPacketFooter))
7674
{
77-
footer = reinterpret_cast<DepthSubPacketFooter *>(ptr_in);
78-
79-
if(footer->magic0 == 0x0 && footer->magic1 == 0x9)
80-
{
81-
footer_found = true;
82-
break;
83-
}
75+
in_length -= sizeof(DepthSubPacketFooter);
76+
footer = reinterpret_cast<DepthSubPacketFooter *>(&buffer[in_length]);
77+
footer_found = true;
78+
}
8479

85-
*ptr_out = *ptr_in;
86-
++ptr_in;
87-
++ptr_out;
80+
if(wb.length + in_length > wb.capacity)
81+
{
82+
std::cerr << "[DepthPacketStreamParser::onDataReceived] subpacket too large" << std::endl;
83+
wb.length = 0;
84+
return;
8885
}
8986

90-
wb.length = ptr_out - wb.data;
87+
memcpy(wb.data + wb.length, buffer, in_length);
88+
wb.length += in_length;
9189

9290
if(footer_found)
9391
{
94-
if((in_length - in_offset) < sizeof(DepthSubPacketFooter))
95-
{
96-
std::cerr << "[DepthPacketStreamParser::onDataReceived] incomplete footer detected!" << std::endl;
97-
}
98-
else if(footer->length > wb.length)
92+
if(footer->length != wb.length)
9993
{
10094
std::cerr << "[DepthPacketStreamParser::onDataReceived] image data too short!" << std::endl;
10195
}
@@ -111,14 +105,15 @@ void DepthPacketStreamParser::onDataReceived(unsigned char* buffer, size_t in_le
111105

112106
DepthPacket packet;
113107
packet.sequence = current_sequence_;
108+
packet.timestamp = footer->timestamp;
114109
packet.buffer = buffer_.back().data;
115110
packet.buffer_length = buffer_.back().length;
116111

117112
processor_->process(packet);
118113
}
119114
else
120115
{
121-
//std::cerr << "[DepthPacketStreamParser::handleNewData] skipping depth packet!" << std::endl;
116+
std::cerr << "[DepthPacketStreamParser::onDataReceived] skipping depth packet" << std::endl;
122117
}
123118
}
124119
else
@@ -147,32 +142,6 @@ void DepthPacketStreamParser::onDataReceived(unsigned char* buffer, size_t in_le
147142

148143
// reset working buffer
149144
wb.length = 0;
150-
// skip header
151-
in_offset += sizeof(DepthSubPacketFooter);
152-
}
153-
else
154-
{
155-
if((wb.length + 8) >= wb.capacity)
156-
{
157-
std::cerr << "[DepthPacketStreamParser::onDataReceived] working buffer full, resetting it!" << std::endl;
158-
wb.length = 0;
159-
ptr_out = wb.data;
160-
}
161-
162-
// copy remaining 8 bytes
163-
if((in_length - in_offset) != 8)
164-
{
165-
std::cerr << "[DepthPacketStreamParser::onDataReceived] remaining data should be 8 bytes, but is " << (in_length - in_offset) << std::endl;
166-
}
167-
168-
for(; in_offset < in_length; ++in_offset)
169-
{
170-
*ptr_out = *ptr_in;
171-
++ptr_in;
172-
++ptr_out;
173-
}
174-
175-
wb.length = ptr_out - wb.data;
176145
}
177146
}
178147
}

examples/protonect/src/opencl_depth_packet_processor.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,11 @@ void OpenCLDepthPacketProcessor::process(const DepthPacket &packet)
653653

654654
impl_->startTiming();
655655

656+
impl_->ir_frame->timestamp = packet.timestamp;
657+
impl_->depth_frame->timestamp = packet.timestamp;
658+
impl_->ir_frame->sequence = packet.sequence;
659+
impl_->depth_frame->sequence = packet.sequence;
660+
656661
impl_->run(packet);
657662

658663
impl_->stopTiming();

examples/protonect/src/opengl_depth_packet_processor.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,11 @@ void OpenGLDepthPacketProcessor::process(const DepthPacket &packet)
940940

941941
if(has_listener)
942942
{
943+
ir->timestamp = packet.timestamp;
944+
depth->timestamp = packet.timestamp;
945+
ir->sequence = packet.sequence;
946+
depth->sequence = packet.sequence;
947+
943948
if(!this->listener_->onNewFrame(Frame::Ir, ir))
944949
{
945950
delete ir;

examples/protonect/src/rgb_packet_stream_parser.cpp

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,29 @@ namespace libfreenect2
3636
LIBFREENECT2_PACK(struct RawRgbPacket
3737
{
3838
uint32_t sequence;
39-
uint32_t unknown0;
39+
uint32_t magic_header; // is 'BBBB' equal 0x42424242
4040

4141
unsigned char jpeg_buffer[0];
4242
});
4343

44+
// starting from JPEG EOI: 0xff 0xd9
45+
// char pad_0xa5[]; //0-3 bytes alignment of 0xa5
46+
// char filler[filler_length] = "ZZZZ...";
47+
LIBFREENECT2_PACK(struct RgbPacketFooter {
48+
uint32_t magic_header; // is '9999' equal 0x39393939
49+
uint32_t sequence;
50+
uint32_t filler_length;
51+
uint32_t unknown1; // seems 0 always
52+
uint32_t unknown2; // seems 0 always
53+
uint32_t timestamp;
54+
float exposure; // ? ranges from 0.5 to about 60.0 with powerfull light at camera or totally covered
55+
float gain; // ? ranges from 1.0 when camera is clear to 1.5 when camera is covered.
56+
uint32_t magic_footer; // is 'BBBB' equal 0x42424242
57+
uint32_t packet_size;
58+
float unknown3; // seems 1.0f always
59+
uint32_t unknown4[3]; // seems to be 0 all the time.
60+
});
61+
4462
RgbPacketStreamParser::RgbPacketStreamParser() :
4563
processor_(noopProcessor<RgbPacket>())
4664
{
@@ -71,12 +89,54 @@ void RgbPacketStreamParser::onDataReceived(unsigned char* buffer, size_t length)
7189
else
7290
{
7391
std::cerr << "[RgbPacketStreamParser::onDataReceived] buffer overflow!" << std::endl;
92+
fb.length = 0;
93+
return;
7494
}
7595

76-
// not full transfer buffer and we already have some data -> signals end of rgb image packet
77-
// TODO: better method, is unknown0 a magic? detect JPEG magic?
78-
if(length < 0x4000 && fb.length > sizeof(RgbPacket))
96+
// not enough data to do anything
97+
if (fb.length <= sizeof(RawRgbPacket) + sizeof(RgbPacketFooter))
98+
return;
99+
100+
RgbPacketFooter* footer = reinterpret_cast<RgbPacketFooter *>(&fb.data[fb.length - sizeof(RgbPacketFooter)]);
101+
102+
if (footer->magic_header == 0x39393939 && footer->magic_footer == 0x42424242)
79103
{
104+
RawRgbPacket *raw_packet = reinterpret_cast<RawRgbPacket *>(fb.data);
105+
106+
if (fb.length != footer->packet_size || raw_packet->sequence != footer->sequence)
107+
{
108+
std::cerr << "[RgbPacketStreamParser::onDataReceived] packetsize or sequence doesn't match!" << std::endl;
109+
fb.length = 0;
110+
return;
111+
}
112+
113+
if (fb.length - sizeof(RawRgbPacket) - sizeof(RgbPacketFooter) < footer->filler_length)
114+
{
115+
std::cerr << "[RgbPacketStreamParser::onDataReceived] not enough space for packet filler!" << std::endl;
116+
fb.length = 0;
117+
return;
118+
}
119+
120+
size_t jpeg_length = 0;
121+
//check for JPEG EOI 0xff 0xd9 within 0 to 3 alignment bytes
122+
size_t length_no_filler = fb.length - sizeof(RawRgbPacket) - sizeof(RgbPacketFooter) - footer->filler_length;
123+
for (size_t i = 0; i < 4; i++)
124+
{
125+
if (length_no_filler < i + 2)
126+
break;
127+
size_t eoi = length_no_filler - i;
128+
129+
if (raw_packet->jpeg_buffer[eoi - 2] == 0xff && raw_packet->jpeg_buffer[eoi - 1] == 0xd9)
130+
jpeg_length = eoi;
131+
}
132+
133+
if (jpeg_length == 0)
134+
{
135+
std::cerr << "[RgbPacketStreamParser::onDataReceived] no JPEG detected!" << std::endl;
136+
fb.length = 0;
137+
return;
138+
}
139+
80140
// can the processor handle the next image?
81141
if(processor_->ready())
82142
{
@@ -86,8 +146,9 @@ void RgbPacketStreamParser::onDataReceived(unsigned char* buffer, size_t length)
86146
RawRgbPacket *raw_packet = reinterpret_cast<RawRgbPacket *>(bb.data);
87147
RgbPacket rgb_packet;
88148
rgb_packet.sequence = raw_packet->sequence;
149+
rgb_packet.timestamp = footer->timestamp;
89150
rgb_packet.jpeg_buffer = raw_packet->jpeg_buffer;
90-
rgb_packet.jpeg_buffer_length = bb.length - sizeof(RawRgbPacket);
151+
rgb_packet.jpeg_buffer_length = jpeg_length;
91152

92153
// call the processor
93154
processor_->process(rgb_packet);

examples/protonect/src/turbo_jpeg_rgb_packet_processor.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ void TurboJpegRgbPacketProcessor::process(const RgbPacket &packet)
112112
{
113113
impl_->startTiming();
114114

115+
impl_->frame->timestamp = packet.timestamp;
116+
impl_->frame->sequence = packet.sequence;
117+
115118
int r = tjDecompress2(impl_->decompressor, packet.jpeg_buffer, packet.jpeg_buffer_length, impl_->frame->data, 1920, 1920 * tjPixelSize[TJPF_BGR], 1080, TJPF_BGR, 0);
116119

117120
if(r == 0)

0 commit comments

Comments
 (0)