mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 12:33:27 +02:00
Merge branch 'master' of mini:hifi
This commit is contained in:
commit
dc19a1c5cf
53 changed files with 4136 additions and 299 deletions
|
@ -117,6 +117,7 @@ int main(int argc, const char* argv[]) {
|
|||
|
||||
break;
|
||||
case PACKET_TYPE_AVATAR_VOXEL_URL:
|
||||
case PACKET_TYPE_AVATAR_FACE_VIDEO:
|
||||
// grab the node ID from the packet
|
||||
unpackNodeId(packetData + numBytesForPacketHeader(packetData), &nodeID);
|
||||
|
||||
|
|
46
cmake/modules/FindLibVPX.cmake
Normal file
46
cmake/modules/FindLibVPX.cmake
Normal file
|
@ -0,0 +1,46 @@
|
|||
# - Try to find the LibVPX library to perform VP8 video encoding/decoding
|
||||
#
|
||||
# You must provide a LIBVPX_ROOT_DIR which contains lib and include directories
|
||||
#
|
||||
# Once done this will define
|
||||
#
|
||||
# LIBVPX_FOUND - system found LibVPX
|
||||
# LIBVPX_INCLUDE_DIRS - the LibVPX include directory
|
||||
# LIBVPX_LIBRARIES - Link this to use LibVPX
|
||||
#
|
||||
# Created on 7/17/2013 by Andrzej Kapolka
|
||||
# Copyright (c) 2013 High Fidelity
|
||||
#
|
||||
|
||||
if (LIBVPX_LIBRARIES AND LIBVPX_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(LIBVPX_FOUND TRUE)
|
||||
else (LIBVPX_LIBRARIES AND LIBVPX_INCLUDE_DIRS)
|
||||
find_path(LIBVPX_INCLUDE_DIRS vpx_codec.h ${LIBVPX_ROOT_DIR}/include)
|
||||
|
||||
if (APPLE)
|
||||
find_library(LIBVPX_LIBRARIES libvpx.a ${LIBVPX_ROOT_DIR}/lib/MacOS/)
|
||||
elseif (UNIX)
|
||||
find_library(LIBVPX_LIBRARIES libvpx.a ${LIBVPX_ROOT_DIR}/lib/UNIX/)
|
||||
elseif (WIN32)
|
||||
find_library(LIBVPX_LIBRARIES libvpx.lib ${LIBVPX_ROOT_DIR}/lib/Win32/)
|
||||
endif ()
|
||||
|
||||
if (LIBVPX_INCLUDE_DIRS AND LIBVPX_LIBRARIES)
|
||||
set(LIBVPX_FOUND TRUE)
|
||||
endif (LIBVPX_INCLUDE_DIRS AND LIBVPX_LIBRARIES)
|
||||
|
||||
if (LIBVPX_FOUND)
|
||||
if (NOT LibVPX_FIND_QUIETLY)
|
||||
message(STATUS "Found LibVPX: ${LIBVPX_LIBRARIES}")
|
||||
endif (NOT LibVPX_FIND_QUIETLY)
|
||||
else (LIBVPX_FOUND)
|
||||
if (LibVPX_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find LibVPX")
|
||||
endif (LibVPX_FIND_REQUIRED)
|
||||
endif (LIBVPX_FOUND)
|
||||
|
||||
# show the LIBVPX_INCLUDE_DIRS and LIBVPX_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(LIBVPX_INCLUDE_DIRS LIBVPX_LIBRARIES)
|
||||
|
||||
endif (LIBVPX_LIBRARIES AND LIBVPX_INCLUDE_DIRS)
|
|
@ -9,6 +9,7 @@ project(${TARGET_NAME})
|
|||
# setup for find modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
||||
set(LIBOVR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/LibOVR)
|
||||
set(LIBVPX_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/LibVPX)
|
||||
set(LEAP_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/Leap)
|
||||
set(MOTIONDRIVER_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/MotionDriver)
|
||||
set(PORTAUDIO_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/PortAudio)
|
||||
|
@ -36,7 +37,7 @@ configure_file(InterfaceConfig.h.in ${PROJECT_BINARY_DIR}/includes/InterfaceConf
|
|||
|
||||
# grab the implementation and header files from src dirs
|
||||
file(GLOB INTERFACE_SRCS src/*.cpp src/*.h)
|
||||
foreach(SUBDIR ui renderer)
|
||||
foreach(SUBDIR avatar ui renderer)
|
||||
file(GLOB SUBDIR_SRCS src/${SUBDIR}/*.cpp src/${SUBDIR}/*.h)
|
||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} ${SUBDIR_SRCS})
|
||||
endforeach(SUBDIR)
|
||||
|
@ -75,7 +76,8 @@ add_subdirectory(external/fervor/)
|
|||
include_directories(external/fervor/)
|
||||
|
||||
# run qt moc on qt-enabled headers
|
||||
qt4_wrap_cpp(INTERFACE_SRCS src/Application.h src/AvatarVoxelSystem.h src/Webcam.h src/ui/BandwidthDialog.h)
|
||||
qt4_wrap_cpp(INTERFACE_SRCS src/Application.h src/Webcam.h src/avatar/AvatarVoxelSystem.h
|
||||
src/avatar/Face.h src/ui/BandwidthDialog.h)
|
||||
|
||||
# create the executable, make it a bundle on OS X
|
||||
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS})
|
||||
|
@ -92,6 +94,7 @@ link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})
|
|||
# find required libraries
|
||||
find_package(GLM REQUIRED)
|
||||
find_package(LibOVR)
|
||||
find_package(LibVPX)
|
||||
find_package(Leap)
|
||||
find_package(MotionDriver)
|
||||
find_package(OpenCV)
|
||||
|
@ -119,6 +122,7 @@ include_directories(
|
|||
SYSTEM
|
||||
${GLM_INCLUDE_DIRS}
|
||||
${LIBOVR_INCLUDE_DIRS}
|
||||
${LIBVPX_INCLUDE_DIRS}
|
||||
${LEAP_INCLUDE_DIRS}
|
||||
${MOTIONDRIVER_INCLUDE_DIRS}
|
||||
${OPENCV_INCLUDE_DIRS}
|
||||
|
@ -128,6 +132,7 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${OPENCV_INCLUDE_DIRS}")
|
|||
target_link_libraries(
|
||||
${TARGET_NAME}
|
||||
${QT_LIBRARIES}
|
||||
${LIBVPX_LIBRARIES}
|
||||
${MOTIONDRIVER_LIBRARIES}
|
||||
${OPENCV_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
|
|
65
interface/external/LibVPX/AUTHORS
vendored
Normal file
65
interface/external/LibVPX/AUTHORS
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
# This file is automatically generated from the git commit history
|
||||
# by tools/gen_authors.sh.
|
||||
|
||||
Aaron Watry <awatry@gmail.com>
|
||||
Adrian Grange <agrange@google.com>
|
||||
Alex Converse <alex.converse@gmail.com>
|
||||
Alexis Ballier <aballier@gentoo.org>
|
||||
Alok Ahuja <waveletcoeff@gmail.com>
|
||||
Alpha Lam <hclam@google.com>
|
||||
Andoni Morales Alastruey <ylatuya@gmail.com>
|
||||
Andres Mejia <mcitadel@gmail.com>
|
||||
Aron Rosenberg <arosenberg@logitech.com>
|
||||
Attila Nagy <attilanagy@google.com>
|
||||
Deb Mukherjee <debargha@google.com>
|
||||
Fabio Pedretti <fabio.ped@libero.it>
|
||||
Frank Galligan <fgalligan@google.com>
|
||||
Fredrik Söderquist <fs@opera.com>
|
||||
Fritz Koenig <frkoenig@google.com>
|
||||
Gaute Strokkenes <gaute.strokkenes@broadcom.com>
|
||||
Giuseppe Scrivano <gscrivano@gnu.org>
|
||||
Guillermo Ballester Valor <gbvalor@gmail.com>
|
||||
Henrik Lundin <hlundin@google.com>
|
||||
James Berry <jamesberry@google.com>
|
||||
James Zern <jzern@google.com>
|
||||
Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
Jeff Faust <jfaust@google.com>
|
||||
Jeff Muizelaar <jmuizelaar@mozilla.com>
|
||||
Jim Bankoski <jimbankoski@google.com>
|
||||
Johann Koenig <johannkoenig@google.com>
|
||||
John Koleszar <jkoleszar@google.com>
|
||||
Joshua Bleecher Snyder <josh@treelinelabs.com>
|
||||
Justin Clift <justin@salasaga.org>
|
||||
Justin Lebar <justin.lebar@gmail.com>
|
||||
KO Myung-Hun <komh@chollian.net>
|
||||
Lou Quillio <louquillio@google.com>
|
||||
Luca Barbato <lu_zero@gentoo.org>
|
||||
Makoto Kato <makoto.kt@gmail.com>
|
||||
Marco Paniconi <marpan@google.com>
|
||||
Martin Ettl <ettl.martin78@googlemail.com>
|
||||
Michael Kohler <michaelkohler@live.com>
|
||||
Mike Hommey <mhommey@mozilla.com>
|
||||
Mikhal Shemer <mikhal@google.com>
|
||||
Pascal Massimino <pascal.massimino@gmail.com>
|
||||
Patrik Westin <patrik.westin@gmail.com>
|
||||
Paul Wilkins <paulwilkins@google.com>
|
||||
Pavol Rusnak <stick@gk2.sk>
|
||||
Philip Jägenstedt <philipj@opera.com>
|
||||
Priit Laes <plaes@plaes.org>
|
||||
Rafael Ávila de Espíndola <rafael.espindola@gmail.com>
|
||||
Rafaël Carré <funman@videolan.org>
|
||||
Ralph Giles <giles@xiph.org>
|
||||
Ronald S. Bultje <rbultje@google.com>
|
||||
Scott LaVarnway <slavarnway@google.com>
|
||||
Stefan Holmer <holmer@google.com>
|
||||
Taekhyun Kim <takim@nvidia.com>
|
||||
Takanori MATSUURA <t.matsuu@gmail.com>
|
||||
Tero Rintaluoma <teror@google.com>
|
||||
Thijs Vermeir <thijsvermeir@gmail.com>
|
||||
Timothy B. Terriberry <tterribe@xiph.org>
|
||||
Tom Finegan <tomfinegan@google.com>
|
||||
Yaowu Xu <yaowu@google.com>
|
||||
Yunqing Wang <yunqingwang@google.com>
|
||||
Google Inc.
|
||||
The Mozilla Foundation
|
||||
The Xiph.Org Foundation
|
31
interface/external/LibVPX/LICENSE
vendored
Normal file
31
interface/external/LibVPX/LICENSE
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
Copyright (c) 2010, The WebM Project authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of Google, nor the WebM Project, nor the names
|
||||
of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
22
interface/external/LibVPX/PATENTS
vendored
Normal file
22
interface/external/LibVPX/PATENTS
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
Additional IP Rights Grant (Patents)
|
||||
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the WebM Project.
|
||||
|
||||
Google hereby grants to you a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||
patent license to make, have made, use, offer to sell, sell, import,
|
||||
transfer, and otherwise run, modify and propagate the contents of this
|
||||
implementation of VP8, where such license applies only to those patent
|
||||
claims, both currently owned by Google and acquired in the future,
|
||||
licensable by Google that are necessarily infringed by this
|
||||
implementation of VP8. This grant does not include claims that would be
|
||||
infringed only as a consequence of further modification of this
|
||||
implementation. If you or your agent or exclusive licensee institute or
|
||||
order or agree to the institution of patent litigation against any
|
||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that this implementation of VP8 or any code incorporated within this
|
||||
implementation of VP8 constitutes direct or contributory patent
|
||||
infringement, or inducement of patent infringement, then any patent
|
||||
rights granted to you under this License for this implementation of VP8
|
||||
shall terminate as of the date such litigation is filed.
|
129
interface/external/LibVPX/include/vp8.h
vendored
Normal file
129
interface/external/LibVPX/include/vp8.h
vendored
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
/*!\defgroup vp8 VP8
|
||||
* \ingroup codecs
|
||||
* VP8 is vpx's newest video compression algorithm that uses motion
|
||||
* compensated prediction, Discrete Cosine Transform (DCT) coding of the
|
||||
* prediction error signal and context dependent entropy coding techniques
|
||||
* based on arithmetic principles. It features:
|
||||
* - YUV 4:2:0 image format
|
||||
* - Macro-block based coding (16x16 luma plus two 8x8 chroma)
|
||||
* - 1/4 (1/8) pixel accuracy motion compensated prediction
|
||||
* - 4x4 DCT transform
|
||||
* - 128 level linear quantizer
|
||||
* - In loop deblocking filter
|
||||
* - Context-based entropy coding
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
/*!\file
|
||||
* \brief Provides controls common to both the VP8 encoder and decoder.
|
||||
*/
|
||||
#ifndef VP8_H
|
||||
#define VP8_H
|
||||
#include "vpx_codec_impl_top.h"
|
||||
|
||||
/*!\brief Control functions
|
||||
*
|
||||
* The set of macros define the control functions of VP8 interface
|
||||
*/
|
||||
enum vp8_com_control_id {
|
||||
VP8_SET_REFERENCE = 1, /**< pass in an external frame into decoder to be used as reference frame */
|
||||
VP8_COPY_REFERENCE = 2, /**< get a copy of reference frame from the decoder */
|
||||
VP8_SET_POSTPROC = 3, /**< set the decoder's post processing settings */
|
||||
VP8_SET_DBG_COLOR_REF_FRAME = 4, /**< set the reference frames to color for each macroblock */
|
||||
VP8_SET_DBG_COLOR_MB_MODES = 5, /**< set which macro block modes to color */
|
||||
VP8_SET_DBG_COLOR_B_MODES = 6, /**< set which blocks modes to color */
|
||||
VP8_SET_DBG_DISPLAY_MV = 7, /**< set which motion vector modes to draw */
|
||||
|
||||
/* TODO(jkoleszar): The encoder incorrectly reuses some of these values (5+)
|
||||
* for its control ids. These should be migrated to something like the
|
||||
* VP8_DECODER_CTRL_ID_START range next time we're ready to break the ABI.
|
||||
*/
|
||||
VP9_GET_REFERENCE = 128, /**< get a pointer to a reference frame */
|
||||
VP8_COMMON_CTRL_ID_MAX,
|
||||
VP8_DECODER_CTRL_ID_START = 256
|
||||
};
|
||||
|
||||
/*!\brief post process flags
|
||||
*
|
||||
* The set of macros define VP8 decoder post processing flags
|
||||
*/
|
||||
enum vp8_postproc_level {
|
||||
VP8_NOFILTERING = 0,
|
||||
VP8_DEBLOCK = 1 << 0,
|
||||
VP8_DEMACROBLOCK = 1 << 1,
|
||||
VP8_ADDNOISE = 1 << 2,
|
||||
VP8_DEBUG_TXT_FRAME_INFO = 1 << 3, /**< print frame information */
|
||||
VP8_DEBUG_TXT_MBLK_MODES = 1 << 4, /**< print macro block modes over each macro block */
|
||||
VP8_DEBUG_TXT_DC_DIFF = 1 << 5, /**< print dc diff for each macro block */
|
||||
VP8_DEBUG_TXT_RATE_INFO = 1 << 6, /**< print video rate info (encoder only) */
|
||||
VP8_MFQE = 1 << 10
|
||||
};
|
||||
|
||||
/*!\brief post process flags
|
||||
*
|
||||
* This define a structure that describe the post processing settings. For
|
||||
* the best objective measure (using the PSNR metric) set post_proc_flag
|
||||
* to VP8_DEBLOCK and deblocking_level to 1.
|
||||
*/
|
||||
|
||||
typedef struct vp8_postproc_cfg {
|
||||
int post_proc_flag; /**< the types of post processing to be done, should be combination of "vp8_postproc_level" */
|
||||
int deblocking_level; /**< the strength of deblocking, valid range [0, 16] */
|
||||
int noise_level; /**< the strength of additive noise, valid range [0, 16] */
|
||||
} vp8_postproc_cfg_t;
|
||||
|
||||
/*!\brief reference frame type
|
||||
*
|
||||
* The set of macros define the type of VP8 reference frames
|
||||
*/
|
||||
typedef enum vpx_ref_frame_type {
|
||||
VP8_LAST_FRAME = 1,
|
||||
VP8_GOLD_FRAME = 2,
|
||||
VP8_ALTR_FRAME = 4
|
||||
} vpx_ref_frame_type_t;
|
||||
|
||||
/*!\brief reference frame data struct
|
||||
*
|
||||
* define the data struct to access vp8 reference frames
|
||||
*/
|
||||
|
||||
typedef struct vpx_ref_frame {
|
||||
vpx_ref_frame_type_t frame_type; /**< which reference frame */
|
||||
vpx_image_t img; /**< reference frame data in image format */
|
||||
} vpx_ref_frame_t;
|
||||
|
||||
typedef struct vp9_ref_frame {
|
||||
int idx; /**< frame index to get (input) */
|
||||
vpx_image_t img; /**< img structure to populate (output) */
|
||||
} vp9_ref_frame_t;
|
||||
|
||||
/*!\brief vp8 decoder control function parameter type
|
||||
*
|
||||
* defines the data type for each of VP8 decoder control function requires
|
||||
*/
|
||||
|
||||
VPX_CTRL_USE_TYPE(VP8_SET_REFERENCE, vpx_ref_frame_t *)
|
||||
VPX_CTRL_USE_TYPE(VP8_COPY_REFERENCE, vpx_ref_frame_t *)
|
||||
VPX_CTRL_USE_TYPE(VP8_SET_POSTPROC, vp8_postproc_cfg_t *)
|
||||
VPX_CTRL_USE_TYPE(VP8_SET_DBG_COLOR_REF_FRAME, int)
|
||||
VPX_CTRL_USE_TYPE(VP8_SET_DBG_COLOR_MB_MODES, int)
|
||||
VPX_CTRL_USE_TYPE(VP8_SET_DBG_COLOR_B_MODES, int)
|
||||
VPX_CTRL_USE_TYPE(VP8_SET_DBG_DISPLAY_MV, int)
|
||||
VPX_CTRL_USE_TYPE(VP9_GET_REFERENCE, vp9_ref_frame_t *)
|
||||
|
||||
|
||||
/*! @} - end defgroup vp8 */
|
||||
|
||||
#include "vpx_codec_impl_bottom.h"
|
||||
#endif
|
321
interface/external/LibVPX/include/vp8cx.h
vendored
Normal file
321
interface/external/LibVPX/include/vp8cx.h
vendored
Normal file
|
@ -0,0 +1,321 @@
|
|||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
/*!\defgroup vp8_encoder WebM VP8 Encoder
|
||||
* \ingroup vp8
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#include "vp8.h"
|
||||
|
||||
/*!\file
|
||||
* \brief Provides definitions for using the VP8 encoder algorithm within the
|
||||
* vpx Codec Interface.
|
||||
*/
|
||||
#ifndef VP8CX_H
|
||||
#define VP8CX_H
|
||||
#include "vpx_codec_impl_top.h"
|
||||
|
||||
/*!\name Algorithm interface for VP8
|
||||
*
|
||||
* This interface provides the capability to encode raw VP8 streams, as would
|
||||
* be found in AVI files.
|
||||
* @{
|
||||
*/
|
||||
extern vpx_codec_iface_t vpx_codec_vp8_cx_algo;
|
||||
extern vpx_codec_iface_t *vpx_codec_vp8_cx(void);
|
||||
|
||||
/* TODO(jkoleszar): These move to VP9 in a later patch set. */
|
||||
extern vpx_codec_iface_t vpx_codec_vp9_cx_algo;
|
||||
extern vpx_codec_iface_t *vpx_codec_vp9_cx(void);
|
||||
extern vpx_codec_iface_t vpx_codec_vp9x_cx_algo;
|
||||
extern vpx_codec_iface_t *vpx_codec_vp9x_cx(void);
|
||||
|
||||
/*!@} - end algorithm interface member group*/
|
||||
|
||||
|
||||
/*
|
||||
* Algorithm Flags
|
||||
*/
|
||||
|
||||
/*!\brief Don't reference the last frame
|
||||
*
|
||||
* When this flag is set, the encoder will not use the last frame as a
|
||||
* predictor. When not set, the encoder will choose whether to use the
|
||||
* last frame or not automatically.
|
||||
*/
|
||||
#define VP8_EFLAG_NO_REF_LAST (1<<16)
|
||||
|
||||
|
||||
/*!\brief Don't reference the golden frame
|
||||
*
|
||||
* When this flag is set, the encoder will not use the golden frame as a
|
||||
* predictor. When not set, the encoder will choose whether to use the
|
||||
* golden frame or not automatically.
|
||||
*/
|
||||
#define VP8_EFLAG_NO_REF_GF (1<<17)
|
||||
|
||||
|
||||
/*!\brief Don't reference the alternate reference frame
|
||||
*
|
||||
* When this flag is set, the encoder will not use the alt ref frame as a
|
||||
* predictor. When not set, the encoder will choose whether to use the
|
||||
* alt ref frame or not automatically.
|
||||
*/
|
||||
#define VP8_EFLAG_NO_REF_ARF (1<<21)
|
||||
|
||||
|
||||
/*!\brief Don't update the last frame
|
||||
*
|
||||
* When this flag is set, the encoder will not update the last frame with
|
||||
* the contents of the current frame.
|
||||
*/
|
||||
#define VP8_EFLAG_NO_UPD_LAST (1<<18)
|
||||
|
||||
|
||||
/*!\brief Don't update the golden frame
|
||||
*
|
||||
* When this flag is set, the encoder will not update the golden frame with
|
||||
* the contents of the current frame.
|
||||
*/
|
||||
#define VP8_EFLAG_NO_UPD_GF (1<<22)
|
||||
|
||||
|
||||
/*!\brief Don't update the alternate reference frame
|
||||
*
|
||||
* When this flag is set, the encoder will not update the alt ref frame with
|
||||
* the contents of the current frame.
|
||||
*/
|
||||
#define VP8_EFLAG_NO_UPD_ARF (1<<23)
|
||||
|
||||
|
||||
/*!\brief Force golden frame update
|
||||
*
|
||||
* When this flag is set, the encoder copy the contents of the current frame
|
||||
* to the golden frame buffer.
|
||||
*/
|
||||
#define VP8_EFLAG_FORCE_GF (1<<19)
|
||||
|
||||
|
||||
/*!\brief Force alternate reference frame update
|
||||
*
|
||||
* When this flag is set, the encoder copy the contents of the current frame
|
||||
* to the alternate reference frame buffer.
|
||||
*/
|
||||
#define VP8_EFLAG_FORCE_ARF (1<<24)
|
||||
|
||||
|
||||
/*!\brief Disable entropy update
|
||||
*
|
||||
* When this flag is set, the encoder will not update its internal entropy
|
||||
* model based on the entropy of this frame.
|
||||
*/
|
||||
#define VP8_EFLAG_NO_UPD_ENTROPY (1<<20)
|
||||
|
||||
|
||||
/*!\brief VP8 encoder control functions
|
||||
*
|
||||
* This set of macros define the control functions available for the VP8
|
||||
* encoder interface.
|
||||
*
|
||||
* \sa #vpx_codec_control
|
||||
*/
|
||||
enum vp8e_enc_control_id {
|
||||
VP8E_UPD_ENTROPY = 5, /**< control function to set mode of entropy update in encoder */
|
||||
VP8E_UPD_REFERENCE, /**< control function to set reference update mode in encoder */
|
||||
VP8E_USE_REFERENCE, /**< control function to set which reference frame encoder can use */
|
||||
VP8E_SET_ROI_MAP, /**< control function to pass an ROI map to encoder */
|
||||
VP8E_SET_ACTIVEMAP, /**< control function to pass an Active map to encoder */
|
||||
VP8E_SET_SCALEMODE = 11, /**< control function to set encoder scaling mode */
|
||||
/*!\brief control function to set vp8 encoder cpuused
|
||||
*
|
||||
* Changes in this value influences, among others, the encoder's selection
|
||||
* of motion estimation methods. Values greater than 0 will increase encoder
|
||||
* speed at the expense of quality.
|
||||
* The full set of adjustments can be found in
|
||||
* onyx_if.c:vp8_set_speed_features().
|
||||
* \todo List highlights of the changes at various levels.
|
||||
*
|
||||
* \note Valid range: -16..16
|
||||
*/
|
||||
VP8E_SET_CPUUSED = 13,
|
||||
VP8E_SET_ENABLEAUTOALTREF, /**< control function to enable vp8 to automatic set and use altref frame */
|
||||
VP8E_SET_NOISE_SENSITIVITY, /**< control function to set noise sensitivity */
|
||||
VP8E_SET_SHARPNESS, /**< control function to set sharpness */
|
||||
VP8E_SET_STATIC_THRESHOLD, /**< control function to set the threshold for macroblocks treated static */
|
||||
VP8E_SET_TOKEN_PARTITIONS, /**< control function to set the number of token partitions */
|
||||
VP8E_GET_LAST_QUANTIZER, /**< return the quantizer chosen by the
|
||||
encoder for the last frame using the internal
|
||||
scale */
|
||||
VP8E_GET_LAST_QUANTIZER_64, /**< return the quantizer chosen by the
|
||||
encoder for the last frame, using the 0..63
|
||||
scale as used by the rc_*_quantizer config
|
||||
parameters */
|
||||
VP8E_SET_ARNR_MAXFRAMES, /**< control function to set the max number of frames blurred creating arf*/
|
||||
VP8E_SET_ARNR_STRENGTH, /**< control function to set the filter strength for the arf */
|
||||
VP8E_SET_ARNR_TYPE, /**< control function to set the type of filter to use for the arf*/
|
||||
VP8E_SET_TUNING, /**< control function to set visual tuning */
|
||||
/*!\brief control function to set constrained quality level
|
||||
*
|
||||
* \attention For this value to be used vpx_codec_enc_cfg_t::g_usage must be
|
||||
* set to #VPX_CQ.
|
||||
* \note Valid range: 0..63
|
||||
*/
|
||||
VP8E_SET_CQ_LEVEL,
|
||||
|
||||
/*!\brief Max data rate for Intra frames
|
||||
*
|
||||
* This value controls additional clamping on the maximum size of a
|
||||
* keyframe. It is expressed as a percentage of the average
|
||||
* per-frame bitrate, with the special (and default) value 0 meaning
|
||||
* unlimited, or no additional clamping beyond the codec's built-in
|
||||
* algorithm.
|
||||
*
|
||||
* For example, to allocate no more than 4.5 frames worth of bitrate
|
||||
* to a keyframe, set this to 450.
|
||||
*
|
||||
*/
|
||||
VP8E_SET_MAX_INTRA_BITRATE_PCT,
|
||||
|
||||
|
||||
/* TODO(jkoleszar): Move to vp9cx.h */
|
||||
VP9E_SET_LOSSLESS,
|
||||
VP9E_SET_TILE_COLUMNS,
|
||||
VP9E_SET_TILE_ROWS,
|
||||
VP9E_SET_FRAME_PARALLEL_DECODING
|
||||
};
|
||||
|
||||
/*!\brief vpx 1-D scaling mode
|
||||
*
|
||||
* This set of constants define 1-D vpx scaling modes
|
||||
*/
|
||||
typedef enum vpx_scaling_mode_1d {
|
||||
VP8E_NORMAL = 0,
|
||||
VP8E_FOURFIVE = 1,
|
||||
VP8E_THREEFIVE = 2,
|
||||
VP8E_ONETWO = 3
|
||||
} VPX_SCALING_MODE;
|
||||
|
||||
|
||||
/*!\brief vpx region of interest map
|
||||
*
|
||||
* These defines the data structures for the region of interest map
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct vpx_roi_map {
|
||||
unsigned char *roi_map; /**< specify an id between 0 and 3 for each 16x16 region within a frame */
|
||||
unsigned int rows; /**< number of rows */
|
||||
unsigned int cols; /**< number of cols */
|
||||
// TODO(paulwilkins): broken for VP9 which has 8 segments
|
||||
// q and loop filter deltas for each segment
|
||||
// (see MAX_MB_SEGMENTS)
|
||||
int delta_q[4];
|
||||
int delta_lf[4];
|
||||
// Static breakout threshold for each segment
|
||||
unsigned int static_threshold[4];
|
||||
} vpx_roi_map_t;
|
||||
|
||||
/*!\brief vpx active region map
|
||||
*
|
||||
* These defines the data structures for active region map
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
typedef struct vpx_active_map {
|
||||
unsigned char *active_map; /**< specify an on (1) or off (0) each 16x16 region within a frame */
|
||||
unsigned int rows; /**< number of rows */
|
||||
unsigned int cols; /**< number of cols */
|
||||
} vpx_active_map_t;
|
||||
|
||||
/*!\brief vpx image scaling mode
|
||||
*
|
||||
* This defines the data structure for image scaling mode
|
||||
*
|
||||
*/
|
||||
typedef struct vpx_scaling_mode {
|
||||
VPX_SCALING_MODE h_scaling_mode; /**< horizontal scaling mode */
|
||||
VPX_SCALING_MODE v_scaling_mode; /**< vertical scaling mode */
|
||||
} vpx_scaling_mode_t;
|
||||
|
||||
/*!\brief VP8 token partition mode
|
||||
*
|
||||
* This defines VP8 partitioning mode for compressed data, i.e., the number of
|
||||
* sub-streams in the bitstream. Used for parallelized decoding.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
VP8_ONE_TOKENPARTITION = 0,
|
||||
VP8_TWO_TOKENPARTITION = 1,
|
||||
VP8_FOUR_TOKENPARTITION = 2,
|
||||
VP8_EIGHT_TOKENPARTITION = 3
|
||||
} vp8e_token_partitions;
|
||||
|
||||
|
||||
/*!\brief VP8 model tuning parameters
|
||||
*
|
||||
* Changes the encoder to tune for certain types of input material.
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
VP8_TUNE_PSNR,
|
||||
VP8_TUNE_SSIM
|
||||
} vp8e_tuning;
|
||||
|
||||
|
||||
/*!\brief VP8 encoder control function parameter type
|
||||
*
|
||||
* Defines the data types that VP8E control functions take. Note that
|
||||
* additional common controls are defined in vp8.h
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* These controls have been deprecated in favor of the flags parameter to
|
||||
* vpx_codec_encode(). See the definition of VP8_EFLAG_* above.
|
||||
*/
|
||||
VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_UPD_ENTROPY, int)
|
||||
VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_UPD_REFERENCE, int)
|
||||
VPX_CTRL_USE_TYPE_DEPRECATED(VP8E_USE_REFERENCE, int)
|
||||
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_ROI_MAP, vpx_roi_map_t *)
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_ACTIVEMAP, vpx_active_map_t *)
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_SCALEMODE, vpx_scaling_mode_t *)
|
||||
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_CPUUSED, int)
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_ENABLEAUTOALTREF, unsigned int)
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_NOISE_SENSITIVITY, unsigned int)
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_SHARPNESS, unsigned int)
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_STATIC_THRESHOLD, unsigned int)
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_TOKEN_PARTITIONS, int) /* vp8e_token_partitions */
|
||||
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_MAXFRAMES, unsigned int)
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_STRENGTH, unsigned int)
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_TYPE, unsigned int)
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_TUNING, int) /* vp8e_tuning */
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_CQ_LEVEL, unsigned int)
|
||||
|
||||
VPX_CTRL_USE_TYPE(VP9E_SET_TILE_COLUMNS, int)
|
||||
VPX_CTRL_USE_TYPE(VP9E_SET_TILE_ROWS, int)
|
||||
|
||||
VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER, int *)
|
||||
VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER_64, int *)
|
||||
|
||||
VPX_CTRL_USE_TYPE(VP8E_SET_MAX_INTRA_BITRATE_PCT, unsigned int)
|
||||
|
||||
VPX_CTRL_USE_TYPE(VP9E_SET_LOSSLESS, unsigned int)
|
||||
|
||||
VPX_CTRL_USE_TYPE(VP9E_SET_FRAME_PARALLEL_DECODING, unsigned int)
|
||||
/*! @} - end defgroup vp8_encoder */
|
||||
#include "vpx_codec_impl_bottom.h"
|
||||
#endif
|
105
interface/external/LibVPX/include/vp8dx.h
vendored
Normal file
105
interface/external/LibVPX/include/vp8dx.h
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
#include "vp8.h"
|
||||
|
||||
/*!\defgroup vp8_decoder WebM VP8 Decoder
|
||||
* \ingroup vp8
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
/*!\file
|
||||
* \brief Provides definitions for using the VP8 algorithm within the vpx Decoder
|
||||
* interface.
|
||||
*/
|
||||
#ifndef VP8DX_H
|
||||
#define VP8DX_H
|
||||
#include "vpx_codec_impl_top.h"
|
||||
|
||||
/*!\name Algorithm interface for VP8
|
||||
*
|
||||
* This interface provides the capability to decode raw VP8 streams, as would
|
||||
* be found in AVI files and other non-Flash uses.
|
||||
* @{
|
||||
*/
|
||||
extern vpx_codec_iface_t vpx_codec_vp8_dx_algo;
|
||||
extern vpx_codec_iface_t *vpx_codec_vp8_dx(void);
|
||||
|
||||
/* TODO(jkoleszar): These move to VP9 in a later patch set. */
|
||||
extern vpx_codec_iface_t vpx_codec_vp9_dx_algo;
|
||||
extern vpx_codec_iface_t *vpx_codec_vp9_dx(void);
|
||||
/*!@} - end algorithm interface member group*/
|
||||
|
||||
/* Include controls common to both the encoder and decoder */
|
||||
#include "vp8.h"
|
||||
|
||||
|
||||
/*!\brief VP8 decoder control functions
|
||||
*
|
||||
* This set of macros define the control functions available for the VP8
|
||||
* decoder interface.
|
||||
*
|
||||
* \sa #vpx_codec_control
|
||||
*/
|
||||
enum vp8_dec_control_id {
|
||||
/** control function to get info on which reference frames were updated
|
||||
* by the last decode
|
||||
*/
|
||||
VP8D_GET_LAST_REF_UPDATES = VP8_DECODER_CTRL_ID_START,
|
||||
|
||||
/** check if the indicated frame is corrupted */
|
||||
VP8D_GET_FRAME_CORRUPTED,
|
||||
|
||||
/** control function to get info on which reference frames were used
|
||||
* by the last decode
|
||||
*/
|
||||
VP8D_GET_LAST_REF_USED,
|
||||
|
||||
/** decryption function to decrypt encoded buffer data immediately
|
||||
* before decoding. Takes a vp8_decrypt_init, which contains
|
||||
* a callback function and opaque context pointer.
|
||||
*/
|
||||
VP8D_SET_DECRYPTOR,
|
||||
|
||||
/** For testing. */
|
||||
VP9_INVERT_TILE_DECODE_ORDER,
|
||||
|
||||
VP8_DECODER_CTRL_ID_MAX
|
||||
};
|
||||
|
||||
typedef struct vp8_decrypt_init {
|
||||
/** Decrypt n bytes of data from input -> output, using the decrypt_state
|
||||
* passed in VP8D_SET_DECRYPTOR.
|
||||
*/
|
||||
void (*decrypt_cb)(void *decrypt_state, const unsigned char *input,
|
||||
unsigned char *output, int count);
|
||||
void *decrypt_state;
|
||||
} vp8_decrypt_init;
|
||||
|
||||
/*!\brief VP8 decoder control function parameter type
|
||||
*
|
||||
* Defines the data types that VP8D control functions take. Note that
|
||||
* additional common controls are defined in vp8.h
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_UPDATES, int *)
|
||||
VPX_CTRL_USE_TYPE(VP8D_GET_FRAME_CORRUPTED, int *)
|
||||
VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_USED, int *)
|
||||
VPX_CTRL_USE_TYPE(VP8D_SET_DECRYPTOR, vp8_decrypt_init *)
|
||||
VPX_CTRL_USE_TYPE(VP9_INVERT_TILE_DECODE_ORDER, int)
|
||||
|
||||
/*! @} - end defgroup vp8_decoder */
|
||||
|
||||
|
||||
#include "vpx_codec_impl_bottom.h"
|
||||
#endif
|
558
interface/external/LibVPX/include/vpx_codec.h
vendored
Normal file
558
interface/external/LibVPX/include/vpx_codec.h
vendored
Normal file
|
@ -0,0 +1,558 @@
|
|||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
/*!\defgroup codec Common Algorithm Interface
|
||||
* This abstraction allows applications to easily support multiple video
|
||||
* formats with minimal code duplication. This section describes the interface
|
||||
* common to all codecs (both encoders and decoders).
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!\file
|
||||
* \brief Describes the codec algorithm interface to applications.
|
||||
*
|
||||
* This file describes the interface between an application and a
|
||||
* video codec algorithm.
|
||||
*
|
||||
* An application instantiates a specific codec instance by using
|
||||
* vpx_codec_init() and a pointer to the algorithm's interface structure:
|
||||
* <pre>
|
||||
* my_app.c:
|
||||
* extern vpx_codec_iface_t my_codec;
|
||||
* {
|
||||
* vpx_codec_ctx_t algo;
|
||||
* res = vpx_codec_init(&algo, &my_codec);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Once initialized, the instance is manged using other functions from
|
||||
* the vpx_codec_* family.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef VPX_CODEC_H
|
||||
#define VPX_CODEC_H
|
||||
#include "vpx_integer.h"
|
||||
#include "vpx_image.h"
|
||||
|
||||
/*!\brief Decorator indicating a function is deprecated */
|
||||
#ifndef DEPRECATED
|
||||
#if defined(__GNUC__) && __GNUC__
|
||||
#define DEPRECATED __attribute__ ((deprecated))
|
||||
#elif defined(_MSC_VER)
|
||||
#define DEPRECATED
|
||||
#else
|
||||
#define DEPRECATED
|
||||
#endif
|
||||
#endif /* DEPRECATED */
|
||||
|
||||
#ifndef DECLSPEC_DEPRECATED
|
||||
#if defined(__GNUC__) && __GNUC__
|
||||
#define DECLSPEC_DEPRECATED /**< \copydoc #DEPRECATED */
|
||||
#elif defined(_MSC_VER)
|
||||
#define DECLSPEC_DEPRECATED __declspec(deprecated) /**< \copydoc #DEPRECATED */
|
||||
#else
|
||||
#define DECLSPEC_DEPRECATED /**< \copydoc #DEPRECATED */
|
||||
#endif
|
||||
#endif /* DECLSPEC_DEPRECATED */
|
||||
|
||||
/*!\brief Decorator indicating a function is potentially unused */
|
||||
#ifdef UNUSED
|
||||
#elif __GNUC__
|
||||
#define UNUSED __attribute__ ((unused))
|
||||
#else
|
||||
#define UNUSED
|
||||
#endif
|
||||
|
||||
/*!\brief Current ABI version number
|
||||
*
|
||||
* \internal
|
||||
* If this file is altered in any way that changes the ABI, this value
|
||||
* must be bumped. Examples include, but are not limited to, changing
|
||||
* types, removing or reassigning enums, adding/removing/rearranging
|
||||
* fields to structures
|
||||
*/
|
||||
#define VPX_CODEC_ABI_VERSION (2 + VPX_IMAGE_ABI_VERSION) /**<\hideinitializer*/
|
||||
|
||||
/*!\brief Algorithm return codes */
|
||||
typedef enum {
|
||||
/*!\brief Operation completed without error */
|
||||
VPX_CODEC_OK,
|
||||
|
||||
/*!\brief Unspecified error */
|
||||
VPX_CODEC_ERROR,
|
||||
|
||||
/*!\brief Memory operation failed */
|
||||
VPX_CODEC_MEM_ERROR,
|
||||
|
||||
/*!\brief ABI version mismatch */
|
||||
VPX_CODEC_ABI_MISMATCH,
|
||||
|
||||
/*!\brief Algorithm does not have required capability */
|
||||
VPX_CODEC_INCAPABLE,
|
||||
|
||||
/*!\brief The given bitstream is not supported.
|
||||
*
|
||||
* The bitstream was unable to be parsed at the highest level. The decoder
|
||||
* is unable to proceed. This error \ref SHOULD be treated as fatal to the
|
||||
* stream. */
|
||||
VPX_CODEC_UNSUP_BITSTREAM,
|
||||
|
||||
/*!\brief Encoded bitstream uses an unsupported feature
|
||||
*
|
||||
* The decoder does not implement a feature required by the encoder. This
|
||||
* return code should only be used for features that prevent future
|
||||
* pictures from being properly decoded. This error \ref MAY be treated as
|
||||
* fatal to the stream or \ref MAY be treated as fatal to the current GOP.
|
||||
*/
|
||||
VPX_CODEC_UNSUP_FEATURE,
|
||||
|
||||
/*!\brief The coded data for this stream is corrupt or incomplete
|
||||
*
|
||||
* There was a problem decoding the current frame. This return code
|
||||
* should only be used for failures that prevent future pictures from
|
||||
* being properly decoded. This error \ref MAY be treated as fatal to the
|
||||
* stream or \ref MAY be treated as fatal to the current GOP. If decoding
|
||||
* is continued for the current GOP, artifacts may be present.
|
||||
*/
|
||||
VPX_CODEC_CORRUPT_FRAME,
|
||||
|
||||
/*!\brief An application-supplied parameter is not valid.
|
||||
*
|
||||
*/
|
||||
VPX_CODEC_INVALID_PARAM,
|
||||
|
||||
/*!\brief An iterator reached the end of list.
|
||||
*
|
||||
*/
|
||||
VPX_CODEC_LIST_END
|
||||
|
||||
}
|
||||
vpx_codec_err_t;
|
||||
|
||||
|
||||
/*! \brief Codec capabilities bitfield
|
||||
*
|
||||
* Each codec advertises the capabilities it supports as part of its
|
||||
* ::vpx_codec_iface_t interface structure. Capabilities are extra interfaces
|
||||
* or functionality, and are not required to be supported.
|
||||
*
|
||||
* The available flags are specified by VPX_CODEC_CAP_* defines.
|
||||
*/
|
||||
typedef long vpx_codec_caps_t;
|
||||
#define VPX_CODEC_CAP_DECODER 0x1 /**< Is a decoder */
|
||||
#define VPX_CODEC_CAP_ENCODER 0x2 /**< Is an encoder */
|
||||
#define VPX_CODEC_CAP_XMA 0x4 /**< Supports eXternal Memory Allocation */
|
||||
|
||||
|
||||
/*! \brief Initialization-time Feature Enabling
|
||||
*
|
||||
* Certain codec features must be known at initialization time, to allow for
|
||||
* proper memory allocation.
|
||||
*
|
||||
* The available flags are specified by VPX_CODEC_USE_* defines.
|
||||
*/
|
||||
typedef long vpx_codec_flags_t;
|
||||
#define VPX_CODEC_USE_XMA 0x00000001 /**< Use eXternal Memory Allocation mode */
|
||||
|
||||
|
||||
/*!\brief Codec interface structure.
|
||||
*
|
||||
* Contains function pointers and other data private to the codec
|
||||
* implementation. This structure is opaque to the application.
|
||||
*/
|
||||
typedef const struct vpx_codec_iface vpx_codec_iface_t;
|
||||
|
||||
|
||||
/*!\brief Codec private data structure.
|
||||
*
|
||||
* Contains data private to the codec implementation. This structure is opaque
|
||||
* to the application.
|
||||
*/
|
||||
typedef struct vpx_codec_priv vpx_codec_priv_t;
|
||||
|
||||
|
||||
/*!\brief Iterator
|
||||
*
|
||||
* Opaque storage used for iterating over lists.
|
||||
*/
|
||||
typedef const void *vpx_codec_iter_t;
|
||||
|
||||
|
||||
/*!\brief Codec context structure
|
||||
*
|
||||
* All codecs \ref MUST support this context structure fully. In general,
|
||||
* this data should be considered private to the codec algorithm, and
|
||||
* not be manipulated or examined by the calling application. Applications
|
||||
* may reference the 'name' member to get a printable description of the
|
||||
* algorithm.
|
||||
*/
|
||||
typedef struct vpx_codec_ctx {
|
||||
const char *name; /**< Printable interface name */
|
||||
vpx_codec_iface_t *iface; /**< Interface pointers */
|
||||
vpx_codec_err_t err; /**< Last returned error */
|
||||
const char *err_detail; /**< Detailed info, if available */
|
||||
vpx_codec_flags_t init_flags; /**< Flags passed at init time */
|
||||
union {
|
||||
struct vpx_codec_dec_cfg *dec; /**< Decoder Configuration Pointer */
|
||||
struct vpx_codec_enc_cfg *enc; /**< Encoder Configuration Pointer */
|
||||
void *raw;
|
||||
} config; /**< Configuration pointer aliasing union */
|
||||
vpx_codec_priv_t *priv; /**< Algorithm private storage */
|
||||
} vpx_codec_ctx_t;
|
||||
|
||||
|
||||
/*
|
||||
* Library Version Number Interface
|
||||
*
|
||||
* For example, see the following sample return values:
|
||||
* vpx_codec_version() (1<<16 | 2<<8 | 3)
|
||||
* vpx_codec_version_str() "v1.2.3-rc1-16-gec6a1ba"
|
||||
* vpx_codec_version_extra_str() "rc1-16-gec6a1ba"
|
||||
*/
|
||||
|
||||
/*!\brief Return the version information (as an integer)
|
||||
*
|
||||
* Returns a packed encoding of the library version number. This will only include
|
||||
* the major.minor.patch component of the version number. Note that this encoded
|
||||
* value should be accessed through the macros provided, as the encoding may change
|
||||
* in the future.
|
||||
*
|
||||
*/
|
||||
int vpx_codec_version(void);
|
||||
#define VPX_VERSION_MAJOR(v) ((v>>16)&0xff) /**< extract major from packed version */
|
||||
#define VPX_VERSION_MINOR(v) ((v>>8)&0xff) /**< extract minor from packed version */
|
||||
#define VPX_VERSION_PATCH(v) ((v>>0)&0xff) /**< extract patch from packed version */
|
||||
|
||||
/*!\brief Return the version major number */
|
||||
#define vpx_codec_version_major() ((vpx_codec_version()>>16)&0xff)
|
||||
|
||||
/*!\brief Return the version minor number */
|
||||
#define vpx_codec_version_minor() ((vpx_codec_version()>>8)&0xff)
|
||||
|
||||
/*!\brief Return the version patch number */
|
||||
#define vpx_codec_version_patch() ((vpx_codec_version()>>0)&0xff)
|
||||
|
||||
|
||||
/*!\brief Return the version information (as a string)
|
||||
*
|
||||
* Returns a printable string containing the full library version number. This may
|
||||
* contain additional text following the three digit version number, as to indicate
|
||||
* release candidates, prerelease versions, etc.
|
||||
*
|
||||
*/
|
||||
const char *vpx_codec_version_str(void);
|
||||
|
||||
|
||||
/*!\brief Return the version information (as a string)
|
||||
*
|
||||
* Returns a printable "extra string". This is the component of the string returned
|
||||
* by vpx_codec_version_str() following the three digit version number.
|
||||
*
|
||||
*/
|
||||
const char *vpx_codec_version_extra_str(void);
|
||||
|
||||
|
||||
/*!\brief Return the build configuration
|
||||
*
|
||||
* Returns a printable string containing an encoded version of the build
|
||||
* configuration. This may be useful to vpx support.
|
||||
*
|
||||
*/
|
||||
const char *vpx_codec_build_config(void);
|
||||
|
||||
|
||||
/*!\brief Return the name for a given interface
|
||||
*
|
||||
* Returns a human readable string for name of the given codec interface.
|
||||
*
|
||||
* \param[in] iface Interface pointer
|
||||
*
|
||||
*/
|
||||
const char *vpx_codec_iface_name(vpx_codec_iface_t *iface);
|
||||
|
||||
|
||||
/*!\brief Convert error number to printable string
|
||||
*
|
||||
* Returns a human readable string for the last error returned by the
|
||||
* algorithm. The returned error will be one line and will not contain
|
||||
* any newline characters.
|
||||
*
|
||||
*
|
||||
* \param[in] err Error number.
|
||||
*
|
||||
*/
|
||||
const char *vpx_codec_err_to_string(vpx_codec_err_t err);
|
||||
|
||||
|
||||
/*!\brief Retrieve error synopsis for codec context
|
||||
*
|
||||
* Returns a human readable string for the last error returned by the
|
||||
* algorithm. The returned error will be one line and will not contain
|
||||
* any newline characters.
|
||||
*
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context.
|
||||
*
|
||||
*/
|
||||
const char *vpx_codec_error(vpx_codec_ctx_t *ctx);
|
||||
|
||||
|
||||
/*!\brief Retrieve detailed error information for codec context
|
||||
*
|
||||
* Returns a human readable string providing detailed information about
|
||||
* the last error.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context.
|
||||
*
|
||||
* \retval NULL
|
||||
* No detailed information is available.
|
||||
*/
|
||||
const char *vpx_codec_error_detail(vpx_codec_ctx_t *ctx);
|
||||
|
||||
|
||||
/* REQUIRED FUNCTIONS
|
||||
*
|
||||
* The following functions are required to be implemented for all codecs.
|
||||
* They represent the base case functionality expected of all codecs.
|
||||
*/
|
||||
|
||||
/*!\brief Destroy a codec instance
|
||||
*
|
||||
* Destroys a codec context, freeing any associated memory buffers.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context
|
||||
*
|
||||
* \retval #VPX_CODEC_OK
|
||||
* The codec algorithm initialized.
|
||||
* \retval #VPX_CODEC_MEM_ERROR
|
||||
* Memory allocation failed.
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx);
|
||||
|
||||
|
||||
/*!\brief Get the capabilities of an algorithm.
|
||||
*
|
||||
* Retrieves the capabilities bitfield from the algorithm's interface.
|
||||
*
|
||||
* \param[in] iface Pointer to the algorithm interface
|
||||
*
|
||||
*/
|
||||
vpx_codec_caps_t vpx_codec_get_caps(vpx_codec_iface_t *iface);
|
||||
|
||||
|
||||
/*!\brief Control algorithm
|
||||
*
|
||||
* This function is used to exchange algorithm specific data with the codec
|
||||
* instance. This can be used to implement features specific to a particular
|
||||
* algorithm.
|
||||
*
|
||||
* This wrapper function dispatches the request to the helper function
|
||||
* associated with the given ctrl_id. It tries to call this function
|
||||
* transparently, but will return #VPX_CODEC_ERROR if the request could not
|
||||
* be dispatched.
|
||||
*
|
||||
* Note that this function should not be used directly. Call the
|
||||
* #vpx_codec_control wrapper macro instead.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context
|
||||
* \param[in] ctrl_id Algorithm specific control identifier
|
||||
*
|
||||
* \retval #VPX_CODEC_OK
|
||||
* The control request was processed.
|
||||
* \retval #VPX_CODEC_ERROR
|
||||
* The control request was not processed.
|
||||
* \retval #VPX_CODEC_INVALID_PARAM
|
||||
* The data was not valid.
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t *ctx,
|
||||
int ctrl_id,
|
||||
...);
|
||||
#if defined(VPX_DISABLE_CTRL_TYPECHECKS) && VPX_DISABLE_CTRL_TYPECHECKS
|
||||
# define vpx_codec_control(ctx,id,data) vpx_codec_control_(ctx,id,data)
|
||||
# define VPX_CTRL_USE_TYPE(id, typ)
|
||||
# define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ)
|
||||
# define VPX_CTRL_VOID(id, typ)
|
||||
|
||||
#else
|
||||
/*!\brief vpx_codec_control wrapper macro
|
||||
*
|
||||
* This macro allows for type safe conversions across the variadic parameter
|
||||
* to vpx_codec_control_().
|
||||
*
|
||||
* \internal
|
||||
* It works by dispatching the call to the control function through a wrapper
|
||||
* function named with the id parameter.
|
||||
*/
|
||||
# define vpx_codec_control(ctx,id,data) vpx_codec_control_##id(ctx,id,data)\
|
||||
/**<\hideinitializer*/
|
||||
|
||||
|
||||
/*!\brief vpx_codec_control type definition macro
|
||||
*
|
||||
* This macro allows for type safe conversions across the variadic parameter
|
||||
* to vpx_codec_control_(). It defines the type of the argument for a given
|
||||
* control identifier.
|
||||
*
|
||||
* \internal
|
||||
* It defines a static function with
|
||||
* the correctly typed arguments as a wrapper to the type-unsafe internal
|
||||
* function.
|
||||
*/
|
||||
# define VPX_CTRL_USE_TYPE(id, typ) \
|
||||
static vpx_codec_err_t \
|
||||
vpx_codec_control_##id(vpx_codec_ctx_t*, int, typ) UNUSED;\
|
||||
\
|
||||
static vpx_codec_err_t \
|
||||
vpx_codec_control_##id(vpx_codec_ctx_t *ctx, int ctrl_id, typ data) {\
|
||||
return vpx_codec_control_(ctx, ctrl_id, data);\
|
||||
} /**<\hideinitializer*/
|
||||
|
||||
|
||||
/*!\brief vpx_codec_control deprecated type definition macro
|
||||
*
|
||||
* Like #VPX_CTRL_USE_TYPE, but indicates that the specified control is
|
||||
* deprecated and should not be used. Consult the documentation for your
|
||||
* codec for more information.
|
||||
*
|
||||
* \internal
|
||||
* It defines a static function with the correctly typed arguments as a
|
||||
* wrapper to the type-unsafe internal function.
|
||||
*/
|
||||
# define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ) \
|
||||
DECLSPEC_DEPRECATED static vpx_codec_err_t \
|
||||
vpx_codec_control_##id(vpx_codec_ctx_t*, int, typ) DEPRECATED UNUSED;\
|
||||
\
|
||||
DECLSPEC_DEPRECATED static vpx_codec_err_t \
|
||||
vpx_codec_control_##id(vpx_codec_ctx_t *ctx, int ctrl_id, typ data) {\
|
||||
return vpx_codec_control_(ctx, ctrl_id, data);\
|
||||
} /**<\hideinitializer*/
|
||||
|
||||
|
||||
/*!\brief vpx_codec_control void type definition macro
|
||||
*
|
||||
* This macro allows for type safe conversions across the variadic parameter
|
||||
* to vpx_codec_control_(). It indicates that a given control identifier takes
|
||||
* no argument.
|
||||
*
|
||||
* \internal
|
||||
* It defines a static function without a data argument as a wrapper to the
|
||||
* type-unsafe internal function.
|
||||
*/
|
||||
# define VPX_CTRL_VOID(id) \
|
||||
static vpx_codec_err_t \
|
||||
vpx_codec_control_##id(vpx_codec_ctx_t*, int) UNUSED;\
|
||||
\
|
||||
static vpx_codec_err_t \
|
||||
vpx_codec_control_##id(vpx_codec_ctx_t *ctx, int ctrl_id) {\
|
||||
return vpx_codec_control_(ctx, ctrl_id);\
|
||||
} /**<\hideinitializer*/
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*!\defgroup cap_xma External Memory Allocation Functions
|
||||
*
|
||||
* The following functions are required to be implemented for all codecs
|
||||
* that advertise the VPX_CODEC_CAP_XMA capability. Calling these functions
|
||||
* for codecs that don't advertise this capability will result in an error
|
||||
* code being returned, usually VPX_CODEC_INCAPABLE
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*!\brief Memory Map Entry
|
||||
*
|
||||
* This structure is used to contain the properties of a memory segment. It
|
||||
* is populated by the codec in the request phase, and by the calling
|
||||
* application once the requested allocation has been performed.
|
||||
*/
|
||||
typedef struct vpx_codec_mmap {
|
||||
/*
|
||||
* The following members are set by the codec when requesting a segment
|
||||
*/
|
||||
unsigned int id; /**< identifier for the segment's contents */
|
||||
unsigned long sz; /**< size of the segment, in bytes */
|
||||
unsigned int align; /**< required alignment of the segment, in bytes */
|
||||
unsigned int flags; /**< bitfield containing segment properties */
|
||||
#define VPX_CODEC_MEM_ZERO 0x1 /**< Segment must be zeroed by allocation */
|
||||
#define VPX_CODEC_MEM_WRONLY 0x2 /**< Segment need not be readable */
|
||||
#define VPX_CODEC_MEM_FAST 0x4 /**< Place in fast memory, if available */
|
||||
|
||||
/* The following members are to be filled in by the allocation function */
|
||||
void *base; /**< pointer to the allocated segment */
|
||||
void (*dtor)(struct vpx_codec_mmap *map); /**< destructor to call */
|
||||
void *priv; /**< allocator private storage */
|
||||
} vpx_codec_mmap_t; /**< alias for struct vpx_codec_mmap */
|
||||
|
||||
|
||||
/*!\brief Iterate over the list of segments to allocate.
|
||||
*
|
||||
* Iterates over a list of the segments to allocate. The iterator storage
|
||||
* should be initialized to NULL to start the iteration. Iteration is complete
|
||||
* when this function returns VPX_CODEC_LIST_END. The amount of memory needed to
|
||||
* allocate is dependent upon the size of the encoded stream. In cases where the
|
||||
* stream is not available at allocation time, a fixed size must be requested.
|
||||
* The codec will not be able to operate on streams larger than the size used at
|
||||
* allocation time.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context.
|
||||
* \param[out] mmap Pointer to the memory map entry to populate.
|
||||
* \param[in,out] iter Iterator storage, initialized to NULL
|
||||
*
|
||||
* \retval #VPX_CODEC_OK
|
||||
* The memory map entry was populated.
|
||||
* \retval #VPX_CODEC_ERROR
|
||||
* Codec does not support XMA mode.
|
||||
* \retval #VPX_CODEC_MEM_ERROR
|
||||
* Unable to determine segment size from stream info.
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_get_mem_map(vpx_codec_ctx_t *ctx,
|
||||
vpx_codec_mmap_t *mmap,
|
||||
vpx_codec_iter_t *iter);
|
||||
|
||||
|
||||
/*!\brief Identify allocated segments to codec instance
|
||||
*
|
||||
* Stores a list of allocated segments in the codec. Segments \ref MUST be
|
||||
* passed in the order they are read from vpx_codec_get_mem_map(), but may be
|
||||
* passed in groups of any size. Segments \ref MUST be set only once. The
|
||||
* allocation function \ref MUST ensure that the vpx_codec_mmap_t::base member
|
||||
* is non-NULL. If the segment requires cleanup handling (e.g., calling free()
|
||||
* or close()) then the vpx_codec_mmap_t::dtor member \ref MUST be populated.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context.
|
||||
* \param[in] mmaps Pointer to the first memory map entry in the list.
|
||||
* \param[in] num_maps Number of entries being set at this time
|
||||
*
|
||||
* \retval #VPX_CODEC_OK
|
||||
* The segment was stored in the codec context.
|
||||
* \retval #VPX_CODEC_INCAPABLE
|
||||
* Codec does not support XMA mode.
|
||||
* \retval #VPX_CODEC_MEM_ERROR
|
||||
* Segment base address was not set, or segment was already stored.
|
||||
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_set_mem_map(vpx_codec_ctx_t *ctx,
|
||||
vpx_codec_mmap_t *mmaps,
|
||||
unsigned int num_maps);
|
||||
|
||||
/*!@} - end defgroup cap_xma*/
|
||||
/*!@} - end defgroup codec*/
|
||||
|
||||
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
19
interface/external/LibVPX/include/vpx_codec_impl_bottom.h
vendored
Normal file
19
interface/external/LibVPX/include/vpx_codec_impl_bottom.h
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This file is to be included at the bottom of the header files defining the
|
||||
* interface to individual codecs and contains matching blocks to those defined
|
||||
* in vpx_codec_impl_top.h
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
19
interface/external/LibVPX/include/vpx_codec_impl_top.h
vendored
Normal file
19
interface/external/LibVPX/include/vpx_codec_impl_top.h
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This file is to be included at the top of the header files defining the
|
||||
* interface to individual codecs and contains various workarounds common
|
||||
* to all codec implementations.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
336
interface/external/LibVPX/include/vpx_decoder.h
vendored
Normal file
336
interface/external/LibVPX/include/vpx_decoder.h
vendored
Normal file
|
@ -0,0 +1,336 @@
|
|||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
/*!\defgroup decoder Decoder Algorithm Interface
|
||||
* \ingroup codec
|
||||
* This abstraction allows applications using this decoder to easily support
|
||||
* multiple video formats with minimal code duplication. This section describes
|
||||
* the interface common to all decoders.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!\file
|
||||
* \brief Describes the decoder algorithm interface to applications.
|
||||
*
|
||||
* This file describes the interface between an application and a
|
||||
* video decoder algorithm.
|
||||
*
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef VPX_DECODER_H
|
||||
#define VPX_DECODER_H
|
||||
#include "vpx_codec.h"
|
||||
|
||||
/*!\brief Current ABI version number
|
||||
*
|
||||
* \internal
|
||||
* If this file is altered in any way that changes the ABI, this value
|
||||
* must be bumped. Examples include, but are not limited to, changing
|
||||
* types, removing or reassigning enums, adding/removing/rearranging
|
||||
* fields to structures
|
||||
*/
|
||||
#define VPX_DECODER_ABI_VERSION (2 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
|
||||
|
||||
/*! \brief Decoder capabilities bitfield
|
||||
*
|
||||
* Each decoder advertises the capabilities it supports as part of its
|
||||
* ::vpx_codec_iface_t interface structure. Capabilities are extra interfaces
|
||||
* or functionality, and are not required to be supported by a decoder.
|
||||
*
|
||||
* The available flags are specified by VPX_CODEC_CAP_* defines.
|
||||
*/
|
||||
#define VPX_CODEC_CAP_PUT_SLICE 0x10000 /**< Will issue put_slice callbacks */
|
||||
#define VPX_CODEC_CAP_PUT_FRAME 0x20000 /**< Will issue put_frame callbacks */
|
||||
#define VPX_CODEC_CAP_POSTPROC 0x40000 /**< Can postprocess decoded frame */
|
||||
#define VPX_CODEC_CAP_ERROR_CONCEALMENT 0x80000 /**< Can conceal errors due to
|
||||
packet loss */
|
||||
#define VPX_CODEC_CAP_INPUT_FRAGMENTS 0x100000 /**< Can receive encoded frames
|
||||
one fragment at a time */
|
||||
|
||||
/*! \brief Initialization-time Feature Enabling
|
||||
*
|
||||
* Certain codec features must be known at initialization time, to allow for
|
||||
* proper memory allocation.
|
||||
*
|
||||
* The available flags are specified by VPX_CODEC_USE_* defines.
|
||||
*/
|
||||
#define VPX_CODEC_CAP_FRAME_THREADING 0x200000 /**< Can support frame-based
|
||||
multi-threading */
|
||||
|
||||
#define VPX_CODEC_USE_POSTPROC 0x10000 /**< Postprocess decoded frame */
|
||||
#define VPX_CODEC_USE_ERROR_CONCEALMENT 0x20000 /**< Conceal errors in decoded
|
||||
frames */
|
||||
#define VPX_CODEC_USE_INPUT_FRAGMENTS 0x40000 /**< The input frame should be
|
||||
passed to the decoder one
|
||||
fragment at a time */
|
||||
#define VPX_CODEC_USE_FRAME_THREADING 0x80000 /**< Enable frame-based
|
||||
multi-threading */
|
||||
|
||||
/*!\brief Stream properties
|
||||
*
|
||||
* This structure is used to query or set properties of the decoded
|
||||
* stream. Algorithms may extend this structure with data specific
|
||||
* to their bitstream by setting the sz member appropriately.
|
||||
*/
|
||||
typedef struct vpx_codec_stream_info {
|
||||
unsigned int sz; /**< Size of this structure */
|
||||
unsigned int w; /**< Width (or 0 for unknown/default) */
|
||||
unsigned int h; /**< Height (or 0 for unknown/default) */
|
||||
unsigned int is_kf; /**< Current frame is a keyframe */
|
||||
} vpx_codec_stream_info_t;
|
||||
|
||||
/* REQUIRED FUNCTIONS
|
||||
*
|
||||
* The following functions are required to be implemented for all decoders.
|
||||
* They represent the base case functionality expected of all decoders.
|
||||
*/
|
||||
|
||||
|
||||
/*!\brief Initialization Configurations
|
||||
*
|
||||
* This structure is used to pass init time configuration options to the
|
||||
* decoder.
|
||||
*/
|
||||
typedef struct vpx_codec_dec_cfg {
|
||||
unsigned int threads; /**< Maximum number of threads to use, default 1 */
|
||||
unsigned int w; /**< Width */
|
||||
unsigned int h; /**< Height */
|
||||
} vpx_codec_dec_cfg_t; /**< alias for struct vpx_codec_dec_cfg */
|
||||
|
||||
|
||||
/*!\brief Initialize a decoder instance
|
||||
*
|
||||
* Initializes a decoder context using the given interface. Applications
|
||||
* should call the vpx_codec_dec_init convenience macro instead of this
|
||||
* function directly, to ensure that the ABI version number parameter
|
||||
* is properly initialized.
|
||||
*
|
||||
* If the library was configured with --disable-multithread, this call
|
||||
* is not thread safe and should be guarded with a lock if being used
|
||||
* in a multithreaded context.
|
||||
*
|
||||
* In XMA mode (activated by setting VPX_CODEC_USE_XMA in the flags
|
||||
* parameter), the storage pointed to by the cfg parameter must be
|
||||
* kept readable and stable until all memory maps have been set.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context.
|
||||
* \param[in] iface Pointer to the algorithm interface to use.
|
||||
* \param[in] cfg Configuration to use, if known. May be NULL.
|
||||
* \param[in] flags Bitfield of VPX_CODEC_USE_* flags
|
||||
* \param[in] ver ABI version number. Must be set to
|
||||
* VPX_DECODER_ABI_VERSION
|
||||
* \retval #VPX_CODEC_OK
|
||||
* The decoder algorithm initialized.
|
||||
* \retval #VPX_CODEC_MEM_ERROR
|
||||
* Memory allocation failed.
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t *ctx,
|
||||
vpx_codec_iface_t *iface,
|
||||
vpx_codec_dec_cfg_t *cfg,
|
||||
vpx_codec_flags_t flags,
|
||||
int ver);
|
||||
|
||||
/*!\brief Convenience macro for vpx_codec_dec_init_ver()
|
||||
*
|
||||
* Ensures the ABI version parameter is properly set.
|
||||
*/
|
||||
#define vpx_codec_dec_init(ctx, iface, cfg, flags) \
|
||||
vpx_codec_dec_init_ver(ctx, iface, cfg, flags, VPX_DECODER_ABI_VERSION)
|
||||
|
||||
|
||||
/*!\brief Parse stream info from a buffer
|
||||
*
|
||||
* Performs high level parsing of the bitstream. Construction of a decoder
|
||||
* context is not necessary. Can be used to determine if the bitstream is
|
||||
* of the proper format, and to extract information from the stream.
|
||||
*
|
||||
* \param[in] iface Pointer to the algorithm interface
|
||||
* \param[in] data Pointer to a block of data to parse
|
||||
* \param[in] data_sz Size of the data buffer
|
||||
* \param[in,out] si Pointer to stream info to update. The size member
|
||||
* \ref MUST be properly initialized, but \ref MAY be
|
||||
* clobbered by the algorithm. This parameter \ref MAY
|
||||
* be NULL.
|
||||
*
|
||||
* \retval #VPX_CODEC_OK
|
||||
* Bitstream is parsable and stream information updated
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t *iface,
|
||||
const uint8_t *data,
|
||||
unsigned int data_sz,
|
||||
vpx_codec_stream_info_t *si);
|
||||
|
||||
|
||||
/*!\brief Return information about the current stream.
|
||||
*
|
||||
* Returns information about the stream that has been parsed during decoding.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context
|
||||
* \param[in,out] si Pointer to stream info to update. The size member
|
||||
* \ref MUST be properly initialized, but \ref MAY be
|
||||
* clobbered by the algorithm. This parameter \ref MAY
|
||||
* be NULL.
|
||||
*
|
||||
* \retval #VPX_CODEC_OK
|
||||
* Bitstream is parsable and stream information updated
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t *ctx,
|
||||
vpx_codec_stream_info_t *si);
|
||||
|
||||
|
||||
/*!\brief Decode data
|
||||
*
|
||||
* Processes a buffer of coded data. If the processing results in a new
|
||||
* decoded frame becoming available, PUT_SLICE and PUT_FRAME events may be
|
||||
* generated, as appropriate. Encoded data \ref MUST be passed in DTS (decode
|
||||
* time stamp) order. Frames produced will always be in PTS (presentation
|
||||
* time stamp) order.
|
||||
* If the decoder is configured with VPX_CODEC_USE_INPUT_FRAGMENTS enabled,
|
||||
* data and data_sz can contain a fragment of the encoded frame. Fragment
|
||||
* \#n must contain at least partition \#n, but can also contain subsequent
|
||||
* partitions (\#n+1 - \#n+i), and if so, fragments \#n+1, .., \#n+i must
|
||||
* be empty. When no more data is available, this function should be called
|
||||
* with NULL as data and 0 as data_sz. The memory passed to this function
|
||||
* must be available until the frame has been decoded.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context
|
||||
* \param[in] data Pointer to this block of new coded data. If
|
||||
* NULL, a VPX_CODEC_CB_PUT_FRAME event is posted
|
||||
* for the previously decoded frame.
|
||||
* \param[in] data_sz Size of the coded data, in bytes.
|
||||
* \param[in] user_priv Application specific data to associate with
|
||||
* this frame.
|
||||
* \param[in] deadline Soft deadline the decoder should attempt to meet,
|
||||
* in us. Set to zero for unlimited.
|
||||
*
|
||||
* \return Returns #VPX_CODEC_OK if the coded data was processed completely
|
||||
* and future pictures can be decoded without error. Otherwise,
|
||||
* see the descriptions of the other error codes in ::vpx_codec_err_t
|
||||
* for recoverability capabilities.
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx,
|
||||
const uint8_t *data,
|
||||
unsigned int data_sz,
|
||||
void *user_priv,
|
||||
long deadline);
|
||||
|
||||
|
||||
/*!\brief Decoded frames iterator
|
||||
*
|
||||
* Iterates over a list of the frames available for display. The iterator
|
||||
* storage should be initialized to NULL to start the iteration. Iteration is
|
||||
* complete when this function returns NULL.
|
||||
*
|
||||
* The list of available frames becomes valid upon completion of the
|
||||
* vpx_codec_decode call, and remains valid until the next call to vpx_codec_decode.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context
|
||||
* \param[in,out] iter Iterator storage, initialized to NULL
|
||||
*
|
||||
* \return Returns a pointer to an image, if one is ready for display. Frames
|
||||
* produced will always be in PTS (presentation time stamp) order.
|
||||
*/
|
||||
vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t *ctx,
|
||||
vpx_codec_iter_t *iter);
|
||||
|
||||
|
||||
/*!\defgroup cap_put_frame Frame-Based Decoding Functions
|
||||
*
|
||||
* The following functions are required to be implemented for all decoders
|
||||
* that advertise the VPX_CODEC_CAP_PUT_FRAME capability. Calling these functions
|
||||
* for codecs that don't advertise this capability will result in an error
|
||||
* code being returned, usually VPX_CODEC_ERROR
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!\brief put frame callback prototype
|
||||
*
|
||||
* This callback is invoked by the decoder to notify the application of
|
||||
* the availability of decoded image data.
|
||||
*/
|
||||
typedef void (*vpx_codec_put_frame_cb_fn_t)(void *user_priv,
|
||||
const vpx_image_t *img);
|
||||
|
||||
|
||||
/*!\brief Register for notification of frame completion.
|
||||
*
|
||||
* Registers a given function to be called when a decoded frame is
|
||||
* available.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context
|
||||
* \param[in] cb Pointer to the callback function
|
||||
* \param[in] user_priv User's private data
|
||||
*
|
||||
* \retval #VPX_CODEC_OK
|
||||
* Callback successfully registered.
|
||||
* \retval #VPX_CODEC_ERROR
|
||||
* Decoder context not initialized, or algorithm not capable of
|
||||
* posting slice completion.
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t *ctx,
|
||||
vpx_codec_put_frame_cb_fn_t cb,
|
||||
void *user_priv);
|
||||
|
||||
|
||||
/*!@} - end defgroup cap_put_frame */
|
||||
|
||||
/*!\defgroup cap_put_slice Slice-Based Decoding Functions
|
||||
*
|
||||
* The following functions are required to be implemented for all decoders
|
||||
* that advertise the VPX_CODEC_CAP_PUT_SLICE capability. Calling these functions
|
||||
* for codecs that don't advertise this capability will result in an error
|
||||
* code being returned, usually VPX_CODEC_ERROR
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!\brief put slice callback prototype
|
||||
*
|
||||
* This callback is invoked by the decoder to notify the application of
|
||||
* the availability of partially decoded image data. The
|
||||
*/
|
||||
typedef void (*vpx_codec_put_slice_cb_fn_t)(void *user_priv,
|
||||
const vpx_image_t *img,
|
||||
const vpx_image_rect_t *valid,
|
||||
const vpx_image_rect_t *update);
|
||||
|
||||
|
||||
/*!\brief Register for notification of slice completion.
|
||||
*
|
||||
* Registers a given function to be called when a decoded slice is
|
||||
* available.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context
|
||||
* \param[in] cb Pointer to the callback function
|
||||
* \param[in] user_priv User's private data
|
||||
*
|
||||
* \retval #VPX_CODEC_OK
|
||||
* Callback successfully registered.
|
||||
* \retval #VPX_CODEC_ERROR
|
||||
* Decoder context not initialized, or algorithm not capable of
|
||||
* posting slice completion.
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t *ctx,
|
||||
vpx_codec_put_slice_cb_fn_t cb,
|
||||
void *user_priv);
|
||||
|
||||
|
||||
/*!@} - end defgroup cap_put_slice*/
|
||||
|
||||
/*!@} - end defgroup decoder*/
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
924
interface/external/LibVPX/include/vpx_encoder.h
vendored
Normal file
924
interface/external/LibVPX/include/vpx_encoder.h
vendored
Normal file
|
@ -0,0 +1,924 @@
|
|||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
/*!\defgroup encoder Encoder Algorithm Interface
|
||||
* \ingroup codec
|
||||
* This abstraction allows applications using this encoder to easily support
|
||||
* multiple video formats with minimal code duplication. This section describes
|
||||
* the interface common to all encoders.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!\file
|
||||
* \brief Describes the encoder algorithm interface to applications.
|
||||
*
|
||||
* This file describes the interface between an application and a
|
||||
* video encoder algorithm.
|
||||
*
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef VPX_ENCODER_H
|
||||
#define VPX_ENCODER_H
|
||||
#include "vpx_codec.h"
|
||||
|
||||
/*! Temporal Scalability: Maximum length of the sequence defining frame
|
||||
* layer membership
|
||||
*/
|
||||
#define VPX_TS_MAX_PERIODICITY 16
|
||||
|
||||
/*! Temporal Scalability: Maximum number of coding layers */
|
||||
#define VPX_TS_MAX_LAYERS 5
|
||||
|
||||
/*!\deprecated Use #VPX_TS_MAX_PERIODICITY instead. */
|
||||
#define MAX_PERIODICITY VPX_TS_MAX_PERIODICITY
|
||||
|
||||
/*!\deprecated Use #VPX_TS_MAX_LAYERS instead. */
|
||||
#define MAX_LAYERS VPX_TS_MAX_LAYERS
|
||||
|
||||
/*!\brief Current ABI version number
|
||||
*
|
||||
* \internal
|
||||
* If this file is altered in any way that changes the ABI, this value
|
||||
* must be bumped. Examples include, but are not limited to, changing
|
||||
* types, removing or reassigning enums, adding/removing/rearranging
|
||||
* fields to structures
|
||||
*/
|
||||
#define VPX_ENCODER_ABI_VERSION (3 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
|
||||
|
||||
|
||||
/*! \brief Encoder capabilities bitfield
|
||||
*
|
||||
* Each encoder advertises the capabilities it supports as part of its
|
||||
* ::vpx_codec_iface_t interface structure. Capabilities are extra
|
||||
* interfaces or functionality, and are not required to be supported
|
||||
* by an encoder.
|
||||
*
|
||||
* The available flags are specified by VPX_CODEC_CAP_* defines.
|
||||
*/
|
||||
#define VPX_CODEC_CAP_PSNR 0x10000 /**< Can issue PSNR packets */
|
||||
|
||||
/*! Can output one partition at a time. Each partition is returned in its
|
||||
* own VPX_CODEC_CX_FRAME_PKT, with the FRAME_IS_FRAGMENT flag set for
|
||||
* every partition but the last. In this mode all frames are always
|
||||
* returned partition by partition.
|
||||
*/
|
||||
#define VPX_CODEC_CAP_OUTPUT_PARTITION 0x20000
|
||||
|
||||
|
||||
/*! \brief Initialization-time Feature Enabling
|
||||
*
|
||||
* Certain codec features must be known at initialization time, to allow
|
||||
* for proper memory allocation.
|
||||
*
|
||||
* The available flags are specified by VPX_CODEC_USE_* defines.
|
||||
*/
|
||||
#define VPX_CODEC_USE_PSNR 0x10000 /**< Calculate PSNR on each frame */
|
||||
#define VPX_CODEC_USE_OUTPUT_PARTITION 0x20000 /**< Make the encoder output one
|
||||
partition at a time. */
|
||||
|
||||
|
||||
/*!\brief Generic fixed size buffer structure
|
||||
*
|
||||
* This structure is able to hold a reference to any fixed size buffer.
|
||||
*/
|
||||
typedef struct vpx_fixed_buf {
|
||||
void *buf; /**< Pointer to the data */
|
||||
size_t sz; /**< Length of the buffer, in chars */
|
||||
} vpx_fixed_buf_t; /**< alias for struct vpx_fixed_buf */
|
||||
|
||||
|
||||
/*!\brief Time Stamp Type
|
||||
*
|
||||
* An integer, which when multiplied by the stream's time base, provides
|
||||
* the absolute time of a sample.
|
||||
*/
|
||||
typedef int64_t vpx_codec_pts_t;
|
||||
|
||||
|
||||
/*!\brief Compressed Frame Flags
|
||||
*
|
||||
* This type represents a bitfield containing information about a compressed
|
||||
* frame that may be useful to an application. The most significant 16 bits
|
||||
* can be used by an algorithm to provide additional detail, for example to
|
||||
* support frame types that are codec specific (MPEG-1 D-frames for example)
|
||||
*/
|
||||
typedef uint32_t vpx_codec_frame_flags_t;
|
||||
#define VPX_FRAME_IS_KEY 0x1 /**< frame is the start of a GOP */
|
||||
#define VPX_FRAME_IS_DROPPABLE 0x2 /**< frame can be dropped without affecting
|
||||
the stream (no future frame depends on
|
||||
this one) */
|
||||
#define VPX_FRAME_IS_INVISIBLE 0x4 /**< frame should be decoded but will not
|
||||
be shown */
|
||||
#define VPX_FRAME_IS_FRAGMENT 0x8 /**< this is a fragment of the encoded
|
||||
frame */
|
||||
|
||||
/*!\brief Error Resilient flags
|
||||
*
|
||||
* These flags define which error resilient features to enable in the
|
||||
* encoder. The flags are specified through the
|
||||
* vpx_codec_enc_cfg::g_error_resilient variable.
|
||||
*/
|
||||
typedef uint32_t vpx_codec_er_flags_t;
|
||||
#define VPX_ERROR_RESILIENT_DEFAULT 0x1 /**< Improve resiliency against
|
||||
losses of whole frames */
|
||||
#define VPX_ERROR_RESILIENT_PARTITIONS 0x2 /**< The frame partitions are
|
||||
independently decodable by the
|
||||
bool decoder, meaning that
|
||||
partitions can be decoded even
|
||||
though earlier partitions have
|
||||
been lost. Note that intra
|
||||
predicition is still done over
|
||||
the partition boundary. */
|
||||
|
||||
/*!\brief Encoder output packet variants
|
||||
*
|
||||
* This enumeration lists the different kinds of data packets that can be
|
||||
* returned by calls to vpx_codec_get_cx_data(). Algorithms \ref MAY
|
||||
* extend this list to provide additional functionality.
|
||||
*/
|
||||
enum vpx_codec_cx_pkt_kind {
|
||||
VPX_CODEC_CX_FRAME_PKT, /**< Compressed video frame */
|
||||
VPX_CODEC_STATS_PKT, /**< Two-pass statistics for this frame */
|
||||
VPX_CODEC_PSNR_PKT, /**< PSNR statistics for this frame */
|
||||
VPX_CODEC_CUSTOM_PKT = 256 /**< Algorithm extensions */
|
||||
};
|
||||
|
||||
|
||||
/*!\brief Encoder output packet
|
||||
*
|
||||
* This structure contains the different kinds of output data the encoder
|
||||
* may produce while compressing a frame.
|
||||
*/
|
||||
typedef struct vpx_codec_cx_pkt {
|
||||
enum vpx_codec_cx_pkt_kind kind; /**< packet variant */
|
||||
union {
|
||||
struct {
|
||||
void *buf; /**< compressed data buffer */
|
||||
size_t sz; /**< length of compressed data */
|
||||
vpx_codec_pts_t pts; /**< time stamp to show frame
|
||||
(in timebase units) */
|
||||
unsigned long duration; /**< duration to show frame
|
||||
(in timebase units) */
|
||||
vpx_codec_frame_flags_t flags; /**< flags for this frame */
|
||||
int partition_id; /**< the partition id
|
||||
defines the decoding order
|
||||
of the partitions. Only
|
||||
applicable when "output partition"
|
||||
mode is enabled. First partition
|
||||
has id 0.*/
|
||||
|
||||
} frame; /**< data for compressed frame packet */
|
||||
struct vpx_fixed_buf twopass_stats; /**< data for two-pass packet */
|
||||
struct vpx_psnr_pkt {
|
||||
unsigned int samples[4]; /**< Number of samples, total/y/u/v */
|
||||
uint64_t sse[4]; /**< sum squared error, total/y/u/v */
|
||||
double psnr[4]; /**< PSNR, total/y/u/v */
|
||||
} psnr; /**< data for PSNR packet */
|
||||
struct vpx_fixed_buf raw; /**< data for arbitrary packets */
|
||||
|
||||
/* This packet size is fixed to allow codecs to extend this
|
||||
* interface without having to manage storage for raw packets,
|
||||
* i.e., if it's smaller than 128 bytes, you can store in the
|
||||
* packet list directly.
|
||||
*/
|
||||
char pad[128 - sizeof(enum vpx_codec_cx_pkt_kind)]; /**< fixed sz */
|
||||
} data; /**< packet data */
|
||||
} vpx_codec_cx_pkt_t; /**< alias for struct vpx_codec_cx_pkt */
|
||||
|
||||
|
||||
/*!\brief Rational Number
|
||||
*
|
||||
* This structure holds a fractional value.
|
||||
*/
|
||||
typedef struct vpx_rational {
|
||||
int num; /**< fraction numerator */
|
||||
int den; /**< fraction denominator */
|
||||
} vpx_rational_t; /**< alias for struct vpx_rational */
|
||||
|
||||
|
||||
/*!\brief Multi-pass Encoding Pass */
|
||||
enum vpx_enc_pass {
|
||||
VPX_RC_ONE_PASS, /**< Single pass mode */
|
||||
VPX_RC_FIRST_PASS, /**< First pass of multi-pass mode */
|
||||
VPX_RC_LAST_PASS /**< Final pass of multi-pass mode */
|
||||
};
|
||||
|
||||
|
||||
/*!\brief Rate control mode */
|
||||
enum vpx_rc_mode {
|
||||
VPX_VBR, /**< Variable Bit Rate (VBR) mode */
|
||||
VPX_CBR, /**< Constant Bit Rate (CBR) mode */
|
||||
VPX_CQ /**< Constant Quality (CQ) mode */
|
||||
};
|
||||
|
||||
|
||||
/*!\brief Keyframe placement mode.
|
||||
*
|
||||
* This enumeration determines whether keyframes are placed automatically by
|
||||
* the encoder or whether this behavior is disabled. Older releases of this
|
||||
* SDK were implemented such that VPX_KF_FIXED meant keyframes were disabled.
|
||||
* This name is confusing for this behavior, so the new symbols to be used
|
||||
* are VPX_KF_AUTO and VPX_KF_DISABLED.
|
||||
*/
|
||||
enum vpx_kf_mode {
|
||||
VPX_KF_FIXED, /**< deprecated, implies VPX_KF_DISABLED */
|
||||
VPX_KF_AUTO, /**< Encoder determines optimal placement automatically */
|
||||
VPX_KF_DISABLED = 0 /**< Encoder does not place keyframes. */
|
||||
};
|
||||
|
||||
|
||||
/*!\brief Encoded Frame Flags
|
||||
*
|
||||
* This type indicates a bitfield to be passed to vpx_codec_encode(), defining
|
||||
* per-frame boolean values. By convention, bits common to all codecs will be
|
||||
* named VPX_EFLAG_*, and bits specific to an algorithm will be named
|
||||
* /algo/_eflag_*. The lower order 16 bits are reserved for common use.
|
||||
*/
|
||||
typedef long vpx_enc_frame_flags_t;
|
||||
#define VPX_EFLAG_FORCE_KF (1<<0) /**< Force this frame to be a keyframe */
|
||||
|
||||
|
||||
/*!\brief Encoder configuration structure
|
||||
*
|
||||
* This structure contains the encoder settings that have common representations
|
||||
* across all codecs. This doesn't imply that all codecs support all features,
|
||||
* however.
|
||||
*/
|
||||
typedef struct vpx_codec_enc_cfg {
|
||||
/*
|
||||
* generic settings (g)
|
||||
*/
|
||||
|
||||
/*!\brief Algorithm specific "usage" value
|
||||
*
|
||||
* Algorithms may define multiple values for usage, which may convey the
|
||||
* intent of how the application intends to use the stream. If this value
|
||||
* is non-zero, consult the documentation for the codec to determine its
|
||||
* meaning.
|
||||
*/
|
||||
unsigned int g_usage;
|
||||
|
||||
|
||||
/*!\brief Maximum number of threads to use
|
||||
*
|
||||
* For multi-threaded implementations, use no more than this number of
|
||||
* threads. The codec may use fewer threads than allowed. The value
|
||||
* 0 is equivalent to the value 1.
|
||||
*/
|
||||
unsigned int g_threads;
|
||||
|
||||
|
||||
/*!\brief Bitstream profile to use
|
||||
*
|
||||
* Some codecs support a notion of multiple bitstream profiles. Typically
|
||||
* this maps to a set of features that are turned on or off. Often the
|
||||
* profile to use is determined by the features of the intended decoder.
|
||||
* Consult the documentation for the codec to determine the valid values
|
||||
* for this parameter, or set to zero for a sane default.
|
||||
*/
|
||||
unsigned int g_profile; /**< profile of bitstream to use */
|
||||
|
||||
|
||||
|
||||
/*!\brief Width of the frame
|
||||
*
|
||||
* This value identifies the presentation resolution of the frame,
|
||||
* in pixels. Note that the frames passed as input to the encoder must
|
||||
* have this resolution. Frames will be presented by the decoder in this
|
||||
* resolution, independent of any spatial resampling the encoder may do.
|
||||
*/
|
||||
unsigned int g_w;
|
||||
|
||||
|
||||
/*!\brief Height of the frame
|
||||
*
|
||||
* This value identifies the presentation resolution of the frame,
|
||||
* in pixels. Note that the frames passed as input to the encoder must
|
||||
* have this resolution. Frames will be presented by the decoder in this
|
||||
* resolution, independent of any spatial resampling the encoder may do.
|
||||
*/
|
||||
unsigned int g_h;
|
||||
|
||||
|
||||
/*!\brief Stream timebase units
|
||||
*
|
||||
* Indicates the smallest interval of time, in seconds, used by the stream.
|
||||
* For fixed frame rate material, or variable frame rate material where
|
||||
* frames are timed at a multiple of a given clock (ex: video capture),
|
||||
* the \ref RECOMMENDED method is to set the timebase to the reciprocal
|
||||
* of the frame rate (ex: 1001/30000 for 29.970 Hz NTSC). This allows the
|
||||
* pts to correspond to the frame number, which can be handy. For
|
||||
* re-encoding video from containers with absolute time timestamps, the
|
||||
* \ref RECOMMENDED method is to set the timebase to that of the parent
|
||||
* container or multimedia framework (ex: 1/1000 for ms, as in FLV).
|
||||
*/
|
||||
struct vpx_rational g_timebase;
|
||||
|
||||
|
||||
/*!\brief Enable error resilient modes.
|
||||
*
|
||||
* The error resilient bitfield indicates to the encoder which features
|
||||
* it should enable to take measures for streaming over lossy or noisy
|
||||
* links.
|
||||
*/
|
||||
vpx_codec_er_flags_t g_error_resilient;
|
||||
|
||||
|
||||
/*!\brief Multi-pass Encoding Mode
|
||||
*
|
||||
* This value should be set to the current phase for multi-pass encoding.
|
||||
* For single pass, set to #VPX_RC_ONE_PASS.
|
||||
*/
|
||||
enum vpx_enc_pass g_pass;
|
||||
|
||||
|
||||
/*!\brief Allow lagged encoding
|
||||
*
|
||||
* If set, this value allows the encoder to consume a number of input
|
||||
* frames before producing output frames. This allows the encoder to
|
||||
* base decisions for the current frame on future frames. This does
|
||||
* increase the latency of the encoding pipeline, so it is not appropriate
|
||||
* in all situations (ex: realtime encoding).
|
||||
*
|
||||
* Note that this is a maximum value -- the encoder may produce frames
|
||||
* sooner than the given limit. Set this value to 0 to disable this
|
||||
* feature.
|
||||
*/
|
||||
unsigned int g_lag_in_frames;
|
||||
|
||||
|
||||
/*
|
||||
* rate control settings (rc)
|
||||
*/
|
||||
|
||||
/*!\brief Temporal resampling configuration, if supported by the codec.
|
||||
*
|
||||
* Temporal resampling allows the codec to "drop" frames as a strategy to
|
||||
* meet its target data rate. This can cause temporal discontinuities in
|
||||
* the encoded video, which may appear as stuttering during playback. This
|
||||
* trade-off is often acceptable, but for many applications is not. It can
|
||||
* be disabled in these cases.
|
||||
*
|
||||
* Note that not all codecs support this feature. All vpx VPx codecs do.
|
||||
* For other codecs, consult the documentation for that algorithm.
|
||||
*
|
||||
* This threshold is described as a percentage of the target data buffer.
|
||||
* When the data buffer falls below this percentage of fullness, a
|
||||
* dropped frame is indicated. Set the threshold to zero (0) to disable
|
||||
* this feature.
|
||||
*/
|
||||
unsigned int rc_dropframe_thresh;
|
||||
|
||||
|
||||
/*!\brief Enable/disable spatial resampling, if supported by the codec.
|
||||
*
|
||||
* Spatial resampling allows the codec to compress a lower resolution
|
||||
* version of the frame, which is then upscaled by the encoder to the
|
||||
* correct presentation resolution. This increases visual quality at
|
||||
* low data rates, at the expense of CPU time on the encoder/decoder.
|
||||
*/
|
||||
unsigned int rc_resize_allowed;
|
||||
|
||||
|
||||
/*!\brief Spatial resampling up watermark.
|
||||
*
|
||||
* This threshold is described as a percentage of the target data buffer.
|
||||
* When the data buffer rises above this percentage of fullness, the
|
||||
* encoder will step up to a higher resolution version of the frame.
|
||||
*/
|
||||
unsigned int rc_resize_up_thresh;
|
||||
|
||||
|
||||
/*!\brief Spatial resampling down watermark.
|
||||
*
|
||||
* This threshold is described as a percentage of the target data buffer.
|
||||
* When the data buffer falls below this percentage of fullness, the
|
||||
* encoder will step down to a lower resolution version of the frame.
|
||||
*/
|
||||
unsigned int rc_resize_down_thresh;
|
||||
|
||||
|
||||
/*!\brief Rate control algorithm to use.
|
||||
*
|
||||
* Indicates whether the end usage of this stream is to be streamed over
|
||||
* a bandwidth constrained link, indicating that Constant Bit Rate (CBR)
|
||||
* mode should be used, or whether it will be played back on a high
|
||||
* bandwidth link, as from a local disk, where higher variations in
|
||||
* bitrate are acceptable.
|
||||
*/
|
||||
enum vpx_rc_mode rc_end_usage;
|
||||
|
||||
|
||||
/*!\brief Two-pass stats buffer.
|
||||
*
|
||||
* A buffer containing all of the stats packets produced in the first
|
||||
* pass, concatenated.
|
||||
*/
|
||||
struct vpx_fixed_buf rc_twopass_stats_in;
|
||||
|
||||
|
||||
/*!\brief Target data rate
|
||||
*
|
||||
* Target bandwidth to use for this stream, in kilobits per second.
|
||||
*/
|
||||
unsigned int rc_target_bitrate;
|
||||
|
||||
|
||||
/*
|
||||
* quantizer settings
|
||||
*/
|
||||
|
||||
|
||||
/*!\brief Minimum (Best Quality) Quantizer
|
||||
*
|
||||
* The quantizer is the most direct control over the quality of the
|
||||
* encoded image. The range of valid values for the quantizer is codec
|
||||
* specific. Consult the documentation for the codec to determine the
|
||||
* values to use. To determine the range programmatically, call
|
||||
* vpx_codec_enc_config_default() with a usage value of 0.
|
||||
*/
|
||||
unsigned int rc_min_quantizer;
|
||||
|
||||
|
||||
/*!\brief Maximum (Worst Quality) Quantizer
|
||||
*
|
||||
* The quantizer is the most direct control over the quality of the
|
||||
* encoded image. The range of valid values for the quantizer is codec
|
||||
* specific. Consult the documentation for the codec to determine the
|
||||
* values to use. To determine the range programmatically, call
|
||||
* vpx_codec_enc_config_default() with a usage value of 0.
|
||||
*/
|
||||
unsigned int rc_max_quantizer;
|
||||
|
||||
|
||||
/*
|
||||
* bitrate tolerance
|
||||
*/
|
||||
|
||||
|
||||
/*!\brief Rate control adaptation undershoot control
|
||||
*
|
||||
* This value, expressed as a percentage of the target bitrate,
|
||||
* controls the maximum allowed adaptation speed of the codec.
|
||||
* This factor controls the maximum amount of bits that can
|
||||
* be subtracted from the target bitrate in order to compensate
|
||||
* for prior overshoot.
|
||||
*
|
||||
* Valid values in the range 0-1000.
|
||||
*/
|
||||
unsigned int rc_undershoot_pct;
|
||||
|
||||
|
||||
/*!\brief Rate control adaptation overshoot control
|
||||
*
|
||||
* This value, expressed as a percentage of the target bitrate,
|
||||
* controls the maximum allowed adaptation speed of the codec.
|
||||
* This factor controls the maximum amount of bits that can
|
||||
* be added to the target bitrate in order to compensate for
|
||||
* prior undershoot.
|
||||
*
|
||||
* Valid values in the range 0-1000.
|
||||
*/
|
||||
unsigned int rc_overshoot_pct;
|
||||
|
||||
|
||||
/*
|
||||
* decoder buffer model parameters
|
||||
*/
|
||||
|
||||
|
||||
/*!\brief Decoder Buffer Size
|
||||
*
|
||||
* This value indicates the amount of data that may be buffered by the
|
||||
* decoding application. Note that this value is expressed in units of
|
||||
* time (milliseconds). For example, a value of 5000 indicates that the
|
||||
* client will buffer (at least) 5000ms worth of encoded data. Use the
|
||||
* target bitrate (#rc_target_bitrate) to convert to bits/bytes, if
|
||||
* necessary.
|
||||
*/
|
||||
unsigned int rc_buf_sz;
|
||||
|
||||
|
||||
/*!\brief Decoder Buffer Initial Size
|
||||
*
|
||||
* This value indicates the amount of data that will be buffered by the
|
||||
* decoding application prior to beginning playback. This value is
|
||||
* expressed in units of time (milliseconds). Use the target bitrate
|
||||
* (#rc_target_bitrate) to convert to bits/bytes, if necessary.
|
||||
*/
|
||||
unsigned int rc_buf_initial_sz;
|
||||
|
||||
|
||||
/*!\brief Decoder Buffer Optimal Size
|
||||
*
|
||||
* This value indicates the amount of data that the encoder should try
|
||||
* to maintain in the decoder's buffer. This value is expressed in units
|
||||
* of time (milliseconds). Use the target bitrate (#rc_target_bitrate)
|
||||
* to convert to bits/bytes, if necessary.
|
||||
*/
|
||||
unsigned int rc_buf_optimal_sz;
|
||||
|
||||
|
||||
/*
|
||||
* 2 pass rate control parameters
|
||||
*/
|
||||
|
||||
|
||||
/*!\brief Two-pass mode CBR/VBR bias
|
||||
*
|
||||
* Bias, expressed on a scale of 0 to 100, for determining target size
|
||||
* for the current frame. The value 0 indicates the optimal CBR mode
|
||||
* value should be used. The value 100 indicates the optimal VBR mode
|
||||
* value should be used. Values in between indicate which way the
|
||||
* encoder should "lean."
|
||||
*/
|
||||
unsigned int rc_2pass_vbr_bias_pct; /**< RC mode bias between CBR and VBR(0-100: 0->CBR, 100->VBR) */
|
||||
|
||||
|
||||
/*!\brief Two-pass mode per-GOP minimum bitrate
|
||||
*
|
||||
* This value, expressed as a percentage of the target bitrate, indicates
|
||||
* the minimum bitrate to be used for a single GOP (aka "section")
|
||||
*/
|
||||
unsigned int rc_2pass_vbr_minsection_pct;
|
||||
|
||||
|
||||
/*!\brief Two-pass mode per-GOP maximum bitrate
|
||||
*
|
||||
* This value, expressed as a percentage of the target bitrate, indicates
|
||||
* the maximum bitrate to be used for a single GOP (aka "section")
|
||||
*/
|
||||
unsigned int rc_2pass_vbr_maxsection_pct;
|
||||
|
||||
|
||||
/*
|
||||
* keyframing settings (kf)
|
||||
*/
|
||||
|
||||
/*!\brief Keyframe placement mode
|
||||
*
|
||||
* This value indicates whether the encoder should place keyframes at a
|
||||
* fixed interval, or determine the optimal placement automatically
|
||||
* (as governed by the #kf_min_dist and #kf_max_dist parameters)
|
||||
*/
|
||||
enum vpx_kf_mode kf_mode;
|
||||
|
||||
|
||||
/*!\brief Keyframe minimum interval
|
||||
*
|
||||
* This value, expressed as a number of frames, prevents the encoder from
|
||||
* placing a keyframe nearer than kf_min_dist to the previous keyframe. At
|
||||
* least kf_min_dist frames non-keyframes will be coded before the next
|
||||
* keyframe. Set kf_min_dist equal to kf_max_dist for a fixed interval.
|
||||
*/
|
||||
unsigned int kf_min_dist;
|
||||
|
||||
|
||||
/*!\brief Keyframe maximum interval
|
||||
*
|
||||
* This value, expressed as a number of frames, forces the encoder to code
|
||||
* a keyframe if one has not been coded in the last kf_max_dist frames.
|
||||
* A value of 0 implies all frames will be keyframes. Set kf_min_dist
|
||||
* equal to kf_max_dist for a fixed interval.
|
||||
*/
|
||||
unsigned int kf_max_dist;
|
||||
|
||||
/*
|
||||
* Temporal scalability settings (ts)
|
||||
*/
|
||||
|
||||
/*!\brief Number of coding layers
|
||||
*
|
||||
* This value specifies the number of coding layers to be used.
|
||||
*/
|
||||
unsigned int ts_number_layers;
|
||||
|
||||
/*!\brief Target bitrate for each layer
|
||||
*
|
||||
* These values specify the target coding bitrate for each coding layer.
|
||||
*/
|
||||
unsigned int ts_target_bitrate[VPX_TS_MAX_LAYERS];
|
||||
|
||||
/*!\brief Frame rate decimation factor for each layer
|
||||
*
|
||||
* These values specify the frame rate decimation factors to apply
|
||||
* to each layer.
|
||||
*/
|
||||
unsigned int ts_rate_decimator[VPX_TS_MAX_LAYERS];
|
||||
|
||||
/*!\brief Length of the sequence defining frame layer membership
|
||||
*
|
||||
* This value specifies the length of the sequence that defines the
|
||||
* membership of frames to layers. For example, if ts_periodicity=8 then
|
||||
* frames are assigned to coding layers with a repeated sequence of
|
||||
* length 8.
|
||||
*/
|
||||
unsigned int ts_periodicity;
|
||||
|
||||
/*!\brief Template defining the membership of frames to coding layers
|
||||
*
|
||||
* This array defines the membership of frames to coding layers. For a
|
||||
* 2-layer encoding that assigns even numbered frames to one layer (0)
|
||||
* and odd numbered frames to a second layer (1) with ts_periodicity=8,
|
||||
* then ts_layer_id = (0,1,0,1,0,1,0,1).
|
||||
*/
|
||||
unsigned int ts_layer_id[VPX_TS_MAX_PERIODICITY];
|
||||
} vpx_codec_enc_cfg_t; /**< alias for struct vpx_codec_enc_cfg */
|
||||
|
||||
|
||||
/*!\brief Initialize an encoder instance
|
||||
*
|
||||
* Initializes a encoder context using the given interface. Applications
|
||||
* should call the vpx_codec_enc_init convenience macro instead of this
|
||||
* function directly, to ensure that the ABI version number parameter
|
||||
* is properly initialized.
|
||||
*
|
||||
* If the library was configured with --disable-multithread, this call
|
||||
* is not thread safe and should be guarded with a lock if being used
|
||||
* in a multithreaded context.
|
||||
*
|
||||
* In XMA mode (activated by setting VPX_CODEC_USE_XMA in the flags
|
||||
* parameter), the storage pointed to by the cfg parameter must be
|
||||
* kept readable and stable until all memory maps have been set.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context.
|
||||
* \param[in] iface Pointer to the algorithm interface to use.
|
||||
* \param[in] cfg Configuration to use, if known. May be NULL.
|
||||
* \param[in] flags Bitfield of VPX_CODEC_USE_* flags
|
||||
* \param[in] ver ABI version number. Must be set to
|
||||
* VPX_ENCODER_ABI_VERSION
|
||||
* \retval #VPX_CODEC_OK
|
||||
* The decoder algorithm initialized.
|
||||
* \retval #VPX_CODEC_MEM_ERROR
|
||||
* Memory allocation failed.
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_enc_init_ver(vpx_codec_ctx_t *ctx,
|
||||
vpx_codec_iface_t *iface,
|
||||
vpx_codec_enc_cfg_t *cfg,
|
||||
vpx_codec_flags_t flags,
|
||||
int ver);
|
||||
|
||||
|
||||
/*!\brief Convenience macro for vpx_codec_enc_init_ver()
|
||||
*
|
||||
* Ensures the ABI version parameter is properly set.
|
||||
*/
|
||||
#define vpx_codec_enc_init(ctx, iface, cfg, flags) \
|
||||
vpx_codec_enc_init_ver(ctx, iface, cfg, flags, VPX_ENCODER_ABI_VERSION)
|
||||
|
||||
|
||||
/*!\brief Initialize multi-encoder instance
|
||||
*
|
||||
* Initializes multi-encoder context using the given interface.
|
||||
* Applications should call the vpx_codec_enc_init_multi convenience macro
|
||||
* instead of this function directly, to ensure that the ABI version number
|
||||
* parameter is properly initialized.
|
||||
*
|
||||
* In XMA mode (activated by setting VPX_CODEC_USE_XMA in the flags
|
||||
* parameter), the storage pointed to by the cfg parameter must be
|
||||
* kept readable and stable until all memory maps have been set.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context.
|
||||
* \param[in] iface Pointer to the algorithm interface to use.
|
||||
* \param[in] cfg Configuration to use, if known. May be NULL.
|
||||
* \param[in] num_enc Total number of encoders.
|
||||
* \param[in] flags Bitfield of VPX_CODEC_USE_* flags
|
||||
* \param[in] dsf Pointer to down-sampling factors.
|
||||
* \param[in] ver ABI version number. Must be set to
|
||||
* VPX_ENCODER_ABI_VERSION
|
||||
* \retval #VPX_CODEC_OK
|
||||
* The decoder algorithm initialized.
|
||||
* \retval #VPX_CODEC_MEM_ERROR
|
||||
* Memory allocation failed.
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_enc_init_multi_ver(vpx_codec_ctx_t *ctx,
|
||||
vpx_codec_iface_t *iface,
|
||||
vpx_codec_enc_cfg_t *cfg,
|
||||
int num_enc,
|
||||
vpx_codec_flags_t flags,
|
||||
vpx_rational_t *dsf,
|
||||
int ver);
|
||||
|
||||
|
||||
/*!\brief Convenience macro for vpx_codec_enc_init_multi_ver()
|
||||
*
|
||||
* Ensures the ABI version parameter is properly set.
|
||||
*/
|
||||
#define vpx_codec_enc_init_multi(ctx, iface, cfg, num_enc, flags, dsf) \
|
||||
vpx_codec_enc_init_multi_ver(ctx, iface, cfg, num_enc, flags, dsf, \
|
||||
VPX_ENCODER_ABI_VERSION)
|
||||
|
||||
|
||||
/*!\brief Get a default configuration
|
||||
*
|
||||
* Initializes a encoder configuration structure with default values. Supports
|
||||
* the notion of "usages" so that an algorithm may offer different default
|
||||
* settings depending on the user's intended goal. This function \ref SHOULD
|
||||
* be called by all applications to initialize the configuration structure
|
||||
* before specializing the configuration with application specific values.
|
||||
*
|
||||
* \param[in] iface Pointer to the algorithm interface to use.
|
||||
* \param[out] cfg Configuration buffer to populate
|
||||
* \param[in] usage End usage. Set to 0 or use codec specific values.
|
||||
*
|
||||
* \retval #VPX_CODEC_OK
|
||||
* The configuration was populated.
|
||||
* \retval #VPX_CODEC_INCAPABLE
|
||||
* Interface is not an encoder interface.
|
||||
* \retval #VPX_CODEC_INVALID_PARAM
|
||||
* A parameter was NULL, or the usage value was not recognized.
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_enc_config_default(vpx_codec_iface_t *iface,
|
||||
vpx_codec_enc_cfg_t *cfg,
|
||||
unsigned int usage);
|
||||
|
||||
|
||||
/*!\brief Set or change configuration
|
||||
*
|
||||
* Reconfigures an encoder instance according to the given configuration.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context
|
||||
* \param[in] cfg Configuration buffer to use
|
||||
*
|
||||
* \retval #VPX_CODEC_OK
|
||||
* The configuration was populated.
|
||||
* \retval #VPX_CODEC_INCAPABLE
|
||||
* Interface is not an encoder interface.
|
||||
* \retval #VPX_CODEC_INVALID_PARAM
|
||||
* A parameter was NULL, or the usage value was not recognized.
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_enc_config_set(vpx_codec_ctx_t *ctx,
|
||||
const vpx_codec_enc_cfg_t *cfg);
|
||||
|
||||
|
||||
/*!\brief Get global stream headers
|
||||
*
|
||||
* Retrieves a stream level global header packet, if supported by the codec.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context
|
||||
*
|
||||
* \retval NULL
|
||||
* Encoder does not support global header
|
||||
* \retval Non-NULL
|
||||
* Pointer to buffer containing global header packet
|
||||
*/
|
||||
vpx_fixed_buf_t *vpx_codec_get_global_headers(vpx_codec_ctx_t *ctx);
|
||||
|
||||
|
||||
#define VPX_DL_REALTIME (1) /**< deadline parameter analogous to
|
||||
* VPx REALTIME mode. */
|
||||
#define VPX_DL_GOOD_QUALITY (1000000) /**< deadline parameter analogous to
|
||||
* VPx GOOD QUALITY mode. */
|
||||
#define VPX_DL_BEST_QUALITY (0) /**< deadline parameter analogous to
|
||||
* VPx BEST QUALITY mode. */
|
||||
/*!\brief Encode a frame
|
||||
*
|
||||
* Encodes a video frame at the given "presentation time." The presentation
|
||||
* time stamp (PTS) \ref MUST be strictly increasing.
|
||||
*
|
||||
* The encoder supports the notion of a soft real-time deadline. Given a
|
||||
* non-zero value to the deadline parameter, the encoder will make a "best
|
||||
* effort" guarantee to return before the given time slice expires. It is
|
||||
* implicit that limiting the available time to encode will degrade the
|
||||
* output quality. The encoder can be given an unlimited time to produce the
|
||||
* best possible frame by specifying a deadline of '0'. This deadline
|
||||
* supercedes the VPx notion of "best quality, good quality, realtime".
|
||||
* Applications that wish to map these former settings to the new deadline
|
||||
* based system can use the symbols #VPX_DL_REALTIME, #VPX_DL_GOOD_QUALITY,
|
||||
* and #VPX_DL_BEST_QUALITY.
|
||||
*
|
||||
* When the last frame has been passed to the encoder, this function should
|
||||
* continue to be called, with the img parameter set to NULL. This will
|
||||
* signal the end-of-stream condition to the encoder and allow it to encode
|
||||
* any held buffers. Encoding is complete when vpx_codec_encode() is called
|
||||
* and vpx_codec_get_cx_data() returns no data.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context
|
||||
* \param[in] img Image data to encode, NULL to flush.
|
||||
* \param[in] pts Presentation time stamp, in timebase units.
|
||||
* \param[in] duration Duration to show frame, in timebase units.
|
||||
* \param[in] flags Flags to use for encoding this frame.
|
||||
* \param[in] deadline Time to spend encoding, in microseconds. (0=infinite)
|
||||
*
|
||||
* \retval #VPX_CODEC_OK
|
||||
* The configuration was populated.
|
||||
* \retval #VPX_CODEC_INCAPABLE
|
||||
* Interface is not an encoder interface.
|
||||
* \retval #VPX_CODEC_INVALID_PARAM
|
||||
* A parameter was NULL, the image format is unsupported, etc.
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_encode(vpx_codec_ctx_t *ctx,
|
||||
const vpx_image_t *img,
|
||||
vpx_codec_pts_t pts,
|
||||
unsigned long duration,
|
||||
vpx_enc_frame_flags_t flags,
|
||||
unsigned long deadline);
|
||||
|
||||
/*!\brief Set compressed data output buffer
|
||||
*
|
||||
* Sets the buffer that the codec should output the compressed data
|
||||
* into. This call effectively sets the buffer pointer returned in the
|
||||
* next VPX_CODEC_CX_FRAME_PKT packet. Subsequent packets will be
|
||||
* appended into this buffer. The buffer is preserved across frames,
|
||||
* so applications must periodically call this function after flushing
|
||||
* the accumulated compressed data to disk or to the network to reset
|
||||
* the pointer to the buffer's head.
|
||||
*
|
||||
* `pad_before` bytes will be skipped before writing the compressed
|
||||
* data, and `pad_after` bytes will be appended to the packet. The size
|
||||
* of the packet will be the sum of the size of the actual compressed
|
||||
* data, pad_before, and pad_after. The padding bytes will be preserved
|
||||
* (not overwritten).
|
||||
*
|
||||
* Note that calling this function does not guarantee that the returned
|
||||
* compressed data will be placed into the specified buffer. In the
|
||||
* event that the encoded data will not fit into the buffer provided,
|
||||
* the returned packet \ref MAY point to an internal buffer, as it would
|
||||
* if this call were never used. In this event, the output packet will
|
||||
* NOT have any padding, and the application must free space and copy it
|
||||
* to the proper place. This is of particular note in configurations
|
||||
* that may output multiple packets for a single encoded frame (e.g., lagged
|
||||
* encoding) or if the application does not reset the buffer periodically.
|
||||
*
|
||||
* Applications may restore the default behavior of the codec providing
|
||||
* the compressed data buffer by calling this function with a NULL
|
||||
* buffer.
|
||||
*
|
||||
* Applications \ref MUSTNOT call this function during iteration of
|
||||
* vpx_codec_get_cx_data().
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context
|
||||
* \param[in] buf Buffer to store compressed data into
|
||||
* \param[in] pad_before Bytes to skip before writing compressed data
|
||||
* \param[in] pad_after Bytes to skip after writing compressed data
|
||||
*
|
||||
* \retval #VPX_CODEC_OK
|
||||
* The buffer was set successfully.
|
||||
* \retval #VPX_CODEC_INVALID_PARAM
|
||||
* A parameter was NULL, the image format is unsupported, etc.
|
||||
*/
|
||||
vpx_codec_err_t vpx_codec_set_cx_data_buf(vpx_codec_ctx_t *ctx,
|
||||
const vpx_fixed_buf_t *buf,
|
||||
unsigned int pad_before,
|
||||
unsigned int pad_after);
|
||||
|
||||
|
||||
/*!\brief Encoded data iterator
|
||||
*
|
||||
* Iterates over a list of data packets to be passed from the encoder to the
|
||||
* application. The different kinds of packets available are enumerated in
|
||||
* #vpx_codec_cx_pkt_kind.
|
||||
*
|
||||
* #VPX_CODEC_CX_FRAME_PKT packets should be passed to the application's
|
||||
* muxer. Multiple compressed frames may be in the list.
|
||||
* #VPX_CODEC_STATS_PKT packets should be appended to a global buffer.
|
||||
*
|
||||
* The application \ref MUST silently ignore any packet kinds that it does
|
||||
* not recognize or support.
|
||||
*
|
||||
* The data buffers returned from this function are only guaranteed to be
|
||||
* valid until the application makes another call to any vpx_codec_* function.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context
|
||||
* \param[in,out] iter Iterator storage, initialized to NULL
|
||||
*
|
||||
* \return Returns a pointer to an output data packet (compressed frame data,
|
||||
* two-pass statistics, etc.) or NULL to signal end-of-list.
|
||||
*
|
||||
*/
|
||||
const vpx_codec_cx_pkt_t *vpx_codec_get_cx_data(vpx_codec_ctx_t *ctx,
|
||||
vpx_codec_iter_t *iter);
|
||||
|
||||
|
||||
/*!\brief Get Preview Frame
|
||||
*
|
||||
* Returns an image that can be used as a preview. Shows the image as it would
|
||||
* exist at the decompressor. The application \ref MUST NOT write into this
|
||||
* image buffer.
|
||||
*
|
||||
* \param[in] ctx Pointer to this instance's context
|
||||
*
|
||||
* \return Returns a pointer to a preview image, or NULL if no image is
|
||||
* available.
|
||||
*
|
||||
*/
|
||||
const vpx_image_t *vpx_codec_get_preview_frame(vpx_codec_ctx_t *ctx);
|
||||
|
||||
|
||||
/*!@} - end defgroup encoder*/
|
||||
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
243
interface/external/LibVPX/include/vpx_image.h
vendored
Normal file
243
interface/external/LibVPX/include/vpx_image.h
vendored
Normal file
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
/*!\file
|
||||
* \brief Describes the vpx image descriptor and associated operations
|
||||
*
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef VPX_IMAGE_H
|
||||
#define VPX_IMAGE_H
|
||||
|
||||
/*!\brief Current ABI version number
|
||||
*
|
||||
* \internal
|
||||
* If this file is altered in any way that changes the ABI, this value
|
||||
* must be bumped. Examples include, but are not limited to, changing
|
||||
* types, removing or reassigning enums, adding/removing/rearranging
|
||||
* fields to structures
|
||||
*/
|
||||
#define VPX_IMAGE_ABI_VERSION (1) /**<\hideinitializer*/
|
||||
|
||||
|
||||
#define VPX_IMG_FMT_PLANAR 0x100 /**< Image is a planar format */
|
||||
#define VPX_IMG_FMT_UV_FLIP 0x200 /**< V plane precedes U plane in memory */
|
||||
#define VPX_IMG_FMT_HAS_ALPHA 0x400 /**< Image has an alpha channel component */
|
||||
|
||||
|
||||
/*!\brief List of supported image formats */
|
||||
typedef enum vpx_img_fmt {
|
||||
VPX_IMG_FMT_NONE,
|
||||
VPX_IMG_FMT_RGB24, /**< 24 bit per pixel packed RGB */
|
||||
VPX_IMG_FMT_RGB32, /**< 32 bit per pixel packed 0RGB */
|
||||
VPX_IMG_FMT_RGB565, /**< 16 bit per pixel, 565 */
|
||||
VPX_IMG_FMT_RGB555, /**< 16 bit per pixel, 555 */
|
||||
VPX_IMG_FMT_UYVY, /**< UYVY packed YUV */
|
||||
VPX_IMG_FMT_YUY2, /**< YUYV packed YUV */
|
||||
VPX_IMG_FMT_YVYU, /**< YVYU packed YUV */
|
||||
VPX_IMG_FMT_BGR24, /**< 24 bit per pixel packed BGR */
|
||||
VPX_IMG_FMT_RGB32_LE, /**< 32 bit packed BGR0 */
|
||||
VPX_IMG_FMT_ARGB, /**< 32 bit packed ARGB, alpha=255 */
|
||||
VPX_IMG_FMT_ARGB_LE, /**< 32 bit packed BGRA, alpha=255 */
|
||||
VPX_IMG_FMT_RGB565_LE, /**< 16 bit per pixel, gggbbbbb rrrrrggg */
|
||||
VPX_IMG_FMT_RGB555_LE, /**< 16 bit per pixel, gggbbbbb 0rrrrrgg */
|
||||
VPX_IMG_FMT_YV12 = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_UV_FLIP | 1, /**< planar YVU */
|
||||
VPX_IMG_FMT_I420 = VPX_IMG_FMT_PLANAR | 2,
|
||||
VPX_IMG_FMT_VPXYV12 = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_UV_FLIP | 3, /** < planar 4:2:0 format with vpx color space */
|
||||
VPX_IMG_FMT_VPXI420 = VPX_IMG_FMT_PLANAR | 4,
|
||||
VPX_IMG_FMT_I422 = VPX_IMG_FMT_PLANAR | 5,
|
||||
VPX_IMG_FMT_I444 = VPX_IMG_FMT_PLANAR | 6,
|
||||
VPX_IMG_FMT_444A = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_HAS_ALPHA | 7
|
||||
} vpx_img_fmt_t; /**< alias for enum vpx_img_fmt */
|
||||
|
||||
#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
|
||||
#define IMG_FMT_PLANAR VPX_IMG_FMT_PLANAR /**< \deprecated Use #VPX_IMG_FMT_PLANAR */
|
||||
#define IMG_FMT_UV_FLIP VPX_IMG_FMT_UV_FLIP /**< \deprecated Use #VPX_IMG_FMT_UV_FLIP */
|
||||
#define IMG_FMT_HAS_ALPHA VPX_IMG_FMT_HAS_ALPHA /**< \deprecated Use #VPX_IMG_FMT_HAS_ALPHA */
|
||||
|
||||
/*!\brief Deprecated list of supported image formats
|
||||
* \deprecated New code should use #vpx_img_fmt
|
||||
*/
|
||||
#define img_fmt vpx_img_fmt
|
||||
/*!\brief alias for enum img_fmt.
|
||||
* \deprecated New code should use #vpx_img_fmt_t
|
||||
*/
|
||||
#define img_fmt_t vpx_img_fmt_t
|
||||
|
||||
#define IMG_FMT_NONE VPX_IMG_FMT_NONE /**< \deprecated Use #VPX_IMG_FMT_NONE */
|
||||
#define IMG_FMT_RGB24 VPX_IMG_FMT_RGB24 /**< \deprecated Use #VPX_IMG_FMT_RGB24 */
|
||||
#define IMG_FMT_RGB32 VPX_IMG_FMT_RGB32 /**< \deprecated Use #VPX_IMG_FMT_RGB32 */
|
||||
#define IMG_FMT_RGB565 VPX_IMG_FMT_RGB565 /**< \deprecated Use #VPX_IMG_FMT_RGB565 */
|
||||
#define IMG_FMT_RGB555 VPX_IMG_FMT_RGB555 /**< \deprecated Use #VPX_IMG_FMT_RGB555 */
|
||||
#define IMG_FMT_UYVY VPX_IMG_FMT_UYVY /**< \deprecated Use #VPX_IMG_FMT_UYVY */
|
||||
#define IMG_FMT_YUY2 VPX_IMG_FMT_YUY2 /**< \deprecated Use #VPX_IMG_FMT_YUY2 */
|
||||
#define IMG_FMT_YVYU VPX_IMG_FMT_YVYU /**< \deprecated Use #VPX_IMG_FMT_YVYU */
|
||||
#define IMG_FMT_BGR24 VPX_IMG_FMT_BGR24 /**< \deprecated Use #VPX_IMG_FMT_BGR24 */
|
||||
#define IMG_FMT_RGB32_LE VPX_IMG_FMT_RGB32_LE /**< \deprecated Use #VPX_IMG_FMT_RGB32_LE */
|
||||
#define IMG_FMT_ARGB VPX_IMG_FMT_ARGB /**< \deprecated Use #VPX_IMG_FMT_ARGB */
|
||||
#define IMG_FMT_ARGB_LE VPX_IMG_FMT_ARGB_LE /**< \deprecated Use #VPX_IMG_FMT_ARGB_LE */
|
||||
#define IMG_FMT_RGB565_LE VPX_IMG_FMT_RGB565_LE /**< \deprecated Use #VPX_IMG_FMT_RGB565_LE */
|
||||
#define IMG_FMT_RGB555_LE VPX_IMG_FMT_RGB555_LE /**< \deprecated Use #VPX_IMG_FMT_RGB555_LE */
|
||||
#define IMG_FMT_YV12 VPX_IMG_FMT_YV12 /**< \deprecated Use #VPX_IMG_FMT_YV12 */
|
||||
#define IMG_FMT_I420 VPX_IMG_FMT_I420 /**< \deprecated Use #VPX_IMG_FMT_I420 */
|
||||
#define IMG_FMT_VPXYV12 VPX_IMG_FMT_VPXYV12 /**< \deprecated Use #VPX_IMG_FMT_VPXYV12 */
|
||||
#define IMG_FMT_VPXI420 VPX_IMG_FMT_VPXI420 /**< \deprecated Use #VPX_IMG_FMT_VPXI420 */
|
||||
#endif /* VPX_CODEC_DISABLE_COMPAT */
|
||||
|
||||
/**\brief Image Descriptor */
|
||||
typedef struct vpx_image {
|
||||
vpx_img_fmt_t fmt; /**< Image Format */
|
||||
|
||||
/* Image storage dimensions */
|
||||
unsigned int w; /**< Stored image width */
|
||||
unsigned int h; /**< Stored image height */
|
||||
|
||||
/* Image display dimensions */
|
||||
unsigned int d_w; /**< Displayed image width */
|
||||
unsigned int d_h; /**< Displayed image height */
|
||||
|
||||
/* Chroma subsampling info */
|
||||
unsigned int x_chroma_shift; /**< subsampling order, X */
|
||||
unsigned int y_chroma_shift; /**< subsampling order, Y */
|
||||
|
||||
/* Image data pointers. */
|
||||
#define VPX_PLANE_PACKED 0 /**< To be used for all packed formats */
|
||||
#define VPX_PLANE_Y 0 /**< Y (Luminance) plane */
|
||||
#define VPX_PLANE_U 1 /**< U (Chroma) plane */
|
||||
#define VPX_PLANE_V 2 /**< V (Chroma) plane */
|
||||
#define VPX_PLANE_ALPHA 3 /**< A (Transparency) plane */
|
||||
#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
|
||||
#define PLANE_PACKED VPX_PLANE_PACKED
|
||||
#define PLANE_Y VPX_PLANE_Y
|
||||
#define PLANE_U VPX_PLANE_U
|
||||
#define PLANE_V VPX_PLANE_V
|
||||
#define PLANE_ALPHA VPX_PLANE_ALPHA
|
||||
#endif
|
||||
unsigned char *planes[4]; /**< pointer to the top left pixel for each plane */
|
||||
int stride[4]; /**< stride between rows for each plane */
|
||||
|
||||
int bps; /**< bits per sample (for packed formats) */
|
||||
|
||||
/* The following member may be set by the application to associate data
|
||||
* with this image.
|
||||
*/
|
||||
void *user_priv; /**< may be set by the application to associate data
|
||||
* with this image. */
|
||||
|
||||
/* The following members should be treated as private. */
|
||||
unsigned char *img_data; /**< private */
|
||||
int img_data_owner; /**< private */
|
||||
int self_allocd; /**< private */
|
||||
} vpx_image_t; /**< alias for struct vpx_image */
|
||||
|
||||
/**\brief Representation of a rectangle on a surface */
|
||||
typedef struct vpx_image_rect {
|
||||
unsigned int x; /**< leftmost column */
|
||||
unsigned int y; /**< topmost row */
|
||||
unsigned int w; /**< width */
|
||||
unsigned int h; /**< height */
|
||||
} vpx_image_rect_t; /**< alias for struct vpx_image_rect */
|
||||
|
||||
/*!\brief Open a descriptor, allocating storage for the underlying image
|
||||
*
|
||||
* Returns a descriptor for storing an image of the given format. The
|
||||
* storage for the descriptor is allocated on the heap.
|
||||
*
|
||||
* \param[in] img Pointer to storage for descriptor. If this parameter
|
||||
* is NULL, the storage for the descriptor will be
|
||||
* allocated on the heap.
|
||||
* \param[in] fmt Format for the image
|
||||
* \param[in] d_w Width of the image
|
||||
* \param[in] d_h Height of the image
|
||||
* \param[in] align Alignment, in bytes, of the image buffer and
|
||||
* each row in the image(stride).
|
||||
*
|
||||
* \return Returns a pointer to the initialized image descriptor. If the img
|
||||
* parameter is non-null, the value of the img parameter will be
|
||||
* returned.
|
||||
*/
|
||||
vpx_image_t *vpx_img_alloc(vpx_image_t *img,
|
||||
vpx_img_fmt_t fmt,
|
||||
unsigned int d_w,
|
||||
unsigned int d_h,
|
||||
unsigned int align);
|
||||
|
||||
/*!\brief Open a descriptor, using existing storage for the underlying image
|
||||
*
|
||||
* Returns a descriptor for storing an image of the given format. The
|
||||
* storage for descriptor has been allocated elsewhere, and a descriptor is
|
||||
* desired to "wrap" that storage.
|
||||
*
|
||||
* \param[in] img Pointer to storage for descriptor. If this parameter
|
||||
* is NULL, the storage for the descriptor will be
|
||||
* allocated on the heap.
|
||||
* \param[in] fmt Format for the image
|
||||
* \param[in] d_w Width of the image
|
||||
* \param[in] d_h Height of the image
|
||||
* \param[in] align Alignment, in bytes, of each row in the image.
|
||||
* \param[in] img_data Storage to use for the image
|
||||
*
|
||||
* \return Returns a pointer to the initialized image descriptor. If the img
|
||||
* parameter is non-null, the value of the img parameter will be
|
||||
* returned.
|
||||
*/
|
||||
vpx_image_t *vpx_img_wrap(vpx_image_t *img,
|
||||
vpx_img_fmt_t fmt,
|
||||
unsigned int d_w,
|
||||
unsigned int d_h,
|
||||
unsigned int align,
|
||||
unsigned char *img_data);
|
||||
|
||||
|
||||
/*!\brief Set the rectangle identifying the displayed portion of the image
|
||||
*
|
||||
* Updates the displayed rectangle (aka viewport) on the image surface to
|
||||
* match the specified coordinates and size.
|
||||
*
|
||||
* \param[in] img Image descriptor
|
||||
* \param[in] x leftmost column
|
||||
* \param[in] y topmost row
|
||||
* \param[in] w width
|
||||
* \param[in] h height
|
||||
*
|
||||
* \return 0 if the requested rectangle is valid, nonzero otherwise.
|
||||
*/
|
||||
int vpx_img_set_rect(vpx_image_t *img,
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
unsigned int w,
|
||||
unsigned int h);
|
||||
|
||||
|
||||
/*!\brief Flip the image vertically (top for bottom)
|
||||
*
|
||||
* Adjusts the image descriptor's pointers and strides to make the image
|
||||
* be referenced upside-down.
|
||||
*
|
||||
* \param[in] img Image descriptor
|
||||
*/
|
||||
void vpx_img_flip(vpx_image_t *img);
|
||||
|
||||
/*!\brief Close an image descriptor
|
||||
*
|
||||
* Frees all allocated storage associated with an image descriptor.
|
||||
*
|
||||
* \param[in] img Image descriptor
|
||||
*/
|
||||
void vpx_img_free(vpx_image_t *img);
|
||||
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
57
interface/external/LibVPX/include/vpx_integer.h
vendored
Normal file
57
interface/external/LibVPX/include/vpx_integer.h
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef VPX_INTEGER_H
|
||||
#define VPX_INTEGER_H
|
||||
|
||||
/* get ptrdiff_t, size_t, wchar_t, NULL */
|
||||
#include <stddef.h>
|
||||
|
||||
#if (defined(_MSC_VER) && (_MSC_VER < 1600)) || defined(VPX_EMULATE_INTTYPES)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
|
||||
#if (defined(_MSC_VER) && (_MSC_VER < 1600))
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT16_MIN _I16_MIN
|
||||
#endif
|
||||
|
||||
#ifndef _UINTPTR_T_DEFINED
|
||||
typedef size_t uintptr_t;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/* Most platforms have the C99 standard integer types. */
|
||||
|
||||
#if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS)
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#endif
|
||||
|
||||
/* VS2010 defines stdint.h, but not inttypes.h */
|
||||
#if defined(_MSC_VER)
|
||||
#define PRId64 "I64d"
|
||||
#else
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#endif
|
BIN
interface/external/LibVPX/lib/MacOS/libvpx.a
vendored
Normal file
BIN
interface/external/LibVPX/lib/MacOS/libvpx.a
vendored
Normal file
Binary file not shown.
BIN
interface/external/LibVPX/lib/UNIX/libvpx.a
vendored
Normal file
BIN
interface/external/LibVPX/lib/UNIX/libvpx.a
vendored
Normal file
Binary file not shown.
17
interface/resources/shaders/face.frag
Normal file
17
interface/resources/shaders/face.frag
Normal file
|
@ -0,0 +1,17 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// face.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 7/12/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
// the color texture
|
||||
uniform sampler2D colorTexture;
|
||||
|
||||
void main(void) {
|
||||
// for now, just modulate color
|
||||
gl_FragColor = gl_Color * texture2D(colorTexture, gl_TexCoord[0].st);
|
||||
}
|
36
interface/resources/shaders/face.vert
Normal file
36
interface/resources/shaders/face.vert
Normal file
|
@ -0,0 +1,36 @@
|
|||
#version 120
|
||||
|
||||
//
|
||||
// face.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Andrzej Kapolka on 7/12/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
// the lower left texture coordinate
|
||||
uniform vec2 texCoordCorner;
|
||||
|
||||
// the texture coordinate vector from left to right
|
||||
uniform vec2 texCoordRight;
|
||||
|
||||
// the texture coordinate vector from bottom to the top
|
||||
uniform vec2 texCoordUp;
|
||||
|
||||
// the aspect ratio of the image
|
||||
uniform float aspectRatio;
|
||||
|
||||
// the depth texture
|
||||
uniform sampler2D depthTexture;
|
||||
|
||||
void main(void) {
|
||||
gl_TexCoord[0] = vec4(texCoordCorner + gl_Vertex.x * texCoordRight + gl_Vertex.y * texCoordUp, 0.0, 1.0);
|
||||
float depth = texture2D(depthTexture, gl_TexCoord[0].st).r;
|
||||
|
||||
// set alpha to zero for invalid depth values
|
||||
const float MIN_VISIBLE_DEPTH = 1.0 / 255.0;
|
||||
const float MAX_VISIBLE_DEPTH = 254.0 / 255.0;
|
||||
gl_FrontColor = vec4(1.0, 1.0, 1.0, step(MIN_VISIBLE_DEPTH, depth) * (1.0 - step(MAX_VISIBLE_DEPTH, depth)));
|
||||
gl_Position = gl_ModelViewProjectionMatrix * vec4(0.5 - gl_Vertex.x,
|
||||
(gl_Vertex.y - 0.5) / aspectRatio, depth * 2.0 - 2.0, 1.0);
|
||||
}
|
|
@ -199,6 +199,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
_mousePressed(false),
|
||||
_mouseVoxelScale(1.0f / 1024.0f),
|
||||
_justEditedVoxel(false),
|
||||
_isLookingAtOtherAvatar(false),
|
||||
_paintOn(false),
|
||||
_dominantColor(0),
|
||||
_perfStatsOn(false),
|
||||
|
@ -235,6 +236,31 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
NodeList::getInstance()->getNodeSocket()->setBlocking(false);
|
||||
}
|
||||
|
||||
// setup QSettings
|
||||
#ifdef Q_WS_MAC
|
||||
QString resourcesPath = QCoreApplication::applicationDirPath() + "/../Resources";
|
||||
#else
|
||||
QString resourcesPath = QCoreApplication::applicationDirPath() + "/resources";
|
||||
#endif
|
||||
|
||||
// read the ApplicationInfo.ini file for Name/Version/Domain information
|
||||
QSettings applicationInfo(resourcesPath + "/info/ApplicationInfo.ini", QSettings::IniFormat);
|
||||
|
||||
// set the associated application properties
|
||||
applicationInfo.beginGroup("INFO");
|
||||
|
||||
setApplicationName(applicationInfo.value("name").toString());
|
||||
setApplicationVersion(applicationInfo.value("version").toString());
|
||||
setOrganizationName(applicationInfo.value("organizationName").toString());
|
||||
setOrganizationDomain(applicationInfo.value("organizationDomain").toString());
|
||||
|
||||
_settings = new QSettings(this);
|
||||
|
||||
// check if there is a saved domain server hostname
|
||||
// this must be done now instead of with the other setting checks to allow manual override with
|
||||
// --domain or --local options
|
||||
NodeList::getInstance()->loadData(_settings);
|
||||
|
||||
const char* domainIP = getCmdOption(argc, constArgv, "--domain");
|
||||
if (domainIP) {
|
||||
NodeList::getInstance()->setDomainIP(domainIP);
|
||||
|
@ -268,23 +294,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
|
||||
_window->setCentralWidget(_glWidget);
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
QString resourcesPath = QCoreApplication::applicationDirPath() + "/../Resources";
|
||||
#else
|
||||
QString resourcesPath = QCoreApplication::applicationDirPath() + "/resources";
|
||||
#endif
|
||||
|
||||
// read the ApplicationInfo.ini file for Name/Version/Domain information
|
||||
QSettings applicationInfo(resourcesPath + "/info/ApplicationInfo.ini", QSettings::IniFormat);
|
||||
|
||||
// set the associated application properties
|
||||
applicationInfo.beginGroup("INFO");
|
||||
|
||||
setApplicationName(applicationInfo.value("name").toString());
|
||||
setApplicationVersion(applicationInfo.value("version").toString());
|
||||
setOrganizationName(applicationInfo.value("organizationName").toString());
|
||||
setOrganizationDomain(applicationInfo.value("organizationDomain").toString());
|
||||
|
||||
#if defined(Q_WS_MAC) && defined(QT_NO_DEBUG)
|
||||
// if this is a release OS X build use fervor to check for an update
|
||||
FvUpdater::sharedUpdater()->SetFeedURL("https://s3-us-west-1.amazonaws.com/highfidelity/appcast.xml");
|
||||
|
@ -929,6 +938,36 @@ void Application::sendPingPackets() {
|
|||
nodesToPing, sizeof(nodesToPing));
|
||||
}
|
||||
|
||||
void Application::sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data) {
|
||||
unsigned char packet[MAX_PACKET_SIZE];
|
||||
unsigned char* packetPosition = packet;
|
||||
|
||||
packetPosition += populateTypeAndVersion(packetPosition, PACKET_TYPE_AVATAR_FACE_VIDEO);
|
||||
|
||||
*(uint16_t*)packetPosition = NodeList::getInstance()->getOwnerID();
|
||||
packetPosition += sizeof(uint16_t);
|
||||
|
||||
*(uint32_t*)packetPosition = frameCount;
|
||||
packetPosition += sizeof(uint32_t);
|
||||
|
||||
*(uint32_t*)packetPosition = data.size();
|
||||
packetPosition += sizeof(uint32_t);
|
||||
|
||||
uint32_t* offsetPosition = (uint32_t*)packetPosition;
|
||||
packetPosition += sizeof(uint32_t);
|
||||
|
||||
int headerSize = packetPosition - packet;
|
||||
|
||||
// break the data up into submessages of the maximum size
|
||||
*offsetPosition = 0;
|
||||
while (*offsetPosition < data.size()) {
|
||||
int payloadSize = min(data.size() - (int)*offsetPosition, MAX_PACKET_SIZE - headerSize);
|
||||
memcpy(packetPosition, data.constData() + *offsetPosition, payloadSize);
|
||||
getInstance()->controlledBroadcastToNodes(packet, headerSize + payloadSize, &NODE_TYPE_AVATAR_MIXER, 1);
|
||||
*offsetPosition += payloadSize;
|
||||
}
|
||||
}
|
||||
|
||||
// Every second, check the frame rates and other stuff
|
||||
void Application::timer() {
|
||||
gettimeofday(&_timerEnd, NULL);
|
||||
|
@ -1038,7 +1077,7 @@ void Application::sendAvatarVoxelURLMessage(const QUrl& url) {
|
|||
controlledBroadcastToNodes((unsigned char*)message.data(), message.size(), & NODE_TYPE_AVATAR_MIXER, 1);
|
||||
}
|
||||
|
||||
void Application::processAvatarVoxelURLMessage(unsigned char *packetData, size_t dataBytes) {
|
||||
static Avatar* processAvatarMessageHeader(unsigned char*& packetData, size_t& dataBytes) {
|
||||
// skip the header
|
||||
int numBytesPacketHeader = numBytesForPacketHeader(packetData);
|
||||
packetData += numBytesPacketHeader;
|
||||
|
@ -1052,18 +1091,31 @@ void Application::processAvatarVoxelURLMessage(unsigned char *packetData, size_t
|
|||
// make sure the node exists
|
||||
Node* node = NodeList::getInstance()->nodeWithID(nodeID);
|
||||
if (!node || !node->getLinkedData()) {
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
Avatar* avatar = static_cast<Avatar*>(node->getLinkedData());
|
||||
if (!avatar->isInitialized()) {
|
||||
return; // wait until initialized
|
||||
}
|
||||
return avatar->isInitialized() ? avatar : NULL;
|
||||
}
|
||||
|
||||
void Application::processAvatarVoxelURLMessage(unsigned char* packetData, size_t dataBytes) {
|
||||
Avatar* avatar = processAvatarMessageHeader(packetData, dataBytes);
|
||||
if (!avatar) {
|
||||
return;
|
||||
}
|
||||
QUrl url = QUrl::fromEncoded(QByteArray((char*)packetData, dataBytes));
|
||||
|
||||
// invoke the set URL function on the simulate/render thread
|
||||
QMetaObject::invokeMethod(avatar->getVoxels(), "setVoxelURL", Q_ARG(QUrl, url));
|
||||
}
|
||||
|
||||
void Application::processAvatarFaceVideoMessage(unsigned char* packetData, size_t dataBytes) {
|
||||
Avatar* avatar = processAvatarMessageHeader(packetData, dataBytes);
|
||||
if (!avatar) {
|
||||
return;
|
||||
}
|
||||
avatar->getHead().getFace().processVideoMessage(packetData, dataBytes);
|
||||
}
|
||||
|
||||
void Application::checkBandwidthMeterClick() {
|
||||
// ... to be called upon button release
|
||||
|
||||
|
@ -1143,26 +1195,29 @@ void Application::editPreferences() {
|
|||
return;
|
||||
}
|
||||
|
||||
QByteArray newHostname;
|
||||
|
||||
const char* newHostname = domainServerHostname->text().toLocal8Bit().data();
|
||||
|
||||
if (domainServerHostname->text().size() > 0) {
|
||||
// the user input a new hostname, use that
|
||||
newHostname = domainServerHostname->text().toAscii();
|
||||
} else {
|
||||
// the user left the field blank, use the default hostname
|
||||
newHostname = QByteArray(DEFAULT_DOMAIN_HOSTNAME);
|
||||
}
|
||||
|
||||
// check if the domain server hostname is new
|
||||
if (memcmp(NodeList::getInstance()->getDomainHostname(), newHostname, sizeof(&newHostname)) != 0) {
|
||||
// if so we need to clear the nodelist and delete the local voxels
|
||||
Node *voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER);
|
||||
|
||||
if (voxelServer) {
|
||||
voxelServer->lock();
|
||||
}
|
||||
|
||||
_voxels.killLocalVoxels();
|
||||
|
||||
if (voxelServer) {
|
||||
voxelServer->unlock();
|
||||
}
|
||||
if (memcmp(NodeList::getInstance()->getDomainHostname(), newHostname.constData(), newHostname.size()) != 0) {
|
||||
|
||||
NodeList::getInstance()->clear();
|
||||
NodeList::getInstance()->setDomainHostname(newHostname);
|
||||
|
||||
// kill the local voxels
|
||||
_voxels.killLocalVoxels();
|
||||
|
||||
// reset the environment to default
|
||||
_environment.resetToDefault();
|
||||
|
||||
// set the new hostname
|
||||
NodeList::getInstance()->setDomainHostname(newHostname.constData());
|
||||
}
|
||||
|
||||
QUrl url(avatarURL->text());
|
||||
|
@ -1670,10 +1725,13 @@ void Application::initMenu() {
|
|||
(_renderAvatarBalls = renderMenu->addAction("Avatar as Balls"))->setCheckable(true);
|
||||
_renderAvatarBalls->setChecked(false);
|
||||
renderMenu->addAction("Cycle Voxel Mode", _myAvatar.getVoxels(), SLOT(cycleMode()));
|
||||
renderMenu->addAction("Cycle Face Mode", &_myAvatar.getHead().getFace(), SLOT(cycleRenderMode()));
|
||||
(_renderFrameTimerOn = renderMenu->addAction("Show Timer"))->setCheckable(true);
|
||||
_renderFrameTimerOn->setChecked(false);
|
||||
(_renderLookatOn = renderMenu->addAction("Lookat Vectors"))->setCheckable(true);
|
||||
_renderLookatOn->setChecked(false);
|
||||
(_renderLookatIndicatorOn = renderMenu->addAction("Lookat Indicator"))->setCheckable(true);
|
||||
_renderLookatIndicatorOn->setChecked(true);
|
||||
(_manualFirstPerson = renderMenu->addAction(
|
||||
"First Person", this, SLOT(setRenderFirstPerson(bool)), Qt::Key_P))->setCheckable(true);
|
||||
(_manualThirdPerson = renderMenu->addAction(
|
||||
|
@ -1786,7 +1844,6 @@ void Application::initMenu() {
|
|||
settingsMenu->addAction("Export settings", this, SLOT(exportSettings()));
|
||||
|
||||
_networkAccessManager = new QNetworkAccessManager(this);
|
||||
_settings = new QSettings(this);
|
||||
}
|
||||
|
||||
void Application::updateFrustumRenderModeAction() {
|
||||
|
@ -1885,6 +1942,7 @@ bool Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& m
|
|||
glm::vec3 headPosition = avatar->getHead().getPosition();
|
||||
if (rayIntersectsSphere(mouseRayOrigin, mouseRayDirection, headPosition, HEAD_SPHERE_RADIUS)) {
|
||||
eyePosition = avatar->getHead().getEyeLevelPosition();
|
||||
_lookatOtherPosition = headPosition;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1892,6 +1950,15 @@ bool Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& m
|
|||
return false;
|
||||
}
|
||||
|
||||
void Application::renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera) {
|
||||
|
||||
const float DISTANCE_FROM_HEAD_SPHERE = 0.1f;
|
||||
const float YELLOW[] = { 1.0f, 1.0f, 0.0f };
|
||||
glm::vec3 haloOrigin(pointOfInterest.x, pointOfInterest.y + DISTANCE_FROM_HEAD_SPHERE, pointOfInterest.z);
|
||||
glColor3f(YELLOW[0], YELLOW[1], YELLOW[2]);
|
||||
renderCircle(haloOrigin, 0.1f, glm::vec3(0.0f, 1.0f, 0.0f), 30);
|
||||
}
|
||||
|
||||
void Application::update(float deltaTime) {
|
||||
// Use Transmitter Hand to move hand if connected, else use mouse
|
||||
if (_myTransmitter.isConnected()) {
|
||||
|
@ -1919,7 +1986,7 @@ void Application::update(float deltaTime) {
|
|||
|
||||
// Set where I am looking based on my mouse ray (so that other people can see)
|
||||
glm::vec3 eyePosition;
|
||||
if (isLookingAtOtherAvatar(mouseRayOrigin, mouseRayDirection, eyePosition)) {
|
||||
if (_isLookingAtOtherAvatar = isLookingAtOtherAvatar(mouseRayOrigin, mouseRayDirection, eyePosition)) {
|
||||
// If the mouse is over another avatar's head...
|
||||
glm::vec3 myLookAtFromMouse(eyePosition);
|
||||
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
|
||||
|
@ -1936,7 +2003,7 @@ void Application::update(float deltaTime) {
|
|||
glm::vec3 front = orientation * IDENTITY_FRONT;
|
||||
glm::vec3 up = orientation * IDENTITY_UP;
|
||||
glm::vec3 towardVoxel = getMouseVoxelWorldCoordinates(_mouseVoxelDragging)
|
||||
- _myAvatar.getCameraPosition();
|
||||
- _myAvatar.getCameraPosition(); // is this an error? getCameraPosition dne
|
||||
towardVoxel = front * glm::length(towardVoxel);
|
||||
glm::vec3 lateralToVoxel = glm::cross(up, glm::normalize(towardVoxel)) * glm::length(towardVoxel);
|
||||
_voxelThrust = glm::vec3(0, 0, 0);
|
||||
|
@ -2036,10 +2103,8 @@ void Application::update(float deltaTime) {
|
|||
|
||||
// Leap finger-sensing device
|
||||
LeapManager::enableFakeFingers(_simulateLeapHand->isChecked() || _testRaveGlove->isChecked());
|
||||
LeapManager::nextFrame();
|
||||
_myAvatar.getHand().setRaveGloveActive(_testRaveGlove->isChecked());
|
||||
_myAvatar.getHand().setLeapFingers(LeapManager::getFingerTips(), LeapManager::getFingerRoots());
|
||||
_myAvatar.getHand().setLeapHands(LeapManager::getHandPositions(), LeapManager::getHandNormals());
|
||||
LeapManager::nextFrame(_myAvatar);
|
||||
|
||||
// Read serial port interface devices
|
||||
if (_serialHeadSensor.isActive()) {
|
||||
|
@ -2183,7 +2248,7 @@ void Application::updateAvatar(float deltaTime) {
|
|||
_viewFrustum.computePickRay(MIDPOINT_OF_SCREEN, MIDPOINT_OF_SCREEN, screenCenterRayOrigin, screenCenterRayDirection);
|
||||
|
||||
glm::vec3 eyePosition;
|
||||
if (isLookingAtOtherAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition)) {
|
||||
if (_isLookingAtOtherAvatar = isLookingAtOtherAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition)) {
|
||||
glm::vec3 myLookAtFromMouse(eyePosition);
|
||||
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
|
||||
}
|
||||
|
@ -2211,7 +2276,7 @@ void Application::updateAvatar(float deltaTime) {
|
|||
// actually need to calculate the view frustum planes to send these details
|
||||
// to the server.
|
||||
loadViewFrustum(_myCamera, _viewFrustum);
|
||||
_myAvatar.setCameraPosition(_viewFrustum.getPosition());
|
||||
_myAvatar.setCameraPosition(_viewFrustum.getPosition()); // setCameraPosition() dne
|
||||
_myAvatar.setCameraOrientation(_viewFrustum.getOrientation());
|
||||
_myAvatar.setCameraFov(_viewFrustum.getFieldOfView());
|
||||
_myAvatar.setCameraAspectRatio(_viewFrustum.getAspectRatio());
|
||||
|
@ -2582,6 +2647,10 @@ void Application::displaySide(Camera& whichCamera) {
|
|||
}
|
||||
_myAvatar.render(_lookingInMirror->isChecked(), _renderAvatarBalls->isChecked());
|
||||
_myAvatar.setDisplayingLookatVectors(_renderLookatOn->isChecked());
|
||||
|
||||
if (_renderLookatIndicatorOn->isChecked() && _isLookingAtOtherAvatar) {
|
||||
renderLookatIndicator(_lookatOtherPosition, whichCamera);
|
||||
}
|
||||
}
|
||||
|
||||
if (TESTING_PARTICLE_SYSTEM) {
|
||||
|
@ -3352,7 +3421,7 @@ void* Application::networkReceive(void* args) {
|
|||
case PACKET_TYPE_ENVIRONMENT_DATA: {
|
||||
if (app->_renderVoxels->isChecked()) {
|
||||
Node* voxelServer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_VOXEL_SERVER);
|
||||
if (voxelServer) {
|
||||
if (voxelServer && socketMatch(voxelServer->getActiveSocket(), &senderAddress)) {
|
||||
voxelServer->lock();
|
||||
|
||||
if (app->_incomingPacket[0] == PACKET_TYPE_ENVIRONMENT_DATA) {
|
||||
|
@ -3375,6 +3444,9 @@ void* Application::networkReceive(void* args) {
|
|||
case PACKET_TYPE_AVATAR_VOXEL_URL:
|
||||
processAvatarVoxelURLMessage(app->_incomingPacket, bytesReceived);
|
||||
break;
|
||||
case PACKET_TYPE_AVATAR_FACE_VIDEO:
|
||||
processAvatarFaceVideoMessage(app->_incomingPacket, bytesReceived);
|
||||
break;
|
||||
default:
|
||||
NodeList::getInstance()->processNodeData(&senderAddress, app->_incomingPacket, bytesReceived);
|
||||
break;
|
||||
|
@ -3456,7 +3528,7 @@ void Application::saveSettings(QSettings* settings) {
|
|||
if (!settings) {
|
||||
settings = getSettings();
|
||||
}
|
||||
|
||||
|
||||
settings->setValue("headCameraPitchYawScale", _headCameraPitchYawScale);
|
||||
settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples);
|
||||
settings->setValue("horizontalFieldOfView", _horizontalFieldOfView);
|
||||
|
@ -3471,6 +3543,9 @@ void Application::saveSettings(QSettings* settings) {
|
|||
scanMenuBar(&Application::saveAction, settings);
|
||||
getAvatar()->saveData(settings);
|
||||
_swatch.saveData(settings);
|
||||
|
||||
// ask the NodeList to save its data
|
||||
NodeList::getInstance()->saveData(settings);
|
||||
}
|
||||
|
||||
void Application::importSettings() {
|
||||
|
|
|
@ -20,16 +20,15 @@
|
|||
#include <QList>
|
||||
|
||||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include "Audio.h"
|
||||
#endif
|
||||
|
||||
#include "Avatar.h"
|
||||
#include "BandwidthMeter.h"
|
||||
#include "Camera.h"
|
||||
#include "Environment.h"
|
||||
#include "HandControl.h"
|
||||
#include "PacketHeaders.h"
|
||||
#include "ParticleSystem.h"
|
||||
#include "renderer/GeometryCache.h"
|
||||
|
@ -37,12 +36,13 @@
|
|||
#include "Stars.h"
|
||||
#include "Swatch.h"
|
||||
#include "ToolsPalette.h"
|
||||
#include "ui/ChatEntry.h"
|
||||
#include "ui/BandwidthDialog.h"
|
||||
#include "ViewFrustum.h"
|
||||
#include "VoxelSystem.h"
|
||||
#include "Webcam.h"
|
||||
|
||||
#include "avatar/Avatar.h"
|
||||
#include "avatar/HandControl.h"
|
||||
#include "ui/BandwidthDialog.h"
|
||||
#include "ui/ChatEntry.h"
|
||||
|
||||
class QAction;
|
||||
class QActionGroup;
|
||||
|
@ -103,6 +103,10 @@ public:
|
|||
|
||||
QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; }
|
||||
GeometryCache* getGeometryCache() { return &_geometryCache; }
|
||||
|
||||
public slots:
|
||||
|
||||
void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data);
|
||||
|
||||
void setGroundPlaneImpact(float groundPlaneImpact) { _groundPlaneImpact = groundPlaneImpact; }
|
||||
|
||||
|
@ -185,7 +189,8 @@ private:
|
|||
static bool sendVoxelsOperation(VoxelNode* node, void* extraData);
|
||||
static void sendVoxelEditMessage(PACKET_TYPE type, VoxelDetail& detail);
|
||||
static void sendAvatarVoxelURLMessage(const QUrl& url);
|
||||
static void processAvatarVoxelURLMessage(unsigned char *packetData, size_t dataBytes);
|
||||
static void processAvatarVoxelURLMessage(unsigned char* packetData, size_t dataBytes);
|
||||
static void processAvatarFaceVideoMessage(unsigned char* packetData, size_t dataBytes);
|
||||
static void sendPingPackets();
|
||||
|
||||
void initMenu();
|
||||
|
@ -195,6 +200,7 @@ private:
|
|||
|
||||
void update(float deltaTime);
|
||||
bool isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection, glm::vec3& eyePosition);
|
||||
void renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera);
|
||||
void updateAvatar(float deltaTime);
|
||||
void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum);
|
||||
|
||||
|
@ -250,6 +256,7 @@ private:
|
|||
QAction* _renderStatsOn; // Whether to show onscreen text overlay with stats
|
||||
QAction* _renderFrameTimerOn; // Whether to show onscreen text overlay with stats
|
||||
QAction* _renderLookatOn; // Whether to show lookat vectors from avatar eyes if looking at something
|
||||
QAction* _renderLookatIndicatorOn;
|
||||
QAction* _manualFirstPerson; // Whether to force first-person mode
|
||||
QAction* _manualThirdPerson; // Whether to force third-person mode
|
||||
QAction* _logOn; // Whether to show on-screen log
|
||||
|
@ -363,6 +370,9 @@ private:
|
|||
float _mouseVoxelScale; // the scale for adding/removing voxels
|
||||
glm::vec3 _lastMouseVoxelPos; // the position of the last mouse voxel edit
|
||||
bool _justEditedVoxel; // set when we've just added/deleted/colored a voxel
|
||||
|
||||
bool _isLookingAtOtherAvatar;
|
||||
glm::vec3 _lookatOtherPosition;
|
||||
|
||||
bool _paintOn; // Whether to paint voxels as you fly around
|
||||
unsigned char _dominantColor; // The dominant color of the voxel we're painting
|
||||
|
|
|
@ -47,6 +47,11 @@ void Environment::init() {
|
|||
_data[getZeroAddress()][0];
|
||||
}
|
||||
|
||||
void Environment::resetToDefault() {
|
||||
_data.clear();
|
||||
_data[getZeroAddress()][0];
|
||||
}
|
||||
|
||||
void Environment::renderAtmospheres(Camera& camera) {
|
||||
// get the lock for the duration of the call
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
|
|
@ -24,6 +24,7 @@ class Environment {
|
|||
public:
|
||||
|
||||
void init();
|
||||
void resetToDefault();
|
||||
void renderAtmospheres(Camera& camera);
|
||||
|
||||
glm::vec3 getGravity (const glm::vec3& position);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
|
||||
#include "LeapManager.h"
|
||||
#include "avatar/Avatar.h"
|
||||
#include <Leap.h>
|
||||
#include <dlfcn.h> // needed for RTLD_LAZY
|
||||
#include <sstream>
|
||||
|
@ -16,48 +17,15 @@ bool LeapManager::_doFakeFingers = false;
|
|||
Leap::Controller* LeapManager::_controller = NULL;
|
||||
HifiLeapListener* LeapManager::_listener = NULL;
|
||||
|
||||
namespace {
|
||||
glm::vec3 fakeHandOffset(0.0f, 50.0f, 50.0f);
|
||||
} // end anonymous namespace
|
||||
|
||||
class HifiLeapListener : public Leap::Listener {
|
||||
public:
|
||||
HifiLeapListener() {}
|
||||
virtual ~HifiLeapListener() {}
|
||||
|
||||
Leap::Frame lastFrame;
|
||||
std::vector<glm::vec3> fingerTips;
|
||||
std::vector<glm::vec3> fingerRoots;
|
||||
std::vector<glm::vec3> handPositions;
|
||||
std::vector<glm::vec3> handNormals;
|
||||
|
||||
virtual void onFrame(const Leap::Controller& controller) {
|
||||
#ifndef LEAP_STUBS
|
||||
Leap::Frame frame = controller.frame();
|
||||
int numFingers = frame.fingers().count();
|
||||
fingerTips.resize(numFingers);
|
||||
fingerRoots.resize(numFingers);
|
||||
for (int i = 0; i < numFingers; ++i) {
|
||||
const Leap::Finger& thisFinger = frame.fingers()[i];
|
||||
const Leap::Vector pos = thisFinger.stabilizedTipPosition();
|
||||
fingerTips[i] = glm::vec3(pos.x, pos.y, pos.z);
|
||||
|
||||
const Leap::Vector root = pos - thisFinger.direction() * thisFinger.length();
|
||||
fingerRoots[i] = glm::vec3(root.x, root.y, root.z);
|
||||
}
|
||||
|
||||
int numHands = frame.hands().count();
|
||||
handPositions.resize(numHands);
|
||||
handNormals.resize(numHands);
|
||||
for (int i = 0; i < numHands; ++i) {
|
||||
const Leap::Hand& thisHand = frame.hands()[i];
|
||||
const Leap::Vector pos = thisHand.palmPosition();
|
||||
handPositions[i] = glm::vec3(pos.x, pos.y, pos.z);
|
||||
|
||||
const Leap::Vector norm = thisHand.palmNormal();
|
||||
handNormals[i] = glm::vec3(norm.x, norm.y, norm.z);
|
||||
}
|
||||
lastFrame = frame;
|
||||
lastFrame = controller.frame();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -80,10 +48,195 @@ void LeapManager::terminate() {
|
|||
_controller = NULL;
|
||||
}
|
||||
|
||||
void LeapManager::nextFrame() {
|
||||
void LeapManager::nextFrame(Avatar& avatar) {
|
||||
// Apply the frame data directly to the avatar.
|
||||
Hand& hand = avatar.getHand();
|
||||
|
||||
// If we actually get valid Leap data, this will be set to true;
|
||||
bool gotRealData = false;
|
||||
|
||||
if (controllersExist()) {
|
||||
_listener->onFrame(*_controller);
|
||||
}
|
||||
|
||||
#ifndef LEAP_STUBS
|
||||
if (controllersExist()) {
|
||||
gotRealData = true;
|
||||
// First, see which palms and fingers are still valid.
|
||||
Leap::Frame& frame = _listener->lastFrame;
|
||||
|
||||
// Note that this is O(n^2) at worst, but n is very small.
|
||||
|
||||
// After this many frames of no data, assume the digit is lost.
|
||||
const int assumeLostAfterFrameCount = 10;
|
||||
|
||||
// Increment our frame data counters
|
||||
for (size_t i = 0; i < hand.getNumPalms(); ++i) {
|
||||
PalmData& palm = hand.getPalms()[i];
|
||||
palm.incrementFramesWithoutData();
|
||||
if (palm.getFramesWithoutData() > assumeLostAfterFrameCount) {
|
||||
palm.setActive(false);
|
||||
}
|
||||
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
|
||||
FingerData& finger = palm.getFingers()[f];
|
||||
finger.incrementFramesWithoutData();
|
||||
if (finger.getFramesWithoutData() > assumeLostAfterFrameCount) {
|
||||
finger.setActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t numLeapHands = frame.hands().count();
|
||||
std::vector<PalmData*> palmAssignment(numLeapHands);
|
||||
|
||||
// Look for matches
|
||||
for (size_t index = 0; index < numLeapHands; ++index) {
|
||||
PalmData* takeoverCandidate = NULL;
|
||||
palmAssignment[index] = NULL;
|
||||
Leap::Hand leapHand = frame.hands()[index];
|
||||
int id = leapHand.id();
|
||||
if (leapHand.isValid()) {
|
||||
for (size_t i = 0; i < hand.getNumPalms() && palmAssignment[index] == NULL; ++i) {
|
||||
PalmData& palm = hand.getPalms()[i];
|
||||
if (palm.getLeapID() == id) {
|
||||
// Found hand with the same ID. We're set!
|
||||
palmAssignment[index] = &palm;
|
||||
palm.resetFramesWithoutData();
|
||||
}
|
||||
else if (palm.getFramesWithoutData() > assumeLostAfterFrameCount) {
|
||||
takeoverCandidate = &palm;
|
||||
}
|
||||
}
|
||||
if (palmAssignment[index] == NULL) {
|
||||
palmAssignment[index] = takeoverCandidate;
|
||||
}
|
||||
if (palmAssignment[index] == NULL) {
|
||||
palmAssignment[index] = &hand.addNewPalm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the assignments
|
||||
for (size_t index = 0; index < numLeapHands; ++index) {
|
||||
if (palmAssignment[index]) {
|
||||
Leap::Hand leapHand = frame.hands()[index];
|
||||
PalmData& palm = *(palmAssignment[index]);
|
||||
|
||||
palm.resetFramesWithoutData();
|
||||
palm.setLeapID(leapHand.id());
|
||||
palm.setActive(true);
|
||||
const Leap::Vector pos = leapHand.palmPosition();
|
||||
const Leap::Vector normal = leapHand.palmNormal();
|
||||
palm.setRawPosition(glm::vec3(pos.x, pos.y, pos.z));
|
||||
palm.setRawNormal(glm::vec3(normal.x, normal.y, normal.z));
|
||||
}
|
||||
}
|
||||
|
||||
// Look for fingers per palm
|
||||
for (size_t i = 0; i < hand.getNumPalms(); ++i) {
|
||||
PalmData& palm = hand.getPalms()[i];
|
||||
if (palm.isActive()) {
|
||||
Leap::Hand leapHand = frame.hand(palm.getLeapID());
|
||||
if (leapHand.isValid()) {
|
||||
int numLeapFingers = leapHand.fingers().count();
|
||||
std::vector<FingerData*> fingerAssignment(numLeapFingers);
|
||||
|
||||
|
||||
// Look for matches
|
||||
for (size_t index = 0; index < numLeapFingers; ++index) {
|
||||
FingerData* takeoverCandidate = NULL;
|
||||
fingerAssignment[index] = NULL;
|
||||
Leap::Finger leapFinger = leapHand.fingers()[index];
|
||||
int id = leapFinger.id();
|
||||
if (leapFinger.isValid()) {
|
||||
for (size_t f = 0; f < palm.getNumFingers() && fingerAssignment[index] == NULL; ++f) {
|
||||
FingerData& finger = palm.getFingers()[f];
|
||||
if (finger.getLeapID() == id) {
|
||||
// Found hand with the same ID. We're set!
|
||||
fingerAssignment[index] = &finger;
|
||||
}
|
||||
else if (finger.getFramesWithoutData() > assumeLostAfterFrameCount) {
|
||||
takeoverCandidate = &finger;
|
||||
}
|
||||
}
|
||||
// If we didn't find a match, but we found an unused finger, us it.
|
||||
if (fingerAssignment[index] == NULL) {
|
||||
fingerAssignment[index] = takeoverCandidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the assignments
|
||||
for (size_t index = 0; index < numLeapFingers; ++index) {
|
||||
if (fingerAssignment[index]) {
|
||||
Leap::Finger leapFinger = leapHand.fingers()[index];
|
||||
FingerData& finger = *(fingerAssignment[index]);
|
||||
|
||||
finger.resetFramesWithoutData();
|
||||
finger.setLeapID(leapFinger.id());
|
||||
finger.setActive(true);
|
||||
const Leap::Vector tip = leapFinger.stabilizedTipPosition();
|
||||
const Leap::Vector root = tip - leapFinger.direction() * leapFinger.length();
|
||||
finger.setRawTipPosition(glm::vec3(tip.x, tip.y, tip.z));
|
||||
finger.setRawRootPosition(glm::vec3(root.x, root.y, root.z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!gotRealData) {
|
||||
if (_doFakeFingers) {
|
||||
// There's no real Leap data and we need to fake it.
|
||||
for (size_t i = 0; i < hand.getNumPalms(); ++i) {
|
||||
static const glm::vec3 fakeHandOffsets[] = {
|
||||
glm::vec3( -500.0f, 50.0f, 50.0f),
|
||||
glm::vec3( 0.0f, 50.0f, 50.0f)
|
||||
};
|
||||
static const glm::vec3 fakeHandFingerMirrors[] = {
|
||||
glm::vec3( -1.0f, 1.0f, 1.0f),
|
||||
glm::vec3( 1.0f, 1.0f, 1.0f)
|
||||
};
|
||||
static const glm::vec3 fakeFingerPositions[] = {
|
||||
glm::vec3( -60.0f, 0.0f, -40.0f),
|
||||
glm::vec3( -20.0f, 0.0f, -60.0f),
|
||||
glm::vec3( 20.0f, 0.0f, -60.0f),
|
||||
glm::vec3( 60.0f, 0.0f, -40.0f),
|
||||
glm::vec3( -50.0f, 0.0f, 30.0f)
|
||||
};
|
||||
|
||||
PalmData& palm = hand.getPalms()[i];
|
||||
palm.setActive(true);
|
||||
// Simulated data
|
||||
|
||||
palm.setRawPosition(glm::vec3( 0.0f, 0.0f, 0.0f) + fakeHandOffsets[i]);
|
||||
palm.setRawNormal(glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
|
||||
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
|
||||
FingerData& finger = palm.getFingers()[f];
|
||||
finger.setActive(true);
|
||||
const float tipScale = 1.5f;
|
||||
const float rootScale = 0.75f;
|
||||
glm::vec3 fingerPos = fakeFingerPositions[f] * fakeHandFingerMirrors[i];
|
||||
finger.setRawTipPosition(fingerPos * tipScale + fakeHandOffsets[i]);
|
||||
finger.setRawRootPosition(fingerPos * rootScale + fakeHandOffsets[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Just deactivate everything.
|
||||
for (size_t i = 0; i < hand.getNumPalms(); ++i) {
|
||||
PalmData& palm = hand.getPalms()[i];
|
||||
palm.setActive(false);
|
||||
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
|
||||
FingerData& finger = palm.getFingers()[f];
|
||||
finger.setActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
hand.updateFingerTrails();
|
||||
}
|
||||
|
||||
void LeapManager::enableFakeFingers(bool enable) {
|
||||
|
@ -98,77 +251,6 @@ bool LeapManager::controllersExist() {
|
|||
#endif
|
||||
}
|
||||
|
||||
const std::vector<glm::vec3>& LeapManager::getFingerTips() {
|
||||
if (controllersExist()) {
|
||||
return _listener->fingerTips;
|
||||
}
|
||||
else {
|
||||
static std::vector<glm::vec3> stubData;
|
||||
stubData.clear();
|
||||
if (_doFakeFingers) {
|
||||
// Simulated data
|
||||
float scale = 1.5f;
|
||||
stubData.push_back(glm::vec3( -60.0f, 0.0f, -40.0f) * scale + fakeHandOffset);
|
||||
stubData.push_back(glm::vec3( -20.0f, 0.0f, -60.0f) * scale + fakeHandOffset);
|
||||
stubData.push_back(glm::vec3( 20.0f, 0.0f, -60.0f) * scale + fakeHandOffset);
|
||||
stubData.push_back(glm::vec3( 60.0f, 0.0f, -40.0f) * scale + fakeHandOffset);
|
||||
stubData.push_back(glm::vec3( -50.0f, 0.0f, 30.0f) * scale + fakeHandOffset);
|
||||
}
|
||||
return stubData;
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<glm::vec3>& LeapManager::getFingerRoots() {
|
||||
if (controllersExist()) {
|
||||
return _listener->fingerRoots;
|
||||
}
|
||||
else {
|
||||
static std::vector<glm::vec3> stubData;
|
||||
stubData.clear();
|
||||
if (_doFakeFingers) {
|
||||
// Simulated data
|
||||
float scale = 0.75f;
|
||||
stubData.push_back(glm::vec3( -60.0f, 0.0f, -40.0f) * scale + fakeHandOffset);
|
||||
stubData.push_back(glm::vec3( -20.0f, 0.0f, -60.0f) * scale + fakeHandOffset);
|
||||
stubData.push_back(glm::vec3( 20.0f, 0.0f, -60.0f) * scale + fakeHandOffset);
|
||||
stubData.push_back(glm::vec3( 60.0f, 0.0f, -40.0f) * scale + fakeHandOffset);
|
||||
stubData.push_back(glm::vec3( -50.0f, 0.0f, 30.0f) * scale + fakeHandOffset);
|
||||
}
|
||||
return stubData;
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<glm::vec3>& LeapManager::getHandPositions() {
|
||||
if (controllersExist()) {
|
||||
return _listener->handPositions;
|
||||
}
|
||||
else {
|
||||
static std::vector<glm::vec3> stubData;
|
||||
stubData.clear();
|
||||
if (_doFakeFingers) {
|
||||
// Simulated data
|
||||
glm::vec3 handOffset(0.0f, 50.0f, 50.0f);
|
||||
stubData.push_back(glm::vec3( 0.0f, 0.0f, 0.0f) + fakeHandOffset);
|
||||
}
|
||||
return stubData;
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<glm::vec3>& LeapManager::getHandNormals() {
|
||||
if (controllersExist()) {
|
||||
return _listener->handNormals;
|
||||
}
|
||||
else {
|
||||
static std::vector<glm::vec3> stubData;
|
||||
stubData.clear();
|
||||
if (_doFakeFingers) {
|
||||
// Simulated data
|
||||
stubData.push_back(glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
}
|
||||
return stubData;
|
||||
}
|
||||
}
|
||||
|
||||
std::string LeapManager::statusString() {
|
||||
std::stringstream leapString;
|
||||
#ifndef LEAP_STUBS
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <glm/glm.hpp>
|
||||
#include <string>
|
||||
|
||||
class Avatar;
|
||||
class HifiLeapListener;
|
||||
namespace Leap {
|
||||
class Controller;
|
||||
|
@ -20,7 +21,7 @@ namespace Leap {
|
|||
|
||||
class LeapManager {
|
||||
public:
|
||||
static void nextFrame(); // called once per frame to get new Leap data
|
||||
static void nextFrame(Avatar& avatar); // called once per frame to get new Leap data
|
||||
static bool controllersExist(); // Returns true if there's at least one active Leap plugged in
|
||||
static void enableFakeFingers(bool enable); // put fake data in if there's no Leap plugged in
|
||||
static const std::vector<glm::vec3>& getFingerTips();
|
||||
|
|
|
@ -541,8 +541,6 @@ void runTimingTests() {
|
|||
gettimeofday(&endTime, NULL);
|
||||
elapsedMsecs = diffclock(&startTime, &endTime);
|
||||
qDebug("vec3 assign and dot() usecs: %f\n", 1000.0f * elapsedMsecs / (float) numTests);
|
||||
|
||||
|
||||
}
|
||||
|
||||
float loadSetting(QSettings* settings, const char* name, float defaultValue) {
|
||||
|
|
|
@ -71,7 +71,6 @@ void renderCircle(glm::vec3 position, float radius, glm::vec3 surfaceNormal, int
|
|||
|
||||
void runTimingTests();
|
||||
|
||||
|
||||
float loadSetting(QSettings* settings, const char* name, float defaultValue);
|
||||
|
||||
bool rayIntersectsSphere(glm::vec3& rayStarting, glm::vec3& rayNormalizedDirection, glm::vec3& sphereCenter, double sphereRadius);
|
||||
|
|
|
@ -8,12 +8,15 @@
|
|||
#include <QTimer>
|
||||
#include <QtDebug>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <vpx_encoder.h>
|
||||
#include <vp8cx.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <UVCCameraControl.hpp>
|
||||
#endif
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Webcam.h"
|
||||
|
||||
|
@ -25,11 +28,11 @@ using namespace xn;
|
|||
#endif
|
||||
|
||||
// register types with Qt metatype system
|
||||
int jointVectorMetaType = qRegisterMetaType<JointVector>("JointVector");
|
||||
int jointVectorMetaType = qRegisterMetaType<JointVector>("JointVector");
|
||||
int matMetaType = qRegisterMetaType<Mat>("cv::Mat");
|
||||
int rotatedRectMetaType = qRegisterMetaType<RotatedRect>("cv::RotatedRect");
|
||||
|
||||
Webcam::Webcam() : _enabled(false), _active(false), _frameTextureID(0), _depthTextureID(0) {
|
||||
Webcam::Webcam() : _enabled(false), _active(false), _colorTextureID(0), _depthTextureID(0) {
|
||||
// the grabber simply runs as fast as possible
|
||||
_grabber = new FrameGrabber();
|
||||
_grabber->moveToThread(&_grabberThread);
|
||||
|
@ -64,13 +67,13 @@ void Webcam::reset() {
|
|||
}
|
||||
|
||||
void Webcam::renderPreview(int screenWidth, int screenHeight) {
|
||||
if (_enabled && _frameTextureID != 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, _frameTextureID);
|
||||
if (_enabled && _colorTextureID != 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
glBegin(GL_QUADS);
|
||||
const int PREVIEW_HEIGHT = 200;
|
||||
int previewWidth = _frameWidth * PREVIEW_HEIGHT / _frameHeight;
|
||||
int previewWidth = _textureSize.width * PREVIEW_HEIGHT / _textureSize.height;
|
||||
int top = screenHeight - 600;
|
||||
int left = screenWidth - previewWidth - 10;
|
||||
|
||||
|
@ -87,16 +90,14 @@ void Webcam::renderPreview(int screenWidth, int screenHeight) {
|
|||
if (_depthTextureID != 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, _depthTextureID);
|
||||
glBegin(GL_QUADS);
|
||||
int depthPreviewWidth = _depthWidth * PREVIEW_HEIGHT / _depthHeight;
|
||||
int depthLeft = screenWidth - depthPreviewWidth - 10;
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex2f(depthLeft, top - PREVIEW_HEIGHT);
|
||||
glVertex2f(left, top - PREVIEW_HEIGHT);
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex2f(depthLeft + depthPreviewWidth, top - PREVIEW_HEIGHT);
|
||||
glVertex2f(left + previewWidth, top - PREVIEW_HEIGHT);
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex2f(depthLeft + depthPreviewWidth, top);
|
||||
glVertex2f(left + previewWidth, top);
|
||||
glTexCoord2f(0, 1);
|
||||
glVertex2f(depthLeft, top);
|
||||
glVertex2f(left, top);
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
@ -106,10 +107,10 @@ void Webcam::renderPreview(int screenWidth, int screenHeight) {
|
|||
glColor3f(1.0f, 0.0f, 0.0f);
|
||||
glPointSize(4.0f);
|
||||
glBegin(GL_POINTS);
|
||||
float projectedScale = PREVIEW_HEIGHT / (float)_depthHeight;
|
||||
float projectedScale = PREVIEW_HEIGHT / _textureSize.height;
|
||||
foreach (const Joint& joint, _joints) {
|
||||
if (joint.isValid) {
|
||||
glVertex2f(depthLeft + joint.projected.x * projectedScale,
|
||||
glVertex2f(left + joint.projected.x * projectedScale,
|
||||
top - PREVIEW_HEIGHT + joint.projected.y * projectedScale);
|
||||
}
|
||||
}
|
||||
|
@ -125,15 +126,16 @@ void Webcam::renderPreview(int screenWidth, int screenHeight) {
|
|||
glBegin(GL_LINE_LOOP);
|
||||
Point2f facePoints[4];
|
||||
_faceRect.points(facePoints);
|
||||
float xScale = previewWidth / (float)_frameWidth;
|
||||
float yScale = PREVIEW_HEIGHT / (float)_frameHeight;
|
||||
float xScale = previewWidth / _textureSize.width;
|
||||
float yScale = PREVIEW_HEIGHT / _textureSize.height;
|
||||
glVertex2f(left + facePoints[0].x * xScale, top + facePoints[0].y * yScale);
|
||||
glVertex2f(left + facePoints[1].x * xScale, top + facePoints[1].y * yScale);
|
||||
glVertex2f(left + facePoints[2].x * xScale, top + facePoints[2].y * yScale);
|
||||
glVertex2f(left + facePoints[3].x * xScale, top + facePoints[3].y * yScale);
|
||||
glEnd();
|
||||
|
||||
char fps[20];
|
||||
const int MAX_FPS_CHARACTERS = 30;
|
||||
char fps[MAX_FPS_CHARACTERS];
|
||||
sprintf(fps, "FPS: %d", (int)(roundf(_frameCount * 1000000.0f / (usecTimestampNow() - _startTimestamp))));
|
||||
drawtext(left, top + PREVIEW_HEIGHT + 20, 0.10, 0, 1, 0, fps);
|
||||
}
|
||||
|
@ -147,20 +149,21 @@ Webcam::~Webcam() {
|
|||
delete _grabber;
|
||||
}
|
||||
|
||||
void Webcam::setFrame(const Mat& frame, int format, const Mat& depth, const RotatedRect& faceRect, const JointVector& joints) {
|
||||
IplImage image = frame;
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, image.widthStep / 3);
|
||||
if (_frameTextureID == 0) {
|
||||
glGenTextures(1, &_frameTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _frameTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _frameWidth = image.width, _frameHeight = image.height, 0, format,
|
||||
GL_UNSIGNED_BYTE, image.imageData);
|
||||
void Webcam::setFrame(const Mat& color, int format, const Mat& depth, const RotatedRect& faceRect, const JointVector& joints) {
|
||||
IplImage colorImage = color;
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, colorImage.widthStep / 3);
|
||||
if (_colorTextureID == 0) {
|
||||
glGenTextures(1, &_colorTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _textureSize.width = colorImage.width, _textureSize.height = colorImage.height,
|
||||
0, format, GL_UNSIGNED_BYTE, colorImage.imageData);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
qDebug("Capturing video at %dx%d.\n", _frameWidth, _frameHeight);
|
||||
qDebug("Capturing video at %gx%g.\n", _textureSize.width, _textureSize.height);
|
||||
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, _frameTextureID);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _frameWidth, _frameHeight, format, GL_UNSIGNED_BYTE, image.imageData);
|
||||
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _textureSize.width, _textureSize.height, format,
|
||||
GL_UNSIGNED_BYTE, colorImage.imageData);
|
||||
}
|
||||
|
||||
if (!depth.empty()) {
|
||||
|
@ -169,14 +172,14 @@ void Webcam::setFrame(const Mat& frame, int format, const Mat& depth, const Rota
|
|||
if (_depthTextureID == 0) {
|
||||
glGenTextures(1, &_depthTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _depthTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, _depthWidth = depthImage.width, _depthHeight = depthImage.height, 0,
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, depthImage.width, depthImage.height, 0,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, depthImage.imageData);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
qDebug("Capturing depth at %dx%d.\n", _depthWidth, _depthHeight);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, _depthTextureID);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _depthWidth, _depthHeight, GL_LUMINANCE,
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _textureSize.width, _textureSize.height, GL_LUMINANCE,
|
||||
GL_UNSIGNED_BYTE, depthImage.imageData);
|
||||
}
|
||||
}
|
||||
|
@ -225,30 +228,23 @@ void Webcam::setFrame(const Mat& frame, int format, const Mat& depth, const Rota
|
|||
_estimatedPosition = _estimatedJoints[AVATAR_JOINT_HEAD_BASE].position;
|
||||
|
||||
} else {
|
||||
// roll is just the angle of the face rect (correcting for 180 degree rotations)
|
||||
float roll = faceRect.angle;
|
||||
if (roll < -90.0f) {
|
||||
roll += 180.0f;
|
||||
|
||||
} else if (roll > 90.0f) {
|
||||
roll -= 180.0f;
|
||||
}
|
||||
// roll is just the angle of the face rect
|
||||
const float ROTATION_SMOOTHING = 0.95f;
|
||||
_estimatedRotation.z = glm::mix(roll, _estimatedRotation.z, ROTATION_SMOOTHING);
|
||||
_estimatedRotation.z = glm::mix(_faceRect.angle, _estimatedRotation.z, ROTATION_SMOOTHING);
|
||||
|
||||
// determine position based on translation and scaling of the face rect
|
||||
if (_initialFaceRect.size.area() == 0) {
|
||||
_initialFaceRect = faceRect;
|
||||
_initialFaceRect = _faceRect;
|
||||
_estimatedPosition = glm::vec3();
|
||||
|
||||
} else {
|
||||
float proportion = sqrtf(_initialFaceRect.size.area() / (float)faceRect.size.area());
|
||||
float proportion = sqrtf(_initialFaceRect.size.area() / (float)_faceRect.size.area());
|
||||
const float DISTANCE_TO_CAMERA = 0.333f;
|
||||
const float POSITION_SCALE = 0.5f;
|
||||
float z = DISTANCE_TO_CAMERA * proportion - DISTANCE_TO_CAMERA;
|
||||
glm::vec3 position = glm::vec3(
|
||||
(faceRect.center.x - _initialFaceRect.center.x) * proportion * POSITION_SCALE / _frameWidth,
|
||||
(faceRect.center.y - _initialFaceRect.center.y) * proportion * POSITION_SCALE / _frameWidth,
|
||||
(_faceRect.center.x - _initialFaceRect.center.x) * proportion * POSITION_SCALE / _textureSize.width,
|
||||
(_faceRect.center.y - _initialFaceRect.center.y) * proportion * POSITION_SCALE / _textureSize.width,
|
||||
z);
|
||||
const float POSITION_SMOOTHING = 0.95f;
|
||||
_estimatedPosition = glm::mix(position, _estimatedPosition, POSITION_SMOOTHING);
|
||||
|
@ -262,7 +258,8 @@ void Webcam::setFrame(const Mat& frame, int format, const Mat& depth, const Rota
|
|||
QTimer::singleShot(qMax((int)remaining / 1000, 0), _grabber, SLOT(grabFrame()));
|
||||
}
|
||||
|
||||
FrameGrabber::FrameGrabber() : _initialized(false), _capture(0), _searchWindow(0, 0, 0, 0) {
|
||||
FrameGrabber::FrameGrabber() : _initialized(false), _capture(0), _searchWindow(0, 0, 0, 0),
|
||||
_depthOffset(0.0), _codec(), _frameCount(0) {
|
||||
}
|
||||
|
||||
FrameGrabber::~FrameGrabber() {
|
||||
|
@ -370,29 +367,35 @@ void FrameGrabber::shutdown() {
|
|||
cvReleaseCapture(&_capture);
|
||||
_capture = 0;
|
||||
}
|
||||
if (_codec.name != 0) {
|
||||
vpx_codec_destroy(&_codec);
|
||||
_codec.name = 0;
|
||||
}
|
||||
_initialized = false;
|
||||
|
||||
thread()->quit();
|
||||
}
|
||||
|
||||
static Point clip(const Point& point, const Rect& bounds) {
|
||||
return Point(glm::clamp(point.x, bounds.x, bounds.x + bounds.width - 1),
|
||||
glm::clamp(point.y, bounds.y, bounds.y + bounds.height - 1));
|
||||
}
|
||||
|
||||
void FrameGrabber::grabFrame() {
|
||||
if (!(_initialized || init())) {
|
||||
return;
|
||||
}
|
||||
int format = GL_BGR;
|
||||
Mat frame;
|
||||
Mat color, depth;
|
||||
JointVector joints;
|
||||
|
||||
#ifdef HAVE_OPENNI
|
||||
if (_depthGenerator.IsValid()) {
|
||||
_xnContext.WaitAnyUpdateAll();
|
||||
frame = Mat(_imageMetaData.YRes(), _imageMetaData.XRes(), CV_8UC3, (void*)_imageGenerator.GetImageMap());
|
||||
color = Mat(_imageMetaData.YRes(), _imageMetaData.XRes(), CV_8UC3, (void*)_imageGenerator.GetImageMap());
|
||||
format = GL_RGB;
|
||||
|
||||
Mat depth = Mat(_depthMetaData.YRes(), _depthMetaData.XRes(), CV_16UC1, (void*)_depthGenerator.GetDepthMap());
|
||||
const double EIGHT_BIT_MAX = 255;
|
||||
const double ELEVEN_BIT_MAX = 2047;
|
||||
depth.convertTo(_grayDepthFrame, CV_8UC1, EIGHT_BIT_MAX / ELEVEN_BIT_MAX);
|
||||
depth = Mat(_depthMetaData.YRes(), _depthMetaData.XRes(), CV_16UC1, (void*)_depthGenerator.GetDepthMap());
|
||||
|
||||
_userID = 0;
|
||||
XnUInt16 userCount = 1;
|
||||
|
@ -428,7 +431,7 @@ void FrameGrabber::grabFrame() {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (frame.empty()) {
|
||||
if (color.empty()) {
|
||||
IplImage* image = cvQueryFrame(_capture);
|
||||
if (image == 0) {
|
||||
// try again later
|
||||
|
@ -441,7 +444,7 @@ void FrameGrabber::grabFrame() {
|
|||
qDebug("Invalid webcam image format.\n");
|
||||
return;
|
||||
}
|
||||
frame = image;
|
||||
color = image;
|
||||
}
|
||||
|
||||
// if we don't have a search window (yet), try using the face cascade
|
||||
|
@ -449,11 +452,11 @@ void FrameGrabber::grabFrame() {
|
|||
float ranges[] = { 0, 180 };
|
||||
const float* range = ranges;
|
||||
if (_searchWindow.area() == 0) {
|
||||
vector<cv::Rect> faces;
|
||||
_faceCascade.detectMultiScale(frame, faces, 1.1, 6);
|
||||
vector<Rect> faces;
|
||||
_faceCascade.detectMultiScale(color, faces, 1.1, 6);
|
||||
if (!faces.empty()) {
|
||||
_searchWindow = faces.front();
|
||||
updateHSVFrame(frame, format);
|
||||
updateHSVFrame(color, format);
|
||||
|
||||
Mat faceHsv(_hsvFrame, _searchWindow);
|
||||
Mat faceMask(_mask, _searchWindow);
|
||||
|
@ -466,17 +469,159 @@ void FrameGrabber::grabFrame() {
|
|||
}
|
||||
RotatedRect faceRect;
|
||||
if (_searchWindow.area() > 0) {
|
||||
updateHSVFrame(frame, format);
|
||||
updateHSVFrame(color, format);
|
||||
|
||||
calcBackProject(&_hsvFrame, 1, &channels, _histogram, _backProject, &range);
|
||||
bitwise_and(_backProject, _mask, _backProject);
|
||||
|
||||
faceRect = CamShift(_backProject, _searchWindow, TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1));
|
||||
_searchWindow = faceRect.boundingRect();
|
||||
}
|
||||
Rect faceBounds = faceRect.boundingRect();
|
||||
Rect imageBounds(0, 0, color.cols, color.rows);
|
||||
_searchWindow = Rect(clip(faceBounds.tl(), imageBounds), clip(faceBounds.br(), imageBounds));
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENNI
|
||||
if (_depthGenerator.IsValid()) {
|
||||
// convert from 11 to 8 bits, centered about the mean face depth (if possible)
|
||||
if (_searchWindow.area() > 0) {
|
||||
const double DEPTH_OFFSET_SMOOTHING = 0.95;
|
||||
const double EIGHT_BIT_MIDPOINT = 128.0;
|
||||
double meanOffset = EIGHT_BIT_MIDPOINT - mean(depth(_searchWindow))[0];
|
||||
_depthOffset = (_depthOffset == 0.0) ? meanOffset : glm::mix(meanOffset, _depthOffset, DEPTH_OFFSET_SMOOTHING);
|
||||
}
|
||||
depth.convertTo(_grayDepthFrame, CV_8UC1, 1.0, _depthOffset);
|
||||
}
|
||||
#endif
|
||||
|
||||
const int ENCODED_FACE_WIDTH = 128;
|
||||
const int ENCODED_FACE_HEIGHT = 128;
|
||||
int combinedFaceHeight = ENCODED_FACE_HEIGHT * (depth.empty() ? 1 : 2);
|
||||
if (_codec.name == 0) {
|
||||
// initialize encoder context
|
||||
vpx_codec_enc_cfg_t codecConfig;
|
||||
vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &codecConfig, 0);
|
||||
codecConfig.rc_target_bitrate = ENCODED_FACE_WIDTH * combinedFaceHeight * codecConfig.rc_target_bitrate /
|
||||
codecConfig.g_w / codecConfig.g_h;
|
||||
codecConfig.g_w = ENCODED_FACE_WIDTH;
|
||||
codecConfig.g_h = combinedFaceHeight;
|
||||
vpx_codec_enc_init(&_codec, vpx_codec_vp8_cx(), &codecConfig, 0);
|
||||
}
|
||||
|
||||
// correct for 180 degree rotations
|
||||
if (faceRect.angle < -90.0f) {
|
||||
faceRect.angle += 180.0f;
|
||||
|
||||
} else if (faceRect.angle > 90.0f) {
|
||||
faceRect.angle -= 180.0f;
|
||||
}
|
||||
|
||||
// compute the smoothed face rect
|
||||
if (_smoothedFaceRect.size.area() == 0) {
|
||||
_smoothedFaceRect = faceRect;
|
||||
|
||||
} else {
|
||||
const float FACE_RECT_SMOOTHING = 0.9f;
|
||||
_smoothedFaceRect.center.x = glm::mix(faceRect.center.x, _smoothedFaceRect.center.x, FACE_RECT_SMOOTHING);
|
||||
_smoothedFaceRect.center.y = glm::mix(faceRect.center.y, _smoothedFaceRect.center.y, FACE_RECT_SMOOTHING);
|
||||
_smoothedFaceRect.size.width = glm::mix(faceRect.size.width, _smoothedFaceRect.size.width, FACE_RECT_SMOOTHING);
|
||||
_smoothedFaceRect.size.height = glm::mix(faceRect.size.height, _smoothedFaceRect.size.height, FACE_RECT_SMOOTHING);
|
||||
_smoothedFaceRect.angle = glm::mix(faceRect.angle, _smoothedFaceRect.angle, FACE_RECT_SMOOTHING);
|
||||
}
|
||||
|
||||
// resize/rotate face into encoding rectangle
|
||||
_faceColor.create(ENCODED_FACE_WIDTH, ENCODED_FACE_HEIGHT, CV_8UC3);
|
||||
Point2f sourcePoints[4];
|
||||
_smoothedFaceRect.points(sourcePoints);
|
||||
Point2f destPoints[] = { Point2f(0, ENCODED_FACE_HEIGHT), Point2f(0, 0), Point2f(ENCODED_FACE_WIDTH, 0) };
|
||||
Mat transform = getAffineTransform(sourcePoints, destPoints);
|
||||
warpAffine(color, _faceColor, transform, _faceColor.size());
|
||||
|
||||
// convert from RGB to YV12
|
||||
const int ENCODED_BITS_PER_Y = 8;
|
||||
const int ENCODED_BITS_PER_VU = 2;
|
||||
const int ENCODED_BITS_PER_PIXEL = ENCODED_BITS_PER_Y + 2 * ENCODED_BITS_PER_VU;
|
||||
const int BITS_PER_BYTE = 8;
|
||||
_encodedFace.fill(128, ENCODED_FACE_WIDTH * combinedFaceHeight * ENCODED_BITS_PER_PIXEL / BITS_PER_BYTE);
|
||||
vpx_image_t vpxImage;
|
||||
vpx_img_wrap(&vpxImage, VPX_IMG_FMT_YV12, ENCODED_FACE_WIDTH, combinedFaceHeight, 1, (unsigned char*)_encodedFace.data());
|
||||
uchar* yline = vpxImage.planes[0];
|
||||
uchar* vline = vpxImage.planes[1];
|
||||
uchar* uline = vpxImage.planes[2];
|
||||
const int Y_RED_WEIGHT = (int)(0.299 * 256);
|
||||
const int Y_GREEN_WEIGHT = (int)(0.587 * 256);
|
||||
const int Y_BLUE_WEIGHT = (int)(0.114 * 256);
|
||||
const int V_RED_WEIGHT = (int)(0.713 * 256);
|
||||
const int U_BLUE_WEIGHT = (int)(0.564 * 256);
|
||||
int redIndex = 0;
|
||||
int greenIndex = 1;
|
||||
int blueIndex = 2;
|
||||
if (format == GL_BGR) {
|
||||
redIndex = 2;
|
||||
blueIndex = 0;
|
||||
}
|
||||
for (int i = 0; i < ENCODED_FACE_HEIGHT; i += 2) {
|
||||
uchar* ydest = yline;
|
||||
uchar* vdest = vline;
|
||||
uchar* udest = uline;
|
||||
for (int j = 0; j < ENCODED_FACE_WIDTH; j += 2) {
|
||||
uchar* tl = _faceColor.ptr(i, j);
|
||||
uchar* tr = _faceColor.ptr(i, j + 1);
|
||||
uchar* bl = _faceColor.ptr(i + 1, j);
|
||||
uchar* br = _faceColor.ptr(i + 1, j + 1);
|
||||
|
||||
ydest[0] = (tl[redIndex] * Y_RED_WEIGHT + tl[1] * Y_GREEN_WEIGHT + tl[blueIndex] * Y_BLUE_WEIGHT) >> 8;
|
||||
ydest[1] = (tr[redIndex] * Y_RED_WEIGHT + tr[1] * Y_GREEN_WEIGHT + tr[blueIndex] * Y_BLUE_WEIGHT) >> 8;
|
||||
ydest[ENCODED_FACE_WIDTH] = (bl[redIndex] * Y_RED_WEIGHT + bl[greenIndex] *
|
||||
Y_GREEN_WEIGHT + bl[blueIndex] * Y_BLUE_WEIGHT) >> 8;
|
||||
ydest[ENCODED_FACE_WIDTH + 1] = (br[redIndex] * Y_RED_WEIGHT + br[greenIndex] *
|
||||
Y_GREEN_WEIGHT + br[blueIndex] * Y_BLUE_WEIGHT) >> 8;
|
||||
ydest += 2;
|
||||
|
||||
int totalRed = tl[redIndex] + tr[redIndex] + bl[redIndex] + br[redIndex];
|
||||
int totalGreen = tl[greenIndex] + tr[greenIndex] + bl[greenIndex] + br[greenIndex];
|
||||
int totalBlue = tl[blueIndex] + tr[blueIndex] + bl[blueIndex] + br[blueIndex];
|
||||
int totalY = (totalRed * Y_RED_WEIGHT + totalGreen * Y_GREEN_WEIGHT + totalBlue * Y_BLUE_WEIGHT) >> 8;
|
||||
|
||||
*vdest++ = (((totalRed - totalY) * V_RED_WEIGHT) >> 10) + 128;
|
||||
*udest++ = (((totalBlue - totalY) * U_BLUE_WEIGHT) >> 10) + 128;
|
||||
}
|
||||
yline += vpxImage.stride[0] * 2;
|
||||
vline += vpxImage.stride[1];
|
||||
uline += vpxImage.stride[2];
|
||||
}
|
||||
|
||||
// if we have depth data, warp that and just copy it in
|
||||
if (!depth.empty()) {
|
||||
_faceDepth.create(ENCODED_FACE_WIDTH, ENCODED_FACE_HEIGHT, CV_8UC1);
|
||||
warpAffine(_grayDepthFrame, _faceDepth, transform, _faceDepth.size());
|
||||
|
||||
uchar* dest = (uchar*)_encodedFace.data() + vpxImage.stride[0] * ENCODED_FACE_HEIGHT;
|
||||
for (int i = 0; i < ENCODED_FACE_HEIGHT; i++) {
|
||||
memcpy(dest, _faceDepth.ptr(i), ENCODED_FACE_WIDTH);
|
||||
dest += vpxImage.stride[0];
|
||||
}
|
||||
}
|
||||
|
||||
// encode the frame
|
||||
vpx_codec_encode(&_codec, &vpxImage, ++_frameCount, 1, 0, VPX_DL_REALTIME);
|
||||
|
||||
// extract the encoded frame
|
||||
vpx_codec_iter_t iterator = 0;
|
||||
const vpx_codec_cx_pkt_t* packet;
|
||||
while ((packet = vpx_codec_get_cx_data(&_codec, &iterator)) != 0) {
|
||||
if (packet->kind == VPX_CODEC_CX_FRAME_PKT) {
|
||||
// prepend the aspect ratio
|
||||
QByteArray payload(sizeof(float), 0);
|
||||
*(float*)payload.data() = _smoothedFaceRect.size.width / _smoothedFaceRect.size.height;
|
||||
payload.append((const char*)packet->data.frame.buf, packet->data.frame.sz);
|
||||
QMetaObject::invokeMethod(Application::getInstance(), "sendAvatarFaceVideoMessage", Q_ARG(int, _frameCount),
|
||||
Q_ARG(QByteArray, payload));
|
||||
}
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(Application::getInstance()->getWebcam(), "setFrame",
|
||||
Q_ARG(cv::Mat, frame), Q_ARG(int, format), Q_ARG(cv::Mat, _grayDepthFrame),
|
||||
Q_ARG(cv::RotatedRect, faceRect), Q_ARG(JointVector, joints));
|
||||
Q_ARG(cv::Mat, color), Q_ARG(int, format), Q_ARG(cv::Mat, _grayDepthFrame),
|
||||
Q_ARG(cv::RotatedRect, _smoothedFaceRect), Q_ARG(JointVector, joints));
|
||||
}
|
||||
|
||||
bool FrameGrabber::init() {
|
||||
|
@ -506,6 +651,11 @@ bool FrameGrabber::init() {
|
|||
|
||||
_userGenerator.GetSkeletonCap().SetSkeletonProfile(XN_SKEL_PROFILE_UPPER);
|
||||
|
||||
// make the depth viewpoint match that of the video image
|
||||
if (_depthGenerator.IsCapabilitySupported(XN_CAPABILITY_ALTERNATIVE_VIEW_POINT)) {
|
||||
_depthGenerator.GetAlternativeViewPointCap().SetViewPoint(_imageGenerator);
|
||||
}
|
||||
|
||||
_xnContext.StartGeneratingAll();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <XnCppWrapper.h>
|
||||
#endif
|
||||
|
||||
#include <vpx_codec.h>
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
class QImage;
|
||||
|
@ -42,7 +44,14 @@ public:
|
|||
Webcam();
|
||||
~Webcam();
|
||||
|
||||
const bool isActive() const { return _active; }
|
||||
bool isActive() const { return _active; }
|
||||
|
||||
GLuint getColorTextureID() const { return _colorTextureID; }
|
||||
GLuint getDepthTextureID() const { return _depthTextureID; }
|
||||
const cv::Size2f& getTextureSize() const { return _textureSize; }
|
||||
|
||||
const cv::RotatedRect& getFaceRect() const { return _faceRect; }
|
||||
|
||||
const glm::vec3& getEstimatedPosition() const { return _estimatedPosition; }
|
||||
const glm::vec3& getEstimatedRotation() const { return _estimatedRotation; }
|
||||
const JointVector& getEstimatedJoints() const { return _estimatedJoints; }
|
||||
|
@ -53,9 +62,9 @@ public:
|
|||
public slots:
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
void setFrame(const cv::Mat& video, int format, const cv::Mat& depth,
|
||||
void setFrame(const cv::Mat& color, int format, const cv::Mat& depth,
|
||||
const cv::RotatedRect& faceRect, const JointVector& joints);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
QThread _grabberThread;
|
||||
|
@ -63,12 +72,9 @@ private:
|
|||
|
||||
bool _enabled;
|
||||
bool _active;
|
||||
int _frameWidth;
|
||||
int _frameHeight;
|
||||
int _depthWidth;
|
||||
int _depthHeight;
|
||||
GLuint _frameTextureID;
|
||||
GLuint _colorTextureID;
|
||||
GLuint _depthTextureID;
|
||||
cv::Size2f _textureSize;
|
||||
cv::RotatedRect _faceRect;
|
||||
cv::RotatedRect _initialFaceRect;
|
||||
JointVector _joints;
|
||||
|
@ -111,7 +117,15 @@ private:
|
|||
cv::Mat _backProject;
|
||||
cv::Rect _searchWindow;
|
||||
cv::Mat _grayDepthFrame;
|
||||
|
||||
double _depthOffset;
|
||||
|
||||
vpx_codec_ctx_t _codec;
|
||||
int _frameCount;
|
||||
cv::Mat _faceColor;
|
||||
cv::Mat _faceDepth;
|
||||
QByteArray _encodedFace;
|
||||
cv::RotatedRect _smoothedFaceRect;
|
||||
|
||||
#ifdef HAVE_OPENNI
|
||||
xn::Context _xnContext;
|
||||
xn::DepthGenerator _depthGenerator;
|
||||
|
|
|
@ -313,6 +313,12 @@ void Avatar::updateFromGyrosAndOrWebcam(bool gyroLook,
|
|||
if (webcam->isActive()) {
|
||||
estimatedPosition = webcam->getEstimatedPosition();
|
||||
|
||||
// apply face data
|
||||
_head.getFace().setColorTextureID(webcam->getColorTextureID());
|
||||
_head.getFace().setDepthTextureID(webcam->getDepthTextureID());
|
||||
_head.getFace().setTextureSize(webcam->getTextureSize());
|
||||
_head.getFace().setTextureRect(webcam->getFaceRect());
|
||||
|
||||
// compute and store the joint rotations
|
||||
const JointVector& joints = webcam->getEstimatedJoints();
|
||||
_joints.clear();
|
||||
|
@ -327,6 +333,8 @@ void Avatar::updateFromGyrosAndOrWebcam(bool gyroLook,
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_head.getFace().setColorTextureID(0);
|
||||
}
|
||||
_head.setPitch(estimatedRotation.x * amplifyAngle.x + pitchFromTouch);
|
||||
_head.setYaw(estimatedRotation.y * amplifyAngle.y + yawFromTouch);
|
345
interface/src/avatar/Face.cpp
Normal file
345
interface/src/avatar/Face.cpp
Normal file
|
@ -0,0 +1,345 @@
|
|||
//
|
||||
// Face.cpp
|
||||
// interface
|
||||
//
|
||||
// Created by Andrzej Kapolka on 7/11/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include <vpx_decoder.h>
|
||||
#include <vp8dx.h>
|
||||
|
||||
#include <PacketHeaders.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Avatar.h"
|
||||
#include "Head.h"
|
||||
#include "Face.h"
|
||||
#include "renderer/ProgramObject.h"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
ProgramObject* Face::_program = 0;
|
||||
int Face::_texCoordCornerLocation;
|
||||
int Face::_texCoordRightLocation;
|
||||
int Face::_texCoordUpLocation;
|
||||
int Face::_aspectRatioLocation;
|
||||
GLuint Face::_vboID;
|
||||
GLuint Face::_iboID;
|
||||
|
||||
Face::Face(Head* owningHead) : _owningHead(owningHead), _renderMode(MESH),
|
||||
_colorTextureID(0), _depthTextureID(0), _codec(), _frameCount(0) {
|
||||
// we may have been created in the network thread, but we live in the main thread
|
||||
moveToThread(Application::getInstance()->thread());
|
||||
}
|
||||
|
||||
Face::~Face() {
|
||||
if (_codec.name != 0) {
|
||||
vpx_codec_destroy(&_codec);
|
||||
|
||||
// delete our textures, since we know that we own them
|
||||
if (_colorTextureID != 0) {
|
||||
glDeleteTextures(1, &_colorTextureID);
|
||||
}
|
||||
if (_depthTextureID != 0) {
|
||||
glDeleteTextures(1, &_depthTextureID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Face::setTextureRect(const cv::RotatedRect& textureRect) {
|
||||
_textureRect = textureRect;
|
||||
_aspectRatio = _textureRect.size.width / _textureRect.size.height;
|
||||
}
|
||||
|
||||
int Face::processVideoMessage(unsigned char* packetData, size_t dataBytes) {
|
||||
if (_codec.name == 0) {
|
||||
// initialize decoder context
|
||||
vpx_codec_dec_init(&_codec, vpx_codec_vp8_dx(), 0, 0);
|
||||
}
|
||||
// skip the header
|
||||
unsigned char* packetPosition = packetData;
|
||||
|
||||
int frameCount = *(uint32_t*)packetPosition;
|
||||
packetPosition += sizeof(uint32_t);
|
||||
|
||||
int frameSize = *(uint32_t*)packetPosition;
|
||||
packetPosition += sizeof(uint32_t);
|
||||
|
||||
int frameOffset = *(uint32_t*)packetPosition;
|
||||
packetPosition += sizeof(uint32_t);
|
||||
|
||||
if (frameCount < _frameCount) { // old frame; ignore
|
||||
return dataBytes;
|
||||
|
||||
} else if (frameCount > _frameCount) { // new frame; reset
|
||||
_frameCount = frameCount;
|
||||
_frameBytesRemaining = frameSize;
|
||||
_arrivingFrame.resize(frameSize);
|
||||
}
|
||||
|
||||
int payloadSize = dataBytes - (packetPosition - packetData);
|
||||
memcpy(_arrivingFrame.data() + frameOffset, packetPosition, payloadSize);
|
||||
|
||||
if ((_frameBytesRemaining -= payloadSize) <= 0) {
|
||||
float aspectRatio = *(const float*)_arrivingFrame.constData();
|
||||
vpx_codec_decode(&_codec, (const uint8_t*)_arrivingFrame.constData() + sizeof(float),
|
||||
_arrivingFrame.size() - sizeof(float), 0, 0);
|
||||
vpx_codec_iter_t iterator = 0;
|
||||
vpx_image_t* image;
|
||||
while ((image = vpx_codec_get_frame(&_codec, &iterator)) != 0) {
|
||||
// convert from YV12 to RGB
|
||||
const int imageHeight = image->d_w;
|
||||
Mat color(imageHeight, image->d_w, CV_8UC3);
|
||||
uchar* yline = image->planes[0];
|
||||
uchar* vline = image->planes[1];
|
||||
uchar* uline = image->planes[2];
|
||||
const int RED_V_WEIGHT = (int)(1.403 * 256);
|
||||
const int GREEN_V_WEIGHT = (int)(0.714 * 256);
|
||||
const int GREEN_U_WEIGHT = (int)(0.344 * 256);
|
||||
const int BLUE_U_WEIGHT = (int)(1.773 * 256);
|
||||
for (int i = 0; i < imageHeight; i += 2) {
|
||||
uchar* ysrc = yline;
|
||||
uchar* vsrc = vline;
|
||||
uchar* usrc = uline;
|
||||
for (int j = 0; j < image->d_w; j += 2) {
|
||||
uchar* tl = color.ptr(i, j);
|
||||
uchar* tr = color.ptr(i, j + 1);
|
||||
uchar* bl = color.ptr(i + 1, j);
|
||||
uchar* br = color.ptr(i + 1, j + 1);
|
||||
|
||||
int v = *vsrc++ - 128;
|
||||
int u = *usrc++ - 128;
|
||||
|
||||
int redOffset = (RED_V_WEIGHT * v) >> 8;
|
||||
int greenOffset = (GREEN_V_WEIGHT * v + GREEN_U_WEIGHT * u) >> 8;
|
||||
int blueOffset = (BLUE_U_WEIGHT * u) >> 8;
|
||||
|
||||
int ytl = ysrc[0];
|
||||
int ytr = ysrc[1];
|
||||
int ybl = ysrc[image->w];
|
||||
int ybr = ysrc[image->w + 1];
|
||||
ysrc += 2;
|
||||
|
||||
tl[0] = ytl + redOffset;
|
||||
tl[1] = ytl - greenOffset;
|
||||
tl[2] = ytl + blueOffset;
|
||||
|
||||
tr[0] = ytr + redOffset;
|
||||
tr[1] = ytr - greenOffset;
|
||||
tr[2] = ytr + blueOffset;
|
||||
|
||||
bl[0] = ybl + redOffset;
|
||||
bl[1] = ybl - greenOffset;
|
||||
bl[2] = ybl + blueOffset;
|
||||
|
||||
br[0] = ybr + redOffset;
|
||||
br[1] = ybr - greenOffset;
|
||||
br[2] = ybr + blueOffset;
|
||||
}
|
||||
yline += image->stride[0] * 2;
|
||||
vline += image->stride[1];
|
||||
uline += image->stride[2];
|
||||
}
|
||||
Mat depth;
|
||||
if (image->d_h > imageHeight) {
|
||||
// if the height is greater than the width, we have depth data
|
||||
depth.create(imageHeight, image->d_w, CV_8UC1);
|
||||
uchar* src = image->planes[0] + image->stride[0] * imageHeight;
|
||||
for (int i = 0; i < imageHeight; i++) {
|
||||
memcpy(depth.ptr(i), src, image->d_w);
|
||||
src += image->stride[0];
|
||||
}
|
||||
}
|
||||
QMetaObject::invokeMethod(this, "setFrame", Q_ARG(cv::Mat, color),
|
||||
Q_ARG(cv::Mat, depth), Q_ARG(float, aspectRatio));
|
||||
}
|
||||
}
|
||||
|
||||
return dataBytes;
|
||||
}
|
||||
|
||||
bool Face::render(float alpha) {
|
||||
if (_colorTextureID == 0 || _textureRect.size.area() == 0) {
|
||||
return false;
|
||||
}
|
||||
glPushMatrix();
|
||||
|
||||
glTranslatef(_owningHead->getPosition().x, _owningHead->getPosition().y, _owningHead->getPosition().z);
|
||||
glm::quat orientation = _owningHead->getOrientation();
|
||||
glm::vec3 axis = glm::axis(orientation);
|
||||
glRotatef(glm::angle(orientation), axis.x, axis.y, axis.z);
|
||||
float scale = BODY_BALL_RADIUS_HEAD_BASE * _owningHead->getScale();
|
||||
glScalef(scale, scale, scale);
|
||||
|
||||
glColor4f(1.0f, 1.0f, 1.0f, alpha);
|
||||
|
||||
Point2f points[4];
|
||||
_textureRect.points(points);
|
||||
|
||||
if (_depthTextureID != 0) {
|
||||
const int VERTEX_WIDTH = 100;
|
||||
const int VERTEX_HEIGHT = 100;
|
||||
const int VERTEX_COUNT = VERTEX_WIDTH * VERTEX_HEIGHT;
|
||||
const int ELEMENTS_PER_VERTEX = 2;
|
||||
const int BUFFER_ELEMENTS = VERTEX_COUNT * ELEMENTS_PER_VERTEX;
|
||||
const int QUAD_WIDTH = VERTEX_WIDTH - 1;
|
||||
const int QUAD_HEIGHT = VERTEX_HEIGHT - 1;
|
||||
const int QUAD_COUNT = QUAD_WIDTH * QUAD_HEIGHT;
|
||||
const int TRIANGLES_PER_QUAD = 2;
|
||||
const int INDICES_PER_TRIANGLE = 3;
|
||||
const int INDEX_COUNT = QUAD_COUNT * TRIANGLES_PER_QUAD * INDICES_PER_TRIANGLE;
|
||||
|
||||
if (_program == 0) {
|
||||
_program = new ProgramObject();
|
||||
_program->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/face.vert");
|
||||
_program->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/face.frag");
|
||||
_program->link();
|
||||
|
||||
_program->bind();
|
||||
_program->setUniformValue("depthTexture", 0);
|
||||
_program->setUniformValue("colorTexture", 1);
|
||||
_program->release();
|
||||
|
||||
_texCoordCornerLocation = _program->uniformLocation("texCoordCorner");
|
||||
_texCoordRightLocation = _program->uniformLocation("texCoordRight");
|
||||
_texCoordUpLocation = _program->uniformLocation("texCoordUp");
|
||||
_aspectRatioLocation = _program->uniformLocation("aspectRatio");
|
||||
|
||||
glGenBuffers(1, &_vboID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vboID);
|
||||
float* vertices = new float[BUFFER_ELEMENTS];
|
||||
float* vertexPosition = vertices;
|
||||
for (int i = 0; i < VERTEX_HEIGHT; i++) {
|
||||
for (int j = 0; j < VERTEX_WIDTH; j++) {
|
||||
*vertexPosition++ = j / (float)(VERTEX_WIDTH - 1);
|
||||
*vertexPosition++ = i / (float)(VERTEX_HEIGHT - 1);
|
||||
}
|
||||
}
|
||||
glBufferData(GL_ARRAY_BUFFER, BUFFER_ELEMENTS * sizeof(float), vertices, GL_STATIC_DRAW);
|
||||
delete[] vertices;
|
||||
|
||||
glGenBuffers(1, &_iboID);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iboID);
|
||||
int* indices = new int[INDEX_COUNT];
|
||||
int* indexPosition = indices;
|
||||
for (int i = 0; i < QUAD_HEIGHT; i++) {
|
||||
for (int j = 0; j < QUAD_WIDTH; j++) {
|
||||
*indexPosition++ = i * VERTEX_WIDTH + j;
|
||||
*indexPosition++ = (i + 1) * VERTEX_WIDTH + j;
|
||||
*indexPosition++ = i * VERTEX_WIDTH + j + 1;
|
||||
|
||||
*indexPosition++ = i * VERTEX_WIDTH + j + 1;
|
||||
*indexPosition++ = (i + 1) * VERTEX_WIDTH + j;
|
||||
*indexPosition++ = (i + 1) * VERTEX_WIDTH + j + 1;
|
||||
}
|
||||
}
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, INDEX_COUNT * sizeof(int), indices, GL_STATIC_DRAW);
|
||||
delete[] indices;
|
||||
|
||||
} else {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vboID);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iboID);
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, _depthTextureID);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
|
||||
|
||||
_program->bind();
|
||||
_program->setUniformValue(_texCoordCornerLocation,
|
||||
points[0].x / _textureSize.width, points[0].y / _textureSize.height);
|
||||
_program->setUniformValue(_texCoordRightLocation,
|
||||
(points[3].x - points[0].x) / _textureSize.width, (points[3].y - points[0].y) / _textureSize.height);
|
||||
_program->setUniformValue(_texCoordUpLocation,
|
||||
(points[1].x - points[0].x) / _textureSize.width, (points[1].y - points[0].y) / _textureSize.height);
|
||||
_program->setUniformValue(_aspectRatioLocation, _aspectRatio);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, 0);
|
||||
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_EQUAL, 1.0f);
|
||||
|
||||
if (_renderMode == MESH) {
|
||||
glDrawRangeElementsEXT(GL_TRIANGLES, 0, VERTEX_COUNT - 1, INDEX_COUNT, GL_UNSIGNED_INT, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
} else { // _renderMode == POINTS
|
||||
glPointSize(5.0f);
|
||||
glDrawArrays(GL_POINTS, 0, VERTEX_COUNT);
|
||||
glPointSize(1.0f);
|
||||
}
|
||||
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
_program->release();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(points[0].x / _textureSize.width, points[0].y / _textureSize.height);
|
||||
glVertex3f(0.5f, -0.5f / _aspectRatio, -0.5f);
|
||||
glTexCoord2f(points[1].x / _textureSize.width, points[1].y / _textureSize.height);
|
||||
glVertex3f(0.5f, 0.5f / _aspectRatio, -0.5f);
|
||||
glTexCoord2f(points[2].x / _textureSize.width, points[2].y / _textureSize.height);
|
||||
glVertex3f(-0.5f, 0.5f / _aspectRatio, -0.5f);
|
||||
glTexCoord2f(points[3].x / _textureSize.width, points[3].y / _textureSize.height);
|
||||
glVertex3f(-0.5f, -0.5f / _aspectRatio, -0.5f);
|
||||
glEnd();
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Face::cycleRenderMode() {
|
||||
_renderMode = (RenderMode)((_renderMode + 1) % RENDER_MODE_COUNT);
|
||||
}
|
||||
|
||||
void Face::setFrame(const cv::Mat& color, const cv::Mat& depth, float aspectRatio) {
|
||||
if (_colorTextureID == 0) {
|
||||
glGenTextures(1, &_colorTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, color.cols, color.rows, 0, GL_RGB, GL_UNSIGNED_BYTE, color.ptr());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
_textureSize = color.size();
|
||||
_textureRect = RotatedRect(Point2f(color.cols * 0.5f, color.rows * 0.5f), _textureSize, 0.0f);
|
||||
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, color.cols, color.rows, GL_RGB, GL_UNSIGNED_BYTE, color.ptr());
|
||||
}
|
||||
|
||||
if (!depth.empty()) {
|
||||
if (_depthTextureID == 0) {
|
||||
glGenTextures(1, &_depthTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _depthTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, depth.cols, depth.rows, 0,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, depth.ptr());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, _depthTextureID);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, depth.cols, depth.rows, GL_LUMINANCE, GL_UNSIGNED_BYTE, depth.ptr());
|
||||
}
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
_aspectRatio = aspectRatio;
|
||||
}
|
||||
|
75
interface/src/avatar/Face.h
Normal file
75
interface/src/avatar/Face.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// Face.h
|
||||
// interface
|
||||
//
|
||||
// Created by Andrzej Kapolka on 7/11/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__Face__
|
||||
#define __interface__Face__
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
#include <vpx_codec.h>
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
class Head;
|
||||
class ProgramObject;
|
||||
|
||||
class Face : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
Face(Head* owningHead);
|
||||
~Face();
|
||||
|
||||
void setColorTextureID(GLuint colorTextureID) { _colorTextureID = colorTextureID; }
|
||||
void setDepthTextureID(GLuint depthTextureID) { _depthTextureID = depthTextureID; }
|
||||
void setTextureSize(const cv::Size2f& textureSize) { _textureSize = textureSize; }
|
||||
void setTextureRect(const cv::RotatedRect& textureRect);
|
||||
|
||||
int processVideoMessage(unsigned char* packetData, size_t dataBytes);
|
||||
|
||||
bool render(float alpha);
|
||||
|
||||
public slots:
|
||||
|
||||
void cycleRenderMode();
|
||||
|
||||
private slots:
|
||||
|
||||
void setFrame(const cv::Mat& color, const cv::Mat& depth, float aspectRatio);
|
||||
|
||||
private:
|
||||
|
||||
enum RenderMode { MESH, POINTS, RENDER_MODE_COUNT };
|
||||
|
||||
Head* _owningHead;
|
||||
RenderMode _renderMode;
|
||||
GLuint _colorTextureID;
|
||||
GLuint _depthTextureID;
|
||||
cv::Size2f _textureSize;
|
||||
cv::RotatedRect _textureRect;
|
||||
float _aspectRatio;
|
||||
|
||||
vpx_codec_ctx_t _codec;
|
||||
|
||||
QByteArray _arrivingFrame;
|
||||
int _frameCount;
|
||||
int _frameBytesRemaining;
|
||||
|
||||
static ProgramObject* _program;
|
||||
static int _texCoordCornerLocation;
|
||||
static int _texCoordRightLocation;
|
||||
static int _texCoordUpLocation;
|
||||
static int _aspectRatioLocation;
|
||||
static GLuint _vboID;
|
||||
static GLuint _iboID;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__Face__) */
|
|
@ -95,6 +95,7 @@ void Hand::render(bool lookingInMirror) {
|
|||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_RESCALE_NORMAL);
|
||||
|
||||
renderFingerTrails();
|
||||
renderHandSpheres();
|
||||
}
|
||||
|
||||
|
@ -173,44 +174,35 @@ void Hand::renderHandSpheres() {
|
|||
glPopMatrix();
|
||||
}
|
||||
|
||||
void Hand::setLeapFingers(const std::vector<glm::vec3>& fingerTips,
|
||||
const std::vector<glm::vec3>& fingerRoots) {
|
||||
// TODO: add id-checking here to increase finger stability
|
||||
|
||||
size_t fingerIndex = 0;
|
||||
void Hand::renderFingerTrails() {
|
||||
// Draw the finger root cones
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
|
||||
FingerData& finger = palm.getFingers()[f];
|
||||
if (fingerIndex < fingerTips.size()) {
|
||||
finger.setActive(true);
|
||||
finger.setRawTipPosition(fingerTips[fingerIndex]);
|
||||
finger.setRawRootPosition(fingerRoots[fingerIndex]);
|
||||
fingerIndex++;
|
||||
}
|
||||
else {
|
||||
finger.setActive(false);
|
||||
if (palm.isActive()) {
|
||||
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
|
||||
FingerData& finger = palm.getFingers()[f];
|
||||
int numPositions = finger.getTrailNumPositions();
|
||||
if (numPositions > 0) {
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (int t = 0; t < numPositions; ++t)
|
||||
{
|
||||
const glm::vec3& center = finger.getTrailPosition(t);
|
||||
const float halfWidth = 0.001f;
|
||||
const glm::vec3 edgeDirection(1.0f, 0.0f, 0.0f);
|
||||
glm::vec3 edge0 = center + edgeDirection * halfWidth;
|
||||
glm::vec3 edge1 = center - edgeDirection * halfWidth;
|
||||
float alpha = 1.0f - ((float)t / (float)(numPositions - 1));
|
||||
glColor4f(1.0f, 0.0f, 0.0f, alpha);
|
||||
glVertex3fv((float*)&edge0);
|
||||
glVertex3fv((float*)&edge1);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Hand::setLeapHands(const std::vector<glm::vec3>& handPositions,
|
||||
const std::vector<glm::vec3>& handNormals) {
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
if (i < handPositions.size()) {
|
||||
palm.setActive(true);
|
||||
palm.setRawPosition(handPositions[i]);
|
||||
palm.setRawNormal(handNormals[i]);
|
||||
}
|
||||
else {
|
||||
palm.setActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Hand::updateFingerParticles(float deltaTime) {
|
||||
|
||||
if (!_particleSystemInitialized) {
|
|
@ -42,10 +42,6 @@ public:
|
|||
void render(bool lookingInMirror);
|
||||
|
||||
void setBallColor (glm::vec3 ballColor ) { _ballColor = ballColor; }
|
||||
void setLeapFingers (const std::vector<glm::vec3>& fingerTips,
|
||||
const std::vector<glm::vec3>& fingerRoots);
|
||||
void setLeapHands (const std::vector<glm::vec3>& handPositions,
|
||||
const std::vector<glm::vec3>& handNormals);
|
||||
void updateFingerParticles(float deltaTime);
|
||||
void setRaveGloveActive(bool active) { _isRaveGloveActive = active; }
|
||||
|
||||
|
@ -74,6 +70,7 @@ private:
|
|||
// private methods
|
||||
void renderRaveGloveStage();
|
||||
void renderHandSpheres();
|
||||
void renderFingerTrails();
|
||||
void calculateGeometry();
|
||||
};
|
||||
|
|
@ -82,7 +82,8 @@ Head::Head(Avatar* owningAvatar) :
|
|||
_cameraYaw(_yaw),
|
||||
_isCameraMoving(false),
|
||||
_cameraFollowsHead(false),
|
||||
_cameraFollowHeadRate(0.0f)
|
||||
_cameraFollowHeadRate(0.0f),
|
||||
_face(this)
|
||||
{
|
||||
if (USING_PHYSICAL_MOHAWK) {
|
||||
resetHairPhysics();
|
||||
|
@ -271,7 +272,7 @@ void Head::calculateGeometry() {
|
|||
+ up * _scale * BODY_BALL_RADIUS_HEAD_BASE * EYE_UP_OFFSET
|
||||
+ front * _scale * BODY_BALL_RADIUS_HEAD_BASE * EYE_FRONT_OFFSET;
|
||||
|
||||
_eyeLevelPosition = _position + up * _scale * EYE_UP_OFFSET;
|
||||
_eyeLevelPosition = _position + up * _scale * BODY_BALL_RADIUS_HEAD_BASE * EYE_UP_OFFSET;
|
||||
|
||||
//calculate the eyebrow positions
|
||||
_leftEyeBrowPosition = _leftEyePosition;
|
||||
|
@ -291,18 +292,20 @@ void Head::render(float alpha) {
|
|||
|
||||
_renderAlpha = alpha;
|
||||
|
||||
calculateGeometry();
|
||||
if (!_face.render(alpha)) {
|
||||
calculateGeometry();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_RESCALE_NORMAL);
|
||||
|
||||
renderMohawk();
|
||||
renderHeadSphere();
|
||||
renderEyeBalls();
|
||||
renderEars();
|
||||
renderMouth();
|
||||
renderEyeBrows();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_RESCALE_NORMAL);
|
||||
|
||||
renderMohawk();
|
||||
renderHeadSphere();
|
||||
renderEyeBalls();
|
||||
renderEars();
|
||||
renderMouth();
|
||||
renderEyeBrows();
|
||||
}
|
||||
|
||||
if (_renderLookatVectors) {
|
||||
renderLookatVectors(_leftEyePosition, _rightEyePosition, _lookAtPosition);
|
||||
}
|
||||
|
@ -592,7 +595,7 @@ void Head::renderEyeBalls() {
|
|||
glm::quat rotation = rotationBetween(front, targetLookatVector) * orientation;
|
||||
glm::vec3 rotationAxis = glm::axis(rotation);
|
||||
glRotatef(glm::angle(rotation), rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||
glTranslatef(0.0f, 0.0f, -IRIS_PROTRUSION);
|
||||
glTranslatef(0.0f, 0.0f, -_scale * IRIS_PROTRUSION);
|
||||
glScalef(_scale * IRIS_RADIUS * 2.0f,
|
||||
_scale * IRIS_RADIUS * 2.0f,
|
||||
_scale * IRIS_RADIUS); // flatten the iris
|
||||
|
@ -616,7 +619,7 @@ void Head::renderEyeBalls() {
|
|||
glm::quat rotation = rotationBetween(front, targetLookatVector) * orientation;
|
||||
glm::vec3 rotationAxis = glm::axis(rotation);
|
||||
glRotatef(glm::angle(rotation), rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||
glTranslatef(0.0f, 0.0f, -IRIS_PROTRUSION);
|
||||
glTranslatef(0.0f, 0.0f, -_scale * IRIS_PROTRUSION);
|
||||
glScalef(_scale * IRIS_RADIUS * 2.0f,
|
||||
_scale * IRIS_RADIUS * 2.0f,
|
||||
_scale * IRIS_RADIUS); // flatten the iris
|
|
@ -10,11 +10,17 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include <AvatarData.h>
|
||||
#include "world.h"
|
||||
|
||||
#include <VoxelConstants.h>
|
||||
|
||||
#include "Face.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "SerialInterface.h"
|
||||
#include <SharedUtil.h>
|
||||
#include "world.h"
|
||||
|
||||
enum eyeContactTargets
|
||||
{
|
||||
|
@ -53,12 +59,15 @@ public:
|
|||
glm::quat getOrientation() const;
|
||||
glm::quat getCameraOrientation () const;
|
||||
|
||||
float getScale() const { return _scale; }
|
||||
glm::vec3 getPosition() const { return _position; }
|
||||
const glm::vec3& getEyeLevelPosition() const { return _eyeLevelPosition; }
|
||||
glm::vec3 getRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
|
||||
glm::vec3 getUpDirection () const { return getOrientation() * IDENTITY_UP; }
|
||||
glm::vec3 getFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
|
||||
|
||||
Face& getFace() { return _face; }
|
||||
|
||||
const bool getReturnToCenter() const { return _returnHeadToCenter; } // Do you want head to try to return to center (depends on interface detected)
|
||||
float getAverageLoudness() {return _averageLoudness;};
|
||||
glm::vec3 calculateAverageEyePosition() { return _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF; }
|
||||
|
@ -120,6 +129,7 @@ private:
|
|||
bool _isCameraMoving;
|
||||
bool _cameraFollowsHead;
|
||||
float _cameraFollowHeadRate;
|
||||
Face _face;
|
||||
|
||||
static ProgramObject* _irisProgram;
|
||||
static GLuint _irisTextureID;
|
|
@ -13,15 +13,22 @@ HandData::HandData(AvatarData* owningAvatar) :
|
|||
_baseOrientation(0.0f, 0.0f, 0.0f, 1.0f),
|
||||
_owningAvatarData(owningAvatar)
|
||||
{
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
_palms.push_back(PalmData(this));
|
||||
}
|
||||
// Start with two palms
|
||||
addNewPalm();
|
||||
addNewPalm();
|
||||
}
|
||||
|
||||
PalmData& HandData::addNewPalm() {
|
||||
_palms.push_back(PalmData(this));
|
||||
return _palms.back();
|
||||
}
|
||||
|
||||
PalmData::PalmData(HandData* owningHandData) :
|
||||
_rawPosition(0, 0, 0),
|
||||
_rawNormal(0, 1, 0),
|
||||
_isActive(false),
|
||||
_leapID(LEAPID_INVALID),
|
||||
_numFramesWithoutData(0),
|
||||
_owningHandData(owningHandData)
|
||||
{
|
||||
for (int i = 0; i < NUM_FINGERS_PER_HAND; ++i) {
|
||||
|
@ -33,9 +40,13 @@ FingerData::FingerData(PalmData* owningPalmData, HandData* owningHandData) :
|
|||
_tipRawPosition(0, 0, 0),
|
||||
_rootRawPosition(0, 0, 0),
|
||||
_isActive(false),
|
||||
_leapID(LEAPID_INVALID),
|
||||
_numFramesWithoutData(0),
|
||||
_owningPalmData(owningPalmData),
|
||||
_owningHandData(owningHandData)
|
||||
{
|
||||
const int standardTrailLength = 30;
|
||||
setTrailLength(standardTrailLength);
|
||||
}
|
||||
|
||||
void HandData::encodeRemoteData(std::vector<glm::vec3>& fingerVectors) {
|
||||
|
@ -80,3 +91,66 @@ void HandData::decodeRemoteData(const std::vector<glm::vec3>& fingerVectors) {
|
|||
}
|
||||
}
|
||||
|
||||
void HandData::setFingerTrailLength(unsigned int length) {
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
|
||||
FingerData& finger = palm.getFingers()[f];
|
||||
finger.setTrailLength(length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandData::updateFingerTrails() {
|
||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
|
||||
FingerData& finger = palm.getFingers()[f];
|
||||
finger.updateTrail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FingerData::setTrailLength(unsigned int length) {
|
||||
_tipTrailPositions.resize(length);
|
||||
_tipTrailCurrentStartIndex = 0;
|
||||
_tipTrailCurrentValidLength = 0;
|
||||
}
|
||||
|
||||
void FingerData::updateTrail() {
|
||||
if (_tipTrailPositions.size() == 0)
|
||||
return;
|
||||
|
||||
if (_isActive) {
|
||||
// Add the next point in the trail.
|
||||
_tipTrailCurrentStartIndex--;
|
||||
if (_tipTrailCurrentStartIndex < 0)
|
||||
_tipTrailCurrentStartIndex = _tipTrailPositions.size() - 1;
|
||||
|
||||
_tipTrailPositions[_tipTrailCurrentStartIndex] = getTipPosition();
|
||||
|
||||
if (_tipTrailCurrentValidLength < _tipTrailPositions.size())
|
||||
_tipTrailCurrentValidLength++;
|
||||
}
|
||||
else {
|
||||
// It's not active, so just shorten the trail.
|
||||
if (_tipTrailCurrentValidLength > 0)
|
||||
_tipTrailCurrentValidLength--;
|
||||
}
|
||||
}
|
||||
|
||||
int FingerData::getTrailNumPositions() {
|
||||
return _tipTrailCurrentValidLength;
|
||||
}
|
||||
|
||||
const glm::vec3& FingerData::getTrailPosition(int index) {
|
||||
if (index >= _tipTrailCurrentValidLength) {
|
||||
static glm::vec3 zero(0,0,0);
|
||||
return zero;
|
||||
}
|
||||
int posIndex = (index + _tipTrailCurrentStartIndex) % _tipTrailCurrentValidLength;
|
||||
return _tipTrailPositions[posIndex];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ class FingerData;
|
|||
class PalmData;
|
||||
|
||||
const int NUM_FINGERS_PER_HAND = 5;
|
||||
const int LEAPID_INVALID = -1;
|
||||
|
||||
class HandData {
|
||||
public:
|
||||
|
@ -39,6 +40,10 @@ public:
|
|||
|
||||
std::vector<PalmData>& getPalms() { return _palms; }
|
||||
size_t getNumPalms() { return _palms.size(); }
|
||||
PalmData& addNewPalm();
|
||||
|
||||
void setFingerTrailLength(unsigned int length);
|
||||
void updateFingerTrails();
|
||||
|
||||
// Use these for sending and receiving hand data
|
||||
void encodeRemoteData(std::vector<glm::vec3>& fingerVectors);
|
||||
|
@ -65,15 +70,31 @@ public:
|
|||
const glm::vec3& getTipRawPosition() const { return _tipRawPosition; }
|
||||
const glm::vec3& getRootRawPosition() const { return _rootRawPosition; }
|
||||
bool isActive() const { return _isActive; }
|
||||
int getLeapID() const { return _leapID; }
|
||||
|
||||
void setActive(bool active) { _isActive = active; }
|
||||
void setLeapID(int id) { _leapID = id; }
|
||||
void setRawTipPosition(const glm::vec3& pos) { _tipRawPosition = pos; }
|
||||
void setRawRootPosition(const glm::vec3& pos) { _rootRawPosition = pos; }
|
||||
void setTrailLength(unsigned int length);
|
||||
void updateTrail();
|
||||
|
||||
int getTrailNumPositions();
|
||||
const glm::vec3& getTrailPosition(int index);
|
||||
|
||||
void incrementFramesWithoutData() { _numFramesWithoutData++; }
|
||||
void resetFramesWithoutData() { _numFramesWithoutData = 0; }
|
||||
int getFramesWithoutData() const { return _numFramesWithoutData; }
|
||||
|
||||
private:
|
||||
glm::vec3 _tipRawPosition;
|
||||
glm::vec3 _rootRawPosition;
|
||||
bool _isActive; // This has current valid data
|
||||
bool _isActive; // This has current valid data
|
||||
int _leapID; // the Leap's serial id for this tracked object
|
||||
int _numFramesWithoutData; // after too many frames without data, this tracked object assumed lost.
|
||||
std::vector<glm::vec3> _tipTrailPositions;
|
||||
int _tipTrailCurrentStartIndex;
|
||||
int _tipTrailCurrentValidLength;
|
||||
PalmData* _owningPalmData;
|
||||
HandData* _owningHandData;
|
||||
};
|
||||
|
@ -86,19 +107,27 @@ public:
|
|||
const glm::vec3& getRawPosition() const { return _rawPosition; }
|
||||
const glm::vec3& getRawNormal() const { return _rawNormal; }
|
||||
bool isActive() const { return _isActive; }
|
||||
int getLeapID() const { return _leapID; }
|
||||
|
||||
std::vector<FingerData>& getFingers() { return _fingers; }
|
||||
size_t getNumFingers() { return _fingers.size(); }
|
||||
|
||||
void setActive(bool active) { _isActive = active; }
|
||||
void setLeapID(int id) { _leapID = id; }
|
||||
void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; }
|
||||
void setRawNormal(const glm::vec3& normal) { _rawNormal = normal; }
|
||||
|
||||
void incrementFramesWithoutData() { _numFramesWithoutData++; }
|
||||
void resetFramesWithoutData() { _numFramesWithoutData = 0; }
|
||||
int getFramesWithoutData() const { return _numFramesWithoutData; }
|
||||
|
||||
private:
|
||||
std::vector<FingerData> _fingers;
|
||||
glm::vec3 _rawPosition;
|
||||
glm::vec3 _rawNormal;
|
||||
bool _isActive; // This has current valid data
|
||||
bool _isActive; // This has current valid data
|
||||
int _leapID; // the Leap's serial id for this tracked object
|
||||
int _numFramesWithoutData; // after too many frames without data, this tracked object assumed lost.
|
||||
HandData* _owningHandData;
|
||||
};
|
||||
|
||||
|
|
|
@ -499,6 +499,37 @@ void NodeList::startSilentNodeRemovalThread() {
|
|||
void NodeList::stopSilentNodeRemovalThread() {
|
||||
silentNodeThreadStopFlag = true;
|
||||
pthread_join(removeSilentNodesThread, NULL);
|
||||
|
||||
}
|
||||
|
||||
const QString QSETTINGS_GROUP_NAME = "NodeList";
|
||||
const QString DOMAIN_SERVER_SETTING_KEY = "domainServerHostname";
|
||||
|
||||
void NodeList::loadData(QSettings *settings) {
|
||||
settings->beginGroup(DOMAIN_SERVER_SETTING_KEY);
|
||||
|
||||
QString domainServerHostname = settings->value(DOMAIN_SERVER_SETTING_KEY).toString();
|
||||
|
||||
if (domainServerHostname.size() > 0) {
|
||||
memset(_domainHostname, 0, MAX_HOSTNAME_BYTES);
|
||||
memcpy(_domainHostname, domainServerHostname.toAscii().constData(), domainServerHostname.size());
|
||||
}
|
||||
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
void NodeList::saveData(QSettings* settings) {
|
||||
settings->beginGroup(DOMAIN_SERVER_SETTING_KEY);
|
||||
|
||||
if (memcmp(_domainHostname, DEFAULT_DOMAIN_HOSTNAME, strlen(DEFAULT_DOMAIN_HOSTNAME)) != 0) {
|
||||
// the user is using a different hostname, store it
|
||||
settings->setValue(DOMAIN_SERVER_SETTING_KEY, QVariant(_domainHostname));
|
||||
} else {
|
||||
// the user has switched back to default, remove the current setting
|
||||
settings->remove(DOMAIN_SERVER_SETTING_KEY);
|
||||
}
|
||||
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
NodeList::iterator NodeList::begin() const {
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <iterator>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
#include "Node.h"
|
||||
#include "UDPSocket.h"
|
||||
|
||||
|
@ -32,7 +34,7 @@ const int DOMAIN_SERVER_CHECK_IN_USECS = 1 * 1000000;
|
|||
|
||||
extern const char SOLO_NODE_TYPES[3];
|
||||
|
||||
const int MAX_HOSTNAME_BYTES = 255;
|
||||
const int MAX_HOSTNAME_BYTES = 256;
|
||||
|
||||
extern const char DEFAULT_DOMAIN_HOSTNAME[MAX_HOSTNAME_BYTES];
|
||||
extern const char DEFAULT_DOMAIN_IP[INET_ADDRSTRLEN]; // IP Address will be re-set by lookup on startup
|
||||
|
@ -99,6 +101,9 @@ public:
|
|||
void startSilentNodeRemovalThread();
|
||||
void stopSilentNodeRemovalThread();
|
||||
|
||||
void loadData(QSettings* settings);
|
||||
void saveData(QSettings* settings);
|
||||
|
||||
friend class NodeListIterator;
|
||||
private:
|
||||
static NodeList* _sharedInstance;
|
||||
|
|
|
@ -29,6 +29,7 @@ const PACKET_TYPE PACKET_TYPE_VOXEL_DATA = 'V';
|
|||
const PACKET_TYPE PACKET_TYPE_VOXEL_DATA_MONOCHROME = 'v';
|
||||
const PACKET_TYPE PACKET_TYPE_BULK_AVATAR_DATA = 'X';
|
||||
const PACKET_TYPE PACKET_TYPE_AVATAR_VOXEL_URL = 'U';
|
||||
const PACKET_TYPE PACKET_TYPE_AVATAR_FACE_VIDEO = 'F';
|
||||
const PACKET_TYPE PACKET_TYPE_TRANSMITTER_DATA_V2 = 'T';
|
||||
const PACKET_TYPE PACKET_TYPE_ENVIRONMENT_DATA = 'e';
|
||||
const PACKET_TYPE PACKET_TYPE_DOMAIN_LIST_REQUEST = 'L';
|
||||
|
|
|
@ -364,8 +364,6 @@ bool ViewFrustum::matches(const ViewFrustum& compareTo, bool debug) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ViewFrustum::computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const {
|
||||
origin = _nearTopLeft + x*(_nearTopRight - _nearTopLeft) + y*(_nearBottomLeft - _nearTopLeft);
|
||||
direction = glm::normalize(origin - _position);
|
||||
|
|
|
@ -44,9 +44,9 @@ const int MIN_BRIGHTNESS = 64;
|
|||
const float DEATH_STAR_RADIUS = 4.0;
|
||||
const float MAX_CUBE = 0.05f;
|
||||
|
||||
const int VOXEL_SEND_INTERVAL_USECS = 100 * 1000;
|
||||
int PACKETS_PER_CLIENT_PER_INTERVAL = 30;
|
||||
const int SENDING_TIME_TO_SPARE = 20 * 1000; // usec of sending interval to spare for calculating voxels
|
||||
const int VOXEL_SEND_INTERVAL_USECS = 17 * 1000; // approximately 60fps
|
||||
int PACKETS_PER_CLIENT_PER_INTERVAL = 20;
|
||||
const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels
|
||||
|
||||
const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
|
||||
|
||||
|
|
Loading…
Reference in a new issue