Compare commits
47 Commits
main
...
v1.5.2-Fir
Author | SHA1 | Date | |
---|---|---|---|
![]() |
01d9132430 | ||
![]() |
778e87520e | ||
![]() |
ac9ca8f879 | ||
![]() |
48002c8091 | ||
![]() |
8ce9ff9e34 | ||
![]() |
941966f1e8 | ||
![]() |
21e44bda8b | ||
![]() |
c9b3fe54a4 | ||
![]() |
e264547368 | ||
![]() |
347c463f0a | ||
![]() |
e1a472cab5 | ||
![]() |
71d99d0408 | ||
![]() |
e5d0bce6d0 | ||
![]() |
b664150875 | ||
![]() |
6212a5984b | ||
![]() |
1539616777 | ||
![]() |
d804e8b443 | ||
![]() |
0ce464d83e | ||
![]() |
08473ae184 | ||
![]() |
02d7f3d386 | ||
![]() |
59cec41c53 | ||
![]() |
2610ab1832 | ||
![]() |
1072deea64 | ||
![]() |
9e1f1790e3 | ||
![]() |
fdc713099e | ||
![]() |
32c51ecb11 | ||
![]() |
c24aad5654 | ||
![]() |
f99f65099b | ||
![]() |
e007606545 | ||
![]() |
9c88070c6e | ||
![]() |
6e052edcef | ||
![]() |
fcab199083 | ||
![]() |
aa2c5cee0d | ||
![]() |
68c6835c76 | ||
![]() |
e86a91498d | ||
![]() |
97ba688a54 | ||
![]() |
02904aa40e | ||
![]() |
a58e169ee8 | ||
![]() |
0b2d724c3e | ||
![]() |
d6b1680842 | ||
![]() |
c6714d395f | ||
![]() |
ba5a21705b | ||
![]() |
b548bd098e | ||
![]() |
ccf994f00a | ||
![]() |
7fc14895ee | ||
![]() |
8599789ac0 | ||
![]() |
a1e09bf8c0 |
33
Makefile
33
Makefile
@ -33,8 +33,8 @@ GMP_API_BRANCH=Firefox39
|
||||
CCASFLAGS=$(CFLAGS)
|
||||
STATIC_LDFLAGS=-lstdc++
|
||||
|
||||
VERSION=1.4
|
||||
SHAREDLIBVERSION=0
|
||||
VERSION=1.5.2
|
||||
SHAREDLIBVERSION=1
|
||||
|
||||
ifeq (,$(wildcard $(SRC_PATH)gmp-api))
|
||||
HAVE_GMP_API=No
|
||||
@ -52,6 +52,10 @@ endif
|
||||
ifeq ($(BUILDTYPE), Release)
|
||||
CFLAGS += $(CFLAGS_OPT)
|
||||
USE_ASM = Yes
|
||||
ifeq ($(DEBUGSYMBOLS), True)
|
||||
CFLAGS += -g
|
||||
CXXFLAGS += -g
|
||||
endif
|
||||
else
|
||||
CFLAGS += $(CFLAGS_DEBUG)
|
||||
USE_ASM = No
|
||||
@ -62,11 +66,17 @@ CFLAGS += -fsanitize=address
|
||||
LDFLAGS += -fsanitize=address
|
||||
endif
|
||||
|
||||
STRIP_FLAGS := -S
|
||||
ifeq (linux, $((OS)))
|
||||
STRIP_FLAGS := -g
|
||||
endif
|
||||
|
||||
# Make sure the all target is the first one
|
||||
all: libraries binaries
|
||||
|
||||
include $(SRC_PATH)build/platform-$(OS).mk
|
||||
|
||||
MODULE := $(LIBPREFIX)$(MODULE_NAME).$(SHAREDLIBSUFFIX)
|
||||
|
||||
CFLAGS += -DGENERATED_VERSION_HEADER
|
||||
LDFLAGS +=
|
||||
@ -215,10 +225,16 @@ LIBRARIES += $(LIBPREFIX)$(PROJECT_NAME).$(LIBSUFFIX) $(LIBPREFIX)$(PROJECT_NAME
|
||||
$(LIBPREFIX)$(PROJECT_NAME).$(LIBSUFFIX): $(ENCODER_OBJS) $(DECODER_OBJS) $(PROCESSING_OBJS) $(COMMON_OBJS)
|
||||
$(QUIET)rm -f $@
|
||||
$(QUIET_AR)$(AR) $(AR_OPTS) $+
|
||||
ifeq (True, $(DEBUGSYMBOLS))
|
||||
strip $(STRIP_FLAGS) $@ -o $(LIBPREFIX)$(PROJECT_NAME)_stripped.$(LIBSUFFIX)
|
||||
endif
|
||||
|
||||
$(LIBPREFIX)$(PROJECT_NAME).$(SHAREDLIBSUFFIXVER): $(ENCODER_OBJS) $(DECODER_OBJS) $(PROCESSING_OBJS) $(COMMON_OBJS)
|
||||
$(QUIET)rm -f $@
|
||||
$(QUIET_CXX)$(CXX) $(SHARED) $(CXX_LINK_O) $+ $(LDFLAGS) $(SHLDFLAGS)
|
||||
ifeq (True, $(DEBUGSYMBOLS))
|
||||
strip $(STRIP_FLAGS) $@ -o $(LIBPREFIX)$(PROJECT_NAME)_stripped.$(SHAREDLIBSUFFIXVER)
|
||||
endif
|
||||
|
||||
ifneq ($(SHAREDLIBSUFFIXVER),$(SHAREDLIBSUFFIX))
|
||||
$(LIBPREFIX)$(PROJECT_NAME).$(SHAREDLIBSUFFIX): $(LIBPREFIX)$(PROJECT_NAME).$(SHAREDLIBSUFFIXVER)
|
||||
@ -226,7 +242,7 @@ $(LIBPREFIX)$(PROJECT_NAME).$(SHAREDLIBSUFFIX): $(LIBPREFIX)$(PROJECT_NAME).$(SH
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_GMP_API),Yes)
|
||||
plugin: $(LIBPREFIX)$(MODULE_NAME).$(SHAREDLIBSUFFIX)
|
||||
plugin: $(MODULE)
|
||||
LIBRARIES += $(LIBPREFIX)$(MODULE_NAME).$(SHAREDLIBSUFFIXVER)
|
||||
else
|
||||
plugin:
|
||||
@ -234,13 +250,22 @@ plugin:
|
||||
@echo "You do not have gmp-api. Run make gmp-bootstrap to get the gmp-api headers."
|
||||
endif
|
||||
|
||||
echo-plugin-name:
|
||||
@echo $(MODULE)
|
||||
|
||||
$(LIBPREFIX)$(MODULE_NAME).$(SHAREDLIBSUFFIXVER): $(MODULE_OBJS) $(ENCODER_OBJS) $(DECODER_OBJS) $(PROCESSING_OBJS) $(COMMON_OBJS)
|
||||
$(QUIET)rm -f $@
|
||||
$(QUIET_CXX)$(CXX) $(SHARED) $(CXX_LINK_O) $+ $(LDFLAGS) $(SHLDFLAGS) $(MODULE_LDFLAGS)
|
||||
ifeq (True, $(DEBUGSYMBOLS))
|
||||
strip $(STRIP_FLAGS) $@ -o $(LIBPREFIX)$(MODULE_NAME)_stripped.$(SHAREDLIBSUFFIXVER)
|
||||
endif
|
||||
|
||||
ifneq ($(SHAREDLIBSUFFIXVER),$(SHAREDLIBSUFFIX))
|
||||
$(LIBPREFIX)$(MODULE_NAME).$(SHAREDLIBSUFFIX): $(LIBPREFIX)$(MODULE_NAME).$(SHAREDLIBSUFFIXVER)
|
||||
$(MODULE): $(LIBPREFIX)$(MODULE_NAME).$(SHAREDLIBSUFFIXVER)
|
||||
$(QUIET)ln -sfn $+ $@
|
||||
ifeq (True, $(DEBUGSYMBOLS))
|
||||
$(QUIET)ln -sfn $(LIBPREFIX)$(MODULE_NAME)_stripped.$(SHAREDLIBSUFFIXVER) $(LIBPREFIX)$(MODULE_NAME)_stripped.$(SHAREDLIBSUFFIX)
|
||||
endif
|
||||
endif
|
||||
|
||||
$(PROJECT_NAME).pc: $(PROJECT_NAME).pc.in
|
||||
|
@ -129,6 +129,7 @@ From the main project directory:
|
||||
- `make ARCH=i386` for x86 32bit builds
|
||||
- `make ARCH=x86_64` for x86 64bit builds
|
||||
- `make V=No` for a silent build (not showing the actual compiler commands)
|
||||
- `make DEBUGSYMBOLS=True` for two libraries, one is normal libraries, another one is removed the debugging symbol table entries (those created by the -g option )
|
||||
|
||||
The command line programs `h264enc` and `h264dec` will appear in the main project directory.
|
||||
|
||||
|
47
RELEASES
47
RELEASES
@ -1,6 +1,42 @@
|
||||
|
||||
Releases
|
||||
-----------
|
||||
v1.5.2
|
||||
------
|
||||
- Fix GMP Plugin causing the Browser crash on Android
|
||||
|
||||
v1.5.1
|
||||
------
|
||||
- Bug fixes for GMP Plugin
|
||||
|
||||
v1.5.0
|
||||
------
|
||||
- Correct a typo in codec return value (github issue#2046, cmUnkonwReason -> cmUnknownReason)
|
||||
- Added Codec demo and auto build script for WP8
|
||||
- Decoder support of 'Constrained High Profile' of H.264
|
||||
- Encoder support of CABAC of H.264
|
||||
- Encoder support of input frame rate 60
|
||||
- Improved syntax of gaps_in_frame_num_value_allowed_flag in encoder
|
||||
- Improved memory usage for multi-threading in encoder
|
||||
- Added VUI info for base layer in encoder
|
||||
- Added encoder interface to get external setting of iMaxQp and iMinQp for rate control
|
||||
- Bug fixes for Rate Control, multi-threading and simulcasting in encoder
|
||||
- Bug fixes for NoDelay API, ParseOnly functions, error-concealment off functiond and error-detection in decoder
|
||||
- Bug fixes for UT
|
||||
- Fixes to avoid valgrind warnings, potential crash and calculation overflow
|
||||
- Merged files for decoder/encoder and remove unused files
|
||||
- Improvements on build scripts, UT, error-protection in decoder, input param checking in encoder, assembly for 64bit support, downsampling, logging and documentation
|
||||
|
||||
Note:
|
||||
'Constrained High Profile' = 'Constrained Baseline Profile' plus:
|
||||
- CABAC
|
||||
- Intra 8x8 mode support
|
||||
- 8x8 transform
|
||||
- QP scaling matrices
|
||||
- QP per chroma component
|
||||
- Mono 4:0:0 (experimental)
|
||||
- Weighted prediction
|
||||
|
||||
v1.4.0
|
||||
------
|
||||
- Decoder new interface of DecodeFrameNoDelay
|
||||
@ -67,6 +103,17 @@ Binaries
|
||||
These binary releases are distributed under this license:
|
||||
http://www.openh264.org/BINARY_LICENSE.txt
|
||||
|
||||
v1.5.0
|
||||
------
|
||||
http://ciscobinary.openh264.org/libopenh264-1.5.0-android19.so.bz2
|
||||
http://ciscobinary.openh264.org/libopenh264-1.5.0-ios.a.bz2
|
||||
http://ciscobinary.openh264.org/libopenh264-1.5.0-linux32.so.bz2
|
||||
http://ciscobinary.openh264.org/libopenh264-1.5.0-linux64.so.bz2
|
||||
http://ciscobinary.openh264.org/libopenh264-1.5.0-osx32.dylib.bz2
|
||||
http://ciscobinary.openh264.org/libopenh264-1.5.0-osx64.dylib.bz2
|
||||
http://ciscobinary.openh264.org/openh264-1.5.0-win32msvc.dll.bz2
|
||||
http://ciscobinary.openh264.org/openh264-1.5.0-win64msvc.dll.bz2
|
||||
|
||||
v1.4.0
|
||||
------
|
||||
http://ciscobinary.openh264.org/libopenh264-1.4.0-android19.so.bz2
|
||||
|
@ -22,7 +22,7 @@ CXX_O=-Fo$@
|
||||
# it unconditionally. The same issue can also be worked around by adding
|
||||
# -DGTEST_HAS_TR1_TUPLE=0 instead, but we prefer this version since it
|
||||
# matches what gtest itself does.
|
||||
CFLAGS += -nologo -Fd$(PROJECT_NAME).pdb -W3 -EHsc -fp:precise -Zc:wchar_t -Zc:forScope -D_VARIADIC_MAX=10
|
||||
CFLAGS += -nologo -W3 -EHsc -fp:precise -Zc:wchar_t -Zc:forScope -D_VARIADIC_MAX=10
|
||||
CXX_LINK_O=-nologo -Fe$@
|
||||
AR_OPTS=-nologo -out:$@
|
||||
CFLAGS_OPT=-O2 -Ob1 -Oy- -Zi -GF -Gm- -GS -Gy -DNDEBUG
|
||||
@ -41,7 +41,7 @@ SHAREDLIBSUFFIXVER=$(SHAREDLIBSUFFIX)
|
||||
SHARED=-LD
|
||||
EXTRA_LIBRARY=$(PROJECT_NAME)_dll.lib
|
||||
LDFLAGS += -link
|
||||
SHLDFLAGS=-pdb:$(PROJECT_NAME).pdb -def:$(SRC_PATH)openh264.def -implib:$(EXTRA_LIBRARY)
|
||||
SHLDFLAGS=-debug -opt:ref -opt:icf -def:$(SRC_PATH)openh264.def -implib:$(EXTRA_LIBRARY)
|
||||
STATIC_LDFLAGS=
|
||||
CODEC_UNITTEST_CFLAGS=-D_CRT_SECURE_NO_WARNINGS
|
||||
|
||||
|
@ -80,7 +80,7 @@ typedef enum {
|
||||
typedef enum {
|
||||
cmResultSuccess, ///< successful
|
||||
cmInitParaError, ///< parameters are invalid
|
||||
cmUnkonwReason,
|
||||
cmUnknownReason,
|
||||
cmMallocMemeError, ///< malloc a memory error
|
||||
cmInitExpected, ///< initial action is expected
|
||||
cmUnsupportedData
|
||||
|
@ -4,12 +4,12 @@
|
||||
|
||||
#include "codec_app_def.h"
|
||||
|
||||
static const OpenH264Version g_stCodecVersion = {1, 4, 1, 0};
|
||||
static const char* const g_strCodecVer = "OpenH264 version:1.4.1.0";
|
||||
static const OpenH264Version g_stCodecVersion = {1, 5, 2, 0};
|
||||
static const char* const g_strCodecVer = "OpenH264 version:1.5.2.0";
|
||||
|
||||
#define OPENH264_MAJOR (1)
|
||||
#define OPENH264_MINOR (4)
|
||||
#define OPENH264_REVISION (1)
|
||||
#define OPENH264_MINOR (5)
|
||||
#define OPENH264_REVISION (2)
|
||||
#define OPENH264_RESERVED (0)
|
||||
|
||||
#endif // CODEC_VER_H
|
||||
|
@ -79,7 +79,7 @@ typedef struct TagWelsTime {
|
||||
|
||||
int32_t WelsSnprintf (char* buffer, int32_t sizeOfBuffer, const char* format, ...);
|
||||
char* WelsStrncpy (char* dest, int32_t sizeInBytes, const char* src);
|
||||
char* WelsStrcat (char* dest, int32_t sizeInBytes, const char* src);
|
||||
char* WelsStrcat (char* dest, uint32_t sizeInBytes, const char* src);
|
||||
int32_t WelsVsnprintf (char* buffer, int32_t sizeOfBuffer, const char* format, va_list argptr);
|
||||
|
||||
WelsFileHandle* WelsFopen (const char* filename, const char* mode);
|
||||
|
@ -242,9 +242,11 @@ int32_t WelsStrftime (char* pBuffer, int32_t iSize, const char* kpFormat, const
|
||||
#endif
|
||||
|
||||
|
||||
char* WelsStrcat (char* pDest, int32_t iSizeInBytes, const char* kpSrc) {
|
||||
int32_t iCurLen = (int32_t)strlen (pDest);
|
||||
return WelsStrncpy (pDest + iCurLen, iSizeInBytes - iCurLen, kpSrc);
|
||||
char* WelsStrcat (char* pDest, uint32_t uiSizeInBytes, const char* kpSrc) {
|
||||
uint32_t uiCurLen = (uint32_t) strlen (pDest);
|
||||
if (uiSizeInBytes > uiCurLen)
|
||||
return WelsStrncpy (pDest + uiCurLen, uiSizeInBytes - uiCurLen, kpSrc);
|
||||
return pDest;
|
||||
}
|
||||
|
||||
int32_t WelsFwrite (const void* kpBuffer, int32_t iSize, int32_t iCount, WelsFileHandle* pFp) {
|
||||
|
@ -21,14 +21,14 @@ void DeblockLumaLt4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_
|
||||
bool bDetaP2P0 = WELS_ABS (p2 - p0) < iBeta;
|
||||
bool bDetaQ2Q0 = WELS_ABS (q2 - q0) < iBeta;
|
||||
if (bDetaP2P0) {
|
||||
pPix[-2 * iStrideX] = p1 + WELS_CLIP3 ((p2 + ((p0 + q0 + 1) >> 1) - (p1 << 1)) >> 1, -iTc0, iTc0);
|
||||
pPix[-2 * iStrideX] = p1 + WELS_CLIP3 ((p2 + ((p0 + q0 + 1) >> 1) - (p1 * (1 << 1))) >> 1, -iTc0, iTc0);
|
||||
iTc++;
|
||||
}
|
||||
if (bDetaQ2Q0) {
|
||||
pPix[iStrideX] = q1 + WELS_CLIP3 ((q2 + ((p0 + q0 + 1) >> 1) - (q1 << 1)) >> 1, -iTc0, iTc0);
|
||||
pPix[iStrideX] = q1 + WELS_CLIP3 ((q2 + ((p0 + q0 + 1) >> 1) - (q1 * (1 << 1))) >> 1, -iTc0, iTc0);
|
||||
iTc++;
|
||||
}
|
||||
int32_t iDeta = WELS_CLIP3 ((((q0 - p0) << 2) + (p1 - q1) + 4) >> 3, -iTc, iTc);
|
||||
int32_t iDeta = WELS_CLIP3 ((((q0 - p0) * (1 << 2)) + (p1 - q1) + 4) >> 3, -iTc, iTc);
|
||||
pPix[-iStrideX] = WelsClip1 (p0 + iDeta); /* p0' */
|
||||
pPix[0] = WelsClip1 (q0 - iDeta); /* q0' */
|
||||
}
|
||||
@ -56,23 +56,23 @@ void DeblockLumaEq4_c (uint8_t* pPix, int32_t iStrideX, int32_t iStrideY, int32_
|
||||
bool bDetaQ2Q0 = WELS_ABS (q2 - q0) < iBeta;
|
||||
if (bDetaP2P0) {
|
||||
const int32_t p3 = pPix[-4 * iStrideX];
|
||||
pPix[-iStrideX] = (p2 + (p1 << 1) + (p0 << 1) + (q0 << 1) + q1 + 4) >> 3; //p0
|
||||
pPix[-iStrideX] = (p2 + (p1 * (1 << 1)) + (p0 * (1 << 1)) + (q0 * (1 << 1)) + q1 + 4) >> 3; //p0
|
||||
pPix[-2 * iStrideX] = (p2 + p1 + p0 + q0 + 2) >> 2; //p1
|
||||
pPix[-3 * iStrideX] = ((p3 << 1) + p2 + (p2 << 1) + p1 + p0 + q0 + 4) >> 3; //p2
|
||||
pPix[-3 * iStrideX] = ((p3 * (1 << 1)) + p2 + (p2 * (1 << 1)) + p1 + p0 + q0 + 4) >> 3; //p2
|
||||
} else {
|
||||
pPix[-1 * iStrideX] = ((p1 << 1) + p0 + q1 + 2) >> 2; //p0
|
||||
pPix[-1 * iStrideX] = ((p1 * (1 << 1)) + p0 + q1 + 2) >> 2; //p0
|
||||
}
|
||||
if (bDetaQ2Q0) {
|
||||
const int32_t q3 = pPix[3 * iStrideX];
|
||||
pPix[0] = (p1 + (p0 << 1) + (q0 << 1) + (q1 << 1) + q2 + 4) >> 3; //q0
|
||||
pPix[0] = (p1 + (p0 * (1 << 1)) + (q0 * (1 << 1)) + (q1 * (1 << 1)) + q2 + 4) >> 3; //q0
|
||||
pPix[iStrideX] = (p0 + q0 + q1 + q2 + 2) >> 2; //q1
|
||||
pPix[2 * iStrideX] = ((q3 << 1) + q2 + (q2 << 1) + q1 + q0 + p0 + 4) >> 3; //q2
|
||||
pPix[2 * iStrideX] = ((q3 * (1 << 1)) + q2 + (q2 * (1 << 1)) + q1 + q0 + p0 + 4) >> 3; //q2
|
||||
} else {
|
||||
pPix[0] = ((q1 << 1) + q0 + p1 + 2) >> 2; //q0
|
||||
pPix[0] = ((q1 * (1 << 1)) + q0 + p1 + 2) >> 2; //q0
|
||||
}
|
||||
} else {
|
||||
pPix[-iStrideX] = ((p1 << 1) + p0 + q1 + 2) >> 2; //p0
|
||||
pPix[ 0] = ((q1 << 1) + q0 + p1 + 2) >> 2; //q0
|
||||
pPix[-iStrideX] = ((p1 * (1 << 1)) + p0 + q1 + 2) >> 2; //p0
|
||||
pPix[ 0] = ((q1 * (1 << 1)) + q0 + p1 + 2) >> 2; //q0
|
||||
}
|
||||
}
|
||||
pPix += iStrideY;
|
||||
@ -107,7 +107,7 @@ void DeblockChromaLt4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int
|
||||
bDetaP1P0 = WELS_ABS (p1 - p0) < iBeta;
|
||||
bDetaQ1Q0 = WELS_ABS (q1 - q0) < iBeta;
|
||||
if (bDetaP0Q0 && bDetaP1P0 && bDetaQ1Q0) {
|
||||
iDeta = WELS_CLIP3 ((((q0 - p0) << 2) + (p1 - q1) + 4) >> 3, -iTc0, iTc0);
|
||||
iDeta = WELS_CLIP3 ((((q0 - p0) * (1 << 2)) + (p1 - q1) + 4) >> 3, -iTc0, iTc0);
|
||||
pPixCb[-iStrideX] = WelsClip1 (p0 + iDeta); /* p0' */
|
||||
pPixCb[0] = WelsClip1 (q0 - iDeta); /* q0' */
|
||||
}
|
||||
@ -123,7 +123,7 @@ void DeblockChromaLt4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int
|
||||
bDetaQ1Q0 = WELS_ABS (q1 - q0) < iBeta;
|
||||
|
||||
if (bDetaP0Q0 && bDetaP1P0 && bDetaQ1Q0) {
|
||||
iDeta = WELS_CLIP3 ((((q0 - p0) << 2) + (p1 - q1) + 4) >> 3, -iTc0, iTc0);
|
||||
iDeta = WELS_CLIP3 ((((q0 - p0) * (1 << 2)) + (p1 - q1) + 4) >> 3, -iTc0, iTc0);
|
||||
pPixCr[-iStrideX] = WelsClip1 (p0 + iDeta); /* p0' */
|
||||
pPixCr[0] = WelsClip1 (q0 - iDeta); /* q0' */
|
||||
}
|
||||
@ -146,8 +146,8 @@ void DeblockChromaEq4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int
|
||||
bDetaP1P0 = WELS_ABS (p1 - p0) < iBeta;
|
||||
bDetaQ1Q0 = WELS_ABS (q1 - q0) < iBeta;
|
||||
if (bDetaP0Q0 && bDetaP1P0 && bDetaQ1Q0) {
|
||||
pPixCb[-iStrideX] = ((p1 << 1) + p0 + q1 + 2) >> 2; /* p0' */
|
||||
pPixCb[0] = ((q1 << 1) + q0 + p1 + 2) >> 2; /* q0' */
|
||||
pPixCb[-iStrideX] = ((p1 * (1 << 1)) + p0 + q1 + 2) >> 2; /* p0' */
|
||||
pPixCb[0] = ((q1 * (1 << 1)) + q0 + p1 + 2) >> 2; /* q0' */
|
||||
}
|
||||
|
||||
//cr
|
||||
@ -159,8 +159,8 @@ void DeblockChromaEq4_c (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iStrideX, int
|
||||
bDetaP1P0 = WELS_ABS (p1 - p0) < iBeta;
|
||||
bDetaQ1Q0 = WELS_ABS (q1 - q0) < iBeta;
|
||||
if (bDetaP0Q0 && bDetaP1P0 && bDetaQ1Q0) {
|
||||
pPixCr[-iStrideX] = ((p1 << 1) + p0 + q1 + 2) >> 2; /* p0' */
|
||||
pPixCr[0] = ((q1 << 1) + q0 + p1 + 2) >> 2; /* q0' */
|
||||
pPixCr[-iStrideX] = ((p1 * (1 << 1)) + p0 + q1 + 2) >> 2; /* p0' */
|
||||
pPixCr[0] = ((q1 * (1 << 1)) + q0 + p1 + 2) >> 2; /* q0' */
|
||||
}
|
||||
pPixCr += iStrideY;
|
||||
pPixCb += iStrideY;
|
||||
@ -198,7 +198,7 @@ void DeblockChromaLt42_c (uint8_t* pPixCbCr, int32_t iStrideX, int32_t iStrideY,
|
||||
bDetaP1P0 = WELS_ABS (p1 - p0) < iBeta;
|
||||
bDetaQ1Q0 = WELS_ABS (q1 - q0) < iBeta;
|
||||
if (bDetaP0Q0 && bDetaP1P0 && bDetaQ1Q0) {
|
||||
iDeta = WELS_CLIP3 ((((q0 - p0) << 2) + (p1 - q1) + 4) >> 3, -iTc0, iTc0);
|
||||
iDeta = WELS_CLIP3 ((((q0 - p0) * (1 << 2)) + (p1 - q1) + 4) >> 3, -iTc0, iTc0);
|
||||
pPixCbCr[-iStrideX] = WelsClip1 (p0 + iDeta); /* p0' */
|
||||
pPixCbCr[0] = WelsClip1 (q0 - iDeta); /* q0' */
|
||||
}
|
||||
@ -221,8 +221,8 @@ void DeblockChromaEq42_c (uint8_t* pPixCbCr, int32_t iStrideX, int32_t iStrideY,
|
||||
bDetaP1P0 = WELS_ABS (p1 - p0) < iBeta;
|
||||
bDetaQ1Q0 = WELS_ABS (q1 - q0) < iBeta;
|
||||
if (bDetaP0Q0 && bDetaP1P0 && bDetaQ1Q0) {
|
||||
pPixCbCr[-iStrideX] = ((p1 << 1) + p0 + q1 + 2) >> 2; /* p0' */
|
||||
pPixCbCr[0] = ((q1 << 1) + q0 + p1 + 2) >> 2; /* q0' */
|
||||
pPixCbCr[-iStrideX] = ((p1 * (1 << 1)) + p0 + q1 + 2) >> 2; /* p0' */
|
||||
pPixCbCr[0] = ((q1 * (1 << 1)) + q0 + p1 + 2) >> 2; /* q0' */
|
||||
}
|
||||
|
||||
pPixCbCr += iStrideY;
|
||||
|
@ -50,7 +50,7 @@ float WelsCalcPsnr (const void* kpTarPic,
|
||||
|
||||
void WelsLog (SLogContext* logCtx, int32_t iLevel, const char* kpFmt, ...) {
|
||||
va_list vl;
|
||||
char pTraceTag[MAX_LOG_SIZE];
|
||||
char pTraceTag[MAX_LOG_SIZE] = {0};
|
||||
switch (iLevel) {
|
||||
case WELS_LOG_ERROR:
|
||||
WelsSnprintf (pTraceTag, MAX_LOG_SIZE, "[OpenH264] this = 0x%p, Error:", logCtx->pCodecInstance);
|
||||
|
@ -179,7 +179,7 @@ static inline uint32_t BsGetUe (PBitStringAux pBs, uint32_t* pCode) {
|
||||
DUMP_BITS (pBs->uiCurBits, pBs->pCurBuf, pBs->iLeftBits, iLeadingZeroBits, iAllowedBytes, iReadBytes);
|
||||
}
|
||||
|
||||
*pCode = ((1 << iLeadingZeroBits) - 1 + iValue);
|
||||
*pCode = ((1u << iLeadingZeroBits) - 1 + iValue);
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,9 @@ ERR_INFO_NO_IDR_PIC = ERR_INFO_LOGIC_BASE, // NO IDR picture availa
|
||||
ERR_INFO_EC_NO_NEIGHBOUR_MBS,
|
||||
ERR_INFO_EC_UNEXPECTED_MB_TYPE,
|
||||
ERR_INFO_EC_NO_ENOUGH_NEIGHBOUR_MBS,
|
||||
ERR_INFO_DUPLICATE_FRAME_NUM,
|
||||
//for LTR
|
||||
ERR_INFO_INVALID_MMCO_NUM,
|
||||
ERR_INFO_INVALID_MMCO_OPCODE_BASE,
|
||||
ERR_INFO_INVALID_MMCO_SHORT2UNUSED,
|
||||
EER_INFO_INVALID_MMCO_LONG2UNUSED,
|
||||
@ -194,6 +196,7 @@ ERR_INFO_INVALID_MMCO_REF_NUM_NOT_ENOUGH,
|
||||
ERR_INFO_INVALID_MMCO_LONG_TERM_IDX_EXCEED_MAX,
|
||||
//for CABAC
|
||||
ERR_CABAC_NO_BS_TO_READ,
|
||||
ERR_CABAC_UNEXPECTED_VALUE,
|
||||
//for scaling list
|
||||
ERR_SCALING_LIST_DELTA_SCALE,
|
||||
};
|
||||
|
@ -837,31 +837,39 @@ bool CheckSpsActive (PWelsDecoderContext pCtx, PSps pSps, bool bUseSubsetFlag) {
|
||||
}
|
||||
// Pre-active, will be used soon
|
||||
if (bUseSubsetFlag) {
|
||||
if (pSps->iMbWidth > 0 && pSps->iMbHeight > 0 && pCtx->bSubspsAvailFlags[pSps->iSpsId]
|
||||
&& pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
|
||||
int i = 0, iNum = (int32_t) pCtx->pAccessUnitList->uiAvailUnitsNum;
|
||||
while (i < iNum) {
|
||||
PNalUnit pNalUnit = pCtx->pAccessUnitList->pNalUnitsList[i];
|
||||
if (pNalUnit->sNalData.sVclNal.bSliceHeaderExtFlag) { //ext data
|
||||
PSps pNextUsedSps = pNalUnit->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps;
|
||||
if (pNextUsedSps->iSpsId == pSps->iSpsId)
|
||||
return true;
|
||||
if (pSps->iMbWidth > 0 && pSps->iMbHeight > 0 && pCtx->bSubspsAvailFlags[pSps->iSpsId]) {
|
||||
if (pCtx->iTotalNumMbRec > 0) {
|
||||
return true;
|
||||
}
|
||||
if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
|
||||
int i = 0, iNum = (int32_t) pCtx->pAccessUnitList->uiAvailUnitsNum;
|
||||
while (i < iNum) {
|
||||
PNalUnit pNalUnit = pCtx->pAccessUnitList->pNalUnitsList[i];
|
||||
if (pNalUnit->sNalData.sVclNal.bSliceHeaderExtFlag) { //ext data
|
||||
PSps pNextUsedSps = pNalUnit->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps;
|
||||
if (pNextUsedSps->iSpsId == pSps->iSpsId)
|
||||
return true;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (pSps->iMbWidth > 0 && pSps->iMbHeight > 0 && pCtx->bSpsAvailFlags[pSps->iSpsId]
|
||||
&& pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
|
||||
int i = 0, iNum = (int32_t) pCtx->pAccessUnitList->uiAvailUnitsNum;
|
||||
while (i < iNum) {
|
||||
PNalUnit pNalUnit = pCtx->pAccessUnitList->pNalUnitsList[i];
|
||||
if (!pNalUnit->sNalData.sVclNal.bSliceHeaderExtFlag) { //non-ext data
|
||||
PSps pNextUsedSps = pNalUnit->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps;
|
||||
if (pNextUsedSps->iSpsId == pSps->iSpsId)
|
||||
return true;
|
||||
if (pSps->iMbWidth > 0 && pSps->iMbHeight > 0 && pCtx->bSpsAvailFlags[pSps->iSpsId]) {
|
||||
if (pCtx->iTotalNumMbRec > 0) {
|
||||
return true;
|
||||
}
|
||||
if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
|
||||
int i = 0, iNum = (int32_t) pCtx->pAccessUnitList->uiAvailUnitsNum;
|
||||
while (i < iNum) {
|
||||
PNalUnit pNalUnit = pCtx->pAccessUnitList->pNalUnitsList[i];
|
||||
if (!pNalUnit->sNalData.sVclNal.bSliceHeaderExtFlag) { //non-ext data
|
||||
PSps pNextUsedSps = pNalUnit->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps;
|
||||
if (pNextUsedSps->iSpsId == pSps->iSpsId)
|
||||
return true;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1035,8 +1043,8 @@ int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicW
|
||||
pSps->bGapsInFrameNumValueAllowedFlag = !!uiCode;
|
||||
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //pic_width_in_mbs_minus1
|
||||
pSps->iMbWidth = PIC_WIDTH_IN_MBS_OFFSET + uiCode;
|
||||
if (pSps->iMbWidth > MAX_MB_SIZE) {
|
||||
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "pic_width_in_mbs(%d) exceeds the maximum allowed!", pSps->iMbWidth);
|
||||
if (pSps->iMbWidth > MAX_MB_SIZE || pSps->iMbWidth == 0) {
|
||||
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "pic_width_in_mbs(%d) invalid!", pSps->iMbWidth);
|
||||
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_MAX_MB_SIZE);
|
||||
}
|
||||
if (((uint64_t)pSps->iMbWidth * (uint64_t)pSps->iMbWidth) > (uint64_t) (8 * pSLevelLimits->uiMaxFS)) {
|
||||
@ -1045,8 +1053,8 @@ int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicW
|
||||
}
|
||||
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //pic_height_in_map_units_minus1
|
||||
pSps->iMbHeight = PIC_HEIGHT_IN_MAP_UNITS_OFFSET + uiCode;
|
||||
if (pSps->iMbHeight > MAX_MB_SIZE) {
|
||||
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "pic_height_in_mbs(%d) exceeds the maximum allowed!", pSps->iMbHeight);
|
||||
if (pSps->iMbHeight > MAX_MB_SIZE || pSps->iMbHeight == 0) {
|
||||
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "pic_height_in_mbs(%d) invalid!", pSps->iMbHeight);
|
||||
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_MAX_MB_SIZE);
|
||||
}
|
||||
if (((uint64_t)pSps->iMbHeight * (uint64_t)pSps->iMbHeight) > (uint64_t) (8 * pSLevelLimits->uiMaxFS)) {
|
||||
|
@ -273,7 +273,10 @@ int32_t DecodeExpBypassCabac (PWelsCabacDecEngine pDecEngine, int32_t iCount, ui
|
||||
iSymTmp += (1 << iCount);
|
||||
++iCount;
|
||||
}
|
||||
} while (uiCode != 0);
|
||||
} while (uiCode != 0 && iCount != 16);
|
||||
if (iCount == 16) {
|
||||
return ERR_CABAC_UNEXPECTED_VALUE;
|
||||
}
|
||||
|
||||
while (iCount--) {
|
||||
WELS_READ_VERIFY (DecodeBypassCabac (pDecEngine, uiCode));
|
||||
|
@ -1453,7 +1453,7 @@ int32_t WelsActualDecodeMbCavlcISlice (PWelsDecoderContext pCtx) {
|
||||
} else { //non-MB_TYPE_INTRA16x16
|
||||
if (pCurLayer->pTransformSize8x8Flag[iMbXy]) {
|
||||
for (iId8x8 = 0; iId8x8 < 4; iId8x8++) {
|
||||
iMbResProperty = (IS_INTRA (pCurLayer->pMbType[iMbXy])) ? LUMA_DC_AC_INTRA : LUMA_DC_AC_INTER;
|
||||
iMbResProperty = (IS_INTRA (pCurLayer->pMbType[iMbXy])) ? LUMA_DC_AC_INTRA_8 : LUMA_DC_AC_INTER_8;
|
||||
if (uiCbpL & (1 << iId8x8)) {
|
||||
int32_t iIndex = (iId8x8 << 2);
|
||||
for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
|
||||
@ -1815,7 +1815,7 @@ int32_t WelsActualDecodeMbCavlcPSlice (PWelsDecoderContext pCtx) {
|
||||
} else { //non-MB_TYPE_INTRA16x16
|
||||
if (pCurLayer->pTransformSize8x8Flag[iMbXy]) {
|
||||
for (iId8x8 = 0; iId8x8 < 4; iId8x8++) {
|
||||
iMbResProperty = (IS_INTRA (pCurLayer->pMbType[iMbXy])) ? LUMA_DC_AC_INTRA : LUMA_DC_AC_INTER;
|
||||
iMbResProperty = (IS_INTRA (pCurLayer->pMbType[iMbXy])) ? LUMA_DC_AC_INTRA_8 : LUMA_DC_AC_INTER_8;
|
||||
if (uiCbpL & (1 << iId8x8)) {
|
||||
int32_t iIndex = (iId8x8 << 2);
|
||||
for (iId4x4 = 0; iId4x4 < 4; iId4x4++) {
|
||||
|
@ -389,25 +389,25 @@ int32_t ParseDecRefPicMarking (PWelsDecoderContext pCtx, PBitStringAux pBs, PSli
|
||||
int32_t iIdx = 0;
|
||||
do {
|
||||
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //memory_management_control_operation
|
||||
const int32_t kiMmco = uiCode;
|
||||
const uint32_t kuiMmco = uiCode;
|
||||
|
||||
kpRefMarking->sMmcoRef[iIdx].uiMmcoType = kiMmco;
|
||||
if (kiMmco == MMCO_END)
|
||||
kpRefMarking->sMmcoRef[iIdx].uiMmcoType = kuiMmco;
|
||||
if (kuiMmco == MMCO_END)
|
||||
break;
|
||||
|
||||
if (kiMmco == MMCO_SHORT2UNUSED || kiMmco == MMCO_SHORT2LONG) {
|
||||
if (kuiMmco == MMCO_SHORT2UNUSED || kuiMmco == MMCO_SHORT2LONG) {
|
||||
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //difference_of_pic_nums_minus1
|
||||
kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum = 1 + uiCode;
|
||||
kpRefMarking->sMmcoRef[iIdx].iShortFrameNum = (pSh->iFrameNum - kpRefMarking->sMmcoRef[iIdx].iDiffOfPicNum) & ((
|
||||
1 << pSps->uiLog2MaxFrameNum) - 1);
|
||||
} else if (kiMmco == MMCO_LONG2UNUSED) {
|
||||
} else if (kuiMmco == MMCO_LONG2UNUSED) {
|
||||
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_pic_num
|
||||
kpRefMarking->sMmcoRef[iIdx].uiLongTermPicNum = uiCode;
|
||||
}
|
||||
if (kiMmco == MMCO_SHORT2LONG || kiMmco == MMCO_LONG) {
|
||||
if (kuiMmco == MMCO_SHORT2LONG || kuiMmco == MMCO_LONG) {
|
||||
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //long_term_frame_idx
|
||||
kpRefMarking->sMmcoRef[iIdx].iLongTermFrameIdx = uiCode;
|
||||
} else if (kiMmco == MMCO_SET_MAX_LONG) {
|
||||
} else if (kuiMmco == MMCO_SET_MAX_LONG) {
|
||||
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //max_long_term_frame_idx_plus1
|
||||
kpRefMarking->sMmcoRef[iIdx].iMaxLongTermFrameIdx = -1 + uiCode;
|
||||
}
|
||||
@ -690,6 +690,8 @@ int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, co
|
||||
|
||||
// first_mb_in_slice
|
||||
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //first_mb_in_slice
|
||||
WELS_CHECK_SE_UPPER_ERROR (uiCode, 36863u, "first_mb_in_slice", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER,
|
||||
ERR_INFO_INVALID_FIRST_MB_IN_SLICE));
|
||||
pSliceHead->iFirstMbInSlice = uiCode;
|
||||
|
||||
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //slice_type
|
||||
@ -721,13 +723,10 @@ int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, co
|
||||
pSliceHead->eSliceType = static_cast <EWelsSliceType> (uiSliceType);
|
||||
|
||||
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //pic_parameter_set_id
|
||||
WELS_CHECK_SE_UPPER_ERROR (uiCode, (MAX_PPS_COUNT - 1), "iPpsId out of range", GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER,
|
||||
ERR_INFO_PPS_ID_OVERFLOW));
|
||||
iPpsId = uiCode;
|
||||
|
||||
if (iPpsId >= MAX_PPS_COUNT) {
|
||||
WelsLog (pLogCtx, WELS_LOG_WARNING, "iPpsId out of range");
|
||||
return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_PPS_ID_OVERFLOW);
|
||||
}
|
||||
|
||||
//add check PPS available here
|
||||
if (pCtx->bPpsAvailFlags[iPpsId] == false) {
|
||||
pCtx->sDecoderStatistics.iPpsReportErrorNum++;
|
||||
@ -808,7 +807,7 @@ int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, co
|
||||
return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_NO_PARAM_SETS);
|
||||
}
|
||||
// check first_mb_in_slice
|
||||
WELS_CHECK_SE_UPPER_ERROR ((uint32_t) (pSliceHead->iFirstMbInSlice), pSps->uiTotalMbCount, "first_mb_in_slice",
|
||||
WELS_CHECK_SE_UPPER_ERROR ((uint32_t) (pSliceHead->iFirstMbInSlice), (pSps->uiTotalMbCount - 1), "first_mb_in_slice",
|
||||
GENERATE_ERROR_NO (ERR_LEVEL_SLICE_HEADER, ERR_INFO_INVALID_FIRST_MB_IN_SLICE));
|
||||
WELS_READ_VERIFY (BsGetBits (pBs, pSps->uiLog2MaxFrameNum, &uiCode)); //frame_num
|
||||
pSliceHead->iFrameNum = uiCode;
|
||||
@ -939,9 +938,8 @@ int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, co
|
||||
if (pPps->bEntropyCodingModeFlag) {
|
||||
if (pSliceHead->eSliceType != I_SLICE && pSliceHead->eSliceType != SI_SLICE) {
|
||||
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode));
|
||||
WELS_CHECK_SE_UPPER_ERROR (uiCode, SLICE_HEADER_CABAC_INIT_IDC_MAX, "cabac_init_idc", ERR_INFO_INVALID_CABAC_INIT_IDC);
|
||||
pSliceHead->iCabacInitIdc = uiCode;
|
||||
WELS_CHECK_SE_UPPER_ERROR (pSliceHead->iCabacInitIdc, SLICE_HEADER_CABAC_INIT_IDC_MAX, "cabac_init_idc",
|
||||
ERR_INFO_INVALID_CABAC_INIT_IDC);
|
||||
} else
|
||||
pSliceHead->iCabacInitIdc = 0;
|
||||
}
|
||||
@ -2360,6 +2358,8 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBuf
|
||||
if (uiNalRefIdc > 0) {
|
||||
iRet = WelsMarkAsRef (pCtx);
|
||||
if (iRet != ERR_NONE) {
|
||||
if (iRet == ERR_INFO_DUPLICATE_FRAME_NUM)
|
||||
pCtx->iErrorCode |= dsBitstreamError;
|
||||
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE) {
|
||||
pCtx->pDec = NULL;
|
||||
return iRet;
|
||||
|
@ -224,23 +224,23 @@ void DoMbECMvCopy (PWelsDecoderContext pCtx, PPicture pDec, PPicture pRef, int32
|
||||
iPicHeightBottomLimit = (pMCRefMem->iPicHeight - pCtx->sFrameCrop.iTopOffset * 2);
|
||||
}
|
||||
// further make sure no need to expand picture
|
||||
int32_t iMinLeftOffset = (iPicWidthLeftLimit + 2) << 2;
|
||||
int32_t iMaxRightOffset = ((iPicWidthRightLimit - 19) << 2);
|
||||
int32_t iMinTopOffset = (iPicHeightTopLimit + 2) << 2;
|
||||
int32_t iMaxBottomOffset = ((iPicHeightBottomLimit - 19) << 2);
|
||||
int32_t iMinLeftOffset = (iPicWidthLeftLimit + 2) * (1 << 2);
|
||||
int32_t iMaxRightOffset = ((iPicWidthRightLimit - 19) * (1 << 2));
|
||||
int32_t iMinTopOffset = (iPicHeightTopLimit + 2) * (1 << 2);
|
||||
int32_t iMaxBottomOffset = ((iPicHeightBottomLimit - 19) * (1 << 2));
|
||||
if (iFullMVx < iMinLeftOffset) {
|
||||
iFullMVx = (iFullMVx >> 2) << 2;
|
||||
iFullMVx = (iFullMVx >> 2) * (1 << 2);
|
||||
iFullMVx = WELS_MAX (iPicWidthLeftLimit, iFullMVx);
|
||||
} else if (iFullMVx > iMaxRightOffset) {
|
||||
iFullMVx = (iFullMVx >> 2) << 2;
|
||||
iFullMVx = WELS_MIN (((iPicWidthRightLimit - 17) << 2), iFullMVx);
|
||||
iFullMVx = (iFullMVx >> 2) * (1 << 2);
|
||||
iFullMVx = WELS_MIN (((iPicWidthRightLimit - 17) * (1 << 2)), iFullMVx);
|
||||
}
|
||||
if (iFullMVy < iMinTopOffset) {
|
||||
iFullMVy = (iFullMVy >> 2) << 2;
|
||||
iFullMVy = (iFullMVy >> 2) * (1 << 2);
|
||||
iFullMVy = WELS_MAX (iPicHeightTopLimit, iFullMVy);
|
||||
} else if (iFullMVy > iMaxBottomOffset) {
|
||||
iFullMVy = (iFullMVy >> 2) << 2;
|
||||
iFullMVy = WELS_MIN (((iPicHeightBottomLimit - 17) << 2), iFullMVy);
|
||||
iFullMVy = (iFullMVy >> 2) * (1 << 2);
|
||||
iFullMVy = WELS_MIN (((iPicHeightBottomLimit - 17) * (1 << 2)), iFullMVy);
|
||||
}
|
||||
iMVs[0] = iFullMVx - (iMbXInPix << 2);
|
||||
iMVs[1] = iFullMVy - (iMbYInPix << 2);
|
||||
@ -431,6 +431,7 @@ void DoErrorConSliceMVCopy (PWelsDecoderContext pCtx) {
|
||||
//Mark erroneous frame as Ref Pic into DPB
|
||||
int32_t MarkECFrameAsRef (PWelsDecoderContext pCtx) {
|
||||
int32_t iRet = WelsMarkAsRef (pCtx);
|
||||
// Under EC mode, the ERR_INFO_DUPLICATE_FRAME_NUM does not need to be process
|
||||
if (iRet != ERR_NONE) {
|
||||
return iRet;
|
||||
}
|
||||
|
@ -294,6 +294,7 @@ int32_t WelsMarkAsRef (PWelsDecoderContext pCtx) {
|
||||
if (iRet != ERR_NONE) {
|
||||
if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
|
||||
iRet = RemainOneBufferInDpbForEC (pCtx);
|
||||
WELS_VERIFY_RETURN_IF (iRet, iRet);
|
||||
} else {
|
||||
return iRet;
|
||||
}
|
||||
@ -309,6 +310,7 @@ int32_t WelsMarkAsRef (PWelsDecoderContext pCtx) {
|
||||
if (iRet != ERR_NONE) {
|
||||
if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
|
||||
iRet = RemainOneBufferInDpbForEC (pCtx);
|
||||
WELS_VERIFY_RETURN_IF (iRet, iRet);
|
||||
} else {
|
||||
return iRet;
|
||||
}
|
||||
@ -320,11 +322,12 @@ int32_t WelsMarkAsRef (PWelsDecoderContext pCtx) {
|
||||
if (pRefPic->uiLongRefCount[LIST_0] + pRefPic->uiShortRefCount[LIST_0] >= WELS_MAX (1, pCtx->pSps->iNumRefFrames)) {
|
||||
if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
|
||||
iRet = RemainOneBufferInDpbForEC (pCtx);
|
||||
WELS_VERIFY_RETURN_IF (iRet, iRet);
|
||||
} else {
|
||||
return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW;
|
||||
}
|
||||
}
|
||||
AddShortTermToList (pRefPic, pCtx->pDec);
|
||||
iRet = AddShortTermToList (pRefPic, pCtx->pDec);
|
||||
}
|
||||
|
||||
return iRet;
|
||||
@ -334,7 +337,7 @@ static int32_t MMCO (PWelsDecoderContext pCtx, PRefPicMarking pRefPicMarking) {
|
||||
PSps pSps = pCtx->pCurDqLayer->sLayerInfo.pSps;
|
||||
int32_t i = 0;
|
||||
int32_t iRet = ERR_NONE;
|
||||
for (i = 0; pRefPicMarking->sMmcoRef[i].uiMmcoType != MMCO_END; i++) {
|
||||
for (i = 0; i < MAX_MMCO_COUNT && pRefPicMarking->sMmcoRef[i].uiMmcoType != MMCO_END; i++) {
|
||||
uint32_t uiMmcoType = pRefPicMarking->sMmcoRef[i].uiMmcoType;
|
||||
int32_t iShortFrameNum = (pCtx->iFrameNum - pRefPicMarking->sMmcoRef[i].iDiffOfPicNum) & ((
|
||||
1 << pSps->uiLog2MaxFrameNum) - 1);
|
||||
@ -349,6 +352,9 @@ static int32_t MMCO (PWelsDecoderContext pCtx, PRefPicMarking pRefPicMarking) {
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
if (i == MAX_MMCO_COUNT) { //although Rec does not handle this condition, we here prohibit too many MMCO op
|
||||
return ERR_INFO_INVALID_MMCO_NUM;
|
||||
}
|
||||
|
||||
return ERR_NONE;
|
||||
}
|
||||
@ -515,6 +521,15 @@ static int32_t AddShortTermToList (PRefPic pRefPic, PPicture pPic) {
|
||||
pPic->bIsLongRef = false;
|
||||
pPic->iLongTermFrameIdx = -1;
|
||||
if (pRefPic->uiShortRefCount[LIST_0] > 0) {
|
||||
// Check the duplicate frame_num in short ref list
|
||||
for (int32_t iPos = 0; iPos < pRefPic->uiShortRefCount[LIST_0]; iPos++) {
|
||||
if (pPic->iFrameNum == pRefPic->pShortRefList[LIST_0][iPos]->iFrameNum) {
|
||||
// Replace the previous ref pic with the new one with the same frame_num
|
||||
pRefPic->pShortRefList[LIST_0][iPos] = pPic;
|
||||
return ERR_INFO_DUPLICATE_FRAME_NUM;
|
||||
}
|
||||
}
|
||||
|
||||
memmove (&pRefPic->pShortRefList[LIST_0][1], &pRefPic->pShortRefList[LIST_0][0],
|
||||
pRefPic->uiShortRefCount[LIST_0]*sizeof (PPicture));//confirmed_safe_unsafe_usage
|
||||
}
|
||||
|
@ -889,7 +889,7 @@ int32_t ParseResidualBlockCabac8x8 (PWelsNeighAvail pNeighAvail, uint8_t* pNonZe
|
||||
do {
|
||||
if (pSignificantMap[j] != 0) {
|
||||
i = pScanTable[ j ];
|
||||
sTCoeff[i] = uiQp >= 36 ? ((pSignificantMap[j] * pDeQuantMul[i]) << (uiQp / 6 - 6)) : ((
|
||||
sTCoeff[i] = uiQp >= 36 ? ((pSignificantMap[j] * pDeQuantMul[i]) * (1 << (uiQp / 6 - 6))) : ((
|
||||
pSignificantMap[j] * pDeQuantMul[i] + (1 << (5 - uiQp / 6))) >> (6 - uiQp / 6));
|
||||
}
|
||||
++j;
|
||||
|
@ -981,7 +981,7 @@ int32_t WelsResidualBlockCavlc8x8 (SVlcTable* pVlcTable, uint8_t* pNonZeroCountC
|
||||
iCoeffNum += iRun[i] + 1; //FIXME add 1 earlier ?
|
||||
j = (iCoeffNum << 2) + iIdx4x4;
|
||||
j = kpZigzagTable[ j ];
|
||||
pTCoeff[j] = uiQp >= 36 ? ((iLevel[i] * kpDequantCoeff[j]) << (uiQp / 6 - 6))
|
||||
pTCoeff[j] = uiQp >= 36 ? ((iLevel[i] * kpDequantCoeff[j]) * (1 << (uiQp / 6 - 6)))
|
||||
: ((iLevel[i] * kpDequantCoeff[j] + (1 << (5 - uiQp / 6))) >> (6 - uiQp / 6));
|
||||
}
|
||||
|
||||
|
@ -243,8 +243,8 @@ void BaseMC (sMCRefMember* pMCRefMem, int32_t iXOffset, int32_t iYOffset, SMcFun
|
||||
int32_t iBlkWidth, int32_t iBlkHeight, int16_t iMVs[2]) {
|
||||
int32_t iFullMVx = (iXOffset << 2) + iMVs[0]; //quarter pixel
|
||||
int32_t iFullMVy = (iYOffset << 2) + iMVs[1];
|
||||
iFullMVx = WELS_CLIP3 (iFullMVx, ((-PADDING_LENGTH + 2) << 2), ((pMCRefMem->iPicWidth + PADDING_LENGTH - 19) << 2));
|
||||
iFullMVy = WELS_CLIP3 (iFullMVy, ((-PADDING_LENGTH + 2) << 2), ((pMCRefMem->iPicHeight + PADDING_LENGTH - 19) << 2));
|
||||
iFullMVx = WELS_CLIP3 (iFullMVx, ((-PADDING_LENGTH + 2) * (1 << 2)), ((pMCRefMem->iPicWidth + PADDING_LENGTH - 19) * (1 << 2)));
|
||||
iFullMVy = WELS_CLIP3 (iFullMVy, ((-PADDING_LENGTH + 2) * (1 << 2)), ((pMCRefMem->iPicHeight + PADDING_LENGTH - 19) * (1 << 2)));
|
||||
|
||||
int32_t iSrcPixOffsetLuma = (iFullMVx >> 2) + (iFullMVy >> 2) * pMCRefMem->iSrcLineLuma;
|
||||
int32_t iSrcPixOffsetChroma = (iFullMVx >> 3) + (iFullMVy >> 3) * pMCRefMem->iSrcLineChroma;
|
||||
|
@ -215,8 +215,8 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
|
||||
|
||||
SUsedPicRect.iLeft = 0;
|
||||
SUsedPicRect.iTop = 0;
|
||||
SUsedPicRect.iWidth = ((iPicWidth >> 1) << 1);
|
||||
SUsedPicRect.iHeight = ((iPicHeight >> 1) << 1);
|
||||
SUsedPicRect.iWidth = ((iPicWidth >> 1) * (1 << 1));
|
||||
SUsedPicRect.iHeight = ((iPicHeight >> 1) * (1 << 1));
|
||||
|
||||
iRCMode = pCodingParam.iRCMode; // rc mode
|
||||
|
||||
|
@ -336,10 +336,10 @@ inline void SetMvWithinIntegerMvRange (const int32_t kiMbWidth, const int32_t ki
|
||||
const int32_t kiMbY,
|
||||
const int32_t kiMaxMvRange,
|
||||
SMVUnitXY* pMvMin, SMVUnitXY* pMvMax) {
|
||||
pMvMin->iMvX = WELS_MAX (-1 * ((kiMbX + 1) << 4) + INTPEL_NEEDED_MARGIN, -1 * kiMaxMvRange);
|
||||
pMvMin->iMvY = WELS_MAX (-1 * ((kiMbY + 1) << 4) + INTPEL_NEEDED_MARGIN, -1 * kiMaxMvRange);
|
||||
pMvMax->iMvX = WELS_MIN (((kiMbWidth - kiMbX) << 4) - INTPEL_NEEDED_MARGIN, kiMaxMvRange);
|
||||
pMvMax->iMvY = WELS_MIN (((kiMbHeight - kiMbY) << 4) - INTPEL_NEEDED_MARGIN, kiMaxMvRange);
|
||||
pMvMin->iMvX = WELS_MAX (-1 * ((kiMbX + 1) * (1 << 4)) + INTPEL_NEEDED_MARGIN, -1 * kiMaxMvRange);
|
||||
pMvMin->iMvY = WELS_MAX (-1 * ((kiMbY + 1) * (1 << 4)) + INTPEL_NEEDED_MARGIN, -1 * kiMaxMvRange);
|
||||
pMvMax->iMvX = WELS_MIN (((kiMbWidth - kiMbX) * (1 << 4)) - INTPEL_NEEDED_MARGIN, kiMaxMvRange);
|
||||
pMvMax->iMvY = WELS_MIN (((kiMbHeight - kiMbY) * (1 << 4)) - INTPEL_NEEDED_MARGIN, kiMaxMvRange);
|
||||
}
|
||||
|
||||
inline bool CheckMvInRange (const SMVUnitXY ksCurrentMv, const SMVUnitXY ksMinMv, const SMVUnitXY ksMaxMv) {
|
||||
|
@ -333,8 +333,8 @@ void WelsDctT4_c (int16_t* pDct, uint8_t* pPixel1, int32_t iStride1, uint8_t* pP
|
||||
|
||||
pDct[i ] = s[0] + s[1];
|
||||
pDct[kiI2] = s[0] - s[1];
|
||||
pDct[kiI1] = (s[3] << 1) + s[2];
|
||||
pDct[kiI3] = s[3] - (s[2] << 1);
|
||||
pDct[kiI1] = (s[3] * (1 << 1)) + s[2];
|
||||
pDct[kiI3] = s[3] - (s[2] * (1 << 1));
|
||||
}
|
||||
|
||||
/* vertical transform */
|
||||
@ -350,8 +350,8 @@ void WelsDctT4_c (int16_t* pDct, uint8_t* pPixel1, int32_t iStride1, uint8_t* pP
|
||||
|
||||
pDct[i ] = s[0] + s[1];
|
||||
pDct[kiI8 ] = s[0] - s[1];
|
||||
pDct[kiI4 ] = (s[3] << 1) + s[2];
|
||||
pDct[kiI12] = s[3] - (s[2] << 1);
|
||||
pDct[kiI4 ] = (s[3] * (1 << 1)) + s[2];
|
||||
pDct[kiI12] = s[3] - (s[2] * (1 << 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ int32_t WriteBlockResidualCavlc (SWelsFuncPtrList* pFuncList, int16_t* pCoffLev
|
||||
for (i = iTrailingOnes; i < iTotalCoeffs; i++) {
|
||||
int32_t iVal = iLevel[i];
|
||||
|
||||
iLevelCode = (iVal - 1) << 1;
|
||||
iLevelCode = (iVal - 1) * (1 << 1);
|
||||
uiSign = (iLevelCode >> 31);
|
||||
iLevelCode = (iLevelCode ^ uiSign) + (uiSign << 1);
|
||||
iLevelCode -= ((i == iTrailingOnes) && (iTrailingOnes < 3)) << 1;
|
||||
|
@ -133,8 +133,8 @@ void SetMvBaseEnhancelayer (SWelsMD* pMd, SMB* pCurMb, const SMB* kpRefMb) {
|
||||
SMVUnitXY sMv;
|
||||
int32_t iRefMbPartIdx = ((pCurMb->iMbY & 0x01) << 1) + (pCurMb->iMbX & 0x01); //may be need modified
|
||||
int32_t iScan4RefPartIdx = g_kuiMbCountScan4Idx[ (iRefMbPartIdx << 2)];
|
||||
sMv.iMvX = kpRefMb->sMv[iScan4RefPartIdx].iMvX << 1;
|
||||
sMv.iMvY = kpRefMb->sMv[iScan4RefPartIdx].iMvY << 1;
|
||||
sMv.iMvX = kpRefMb->sMv[iScan4RefPartIdx].iMvX * (1 << 1);
|
||||
sMv.iMvY = kpRefMb->sMv[iScan4RefPartIdx].iMvY * (1 << 1);
|
||||
|
||||
pMd->sMe.sMe16x16.sMvBase = sMv;
|
||||
|
||||
|
@ -65,8 +65,8 @@ static inline void UpdateMeResults (const SMVUnitXY ksBestMv, const uint32_t kiB
|
||||
}
|
||||
static inline void MeEndIntepelSearch (SWelsME* pMe) {
|
||||
/* -> qpel mv */
|
||||
pMe->sMv.iMvX <<= 2;
|
||||
pMe->sMv.iMvY <<= 2;
|
||||
pMe->sMv.iMvX *= (1 << 2);
|
||||
pMe->sMv.iMvY *= (1 << 2);
|
||||
pMe->uiSatdCost = pMe->uiSadCost;
|
||||
}
|
||||
|
||||
@ -194,7 +194,7 @@ void WelsMotionEstimateSearchScrolled (SWelsFuncPtrList* pFuncList, SDqLayer* pC
|
||||
pMe->pRefMb = pMe->pColoRefMb + pMe->sMv.iMvY * kiStrideRef + pMe->sMv.iMvX;
|
||||
pMe->uiSadCost =
|
||||
pFuncList->sSampleDealingFuncs.pfSampleSad[pMe->uiBlockSize] (pMe->pEncMb, kiStrideEnc, pMe->pRefMb, kiStrideRef)
|
||||
+ COST_MVD (pMe->pMvdCost, (pMe->sMv.iMvX << 2) - pMe->sMvp.iMvX, (pMe->sMv.iMvY << 2) - pMe->sMvp.iMvY);
|
||||
+ COST_MVD (pMe->pMvdCost, (pMe->sMv.iMvX * (1 << 2)) - pMe->sMvp.iMvX, (pMe->sMv.iMvY * (1 << 2)) - pMe->sMvp.iMvY);
|
||||
MeEndIntepelSearch (pMe);
|
||||
pFuncList->pfCalculateSatd (pFuncList->sSampleDealingFuncs.pfSampleSatd[pMe->uiBlockSize], pMe, kiStrideEnc,
|
||||
kiStrideRef);
|
||||
@ -235,7 +235,7 @@ bool WelsMotionEstimateInitialPoint (SWelsFuncPtrList* pFuncList, SWelsME* pMe,
|
||||
pRefMb = &pMe->pRefMb[sMv.iMvY * iStrideRef + sMv.iMvX];
|
||||
|
||||
iBestSadCost = pSad (kpEncMb, iStrideEnc, pRefMb, iStrideRef);
|
||||
iBestSadCost += COST_MVD (kpMvdCost, ((sMv.iMvX) << 2) - ksMvp.iMvX, ((sMv.iMvY) << 2) - ksMvp.iMvY);
|
||||
iBestSadCost += COST_MVD (kpMvdCost, ((sMv.iMvX) * (1 << 2)) - ksMvp.iMvX, ((sMv.iMvY) * (1 << 2)) - ksMvp.iMvY);
|
||||
|
||||
for (i = 0; i < kuiMvcNum; i++) {
|
||||
//clipping here is essential since some pOut-of-range MVC may happen here (i.e., refer to baseMV)
|
||||
@ -246,7 +246,7 @@ bool WelsMotionEstimateInitialPoint (SWelsFuncPtrList* pFuncList, SWelsME* pMe,
|
||||
pFref2 = &pMe->pRefMb[iMvc1 * iStrideRef + iMvc0];
|
||||
|
||||
iSadCost = pSad (kpEncMb, iStrideEnc, pFref2, iStrideRef) +
|
||||
COST_MVD (kpMvdCost, (iMvc0 << 2) - ksMvp.iMvX, (iMvc1 << 2) - ksMvp.iMvY);
|
||||
COST_MVD (kpMvdCost, (iMvc0 * (1 << 2)) - ksMvp.iMvX, (iMvc1 * (1 << 2)) - ksMvp.iMvY);
|
||||
|
||||
if (iSadCost < iBestSadCost) {
|
||||
sMv.iMvX = iMvc0;
|
||||
@ -333,8 +333,8 @@ void WelsDiamondSearch (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlic
|
||||
const SMVUnitXY ksMvStartMin = pSlice->sMvStartMin;
|
||||
const SMVUnitXY ksMvStartMax = pSlice->sMvStartMax;
|
||||
|
||||
int32_t iMvDx = ((pMe->sMv.iMvX) << 2) - pMe->sMvp.iMvX;
|
||||
int32_t iMvDy = ((pMe->sMv.iMvY) << 2) - pMe->sMvp.iMvY;
|
||||
int32_t iMvDx = ((pMe->sMv.iMvX) * (1 << 2)) - pMe->sMvp.iMvX;
|
||||
int32_t iMvDy = ((pMe->sMv.iMvY) * (1 << 2)) - pMe->sMvp.iMvY;
|
||||
|
||||
uint8_t* pRefMb = pFref;
|
||||
int32_t iBestCost = (pMe->uiSadCost);
|
||||
@ -355,8 +355,8 @@ void WelsDiamondSearch (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlic
|
||||
if (kbIsBestCostWorse)
|
||||
break;
|
||||
|
||||
iMvDx -= iX << 2 ;
|
||||
iMvDy -= iY << 2 ;
|
||||
iMvDx -= (iX * (1 << 2)) ;
|
||||
iMvDy -= (iY * (1 << 2)) ;
|
||||
|
||||
pRefMb -= (iX + iY * kiStrideRef);
|
||||
|
||||
@ -384,7 +384,7 @@ bool CheckDirectionalMv (PSampleSadSatdCostFunc pSad, SWelsME* pMe,
|
||||
&& CheckMvInRange (pMe->sDirectionalMv, ksMinMv, ksMaxMv)) {
|
||||
uint8_t* pRef = &pMe->pColoRefMb[kiMvY * kiRefStride + kiMvX];
|
||||
uint32_t uiCurrentSadCost = pSad (pMe->pEncMb, kiEncStride, pRef, kiRefStride) +
|
||||
COST_MVD (pMe->pMvdCost, (kiMvX << 2) - pMe->sMvp.iMvX, (kiMvY << 2) - pMe->sMvp.iMvY);
|
||||
COST_MVD (pMe->pMvdCost, (kiMvX * (1 << 2)) - pMe->sMvp.iMvX, (kiMvY * (1 << 2)) - pMe->sMvp.iMvY);
|
||||
if (uiCurrentSadCost < pMe->uiSadCost) {
|
||||
iBestSadCost = uiCurrentSadCost;
|
||||
return true;
|
||||
@ -405,7 +405,7 @@ bool CheckDirectionalMvFalse (PSampleSadSatdCostFunc pSad, SWelsME* vpMe,
|
||||
#if defined (X86_ASM)
|
||||
void CalcMvdCostx8_c (uint16_t* pMvdCost, const int32_t kiStartMv, uint16_t* pMvdTable, const uint16_t kiFixedCost) {
|
||||
uint16_t* pBaseCost = pMvdCost;
|
||||
const int32_t kiOffset = (kiStartMv << 2);
|
||||
const int32_t kiOffset = (kiStartMv * (1 << 2));
|
||||
uint16_t* pMvd = pMvdTable + kiOffset;
|
||||
for (int32_t i = 0; i < 8; ++ i) {
|
||||
pBaseCost[i] = ((*pMvd) + kiFixedCost);
|
||||
@ -426,7 +426,7 @@ void VerticalFullSearchUsingSSE41 (SWelsFuncPtrList* pFuncList, SWelsME* pMe,
|
||||
int32_t iMinPos = kiCurMeBlockPixY + kiMinMv;
|
||||
int32_t iMaxPos = kiCurMeBlockPixY + kiMaxMv;
|
||||
int32_t iFixedMvd = * (pMvdTable - pMe->sMvp.iMvX);
|
||||
uint16_t* pMvdCost = & (pMvdTable[ (kiMinMv << 2) - pMe->sMvp.iMvY]);
|
||||
uint16_t* pMvdCost = & (pMvdTable[ (kiMinMv * (1 << 2)) - pMe->sMvp.iMvY]);
|
||||
int16_t iStartMv = 0;
|
||||
|
||||
|
||||
@ -476,7 +476,7 @@ void VerticalFullSearchUsingSSE41 (SWelsFuncPtrList* pFuncList, SWelsME* pMe,
|
||||
kpEncMb = pMe->pEncMb;
|
||||
pRef = &pMe->pColoRefMb[ (iTargetPos - kiCurMeBlockPix) * kiRefStride];
|
||||
while (iTargetPos < iMaxPos) {
|
||||
const uint16_t uiMvdCost = pMvdCost[iStartMv << 2];
|
||||
const uint16_t uiMvdCost = pMvdCost[iStartMv * (1 << 2)];
|
||||
uint32_t uiSadCost = pSad (kpEncMb, kiEncStride, pRef, kiRefStride) + (iFixedMvd + uiMvdCost);
|
||||
if (uiSadCost < uiBestCost) {
|
||||
uiBestCost = uiSadCost;
|
||||
@ -506,7 +506,7 @@ void HorizontalFullSearchUsingSSE41 (SWelsFuncPtrList* pFuncList, SWelsME* pMe,
|
||||
int32_t iMinPos = iCurMeBlockPixX + kiMinMv;
|
||||
int32_t iMaxPos = iCurMeBlockPixX + kiMaxMv;
|
||||
int32_t iFixedMvd = * (pMvdTable - pMe->sMvp.iMvY);
|
||||
uint16_t* pMvdCost = & (pMvdTable[ (kiMinMv << 2) - pMe->sMvp.iMvX]);
|
||||
uint16_t* pMvdCost = & (pMvdTable[ (kiMinMv * (1 << 2)) - pMe->sMvp.iMvX]);
|
||||
int16_t iStartMv = 0;
|
||||
uint8_t* pRef = &pMe->pColoRefMb[kiMinMv];
|
||||
const int32_t kIsBlock16x16 = pMe->uiBlockSize == BLOCK_16x16;
|
||||
@ -536,7 +536,7 @@ void HorizontalFullSearchUsingSSE41 (SWelsFuncPtrList* pFuncList, SWelsME* pMe,
|
||||
}
|
||||
if (kiRemainingLoop8 > 0) {
|
||||
while (iTargetPos < iMaxPos) {
|
||||
const uint16_t uiMvdCost = pMvdCost[iStartMv << 2];
|
||||
const uint16_t uiMvdCost = pMvdCost[iStartMv * (1 << 2)];
|
||||
uint32_t uiSadCost = pSad (kpEncMb, kiEncStride, pRef, kiRefStride) + (iFixedMvd + uiMvdCost);
|
||||
if (uiSadCost < uiBestCost) {
|
||||
uiBestCost = uiSadCost;
|
||||
@ -575,14 +575,14 @@ void LineFullSearch_c (SWelsFuncPtrList* pFuncList, SWelsME* pMe,
|
||||
iFixedMvd = * (pMvdTable - pMe->sMvp.iMvX);
|
||||
iCurMeBlockPix = pMe->iCurMeBlockPixY;
|
||||
iStride = kiRefStride;
|
||||
pMvdCost = & (pMvdTable[ (iMinMv << 2) - pMe->sMvp.iMvY]);
|
||||
pMvdCost = & (pMvdTable[ (iMinMv * (1 << 2)) - pMe->sMvp.iMvY]);
|
||||
} else {
|
||||
iMinPos = kiCurMeBlockPixX + iMinMv;
|
||||
iMaxPos = kiCurMeBlockPixX + iMaxMv;
|
||||
iFixedMvd = * (pMvdTable - pMe->sMvp.iMvY);
|
||||
iCurMeBlockPix = pMe->iCurMeBlockPixX;
|
||||
iStride = 1;
|
||||
pMvdCost = & (pMvdTable[ (iMinMv << 2) - pMe->sMvp.iMvX]);
|
||||
pMvdCost = & (pMvdTable[ (iMinMv * (1 << 2)) - pMe->sMvp.iMvX]);
|
||||
}
|
||||
uint8_t* pRef = &pMe->pColoRefMb[ iMinMv * iStride];
|
||||
uint32_t uiBestCost = 0xFFFFFFFF;
|
||||
@ -906,10 +906,10 @@ bool SetFeatureSearchIn (SWelsFuncPtrList* pFunc, const SWelsME& sMe,
|
||||
pFeatureSearchIn->pMvdCostX = sMe.pMvdCost - pFeatureSearchIn->iCurPixXQpel - sMe.sMvp.iMvX;
|
||||
pFeatureSearchIn->pMvdCostY = sMe.pMvdCost - pFeatureSearchIn->iCurPixYQpel - sMe.sMvp.iMvY;
|
||||
|
||||
pFeatureSearchIn->iMinQpelX = pFeatureSearchIn->iCurPixXQpel + ((pSlice->sMvStartMin.iMvX) << 2);
|
||||
pFeatureSearchIn->iMinQpelY = pFeatureSearchIn->iCurPixYQpel + ((pSlice->sMvStartMin.iMvY) << 2);
|
||||
pFeatureSearchIn->iMaxQpelX = pFeatureSearchIn->iCurPixXQpel + ((pSlice->sMvStartMax.iMvX) << 2);
|
||||
pFeatureSearchIn->iMaxQpelY = pFeatureSearchIn->iCurPixYQpel + ((pSlice->sMvStartMax.iMvY) << 2);
|
||||
pFeatureSearchIn->iMinQpelX = pFeatureSearchIn->iCurPixXQpel + ((pSlice->sMvStartMin.iMvX) * (1 << 2));
|
||||
pFeatureSearchIn->iMinQpelY = pFeatureSearchIn->iCurPixYQpel + ((pSlice->sMvStartMin.iMvY) * (1 << 2));
|
||||
pFeatureSearchIn->iMaxQpelX = pFeatureSearchIn->iCurPixXQpel + ((pSlice->sMvStartMax.iMvX) * (1 << 2));
|
||||
pFeatureSearchIn->iMaxQpelY = pFeatureSearchIn->iCurPixYQpel + ((pSlice->sMvStartMax.iMvY) * (1 << 2));
|
||||
|
||||
if (NULL == pFeatureSearchIn->pSad || NULL == pFeatureSearchIn->pTimesOfFeature
|
||||
|| NULL == pFeatureSearchIn->pQpelLocationOfFeature) {
|
||||
|
@ -408,7 +408,7 @@ int CWelsH264SVCEncoder ::EncodeFrameInternal (const SSourcePicture* pSrcPic, S
|
||||
} else if ((kiEncoderReturn != ENC_RETURN_SUCCESS) && (kiEncoderReturn == ENC_RETURN_CORRECTED)) {
|
||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "unexpected return(%d) from EncodeFrameInternal()!",
|
||||
kiEncoderReturn);
|
||||
return cmUnkonwReason;
|
||||
return cmUnknownReason;
|
||||
}
|
||||
|
||||
UpdateStatistics (pSrcPic->uiTimeStamp, pBsInfo->eFrameType, pBsInfo->iFrameSizeInBytes, kiCurrentFrameMs);
|
||||
|
@ -1,4 +1,4 @@
|
||||
Name: gmpopenh264
|
||||
Description: GMP Plugin for OpenH264.
|
||||
Version: 1.4
|
||||
Version: 1.5.2
|
||||
APIs: encode-video[h264], decode-video[h264]
|
||||
|
@ -187,7 +187,8 @@ class OpenH264VideoEncoder : public GMPVideoEncoder, public RefCounted {
|
||||
encoder_ (nullptr),
|
||||
max_payload_size_ (0),
|
||||
callback_ (nullptr),
|
||||
stats_ ("Encoder") {
|
||||
stats_ ("Encoder"),
|
||||
shutting_down(false) {
|
||||
AddRef();
|
||||
}
|
||||
|
||||
@ -361,12 +362,40 @@ class OpenH264VideoEncoder : public GMPVideoEncoder, public RefCounted {
|
||||
}
|
||||
|
||||
virtual void EncodingComplete() {
|
||||
shutting_down = true;
|
||||
|
||||
// Release the reference to the external objects, because it is no longer safe to call them
|
||||
host_ = nullptr;
|
||||
callback_ = nullptr;
|
||||
TearDownEncoder();
|
||||
|
||||
Release();
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~OpenH264VideoEncoder() {
|
||||
worker_thread_->Join();
|
||||
// Tear down the internal encoder in case of EncodingComplete() not being called
|
||||
TearDownEncoder();
|
||||
}
|
||||
|
||||
void TearDownEncoder() {
|
||||
// Stop the worker thread first
|
||||
if (worker_thread_) {
|
||||
worker_thread_->Join();
|
||||
worker_thread_ = nullptr;
|
||||
}
|
||||
|
||||
// Destroy OpenH264 encoder
|
||||
if (encoder_) {
|
||||
WelsDestroySVCEncoder(encoder_);
|
||||
encoder_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void TrySyncRunOnMainThread(GMPTask* aTask) {
|
||||
if (!shutting_down && g_platform_api) {
|
||||
g_platform_api->syncrunonmainthread (aTask);
|
||||
}
|
||||
}
|
||||
|
||||
void Error (GMPErr error) {
|
||||
@ -446,30 +475,36 @@ class OpenH264VideoEncoder : public GMPVideoEncoder, public RefCounted {
|
||||
|
||||
if (!has_frame) {
|
||||
// This frame must be destroyed on the main thread.
|
||||
g_platform_api->syncrunonmainthread (WrapTask (
|
||||
this,
|
||||
&OpenH264VideoEncoder::DestroyInputFrame_m,
|
||||
inputImage));
|
||||
TrySyncRunOnMainThread (WrapTask (
|
||||
this,
|
||||
&OpenH264VideoEncoder::DestroyInputFrame_m,
|
||||
inputImage));
|
||||
return;
|
||||
}
|
||||
|
||||
// Synchronously send this back to the main thread for delivery.
|
||||
g_platform_api->syncrunonmainthread (WrapTask (
|
||||
this,
|
||||
&OpenH264VideoEncoder::Encode_m,
|
||||
inputImage,
|
||||
&encoded,
|
||||
encoded_type));
|
||||
TrySyncRunOnMainThread (WrapTask (
|
||||
this,
|
||||
&OpenH264VideoEncoder::Encode_m,
|
||||
inputImage,
|
||||
&encoded,
|
||||
encoded_type));
|
||||
}
|
||||
|
||||
void Encode_m (GMPVideoi420Frame* frame, SFrameBSInfo* encoded,
|
||||
GMPVideoFrameType frame_type) {
|
||||
// Attach a self-destructor so that this dies on return.
|
||||
SelfDestruct<GMPVideoi420Frame> ifd (frame);
|
||||
|
||||
if (!host_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Now return the encoded data back to the parent.
|
||||
GMPVideoFrame* ftmp;
|
||||
GMPErr err = host_->CreateFrame (kGMPEncodedVideoFrame, &ftmp);
|
||||
if (err != GMPNoErr) {
|
||||
GMPLOG (GL_ERROR, "Error creating encoded frame");
|
||||
frame->Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -496,7 +531,6 @@ class OpenH264VideoEncoder : public GMPVideoEncoder, public RefCounted {
|
||||
if (err != GMPNoErr) {
|
||||
GMPLOG (GL_ERROR, "Error allocating frame data");
|
||||
f->Destroy();
|
||||
frame->Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -522,9 +556,6 @@ class OpenH264VideoEncoder : public GMPVideoEncoder, public RefCounted {
|
||||
<< " timestamp="
|
||||
<< f->TimeStamp());
|
||||
|
||||
// Destroy the frame.
|
||||
frame->Destroy();
|
||||
|
||||
// Return the encoded frame.
|
||||
GMPCodecSpecificInfo info;
|
||||
memset (&info, 0, sizeof (info)); // shouldn't be needed, we init everything
|
||||
@ -532,7 +563,9 @@ class OpenH264VideoEncoder : public GMPVideoEncoder, public RefCounted {
|
||||
info.mBufferType = GMP_BufferLength32;
|
||||
info.mCodecSpecific.mH264.mSimulcastIdx = 0;
|
||||
|
||||
callback_->Encoded (f, reinterpret_cast<uint8_t*> (&info), sizeof (info));
|
||||
if (callback_) {
|
||||
callback_->Encoded (f, reinterpret_cast<uint8_t*> (&info), sizeof (info));
|
||||
}
|
||||
|
||||
stats_.FrameOut();
|
||||
}
|
||||
@ -550,6 +583,7 @@ class OpenH264VideoEncoder : public GMPVideoEncoder, public RefCounted {
|
||||
uint32_t max_payload_size_;
|
||||
GMPVideoEncoderCallback* callback_;
|
||||
FrameStats stats_;
|
||||
bool shutting_down;
|
||||
};
|
||||
|
||||
uint16_t readU16BE(const uint8_t* in) {
|
||||
@ -569,7 +603,8 @@ class OpenH264VideoDecoder : public GMPVideoDecoder, public RefCounted {
|
||||
worker_thread_ (nullptr),
|
||||
callback_ (nullptr),
|
||||
decoder_ (nullptr),
|
||||
stats_ ("Decoder") {
|
||||
stats_ ("Decoder"),
|
||||
shutting_down(false) {
|
||||
AddRef();
|
||||
}
|
||||
|
||||
@ -716,11 +751,40 @@ class OpenH264VideoDecoder : public GMPVideoDecoder, public RefCounted {
|
||||
}
|
||||
|
||||
virtual void DecodingComplete() {
|
||||
shutting_down = true;
|
||||
|
||||
// Release the reference to the external objects, because it is no longer safe to call them
|
||||
host_ = nullptr;
|
||||
callback_ = nullptr;
|
||||
TearDownDecoder();
|
||||
|
||||
Release();
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~OpenH264VideoDecoder() {
|
||||
// Tear down the internal decoder in case of DecodingComplete() not being called
|
||||
TearDownDecoder();
|
||||
}
|
||||
|
||||
void TearDownDecoder() {
|
||||
// Stop the worker thread first
|
||||
if (worker_thread_) {
|
||||
worker_thread_->Join();
|
||||
worker_thread_ = nullptr;
|
||||
}
|
||||
|
||||
// Destroy OpenH264 decoder
|
||||
if (decoder_) {
|
||||
WelsDestroyDecoder(decoder_);
|
||||
decoder_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void TrySyncRunOnMainThread(GMPTask* aTask) {
|
||||
if (!shutting_down && g_platform_api) {
|
||||
g_platform_api->syncrunonmainthread (aTask);
|
||||
}
|
||||
}
|
||||
|
||||
void Error (GMPErr error) {
|
||||
@ -752,14 +816,14 @@ class OpenH264VideoDecoder : public GMPVideoDecoder, public RefCounted {
|
||||
valid = true;
|
||||
}
|
||||
|
||||
g_platform_api->syncrunonmainthread (WrapTask (
|
||||
this,
|
||||
&OpenH264VideoDecoder::Decode_m,
|
||||
inputFrame,
|
||||
&decoded,
|
||||
data,
|
||||
renderTimeMs,
|
||||
valid));
|
||||
TrySyncRunOnMainThread (WrapTask (
|
||||
this,
|
||||
&OpenH264VideoDecoder::Decode_m,
|
||||
inputFrame,
|
||||
&decoded,
|
||||
data,
|
||||
renderTimeMs,
|
||||
valid));
|
||||
}
|
||||
|
||||
// Return the decoded data back to the parent.
|
||||
@ -780,7 +844,9 @@ class OpenH264VideoDecoder : public GMPVideoDecoder, public RefCounted {
|
||||
|
||||
if (decoded->iBufferStatus != 1) {
|
||||
GMPLOG (GL_ERROR, "iBufferStatus=" << decoded->iBufferStatus);
|
||||
callback_->InputDataExhausted();
|
||||
if (callback_) {
|
||||
callback_->InputDataExhausted();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -798,6 +864,10 @@ class OpenH264VideoDecoder : public GMPVideoDecoder, public RefCounted {
|
||||
|
||||
GMPVideoFrame* ftmp = nullptr;
|
||||
|
||||
if (!host_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Translate the image.
|
||||
GMPErr err = host_->CreateFrame (kGMPI420VideoFrame, &ftmp);
|
||||
if (err != GMPNoErr) {
|
||||
@ -822,7 +892,9 @@ class OpenH264VideoDecoder : public GMPVideoDecoder, public RefCounted {
|
||||
<< frame->AllocatedSize (kGMPYPlane));
|
||||
frame->SetTimestamp (inputFrame->TimeStamp());
|
||||
frame->SetDuration (inputFrame->Duration());
|
||||
callback_->Decoded (frame);
|
||||
if (callback_) {
|
||||
callback_->Decoded (frame);
|
||||
}
|
||||
|
||||
stats_.FrameOut();
|
||||
}
|
||||
@ -832,6 +904,7 @@ class OpenH264VideoDecoder : public GMPVideoDecoder, public RefCounted {
|
||||
GMPVideoDecoderCallback* callback_;
|
||||
ISVCDecoder* decoder_;
|
||||
FrameStats stats_;
|
||||
bool shutting_down;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
@ -24,8 +24,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,4,1,0
|
||||
PRODUCTVERSION 1,4,1,0
|
||||
FILEVERSION 1,5,2,0
|
||||
PRODUCTVERSION 1,5,2,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -43,12 +43,12 @@ BEGIN
|
||||
VALUE "Comments", "Cisco OpenH264 codec"
|
||||
VALUE "CompanyName", "Cisco Systems Inc."
|
||||
VALUE "FileDescription", "Cisco OpenH264 codec"
|
||||
VALUE "FileVersion", "1.4.1.0"
|
||||
VALUE "FileVersion", "1.5.2.0"
|
||||
VALUE "InternalName", "openh264.dll"
|
||||
VALUE "LegalCopyright", "© 2011-2015 Cisco and/or its affiliates. All rights reserved."
|
||||
VALUE "OriginalFilename", "openh264.dll"
|
||||
VALUE "ProductName", "Cisco OpenH264 codec"
|
||||
VALUE "ProductVersion", "1.4.1.0"
|
||||
VALUE "ProductVersion", "1.5.2.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -204,7 +204,7 @@ class EncodeDecodeTestAPIBase : public EncodeDecodeTestBase {
|
||||
if (0 == iCheckTypeIndex)
|
||||
ASSERT_TRUE (rv == cmResultSuccess);
|
||||
else if (1 == iCheckTypeIndex)
|
||||
ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnkonwReason);
|
||||
ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason);
|
||||
}
|
||||
|
||||
void EncDecOneFrame (const int iWidth, const int iHeight, const int iFrame, FILE* pfEnc) {
|
||||
@ -990,7 +990,7 @@ TEST_P (EncodeDecodeTestAPI, GetOptionLTR_ALLLTR) {
|
||||
if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
|
||||
ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
|
||||
}
|
||||
ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnkonwReason);
|
||||
ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason);
|
||||
m_LTR_Recover_Request.uiFeedbackType = LTR_RECOVERY_REQUEST;
|
||||
m_LTR_Recover_Request.iCurrentFrameNum = rand() % 2 == 1 ? -rand() % 10000 : rand() % 10000;
|
||||
m_LTR_Recover_Request.uiIDRPicId = rand() % 2 == 1 ? -rand() % 10000 : rand() % 10000;
|
||||
@ -2277,7 +2277,7 @@ class DecodeCrashTestAPI : public ::testing::TestWithParam<EncodeDecodeFileParam
|
||||
memset (buf_.data(), iRandValue, (frameSize >> 2));
|
||||
memset (buf_.data() + (frameSize >> 2), rand() % 256, (frameSize - (frameSize >> 2)));
|
||||
int rv = encoder_->EncodeFrame (&EncPic, &info);
|
||||
ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnkonwReason);
|
||||
ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason);
|
||||
}
|
||||
protected:
|
||||
unsigned char* ucBuf_;
|
||||
@ -2562,7 +2562,7 @@ class DecodeParseAPI : public ::testing::TestWithParam<EncodeDecodeFileParamBase
|
||||
ASSERT_TRUE (iSize == iFrameSize);
|
||||
}
|
||||
int rv = encoder_->EncodeFrame (&EncPic, &info);
|
||||
ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnkonwReason);
|
||||
ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason);
|
||||
}
|
||||
|
||||
void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate, SEncParamExt* pParam) {
|
||||
@ -3505,7 +3505,7 @@ class EncodeTestAPI : public ::testing::TestWithParam<EncodeOptionParam>, public
|
||||
if (0 == iCheckTypeIndex)
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv=" << rv;
|
||||
else if (1 == iCheckTypeIndex)
|
||||
ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnkonwReason) << "rv=" << rv;
|
||||
ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnknownReason) << "rv=" << rv;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -122,7 +122,7 @@ void anchor_DeblockingLumaNormal (uint8_t* pPix, int32_t iStrideX, int32_t iStri
|
||||
iTc++;
|
||||
}
|
||||
// 8-467,468,469
|
||||
iDelta = WELS_CLIP3 (((((q[0] - p[0]) << 2) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
|
||||
iDelta = WELS_CLIP3 (((((q[0] - p[0]) * (1 << 2)) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
|
||||
pPix[iStrideX * -1] = WELS_CLIP3 ((p[0] + iDelta), 0, 255);
|
||||
pPix[0] = WELS_CLIP3 ((q[0] - iDelta), 0, 255);
|
||||
}
|
||||
@ -194,7 +194,7 @@ void anchor_DeblockingChromaNormal (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iS
|
||||
// filterSampleFlag, 8-460
|
||||
if (abs (p[0] - q[0]) < iAlpha && abs (p[1] - p[0]) < iBeta && abs (q[1] - q[0]) < iBeta) {
|
||||
// 8-467, 468, 469
|
||||
iDelta = WELS_CLIP3 (((((q[0] - p[0]) << 2) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
|
||||
iDelta = WELS_CLIP3 (((((q[0] - p[0]) * (1 << 2)) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
|
||||
pPixCb[iStrideX * -1] = WELS_CLIP3 ((p[0] + iDelta), 0, 255);
|
||||
pPixCb[iStrideX * 0 ] = WELS_CLIP3 ((q[0] - iDelta), 0, 255);
|
||||
}
|
||||
@ -209,7 +209,7 @@ void anchor_DeblockingChromaNormal (uint8_t* pPixCb, uint8_t* pPixCr, int32_t iS
|
||||
// filterSampleFlag, 8-460
|
||||
if (abs (p[0] - q[0]) < iAlpha && abs (p[1] - p[0]) < iBeta && abs (q[1] - q[0]) < iBeta) {
|
||||
// 8-467, 468, 469
|
||||
iDelta = WELS_CLIP3 (((((q[0] - p[0]) << 2) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
|
||||
iDelta = WELS_CLIP3 (((((q[0] - p[0]) * (1 << 2)) + (p[1] - q[1]) + 4) >> 3), -1 * iTc, iTc);
|
||||
pPixCr[iStrideX * -1] = WELS_CLIP3 ((p[0] + iDelta), 0, 255);
|
||||
pPixCr[iStrideX * 0 ] = WELS_CLIP3 ((q[0] - iDelta), 0, 255);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user