1
0
Fork 0

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:
egur 2011-11-07 09:26:34 +00:00
commit 9c439b090b
40 changed files with 7060 additions and 0 deletions

68
CodecInfo.h Normal file
View File

@ -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
};

101
H264Nalu.cpp Normal file
View File

@ -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;
}

81
H264Nalu.h Normal file
View File

@ -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();
};

133
IQuickSyncDecoder.h Normal file
View File

@ -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);
}

View File

@ -0,0 +1,4 @@
EXPORTS
createQuickSync
destroyQuickSync
getVersion

View File

@ -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>

View File

@ -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>

105
MSDK/include/mfxdefs.h Normal file
View File

@ -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__ */

91
MSDK/include/mfxmvc.h Normal file
View File

@ -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

View File

@ -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

90
MSDK/include/mfxplugin.h Normal file
View File

@ -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__ */

View File

@ -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

127
MSDK/include/mfxvideo++.h Normal file
View File

@ -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

117
MSDK/include/mfxvideo.h Normal file
View File

@ -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

BIN
MSDK/lib/win32/libmfx.lib Normal file

Binary file not shown.

BIN
MSDK/lib/win32/libmfxmd.lib Normal file

Binary file not shown.

BIN
MSDK/lib/x64/libmfx.lib Normal file

Binary file not shown.

BIN
MSDK/lib/x64/libmfxmd.lib Normal file

Binary file not shown.

965
QuickSync.cpp Normal file
View File

@ -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(&params);
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, &params, 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;
}

115
QuickSync.h Normal file
View File

@ -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;
};

501
QuickSyncDecoder.cpp Normal file
View File

@ -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);
}

122
QuickSyncDecoder.h Normal file
View File

@ -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);
};

50
QuickSyncExports.cpp Normal file
View File

@ -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.";
}

378
QuickSyncUtils.cpp Normal file
View File

@ -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";
}

86
QuickSyncUtils.h Normal file
View File

@ -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);
};

125
QuickSync_defs.h Normal file
View File

@ -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

463
TimeManager.cpp Normal file
View File

@ -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;
}

134
TimeManager.h Normal file
View File

@ -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;
};

229
base_alllocator.cpp Normal file
View File

@ -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);
}

163
base_allocator.h Normal file
View File

@ -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);
};

358
d3d_allocator.cpp Normal file
View File

@ -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;
}

74
d3d_allocator.h Normal file
View File

@ -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;
};

BIN
doc/FFDShow QuickSync.docx Normal file

Binary file not shown.

623
frame_constructors.cpp Normal file
View File

@ -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;
}

92
frame_constructors.h Normal file
View File

@ -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;
};

26
license.txt Normal file
View File

@ -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.

8
stdafx.cpp Normal file
View File

@ -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

31
stdafx.h Normal file
View 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

352
sysmem_allocator.cpp Normal file
View File

@ -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;
}

91
sysmem_allocator.h Normal file
View File

@ -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);
};