mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-25 14:57:20 +00:00
[client] added initial decoder framework
This commit is contained in:
parent
c239306d82
commit
076a45acc5
@ -1,12 +1,12 @@
|
||||
BINARY = looking-glass-client
|
||||
CFLAGS = -g -O3 -std=gnu99 -march=native -Wall -Werror -I./ -I../common -DDEBUG -DATOMIC_LOCKING
|
||||
CFLAGS = -g -Og -std=gnu99 -march=native -Wall -Werror -I./ -I../common -DDEBUG -DATOMIC_LOCKING
|
||||
LDFLAGS = -lrt
|
||||
|
||||
CFLAGS += -ffast-math
|
||||
CFLAGS += -fdata-sections -ffunction-sections
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
|
||||
LIBS = sdl2 SDL2_ttf gl glu libssl openssl spice-protocol fontconfig x11 libconfig
|
||||
LIBS = sdl2 SDL2_ttf gl glu libssl openssl spice-protocol fontconfig x11 libconfig libva
|
||||
CFLAGS += $(shell pkg-config --cflags $(LIBS))
|
||||
LDFLAGS += $(shell pkg-config --libs $(LIBS))
|
||||
BUILD ?= .build
|
||||
@ -17,6 +17,8 @@ CFLAGS += -DBUILD_VERSION='"$(shell git describe --always --long --dirty --abbr
|
||||
OBJS = main.o \
|
||||
lg-renderer.o \
|
||||
spice/spice.o \
|
||||
decoders/null.o \
|
||||
decoders/h264.o \
|
||||
renderers/opengl.o
|
||||
# renderers/opengl-basic.o
|
||||
|
||||
|
110
client/decoders/h264.c
Normal file
110
client/decoders/h264.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||
Copyright (C) 2017 Geoffrey McRae <geoff@hostfission.com>
|
||||
https://looking-glass.hostfission.com
|
||||
|
||||
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 of the License, 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; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lg-decoder.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct Inst
|
||||
{
|
||||
bool initialized;
|
||||
|
||||
LG_RendererFormat format;
|
||||
};
|
||||
|
||||
static bool lgd_h264_create (void ** opaque);
|
||||
static void lgd_h264_destroy (void * opaque);
|
||||
static bool lgd_h264_initialize (void * opaque, const LG_RendererFormat format);
|
||||
static void lgd_h264_deinitialize (void * opaque);
|
||||
static LG_OutFormat lgd_h264_get_out_format (void * opaque);
|
||||
static unsigned int lgd_h264_get_frame_pitch(void * opaque);
|
||||
static bool lgd_h264_decode(void * opaque, uint8_t * dst, size_t dstSize, const uint8_t * src, size_t srcSize);
|
||||
|
||||
static bool lgd_h264_create(void ** opaque)
|
||||
{
|
||||
// create our local storage
|
||||
*opaque = malloc(sizeof(struct Inst));
|
||||
if (!*opaque)
|
||||
{
|
||||
DEBUG_INFO("Failed to allocate %lu bytes", sizeof(struct Inst));
|
||||
return false;
|
||||
}
|
||||
memset(*opaque, 0, sizeof(struct Inst));
|
||||
|
||||
//struct Inst * this = (struct Inst *)*opaque;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void lgd_h264_destroy(void * opaque)
|
||||
{
|
||||
struct Inst * this = (struct Inst *)opaque;
|
||||
lgd_h264_deinitialize(opaque);
|
||||
free(this);
|
||||
}
|
||||
|
||||
static bool lgd_h264_initialize(void * opaque, const LG_RendererFormat format)
|
||||
{
|
||||
struct Inst * this = (struct Inst *)opaque;
|
||||
if (this->initialized)
|
||||
lgd_h264_deinitialize(opaque);
|
||||
|
||||
memcpy(&this->format, &format, sizeof(LG_RendererFormat));
|
||||
return true;
|
||||
}
|
||||
|
||||
static void lgd_h264_deinitialize(void * opaque)
|
||||
{
|
||||
struct Inst * this = (struct Inst *)opaque;
|
||||
if (!this->initialized)
|
||||
return;
|
||||
|
||||
memset(this, 0, sizeof(struct Inst));
|
||||
}
|
||||
|
||||
static LG_OutFormat lgd_h264_get_out_format(void * opaque)
|
||||
{
|
||||
return LG_OUTPUT_BGRA;
|
||||
}
|
||||
|
||||
static unsigned int lgd_h264_get_frame_pitch(void * opaque)
|
||||
{
|
||||
struct Inst * this = (struct Inst *)opaque;
|
||||
return this->format.width * 4;
|
||||
}
|
||||
|
||||
static bool lgd_h264_decode(void * opaque, uint8_t * dst, size_t dstSize, const uint8_t * src, size_t srcSize)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const LG_Decoder LGD_H264 =
|
||||
{
|
||||
.name = "H.264",
|
||||
.create = lgd_h264_create,
|
||||
.destroy = lgd_h264_destroy,
|
||||
.initialize = lgd_h264_initialize,
|
||||
.deinitialize = lgd_h264_deinitialize,
|
||||
.get_out_format = lgd_h264_get_out_format,
|
||||
.get_frame_pitch = lgd_h264_get_frame_pitch,
|
||||
.decode = lgd_h264_decode
|
||||
};
|
97
client/decoders/null.c
Normal file
97
client/decoders/null.c
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||
Copyright (C) 2017 Geoffrey McRae <geoff@hostfission.com>
|
||||
https://looking-glass.hostfission.com
|
||||
|
||||
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 of the License, 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; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lg-decoder.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "memcpySSE.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct Inst
|
||||
{
|
||||
LG_RendererFormat format;
|
||||
};
|
||||
|
||||
static bool lgd_null_create (void ** opaque);
|
||||
static void lgd_null_destroy (void * opaque);
|
||||
static bool lgd_null_initialize (void * opaque, const LG_RendererFormat format);
|
||||
static void lgd_null_deinitialize (void * opaque);
|
||||
static LG_OutFormat lgd_null_get_out_format (void * opaque);
|
||||
static unsigned int lgd_null_get_frame_pitch(void * opaque);
|
||||
static bool lgd_null_decode (void * opaque, uint8_t * dst, size_t dstSize, const uint8_t * src, size_t srcSize);
|
||||
|
||||
static bool lgd_null_create(void ** opaque)
|
||||
{
|
||||
// create our local storage
|
||||
*opaque = malloc(sizeof(struct Inst));
|
||||
if (!*opaque)
|
||||
{
|
||||
DEBUG_INFO("Failed to allocate %lu bytes", sizeof(struct Inst));
|
||||
return false;
|
||||
}
|
||||
memset(*opaque, 0, sizeof(struct Inst));
|
||||
return true;
|
||||
}
|
||||
|
||||
static void lgd_null_destroy(void * opaque)
|
||||
{
|
||||
free(opaque);
|
||||
}
|
||||
|
||||
static bool lgd_null_initialize(void * opaque, const LG_RendererFormat format)
|
||||
{
|
||||
struct Inst * this = (struct Inst *)opaque;
|
||||
memcpy(&this->format, &format, sizeof(LG_RendererFormat));
|
||||
return true;
|
||||
}
|
||||
|
||||
static void lgd_null_deinitialize(void * opaque)
|
||||
{
|
||||
}
|
||||
|
||||
static LG_OutFormat lgd_null_get_out_format(void * opaque)
|
||||
{
|
||||
return LG_OUTPUT_BGRA;
|
||||
}
|
||||
|
||||
static unsigned int lgd_null_get_frame_pitch(void * opaque)
|
||||
{
|
||||
struct Inst * this = (struct Inst *)opaque;
|
||||
return this->format.pitch;
|
||||
}
|
||||
|
||||
static bool lgd_null_decode(void * opaque, uint8_t * dst, size_t dstSize, const uint8_t * src, size_t srcSize)
|
||||
{
|
||||
memcpySSE(dst, src, dstSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
const LG_Decoder LGD_NULL =
|
||||
{
|
||||
.name = "NULL",
|
||||
.create = lgd_null_create,
|
||||
.destroy = lgd_null_destroy,
|
||||
.initialize = lgd_null_initialize,
|
||||
.deinitialize = lgd_null_deinitialize,
|
||||
.get_out_format = lgd_null_get_out_format,
|
||||
.get_frame_pitch = lgd_null_get_frame_pitch,
|
||||
.decode = lgd_null_decode
|
||||
};
|
52
client/lg-decoder.h
Normal file
52
client/lg-decoder.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||
Copyright (C) 2017 Geoffrey McRae <geoff@hostfission.com>
|
||||
https://looking-glass.hostfission.com
|
||||
|
||||
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 of the License, 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; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "lg-renderer.h"
|
||||
|
||||
typedef enum LG_OutFormat
|
||||
{
|
||||
LG_OUTPUT_BGRA
|
||||
}
|
||||
LG_OutFormat;
|
||||
|
||||
typedef bool (* LG_DecoderCreate )(void ** opaque);
|
||||
typedef void (* LG_DecoderDestroy )(void * opaque);
|
||||
typedef bool (* LG_DecoderInitialize )(void * opaque, const LG_RendererFormat format);
|
||||
typedef void (* LG_DecoderDeInitialize )(void * opaque);
|
||||
typedef LG_OutFormat (* LG_DecoderGetOutFormat )(void * opaque);
|
||||
typedef unsigned int (* LG_DecoderGetFramePitch)(void * opaque);
|
||||
typedef bool (* LG_DecoderDecode )(void * opaque, uint8_t * dst, size_t dstSize, const uint8_t * src, size_t srcSize);
|
||||
|
||||
typedef struct LG_Decoder
|
||||
{
|
||||
const char * name;
|
||||
LG_DecoderCreate create;
|
||||
LG_DecoderDestroy destroy;
|
||||
LG_DecoderInitialize initialize;
|
||||
LG_DecoderDeInitialize deinitialize;
|
||||
LG_DecoderGetOutFormat get_out_format;
|
||||
LG_DecoderGetFramePitch get_frame_pitch;
|
||||
LG_DecoderDecode decode;
|
||||
}
|
||||
LG_Decoder;
|
33
client/lg-decoders.h
Normal file
33
client/lg-decoders.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||
Copyright (C) 2017 Geoffrey McRae <geoff@hostfission.com>
|
||||
https://looking-glass.hostfission.com
|
||||
|
||||
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 of the License, 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; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "lg-decoder.h"
|
||||
|
||||
extern const LG_Decoder LGD_H264;
|
||||
extern const LG_Decoder LGD_NULL;
|
||||
|
||||
const LG_Decoder * LG_Decoders[] =
|
||||
{
|
||||
&LGD_NULL,
|
||||
&LGD_H264,
|
||||
NULL // end of array sentinal
|
||||
};
|
||||
|
||||
#define LG_DECODER_COUNT ((sizeof(LG_Decoders) / sizeof(LG_Decoder *)) - 1)
|
@ -325,14 +325,17 @@ int frameThread(void * unused)
|
||||
lgrFormat.stride = header.detail.frame.stride;
|
||||
lgrFormat.pitch = header.detail.frame.pitch;
|
||||
|
||||
size_t dataSize;
|
||||
switch(header.detail.frame.type)
|
||||
{
|
||||
case FRAME_TYPE_ARGB:
|
||||
dataSize = lgrFormat.height * lgrFormat.pitch;
|
||||
lgrFormat.comp = LG_COMPRESSION_NONE;
|
||||
lgrFormat.bpp = 32;
|
||||
break;
|
||||
|
||||
case FRAME_TYPE_H264:
|
||||
dataSize = lgrFormat.pitch;
|
||||
lgrFormat.comp = LG_COMPRESSION_H264;
|
||||
lgrFormat.bpp = 0;
|
||||
break;
|
||||
@ -347,7 +350,6 @@ int frameThread(void * unused)
|
||||
break;
|
||||
|
||||
// check the header's dataPos is sane
|
||||
const size_t dataSize = lgrFormat.height * lgrFormat.pitch;
|
||||
if (header.detail.frame.dataPos + dataSize > state.shmSize)
|
||||
{
|
||||
DEBUG_ERROR("The guest sent an invalid dataPos");
|
||||
|
@ -32,6 +32,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "debug.h"
|
||||
#include "memcpySSE.h"
|
||||
#include "utils.h"
|
||||
#include "lg-decoders.h"
|
||||
|
||||
#define BUFFER_COUNT 2
|
||||
|
||||
@ -76,6 +77,8 @@ struct Inst
|
||||
GLuint intFormat;
|
||||
GLuint vboFormat;
|
||||
size_t texSize;
|
||||
const LG_Decoder* decoder;
|
||||
void * decoderData;
|
||||
|
||||
uint64_t drawStart;
|
||||
bool hasBuffers;
|
||||
@ -282,7 +285,18 @@ bool opengl_on_frame_event(void * opaque, const LG_RendererFormat format, const
|
||||
|
||||
// lock, perform the update, then unlock
|
||||
LG_LOCK(this->syncLock);
|
||||
memcpySSE(this->texPixels[this->wTexIndex], data, this->texSize);
|
||||
if (!this->decoder->decode(
|
||||
this->decoderData,
|
||||
this->texPixels[this->wTexIndex],
|
||||
this->texSize,
|
||||
data,
|
||||
this->format.pitch
|
||||
))
|
||||
{
|
||||
DEBUG_ERROR("decode returned failure");
|
||||
LG_UNLOCK(this->syncLock);
|
||||
return false;
|
||||
}
|
||||
this->frameUpdate = true;
|
||||
LG_UNLOCK(this->syncLock);
|
||||
|
||||
@ -552,30 +566,52 @@ static bool configure(struct Inst * this, SDL_Window *window)
|
||||
switch(this->format.comp)
|
||||
{
|
||||
case LG_COMPRESSION_NONE:
|
||||
this->decoder = &LGD_NULL;
|
||||
break;
|
||||
|
||||
case LG_COMPRESSION_H264:
|
||||
DEBUG_INFO("h264 not supported yet");
|
||||
LG_UNLOCK(this->formatLock);
|
||||
this->decoder = &LGD_H264;
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_ERROR("Unknown/unsupported compression type");
|
||||
return false;
|
||||
}
|
||||
|
||||
// assume 32 bit formats are BGRA
|
||||
switch(this->format.bpp)
|
||||
DEBUG_INFO("Using decoder: %s", this->decoder->name);
|
||||
|
||||
if (!this->decoder->create(&this->decoderData))
|
||||
{
|
||||
case 32:
|
||||
DEBUG_ERROR("Failed to create the decoder");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this->decoder->initialize(
|
||||
this->decoderData,
|
||||
this->format
|
||||
))
|
||||
{
|
||||
DEBUG_ERROR("Failed to initialize decoder");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch(this->decoder->get_out_format(this->decoderData))
|
||||
{
|
||||
case LG_OUTPUT_BGRA:
|
||||
this->intFormat = GL_RGBA8;
|
||||
this->vboFormat = GL_BGRA;
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_INFO("%d bpp not supported", this->format.bpp);
|
||||
DEBUG_ERROR("Format not supported");
|
||||
LG_UNLOCK(this->formatLock);
|
||||
return false;
|
||||
}
|
||||
|
||||
// calculate the texture size in bytes
|
||||
this->texSize = this->format.height * this->format.pitch;
|
||||
this->texSize =
|
||||
this->format.height *
|
||||
this->decoder->get_frame_pitch(this->decoderData);
|
||||
|
||||
// generate lists for drawing
|
||||
this->texList = glGenLists(BUFFER_COUNT);
|
||||
@ -729,6 +765,12 @@ static void deconfigure(struct Inst * this)
|
||||
this->glContext = NULL;
|
||||
}
|
||||
|
||||
if (this->decoder)
|
||||
{
|
||||
this->decoder->destroy(this->decoderData);
|
||||
this->decoderData = NULL;
|
||||
}
|
||||
|
||||
this->configured = false;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user