Merge remote-tracking branch 'upstream/master' into mh-channel-fix
Conflicts: channels/drdynvc/client/drdynvc_main.c channels/rdpgfx/client/rdpgfx_main.c client/X11/xf_gfx.c
This commit is contained in:
commit
420a86e1c7
@ -537,6 +537,10 @@ set(JPEG_FEATURE_TYPE "OPTIONAL")
|
||||
set(JPEG_FEATURE_PURPOSE "codec")
|
||||
set(JPEG_FEATURE_DESCRIPTION "use JPEG library")
|
||||
|
||||
set(X264_FEATURE_TYPE "OPTIONAL")
|
||||
set(X264_FEATURE_PURPOSE "codec")
|
||||
set(X264_FEATURE_DESCRIPTION "use x264 library")
|
||||
|
||||
set(OPENH264_FEATURE_TYPE "OPTIONAL")
|
||||
set(OPENH264_FEATURE_PURPOSE "codec")
|
||||
set(OPENH264_FEATURE_DESCRIPTION "use OpenH264 library")
|
||||
@ -620,6 +624,7 @@ find_feature(GStreamer_0_10 ${GSTREAMER_0_10_FEATURE_TYPE} ${GSTREAMER_0_10_FEAT
|
||||
find_feature(GStreamer_1_0 ${GSTREAMER_1_0_FEATURE_TYPE} ${GSTREAMER_1_0_FEATURE_PURPOSE} ${GSTREAMER_1_0_FEATURE_DESCRIPTION})
|
||||
|
||||
find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DESCRIPTION})
|
||||
find_feature(x264 ${X264_FEATURE_TYPE} ${X264_FEATURE_PURPOSE} ${X264_FEATURE_DESCRIPTION})
|
||||
find_feature(OpenH264 ${OPENH264_FEATURE_TYPE} ${OPENH264_FEATURE_PURPOSE} ${OPENH264_FEATURE_DESCRIPTION})
|
||||
find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION})
|
||||
|
||||
|
@ -50,6 +50,7 @@ static WIN32ERROR dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
|
||||
WLog_DBG(TAG, "create_listener: %d.%s.", dvcman->num_listeners, pszChannelName);
|
||||
|
||||
listener = (DVCMAN_LISTENER*) calloc(1, sizeof(DVCMAN_LISTENER));
|
||||
|
||||
if (!listener)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -501,8 +502,12 @@ WIN32ERROR dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 C
|
||||
|
||||
if (!channel)
|
||||
{
|
||||
WLog_ERR(TAG, "ChannelId %d not found!", ChannelId);
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
//WLog_ERR(TAG, "ChannelId %d not found!", ChannelId);
|
||||
/**
|
||||
* Windows 8 / Windows Server 2012 send close requests for channels that failed to be created.
|
||||
* Do not warn, simply return success here.
|
||||
*/
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
if (channel->status == CHANNEL_RC_OK)
|
||||
@ -548,6 +553,7 @@ WIN32ERROR dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannel
|
||||
Stream_Release(channel->dvc_data);
|
||||
|
||||
channel->dvc_data = StreamPool_Take(channel->dvcman->pool, length);
|
||||
|
||||
if (!channel->dvc_data)
|
||||
{
|
||||
WLog_ERR(TAG, "StreamPool_Take failed!");
|
||||
@ -755,6 +761,7 @@ static WIN32ERROR drdynvc_send_capability_response(drdynvcPlugin* drdynvc)
|
||||
wStream* s;
|
||||
|
||||
WLog_DBG(TAG, "capability_response");
|
||||
|
||||
s = Stream_New(NULL, 4);
|
||||
|
||||
if (!s)
|
||||
@ -877,12 +884,7 @@ static WIN32ERROR drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
|
||||
else
|
||||
{
|
||||
WLog_DBG(TAG, "no listener");
|
||||
Stream_Write_UINT32(data_out, (UINT32)(-1));
|
||||
if ((status = dvcman_close_channel(drdynvc->channel_mgr, ChannelId)))
|
||||
{
|
||||
WLog_ERR(TAG, "dvcman_close_channel failed with error %lu!", status);
|
||||
return status;
|
||||
}
|
||||
Stream_Write_UINT32(data_out, (UINT32) 0xC0000001); /* same code used by mstsc */
|
||||
}
|
||||
|
||||
status = drdynvc_send(drdynvc, data_out);
|
||||
@ -902,6 +904,11 @@ static WIN32ERROR drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
|
||||
return status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((status = dvcman_close_channel(drdynvc->channel_mgr, ChannelId)))
|
||||
WLog_ERR(TAG, "dvcman_close_channel failed with error %lu!", status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -1052,6 +1059,7 @@ void* drdynvc_get_init_handle_data(void* pInitHandle)
|
||||
void drdynvc_remove_init_handle_data(void* pInitHandle)
|
||||
{
|
||||
ListDictionary_Remove(g_InitHandles, pInitHandle);
|
||||
|
||||
if (ListDictionary_Count(g_InitHandles) < 1)
|
||||
{
|
||||
ListDictionary_Free(g_InitHandles);
|
||||
@ -1093,6 +1101,7 @@ void drdynvc_remove_open_handle_data(DWORD openHandle)
|
||||
{
|
||||
void* pOpenHandle = (void*) (size_t) openHandle;
|
||||
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
|
||||
|
||||
if (ListDictionary_Count(g_OpenHandles) < 1)
|
||||
{
|
||||
ListDictionary_Free(g_OpenHandles);
|
||||
|
@ -130,7 +130,6 @@ WIN32ERROR rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStre
|
||||
RDPGFX_CAPSET capsSet;
|
||||
UINT32 capsDataLength;
|
||||
RDPGFX_CAPS_CONFIRM_PDU pdu;
|
||||
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
|
||||
|
||||
pdu.capsSet = &capsSet;
|
||||
|
||||
@ -143,8 +142,6 @@ WIN32ERROR rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStre
|
||||
Stream_Read_UINT32(s, capsSet.version); /* version (4 bytes) */
|
||||
Stream_Read_UINT32(s, capsDataLength); /* capsDataLength (4 bytes) */
|
||||
Stream_Read_UINT32(s, capsSet.flags); /* capsData (4 bytes) */
|
||||
|
||||
/*TODO: interpret this answer*/
|
||||
|
||||
WLog_DBG(TAG, "RecvCapsConfirmPdu: version: 0x%04X flags: 0x%04X",
|
||||
capsSet.version, capsSet.flags);
|
||||
@ -157,7 +154,6 @@ WIN32ERROR rdpgfx_send_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
|
||||
WIN32ERROR error;
|
||||
wStream* s;
|
||||
RDPGFX_HEADER header;
|
||||
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
|
||||
|
||||
header.flags = 0;
|
||||
header.cmdId = RDPGFX_CMDID_FRAMEACKNOWLEDGE;
|
||||
@ -461,11 +457,20 @@ WIN32ERROR rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream*
|
||||
ack.frameId = pdu.frameId;
|
||||
ack.totalFramesDecoded = gfx->TotalDecodedFrames;
|
||||
|
||||
//ack.queueDepth = SUSPEND_FRAME_ACKNOWLEDGEMENT;
|
||||
ack.queueDepth = QUEUE_DEPTH_UNAVAILABLE;
|
||||
if (gfx->suspendFrameAcks)
|
||||
{
|
||||
ack.queueDepth = SUSPEND_FRAME_ACKNOWLEDGEMENT;
|
||||
|
||||
if ((error = rdpgfx_send_frame_acknowledge_pdu(callback, &ack)))
|
||||
WLog_ERR(TAG, "rdpgfx_send_frame_acknowledge_pdu failed with error %lu", error);
|
||||
if (gfx->TotalDecodedFrames == 1)
|
||||
if ((error = rdpgfx_send_frame_acknowledge_pdu(callback, &ack)))
|
||||
WLog_ERR(TAG, "rdpgfx_send_frame_acknowledge_pdu failed with error %lu", error);
|
||||
}
|
||||
else
|
||||
{
|
||||
ack.queueDepth = QUEUE_DEPTH_UNAVAILABLE;
|
||||
if ((error = rdpgfx_send_frame_acknowledge_pdu(callback, &ack)))
|
||||
WLog_ERR(TAG, "rdpgfx_send_frame_acknowledge_pdu failed with error %lu", error);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -1086,7 +1091,6 @@ static WIN32ERROR rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCa
|
||||
static WIN32ERROR rdpgfx_on_open(IWTSVirtualChannelCallback* pChannelCallback)
|
||||
{
|
||||
RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
|
||||
|
||||
WLog_DBG(TAG, "OnOpen");
|
||||
|
||||
@ -1095,13 +1099,62 @@ static WIN32ERROR rdpgfx_on_open(IWTSVirtualChannelCallback* pChannelCallback)
|
||||
|
||||
static WIN32ERROR rdpgfx_on_close(IWTSVirtualChannelCallback* pChannelCallback)
|
||||
{
|
||||
int count;
|
||||
int index;
|
||||
ULONG_PTR* pKeys = NULL;
|
||||
RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
|
||||
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
|
||||
|
||||
WLog_DBG(TAG, "OnClose");
|
||||
|
||||
free(callback);
|
||||
|
||||
gfx->UnacknowledgedFrames = 0;
|
||||
gfx->TotalDecodedFrames = 0;
|
||||
|
||||
if (gfx->zgfx)
|
||||
{
|
||||
zgfx_context_free(gfx->zgfx);
|
||||
gfx->zgfx = zgfx_context_new(FALSE);
|
||||
|
||||
if (!gfx->zgfx)
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
count = HashTable_GetKeys(gfx->SurfaceTable, &pKeys);
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
RDPGFX_DELETE_SURFACE_PDU pdu;
|
||||
|
||||
pdu.surfaceId = ((UINT16) pKeys[index]) - 1;
|
||||
|
||||
if (context && context->DeleteSurface)
|
||||
{
|
||||
context->DeleteSurface(context, &pdu);
|
||||
}
|
||||
}
|
||||
|
||||
free(pKeys);
|
||||
|
||||
for (index = 0; index < gfx->MaxCacheSlot; index++)
|
||||
{
|
||||
if (gfx->CacheSlots[index])
|
||||
{
|
||||
RDPGFX_EVICT_CACHE_ENTRY_PDU pdu;
|
||||
|
||||
pdu.cacheSlot = (UINT16) index;
|
||||
|
||||
if (context && context->EvictCacheEntry)
|
||||
{
|
||||
context->EvictCacheEntry(context, &pdu);
|
||||
}
|
||||
|
||||
gfx->CacheSlots[index] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,7 @@ struct _RDPGFX_PLUGIN
|
||||
ZGFX_CONTEXT* zgfx;
|
||||
UINT32 UnacknowledgedFrames;
|
||||
UINT32 TotalDecodedFrames;
|
||||
BOOL suspendFrameAcks;
|
||||
|
||||
wHashTable* SurfaceTable;
|
||||
|
||||
|
@ -467,7 +467,7 @@ WIN32ERROR xf_SurfaceCommand_Alpha(xfContext* xfc, RdpgfxClientContext* context,
|
||||
if (!surface)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
WLog_DBG(TAG, "xf_SurfaceCommand_Alpha: status: %d\n", status);
|
||||
WLog_DBG(TAG, "xf_SurfaceCommand_Alpha: status: %d", status);
|
||||
/* fill with green for now to distinguish from the rest */
|
||||
|
||||
freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
|
||||
|
33
cmake/Findx264.cmake
Normal file
33
cmake/Findx264.cmake
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
if (X264_INCLUDE_DIR AND X264_LIBRARY)
|
||||
set(X264_FIND_QUIETLY TRUE)
|
||||
endif (X264_INCLUDE_DIR AND X264_LIBRARY)
|
||||
|
||||
find_path(X264_INCLUDE_DIR NAMES x264.h
|
||||
PATH_SUFFIXES include
|
||||
HINTS ${X264_ROOT})
|
||||
find_library(X264_LIBRARY
|
||||
NAMES x264
|
||||
PATH_SUFFIXES lib
|
||||
HINTS ${X264_ROOT})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(x264 DEFAULT_MSG X264_LIBRARY X264_INCLUDE_DIR)
|
||||
|
||||
if (X264_INCLUDE_DIR AND X264_LIBRARY)
|
||||
set(X264_FOUND TRUE)
|
||||
set(X264_LIBRARIES ${X264_LIBRARY})
|
||||
endif (X264_INCLUDE_DIR AND X264_LIBRARY)
|
||||
|
||||
if (X264_FOUND)
|
||||
if (NOT X264_FIND_QUIETLY)
|
||||
message(STATUS "Found x264: ${X264_LIBRARIES}")
|
||||
endif (NOT X264_FIND_QUIETLY)
|
||||
else (X264_FOUND)
|
||||
if (X264_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "x264 was not found")
|
||||
endif(X264_FIND_REQUIRED)
|
||||
endif (X264_FOUND)
|
||||
|
||||
mark_as_advanced(X264_INCLUDE_DIR X264_LIBRARY)
|
||||
|
@ -165,6 +165,12 @@ if(WITH_JPEG)
|
||||
freerdp_library_add(${JPEG_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(WITH_X264)
|
||||
freerdp_definition_add(-DWITH_X264)
|
||||
freerdp_include_directory_add(${X264_INCLUDE_DIR})
|
||||
freerdp_library_add(${X264_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(WITH_OPENH264)
|
||||
freerdp_definition_add(-DWITH_OPENH264)
|
||||
freerdp_include_directory_add(${OPENH264_INCLUDE_DIR})
|
||||
|
@ -58,6 +58,739 @@ static H264_CONTEXT_SUBSYSTEM g_Subsystem_dummy =
|
||||
dummy_decompress
|
||||
};
|
||||
|
||||
/**
|
||||
* Media Foundation subsystem
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <ks.h>
|
||||
#include <codecapi.h>
|
||||
|
||||
#include <mfapi.h>
|
||||
#include <mferror.h>
|
||||
#include <wmcodecdsp.h>
|
||||
#include <mftransform.h>
|
||||
|
||||
#undef DEFINE_GUID
|
||||
#define INITGUID
|
||||
#include <initguid.h>
|
||||
|
||||
DEFINE_GUID(CLSID_CMSH264DecoderMFT,0x62CE7E72,0x4C71,0x4d20,0xB1,0x5D,0x45,0x28,0x31,0xA8,0x7D,0x9D);
|
||||
DEFINE_GUID(CLSID_VideoProcessorMFT,0x88753b26,0x5b24,0x49bd,0xb2,0xe7,0x0c,0x44,0x5c,0x78,0xc9,0x82);
|
||||
DEFINE_GUID(IID_IMFTransform,0xbf94c121,0x5b05,0x4e6f,0x80,0x00,0xba,0x59,0x89,0x61,0x41,0x4d);
|
||||
DEFINE_GUID(MF_MT_MAJOR_TYPE,0x48eba18e,0xf8c9,0x4687,0xbf,0x11,0x0a,0x74,0xc9,0xf9,0x6a,0x8f);
|
||||
DEFINE_GUID(MF_MT_FRAME_SIZE,0x1652c33d,0xd6b2,0x4012,0xb8,0x34,0x72,0x03,0x08,0x49,0xa3,0x7d);
|
||||
DEFINE_GUID(MF_MT_DEFAULT_STRIDE,0x644b4e48,0x1e02,0x4516,0xb0,0xeb,0xc0,0x1c,0xa9,0xd4,0x9a,0xc6);
|
||||
DEFINE_GUID(MF_MT_SUBTYPE,0xf7e34c9a,0x42e8,0x4714,0xb7,0x4b,0xcb,0x29,0xd7,0x2c,0x35,0xe5);
|
||||
DEFINE_GUID(MF_XVP_DISABLE_FRC,0x2c0afa19,0x7a97,0x4d5a,0x9e,0xe8,0x16,0xd4,0xfc,0x51,0x8d,0x8c);
|
||||
DEFINE_GUID(MFMediaType_Video,0x73646976,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71);
|
||||
DEFINE_GUID(MFVideoFormat_RGB32,22,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71);
|
||||
DEFINE_GUID(MFVideoFormat_ARGB32,21,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71);
|
||||
DEFINE_GUID(MFVideoFormat_H264,0x34363248,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
|
||||
DEFINE_GUID(MFVideoFormat_IYUV,0x56555949,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
|
||||
DEFINE_GUID(IID_ICodecAPI,0x901db4c7,0x31ce,0x41a2,0x85,0xdc,0x8f,0xa0,0xbf,0x41,0xb8,0xda);
|
||||
DEFINE_GUID(CODECAPI_AVLowLatencyMode,0x9c27891a,0xed7a,0x40e1,0x88,0xe8,0xb2,0x27,0x27,0xa0,0x24,0xee);
|
||||
DEFINE_GUID(CODECAPI_AVDecVideoMaxCodedWidth,0x5ae557b8,0x77af,0x41f5,0x9f,0xa6,0x4d,0xb2,0xfe,0x1d,0x4b,0xca);
|
||||
DEFINE_GUID(CODECAPI_AVDecVideoMaxCodedHeight,0x7262a16a,0xd2dc,0x4e75,0x9b,0xa8,0x65,0xc0,0xc6,0xd3,0x2b,0x13);
|
||||
|
||||
#ifndef __IMFDXGIDeviceManager_FWD_DEFINED__
|
||||
#define __IMFDXGIDeviceManager_FWD_DEFINED__
|
||||
typedef interface IMFDXGIDeviceManager IMFDXGIDeviceManager;
|
||||
#endif /* __IMFDXGIDeviceManager_FWD_DEFINED__ */
|
||||
|
||||
#ifndef __IMFDXGIDeviceManager_INTERFACE_DEFINED__
|
||||
#define __IMFDXGIDeviceManager_INTERFACE_DEFINED__
|
||||
|
||||
typedef struct IMFDXGIDeviceManagerVtbl
|
||||
{
|
||||
HRESULT (STDMETHODCALLTYPE * QueryInterface)(IMFDXGIDeviceManager* This, REFIID riid, void** ppvObject);
|
||||
ULONG (STDMETHODCALLTYPE * AddRef)(IMFDXGIDeviceManager* This);
|
||||
ULONG (STDMETHODCALLTYPE * Release)(IMFDXGIDeviceManager* This);
|
||||
HRESULT (STDMETHODCALLTYPE * CloseDeviceHandle)(IMFDXGIDeviceManager* This, HANDLE hDevice);
|
||||
HRESULT (STDMETHODCALLTYPE * GetVideoService)(IMFDXGIDeviceManager* This, HANDLE hDevice, REFIID riid, void** ppService);
|
||||
HRESULT (STDMETHODCALLTYPE * LockDevice)(IMFDXGIDeviceManager* This, HANDLE hDevice, REFIID riid, void** ppUnkDevice, BOOL fBlock);
|
||||
HRESULT (STDMETHODCALLTYPE * OpenDeviceHandle)(IMFDXGIDeviceManager* This, HANDLE* phDevice);
|
||||
HRESULT (STDMETHODCALLTYPE * ResetDevice)(IMFDXGIDeviceManager* This, IUnknown* pUnkDevice, UINT resetToken);
|
||||
HRESULT (STDMETHODCALLTYPE * TestDevice)(IMFDXGIDeviceManager* This, HANDLE hDevice);
|
||||
HRESULT (STDMETHODCALLTYPE * UnlockDevice)(IMFDXGIDeviceManager* This, HANDLE hDevice, BOOL fSaveState);
|
||||
}
|
||||
IMFDXGIDeviceManagerVtbl;
|
||||
|
||||
interface IMFDXGIDeviceManager
|
||||
{
|
||||
CONST_VTBL struct IMFDXGIDeviceManagerVtbl* lpVtbl;
|
||||
};
|
||||
|
||||
#endif /* __IMFDXGIDeviceManager_INTERFACE_DEFINED__ */
|
||||
|
||||
typedef HRESULT (__stdcall * pfnMFStartup)(ULONG Version, DWORD dwFlags);
|
||||
typedef HRESULT (__stdcall * pfnMFShutdown)(void);
|
||||
typedef HRESULT (__stdcall * pfnMFCreateSample)(IMFSample** ppIMFSample);
|
||||
typedef HRESULT (__stdcall * pfnMFCreateMemoryBuffer)(DWORD cbMaxLength, IMFMediaBuffer** ppBuffer);
|
||||
typedef HRESULT (__stdcall * pfnMFCreateMediaType)(IMFMediaType** ppMFType);
|
||||
typedef HRESULT (__stdcall * pfnMFCreateDXGIDeviceManager)(UINT* pResetToken, IMFDXGIDeviceManager** ppDXVAManager);
|
||||
|
||||
struct _H264_CONTEXT_MF
|
||||
{
|
||||
ICodecAPI* codecApi;
|
||||
IMFTransform* transform;
|
||||
IMFMediaType* inputType;
|
||||
IMFMediaType* outputType;
|
||||
IMFSample* sample;
|
||||
UINT32 frameWidth;
|
||||
UINT32 frameHeight;
|
||||
IMFSample* outputSample;
|
||||
IMFMediaBuffer* outputBuffer;
|
||||
HMODULE mfplat;
|
||||
pfnMFStartup MFStartup;
|
||||
pfnMFShutdown MFShutdown;
|
||||
pfnMFCreateSample MFCreateSample;
|
||||
pfnMFCreateMemoryBuffer MFCreateMemoryBuffer;
|
||||
pfnMFCreateMediaType MFCreateMediaType;
|
||||
pfnMFCreateDXGIDeviceManager MFCreateDXGIDeviceManager;
|
||||
};
|
||||
typedef struct _H264_CONTEXT_MF H264_CONTEXT_MF;
|
||||
|
||||
static HRESULT mf_find_output_type(H264_CONTEXT_MF* sys, const GUID* guid, IMFMediaType** ppMediaType)
|
||||
{
|
||||
DWORD idx = 0;
|
||||
GUID mediaGuid;
|
||||
HRESULT hr = S_OK;
|
||||
IMFMediaType* pMediaType = NULL;
|
||||
|
||||
while (1)
|
||||
{
|
||||
hr = sys->transform->lpVtbl->GetOutputAvailableType(sys->transform, 0, idx, &pMediaType);
|
||||
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
|
||||
pMediaType->lpVtbl->GetGUID(pMediaType, &MF_MT_SUBTYPE, &mediaGuid);
|
||||
|
||||
if (IsEqualGUID(&mediaGuid, guid))
|
||||
{
|
||||
*ppMediaType = pMediaType;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
pMediaType->lpVtbl->Release(pMediaType);
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT mf_create_output_sample(H264_CONTEXT_MF* sys)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
MFT_OUTPUT_STREAM_INFO streamInfo;
|
||||
|
||||
if (sys->outputSample)
|
||||
{
|
||||
sys->outputSample->lpVtbl->Release(sys->outputSample);
|
||||
sys->outputSample = NULL;
|
||||
}
|
||||
|
||||
hr = sys->MFCreateSample(&sys->outputSample);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "MFCreateSample failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->transform->lpVtbl->GetOutputStreamInfo(sys->transform, 0, &streamInfo);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "GetOutputStreamInfo failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->MFCreateMemoryBuffer(streamInfo.cbSize, &sys->outputBuffer);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "MFCreateMemoryBuffer failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
sys->outputSample->lpVtbl->AddBuffer(sys->outputSample, sys->outputBuffer);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "AddBuffer failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
sys->outputBuffer->lpVtbl->Release(sys->outputBuffer);
|
||||
|
||||
error:
|
||||
return hr;
|
||||
}
|
||||
|
||||
static int mf_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize)
|
||||
{
|
||||
HRESULT hr;
|
||||
BYTE* pbBuffer = NULL;
|
||||
DWORD cbMaxLength = 0;
|
||||
DWORD cbCurrentLength = 0;
|
||||
DWORD outputStatus = 0;
|
||||
IMFSample* inputSample = NULL;
|
||||
IMFMediaBuffer* inputBuffer = NULL;
|
||||
IMFMediaBuffer* outputBuffer = NULL;
|
||||
MFT_OUTPUT_DATA_BUFFER outputDataBuffer;
|
||||
H264_CONTEXT_MF* sys = (H264_CONTEXT_MF*) h264->pSystemData;
|
||||
|
||||
hr = sys->MFCreateMemoryBuffer(SrcSize, &inputBuffer);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "MFCreateMemoryBuffer failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = inputBuffer->lpVtbl->Lock(inputBuffer, &pbBuffer, &cbMaxLength, &cbCurrentLength);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "Lock failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
CopyMemory(pbBuffer, pSrcData, SrcSize);
|
||||
|
||||
hr = inputBuffer->lpVtbl->SetCurrentLength(inputBuffer, SrcSize);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "SetCurrentLength failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = inputBuffer->lpVtbl->Unlock(inputBuffer);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "Unlock failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->MFCreateSample(&inputSample);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "MFCreateSample failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
inputSample->lpVtbl->AddBuffer(inputSample, inputBuffer);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "AddBuffer failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
inputBuffer->lpVtbl->Release(inputBuffer);
|
||||
|
||||
hr = sys->transform->lpVtbl->ProcessInput(sys->transform, 0, inputSample, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "ProcessInput failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = mf_create_output_sample(sys);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "mf_create_output_sample failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
outputDataBuffer.dwStreamID = 0;
|
||||
outputDataBuffer.dwStatus = 0;
|
||||
outputDataBuffer.pEvents = NULL;
|
||||
outputDataBuffer.pSample = sys->outputSample;
|
||||
|
||||
hr = sys->transform->lpVtbl->ProcessOutput(sys->transform, 0, 1, &outputDataBuffer, &outputStatus);
|
||||
|
||||
if (hr == MF_E_TRANSFORM_STREAM_CHANGE)
|
||||
{
|
||||
BYTE* pYUVData;
|
||||
int offset = 0;
|
||||
UINT32 stride = 0;
|
||||
UINT64 frameSize = 0;
|
||||
IMFAttributes* attributes = NULL;
|
||||
|
||||
if (sys->outputType)
|
||||
{
|
||||
sys->outputType->lpVtbl->Release(sys->outputType);
|
||||
sys->outputType = NULL;
|
||||
}
|
||||
|
||||
hr = mf_find_output_type(sys, &MFVideoFormat_IYUV, &sys->outputType);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "mf_find_output_type failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->transform->lpVtbl->SetOutputType(sys->transform, 0, sys->outputType, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "SetOutputType failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = mf_create_output_sample(sys);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "mf_create_output_sample failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->outputType->lpVtbl->GetUINT64(sys->outputType, &MF_MT_FRAME_SIZE, &frameSize);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "GetUINT64(MF_MT_FRAME_SIZE) failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
sys->frameWidth = (UINT32) (frameSize >> 32);
|
||||
sys->frameHeight = (UINT32) frameSize;
|
||||
|
||||
hr = sys->outputType->lpVtbl->GetUINT32(sys->outputType, &MF_MT_DEFAULT_STRIDE, &stride);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "GetUINT32(MF_MT_DEFAULT_STRIDE) failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
h264->iStride[0] = stride;
|
||||
h264->iStride[1] = stride / 2;
|
||||
h264->iStride[2] = stride / 2;
|
||||
|
||||
pYUVData = (BYTE*) calloc(1, 2 * stride * sys->frameHeight);
|
||||
|
||||
h264->pYUVData[0] = &pYUVData[offset];
|
||||
pYUVData += h264->iStride[0] * sys->frameHeight;
|
||||
|
||||
h264->pYUVData[1] = &pYUVData[offset];
|
||||
pYUVData += h264->iStride[1] * (sys->frameHeight / 2);
|
||||
|
||||
h264->pYUVData[2] = &pYUVData[offset];
|
||||
pYUVData += h264->iStride[2] * (sys->frameHeight / 2);
|
||||
|
||||
h264->width = sys->frameWidth;
|
||||
h264->height = sys->frameHeight;
|
||||
}
|
||||
else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
|
||||
{
|
||||
|
||||
}
|
||||
else if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "ProcessOutput failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = 0;
|
||||
BYTE* buffer = NULL;
|
||||
DWORD bufferCount = 0;
|
||||
DWORD cbMaxLength = 0;
|
||||
DWORD cbCurrentLength = 0;
|
||||
|
||||
hr = sys->outputSample->lpVtbl->GetBufferCount(sys->outputSample, &bufferCount);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "GetBufferCount failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->outputSample->lpVtbl->GetBufferByIndex(sys->outputSample, 0, &outputBuffer);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "GetBufferByIndex failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = outputBuffer->lpVtbl->Lock(outputBuffer, &buffer, &cbMaxLength, &cbCurrentLength);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "Lock failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
CopyMemory(h264->pYUVData[0], &buffer[offset], h264->iStride[0] * sys->frameHeight);
|
||||
offset += h264->iStride[0] * sys->frameHeight;
|
||||
|
||||
CopyMemory(h264->pYUVData[1], &buffer[offset], h264->iStride[1] * (sys->frameHeight / 2));
|
||||
offset += h264->iStride[1] * (sys->frameHeight / 2);
|
||||
|
||||
CopyMemory(h264->pYUVData[2], &buffer[offset], h264->iStride[2] * (sys->frameHeight / 2));
|
||||
offset += h264->iStride[2] * (sys->frameHeight / 2);
|
||||
|
||||
hr = outputBuffer->lpVtbl->Unlock(outputBuffer);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "Unlock failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
outputBuffer->lpVtbl->Release(outputBuffer);
|
||||
}
|
||||
|
||||
inputSample->lpVtbl->Release(inputSample);
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
fprintf(stderr, "mf_decompress error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mf_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize)
|
||||
{
|
||||
H264_CONTEXT_MF* sys = (H264_CONTEXT_MF*) h264->pSystemData;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void mf_uninit(H264_CONTEXT* h264)
|
||||
{
|
||||
H264_CONTEXT_MF* sys = (H264_CONTEXT_MF*) h264->pSystemData;
|
||||
|
||||
if (sys)
|
||||
{
|
||||
if (sys->transform)
|
||||
{
|
||||
sys->transform->lpVtbl->Release(sys->transform);
|
||||
sys->transform = NULL;
|
||||
}
|
||||
|
||||
if (sys->codecApi)
|
||||
{
|
||||
sys->codecApi->lpVtbl->Release(sys->codecApi);
|
||||
sys->codecApi = NULL;
|
||||
}
|
||||
|
||||
if (sys->inputType)
|
||||
{
|
||||
sys->inputType->lpVtbl->Release(sys->inputType);
|
||||
sys->inputType = NULL;
|
||||
}
|
||||
|
||||
if (sys->outputType)
|
||||
{
|
||||
sys->outputType->lpVtbl->Release(sys->outputType);
|
||||
sys->outputType = NULL;
|
||||
}
|
||||
|
||||
if (sys->outputSample)
|
||||
{
|
||||
sys->outputSample->lpVtbl->Release(sys->outputSample);
|
||||
sys->outputSample = NULL;
|
||||
}
|
||||
|
||||
if (sys->mfplat)
|
||||
{
|
||||
FreeLibrary(sys->mfplat);
|
||||
sys->mfplat = NULL;
|
||||
}
|
||||
|
||||
free(h264->pYUVData[0]);
|
||||
h264->pYUVData[0] = h264->pYUVData[1] = h264->pYUVData[2] = NULL;
|
||||
h264->iStride[0] = h264->iStride[1] = h264->iStride[2] = 0;
|
||||
|
||||
sys->MFShutdown();
|
||||
|
||||
CoUninitialize();
|
||||
|
||||
free(sys);
|
||||
h264->pSystemData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL mf_init(H264_CONTEXT* h264)
|
||||
{
|
||||
HRESULT hr;
|
||||
H264_CONTEXT_MF* sys;
|
||||
|
||||
sys = (H264_CONTEXT_MF*) calloc(1, sizeof(H264_CONTEXT_MF));
|
||||
|
||||
if (!sys)
|
||||
goto error;
|
||||
|
||||
h264->pSystemData = (void*) sys;
|
||||
|
||||
/* http://decklink-sdk-delphi.googlecode.com/svn/trunk/Blackmagic%20DeckLink%20SDK%209.7/Win/Samples/Streaming/StreamingPreview/DecoderMF.cpp */
|
||||
|
||||
sys->mfplat = LoadLibraryA("mfplat.dll");
|
||||
|
||||
if (!sys->mfplat)
|
||||
goto error;
|
||||
|
||||
sys->MFStartup = (pfnMFStartup) GetProcAddress(sys->mfplat, "MFStartup");
|
||||
sys->MFShutdown = (pfnMFShutdown) GetProcAddress(sys->mfplat, "MFShutdown");
|
||||
sys->MFCreateSample = (pfnMFCreateSample) GetProcAddress(sys->mfplat, "MFCreateSample");
|
||||
sys->MFCreateMemoryBuffer = (pfnMFCreateMemoryBuffer) GetProcAddress(sys->mfplat, "MFCreateMemoryBuffer");
|
||||
sys->MFCreateMediaType = (pfnMFCreateMediaType) GetProcAddress(sys->mfplat, "MFCreateMediaType");
|
||||
sys->MFCreateDXGIDeviceManager = (pfnMFCreateDXGIDeviceManager) GetProcAddress(sys->mfplat, "MFCreateDXGIDeviceManager");
|
||||
|
||||
if (!sys->MFStartup || !sys->MFShutdown || !sys->MFCreateSample || !sys->MFCreateMemoryBuffer ||
|
||||
!sys->MFCreateMediaType || !sys->MFCreateDXGIDeviceManager)
|
||||
goto error;
|
||||
|
||||
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||
|
||||
if (h264->Compressor)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
VARIANT var = { 0 };
|
||||
|
||||
hr = sys->MFStartup(MF_VERSION, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "MFStartup failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = CoCreateInstance(&CLSID_CMSH264DecoderMFT, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void**) &sys->transform);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "CoCreateInstance(CLSID_CMSH264DecoderMFT) failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->transform->lpVtbl->QueryInterface(sys->transform, &IID_ICodecAPI, (void**) &sys->codecApi);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "QueryInterface(IID_ICodecAPI) failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
var.vt = VT_UI4;
|
||||
var.ulVal = 1;
|
||||
|
||||
hr = sys->codecApi->lpVtbl->SetValue(sys->codecApi, &CODECAPI_AVLowLatencyMode, &var);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "SetValue(CODECAPI_AVLowLatencyMode) failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->MFCreateMediaType(&sys->inputType);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "MFCreateMediaType failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->inputType->lpVtbl->SetGUID(sys->inputType, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "SetGUID(MF_MT_MAJOR_TYPE) failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->inputType->lpVtbl->SetGUID(sys->inputType, &MF_MT_SUBTYPE, &MFVideoFormat_H264);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "SetGUID(MF_MT_SUBTYPE) failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->transform->lpVtbl->SetInputType(sys->transform, 0, sys->inputType, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "SetInputType failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = mf_find_output_type(sys, &MFVideoFormat_IYUV, &sys->outputType);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "mf_find_output_type failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->transform->lpVtbl->SetOutputType(sys->transform, 0, sys->outputType, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "SetOutputType failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = mf_create_output_sample(sys);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_ERR(TAG, "mf_create_output_sample failure: 0x%04X", hr);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
WLog_ERR(TAG, "mf_init failure");
|
||||
mf_uninit(h264);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static H264_CONTEXT_SUBSYSTEM g_Subsystem_MF =
|
||||
{
|
||||
"MediaFoundation",
|
||||
mf_init,
|
||||
mf_uninit,
|
||||
mf_decompress,
|
||||
mf_compress
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* x264 subsystem
|
||||
*/
|
||||
|
||||
#ifdef WITH_X264
|
||||
|
||||
#define NAL_UNKNOWN X264_NAL_UNKNOWN
|
||||
#define NAL_SLICE X264_NAL_SLICE
|
||||
#define NAL_SLICE_DPA X264_NAL_SLICE_DPA
|
||||
#define NAL_SLICE_DPB X264_NAL_SLICE_DPB
|
||||
#define NAL_SLICE_DPC X264_NAL_SLICE_DPC
|
||||
#define NAL_SLICE_IDR X264_NAL_SLICE_IDR
|
||||
#define NAL_SEI X264_NAL_SEI
|
||||
#define NAL_SPS X264_NAL_SPS
|
||||
#define NAL_PPS X264_NAL_PPS
|
||||
#define NAL_AUD X264_NAL_AUD
|
||||
#define NAL_FILLER X264_NAL_FILLER
|
||||
|
||||
#define NAL_PRIORITY_DISPOSABLE X264_NAL_PRIORITY_DISPOSABLE
|
||||
#define NAL_PRIORITY_LOW X264_NAL_PRIORITY_LOW
|
||||
#define NAL_PRIORITY_HIGH X264_NAL_PRIORITY_HIGH
|
||||
#define NAL_PRIORITY_HIGHEST X264_NAL_PRIORITY_HIGHEST
|
||||
|
||||
#include <stdint.h>
|
||||
#include <x264.h>
|
||||
|
||||
struct _H264_CONTEXT_X264
|
||||
{
|
||||
void* dummy;
|
||||
};
|
||||
typedef struct _H264_CONTEXT_X264 H264_CONTEXT_X264;
|
||||
|
||||
static int x264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize)
|
||||
{
|
||||
//H264_CONTEXT_X264* sys = (H264_CONTEXT_X264*) h264->pSystemData;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int x264_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize)
|
||||
{
|
||||
//H264_CONTEXT_X264* sys = (H264_CONTEXT_X264*) h264->pSystemData;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void x264_uninit(H264_CONTEXT* h264)
|
||||
{
|
||||
H264_CONTEXT_X264* sys = (H264_CONTEXT_X264*) h264->pSystemData;
|
||||
|
||||
if (sys)
|
||||
{
|
||||
free(sys);
|
||||
h264->pSystemData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL x264_init(H264_CONTEXT* h264)
|
||||
{
|
||||
H264_CONTEXT_X264* sys;
|
||||
|
||||
sys = (H264_CONTEXT_X264*) calloc(1, sizeof(H264_CONTEXT_X264));
|
||||
|
||||
if (!sys)
|
||||
{
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
h264->pSystemData = (void*) sys;
|
||||
|
||||
if (h264->Compressor)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
EXCEPTION:
|
||||
x264_uninit(h264);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static H264_CONTEXT_SUBSYSTEM g_Subsystem_x264 =
|
||||
{
|
||||
"x264",
|
||||
x264_init,
|
||||
x264_uninit,
|
||||
x264_decompress,
|
||||
x264_compress
|
||||
};
|
||||
|
||||
#undef NAL_UNKNOWN
|
||||
#undef NAL_SLICE
|
||||
#undef NAL_SLICE_DPA
|
||||
#undef NAL_SLICE_DPB
|
||||
#undef NAL_SLICE_DPC
|
||||
#undef NAL_SLICE_IDR
|
||||
#undef NAL_SEI
|
||||
#undef NAL_SPS
|
||||
#undef NAL_PPS
|
||||
#undef NAL_AUD
|
||||
#undef NAL_FILLER
|
||||
|
||||
#undef NAL_PRIORITY_DISPOSABLE
|
||||
#undef NAL_PRIORITY_LOW
|
||||
#undef NAL_PRIORITY_HIGH
|
||||
#undef NAL_PRIORITY_HIGHEST
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* OpenH264 subsystem
|
||||
*/
|
||||
@ -90,7 +823,7 @@ static int openh264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSiz
|
||||
H264_CONTEXT_OPENH264* sys = (H264_CONTEXT_OPENH264*) h264->pSystemData;
|
||||
|
||||
if (!sys->pDecoder)
|
||||
return -1;
|
||||
return -2001;
|
||||
|
||||
/*
|
||||
* Decompress the image. The RDP host only seems to send I420 format.
|
||||
@ -102,22 +835,38 @@ static int openh264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSiz
|
||||
|
||||
ZeroMemory(&sBufferInfo, sizeof(sBufferInfo));
|
||||
|
||||
state = (*sys->pDecoder)->DecodeFrame2(
|
||||
sys->pDecoder,
|
||||
pSrcData,
|
||||
SrcSize,
|
||||
h264->pYUVData,
|
||||
&sBufferInfo);
|
||||
|
||||
/**
|
||||
* Calling DecodeFrame2 twice apparently works around Openh264 issue #1136:
|
||||
* https://github.com/cisco/openh264/issues/1136
|
||||
*
|
||||
* This is a hack, but it works and it is only necessary for the first frame.
|
||||
*/
|
||||
state = (*sys->pDecoder)->DecodeFrame2(sys->pDecoder, pSrcData, SrcSize, h264->pYUVData, &sBufferInfo);
|
||||
|
||||
if (sBufferInfo.iBufferStatus != 1)
|
||||
state = (*sys->pDecoder)->DecodeFrame2(sys->pDecoder, NULL, 0, h264->pYUVData, &sBufferInfo);
|
||||
{
|
||||
if (state == dsNoParamSets)
|
||||
{
|
||||
/* this happens on the first frame due to missing parameter sets */
|
||||
state = (*sys->pDecoder)->DecodeFrame2(sys->pDecoder, NULL, 0, h264->pYUVData, &sBufferInfo);
|
||||
}
|
||||
else if (state == dsErrorFree)
|
||||
{
|
||||
/* call DecodeFrame2 again to decode without delay */
|
||||
state = (*sys->pDecoder)->DecodeFrame2(sys->pDecoder, NULL, 0, h264->pYUVData, &sBufferInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_WARN(TAG, "DecodeFrame2 state: 0x%02X iBufferStatus: %d", state, sBufferInfo.iBufferStatus);
|
||||
return -2002;
|
||||
}
|
||||
}
|
||||
|
||||
if (sBufferInfo.iBufferStatus != 1)
|
||||
{
|
||||
WLog_WARN(TAG, "DecodeFrame2 iBufferStatus: %d", sBufferInfo.iBufferStatus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (state != dsErrorFree)
|
||||
{
|
||||
WLog_WARN(TAG, "DecodeFrame2 state: 0x%02X", state);
|
||||
return -2003;
|
||||
}
|
||||
|
||||
pSystemBuffer = &sBufferInfo.UsrData.sSystemBuffer;
|
||||
|
||||
@ -128,17 +877,11 @@ static int openh264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSiz
|
||||
pSystemBuffer->iStride[0], pSystemBuffer->iStride[1]);
|
||||
#endif
|
||||
|
||||
if (state != 0)
|
||||
return -1;
|
||||
|
||||
if (sBufferInfo.iBufferStatus != 1)
|
||||
return -2;
|
||||
|
||||
if (pSystemBuffer->iFormat != videoFormatI420)
|
||||
return -1;
|
||||
return -2004;
|
||||
|
||||
if (!h264->pYUVData[0] || !h264->pYUVData[1] || !h264->pYUVData[2])
|
||||
return -1;
|
||||
return -2005;
|
||||
|
||||
h264->iStride[0] = pSystemBuffer->iStride[0];
|
||||
h264->iStride[1] = pSystemBuffer->iStride[1];
|
||||
@ -165,8 +908,7 @@ static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstS
|
||||
if (!h264->pYUVData[0] || !h264->pYUVData[1] || !h264->pYUVData[2])
|
||||
return -1;
|
||||
|
||||
if (sys->EncParamExt.iPicWidth != h264->width ||
|
||||
sys->EncParamExt.iPicHeight != h264->height)
|
||||
if ((sys->EncParamExt.iPicWidth != h264->width) || (sys->EncParamExt.iPicHeight != h264->height))
|
||||
{
|
||||
status = (*sys->pEncoder)->GetDefaultParams(sys->pEncoder, &sys->EncParamExt);
|
||||
|
||||
@ -190,6 +932,7 @@ static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstS
|
||||
sys->EncParamExt.sSpatialLayers[0].iVideoWidth = sys->EncParamExt.iPicWidth;
|
||||
sys->EncParamExt.sSpatialLayers[0].iVideoHeight = sys->EncParamExt.iPicHeight;
|
||||
sys->EncParamExt.sSpatialLayers[0].iMaxSpatialBitrate = sys->EncParamExt.iMaxBitrate;
|
||||
|
||||
switch (h264->RateControlMode)
|
||||
{
|
||||
case H264_RATECONTROL_VBR:
|
||||
@ -197,6 +940,7 @@ static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstS
|
||||
sys->EncParamExt.iTargetBitrate = h264->BitRate;
|
||||
sys->EncParamExt.sSpatialLayers[0].iSpatialBitrate = sys->EncParamExt.iTargetBitrate;
|
||||
break;
|
||||
|
||||
case H264_RATECONTROL_CQP:
|
||||
sys->EncParamExt.iRCMode = RC_OFF_MODE;
|
||||
sys->EncParamExt.sSpatialLayers[0].iDLayerQp = h264->QP;
|
||||
@ -259,6 +1003,7 @@ static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstS
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case H264_RATECONTROL_CQP:
|
||||
if (sys->EncParamExt.sSpatialLayers[0].iDLayerQp != h264->QP)
|
||||
{
|
||||
@ -296,8 +1041,10 @@ static int openh264_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstS
|
||||
WLog_ERR(TAG, "Failed to encode frame (status=%ld)", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
*ppDstData = info.sLayerInfo[0].pBsBuf;
|
||||
*pDstSize = 0;
|
||||
|
||||
for (i = 0; i < info.iLayerNum; i++)
|
||||
{
|
||||
for (j = 0; j < info.sLayerInfo[i].iNalCount; j++)
|
||||
@ -375,7 +1122,7 @@ static BOOL openh264_init(H264_CONTEXT* h264)
|
||||
ZeroMemory(&sDecParam, sizeof(sDecParam));
|
||||
sDecParam.eOutputColorFormat = videoFormatI420;
|
||||
sDecParam.eEcActiveIdc = ERROR_CON_FRAME_COPY;
|
||||
sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
|
||||
sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC;
|
||||
|
||||
status = (*sys->pDecoder)->Initialize(sys->pDecoder, &sDecParam);
|
||||
|
||||
@ -618,10 +1365,10 @@ int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
|
||||
int width, height;
|
||||
BYTE* pYUVPoint[3];
|
||||
RDPGFX_RECT16* rect;
|
||||
primitives_t *prims = primitives_get();
|
||||
primitives_t* prims = primitives_get();
|
||||
|
||||
if (!h264)
|
||||
return -1;
|
||||
return -1001;
|
||||
|
||||
#if 0
|
||||
WLog_INFO(TAG, "h264_decompress: pSrcData=%p, SrcSize=%u, pDstData=%p, nDstStep=%d, nDstHeight=%d, numRegionRects=%d",
|
||||
@ -629,9 +1376,14 @@ int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
|
||||
#endif
|
||||
|
||||
if (!(pDstData = *ppDstData))
|
||||
return -1;
|
||||
return -1002;
|
||||
|
||||
if ((status = h264->subsystem->Decompress(h264, pSrcData, SrcSize)) < 0)
|
||||
status = h264->subsystem->Decompress(h264, pSrcData, SrcSize);
|
||||
|
||||
if (status == 0)
|
||||
return 1;
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
pYUVData = h264->pYUVData;
|
||||
@ -641,17 +1393,17 @@ int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
|
||||
{
|
||||
rect = &(regionRects[index]);
|
||||
|
||||
/* Check, if the ouput rectangle is valid in decoded h264 frame. */
|
||||
/* Check, if the output rectangle is valid in decoded h264 frame. */
|
||||
if ((rect->right > h264->width) || (rect->left > h264->width))
|
||||
return -1;
|
||||
return -1003;
|
||||
if ((rect->top > h264->height) || (rect->bottom > h264->height))
|
||||
return -1;
|
||||
return -1004;
|
||||
|
||||
/* Check, if the output rectangle is valid in destination buffer. */
|
||||
if ((rect->right > nDstWidth) || (rect->left > nDstWidth))
|
||||
return -1;
|
||||
return -1005;
|
||||
if ((rect->bottom > nDstHeight) || (rect->top > nDstHeight))
|
||||
return -1;
|
||||
return -1006;
|
||||
|
||||
width = rect->right - rect->left;
|
||||
height = rect->bottom - rect->top;
|
||||
@ -682,7 +1434,7 @@ int h264_compress(H264_CONTEXT* h264, BYTE* pSrcData, DWORD SrcFormat,
|
||||
int status = -1;
|
||||
prim_size_t roi;
|
||||
int nWidth, nHeight;
|
||||
primitives_t *prims = primitives_get();
|
||||
primitives_t* prims = primitives_get();
|
||||
|
||||
if (!h264)
|
||||
return -1;
|
||||
@ -727,6 +1479,14 @@ error_1:
|
||||
|
||||
BOOL h264_context_init(H264_CONTEXT* h264)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (g_Subsystem_MF.Init(h264))
|
||||
{
|
||||
h264->subsystem = &g_Subsystem_MF;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_LIBAVCODEC
|
||||
if (g_Subsystem_libavcodec.Init(h264))
|
||||
{
|
||||
@ -743,6 +1503,14 @@ BOOL h264_context_init(H264_CONTEXT* h264)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_X264
|
||||
if (g_Subsystem_x264.Init(h264))
|
||||
{
|
||||
h264->subsystem = &g_Subsystem_x264;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -3594,10 +3594,23 @@ BOOL rdp_recv_demand_active(rdpRdp* rdp, wStream* s)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pduType == PDU_TYPE_DATA)
|
||||
{
|
||||
/**
|
||||
* We can receive a Save Session Info Data PDU containing a LogonErrorInfo
|
||||
* structure at this point from the server to indicate a connection error.
|
||||
*/
|
||||
|
||||
if (rdp_recv_data_pdu(rdp, s) < 0)
|
||||
return FALSE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pduType != PDU_TYPE_DEMAND_ACTIVE)
|
||||
{
|
||||
if (pduType != PDU_TYPE_SERVER_REDIRECTION)
|
||||
WLog_ERR(TAG, "expected PDU_TYPE_DEMAND_ACTIVE %04x, got %04x", PDU_TYPE_DEMAND_ACTIVE, pduType);
|
||||
WLog_ERR(TAG, "expected PDU_TYPE_DEMAND_ACTIVE %04x, got %04x", PDU_TYPE_DEMAND_ACTIVE, pduType);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -726,7 +726,6 @@ int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, P
|
||||
EntryPoints.pVirtualChannelClose = FreeRDP_VirtualChannelClose;
|
||||
EntryPoints.pVirtualChannelWrite = FreeRDP_VirtualChannelWrite;
|
||||
|
||||
g_pInterface = NULL;
|
||||
EntryPoints.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER;
|
||||
EntryPoints.ppInterface = &g_pInterface;
|
||||
EntryPoints.pExtendedData = data;
|
||||
@ -738,6 +737,7 @@ int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, P
|
||||
|
||||
EnterCriticalSection(&g_channels_lock);
|
||||
|
||||
g_pInterface = NULL;
|
||||
g_ChannelInitData.channels = channels;
|
||||
status = pChannelClientData->entry((PCHANNEL_ENTRY_POINTS) &EntryPoints);
|
||||
|
||||
|
@ -726,7 +726,7 @@ BOOL rdp_recv_logon_error_info(rdpRdp* rdp, wStream* s)
|
||||
UINT32 errorNotificationData;
|
||||
UINT32 errorNotificationType;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 4)
|
||||
if (Stream_GetRemainingLength(s) < 8)
|
||||
return FALSE;
|
||||
|
||||
Stream_Read_UINT32(s, errorNotificationData); /* errorNotificationData (4 bytes) */
|
||||
|
@ -34,7 +34,6 @@
|
||||
|
||||
#define TAG FREERDP_TAG("core.rdp")
|
||||
|
||||
#ifdef WITH_DEBUG_RDP
|
||||
const char* DATA_PDU_TYPE_STRINGS[80] =
|
||||
{
|
||||
"?", "?", /* 0x00 - 0x01 */
|
||||
@ -72,7 +71,6 @@ const char* DATA_PDU_TYPE_STRINGS[80] =
|
||||
"FrameAcknowledge", "?", "?", /* 0x38 - 0x40 */
|
||||
"?", "?", "?", "?", "?", "?" /* 0x41 - 0x46 */
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Read RDP Security Header.\n
|
||||
@ -809,10 +807,8 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
|
||||
Stream_Seek(s, SrcSize);
|
||||
}
|
||||
|
||||
#ifdef WITH_DEBUG_RDP
|
||||
WLog_DBG(TAG, "recv %s Data PDU (0x%02X), length: %d",
|
||||
type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length);
|
||||
#endif
|
||||
|
||||
switch (type)
|
||||
{
|
||||
|
@ -470,6 +470,9 @@ out_free:
|
||||
|
||||
void ArrayList_Free(wArrayList *arrayList)
|
||||
{
|
||||
if (!arrayList)
|
||||
return;
|
||||
|
||||
ArrayList_Clear(arrayList);
|
||||
DeleteCriticalSection(&arrayList->lock);
|
||||
free(arrayList->array);
|
||||
|
@ -348,5 +348,8 @@ wBitStream* BitStream_New()
|
||||
|
||||
void BitStream_Free(wBitStream* bs)
|
||||
{
|
||||
if (!bs)
|
||||
return;
|
||||
|
||||
free(bs);
|
||||
}
|
||||
|
@ -182,6 +182,9 @@ fail_critical_section:
|
||||
|
||||
void CountdownEvent_Free(wCountdownEvent* countdown)
|
||||
{
|
||||
if (!countdown)
|
||||
return;
|
||||
|
||||
DeleteCriticalSection(&countdown->lock);
|
||||
CloseHandle(countdown->event);
|
||||
|
||||
|
@ -128,6 +128,9 @@ wDictionary* Dictionary_New(BOOL synchronized)
|
||||
|
||||
void Dictionary_Free(wDictionary* dictionary)
|
||||
{
|
||||
if (!dictionary)
|
||||
return;
|
||||
|
||||
free(dictionary);
|
||||
}
|
||||
|
||||
|
@ -46,5 +46,8 @@ wKeyValuePair* KeyValuePair_New(void* key, void* value)
|
||||
|
||||
void KeyValuePair_Free(wKeyValuePair* keyValuePair)
|
||||
{
|
||||
if (!keyValuePair)
|
||||
return;
|
||||
|
||||
free(keyValuePair);
|
||||
}
|
||||
|
@ -223,6 +223,9 @@ error_array:
|
||||
|
||||
void MessageQueue_Free(wMessageQueue* queue)
|
||||
{
|
||||
if (!queue)
|
||||
return;
|
||||
|
||||
CloseHandle(queue->event);
|
||||
DeleteCriticalSection(&queue->lock);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user