2010-02-10 30 views
5

gelen timestamping verileri Ben Video sunucusundan RTP veri almak veya işleyici onları itmek gerekiyordu özel DirectShow kaynak itme filtresi yazıyorum. Video sunucusundan RTP paketleri alan bir iş parçacığı için bir sarıcı olan CSourceStream ve CVideoReceiverThread sınıfından miras alan bir CVideoPushPin sınıfı yazdım. 256 eleman kuyruğuna, onlar hakkında tampon ve mağazalar bilgilere kopya onlarıYazma özel DirectShow RTSP/RTP Kaynak itme filtresi - canlı kaynaklardan

  • çiğ RTP paketlerini alır ve Alıcı için gerekli olan bazı veriler
  • kareleri bir araya Raporları toplar: alıcı iplik esasen üç şey yapar tanımlanmış olan aşağıdaki gibidir:

    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; 
    }; 
    
  • her bir alınan çerçeve mevcut akış süresi ile timestamped edilir

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

Sorunlar, FillBuffer yöntemindeki her MediaSample için zaman damgalarını nasıl ayarlayacağımı bilmiyorum. Birkaç yol denedim, ancak oynatma ya duruyor ya da çok yavaş.

fark ettim Bu durumda
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 yöntemi yeterince hızlı veri çekip olamaz nedense) çok hızlı kuyruk artar öğe sayısı ve sonuç şudur: Şu FillBuffer yöntemi şöyle video oynatırken gecikme artar. Canlı kaynaklardan veri alırken zaman damgasını nasıl yapmalıyım? Grafiğin akış süresi örnek nesnesinde damgası ulaştığında

cevap

6

oluşturucu çerçeve çekecektir. Kodunuzu doğru olarak okursam, bunları varışta akış saatiyle zamanlamaya ayırıyorsunuz, böylece her zaman işleme koymaya geç olacaklar. Bu, ses oluşturucu tarafından biraz kafa karıştırılır: Eğer ses oluşturucu grafiğin saatini sağlıyorsa, o anda çalmakta olduğu herhangi bir örnek için geçerli akış zamanını rapor edecektir ve bu, istenmeyen bir zaman davranışına neden olacaktır.

  1. Grafiğin yoluyla gecikme ve filtrede herhangi tamponlama için izin vermek, gelecekte bir zamanı ayarlamak istiyorum. Gelecekte belki de 300ms'lik bir zaman ayarlamayı deneyin (şimdi akış süresi + 300ms).

  2. Sen kareler arasında tutarlı olmasını istiyorum, böylece her çerçevenin geliş zamanına göre bunları damgası yoktur. Her bir çerçeve için RTP zaman damgasını kullanın ve ilkinin temel çizgisini, 300ms olacak şekilde geleceğe ayarlayın; sonraki kareler (rtp - rtp_at_baseline) + dshow taban çizgisi (uygun birim dönüşümleri ile)

  3. Ses ve video akışlarını aynı temel çizgiyi kullanarak aynı şekilde eklemeniz gerekir. zaman damgaları her bir akışta farklı bir taban çizgisine sahiptir, bu yüzden RTP zaman damgasını (mutlak) NTP zamanına dönüştürmek için RTCP paketlerini kullanmanız ve ardından NTP'yi başlangıç ​​taban çizginizi kullanarak doğrudan gösterime dönüştürmeniz gerekir (temel NTP = dshow akış süresi şimdi + 300ms).

G

+0

Geraint, teşekkürler girişi için. biraz c yapılmış kodumda duruyor, ancak video çalıştırdıktan hemen sonra donuyor. Günlük dosyasında, FillBuffer yönteminin yalnızca iki kez çağrıldığını fark ettim.İlk kez çağrıldığında, akış süresi 3633950000, frameStartTime 3635700000 ve frameEndTime ise 3635703600'dür. İkinci kez akış zamanı 3634370000, frameStartTime 3635703600 ve frameEndTime ise 3635707200'dür. İlk karedeki zaman damgasına ulaşmak için akış zamanı ve daha sonra sorunsuz çalışır, ancak ne yazık ki olmaz. – mkurek