2017-06-05 76 views
0

我有一台IP摄像机,它在UDP/RTP中传输JPEG压缩数据。我使用Boost Asio来接收数据。我知道我已经收到了正确的数据,因为我使用Wireshark检查了每个数据包的标题信息。将从IP摄像机接收到的JPEG数据流解码为C++中的RGB图像

#include <boost/asio.hpp> 

#define MAX_BYTES 1500 

using boost::asio::ip::udp; 

int main(){ 

    boost::asio::io_service io_service; 
    udp::socket socket(io_service , udp::endpoint(udp::v4(),50242)); 
    char data[MAX_BYTES]; 
    size_t bytes_received = 0; 

    while(true){ 

    bytes_received = socket.receive(boost::asio::buffer(data,MAX_BYTES)); 

    } 

} 

我接收的总的1452个字节的每个分组,其中前20个字节是RTP报头(12个字节),接着JPEG报头(8个字节)。剩余的1432个字节包含有效载荷。假设每个帧由145个数据包组成(frm_pckts = 145)。排序报文后我将它们存储在缓冲器中用于单个帧如下:

unsigned char* buffer = (unsigned char*) malloc(frm_pckts * 1432 * sizeof(unsigned char); 

memcpy(&buffer[packet_index*1432] , &data[20], 1432); 

如果我这个缓冲器复制到一个OpenCV的垫,并显示它会显示无用值。我也试过

cv::Mat img = cv::imdecode(frame, CV_LOAD_IMAGE_COLOR); 

但它也没有工作。我看到了所有可能的解决方案,我可以在这个网站上找到,但没有人为我工作。有没有可用于将此缓冲区传递给其中一个函数并检索JPEG帧的库?另外,为了解码帧,我还应该在缓冲区中包含头字节?如果是,哪个头? JPEG标头,RTP标头还是两者?

我非常感谢任何有用的解决方案或建议。

+0

您究竟如何整理数据包?这可能是你问题的根源。 –

+0

你必须在传递给'cv :: imdecode()'的缓冲区中包含JPEG头文件。它必须能够知道图像的格式,所以它需要标题。作为您正确接收图像的第一个测试,将其保存到文件并尝试使用任何JPEG查看器打开该文件。作为另一个测试,我建议使用'cv :: imdecode()'来创建一个小程序,用它解码JPEG文件,以查看您是否正确使用API​​。 – zett42

+0

感谢您的回复。我不认为排序有任何问题,因为我根据从RTP头获得的时间戳和序列号对数据包进行排序。 –

回答

0

JPEG over RTP标题被称为主标题,只有8个字节长。由此创建JFIF头以便能够解码JPEG压缩数据。 JFIF头创建可以使用“RFC 2435”格式完成。那里已经解释了一切。一旦创建了JFIF头部,它就应该被压缩数据前置,然后传递给uncompressedFrame = cv :: imdecode(compressedImage,1)或任何其他JPEG解码器来检索未压缩的帧。如果遇到这样的问题,请通过([email protected])告诉我,我将非常乐意提供帮助。