diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 16a13265..7621c6c7 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -107,7 +107,6 @@ add_subdirectory("${PROJECT_TOP}/repos/PureSpice" "${CMAKE_BINARY_DIR}/PureSpice add_subdirectory(renderers) add_subdirectory(clipboards) add_subdirectory(fonts) -add_subdirectory(decoders) add_executable(looking-glass-client ${SOURCES}) target_compile_options(looking-glass-client PUBLIC ${PKGCONFIG_CFLAGS_OTHER} ${PKGCONFIG_OPT_CFLAGS_OTHER}) diff --git a/client/decoders/CMakeLists.txt b/client/decoders/CMakeLists.txt deleted file mode 100644 index 0bd722f6..00000000 --- a/client/decoders/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -cmake_minimum_required(VERSION 3.0) -project(decoders LANGUAGES C) - -#find_package(PkgConfig) -#pkg_check_modules(DECODERS_PKGCONFIG REQUIRED -#) - -add_library(decoders STATIC - src/null.c - src/yuv420.c -) - -target_link_libraries(decoders - lg_common - ${DECODERS_PKGCONFIG_LIBRARIES} -) - -target_include_directories(decoders - PUBLIC - $ - $ - PRIVATE - src - ${DECODERS_PKGCONFIG_INCLUDE_DIRS} -) diff --git a/client/decoders/src/h264.c b/client/decoders/src/h264.c deleted file mode 100644 index c3abbbf2..00000000 --- a/client/decoders/src/h264.c +++ /dev/null @@ -1,981 +0,0 @@ -/* -Looking Glass - KVM FrameRelay (KVMFR) Client -Copyright (C) 2017-2019 Geoffrey McRae -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 "parsers/nal.h" - -#include -#include -#include -#include -#include - -#define SURFACE_NUM 3 - -struct Inst -{ - LG_RendererFormat format; - SDL_Window * window; - VADisplay vaDisplay; - int vaMajorVer, vaMinorVer; - VASurfaceID vaSurfaceID[SURFACE_NUM]; - VAConfigID vaConfigID; - VAContextID vaContextID; - int lastSID; - int currentSID; - VAPictureH264 curPic; - VAPictureH264 oldPic; - int frameNum; - int fieldCount; - VABufferID picBufferID[SURFACE_NUM]; - VABufferID matBufferID[SURFACE_NUM]; - VABufferID sliBufferID[SURFACE_NUM]; - VABufferID datBufferID[SURFACE_NUM]; - bool t2First; - int sliceType; - - NAL nal; -}; - -static const unsigned char MatrixBufferH264[] = { - //ScalingList4x4[6][16] - 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, - 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, - 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, - 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, - 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, - 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, - //ScalingList8x8[2][64] - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -}; - -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, SDL_Window * window); -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 unsigned int lgd_h264_get_frame_stride(void * opaque); -static bool lgd_h264_decode (void * opaque, const uint8_t * src, size_t srcSize); -static bool lgd_h264_get_buffer (void * opaque, uint8_t * dst, size_t dstSize); - -static bool lgd_h264_init_gl_texture (void * opaque, GLenum target, GLuint texture, void ** ref); -static void lgd_h264_free_gl_texture (void * opaque, void * ref); -static bool lgd_h264_update_gl_texture(void * opaque, void * ref); - -#define check_surface(x, y, z) _check_surface(__LINE__, x, y, z) -static bool _check_surface(const unsigned int line, struct Inst * this, unsigned int sid, VASurfaceStatus *out) -{ - VASurfaceStatus surfStatus; - VAStatus status = vaQuerySurfaceStatus( - this->vaDisplay, - this->vaSurfaceID[sid], - &surfStatus - ); - - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaQuerySurfaceStatus: %s", vaErrorStr(status)); - return false; - } - -#if 0 - DEBUG_INFO("L%d: surface %u status: %d", line, sid, surfStatus); -#endif - if (out) - *out = surfStatus; - return true; -} - -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; - - this->vaSurfaceID[0] = VA_INVALID_ID; - this->vaConfigID = VA_INVALID_ID; - this->vaContextID = VA_INVALID_ID; - for(int i = 0; i < SURFACE_NUM; ++i) - this->picBufferID[i] = - this->matBufferID[i] = - this->sliBufferID[i] = - this->datBufferID[i] = VA_INVALID_ID; - - if (!nal_initialize(&this->nal)) - { - DEBUG_INFO("Failed to initialize NAL parser"); - free(this); - return false; - } - - lgd_h264_deinitialize(this); - return true; -} - -static void lgd_h264_destroy(void * opaque) -{ - struct Inst * this = (struct Inst *)opaque; - nal_deinitialize(this->nal); - lgd_h264_deinitialize(this); - free(this); -} - -static bool lgd_h264_initialize(void * opaque, const LG_RendererFormat format, SDL_Window * window) -{ - struct Inst * this = (struct Inst *)opaque; - lgd_h264_deinitialize(this); - - memcpy(&this->format, &format, sizeof(LG_RendererFormat)); - this->window = window; - - SDL_SysWMinfo wminfo; - SDL_VERSION(&wminfo.version); - if (!SDL_GetWindowWMInfo(window, &wminfo)) - { - DEBUG_ERROR("Failed to get SDL window WM Info"); - return false; - } - - switch(wminfo.subsystem) - { - case SDL_SYSWM_X11: - this->vaDisplay = vaGetDisplayGLX(wminfo.info.x11.display); - break; - - default: - DEBUG_ERROR("Unsupported window subsystem"); - return false; - } - - VAStatus status; - status = vaInitialize(this->vaDisplay, &this->vaMajorVer, &this->vaMinorVer); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaInitialize Failed"); - return false; - } - - DEBUG_INFO("Vendor: %s", vaQueryVendorString(this->vaDisplay)); - - VAEntrypoint entryPoints[5]; - int entryPointCount; - - status = vaQueryConfigEntrypoints( - this->vaDisplay, - VAProfileH264High, - entryPoints, - &entryPointCount - ); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaQueryConfigEntrypoints Failed"); - return false; - } - - int ep; - for(ep = 0; ep < entryPointCount; ++ep) - if (entryPoints[ep] == VAEntrypointVLD) - break; - - if (ep == entryPointCount) - { - DEBUG_ERROR("Failed to find VAEntrypointVLD index"); - return false; - } - - VAConfigAttrib attrib; - attrib.type = VAConfigAttribRTFormat; - vaGetConfigAttributes( - this->vaDisplay, - VAProfileH264High, - VAEntrypointVLD, - &attrib, - 1); - - if (!(attrib.value & VA_RT_FORMAT_YUV420)) - { - DEBUG_ERROR("Failed to find desired YUV420 RT format"); - return false; - } - - status = vaCreateConfig( - this->vaDisplay, - VAProfileH264High, - VAEntrypointVLD, - &attrib, - 1, - &this->vaConfigID); - - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaCreateConfig"); - return false; - } - - status = vaCreateSurfaces( - this->vaDisplay, - VA_RT_FORMAT_YUV420, - this->format.width, - this->format.height, - this->vaSurfaceID, - SURFACE_NUM, - NULL, - 0 - ); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaCreateSurfaces"); - return false; - } - - for(int i = 0; i < SURFACE_NUM; ++i) - if (!check_surface(this, i, NULL)) - return false; - - status = vaCreateContext( - this->vaDisplay, - this->vaConfigID, - this->format.width, - this->format.height, - VA_PROGRESSIVE, - this->vaSurfaceID, - SURFACE_NUM, - &this->vaContextID - ); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaCreateContext"); - return false; - } - - this->currentSID = 0; - this->sliceType = 2; - this->t2First = true; - - status = vaBeginPicture(this->vaDisplay, this->vaContextID, this->vaSurfaceID[0]); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaBeginPicture"); - return false; - } - - return true; -} - -static void lgd_h264_deinitialize(void * opaque) -{ - struct Inst * this = (struct Inst *)opaque; - - for(int i = 0; i < SURFACE_NUM; ++i) - { - if (this->picBufferID[i] != VA_INVALID_ID) - vaDestroyBuffer(this->vaDisplay, this->picBufferID[i]); - - if (this->matBufferID[i] != VA_INVALID_ID) - vaDestroyBuffer(this->vaDisplay, this->matBufferID[i]); - - if (this->sliBufferID[i] != VA_INVALID_ID) - vaDestroyBuffer(this->vaDisplay, this->sliBufferID[i]); - - if (this->datBufferID[i] != VA_INVALID_ID) - vaDestroyBuffer(this->vaDisplay, this->datBufferID[i]); - - this->picBufferID[i] = - this->matBufferID[i] = - this->sliBufferID[i] = - this->datBufferID[i] = VA_INVALID_ID; - } - - if (this->vaSurfaceID[0] != VA_INVALID_ID) - vaDestroySurfaces(this->vaDisplay, this->vaSurfaceID, SURFACE_NUM); - this->vaSurfaceID[0] = VA_INVALID_ID; - - if (this->vaContextID != VA_INVALID_ID) - vaDestroyContext(this->vaDisplay, this->vaContextID); - this->vaContextID = VA_INVALID_ID; - - if (this->vaConfigID != VA_INVALID_ID) - vaDestroyConfig(this->vaDisplay, this->vaConfigID); - this->vaConfigID = VA_INVALID_ID; - - if (this->vaDisplay) - vaTerminate(this->vaDisplay); - this->vaDisplay = NULL; -} - -static LG_OutFormat lgd_h264_get_out_format(void * opaque) -{ - return LG_OUTPUT_YUV420; -} - -static unsigned int lgd_h264_get_frame_pitch(void * opaque) -{ - struct Inst * this = (struct Inst *)opaque; - return this->format.width * 4; -} - -static unsigned int lgd_h264_get_frame_stride(void * opaque) -{ - struct Inst * this = (struct Inst *)opaque; - return this->format.width; -} - -static bool get_buffer(struct Inst * this, const VABufferType type, const unsigned int size, VABufferID * buf_id) -{ - if (*buf_id != VA_INVALID_ID) - return true; - - VAStatus status = vaCreateBuffer(this->vaDisplay, this->vaContextID, type, size, 1, NULL, buf_id); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("Failed to create buffer: %s", vaErrorStr(status)); - return false; - } - - if (!check_surface(this, this->currentSID, NULL)) - return false; - - return true; -} - -static bool setup_pic_buffer(struct Inst * this, const NAL_SLICE * slice) -{ - VAStatus status; - - VABufferID * picBufferID = &this->picBufferID[this->currentSID]; - if (!get_buffer(this, VAPictureParameterBufferType, sizeof(VAPictureParameterBufferH264), picBufferID)) - { - DEBUG_ERROR("get picBuffer failed"); - return false; - } - - VAPictureParameterBufferH264 *p; - status = vaMapBuffer(this->vaDisplay, *picBufferID, (void **)&p); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaMapBuffer: %s", vaErrorStr(status)); - return false; - } - - const NAL_SPS * sps; - if (!nal_get_sps(this->nal, &sps)) - { - DEBUG_ERROR("nal_get_sps"); - return false; - } - - const NAL_PPS * pps; - if (!nal_get_pps(this->nal, &pps)) - { - DEBUG_ERROR("nal_get_pps"); - return false; - } - - memset(p, 0, sizeof(VAPictureParameterBufferH264)); - p->picture_width_in_mbs_minus1 = sps->pic_width_in_mbs_minus1; - p->picture_height_in_mbs_minus1 = sps->pic_height_in_map_units_minus1; - p->bit_depth_luma_minus8 = sps->bit_depth_luma_minus8; - p->bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8; - p->num_ref_frames = sps->num_ref_frames; - - p->seq_fields.value = 0; - p->seq_fields.bits.chroma_format_idc = sps->chroma_format_idc; - p->seq_fields.bits.residual_colour_transform_flag = sps->gaps_in_frame_num_value_allowed_flag; - p->seq_fields.bits.frame_mbs_only_flag = sps->frame_mbs_only_flag; - p->seq_fields.bits.mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag; - p->seq_fields.bits.direct_8x8_inference_flag = sps->direct_8x8_inference_flag; - p->seq_fields.bits.MinLumaBiPredSize8x8 = sps->level_idc >= 31; - p->seq_fields.bits.log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4; - p->seq_fields.bits.pic_order_cnt_type = sps->pic_order_cnt_type; - p->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4; - p->seq_fields.bits.delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag; - -#if 0 - // these are deprecated, FMO is not supported - p->num_slice_groups_minus1 = pps->num_slice_groups_minus1; - p->slice_group_map_type = pps->slice_group_map_type; - p->slice_group_change_rate_minus1 = pps->slice_group_change_rate_minus1; -#endif - - p->pic_init_qp_minus26 = pps->pic_init_qp_minus26; - p->pic_init_qs_minus26 = pps->pic_init_qs_minus26; - p->chroma_qp_index_offset = pps->chroma_qp_index_offset; - p->second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset; - - p->pic_fields.value = 0; - p->pic_fields.bits.entropy_coding_mode_flag = pps->entropy_coding_mode_flag; - p->pic_fields.bits.weighted_pred_flag = pps->weighted_pred_flag; - p->pic_fields.bits.weighted_bipred_idc = pps->weighted_bipred_idc; - p->pic_fields.bits.transform_8x8_mode_flag = pps->transform_8x8_mode_flag; - p->pic_fields.bits.field_pic_flag = slice->field_pic_flag; - p->pic_fields.bits.constrained_intra_pred_flag = pps->constrained_intra_pred_flag; - p->pic_fields.bits.pic_order_present_flag = pps->pic_order_present_flag; - p->pic_fields.bits.deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; - p->pic_fields.bits.redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; - p->pic_fields.bits.reference_pic_flag = slice->nal_ref_idc != 0; - - p->frame_num = slice->frame_num; - - for(int i = 0; i < 16; ++i) - { - p->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID; - p->ReferenceFrames[i].picture_id = 0xFFFFFFFF; - } - - this->curPic.picture_id = this->vaSurfaceID[this->currentSID]; - this->curPic.frame_idx = p->frame_num; - this->curPic.flags = 0; - this->curPic.BottomFieldOrderCnt = this->fieldCount; - this->curPic.TopFieldOrderCnt = this->fieldCount; - memcpy(&p->CurrPic, &this->curPic, sizeof(VAPictureH264)); - - if (this->sliceType != 2) - { - memcpy(&p->ReferenceFrames[0], &this->oldPic, sizeof(VAPictureH264)); - p->ReferenceFrames[0].flags = 0; - } - - status = vaUnmapBuffer(this->vaDisplay, *picBufferID); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaUnmapBuffer: %s", vaErrorStr(status)); - return false; - } - - return true; -} - -static bool setup_mat_buffer(struct Inst * this) -{ - VAStatus status; - - VABufferID * matBufferID = &this->matBufferID[this->currentSID]; - if (!get_buffer(this, VAIQMatrixBufferType, sizeof(VAIQMatrixBufferH264), matBufferID)) - { - DEBUG_ERROR("get matBuffer failed"); - return false; - } - - VAIQMatrixBufferH264 * m; - status = vaMapBuffer(this->vaDisplay, *matBufferID, (void **)&m); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaMapBuffer: %s", vaErrorStr(status)); - return false; - } - - memcpy(m, MatrixBufferH264, sizeof(MatrixBufferH264)); - - status = vaUnmapBuffer(this->vaDisplay, *matBufferID); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaUnmapBuffer: %s", vaErrorStr(status)); - return false; - } - - return true; -} - -static void fill_pred_weight_table( - NAL_PW_TABLE_L * list, - uint32_t active, - uint32_t luma_log2_weight_denom, - uint8_t luma_weight_flag, - short luma_weight[32], - short luma_offset[32], - uint32_t chroma_log2_weight_denom, - uint8_t chroma_weight_flag, - short chroma_weight[32][2], - short chroma_offset[32][2] -) -{ - assert(active < 32); - - for(uint32_t i = 0; i <= active; ++i) - { - NAL_PW_TABLE_L * l = &list[i]; - if (luma_weight_flag) - { - luma_weight[i] = l->luma_weight; - luma_offset[i] = l->luma_offset; - } - else - { - luma_weight[i] = 1 << luma_log2_weight_denom; - luma_weight[i] = 0; - } - - if (chroma_weight_flag) - { - chroma_weight[i][0] = l->chroma_weight[0]; - chroma_offset[i][0] = l->chroma_offset[0]; - chroma_weight[i][1] = l->chroma_weight[1]; - chroma_offset[i][1] = l->chroma_offset[1]; - } - else - { - chroma_weight[i][0] = 1 << chroma_log2_weight_denom; - chroma_weight[i][0] = 0; - chroma_weight[i][1] = 1 << chroma_log2_weight_denom; - chroma_weight[i][1] = 0; - } - } -} - -static bool setup_sli_buffer(struct Inst * this, size_t srcSize, const NAL_SLICE * slice, const size_t seek) -{ - VAStatus status; - - VABufferID * sliBufferID = &this->sliBufferID[this->currentSID]; - if (!get_buffer(this, VASliceParameterBufferType, sizeof(VASliceParameterBufferH264), sliBufferID)) - { - DEBUG_ERROR("get sliBuffer failed"); - return false; - } - - VASliceParameterBufferH264 * s; - status = vaMapBuffer(this->vaDisplay, *sliBufferID, (void **)&s); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaMapBuffer: %s", vaErrorStr(status)); - return false; - } - - memset(s, 0, sizeof(VASliceParameterBufferH264)); - - s->slice_data_size = srcSize; - s->slice_data_bit_offset = seek << 3; - s->slice_data_flag = VA_SLICE_DATA_FLAG_ALL; - - s->first_mb_in_slice = slice->first_mb_in_slice; - s->slice_type = slice->slice_type; - s->direct_spatial_mv_pred_flag = slice->direct_spatial_mv_pred_flag; - s->num_ref_idx_l0_active_minus1 = slice->num_ref_idx_l0_active_minus1; - s->num_ref_idx_l1_active_minus1 = slice->num_ref_idx_l1_active_minus1; - s->cabac_init_idc = slice->cabac_init_idc; - s->slice_qp_delta = slice->slice_qp_delta; - s->disable_deblocking_filter_idc = slice->disable_deblocking_filter_idc; - s->slice_alpha_c0_offset_div2 = slice->slice_alpha_c0_offset_div2; - s->slice_beta_offset_div2 = slice->slice_beta_offset_div2; - s->luma_log2_weight_denom = slice->pred_weight_table.luma_log2_weight_denom; - s->chroma_log2_weight_denom = slice->pred_weight_table.chroma_log2_weight_denom; - s->luma_weight_l0_flag = slice->pred_weight_table.luma_weight_flag [0]; - s->chroma_weight_l0_flag = slice->pred_weight_table.chroma_weight_flag[0]; - s->luma_weight_l1_flag = slice->pred_weight_table.luma_weight_flag [1]; - s->chroma_weight_l1_flag = slice->pred_weight_table.chroma_weight_flag[1]; - - //RefPicList0/1 - - fill_pred_weight_table( - slice->pred_weight_table.l0, - s->num_ref_idx_l0_active_minus1, - s->luma_log2_weight_denom, - s->luma_weight_l0_flag, - s->luma_weight_l0, - s->luma_offset_l0, - s->chroma_log2_weight_denom, - s->chroma_weight_l0_flag, - s->chroma_weight_l0, - s->chroma_weight_l0 - ); - - fill_pred_weight_table( - slice->pred_weight_table.l1, - s->num_ref_idx_l1_active_minus1, - s->luma_log2_weight_denom, - s->luma_weight_l1_flag, - s->luma_weight_l1, - s->luma_offset_l1, - s->chroma_log2_weight_denom, - s->chroma_weight_l1_flag, - s->chroma_weight_l1, - s->chroma_weight_l1 - ); - -#if 0 - if (this->sliceType == 2) - { - set_slice_parameter_buffer_t2(s, this->t2First); - this->t2First = false; - } - else - { - set_slice_parameter_buffer(s); - memcpy(&s->RefPicList0[0], &this->oldPic, sizeof(VAPictureH264)); - s->RefPicList0[0].flags = 0; - } -#endif - - status = vaUnmapBuffer(this->vaDisplay, *sliBufferID); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaUnmapBuffer: %s", vaErrorStr(status)); - return false; - } - - return true; -} - -static bool setup_dat_buffer(struct Inst * this, const uint8_t * src, size_t srcSize) -{ - VAStatus status; - - VABufferID * datBufferID = &this->datBufferID[this->currentSID]; - - if (!get_buffer(this, VASliceDataBufferType, srcSize, datBufferID)) - { - DEBUG_ERROR("get datBuffer failed"); - return false; - } - - uint8_t * d; - status = vaMapBuffer(this->vaDisplay, *datBufferID, (void **)&d); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaMapBuffer: %s", vaErrorStr(status)); - return false; - } - - memcpySSE(d, src, srcSize); - - status = vaUnmapBuffer(this->vaDisplay, *datBufferID); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaUnmapBuffer: %s", vaErrorStr(status)); - return false; - } - - return true; -} - -static bool lgd_h264_decode(void * opaque, const uint8_t * src, size_t srcSize) -{ - VAStatus status; - struct Inst * this = (struct Inst *)opaque; - - size_t seek; - if (!nal_parse(this->nal, src, srcSize, &seek)) - { - DEBUG_WARN("nal_parse, perhaps mid stream"); - return true; - } - - const NAL_SLICE * slice; - if (!nal_get_slice(this->nal, &slice)) - { - DEBUG_WARN("nal_get_slice failed"); - return true; - } - - assert(seek < srcSize); - this->sliceType = slice->slice_type; - - // don't start until we have an I-FRAME - if (this->frameNum == 0 && this->sliceType != NAL_SLICE_TYPE_I) - return true; - - { - if (!setup_pic_buffer(this, slice)) return false; - if (!setup_mat_buffer(this)) return false; - - VABufferID bufferIDs[] = - { - this->picBufferID[this->currentSID], - this->matBufferID[this->currentSID] - }; - - status = vaRenderPicture(this->vaDisplay, this->vaContextID, bufferIDs, 2); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaRenderPicture: %s", vaErrorStr(status)); - return false; - } - - // intel broke the ABI here, see: - // https://github.com/01org/libva/commit/3eb038aa13bdd785808286c0a4995bd7a1ef07e9 - // the buffers are released by vaRenderPicture in old versions - if (this->vaMajorVer == 0 && this->vaMinorVer < 40) - { - this->picBufferID[this->currentSID] = - this->matBufferID[this->currentSID] = VA_INVALID_ID; - } - } - - { - if (!setup_sli_buffer(this, srcSize, slice, seek)) return false; - if (!setup_dat_buffer(this, src, srcSize )) return false; - VABufferID bufferIDs[] = - { - this->sliBufferID[this->currentSID], - this->datBufferID[this->currentSID] - }; - - status = vaRenderPicture(this->vaDisplay, this->vaContextID, bufferIDs, 2); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaRenderPicture: %s", vaErrorStr(status)); - return false; - } - - // intel broke the ABI here, see: - // https://github.com/01org/libva/commit/3eb038aa13bdd785808286c0a4995bd7a1ef07e9 - // the buffers are released by vaRenderPicture in old versions - if (this->vaMajorVer == 0 && this->vaMinorVer < 40) - { - this->sliBufferID[this->currentSID] = - this->datBufferID[this->currentSID] = VA_INVALID_ID; - } - } - - status = vaEndPicture(this->vaDisplay, this->vaContextID); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaEndPicture: %s", vaErrorStr(status)); - return false; - } - - // advance to the next surface and save the old picture info - this->lastSID = this->currentSID; - if (++this->currentSID == SURFACE_NUM) - this->currentSID = 0; - this->frameNum += 1; - this->fieldCount += 2; - memcpy(&this->oldPic, &this->curPic, sizeof(VAPictureH264)); - - // prepare the next surface - status = vaBeginPicture(this->vaDisplay, this->vaContextID, this->vaSurfaceID[this->currentSID]); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaBeginPicture: %s", vaErrorStr(status)); - return false; - } - - return true; -} - -static bool lgd_h264_get_buffer(void * opaque, uint8_t * dst, size_t dstSize) -{ - struct Inst * this = (struct Inst *)opaque; - VAStatus status; - - // don't return anything until we have some data - if (this->frameNum == 0) - return true; - - // ensure the surface is ready - status = vaSyncSurface(this->vaDisplay, this->vaSurfaceID[this->lastSID]); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaSyncSurface: %s", vaErrorStr(status)); - return false; - } - -#if 0 - // this doesn't work on my system, seems the vdpau va driver is bugged - VASurfaceStatus surfStatus; - if (!check_surface(this, this->lastSID, &surfStatus)) - return false; - - if (surfStatus != VASurfaceReady) - { - DEBUG_ERROR("vaSyncSurface didn't block, the surface is not ready!"); - return false; - } -#endif - - // get the decoded data - VAImage decoded = - { - .image_id = VA_INVALID_ID, - .buf = VA_INVALID_ID - }; - - status = vaDeriveImage(this->vaDisplay, this->vaSurfaceID[this->lastSID], &decoded); - if (status == VA_STATUS_ERROR_OPERATION_FAILED) - { - VAImageFormat format = - { - .fourcc = VA_FOURCC_NV12, - .byte_order = VA_LSB_FIRST, - .bits_per_pixel = 12 - }; - - status = vaCreateImage( - this->vaDisplay, - &format, - this->format.width, - this->format.height, - &decoded - ); - - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaCreateImage: %s", vaErrorStr(status)); - return false; - } - - status = vaPutImage( - this->vaDisplay, - this->vaSurfaceID[this->lastSID], - decoded.image_id, - 0 , 0 , - this->format.width, this->format.height, - 0 , 0 , - this->format.width, this->format.height - ); - - if (status != VA_STATUS_SUCCESS) - { - vaDestroyImage(this->vaDisplay, decoded.image_id); - DEBUG_ERROR("vaPutImage: %s", vaErrorStr(status)); - return false; - } - } - else - { - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaDeriveImage: %s", vaErrorStr(status)); - return false; - } - } - - uint8_t * d; - status = vaMapBuffer(this->vaDisplay, decoded.buf, (void **)&d); - if (status != VA_STATUS_SUCCESS) - { - vaDestroyImage(this->vaDisplay, decoded.image_id); - DEBUG_ERROR("vaMapBuffer: %s", vaErrorStr(status)); - return false; - } - - memcpySSE(dst, d, decoded.data_size); - - status = vaUnmapBuffer(this->vaDisplay, decoded.buf); - if (status != VA_STATUS_SUCCESS) - { - vaDestroyImage(this->vaDisplay, decoded.image_id); - DEBUG_ERROR("vaUnmapBuffer: %s", vaErrorStr(status)); - return false; - } - - status = vaDestroyImage(this->vaDisplay, decoded.image_id); - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaDestroyImage: %s", vaErrorStr(status)); - return false; - } - - return true; -} - -static bool lgd_h264_init_gl_texture(void * opaque, GLenum target, GLuint texture, void ** ref) -{ - struct Inst * this = (struct Inst *)opaque; - VAStatus status; - - status = vaCreateSurfaceGLX(this->vaDisplay, target, texture, ref); - if (status != VA_STATUS_SUCCESS) - { - *ref = NULL; - DEBUG_ERROR("vaCreateSurfaceGLX: %s", vaErrorStr(status)); - return false; - } - - return true; -} - -static void lgd_h264_free_gl_texture(void * opaque, void * ref) -{ - struct Inst * this = (struct Inst *)opaque; - VAStatus status; - - status = vaDestroySurfaceGLX(this->vaDisplay, ref); - if (status != VA_STATUS_SUCCESS) - DEBUG_ERROR("vaDestroySurfaceGLX: %s", vaErrorStr(status)); -} - -static bool lgd_h264_update_gl_texture(void * opaque, void * ref) -{ - struct Inst * this = (struct Inst *)opaque; - VAStatus status; - - // don't return anything until we have some data - if (this->frameNum == 0) - return true; - - status = vaCopySurfaceGLX( - this->vaDisplay, - ref, - this->vaSurfaceID[this->lastSID], - 0 - ); - - if (status != VA_STATUS_SUCCESS) - { - DEBUG_ERROR("vaCopySurfaceGLX: %s", vaErrorStr(status)); - return false; - } - - 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, - .get_frame_stride = lgd_h264_get_frame_stride, - .decode = lgd_h264_decode, - .get_buffer = lgd_h264_get_buffer, - - .has_gl = true, - .init_gl_texture = lgd_h264_init_gl_texture, - .free_gl_texture = lgd_h264_free_gl_texture, - .update_gl_texture = lgd_h264_update_gl_texture -}; \ No newline at end of file diff --git a/client/decoders/src/null.c b/client/decoders/src/null.c deleted file mode 100644 index bd30b55d..00000000 --- a/client/decoders/src/null.c +++ /dev/null @@ -1,130 +0,0 @@ -/* -Looking Glass - KVM FrameRelay (KVMFR) Client -Copyright (C) 2017-2019 Geoffrey McRae -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 "interface/decoder.h" - -#include "common/debug.h" -#include "common/memcpySSE.h" - -#include -#include - -struct Inst -{ - LG_RendererFormat format; - const uint8_t * src; -}; - -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, SDL_Window * window); -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 unsigned int lgd_null_get_frame_stride(void * opaque); -static bool lgd_null_decode (void * opaque, const uint8_t * src, size_t srcSize); -static const uint8_t * lgd_null_get_buffer (void * opaque); - -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, SDL_Window * window) -{ - struct Inst * this = (struct Inst *)opaque; - memcpy(&this->format, &format, sizeof(LG_RendererFormat)); - return true; -} - -static void lgd_null_deinitialize(void * opaque) -{ - struct Inst * this = (struct Inst *)opaque; - memset(this, 0, sizeof(struct Inst)); -} - -static LG_OutFormat lgd_null_get_out_format(void * opaque) -{ - struct Inst * this = (struct Inst *)opaque; - switch(this->format.type) - { - case FRAME_TYPE_BGRA : return LG_OUTPUT_BGRA; - case FRAME_TYPE_RGBA : return LG_OUTPUT_RGBA; - case FRAME_TYPE_RGBA10: return LG_OUTPUT_RGBA10; - - default: - DEBUG_ERROR("Unknown frame type"); - return LG_OUTPUT_INVALID; - } -} - -static unsigned int lgd_null_get_frame_pitch(void * opaque) -{ - struct Inst * this = (struct Inst *)opaque; - return this->format.pitch; -} - -static unsigned int lgd_null_get_frame_stride(void * opaque) -{ - struct Inst * this = (struct Inst *)opaque; - return this->format.stride; -} - -static bool lgd_null_decode(void * opaque, const uint8_t * src, size_t srcSize) -{ - struct Inst * this = (struct Inst *)opaque; - this->src = src; - return true; -} - -static const uint8_t * lgd_null_get_buffer(void * opaque) -{ - struct Inst * this = (struct Inst *)opaque; - if (!this->src) - return NULL; - - return this->src; -} - -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, - .get_frame_stride = lgd_null_get_frame_stride, - .decode = lgd_null_decode, - .get_buffer = lgd_null_get_buffer -}; \ No newline at end of file diff --git a/client/decoders/src/yuv420.c b/client/decoders/src/yuv420.c deleted file mode 100644 index b4c1b863..00000000 --- a/client/decoders/src/yuv420.c +++ /dev/null @@ -1,169 +0,0 @@ -/* -Looking Glass - KVM FrameRelay (KVMFR) Client -Copyright (C) 2017-2019 Geoffrey McRae -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 "interface/decoder.h" - -#include "common/debug.h" -#include "common/memcpySSE.h" - -#include -#include -#include - -#include - -struct Pixel -{ - uint8_t b, g, r, a; -}; - -struct Inst -{ - LG_RendererFormat format; - struct Pixel * pixels; - unsigned int yBytes; -}; - -static bool lgd_yuv420_create (void ** opaque); -static void lgd_yuv420_destroy (void * opaque); -static bool lgd_yuv420_initialize (void * opaque, const LG_RendererFormat format, SDL_Window * window); -static void lgd_yuv420_deinitialize (void * opaque); -static LG_OutFormat lgd_yuv420_get_out_format (void * opaque); -static unsigned int lgd_yuv420_get_frame_pitch (void * opaque); -static unsigned int lgd_yuv420_get_frame_stride(void * opaque); -static bool lgd_yuv420_decode (void * opaque, const uint8_t * src, size_t srcSize); -static const uint8_t * lgd_yuv420_get_buffer (void * opaque); - -static bool lgd_yuv420_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_yuv420_destroy(void * opaque) -{ - free(opaque); -} - -static bool lgd_yuv420_initialize(void * opaque, const LG_RendererFormat format, SDL_Window * window) -{ - struct Inst * this = (struct Inst *)opaque; - memcpy(&this->format, &format, sizeof(LG_RendererFormat)); - - this->yBytes = format.width * format.height; - this->pixels = malloc(sizeof(struct Pixel) * (format.width * format.height)); - return true; -} - -static void lgd_yuv420_deinitialize(void * opaque) -{ - struct Inst * this = (struct Inst *)opaque; - free(this->pixels); -} - -static LG_OutFormat lgd_yuv420_get_out_format(void * opaque) -{ - return LG_OUTPUT_BGRA; -} - -static unsigned int lgd_yuv420_get_frame_pitch(void * opaque) -{ - struct Inst * this = (struct Inst *)opaque; - return this->format.width * 4; -} - -static unsigned int lgd_yuv420_get_frame_stride(void * opaque) -{ - struct Inst * this = (struct Inst *)opaque; - return this->format.width; -} - -static bool lgd_yuv420_decode(void * opaque, const uint8_t * src, size_t srcSize) -{ - //FIXME: implement this properly using GLSL - - struct Inst * this = (struct Inst *)opaque; - const unsigned int hw = this->format.width / 2; - const unsigned int hp = this->yBytes / 4; - - for(size_t y = 0; y < this->format.height; ++y) - for(size_t x = 0; x < this->format.width; ++x) - { - const unsigned int yoff = y * this->format.width + x; - const unsigned int uoff = this->yBytes + ((y / 2) * hw + x / 2); - const unsigned int voff = uoff + hp; - - float b = 1.164f * ((float)src[yoff] - 16.0f) + 2.018f * ((float)src[uoff] - 128.0f); - float g = 1.164f * ((float)src[yoff] - 16.0f) - 0.813f * ((float)src[voff] - 128.0f) - 0.391f * ((float)src[uoff] - 128.0f); - float r = 1.164f * ((float)src[yoff] - 16.0f) + 1.596f * ((float)src[voff] - 128.0f); - - #define CLAMP(x) (x < 0 ? 0 : (x > 255 ? 255 : x)) - this->pixels[yoff].b = CLAMP(b); - this->pixels[yoff].g = CLAMP(g); - this->pixels[yoff].r = CLAMP(r); - } - - return true; -} - -static const uint8_t * lgd_yuv420_get_buffer(void * opaque) -{ - struct Inst * this = (struct Inst *)opaque; - return (uint8_t *)this->pixels; -} - -bool lgd_yuv420_init_gl_texture(void * opaque, GLenum target, GLuint texture, void ** ref) -{ - return false; -} - -void lgd_yuv420_free_gl_texture(void * opaque, void * ref) -{ -} - -bool lgd_yuv420_update_gl_texture(void * opaque, void * ref) -{ - return false; -} - -const LG_Decoder LGD_YUV420 = -{ - .name = "YUV420", - .create = lgd_yuv420_create, - .destroy = lgd_yuv420_destroy, - .initialize = lgd_yuv420_initialize, - .deinitialize = lgd_yuv420_deinitialize, - .get_out_format = lgd_yuv420_get_out_format, - .get_frame_pitch = lgd_yuv420_get_frame_pitch, - .get_frame_stride = lgd_yuv420_get_frame_stride, - .decode = lgd_yuv420_decode, - .get_buffer = lgd_yuv420_get_buffer, - - .has_gl = false, //FIXME: Implement this - .init_gl_texture = lgd_yuv420_init_gl_texture, - .free_gl_texture = lgd_yuv420_free_gl_texture, - .update_gl_texture = lgd_yuv420_update_gl_texture -}; \ No newline at end of file diff --git a/client/parsers/nal.c b/client/parsers/nal.c deleted file mode 100644 index c91129af..00000000 --- a/client/parsers/nal.c +++ /dev/null @@ -1,1009 +0,0 @@ -/* -Looking Glass - KVM FrameRelay (KVMFR) Client -Copyright (C) 2017-2019 Geoffrey McRae -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 "nal.h" - -#include "debug.h" -#include "utils.h" - -#include -#include - -#define DEBUG_NAL - -struct NAL -{ - uint8_t primary_pic_type; - bool primary_pic_type_valid; - - bool sps_valid; - NAL_SPS sps; - int32_t * sps_offset_for_ref_frame; - uint32_t sps_num_ref_frames_in_pic_order_cnt_cycle; - - bool vui_valid; - NAL_VUI vui; - NAL_CPB * vui_nal_hrd_parameters_cpb; - uint32_t vui_nal_hrd_parameters_cpb_size; - NAL_CPB * vui_vcl_hrd_parameters_cpb; - uint32_t vui_vcl_hrd_parameters_cpb_size; - - bool pps_valid; - NAL_PPS pps; - NAL_SLICE_GROUP * pps_slice_groups; - uint32_t pps_slice_groups_size; - uint32_t * pps_slice_group_id; - uint32_t pps_slice_group_id_size; - - bool slice_valid; - NAL_SLICE slice; - NAL_PW_TABLE_L * slice_pred_weight_table_l0; - uint32_t slice_pred_weight_table_l0_size; - NAL_PW_TABLE_L * slice_pred_weight_table_l1; - uint32_t slice_pred_weight_table_l1_size; -}; - -bool nal_initialize(NAL * ptr) -{ - *ptr = (NAL)malloc(sizeof(struct NAL)); - memset(*ptr, 0, sizeof(struct NAL)); - return true; -} - -void nal_deinitialize(NAL this) -{ - free(this->slice_pred_weight_table_l1); - free(this->slice_pred_weight_table_l0); - free(this->pps_slice_group_id); - free(this->pps_slice_groups); - free(this->sps_offset_for_ref_frame); - free(this->vui_nal_hrd_parameters_cpb); - free(this->vui_vcl_hrd_parameters_cpb); - free(this); -} - -static bool parse_nal_hrd( - NAL_HRD * const hrd, - NAL_CPB ** cpb, - uint32_t * cpb_size, - const uint8_t * src, - size_t size, - size_t * const offset) -{ - hrd->cpb_cnt_minus1 = decode_u_golomb(src, offset); - hrd->bit_rate_scale = get_bits(src, offset, 4); - hrd->cpb_size_scale = get_bits(src, offset, 4); - - if (*cpb_size < hrd->cpb_size_scale) - { - *cpb = realloc(*cpb, hrd->cpb_size_scale * sizeof(NAL_CPB)); - *cpb_size = hrd->cpb_size_scale; - } - - hrd->cpb = *cpb; - for(uint32_t i = 0; i < hrd->cpb_size_scale; ++i) - { - hrd->cpb[i].bit_rate_value_minus1 = decode_u_golomb(src, offset); - hrd->cpb[i].cpb_size_value_minus1 = decode_u_golomb(src, offset); - hrd->cpb[i].cbr_flag = get_bit(src, offset); - } - - hrd->initial_cpb_removal_delay_length_minus1 = get_bits(src, offset, 5); - hrd->cpb_removal_delay_length_minus1 = get_bits(src, offset, 5); - hrd->dpb_output_delay_length_minus1 = get_bits(src, offset, 5); - hrd->time_offset_length = get_bits(src, offset, 5); - - return true; -} - -static bool parse_nal_vui(NAL this, const uint8_t * src, size_t size, size_t * const offset) -{ - NAL_VUI * vui = &this->vui; - memset(vui, 0, sizeof(NAL_VUI)); - - vui->aspect_ratio_info_present_flag = get_bit(src, offset); - if (vui->aspect_ratio_info_present_flag) - { - vui->aspect_ratio_idc = get_bits(src, offset, 8); - if (vui->aspect_ratio_idc == IDC_VUI_ASPECT_RATIO_EXTENDED_SAR) - { - vui->sar_width = get_bits(src, offset, 16); - vui->sar_height = get_bits(src, offset, 16); - } - } - - vui->overscan_info_present_flag = get_bit(src, offset); - if (vui->overscan_info_present_flag) - vui->overscan_appropriate_flag = get_bit(src, offset); - - vui->video_signal_type_present_flag = get_bit(src, offset); - if (vui->video_signal_type_present_flag) - { - vui->video_format = get_bits(src, offset, 3); - vui->video_full_range_flag = get_bit(src, offset); - vui->colour_description_present_flag = get_bit(src, offset); - if (vui->colour_description_present_flag) - { - vui->colour_primaries = get_bits(src, offset, 8); - vui->transfer_characteristics = get_bits(src, offset, 8); - vui->matrix_coefficients = get_bits(src, offset, 8); - } - } - - vui->chroma_loc_info_present_flag = get_bit(src, offset); - if (vui->chroma_loc_info_present_flag) - { - vui->chroma_sample_loc_type_top_field = decode_u_golomb(src, offset); - vui->chroma_sample_loc_type_bottom_field = decode_u_golomb(src, offset); - } - - vui->timing_info_present_flag = get_bit(src, offset); - if (vui->timing_info_present_flag) - { - vui->num_units_in_tick = get_bits(src, offset, 32); - vui->time_scale = get_bits(src, offset, 32); - vui->fixed_frame_rate_flag = get_bit(src, offset); - } - - vui->nal_hrd_parameters_present_flag = get_bit(src, offset); - if (vui->nal_hrd_parameters_present_flag) - if (!parse_nal_hrd( - &vui->nal_hrd_parameters, - &this->vui_nal_hrd_parameters_cpb, - &this->vui_nal_hrd_parameters_cpb_size, - src, - size, - offset)) - return false; - - vui->vcl_hrd_parameters_present_flag = get_bit(src, offset); - if (vui->vcl_hrd_parameters_present_flag) - if (!parse_nal_hrd( - &vui->vcl_hrd_parameters, - &this->vui_vcl_hrd_parameters_cpb, - &this->vui_vcl_hrd_parameters_cpb_size, - src, - size, - offset)) - return false; - - if (vui->nal_hrd_parameters_present_flag || vui->vcl_hrd_parameters_present_flag) - vui->low_delay_hrd_flag = get_bit(src, offset); - - vui->pic_struct_present_flag = get_bit(src, offset); - vui->bitstream_restriction_flag = get_bit(src, offset); - if (vui->bitstream_restriction_flag) - { - vui->motion_vectors_over_pic_boundaries_flag = get_bit(src, offset); - vui->max_bytes_per_pic_denom = decode_u_golomb(src, offset); - vui->max_bits_per_mb_denom = decode_u_golomb(src, offset); - vui->log2_max_mv_length_horizontal = decode_u_golomb(src, offset); - vui->log2_max_mv_length_vertical = decode_u_golomb(src, offset); - vui->num_reorder_frames = decode_u_golomb(src, offset); - vui->max_dec_frame_buffering = decode_u_golomb(src, offset); - } - - return true; -} - -static bool parse_nal_trailing_bits(NAL this, const uint8_t * src, size_t size, size_t * const offset) -{ - if (!get_bit(src, offset)) - { - DEBUG_ERROR("Missing stop bit"); - return false; - } - - // byte align - *offset = (*offset + 0x7) & ~0x7; - return true; -} - -static bool parse_nal_sps(NAL this, const uint8_t * src, size_t size, size_t * const offset) -{ - this->sps_valid = false; - memset(&this->sps, 0, sizeof(this->sps)); - - this->sps.profile_idc = get_bits(src, offset, 8); - if ((this->sps.profile_idc != IDC_PROFILE_BASELINE) && - (this->sps.profile_idc != IDC_PROFILE_MAIN ) && - (this->sps.profile_idc != IDC_PROFILE_EXTENDED) && - (this->sps.profile_idc != IDC_PROFILE_HP ) && - (this->sps.profile_idc != IDC_PROFILE_Hi10P ) && - (this->sps.profile_idc != IDC_PROFILE_Hi422 ) && - (this->sps.profile_idc != IDC_PROFILE_Hi444 ) && - (this->sps.profile_idc != IDC_PROFILE_CAVLC444)) - { - DEBUG_ERROR("Invalid profile IDC (%d) encountered", this->sps.profile_idc); - return false; - } - - this->sps.constraint_set_flags[0] = get_bit(src, offset); - this->sps.constraint_set_flags[1] = get_bit(src, offset); - this->sps.constraint_set_flags[2] = get_bit(src, offset); - *offset += 5; - - this->sps.level_idc = get_bits(src, offset, 8); - this->sps.seq_parameter_set_id = decode_u_golomb(src, offset); - - if ((this->sps.profile_idc == IDC_PROFILE_HP ) || - (this->sps.profile_idc == IDC_PROFILE_Hi10P ) || - (this->sps.profile_idc == IDC_PROFILE_Hi422 ) || - (this->sps.profile_idc == IDC_PROFILE_Hi444 ) || - (this->sps.profile_idc == IDC_PROFILE_CAVLC444)) - { - this->sps.chroma_format_idc = decode_u_golomb(src, offset); - if (this->sps.chroma_format_idc == IDC_CHROMA_FORMAT_YUV444) - this->sps.seperate_colour_plane_flag = get_bit(src, offset); - - this->sps.bit_depth_luma_minus8 = decode_u_golomb(src, offset); - this->sps.bit_depth_chroma_minus8 = decode_u_golomb(src, offset); - this->sps.lossless_qpprime_y_zero_flag = get_bit(src, offset); - this->sps.seq_scaling_matrix_present_flag = get_bit(src, offset); - - if (this->sps.seq_scaling_matrix_present_flag) - { - const int cnt = this->sps.chroma_format_idc == IDC_CHROMA_FORMAT_YUV444 ? 12 : 8; - for(int i = 0; i < cnt; ++i) - this->sps.seq_scaling_list_present_flag[i] = get_bit(src, offset); - } - } - else - this->sps.chroma_format_idc = IDC_CHROMA_FORMAT_YUV420; - - this->sps.log2_max_frame_num_minus4 = decode_u_golomb(src, offset); - this->sps.pic_order_cnt_type = decode_u_golomb(src, offset); - - if (this->sps.pic_order_cnt_type == 0) - this->sps.log2_max_pic_order_cnt_lsb_minus4 = decode_u_golomb(src, offset); - else - { - if (this->sps.pic_order_cnt_type == 1) - { - this->sps.delta_pic_order_always_zero_flag = get_bit(src, offset); - this->sps.offset_for_non_ref_pic = decode_s_golomb(src, offset); - this->sps.offset_for_top_to_bottom_field = decode_s_golomb(src, offset); - - this->sps.num_ref_frames_in_pic_order_cnt_cycle = decode_u_golomb(src, offset); - if (this->sps.num_ref_frames_in_pic_order_cnt_cycle > this->sps_num_ref_frames_in_pic_order_cnt_cycle) - { - this->sps_offset_for_ref_frame = realloc( - this->sps_offset_for_ref_frame, - this->sps.num_ref_frames_in_pic_order_cnt_cycle * sizeof(int32_t) - ); - this->sps_num_ref_frames_in_pic_order_cnt_cycle = this->sps.num_ref_frames_in_pic_order_cnt_cycle; - } - - this->sps.offset_for_ref_frame = this->sps_offset_for_ref_frame; - for(uint32_t i = 0; i < this->sps.num_ref_frames_in_pic_order_cnt_cycle; ++i) - this->sps.offset_for_ref_frame[i] = decode_s_golomb(src, offset); - } - } - - this->sps.num_ref_frames = decode_u_golomb(src, offset); - this->sps.gaps_in_frame_num_value_allowed_flag = get_bit(src, offset); - this->sps.pic_width_in_mbs_minus1 = decode_u_golomb(src, offset); - this->sps.pic_height_in_map_units_minus1 = decode_u_golomb(src, offset); - this->sps.frame_mbs_only_flag = get_bit(src, offset); - - if (!this->sps.frame_mbs_only_flag) - this->sps.mb_adaptive_frame_field_flag = get_bit(src, offset); - - this->sps.direct_8x8_inference_flag = get_bit(src, offset); - this->sps.frame_cropping_flag = get_bit(src, offset); - - if (this->sps.frame_cropping_flag) - { - this->sps.frame_crop_left_offset = decode_u_golomb(src, offset); - this->sps.frame_crop_right_offset = decode_u_golomb(src, offset); - this->sps.frame_crop_top_offset = decode_u_golomb(src, offset); - this->sps.frame_crop_bottom_offset = decode_u_golomb(src, offset); - } - - this->sps.vui_parameters_present_flag = get_bit(src, offset); - -#ifdef DEBUG_NAL - DEBUG_INFO("SPS\n" - "profile_idc : %u\n" - "constraint_set_flags : %u %u %u\n" - "level_idc : %u\n" - "sec_parameter_set_id : %u\n" - "chroma_format_idc : %u\n" - "seperate_colour_plane_flag : %u\n" - "bit_depth_luma_minus8 : %u\n" - "bit_depth_chroma_minus8 : %u\n" - "lossless_qpprime_y_zero_flag : %u\n" - "seq_scaling_matrix_present_flag : %u\n" - "log2_max_frame_num_minus4 : %u\n" - "pic_order_cnt_type : %u\n" - "log2_max_pic_order_cnt_lsb_minus4 : %u\n" - "delta_pic_order_always_zero_flag : %u\n" - "offset_for_non_ref_pic : %d\n" - "offset_for_top_to_bottom_field : %d\n" - "num_ref_frames_in_pic_order_cnt_cycle: %u\n" - "num_ref_frames : %u\n" - "gaps_in_frame_num_value_allowed_flag : %u\n" - "pic_width_in_mbs_minus1 : %3u (%u)\n" - "pic_height_in_map_units_minus1 : %3u (%u)\n" - "frame_mbs_only_flag : %u\n" - "mb_adaptive_frame_field_flag : %u\n" - "direct_8x8_inference_flag : %u\n" - "frame_cropping_flag : %u\n" - "frame_crop_left_offset : %u\n" - "frame_crop_right_offset : %u\n" - "frame_crop_top_offset : %u\n" - "frame_crop_bottom_offset : %u\n" - "vui_parameters_present_flag : %u", - this->sps.profile_idc, - this->sps.constraint_set_flags[0], - this->sps.constraint_set_flags[1], - this->sps.constraint_set_flags[2], - this->sps.level_idc, - this->sps.seq_parameter_set_id, - this->sps.chroma_format_idc, - this->sps.seperate_colour_plane_flag, - this->sps.bit_depth_luma_minus8, - this->sps.bit_depth_chroma_minus8, - this->sps.lossless_qpprime_y_zero_flag, - this->sps.seq_scaling_matrix_present_flag, - this->sps.log2_max_frame_num_minus4, - this->sps.pic_order_cnt_type, - this->sps.log2_max_pic_order_cnt_lsb_minus4, - this->sps.delta_pic_order_always_zero_flag, - this->sps.offset_for_non_ref_pic, - this->sps.offset_for_top_to_bottom_field, - this->sps.num_ref_frames_in_pic_order_cnt_cycle, - this->sps.num_ref_frames, - this->sps.gaps_in_frame_num_value_allowed_flag, - this->sps.pic_width_in_mbs_minus1 , (this->sps.pic_width_in_mbs_minus1 + 1) * 16, - this->sps.pic_height_in_map_units_minus1, (this->sps.pic_height_in_map_units_minus1 + 1) * 16, - this->sps.frame_mbs_only_flag, - this->sps.mb_adaptive_frame_field_flag, - this->sps.direct_8x8_inference_flag, - this->sps.frame_cropping_flag, - this->sps.frame_crop_left_offset, - this->sps.frame_crop_right_offset, - this->sps.frame_crop_top_offset, - this->sps.frame_crop_bottom_offset, - this->sps.vui_parameters_present_flag - ); -#endif - - if (this->sps.vui_parameters_present_flag) - { - if (!parse_nal_vui(this, src, size, offset)) - return false; - this->vui_valid = true; - } - - if (!parse_nal_trailing_bits(this, src, size, offset)) - return false; - - this->sps_valid = true; - return true; -} - -static bool parse_nal_pps(NAL this, const uint8_t * src, size_t size, size_t * const offset) -{ - NAL_PPS * pps = &this->pps; - this->pps_valid = false; - memset(pps, 0, sizeof(NAL_PPS)); - - pps->pic_parameter_set_id = decode_u_golomb(src, offset); - pps->seq_parameter_set_id = decode_u_golomb(src, offset); - pps->entropy_coding_mode_flag = get_bit(src, offset); - pps->pic_order_present_flag = get_bit(src, offset); - pps->num_slice_groups_minus1 = decode_u_golomb(src, offset); - - if (pps->num_slice_groups_minus1 > 0) - { - pps->slice_group_map_type = decode_u_golomb(src, offset); - if (pps->slice_group_map_type == 0 || pps->slice_group_map_type == 2) - { - if (this->pps_slice_groups_size < pps->num_slice_groups_minus1 + 1) - { - this->pps_slice_groups_size = pps->num_slice_groups_minus1 + 1; - this->pps_slice_groups = (NAL_SLICE_GROUP *)realloc( - this->pps_slice_groups, this->pps_slice_groups_size * sizeof(NAL_SLICE_GROUP)); - } - pps->slice_groups = this->pps_slice_groups; - memset(pps->slice_groups, 0, (pps->num_slice_groups_minus1 + 1) * sizeof(NAL_SLICE_GROUP)); - - if (pps->slice_group_map_type == 0) - { - for(uint32_t group = 0; group <= pps->num_slice_groups_minus1; ++group) - pps->slice_groups[group].t0.run_length_minus1 = decode_u_golomb(src, offset); - } - else - { - for(uint32_t group = 0; group < pps->num_slice_groups_minus1; ++group) - { - pps->slice_groups[group].t2.top_left = decode_u_golomb(src, offset); - pps->slice_groups[group].t2.bottom_right = decode_u_golomb(src, offset); - } - } - } - else - { - if (pps->slice_group_map_type == 3 || - pps->slice_group_map_type == 4 || - pps->slice_group_map_type == 5) - { - pps->slice_group_change_direction_flag = get_bit(src, offset); - pps->slice_group_change_rate_minus1 = decode_u_golomb(src, offset); - } - else - { - if (pps->slice_group_map_type == 6) - { - pps->pic_size_in_map_units_minus1 = decode_u_golomb(src, offset); - - uint32_t slice_groups = pps->pic_size_in_map_units_minus1 + 1; - uint32_t bits = 0; - if ((slice_groups & (slice_groups - 1)) != 0) - ++slice_groups; - - while(slice_groups > 0) - { - slice_groups >>= 1; - ++bits; - } - - if (this->pps_slice_group_id_size < pps->pic_size_in_map_units_minus1 + 1) - { - this->pps_slice_group_id_size = pps->pic_size_in_map_units_minus1 + 1; - this->pps_slice_group_id = realloc(this->pps_slice_group_id, - this->pps_slice_group_id_size * sizeof(uint32_t)); - } - pps->slice_group_id = this->pps_slice_group_id; - - for(uint32_t group = 0; group <= pps->pic_size_in_map_units_minus1; ++group) - pps->slice_group_id[group] = get_bits(src, offset, bits); - } - else - { - DEBUG_ERROR("Invalid slice_group_map_type: %d", pps->slice_group_map_type); - return false; - } - } - } - } - - pps->num_ref_idx_l0_active_minus1 = decode_u_golomb(src, offset); - pps->num_ref_idx_l1_active_minus1 = decode_u_golomb(src, offset); - pps->weighted_pred_flag = get_bit(src, offset); - pps->weighted_bipred_idc = get_bits(src, offset, 2); - pps->pic_init_qp_minus26 = decode_s_golomb(src, offset); - pps->pic_init_qs_minus26 = decode_s_golomb(src, offset); - pps->chroma_qp_index_offset = decode_s_golomb(src, offset); - pps->deblocking_filter_control_present_flag = get_bit(src, offset); - pps->constrained_intra_pred_flag = get_bit(src, offset); - pps->redundant_pic_cnt_present_flag = get_bit(src, offset); - - if (pps->num_ref_idx_l0_active_minus1 + 1 > this->slice_pred_weight_table_l0_size) - { - this->slice_pred_weight_table_l0_size = pps->num_ref_idx_l0_active_minus1 + 1; - this->slice_pred_weight_table_l0 = realloc(this->slice_pred_weight_table_l0, - this->slice_pred_weight_table_l0_size * sizeof(NAL_PW_TABLE_L)); - } - - if (pps->num_ref_idx_l1_active_minus1 + 1 > this->slice_pred_weight_table_l1_size) - { - this->slice_pred_weight_table_l1_size = pps->num_ref_idx_l1_active_minus1 + 1; - this->slice_pred_weight_table_l1 = realloc(this->slice_pred_weight_table_l1, - this->slice_pred_weight_table_l1_size * sizeof(NAL_PW_TABLE_L)); - } - - const bool extraData = get_bit(src, offset) == 0; - --*offset; - - if (extraData) - { - pps->transform_8x8_mode_flag = get_bit(src, offset); - pps->pic_scaling_matrix_present_flag = get_bit(src, offset); - if (pps->pic_scaling_matrix_present_flag) - { - //TODO - } - pps->second_chroma_qp_index_offset = decode_s_golomb(src, offset); - } - -#ifdef DEBUG_NAL - DEBUG_INFO("PPS:\n" - "pic_parameter_set_id : %u\n" - "seq_parameter_set_id : %u\n" - "entropy_coding_mode_flag : %u\n" - "pic_order_present_flag : %u\n" - "num_slice_groups_minus1 : %u\n" - "slice_group_map_type : %u\n" - "slice_group_change_direction_flag : %u\n" - "slice_group_change_rate_minus1 : %u\n" - "pic_size_in_map_units_minus1 : %u\n" - "num_ref_idx_l0_active_minus1 : %u\n" - "num_ref_idx_l1_active_minus1 : %u\n" - "weighted_pred_flag : %u\n" - "weighted_bipred_idc : %u\n" - "pic_init_qp_minus26 : %d\n" - "pic_init_qs_minus26 : %d\n" - "chroma_qp_index_offset : %d\n" - "deblocking_filter_control_present_flag: %u\n" - "constrained_intra_pred_flag : %u\n" - "redundant_pic_cnt_present_flag : %u\n" - "transform_8x8_mode_flag : %u\n" - "pic_scaling_matrix_present_flag : %u\n" - "second_chroma_qp_index_offset : %u", - pps->pic_parameter_set_id, - pps->seq_parameter_set_id, - pps->entropy_coding_mode_flag, - pps->pic_order_present_flag, - pps->num_slice_groups_minus1, - pps->slice_group_map_type, - pps->slice_group_change_direction_flag, - pps->slice_group_change_rate_minus1, - pps->pic_size_in_map_units_minus1, - pps->num_ref_idx_l0_active_minus1, - pps->num_ref_idx_l1_active_minus1, - pps->weighted_pred_flag, - pps->weighted_bipred_idc, - pps->pic_init_qp_minus26, - pps->pic_init_qs_minus26, - pps->chroma_qp_index_offset, - pps->deblocking_filter_control_present_flag, - pps->constrained_intra_pred_flag, - pps->redundant_pic_cnt_present_flag, - pps->transform_8x8_mode_flag, - pps->pic_scaling_matrix_present_flag, - pps->second_chroma_qp_index_offset - ); -#endif - - if (!parse_nal_trailing_bits(this, src, size, offset)) - return false; - - this->pps_valid = true; - return true; -} - -static bool parse_nal_ref_pic_list_reordering(NAL this, const uint8_t * src, size_t size, size_t * const offset) -{ - NAL_SLICE * slice = &this->slice; - NAL_RPL_REORDER * rpl = &this->slice.ref_pic_list_reordering; - - if (slice->slice_type != NAL_SLICE_TYPE_I && slice->slice_type != NAL_SLICE_TYPE_SI) - { - rpl->ref_pic_list_reordering_flag_l0 = get_bit(src, offset); - if(rpl->ref_pic_list_reordering_flag_l0) - { - int index = 0; - NAL_RPL_REORDER_L * l; - do - { - if (index > 2) - { - DEBUG_ERROR("too many reorder records"); - return false; - } - - l = &rpl->l0[index++]; - l->valid = true; - l->reordering_of_pic_nums_idc = decode_u_golomb(src, offset); - if (l->reordering_of_pic_nums_idc == 0 || l->reordering_of_pic_nums_idc == 1) - l->abs_diff_pic_num_minus1 = decode_u_golomb(src, offset); - else - if (l->reordering_of_pic_nums_idc == 2) - l->long_term_pic_num = decode_u_golomb(src, offset); - } - while(l->reordering_of_pic_nums_idc != 3); - } - } - - if (slice->slice_type == NAL_SLICE_TYPE_B) - { - rpl->ref_pic_list_reordering_flag_l1 = get_bit(src, offset); - if (rpl->ref_pic_list_reordering_flag_l1) - { - int index = 0; - NAL_RPL_REORDER_L * l; - do - { - if (index > 2) - { - DEBUG_ERROR("too many reorder records"); - return false; - } - - l = &rpl->l1[index++]; - l->valid = true; - l->reordering_of_pic_nums_idc = decode_u_golomb(src, offset); - if (l->reordering_of_pic_nums_idc == 0 || l->reordering_of_pic_nums_idc == 1) - l->abs_diff_pic_num_minus1 = decode_u_golomb(src, offset); - else - if (l->reordering_of_pic_nums_idc == 2) - l->long_term_pic_num = decode_u_golomb(src, offset); - } - while(l->reordering_of_pic_nums_idc != 3); - } - } - - return true; -} - -static bool parse_pred_weight_table(NAL this, const uint8_t * src, size_t size, size_t * const offset) -{ - NAL_SLICE * slice = &this->slice; - NAL_PW_TABLE * tbl = &this->slice.pred_weight_table; - - tbl->luma_log2_weight_denom = decode_u_golomb(src, offset); - if (this->sps.chroma_format_idc != 0) - tbl->chroma_log2_weight_denom = decode_u_golomb(src, offset); - - for(uint32_t i = 0; i <= this->pps.num_ref_idx_l0_active_minus1; ++i) - { - NAL_PW_TABLE_L * l = &tbl->l0[i]; - - tbl->luma_weight_flag[0] = get_bit(src, offset); - if (tbl->luma_weight_flag[0]) - { - l->luma_weight = decode_s_golomb(src, offset); - l->luma_offset = decode_s_golomb(src, offset); - } - - if (this->sps.chroma_format_idc != 0) - { - tbl->chroma_weight_flag[0] = get_bit(src, offset); - if (tbl->chroma_weight_flag[0]) - for(int j = 0; j < 2; ++j) - { - l->chroma_weight[j] = decode_s_golomb(src, offset); - l->chroma_offset[j] = decode_s_golomb(src, offset); - } - } - } - - if (slice->slice_type == NAL_SLICE_TYPE_B) - { - for(uint32_t i = 0; i <= this->pps.num_ref_idx_l1_active_minus1; ++i) - { - NAL_PW_TABLE_L * l = &tbl->l1[i]; - - tbl->luma_weight_flag[1] = get_bit(src, offset); - if (tbl->luma_weight_flag[1]) - { - l->luma_weight = decode_s_golomb(src, offset); - l->luma_offset = decode_s_golomb(src, offset); - } - - if (this->sps.chroma_format_idc != 0) - { - tbl->chroma_weight_flag[1] = get_bit(src, offset); - if (tbl->chroma_weight_flag[1]) - for(int j = 0; j < 2; ++j) - { - l->chroma_weight[j] = decode_s_golomb(src, offset); - l->chroma_offset[j] = decode_s_golomb(src, offset); - } - } - } - } - - return true; -} - -static bool parse_dec_ref_pic_marking( - NAL this, - const uint8_t ref_unit_type, - const uint8_t * src, - size_t size, - size_t * const offset -) -{ - NAL_RP_MARKING * m = &this->slice.dec_ref_pic_marking; - if (ref_unit_type == 5) - { - m->no_output_of_prior_pics_flag = get_bit(src, offset); - m->long_term_reference_flag = get_bit(src, offset); - } - else - { - m->adaptive_ref_pic_marking_mode_flag = get_bit(src, offset); - if (m->adaptive_ref_pic_marking_mode_flag) - { - uint32_t op; - do - { - op = decode_u_golomb(src, offset); - if (op == 1 || op == 3) - m->difference_of_pic_nums_minus1 = decode_u_golomb(src, offset); - - if (op == 2) - m->long_term_pic_num = decode_u_golomb(src, offset); - - if (op == 3 || op == 6) - m->long_term_frame_idx = decode_u_golomb(src, offset); - - if (op == 4) - m->max_long_term_frame_idx_plus1 = decode_u_golomb(src, offset); - - } while (op != 0); - } - } - - return true; -} - -static bool parse_nal_coded_slice( - NAL this, - const uint8_t ref_idc, - const uint8_t ref_unit_type, - const uint8_t * src, - size_t size, - size_t * const offset -) -{ - if (!this->sps_valid || !this->pps_valid) - return false; - - NAL_SLICE * slice = &this->slice; - memset(slice, 0, sizeof(NAL_SLICE)); - - slice->nal_ref_idc = ref_idc; - slice->first_mb_in_slice = decode_u_golomb(src, offset); - slice->slice_type = decode_u_golomb(src, offset); - slice->pic_parameter_set_id = decode_u_golomb(src, offset); - slice->frame_num = get_bits(src, offset, this->sps.log2_max_frame_num_minus4 + 4); - slice->pred_weight_table.l0 = this->slice_pred_weight_table_l0; - slice->pred_weight_table.l1 = this->slice_pred_weight_table_l1; - - if (!this->sps.frame_mbs_only_flag) - { - slice->field_pic_flag = get_bit(src, offset); - if (slice->field_pic_flag) - slice->bottom_field_flag = get_bit(src, offset); - } - - if (ref_unit_type == 5) - slice->idr_pic_id = decode_u_golomb(src, offset); - - if (this->sps.pic_order_cnt_type == 0) - { - slice->pic_order_cnt_lsb = get_bits(src, offset, this->sps.log2_max_pic_order_cnt_lsb_minus4 + 4); - if (this->pps.pic_order_present_flag && !slice->field_pic_flag) - slice->delta_pic_order_cnt_bottom = decode_s_golomb(src, offset); - } - else - if (this->sps.pic_order_cnt_type == 1 && !this->sps.delta_pic_order_always_zero_flag) - { - slice->delta_pic_order_cnt[0] = decode_s_golomb(src, offset); - if (this->pps.pic_order_present_flag && !slice->field_pic_flag) - slice->delta_pic_order_cnt[1] = decode_s_golomb(src, offset); - } - - if (this->pps.redundant_pic_cnt_present_flag) - slice->redundant_pic_cnt = decode_u_golomb(src, offset); - - if (slice->slice_type == NAL_SLICE_TYPE_B) - slice->direct_spatial_mv_pred_flag = get_bit(src, offset); - - if (slice->slice_type == NAL_SLICE_TYPE_P || - slice->slice_type == NAL_SLICE_TYPE_SP || - slice->slice_type == NAL_SLICE_TYPE_B) - { - slice->num_ref_idx_active_override_flag = get_bit(src, offset); - if (slice->num_ref_idx_active_override_flag) - { - slice->num_ref_idx_l0_active_minus1 = decode_u_golomb(src, offset); - if (slice->slice_type == NAL_SLICE_TYPE_B) - slice->num_ref_idx_l1_active_minus1 = decode_u_golomb(src, offset); - } - } - - if (!parse_nal_ref_pic_list_reordering(this, src, size, offset)) - return false; - - if ((this->pps.weighted_pred_flag && (slice->slice_type == NAL_SLICE_TYPE_P || slice->slice_type == NAL_SLICE_TYPE_SP)) || - (this->pps.weighted_bipred_idc == 1 && slice->slice_type == NAL_SLICE_TYPE_B)) - { - if (!parse_pred_weight_table(this, src, size, offset)) - return false; - } - - if (ref_idc != 0) - if (!parse_dec_ref_pic_marking(this, ref_unit_type, src, size, offset)) - return false; - - if (this->pps.entropy_coding_mode_flag && slice->slice_type != NAL_SLICE_TYPE_I && slice->slice_type != NAL_SLICE_TYPE_SI) - slice->cabac_init_idc = decode_u_golomb(src, offset); - - slice->slice_qp_delta = decode_s_golomb(src, offset); - - if (slice->slice_type == NAL_SLICE_TYPE_SP || slice->slice_type == NAL_SLICE_TYPE_SI) - { - if (slice->slice_type == NAL_SLICE_TYPE_SP) - slice->sp_for_switch_flag = get_bit(src, offset); - slice->slice_qs_delta = decode_s_golomb(src, offset); - } - - if (this->pps.deblocking_filter_control_present_flag) - { - slice->disable_deblocking_filter_idc = decode_u_golomb(src, offset); - if (slice->disable_deblocking_filter_idc != 1) - { - slice->slice_alpha_c0_offset_div2 = decode_s_golomb(src, offset); - slice->slice_beta_offset_div2 = decode_s_golomb(src, offset); - } - } - - if (this->pps.num_slice_groups_minus1 > 0 && this->pps.slice_group_map_type >= 3 && this->pps.slice_group_map_type <= 5) - slice->slice_group_change_cycle = decode_u_golomb(src, offset); - -#ifdef DEBUG_NAL - DEBUG_INFO("SLICE:\n" - "first_mb_in_slice : %u\n" - "slice_type : %u\n" - "pic_parameter_set_id : %u\n" - "frame_num : %u\n" - "field_pic_flag : %u\n" - "bottom_field_flag : %u\n" - "idr_pic_id : %u\n" - "pic_order_cnt_lsb : %u\n" - "delta_pic_order_cnt_bottom : %d\n" - "delta_pic_order_cnt[0] : %d\n" - "delta_pic_order_cnt[1] : %d\n" - "redundant_pic_cnt : %u\n" - "direct_spatial_mv_pred_flag : %u\n" - "num_ref_idx_active_override_flag: %u\n" - "num_ref_idx_l0_active_minus1 : %u\n" - "num_ref_idx_l1_active_minus1 : %u", - slice->first_mb_in_slice, - slice->slice_type, - slice->pic_parameter_set_id, - slice->frame_num, - slice->field_pic_flag, - slice->bottom_field_flag, - slice->idr_pic_id, - slice->pic_order_cnt_lsb, - slice->delta_pic_order_cnt_bottom, - slice->delta_pic_order_cnt[0], - slice->delta_pic_order_cnt[1], - slice->redundant_pic_cnt, - slice->direct_spatial_mv_pred_flag, - slice->num_ref_idx_active_override_flag, - slice->num_ref_idx_l0_active_minus1, - slice->num_ref_idx_l1_active_minus1 - ); -#endif - - if (!parse_nal_trailing_bits(this, src, size, offset)) - return false; - - this->slice_valid = true; - return true; -} - -bool nal_parse(NAL this, const uint8_t * src, size_t size, size_t * seek) -{ -#ifdef DEBUG_NAL - static FILE * fd = NULL; - if (!fd) - fd = fopen("/tmp/stream.h264", "w"); - fwrite(src, size, 1, fd); - fflush(fd); -#endif - - *seek = 0; - for(size_t i = 0; i < size - 4; ++i) - { - if (src[i++] != 0 || src[i++] != 0) - break; - - if (src[i] == 0) - ++i; - - if (src[i++] != 1) - break; - - size_t offset = i << 3; -#ifdef DEBUG_NAL - DEBUG_INFO("nal @ %lu (%lu)", *seek, offset); -#endif - - // ensure the forbidden zero bit is not set - if (get_bit(src, &offset) != 0) - { - DEBUG_ERROR("forbidden_zero_bit is set"); - return false; - } - - uint8_t ref_idc = get_bits(src, &offset, 2); - uint8_t ref_unit_type = get_bits(src, &offset, 5); - DEBUG_INFO("ref idc: %d, ref unit type: %d", ref_idc, ref_unit_type); - - switch(ref_unit_type) - { - case NAL_TYPE_CODED_SLICE_IDR: - case NAL_TYPE_CODED_SLICE_NON_IDR: - case NAL_TYPE_CODED_SLICE_AUX: - if (!parse_nal_coded_slice(this, ref_idc, ref_unit_type, src, size, &offset)) - return false; - break; - - case NAL_TYPE_AUD: - { - this->primary_pic_type = get_bits(src, &offset, 3); - this->primary_pic_type_valid = true; - if (!parse_nal_trailing_bits(this, src, size, &offset)) - return false; - break; - } - - case NAL_TYPE_SPS: - if (!parse_nal_sps(this, src, size, &offset)) - return false; - break; - - case NAL_TYPE_PPS: - if (!parse_nal_pps(this, src, size, &offset)) - return false; - break; - - default: - DEBUG_ERROR("Unknown NAL ref unit type: %d", ref_unit_type); - return false; - } - - i = offset >> 3; - *seek = i; - } - - return true; -} - -bool nal_get_sps(NAL this, const NAL_SPS ** sps) -{ - if (!this->sps_valid) - return false; - *sps = &this->sps; - return true; -} - -bool nal_get_primary_picture_type(NAL this, uint8_t * pic_type) -{ - if (!this->primary_pic_type_valid) - return false; - *pic_type = this->primary_pic_type; - return true; -} - -bool nal_get_pps(NAL this, const NAL_PPS ** pps) -{ - if (!this->pps_valid) - return false; - - *pps = &this->pps; - return true; -} - -bool nal_get_slice(NAL this, const NAL_SLICE ** slice) -{ - if (!this->slice_valid) - return false; - - *slice = &this->slice; - return true; -} \ No newline at end of file diff --git a/client/parsers/nal.h b/client/parsers/nal.h deleted file mode 100644 index 994d9f8c..00000000 --- a/client/parsers/nal.h +++ /dev/null @@ -1,305 +0,0 @@ -/* -Looking Glass - KVM FrameRelay (KVMFR) Client -Copyright (C) 2017-2019 Geoffrey McRae -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 -#include -#include - -#define NAL_TYPE_CODED_SLICE_NON_IDR 1 -#define NAL_TYPE_CODED_SLICE_DATA_PARTITION_A 2 -#define NAL_TYPE_CODED_SLICE_DATA_PARTITION_B 3 -#define NAL_TYPE_CODED_SLICE_DATA_PARTITION_C 4 -#define NAL_TYPE_CODED_SLICE_IDR 5 -#define NAL_TYPE_SPS 7 -#define NAL_TYPE_PPS 8 -#define NAL_TYPE_AUD 9 -#define NAL_TYPE_END_OF_SEQUENCE 10 -#define NAL_TYPE_END_OF_STREAM 11 -#define NAL_TYPE_CODED_SLICE_AUX 19 - -#define IDC_PROFILE_BASELINE 66 -#define IDC_PROFILE_MAIN 77 -#define IDC_PROFILE_EXTENDED 88 -#define IDC_PROFILE_HP 100 -#define IDC_PROFILE_Hi10P 110 -#define IDC_PROFILE_Hi422 122 -#define IDC_PROFILE_Hi444 244 -#define IDC_PROFILE_CAVLC444 44 - -#define IDC_CHROMA_FORMAT_YUV400 0 -#define IDC_CHROMA_FORMAT_YUV420 1 -#define IDC_CHROMA_FORMAT_YVU422 2 -#define IDC_CHROMA_FORMAT_YUV444 3 - -#define IDC_VUI_ASPECT_RATIO_EXTENDED_SAR 0xFF - -#define NAL_PICTURE_TYPE_I 0 -#define NAL_PICTURE_TYPE_P 1 -#define NAL_PICTURE_TYPE_B 2 - -#define NAL_SLICE_TYPE_P 0 -#define NAL_SLICE_TYPE_B 1 -#define NAL_SLICE_TYPE_I 2 -#define NAL_SLICE_TYPE_SP 3 -#define NAL_SLICE_TYPE_SI 4 - -typedef struct NAL_SPS -{ - uint8_t profile_idc; - uint8_t constraint_set_flags[3]; - uint8_t level_idc; - uint32_t seq_parameter_set_id; - uint32_t chroma_format_idc; - uint8_t seperate_colour_plane_flag; - uint32_t bit_depth_luma_minus8; - uint32_t bit_depth_chroma_minus8; - uint8_t lossless_qpprime_y_zero_flag; - uint8_t seq_scaling_matrix_present_flag; - uint8_t seq_scaling_list_present_flag[12]; - uint32_t log2_max_frame_num_minus4; - uint32_t pic_order_cnt_type; - uint32_t log2_max_pic_order_cnt_lsb_minus4; - uint8_t delta_pic_order_always_zero_flag; - int32_t offset_for_non_ref_pic; - int32_t offset_for_top_to_bottom_field; - uint32_t num_ref_frames_in_pic_order_cnt_cycle; - int32_t * offset_for_ref_frame; - uint32_t num_ref_frames; - uint8_t gaps_in_frame_num_value_allowed_flag; - uint32_t pic_width_in_mbs_minus1; - uint32_t pic_height_in_map_units_minus1; - uint8_t frame_mbs_only_flag; - uint8_t mb_adaptive_frame_field_flag; - uint8_t direct_8x8_inference_flag; - uint8_t frame_cropping_flag; - uint32_t frame_crop_left_offset; - uint32_t frame_crop_right_offset; - uint32_t frame_crop_top_offset; - uint32_t frame_crop_bottom_offset; - uint8_t vui_parameters_present_flag; -} -NAL_SPS; - -typedef struct NAL_CPB -{ - uint32_t bit_rate_value_minus1; - uint32_t cpb_size_value_minus1; - uint8_t cbr_flag; -} -NAL_CPB; - -typedef struct NAL_HRD -{ - uint32_t cpb_cnt_minus1; - uint8_t bit_rate_scale; - uint8_t cpb_size_scale; - uint8_t cpb_size_count; - NAL_CPB * cpb; - uint8_t initial_cpb_removal_delay_length_minus1; - uint8_t cpb_removal_delay_length_minus1; - uint8_t dpb_output_delay_length_minus1; - uint8_t time_offset_length; -} -NAL_HRD; - -typedef struct NAL_VUI -{ - uint8_t aspect_ratio_info_present_flag; - uint8_t aspect_ratio_idc; - uint16_t sar_width; - uint16_t sar_height; - uint8_t overscan_info_present_flag; - uint8_t overscan_appropriate_flag; - uint8_t video_signal_type_present_flag; - uint8_t video_format; - uint8_t video_full_range_flag; - uint8_t colour_description_present_flag; - uint8_t colour_primaries; - uint8_t transfer_characteristics; - uint8_t matrix_coefficients; - uint8_t chroma_loc_info_present_flag; - uint32_t chroma_sample_loc_type_top_field; - uint32_t chroma_sample_loc_type_bottom_field; - uint8_t timing_info_present_flag; - uint32_t num_units_in_tick; - uint32_t time_scale; - uint8_t fixed_frame_rate_flag; - uint8_t nal_hrd_parameters_present_flag; - NAL_HRD nal_hrd_parameters; - uint8_t vcl_hrd_parameters_present_flag; - NAL_HRD vcl_hrd_parameters; - uint8_t low_delay_hrd_flag; - uint8_t pic_struct_present_flag; - uint8_t bitstream_restriction_flag; - uint8_t motion_vectors_over_pic_boundaries_flag; - uint32_t max_bytes_per_pic_denom; - uint32_t max_bits_per_mb_denom; - uint32_t log2_max_mv_length_horizontal; - uint32_t log2_max_mv_length_vertical; - uint32_t num_reorder_frames; - uint32_t max_dec_frame_buffering; -} -NAL_VUI; - -typedef struct NAL_SLICE_GROUP_T0 -{ - uint32_t run_length_minus1; -} -NAL_SLICE_GROUP_T0; - -typedef struct NAL_SLICE_GROUP_T2 -{ - uint32_t top_left; - uint32_t bottom_right; -} -NAL_SLICE_GROUP_T2; - -typedef union NAL_SLICE_GROUP -{ - NAL_SLICE_GROUP_T0 t0; - NAL_SLICE_GROUP_T2 t2; -} -NAL_SLICE_GROUP; - -typedef struct NAL_PPS -{ - uint32_t pic_parameter_set_id; - uint32_t seq_parameter_set_id; - uint8_t entropy_coding_mode_flag; - uint8_t pic_order_present_flag; - uint32_t num_slice_groups_minus1; - NAL_SLICE_GROUP * slice_groups; - uint32_t slice_group_map_type; - uint8_t slice_group_change_direction_flag; - uint32_t slice_group_change_rate_minus1; - uint32_t pic_size_in_map_units_minus1; - uint32_t * slice_group_id; - uint32_t num_ref_idx_l0_active_minus1; - uint32_t num_ref_idx_l1_active_minus1; - uint8_t weighted_pred_flag; - uint8_t weighted_bipred_idc; - int32_t pic_init_qp_minus26; - int32_t pic_init_qs_minus26; - int32_t chroma_qp_index_offset; - uint8_t deblocking_filter_control_present_flag; - uint8_t constrained_intra_pred_flag; - uint8_t redundant_pic_cnt_present_flag; - - uint8_t transform_8x8_mode_flag; - uint8_t pic_scaling_matrix_present_flag; - uint8_t pic_scaling_list_present_flag[6]; - int32_t scaling_list_4x4[6]; - int32_t scaling_list_8x8[2]; - int32_t second_chroma_qp_index_offset; -} -NAL_PPS; - -typedef struct NAL_RPL_REORDER_L -{ - bool valid; - uint32_t reordering_of_pic_nums_idc; - uint32_t abs_diff_pic_num_minus1; - uint32_t long_term_pic_num; -} -NAL_RPL_REORDER_L; - -typedef struct NAL_RPL_REORDER -{ - uint8_t ref_pic_list_reordering_flag_l0; - NAL_RPL_REORDER_L l0[3]; - uint8_t ref_pic_list_reordering_flag_l1; - NAL_RPL_REORDER_L l1[3]; -} -NAL_RPL_REORDER; - -typedef struct NAL_PW_TABLE_L -{ - int32_t luma_weight; - int32_t luma_offset; - int32_t chroma_weight[2]; - int32_t chroma_offset[2]; -} -NAL_PW_TABLE_L; - -typedef struct NAL_PW_TABLE -{ - uint32_t luma_log2_weight_denom; - uint32_t chroma_log2_weight_denom; - uint8_t luma_weight_flag[2]; - uint8_t chroma_weight_flag[2]; - NAL_PW_TABLE_L * l0; - NAL_PW_TABLE_L * l1; -} -NAL_PW_TABLE; - -typedef struct NAL_RP_MARKING -{ - uint8_t no_output_of_prior_pics_flag; - uint8_t long_term_reference_flag; - uint8_t adaptive_ref_pic_marking_mode_flag; - uint32_t memory_management_control_operation; - uint32_t difference_of_pic_nums_minus1; - uint32_t long_term_pic_num; - uint32_t long_term_frame_idx; - uint32_t max_long_term_frame_idx_plus1; -} -NAL_RP_MARKING; - -typedef struct NAL_SLICE -{ - uint8_t nal_ref_idc; - uint32_t first_mb_in_slice; - uint32_t slice_type; - uint32_t pic_parameter_set_id; - uint32_t frame_num; - uint8_t field_pic_flag; - uint8_t bottom_field_flag; - uint32_t idr_pic_id; - uint32_t pic_order_cnt_lsb; - int32_t delta_pic_order_cnt_bottom; - int32_t delta_pic_order_cnt[2]; - uint32_t redundant_pic_cnt; - uint8_t direct_spatial_mv_pred_flag; - uint8_t num_ref_idx_active_override_flag; - uint32_t num_ref_idx_l0_active_minus1; - uint32_t num_ref_idx_l1_active_minus1; - NAL_RPL_REORDER ref_pic_list_reordering; - NAL_PW_TABLE pred_weight_table; - NAL_RP_MARKING dec_ref_pic_marking; - uint32_t cabac_init_idc; - int32_t slice_qp_delta; - uint8_t sp_for_switch_flag; - int32_t slice_qs_delta; - uint32_t disable_deblocking_filter_idc; - int32_t slice_alpha_c0_offset_div2; - int32_t slice_beta_offset_div2; - uint32_t slice_group_change_cycle; -} -NAL_SLICE; - -typedef struct NAL * NAL; - -bool nal_initialize (NAL * ptr); -void nal_deinitialize(NAL this ); -bool nal_parse (NAL this, const uint8_t * src, size_t size, size_t * seek); - -bool nal_get_primary_picture_type(NAL this, uint8_t * pic_type); -bool nal_get_sps (NAL this, const NAL_SPS ** sps ); -bool nal_get_pps (NAL this, const NAL_PPS ** pps ); -bool nal_get_slice(NAL this, const NAL_SLICE ** slice); \ No newline at end of file diff --git a/client/renderers/OpenGL/CMakeLists.txt b/client/renderers/OpenGL/CMakeLists.txt index f1dda0af..16f0c137 100644 --- a/client/renderers/OpenGL/CMakeLists.txt +++ b/client/renderers/OpenGL/CMakeLists.txt @@ -14,7 +14,6 @@ add_library(renderer_OpenGL STATIC target_link_libraries(renderer_OpenGL ${RENDERER_OPENGL_PKGCONFIG_LIBRARIES} lg_common - decoders fonts )