简体   繁体   中英

Processing image over tcp socket with c

I have a small c program which connect and authenticate with my security DVR which in turn starts sending me data over the socket. I can connect on port 5000 or port 80 sending different authentification methods to start receiving the video/images. My problem is; I am new to c first of all, and I am very lost on how to process the data received over the socket. This is the data I am sending to authenticate.

char authenticate[] = {
    0x31, 0x31, 0x31, 0x31, 0x88, 0x00, 0x00, 0x00, 
    0x01, 0x01, 0x00, 0x00, 0x88, 0x7d, 0xa6, 0x47, 
    0x0c, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 
    0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x61, 0x64, 0x6d, 0x69, 0x6e, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x31, 0x32, 0x33, 0x34, 
    0x35, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x43, 0x6f, 0x6c, 0x74, 0x6f, 0x6e, 0x73, 0x2d, 
    0x4d, 0x61, 0x63, 0x42, 0x6f, 0x6f, 0x6b, 0x2d, 
    0x50, 0x72, 0x6f, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 
    0x6c, 0x00, 0x00, 0x00, 0x35, 0x34, 0x32, 0x36, 
    0x39, 0x36, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 
 };

  x = sendto(sockfd, authenticate, sizeof(authenticate), 0,
  (struct sockaddr*)&servaddr, sizeof(servaddr));

I am then recieving the data with

while(1)
{
  n = recvfrom(sockfd, data, 2048, 0, NULL, NULL);

When I connect via http port 80 This is the image data that I receive:

Content-length: 2153
Content-type: image/jpeg

ˇÿˇ‡JFIFHHˇ€Cˇ€Cˇ¿#ˇƒ  
    ˇƒ8 2A!$X"#3QRTqëîóò“’÷ˇƒˇƒ@   
        !1A"2QRqrë#SacÅ°¢≥—“ÒBCstÇí¥”ˇ⁄     ?e›n◊}mÀ⁄ÔÅ≥j¿ò[0ÂáֱNU…9'*‚®@ô &yéïùr‰Ù®{ï“däŒÆl$Kkë       R,√fƒSl—EX
    z   \û£≠âflüÈ‚≠ê*àÉ*—1E;q}Ìp6@>øÆÂòŸR≠^Ì˝çò ı;R∆b¡»ü>aÊ∫a˙5KKüz∑¶Î´D“≤κl∂ÎÓ„∆Àn∫¥•sh8vß4≠äöûñy‰H¢çyºí0TQrÏ@π dÅèåfi*XY*F¨Óƒl™¢‰˝S^sgh]î…flzXNü‡†2∑ñæ5t€Tp`qìåos◊iGùjˆ˙+FÈ™‚‘_§≈[”Jˇ     *•<*´∆≥ÁpVGfl
    ï¶ñ—€{ñgíJmd*ôï„å[YT-J†∞π∂¯ë…{¶dyÓaÓhå©!øg⁄∆™≤È:
    ≥Ô`Mú)∞ÚÌǯhˇÿ„Tø∑,9˛õ°˛ıØö~ø«ûÔ˝˙aa{ÜÔû÷Èé‡ÂΩk÷ºµ\sÉÒ¬XÓ∞`¯⁄X“">eäÅœ»G¡ìöÜ"˘mütòÅtuÓbÌh;vB1dflL ∂)
    ´È
    Hm∂Í
    Ω¡î*Ä≤e‘nÄï‘HΩ…77ÙIè6%â%ãµ"T¿n¢Í3%‹zj#™:”ÂmR˛=L  ZsZ[_ïz±»r…™2®ú.«]∑$q¢1)ùftÙ˘îà[q£°Îü&%Ï÷@á∂¿ôEy!ËÇJ0‚‚j»¥|∆fi–ü5"èRj›D˘„õUäú≥û>•«bdôãq]Ö$2ˆ„Gc#,ó±Ò<√-p}ZÍSÛ                                                          £ëóŒsäóNçı≠◊òÊö•mÈÇ_W„Y2∆∫9œxπŸ¸*±’dË⁄1(¸05{üfW∆Éû
    ‘ÿSÑ‘„û.JTÓ9˙Ìø˝∆º=∆        ¬ï∆h≥!`uˆ’Uçõèd„Ï…ı®*GÕıŸ6iíÆiñ¶’ØmBë‰WáÈö˛â‚ı∞>Ó˛◊_Â’ˇπ?º”˘øh~8TÔÕ/ùˆO¬Ewü^◊]…6
    ÕïÊ«p2ˆ◊ä”õU÷ËÖˆ◊䲲ãk–«_2ûk4Éÿ‰aÖƒîP∑ùg⁄†·¢µ’ÂS÷}XNï¯5GWæßGk”óS8fòˇ;˝âp;≈“ƒ5ˇ˜„Éû·&Áa¨ö2tÿ±íÉìcÇeÓ"¬Â„(8¯:øØíM    £rmfiá~≠æ(:oT/U≤/täó       U√ñT0ëªÕ      ê’¢víRT@˙‚ìO7ÖÆÒ‘D<dm@;F®—yÑmPǃ5É+FZÀ"8≥-˙7"ç–ãm{Å∑Öunü»à·®icëcoDìf¬·ñ)!å A¡ñÂNrx√aeP\ZM®£      ‘Y\<kJÿ‚’Ó#„Œª+â3
    ¨π©%Uü±Àñ¨œò§S2àŸßUJjwûYãZ@Ç∆˚¶&hr⁄xj¬ì  È™sàK-…  28Fm‡Ôr√û      8Qè
    ª∑ØP ptt£‚N—Œ∆Iπ ıo«Y{Èe.U[´‰•ı∫ÎæöÙU’‘…)¶Gy
    †“ä]ãä6U≤Å∞b 7X„        ™˙@ÓMÖ∑>_ó
    =fiÔ>·π∂ˇ÷ãÎΩfl«Y!µÎô≥—ß;¨J™èΩ|tLoîRˇM›.@nŸÍ±≈±Ê∏Ï~qkãsv≈Xõ‰í∞Lπ/cR,j*6.Sí„ÿ˘fÑ»7f|_™≥RçÿíE°°bã {{Ïõç#·Ãæ:7çú√´u      o
    ⁄N¨Ω\€ù◊K,Z4àÕ8N\˙πÍë’D∫vbfl∏¢>äz.¸¨⁄Ä‘°dx≈ªàˆÕ45‡ßõub-ü%TVTN8⁄∞¨≤µÁñÜD[;o—˘ƒNˇóóØ[ò;´¡O*∫¿ƒ©∏2ߘG#20˘H∆µªú’2€∂O°Â⁄Ùb®äÌ/hÿQÁXÓŸJzB¬Öw]Ù2ÿ—⁄§∆«gÜö·´˚Ëãt‚+˛Iì¯∂⁄nÎ{ºVʬ)aà∆´°ÀÚËÃkr÷â„ç^1©ôæ
    óv'ô8∆ãπkB˙цπ¯zÉsÀpv;Ã]ÓI€[Ìj/˙A≤øÒ}O˚ËS|Dûƒˇ¶3=ÓÍæ6?Ú…å!¥›¨Ûˆ¸f…€·I~à≥      g>∆®‰√Û0≥30®Æ) èMÖçGÃ∑dÑÖ∞¥Œéf≥ÔyµE¢Yå.õ·ç+r˙ú ≤ZÄP    ‰y¨Km⁄±~ävfl¡'I+b»Ñî[ö<¬        æñ8raEãk

I am unsure if this data is some weird encoding or if it need to be processed somehow to make it valid. I have searched around with no luck or examples of how to properly do this. If i connect via the data port (port 5000 which sends via instead of an image) the data looks pretty much the same although i know it may be processed or unprocessed H.246 video data.

The raw data is an image. It starts after the blank line which terminate the headers.

Code:

n = recvfrom(sockfd, data, 2048, 0, NULL, NULL); // might as well replace with read().  
// use a much larger buffer, ideally large enough to fit largest possible whole image

headers_end_str = "\r\n\r\n";
headers_end_position = strstr(data, headers_end_str);
headers_end_position += strlen(headers_end_str );

if (headers_end_position > n) { ... } // handle errors

FILE* fh = fopen("image.jpg", "wb");

int result = fwrite( &( data[ headers_end_position ), n - headers_end_position, 1, fh);
// check result for errors

// continue reading from socket and writing to file, subsequent reads do not have headers

This should get you started, you need to fine tune reading additional data, and also error handling and end of file.

However, even before you have done all that, you should be able to run "file -s image.jpg" (on linux, or cygwin) and it will tell you it's a JPEG image.

I used WireShark to monitor the communication between the DVR and it's web browser plugin client and the authentication message header is similar to your post (0x31 0x31 0x31 0x31...). How did you construct this array? I searched a lot for this protocol documentation but I didn't find.

In my case I do the requests at port 7171 (it's a DVR settings). I also used a while(true) to keep listening this port and the server sends me a h264 stream.

The problem is that the stream is not like rtps protocol describes, see this great post . In our case we have to parse a kind of proprietary header first (that starts with 0x31 0x31 0x31 0x31) to stract the frame, sps and pps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM