[xiph-commits] r15504 - in trunk/oggdsf/src/lib: codecs/speex/filters/dsfSpeexEncoder codecs/theora/filters/dsfTheoraEncoder codecs/vorbis/filters/dsfVorbisEncoder core/directshow/libDirectshowAbstracts

cristianadam at svn.xiph.org cristianadam at svn.xiph.org
Mon Nov 3 13:44:22 PST 2008


Author: cristianadam
Date: 2008-11-03 13:44:22 -0800 (Mon, 03 Nov 2008)
New Revision: 15504

Modified:
   trunk/oggdsf/src/lib/codecs/speex/filters/dsfSpeexEncoder/SpeexEncodeInputPin.cpp
   trunk/oggdsf/src/lib/codecs/theora/filters/dsfTheoraEncoder/TheoraEncodeInputPin.cpp
   trunk/oggdsf/src/lib/codecs/theora/filters/dsfTheoraEncoder/TheoraEncodeInputPin.h
   trunk/oggdsf/src/lib/codecs/vorbis/filters/dsfVorbisEncoder/VorbisEncodeInputPin.cpp
   trunk/oggdsf/src/lib/core/directshow/libDirectshowAbstracts/AbstractTransformInputPin.cpp
   trunk/oggdsf/src/lib/core/directshow/libDirectshowAbstracts/AbstractTransformInputPin.h
Log:
Ticket #1262. Committed [PATCH] directshow filters: generate correct number of frames, for Theora, Speex and Vorbis encoders

Modified: trunk/oggdsf/src/lib/codecs/speex/filters/dsfSpeexEncoder/SpeexEncodeInputPin.cpp
===================================================================
--- trunk/oggdsf/src/lib/codecs/speex/filters/dsfSpeexEncoder/SpeexEncodeInputPin.cpp	2008-11-03 21:03:35 UTC (rev 15503)
+++ trunk/oggdsf/src/lib/codecs/speex/filters/dsfSpeexEncoder/SpeexEncodeInputPin.cpp	2008-11-03 21:44:22 UTC (rev 15504)
@@ -32,6 +32,10 @@
 #include "stdafx.h"
 #include "SpeexEncodeInputPin.h"
 
+
+#define ADAPT_FRAME_RATE 1
+
+
 SpeexEncodeInputPin::SpeexEncodeInputPin(       AbstractTransformFilter* inParentFilter
                                             ,   CCritSec* inFilterLock
                                             ,   AbstractTransformOutputPin* inOutputPin
@@ -80,10 +84,33 @@
     unsigned long locNumSamplesPerChannel = bufferBytesToSampleCount(inNumBytes);
     locPackets = mSpeexEncoder.encode((const short* const)inBuf, locNumSamplesPerChannel);
 
+#ifdef ADAPT_FRAME_RATE
+	/* skip packet if we are too late ? */
+	__int64 curTime = (m_dsTimeStart * mEncoderSettings.sampleRate())/1000;
+	if (mUptoFrame-curTime > locNumSamplesPerChannel) 
+	{
+		return S_OK;
+	}
+#endif
+
     locHR = sendPackets(locPackets);
     deletePacketsAndEmptyVector(locPackets);
-    return locHR;
 
+#ifdef ADAPT_FRAME_RATE
+	/* Resend same packet if we are too early */
+	if (!FAILED(locHR)) 
+	{
+		while (curTime-mUptoFrame > locNumSamplesPerChannel) 
+		{
+		    locPackets = mSpeexEncoder.encode((const short* const)inBuf, locNumSamplesPerChannel);
+			locHR = sendPackets(locPackets);
+			deletePacketsAndEmptyVector(locPackets);
+		}
+	}
+#endif
+
+	return locHR;
+
 }
 bool SpeexEncodeInputPin::ConstructCodec() 
 {

Modified: trunk/oggdsf/src/lib/codecs/theora/filters/dsfTheoraEncoder/TheoraEncodeInputPin.cpp
===================================================================
--- trunk/oggdsf/src/lib/codecs/theora/filters/dsfTheoraEncoder/TheoraEncodeInputPin.cpp	2008-11-03 21:03:35 UTC (rev 15503)
+++ trunk/oggdsf/src/lib/codecs/theora/filters/dsfTheoraEncoder/TheoraEncodeInputPin.cpp	2008-11-03 21:44:22 UTC (rev 15504)
@@ -32,6 +32,10 @@
 #include "stdafx.h"
 #include "theoraencodeinputpin.h"
 
+/* Define to adapt theora frame rate to DirectShow clock */
+#define ADAPT_FRAME_RATE 1
+
+
 TheoraEncodeInputPin::TheoraEncodeInputPin(AbstractTransformFilter* inParentFilter, CCritSec* inFilterLock, AbstractTransformOutputPin* inOutputPin, vector<CMediaType*> inAcceptableMediaTypes)
 	:	AbstractTransformInputPin(inParentFilter, inFilterLock, inOutputPin, NAME("TheoraEncodeInputPin"), L"Theora In", inAcceptableMediaTypes)
 	,	m_xOffset(0)
@@ -40,6 +44,8 @@
 	,	m_width(0)
 	,	m_uptoFrame(0)
 	,	m_hasBegun(false)
+	,	m_numFrames(0)
+
 {
 	//debugLog.open("g:\\logs\\theoencfiltinput.log", ios_base::out);
 	m_yuv.y = NULL;
@@ -1233,7 +1239,19 @@
 		throw 0;
 	}
 	
+#ifdef ADAPT_FRAME_RATE
+	__int64 frameTime = (1000 * m_theoraInfo.fps_denominator) / m_theoraInfo.fps_numerator;
+	__int64 curTheoraTime = (m_numFrames * 1000 * m_theoraInfo.fps_denominator) / m_theoraInfo.fps_numerator;
 
+	// Skip a frame if we are too late
+	if (curTheoraTime - m_dsTimeStart > frameTime) 
+	{
+		//debugLog<<" too late: "<< curTheoraTime << "," << timeStart << ":" << frameTime <<endl;
+		return S_OK;
+	}
+#endif
+
+
 	StampedOggPacket* locPacket = m_theoraEncoder.encodeTheora(&m_yuv);
 	if (locPacket == NULL) {
 		//debugLog<<"Encode returns NULL"<<endl;
@@ -1246,9 +1264,56 @@
 	//We still own the packet after this, we have to delete it.
 	locHR = deliverData(locFrameStart, locFrameEnd, locPacket->packetData(), locPacket->packetSize());
 	delete locPacket;
+
+
+#ifdef ADAPT_FRAME_RATE
+	if (!FAILED(locHR)) 
+	{
+		++m_numFrames;
+		locHR = encodeMoreFrames();
+	}
+#endif
+
 	return locHR;
 }
 
+HRESULT TheoraEncodeInputPin::encodeMoreFrames()
+{
+	HRESULT locHR = S_OK;
+
+	__int64 frameTime = (1000 * m_theoraInfo.fps_denominator) / m_theoraInfo.fps_numerator;
+	__int64 curTheoraTime = (m_numFrames * 1000 * m_theoraInfo.fps_denominator) / m_theoraInfo.fps_numerator;
+
+	/* Resend previous packet, if we are too fast */
+	while (m_dsTimeStart - curTheoraTime > frameTime) 
+	{
+		LONGLONG locFrameStart = m_uptoFrame;
+		LONGLONG locFrameEnd = 0;
+
+		StampedOggPacket* locPacket = m_theoraEncoder.encodeTheora(&m_yuv);
+		if (locPacket == NULL) 
+		{
+			//debugLog<<"Encode returns NULL"<<endl;
+			return S_FALSE;
+		}
+		locFrameEnd	= m_uptoFrame = locPacket->endTime();
+		//debugLog<<"Delivering..."<<endl;
+
+		//We still own the packet after this, we have to delete it.
+		locHR = deliverData(locFrameStart, locFrameEnd, locPacket->packetData(), locPacket->packetSize());
+		delete locPacket;
+		if (FAILED(locHR)) 
+		{
+			break;
+		}
+
+		++m_numFrames;
+		curTheoraTime = (m_numFrames * 1000 * m_theoraInfo.fps_denominator) / m_theoraInfo.fps_numerator;
+	}
+
+	return locHR;
+}
+
 bool TheoraEncodeInputPin::ConstructCodec() 
 {
 	//debugLog<<"Contructing codec..."<<endl;

Modified: trunk/oggdsf/src/lib/codecs/theora/filters/dsfTheoraEncoder/TheoraEncodeInputPin.h
===================================================================
--- trunk/oggdsf/src/lib/codecs/theora/filters/dsfTheoraEncoder/TheoraEncodeInputPin.h	2008-11-03 21:03:35 UTC (rev 15503)
+++ trunk/oggdsf/src/lib/codecs/theora/filters/dsfTheoraEncoder/TheoraEncodeInputPin.h	2008-11-03 21:44:22 UTC (rev 15504)
@@ -75,6 +75,8 @@
 	long encodeYVYUToYV12(unsigned char* inBuf, long inNumBytes);
 	long encodeIYUVToYV12(unsigned char* inBuf, long inNumBytes);
 
+	HRESULT encodeMoreFrames();
+
 protected:
 	HRESULT m_hr;
 
@@ -95,6 +97,9 @@
 
 	bool m_hasBegun;
 
+	/* To adapt theora frame rate to variable directshow clock */
+	unsigned __int64 m_numFrames;
+
 	//DEBUG ONLY
 	//fstream debugLog;
 };

Modified: trunk/oggdsf/src/lib/codecs/vorbis/filters/dsfVorbisEncoder/VorbisEncodeInputPin.cpp
===================================================================
--- trunk/oggdsf/src/lib/codecs/vorbis/filters/dsfVorbisEncoder/VorbisEncodeInputPin.cpp	2008-11-03 21:03:35 UTC (rev 15503)
+++ trunk/oggdsf/src/lib/codecs/vorbis/filters/dsfVorbisEncoder/VorbisEncodeInputPin.cpp	2008-11-03 21:44:22 UTC (rev 15504)
@@ -32,6 +32,9 @@
 #include "stdafx.h"
 #include "VorbisEncodeInputPin.h"
 
+#define ADAPT_FRAME_RATE 1
+
+
 VorbisEncodeInputPin::VorbisEncodeInputPin(     AbstractTransformFilter* inParentFilter
                                             ,   CCritSec* inFilterLock
                                             ,   AbstractTransformOutputPin* inOutputPin
@@ -80,10 +83,32 @@
     unsigned long locNumSamplesPerChannel = bufferBytesToSampleCount(inNumBytes);
     locPackets = mVorbisEncoder.encodeVorbis((const short* const)inBuf, locNumSamplesPerChannel);
 
+#ifdef ADAPT_FRAME_RATE
+	/* skip packet if we are too late ? */
+	__int64 curTime = (m_dsTimeStart * mEncoderSettings.mSampleRate) / 1000;
+	if (mUptoFrame-curTime > locNumSamplesPerChannel) 
+	{
+		return S_OK;
+	}
+#endif
+
     locHR = sendPackets(locPackets);
     deletePacketsAndEmptyVector(locPackets);
-    return locHR;
+    
+#ifdef ADAPT_FRAME_RATE
+	/* Resend same packet if we are too early */
+	if (!FAILED(locHR)) 
+	{
+		while (curTime - mUptoFrame > locNumSamplesPerChannel) 
+		{
+		    locPackets = mVorbisEncoder.encodeVorbis((const short* const)inBuf, locNumSamplesPerChannel);
+			locHR = sendPackets(locPackets);
+			deletePacketsAndEmptyVector(locPackets);
+		}
+	}
+#endif
 
+	return locHR;
 }
 
 bool VorbisEncodeInputPin::ConstructCodec() 

Modified: trunk/oggdsf/src/lib/core/directshow/libDirectshowAbstracts/AbstractTransformInputPin.cpp
===================================================================
--- trunk/oggdsf/src/lib/core/directshow/libDirectshowAbstracts/AbstractTransformInputPin.cpp	2008-11-03 21:03:35 UTC (rev 15503)
+++ trunk/oggdsf/src/lib/core/directshow/libDirectshowAbstracts/AbstractTransformInputPin.cpp	2008-11-03 21:44:22 UTC (rev 15504)
@@ -40,8 +40,9 @@
 	,	mParentFilter (inParentFilter)
 	
 	,	mAcceptableMediaTypes(inAcceptableMediaTypes)
+	,	m_dsTimeStart(0)
+	,	m_dsTimeEnd(0)
 
-
 {
 	mStreamLock = new CCritSec;			//Deleted in destructor.
 }
@@ -110,7 +111,17 @@
 		if (locHR != S_OK) {
 			//TODO::: Do a debug dump or something here with specific error info.
 			return locHR;
-		} else {
+		} 
+		else 
+		{
+			/* Read DirectShow timestamps */
+			REFERENCE_TIME pTimeStart, pTimeEnd;
+			if (inSample->GetTime(&pTimeStart, &pTimeEnd) == NOERROR) 
+			{
+				m_dsTimeStart = pTimeStart/10000;
+				m_dsTimeEnd = pTimeEnd/10000;
+			}
+
             //http://windowssdk.msdn.microsoft.com/en-us/library/ms787541.aspx
             //Consider using receive to validate conditions ^^^
 			HRESULT locResult = TransformData(locBuff, inSample->GetActualDataLength());

Modified: trunk/oggdsf/src/lib/core/directshow/libDirectshowAbstracts/AbstractTransformInputPin.h
===================================================================
--- trunk/oggdsf/src/lib/core/directshow/libDirectshowAbstracts/AbstractTransformInputPin.h	2008-11-03 21:03:35 UTC (rev 15503)
+++ trunk/oggdsf/src/lib/core/directshow/libDirectshowAbstracts/AbstractTransformInputPin.h	2008-11-03 21:44:22 UTC (rev 15504)
@@ -102,6 +102,10 @@
 	AbstractTransformFilter* mParentFilter;
 	vector<CMediaType*> mAcceptableMediaTypes;
 
+	//DirectShow timestamps in milliseconds
+	__int64 m_dsTimeStart;
+	__int64 m_dsTimeEnd;
+
 	//fstream debugLog;
 	CCritSec* mStreamLock;
 };



More information about the commits mailing list