Initial addition to SVN - matches v0.18 alpha
git-svn-id: svn://svn.code.sf.net/p/qsdecoder/code/trunk/IntelQuickSyncDecoder@2 dfccccb7-dd81-40b7-a334-5a7ba89c2b1d
This commit is contained in:
commit
9c439b090b
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
QS_PROFILE_MPEG2_422 = 0, /* 4:2:2 or 4:2:0 */
|
||||
QS_PROFILE_MPEG2_HIGH = 1, /* 4:2:2 or 4:2:0 */
|
||||
QS_PROFILE_MPEG2_SPATIALLY_SCALABLE = 2, /* 4:2:0 */
|
||||
QS_PROFILE_MPEG2_SNR_SCALABLE = 3, /* 4:2:0 */
|
||||
QS_PROFILE_MPEG2_MAIN = 4, /* 4:2:0 */
|
||||
QS_PROFILE_MPEG2_SIMPLE = 5 /* 4:2:0 */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
// profile modifiers
|
||||
QS_PROFILE_H264_CONSTRAINED = (1<<9), // 8+1; constraint_set1_flag
|
||||
QS_PROFILE_H264_INTRA = (1<<11), // 8+3; constraint_set3_flag
|
||||
|
||||
QS_PROFILE_H264_BASELINE = 66,
|
||||
QS_PROFILE_H264_CONSTRAINED_BASELINE = (66|QS_PROFILE_H264_CONSTRAINED),
|
||||
QS_PROFILE_H264_MAIN = 77,
|
||||
QS_PROFILE_H264_EXTENDED = 88,
|
||||
QS_PROFILE_H264_HIGH = 100,
|
||||
QS_PROFILE_H264_HIGH_10 = 110,
|
||||
QS_PROFILE_H264_HIGH_10_INTRA = (110|QS_PROFILE_H264_INTRA),
|
||||
QS_PROFILE_H264_HIGH_422 = 122,
|
||||
QS_PROFILE_H264_HIGH_422_INTRA = (122|QS_PROFILE_H264_INTRA),
|
||||
QS_PROFILE_H264_HIGH_444 = 144,
|
||||
QS_PROFILE_H264_HIGH_444_PREDICTIVE = 244,
|
||||
QS_PROFILE_H264_HIGH_444_INTRA = (244|QS_PROFILE_H264_INTRA),
|
||||
QS_PROFILE_H264_CAVLC_444 = 44,
|
||||
QS_PROFILE_H264_MULTIVIEW_HIGH = 118,
|
||||
QS_PROFILE_H264_STEREO_HIGH = 128
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
QS_PROFILE_VC1_SIMPLE = 0,
|
||||
QS_PROFILE_VC1_MAIN = 1,
|
||||
QS_PROFILE_VC1_COMPLEX = 2,
|
||||
QS_PROFILE_VC1_ADVANCED = 3
|
||||
};
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Hendrik Leppkes
|
||||
* http://www.1f0.de
|
||||
*
|
||||
* This Program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This Program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Initial design and concept by Gabest and the MPC-HC Team, copyright under GPLv2
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "H264Nalu.h"
|
||||
|
||||
void CH264Nalu::SetBuffer(BYTE* pBuffer, int nSize, int nNALSize)
|
||||
{
|
||||
m_pBuffer = pBuffer;
|
||||
m_nSize = nSize;
|
||||
m_nNALSize = nNALSize;
|
||||
m_nCurPos = 0;
|
||||
m_nNextRTP = 0;
|
||||
|
||||
m_nNALStartPos = 0;
|
||||
m_nNALDataPos = 0;
|
||||
}
|
||||
|
||||
bool CH264Nalu::MoveToNextAnnexBStartcode()
|
||||
{
|
||||
int nBuffEnd = m_nSize - 4;
|
||||
|
||||
for (int i=m_nCurPos; i<nBuffEnd; i++) {
|
||||
if ((*((DWORD*)(m_pBuffer+i)) & 0x00FFFFFF) == 0x00010000) {
|
||||
// Find next AnnexB Nal
|
||||
m_nCurPos = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
m_nCurPos = m_nSize;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CH264Nalu::MoveToNextRTPStartcode()
|
||||
{
|
||||
if (m_nNextRTP < m_nSize) {
|
||||
m_nCurPos = m_nNextRTP;
|
||||
return true;
|
||||
}
|
||||
|
||||
m_nCurPos = m_nSize;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CH264Nalu::ReadNext()
|
||||
{
|
||||
|
||||
if (m_nCurPos >= m_nSize) return false;
|
||||
|
||||
if ((m_nNALSize != 0) && (m_nCurPos == m_nNextRTP))
|
||||
{
|
||||
// RTP Nalu type : (XX XX) XX XX NAL..., with XX XX XX XX or XX XX equal to NAL size
|
||||
m_nNALStartPos = m_nCurPos;
|
||||
m_nNALDataPos = m_nCurPos + m_nNALSize;
|
||||
unsigned nTemp = 0;
|
||||
for (int i=0; i<m_nNALSize; i++)
|
||||
{
|
||||
nTemp = (nTemp << 8) + m_pBuffer[m_nCurPos++];
|
||||
}
|
||||
m_nNextRTP += nTemp + m_nNALSize;
|
||||
MoveToNextRTPStartcode();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove trailing bits
|
||||
while (m_pBuffer[m_nCurPos]==0x00 && ((*((DWORD*)(m_pBuffer+m_nCurPos)) & 0x00FFFFFF) != 0x00010000))
|
||||
m_nCurPos++;
|
||||
|
||||
// AnnexB Nalu : 00 00 01 NAL...
|
||||
m_nNALStartPos = m_nCurPos;
|
||||
m_nCurPos += 3;
|
||||
m_nNALDataPos = m_nCurPos;
|
||||
MoveToNextAnnexBStartcode();
|
||||
}
|
||||
|
||||
forbidden_bit = (m_pBuffer[m_nNALDataPos]>>7) & 1;
|
||||
nal_reference_idc = (m_pBuffer[m_nNALDataPos]>>5) & 3;
|
||||
nal_unit_type = (NALU_TYPE) (m_pBuffer[m_nNALDataPos] & 0x1f);
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Hendrik Leppkes
|
||||
* http://www.1f0.de
|
||||
*
|
||||
* This Program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This Program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* Initial design and concept by Gabest and the MPC-HC Team, copyright under GPLv2
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NALU_TYPE_SLICE = 1,
|
||||
NALU_TYPE_DPA = 2,
|
||||
NALU_TYPE_DPB = 3,
|
||||
NALU_TYPE_DPC = 4,
|
||||
NALU_TYPE_IDR = 5,
|
||||
NALU_TYPE_SEI = 6,
|
||||
NALU_TYPE_SPS = 7,
|
||||
NALU_TYPE_PPS = 8,
|
||||
NALU_TYPE_AUD = 9,
|
||||
NALU_TYPE_EOSEQ = 10,
|
||||
NALU_TYPE_EOSTREAM = 11,
|
||||
NALU_TYPE_FILL = 12
|
||||
} NALU_TYPE;
|
||||
|
||||
|
||||
class CH264Nalu
|
||||
{
|
||||
private :
|
||||
int forbidden_bit; //! should be always FALSE
|
||||
int nal_reference_idc; //! NALU_PRIORITY_xxxx
|
||||
NALU_TYPE nal_unit_type; //! NALU_TYPE_xxxx
|
||||
|
||||
int m_nNALStartPos; //! NALU start (including startcode / size)
|
||||
int m_nNALDataPos; //! Useful part
|
||||
|
||||
BYTE *m_pBuffer;
|
||||
int m_nCurPos;
|
||||
int m_nNextRTP;
|
||||
int m_nSize;
|
||||
int m_nNALSize;
|
||||
|
||||
bool MoveToNextAnnexBStartcode();
|
||||
bool MoveToNextRTPStartcode();
|
||||
|
||||
public :
|
||||
CH264Nalu() { SetBuffer(NULL, 0, 0); }
|
||||
NALU_TYPE GetType() const { return nal_unit_type; }
|
||||
bool IsRefFrame() const { return (nal_reference_idc != 0); }
|
||||
|
||||
int GetDataLength() const { return m_nCurPos - m_nNALDataPos; }
|
||||
BYTE *GetDataBuffer() { return m_pBuffer + m_nNALDataPos; }
|
||||
int GetRoundedDataLength() const
|
||||
{
|
||||
int nSize = m_nCurPos - m_nNALDataPos;
|
||||
return nSize + 128 - (nSize %128);
|
||||
}
|
||||
|
||||
int GetLength() const { return m_nCurPos - m_nNALStartPos; }
|
||||
BYTE *GetNALBuffer() { return m_pBuffer + m_nNALStartPos; }
|
||||
bool IsEOF() const { return m_nCurPos >= m_nSize; }
|
||||
|
||||
void SetBuffer (BYTE *pBuffer, int nSize, int nNALSize);
|
||||
bool ReadNext();
|
||||
};
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define QS_DEC_DLL_NAME "IntelQuickSyncDecoder.dll"
|
||||
#define QS_DEC_VERSION "v0.18 Alpha"
|
||||
|
||||
// This struct holds an output frame + meta data
|
||||
struct QsFrameData
|
||||
{
|
||||
QsFrameData() { memset(this, 0, sizeof(QsFrameData)); }
|
||||
|
||||
enum QsFrameType
|
||||
{
|
||||
Invalid = 0,
|
||||
I = 1,
|
||||
P = 2,
|
||||
B = 3
|
||||
};
|
||||
|
||||
unsigned char* y;
|
||||
unsigned char* u;
|
||||
unsigned char* v;
|
||||
DWORD dwWidth;
|
||||
DWORD dwHeight;
|
||||
DWORD dwStride;
|
||||
REFERENCE_TIME rtStart, rtStop;
|
||||
DWORD dwInterlaceFlags; // same as dwTypeSpecificFlags (AM_SAMPLE2_PROPERTIES)
|
||||
bool bFilm;
|
||||
DWORD dwPictAspectRatioX;
|
||||
DWORD dwPictAspectRatioY;
|
||||
QsFrameType frameType;
|
||||
};
|
||||
|
||||
// config for QuickSync component
|
||||
struct CQsConfig
|
||||
{
|
||||
CQsConfig() :
|
||||
dwOutputQueueLength(16)
|
||||
{
|
||||
}
|
||||
|
||||
DWORD dwOutputQueueLength;
|
||||
};
|
||||
|
||||
// Interafce to QuickSync component
|
||||
struct IQuickSyncDecoder
|
||||
{
|
||||
typedef HRESULT (*TQS_DeliverSurfaceCallback) (void* obj, QsFrameData* data);
|
||||
|
||||
// useless constructor to keep several compilers happy...
|
||||
IQuickSyncDecoder() {}
|
||||
|
||||
|
||||
// Object is OK
|
||||
virtual bool getOK() = 0;
|
||||
|
||||
// Test if the decoder supports the media type
|
||||
// Return codes are:
|
||||
// S_OK - support with HW acceleration.
|
||||
// S_FALSE - support with SW implementation
|
||||
// E_FAIL - no support
|
||||
// Other errors indicate bad parameters.
|
||||
virtual HRESULT TestMediaType(const AM_MEDIA_TYPE* mtIn, FOURCC fourCC) = 0;
|
||||
|
||||
// Initialize decoder
|
||||
virtual HRESULT InitDecoder(const AM_MEDIA_TYPE* mtIn, FOURCC fourCC) = 0;
|
||||
|
||||
// Decode a sample. Decoded frames are delivered via a callback.
|
||||
// Call SetDeliverSurfaceCallback to specify the callback
|
||||
virtual HRESULT Decode(IMediaSample* pIn) = 0;
|
||||
|
||||
// Flush decoder
|
||||
// When deliverFrames == true, the frames will be delivered via a callback (same as Decode).
|
||||
virtual HRESULT Flush(bool deliverFrames = true) = 0;
|
||||
|
||||
// OnSeek/NewSegment - marks the decoding of a new segment.
|
||||
// Resets the decoder discarding old data.
|
||||
virtual HRESULT OnSeek(REFERENCE_TIME segmentStart) = 0;
|
||||
|
||||
// Marks the start of a flush. All calls to Decode will be ignored.
|
||||
// Usually called asynchroniously from the application thread.
|
||||
virtual HRESULT BeginFlush() = 0;
|
||||
|
||||
// Marks the end of a flush. All calls to Decode after this function is called will be accepted.
|
||||
// Usually called asynchroniously from the application thread.
|
||||
// An implicit OnSeek call will be generated after the next Decode call.
|
||||
virtual HRESULT EndFlush() = 0;
|
||||
|
||||
// Sets the callback funtion for a DeliverSurface event. This the only method for frame delivery.
|
||||
virtual void SetDeliverSurfaceCallback(void* obj, TQS_DeliverSurfaceCallback func) = 0;
|
||||
|
||||
protected:
|
||||
// Ban copying!
|
||||
IQuickSyncDecoder& operator=(const IQuickSyncDecoder&);
|
||||
IQuickSyncDecoder(const IQuickSyncDecoder&);
|
||||
// Ban destruction of interface
|
||||
~IQuickSyncDecoder() {}
|
||||
};
|
||||
|
||||
// exported functions
|
||||
extern "C"
|
||||
{
|
||||
IQuickSyncDecoder* __stdcall createQuickSync();
|
||||
void __stdcall destroyQuickSync(IQuickSyncDecoder*);
|
||||
void __stdcall getVersion(char* ver, const char** license);
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
EXPORTS
|
||||
createQuickSync
|
||||
destroyQuickSync
|
||||
getVersion
|
|
@ -0,0 +1,270 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{83F0170E-6AB3-467B-98D5-E061BD2BF00D}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>QuickSync</RootNamespace>
|
||||
<ProjectName>IntelQuickSyncDecoder</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)obj\$(Configuration)_$(PlatformName)_VC2010\$(ProjectName)\</OutDir>
|
||||
<IntDir>$(SolutionDir)obj\$(Configuration)_$(PlatformName)_VC2010\$(ProjectName)\</IntDir>
|
||||
<GenerateManifest>true</GenerateManifest>
|
||||
<IncludePath>MSDK\include;./BaseClasses;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>MSDK\lib\$(PlatformName);$(LibraryPath)</LibraryPath>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)obj\$(Configuration)_$(PlatformName)_VC2010\$(ProjectName)\</OutDir>
|
||||
<IntDir>$(SolutionDir)obj\$(Configuration)_$(PlatformName)_VC2010\$(ProjectName)\</IntDir>
|
||||
<GenerateManifest>true</GenerateManifest>
|
||||
<IncludePath>MSDK\include;./BaseClasses;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>MSDK\lib\$(PlatformName);$(LibraryPath)</LibraryPath>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)obj\$(Configuration)_$(PlatformName)_VC2010\</OutDir>
|
||||
<IntDir>$(SolutionDir)obj\$(Configuration)_$(PlatformName)_VC2010\$(ProjectName)\</IntDir>
|
||||
<GenerateManifest>true</GenerateManifest>
|
||||
<IncludePath>MSDK\include;./BaseClasses;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>MSDK\lib\$(PlatformName);$(LibraryPath)</LibraryPath>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)obj\$(Configuration)_$(PlatformName)_VC2010\</OutDir>
|
||||
<IntDir>$(SolutionDir)obj\$(Configuration)_$(PlatformName)_VC2010\$(ProjectName)\</IntDir>
|
||||
<GenerateManifest>true</GenerateManifest>
|
||||
<IncludePath>MSDK\include;./BaseClasses;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>MSDK\lib\$(PlatformName);$(LibraryPath)</LibraryPath>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;DEBUG;_DEBUG;_WINDOWS;_USRDLL;QUICKSYNC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4996;4245;4995</DisableSpecificWarnings>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>IntelQuickSyncDecoder.def</ModuleDefinitionFile>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<OutputFile>$(SolutionDir)bin\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<AdditionalDependencies>winmm.lib;uuid.lib;D3D9.lib;Dxva2.lib;libmfx.lib;strmiids.lib</AdditionalDependencies>
|
||||
<Version>
|
||||
</Version>
|
||||
<IgnoreSpecificDefaultLibraries>LIBCMT.LIB</IgnoreSpecificDefaultLibraries>
|
||||
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;DEBUG;_DEBUG;_WINDOWS;_USRDLL;QUICKSYNC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4996;4245;4995</DisableSpecificWarnings>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>IntelQuickSyncDecoder.def</ModuleDefinitionFile>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<OutputFile>$(SolutionDir)bin\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<AdditionalDependencies>winmm.lib;uuid.lib;D3D9.lib;Dxva2.lib;libmfx.lib;strmiids.lib</AdditionalDependencies>
|
||||
<Version>
|
||||
</Version>
|
||||
<IgnoreSpecificDefaultLibraries>LIBCMT.LIB</IgnoreSpecificDefaultLibraries>
|
||||
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;QUICKSYNC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4996;4245;4995</DisableSpecificWarnings>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>IntelQuickSyncDecoder.def</ModuleDefinitionFile>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<OutputFile>$(SolutionDir)bin\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<AdditionalDependencies>winmm.lib;uuid.lib;D3D9.lib;Dxva2.lib;libmfx.lib;strmiids.lib</AdditionalDependencies>
|
||||
<Version>
|
||||
</Version>
|
||||
<IgnoreSpecificDefaultLibraries>LIBCMTD.LIB</IgnoreSpecificDefaultLibraries>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;QUICKSYNC_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4996;4245;4995</DisableSpecificWarnings>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<AssemblerOutput>NoListing</AssemblerOutput>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>IntelQuickSyncDecoder.def</ModuleDefinitionFile>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<OutputFile>$(SolutionDir)bin\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<AdditionalDependencies>winmm.lib;uuid.lib;D3D9.lib;Dxva2.lib;libmfx.lib;strmiids.lib</AdditionalDependencies>
|
||||
<Version>
|
||||
</Version>
|
||||
<IgnoreSpecificDefaultLibraries>LIBCMTD.LIB</IgnoreSpecificDefaultLibraries>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<None Include="IntelQuickSyncDecoder.def" />
|
||||
<None Include="license.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="base_allocator.h" />
|
||||
<ClInclude Include="CodecInfo.h" />
|
||||
<ClInclude Include="H264Nalu.h" />
|
||||
<ClInclude Include="QuickSyncDecoder.h" />
|
||||
<ClInclude Include="d3d_allocator.h" />
|
||||
<ClInclude Include="IQuickSyncDecoder.h" />
|
||||
<ClInclude Include="frame_constructors.h" />
|
||||
<ClInclude Include="QuickSync.h" />
|
||||
<ClInclude Include="QuickSyncUtils.h" />
|
||||
<ClInclude Include="QuickSync_defs.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="sysmem_allocator.h" />
|
||||
<ClInclude Include="TimeManager.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="base_alllocator.cpp" />
|
||||
<ClCompile Include="QuickSyncExports.cpp" />
|
||||
<ClCompile Include="H264Nalu.cpp" />
|
||||
<ClCompile Include="QuickSyncDecoder.cpp" />
|
||||
<ClCompile Include="d3d_allocator.cpp" />
|
||||
<ClCompile Include="frame_constructors.cpp" />
|
||||
<ClCompile Include="QuickSync.cpp" />
|
||||
<ClCompile Include="QuickSyncUtils.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sysmem_allocator.cpp" />
|
||||
<ClCompile Include="TimeManager.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -0,0 +1,93 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="QuickSync.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="frame_constructors.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="base_allocator.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d3d_allocator.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sysmem_allocator.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="QuickSync_defs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TimeManager.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="QuickSyncDecoder.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="QuickSyncUtils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="H264Nalu.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IQuickSyncDecoder.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CodecInfo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QuickSync.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="frame_constructors.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="base_alllocator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="d3d_allocator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sysmem_allocator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QuickSyncDecoder.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QuickSyncUtils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="H264Nalu.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TimeManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QuickSyncExports.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="license.txt" />
|
||||
<None Include="IntelQuickSyncDecoder.def" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,105 @@
|
|||
/* ****************************************************************************** *\
|
||||
|
||||
INTEL CORPORATION PROPRIETARY INFORMATION
|
||||
This software is supplied under the terms of a license agreement or nondisclosure
|
||||
agreement with Intel Corporation and may not be copied or disclosed except in
|
||||
accordance with the terms of that agreement
|
||||
Copyright(c) 2007-2011 Intel Corporation. All Rights Reserved.
|
||||
|
||||
File Name: mfxdefs.h
|
||||
|
||||
\* ****************************************************************************** */
|
||||
#ifndef __MFXDEFS_H__
|
||||
#define __MFXDEFS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#if defined( _WIN32 ) || defined ( _WIN64 )
|
||||
#define __INT64 __int64
|
||||
#define __UINT64 unsigned __int64
|
||||
#else
|
||||
#define __INT64 long long
|
||||
#define __UINT64 unsigned long long
|
||||
#endif
|
||||
|
||||
typedef unsigned char mfxU8;
|
||||
typedef char mfxI8;
|
||||
typedef short mfxI16;
|
||||
typedef unsigned short mfxU16;
|
||||
typedef unsigned int mfxU32;
|
||||
typedef int mfxI32;
|
||||
typedef unsigned long mfxUL32;
|
||||
typedef long mfxL32;
|
||||
typedef float mfxF32;
|
||||
typedef double mfxF64;
|
||||
typedef __UINT64 mfxU64;
|
||||
typedef __INT64 mfxI64;
|
||||
typedef void* mfxHDL;
|
||||
typedef mfxHDL mfxMemId;
|
||||
typedef void* mfxThreadTask;
|
||||
|
||||
typedef struct {
|
||||
mfxI16 x;
|
||||
mfxI16 y;
|
||||
} mfxI16Pair;
|
||||
|
||||
typedef struct {
|
||||
mfxHDL first;
|
||||
mfxHDL second;
|
||||
} mfxHDLPair;
|
||||
|
||||
|
||||
/*********************************************************************************\
|
||||
Error message
|
||||
\*********************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
/* no error */
|
||||
MFX_ERR_NONE = 0, /* no error */
|
||||
|
||||
/* reserved for unexpected errors */
|
||||
MFX_ERR_UNKNOWN = -1, /* unknown error. */
|
||||
|
||||
/* error codes <0 */
|
||||
MFX_ERR_NULL_PTR = -2, /* null pointer */
|
||||
MFX_ERR_UNSUPPORTED = -3, /* undeveloped feature */
|
||||
MFX_ERR_MEMORY_ALLOC = -4, /* failed to allocate memory */
|
||||
MFX_ERR_NOT_ENOUGH_BUFFER = -5, /* insufficient buffer at input/output */
|
||||
MFX_ERR_INVALID_HANDLE = -6, /* invalid handle */
|
||||
MFX_ERR_LOCK_MEMORY = -7, /* failed to lock the memory block */
|
||||
MFX_ERR_NOT_INITIALIZED = -8, /* member function called before initialization */
|
||||
MFX_ERR_NOT_FOUND = -9, /* the specified object is not found */
|
||||
MFX_ERR_MORE_DATA = -10, /* expect more data at input */
|
||||
MFX_ERR_MORE_SURFACE = -11, /* expect more surface at output */
|
||||
MFX_ERR_ABORTED = -12, /* operation aborted */
|
||||
MFX_ERR_DEVICE_LOST = -13, /* lose the HW acceleration device */
|
||||
MFX_ERR_INCOMPATIBLE_VIDEO_PARAM = -14, /* incompatible video parameters */
|
||||
MFX_ERR_INVALID_VIDEO_PARAM = -15, /* invalid video parameters */
|
||||
MFX_ERR_UNDEFINED_BEHAVIOR = -16, /* undefined behavior */
|
||||
MFX_ERR_DEVICE_FAILED = -17, /* device operation failure */
|
||||
MFX_ERR_MORE_BITSTREAM = -18, /* expect more bitstream buffers at output */
|
||||
|
||||
/* warnings >0 */
|
||||
MFX_WRN_IN_EXECUTION = 1, /* the previous asynchrous operation is in execution */
|
||||
MFX_WRN_DEVICE_BUSY = 2, /* the HW acceleration device is busy */
|
||||
MFX_WRN_VIDEO_PARAM_CHANGED = 3, /* the video parameters are changed during decoding */
|
||||
MFX_WRN_PARTIAL_ACCELERATION = 4, /* SW is used */
|
||||
MFX_WRN_INCOMPATIBLE_VIDEO_PARAM = 5, /* incompatible video parameters */
|
||||
MFX_WRN_VALUE_NOT_CHANGED = 6, /* the value is saturated based on its valid range */
|
||||
MFX_WRN_OUT_OF_RANGE = 7, /* the value is out of valid range */
|
||||
|
||||
/* threading statuses */
|
||||
MFX_TASK_DONE = MFX_ERR_NONE, /* task has been completed */
|
||||
MFX_TASK_WORKING = 8, /* there is some more work to do */
|
||||
MFX_TASK_BUSY = 9 /* task is waiting for resources */
|
||||
|
||||
} mfxStatus;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MFXDEFS_H__ */
|
|
@ -0,0 +1,91 @@
|
|||
/******************************************************************************* *\
|
||||
|
||||
INTEL CORPORATION PROPRIETARY INFORMATION
|
||||
This software is supplied under the terms of a license agreement or nondisclosure
|
||||
agreement with Intel Corporation and may not be copied or disclosed except in
|
||||
accordance with the terms of that agreement
|
||||
Copyright(c) 2010 - 2011 Intel Corporation. All Rights Reserved.
|
||||
|
||||
File Name: mfxmvc.h
|
||||
|
||||
*******************************************************************************/
|
||||
#ifndef __MFXMVC_H__
|
||||
#define __MFXMVC_H__
|
||||
|
||||
#include "mfxdefs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* CodecProfile, CodecLevel */
|
||||
enum {
|
||||
/* MVC profiles */
|
||||
MFX_PROFILE_AVC_MULTIVIEW_HIGH =118,
|
||||
MFX_PROFILE_AVC_STEREO_HIGH =128
|
||||
};
|
||||
|
||||
/* Extended Buffer Ids */
|
||||
enum {
|
||||
MFX_EXTBUFF_MVC_SEQ_DESC = MFX_MAKEFOURCC('M','V','C','D'),
|
||||
MFX_EXTBUFF_MVC_TARGET_VIEWS = MFX_MAKEFOURCC('M','V','C','T')
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
mfxU16 ViewId;
|
||||
|
||||
mfxU16 NumAnchorRefsL0;
|
||||
mfxU16 NumAnchorRefsL1;
|
||||
mfxU16 AnchorRefL0[16];
|
||||
mfxU16 AnchorRefL1[16];
|
||||
|
||||
mfxU16 NumNonAnchorRefsL0;
|
||||
mfxU16 NumNonAnchorRefsL1;
|
||||
mfxU16 NonAnchorRefL0[16];
|
||||
mfxU16 NonAnchorRefL1[16];
|
||||
} mfxMVCViewDependency;
|
||||
|
||||
typedef struct {
|
||||
mfxU16 TemporalId; /* operation point temporal ID */
|
||||
mfxU16 LevelIdc;
|
||||
|
||||
mfxU16 NumViews; /* total number of views, including "depend on" views */
|
||||
mfxU16 NumTargetViews; /* number of the output views for the current operation point */
|
||||
mfxU16 *TargetViewId; /* array of target view ID, it points to mfxExtMVCSeqDesc::ViewId, set by SDK */
|
||||
} mfxMVCOperationPoint;
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
|
||||
mfxU32 NumView; /* number of view in the stream, set by SDK */
|
||||
mfxU32 NumViewAlloc; /* number of allocated elements, set by application */
|
||||
mfxMVCViewDependency *View; /* view ID and list of views used as reference for this view, allocated by application */
|
||||
|
||||
mfxU32 NumViewId; /* num of views IDs, to simplify copying, set by SDK */
|
||||
mfxU32 NumViewIdAlloc; /* number of allocated elements, set by application */
|
||||
mfxU16 *ViewId; /* allocated by application */
|
||||
|
||||
mfxU32 NumOP; /* number of operation points in OP array, set by SDK */
|
||||
mfxU32 NumOPAlloc; /* number of allocated elements in OP array, set by application */
|
||||
mfxMVCOperationPoint *OP; /* allocated by application */
|
||||
|
||||
mfxU16 NumRefsTotal; /* total number of reference frames in the sequence */
|
||||
mfxU32 Reserved[16];
|
||||
|
||||
} mfxExtMVCSeqDesc;
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
|
||||
mfxU16 TemporalId;
|
||||
mfxU32 NumView; /* number of view to decode */
|
||||
mfxU16 ViewId[1024];
|
||||
} mfxExtMVCTargetViews ;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/* ****************************************************************************** *\
|
||||
|
||||
INTEL CORPORATION PROPRIETARY INFORMATION
|
||||
This software is supplied under the terms of a license agreement or nondisclosure
|
||||
agreement with Intel Corporation and may not be copied or disclosed except in
|
||||
accordance with the terms of that agreement
|
||||
Copyright(c) 2011 Intel Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
File Name: mfxplugin++.h
|
||||
|
||||
\* ****************************************************************************** */
|
||||
|
||||
#ifndef __MFXPLUGINPLUSPLUS_H
|
||||
#define __MFXPLUGINPLUSPLUS_H
|
||||
|
||||
#include "mfxvideo.h"
|
||||
#include "mfxplugin.h"
|
||||
|
||||
class MFXPlugin
|
||||
{
|
||||
public:
|
||||
virtual mfxStatus mfxPluginInit(mfxCoreInterface *core) = 0;
|
||||
virtual mfxStatus mfxPluginClose() = 0;
|
||||
virtual mfxStatus mfxGetPluginParam(mfxPluginParam *par) = 0;
|
||||
virtual mfxStatus mfxSubmit(const mfxHDL *in, mfxU32 in_num, const mfxHDL *out, mfxU32 out_num, mfxThreadTask *task) = 0;
|
||||
virtual mfxStatus mfxExecute(mfxThreadTask task, mfxU32 uid_p, mfxU32 uid_a) = 0;
|
||||
virtual mfxStatus mfxFreeResources(mfxThreadTask task, mfxStatus sts) = 0;
|
||||
};
|
||||
|
||||
/* Class adapter between "C" structure mfxPlugin and C++ interface MFXPlugin */
|
||||
class MFXPluginAdapter : public mfxPlugin
|
||||
{
|
||||
public:
|
||||
MFXPluginAdapter(MFXPlugin *pPlugin)
|
||||
{
|
||||
pthis = pPlugin;
|
||||
PluginInit = MFXPluginAdapter::_PluginInit;
|
||||
PluginClose = MFXPluginAdapter::_PluginClose;
|
||||
GetPluginParam = MFXPluginAdapter::_GetPluginParam;
|
||||
Submit = MFXPluginAdapter::_Submit;
|
||||
Execute = MFXPluginAdapter::_Execute;
|
||||
FreeResources = MFXPluginAdapter::_FreeResources;
|
||||
}
|
||||
|
||||
private:
|
||||
static mfxStatus _PluginInit(mfxHDL pthis, mfxCoreInterface *core) { return ((MFXPlugin*)pthis)->mfxPluginInit(core); }
|
||||
static mfxStatus _PluginClose(mfxHDL pthis) { return ((MFXPlugin*)pthis)->mfxPluginClose(); }
|
||||
static mfxStatus _GetPluginParam(mfxHDL pthis, mfxPluginParam *par) { return ((MFXPlugin*)pthis)->mfxGetPluginParam(par); }
|
||||
static mfxStatus _Submit(mfxHDL pthis, const mfxHDL *in, mfxU32 in_num, const mfxHDL *out, mfxU32 out_num, mfxThreadTask *task) { return ((MFXPlugin*)pthis)->mfxSubmit(in, in_num, out, out_num, task); }
|
||||
static mfxStatus _Execute(mfxHDL pthis, mfxThreadTask task, mfxU32 thread_id, mfxU32 call_count) { return ((MFXPlugin*)pthis)->mfxExecute(task, thread_id, call_count); }
|
||||
static mfxStatus _FreeResources(mfxHDL pthis, mfxThreadTask task, mfxStatus sts) { return ((MFXPlugin*)pthis)->mfxFreeResources(task, sts); }
|
||||
};
|
||||
|
||||
#endif // __MFXPLUGINPLUSPLUS_H
|
|
@ -0,0 +1,90 @@
|
|||
/******************************************************************************* *\
|
||||
|
||||
INTEL CORPORATION PROPRIETARY INFORMATION
|
||||
This software is supplied under the terms of a license agreement or nondisclosure
|
||||
agreement with Intel Corporation and may not be copied or disclosed except in
|
||||
accordance with the terms of that agreement
|
||||
Copyright(c) 2007-2011 Intel Corporation. All Rights Reserved.
|
||||
|
||||
File Name: mfxplugin.h
|
||||
|
||||
*******************************************************************************/
|
||||
#ifndef __MFXPLUGIN_H__
|
||||
#define __MFXPLUGIN_H__
|
||||
#include "mfxvideo.h"
|
||||
|
||||
#pragma warning(disable: 4201)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef enum {
|
||||
MFX_THREADPOLICY_SERIAL = 0,
|
||||
MFX_THREADPOLICY_PARALLEL = 1
|
||||
} mfxThreadPolicy;
|
||||
|
||||
typedef struct mfxPluginParam {
|
||||
mfxU32 reserved[14];
|
||||
mfxThreadPolicy ThreadPolicy;
|
||||
mfxU32 MaxThreadNum;
|
||||
} mfxPluginParam;
|
||||
|
||||
typedef struct mfxCoreParam{
|
||||
mfxU32 reserved[13];
|
||||
mfxIMPL Impl;
|
||||
mfxVersion Version;
|
||||
mfxU32 NumWorkingThread;
|
||||
} mfxCoreParam;
|
||||
|
||||
typedef struct mfxCoreInterface {
|
||||
mfxHDL pthis;
|
||||
|
||||
mfxHDL reserved1[2];
|
||||
mfxFrameAllocator FrameAllocator;
|
||||
mfxBufferAllocator reserved3;
|
||||
|
||||
mfxStatus (*GetCoreParam)(mfxHDL pthis, mfxCoreParam *par);
|
||||
mfxStatus (*GetHandle) (mfxHDL pthis, mfxHandleType type, mfxHDL *handle);
|
||||
mfxStatus (*IncreaseReference) (mfxHDL pthis, mfxFrameData *fd);
|
||||
mfxStatus (*DecreaseReference) (mfxHDL pthis, mfxFrameData *fd);
|
||||
mfxStatus (*CopyFrame) (mfxHDL pthis, mfxFrameSurface1 *dst, mfxFrameSurface1 *src);
|
||||
mfxStatus (*CopyBuffer)(mfxHDL pthis, mfxU8 *dst, mfxU32 size, mfxFrameSurface1 *src);
|
||||
|
||||
mfxStatus (*MapOpaqueSurface)(mfxHDL pthis, mfxU32 num, mfxU32 type, mfxFrameSurface1 **op_surf);
|
||||
mfxStatus (*UnmapOpaqueSurface)(mfxHDL pthis, mfxU32 num, mfxU32 type, mfxFrameSurface1 **op_surf);
|
||||
|
||||
mfxStatus (*GetRealSurface)(mfxHDL pthis, mfxFrameSurface1 *op_surf, mfxFrameSurface1 **surf);
|
||||
mfxStatus (*GetOpaqueSurface)(mfxHDL pthis, mfxFrameSurface1 *surf, mfxFrameSurface1 **op_surf);
|
||||
|
||||
mfxHDL reserved4[4];
|
||||
} mfxCoreInterface;
|
||||
|
||||
typedef struct mfxPlugin{
|
||||
mfxHDL pthis;
|
||||
|
||||
mfxStatus (*PluginInit) (mfxHDL pthis, mfxCoreInterface *core);
|
||||
mfxStatus (*PluginClose) (mfxHDL pthis);
|
||||
|
||||
mfxStatus (*GetPluginParam)(mfxHDL pthis, mfxPluginParam *par);
|
||||
|
||||
mfxStatus (*Submit)(mfxHDL pthis, const mfxHDL *in, mfxU32 in_num, const mfxHDL *out, mfxU32 out_num, mfxThreadTask *task);
|
||||
mfxStatus (*Execute)(mfxHDL pthis, mfxThreadTask task, mfxU32 uid_p, mfxU32 uid_a);
|
||||
mfxStatus (*FreeResources)(mfxHDL pthis, mfxThreadTask task, mfxStatus sts);
|
||||
|
||||
mfxHDL reserved[9];
|
||||
} mfxPlugin;
|
||||
|
||||
|
||||
|
||||
mfxStatus MFXVideoUSER_Register(mfxSession session, mfxU32 type, const mfxPlugin *par);
|
||||
mfxStatus MFXVideoUSER_Unregister(mfxSession session, mfxU32 type);
|
||||
|
||||
mfxStatus MFXVideoUSER_ProcessFrameAsync(mfxSession session, const mfxHDL *in, mfxU32 in_num, const mfxHDL *out, mfxU32 out_num, mfxSyncPoint *syncp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __MFXPLUGIN_H__ */
|
|
@ -0,0 +1,739 @@
|
|||
/******************************************************************************* *\
|
||||
|
||||
INTEL CORPORATION PROPRIETARY INFORMATION
|
||||
This software is supplied under the terms of a license agreement or nondisclosure
|
||||
agreement with Intel Corporation and may not be copied or disclosed except in
|
||||
accordance with the terms of that agreement
|
||||
Copyright(c) 2007-2011 Intel Corporation. All Rights Reserved.
|
||||
|
||||
File Name: mfxstructures.h
|
||||
|
||||
*******************************************************************************/
|
||||
#ifndef __MFXSTRUCTURES_H__
|
||||
#define __MFXSTRUCTURES_H__
|
||||
#include "mfxdefs.h"
|
||||
|
||||
#pragma warning(disable: 4201)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MFX_MAKEFOURCC(A,B,C,D) ((((int)A))+(((int)B)<<8)+(((int)C)<<16)+(((int)D)<<24))
|
||||
|
||||
/* Extended Configuration Header Structure */
|
||||
typedef struct {
|
||||
mfxU32 BufferId;
|
||||
mfxU32 BufferSz;
|
||||
} mfxExtBuffer;
|
||||
|
||||
/* Frame ID for SVC and MVC */
|
||||
typedef struct {
|
||||
mfxU16 TemporalId;
|
||||
mfxU16 PriorityId;
|
||||
union {
|
||||
struct {
|
||||
mfxU16 DependencyId;
|
||||
mfxU16 QualityId;
|
||||
};
|
||||
struct {
|
||||
mfxU16 ViewId;
|
||||
};
|
||||
};
|
||||
} mfxFrameId;
|
||||
|
||||
/* Frame Info */
|
||||
typedef struct {
|
||||
mfxU32 reserved[6];
|
||||
mfxFrameId FrameId;
|
||||
|
||||
mfxU32 FourCC;
|
||||
mfxU16 Width;
|
||||
mfxU16 Height;
|
||||
|
||||
mfxU16 CropX;
|
||||
mfxU16 CropY;
|
||||
mfxU16 CropW;
|
||||
mfxU16 CropH;
|
||||
|
||||
mfxU32 FrameRateExtN;
|
||||
mfxU32 FrameRateExtD;
|
||||
mfxU16 reserved3;
|
||||
|
||||
mfxU16 AspectRatioW;
|
||||
mfxU16 AspectRatioH;
|
||||
|
||||
mfxU16 PicStruct;
|
||||
mfxU16 ChromaFormat;
|
||||
mfxU16 reserved2;
|
||||
} mfxFrameInfo;
|
||||
|
||||
/* FourCC */
|
||||
enum {
|
||||
MFX_FOURCC_NV12 = MFX_MAKEFOURCC('N','V','1','2'), /* Native Format */
|
||||
MFX_FOURCC_YV12 = MFX_MAKEFOURCC('Y','V','1','2'),
|
||||
MFX_FOURCC_YUY2 = MFX_MAKEFOURCC('Y','U','Y','2'),
|
||||
MFX_FOURCC_RGB3 = MFX_MAKEFOURCC('R','G','B','3'), /* RGB24 */
|
||||
MFX_FOURCC_RGB4 = MFX_MAKEFOURCC('R','G','B','4'), /* RGB32 */
|
||||
MFX_FOURCC_P8 = 41 /* D3DFMT_P8 */
|
||||
};
|
||||
|
||||
/* PicStruct */
|
||||
enum {
|
||||
MFX_PICSTRUCT_UNKNOWN =0x00,
|
||||
MFX_PICSTRUCT_PROGRESSIVE =0x01,
|
||||
MFX_PICSTRUCT_FIELD_TFF =0x02,
|
||||
MFX_PICSTRUCT_FIELD_BFF =0x04,
|
||||
|
||||
MFX_PICSTRUCT_FIELD_REPEATED=0x10, /* first field repeated, pic_struct=5 or 6 in H.264 */
|
||||
MFX_PICSTRUCT_FRAME_DOUBLING=0x20, /* pic_struct=7 in H.264 */
|
||||
MFX_PICSTRUCT_FRAME_TRIPLING=0x40 /* pic_struct=8 in H.264 */
|
||||
};
|
||||
|
||||
/* ColorFormat */
|
||||
enum {
|
||||
MFX_CHROMAFORMAT_MONOCHROME =0,
|
||||
MFX_CHROMAFORMAT_YUV420 =1,
|
||||
MFX_CHROMAFORMAT_YUV422 =2,
|
||||
MFX_CHROMAFORMAT_YUV444 =3
|
||||
};
|
||||
|
||||
enum {
|
||||
MFX_TIMESTAMP_UNKNOWN = -1
|
||||
};
|
||||
|
||||
enum {
|
||||
MFX_FRAMEORDER_UNKNOWN = -1
|
||||
};
|
||||
|
||||
/* DataFlag in mfxFrameData */
|
||||
enum {
|
||||
MFX_FRAMEDATA_ORIGINAL_TIMESTAMP = 0x0001
|
||||
};
|
||||
|
||||
/* Corrupted in mfxFrameData */
|
||||
enum {
|
||||
MFX_CORRUPTION_MINOR = 0x0001,
|
||||
MFX_CORRUPTION_MAJOR = 0x0002,
|
||||
MFX_CORRUPTION_REFERENCE_FRAME = 0x0010,
|
||||
MFX_CORRUPTION_REFERENCE_LIST = 0x0020
|
||||
};
|
||||
|
||||
/* Frame Data Info */
|
||||
typedef struct {
|
||||
mfxU32 reserved[8];
|
||||
|
||||
mfxU64 TimeStamp;
|
||||
mfxU32 FrameOrder;
|
||||
mfxU16 Locked;
|
||||
mfxU16 Pitch;
|
||||
|
||||
/* color planes */
|
||||
union {
|
||||
mfxU8 *Y;
|
||||
mfxU8 *R;
|
||||
};
|
||||
union {
|
||||
mfxU8 *UV; /* for UV merged formats */
|
||||
mfxU8 *VU; /* for VU merged formats */
|
||||
mfxU8 *CbCr; /* for CbCr merged formats */
|
||||
mfxU8 *CrCb; /* for CrCb merged formats */
|
||||
mfxU8 *Cb;
|
||||
mfxU8 *U;
|
||||
mfxU8 *G;
|
||||
};
|
||||
union {
|
||||
mfxU8 *Cr;
|
||||
mfxU8 *V;
|
||||
mfxU8 *B;
|
||||
};
|
||||
mfxU8 *A;
|
||||
mfxMemId MemId;
|
||||
|
||||
/* Additional Flags */
|
||||
mfxU16 Corrupted;
|
||||
mfxU16 DataFlag;
|
||||
} mfxFrameData;
|
||||
|
||||
/* Frame Surface */
|
||||
typedef struct {
|
||||
mfxU32 reserved[4];
|
||||
mfxFrameInfo Info;
|
||||
mfxFrameData Data;
|
||||
} mfxFrameSurface1;
|
||||
|
||||
enum {
|
||||
MFX_TIMESTAMPCALC_UNKNOWN = 0,
|
||||
MFX_TIMESTAMPCALC_TELECINE = 1,
|
||||
};
|
||||
|
||||
/* Transcoding Info */
|
||||
typedef struct {
|
||||
mfxU32 reserved[7];
|
||||
|
||||
mfxU16 reserved4;
|
||||
mfxU16 BRCParamMultiplier;
|
||||
|
||||
mfxFrameInfo FrameInfo;
|
||||
mfxU32 CodecId;
|
||||
mfxU16 CodecProfile;
|
||||
mfxU16 CodecLevel;
|
||||
mfxU16 NumThread;
|
||||
|
||||
union {
|
||||
struct { /* MPEG-2/H.264 Encoding Options */
|
||||
mfxU16 TargetUsage;
|
||||
|
||||
mfxU16 GopPicSize;
|
||||
mfxU16 GopRefDist;
|
||||
mfxU16 GopOptFlag;
|
||||
mfxU16 IdrInterval;
|
||||
|
||||
mfxU16 RateControlMethod;
|
||||
union {
|
||||
mfxU16 InitialDelayInKB;
|
||||
mfxU16 QPI;
|
||||
mfxU16 Accuracy;
|
||||
};
|
||||
mfxU16 BufferSizeInKB;
|
||||
union {
|
||||
mfxU16 TargetKbps;
|
||||
mfxU16 QPP;
|
||||
};
|
||||
union {
|
||||
mfxU16 MaxKbps;
|
||||
mfxU16 QPB;
|
||||
mfxU16 Convergence;
|
||||
};
|
||||
|
||||
mfxU16 NumSlice;
|
||||
mfxU16 NumRefFrame;
|
||||
mfxU16 EncodedOrder;
|
||||
};
|
||||
struct { /* H.264, MPEG-2 and VC-1 Decoding Options */
|
||||
mfxU16 DecodedOrder;
|
||||
mfxU16 ExtendedPicStruct;
|
||||
mfxU16 TimeStampCalc;
|
||||
mfxU16 reserved2[10];
|
||||
};
|
||||
};
|
||||
} mfxInfoMFX;
|
||||
|
||||
typedef struct {
|
||||
mfxU32 reserved[8];
|
||||
mfxFrameInfo In;
|
||||
mfxFrameInfo Out;
|
||||
} mfxInfoVPP;
|
||||
|
||||
typedef struct {
|
||||
mfxU32 reserved[3];
|
||||
mfxU16 reserved3;
|
||||
mfxU16 AsyncDepth;
|
||||
|
||||
union {
|
||||
mfxInfoMFX mfx;
|
||||
mfxInfoVPP vpp;
|
||||
};
|
||||
mfxU16 Protected;
|
||||
mfxU16 IOPattern;
|
||||
mfxExtBuffer** ExtParam;
|
||||
mfxU16 NumExtParam;
|
||||
mfxU16 reserved2;
|
||||
} mfxVideoParam;
|
||||
|
||||
/* IOPattern */
|
||||
enum {
|
||||
MFX_IOPATTERN_IN_VIDEO_MEMORY = 0x01,
|
||||
MFX_IOPATTERN_IN_SYSTEM_MEMORY = 0x02,
|
||||
MFX_IOPATTERN_IN_OPAQUE_MEMORY = 0x04,
|
||||
MFX_IOPATTERN_OUT_VIDEO_MEMORY = 0x10,
|
||||
MFX_IOPATTERN_OUT_SYSTEM_MEMORY = 0x20,
|
||||
MFX_IOPATTERN_OUT_OPAQUE_MEMORY = 0x40
|
||||
};
|
||||
|
||||
/* CodecId */
|
||||
enum {
|
||||
MFX_CODEC_AVC =MFX_MAKEFOURCC('A','V','C',' '),
|
||||
MFX_CODEC_MPEG2 =MFX_MAKEFOURCC('M','P','G','2'),
|
||||
MFX_CODEC_VC1 =MFX_MAKEFOURCC('V','C','1',' ')
|
||||
};
|
||||
|
||||
/* CodecProfile, CodecLevel */
|
||||
enum {
|
||||
MFX_PROFILE_UNKNOWN =0,
|
||||
MFX_LEVEL_UNKNOWN =0,
|
||||
|
||||
/* AVC Profiles & Levels */
|
||||
MFX_PROFILE_AVC_BASELINE =66,
|
||||
MFX_PROFILE_AVC_MAIN =77,
|
||||
MFX_PROFILE_AVC_EXTENDED =88,
|
||||
MFX_PROFILE_AVC_HIGH =100,
|
||||
|
||||
MFX_LEVEL_AVC_1 =10,
|
||||
MFX_LEVEL_AVC_1b =9,
|
||||
MFX_LEVEL_AVC_11 =11,
|
||||
MFX_LEVEL_AVC_12 =12,
|
||||
MFX_LEVEL_AVC_13 =13,
|
||||
MFX_LEVEL_AVC_2 =20,
|
||||
MFX_LEVEL_AVC_21 =21,
|
||||
MFX_LEVEL_AVC_22 =22,
|
||||
MFX_LEVEL_AVC_3 =30,
|
||||
MFX_LEVEL_AVC_31 =31,
|
||||
MFX_LEVEL_AVC_32 =32,
|
||||
MFX_LEVEL_AVC_4 =40,
|
||||
MFX_LEVEL_AVC_41 =41,
|
||||
MFX_LEVEL_AVC_42 =42,
|
||||
MFX_LEVEL_AVC_5 =50,
|
||||
MFX_LEVEL_AVC_51 =51,
|
||||
|
||||
/* MPEG-2 Profiles & Levels */
|
||||
MFX_PROFILE_MPEG2_SIMPLE =0x50,
|
||||
MFX_PROFILE_MPEG2_MAIN =0x40,
|
||||
MFX_PROFILE_MPEG2_HIGH =0x10,
|
||||
|
||||
MFX_LEVEL_MPEG2_LOW =0xA,
|
||||
MFX_LEVEL_MPEG2_MAIN =0x8,
|
||||
MFX_LEVEL_MPEG2_HIGH =0x4,
|
||||
MFX_LEVEL_MPEG2_HIGH1440 =0x6,
|
||||
|
||||
/* VC1 Profiles & Levels */
|
||||
MFX_PROFILE_VC1_SIMPLE =(0+1),
|
||||
MFX_PROFILE_VC1_MAIN =(4+1),
|
||||
MFX_PROFILE_VC1_ADVANCED =(12+1),
|
||||
|
||||
/* VC1 levels for simple & main profiles */
|
||||
MFX_LEVEL_VC1_LOW =(0+1),
|
||||
MFX_LEVEL_VC1_MEDIAN =(2+1),
|
||||
MFX_LEVEL_VC1_HIGH =(4+1),
|
||||
|
||||
/* VC1 levels for the advanced profile */
|
||||
MFX_LEVEL_VC1_0 =(0x00+1),
|
||||
MFX_LEVEL_VC1_1 =(0x01+1),
|
||||
MFX_LEVEL_VC1_2 =(0x02+1),
|
||||
MFX_LEVEL_VC1_3 =(0x03+1),
|
||||
MFX_LEVEL_VC1_4 =(0x04+1)
|
||||
};
|
||||
|
||||
/* GopOptFlag */
|
||||
enum {
|
||||
MFX_GOP_CLOSED =1,
|
||||
MFX_GOP_STRICT =2
|
||||
};
|
||||
|
||||
/* TargetUsages: from 1 to 7 inclusive */
|
||||
enum {
|
||||
MFX_TARGETUSAGE_UNKNOWN =0,
|
||||
MFX_TARGETUSAGE_BEST_QUALITY =1,
|
||||
MFX_TARGETUSAGE_BALANCED =4,
|
||||
MFX_TARGETUSAGE_BEST_SPEED =7
|
||||
};
|
||||
|
||||
/* RateControlMethod */
|
||||
enum {
|
||||
MFX_RATECONTROL_CBR =1,
|
||||
MFX_RATECONTROL_VBR =2,
|
||||
MFX_RATECONTROL_CQP =3,
|
||||
MFX_RATECONTROL_AVBR =4
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
|
||||
mfxU16 reserved1;
|
||||
mfxU16 RateDistortionOpt; /* tri-state option */
|
||||
mfxU16 MECostType;
|
||||
mfxU16 MESearchType;
|
||||
mfxI16Pair MVSearchWindow;
|
||||
mfxU16 EndOfSequence; /* tri-state option */
|
||||
mfxU16 FramePicture; /* tri-state option */
|
||||
|
||||
union {
|
||||
struct { /* AVC */
|
||||
mfxU16 CAVLC; /* tri-state option */
|
||||
mfxU16 reserved2[4];
|
||||
mfxU16 NalHrdConformance; /* tri-state option */
|
||||
mfxU16 SingleSeiNalUnit; /* tri-state option */
|
||||
mfxU16 VuiVclHrdParameters; /* tri-state option */
|
||||
|
||||
mfxU16 RefPicListReordering; /* tri-state option */
|
||||
mfxU16 ResetRefList; /* tri-state option */
|
||||
mfxU16 RefPicMarkRep; /* tri-state option */
|
||||
mfxU16 FieldOutput; /* tri-state option */
|
||||
|
||||
mfxU16 IntraPredBlockSize;
|
||||
mfxU16 InterPredBlockSize;
|
||||
mfxU16 MVPrecision;
|
||||
mfxU16 MaxDecFrameBuffering;
|
||||
|
||||
mfxU16 AUDelimiter; /* tri-state option */
|
||||
mfxU16 EndOfStream; /* tri-state option */
|
||||
mfxU16 PicTimingSEI; /* tri-state option */
|
||||
mfxU16 VuiNalHrdParameters; /* tri-state option */
|
||||
};
|
||||
};
|
||||
} mfxExtCodingOption;
|
||||
|
||||
/* IntraPredBlockSize/InterPredBlockSize */
|
||||
enum {
|
||||
MFX_BLOCKSIZE_UNKNOWN = 0,
|
||||
MFX_BLOCKSIZE_MIN_16X16 = 1, /* 16x16 */
|
||||
MFX_BLOCKSIZE_MIN_8X8 = 2, /* 16x16, 8x8 */
|
||||
MFX_BLOCKSIZE_MIN_4X4 = 3 /* 16x16, 8x8, 4x4 */
|
||||
};
|
||||
|
||||
/* MVPrecision */
|
||||
enum {
|
||||
MFX_MVPRECISION_UNKNOWN = 0,
|
||||
MFX_MVPRECISION_INTEGER = (1 << 0),
|
||||
MFX_MVPRECISION_HALFPEL = (1 << 1),
|
||||
MFX_MVPRECISION_QUARTERPEL = (1 << 2)
|
||||
};
|
||||
|
||||
enum {
|
||||
MFX_CODINGOPTION_UNKNOWN =0,
|
||||
MFX_CODINGOPTION_ON =0x10,
|
||||
MFX_CODINGOPTION_OFF =0x20
|
||||
};
|
||||
|
||||
typedef struct _mfxEncryptedData mfxEncryptedData;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
mfxEncryptedData* EncryptedData;
|
||||
mfxU32 reserved[8];
|
||||
};
|
||||
mfxU64 TimeStamp;
|
||||
mfxU8* Data;
|
||||
mfxU32 DataOffset;
|
||||
mfxU32 DataLength;
|
||||
mfxU32 MaxLength;
|
||||
|
||||
mfxU16 PicStruct;
|
||||
mfxU16 FrameType;
|
||||
mfxU16 DataFlag;
|
||||
mfxU16 reserved2;
|
||||
} mfxBitstream;
|
||||
|
||||
/* Data Flag */
|
||||
enum {
|
||||
MFX_BITSTREAM_COMPLETE_FRAME = 0x0001 /* the bitstream contains a complete frame or field pair of data */
|
||||
};
|
||||
|
||||
/* Extended Buffer Ids */
|
||||
enum {
|
||||
MFX_EXTBUFF_CODING_OPTION = MFX_MAKEFOURCC('C','D','O','P'),
|
||||
MFX_EXTBUFF_CODING_OPTION_SPSPPS= MFX_MAKEFOURCC('C','O','S','P'),
|
||||
MFX_EXTBUFF_VPP_DONOTUSE = MFX_MAKEFOURCC('N','U','S','E'),
|
||||
MFX_EXTBUFF_VPP_AUXDATA = MFX_MAKEFOURCC('A','U','X','D'),
|
||||
MFX_EXTBUFF_VPP_DENOISE = MFX_MAKEFOURCC('D','N','I','S'),
|
||||
MFX_EXTBUFF_VPP_SCENE_ANALYSIS = MFX_MAKEFOURCC('S','C','L','Y'),
|
||||
MFX_EXTBUFF_VPP_SCENE_CHANGE = MFX_EXTBUFF_VPP_SCENE_ANALYSIS,
|
||||
MFX_EXTBUFF_VPP_PROCAMP = MFX_MAKEFOURCC('P','A','M','P'),
|
||||
MFX_EXTBUFF_VPP_DETAIL = MFX_MAKEFOURCC('D','E','T',' '),
|
||||
MFX_EXTBUFF_VIDEO_SIGNAL_INFO = MFX_MAKEFOURCC('V','S','I','N'),
|
||||
MFX_EXTBUFF_VPP_DOUSE = MFX_MAKEFOURCC('D','U','S','E'),
|
||||
MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION = MFX_MAKEFOURCC('O','P','Q','S'),
|
||||
MFX_EXTBUFF_AVC_REFLIST_CTRL = MFX_MAKEFOURCC('R','L','S','T'),
|
||||
MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION = MFX_MAKEFOURCC('F','R','C',' '),
|
||||
MFX_EXTBUFF_PICTURE_TIMING_SEI = MFX_MAKEFOURCC('P','T','S','E'),
|
||||
MFX_EXTBUFF_AVC_TEMPORAL_LAYERS = MFX_MAKEFOURCC('A','T','M','L')
|
||||
};
|
||||
|
||||
/* VPP Conf: Do not use certain algorithms */
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
mfxU32 NumAlg;
|
||||
mfxU32* AlgList;
|
||||
} mfxExtVPPDoNotUse;
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
mfxU16 DenoiseFactor;
|
||||
} mfxExtVPPDenoise;
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
mfxU16 DetailFactor;
|
||||
} mfxExtVPPDetail;
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
mfxF64 Brightness;
|
||||
mfxF64 Contrast;
|
||||
mfxF64 Hue;
|
||||
mfxF64 Saturation;
|
||||
} mfxExtVPPProcAmp;
|
||||
|
||||
/* statistics collected for decode, encode and vpp */
|
||||
typedef struct {
|
||||
mfxU32 reserved[16];
|
||||
mfxU32 NumFrame;
|
||||
mfxU64 NumBit;
|
||||
mfxU32 NumCachedFrame;
|
||||
} mfxEncodeStat;
|
||||
|
||||
typedef struct {
|
||||
mfxU32 reserved[16];
|
||||
mfxU32 NumFrame;
|
||||
mfxU32 NumSkippedFrame;
|
||||
mfxU32 NumError;
|
||||
mfxU32 NumCachedFrame;
|
||||
} mfxDecodeStat;
|
||||
|
||||
typedef struct {
|
||||
mfxU32 reserved[16];
|
||||
mfxU32 NumFrame;
|
||||
mfxU32 NumCachedFrame;
|
||||
} mfxVPPStat;
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
mfxU32 SpatialComplexity;
|
||||
mfxU32 TemporalComplexity;
|
||||
mfxU16 SceneChangeRate;
|
||||
mfxU16 RepeatedFrame;
|
||||
} mfxExtVppAuxData;
|
||||
|
||||
typedef struct {
|
||||
mfxU32 reserved[4];
|
||||
mfxU8 *Data; /* buffer pointer */
|
||||
mfxU32 NumBit; /* number of bits */
|
||||
mfxU16 Type; /* SEI message type in H.264 or user data start_code in MPEG-2 */
|
||||
mfxU16 BufSize; /* payload buffer size in bytes */
|
||||
} mfxPayload;
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
mfxU32 reserved[5];
|
||||
mfxU16 reserved1;
|
||||
|
||||
mfxU16 QP; /* per frame QP */
|
||||
|
||||
mfxU16 FrameType;
|
||||
mfxU16 NumExtParam;
|
||||
mfxU16 NumPayload; /* MPEG-2 user data or H.264 SEI message(s) */
|
||||
mfxU16 reserved2;
|
||||
|
||||
mfxExtBuffer **ExtParam;
|
||||
mfxPayload **Payload; /* for field pair, first field uses even payloads and second field uses odd payloads */
|
||||
} mfxEncodeCtrl;
|
||||
|
||||
/* Buffer Memory Types */
|
||||
enum {
|
||||
/* Buffer types */
|
||||
MFX_MEMTYPE_PERSISTENT_MEMORY =0x0002
|
||||
};
|
||||
|
||||
/* Frame Memory Types */
|
||||
#define MFX_MEMTYPE_BASE(x) (0xf0ff & (x))
|
||||
|
||||
enum {
|
||||
MFX_MEMTYPE_DXVA2_DECODER_TARGET =0x0010,
|
||||
MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET =0x0020,
|
||||
MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET = MFX_MEMTYPE_DXVA2_DECODER_TARGET,
|
||||
MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET = MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET,
|
||||
MFX_MEMTYPE_SYSTEM_MEMORY =0x0040,
|
||||
|
||||
MFX_MEMTYPE_FROM_ENCODE = 0x0100,
|
||||
MFX_MEMTYPE_FROM_DECODE = 0x0200,
|
||||
MFX_MEMTYPE_FROM_VPPIN = 0x0400,
|
||||
MFX_MEMTYPE_FROM_VPPOUT = 0x0800,
|
||||
|
||||
MFX_MEMTYPE_INTERNAL_FRAME = 0x0001,
|
||||
MFX_MEMTYPE_EXTERNAL_FRAME = 0x0002,
|
||||
MFX_MEMTYPE_OPAQUE_FRAME = 0x0004
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
mfxU32 reserved[4];
|
||||
mfxFrameInfo Info;
|
||||
mfxU16 Type; /* decoder or processor render targets */
|
||||
mfxU16 NumFrameMin;
|
||||
mfxU16 NumFrameSuggested;
|
||||
mfxU16 reserved2;
|
||||
} mfxFrameAllocRequest;
|
||||
|
||||
typedef struct {
|
||||
mfxU32 reserved[4];
|
||||
mfxMemId *mids; /* the array allocated by application */
|
||||
mfxU16 NumFrameActual;
|
||||
mfxU16 reserved2;
|
||||
} mfxFrameAllocResponse;
|
||||
|
||||
/* FrameType */
|
||||
enum {
|
||||
MFX_FRAMETYPE_UNKNOWN =0x0000,
|
||||
|
||||
MFX_FRAMETYPE_I =0x0001,
|
||||
MFX_FRAMETYPE_P =0x0002,
|
||||
MFX_FRAMETYPE_B =0x0004,
|
||||
MFX_FRAMETYPE_S =0x0008,
|
||||
|
||||
MFX_FRAMETYPE_REF =0x0040,
|
||||
MFX_FRAMETYPE_IDR =0x0080,
|
||||
|
||||
MFX_FRAMETYPE_xI =0x0100,
|
||||
MFX_FRAMETYPE_xP =0x0200,
|
||||
MFX_FRAMETYPE_xB =0x0400,
|
||||
MFX_FRAMETYPE_xS =0x0800,
|
||||
|
||||
MFX_FRAMETYPE_xREF =0x4000,
|
||||
MFX_FRAMETYPE_xIDR =0x8000
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
MFX_HANDLE_DIRECT3D_DEVICE_MANAGER9 =1, /* IDirect3DDeviceManager9 */
|
||||
MFX_HANDLE_D3D9_DEVICE_MANAGER = MFX_HANDLE_DIRECT3D_DEVICE_MANAGER9,
|
||||
MFX_HANDLE_D3D11_DEVICE_AND_CONTEXT = 2
|
||||
} mfxHandleType;
|
||||
|
||||
typedef enum {
|
||||
MFX_SKIPMODE_NOSKIP=0,
|
||||
MFX_SKIPMODE_MORE=1,
|
||||
MFX_SKIPMODE_LESS=2
|
||||
} mfxSkipMode;
|
||||
|
||||
/* Library initialization and deinitialization */
|
||||
typedef mfxI32 mfxIMPL;
|
||||
#define MFX_IMPL_BASETYPE(x) (0x00ff & (x))
|
||||
|
||||
enum {
|
||||
MFX_IMPL_AUTO = 0x0000, /* Auto Selection/In or Not Supported/Out */
|
||||
MFX_IMPL_SOFTWARE = 0x0001, /* Pure Software Implementation */
|
||||
MFX_IMPL_HARDWARE = 0x0002, /* Hardware Accelerated Implementation (default device) */
|
||||
MFX_IMPL_AUTO_ANY = 0x0003, /* Auto selection of any hardware/software implementation */
|
||||
MFX_IMPL_HARDWARE_ANY = 0x0004, /* Auto selection of any hardware implementation */
|
||||
MFX_IMPL_HARDWARE2 = 0x0005, /* Hardware accelerated implementation (2nd device) */
|
||||
MFX_IMPL_HARDWARE3 = 0x0006, /* Hardware accelerated implementation (3rd device) */
|
||||
MFX_IMPL_HARDWARE4 = 0x0007, /* Hardware accelerated implementation (4th device) */
|
||||
|
||||
MFX_IMPL_VIA_ANY = 0x0100,
|
||||
MFX_IMPL_VIA_D3D9 = 0x0200,
|
||||
MFX_IMPL_VIA_D3D11 = 0x0300,
|
||||
|
||||
MFX_IMPL_UNSUPPORTED = 0x0000 /* One of the MFXQueryIMPL returns */
|
||||
};
|
||||
|
||||
/* Version Info */
|
||||
typedef union {
|
||||
struct {
|
||||
mfxU16 Minor;
|
||||
mfxU16 Major;
|
||||
};
|
||||
mfxU32 Version;
|
||||
} mfxVersion;
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
mfxU8 *SPSBuffer;
|
||||
mfxU8 *PPSBuffer;
|
||||
mfxU16 SPSBufSize;
|
||||
mfxU16 PPSBufSize;
|
||||
mfxU16 SPSId;
|
||||
mfxU16 PPSId;
|
||||
} mfxExtCodingOptionSPSPPS;
|
||||
|
||||
/* session priority */
|
||||
typedef enum
|
||||
{
|
||||
MFX_PRIORITY_LOW = 0,
|
||||
MFX_PRIORITY_NORMAL = 1,
|
||||
MFX_PRIORITY_HIGH = 2
|
||||
|
||||
} mfxPriority;
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
mfxU16 VideoFormat;
|
||||
mfxU16 VideoFullRange;
|
||||
mfxU16 ColourDescriptionPresent;
|
||||
mfxU16 ColourPrimaries;
|
||||
mfxU16 TransferCharacteristics;
|
||||
mfxU16 MatrixCoefficients;
|
||||
} mfxExtVideoSignalInfo;
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
mfxU32 NumAlg;
|
||||
mfxU32 *AlgList;
|
||||
} mfxExtVPPDoUse;
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
mfxU32 reserved1[2];
|
||||
struct {
|
||||
mfxFrameSurface1 **Surfaces;
|
||||
mfxU32 reserved2[5];
|
||||
mfxU16 Type;
|
||||
mfxU16 NumSurface;
|
||||
} In, Out;
|
||||
} mfxExtOpaqueSurfaceAlloc;
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
mfxU16 NumRefIdxL0Active;
|
||||
mfxU16 NumRefIdxL1Active;
|
||||
|
||||
struct {
|
||||
mfxU32 FrameOrder;
|
||||
mfxU16 PicStruct;
|
||||
mfxU16 ViewId;
|
||||
mfxU32 reserved[2];
|
||||
} PreferredRefList[32], RejectedRefList[16], LongTermRefList[16];
|
||||
|
||||
mfxU32 reserved[8];
|
||||
} mfxExtAVCRefListCtrl;
|
||||
|
||||
enum {
|
||||
MFX_FRCALGM_PRESERVE_TIMESTAMP = 1,
|
||||
MFX_FRCALGM_DISTRIBUTED_TIMESTAMP = 2
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
mfxU16 Algorithm;
|
||||
mfxU16 reserved;
|
||||
mfxU32 reserved2[15];
|
||||
} mfxExtVPPFrameRateConversion;
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
mfxU32 reserved[14];
|
||||
|
||||
struct {
|
||||
mfxU16 ClockTimestampFlag;
|
||||
mfxU16 CtType;
|
||||
mfxU16 NuitFieldBasedFlag;
|
||||
mfxU16 CountingType;
|
||||
mfxU16 FullTimestampFlag;
|
||||
mfxU16 DiscontinuityFlag;
|
||||
mfxU16 CntDroppedFlag;
|
||||
mfxU16 NFrames;
|
||||
mfxU16 SecondsFlag;
|
||||
mfxU16 MinutesFlag;
|
||||
mfxU16 HoursFlag;
|
||||
mfxU16 SecondsValue;
|
||||
mfxU16 MinutesValue;
|
||||
mfxU16 HoursValue;
|
||||
mfxU32 TimeOffset;
|
||||
} TimeStamp[3];
|
||||
} mfxExtPictureTimingSEI;
|
||||
|
||||
typedef struct {
|
||||
mfxExtBuffer Header;
|
||||
mfxU32 reserved1[4];
|
||||
mfxU16 reserved2;
|
||||
mfxU16 BaseLayerPID;
|
||||
|
||||
struct {
|
||||
mfxU16 Scale;
|
||||
mfxU16 reserved[3];
|
||||
}Layer[8];
|
||||
} mfxExtAvcTemporalLayers;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
/* ****************************************************************************** *\
|
||||
|
||||
INTEL CORPORATION PROPRIETARY INFORMATION
|
||||
This software is supplied under the terms of a license agreement or nondisclosure
|
||||
agreement with Intel Corporation and may not be copied or disclosed except in
|
||||
accordance with the terms of that agreement
|
||||
Copyright(c) 2007-2010 Intel Corporation. All Rights Reserved.
|
||||
|
||||
|
||||
File Name: mfxvideo++.h
|
||||
|
||||
\* ****************************************************************************** */
|
||||
|
||||
#ifndef __MFXVIDEOPLUSPLUS_H
|
||||
#define __MFXVIDEOPLUSPLUS_H
|
||||
|
||||
#include "mfxvideo.h"
|
||||
|
||||
class MFXVideoSession
|
||||
{
|
||||
public:
|
||||
MFXVideoSession(void) { m_session = (mfxSession) 0; }
|
||||
virtual ~MFXVideoSession(void) { Close(); }
|
||||
|
||||
mfxStatus Init(mfxIMPL impl, mfxVersion *ver) { return MFXInit(impl, ver, &m_session); }
|
||||
mfxStatus Close(void)
|
||||
{
|
||||
mfxStatus mfxRes;
|
||||
mfxRes = MFXClose(m_session); m_session = (mfxSession) 0;
|
||||
return mfxRes;
|
||||
}
|
||||
|
||||
mfxStatus QueryIMPL(mfxIMPL *impl) { return MFXQueryIMPL(m_session, impl); }
|
||||
mfxStatus QueryVersion(mfxVersion *version) { return MFXQueryVersion(m_session, version); }
|
||||
|
||||
mfxStatus JoinSession(mfxSession child_session) { return MFXJoinSession(m_session, child_session);}
|
||||
mfxStatus DisjoinSession( ) { return MFXDisjoinSession(m_session);}
|
||||
mfxStatus CloneSession( mfxSession *clone) { return MFXCloneSession(m_session, clone);}
|
||||
mfxStatus SetPriority( mfxPriority priority) { return MFXSetPriority(m_session, priority);}
|
||||
mfxStatus GetPriority( mfxPriority *priority) { return MFXGetPriority(m_session, priority);}
|
||||
|
||||
mfxStatus SetBufferAllocator(mfxBufferAllocator *allocator) { return MFXVideoCORE_SetBufferAllocator(m_session, allocator); }
|
||||
mfxStatus SetFrameAllocator(mfxFrameAllocator *allocator) { return MFXVideoCORE_SetFrameAllocator(m_session, allocator); }
|
||||
mfxStatus SetHandle(mfxHandleType type, mfxHDL hdl) { return MFXVideoCORE_SetHandle(m_session, type, hdl); }
|
||||
mfxStatus GetHandle(mfxHandleType type, mfxHDL *hdl) { return MFXVideoCORE_GetHandle(m_session, type, hdl); }
|
||||
|
||||
mfxStatus SyncOperation(mfxSyncPoint syncp, mfxU32 wait) { return MFXVideoCORE_SyncOperation(m_session, syncp, wait); }
|
||||
|
||||
operator mfxSession (void) { return m_session; }
|
||||
|
||||
protected:
|
||||
|
||||
mfxSession m_session; // (mfxSession) handle to the owning session
|
||||
};
|
||||
|
||||
class MFXVideoENCODE
|
||||
{
|
||||
public:
|
||||
|
||||
MFXVideoENCODE(mfxSession session) { m_session = session; }
|
||||
virtual ~MFXVideoENCODE(void) { Close(); }
|
||||
|
||||
mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) { return MFXVideoENCODE_Query(m_session, in, out); }
|
||||
mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) { return MFXVideoENCODE_QueryIOSurf(m_session, par, request); }
|
||||
mfxStatus Init(mfxVideoParam *par) { return MFXVideoENCODE_Init(m_session, par); }
|
||||
mfxStatus Reset(mfxVideoParam *par) { return MFXVideoENCODE_Reset(m_session, par); }
|
||||
mfxStatus Close(void) { return MFXVideoENCODE_Close(m_session); }
|
||||
|
||||
mfxStatus GetVideoParam(mfxVideoParam *par) { return MFXVideoENCODE_GetVideoParam(m_session, par); }
|
||||
mfxStatus GetEncodeStat(mfxEncodeStat *stat) { return MFXVideoENCODE_GetEncodeStat(m_session, stat); }
|
||||
|
||||
mfxStatus EncodeFrameAsync(mfxEncodeCtrl *ctrl, mfxFrameSurface1 *surface, mfxBitstream *bs, mfxSyncPoint *syncp) { return MFXVideoENCODE_EncodeFrameAsync(m_session, ctrl, surface, bs, syncp); }
|
||||
|
||||
protected:
|
||||
|
||||
mfxSession m_session; // (mfxSession) handle to the owning session
|
||||
};
|
||||
|
||||
class MFXVideoDECODE
|
||||
{
|
||||
public:
|
||||
|
||||
MFXVideoDECODE(mfxSession session) { m_session = session; }
|
||||
virtual ~MFXVideoDECODE(void) { Close(); }
|
||||
|
||||
mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) { return MFXVideoDECODE_Query(m_session, in, out); }
|
||||
mfxStatus DecodeHeader(mfxBitstream *bs, mfxVideoParam *par) { return MFXVideoDECODE_DecodeHeader(m_session, bs, par); }
|
||||
mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) { return MFXVideoDECODE_QueryIOSurf(m_session, par, request); }
|
||||
mfxStatus Init(mfxVideoParam *par) { return MFXVideoDECODE_Init(m_session, par); }
|
||||
mfxStatus Reset(mfxVideoParam *par) { return MFXVideoDECODE_Reset(m_session, par); }
|
||||
mfxStatus Close(void) { return MFXVideoDECODE_Close(m_session); }
|
||||
|
||||
mfxStatus GetVideoParam(mfxVideoParam *par) { return MFXVideoDECODE_GetVideoParam(m_session, par); }
|
||||
|
||||
mfxStatus GetDecodeStat(mfxDecodeStat *stat) { return MFXVideoDECODE_GetDecodeStat(m_session, stat); }
|
||||
mfxStatus GetPayload(mfxU64 *ts, mfxPayload *payload) {return MFXVideoDECODE_GetPayload(m_session, ts, payload); }
|
||||
mfxStatus SetSkipMode(mfxSkipMode mode) { return MFXVideoDECODE_SetSkipMode(m_session, mode); }
|
||||
mfxStatus DecodeFrameAsync(mfxBitstream *bs, mfxFrameSurface1 *surface_work, mfxFrameSurface1 **surface_out, mfxSyncPoint *syncp) { return MFXVideoDECODE_DecodeFrameAsync(m_session, bs, surface_work, surface_out, syncp); }
|
||||
|
||||
protected:
|
||||
|
||||
mfxSession m_session; // (mfxSession) handle to the owning session
|
||||
};
|
||||
|
||||
class MFXVideoVPP
|
||||
{
|
||||
public:
|
||||
|
||||
MFXVideoVPP(mfxSession session) { m_session = session; }
|
||||
virtual ~MFXVideoVPP(void) { Close(); }
|
||||
|
||||
mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) { return MFXVideoVPP_Query(m_session, in, out); }
|
||||
mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest request[2]) { return MFXVideoVPP_QueryIOSurf(m_session, par, request); }
|
||||
mfxStatus Init(mfxVideoParam *par) { return MFXVideoVPP_Init(m_session, par); }
|
||||
mfxStatus Reset(mfxVideoParam *par) { return MFXVideoVPP_Reset(m_session, par); }
|
||||
mfxStatus Close(void) { return MFXVideoVPP_Close(m_session); }
|
||||
|
||||
mfxStatus GetVideoParam(mfxVideoParam *par) { return MFXVideoVPP_GetVideoParam(m_session, par); }
|
||||
mfxStatus GetVPPStat(mfxVPPStat *stat) { return MFXVideoVPP_GetVPPStat(m_session, stat); }
|
||||
mfxStatus RunFrameVPPAsync(mfxFrameSurface1 *in, mfxFrameSurface1 *out, mfxExtVppAuxData *aux, mfxSyncPoint *syncp) { return MFXVideoVPP_RunFrameVPPAsync(m_session, in, out, aux, syncp); }
|
||||
|
||||
protected:
|
||||
|
||||
mfxSession m_session; // (mfxSession) handle to the owning session
|
||||
};
|
||||
|
||||
#endif // __MFXVIDEOPLUSPLUS_H
|
|
@ -0,0 +1,117 @@
|
|||
/* ****************************************************************************** *\
|
||||
|
||||
INTEL CORPORATION PROPRIETARY INFORMATION
|
||||
This software is supplied under the terms of a license agreement or nondisclosure
|
||||
agreement with Intel Corporation and may not be copied or disclosed except in
|
||||
accordance with the terms of that agreement
|
||||
Copyright(c) 2007-2011 Intel Corporation. All Rights Reserved.
|
||||
|
||||
File Name: mfxvideo.h
|
||||
|
||||
\* ****************************************************************************** */
|
||||
#ifndef __MFXVIDEO_H__
|
||||
#define __MFXVIDEO_H__
|
||||
#include "mfxstructures.h"
|
||||
|
||||
/* This is the external include file for the Intel(R) Media Sofware Development Kit product */
|
||||
#define MFX_VERSION_MAJOR 1
|
||||
#define MFX_VERSION_MINOR 3
|
||||
|
||||
#ifdef _WIN32
|
||||
#define MFX_CDECL __cdecl
|
||||
#define MFX_STDCALL __stdcall
|
||||
#else
|
||||
#define MFX_CDECL
|
||||
#define MFX_STDCALL
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* MFXVideoCORE */
|
||||
typedef struct {
|
||||
mfxU32 reserved[4];
|
||||
mfxHDL pthis;
|
||||
mfxStatus (MFX_CDECL *Alloc) (mfxHDL pthis, mfxU32 nbytes, mfxU16 type, mfxMemId *mid);
|
||||
mfxStatus (MFX_CDECL *Lock) (mfxHDL pthis, mfxMemId mid, mfxU8 **ptr);
|
||||
mfxStatus (MFX_CDECL *Unlock) (mfxHDL pthis, mfxMemId mid);
|
||||
mfxStatus (MFX_CDECL *Free) (mfxHDL pthis, mfxMemId mid);
|
||||
} mfxBufferAllocator;
|
||||
|
||||
typedef struct {
|
||||
mfxU32 reserved[4];
|
||||
mfxHDL pthis;
|
||||
|
||||
mfxStatus (MFX_CDECL *Alloc) (mfxHDL pthis, mfxFrameAllocRequest *request, mfxFrameAllocResponse *response);
|
||||
mfxStatus (MFX_CDECL *Lock) (mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr);
|
||||
mfxStatus (MFX_CDECL *Unlock) (mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr);
|
||||
mfxStatus (MFX_CDECL *GetHDL) (mfxHDL pthis, mfxMemId mid, mfxHDL *handle);
|
||||
mfxStatus (MFX_CDECL *Free) (mfxHDL pthis, mfxFrameAllocResponse *response);
|
||||
} mfxFrameAllocator;
|
||||
|
||||
/* Global Functions */
|
||||
typedef struct _mfxSession *mfxSession;
|
||||
mfxStatus MFX_CDECL MFXInit(mfxIMPL impl, mfxVersion *ver, mfxSession *session);
|
||||
mfxStatus MFX_CDECL MFXClose(mfxSession session);
|
||||
|
||||
mfxStatus MFX_CDECL MFXQueryIMPL(mfxSession session, mfxIMPL *impl);
|
||||
mfxStatus MFX_CDECL MFXQueryVersion(mfxSession session, mfxVersion *version);
|
||||
|
||||
mfxStatus MFX_CDECL MFXJoinSession(mfxSession session, mfxSession child);
|
||||
mfxStatus MFX_CDECL MFXDisjoinSession(mfxSession session);
|
||||
mfxStatus MFX_CDECL MFXCloneSession(mfxSession session, mfxSession *clone);
|
||||
mfxStatus MFX_CDECL MFXSetPriority(mfxSession session, mfxPriority priority);
|
||||
mfxStatus MFX_CDECL MFXGetPriority(mfxSession session, mfxPriority *priority);
|
||||
|
||||
/* VideoCORE */
|
||||
mfxStatus MFX_CDECL MFXVideoCORE_SetBufferAllocator(mfxSession session, mfxBufferAllocator *allocator);
|
||||
mfxStatus MFX_CDECL MFXVideoCORE_SetFrameAllocator(mfxSession session, mfxFrameAllocator *allocator);
|
||||
mfxStatus MFX_CDECL MFXVideoCORE_SetHandle(mfxSession session, mfxHandleType type, mfxHDL hdl);
|
||||
mfxStatus MFX_CDECL MFXVideoCORE_GetHandle(mfxSession session, mfxHandleType type, mfxHDL *hdl);
|
||||
|
||||
typedef struct _mfxSyncPoint *mfxSyncPoint;
|
||||
mfxStatus MFX_CDECL MFXVideoCORE_SyncOperation(mfxSession session, mfxSyncPoint syncp, mfxU32 wait);
|
||||
|
||||
/* VideoENCODE */
|
||||
mfxStatus MFX_CDECL MFXVideoENCODE_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out);
|
||||
mfxStatus MFX_CDECL MFXVideoENCODE_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request);
|
||||
mfxStatus MFX_CDECL MFXVideoENCODE_Init(mfxSession session, mfxVideoParam *par);
|
||||
mfxStatus MFX_CDECL MFXVideoENCODE_Reset(mfxSession session, mfxVideoParam *par);
|
||||
mfxStatus MFX_CDECL MFXVideoENCODE_Close(mfxSession session);
|
||||
|
||||
mfxStatus MFX_CDECL MFXVideoENCODE_GetVideoParam(mfxSession session, mfxVideoParam *par);
|
||||
mfxStatus MFX_CDECL MFXVideoENCODE_GetEncodeStat(mfxSession session, mfxEncodeStat *stat);
|
||||
mfxStatus MFX_CDECL MFXVideoENCODE_EncodeFrameAsync(mfxSession session, mfxEncodeCtrl *ctrl, mfxFrameSurface1 *surface, mfxBitstream *bs, mfxSyncPoint *syncp);
|
||||
|
||||
/* VideoDECODE */
|
||||
mfxStatus MFX_CDECL MFXVideoDECODE_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out);
|
||||
mfxStatus MFX_CDECL MFXVideoDECODE_DecodeHeader(mfxSession session, mfxBitstream *bs, mfxVideoParam *par);
|
||||
mfxStatus MFX_CDECL MFXVideoDECODE_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request);
|
||||
mfxStatus MFX_CDECL MFXVideoDECODE_Init(mfxSession session, mfxVideoParam *par);
|
||||
mfxStatus MFX_CDECL MFXVideoDECODE_Reset(mfxSession session, mfxVideoParam *par);
|
||||
mfxStatus MFX_CDECL MFXVideoDECODE_Close(mfxSession session);
|
||||
|
||||
mfxStatus MFX_CDECL MFXVideoDECODE_GetVideoParam(mfxSession session, mfxVideoParam *par);
|
||||
mfxStatus MFX_CDECL MFXVideoDECODE_GetDecodeStat(mfxSession session, mfxDecodeStat *stat);
|
||||
mfxStatus MFX_CDECL MFXVideoDECODE_SetSkipMode(mfxSession session, mfxSkipMode mode);
|
||||
mfxStatus MFX_CDECL MFXVideoDECODE_GetPayload(mfxSession session, mfxU64 *ts, mfxPayload *payload);
|
||||
mfxStatus MFX_CDECL MFXVideoDECODE_DecodeFrameAsync(mfxSession session, mfxBitstream *bs, mfxFrameSurface1 *surface_work, mfxFrameSurface1 **surface_out, mfxSyncPoint *syncp);
|
||||
|
||||
/* VideoVPP */
|
||||
mfxStatus MFX_CDECL MFXVideoVPP_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out);
|
||||
mfxStatus MFX_CDECL MFXVideoVPP_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest request[2]);
|
||||
mfxStatus MFX_CDECL MFXVideoVPP_Init(mfxSession session, mfxVideoParam *par);
|
||||
mfxStatus MFX_CDECL MFXVideoVPP_Reset(mfxSession session, mfxVideoParam *par);
|
||||
mfxStatus MFX_CDECL MFXVideoVPP_Close(mfxSession session);
|
||||
|
||||
mfxStatus MFX_CDECL MFXVideoVPP_GetVideoParam(mfxSession session, mfxVideoParam *par);
|
||||
mfxStatus MFX_CDECL MFXVideoVPP_GetVPPStat(mfxSession session, mfxVPPStat *stat);
|
||||
mfxStatus MFX_CDECL MFXVideoVPP_RunFrameVPPAsync(mfxSession session, mfxFrameSurface1 *in, mfxFrameSurface1 *out, mfxExtVppAuxData *aux, mfxSyncPoint *syncp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,965 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "IQuickSyncDecoder.h"
|
||||
#include "QuickSync_defs.h"
|
||||
#include "CodecInfo.h"
|
||||
#include "TimeManager.h"
|
||||
#include "QuickSyncDecoder.h"
|
||||
#include "frame_constructors.h"
|
||||
#include "QuickSyncUtils.h"
|
||||
#include "QuickSync.h"
|
||||
|
||||
#define MEMCPY gpu_memcpy
|
||||
//#define MEMCPY memcpy
|
||||
#define PAGE_MASK 4095
|
||||
|
||||
EXTERN_GUID(WMMEDIASUBTYPE_WVC1,
|
||||
0x31435657, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
EXTERN_GUID(WMMEDIASUBTYPE_WMV3,
|
||||
0x33564D57, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71);
|
||||
|
||||
DEFINE_GUID(WMMEDIASUBTYPE_WVC1_PDVD,
|
||||
0xD979F77B, 0xDBEA, 0x4BF6, 0x9E, 0x6D, 0x1D, 0x7E, 0x57, 0xFB, 0xAD, 0x53);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// CQuickSync
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CQuickSync::CQuickSync() :
|
||||
m_nPitch(0),
|
||||
m_pFrameConstructor(NULL),
|
||||
m_OutputBuffer(NULL),
|
||||
m_OutputBufferSize(0),
|
||||
m_nSegmentFrameCount(0),
|
||||
m_bForceOutput(false),
|
||||
m_bDvdDecoding(false),
|
||||
m_bFlushing(false),
|
||||
m_bNeedToFlush(false)
|
||||
{
|
||||
MSDK_TRACE("QSDcoder: Constructor\n");
|
||||
|
||||
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
m_pDecoder = new CQuickSyncDecoder(sts);
|
||||
|
||||
MSDK_ZERO_VAR(m_mfxParamsVideo);
|
||||
//m_mfxParamsVideo.AsyncDepth = 1; //causes issues when 1
|
||||
m_mfxParamsVideo.mfx.ExtendedPicStruct = 1;
|
||||
// m_mfxParamsVideo.mfx.TimeStampCalc = MFX_TIMESTAMPCALC_TELECINE;
|
||||
m_Config.dwOutputQueueLength = 8;
|
||||
|
||||
m_OK = (sts == MFX_ERR_NONE);
|
||||
}
|
||||
|
||||
CQuickSync::~CQuickSync()
|
||||
{
|
||||
MSDK_TRACE("QSDcoder: Destructor\n");
|
||||
|
||||
CQsAutoLock cObjectLock(&m_csLock);
|
||||
|
||||
MSDK_SAFE_DELETE(m_pFrameConstructor);
|
||||
MSDK_SAFE_DELETE(m_pDecoder);
|
||||
_aligned_free(m_OutputBuffer);
|
||||
}
|
||||
|
||||
HRESULT CQuickSync::HandleSubType(const GUID& subType, FOURCC fourCC)
|
||||
{
|
||||
MSDK_SAFE_DELETE(m_pFrameConstructor);
|
||||
|
||||
//MPEG2
|
||||
if (subType == MEDIASUBTYPE_MPEG2_VIDEO)//(fourCC == FOURCC_mpg2) || (fourCC == FOURCC_MPG2))
|
||||
{
|
||||
m_mfxParamsVideo.mfx.CodecId = MFX_CODEC_MPEG2;
|
||||
m_pFrameConstructor = new CFrameConstructor;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//VC1
|
||||
if ((fourCC == FOURCC_VC1) || (fourCC == FOURCC_WMV3))
|
||||
{
|
||||
m_mfxParamsVideo.mfx.CodecId = MFX_CODEC_VC1;
|
||||
|
||||
if (subType == WMMEDIASUBTYPE_WMV3)
|
||||
{
|
||||
m_mfxParamsVideo.mfx.CodecProfile = MFX_PROFILE_VC1_SIMPLE;
|
||||
}
|
||||
else if (fourCC == FOURCC_VC1)
|
||||
{
|
||||
m_mfxParamsVideo.mfx.CodecProfile = MFX_PROFILE_VC1_ADVANCED;
|
||||
}
|
||||
else
|
||||
{
|
||||
return VFW_E_INVALIDMEDIATYPE;
|
||||
}
|
||||
|
||||
m_pFrameConstructor = new CVC1FrameConstructor();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// H264
|
||||
if ((fourCC == FOURCC_H264) || (fourCC == FOURCC_X264) || (fourCC == FOURCC_h264) ||
|
||||
(fourCC == FOURCC_avc1) || (fourCC == FOURCC_VSSH) || (fourCC == FOURCC_DAVC) ||
|
||||
(fourCC == FOURCC_PAVC) || (fourCC == FOURCC_AVC1))
|
||||
{
|
||||
m_mfxParamsVideo.mfx.CodecId = MFX_CODEC_AVC;
|
||||
|
||||
m_pFrameConstructor = ((fourCC == FOURCC_avc1) || (fourCC == FOURCC_AVC1)) ?
|
||||
new CAVCFrameConstructor :
|
||||
new CFrameConstructor;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
HRESULT CQuickSync::TestMediaType(const AM_MEDIA_TYPE* mtIn, FOURCC fourCC)
|
||||
{
|
||||
MSDK_TRACE("QSDcoder: TestMediaType\n");
|
||||
if (!m_OK)
|
||||
return E_FAIL;
|
||||
|
||||
|
||||
return S_OK;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
CQsAutoLock cObjectLock(&m_csLock);
|
||||
|
||||
// Parameter check
|
||||
MSDK_CHECK_POINTER(mtIn, E_POINTER);
|
||||
MSDK_CHECK_POINTER(mtIn->pbFormat, E_UNEXPECTED);
|
||||
|
||||
if (!(mtIn->majortype == MEDIATYPE_DVD_ENCRYPTED_PACK || mtIn->majortype == MEDIATYPE_Video))
|
||||
return VFW_E_INVALIDMEDIATYPE;
|
||||
|
||||
HRESULT hr;
|
||||
VIDEOINFOHEADER2* vih2 = NULL;
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
const GUID& subType = mtIn->subtype;
|
||||
hr = HandleSubType(subType, fourCC);
|
||||
MSDK_CHECK_RESULT_P_RET(hr, S_OK);
|
||||
const GUID& guidFormat = mtIn->formattype;
|
||||
|
||||
size_t nSampleSize, nVideoInfoSize;
|
||||
hr = CopyMediaTypeToVIDEOINFOHEADER2(mtIn, vih2, nVideoInfoSize, nSampleSize);
|
||||
MSDK_CHECK_RESULT_P_RET(hr, S_OK);
|
||||
|
||||
mfxVideoParam videoParams;
|
||||
MSDK_ZERO_VAR(videoParams);
|
||||
mfxInfoMFX& mfx = m_mfxParamsVideo.mfx;
|
||||
|
||||
// check if codec profile and level are supported before calling DecodeHeader
|
||||
if (FORMAT_MPEG2_VIDEO == guidFormat)
|
||||
{
|
||||
MPEG2VIDEOINFO* mp2 = (MPEG2VIDEOINFO*)(mtIn->pbFormat);
|
||||
hr = CheckCodecProfileSupport(mfx.CodecId, mp2->dwProfile, mp2->dwLevel);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
MSDK_TRACE("QSDcoder::InitDecoder - failed due to unsupported codec (%s), profile (%s), level (%i) combination\n",
|
||||
GetCodecName(mfx.CodecId), GetProfileName(mfx.CodecId, mp2->dwProfile), mp2->dwLevel);
|
||||
sts = MFX_ERR_UNSUPPORTED;
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
{
|
||||
MSDK_TRACE("QSDcoder::InitDecoder - codec (%s), profile (%s), level (%i)\n",
|
||||
GetCodecName(mfx.CodecId), GetProfileName(mfx.CodecId, mp2->dwProfile), mp2->dwLevel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
done:
|
||||
delete[] (mfxU8*)vih2;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CQuickSync::CopyMediaTypeToVIDEOINFOHEADER2(const AM_MEDIA_TYPE* mtIn, VIDEOINFOHEADER2*& vih2, size_t& nVideoInfoSize, size_t& nSampleSize)
|
||||
{
|
||||
vih2 = NULL;
|
||||
const GUID& guidFormat = mtIn->formattype;
|
||||
nVideoInfoSize = sizeof(VIDEOINFOHEADER2);
|
||||
|
||||
if (FORMAT_VideoInfo2 == guidFormat || FORMAT_MPEG2_VIDEO == guidFormat)
|
||||
{
|
||||
if (FORMAT_MPEG2_VIDEO == guidFormat)
|
||||
{
|
||||
nVideoInfoSize = sizeof(MPEG2VIDEOINFO);
|
||||
}
|
||||
|
||||
nSampleSize = mtIn->cbFormat;
|
||||
vih2 = (VIDEOINFOHEADER2*) new mfxU8[nSampleSize];
|
||||
|
||||
// copy the sample as is
|
||||
memcpy(vih2, mtIn->pbFormat, nSampleSize);
|
||||
}
|
||||
// translate VIDEOINFOHEADER to VIDEOINFOHEADER2 (easier to work with down the road)
|
||||
else if (FORMAT_VideoInfo == guidFormat)
|
||||
{
|
||||
size_t extraDataLen = mtIn->cbFormat - sizeof(VIDEOINFOHEADER);
|
||||
nSampleSize = sizeof(VIDEOINFOHEADER2) + extraDataLen;
|
||||
vih2 = (VIDEOINFOHEADER2*) new mfxU8[nSampleSize];
|
||||
MSDK_ZERO_MEMORY(vih2, sizeof(VIDEOINFOHEADER2));
|
||||
|
||||
// initialize the VIDEOINFOHEADER2 structure
|
||||
VIDEOINFOHEADER* pvi = (VIDEOINFOHEADER*)(mtIn->pbFormat);
|
||||
vih2->rcSource = pvi->rcSource;
|
||||
vih2->rcTarget = pvi->rcTarget;
|
||||
vih2->dwBitRate = pvi->dwBitRate;
|
||||
vih2->dwBitErrorRate = pvi->dwBitErrorRate;
|
||||
vih2->bmiHeader = pvi->bmiHeader;
|
||||
vih2->AvgTimePerFrame = pvi->AvgTimePerFrame;
|
||||
vih2->dwPictAspectRatioX = pvi->bmiHeader.biWidth;
|
||||
vih2->dwPictAspectRatioY = pvi->bmiHeader.biHeight;
|
||||
|
||||
// copy the out of band data (data past the VIDEOINFOHEADER structure.
|
||||
// Note: copy past the size of vih2
|
||||
if (extraDataLen)
|
||||
{
|
||||
memcpy(((mfxU8*)vih2) + nVideoInfoSize, mtIn->pbFormat + sizeof(VIDEOINFOHEADER), extraDataLen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return VFW_E_INVALIDMEDIATYPE;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CQuickSync::InitDecoder(const AM_MEDIA_TYPE* mtIn, FOURCC fourCC)
|
||||
|
||||
{
|
||||
MSDK_TRACE("QSDcoder: InitDecoder\n");
|
||||
|
||||
CQsAutoLock cObjectLock(&m_csLock);
|
||||
|
||||
VIDEOINFOHEADER2* vih2 = NULL;
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
mfxInfoMFX& mfx = m_mfxParamsVideo.mfx;
|
||||
HRESULT hr;
|
||||
MSDK_CHECK_POINTER(mtIn, E_POINTER);
|
||||
MSDK_CHECK_POINTER(mtIn->pbFormat, E_UNEXPECTED);
|
||||
|
||||
if (!(mtIn->majortype == MEDIATYPE_DVD_ENCRYPTED_PACK || mtIn->majortype == MEDIATYPE_Video))
|
||||
return VFW_E_INVALIDMEDIATYPE;
|
||||
|
||||
const GUID& guidFormat = mtIn->formattype;
|
||||
const GUID& subType = mtIn->subtype;
|
||||
hr = HandleSubType(subType, fourCC);
|
||||
MSDK_CHECK_RESULT_P_RET(hr, S_OK);
|
||||
|
||||
size_t nSampleSize, nVideoInfoSize;
|
||||
hr = CopyMediaTypeToVIDEOINFOHEADER2(mtIn, vih2, nVideoInfoSize, nSampleSize);
|
||||
MSDK_CHECK_RESULT_P_RET(hr, S_OK);
|
||||
|
||||
|
||||
if (MEDIATYPE_DVD_ENCRYPTED_PACK == mtIn->majortype)
|
||||
{
|
||||
m_pFrameConstructor->SetDvdPacketStripping(true);
|
||||
m_bDvdDecoding = true;
|
||||
}
|
||||
|
||||
if (!vih2->bmiHeader.biWidth || !vih2->bmiHeader.biHeight)
|
||||
{
|
||||
return VFW_E_INVALIDMEDIATYPE;
|
||||
}
|
||||
|
||||
// check if codec profile and level are supported before calling DecodeHeader
|
||||
if (FORMAT_MPEG2_VIDEO == guidFormat)
|
||||
{
|
||||
MPEG2VIDEOINFO* mp2 = (MPEG2VIDEOINFO*)(mtIn->pbFormat);
|
||||
hr = CheckCodecProfileSupport(mfx.CodecId, mp2->dwProfile, mp2->dwLevel);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
MSDK_TRACE("QSDcoder::InitDecoder - failed due to unsupported codec (%s), profile (%s), level (%i) combination\n",
|
||||
GetCodecName(mfx.CodecId), GetProfileName(mfx.CodecId, mp2->dwProfile), mp2->dwLevel);
|
||||
sts = MFX_ERR_UNSUPPORTED;
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
{
|
||||
MSDK_TRACE("QSDcoder::InitDecoder - codec (%s), profile (%s), level (%i)\n",
|
||||
GetCodecName(mfx.CodecId), GetProfileName(mfx.CodecId, mp2->dwProfile), mp2->dwLevel);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MSDK_TRACE("QSDcoder::InitDecoder - codec (%s)\n", GetCodecName(mfx.CodecId));
|
||||
}
|
||||
|
||||
// construct sequence header and decode the sequence header.
|
||||
if (nVideoInfoSize < nSampleSize)
|
||||
{
|
||||
sts = m_pFrameConstructor->ConstructHeaders(vih2, guidFormat, nSampleSize, nVideoInfoSize);
|
||||
if (MFX_ERR_NONE == sts)
|
||||
{
|
||||
sts = m_pDecoder->DecodeHeader(&m_pFrameConstructor->GetHeaders(), &m_mfxParamsVideo);
|
||||
}
|
||||
}
|
||||
// Simple info header (without extra data) or DecodeHeader failed (usually not critical)
|
||||
else
|
||||
{
|
||||
mfx.FrameInfo.CropH = (mfxU16)MSDK_ALIGN16(vih2->bmiHeader.biHeight);
|
||||
mfx.FrameInfo.CropW = (mfxU16)MSDK_ALIGN16(vih2->bmiHeader.biWidth);
|
||||
mfx.FrameInfo.Width = mfx.FrameInfo.CropW;
|
||||
mfx.FrameInfo.Height = mfx.FrameInfo.CropH;
|
||||
mfx.FrameInfo.FourCC = MFX_FOURCC_NV12;
|
||||
mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
|
||||
ConvertFrameRate(m_TimeManager.GetFrameRate(),
|
||||
mfx.FrameInfo.FrameRateExtN,
|
||||
mfx.FrameInfo.FrameRateExtD);
|
||||
}
|
||||
|
||||
ASSERT(sts == MFX_ERR_NONE);
|
||||
|
||||
// setup frame rate from either the media type or the decoded header
|
||||
bool bIsFields = (vih2->dwInterlaceFlags & AMINTERLACE_IsInterlaced) &&
|
||||
(vih2->dwInterlaceFlags & AMINTERLACE_1FieldPerSample);
|
||||
// Try getting the frame rate from the decoded headers
|
||||
if (0 < vih2->AvgTimePerFrame)
|
||||
{
|
||||
m_TimeManager.SetFrameRate(1e7 / vih2->AvgTimePerFrame, bIsFields);
|
||||
}
|
||||
else if (mfx.FrameInfo.FrameRateExtN * mfx.FrameInfo.FrameRateExtD != 0)
|
||||
{
|
||||
double frameRate = (double)mfx.FrameInfo.FrameRateExtN / (double)mfx.FrameInfo.FrameRateExtD;
|
||||
m_TimeManager.SetFrameRate(frameRate, bIsFields);
|
||||
}
|
||||
|
||||
// we might decode well even if DecodeHeader failed with MFX_ERR_MORE_DATA
|
||||
MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA);
|
||||
|
||||
m_nPitch = mfx.FrameInfo.Width;
|
||||
|
||||
SetAspectRatio(*vih2, mfx.FrameInfo);
|
||||
|
||||
// Init Media SDK decoder
|
||||
if (sts == MFX_ERR_NONE)
|
||||
{
|
||||
m_pDecoder->SetConfig(m_Config);
|
||||
sts = m_pDecoder->Init(&m_mfxParamsVideo, m_nPitch);
|
||||
|
||||
if (sts == MFX_WRN_PARTIAL_ACCELERATION)
|
||||
{
|
||||
MSDK_TRACE("\n\n\nQSDcoder::InitDecoder - stream isn't supported by HW acceleration!\n\n\n\n");
|
||||
sts = MFX_ERR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
delete[] (mfxU8*)vih2;
|
||||
m_OK = (sts == MFX_ERR_NONE);
|
||||
return (m_OK) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
void CQuickSync::SetAspectRatio(VIDEOINFOHEADER2& vih2, mfxFrameInfo& FrameInfo)
|
||||
{
|
||||
DWORD alignedWidth = MSDK_ALIGN16(FrameInfo.CropW);
|
||||
|
||||
// fix small aspect ratio errors
|
||||
if (MSDK_ALIGN16(vih2.dwPictAspectRatioX) == alignedWidth)
|
||||
{
|
||||
vih2.dwPictAspectRatioX = alignedWidth;
|
||||
}
|
||||
|
||||
// AR is not always contained in the header (it's optional for MFX decoder initialization though)
|
||||
if (FrameInfo.AspectRatioW * FrameInfo.AspectRatioH == 0)
|
||||
{
|
||||
//convert display aspect ratio (is in VIDEOINFOHEADER2) to pixel aspect ratio (is accepted by MediaSDK components)
|
||||
mfxStatus sts = DARtoPAR(vih2.dwPictAspectRatioX, vih2.dwPictAspectRatioY,
|
||||
FrameInfo.CropW, FrameInfo.CropH,
|
||||
FrameInfo.AspectRatioW, FrameInfo.AspectRatioH);
|
||||
|
||||
if (sts != MFX_ERR_NONE)
|
||||
{
|
||||
FrameInfo.AspectRatioW = FrameInfo.AspectRatioH = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// use image size as aspect ratio when PAR is 1x1
|
||||
if (FrameInfo.AspectRatioW == FrameInfo.AspectRatioH)
|
||||
{
|
||||
m_FrameData.dwPictAspectRatioX = alignedWidth;
|
||||
m_FrameData.dwPictAspectRatioY = FrameInfo.CropH;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_FrameData.dwPictAspectRatioX = vih2.dwPictAspectRatioX;
|
||||
m_FrameData.dwPictAspectRatioY = vih2.dwPictAspectRatioY;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CQuickSync::Decode(IMediaSample* pSample)
|
||||
{
|
||||
// DEBUG
|
||||
#if 0 //def _DEBUG
|
||||
static bool isSetThreadName = false;
|
||||
if (!isSetThreadName)
|
||||
{
|
||||
isSetThreadName = true;
|
||||
SetThreadName("*** Decoder ***");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Input samples should be discarded - we are in the middle of a flush.
|
||||
if (m_bFlushing)
|
||||
return S_FALSE;
|
||||
|
||||
CQsAutoLock cObjectLock(&m_csLock);
|
||||
|
||||
MSDK_TRACE("QSDcoder: Decode\n");
|
||||
|
||||
// We haven't flushed since the last BeginFlush call - probably a DVD playback scenario
|
||||
// where NewSegment/OnSeek isn't issued.
|
||||
if (m_bNeedToFlush)
|
||||
{
|
||||
OnSeek(0);
|
||||
}
|
||||
|
||||
MSDK_CHECK_NOT_EQUAL(m_OK, true, E_UNEXPECTED);
|
||||
HRESULT hr = S_OK;
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
mfxFrameSurface1* pSurfaceOut = NULL;
|
||||
mfxBitstream mfxBS;
|
||||
MSDK_ZERO_VAR(mfxBS);
|
||||
|
||||
// Check error(s)
|
||||
if (NULL == pSample)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (0 == pSample->GetActualDataLength())
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
m_TimeManager.AddTimeStamp(pSample);
|
||||
|
||||
// Manipulate bitstream for decoder
|
||||
sts = m_pFrameConstructor->ConstructFrame(pSample, &mfxBS);
|
||||
ASSERT(mfxBS.DataLength <= mfxBS.MaxLength);
|
||||
MSDK_CHECK_ERROR(sts, MFX_ERR_MORE_DATA, S_OK); // not an error
|
||||
MSDK_CHECK_NOT_EQUAL(sts, MFX_ERR_NONE, E_FAIL);
|
||||
|
||||
// Decode mfxBitstream until all data is taken by decoder
|
||||
while (mfxBS.DataLength > 0 && !m_bNeedToFlush)
|
||||
{
|
||||
// Decode the bitstream
|
||||
sts = m_pDecoder->Decode(&mfxBS, pSurfaceOut);
|
||||
|
||||
if (MFX_ERR_NONE == sts)
|
||||
{
|
||||
DeliverSurface(pSurfaceOut);
|
||||
continue;
|
||||
}
|
||||
else if (MFX_ERR_MORE_DATA == sts)
|
||||
{
|
||||
break; // Need to receive more data from upstream filter
|
||||
}
|
||||
else if (MFX_WRN_VIDEO_PARAM_CHANGED == sts)
|
||||
{
|
||||
MSDK_TRACE("QSDcoder: Decode MFX_WRN_VIDEO_PARAM_CHANGED\n");
|
||||
|
||||
// Need to reset the analysis done so far...
|
||||
|
||||
sts = OnVideoParamsChanged();
|
||||
continue; // just continue processing
|
||||
}
|
||||
// Need another work surface
|
||||
else if (MFX_ERR_MORE_SURFACE == sts)
|
||||
{
|
||||
// Just continue, new work surface will be found in m_pDecoder->Decode
|
||||
continue;
|
||||
}
|
||||
else if (MFX_ERR_NOT_ENOUGH_BUFFER == sts)
|
||||
{
|
||||
MSDK_TRACE("QSDcoder: Decode MFX_ERR_NOT_ENOUGH_BUFFER\n");
|
||||
if (!m_pDecoder->GetOutputQueue()->empty())
|
||||
{
|
||||
FlushOutputQueue(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
MSDK_TRACE("QSDcoder: Error - ran out of work buffers!\n");
|
||||
// This is a system malfunction!
|
||||
break;
|
||||
}
|
||||
else if (MFX_ERR_INCOMPATIBLE_VIDEO_PARAM == sts)
|
||||
{
|
||||
MSDK_TRACE("QSDcoder: Decode MFX_ERR_INCOMPATIBLE_VIDEO_PARAM\n");
|
||||
|
||||
// Flush existing frames
|
||||
Flush(true);
|
||||
|
||||
// Retrieve new parameters
|
||||
mfxVideoParam VideoParams;
|
||||
MSDK_ZERO_VAR(VideoParams);
|
||||
VideoParams.mfx.CodecId = m_mfxParamsVideo.mfx.CodecId;
|
||||
sts = m_pDecoder->DecodeHeader(&mfxBS, &VideoParams);
|
||||
if (MFX_ERR_MORE_DATA == sts)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Save IOPattern and update parameters
|
||||
VideoParams.IOPattern = m_mfxParamsVideo.IOPattern;
|
||||
memcpy(&m_mfxParamsVideo, &VideoParams, sizeof(mfxVideoParam));
|
||||
m_nPitch = MSDK_ALIGN16(m_mfxParamsVideo.mfx.FrameInfo.Width);
|
||||
sts = m_pDecoder->Reset(&m_mfxParamsVideo, m_nPitch);
|
||||
if (MFX_ERR_NONE == sts)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
MSDK_TRACE("QSDcoder: Decode didn't recover from MFX_ERR_INCOMPATIBLE_VIDEO_PARAM\n");
|
||||
}
|
||||
|
||||
// The decoder has returned with an error
|
||||
hr = E_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr) && !m_bNeedToFlush)
|
||||
m_pFrameConstructor->SaveResidialData(&mfxBS);
|
||||
|
||||
MSDK_SAFE_DELETE_ARRAY(mfxBS.Data);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CQuickSync::DeliverSurface(mfxFrameSurface1* pSurface)
|
||||
{
|
||||
if (m_bNeedToFlush)
|
||||
return S_OK;
|
||||
|
||||
MSDK_TRACE("QSDcoder: DeliverSurface\n");
|
||||
|
||||
MSDK_CHECK_POINTER(m_DeliverSurfaceCallback, E_UNEXPECTED);
|
||||
|
||||
// Got a new surface. A NULL surface means to get a surface from the output queue
|
||||
if (pSurface != NULL)
|
||||
{
|
||||
// Initial frames with invalid times are discarded
|
||||
REFERENCE_TIME rtStart = m_TimeManager.ConvertMFXTime2ReferenceTime(pSurface->Data.TimeStamp);
|
||||
if (m_pDecoder->GetOutputQueue()->empty() && rtStart == INVALID_REFTIME)
|
||||
return S_OK;
|
||||
|
||||
PushSurface(pSurface);
|
||||
|
||||
// Not enough surfaces for proper time stamp correction
|
||||
DWORD queueSize = (m_bDvdDecoding) ? 0 :
|
||||
m_Config.dwOutputQueueLength;
|
||||
|
||||
if (!m_bForceOutput && m_pDecoder->GetOutputQueue()->size() < queueSize)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Get oldest surface from queue
|
||||
pSurface = PopSurface();
|
||||
MSDK_CHECK_POINTER(pSurface, E_POINTER);
|
||||
|
||||
if (pSurface->Data.Corrupted)
|
||||
{
|
||||
// Do something with a corrupted surface?
|
||||
pSurface->Data.Corrupted = pSurface->Data.Corrupted;
|
||||
}
|
||||
|
||||
++m_nSegmentFrameCount;
|
||||
|
||||
// Result is in m_FrameData
|
||||
// False return value means that the frame has a negative time stamp and should not be displayed.
|
||||
if (!SetTimeStamp(pSurface))
|
||||
return S_OK;
|
||||
|
||||
m_FrameData.bFilm = false;
|
||||
|
||||
// Setup interlacing info
|
||||
m_FrameData.dwInterlaceFlags = PicStructToDsFlags(pSurface->Info.PicStruct);
|
||||
|
||||
// TODO: find actual frame type I/P/B
|
||||
// Media sample isn't reliable as it referes to an older frame!
|
||||
m_FrameData.frameType = QsFrameData::I;
|
||||
|
||||
// Obtain surface data and copy it to temp buffer.
|
||||
mfxFrameData frameData;
|
||||
m_pDecoder->LockFrame(pSurface, &frameData);
|
||||
|
||||
// Setup output buffer
|
||||
m_FrameData.dwStride = frameData.Pitch;
|
||||
size_t outSize = 4096 + // Adding 4K for page alignment optimizations
|
||||
m_FrameData.dwStride * pSurface->Info.CropH * 3 / 2;
|
||||
|
||||
if (!m_OutputBuffer || m_OutputBufferSize != outSize)
|
||||
{
|
||||
if (m_OutputBuffer)
|
||||
{
|
||||
_aligned_free(m_OutputBuffer);
|
||||
}
|
||||
|
||||
m_OutputBufferSize = outSize;
|
||||
// malloc with page alignment (easier to offset)
|
||||
m_OutputBuffer = (BYTE*)_aligned_malloc(m_OutputBufferSize, 16);
|
||||
}
|
||||
|
||||
size_t height = pSurface->Info.CropH; // Cropped image height
|
||||
size_t pitch = frameData.Pitch; // Image line + padding in bytes --> set by the driver
|
||||
|
||||
// Fill output size
|
||||
m_FrameData.dwHeight = pSurface->Info.CropH;
|
||||
m_FrameData.dwWidth = MSDK_ALIGN16(pSurface->Info.CropW + pSurface->Info.CropX);
|
||||
|
||||
// Offset output buffer's address for fastest SSE4 copy.
|
||||
// Page offset (12 lsb of addresses) sould be 2K apart from source buffer
|
||||
size_t offset = ((size_t)frameData.Y & PAGE_MASK) ^ (1 << 11);
|
||||
m_FrameData.y = m_OutputBuffer + offset;
|
||||
m_FrameData.u = m_FrameData.y + (pitch * height);
|
||||
|
||||
// Copy Y
|
||||
MEMCPY(m_FrameData.y, frameData.Y + (pSurface->Info.CropY * pitch), height * pitch);
|
||||
|
||||
// Copy UV
|
||||
MEMCPY(m_FrameData.u, frameData.CbCr + (pSurface->Info.CropY * pitch), pitch * height / 2);
|
||||
|
||||
// Add borders for non standard images
|
||||
if (pSurface->Info.CropW < m_FrameData.dwWidth)
|
||||
{
|
||||
AddBorders(pSurface);
|
||||
}
|
||||
|
||||
// Unlock the frame
|
||||
m_pDecoder->UnlockFrame(pSurface, &frameData);
|
||||
|
||||
// Send the surface out - return code from dshow filter is ignored.
|
||||
if (m_bNeedToFlush)
|
||||
return S_OK;
|
||||
|
||||
MSDK_TRACE("QSDcoder: DeliverSurfaceCallback (%I64d, %I64d)\n", m_FrameData.rtStart, m_FrameData.rtStop);
|
||||
m_DeliverSurfaceCallback(m_ObjParent, &m_FrameData);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void CQuickSync::AddBorders(mfxFrameSurface1* pSurface)
|
||||
{
|
||||
DWORD h = m_FrameData.dwHeight;
|
||||
|
||||
// Left border
|
||||
if (pSurface->Info.CropX > 0)
|
||||
{
|
||||
for (DWORD y = 0; y < h; ++y)
|
||||
{
|
||||
memset(m_FrameData.y + m_FrameData.dwStride * y, 16, pSurface->Info.CropX);
|
||||
|
||||
if (y < h / 2)
|
||||
{
|
||||
memset(m_FrameData.u + m_FrameData.dwStride * y, 128, pSurface->Info.CropX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Right border
|
||||
int rBorderWidth = (int)m_FrameData.dwWidth - (pSurface->Info.CropX + pSurface->Info.CropW);
|
||||
if (rBorderWidth)
|
||||
{
|
||||
for (DWORD y = 0; y < m_FrameData.dwHeight; ++y)
|
||||
{
|
||||
memset(m_FrameData.y + m_FrameData.dwStride * y + pSurface->Info.CropX + pSurface->Info.CropW,
|
||||
16, rBorderWidth);
|
||||
|
||||
if (y < h / 2)
|
||||
{
|
||||
memset(m_FrameData.u + m_FrameData.dwStride * y + pSurface->Info.CropX + pSurface->Info.CropW,
|
||||
128, rBorderWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mfxU32 CQuickSync::PicStructToDsFlags(mfxU32 picStruct)
|
||||
{
|
||||
if (m_TimeManager.GetInverseTelecine())
|
||||
{
|
||||
return AM_VIDEO_FLAG_WEAVE;
|
||||
}
|
||||
|
||||
mfxU32 flags = 0;
|
||||
// progressive frame - note that sometimes interlaced content has the MFX_PICSTRUCT_PROGRESSIVE in combination with other flags
|
||||
if (picStruct == MFX_PICSTRUCT_PROGRESSIVE)
|
||||
{
|
||||
return AM_VIDEO_FLAG_WEAVE;
|
||||
}
|
||||
|
||||
// top field first
|
||||
if (picStruct & MFX_PICSTRUCT_FIELD_TFF)
|
||||
{
|
||||
flags |= AM_VIDEO_FLAG_FIELD1FIRST;
|
||||
}
|
||||
|
||||
// telecine flag
|
||||
if (picStruct & MFX_PICSTRUCT_FIELD_REPEATED)
|
||||
{
|
||||
flags |= AM_VIDEO_FLAG_REPEAT_FIELD;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
mfxStatus CQuickSync::ConvertFrameRate(mfxF64 dFrameRate, mfxU32& nFrameRateExtN, mfxU32& nFrameRateExtD)
|
||||
{
|
||||
mfxU32 fr = (mfxU32)(dFrameRate + .5);
|
||||
if (fabs(fr - dFrameRate) < 0.0001)
|
||||
{
|
||||
nFrameRateExtN = fr;
|
||||
nFrameRateExtD = 1;
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
fr = (mfxU32)(dFrameRate * 1.001 + .5);
|
||||
|
||||
if (fabs(fr * 1000 - dFrameRate * 1001) < 10)
|
||||
{
|
||||
nFrameRateExtN = fr * 1000;
|
||||
nFrameRateExtD = 1001;
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
nFrameRateExtN = (mfxU32)(dFrameRate * 10000 + .5);
|
||||
nFrameRateExtD = 10000;
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
HRESULT CQuickSync::Flush(bool deliverFrames)
|
||||
{
|
||||
MSDK_TRACE("QSDcoder: Flush\n");
|
||||
|
||||
CQsAutoLock cObjectLock(&m_csLock);
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
// recieved a BeginFlush that wasn't handled for some reason
|
||||
// this overrides the request to output the remaining frames
|
||||
deliverFrames = deliverFrames && !m_bNeedToFlush;
|
||||
m_bForceOutput = deliverFrames;
|
||||
|
||||
// Flush internal queue
|
||||
FlushOutputQueue(deliverFrames);
|
||||
|
||||
// flush HW decoder by sending NULL bitstreams.
|
||||
while (MFX_ERR_NONE == sts || MFX_ERR_MORE_SURFACE == sts)
|
||||
{
|
||||
mfxFrameSurface1* pSurf = NULL;
|
||||
sts = m_pDecoder->Decode(NULL, pSurf);
|
||||
|
||||
if (MFX_ERR_NONE == sts && deliverFrames)
|
||||
{
|
||||
hr = DeliverSurface(pSurf);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Flush internal queue again
|
||||
FlushOutputQueue(deliverFrames);
|
||||
|
||||
ASSERT(m_pDecoder->GetOutputQueue()->empty());
|
||||
|
||||
m_TimeManager.Reset();
|
||||
m_bForceOutput = false;
|
||||
|
||||
// all data has been flushed
|
||||
m_bNeedToFlush = false;
|
||||
|
||||
MSDK_TRACE("QSDcoder: Flush ended\n");
|
||||
return hr;
|
||||
}
|
||||
|
||||
void CQuickSync::FlushOutputQueue(bool deliverFrames)
|
||||
{
|
||||
bool bForceOutputSave = m_bForceOutput;
|
||||
m_bForceOutput = deliverFrames && !m_bNeedToFlush;
|
||||
|
||||
MSDK_TRACE("QSDcoder: FlushOutputQueue (deliverFrames=%s)\n", (m_bForceOutput) ? "TRUE" : "FALSE");
|
||||
|
||||
while (!m_pDecoder->GetOutputQueue()->empty() && deliverFrames && !m_bNeedToFlush)
|
||||
{
|
||||
DeliverSurface(NULL);
|
||||
}
|
||||
|
||||
// clear the internal frame queue - either failure in flushing or no need to deliver the frames.
|
||||
while (!m_pDecoder->GetOutputQueue()->empty())
|
||||
{
|
||||
PopSurface();
|
||||
}
|
||||
|
||||
m_bForceOutput = bForceOutputSave;
|
||||
}
|
||||
|
||||
HRESULT CQuickSync::OnSeek(REFERENCE_TIME segmentStart)
|
||||
{
|
||||
MSDK_TRACE("QSDcoder: OnSeek\n");
|
||||
|
||||
CQsAutoLock cObjectLock(&m_csLock);
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
m_nSegmentFrameCount = 0;
|
||||
|
||||
if (m_pDecoder)
|
||||
{
|
||||
m_TimeManager.Reset();
|
||||
sts = m_pDecoder->Reset(&m_mfxParamsVideo, m_nPitch);
|
||||
ASSERT(sts == MFX_ERR_NONE);
|
||||
m_pFrameConstructor->Reset();
|
||||
|
||||
FlushOutputQueue(false);
|
||||
}
|
||||
|
||||
m_bNeedToFlush = false;
|
||||
return (sts == MFX_ERR_NONE) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
bool CQuickSync::SetTimeStamp(mfxFrameSurface1* pSurface)
|
||||
{
|
||||
if (!m_TimeManager.GetSampleTimeStamp(pSurface, *m_pDecoder->GetOutputQueue(), m_FrameData.rtStart, m_FrameData.rtStop))
|
||||
return false;
|
||||
|
||||
//TODO: force BOB DI after loss of IVTC for a few frames
|
||||
return m_FrameData.rtStart >= 0;
|
||||
}
|
||||
|
||||
mfxStatus CQuickSync::OnVideoParamsChanged()
|
||||
{
|
||||
mfxVideoParam params;
|
||||
MSDK_ZERO_VAR(params);
|
||||
mfxStatus sts = m_pDecoder->GetVideoParams(¶ms);
|
||||
MSDK_CHECK_RESULT_P_RET(sts, MFX_ERR_NONE);
|
||||
|
||||
mfxFrameInfo& curInfo = m_mfxParamsVideo.mfx.FrameInfo;
|
||||
mfxFrameInfo& newInfo = params.mfx.FrameInfo;
|
||||
|
||||
bool bResChange = (curInfo.CropH != newInfo.CropH) || (curInfo.CropW != newInfo.CropW);
|
||||
bool bAspectRatioChange = (curInfo.AspectRatioH != newInfo.AspectRatioH) || (curInfo.AspectRatioW != newInfo.AspectRatioW);
|
||||
bool bFrameRateChange = (curInfo.FrameRateExtN != newInfo.FrameRateExtN) ||(curInfo.FrameRateExtD != newInfo.FrameRateExtD);
|
||||
bool bFrameStructChange = curInfo.PicStruct != newInfo.PicStruct;
|
||||
|
||||
if (!(bResChange || bAspectRatioChange || bFrameRateChange || bFrameStructChange))
|
||||
return MFX_ERR_NONE;
|
||||
|
||||
// Copy video params
|
||||
params.AsyncDepth = m_mfxParamsVideo.AsyncDepth;
|
||||
params.IOPattern = m_mfxParamsVideo.IOPattern;
|
||||
memcpy(&m_mfxParamsVideo, ¶ms, sizeof(params));
|
||||
|
||||
// Flush images with old parameters
|
||||
FlushOutputQueue(true);
|
||||
|
||||
// Calculate new size and aspect ratio
|
||||
if (bAspectRatioChange || bResChange)
|
||||
{
|
||||
DWORD alignedWidth = MSDK_ALIGN16(newInfo.CropW);
|
||||
PARtoDAR(newInfo.AspectRatioW, newInfo.AspectRatioH, alignedWidth, newInfo.CropH, m_FrameData.dwPictAspectRatioX, m_FrameData.dwPictAspectRatioY);
|
||||
}
|
||||
|
||||
if (bFrameRateChange || bFrameStructChange)
|
||||
{
|
||||
double frameRate = (double)curInfo.FrameRateExtN / (double)curInfo.FrameRateExtD;
|
||||
m_TimeManager.OnVideoParamsChanged(frameRate);
|
||||
}
|
||||
|
||||
// Might be needed for DVD menus - currently not working as expected :(
|
||||
// Flush(true);
|
||||
// OnSeek(0);
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
void CQuickSync::PushSurface(mfxFrameSurface1* pSurface)
|
||||
{
|
||||
m_pDecoder->PushSurface(pSurface);
|
||||
|
||||
// Note - no need to lock as all API functions are already exclusive.
|
||||
m_TimeManager.AddOutputTimeStamp(pSurface);
|
||||
}
|
||||
|
||||
mfxFrameSurface1* CQuickSync::PopSurface()
|
||||
{
|
||||
return m_pDecoder->PopSurface();
|
||||
}
|
||||
|
||||
HRESULT CQuickSync::CheckCodecProfileSupport(DWORD codec, DWORD profile, DWORD level)
|
||||
{
|
||||
// H264
|
||||
if (codec == MFX_CODEC_AVC)
|
||||
{
|
||||
switch (profile)
|
||||
{
|
||||
case QS_PROFILE_H264_BASELINE:
|
||||
case QS_PROFILE_H264_CONSTRAINED_BASELINE:
|
||||
case QS_PROFILE_H264_MAIN:
|
||||
case QS_PROFILE_H264_HIGH:
|
||||
return S_OK;
|
||||
default:
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
}
|
||||
|
||||
// MPEG2
|
||||
if (codec == MFX_CODEC_MPEG2)
|
||||
{
|
||||
switch (profile)
|
||||
{
|
||||
case QS_PROFILE_MPEG2_SIMPLE:
|
||||
case QS_PROFILE_MPEG2_MAIN:
|
||||
case QS_PROFILE_MPEG2_HIGH:
|
||||
case QS_PROFILE_MPEG2_SPATIALLY_SCALABLE:
|
||||
return S_OK;
|
||||
default:
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
}
|
||||
|
||||
// VC1/WMV
|
||||
if (codec == MFX_CODEC_VC1)
|
||||
{
|
||||
switch (profile)
|
||||
{
|
||||
case QS_PROFILE_VC1_SIMPLE:
|
||||
case QS_PROFILE_VC1_MAIN:
|
||||
return S_FALSE;
|
||||
case QS_PROFILE_VC1_ADVANCED:
|
||||
return S_OK;
|
||||
default:
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
}
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// forward declarations
|
||||
class CQuickSyncDecoder;
|
||||
class CFrameConstructor;
|
||||
class MFXFrameAllocator;
|
||||
|
||||
class CQuickSync : public IQuickSyncDecoder
|
||||
{
|
||||
public:
|
||||
CQuickSync();
|
||||
virtual ~CQuickSync();
|
||||
|
||||
protected:
|
||||
virtual bool getOK() { return m_OK; }
|
||||
virtual HRESULT TestMediaType(const AM_MEDIA_TYPE* mtIn, FOURCC fourCC);
|
||||
virtual HRESULT InitDecoder(const AM_MEDIA_TYPE* mtIn, FOURCC fourCC);
|
||||
virtual HRESULT Decode(IMediaSample* pIn);
|
||||
virtual HRESULT Flush(bool deliverFrames = true);
|
||||
virtual HRESULT CheckCodecProfileSupport(DWORD codec, DWORD profile, DWORD level);
|
||||
|
||||
// Marks the beginning of a flush (discard frames or reset).
|
||||
// Any samples recieved during the flush period are discarded internally.
|
||||
// Can't do anything but change flags to avoid deadlocks.
|
||||
// Called asynchroniously from the application thread.
|
||||
virtual HRESULT BeginFlush()
|
||||
{
|
||||
// Don't use a lock - causes deadlocks!
|
||||
MSDK_TRACE("QSDcoder: BeginFlush\n");
|
||||
m_bFlushing = true;
|
||||
m_bNeedToFlush = true; // Need to flush buffers (reset) in the future (within the decoding thread!).
|
||||
// Set to false during OnSeek or Flush.
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Marks the end of the flush period - from now on, Decode receives valid samples.
|
||||
// Called asynchroniously from the application thread
|
||||
virtual HRESULT EndFlush()
|
||||
{
|
||||
// Don't use a lock - causes deadlocks!
|
||||
MSDK_TRACE("QSDcoder: EndFlush\n");
|
||||
m_bFlushing = false;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT HandleSubType(const GUID& subType, FOURCC fourCC);
|
||||
HRESULT CopyMediaTypeToVIDEOINFOHEADER2(const AM_MEDIA_TYPE* mtIn, VIDEOINFOHEADER2*& vih2, size_t& nVideoInfoSize, size_t& nSampleSize);
|
||||
HRESULT DeliverSurface(mfxFrameSurface1* pSurfaceOut);
|
||||
virtual void SetDeliverSurfaceCallback(void* obj, TQS_DeliverSurfaceCallback func)
|
||||
{
|
||||
CQsAutoLock cObjectLock(&m_csLock);
|
||||
m_ObjParent = obj;
|
||||
m_DeliverSurfaceCallback = func;
|
||||
}
|
||||
virtual HRESULT OnSeek(REFERENCE_TIME segmentStart);
|
||||
bool SetTimeStamp(mfxFrameSurface1* pSurface);
|
||||
void SetAspectRatio(VIDEOINFOHEADER2& vih2, mfxFrameInfo& FrameInfo);
|
||||
mfxStatus ConvertFrameRate(mfxF64 dFrameRate, mfxU32& nFrameRateExtN, mfxU32& nFrameRateExtD);
|
||||
mfxStatus OnVideoParamsChanged();
|
||||
mfxU32 PicStructToDsFlags(mfxU32 picStruct);
|
||||
inline void PushSurface(mfxFrameSurface1* pSurface);
|
||||
inline mfxFrameSurface1* PopSurface();
|
||||
void FlushOutputQueue(bool deliverFrames = true);
|
||||
void AddBorders(mfxFrameSurface1* pSurface);
|
||||
|
||||
// data members
|
||||
bool m_OK;
|
||||
void* m_ObjParent;
|
||||
TQS_DeliverSurfaceCallback m_DeliverSurfaceCallback;
|
||||
CQsLock m_csLock;
|
||||
CQuickSyncDecoder* m_pDecoder;
|
||||
mfxVideoParam m_mfxParamsVideo; // video params
|
||||
mfxU32 m_nPitch;
|
||||
CDecTimeManager m_TimeManager;
|
||||
CFrameConstructor* m_pFrameConstructor;
|
||||
unsigned char* m_OutputBuffer;
|
||||
size_t m_OutputBufferSize;
|
||||
size_t m_nSegmentFrameCount; // used for debugging mostly
|
||||
volatile bool m_bFlushing; // like in DirectShow - current frame and data should be discarded
|
||||
volatile bool m_bNeedToFlush;
|
||||
bool m_bForceOutput;
|
||||
bool m_bDvdDecoding;
|
||||
CQsConfig m_Config;
|
||||
|
||||
// Output frame data
|
||||
QsFrameData m_FrameData;
|
||||
};
|
|
@ -0,0 +1,501 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "IQuickSyncDecoder.h"
|
||||
#include "QuickSync_defs.h"
|
||||
#include "QuickSyncUtils.h"
|
||||
#include "QuickSyncDecoder.h"
|
||||
|
||||
#define MIN_REQUIRED_API_VER_MINOR 1
|
||||
#define MIN_REQUIRED_API_VER_MAJOR 1
|
||||
|
||||
static int GetIntelAdapterId(IDirect3D9* pd3d)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pd3d, 0);
|
||||
|
||||
unsigned adapterCount = (int)pd3d->GetAdapterCount();
|
||||
D3DADAPTER_IDENTIFIER9 adIdentifier;
|
||||
for (int i = adapterCount-1; i >= 0; --i)
|
||||
{
|
||||
HRESULT hr = pd3d->GetAdapterIdentifier(i, 0, &adIdentifier);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Look for Intel's vendor ID (8086h)
|
||||
if (adIdentifier.VendorId == 0x8086)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
CQuickSyncDecoder::CQuickSyncDecoder(mfxStatus& sts) :
|
||||
m_pFrameSurfaces(NULL),
|
||||
m_pmfxDEC(0),
|
||||
m_nRequiredFramesNum(0),
|
||||
m_pFrameAllocator(NULL),
|
||||
m_mfxImpl(MFX_IMPL_UNSUPPORTED),
|
||||
m_pVideoParams(0),
|
||||
m_pd3dDeviceManager(NULL),
|
||||
m_pd3dDevice(NULL)
|
||||
{
|
||||
MSDK_ZERO_VAR(m_AllocResponse);
|
||||
|
||||
m_ApiVersion.Major = MIN_REQUIRED_API_VER_MAJOR;
|
||||
m_ApiVersion.Minor = MIN_REQUIRED_API_VER_MINOR;
|
||||
mfxIMPL impl = MFX_IMPL_AUTO_ANY;
|
||||
|
||||
// Uncomment for SW emulation
|
||||
//impl = MFX_IMPL_SOFTWARE;
|
||||
|
||||
sts = m_mfxVideoSession.Init(impl, &m_ApiVersion);
|
||||
if (MFX_ERR_NONE != sts)
|
||||
return;
|
||||
|
||||
//m_mfxVideoSession.SetPriority(MFX_PRIORITY_LOW);
|
||||
m_mfxVideoSession.QueryIMPL(&m_mfxImpl);
|
||||
m_mfxVideoSession.QueryVersion(&m_ApiVersion);
|
||||
|
||||
m_bHwAcceleration = m_mfxImpl != MFX_IMPL_SOFTWARE;
|
||||
m_pmfxDEC = new MFXVideoDECODE(m_mfxVideoSession);
|
||||
}
|
||||
|
||||
CQuickSyncDecoder::~CQuickSyncDecoder()
|
||||
{
|
||||
if (m_pmfxDEC)
|
||||
{
|
||||
m_pmfxDEC->Close();
|
||||
delete m_pmfxDEC;
|
||||
}
|
||||
|
||||
FreeFrameAllocator();
|
||||
delete m_pFrameAllocator;
|
||||
CloseD3D();
|
||||
}
|
||||
|
||||
mfxFrameSurface1* CQuickSyncDecoder::FindFreeSurface()
|
||||
{
|
||||
MSDK_CHECK_POINTER(m_pFrameSurfaces, NULL);
|
||||
|
||||
//0.1 seconds cycle
|
||||
for (int tries = 0; tries < 100; ++tries)
|
||||
{
|
||||
for (mfxU8 i = 0; i < m_nRequiredFramesNum; ++i)
|
||||
{
|
||||
if (0 == m_pFrameSurfaces[i].Data.Locked)
|
||||
{
|
||||
// find if surface is in output queue
|
||||
bool bInQueue = false;
|
||||
for (size_t j = 0; j < m_OutputSurfaceQueue.size(); ++j)
|
||||
{
|
||||
if (m_OutputSurfaceQueue[j] == &m_pFrameSurfaces[i])
|
||||
{
|
||||
bInQueue = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// found free surface :)
|
||||
if (!bInQueue)
|
||||
return &m_pFrameSurfaces[i];
|
||||
}
|
||||
}
|
||||
|
||||
MSDK_TRACE("QSDcoder: FindFreeSurface - all surfaces are in use, retrying in 1ms\n");
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mfxStatus CQuickSyncDecoder::InitFrameAllocator(mfxVideoParam* pVideoParams, mfxU32 nPitch)
|
||||
{
|
||||
// already initializerd
|
||||
if (m_pFrameSurfaces)
|
||||
{
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
MSDK_CHECK_POINTER(m_pmfxDEC, MFX_ERR_NOT_INITIALIZED);
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
// Initialize frame allocator (if needed)
|
||||
sts = CreateAllocator();
|
||||
MSDK_CHECK_NOT_EQUAL(sts, MFX_ERR_NONE, MFX_ERR_MEMORY_ALLOC);
|
||||
|
||||
// Find how many surfaces are needed
|
||||
mfxFrameAllocRequest allocRequest;
|
||||
MSDK_ZERO_VAR(allocRequest);
|
||||
sts = m_pmfxDEC->QueryIOSurf(pVideoParams, &allocRequest);
|
||||
MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
|
||||
MSDK_IGNORE_MFX_STS(sts, MFX_WRN_INCOMPATIBLE_VIDEO_PARAM);
|
||||
allocRequest.NumFrameSuggested = (mfxU16)m_Config.dwOutputQueueLength + allocRequest.NumFrameSuggested + 1;
|
||||
allocRequest.NumFrameMin = allocRequest.NumFrameSuggested;
|
||||
MSDK_CHECK_RESULT_P_RET(sts, MFX_ERR_NONE);
|
||||
|
||||
// decide memory type
|
||||
allocRequest.Type = MFX_MEMTYPE_EXTERNAL_FRAME | MFX_MEMTYPE_FROM_DECODE;
|
||||
allocRequest.Type |= (MFX_IMPL_SOFTWARE == m_mfxImpl) ?
|
||||
MFX_MEMTYPE_SYSTEM_MEMORY : MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
|
||||
|
||||
memcpy(&allocRequest.Info, &pVideoParams->mfx.FrameInfo, sizeof(mfxFrameInfo));
|
||||
|
||||
// allocate frames with H aligned at 32 for both progressive and interlaced content
|
||||
allocRequest.Info.Height = MSDK_ALIGN32(allocRequest.Info.Height);
|
||||
allocRequest.Info.Width = (mfxU16)nPitch;
|
||||
|
||||
// perform allocation call. result is saved in m_AllocResponse
|
||||
sts = m_pFrameAllocator->Alloc(m_pFrameAllocator->pthis, &allocRequest, &m_AllocResponse);
|
||||
MSDK_CHECK_RESULT_P_RET(sts, MFX_ERR_NONE);
|
||||
|
||||
m_nRequiredFramesNum = m_AllocResponse.NumFrameActual;
|
||||
ASSERT(m_nRequiredFramesNum == allocRequest.NumFrameSuggested);
|
||||
m_pFrameSurfaces = new mfxFrameSurface1[m_nRequiredFramesNum];
|
||||
MSDK_CHECK_POINTER(m_pFrameSurfaces, MFX_ERR_MEMORY_ALLOC);
|
||||
MSDK_ZERO_MEMORY(m_pFrameSurfaces, sizeof(mfxFrameSurface1) * m_nRequiredFramesNum);
|
||||
|
||||
// alloc decoder work & output surfaces
|
||||
for (mfxU32 i = 0; i < m_nRequiredFramesNum; ++i)
|
||||
{
|
||||
// copy frame info
|
||||
memcpy(&(m_pFrameSurfaces[i].Info), &pVideoParams->mfx.FrameInfo, sizeof(mfxFrameInfo));
|
||||
|
||||
// save pointer to allocator specific surface object (mid)
|
||||
m_pFrameSurfaces[i].Data.MemId = m_AllocResponse.mids[i];
|
||||
m_pFrameSurfaces[i].Data.Pitch = (mfxU16)nPitch;
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
mfxStatus CQuickSyncDecoder::FreeFrameAllocator()
|
||||
{
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
if (m_pFrameAllocator)
|
||||
{
|
||||
sts = m_pFrameAllocator->Free(m_pFrameAllocator->pthis, &m_AllocResponse);
|
||||
MSDK_ZERO_VAR(m_AllocResponse);
|
||||
}
|
||||
|
||||
m_nRequiredFramesNum = 0;
|
||||
MSDK_SAFE_DELETE_ARRAY(m_pFrameSurfaces);
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus CQuickSyncDecoder::InternalReset(mfxVideoParam* pVideoParams, mfxU32 nPitch, bool bInited)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pVideoParams, MFX_ERR_NULL_PTR);
|
||||
MSDK_CHECK_POINTER(m_pmfxDEC, MFX_ERR_NOT_INITIALIZED);
|
||||
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
m_pVideoParams = pVideoParams;
|
||||
|
||||
// reset decoder
|
||||
if (bInited)
|
||||
{
|
||||
// flush - VC1 decoder needs this or surfaces will remain in use (bug workaround)
|
||||
// SW decoder doesn't like this :(
|
||||
if (MFX_IMPL_SOFTWARE != QueryIMPL())
|
||||
{
|
||||
do
|
||||
{
|
||||
mfxFrameSurface1* pSurf = NULL;
|
||||
sts = Decode(NULL, pSurf);
|
||||
} while (sts == MFX_ERR_NONE);
|
||||
}
|
||||
|
||||
sts = m_pmfxDEC->Reset(pVideoParams);
|
||||
// need to reset the frame allocator
|
||||
if (MFX_ERR_NONE != sts)
|
||||
{
|
||||
m_pmfxDEC->Close();
|
||||
FreeFrameAllocator();
|
||||
bInited = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Full init
|
||||
if (!bInited)
|
||||
{
|
||||
// Check if video format is supported by HW acceleration
|
||||
if (MFX_WRN_PARTIAL_ACCELERATION == CheckHwAcceleration(pVideoParams))
|
||||
{
|
||||
// Change behavior to SW decoding
|
||||
// m_mfxImpl = MFX_IMPL_SOFTWARE;
|
||||
}
|
||||
|
||||
// Setup allocator - will initialize D3D if needed
|
||||
sts = InitFrameAllocator(pVideoParams, nPitch);
|
||||
MSDK_CHECK_RESULT_P_RET(sts, MFX_ERR_NONE);
|
||||
|
||||
// Init MSDK decoder
|
||||
sts = m_pmfxDEC->Init(pVideoParams);
|
||||
if (MFX_WRN_PARTIAL_ACCELERATION == sts)
|
||||
{
|
||||
sts = MFX_ERR_NONE;
|
||||
m_bHwAcceleration = false;
|
||||
}
|
||||
}
|
||||
|
||||
MSDK_IGNORE_MFX_STS(sts, MFX_WRN_INCOMPATIBLE_VIDEO_PARAM);
|
||||
return sts;
|
||||
}
|
||||
|
||||
mfxStatus CQuickSyncDecoder::CheckHwAcceleration(mfxVideoParam* pVideoParams)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pVideoParams, MFX_ERR_NULL_PTR);
|
||||
MSDK_CHECK_POINTER(m_pmfxDEC, MFX_ERR_NOT_INITIALIZED);
|
||||
|
||||
mfxFrameAllocRequest allocRequest;
|
||||
MSDK_ZERO_VAR(allocRequest);
|
||||
|
||||
// If we are already using SW decoder then no need for further checks...
|
||||
mfxIMPL impl = QueryIMPL();
|
||||
if (MFX_IMPL_SOFTWARE == impl)
|
||||
return MFX_ERR_NONE;
|
||||
|
||||
mfxU16 ioPaternSave = pVideoParams->IOPattern;
|
||||
pVideoParams->IOPattern = (mfxU16)MFX_IOPATTERN_OUT_VIDEO_MEMORY;
|
||||
mfxStatus sts = m_pmfxDEC->QueryIOSurf(pVideoParams, &allocRequest);
|
||||
pVideoParams->IOPattern = ioPaternSave;
|
||||
return sts;
|
||||
}
|
||||
|
||||
mfxStatus CQuickSyncDecoder::GetVideoParams(mfxVideoParam* pVideoParams)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pVideoParams, MFX_ERR_NULL_PTR);
|
||||
MSDK_CHECK_POINTER(m_pmfxDEC, MFX_ERR_NOT_INITIALIZED);
|
||||
|
||||
return m_pmfxDEC->GetVideoParam(pVideoParams);
|
||||
}
|
||||
|
||||
mfxStatus CQuickSyncDecoder::Decode(mfxBitstream* pBS, mfxFrameSurface1*& pFrameSurface)
|
||||
{
|
||||
MSDK_CHECK_POINTER(m_pmfxDEC, MFX_ERR_NOT_INITIALIZED);
|
||||
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
mfxSyncPoint syncp;
|
||||
mfxFrameSurface1* pWorkSurface = FindFreeSurface();
|
||||
MSDK_CHECK_POINTER(pWorkSurface, MFX_ERR_NOT_ENOUGH_BUFFER);
|
||||
|
||||
do
|
||||
{
|
||||
sts = m_pmfxDEC->DecodeFrameAsync(pBS, pWorkSurface, &pFrameSurface, &syncp);
|
||||
// need 1 more work surface
|
||||
if (MFX_ERR_MORE_SURFACE == sts)
|
||||
{
|
||||
pWorkSurface = FindFreeSurface();
|
||||
MSDK_CHECK_POINTER(pWorkSurface, MFX_ERR_NOT_ENOUGH_BUFFER);
|
||||
}
|
||||
else if (MFX_WRN_DEVICE_BUSY == sts)
|
||||
{
|
||||
Sleep(1);
|
||||
}
|
||||
} while (MFX_WRN_DEVICE_BUSY == sts || MFX_ERR_MORE_SURFACE == sts);
|
||||
|
||||
// Wait for the asynch decoding to finish
|
||||
if (MFX_ERR_NONE == sts)
|
||||
{
|
||||
sts = m_mfxVideoSession.SyncOperation(syncp, 0xFFFF);
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
mfxStatus CQuickSyncDecoder::InitD3D()
|
||||
{
|
||||
// check if the d3d device is functional:
|
||||
if (m_pd3dDeviceManager != NULL)
|
||||
{
|
||||
HRESULT hr = m_pd3dDevice->TestCooperativeLevel();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
CloseD3D();
|
||||
}
|
||||
else
|
||||
{
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
// Create Direct3D
|
||||
CComPtr<IDirect3D9> pd3d = Direct3DCreate9(D3D_SDK_VERSION);
|
||||
UINT resetToken;
|
||||
|
||||
if (!pd3d)
|
||||
{
|
||||
return MFX_ERR_NULL_PTR;
|
||||
}
|
||||
|
||||
static const POINT point = {0, 0};
|
||||
const HWND window = WindowFromPoint(point);
|
||||
|
||||
D3DPRESENT_PARAMETERS d3dParams;
|
||||
MSDK_ZERO_VAR(d3dParams);
|
||||
d3dParams.Windowed = TRUE;
|
||||
d3dParams.hDeviceWindow = window;
|
||||
d3dParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
d3dParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
d3dParams.Flags = D3DPRESENTFLAG_VIDEO;
|
||||
d3dParams.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
|
||||
d3dParams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
|
||||
d3dParams.BackBufferCount = 1;
|
||||
d3dParams.BackBufferFormat = D3DFMT_X8R8G8B8;
|
||||
d3dParams.BackBufferWidth = 0;
|
||||
d3dParams.BackBufferHeight = 0;
|
||||
|
||||
// find Intel adapter number - not always the default adapter
|
||||
int adapterId = GetIntelAdapterId(pd3d);
|
||||
if (adapterId < 0)
|
||||
{
|
||||
MSDK_TRACE("QSDcoder: didn't find an Intel GPU.\n");
|
||||
return MFX_ERR_DEVICE_FAILED;
|
||||
}
|
||||
|
||||
// create d3d device
|
||||
m_pd3dDevice = 0;
|
||||
HRESULT hr = pd3d->CreateDevice(
|
||||
adapterId,
|
||||
D3DDEVTYPE_HAL,
|
||||
window,
|
||||
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
|
||||
&d3dParams,
|
||||
&m_pd3dDevice);
|
||||
|
||||
if (FAILED(hr) || !m_pd3dDevice)
|
||||
{
|
||||
return MFX_ERR_DEVICE_FAILED;
|
||||
}
|
||||
|
||||
// create device manager
|
||||
m_pd3dDeviceManager = NULL;
|
||||
hr = DXVA2CreateDirect3DDeviceManager9(&resetToken, &m_pd3dDeviceManager);
|
||||
if (FAILED(hr) || !m_pd3dDeviceManager)
|
||||
{
|
||||
return MFX_ERR_DEVICE_FAILED;
|
||||
}
|
||||
|
||||
// reset the d3d device
|
||||
hr = m_pd3dDeviceManager->ResetDevice(m_pd3dDevice, resetToken);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return MFX_ERR_DEVICE_FAILED;
|
||||
}
|
||||
|
||||
m_mfxVideoSession.SetHandle(MFX_HANDLE_D3D9_DEVICE_MANAGER, m_pd3dDeviceManager);
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
void CQuickSyncDecoder::CloseD3D()
|
||||
{
|
||||
m_mfxVideoSession.SetHandle(MFX_HANDLE_D3D9_DEVICE_MANAGER, NULL);
|
||||
MSDK_SAFE_RELEASE(m_pd3dDeviceManager);
|
||||
MSDK_SAFE_RELEASE(m_pd3dDevice);
|
||||
}
|
||||
|
||||
mfxStatus CQuickSyncDecoder::DecodeHeader(mfxBitstream* bs, mfxVideoParam* par)
|
||||
{
|
||||
MSDK_CHECK_POINTER(m_pmfxDEC && bs && par, MFX_ERR_NULL_PTR);
|
||||
mfxStatus sts = m_pmfxDEC->DecodeHeader(bs, par);
|
||||
|
||||
// Try again, marking the bitstream as complete
|
||||
// This workaround should work on all driver versions.
|
||||
if (MFX_ERR_MORE_DATA == sts)
|
||||
{
|
||||
mfxU16 oldFlag = bs->DataFlag;
|
||||
bs->DataFlag = MFX_BITSTREAM_COMPLETE_FRAME;
|
||||
sts = m_pmfxDEC->DecodeHeader(bs, par);
|
||||
bs->DataFlag = oldFlag;
|
||||
}
|
||||
|
||||
MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
|
||||
return sts;
|
||||
}
|
||||
|
||||
mfxStatus CQuickSyncDecoder::CreateAllocator()
|
||||
{
|
||||
if (m_pFrameAllocator != NULL)
|
||||
return MFX_ERR_NONE;
|
||||
|
||||
MSDK_TRACE("QSDcoder: CreateAllocator\n");
|
||||
|
||||
mfxIMPL impl = QueryIMPL();
|
||||
ASSERT(m_pVideoParams != NULL);
|
||||
m_pVideoParams->IOPattern = (mfxU16)((MFX_IMPL_SOFTWARE != impl) ? MFX_IOPATTERN_OUT_VIDEO_MEMORY : MFX_IOPATTERN_OUT_SYSTEM_MEMORY);
|
||||
std::auto_ptr<D3DAllocatorParams> pParam(NULL);
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
// Setup allocator - HW acceleration
|
||||
if (MFX_IMPL_SOFTWARE != impl)
|
||||
{
|
||||
if (!m_pd3dDeviceManager)
|
||||
{
|
||||
sts = InitD3D();
|
||||
MSDK_CHECK_RESULT_P_RET(sts, MFX_ERR_NONE);
|
||||
}
|
||||
|
||||
pParam.reset(new D3DAllocatorParams);
|
||||
pParam->pManager = m_pd3dDeviceManager;
|
||||
m_pFrameAllocator = new D3DFrameAllocator();
|
||||
}
|
||||
// Setup allocator - No HW acceleration
|
||||
else
|
||||
{
|
||||
m_pFrameAllocator = new SysMemFrameAllocator();
|
||||
}
|
||||
|
||||
sts = m_pFrameAllocator->Init(pParam.get());
|
||||
if (sts == MFX_ERR_NONE)
|
||||
{
|
||||
// Note - setting the seesion allocator can be done only once!
|
||||
sts = m_mfxVideoSession.SetFrameAllocator(m_pFrameAllocator);
|
||||
}
|
||||
else
|
||||
// Allocator failed to initialize
|
||||
{
|
||||
MSDK_SAFE_DELETE(m_pFrameAllocator);
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
mfxStatus CQuickSyncDecoder::LockFrame(mfxFrameSurface1* pSurface, mfxFrameData* pFrameData)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pSurface, MFX_ERR_NULL_PTR);
|
||||
MSDK_CHECK_POINTER(pFrameData, MFX_ERR_NULL_PTR);
|
||||
return m_pFrameAllocator->Lock(m_pFrameAllocator, pSurface->Data.MemId, pFrameData);
|
||||
}
|
||||
|
||||
mfxStatus CQuickSyncDecoder::UnlockFrame(mfxFrameSurface1* pSurface, mfxFrameData* pFrameData)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pSurface, MFX_ERR_NULL_PTR);
|
||||
MSDK_CHECK_POINTER(pFrameData, MFX_ERR_NULL_PTR);
|
||||
return m_pFrameAllocator->Unlock(m_pFrameAllocator, pSurface->Data.MemId, pFrameData);
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "d3d_allocator.h"
|
||||
#include "sysmem_allocator.h"
|
||||
|
||||
typedef std::deque<mfxFrameSurface1*> TSurfaceQueue;
|
||||
|
||||
class CQuickSyncDecoder
|
||||
{
|
||||
public:
|
||||
CQuickSyncDecoder(mfxStatus& sts);
|
||||
~CQuickSyncDecoder();
|
||||
|
||||
mfxStatus Init(mfxVideoParam* pVideoParams, mfxU32 nPitch)
|
||||
{
|
||||
return InternalReset(pVideoParams, nPitch, false);
|
||||
}
|
||||
|
||||
mfxStatus Reset(mfxVideoParam* pVideoParams, mfxU32 nPitch)
|
||||
{
|
||||
return InternalReset(pVideoParams, nPitch, true);
|
||||
}
|
||||
|
||||
mfxStatus Decode(mfxBitstream* pBS, mfxFrameSurface1*& pFrameSurface);
|
||||
mfxStatus GetVideoParams(mfxVideoParam* pVideoParams);
|
||||
IDirect3DDeviceManager9*& GetD3dDeviceManager()
|
||||
{
|
||||
return m_pd3dDeviceManager;
|
||||
}
|
||||
|
||||
mfxStatus CreateAllocator();
|
||||
mfxStatus InitFrameAllocator(mfxVideoParam* pVideoParams, mfxU32 nPitch);
|
||||
mfxStatus FreeFrameAllocator();
|
||||
|
||||
inline mfxIMPL QueryIMPL()
|
||||
{
|
||||
return m_mfxImpl;
|
||||
}
|
||||
|
||||
mfxStatus DecodeHeader(mfxBitstream* bs, mfxVideoParam* par);
|
||||
mfxStatus CheckHwAcceleration(mfxVideoParam* pVideoParams);
|
||||
void SetConfig(const CQsConfig& cfg) { m_Config = cfg; }
|
||||
TSurfaceQueue* GetOutputQueue() { return &m_OutputSurfaceQueue; }
|
||||
__forceinline void PushSurface(mfxFrameSurface1* pSurface)
|
||||
{
|
||||
m_OutputSurfaceQueue.push_back(pSurface);
|
||||
}
|
||||
|
||||
__forceinline mfxFrameSurface1* PopSurface()
|
||||
{
|
||||
if (m_OutputSurfaceQueue.empty())
|
||||
return NULL;
|
||||
|
||||
mfxFrameSurface1* pSurface = m_OutputSurfaceQueue.front();
|
||||
m_OutputSurfaceQueue.pop_front();
|
||||
return pSurface;
|
||||
}
|
||||
|
||||
mfxStatus LockFrame(mfxFrameSurface1* pSurface, mfxFrameData* pFrameData);
|
||||
mfxStatus UnlockFrame(mfxFrameSurface1* pSurface, mfxFrameData* pFrameData);
|
||||
|
||||
protected:
|
||||
mfxStatus InternalReset(mfxVideoParam* pVideoParams, mfxU32 nPitch, bool bInited);
|
||||
mfxFrameSurface1* FindFreeSurface();
|
||||
mfxStatus InitD3D();
|
||||
void CloseD3D();
|
||||
|
||||
// data members
|
||||
// session
|
||||
MFXVideoSession m_mfxVideoSession;
|
||||
mfxVersion m_ApiVersion;
|
||||
mfxIMPL m_mfxImpl;
|
||||
CQsConfig m_Config;
|
||||
bool m_bHwAcceleration;
|
||||
|
||||
// Decoder
|
||||
MFXVideoDECODE* m_pmfxDEC;
|
||||
mfxVideoParam* m_pVideoParams;
|
||||
|
||||
// Allocator
|
||||
MFXFrameAllocator* m_pFrameAllocator;
|
||||
mfxFrameSurface1* m_pFrameSurfaces;
|
||||
mfxFrameAllocResponse m_AllocResponse;
|
||||
mfxU16 m_nRequiredFramesNum;
|
||||
|
||||
// D3D/DXVA interfaces
|
||||
IDirect3DDeviceManager9* m_pd3dDeviceManager;
|
||||
IDirect3DDevice9* m_pd3dDevice;
|
||||
|
||||
TSurfaceQueue m_OutputSurfaceQueue;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CQuickSyncDecoder);
|
||||
};
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "IQuickSyncDecoder.h"
|
||||
#include "QuickSync_defs.h"
|
||||
#include "QuickSyncUtils.h"
|
||||
#include "TimeManager.h"
|
||||
#include "QuickSync.h"
|
||||
|
||||
IQuickSyncDecoder* __stdcall createQuickSync()
|
||||
{
|
||||
return new CQuickSync();
|
||||
}
|
||||
|
||||
void __stdcall destroyQuickSync(IQuickSyncDecoder* p)
|
||||
{
|
||||
delete (CQuickSync*)(p);
|
||||
}
|
||||
|
||||
void __stdcall getVersion(char* ver, const char** license)
|
||||
{
|
||||
strcpy(ver, QS_DEC_VERSION " by Eric Gur. Compiled using MSVC 2010 ("__DATE__" "__TIME__")");
|
||||
*license = "(C) 2011 Intel\xae Corp.";
|
||||
}
|
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "QuickSync_defs.h"
|
||||
#include "CodecInfo.h"
|
||||
|
||||
// gpu_memcpy is a memcpy style function that copied data very fast from a
|
||||
// GPU tiled memory (write back)
|
||||
// Performance tip: page offset (12 lsb) of both addresses should be different
|
||||
// optimally use a 2K offset between them.
|
||||
void* gpu_memcpy(void* d, const void* s, size_t size)
|
||||
{
|
||||
if (d == NULL || s == NULL) return NULL;
|
||||
|
||||
//if memory is not aligned, use memcpy
|
||||
bool isAligned = (((size_t)(s) | (size_t)(d)) & 0xF) == 0;
|
||||
if (!isAligned)
|
||||
{
|
||||
return memcpy(d, s, size);
|
||||
}
|
||||
|
||||
size_t reminder = size & 127; // copy 128 bytes every loop
|
||||
size_t end = 0;
|
||||
|
||||
__m128i* pTrg = (__m128i*)d;
|
||||
__m128i* pTrgEnd = pTrg + ((size - reminder) >> 4);
|
||||
__m128i* pSrc = (__m128i*)s;
|
||||
|
||||
// make sure source is synced - doesn't hurt if not needed.
|
||||
_mm_sfence();
|
||||
|
||||
// split main loop to 32 and 64 bit code
|
||||
// 64 doesn't have inline assembly and assembly code is faster.
|
||||
// TODO: write a pure ASM function for the 64 bit verrsion.
|
||||
#ifdef _M_X64
|
||||
while (pTrg < pTrgEnd)
|
||||
{
|
||||
// Emits the Streaming SIMD Extensions 4 (SSE4) instruction movntdqa
|
||||
// fastest method for copying GPU RAM
|
||||
pTrg[0] = _mm_stream_load_si128(&pSrc[0]);
|
||||
pTrg[1] = _mm_stream_load_si128(&pSrc[1]);
|
||||
pTrg[2] = _mm_stream_load_si128(&pSrc[2]);
|
||||
pTrg[3] = _mm_stream_load_si128(&pSrc[3]);
|
||||
pTrg[4] = _mm_stream_load_si128(&pSrc[4]);
|
||||
pTrg[5] = _mm_stream_load_si128(&pSrc[5]);
|
||||
pTrg[6] = _mm_stream_load_si128(&pSrc[6]);
|
||||
pTrg[7] = _mm_stream_load_si128(&pSrc[7]);
|
||||
pSrc += 8;
|
||||
pTrg += 8;
|
||||
}
|
||||
#else // end of 64 bit code
|
||||
__asm
|
||||
{
|
||||
mov ecx, pSrc;
|
||||
mov edx, pTrg;
|
||||
mov eax, pTrgEnd;
|
||||
|
||||
// test ending condition
|
||||
cmp edx, eax; // if (pTrgEnd >= pTrg) goto endLoop
|
||||
jae endLoop;
|
||||
startLoop:
|
||||
movntdqa xmm0, [ecx];
|
||||
movdqa [edx], xmm0;
|
||||
movntdqa xmm1, [ecx + 16];
|
||||
movdqa [edx + 16], xmm1;
|
||||
movntdqa xmm2, [ecx + 32];
|
||||
movdqa [edx + 32], xmm2;
|
||||
movntdqa xmm3, [ecx + 48];
|
||||
movdqa [edx + 48], xmm3;
|
||||
movntdqa xmm4, [ecx + 64];
|
||||
movdqa [edx + 64], xmm4;
|
||||
movntdqa xmm5, [ecx + 80];
|
||||
movdqa [edx + 80], xmm5;
|
||||
movntdqa xmm6, [ecx + 96];
|
||||
movdqa [edx + 96], xmm6;
|
||||
movntdqa xmm7, [ecx + 112];
|
||||
movdqa [edx + 112], xmm7;
|
||||
add edx, 128;
|
||||
add ecx, 128;
|
||||
cmp edx, eax; // if (pTrgEnd > pTrg) goto startLoop
|
||||
jb startLoop;
|
||||
endLoop:
|
||||
}
|
||||
|
||||
pTrg = pTrgEnd;
|
||||
pSrc += (size - reminder) >> 4;
|
||||
|
||||
#endif // end of 32 bit code
|
||||
|
||||
// copy in 16 byte steps
|
||||
if (reminder >= 16)
|
||||
{
|
||||
size = reminder;
|
||||
reminder = size & 15;
|
||||
end = size >> 4;
|
||||
for (size_t i = 0; i < end; ++i)
|
||||
{
|
||||
pTrg[i] = _mm_stream_load_si128(&pSrc[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// copy last bytes
|
||||
if (reminder)
|
||||
{
|
||||
__m128i temp = _mm_stream_load_si128(pSrc + end);
|
||||
|
||||
char* ps = (char*)(&temp);
|
||||
char* pt = (char*)(pTrg + end);
|
||||
|
||||
for (size_t i = 0; i < reminder; ++i)
|
||||
{
|
||||
pt[i] = ps[i];
|
||||
}
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
#pragma pack(push, 8)
|
||||
typedef struct tagTHREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; // Must be 0x1000.
|
||||
LPCSTR szName; // Pointer to name (in user addr space).
|
||||
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||
} THREADNAME_INFO;
|
||||
#pragma pack(pop)
|
||||
|
||||
/*
|
||||
Renames current thread. Useful for identifying a thread in VS.
|
||||
*/
|
||||
void SetThreadName(LPCSTR szThreadName, DWORD dwThreadID)
|
||||
{
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = szThreadName;
|
||||
info.dwThreadID = -1;
|
||||
info.dwFlags = 0;
|
||||
|
||||
__try
|
||||
{
|
||||
#define MS_VC_EXCEPTION 0x406D1388
|
||||
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info);
|
||||
}
|
||||
__except(EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void DebugAssert(const TCHAR* pCondition,const TCHAR* pFileName, int iLine)
|
||||
{
|
||||
TCHAR szInfo[256];
|
||||
_stprintf(szInfo, _T("%s \nAt line %d of %s\nContinue? (Cancel to debug)"), pCondition, iLine, pFileName);
|
||||
|
||||
int msgId = MessageBox(NULL, szInfo, _T("ASSERT Failed"),
|
||||
MB_SYSTEMMODAL | MB_ICONHAND | MB_YESNOCANCEL | MB_SETFOREGROUND);
|
||||
switch (msgId)
|
||||
{
|
||||
case IDNO: /* Kill the application */
|
||||
FatalAppExit(FALSE, _T("Application terminated"));
|
||||
break;
|
||||
|
||||
case IDCANCEL: /* Break into the debugger */
|
||||
DebugBreak();
|
||||
break;
|
||||
|
||||
case IDYES: /* Ignore assertion continue execution */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //_DEBUG
|
||||
|
||||
// Finds greatest common denominator
|
||||
mfxU32 GCD(mfxU32 a, mfxU32 b)
|
||||
{
|
||||
if (0 == a)
|
||||
return b;
|
||||
else if (0 == b)
|
||||
return a;
|
||||
|
||||
mfxU32 a1, b1;
|
||||
|
||||
if (a >= b)
|
||||
{
|
||||
a1 = a;
|
||||
b1 = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
a1 = b;
|
||||
b1 = a;
|
||||
}
|
||||
|
||||
// a1 >= b1;
|
||||
mfxU32 r = a1 % b1;
|
||||
|
||||
while (0 != r)
|
||||
{
|
||||
a1 = b1;
|
||||
b1 = r;
|
||||
r = a1 % b1;
|
||||
}
|
||||
|
||||
return b1;
|
||||
}
|
||||
|
||||
mfxStatus PARtoDAR(DWORD parw, DWORD parh, DWORD w, DWORD h, DWORD& darw, DWORD& darh)
|
||||
{
|
||||
MSDK_CHECK_ERROR(parw, 0, MFX_ERR_UNDEFINED_BEHAVIOR);
|
||||
MSDK_CHECK_ERROR(parh, 0, MFX_ERR_UNDEFINED_BEHAVIOR);
|
||||
MSDK_CHECK_ERROR(w, 0, MFX_ERR_UNDEFINED_BEHAVIOR);
|
||||
MSDK_CHECK_ERROR(h, 0, MFX_ERR_UNDEFINED_BEHAVIOR);
|
||||
|
||||
mfxU32 reduced_w = 0, reduced_h = 0;
|
||||
mfxU32 gcd = GCD(w, h);
|
||||
|
||||
// Divide by greatest common divisor
|
||||
reduced_w = w / gcd;
|
||||
reduced_h = h / gcd;
|
||||
|
||||
darw = reduced_w * parw;
|
||||
darh = reduced_h * parh;
|
||||
gcd = GCD(darw, darh);
|
||||
|
||||
darh /= gcd;
|
||||
darw /= gcd;
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus DARtoPAR(mfxU32 darw, mfxU32 darh, mfxU32 w, mfxU32 h, mfxU16& parw, mfxU16& parh)
|
||||
{
|
||||
MSDK_CHECK_ERROR(darw, 0, MFX_ERR_UNDEFINED_BEHAVIOR);
|
||||
MSDK_CHECK_ERROR(darh, 0, MFX_ERR_UNDEFINED_BEHAVIOR);
|
||||
MSDK_CHECK_ERROR(w, 0, MFX_ERR_UNDEFINED_BEHAVIOR);
|
||||
MSDK_CHECK_ERROR(h, 0, MFX_ERR_UNDEFINED_BEHAVIOR);
|
||||
|
||||
mfxU16 reduced_w = 0, reduced_h = 0;
|
||||
mfxU32 gcd = GCD(w, h);
|
||||
|
||||
// Divide by greatest common divisor to fit into mfxU16
|
||||
reduced_w = (mfxU16) (w / gcd);
|
||||
reduced_h = (mfxU16) (h / gcd);
|
||||
|
||||
// for mpeg2 we need to set exact values for par (standard supports only dar 4:3, 16:9, 221:100, 1:1)
|
||||
if (darw * 3 == darh * 4)
|
||||
{
|
||||
parw = 4 * reduced_h;
|
||||
parh = 3 * reduced_w;
|
||||
}
|
||||
else if (darw * 9 == darh * 16)
|
||||
{
|
||||
parw = 16 * reduced_h;
|
||||
parh = 9 * reduced_w;
|
||||
}
|
||||
else if (darw * 100 == darh * 221)
|
||||
{
|
||||
parw = 221 * reduced_h;
|
||||
parh = 100 * reduced_w;
|
||||
}
|
||||
else if (darw == darh)
|
||||
{
|
||||
parw = reduced_h;
|
||||
parh = reduced_w;
|
||||
}
|
||||
else
|
||||
{
|
||||
parw = (mfxU16)((DOUBLE)(darw * reduced_h) / (darh * reduced_w) * 1000);
|
||||
parh = 1000;
|
||||
}
|
||||
|
||||
// Reduce ratio
|
||||
gcd = GCD(parw, parh);
|
||||
parw /= (mfxU16)gcd;
|
||||
parh /= (mfxU16)gcd;
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
void CopyBitstream(const mfxBitstream& src, mfxBitstream& trg)
|
||||
{
|
||||
memcpy(&trg, &src, sizeof(mfxBitstream));
|
||||
trg.Data = new mfxU8[src.DataLength];
|
||||
memcpy(trg.Data, src.Data, src.DataLength);
|
||||
}
|
||||
|
||||
const char* GetCodecName(DWORD codec)
|
||||
{
|
||||
switch(codec)
|
||||
{
|
||||
case MFX_CODEC_AVC: return "AVC";
|
||||
case MFX_CODEC_MPEG2: return "MPEG2";
|
||||
case MFX_CODEC_VC1: return "VC1";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char* GetProfileName(DWORD codec, DWORD profile)
|
||||
{
|
||||
switch(codec)
|
||||
{
|
||||
case MFX_CODEC_AVC:
|
||||
switch(profile)
|
||||
{
|
||||
case QS_PROFILE_H264_BASELINE: return "Baseline";
|
||||
case QS_PROFILE_H264_CONSTRAINED_BASELINE: return "Constrained Baseline";
|
||||
case QS_PROFILE_H264_MAIN: return "Main";
|
||||
case QS_PROFILE_H264_EXTENDED: return "Extended";
|
||||
case QS_PROFILE_H264_HIGH: return "High";
|
||||
case QS_PROFILE_H264_HIGH_10: return "High 10";
|
||||
case QS_PROFILE_H264_HIGH_10_INTRA: return "High 10 Intra";
|
||||
case QS_PROFILE_H264_HIGH_422: return "High 4:2:2";
|
||||
case QS_PROFILE_H264_HIGH_422_INTRA: return "High 4:2:2 Intra";
|
||||
case QS_PROFILE_H264_HIGH_444: return "High 4:4:4";
|
||||
case QS_PROFILE_H264_HIGH_444_PREDICTIVE: return "High 4:4:4 Preditive";
|
||||
case QS_PROFILE_H264_HIGH_444_INTRA: return "High 4:4:4 Intra";
|
||||
case QS_PROFILE_H264_CAVLC_444: return "CAVLC 4:4:4 Intra";
|
||||
case QS_PROFILE_H264_MULTIVIEW_HIGH: return "Multi View High";
|
||||
case QS_PROFILE_H264_STEREO_HIGH: return "Stereo High";
|
||||
}
|
||||
break;
|
||||
|
||||
case MFX_CODEC_MPEG2:
|
||||
switch(profile)
|
||||
{
|
||||
case QS_PROFILE_MPEG2_422: return "4:2:2";
|
||||
case QS_PROFILE_MPEG2_HIGH: return "High";
|
||||
case QS_PROFILE_MPEG2_SPATIALLY_SCALABLE: return "Spatially Scalable";
|
||||
case QS_PROFILE_MPEG2_SNR_SCALABLE: return "SNR Scalable";
|
||||
case QS_PROFILE_MPEG2_MAIN: return "Main";
|
||||
case QS_PROFILE_MPEG2_SIMPLE: return "Simple";
|
||||
}
|
||||
break;
|
||||
|
||||
case MFX_CODEC_VC1:
|
||||
switch(profile)
|
||||
{
|
||||
case QS_PROFILE_VC1_SIMPLE: return "Simple";
|
||||
case QS_PROFILE_VC1_MAIN: return "Main";
|
||||
case QS_PROFILE_VC1_COMPLEX: return "Complex";
|
||||
case QS_PROFILE_VC1_ADVANCED: return "Advanced";
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
void* gpu_memcpy(void* d, const void* s, size_t _size);
|
||||
mfxU32 GCD(mfxU32 a, mfxU32 b);
|
||||
mfxStatus PARtoDAR(DWORD parw, DWORD parh, DWORD w, DWORD h, DWORD& darw, DWORD& darh);
|
||||
mfxStatus DARtoPAR(mfxU32 darw, mfxU32 darh, mfxU32 w, mfxU32 h, mfxU16& parw, mfxU16& parh);
|
||||
void CopyBitstream(const mfxBitstream& src, mfxBitstream& trg);
|
||||
const char* GetCodecName(DWORD codec);
|
||||
const char* GetProfileName(DWORD codec, DWORD profile);
|
||||
|
||||
#ifdef _DEBUG
|
||||
void SetThreadName(LPCSTR szThreadName, DWORD dwThreadID = -1 /* current thread */);
|
||||
void DebugAssert(const TCHAR *pCondition,const TCHAR *pFileName, int iLine);
|
||||
#endif
|
||||
|
||||
// wrapper for whatever critical section we have
|
||||
class CQsLock
|
||||
{
|
||||
public:
|
||||
CQsLock() { InitializeCriticalSection(&m_CritSec); }
|
||||
~CQsLock() { DeleteCriticalSection(&m_CritSec); }
|
||||
void Lock() { EnterCriticalSection(&m_CritSec); }
|
||||
void Unlock() { LeaveCriticalSection(&m_CritSec); }
|
||||
|
||||
protected:
|
||||
// make copy constructor and assignment operator inaccessible
|
||||
DISALLOW_COPY_AND_ASSIGN(CQsLock)
|
||||
// CQsLock(const CQsLock&);
|
||||
// CQsLock& operator=(const CQsLock &);
|
||||
|
||||
CRITICAL_SECTION m_CritSec;
|
||||
};
|
||||
|
||||
// locks a critical section, and unlocks it automatically
|
||||
// when the lock goes out of scope
|
||||
class CQsAutoLock
|
||||
{
|
||||
protected:
|
||||
CQsLock * m_pLock;
|
||||
|
||||
public:
|
||||
CQsAutoLock(CQsLock* plock)
|
||||
{
|
||||
m_pLock = plock;
|
||||
if (m_pLock != NULL)
|
||||
m_pLock->Lock();
|
||||
}
|
||||
|
||||
~CQsAutoLock()
|
||||
{
|
||||
if (m_pLock != NULL)
|
||||
m_pLock->Unlock();
|
||||
}
|
||||
|
||||
// make copy constructor and assignment operator inaccessible
|
||||
CQsAutoLock(const CQsAutoLock &refAutoLock);
|
||||
CQsAutoLock &operator=(const CQsAutoLock &refAutoLock);
|
||||
};
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MSDK_DEC_WAIT_INTERVAL 60000
|
||||
#define MSDK_ENC_WAIT_INTERVAL 10000
|
||||
#define MSDK_VPP_WAIT_INTERVAL 60000
|
||||
#define MSDK_WAIT_INTERVAL MSDK_DEC_WAIT_INTERVAL + 3 * MSDK_VPP_WAIT_INTERVAL + MSDK_ENC_WAIT_INTERVAL // an estimate for the longest pipeline we have in samples
|
||||
|
||||
#define MSDK_INVALID_SURF_IDX 0xFFFF
|
||||
|
||||
#define MSDK_MAX_FILENAME_LEN 1024
|
||||
|
||||
#ifndef countof
|
||||
# define countof(array) (size_t)(sizeof(array)/sizeof(array[0]))
|
||||
#endif
|
||||
|
||||
#define MSDK_PRINT_RET_MSG(ERR) \
|
||||
{\
|
||||
TCHAR msg[1024]; \
|
||||
_stprintf_s(msg, countof(msg), _T("\nReturn on error: error code %d,\t%s\t%d\n\n"), ERR, _T(__FILE__), __LINE__); \
|
||||
OutputDebugString(msg); \
|
||||
_tperror(msg);\
|
||||
}
|
||||
#define MSDK_CHECK_ERROR(P, X, ERR) { if ((X) == (P)) { MSDK_PRINT_RET_MSG(ERR); return ERR; } }
|
||||
#define MSDK_CHECK_NOT_EQUAL(P, X, ERR) { if ((X) != (P)) { MSDK_PRINT_RET_MSG(ERR); return ERR; } }
|
||||
#define MSDK_CHECK_RESULT_P_RET(P, X) { if ((X) != (P)) { return P; } }
|
||||
#define MSDK_CHECK_POINTER(P, ERR) { if (!(P)) { return ERR;}}
|
||||
#define MSDK_CHECK_POINTER_NO_RET(P) { if (!(P)) { return; } }
|
||||
#define MSDK_IGNORE_MFX_STS(P, X) { if ((X) == (P)) { P = MFX_ERR_NONE; } }
|
||||
|
||||
#define MSDK_SAFE_DELETE(P) { delete P; P = NULL; }
|
||||
#define MSDK_SAFE_DELETE_ARRAY(P) { delete[] P; P = NULL; }
|
||||
#define MSDK_SAFE_RELEASE(P) { if (P) { P->Release(); P = NULL; } }
|
||||
|
||||
#define MSDK_ZERO_MEMORY(P, S) { memset(P, 0, S);}
|
||||
#define MSDK_ZERO_VAR(VAR) { memset(&VAR, 0, sizeof(VAR)); }
|
||||
#define MSDK_ALIGN16(SZ) ((SZ + 15) & (~15)) // round up to a multiple of 16
|
||||
#define MSDK_ALIGN32(SZ) ((SZ + 31) & (~31)) // round up to a multiple of 32
|
||||
#define MSDK_ARRAY_LEN(value) (sizeof(value) / sizeof(value[0]))
|
||||
|
||||
#ifdef _DEBUG
|
||||
# define ASSERT(_x_) { if (!(_x_)) DebugAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__); }
|
||||
#else
|
||||
# define ASSERT(x)
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
# define MSDK_TRACE(_format, ...) \
|
||||
{ \
|
||||
char msg[256]; \
|
||||
_snprintf_s(msg, MSDK_ARRAY_LEN(msg), MSDK_ARRAY_LEN(msg) - 1, _format, __VA_ARGS__); \
|
||||
OutputDebugStringA(msg); \
|
||||
}
|
||||
#else
|
||||
# define MSDK_TRACE(_format, ...)
|
||||
#endif
|
||||
|
||||
// A macro to disallow the copy constructor and operator= functions
|
||||
// This should be used in the private: declarations for a class
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&);
|
||||
|
||||
//
|
||||
// FourCC
|
||||
//
|
||||
|
||||
// VC1
|
||||
#define FOURCC_VC1 mmioFOURCC('W','V','C','1')
|
||||
#define FOURCC_WMV3 mmioFOURCC('W','M','V','3')
|
||||
|
||||
//MPEG2
|
||||
#define FOURCC_mpg2 mmioFOURCC('m','p','g','2')
|
||||
#define FOURCC_MPG2 mmioFOURCC('M','P','G','2')
|
||||
|
||||
//H264
|
||||
#define FOURCC_H264 mmioFOURCC('H','2','6','4')
|
||||
#define FOURCC_X264 mmioFOURCC('X','2','6','4')
|
||||
#define FOURCC_h264 mmioFOURCC('h','2','6','4')
|
||||
#define FOURCC_avc1 mmioFOURCC('a','v','c','1')
|
||||
#define FOURCC_VSSH mmioFOURCC('V','S','S','H')
|
||||
#define FOURCC_DAVC mmioFOURCC('D','A','V','C')
|
||||
#define FOURCC_PAVC mmioFOURCC('P','A','V','C')
|
||||
#define FOURCC_AVC1 mmioFOURCC('A','V','C','1')
|
||||
|
||||
// compatibility with SDK v2.0
|
||||
#ifndef MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET
|
||||
# define MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET MFX_MEMTYPE_DXVA2_DECODER_TARGET
|
||||
#endif
|
||||
|
||||
#ifndef MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET
|
||||
# define MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET
|
||||
#endif
|
||||
|
||||
#ifndef MFX_HANDLE_D3D9_DEVICE_MANAGER
|
||||
# define MFX_HANDLE_D3D9_DEVICE_MANAGER MFX_HANDLE_DIRECT3D_DEVICE_MANAGER9
|
||||
#endif
|
||||
|
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "QuickSync_defs.h"
|
||||
#include "QuickSyncUtils.h"
|
||||
#include "TimeManager.h"
|
||||
|
||||
using namespace std;
|
||||
// returns true if value is between upper and lower bounds (inclusive)
|
||||
#define InRange(val, lb, up) ( (val) <= (up) && (val) >= (lb))
|
||||
#define GetSampleRefTime(s) CDecTimeManager::ConvertMFXTime2ReferenceTime((s)->Data.TimeStamp)
|
||||
|
||||
const double CDecTimeManager::fps2997 = 30.0 * 1000.0 / 1001.0;
|
||||
const double CDecTimeManager::fps23976 = 24.0 * 1000.0 / 1001.0;
|
||||
|
||||
void CDecTimeManager::Reset()
|
||||
{
|
||||
m_nOutputFrames = -1;
|
||||
m_nSegmentSampleCount = 0;
|
||||
m_TimeStampQueue.clear();
|
||||
m_OutputTimeStamps.clear();
|
||||
m_bValidFrameRate = false;
|
||||
m_nLastSeenFieldDoubling = 0;
|
||||
m_rtPrevStart = INVALID_REFTIME;
|
||||
m_bIsSampleInFields = false;
|
||||
SetInverseTelecine(false);
|
||||
}
|
||||
|
||||
void CDecTimeManager::AddTimeStamp(IMediaSample* pSample)
|
||||
{
|
||||
REFERENCE_TIME rtStart, rtStop;
|
||||
HRESULT hr = pSample->GetTime(&rtStart, &rtStop);
|
||||
|
||||
if (S_OK != hr && VFW_S_NO_STOP_TIME != hr)
|
||||
{
|
||||
rtStart = INVALID_REFTIME;
|
||||
}
|
||||
|
||||
PushTimeStamp(m_nSegmentSampleCount++, rtStart);
|
||||
}
|
||||
|
||||
bool CDecTimeManager::CalcFrameRate(const mfxFrameSurface1* pSurface,
|
||||
const std::deque<mfxFrameSurface1*>& queue)
|
||||
{
|
||||
if (m_bValidFrameRate)
|
||||
return true;
|
||||
|
||||
m_dFrameRate = m_dOrigFrameRate;
|
||||
|
||||
// first thing, find if the time stamps are PTS (presentation) or DTS (decoding).
|
||||
// PTS time stamps are monotonic.
|
||||
// this is important for deriving correct time stamp in GetSampleTimeStamp
|
||||
REFERENCE_TIME rtCurrent = GetSampleRefTime(pSurface);
|
||||
m_bIsPTS = true;
|
||||
REFERENCE_TIME prevStart = rtCurrent;
|
||||
for (auto it = queue.begin(); it != queue.end(); ++it)
|
||||
{
|
||||
const REFERENCE_TIME& rtStart = GetSampleRefTime(*it);
|
||||
if (INVALID_REFTIME != prevStart)
|
||||
{
|
||||
// not montonic:
|
||||
if (rtStart < prevStart)
|
||||
{
|
||||
m_bIsPTS = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
prevStart = rtStart;
|
||||
}
|
||||
|
||||
// check validity of time stamps
|
||||
set<REFERENCE_TIME> sampleTimesSet;
|
||||
int duplicates = 0, invalids = 0;
|
||||
|
||||
if (rtCurrent != INVALID_REFTIME)
|
||||
{
|
||||
sampleTimesSet.insert(rtCurrent);
|
||||
}
|
||||
else
|
||||
{
|
||||
++invalids;
|
||||
}
|
||||
|
||||
for (auto it = queue.begin(); it != queue.end(); ++it)
|
||||
{
|
||||
REFERENCE_TIME rtStart = GetSampleRefTime(*it);
|
||||
if (rtStart != INVALID_REFTIME)
|
||||
{
|
||||
// note: insert return pair<iterator, bool>. the bool field is true when item was added. otherwise false (item exists)
|
||||
duplicates += (false == (sampleTimesSet.insert(rtStart)).second);
|
||||
}
|
||||
else
|
||||
{
|
||||
++invalids;
|
||||
}
|
||||
}
|
||||
|
||||
double avgFrameRate = m_dFrameRate;
|
||||
|
||||
// need enough samples for average frame rate calculation
|
||||
if (sampleTimesSet.size() > 8)
|
||||
{
|
||||
// find average frame rate (ignore current frame - sometimes wrong values):
|
||||
REFERENCE_TIME rtStart = *(sampleTimesSet.begin()); // lowest
|
||||
REFERENCE_TIME rtStop = *(sampleTimesSet.rbegin()); // highest time stamp
|
||||
|
||||
// TODO: account for newest frames being invalid or duplicates
|
||||
avgFrameRate = (1e7 * (m_OutputTimeStamps.size() - 1)) / // multiply by the count of all frames -1
|
||||
(double)(rtStop - rtStart);
|
||||
}
|
||||
|
||||
// got something that look like a valid frame rate.
|
||||
// check if this is related to the actual time stamps.
|
||||
if (m_dFrameRate > 1.0)
|
||||
{
|
||||
// check if samples are inputted as fields not frames. frame rate might be artificially doubled
|
||||
if (InRange(m_dFrameRate, avgFrameRate * 1.9, avgFrameRate * 2.1) &&
|
||||
pSurface->Info.PicStruct != MFX_PICSTRUCT_PROGRESSIVE)
|
||||
{
|
||||
m_dFrameRate /= 2;
|
||||
}
|
||||
|
||||
// need extra handling?
|
||||
}
|
||||
// use original time stamps
|
||||
else if (m_bIsPTS)
|
||||
{
|
||||
m_dFrameRate = 0;
|
||||
}
|
||||
// need to calc frame rate :(
|
||||
// this isn't optimal.
|
||||
else
|
||||
{
|
||||
// use average frame rate
|
||||
m_dFrameRate = avgFrameRate;
|
||||
}
|
||||
|
||||
m_bValidFrameRate = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDecTimeManager::SetInverseTelecine(bool bIvtc)
|
||||
{
|
||||
// nothing changed
|
||||
bIvtc = bIvtc && m_bEnableIvtc;
|
||||
|
||||
if (bIvtc == m_bIvtc)
|
||||
return;
|
||||
|
||||
m_bIvtc = bIvtc;
|
||||
if (m_bIvtc)
|
||||
{
|
||||
FixFrameRate(fps23976);
|
||||
}
|
||||
else
|
||||
{
|
||||
FixFrameRate(fps2997);
|
||||
}
|
||||
}
|
||||
|
||||
REFERENCE_TIME CDecTimeManager::PopTimeStamp()
|
||||
{
|
||||
if (m_TimeStampQueue.empty())
|
||||
return INVALID_REFTIME;
|
||||
|
||||
TTimeStampInfo tsInfo = m_TimeStampQueue.front();
|
||||
m_TimeStampQueue.pop_front();
|
||||
return tsInfo.rtStart;
|
||||
}
|
||||
|
||||
bool CDecTimeManager::GetSampleTimeStamp(const mfxFrameSurface1* pSurface,
|
||||
const std::deque<mfxFrameSurface1*>& queue,
|
||||
REFERENCE_TIME& rtStart,
|
||||
REFERENCE_TIME& rtStop)
|
||||
{
|
||||
if (!m_bValidFrameRate)
|
||||
{
|
||||
CalcFrameRate(pSurface, queue);
|
||||
}
|
||||
|
||||
bool bFieldDoubling = (0 != (pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED));
|
||||
const REFERENCE_TIME rtDecoder = GetSampleRefTime(pSurface);
|
||||
rtStop = INVALID_REFTIME;
|
||||
|
||||
++m_nLastSeenFieldDoubling;
|
||||
|
||||
// Enter inverse telecine mode
|
||||
if (bFieldDoubling)
|
||||
{
|
||||
SetInverseTelecine(true);
|
||||
m_nLastSeenFieldDoubling = 0;
|
||||
}
|
||||
// Return to normal frame rate due to content change
|
||||
// allow a 1 second grace for the stream to revert to ivtc
|
||||
else if (m_nLastSeenFieldDoubling > 1) //m_dFrameRate)
|
||||
{
|
||||
SetInverseTelecine(false);
|
||||
}
|
||||
|
||||
++m_nOutputFrames;
|
||||
if (m_TimeStampQueue.size() > 100)
|
||||
PopTimeStamp();
|
||||
|
||||
// Can't start the sequence - drop frame
|
||||
if (rtDecoder == INVALID_REFTIME && m_rtPrevStart == INVALID_REFTIME)
|
||||
{
|
||||
rtStart = rtStop = INVALID_REFTIME;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find smallest valid time stamp for first frame
|
||||
rtStart = rtDecoder;
|
||||
|
||||
// First frame in a new frame sequence (first frame after a stop or a seek)
|
||||
// should always be a keyframe
|
||||
if (m_rtPrevStart == INVALID_REFTIME)
|
||||
{
|
||||
// Presentation time stamps (PTS).
|
||||
// Time stamp should be OK (in presentation order)
|
||||
if (m_bIsPTS)
|
||||
{
|
||||
// Easy case - rtDecoder is the time stamp to use
|
||||
if (rtDecoder != INVALID_REFTIME)
|
||||
{
|
||||
rtStart = rtDecoder;
|
||||
auto it = m_OutputTimeStamps.find(rtDecoder);
|
||||
|
||||
ASSERT(it != m_OutputTimeStamps.end());
|
||||
if (it != m_OutputTimeStamps.end())
|
||||
{
|
||||
m_OutputTimeStamps.erase(it);
|
||||
}
|
||||
}
|
||||
// Need to calculate time stamp from future frames
|
||||
else if (!m_OutputTimeStamps.empty())
|
||||
{
|
||||
size_t count = 0;
|
||||
|
||||
// Note - m_OutputTimeStamps contains only valid time stamps - take the smallest
|
||||
rtStart = *(m_OutputTimeStamps.begin());
|
||||
|
||||
// Find distance from current sample
|
||||
for (auto it = queue.begin(); it != queue.end(); ++it)
|
||||
{
|
||||
++count;
|
||||
REFERENCE_TIME t = GetSampleRefTime(*it);
|
||||
if (rtStart == t)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Take negative offset from this future time stamp
|
||||
rtStart = rtStart - (REFERENCE_TIME)(0.5 + (1e7 * count) / m_dFrameRate);
|
||||
}
|
||||
// Can't derive time stamp, frame will be dropped :(
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Decoding time stamps (DTS) - a little tricky, might not be 100%
|
||||
else
|
||||
{
|
||||
// Note - m_OutputTimeStamps contains only valid time stamps - take the smallest
|
||||
if (!m_OutputTimeStamps.empty())
|
||||
{
|
||||
auto it = m_OutputTimeStamps.begin();
|
||||
rtStart = *(it);
|
||||
m_OutputTimeStamps.erase(it);
|
||||
}
|
||||
// Can't derive time stamp, frame will be dropped :(
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 2nd and above frames
|
||||
else
|
||||
{
|
||||
// Check if frame rate has changed
|
||||
double tmpFrameRate;
|
||||
if (CalcCurrentFrameRate(tmpFrameRate, 1 + queue.size()))
|
||||
{
|
||||
FixFrameRate(tmpFrameRate);
|
||||
}
|
||||
|
||||
if (m_dFrameRate > 0 || INVALID_REFTIME == rtDecoder)
|
||||
{
|
||||
rtStart = m_rtPrevStart + (REFERENCE_TIME)(0.5 + 1e7 / m_dFrameRate);
|
||||
auto it = m_OutputTimeStamps.begin();
|
||||
if (it != m_OutputTimeStamps.end())
|
||||
{
|
||||
REFERENCE_TIME rtTemp = *(it);
|
||||
if (rtTemp < rtStart || abs(rtTemp - rtStart) < 25000) // diff is less than 2.5ms
|
||||
{
|
||||
m_OutputTimeStamps.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = m_OutputTimeStamps.begin();
|
||||
if (it != m_OutputTimeStamps.end())
|
||||
{
|
||||
rtStart = *it;
|
||||
m_OutputTimeStamps.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
rtStart = INVALID_REFTIME;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
rtStop = rtStart + 1;
|
||||
m_rtPrevStart = rtStart;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDecTimeManager::AddOutputTimeStamp(mfxFrameSurface1* pSurface)
|
||||
{
|
||||
REFERENCE_TIME rtStart = ConvertMFXTime2ReferenceTime(pSurface->Data.TimeStamp);
|
||||
if (rtStart != INVALID_REFTIME)
|
||||
{
|
||||
m_OutputTimeStamps.insert(rtStart);
|
||||
}
|
||||
}
|
||||
|
||||
void CDecTimeManager::OnVideoParamsChanged(double frameRate)
|
||||
{
|
||||
if (frameRate < 1)
|
||||
return;
|
||||
|
||||
FixFrameRate(frameRate);
|
||||
|
||||
// When this event happens we leave ivtc.
|
||||
SetInverseTelecine(false);
|
||||
}
|
||||
|
||||
void CDecTimeManager::FixFrameRate(double frameRate)
|
||||
{
|
||||
// Too close - probably inaccurate calculations
|
||||
if (fabs(m_dFrameRate - frameRate) < 0.001)
|
||||
return;
|
||||
|
||||
// Modify previous time stamp to reflect frame rate change
|
||||
if (m_dFrameRate > 1 && m_rtPrevStart != INVALID_REFTIME)
|
||||
{
|
||||
m_rtPrevStart += (REFERENCE_TIME)(0.5 + 1e7 / m_dFrameRate);
|
||||
m_rtPrevStart -= (REFERENCE_TIME)(0.5 + 1e7 / frameRate);
|
||||
}
|
||||
|
||||
m_dFrameRate = frameRate;
|
||||
}
|
||||
|
||||
bool CDecTimeManager::CalcCurrentFrameRate(double& tmpFrameRate, size_t nQueuedFrames)
|
||||
{
|
||||
tmpFrameRate = 0;
|
||||
size_t len = m_OutputTimeStamps.size();
|
||||
|
||||
// Need enough frames and that the time stamps are all valid.
|
||||
if (len < 4 || nQueuedFrames > len)
|
||||
return false;
|
||||
|
||||
vector<REFERENCE_TIME> deltaTimes;
|
||||
REFERENCE_TIME prev = INVALID_REFTIME;
|
||||
for (auto it = m_OutputTimeStamps.begin(); it != m_OutputTimeStamps.end(); ++it)
|
||||
{
|
||||
if (INVALID_REFTIME == prev)
|
||||
{
|
||||
prev = *it;
|
||||
}
|
||||
else
|
||||
{
|
||||
REFERENCE_TIME t = *it ;
|
||||
deltaTimes.push_back(t - prev);
|
||||
prev = t;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for consistency
|
||||
len = deltaTimes.size();
|
||||
REFERENCE_TIME d = deltaTimes[0];
|
||||
bool accurateFR = true;
|
||||
for (size_t i = 1; i < len; ++i)
|
||||
{
|
||||
// Check if less than 1ms apart
|
||||
// Note: many times time stamps are rounded to the nearest ms.
|
||||
if (abs(d - deltaTimes[i]) > 12000)
|
||||
{
|
||||
accurateFR = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Can't measure accurately...
|
||||
if (!accurateFR)
|
||||
return false;
|
||||
|
||||
tmpFrameRate = (1e7 * len) / (*m_OutputTimeStamps.rbegin() - *m_OutputTimeStamps.begin());
|
||||
if (fabs(tmpFrameRate - m_dFrameRate) > 1)
|
||||
{
|
||||
// Fine tune the frame rate
|
||||
// Try NTSC ranges
|
||||
if (InRange(m_dFrameRate, 59.93, 59.95) || InRange(m_dFrameRate, 29.96, 29.98) || InRange(m_dFrameRate, 23.96, 23.98))
|
||||
{
|
||||
if (InRange(tmpFrameRate, 28.0, 32.0))
|
||||
{
|
||||
tmpFrameRate = fps2997;
|
||||
}
|
||||
else if (InRange(tmpFrameRate, 22.0, 26.0))
|
||||
{
|
||||
tmpFrameRate = fps23976;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpFrameRate = floor(tmpFrameRate + 0.5);
|
||||
}
|
||||
}
|
||||
// PC/PAL ranges
|
||||
else
|
||||
{
|
||||
tmpFrameRate = floor(tmpFrameRate + 0.5);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MFX_TIME_STAMP_FREQUENCY 90000L
|
||||
#define MFX_TIME_STAMP_INVALID (mfxU64)(-1)
|
||||
#define MFX_TIME_STAMP_MAX ((mfxI64)100000 * (mfxI64)MFX_TIME_STAMP_FREQUENCY)
|
||||
#define INVALID_REFTIME _I64_MIN
|
||||
|
||||
struct TTimeStampInfo
|
||||
{
|
||||
TTimeStampInfo(int _id = 0, REFERENCE_TIME _rtStart = 0) :
|
||||
id(_id), rtStart(_rtStart)
|
||||
{
|
||||
}
|
||||
|
||||
int id;
|
||||
REFERENCE_TIME rtStart;
|
||||
};
|
||||
|
||||
typedef std::deque<TTimeStampInfo> TTimeStampQueue;
|
||||
typedef std::multiset<REFERENCE_TIME> TSortedTimeStamps;
|
||||
|
||||
|
||||
class CDecTimeManager
|
||||
{
|
||||
public:
|
||||
CDecTimeManager(bool bEnableIvtc = true) : m_dFrameRate(0), m_dOrigFrameRate(0), m_bIvtc(false), m_bEnableIvtc(bEnableIvtc)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
double GetFrameRate() { return m_dFrameRate; }
|
||||
void SetFrameRate(double frameRate, bool bIsFields)
|
||||
{
|
||||
m_dFrameRate = (bIsFields && frameRate < 30.0) ? (frameRate / 2) : frameRate;
|
||||
m_dOrigFrameRate = m_dFrameRate;
|
||||
m_bIsSampleInFields = bIsFields;
|
||||
}
|
||||
|
||||
void Reset();
|
||||
void SetInverseTelecine(bool bIvtc);
|
||||
inline bool GetInverseTelecine() { return m_bIvtc; }
|
||||
inline bool HasValidFrameRate() { return m_bValidFrameRate || m_dFrameRate == 0; }
|
||||
|
||||
static mfxU64 ConvertReferenceTime2MFXTime(REFERENCE_TIME rtTime)
|
||||
{
|
||||
if (-1e7 == rtTime || INVALID_REFTIME == rtTime)
|
||||
return MFX_TIME_STAMP_INVALID;
|
||||
|
||||
return (mfxU64)(((double)rtTime / 1e7) * (double)MFX_TIME_STAMP_FREQUENCY);
|
||||
}
|
||||
|
||||
static REFERENCE_TIME ConvertMFXTime2ReferenceTime(mfxU64 nTime)
|
||||
{
|
||||
if (MFX_TIME_STAMP_INVALID == nTime)
|
||||
return (REFERENCE_TIME)INVALID_REFTIME;
|
||||
|
||||
mfxI64 t = (mfxI64)nTime; // don't lose the sign
|
||||
|
||||
if (t < -MFX_TIME_STAMP_MAX || t > MFX_TIME_STAMP_MAX)
|
||||
return (REFERENCE_TIME)INVALID_REFTIME;
|
||||
|
||||
return (REFERENCE_TIME)(((double)t / (double)MFX_TIME_STAMP_FREQUENCY) * 1e7);
|
||||
}
|
||||
|
||||
void AddTimeStamp(IMediaSample* pSample);
|
||||
void AddOutputTimeStamp(mfxFrameSurface1* pSurface);
|
||||
bool CalcFrameRate(const mfxFrameSurface1* pSurface,
|
||||
const std::deque<mfxFrameSurface1*>& queue);
|
||||
bool GetSampleTimeStamp(const mfxFrameSurface1* pSurface,
|
||||
const std::deque<mfxFrameSurface1*>& queue,
|
||||
REFERENCE_TIME& rtStart,
|
||||
REFERENCE_TIME& rtStop);
|
||||
bool IsSampleInFields() { return m_bIsSampleInFields; }
|
||||
void OnVideoParamsChanged(double frameRate);
|
||||
|
||||
static const double fps2997;
|
||||
static const double fps23976;
|
||||
|
||||
protected:
|
||||
inline void PushTimeStamp(int id, REFERENCE_TIME rtStart)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
TTimeStampInfo t(id, rtStart);
|
||||
m_TimeStampQueue.push_back(t);
|
||||
#endif
|
||||
}
|
||||
|
||||
REFERENCE_TIME PopTimeStamp();
|
||||
void FixFrameRate(double frameRate);
|
||||
bool CalcCurrentFrameRate(double& tmpFrameRate, size_t nQueuedFrames);
|
||||
|
||||
// double m_dDecodeTime;
|
||||
double m_dOrigFrameRate;
|
||||
double m_dFrameRate;
|
||||
bool m_bValidFrameRate;
|
||||
bool m_bIvtc;
|
||||
int m_nLastSeenFieldDoubling;
|
||||
bool m_bIsPTS; // true for Presentation Time Stamps (source). output is always PTS.
|
||||
int m_nSegmentSampleCount;
|
||||
int m_nOutputFrames;
|
||||
bool m_bIsSampleInFields;
|
||||
bool m_bEnableIvtc;
|
||||
REFERENCE_TIME m_rtPrevStart;
|
||||
TTimeStampQueue m_TimeStampQueue;
|
||||
TSortedTimeStamps m_OutputTimeStamps;
|
||||
};
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "QuickSync_defs.h"
|
||||
#include "base_allocator.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// MFXFrameAllocator
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
MFXFrameAllocator::MFXFrameAllocator()
|
||||
{
|
||||
pthis = this;
|
||||
Alloc = Alloc_;
|
||||
Lock = Lock_;
|
||||
Free = Free_;
|
||||
Unlock = Unlock_;
|
||||
GetHDL = GetHDL_;
|
||||
}
|
||||
|
||||
mfxStatus MFXFrameAllocator::Alloc_(mfxHDL pthis, mfxFrameAllocRequest* request, mfxFrameAllocResponse* response)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pthis, MFX_ERR_MEMORY_ALLOC);
|
||||
return ((MFXFrameAllocator*)(pthis))->AllocFrames(request, response);
|
||||
}
|
||||
|
||||
mfxStatus MFXFrameAllocator::Lock_(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pthis, MFX_ERR_MEMORY_ALLOC);
|
||||
return ((MFXFrameAllocator*)(pthis))->LockFrame(mid, ptr);
|
||||
}
|
||||
|
||||
mfxStatus MFXFrameAllocator::Unlock_(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pthis, MFX_ERR_MEMORY_ALLOC);
|
||||
return ((MFXFrameAllocator*)(pthis))->UnlockFrame(mid, ptr);
|
||||
}
|
||||
|
||||
mfxStatus MFXFrameAllocator::Free_(mfxHDL pthis, mfxFrameAllocResponse* response)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pthis, MFX_ERR_MEMORY_ALLOC);
|
||||
return ((MFXFrameAllocator*)(pthis))->FreeFrames(response);
|
||||
}
|
||||
|
||||
mfxStatus MFXFrameAllocator::GetHDL_(mfxHDL pthis, mfxMemId mid, mfxHDL* handle)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pthis, MFX_ERR_MEMORY_ALLOC);
|
||||
return ((MFXFrameAllocator*)(pthis))->GetFrameHDL(mid, handle);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BaseFrameAllocator
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
mfxStatus BaseFrameAllocator::CheckRequestType(mfxFrameAllocRequest* request)
|
||||
{
|
||||
MSDK_CHECK_POINTER(request, MFX_ERR_NULL_PTR);
|
||||
|
||||
// check that Media SDK component is specified in request
|
||||
return ((request->Type & MEMTYPE_FROM_MASK) != 0) ? MFX_ERR_NONE : MFX_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
mfxStatus BaseFrameAllocator::AllocFrames(mfxFrameAllocRequest* request, mfxFrameAllocResponse* response)
|
||||
{
|
||||
if (0 == request || 0 == response || 0 == request->NumFrameSuggested)
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
|
||||
if (MFX_ERR_NONE != CheckRequestType(request))
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
if ((request->Type & MFX_MEMTYPE_EXTERNAL_FRAME) && (request->Type & MFX_MEMTYPE_FROM_DECODE))
|
||||
{
|
||||
// external decoder allocations
|
||||
|
||||
if (m_externalDecoderResponse.m_refCount > 0)
|
||||
{
|
||||
// check if enough frames were allocated
|
||||
if (request->NumFrameMin > m_externalDecoderResponse.m_response.NumFrameActual)
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
|
||||
m_externalDecoderResponse.m_refCount++;
|
||||
// return existing response
|
||||
*response = m_externalDecoderResponse.m_response;
|
||||
}
|
||||
else
|
||||
{
|
||||
sts = AllocImpl(request, response);
|
||||
if (sts == MFX_ERR_NONE)
|
||||
{
|
||||
m_externalDecoderResponse.m_response = *response;
|
||||
m_externalDecoderResponse.m_refCount = 1;
|
||||
m_externalDecoderResponse.m_type = request->Type & MEMTYPE_FROM_MASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// internal allocations
|
||||
|
||||
// reserve space before allocation to avoid memory leak
|
||||
m_responses.push_back(mfxFrameAllocResponse());
|
||||
|
||||
sts = AllocImpl(request, response);
|
||||
if (sts == MFX_ERR_NONE)
|
||||
{
|
||||
m_responses.back() = *response;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_responses.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
bool BaseFrameAllocator::IsSame(const mfxFrameAllocResponse& l, const mfxFrameAllocResponse& r)
|
||||
{
|
||||
return l.mids != 0 && r.mids != 0 && l.mids[0] == r.mids[0] && l.NumFrameActual == r.NumFrameActual;
|
||||
}
|
||||
|
||||
mfxStatus BaseFrameAllocator::FreeFrames(mfxFrameAllocResponse* response)
|
||||
{
|
||||
if (response == 0)
|
||||
return MFX_ERR_INVALID_HANDLE;
|
||||
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
// check whether response is m_externalDecoderResponse
|
||||
if (m_externalDecoderResponse.m_refCount > 0 && IsSame(*response, m_externalDecoderResponse.m_response))
|
||||
{
|
||||
if (--m_externalDecoderResponse.m_refCount == 0)
|
||||
{
|
||||
sts = ReleaseResponse(response);
|
||||
m_externalDecoderResponse.Reset();
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
// if not found so far, then search in internal responses
|
||||
for (Iter i = m_responses.begin(); i != m_responses.end(); ++i)
|
||||
{
|
||||
if (IsSame(*response, *i))
|
||||
{
|
||||
sts = ReleaseResponse(response);
|
||||
m_responses.erase(i);
|
||||
return sts;
|
||||
}
|
||||
}
|
||||
|
||||
// not found anywhere, report an error
|
||||
return MFX_ERR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
mfxStatus BaseFrameAllocator::Close()
|
||||
{
|
||||
ReleaseResponse(&(m_externalDecoderResponse.m_response));
|
||||
m_externalDecoderResponse.Reset();
|
||||
|
||||
while (!m_responses.empty())
|
||||
{
|
||||
ReleaseResponse(&(*m_responses.begin()));
|
||||
m_responses.pop_front();
|
||||
}
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// MFXBufferAllocator
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
MFXBufferAllocator::MFXBufferAllocator()
|
||||
{
|
||||
pthis = this;
|
||||
Alloc = Alloc_;
|
||||
Lock = Lock_;
|
||||
Free = Free_;
|
||||
Unlock = Unlock_;
|
||||
}
|
||||
|
||||
mfxStatus MFXBufferAllocator::Alloc_(mfxHDL pthis, mfxU32 nbytes, mfxU16 type, mfxMemId* mid)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pthis, MFX_ERR_MEMORY_ALLOC);
|
||||
return ((MFXBufferAllocator*)pthis)->AllocBuffer(nbytes, type, mid);
|
||||
}
|
||||
|
||||
mfxStatus MFXBufferAllocator::Lock_(mfxHDL pthis, mfxMemId mid, mfxU8** ptr)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pthis, MFX_ERR_MEMORY_ALLOC);
|
||||
return ((MFXBufferAllocator*)pthis)->LockBuffer(mid, ptr);
|
||||
}
|
||||
|
||||
mfxStatus MFXBufferAllocator::Unlock_(mfxHDL pthis, mfxMemId mid)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pthis, MFX_ERR_MEMORY_ALLOC);
|
||||
return ((MFXBufferAllocator*)pthis)->UnlockBuffer(mid);
|
||||
}
|
||||
|
||||
mfxStatus MFXBufferAllocator::Free_(mfxHDL pthis, mfxMemId mid)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pthis, MFX_ERR_MEMORY_ALLOC);
|
||||
return ((MFXBufferAllocator*)pthis)->FreeBuffer(mid);
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct mfxAllocatorParams
|
||||
{
|
||||
virtual ~mfxAllocatorParams(){};
|
||||
};
|
||||
|
||||
// this class implements methods declared in mfxFrameAllocator structure
|
||||
// simply redirecting them to virtual methods which should be overridden in derived classes
|
||||
class MFXFrameAllocator : public mfxFrameAllocator
|
||||
{
|
||||
public:
|
||||
MFXFrameAllocator();
|
||||
virtual ~MFXFrameAllocator() {}
|
||||
|
||||
// optional method, override if need to pass some parameters to allocator from application
|
||||
virtual mfxStatus Init(mfxAllocatorParams* pParams) = 0;
|
||||
virtual mfxStatus Close() = 0;
|
||||
|
||||
protected:
|
||||
virtual mfxStatus AllocFrames(mfxFrameAllocRequest* request, mfxFrameAllocResponse* response) = 0;
|
||||
virtual mfxStatus LockFrame(mfxMemId mid, mfxFrameData* ptr) = 0;
|
||||
virtual mfxStatus UnlockFrame(mfxMemId mid, mfxFrameData* ptr) = 0;
|
||||
virtual mfxStatus GetFrameHDL(mfxMemId mid, mfxHDL* handle) = 0;
|
||||
virtual mfxStatus FreeFrames(mfxFrameAllocResponse* response) = 0;
|
||||
|
||||
private:
|
||||
static mfxStatus Alloc_(mfxHDL pthis, mfxFrameAllocRequest* request, mfxFrameAllocResponse* response);
|
||||
static mfxStatus Lock_(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr);
|
||||
static mfxStatus Unlock_(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr);
|
||||
static mfxStatus GetHDL_(mfxHDL pthis, mfxMemId mid, mfxHDL* handle);
|
||||
static mfxStatus Free_(mfxHDL pthis, mfxFrameAllocResponse* response);
|
||||
};
|
||||
|
||||
// This class implements basic logic of memory allocator
|
||||
// Manages responses for different components according to allocation request type
|
||||
// External frames of a particular component-related type are allocated in one call
|
||||
// Further calls return previously allocated response.
|
||||
// Ex. Preallocated frame chain with type=FROM_ENCODE | FROM_VPPIN will be returned when
|
||||
// request type contains either FROM_ENCODE or FROM_VPPIN
|
||||
|
||||
// This class does not allocate any actual memory
|
||||
class BaseFrameAllocator: public MFXFrameAllocator
|
||||
{
|
||||
public:
|
||||
BaseFrameAllocator() {}
|
||||
virtual ~BaseFrameAllocator() {}
|
||||
|
||||
virtual mfxStatus Init(mfxAllocatorParams* pParams) = 0;
|
||||
virtual mfxStatus Close();
|
||||
|
||||
protected:
|
||||
virtual mfxStatus AllocFrames(mfxFrameAllocRequest* request, mfxFrameAllocResponse* response);
|
||||
virtual mfxStatus FreeFrames(mfxFrameAllocResponse* response);
|
||||
|
||||
typedef std::list<mfxFrameAllocResponse>::iterator Iter;
|
||||
static const mfxU32 MEMTYPE_FROM_MASK = MFX_MEMTYPE_FROM_ENCODE | MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT;
|
||||
|
||||
struct UniqueResponse
|
||||
{
|
||||
mfxU32 m_refCount;
|
||||
mfxFrameAllocResponse m_response;
|
||||
mfxU16 m_type;
|
||||
|
||||
UniqueResponse() { Reset(); }
|
||||
void Reset() { memset(this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
std::list<mfxFrameAllocResponse> m_responses;
|
||||
UniqueResponse m_externalDecoderResponse;
|
||||
|
||||
// checks responses for identity
|
||||
virtual bool IsSame(const mfxFrameAllocResponse& l, const mfxFrameAllocResponse& r);
|
||||
|
||||
// checks if request is supported
|
||||
virtual mfxStatus CheckRequestType(mfxFrameAllocRequest* request);
|
||||
|
||||
// memory type specific methods, must be overridden in derived classes
|
||||
|
||||
virtual mfxStatus LockFrame(mfxMemId mid, mfxFrameData* ptr) = 0;
|
||||
virtual mfxStatus UnlockFrame(mfxMemId mid, mfxFrameData* ptr) = 0;
|
||||
virtual mfxStatus GetFrameHDL(mfxMemId mid, mfxHDL* handle) = 0;
|
||||
|
||||
// frees memory attached to response
|
||||
virtual mfxStatus ReleaseResponse(mfxFrameAllocResponse* response) = 0;
|
||||
// allocates memory
|
||||
virtual mfxStatus AllocImpl(mfxFrameAllocRequest* request, mfxFrameAllocResponse* response) = 0;
|
||||
|
||||
template <class T>
|
||||
class safe_array
|
||||
{
|
||||
public:
|
||||
safe_array(T* ptr = 0) : m_ptr(ptr) {} // construct from object pointer
|
||||
~safe_array() { reset(0); }
|
||||
inline T* get()
|
||||
{ // return wrapped pointer
|
||||
return m_ptr;
|
||||
}
|
||||
inline T* release()
|
||||
{ // return wrapped pointer and give up ownership
|
||||
T* ptr = m_ptr;
|
||||
m_ptr = 0;
|
||||
return ptr;
|
||||
}
|
||||
inline void reset(T* ptr)
|
||||
{ // destroy designated object and store new pointer
|
||||
if (m_ptr)
|
||||
{
|
||||
delete[] m_ptr;
|
||||
}
|
||||
m_ptr = ptr;
|
||||
}
|
||||
protected:
|
||||
T* m_ptr; // the wrapped object pointer
|
||||
};
|
||||
};
|
||||
|
||||
class MFXBufferAllocator : public mfxBufferAllocator
|
||||
{
|
||||
public:
|
||||
MFXBufferAllocator();
|
||||
virtual ~MFXBufferAllocator() {}
|
||||
|
||||
protected:
|
||||
virtual mfxStatus AllocBuffer(mfxU32 nbytes, mfxU16 type, mfxMemId* mid) = 0;
|
||||
virtual mfxStatus LockBuffer(mfxMemId mid, mfxU8** ptr) = 0;
|
||||
virtual mfxStatus UnlockBuffer(mfxMemId mid) = 0;
|
||||
virtual mfxStatus FreeBuffer(mfxMemId mid) = 0;
|
||||
|
||||
private:
|
||||
static mfxStatus Alloc_(mfxHDL pthis, mfxU32 nbytes, mfxU16 type, mfxMemId* mid);
|
||||
static mfxStatus Lock_(mfxHDL pthis, mfxMemId mid, mfxU8** ptr);
|
||||
static mfxStatus Unlock_(mfxHDL pthis, mfxMemId mid);
|
||||
static mfxStatus Free_(mfxHDL pthis, mfxMemId mid);
|
||||
};
|
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "QuickSync_defs.h"
|
||||
#include "d3d_allocator.h"
|
||||
|
||||
static const D3DFORMAT D3DFMT_NV12 = (D3DFORMAT)MAKEFOURCC('N','V','1','2');
|
||||
static const D3DFORMAT D3DFMT_YV12 = (D3DFORMAT)MAKEFOURCC('Y','V','1','2');
|
||||
|
||||
D3DFORMAT ConvertMfxFourccToD3dFormat(mfxU32 fourcc)
|
||||
{
|
||||
switch (fourcc)
|
||||
{
|
||||
case MFX_FOURCC_NV12:
|
||||
return D3DFMT_NV12;
|
||||
case MFX_FOURCC_YV12:
|
||||
return D3DFMT_YV12;
|
||||
case MFX_FOURCC_YUY2:
|
||||
return D3DFMT_YUY2;
|
||||
case MFX_FOURCC_RGB3:
|
||||
return D3DFMT_R8G8B8;
|
||||
case MFX_FOURCC_RGB4:
|
||||
return D3DFMT_A8R8G8B8;
|
||||
case mfxU32(D3DFMT_P8):
|
||||
return D3DFMT_P8;
|
||||
default:
|
||||
return D3DFMT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
class DeviceHandle
|
||||
{
|
||||
public:
|
||||
DeviceHandle(IDirect3DDeviceManager9* manager) :
|
||||
m_Manager(manager),
|
||||
m_Handle(0)
|
||||
{
|
||||
MSDK_CHECK_POINTER_NO_RET(manager);
|
||||
HRESULT hr = manager->OpenDeviceHandle(&m_Handle);
|
||||
if (FAILED(hr))
|
||||
m_Manager = 0;
|
||||
}
|
||||
|
||||
~DeviceHandle()
|
||||
{
|
||||
if (m_Manager && m_Handle)
|
||||
m_Manager->CloseDeviceHandle(m_Handle);
|
||||
}
|
||||
|
||||
HANDLE Detach()
|
||||
{
|
||||
HANDLE tmp = m_Handle;
|
||||
m_Manager = 0;
|
||||
m_Handle = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline operator HANDLE()
|
||||
{
|
||||
return m_Handle;
|
||||
}
|
||||
|
||||
inline bool operator!() const
|
||||
{
|
||||
return m_Handle == 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
CComPtr<IDirect3DDeviceManager9> m_Manager;
|
||||
HANDLE m_Handle;
|
||||
};
|
||||
|
||||
D3DFrameAllocator::D3DFrameAllocator() :
|
||||
m_DecoderService(0), m_ProcessorService(0), m_hDecoder(0), m_hProcessor(0), m_Manager(0)
|
||||
{
|
||||
}
|
||||
|
||||
D3DFrameAllocator::~D3DFrameAllocator()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
mfxStatus D3DFrameAllocator::Init(mfxAllocatorParams* pParams)
|
||||
{
|
||||
D3DAllocatorParams* pd3dParams = 0;
|
||||
pd3dParams = dynamic_cast<D3DAllocatorParams* >(pParams);
|
||||
MSDK_CHECK_POINTER(pd3dParams, MFX_ERR_NOT_INITIALIZED);
|
||||
m_Manager = pd3dParams->pManager;
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus D3DFrameAllocator::Close()
|
||||
{
|
||||
if (m_Manager && m_hDecoder)
|
||||
{
|
||||
m_Manager->CloseDeviceHandle(m_hDecoder);
|
||||
m_Manager = 0;
|
||||
m_hDecoder = 0;
|
||||
}
|
||||
|
||||
if (m_Manager && m_hProcessor)
|
||||
{
|
||||
m_Manager->CloseDeviceHandle(m_hProcessor);
|
||||
m_Manager = 0;
|
||||
m_hProcessor = 0;
|
||||
}
|
||||
|
||||
return BaseFrameAllocator::Close();
|
||||
}
|
||||
|
||||
mfxStatus D3DFrameAllocator::LockFrame(mfxMemId mid, mfxFrameData* ptr)
|
||||
{
|
||||
IDirect3DSurface9* pSurface = (IDirect3DSurface9*)mid;
|
||||
MSDK_CHECK_POINTER(pSurface, MFX_ERR_INVALID_HANDLE);
|
||||
MSDK_CHECK_POINTER(ptr, MFX_ERR_LOCK_MEMORY);
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
HRESULT hr = pSurface->GetDesc(&desc);
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_LOCK_MEMORY;
|
||||
|
||||
if (desc.Format != D3DFMT_NV12 &&
|
||||
desc.Format != D3DFMT_YV12 &&
|
||||
desc.Format != D3DFMT_YUY2 &&
|
||||
desc.Format != D3DFMT_R8G8B8 &&
|
||||
desc.Format != D3DFMT_A8R8G8B8 &&
|
||||
desc.Format != D3DFMT_P8)
|
||||
return MFX_ERR_LOCK_MEMORY;
|
||||
|
||||
D3DLOCKED_RECT locked;
|
||||
|
||||
hr = pSurface->LockRect(&locked, NULL, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_LOCK_MEMORY;
|
||||
|
||||
switch ((DWORD)desc.Format)
|
||||
{
|
||||
case D3DFMT_NV12:
|
||||
ptr->Pitch = (mfxU16)locked.Pitch;
|
||||
ptr->Y = (mfxU8*)locked.pBits;
|
||||
ptr->U = (mfxU8*)locked.pBits + desc.Height * locked.Pitch;
|
||||
ptr->V = ptr->U + 1;
|
||||
break;
|
||||
case D3DFMT_YV12:
|
||||
ptr->Pitch = (mfxU16)locked.Pitch;
|
||||
ptr->Y = (mfxU8*)locked.pBits;
|
||||
ptr->V = ptr->Y + desc.Height * locked.Pitch;
|
||||
ptr->U = ptr->V + (desc.Height * locked.Pitch) / 4;
|
||||
break;
|
||||
case D3DFMT_YUY2:
|
||||
ptr->Pitch = (mfxU16)locked.Pitch;
|
||||
ptr->Y = (mfxU8*)locked.pBits;
|
||||
ptr->U = ptr->Y + 1;
|
||||
ptr->V = ptr->Y + 3;
|
||||
break;
|
||||
case D3DFMT_R8G8B8:
|
||||
ptr->Pitch = (mfxU16)locked.Pitch;
|
||||
ptr->B = (mfxU8*)locked.pBits;
|
||||
ptr->G = ptr->B + 1;
|
||||
ptr->R = ptr->B + 2;
|
||||
break;
|
||||
case D3DFMT_A8R8G8B8:
|
||||
ptr->Pitch = (mfxU16)locked.Pitch;
|
||||
ptr->B = (mfxU8* )locked.pBits;
|
||||
ptr->G = ptr->B + 1;
|
||||
ptr->R = ptr->B + 2;
|
||||
ptr->A = ptr->B + 3;
|
||||
break;
|
||||
case D3DFMT_P8:
|
||||
ptr->Pitch = (mfxU16)locked.Pitch;
|
||||
ptr->Y = (mfxU8*)locked.pBits;
|
||||
ptr->U = 0;
|
||||
ptr->V = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus D3DFrameAllocator::UnlockFrame(mfxMemId mid, mfxFrameData* ptr)
|
||||
{
|
||||
IDirect3DSurface9* pSurface = (IDirect3DSurface9*)mid;
|
||||
if (pSurface == 0)
|
||||
return MFX_ERR_INVALID_HANDLE;
|
||||
|
||||
pSurface->UnlockRect();
|
||||
|
||||
if (NULL != ptr)
|
||||
{
|
||||
ptr->Pitch = 0;
|
||||
ptr->Y = 0;
|
||||
ptr->U = 0;
|
||||
ptr->V = 0;
|
||||
}
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus D3DFrameAllocator::GetFrameHDL(mfxMemId mid, mfxHDL* handle)
|
||||
{
|
||||
if (handle == 0)
|
||||
return MFX_ERR_INVALID_HANDLE;
|
||||
|
||||
*handle = mid;
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus D3DFrameAllocator::CheckRequestType(mfxFrameAllocRequest* request)
|
||||
{
|
||||
mfxStatus sts = BaseFrameAllocator::CheckRequestType(request);
|
||||
if (MFX_ERR_NONE != sts)
|
||||
return sts;
|
||||
|
||||
if ((request->Type & (MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET | MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) != 0)
|
||||
return MFX_ERR_NONE;
|
||||
else
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
mfxStatus D3DFrameAllocator::ReleaseResponse(mfxFrameAllocResponse* response)
|
||||
{
|
||||
if (!response)
|
||||
return MFX_ERR_NULL_PTR;
|
||||
|
||||
if (NULL == response->mids)
|
||||
return MFX_ERR_NONE;
|
||||
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
for (mfxU32 i = 0; i < response->NumFrameActual; i++)
|
||||
{
|
||||
if (response->mids[i])
|
||||
{
|
||||
IDirect3DSurface9* handle = 0;
|
||||
sts = GetFrameHDL(response->mids[i], (mfxHDL*)&handle);
|
||||
if (MFX_ERR_NONE != sts)
|
||||
return sts;
|
||||
handle->Release();
|
||||
}
|
||||
}
|
||||
|
||||
MSDK_SAFE_DELETE_ARRAY(response->mids);
|
||||
return sts;
|
||||
}
|
||||
|
||||
mfxStatus D3DFrameAllocator::AllocImpl(mfxFrameAllocRequest* request, mfxFrameAllocResponse* response)
|
||||
{
|
||||
HRESULT hr;
|
||||
D3DFORMAT format = ConvertMfxFourccToD3dFormat(request->Info.FourCC);
|
||||
|
||||
if (format == D3DFMT_UNKNOWN)
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
|
||||
safe_array<mfxMemId> mids(new mfxMemId[request->NumFrameSuggested]);
|
||||
if (!mids.get())
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
|
||||
// VPP may require at input/output surfaces with color format other than NV12 (in case of color conversion)
|
||||
// VideoProcessorService must be used to create such surfaces
|
||||
if (((request->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) && (MFX_FOURCC_NV12 != request->Info.FourCC))||
|
||||
(request->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) && (request->Type & MFX_MEMTYPE_INTERNAL_FRAME ))
|
||||
{
|
||||
if (!m_hProcessor)
|
||||
{
|
||||
DeviceHandle device(m_Manager);
|
||||
|
||||
if (!device)
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
|
||||
CComPtr<IDirectXVideoProcessorService> service = 0;
|
||||
|
||||
hr = m_Manager->GetVideoService(device, IID_IDirectXVideoProcessorService, (void**)&service);
|
||||
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
|
||||
m_ProcessorService = service;
|
||||
m_hProcessor = device.Detach();
|
||||
}
|
||||
|
||||
hr = m_ProcessorService->CreateSurface(
|
||||
request->Info.Width,
|
||||
request->Info.Height,
|
||||
request->NumFrameSuggested - 1,
|
||||
format,
|
||||
D3DPOOL_DEFAULT,
|
||||
0,
|
||||
DXVA2_VideoProcessorRenderTarget,
|
||||
(IDirect3DSurface9**)mids.get(),
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_hDecoder)
|
||||
{
|
||||
DeviceHandle device(m_Manager);
|
||||
|
||||
if (!device)
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
|
||||
CComPtr<IDirectXVideoDecoderService> service = 0;
|
||||
|
||||
hr = m_Manager->GetVideoService(device, IID_IDirectXVideoDecoderService, (void**)&service);
|
||||
|
||||
if (FAILED(hr))
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
|
||||
m_DecoderService = service;
|
||||
m_hDecoder = device.Detach();
|
||||
}
|
||||
|
||||
hr = m_DecoderService->CreateSurface(
|
||||
request->Info.Width,
|
||||
request->Info.Height,
|
||||
request->NumFrameSuggested - 1,
|
||||
format,
|
||||
D3DPOOL_DEFAULT,
|
||||
0,
|
||||
DXVA2_VideoDecoderRenderTarget,
|
||||
(IDirect3DSurface9**)mids.get(),
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
}
|
||||
|
||||
response->mids = mids.release();
|
||||
response->NumFrameActual = request->NumFrameSuggested;
|
||||
return MFX_ERR_NONE;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atlbase.h>
|
||||
#include <dxva2api.h>
|
||||
#include "base_allocator.h"
|
||||
|
||||
enum eTypeHandle
|
||||
{
|
||||
DXVA2_PROCESSOR = 0x00,
|
||||
DXVA2_DECODER = 0x01
|
||||
};
|
||||
|
||||
struct D3DAllocatorParams : public mfxAllocatorParams
|
||||
{
|
||||
IDirect3DDeviceManager9* pManager;
|
||||
};
|
||||
|
||||
class D3DFrameAllocator : public BaseFrameAllocator
|
||||
{
|
||||
public:
|
||||
D3DFrameAllocator();
|
||||
virtual ~D3DFrameAllocator();
|
||||
|
||||
virtual mfxStatus Init(mfxAllocatorParams* pParams);
|
||||
virtual mfxStatus Close();
|
||||
|
||||
virtual IDirect3DDeviceManager9* GetDeviceManager()
|
||||
{
|
||||
return m_Manager;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual mfxStatus LockFrame(mfxMemId mid, mfxFrameData* ptr);
|
||||
virtual mfxStatus UnlockFrame(mfxMemId mid, mfxFrameData* ptr);
|
||||
virtual mfxStatus GetFrameHDL(mfxMemId mid, mfxHDL* handle);
|
||||
|
||||
virtual mfxStatus CheckRequestType(mfxFrameAllocRequest* request);
|
||||
virtual mfxStatus ReleaseResponse(mfxFrameAllocResponse* response);
|
||||
virtual mfxStatus AllocImpl(mfxFrameAllocRequest* request, mfxFrameAllocResponse* response);
|
||||
|
||||
CComPtr<IDirect3DDeviceManager9> m_Manager;
|
||||
CComPtr<IDirectXVideoDecoderService> m_DecoderService;
|
||||
CComPtr<IDirectXVideoProcessorService> m_ProcessorService;
|
||||
HANDLE m_hDecoder;
|
||||
HANDLE m_hProcessor;
|
||||
};
|
Binary file not shown.
|
@ -0,0 +1,623 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "QuickSync_defs.h"
|
||||
#include "QuickSyncUtils.h"
|
||||
#include "TimeManager.h"
|
||||
#include "frame_constructors.h"
|
||||
#include "H264Nalu.h"
|
||||
|
||||
static inline mfxU32 GetValue32(mfxU8* pBuf)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pBuf, 0);
|
||||
return ((mfxU32)(pBuf[0]) << 24) | ((mfxU32)(pBuf[1]) << 16) | ((mfxU32)(pBuf[2]) << 8) | ((mfxU32)(pBuf[3]));
|
||||
}
|
||||
|
||||
static inline void SetValue(mfxU32 nValue, mfxU8* pBuf)
|
||||
{
|
||||
MSDK_CHECK_POINTER_NO_RET(pBuf);
|
||||
for (mfxU32 i = 0; i < 4; ++i)
|
||||
{
|
||||
*pBuf++ = (mfxU8)(nValue >> 8 * i);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CFrameConstructor
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
CFrameConstructor::CFrameConstructor()
|
||||
{
|
||||
m_bSeqHeaderInserted = false;
|
||||
m_bDvdStripPackets = false;
|
||||
MSDK_ZERO_VAR(m_ResidialBS);
|
||||
MSDK_ZERO_VAR(m_Headers);
|
||||
m_ResidialBS.MaxLength = 100;
|
||||
m_ResidialBS.Data = new mfxU8[m_ResidialBS.MaxLength];
|
||||
}
|
||||
|
||||
CFrameConstructor::~CFrameConstructor()
|
||||
{
|
||||
delete[] m_ResidialBS.Data;
|
||||
delete[] m_Headers.Data;
|
||||
}
|
||||
|
||||
void CFrameConstructor::Reset()
|
||||
{
|
||||
m_ResidialBS.DataOffset = m_ResidialBS.DataLength = 0;
|
||||
m_bSeqHeaderInserted = false;
|
||||
}
|
||||
|
||||
void CFrameConstructor::UpdateTimeStamp(IMediaSample* pSample, mfxBitstream* pBS)
|
||||
{
|
||||
REFERENCE_TIME rtStart, rtEnd;
|
||||
HRESULT hr = pSample->GetTime(&rtStart, &rtEnd);
|
||||
pBS->TimeStamp = (S_OK == hr || VFW_S_NO_STOP_TIME == hr) ?
|
||||
CDecTimeManager::ConvertReferenceTime2MFXTime(rtStart) :
|
||||
MFX_TIME_STAMP_INVALID;
|
||||
}
|
||||
|
||||
void CFrameConstructor::SaveResidialData(mfxBitstream* pBS)
|
||||
{
|
||||
MSDK_CHECK_POINTER_NO_RET(pBS);
|
||||
// m_ResidialBS must be empty
|
||||
ASSERT(m_ResidialBS.DataLength == 0);
|
||||
m_ResidialBS.DataOffset = 0;
|
||||
m_ResidialBS.DataLength = pBS->DataLength;
|
||||
|
||||
// Check if a bigger buffer is needed
|
||||
if (pBS->DataLength > m_ResidialBS.MaxLength)
|
||||
{
|
||||
delete[] m_ResidialBS.Data;
|
||||
mfxU32 newSize = pBS->DataLength;
|
||||
m_ResidialBS.Data = new mfxU8[newSize];
|
||||
MSDK_CHECK_POINTER_NO_RET(m_ResidialBS.Data);
|
||||
m_ResidialBS.MaxLength = newSize;
|
||||
}
|
||||
|
||||
ASSERT(pBS->DataOffset + pBS->DataLength <= pBS->MaxLength);
|
||||
memcpy(m_ResidialBS.Data, pBS->Data + pBS->DataOffset, pBS->DataLength);
|
||||
}
|
||||
|
||||
mfxStatus CFrameConstructor::ConstructHeaders(
|
||||
VIDEOINFOHEADER2* vih,
|
||||
const GUID& guidFormat,
|
||||
size_t nMtSize,
|
||||
size_t nVideoInfoSize)
|
||||
{
|
||||
MSDK_SAFE_DELETE_ARRAY(m_Headers.Data);
|
||||
MSDK_ZERO_VAR(m_Headers);
|
||||
|
||||
// nothing to do here...
|
||||
if (nMtSize <= nVideoInfoSize)
|
||||
{
|
||||
return MFX_ERR_MORE_DATA;
|
||||
}
|
||||
|
||||
// splitter adds sequence headers to the end of the vih
|
||||
size_t nSeqHeaderSize;
|
||||
mfxU8* pSeqHeader;
|
||||
MPEG2VIDEOINFO* mp2 = NULL;
|
||||
if (FORMAT_MPEG2_VIDEO == guidFormat)
|
||||
{
|
||||
mp2 = (MPEG2VIDEOINFO*)(vih);
|
||||
MSDK_CHECK_POINTER(mp2, MFX_ERR_NULL_PTR);
|
||||
pSeqHeader = (mfxU8*)mp2->dwSequenceHeader;
|
||||
nSeqHeaderSize = mp2->cbSequenceHeader;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSeqHeader = (mfxU8*)vih + nVideoInfoSize;
|
||||
nSeqHeaderSize = nMtSize - nVideoInfoSize;
|
||||
}
|
||||
|
||||
m_Headers.Data = new mfxU8[nSeqHeaderSize];
|
||||
m_Headers.MaxLength = m_Headers.DataLength = (mfxU32)nSeqHeaderSize;
|
||||
|
||||
// Copy the sequence header
|
||||
memcpy(m_Headers.Data, pSeqHeader, nSeqHeaderSize);
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus CFrameConstructor::ConstructFrame(IMediaSample* pSample, mfxBitstream* pBS)
|
||||
{
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
mfxU8* pDataBuffer = NULL;
|
||||
int nDataSize = 0;
|
||||
|
||||
MSDK_CHECK_POINTER(pSample, MFX_ERR_NULL_PTR);
|
||||
nDataSize = pSample->GetActualDataLength();
|
||||
MSDK_CHECK_ERROR(nDataSize, 0, MFX_ERR_MORE_DATA);
|
||||
|
||||
pSample->GetPointer(&pDataBuffer);
|
||||
MSDK_CHECK_POINTER(pDataBuffer, MFX_ERR_NULL_PTR);
|
||||
|
||||
MSDK_SAFE_DELETE_ARRAY(pBS->Data);
|
||||
|
||||
if (m_bDvdStripPackets)
|
||||
{
|
||||
StripDvdPacket(pDataBuffer, nDataSize);
|
||||
MSDK_CHECK_ERROR(nDataSize, 0, MFX_ERR_MORE_DATA);
|
||||
}
|
||||
|
||||
// prefix the sequence headers if needed
|
||||
size_t newDataSize = nDataSize + m_ResidialBS.DataLength +
|
||||
((m_bSeqHeaderInserted) ? 0 : m_Headers.DataLength);
|
||||
|
||||
pBS->MaxLength = pBS->DataLength = (mfxU32)newDataSize;
|
||||
|
||||
mfxU8* pData = pBS->Data = new mfxU8[newDataSize];
|
||||
MSDK_CHECK_POINTER(pData, MFX_ERR_NULL_PTR);
|
||||
|
||||
// write data left from previous samples
|
||||
WriteResidualData(pData);
|
||||
|
||||
// write sequence headers
|
||||
WriteHeaders(pData);
|
||||
|
||||
// append new data
|
||||
WriteSampleData(pData, pDataBuffer, nDataSize);
|
||||
pBS->DataLength = (mfxU32)(pData - pBS->Data);
|
||||
|
||||
UpdateTimeStamp(pSample, pBS);
|
||||
return sts;
|
||||
}
|
||||
|
||||
void CFrameConstructor::StripDvdPacket(BYTE*& p, int& len)
|
||||
{
|
||||
if (len > 0 && *(DWORD*)p == 0xba010000)
|
||||
{ // MEDIATYPE_*_PACK
|
||||
len -= 14;
|
||||
p += 14;
|
||||
if(int stuffing = (p[-1]&7))
|
||||
{
|
||||
len -= stuffing;
|
||||
p += stuffing;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 0 && *(DWORD*)p == 0xbb010000)
|
||||
{
|
||||
len -= 4;
|
||||
p += 4;
|
||||
int hdrlen = ((p[0]<<8)|p[1]) + 2;
|
||||
len -= hdrlen;
|
||||
p += hdrlen;
|
||||
}
|
||||
|
||||
if (len > 0 &&
|
||||
((*(DWORD*)p&0xf0ffffff) == 0xe0010000 ||
|
||||
(*(DWORD*)p&0xe0ffffff) == 0xc0010000 ||
|
||||
(*(DWORD*)p&0xbdffffff) == 0xbd010000))
|
||||
{ // PES
|
||||
bool ps1 = (*(DWORD*)p&0xbdffffff) == 0xbd010000;
|
||||
|
||||
len -= 4;
|
||||
p += 4;
|
||||
int expected = ((p[0]<<8)|p[1]);
|
||||
len -= 2;
|
||||
p += 2;
|
||||
BYTE* p0 = p;
|
||||
|
||||
for (int i = 0; i < 16 && *p == 0xff; i++, len--, p++)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
if ((*p&0xc0) == 0x80)
|
||||
{ // mpeg2
|
||||
len -= 2;
|
||||
p += 2;
|
||||
len -= *p+1;
|
||||
p += *p+1;
|
||||
}
|
||||
else
|
||||
{ // mpeg1
|
||||
if((*p&0xc0) == 0x40)
|
||||
{
|
||||
len -= 2;
|
||||
p += 2;
|
||||
}
|
||||
|
||||
if ((*p&0x30) == 0x30 || (*p&0x30) == 0x20)
|
||||
{
|
||||
bool pts = !!(*p&0x20), dts = !!(*p&0x10);
|
||||
if (pts)
|
||||
{
|
||||
len -= 5;
|
||||
}
|
||||
p += 5;
|
||||
if (dts)
|
||||
{
|
||||
ASSERT((*p&0xf0) == 0x10);
|
||||
len -= 5;
|
||||
p += 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len--;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if(ps1)
|
||||
{
|
||||
len--;
|
||||
p++;
|
||||
}
|
||||
|
||||
if (expected > 0)
|
||||
{
|
||||
expected -= (int)(p - p0);
|
||||
len = min(expected, len);
|
||||
}
|
||||
}
|
||||
|
||||
if(len < 0)
|
||||
{
|
||||
ASSERT(len < 0);
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CFrameConstructor::WriteResidualData(mfxU8*& pData)
|
||||
{
|
||||
if (m_ResidialBS.DataLength)
|
||||
{
|
||||
memcpy(pData, m_ResidialBS.Data, m_ResidialBS.DataLength);
|
||||
pData += m_ResidialBS.DataLength;
|
||||
m_ResidialBS.DataLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CFrameConstructor::WriteHeaders(mfxU8*& pData)
|
||||
{
|
||||
if (!m_bSeqHeaderInserted)
|
||||
{
|
||||
memcpy(pData, m_Headers.Data, m_Headers.DataLength);
|
||||
pData += m_Headers.DataLength;
|
||||
m_bSeqHeaderInserted = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CFrameConstructor::WriteSampleData(mfxU8*& pData, const mfxU8* pSrc, size_t nDataSize)
|
||||
{
|
||||
memcpy(pData, pSrc, nDataSize);
|
||||
pData += nDataSize;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CVC1FrameConstructor
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
CVC1FrameConstructor::CVC1FrameConstructor() :
|
||||
m_FourCC(0), m_Width(0), m_Height(0)
|
||||
{
|
||||
}
|
||||
|
||||
void CVC1FrameConstructor::Reset()
|
||||
{
|
||||
if (m_FourCC == FOURCC_WMV3)
|
||||
{
|
||||
CFrameConstructor::Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
bool bHeaderInitialized = m_bSeqHeaderInserted;
|
||||
CFrameConstructor::Reset();
|
||||
m_bSeqHeaderInserted = bHeaderInitialized;
|
||||
}
|
||||
|
||||
mfxStatus CVC1FrameConstructor::ConstructHeaders(
|
||||
VIDEOINFOHEADER2* vih,
|
||||
const GUID& guidFormat,
|
||||
size_t nMtSize,
|
||||
size_t nVideoInfoSize)
|
||||
{
|
||||
m_FourCC = vih->bmiHeader.biCompression;
|
||||
m_Width = vih->bmiHeader.biWidth;
|
||||
m_Height = vih->bmiHeader.biHeight;
|
||||
|
||||
// All other formats except WMV3
|
||||
if (FOURCC_WMV3 != m_FourCC)
|
||||
{
|
||||
if (FOURCC_VC1 == m_FourCC)
|
||||
{
|
||||
++nVideoInfoSize;
|
||||
}
|
||||
|
||||
return CFrameConstructor::ConstructHeaders(vih, guidFormat, nMtSize, nVideoInfoSize);
|
||||
}
|
||||
|
||||
// Special case WMV3
|
||||
MSDK_SAFE_DELETE_ARRAY(m_Headers.Data);
|
||||
MSDK_ZERO_VAR(m_Headers);
|
||||
|
||||
// nothing to do here...
|
||||
if (nMtSize <= nVideoInfoSize)
|
||||
{
|
||||
return MFX_ERR_MORE_DATA;
|
||||
}
|
||||
|
||||
//header should be additionally constructed for main&simple profile in asf data type
|
||||
m_Headers.MaxLength = m_Headers.DataLength = (mfxU32)(nMtSize - nVideoInfoSize + 20);
|
||||
m_Headers.Data = new mfxU8[m_Headers.MaxLength];
|
||||
mfxStatus sts = ConstructHeaderSM(m_Headers.Data,
|
||||
m_Headers.DataLength,
|
||||
(mfxU8*)(vih) + nVideoInfoSize,
|
||||
(mfxU32)(nMtSize - nVideoInfoSize));
|
||||
return sts;
|
||||
}
|
||||
|
||||
mfxStatus CVC1FrameConstructor::ConstructFrame(IMediaSample* pSample, mfxBitstream* pBS)
|
||||
{
|
||||
mfxU8* pDataBuffer = NULL;
|
||||
mfxU32 nDataSize = 0;
|
||||
MSDK_CHECK_POINTER(pSample, MFX_ERR_NULL_PTR);
|
||||
MSDK_CHECK_POINTER(pBS, MFX_ERR_NULL_PTR);
|
||||
|
||||
nDataSize = pSample->GetActualDataLength();
|
||||
MSDK_CHECK_ERROR(nDataSize, 0, MFX_ERR_MORE_DATA);
|
||||
|
||||
pSample->GetPointer(&pDataBuffer);
|
||||
MSDK_CHECK_POINTER(pDataBuffer, MFX_ERR_NULL_PTR);
|
||||
|
||||
UpdateTimeStamp(pSample, pBS);
|
||||
|
||||
// prefix the sequence headers if needed
|
||||
size_t newDataSize = nDataSize + m_ResidialBS.DataLength +
|
||||
((m_bSeqHeaderInserted) ? 0 : m_Headers.DataLength) + // add headers size
|
||||
8; // add upto 8 bytes for extra start codes
|
||||
|
||||
pBS->MaxLength = (mfxU32)newDataSize;
|
||||
|
||||
mfxU8* pData = pBS->Data = new mfxU8[newDataSize];
|
||||
MSDK_CHECK_POINTER(pData, MFX_ERR_NULL_PTR);
|
||||
|
||||
// write data left from previous samples
|
||||
WriteResidualData(pData);
|
||||
|
||||
// write sequence headers
|
||||
WriteHeaders(pData);
|
||||
|
||||
if (FOURCC_VC1 != m_FourCC)
|
||||
{
|
||||
SetValue(nDataSize, pData);
|
||||
SetValue(0, pData + 4);
|
||||
pData += 8;
|
||||
}
|
||||
else if (false == StartCodeExist(pDataBuffer))
|
||||
{
|
||||
// set start code to first 4 bytes
|
||||
SetValue(0x0D010000, pData);
|
||||
pData += 4;
|
||||
}
|
||||
|
||||
// append new data
|
||||
WriteSampleData(pData, pDataBuffer, nDataSize);
|
||||
pBS->DataLength = (mfxU32)(pData - pBS->Data);
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus CVC1FrameConstructor::ConstructHeaderSM(mfxU8* pHeaderSM, mfxU32 nHeaderSize, mfxU8* pDataBuffer, mfxU32 nDataSize)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pHeaderSM, MFX_ERR_NULL_PTR);
|
||||
MSDK_CHECK_POINTER(pDataBuffer, MFX_ERR_NULL_PTR);
|
||||
if (nHeaderSize < nDataSize + 20)
|
||||
{
|
||||
return MFX_ERR_NOT_ENOUGH_BUFFER;
|
||||
}
|
||||
|
||||
// set start code
|
||||
SetValue(0xC5000000, pHeaderSM);
|
||||
|
||||
// set size of sequence header is 4 bytes
|
||||
SetValue(nDataSize, pHeaderSM + 4);
|
||||
|
||||
// copy saved data back
|
||||
memcpy(pHeaderSM + 8, pDataBuffer, nDataSize);
|
||||
|
||||
// set sizes to the end of data
|
||||
SetValue(m_Height, pHeaderSM + 8 + nDataSize);
|
||||
SetValue(m_Width, pHeaderSM + 12 + nDataSize);
|
||||
|
||||
// set 0 to the last 4 bytes
|
||||
SetValue(0, pHeaderSM + 16 + nDataSize);
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
bool CVC1FrameConstructor::StartCodeExist(mfxU8* pStart)
|
||||
{
|
||||
MSDK_CHECK_POINTER(pStart, false);
|
||||
|
||||
//check first 4 bytes to be start code
|
||||
mfxU32 value = GetValue32(pStart);
|
||||
switch (value)
|
||||
{
|
||||
case 0x010A:
|
||||
case 0x010B:
|
||||
case 0x010C:
|
||||
case 0x010D:
|
||||
case 0x010E:
|
||||
case 0x010F:
|
||||
case 0x011B:
|
||||
case 0x011C:
|
||||
case 0x011D:
|
||||
case 0x011E:
|
||||
case 0x011F:
|
||||
// start code found
|
||||
return true;
|
||||
default:
|
||||
// start code not found
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CAVCFrameConstructor
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
CAVCFrameConstructor::CAVCFrameConstructor()
|
||||
{
|
||||
m_HeaderNalSize = 2; //MSDN - MPEG2VideoInfo->dwSequenceHeader delimited by 2 byte length fields
|
||||
SetValue(0x01000000, m_H264StartCode);
|
||||
m_TempBuffer.reserve(1<<20);
|
||||
}
|
||||
|
||||
CAVCFrameConstructor::~CAVCFrameConstructor()
|
||||
{
|
||||
}
|
||||
|
||||
mfxStatus CAVCFrameConstructor::ConstructHeaders(VIDEOINFOHEADER2* vih,
|
||||
const GUID& guidFormat,
|
||||
size_t nMtSize,
|
||||
size_t nVideoInfoSize)
|
||||
{
|
||||
MSDK_SAFE_DELETE_ARRAY(m_Headers.Data);
|
||||
m_Headers.DataLength = m_Headers.MaxLength = 0;
|
||||
|
||||
// nothing to do here...
|
||||
if (nMtSize <= nVideoInfoSize || FORMAT_MPEG2_VIDEO != guidFormat)
|
||||
{
|
||||
return MFX_ERR_MORE_DATA;
|
||||
}
|
||||
|
||||
MPEG2VIDEOINFO* mp2 = (MPEG2VIDEOINFO*)(vih);
|
||||
MSDK_CHECK_POINTER(mp2, MFX_ERR_NULL_PTR);
|
||||
|
||||
// SPS and/or PPS Data will be present
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
mfxU32 nNalDataLen;
|
||||
mfxU8* pNalDataBuff;
|
||||
CH264Nalu itStartCode;
|
||||
MSDK_ZERO_VAR(m_Headers);
|
||||
m_TempBuffer.clear();
|
||||
m_NalSize = mp2->dwFlags;
|
||||
|
||||
itStartCode.SetBuffer((BYTE*)mp2->dwSequenceHeader, mp2->cbSequenceHeader, m_HeaderNalSize); //Nal size = 2
|
||||
while (itStartCode.ReadNext())
|
||||
{
|
||||
nNalDataLen = itStartCode.GetDataLength();
|
||||
pNalDataBuff = itStartCode.GetDataBuffer();
|
||||
|
||||
switch(itStartCode.GetType())
|
||||
{
|
||||
case NALU_TYPE_SPS:
|
||||
case NALU_TYPE_PPS:
|
||||
m_TempBuffer.insert(m_TempBuffer.end(), m_H264StartCode, m_H264StartCode + 4);
|
||||
m_TempBuffer.insert(m_TempBuffer.end(), pNalDataBuff, pNalDataBuff+nNalDataLen);
|
||||
break;
|
||||
default:
|
||||
sts = MFX_ERR_MORE_DATA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_TempBuffer.size())
|
||||
{
|
||||
//Keep a copy of the SPS/PPS to be placed into the decode stream (after each new segment).
|
||||
MSDK_SAFE_DELETE_ARRAY(m_Headers.Data);
|
||||
m_Headers.Data = new mfxU8[m_TempBuffer.size()];
|
||||
m_Headers.DataLength = m_Headers.MaxLength = (mfxU32)m_TempBuffer.size();
|
||||
memcpy(m_Headers.Data, &m_TempBuffer.front(), m_TempBuffer.size());
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
mfxStatus CAVCFrameConstructor::ConstructFrame(IMediaSample* pSample, mfxBitstream* pBS)
|
||||
{
|
||||
mfxU32 nDataSize = 0;
|
||||
mfxU8* pDataBuffer = NULL;
|
||||
CH264Nalu itStartCode;
|
||||
int nNalDataLen;
|
||||
mfxU8* pNalDataBuff;
|
||||
m_TempBuffer.clear();
|
||||
MSDK_CHECK_POINTER(pSample, MFX_ERR_NULL_PTR);
|
||||
MSDK_CHECK_POINTER(pBS, MFX_ERR_NULL_PTR);
|
||||
|
||||
UpdateTimeStamp(pSample, pBS);
|
||||
|
||||
nDataSize = pSample->GetActualDataLength();
|
||||
MSDK_CHECK_ERROR(nDataSize, 0, MFX_ERR_MORE_DATA);
|
||||
m_TempBuffer.reserve(nDataSize * 3 / 2);
|
||||
|
||||
pSample->GetPointer(&pDataBuffer);
|
||||
MSDK_CHECK_POINTER(pDataBuffer, MFX_ERR_NULL_PTR);
|
||||
|
||||
itStartCode.SetBuffer(pDataBuffer, nDataSize, m_NalSize); //Nal size = 4
|
||||
|
||||
// Iterate over the NALUs and convert them to have start codes.
|
||||
while (itStartCode.ReadNext())
|
||||
{
|
||||
NALU_TYPE naluType = itStartCode.GetType();
|
||||
|
||||
// Discard audio NALUs
|
||||
if (NALU_TYPE_AUD == naluType)
|
||||
continue;
|
||||
|
||||
nNalDataLen = itStartCode.GetDataLength();
|
||||
pNalDataBuff = itStartCode.GetDataBuffer();
|
||||
|
||||
ASSERT(nNalDataLen > 0); // Shouldn't fail!
|
||||
if (nNalDataLen > 0)
|
||||
{
|
||||
m_TempBuffer.insert(m_TempBuffer.end(), m_H264StartCode, m_H264StartCode + 4);
|
||||
m_TempBuffer.insert(m_TempBuffer.end(), pNalDataBuff, pNalDataBuff + nNalDataLen);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_TempBuffer.empty())
|
||||
{
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
// Update data size
|
||||
nDataSize = (mfxU32)m_TempBuffer.size();
|
||||
pDataBuffer = &m_TempBuffer.front();
|
||||
size_t newDataSize = nDataSize + m_ResidialBS.DataLength +
|
||||
((m_bSeqHeaderInserted) ? 0 : m_Headers.DataLength);
|
||||
|
||||
mfxU8* pData = pBS->Data = new mfxU8[newDataSize];
|
||||
pBS->MaxLength = (mfxU32)newDataSize;
|
||||
|
||||
// write data left from previous samples
|
||||
WriteResidualData(pData);
|
||||
|
||||
// Write sequence headers if needed
|
||||
WriteHeaders(pData);
|
||||
|
||||
// Append new data
|
||||
WriteSampleData(pData, pDataBuffer, nDataSize);
|
||||
pBS->DataLength = (mfxU32)(pData - pBS->Data);
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class CFrameConstructor
|
||||
{
|
||||
public:
|
||||
CFrameConstructor();
|
||||
virtual ~CFrameConstructor();
|
||||
virtual mfxStatus ConstructHeaders(VIDEOINFOHEADER2* vih, const GUID& guidFormat, size_t nMtSize, size_t nVideoInfoSize);
|
||||
virtual mfxStatus ConstructFrame(IMediaSample* pSample, mfxBitstream* pBS);
|
||||
virtual void Reset();
|
||||
void SaveResidialData(mfxBitstream* pBS);
|
||||
inline mfxBitstream& GetHeaders() { return m_Headers; }
|
||||
void SetDvdPacketStripping(bool stripPackets) { m_bDvdStripPackets = stripPackets; }
|
||||
|
||||
protected:
|
||||
static void UpdateTimeStamp(IMediaSample* pSample, mfxBitstream* pBS);
|
||||
inline void WriteResidualData(mfxU8*& pData);
|
||||
inline void WriteHeaders(mfxU8*& pData);
|
||||
inline void WriteSampleData(mfxU8*& pData, const mfxU8* pSrc, size_t nDataSize);
|
||||
static void CFrameConstructor::StripDvdPacket(BYTE*& p, int& len);
|
||||
|
||||
bool m_bSeqHeaderInserted;
|
||||
bool m_bDvdStripPackets;
|
||||
mfxBitstream m_Headers;
|
||||
mfxBitstream m_ResidialBS;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CVC1FrameConstructor : public CFrameConstructor
|
||||
{
|
||||
public:
|
||||
CVC1FrameConstructor();
|
||||
mfxStatus ConstructFrame(IMediaSample* pSample, mfxBitstream* pBS);
|
||||
mfxStatus ConstructHeaders(VIDEOINFOHEADER2* vih, const GUID& guidFormat, size_t nMtSize, size_t nVideoInfoSize);
|
||||
void Reset();
|
||||
|
||||
protected:
|
||||
mfxStatus ConstructHeaderSM(mfxU8* pHeaderSM, mfxU32 nHeaderSize, mfxU8* pDataBuffer, mfxU32 nDataSize);
|
||||
bool StartCodeExist(mfxU8* pStart);
|
||||
|
||||
FOURCC m_FourCC;
|
||||
DWORD m_Width, m_Height;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CAVCFrameConstructor : public CFrameConstructor
|
||||
{
|
||||
public:
|
||||
CAVCFrameConstructor();
|
||||
~CAVCFrameConstructor();
|
||||
virtual mfxStatus ConstructFrame(IMediaSample* pSample, mfxBitstream* pBS);
|
||||
mfxStatus ConstructHeaders(VIDEOINFOHEADER2* vih,
|
||||
const GUID& guidFormat,
|
||||
size_t nMtSize,
|
||||
size_t nVideoInfoSize);
|
||||
|
||||
private:
|
||||
mfxU32 m_NalSize;
|
||||
mfxU32 m_HeaderNalSize;
|
||||
mfxU8 m_H264StartCode[4];
|
||||
std::vector<mfxU8> m_TempBuffer;
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
Copyright (c) 2011, INTEL CORPORATION
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// QuickSync.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
|
@ -0,0 +1,31 @@
|
|||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#define PTCHAR TCHAR*
|
||||
|
||||
#include <tchar.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Platform SDK
|
||||
#include <d3d9.h>
|
||||
#include <dshow.h>
|
||||
#include <dvdmedia.h>
|
||||
#include <initguid.h>
|
||||
|
||||
// Intel Media SDK
|
||||
#include <mfxvideo++.h>
|
||||
|
||||
// STL
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
// use our own ASSERT macro
|
||||
#undef ASSERT
|
|
@ -0,0 +1,352 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "QuickSync_defs.h"
|
||||
#include "sysmem_allocator.h"
|
||||
|
||||
#define ID_BUFFER MFX_MAKEFOURCC('B','U','F','F')
|
||||
#define ID_FRAME MFX_MAKEFOURCC('F','R','M','E')
|
||||
|
||||
#pragma warning(disable : 4100)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SysMemFrameAllocator
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
SysMemFrameAllocator::SysMemFrameAllocator()
|
||||
: m_pBufferAllocator(0), m_bOwnBufferAllocator(false)
|
||||
{
|
||||
}
|
||||
|
||||
SysMemFrameAllocator::~SysMemFrameAllocator()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
mfxStatus SysMemFrameAllocator::Init(mfxAllocatorParams* pParams)
|
||||
{
|
||||
// check if any params passed from application
|
||||
if (pParams)
|
||||
{
|
||||
SysMemAllocatorParams* pSysMemParams = 0;
|
||||
pSysMemParams = dynamic_cast<SysMemAllocatorParams*>(pParams);
|
||||
if (!pSysMemParams)
|
||||
return MFX_ERR_NOT_INITIALIZED;
|
||||
|
||||
m_pBufferAllocator = pSysMemParams->pBufferAllocator;
|
||||
m_bOwnBufferAllocator = false;
|
||||
}
|
||||
|
||||
// if buffer allocator wasn't passed from application create own
|
||||
if (!m_pBufferAllocator)
|
||||
{
|
||||
m_pBufferAllocator = new SysMemBufferAllocator;
|
||||
if (!m_pBufferAllocator)
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
|
||||
m_bOwnBufferAllocator = true;
|
||||
}
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus SysMemFrameAllocator::Close()
|
||||
{
|
||||
if (m_bOwnBufferAllocator)
|
||||
{
|
||||
delete m_pBufferAllocator;
|
||||
m_pBufferAllocator = 0;
|
||||
}
|
||||
|
||||
return BaseFrameAllocator::Close();
|
||||
}
|
||||
|
||||
mfxStatus SysMemFrameAllocator::LockFrame(mfxMemId mid, mfxFrameData* ptr)
|
||||
{
|
||||
if (!m_pBufferAllocator)
|
||||
return MFX_ERR_NOT_INITIALIZED;
|
||||
|
||||
if (!ptr)
|
||||
return MFX_ERR_NULL_PTR;
|
||||
|
||||
sFrame* fs = 0;
|
||||
mfxStatus sts = m_pBufferAllocator->Lock(m_pBufferAllocator->pthis, mid,(mfxU8**)&fs);
|
||||
|
||||
if (MFX_ERR_NONE != sts)
|
||||
return sts;
|
||||
|
||||
if (ID_FRAME != fs->id)
|
||||
{
|
||||
m_pBufferAllocator->Unlock(m_pBufferAllocator->pthis, mid);
|
||||
return MFX_ERR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
mfxU16 Width2 = (mfxU16)MSDK_ALIGN16(fs->info.Width);
|
||||
mfxU16 Height2 = (mfxU16)MSDK_ALIGN16(fs->info.Height);
|
||||
ptr->R = ptr->Y = (mfxU8*)fs + MSDK_ALIGN16(sizeof(sFrame));
|
||||
|
||||
switch (fs->info.FourCC)
|
||||
{
|
||||
case MFX_FOURCC_NV12:
|
||||
ptr->U = ptr->Y + Width2 * Height2;
|
||||
ptr->V = ptr->U + 1;
|
||||
ptr->Pitch = Width2;
|
||||
break;
|
||||
case MFX_FOURCC_YV12:
|
||||
ptr->V = ptr->Y + Width2 * Height2;
|
||||
ptr->U = ptr->V + (Width2 >> 1) * (Height2 >> 1);
|
||||
ptr->Pitch = Width2;
|
||||
break;
|
||||
case MFX_FOURCC_YUY2:
|
||||
ptr->U = ptr->Y + 1;
|
||||
ptr->V = ptr->Y + 3;
|
||||
ptr->Pitch = 2 * Width2;
|
||||
break;
|
||||
case MFX_FOURCC_RGB3:
|
||||
ptr->G = ptr->R + 1;
|
||||
ptr->B = ptr->R + 2;
|
||||
ptr->Pitch = 3 * Width2;
|
||||
break;
|
||||
case MFX_FOURCC_RGB4:
|
||||
ptr->G = ptr->R + 1;
|
||||
ptr->B = ptr->R + 2;
|
||||
ptr->A = ptr->R + 3;
|
||||
ptr->Pitch = 4 * Width2;
|
||||
break;
|
||||
default:
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus SysMemFrameAllocator::UnlockFrame(mfxMemId mid, mfxFrameData* ptr)
|
||||
{
|
||||
if (!m_pBufferAllocator)
|
||||
return MFX_ERR_NOT_INITIALIZED;
|
||||
|
||||
mfxStatus sts = m_pBufferAllocator->Unlock(m_pBufferAllocator->pthis, mid);
|
||||
|
||||
if (MFX_ERR_NONE != sts)
|
||||
return sts;
|
||||
|
||||
if (NULL != ptr)
|
||||
{
|
||||
ptr->Pitch = 0;
|
||||
ptr->Y = 0;
|
||||
ptr->U = 0;
|
||||
ptr->V = 0;
|
||||
}
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus SysMemFrameAllocator::GetFrameHDL(mfxMemId mid, mfxHDL* handle)
|
||||
{
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
mfxStatus SysMemFrameAllocator::CheckRequestType(mfxFrameAllocRequest* request)
|
||||
{
|
||||
mfxStatus sts = BaseFrameAllocator::CheckRequestType(request);
|
||||
if (MFX_ERR_NONE != sts)
|
||||
return sts;
|
||||
|
||||
if ((request->Type & MFX_MEMTYPE_SYSTEM_MEMORY) != 0)
|
||||
return MFX_ERR_NONE;
|
||||
else
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
mfxStatus SysMemFrameAllocator::AllocImpl(mfxFrameAllocRequest* request, mfxFrameAllocResponse* response)
|
||||
{
|
||||
if (!m_pBufferAllocator)
|
||||
return MFX_ERR_NOT_INITIALIZED;
|
||||
|
||||
mfxU32 numAllocated = 0;
|
||||
|
||||
mfxU32 Width2 = MSDK_ALIGN16(request->Info.Width);
|
||||
mfxU32 Height2 = MSDK_ALIGN16(request->Info.Height);
|
||||
mfxU32 nbytes;
|
||||
mfxU8 nBitsPerPixel;
|
||||
|
||||
switch (request->Info.FourCC)
|
||||
{
|
||||
case MFX_FOURCC_YV12:
|
||||
case MFX_FOURCC_NV12:
|
||||
nBitsPerPixel = 12;
|
||||
break;
|
||||
case MFX_FOURCC_RGB3:
|
||||
nBitsPerPixel = 24;
|
||||
break;
|
||||
case MFX_FOURCC_RGB4:
|
||||
nBitsPerPixel = 32;
|
||||
break;
|
||||
case MFX_FOURCC_YUY2:
|
||||
nBitsPerPixel = 16;
|
||||
break;
|
||||
default:
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
nbytes = Width2 * Height2 * nBitsPerPixel / 8;
|
||||
|
||||
safe_array<mfxMemId> mids(new mfxMemId[request->NumFrameSuggested]);
|
||||
if (!mids.get())
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
|
||||
// allocate frames
|
||||
for (numAllocated = 0; numAllocated < request->NumFrameSuggested; ++numAllocated)
|
||||
{
|
||||
mfxStatus sts = m_pBufferAllocator->Alloc(m_pBufferAllocator->pthis,
|
||||
nbytes + MSDK_ALIGN16(sizeof(sFrame)), request->Type, &(mids.get()[numAllocated]));
|
||||
|
||||
if (MFX_ERR_NONE != sts)
|
||||
break;
|
||||
|
||||
sFrame* fs;
|
||||
sts = m_pBufferAllocator->Lock(m_pBufferAllocator->pthis, mids.get()[numAllocated], (mfxU8**)&fs);
|
||||
|
||||
if (MFX_ERR_NONE != sts)
|
||||
break;
|
||||
|
||||
fs->id = ID_FRAME;
|
||||
fs->info = request->Info;
|
||||
m_pBufferAllocator->Unlock(m_pBufferAllocator->pthis, mids.get()[numAllocated]);
|
||||
}
|
||||
|
||||
// check the number of allocated frames
|
||||
if (numAllocated < request->NumFrameMin)
|
||||
{
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
}
|
||||
|
||||
response->NumFrameActual = (mfxU16) numAllocated;
|
||||
response->mids = mids.release();
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus SysMemFrameAllocator::ReleaseResponse(mfxFrameAllocResponse* response)
|
||||
{
|
||||
if (!response)
|
||||
return MFX_ERR_NULL_PTR;
|
||||
|
||||
if (!m_pBufferAllocator)
|
||||
return MFX_ERR_NOT_INITIALIZED;
|
||||
|
||||
mfxStatus sts = MFX_ERR_NONE;
|
||||
|
||||
if (response->mids)
|
||||
{
|
||||
for (mfxU32 i = 0; i < response->NumFrameActual; i++)
|
||||
{
|
||||
if (response->mids[i])
|
||||
{
|
||||
sts = m_pBufferAllocator->Free(m_pBufferAllocator->pthis, response->mids[i]);
|
||||
if (MFX_ERR_NONE != sts)
|
||||
return sts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] response->mids;
|
||||
response->mids = 0;
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SysMemBufferAllocator
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
SysMemBufferAllocator::SysMemBufferAllocator()
|
||||
{
|
||||
}
|
||||
|
||||
SysMemBufferAllocator::~SysMemBufferAllocator()
|
||||
{
|
||||
}
|
||||
|
||||
mfxStatus SysMemBufferAllocator::AllocBuffer(mfxU32 nbytes, mfxU16 type, mfxMemId* mid)
|
||||
{
|
||||
if (!mid)
|
||||
return MFX_ERR_NULL_PTR;
|
||||
|
||||
if (0 == (type & MFX_MEMTYPE_SYSTEM_MEMORY))
|
||||
return MFX_ERR_UNSUPPORTED;
|
||||
|
||||
size_t allocSize = MSDK_ALIGN16(sizeof(sBuffer)) + nbytes;
|
||||
mfxU8* buffer_ptr = (mfxU8*)_aligned_malloc(allocSize, 16);
|
||||
MSDK_ZERO_MEMORY(buffer_ptr, allocSize);
|
||||
|
||||
if (!buffer_ptr)
|
||||
return MFX_ERR_MEMORY_ALLOC;
|
||||
|
||||
sBuffer* bs = (sBuffer*)buffer_ptr;
|
||||
bs->id = ID_BUFFER;
|
||||
bs->type = type;
|
||||
bs->nbytes = nbytes;
|
||||
*mid = (mfxHDL) bs;
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus SysMemBufferAllocator::LockBuffer(mfxMemId mid, mfxU8** ptr)
|
||||
{
|
||||
if (!ptr)
|
||||
return MFX_ERR_NULL_PTR;
|
||||
|
||||
sBuffer* bs = (sBuffer*)mid;
|
||||
|
||||
if (!bs)
|
||||
return MFX_ERR_INVALID_HANDLE;
|
||||
if (ID_BUFFER != bs->id)
|
||||
return MFX_ERR_INVALID_HANDLE;
|
||||
|
||||
*ptr = (mfxU8*)bs + MSDK_ALIGN16(sizeof(sBuffer));
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus SysMemBufferAllocator::UnlockBuffer(mfxMemId mid)
|
||||
{
|
||||
sBuffer* bs = (sBuffer*)mid;
|
||||
|
||||
if (!bs || ID_BUFFER != bs->id)
|
||||
return MFX_ERR_INVALID_HANDLE;
|
||||
|
||||
return MFX_ERR_NONE;
|
||||
}
|
||||
|
||||
mfxStatus SysMemBufferAllocator::FreeBuffer(mfxMemId mid)
|
||||
{
|
||||
sBuffer* bs = (sBuffer*)mid;
|
||||
if (!bs || ID_BUFFER != bs->id)
|
||||
return MFX_ERR_INVALID_HANDLE;
|
||||
|
||||
_aligned_free (bs);
|
||||
return MFX_ERR_NONE;
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2011, INTEL CORPORATION
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
* Neither the name of INTEL CORPORATION nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base_allocator.h"
|
||||
|
||||
struct sBuffer
|
||||
{
|
||||
union
|
||||
{
|
||||
mfxU32 id;
|
||||
char idName[4];
|
||||
};
|
||||
mfxU32 nbytes;
|
||||
mfxU16 type;
|
||||
};
|
||||
|
||||
struct sFrame
|
||||
{
|
||||
union
|
||||
{
|
||||
mfxU32 id;
|
||||
char idName[4];
|
||||
};
|
||||
mfxFrameInfo info;
|
||||
};
|
||||
|
||||
struct SysMemAllocatorParams : mfxAllocatorParams
|
||||
{
|
||||
MFXBufferAllocator* pBufferAllocator;
|
||||
};
|
||||
|
||||
class SysMemFrameAllocator: public BaseFrameAllocator
|
||||
{
|
||||
public:
|
||||
SysMemFrameAllocator();
|
||||
virtual ~SysMemFrameAllocator();
|
||||
|
||||
virtual mfxStatus Init(mfxAllocatorParams* pParams);
|
||||
virtual mfxStatus Close();
|
||||
|
||||
protected:
|
||||
virtual mfxStatus LockFrame(mfxMemId mid, mfxFrameData* ptr);
|
||||
virtual mfxStatus UnlockFrame(mfxMemId mid, mfxFrameData* ptr);
|
||||
virtual mfxStatus GetFrameHDL(mfxMemId mid, mfxHDL* handle);
|
||||
virtual mfxStatus CheckRequestType(mfxFrameAllocRequest* request);
|
||||
virtual mfxStatus ReleaseResponse(mfxFrameAllocResponse* response);
|
||||
virtual mfxStatus AllocImpl(mfxFrameAllocRequest* request, mfxFrameAllocResponse* response);
|
||||
|
||||
MFXBufferAllocator* m_pBufferAllocator;
|
||||
bool m_bOwnBufferAllocator;
|
||||
};
|
||||
|
||||
class SysMemBufferAllocator : public MFXBufferAllocator
|
||||
{
|
||||
public:
|
||||
SysMemBufferAllocator();
|
||||
virtual ~SysMemBufferAllocator();
|
||||
|
||||
protected:
|
||||
virtual mfxStatus AllocBuffer(mfxU32 nbytes, mfxU16 type, mfxMemId* mid);
|
||||
virtual mfxStatus LockBuffer(mfxMemId mid, mfxU8** ptr);
|
||||
virtual mfxStatus UnlockBuffer(mfxMemId mid);
|
||||
virtual mfxStatus FreeBuffer(mfxMemId mid);
|
||||
};
|
Loading…
Reference in New Issue