mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-27 03:44:06 +08:00
Initial implementation of H.264 decoder for MS-RDPEGFX
This commit is contained in:
parent
20d7184777
commit
4d3d78c487
@ -433,6 +433,10 @@ set(JPEG_FEATURE_TYPE "OPTIONAL")
|
||||
set(JPEG_FEATURE_PURPOSE "codec")
|
||||
set(JPEG_FEATURE_DESCRIPTION "use JPEG library")
|
||||
|
||||
set(OPENH264_FEATURE_TYPE "OPTIONAL")
|
||||
set(OPENH264_FEATURE_PURPOSE "codec")
|
||||
set(OPENH264_FEATURE_DESCRIPTION "use OpenH264 library")
|
||||
|
||||
set(GSM_FEATURE_TYPE "OPTIONAL")
|
||||
set(GSM_FEATURE_PURPOSE "codec")
|
||||
set(GSM_FEATURE_DESCRIPTION "GSM audio codec library")
|
||||
@ -504,6 +508,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(OpenH264 ${OPENH264_FEATURE_TYPE} ${OPENH264_FEATURE_PURPOSE} ${OPENH264_FEATURE_DESCRIPTION})
|
||||
find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION})
|
||||
|
||||
if(TARGET_ARCH MATCHES "x86|x64")
|
||||
|
@ -58,14 +58,19 @@ int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
|
||||
|
||||
gfx->ThinClient = TRUE;
|
||||
gfx->SmallCache = FALSE;
|
||||
|
||||
#ifdef WITH_OPENH264
|
||||
gfx->H264 = TRUE;
|
||||
#else
|
||||
gfx->H264 = FALSE;
|
||||
#endif
|
||||
|
||||
gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600;
|
||||
|
||||
header.flags = 0;
|
||||
header.cmdId = RDPGFX_CMDID_CAPSADVERTISE;
|
||||
|
||||
pdu.capsSetCount = 1;
|
||||
pdu.capsSetCount = 2;
|
||||
pdu.capsSets = (RDPGFX_CAPSET*) capsSets;
|
||||
|
||||
capsSet = &capsSets[0];
|
||||
|
@ -51,8 +51,22 @@ int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* re
|
||||
xfc->nsc->height = resetGraphics->height;
|
||||
nsc_context_set_pixel_format(xfc->nsc, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
|
||||
if (xfc->clear)
|
||||
{
|
||||
clear_context_free(xfc->clear);
|
||||
xfc->clear = NULL;
|
||||
}
|
||||
|
||||
xfc->clear = clear_context_new(FALSE);
|
||||
|
||||
if (xfc->h264)
|
||||
{
|
||||
h264_context_free(xfc->h264);
|
||||
xfc->h264 = NULL;
|
||||
}
|
||||
|
||||
xfc->h264 = h264_context_new(FALSE);
|
||||
|
||||
region16_init(&(xfc->invalidRegion));
|
||||
|
||||
xfc->graphicsReset = TRUE;
|
||||
@ -267,10 +281,16 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R
|
||||
|
||||
DstData = surface->data;
|
||||
|
||||
#if 0
|
||||
status = clear_decompress(NULL, cmd->data, cmd->length, &DstData,
|
||||
PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height);
|
||||
#else
|
||||
status = -1;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
printf("xf_SurfaceCommand_ClearCodec: status: %d\n", status);
|
||||
|
||||
#if 1
|
||||
/* fill with pink for now to distinguish from the rest */
|
||||
|
||||
freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
|
||||
@ -320,6 +340,142 @@ int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGF
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xf_SurfaceCommand_H264(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
|
||||
{
|
||||
int status;
|
||||
BYTE* DstData = NULL;
|
||||
xfGfxSurface* surface;
|
||||
RECTANGLE_16 invalidRect;
|
||||
|
||||
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
|
||||
|
||||
if (!surface)
|
||||
return -1;
|
||||
|
||||
DstData = surface->data;
|
||||
|
||||
#if 1
|
||||
status = h264_decompress(xfc->h264, cmd->data, cmd->length, &DstData,
|
||||
PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height);
|
||||
#else
|
||||
status = -1;
|
||||
#endif
|
||||
|
||||
printf("xf_SurfaceCommand_H264: status: %d\n", status);
|
||||
|
||||
#if 0
|
||||
/* fill with red for now to distinguish from the rest */
|
||||
|
||||
freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
|
||||
cmd->left, cmd->top, cmd->width, cmd->height, 0xFF0000);
|
||||
#endif
|
||||
|
||||
invalidRect.left = cmd->left;
|
||||
invalidRect.top = cmd->top;
|
||||
invalidRect.right = cmd->right;
|
||||
invalidRect.bottom = cmd->bottom;
|
||||
|
||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
|
||||
|
||||
if (!xfc->inGfxFrame)
|
||||
xf_OutputUpdate(xfc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xf_SurfaceCommand_Alpha(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
|
||||
{
|
||||
int status = 0;
|
||||
xfGfxSurface* surface;
|
||||
RECTANGLE_16 invalidRect;
|
||||
|
||||
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
|
||||
|
||||
if (!surface)
|
||||
return -1;
|
||||
|
||||
printf("xf_SurfaceCommand_Alpha: status: %d\n", status);
|
||||
|
||||
/* fill with green for now to distinguish from the rest */
|
||||
|
||||
freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
|
||||
cmd->left, cmd->top, cmd->width, cmd->height, 0x00FF00);
|
||||
|
||||
invalidRect.left = cmd->left;
|
||||
invalidRect.top = cmd->top;
|
||||
invalidRect.right = cmd->right;
|
||||
invalidRect.bottom = cmd->bottom;
|
||||
|
||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
|
||||
|
||||
if (!xfc->inGfxFrame)
|
||||
xf_OutputUpdate(xfc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
|
||||
{
|
||||
int status = 0;
|
||||
xfGfxSurface* surface;
|
||||
RECTANGLE_16 invalidRect;
|
||||
|
||||
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
|
||||
|
||||
if (!surface)
|
||||
return -1;
|
||||
|
||||
printf("xf_SurfaceCommand_Progressive: status: %d\n", status);
|
||||
|
||||
/* fill with blue for now to distinguish from the rest */
|
||||
|
||||
freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
|
||||
cmd->left, cmd->top, cmd->width, cmd->height, 0x0000FF);
|
||||
|
||||
invalidRect.left = cmd->left;
|
||||
invalidRect.top = cmd->top;
|
||||
invalidRect.right = cmd->right;
|
||||
invalidRect.bottom = cmd->bottom;
|
||||
|
||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
|
||||
|
||||
if (!xfc->inGfxFrame)
|
||||
xf_OutputUpdate(xfc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xf_SurfaceCommand_ProgressiveV2(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
|
||||
{
|
||||
int status = 0;
|
||||
xfGfxSurface* surface;
|
||||
RECTANGLE_16 invalidRect;
|
||||
|
||||
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
|
||||
|
||||
if (!surface)
|
||||
return -1;
|
||||
|
||||
printf("xf_SurfaceCommand_ProgressiveV2: status: %d\n", status);
|
||||
|
||||
/* fill with white for now to distinguish from the rest */
|
||||
|
||||
freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
|
||||
cmd->left, cmd->top, cmd->width, cmd->height, 0xFFFFFF);
|
||||
|
||||
invalidRect.left = cmd->left;
|
||||
invalidRect.top = cmd->top;
|
||||
invalidRect.right = cmd->right;
|
||||
invalidRect.bottom = cmd->bottom;
|
||||
|
||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
|
||||
|
||||
if (!xfc->inGfxFrame)
|
||||
xf_OutputUpdate(xfc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
|
||||
{
|
||||
int status = 1;
|
||||
@ -344,19 +500,19 @@ int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
|
||||
break;
|
||||
|
||||
case RDPGFX_CODECID_H264:
|
||||
printf("xf_SurfaceCommand_H264\n");
|
||||
status = xf_SurfaceCommand_H264(xfc, context, cmd);
|
||||
break;
|
||||
|
||||
case RDPGFX_CODECID_ALPHA:
|
||||
printf("xf_SurfaceCommand_Alpha\n");
|
||||
status = xf_SurfaceCommand_Alpha(xfc, context, cmd);
|
||||
break;
|
||||
|
||||
case RDPGFX_CODECID_CAPROGRESSIVE:
|
||||
printf("xf_SurfaceCommand_Progressive\n");
|
||||
status = xf_SurfaceCommand_Progressive(xfc, context, cmd);
|
||||
break;
|
||||
|
||||
case RDPGFX_CODECID_CAPROGRESSIVE_V2:
|
||||
printf("xf_SurfaceCommand_ProgressiveV2\n");
|
||||
status = xf_SurfaceCommand_ProgressiveV2(xfc, context, cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ typedef struct xf_context xfContext;
|
||||
#include <freerdp/codec/clear.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
#include <freerdp/codec/h264.h>
|
||||
#include <freerdp/codec/region.h>
|
||||
|
||||
struct xf_WorkArea
|
||||
@ -152,6 +153,7 @@ struct xf_context
|
||||
RFX_CONTEXT* rfx;
|
||||
NSC_CONTEXT* nsc;
|
||||
CLEAR_CONTEXT* clear;
|
||||
H264_CONTEXT* h264;
|
||||
void* xv_context;
|
||||
void* clipboard_context;
|
||||
|
||||
|
31
cmake/FindOpenH264.cmake
Normal file
31
cmake/FindOpenH264.cmake
Normal file
@ -0,0 +1,31 @@
|
||||
# - Try to find the OpenH264 library
|
||||
# Once done this will define
|
||||
#
|
||||
# OPENH264_FOUND - system has OpenH264
|
||||
# OPENH264_INCLUDE_DIR - the OpenH264 include directory
|
||||
# OPENH264_LIBRARIES - libopenh264 library
|
||||
|
||||
if (OPENH264_INCLUDE_DIR AND OPENH264_LIBRARY)
|
||||
set(OPENH264_FIND_QUIETLY TRUE)
|
||||
endif (OPENH264_INCLUDE_DIR AND OPENH264_LIBRARY)
|
||||
|
||||
find_path(OPENH264_INCLUDE_DIR NAMES wels/codec_api.h wels/codec_app_def.h wels/codec_def.h)
|
||||
find_library(OPENH264_LIBRARY openh264)
|
||||
|
||||
if (OPENH264_INCLUDE_DIR AND OPENH264_LIBRARY)
|
||||
set(OPENH264_FOUND TRUE)
|
||||
set(OPENH264_LIBRARIES ${OPENH264_LIBRARY})
|
||||
endif (OPENH264_INCLUDE_DIR AND OPENH264_LIBRARY)
|
||||
|
||||
if (OPENH264_FOUND)
|
||||
if (NOT OPENH264_FIND_QUIETLY)
|
||||
message(STATUS "Found OpenH264: ${OPENH264_LIBRARIES}")
|
||||
endif (NOT OPENH264_FIND_QUIETLY)
|
||||
else (OPENH264_FOUND)
|
||||
if (OPENH264_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "OpenH264 was not found")
|
||||
endif(OPENH264_FIND_REQUIRED)
|
||||
endif (OPENH264_FOUND)
|
||||
|
||||
mark_as_advanced(OPENH264_INCLUDE_DIR OPENH264_LIBRARY)
|
||||
|
60
include/freerdp/codec/h264.h
Normal file
60
include/freerdp/codec/h264.h
Normal file
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* H.264 Bitmap Compression
|
||||
*
|
||||
* Copyright 2014 Mike McDonald <Mike.McDonald@software.dell.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CODEC_H264_H
|
||||
#define FREERDP_CODEC_H264_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
#ifdef WITH_OPENH264
|
||||
#include "wels/codec_def.h"
|
||||
#include "wels/codec_api.h"
|
||||
#endif
|
||||
|
||||
struct _H264_CONTEXT
|
||||
{
|
||||
BOOL Compressor;
|
||||
|
||||
#ifdef WITH_OPENH264
|
||||
ISVCDecoder* pDecoder;
|
||||
#endif
|
||||
};
|
||||
typedef struct _H264_CONTEXT H264_CONTEXT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FREERDP_API int h264_compress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize);
|
||||
|
||||
FREERDP_API int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight);
|
||||
|
||||
FREERDP_API void h264_context_reset(H264_CONTEXT* h264);
|
||||
|
||||
FREERDP_API H264_CONTEXT* h264_context_new(BOOL Compressor);
|
||||
FREERDP_API void h264_context_free(H264_CONTEXT* h264);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_CODEC_H264_H */
|
||||
|
@ -52,7 +52,8 @@ set(${MODULE_PREFIX}_SRCS
|
||||
mppc.c
|
||||
zgfx.c
|
||||
clear.c
|
||||
jpeg.c)
|
||||
jpeg.c
|
||||
h264.c)
|
||||
|
||||
set(${MODULE_PREFIX}_SSE2_SRCS
|
||||
rfx_sse2.c
|
||||
@ -82,8 +83,13 @@ if(WITH_NEON)
|
||||
endif()
|
||||
|
||||
if(WITH_JPEG)
|
||||
include_directories(${JPEG_INCLUDE_DIR})
|
||||
set(FREERDP_JPEG_LIBS ${JPEG_LIBRARIES})
|
||||
include_directories(${JPEG_INCLUDE_DIR})
|
||||
set(FREERDP_JPEG_LIBS ${JPEG_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(WITH_OPENH264)
|
||||
include_directories(${OPENH264_INCLUDE_DIR})
|
||||
set(FREERDP_OPENH264_LIBS ${OPENH264_LIBRARIES})
|
||||
endif()
|
||||
|
||||
add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT"
|
||||
@ -94,7 +100,8 @@ add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT"
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION} PREFIX "lib")
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS
|
||||
${FREERDP_JPEG_LIBS})
|
||||
${FREERDP_JPEG_LIBS}
|
||||
${FREERDP_OPENH264_LIBS})
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL
|
||||
|
281
libfreerdp/codec/h264.c
Normal file
281
libfreerdp/codec/h264.c
Normal file
@ -0,0 +1,281 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* H.264 Bitmap Compression
|
||||
*
|
||||
* Copyright 2014 Mike McDonald <Mike.McDonald@software.dell.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/bitstream.h>
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/h264.h>
|
||||
|
||||
#ifdef WITH_OPENH264
|
||||
|
||||
#define USE_DUMP_IMAGE 0
|
||||
#define USE_GRAY_SCALE 0
|
||||
|
||||
static UINT32 YUV_to_RGB(BYTE Y, BYTE U, BYTE V)
|
||||
{
|
||||
BYTE R, G, B;
|
||||
|
||||
#if USE_GRAY_SCALE
|
||||
/*
|
||||
* Displays the Y plane as a gray-scale image.
|
||||
*/
|
||||
R = Y;
|
||||
G = Y;
|
||||
B = Y;
|
||||
#else
|
||||
/*
|
||||
* Documented colorspace conversion from YUV to RGB.
|
||||
* See http://msdn.microsoft.com/en-us/library/ms893078.aspx
|
||||
*/
|
||||
|
||||
#define clip(x) ((x) & 0xFF)
|
||||
|
||||
int C, D, E;
|
||||
|
||||
C = Y - 16;
|
||||
D = U - 128;
|
||||
E = V - 128;
|
||||
|
||||
R = clip(( 298 * C + 409 * E + 128) >> 8);
|
||||
G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8);
|
||||
B = clip(( 298 * C + 516 * D + 128) >> 8);
|
||||
#endif
|
||||
|
||||
return RGB32(R, G, B);
|
||||
}
|
||||
|
||||
#if USE_DUMP_IMAGE
|
||||
static void h264_dump_i420_image(BYTE* imageData, int imageWidth, int imageHeight, int* imageStride)
|
||||
{
|
||||
static int frame_num;
|
||||
|
||||
FILE* fp;
|
||||
char buffer[64];
|
||||
BYTE* yp;
|
||||
int x, y;
|
||||
|
||||
sprintf(buffer, "/tmp/h264_frame_%d.ppm", frame_num++);
|
||||
fp = fopen(buffer, "wb");
|
||||
fwrite("P5\n", 1, 3, fp);
|
||||
sprintf(buffer, "%d %d\n", imageWidth, imageHeight);
|
||||
fwrite(buffer, 1, strlen(buffer), fp);
|
||||
fwrite("255\n", 1, 4, fp);
|
||||
|
||||
yp = imageData;
|
||||
for (y = 0; y < imageHeight; y++)
|
||||
{
|
||||
fwrite(yp, 1, imageWidth, fp);
|
||||
yp += imageStride[0];
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
#endif
|
||||
|
||||
int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
|
||||
{
|
||||
DECODING_STATE state;
|
||||
SBufferInfo sBufferInfo;
|
||||
SSysMEMBuffer* pSystemBuffer;
|
||||
UINT32 UncompressedSize;
|
||||
BYTE* pDstData;
|
||||
BYTE* pYUVData[3];
|
||||
BYTE* pY;
|
||||
BYTE* pU;
|
||||
BYTE* pV;
|
||||
int Y, U, V;
|
||||
int i, j;
|
||||
|
||||
if (!h264 || !h264->pDecoder)
|
||||
return -1;
|
||||
|
||||
printf("h264_decompress: pSrcData=%p, SrcSize=%u, pDstData=%p, DstFormat=%lx, nDstStep=%d, nXDst=%d, nYDst=%d, nWidth=%d, nHeight=%d)\n",
|
||||
pSrcData, SrcSize, *ppDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight);
|
||||
|
||||
/* Allocate a destination buffer (if needed). */
|
||||
|
||||
UncompressedSize = nWidth * nHeight * 4;
|
||||
|
||||
if (UncompressedSize == 0)
|
||||
return -1;
|
||||
|
||||
pDstData = *ppDstData;
|
||||
|
||||
if (!pDstData)
|
||||
{
|
||||
pDstData = (BYTE*) malloc(UncompressedSize);
|
||||
|
||||
if (!pDstData)
|
||||
return -1;
|
||||
|
||||
*ppDstData = pDstData;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decompress the image. The RDP host only seems to send I420 format.
|
||||
*/
|
||||
|
||||
pYUVData[0] = NULL;
|
||||
pYUVData[1] = NULL;
|
||||
pYUVData[2] = NULL;
|
||||
|
||||
ZeroMemory(&sBufferInfo, sizeof(sBufferInfo));
|
||||
|
||||
state = (*h264->pDecoder)->DecodeFrame2(
|
||||
h264->pDecoder,
|
||||
pSrcData,
|
||||
SrcSize,
|
||||
pYUVData,
|
||||
&sBufferInfo);
|
||||
|
||||
pSystemBuffer = &sBufferInfo.UsrData.sSystemBuffer;
|
||||
|
||||
printf("h264_decompress: state=%u, pYUVData=[%p,%p,%p], bufferStatus=%d, width=%d, height=%d, format=%d, stride=[%d,%d]\n",
|
||||
state, pYUVData[0], pYUVData[1], pYUVData[2], sBufferInfo.iBufferStatus,
|
||||
pSystemBuffer->iWidth, pSystemBuffer->iHeight, pSystemBuffer->iFormat,
|
||||
pSystemBuffer->iStride[0], pSystemBuffer->iStride[1]);
|
||||
|
||||
if (state != 0)
|
||||
return -1;
|
||||
|
||||
if (!pYUVData[0] || !pYUVData[1] || !pYUVData[2])
|
||||
return -1;
|
||||
|
||||
if (sBufferInfo.iBufferStatus != 1)
|
||||
return -1;
|
||||
|
||||
if (pSystemBuffer->iFormat != videoFormatI420)
|
||||
return -1;
|
||||
|
||||
/* Convert I420 (same as IYUV) to XRGB. */
|
||||
|
||||
#if USE_DUMP_IMAGE
|
||||
h264_dump_i420_image(pY, pSystemBuffer->iWidth, pSystemBuffer->iHeight, pSystemBuffer->iStride);
|
||||
#endif
|
||||
|
||||
pY = pYUVData[0];
|
||||
pU = pYUVData[1];
|
||||
pV = pYUVData[2];
|
||||
|
||||
for (j = 0; j < nHeight; j++)
|
||||
{
|
||||
BYTE *pXRGB = pDstData + ((nYDst + j) * nDstStep) + (nXDst * 4);
|
||||
int y = nYDst + j;
|
||||
|
||||
for (i = 0; i < nWidth; i++)
|
||||
{
|
||||
int x = nXDst + i;
|
||||
|
||||
Y = pY[(y * pSystemBuffer->iStride[0]) + x];
|
||||
U = pU[(y/2) * pSystemBuffer->iStride[1] + (x/2)];
|
||||
V = pV[(y/2) * pSystemBuffer->iStride[1] + (x/2)];
|
||||
|
||||
*(UINT32*)pXRGB = YUV_to_RGB(Y, U, V);
|
||||
|
||||
pXRGB += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int h264_compress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void h264_context_reset(H264_CONTEXT* h264)
|
||||
{
|
||||
}
|
||||
|
||||
H264_CONTEXT* h264_context_new(BOOL Compressor)
|
||||
{
|
||||
static EVideoFormatType videoFormat = videoFormatI420;
|
||||
|
||||
H264_CONTEXT* h264;
|
||||
SDecodingParam sDecParam;
|
||||
long status;
|
||||
|
||||
h264 = (H264_CONTEXT*) calloc(1, sizeof(H264_CONTEXT));
|
||||
|
||||
if (h264)
|
||||
{
|
||||
h264->Compressor = Compressor;
|
||||
|
||||
WelsCreateDecoder(&h264->pDecoder);
|
||||
|
||||
if (!h264->pDecoder)
|
||||
{
|
||||
printf("Failed to create OpenH264 decoder\n");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
ZeroMemory(&sDecParam, sizeof(sDecParam));
|
||||
sDecParam.iOutputColorFormat = videoFormatARGB;
|
||||
status = (*h264->pDecoder)->Initialize(h264->pDecoder, &sDecParam);
|
||||
if (status != 0)
|
||||
{
|
||||
printf("Failed to initialize OpenH264 decoder (status=%ld)\n", status);
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
status = (*h264->pDecoder)->SetOption(h264->pDecoder, DECODER_OPTION_DATAFORMAT, &videoFormat);
|
||||
if (status != 0)
|
||||
{
|
||||
printf("Failed to set data format option on OpenH264 decoder (status=%ld)\n", status);
|
||||
}
|
||||
|
||||
h264_context_reset(h264);
|
||||
}
|
||||
|
||||
return h264;
|
||||
|
||||
EXCEPTION:
|
||||
if (h264->pDecoder)
|
||||
{
|
||||
WelsDestroyDecoder(h264->pDecoder);
|
||||
}
|
||||
|
||||
free(h264);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void h264_context_free(H264_CONTEXT* h264)
|
||||
{
|
||||
if (h264)
|
||||
{
|
||||
if (h264->pDecoder)
|
||||
{
|
||||
(*h264->pDecoder)->Uninitialize(h264->pDecoder);
|
||||
WelsDestroyDecoder(h264->pDecoder);
|
||||
}
|
||||
|
||||
free(h264);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user