2010-02-10 6 views
5

मैं कस्टम डायरेक्टशो स्रोत पुश फ़िल्टर लिख रहा हूं जिसे वीडियो सर्वर से आरटीपी डेटा प्राप्त करना है और उन्हें रेंडरर पर धक्का देना है। मैंने एक सीवीडियोपशपिन क्लास लिखा है जो CSourceStream और CVideoReceiverThread क्लास से विरासत में मिलता है जो एक थ्रेड के लिए एक रैपर है जो वीडियो सर्वर से आरटीपी पैकेट प्राप्त करता है। 256 तत्व कतार मेंकस्टम डायरेक्टशो आरटीएसपी/आरटीपी स्रोत पुश फ़िल्टर लिखना - लाइव स्रोतों से आने वाले टाइमस्टैम्पिंग डेटा

  • कच्चे आरटीपी पैकेट प्राप्त करता है उनके बारे में बफर और जानकारी संग्रहित करने के लिए प्रतियां उन्हें और कुछ डेटा है कि रिसीवर के लिए आवश्यक है रिपोर्ट
  • फ्रेम असेंबल एकत्र करता है,: रिसीवर धागा अनिवार्य रूप से तीन काम करता है है, जो परिभाषित किया गया है इस प्रकार है:

    struct queue_elem { 
        char *start; // Pointer to a frame in a buffer 
        int length; // Lenght of data 
        REFERENCE_TIME recvTime; // Timestamp when the frame was received (stream time) 
    }; 
    
    struct data { 
        struct queue_elem queue[QUEUE_LENGTH]; 
        int qWrIdx; 
        int qRdIdx; 
    HANDLE mutex; 
    }; 
    
  • हर प्राप्त फ्रेम वर्तमान धारा समय के साथ टाइमस्टैंप है

    p->StreamTime(refTime); 
    REFERENCE_TIME rt = refTime.GetUnits(); 
    

समस्या यह है कि मुझे यकीन नहीं है कि मुझे फिलबफर विधि में प्रत्येक मीडिया नमूने के लिए टाइमस्टैम्प कैसे सेट करना है। मैंने कई तरीकों की कोशिश की, लेकिन प्लेबैक या तो बंद हो जाता है या यह बहुत धीमा है।

REFERENCE_TIME thisFrameStartTime, thisFrameEndTime; 
// Make sure if there are at least 4 frames in the buffer 
    if(noOfFrames >= 4) 
    { 
     currentQe = m_myData.queue[m_myData.qRdIdx++]; //Take current frame description  
     if(m_myData.qRdIdx >= QUEUE_LENGTH) 
     { 
      m_myData.qRdIdx = 0; 
     }   
     nextQe = m_myData.queue[m_myData.qRdIdx]; //Take next frame description 
     if(currentQe.length > 0) 
     { 
      memcpy(pData, currentQe.start, currentQe.length);    

      pSample->SetActualDataLength(currentQe.length);     
      CRefTime refTime; 
      m_pFilter->StreamTime(refTime); 
      REFERENCE_TIME rt; 
      rt = refTime.GetUnits(); 
      pSample->GetTime(&thisFrameStartTime, &thisFrameEndTime); 
      thisFrameEndTime = thisFrameStartTime + (nextQe.recvTime - currentQe.recvTime); 
      pSample->SetTime(&thisFrameStartTime, &thisFrameEndTime); 
     } 
    } 
    else 
    { 
     pSample->SetActualDataLength(0); 
    } 

इस मामले में मैंने देखा है बहुत जल्दी कतार बढ़ जाती है में आइटमों की संख्या (किसी कारण FillBuffer विधि काफी तेजी से डेटा बाहर खींच नहीं कर सकता के लिए), और परिणाम है कि: वर्तमान में FillBuffer विधि इस तरह दिखता है वीडियो चलाते समय देरी बढ़ रही है। क्या किसी के पास कोई विचार है कि लाइव स्रोतों से डेटा प्राप्त करते समय मुझे टाइमस्टैम्पिंग कैसे करना चाहिए?

उत्तर

6

ग्राफ़ का स्ट्रीम समय नमूना ऑब्जेक्ट पर टाइमस्टैम्प तक पहुंचने पर रेंडरर फ्रेम को आकर्षित करेगा। अगर मैं आपके कोड को सही तरीके से पढ़ता हूं, तो आप आगमन पर स्ट्रीम समय के साथ टाइमस्टैम्पिंग कर रहे हैं, इसलिए वे हमेशा प्रतिपादन में देर हो जाएंगे। यह ऑडियो रेंडरर द्वारा कुछ हद तक उलझन में है: यदि ऑडियो रेंडरर ग्राफ की घड़ी प्रदान कर रहा है, तो यह वर्तमान धारा समय की रिपोर्ट करेगा जो कि वर्तमान में जो भी नमूना खेल रहा है, और यह कुछ अवांछित समय व्यवहार का कारण बन जाएगा।

  1. आप ग्राफ में विलंबता और आपके फ़िल्टर में किसी भी बफरिंग की अनुमति देने के लिए भविष्य में एक समय निर्धारित करना चाहते हैं। भविष्य में शायद 300 एमएमएस समय निर्धारित करने का प्रयास करें (स्ट्रीम समय अब ​​+ 300 एमएमएस)।

  2. आप फ्रेम के बीच संगत होना चाहते हैं, इसलिए प्रत्येक फ्रेम के आगमन समय के आधार पर उन्हें टाइमस्टैम्प न करें। प्रत्येक फ्रेम के लिए आरटीपी टाइमस्टैम्प का उपयोग करें, और भविष्य में 300ms होने के लिए पहली बार बेसलाइन सेट करें; बाद के फ्रेम तब होते हैं (rtp - rtp_at_baseline) + dshow बेसलाइन (उचित इकाई रूपांतरणों के साथ।

  3. आपको उसी आधार रेखा का उपयोग करके ऑडियो और वीडियो स्ट्रीम को उसी समय टाइमस्टैम्प करने की आवश्यकता है। हालांकि, अगर मुझे याद है, आरटीपी टाइमस्टैम्प में प्रत्येक स्ट्रीम में एक अलग बेसलाइन होती है, इसलिए आपको आरटीपी टाइमस्टैम्प को (पूर्ण) एनटीपी समय में परिवर्तित करने के लिए आरटीसीपी पैकेट्स का उपयोग करने की आवश्यकता होती है, और उसके बाद एनटीपी को अपनी प्रारंभिक बेसलाइन (बेसलाइन एनटीपी = डीएसओ स्ट्रीम टाइम टाइम + 300 एमएमएस) का उपयोग करके डायरेक्टशो में परिवर्तित करने की आवश्यकता होती है।

जी

+0

गेरेंट, आपके इनपुट के लिए धन्यवाद। मैं कुछ ग बनाया मेरे कोड में लटका हुआ है, हालांकि, वीडियो चलाने के बाद ही वीडियो फ्रीज हो जाता है। लॉग फ़ाइल में मैंने देखा कि फिलबफर विधि को केवल दो बार बुलाया जाता है।जब इसे पहली बार बुलाया जाता है, स्ट्रीम समय 3633950000 है, फ्रेमस्टार्टटाइम 3635700000 है और फ्रेमइंडटाइम 3635703600 है। दूसरी बार, स्ट्रीम टाइम 3634370000 है, फ्रेमस्टार्टटाइम 3635703600 है और फ्रेमइंडटाइम 3635707200 है। इसलिए यदि मैं सही ढंग से समझता हूं, तो प्रस्तुतकर्ता को प्रतीक्षा करनी चाहिए पहली फ्रेम पर टाइमस्टैम्प तक पहुंचने के लिए स्ट्रीम समय और फिर सुचारू रूप से चलाएं, लेकिन दुर्भाग्य से ऐसा नहीं होता है। – mkurek

संबंधित मुद्दे