[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