Skip to content

Commit 26c7619

Browse files
committed
Add detailed RGB stream checking
Inspect the magic markers at the end of a JPEG frame and match the sequence number and length. Find out the exact size of the JPEG image for decoders that can't handle garbage after JPEG EOI.
1 parent 2e72fa9 commit 26c7619

File tree

1 file changed

+65
-5
lines changed

1 file changed

+65
-5
lines changed

examples/protonect/src/rgb_packet_stream_parser.cpp

Lines changed: 65 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
{
@@ -87,7 +147,7 @@ void RgbPacketStreamParser::onDataReceived(unsigned char* buffer, size_t length)
87147
RgbPacket rgb_packet;
88148
rgb_packet.sequence = raw_packet->sequence;
89149
rgb_packet.jpeg_buffer = raw_packet->jpeg_buffer;
90-
rgb_packet.jpeg_buffer_length = bb.length - sizeof(RawRgbPacket);
150+
rgb_packet.jpeg_buffer_length = jpeg_length;
91151

92152
// call the processor
93153
processor_->process(rgb_packet);

0 commit comments

Comments
 (0)