अब वापस बैठते हैं, मैं आपको इस बग के बारे में विस्तार से बताऊंगा।
बग के बारे में संक्षेप में
उन लोगों के लिए जिन्होंने पेड़ पर विचार के पिछले प्रसार को नहीं पढ़ा है, और बस समस्या को औपचारिक रूप देने के लिए, मैं संक्षेप में बग को लिखूंगा।
इसलिए आपके पास एक कैमरा है। आप इसे डालते हैं, कनेक्ट करते हैं, देखते हैं - और सब कुछ ठीक है। अब आप इसे थोड़ी देर के लिए छोड़ दें - और वीडियो कलाकृतियों को देखना शुरू करें (विभिन्न कारणों से, पैकेट खो जाते हैं)। आप कहते हैं अहा! और कैमरे को यूडीपी से टीसीपी में स्विच करें (उन्हें वहां खोना नहीं चाहिए!)। और आप एक और दिलचस्प तस्वीर का पालन करते हैं - पर्यावरणीय नियमितता के साथ, कनेक्शन बस गायब हो जाता है। इसी समय, नेटवर्क क्रम में है, कोई भी नुकसान दिखाई नहीं दे रहा है, कुछ भी दिखाई नहीं दे रहा है - लेकिन कैमरा नियमित रूप से बंद हो जाता है ...
उपस्थिति की प्रकृति
तो, RTSP के माध्यम से नेटवर्क पर एक धारा प्रसारित करने वाला एक निश्चित कैमरा है।
यूडीपी पर प्रसारण किया जा सकता है, और फिर प्रत्येक नेटवर्क पैकेट आत्मनिर्भर (अधिक या कम) है। प्रोटोकॉल और बाकी सब कुछ किसी भी समय तैयार होना चाहिए, जिसमें से कोई भी पैकेज गायब हो, या आदेश दूषित हो। प्रोटोकॉल इसके लिए तैयार किया गया है, ग्राहक भी।
प्रसारण टीसीपी पर किया जा सकता है। चूंकि TCP डिलीवरी की गारंटी के साथ एक स्ट्रीमिंग प्रोटोकॉल है, इसलिए यह पैकेट (सिद्धांत में) में नहीं टूटता है, प्रत्येक फ्रेम के लेबल जिनकी लंबाई के साथ उन्हें प्रोटोकॉल में जोड़ा जाता है। यह आपको यूडीपी के रूप में टीसीपी की कल्पना करने की अनुमति देता है - बस मार्कर, लंबाई पढ़ें, और उसके बाद पढ़ें वांछित बाइट लंबाई => हमें पैकेट प्राप्त हुआ, कार्य पिछले एक तक कम हो गया है।
लेकिन कुछ बारीकियां हैं: यदि कैमरा और क्लाइंट के बीच का चैनल कैमरा द्वारा बनाई गई स्ट्रीम से पतला है, तो अगर यूडीपी के पैकेट बस अपने आप ही गायब हो जाते हैं, तो टीसीपी फिर से शुरू हो जाएगा। बाहर जाने वाले पैकेट कैमरे की मेमोरी में जमा होने लगेंगे। इसलिए, कुछ बिंदु पर, कैमरे की मेमोरी समाप्त हो जाएगी।
ऐसा होने से रोकने के लिए, सर्वर साइड के सभी निर्माता एक तरह से या किसी अन्य डेटा को बाहर फेंक देते हैं यदि वे आउटगोइंग छेद में फिट नहीं होते हैं।
लेकिन यह फेंकने की आवश्यकता को सही ढंग से पूरा करने की आवश्यकता है - अगर यूडीपी के पैकेट पूरी तरह से खो जाते हैं, तो टीसीपी पर पैकेट को एक मनमाना क्षण में जमा देता है। और यहाँ से बहुत ही जादू शुरू होता है, जो सभी बुराइयों की जड़ है।
सबसे प्रसिद्ध ओपनसोर्स RTSP स्ट्रीमर Live555 सर्वर है।
एक रूप या किसी अन्य में, यह किनारे पर उपयोग किए जाने वाले कैमरा निर्माताओं के कई अन्य डेरिवेटिव को रेखांकित करता है।
टीसीपी पर पैकेट भेजने के एक पाठ्यपुस्तक कार्यान्वयन पर विचार करें, जो अभी भी कैमरों में मूल रूप में स्थानों पर पाया जाता है।
SendRTPOverTCP फ़ंक्शन पर एक नज़र डालें: भेजने को "हेड-ऑन" लागू किया गया है। हम पैकेज '$' का स्टार्ट लेबल भेजते हैं। अगले बाइट में चैनल नंबर भेजें। फिर हम लंबाई बनाते हैं और अगले दो बाइट्स भेजते हैं। और अंत में, हम पूरे पैकेट को भेजते हैं (जो कि एक भेज () ओम) के साथ यूडीपी में चला जाता है।
प्रत्येक भेजने की जाँच की जाती है कि डेटा भेजा गया है (सॉकेट नॉन-ब्लॉकिंग मोड में है, इसलिए केवल वही भेजा जा सकता है जो भेजा गया है)। यदि भेजने () ने मूल पैकेट की लंबाई वापस नहीं की - एक त्रुटि, भेजें फ़ंक्शन से बाहर निकलें। गिराने का पैकेज।
क्या आप गिर रहे हैं? नहीं!
तो, एक पैकेट भेजने के साथ शुरू करने के लिए 4 अलग-अलग भेजने () के होते हैं। और उनमें से किसी पर एक त्रुटि, बाकी सभी को नहीं बुलाया जाएगा। यही है, यह पता चला है कि केवल $ भेजा जाएगा, और अधिक कुछ नहीं। या $ और चैनल नंबर जाएगा, लेकिन लंबाई नहीं है। या $ जाएगा, चैनल नंबर और लंबाई, लेकिन पैकेट खुद नहीं है। या ...
भेजने () गैर-अवरुद्ध मोड प्रतियों में निवर्तमान बफर के लिए / प्रेषित पैकेट भेजने की कोशिश करता है। उस बाइट की संख्या लौटाता है जो सेंड बफर में गई या गई। एक बार फिर: बाइट्स की संख्या जो भेजे गए बफर में गई या गई।
इस प्रकार, यह पता चला है कि आधा पैकेट भी भेजा जा सकता है। या आधी लंबाई ... नतीजतन, भेजी गई धारा टूट जाएगी, क्योंकि एक पैकेट पूरी तरह से नहीं जाता है। सरल ग्राहक जो केवल $ + चैनल + लंबाई + पैकेज_ को पढ़ते हैं आवश्यक_लॉग इन स्थानों में टूट जाएंगे - लंबाई सबसे विविध होगी, या पूरे पैकेज को पढ़ने के बाद आगे कोई $ नहीं होगा (क्योंकि हम वहां से अधिक पढ़ा गया था)।
एक बिंदु पर, एक बग देखा गया था और "निश्चित"। हम एक और हालिया कार्यान्वयन को देखते हैं : भेजना चार के बजाय दो चरणों में किया जाता है, पहले पैकेज उपसर्ग एकत्र किया जाता है, और फिर पैकेज स्वयं भेजा जाता है। इसके अलावा, भेजना एक विशेष फ़ंक्शन sendDataOverTCP द्वारा किया जाता है, जिसे पूरे पैकेज को भेजने की गारंटी देनी चाहिए, और क्या भेजने में कोई समस्या थी।
यह काम नहीं किया अपने आप को खोजें क्यों?
"गारंटीकृत" भेजने की एल्गोरिथ्म: एक गैर-अवरुद्ध सॉकेट पर भेजें ()। यदि यह एक त्रुटि देता है, तो हम सॉकेट को अवरुद्ध करने के लिए स्विच करते हैं, और इसे अवरुद्ध मोड में भेजते हैं। फिर हम सॉकेट को गैर-अवरुद्ध करने के लिए वापस करते हैं, और रिपोर्ट करते हैं कि कोई त्रुटि थी।
एक बार फिर: क्या आप सुनिश्चित हैं कि आपको एक गलती मिली है? क्या वह सब है? ;)
तो, मुख्य गलती: पहले भेजा () पहले कुछ भेजा! इस प्रकार, ब्लॉकिंग मोड में सेंड () करके हम पैकेट की शुरुआत को फिर से शुरू करते हैं!
हमारे पास दो शिपमेंट हैं। और पहला, यद्यपि यह बल से गुजरता हैSendToSucceed == गलत, कुछ भी पारित कर सकता है। Narpimer, 3 बाइट्स - $, पैकेट संख्या और लंबाई के कम बाइट। फिर एक त्रुटि, डेटा नहीं भेजा जाता है, फिर अगला पैकेट भेजा जाता है, और इसकी $ लंबाई की एक उच्च बाइट की तरह जाती है ...
क्या बग शाश्वत होगा? नहीं! दिसंबर 13 में, बग को "ठीक" किया गया था। यहाँ अंतिम संस्करण है ।
ऐसा लगता है कि उन्होंने सब कुछ के लिए प्रदान किया: यदि कुछ नहीं गया, तो वे एक त्रुटि लौटाते हैं, और पैकेज पूरी तरह से दूर नहीं जाता है। यदि कुछ चला गया, इससे पहले कि हम केवल शेष मोड में भेजते हैं, और यदि शेष पूरी तरह से चला गया है, तो हम सफलता लौटाते हैं। इस प्रकार, पैकेट डेटा का अगला चरण भेजने का प्रदर्शन किया जाएगा। और सब "अच्छा" है।
खैर अब, क्या गलत है? और यहाँ क्या है: पैकेज पूरे को छोड़ देता है, हमेशा अवरुद्ध मोड में। इस प्रकार, एक ग्राहक को भेजने में समस्या कैमरे से जुड़े सभी ग्राहकों पर ब्रेक का कारण बनती है।
और भी, SendPacket () अब कुछ भी नहीं छोड़ता है, अगर कम से कम एक बाइट आउटगोइंग पैकेट में मिला। और चूंकि किसी ने पैकेट के आकार को नहीं जोड़ा, इसलिए आउटगोइंग बफर का आकार और इसके भेजे गए पैकेटों की बहुलता बराबर नहीं है, यह पता चला है कि अगर समस्या भेज रहे हैं, तो बस पैकेट ड्रॉप की स्थिति नहीं होगी ...
ठीक है, कम से कम प्रवाह नहीं टूटेगा। उसके लिए भी धन्यवाद। मुख्य बात इस समय के दौरान ओओएम को पकड़ना नहीं है। बस इतना है कि वीडियो की शुरुआत होगी ...
दूसरे शब्दों में, मैं Live555 में अंतिम समाधान को गलत मानता हूं ...
सही समाधान (और काफी सरल!) मैं अगली बार पाठक के हित को गर्म करने के लिए वर्णन करूंगा :) [अपडेट: अगली बार ]
वितरण क्षेत्र
तो, बग व्यापक है। Live555 कोड में हमने जो सभी त्रुटियां देखीं, वे सामान्य से बाहर नहीं हैं - ये मानक त्रुटियां हैं जो नेटवर्क के साथ काम करने वाले सभी प्रोग्रामर द्वारा दोहराई जाती हैं।
चीनी कैमरों के समुद्र पर एक बग दिखाई देता है; और न केवल Live555 पर आधारित। बग को डी-लिंक कैमरों में देखा गया था। बग को विभिन्न प्रकार के ब्रांडेड कैमरों में देखा गया था (जो हमेशा की तरह, चीनी निर्माताओं के विभिन्न मॉड्यूल पर आधारित हैं)।
कैमरे के बढ़ते रिज़ॉल्यूशन और बिटरेट के साथ समस्याएं होने की संभावना बढ़ जाती है। यह इस कारण से है कि यह लंबे समय तक किसी का ध्यान नहीं गया: कैमरों की कीमत के लिए रिज़ॉल्यूशन का अनुपात कैपिटल रूप से हाल ही में बढ़ना शुरू हो गया है, फुलएचडी और मोटे कैमरे मांग में हैं। और चीनी की कीमतों के लिए धन्यवाद, यह उन पर है कि वे सबसे अधिक बार देखा जाना शुरू करते हैं। हमेशा की तरह, चीनी पाप करना शुरू कर देते हैं ... हालांकि गलतियों को गैर-चीनी प्रोग्रामर ने बिल्कुल गलत किया था।
निदान
यदि आपके पास कैमरे और निगरानी सॉफ्टवेयर है - तो इसे कुछ समय के लिए टीसीपी मोड में परीक्षण के लिए स्विच करें। यदि, एक स्थिर कनेक्शन के बावजूद, डिस्कनेक्ट किया जाता है, या यदि एक अस्थिर कनेक्शन पर, एक संपूर्ण वीडियो या साधारण वीडियो कलाकृतियों के बजाय, सॉफ्टवेयर क्रैश या कनेक्शन खो देता है, तो आपके पास एक छोटी गाड़ी ग्राहक और कैमरे हैं।
एक छड़ी के साथ केवल अपना कैमरा छड़ी करने के लिए - आप मेरी स्क्रिप्ट का उपयोग कर सकते हैं।
यह अंत उपयोगकर्ताओं के लिए अभिप्रेत नहीं है, क्योंकि यह घुटने पर पहना जाता है।
स्क्रिप्ट की शुरुआत में, निम्न पैरामीटर सेट होते हैं: होस्ट - आईपी कैमरा, url - स्ट्रीम URL में पूर्ण पथ सीधे इच्छित ट्रैक पर। एक गैर-मानक पोर्ट के साथ, आप पोर्ट को ओवरराइड कर सकते हैं।
पैरामीटर्स डंप आपको वीडियो को आरटीपी स्ट्रीम लिखने की अनुमति देता है, जिसे एक ही mplayer द्वारा देखा जा सकता है; डंप्राव आपको कच्ची धारा लिखने की अनुमति देता है।
बीट रेट बढ़ाने के लिए, आप 112 ("time.sleep (st)") के साथ लाइन को अनइंस्टॉल कर सकते हैं। और लाइन 176 पर, यदि आप स्ट्रीम रिकवरी मोड का चयन करने की अनुमति देते हैं। झूठी के साथ, स्ट्रीम को फिर से सिंक्रनाइज़ किया जाता है; ट्रू के साथ, एक पूर्ण पुन: संयोजन किया जाता है। यह आपको समय के अंतर का अनुमान लगाने की अनुमति देता है।
उपचार के तरीके
तो एक बग है। यह बहुत व्यापक है, लेकिन यह हाल के दिनों में उभरना शुरू हुआ - इस बग के साथ जंगली में लोहे की एक बड़ी मात्रा पहले से ही है। इस मामले में ठीक से इलाज कैसे करें?
मेरी व्यक्तिगत राय: उपचार द्विपक्षीय होना चाहिए। उसी समय, आपको कैमरा फर्मवेयर को संपादित करने की आवश्यकता है ताकि नया हार्डवेयर बग के बिना चला जाए, और मौजूदा कैमरों के फर्मवेयर को अपडेट करना संभव था।
लेकिन ग्राहकों को संभावित प्रवाह टूटने की स्थिति में रहने में सक्षम होना चाहिए। स्ट्रीम विफलता = अतिरिक्त => बस अगले पूरे पैकेट की शुरुआत की तलाश है। संक्षेप में, यह यूडीपी के लिए स्थिति को कम कर देता है, केवल पैकेट ड्रॉप की अखंडता आवेदन में जाती है।
क्लाइंट पक्ष पर बग को ठीक करने के लिए, आपको इनमें से प्रत्येक क्लाइंट के समर्थन को यातना देने की आवश्यकता है। मैक्रोस्कोप पहले से ही एक पिछले पोस्ट में सदस्यता समाप्त कर दिया है, और शायद यह एक पढ़ें। मैं अब पूरी तरह से AxxonNext पर चला गया हूं - उनके समर्थन को अधिसूचित किया गया है, हालांकि, मैं लंबे समय से इस बग के साथ उन्हें पीड़ा दे रहा हूं। जिन उपयोगकर्ताओं को इस समस्या का सामना करना पड़ रहा है - मैं आपसे टिकट बनाने और अपने सॉफ़्टवेयर के निर्माताओं से अपने हिस्से पर कार्रवाई करने के लिए कहता हूं। Erlyvideo ने हाल ही में मेरे फ़ीड से विफलता के बाद थ्रेड रिकवरी के लिए समर्थन जोड़ा।
आपको मेरी परीक्षण स्क्रिप्ट में लागू किए गए पुनरुत्थान कोड पर विचार नहीं करना चाहिए - यह लिखना जल्दी है; एक अधिक सही एक (पहले और अधिक सही पुनर्रचना) और तेजी से लागू करना संभव है, लेकिन यह एक शुरुआती बिंदु के साथ-साथ अवधारणा के रूप में भी सही है।
कैमरों की तरफ से बग को ठीक करने के लिए, मैंने उन सभी पर अत्याचार करने की कोशिश की जिन तक मैं पहुंच गया: मैंने चीनी विक्रेता को लिखा जो इन मॉड्यूल से एकत्र कर रहे हैं। मैंने अन्य विक्रेताओं को लिखा। मैंने कैमरा बनाने वाले को लिखने की कोशिश की। मैंने एम्बेडेड लिनक्स के निर्माता को लिखने की कोशिश की, जो कैमरे पर खड़ा है। मैंने एक हाब पर लिखा
दुर्भाग्य से, परिणाम शून्य है: मैं बहुत छोटा हूँ। सौभाग्य से, आंद्रेई सिमोकोकिन (डीपबब) , जो ipeye.ru पर काम करता है , ने मुझ पर दस्तक दी
आईपी ईवाईई वीडियो रिकॉर्डिंग और अपने स्वयं के कैमरों का एक क्लाउड-आधारित भंडारण प्रदान करता है, जो मेरे बाहरी कैमरों के बिल्कुल समान मॉड्यूल पर आधारित है - टॉपसी (टीएस 38) से मॉड्यूल पर। वे इन कैमरों के फ़र्मवेयर की इंटरफ़ेस और कार्यक्षमता को बहुत अधिक काम करते हैं। हालांकि, जैसा कि मैं इसे समझता हूं, मूल फर्मवेयर के लिए कोई स्रोत कोड नहीं हैं, वे मौजूदा कैमरों के माध्यम से आवश्यक मॉड्यूल एकत्र करते हैं, सॉफ्टवेयर की जगह लेते हैं, आदि। चूंकि वे क्लाउड प्रदान करते हैं, अधिकांश कैमरे सीधे इंटरनेट से जुड़ते हैं। ऐसे दूरस्थ कैमरों का उपयोग करते हुए, यूडीपी का उपयोग पहले से ही अप्रिय हो रहा है - रेट्रांसमिट की संभावना बहुत अधिक है, हालांकि चैनल मोटाई आंखों के लिए पर्याप्त है। Erlyvideo (flussonic के अर्थ में) सर्वर रिसीवर के रूप में उपयोग किया जाता है। फ़्लोसोनिक के पुराने संस्करण का उपयोग करना (पुन: सिंक्रनाइज़ेशन के बिना) विभिन्न कैमरों के रोल-ऑफ की मात्रा बस विशाल है। अपडेट किए गए संस्करण का उपयोग करना (resynchronization के साथ) पुन: संयोजन की संख्या को काफी कम कर देता है (हालांकि नुकसान की मात्रा अभी भी अप्रिय है)।
इसलिए, विचलित। एंड्री ने सपने देखने वाले का परीक्षण करने का सुझाव दिया कि मैंने उनके स्टैंड पर सुधार किया ... इस प्रकार, मुझे सिग्रैंड से स्रोतों को इकट्ठा करने की कोशिश करने की तुलना में परीक्षण कैमरों तक पहुंच आसान हो गई ।
इलाज
दुर्भाग्य से, वर्तमान लेख पहले से ही बहुत बड़ा है, इसलिए मैंने जिस उपचार पद्धति को लागू किया है, उसे दूसरे दिन एक अलग लेख में वर्णित किया जाएगा।
संक्षेप में: फर्मवेयर को अनपैक करें, वहां से स्ट्रीमर प्राप्त करें, एक खराब जगह की तलाश करें, बिनार में पैच करें, फर्मवेयर को फिर से बनाएं।
बोनस कीड़े
इस बग से निपटने के दौरान, मैक्स लापशिन (@erlyvideo) एक और दिलचस्प बग में भाग गया। एक संपूर्ण के रूप में कैमरा सुंदर दिखता है, उन्होंने बफरिंग की सही विधि लागू की - यदि पैकेट तुरंत पूरी नहीं छोड़ता है, तो यह बफर में रहता है और बाद में समय के अनुसार भेजे जाने की कोशिश करता है; सभी पैकेट जिन्हें अब तक चुपचाप नहीं छोड़ा गया था (और $ / चैनल / आकार और पैकेट संख्या सहित) को पूरी तरह से छोड़ देते हैं, इसलिए यह UDP के समान एक सुंदर पैकेट ड्रॉप लगता है।
इस तरह की बफरिंग पद्धति का सिर्फ एक साइड इफेक्ट है: जैसे ही सर्वर रिक्वेस्ट प्राप्त करता है, टीसीपी स्ट्रीम (GET_PARAMETER या विकल्प) से गुजरने वाले रिक्वेस्ट-रिक्वेस्ट का रिस्पॉन्स आता है। सही दूर है। कैसे एक अनुरोध प्राप्त करने के लिए। यही है, जवाब एक डेटा पैकेट के बीच में भी आ सकता है! इस प्रकार, यदि हम स्ट्रीम को "जैसा है" - $ + पैकेट + लंबाई ... को डिकोड करने का प्रयास करते हैं ... और $ के बजाय RTSP की प्रतीक्षा करते हैं - तो हर बार हम एक कोपलिव (हर 30 सेकंड) भेजते हैं, क्योंकि उनके बिना कैमरा 45 सेकंड के बाद स्ट्रीम को तोड़ देता है, धारा टूटती है - ~ 100 बाइट्स कचरा प्रतिक्रिया में आता है, और एक जाम वीडियो पर बाहर निकलता है, जो निम्न कुंजी फ़ाइल द्वारा तय किया गया है।
क्लाइंट द्वारा इस बग का उपचार पहले से ही अधिक जटिल है: आपको पहले RTSP ... \ r \ n \ r \ n की तलाश और विश्लेषण (हटाने) की आवश्यकता है, और फिर शेष $ + पैकेट + लंबाई + वीडियो देखें। फ्लॉसोनिक नवीनतम संस्करण पहले से ही जानता है कि यह कैसे करना है।
गोलियाँ
सुधार विवरण (क्या और कैसे करना है) बाद में होगा, लेकिन अभी के लिए, यदि आपका कैमरा TS38 के आधार पर बनाया गया है, तो आप फर्मवेयर को मेरे परिवर्तनों के साथ ले और स्थापित कर सकते हैं, जहां टीसीपी के साथ समस्या पूरी तरह से ठीक हो गई है।
इसलिए, मैंने नवीनतम संस्करण 2.5.0.6 के निम्नलिखित फर्मवेयर को एकत्र किया:
- firmware_TS38ABFG006-ONVIF-पी 2 पी-V2.5.0.6_20140126120110- TCPFIX.bin
- firmware_TS38CD-ONVIF-पी 2 पी-V2.5.0.6_20140126121011- TCPFIX.bin
- firmware_TS38HI-ONVIF-पी 2 पी-V2.5.0.6_20140126121444- TCPFIX.bin
- firmware_TS38LM-ONVIF-पी 2 पी-V2.5.0.6_20140126121913- TCPFIX.bin
- firmware_HI3518C-V4-ONVIF-V2.5.0.6_20140126124339- TCPFIX.bin
यदि आपको अचानक उसी निर्माता के किसी अन्य मॉड्यूल पर फिक्स की आवश्यकता है - टिप्पणियों में लिखें, मैं देखूंगा कि क्या संभव है।