2017-06-05 73 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])告訴我,我將非常樂意提供幫助。