Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/LAVFilters.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHendrik Leppkes <h.leppkes@gmail.com>2017-04-22 12:35:39 +0300
committerHendrik Leppkes <h.leppkes@gmail.com>2017-04-22 12:51:24 +0300
commitbe1155eab07f237abdab5b693ee6a13e5cc4e688 (patch)
tree9a349adde0e2999ccf0ce054ebb108fdf5a6dc42 /demuxer
parent00b3a0b2a87130a8e6c27c69bfc1ef58f3932b5a (diff)
Allow the PacketAllocator to allocate new packets on the fly
This allows downstream filters to hang on to them for longer without deadlocking the allocator.
Diffstat (limited to 'demuxer')
-rw-r--r--demuxer/LAVSplitter/LAVSplitter.vcxproj1
-rw-r--r--demuxer/LAVSplitter/LAVSplitter.vcxproj.filters3
-rw-r--r--demuxer/LAVSplitter/OutputPin.cpp2
-rw-r--r--demuxer/LAVSplitter/PacketAllocator.cpp116
-rw-r--r--demuxer/LAVSplitter/PacketAllocator.h13
-rw-r--r--demuxer/LAVSplitter/dllmain.cpp1
6 files changed, 99 insertions, 37 deletions
diff --git a/demuxer/LAVSplitter/LAVSplitter.vcxproj b/demuxer/LAVSplitter/LAVSplitter.vcxproj
index 30768bd9..b64034b8 100644
--- a/demuxer/LAVSplitter/LAVSplitter.vcxproj
+++ b/demuxer/LAVSplitter/LAVSplitter.vcxproj
@@ -114,6 +114,7 @@
<ClInclude Include="..\..\common\includes\IDSMResourceBag.h" />
<ClInclude Include="..\..\common\includes\IGraphRebuildDelegate.h" />
<ClInclude Include="..\..\common\includes\IKeyFrameInfo.h" />
+ <ClInclude Include="..\..\common\includes\ILAVDynamicAllocator.h" />
<ClInclude Include="..\..\common\includes\ILAVPinInfo.h" />
<ClInclude Include="..\..\common\includes\ISpecifyPropertyPages2.h" />
<ClInclude Include="..\..\common\includes\IStreamSourceControl.h" />
diff --git a/demuxer/LAVSplitter/LAVSplitter.vcxproj.filters b/demuxer/LAVSplitter/LAVSplitter.vcxproj.filters
index 3689aaa4..8121654b 100644
--- a/demuxer/LAVSplitter/LAVSplitter.vcxproj.filters
+++ b/demuxer/LAVSplitter/LAVSplitter.vcxproj.filters
@@ -119,6 +119,9 @@
<ClInclude Include="..\..\common\includes\IDSMResourceBag.h">
<Filter>Header Files\common</Filter>
</ClInclude>
+ <ClInclude Include="..\..\common\includes\ILAVDynamicAllocator.h">
+ <Filter>Header Files\common</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="LAVSplitter.rc">
diff --git a/demuxer/LAVSplitter/OutputPin.cpp b/demuxer/LAVSplitter/OutputPin.cpp
index e6b36a5c..66f0aa25 100644
--- a/demuxer/LAVSplitter/OutputPin.cpp
+++ b/demuxer/LAVSplitter/OutputPin.cpp
@@ -164,7 +164,7 @@ HRESULT CLAVOutputPin::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERT
HRESULT hr = S_OK;
- pProperties->cBuffers = max(pProperties->cBuffers, (m_bPacketAllocator ? 10 : m_nBuffers));
+ pProperties->cBuffers = max(pProperties->cBuffers, (m_bPacketAllocator ? 20 : m_nBuffers));
pProperties->cbBuffer = max(max(m_mt.lSampleSize, 256000), (ULONG)pProperties->cbBuffer);
// Vorbis requires at least 2 buffers
diff --git a/demuxer/LAVSplitter/PacketAllocator.cpp b/demuxer/LAVSplitter/PacketAllocator.cpp
index 30456e5c..4ae27f7b 100644
--- a/demuxer/LAVSplitter/PacketAllocator.cpp
+++ b/demuxer/LAVSplitter/PacketAllocator.cpp
@@ -127,6 +127,16 @@ CPacketAllocator::~CPacketAllocator(void)
ReallyFree();
}
+STDMETHODIMP CPacketAllocator::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
+{
+ if (riid == IID_ILAVDynamicAllocator) {
+ return GetInterface((ILAVDynamicAllocator *) this, ppv);
+ }
+ else {
+ return __super::NonDelegatingQueryInterface(riid, ppv);
+ }
+}
+
STDMETHODIMP CPacketAllocator::SetProperties(ALLOCATOR_PROPERTIES* pRequest, ALLOCATOR_PROPERTIES* pActual)
{
CheckPointer(pActual,E_POINTER);
@@ -215,47 +225,13 @@ HRESULT CPacketAllocator::Alloc(void)
return E_OUTOFMEMORY;
}
- /* Compute the aligned size */
- LONG lAlignedSize = m_lSize + m_lPrefix;
-
- /* Check overflow */
- if (lAlignedSize < m_lSize) {
- return E_OUTOFMEMORY;
- }
-
- if (m_lAlignment > 1) {
- LONG lRemainder = lAlignedSize % m_lAlignment;
- if (lRemainder != 0) {
- LONG lNewSize = lAlignedSize + m_lAlignment - lRemainder;
- if (lNewSize < lAlignedSize) {
- return E_OUTOFMEMORY;
- }
- lAlignedSize = lNewSize;
- }
- }
-
- /* Create the contiguous memory block for the samples
- making sure it's properly aligned (64K should be enough!)
- */
- ASSERT(lAlignedSize % m_lAlignment == 0);
-
- LONGLONG lToAllocate = m_lCount * (LONGLONG)lAlignedSize;
-
- /* Check overflow */
- if (lToAllocate > MAXLONG) {
- return E_OUTOFMEMORY;
- }
-
m_bAllocated = TRUE;
CMediaPacketSample *pSample = nullptr;
ASSERT(m_lAllocated == 0);
- // Create the new samples - we have allocated m_lSize bytes for each sample
- // plus m_lPrefix bytes per sample as a prefix. We set the pointer to
- // the memory after the prefix - so that GetPointer() will return a pointer
- // to m_lSize bytes.
+ // Create the initial set of samples
for (; m_lAllocated < m_lCount; m_lAllocated++) {
pSample = new CMediaPacketSample(NAME("LAV Package media sample"), this, &hr);
@@ -272,6 +248,76 @@ HRESULT CPacketAllocator::Alloc(void)
return NOERROR;
}
+// get container for a sample. Blocking, synchronous call to get the
+// next free buffer (as represented by an IMediaSample interface).
+// on return, the time etc properties will be invalid, but the buffer
+// pointer and size will be correct.
+
+HRESULT CPacketAllocator::GetBuffer(__deref_out IMediaSample **ppBuffer,
+ __in_opt REFERENCE_TIME *pStartTime,
+ __in_opt REFERENCE_TIME *pEndTime,
+ DWORD dwFlags
+)
+{
+ UNREFERENCED_PARAMETER(pStartTime);
+ UNREFERENCED_PARAMETER(pEndTime);
+ UNREFERENCED_PARAMETER(dwFlags);
+ CMediaSample *pSample;
+
+ *ppBuffer = NULL;
+ for (;;)
+ {
+ { // scope for lock
+ CAutoLock cObjectLock(this);
+
+ /* Check we are committed */
+ if (!m_bCommitted) {
+ return VFW_E_NOT_COMMITTED;
+ }
+ pSample = (CMediaSample *)m_lFree.RemoveHead();
+
+ /* if no sample was available, allocate a new one */
+ if (pSample == NULL) {
+ HRESULT hr = S_OK;
+ pSample = new CMediaPacketSample(NAME("LAV Package media sample"), this, &hr);
+ ASSERT(SUCCEEDED(hr));
+
+ if (pSample) {
+ m_lAllocated++;
+ DbgLog((LOG_TRACE, 10, "Allocated new sample, %d total", m_lAllocated));
+ }
+ }
+ }
+
+ /* If we didn't get a sample then wait for the list to signal */
+
+ if (pSample) {
+ break;
+ }
+ if (dwFlags & AM_GBF_NOWAIT) {
+ return VFW_E_TIMEOUT;
+ }
+ ASSERT(m_hSem != NULL);
+ WaitForSingleObject(m_hSem, INFINITE);
+ }
+
+ /* Addref the buffer up to one. On release
+ back to zero instead of being deleted, it will requeue itself by
+ calling the ReleaseBuffer member function. NOTE the owner of a
+ media sample must always be derived from CBaseAllocator */
+
+
+ ASSERT(pSample->m_cRef == 0);
+ pSample->m_cRef = 1;
+ *ppBuffer = pSample;
+
+#ifdef DXMPERF
+ PERFLOG_GETBUFFER((IMemAllocator *) this, pSample);
+#endif // DXMPERF
+
+ return NOERROR;
+}
+
// override this to free up any resources we have allocated.
// called from the base class on Decommit when all buffers have been
diff --git a/demuxer/LAVSplitter/PacketAllocator.h b/demuxer/LAVSplitter/PacketAllocator.h
index 1de13118..8f3b03b1 100644
--- a/demuxer/LAVSplitter/PacketAllocator.h
+++ b/demuxer/LAVSplitter/PacketAllocator.h
@@ -25,6 +25,7 @@
#include "Packet.h"
#include "IMediaSideData.h"
#include "IMediaSideDataFFmpeg.h"
+#include "ILAVDynamicAllocator.h"
interface __declspec(uuid("0B2EE323-0ED8-452D-B31E-B9B4DE2C0C39"))
ILAVMediaSample : public IUnknown {
@@ -54,7 +55,7 @@ protected:
MediaSideDataFFMpeg *m_pSideData = nullptr;
};
-class CPacketAllocator : public CBaseAllocator
+class CPacketAllocator : public CBaseAllocator, public ILAVDynamicAllocator
{
protected:
BOOL m_bAllocated = FALSE;
@@ -69,9 +70,19 @@ protected:
// overriden to allocate the memory when commit called
HRESULT Alloc(void);
+
public:
CPacketAllocator(LPCTSTR pName, LPUNKNOWN pUnk, HRESULT *phr);
virtual ~CPacketAllocator(void);
+ // CUnknown support
+ DECLARE_IUNKNOWN;
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
+
+ // CBaseAllocator overrides
STDMETHODIMP SetProperties(ALLOCATOR_PROPERTIES* pRequest, ALLOCATOR_PROPERTIES* pActual);
+ STDMETHODIMP GetBuffer(IMediaSample **ppBuffer, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime, DWORD dwFlags);
+
+ // ILAVDynamicAllocator
+ STDMETHODIMP_(BOOL) IsDynamicAllocator() { return TRUE; }
};
diff --git a/demuxer/LAVSplitter/dllmain.cpp b/demuxer/LAVSplitter/dllmain.cpp
index f65df0d3..1d6e0a74 100644
--- a/demuxer/LAVSplitter/dllmain.cpp
+++ b/demuxer/LAVSplitter/dllmain.cpp
@@ -37,6 +37,7 @@
#include "registry.h"
#include "IGraphRebuildDelegate.h"
#include "IMediaSideDataFFmpeg.h"
+#include "ILAVDynamicAllocator.h"
// The GUID we use to register the splitter media types
DEFINE_GUID(MEDIATYPE_LAVSplitter,