shithub: openh264

Download patch

ref: 84c1f3a4eec95f0feaf898bd5b7dd3edee00a7e3
parent: 7574e5c1dbaa4c3f249e496f14c8c898e8f21cab
parent: 090229f8a195f5f503f0e71b663c2578554e2b2c
author: ruil2 <[email protected]>
date: Wed Jun 11 09:25:48 EDT 2014

Merge pull request #945 from mstorsjo/log-callback

Don't use a global trace level, allow user-specified trace callbacks

--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -93,7 +93,9 @@
 
   ENCODER_OPTION_CURRENT_PATH,
   ENCODER_OPTION_DUMP_FILE,
-  ENCODER_OPTION_TRACE_LEVEL
+  ENCODER_OPTION_TRACE_LEVEL,
+  ENCODER_OPTION_TRACE_CALLBACK, // a void (*)(void* context, int level, const char* message) function which receives log messages
+  ENCODER_OPTION_TRACE_CALLBACK_CONTEXT,
 } ENCODER_OPTION;
 
 /* Option types introduced in decoder application */
@@ -107,6 +109,9 @@
   DECODER_OPTION_LTR_MARKING_FLAG,	// feedback wether current frame mark a LTR
   DECODER_OPTION_LTR_MARKED_FRAME_NUM,	// feedback frame num marked by current Frame
   DECODER_OPTION_ERROR_CON_IDC, //not finished yet, indicate decoder error concealment status, in progress
+  DECODER_OPTION_TRACE_LEVEL,
+  DECODER_OPTION_TRACE_CALLBACK, // a void (*)(void* context, int level, const char* message) function which receives log messages
+  DECODER_OPTION_TRACE_CALLBACK_CONTEXT,
 
 } DECODER_OPTION;
 
--- a/codec/build/android/dec/jni/welsdecdemo.mk
+++ b/codec/build/android/dec/jni/welsdecdemo.mk
@@ -26,7 +26,6 @@
             $(CONSOLE_DEC_PATH)/src/h264dec.cpp \
             $(CONSOLE_DEC_PATH)/src/read_config.cpp \
             $(CONSOLE_DEC_PATH)/src/d3d9_utils.cpp \
-            $(CODEC_PATH)/common/src/logging.cpp \
             myjni.cpp
 #
 # Header Includes
--- a/codec/build/android/enc/jni/welsencdemo.mk
+++ b/codec/build/android/enc/jni/welsencdemo.mk
@@ -25,7 +25,6 @@
 LOCAL_SRC_FILES := \
             $(CONSOLE_ENC_PATH)/src/welsenc.cpp \
             $(CONSOLE_ENC_PATH)/src/read_config.cpp \
-            $(CODEC_PATH)/common/src/logging.cpp \
             myjni.cpp
 
 #
--- a/codec/build/iOS/common/common.xcodeproj/project.pbxproj
+++ b/codec/build/iOS/common/common.xcodeproj/project.pbxproj
@@ -14,7 +14,6 @@
 		4C3406CD18D96EA600DFA14A /* cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3406C418D96EA600DFA14A /* cpu.cpp */; };
 		4C3406CE18D96EA600DFA14A /* crt_util_safe_x.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3406C518D96EA600DFA14A /* crt_util_safe_x.cpp */; };
 		4C3406CF18D96EA600DFA14A /* deblocking_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3406C618D96EA600DFA14A /* deblocking_common.cpp */; };
-		4C3406D018D96EA600DFA14A /* logging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3406C718D96EA600DFA14A /* logging.cpp */; };
 		4C3406D118D96EA600DFA14A /* WelsThreadLib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3406C818D96EA600DFA14A /* WelsThreadLib.cpp */; };
 		4CC61F0918FF6B4B00E56EAB /* copy_mb_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 4CC61F0818FF6B4B00E56EAB /* copy_mb_neon.S */; };
 		4CE443D918B722CD0017DF25 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CE443D818B722CD0017DF25 /* Foundation.framework */; };
@@ -47,7 +46,6 @@
 		4C3406B818D96EA600DFA14A /* cpu_core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu_core.h; sourceTree = "<group>"; };
 		4C3406B918D96EA600DFA14A /* crt_util_safe_x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crt_util_safe_x.h; sourceTree = "<group>"; };
 		4C3406BA18D96EA600DFA14A /* deblocking_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = deblocking_common.h; sourceTree = "<group>"; };
-		4C3406BC18D96EA600DFA14A /* logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = logging.h; sourceTree = "<group>"; };
 		4C3406BD18D96EA600DFA14A /* ls_defines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ls_defines.h; sourceTree = "<group>"; };
 		4C3406BE18D96EA600DFA14A /* macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = macros.h; sourceTree = "<group>"; };
 		4C3406BF18D96EA600DFA14A /* mc_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mc_common.h; sourceTree = "<group>"; };
@@ -57,7 +55,6 @@
 		4C3406C418D96EA600DFA14A /* cpu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cpu.cpp; sourceTree = "<group>"; };
 		4C3406C518D96EA600DFA14A /* crt_util_safe_x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = crt_util_safe_x.cpp; sourceTree = "<group>"; };
 		4C3406C618D96EA600DFA14A /* deblocking_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = deblocking_common.cpp; sourceTree = "<group>"; };
-		4C3406C718D96EA600DFA14A /* logging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = logging.cpp; sourceTree = "<group>"; };
 		4C3406C818D96EA600DFA14A /* WelsThreadLib.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WelsThreadLib.cpp; sourceTree = "<group>"; };
 		4CC61F0818FF6B4B00E56EAB /* copy_mb_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = copy_mb_neon.S; sourceTree = "<group>"; };
 		4CE443D518B722CD0017DF25 /* libcommon.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libcommon.a; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -108,7 +105,6 @@
 				4C3406B918D96EA600DFA14A /* crt_util_safe_x.h */,
 				53C1C9BA193F0F9E00404D8F /* expand_pic.h */,
 				4C3406BA18D96EA600DFA14A /* deblocking_common.h */,
-				4C3406BC18D96EA600DFA14A /* logging.h */,
 				4C3406BD18D96EA600DFA14A /* ls_defines.h */,
 				4C3406BE18D96EA600DFA14A /* macros.h */,
 				4C3406BF18D96EA600DFA14A /* mc_common.h */,
@@ -128,7 +124,6 @@
 				4C3406C518D96EA600DFA14A /* crt_util_safe_x.cpp */,
 				53C1C9BB193F0FB000404D8F /* expand_pic.cpp */,
 				4C3406C618D96EA600DFA14A /* deblocking_common.cpp */,
-				4C3406C718D96EA600DFA14A /* logging.cpp */,
 				4C3406C818D96EA600DFA14A /* WelsThreadLib.cpp */,
 			);
 			path = src;
@@ -238,7 +233,6 @@
 				F556A8241906673900E156A8 /* arm_arch64_common_macro.S in Sources */,
 				4C3406CE18D96EA600DFA14A /* crt_util_safe_x.cpp in Sources */,
 				4C3406CF18D96EA600DFA14A /* deblocking_common.cpp in Sources */,
-				4C3406D018D96EA600DFA14A /* logging.cpp in Sources */,
 				4C3406D118D96EA600DFA14A /* WelsThreadLib.cpp in Sources */,
 				4C3406CC18D96EA600DFA14A /* mc_neon.S in Sources */,
 				4C3406CB18D96EA600DFA14A /* expand_picture_neon.S in Sources */,
--- a/codec/build/win32/dec/WelsDecCore.vcproj
+++ b/codec/build/win32/dec/WelsDecCore.vcproj
@@ -903,10 +903,6 @@
 					>
 				</File>
 				<File
-					RelativePath="..\..\..\common\src\logging.cpp"
-					>
-				</File>
-				<File
 					RelativePath="..\..\..\decoder\core\src\manage_dec_ref.cpp"
 					>
 				</File>
--- a/codec/build/win32/dec/decConsole.vcproj
+++ b/codec/build/win32/dec/decConsole.vcproj
@@ -395,10 +395,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\..\common\src\logging.cpp"
-				>
-			</File>
-			<File
 				RelativePath="..\..\..\console\dec\src\read_config.cpp"
 				>
 			</File>
--- a/codec/build/win32/enc/WelsEncCore.vcproj
+++ b/codec/build/win32/enc/WelsEncCore.vcproj
@@ -396,10 +396,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\..\common\src\logging.cpp"
-				>
-			</File>
-			<File
 				RelativePath="..\..\..\encoder\core\src\mc.cpp"
 				>
 			</File>
--- a/codec/build/win32/enc/encConsole.vcproj
+++ b/codec/build/win32/enc/encConsole.vcproj
@@ -395,10 +395,6 @@
 			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
 			>
 			<File
-				RelativePath="..\..\..\common\src\logging.cpp"
-				>
-			</File>
-			<File
 				RelativePath="..\..\..\console\enc\src\read_config.cpp"
 				>
 			</File>
--- a/codec/common/inc/logging.h
+++ /dev/null
@@ -1,54 +1,0 @@
-/*!
- * \copy
- *     Copyright (c)  2013, Cisco Systems
- *     Copyright (c)  2013, Mozilla
- *     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.
- *
- *     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.
- *
- */
-
-
-#ifndef WELS_LOGGING_H__
-#define WELS_LOGGING_H__
-
-// API surface.
-void WelsStderrSetTraceLevel (int32_t level);
-
-
-// Internal details.
-int32_t welsStderrLevelTrace (int32_t level, const char* format, va_list ap);
-
-template<int level> int32_t welsStderrTrace (
-  const char* format, ...) {
-  va_list ap;
-  va_start (ap, format);
-  welsStderrLevelTrace (level, format, ap);
-  va_end (ap);
-  return 0;
-}
-
-#endif
--- a/codec/common/inc/utils.h
+++ b/codec/common/inc/utils.h
@@ -47,7 +47,6 @@
  *	Log output routines
  */
 
-typedef int32_t	iWelsLogLevel;
 enum {
   WELS_LOG_QUIET		= 0x00,		// Quiet mode
   WELS_LOG_ERROR		= 1 << 0,	// Error log iLevel
@@ -56,7 +55,7 @@
   WELS_LOG_DEBUG		= 1 << 3,	// Debug log iLevel
   WELS_LOG_RESV		= 1 << 4,	// Resversed log iLevel
   WELS_LOG_LEVEL_COUNT = 5,
-  WELS_LOG_DEFAULT	= WELS_LOG_ERROR | WELS_LOG_WARNING | WELS_LOG_INFO | WELS_LOG_DEBUG	// Default log iLevel in Wels codec
+  WELS_LOG_DEFAULT	= WELS_LOG_DEBUG	// Default log iLevel in Wels codec
 };
 
 /*
@@ -65,16 +64,12 @@
 // wels log output
 typedef void (*PWelsLogCallbackFunc) (void* pCtx, const int32_t iLevel, const char* kpFmt, va_list argv);
 
-// wels psnr calc
-typedef float (*PWelsPsnrFunc) (const void* kpTarPic,
-                                const int32_t kiTarStride,
-                                const void* kpRefPic,
-                                const int32_t kiRefStride,
-                                const int32_t kiWidth,
-                                const int32_t kiHeight);
+typedef struct TagLogContext {
+  PWelsLogCallbackFunc pfLog;
+  void* pLogCtx;
+} SLogContext;
 
 
-
 #ifdef __GNUC__
 extern void WelsLog (void* pCtx, int32_t iLevel, const char* kpFmt, ...) __attribute__ ((__format__ (__printf__, 3,
     4)));
@@ -81,19 +76,6 @@
 #else
 extern void WelsLog (void* pCtx, int32_t iLevel, const char* kpFmt, ...);
 #endif
-
-/*!
- *************************************************************************************
- * \brief	set log callback from external call
- *
- * \param	_log	log function routine
- *
- * \return	NONE
- *
- * \note	N/A
- *************************************************************************************
- */
-void WelsSetLogCallback (PWelsLogCallbackFunc _log);
 
 /*
  *	PSNR calculation routines
--- a/codec/common/inc/welsCodecTrace.h
+++ b/codec/common/inc/welsCodecTrace.h
@@ -35,8 +35,9 @@
 
 #include <stdarg.h>
 #include "typedefs.h"
+#include "utils.h"
 
-typedef int32_t (*CM_WELS_TRACE) (const char* format, ...);
+typedef void (*CM_WELS_TRACE) (void* ctx, int level, const char* string);
 
 class welsCodecTrace {
  public:
@@ -43,18 +44,20 @@
   welsCodecTrace();
   ~welsCodecTrace();
 
-  static void TraceString (int32_t iLevel, const char* kpStrFormat);
-  static void CODEC_TRACE (void* pIgnore, const int32_t kiLevel, const char* kpStrFormat, va_list vl);
-
   void SetTraceLevel (const int32_t kiLevel);
+  void SetTraceCallback (CM_WELS_TRACE func);
+  void SetTraceCallbackContext (void* pCtx);
 
+ private:
+  static void StaticCodecTrace (void* pCtx, const int32_t kiLevel, const char* kpStrFormat, va_list vl);
+  void CodecTrace (const int32_t kiLevel, const char* kpStrFormat, va_list vl);
+
+  int32_t	m_iTraceLevel;
+  CM_WELS_TRACE m_fpTrace;
+  void*         m_pTraceCtx;
  public:
-  static int32_t	m_iTraceLevel;
-  static CM_WELS_TRACE m_fpDebugTrace;
-  static CM_WELS_TRACE m_fpInfoTrace;
-  static CM_WELS_TRACE m_fpWarnTrace;
-  static CM_WELS_TRACE m_fpErrorTrace;
 
+  SLogContext m_sLogCtx;
 };
 
 #endif //WELS_CODEC_TRACE
--- a/codec/common/src/logging.cpp
+++ /dev/null
@@ -1,49 +1,0 @@
-/*!
- * \copy
- *     Copyright (c)  2013, Cisco Systems
- *     Copyright (c)  2013, Mozilla
- *     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.
- *
- *     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.
- *
- */
-
-#include <stdarg.h>
-#include <stdio.h>
-#include "typedefs.h"
-
-static int32_t g_TraceLevel = 0;
-
-void WelsStderrSetTraceLevel (int32_t level) {
-  g_TraceLevel = level;
-}
-
-int32_t welsStderrLevelTrace (int32_t level, const char* format, va_list ap) {
-  if (level < g_TraceLevel) {
-    vfprintf (stderr, format, ap);
-  }
-  return 0;
-}
--- a/codec/common/src/utils.cpp
+++ b/codec/common/src/utils.cpp
@@ -48,27 +48,11 @@
                     const int32_t kiHeight);
 
 
-static PWelsLogCallbackFunc	wlog;
-
-/*!
- *************************************************************************************
- * \brief	set log callback from external call
- *
- * \param	_log	log function routine
- *
- * \return	NONE
- *
- * \note	N/A
- *************************************************************************************
- */
-void WelsSetLogCallback (PWelsLogCallbackFunc _log) {
-  wlog	= _log;
-}
-
 void WelsLog (void* pCtx, int32_t iLevel, const char* kpFmt, ...) {
+  SLogContext* logCtx = (SLogContext*) pCtx;
   va_list vl;
   va_start (vl, kpFmt);
-  wlog (pCtx, iLevel, kpFmt, vl);
+  logCtx->pfLog (logCtx->pLogCtx, iLevel, kpFmt, vl);
   va_end (vl);
 }
 
--- a/codec/common/src/welsCodecTrace.cpp
+++ b/codec/common/src/welsCodecTrace.cpp
@@ -44,57 +44,34 @@
 #include "welsCodecTrace.h"
 #include "utils.h"
 
-#include "logging.h"
 
-int32_t	welsCodecTrace::m_iTraceLevel			= WELS_LOG_DEFAULT;
-CM_WELS_TRACE welsCodecTrace::m_fpDebugTrace	= NULL;
-CM_WELS_TRACE welsCodecTrace::m_fpInfoTrace	= NULL;
-CM_WELS_TRACE welsCodecTrace::m_fpWarnTrace	= NULL;
-CM_WELS_TRACE welsCodecTrace::m_fpErrorTrace	= NULL;
 
+static void welsStderrTrace (void* ctx, int level, const char* string) {
+  fprintf (stderr, "%s", string);
+}
+
 welsCodecTrace::welsCodecTrace() {
 
-  m_fpDebugTrace = welsStderrTrace<WELS_LOG_DEBUG>;
-  m_fpInfoTrace = welsStderrTrace<WELS_LOG_INFO>;
-  m_fpWarnTrace = welsStderrTrace<WELS_LOG_WARNING>;
-  m_fpErrorTrace = welsStderrTrace<WELS_LOG_ERROR>;
+  m_iTraceLevel = WELS_LOG_DEFAULT;
+  m_fpTrace = welsStderrTrace;
+  m_pTraceCtx = NULL;
+
+  m_sLogCtx.pLogCtx = this;
+  m_sLogCtx.pfLog = StaticCodecTrace;
 }
 
 welsCodecTrace::~welsCodecTrace() {
-  m_fpDebugTrace = NULL;
-  m_fpInfoTrace = NULL;
-  m_fpWarnTrace = NULL;
-  m_fpErrorTrace = NULL;
+  m_fpTrace = NULL;
 }
 
-void welsCodecTrace::TraceString (int32_t iLevel, const char* str) {
-  switch (iLevel) {
-  case WELS_LOG_ERROR:
-    if (m_fpErrorTrace)
-      m_fpErrorTrace ("%s", str);
-    break;
-  case WELS_LOG_WARNING:
-    if (m_fpWarnTrace)
-      m_fpWarnTrace ("%s", str);
-    break;
-  case WELS_LOG_INFO:
-    if (m_fpInfoTrace)
-      m_fpInfoTrace ("%s", str);
-    break;
-  case WELS_LOG_DEBUG:
-    if (m_fpDebugTrace)
-      m_fpDebugTrace ("%s", str);
-    break;
-  default:
-    if (m_fpDebugTrace)
-      m_fpInfoTrace ("%s", str);
-    break;
-  }
-}
-
 #define MAX_LOG_SIZE	1024
 
-void welsCodecTrace::CODEC_TRACE (void* ignore, const int32_t iLevel, const char* Str_Format, va_list vl) {
+void welsCodecTrace::StaticCodecTrace (void* pCtx, const int32_t iLevel, const char* Str_Format, va_list vl) {
+  welsCodecTrace* self = (welsCodecTrace*) pCtx;
+  self->CodecTrace (iLevel, Str_Format, vl);
+}
+
+void welsCodecTrace::CodecTrace (const int32_t iLevel, const char* Str_Format, va_list vl) {
   if (m_iTraceLevel < iLevel) {
     return;
   }
@@ -102,13 +79,19 @@
   char pBuf[MAX_LOG_SIZE] = {0};
   WelsVsnprintf (pBuf, MAX_LOG_SIZE, Str_Format, vl);	// confirmed_safe_unsafe_usage
 
-  welsCodecTrace::TraceString (iLevel, pBuf);
+  m_fpTrace (m_pTraceCtx, iLevel, pBuf);
 }
 
 void welsCodecTrace::SetTraceLevel (const int32_t iLevel) {
   if (iLevel >= 0)
     m_iTraceLevel	= iLevel;
-  WelsStderrSetTraceLevel (iLevel);
 }
 
+void welsCodecTrace::SetTraceCallback (CM_WELS_TRACE func) {
+  m_fpTrace = func;
+}
+
+void welsCodecTrace::SetTraceCallbackContext (void* ctx) {
+  m_pTraceCtx = ctx;
+}
 
--- a/codec/common/targets.mk
+++ b/codec/common/targets.mk
@@ -5,7 +5,6 @@
 	$(COMMON_SRCDIR)/src/crt_util_safe_x.cpp\
 	$(COMMON_SRCDIR)/src/deblocking_common.cpp\
 	$(COMMON_SRCDIR)/src/expand_pic.cpp\
-	$(COMMON_SRCDIR)/src/logging.cpp\
 	$(COMMON_SRCDIR)/src/sad_common.cpp\
 	$(COMMON_SRCDIR)/src/utils.cpp\
 	$(COMMON_SRCDIR)/src/welsCodecTrace.cpp\
--- a/codec/console/dec/src/h264dec.cpp
+++ b/codec/console/dec/src/h264dec.cpp
@@ -51,7 +51,6 @@
 #include "typedefs.h"
 #include "measure_time.h"
 #include "d3d9_utils.h"
-#include "logging.h"
 
 
 using namespace std;
@@ -311,6 +310,7 @@
 
   SDecodingParam sDecParam = {0};
   string strInputFile (""), strOutputFile (""), strOptionFile ("");
+  int iLevelSetting = -1;
 
   sDecParam.sVideoProperty.size = sizeof (sDecParam.sVideoProperty);
 
@@ -384,7 +384,7 @@
 
         if (!strcmp (cmd, "-options")) {
           if (i + 1 < iArgC)
-            strOptionFile = pArgV[i++];
+            strOptionFile = pArgV[++i];
           else {
             printf ("options file not specified.\n");
             return 1;
@@ -391,7 +391,7 @@
           }
         } else if (!strcmp (cmd, "-trace")) {
           if (i + 1 < iArgC)
-            WelsStderrSetTraceLevel (atoi (pArgV[i++]));
+            iLevelSetting = atoi (pArgV[++i]);
           else {
             printf ("trace level not specified.\n");
             return 1;
@@ -417,6 +417,9 @@
   if (WelsCreateDecoder (&pDecoder)  || (NULL == pDecoder)) {
     printf ("Create Decoder failed.\n");
     return 1;
+  }
+  if (iLevelSetting >= 0) {
+    pDecoder->SetOption (DECODER_OPTION_TRACE_LEVEL, &iLevelSetting);
   }
 
   if (pDecoder->Initialize (&sDecParam)) {
--- a/codec/console/enc/src/welsenc.cpp
+++ b/codec/console/enc/src/welsenc.cpp
@@ -67,7 +67,6 @@
 #include "extern.h"
 #include "macros.h"
 #include "wels_const.h"
-#include "logging.h"
 
 #include "mt_defs.h"
 #include "WelsThreadLib.h"
@@ -102,7 +101,7 @@
 static void    SigIntHandler (int a) {
   g_iCtrlC = 1;
 }
-static int     g_LevelSetting = 0;
+static int     g_LevelSetting = -1;
 
 int ParseLayerConfig (CReadConfig& cRdLayerCfg, const int iLayer, SEncParamExt& pSvcParam, SFilesSet& sFileSet) {
   if (!cRdLayerCfg.ExistFile()) {
@@ -664,6 +663,9 @@
     printf ("parse pCommand line failed\n");
     iRet = 1;
     goto INSIDE_MEM_FREE;
+  }
+  if (g_LevelSetting >= 0) {
+    pPtrEnc->SetOption (ENCODER_OPTION_TRACE_LEVEL, &g_LevelSetting);
   }
   //finish reading the configurations
   iSourceWidth = pSrcPic->iPicWidth;
--- a/codec/decoder/core/inc/decoder.h
+++ b/codec/decoder/core/inc/decoder.h
@@ -68,7 +68,7 @@
  * \note	N/A
  *************************************************************************************
  */
-int32_t WelsInitDecoder (PWelsDecoderContext pCtx);
+int32_t WelsInitDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx);
 
 /*!
  *************************************************************************************
--- a/codec/decoder/core/inc/decoder_context.h
+++ b/codec/decoder/core/inc/decoder_context.h
@@ -164,6 +164,7 @@
  */
 
 typedef struct TagWelsDecoderContext {
+  SLogContext sLogCtx;
   // Input
   void*				pArgDec;			// structured arguments for decoder, reserved here for extension in the future
 
--- a/codec/decoder/core/src/decoder.cpp
+++ b/codec/decoder/core/src/decoder.cpp
@@ -127,9 +127,10 @@
 /*
  * fill data fields in default for decoder context
  */
-void WelsDecoderDefaults (PWelsDecoderContext pCtx) {
+void WelsDecoderDefaults (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
   int32_t iCpuCores               = 1;
   memset (pCtx, 0, sizeof (SWelsDecoderContext));	// fill zero first
+  pCtx->sLogCtx = *pLogCtx;
 
   pCtx->pArgDec                   = NULL;
 
@@ -350,13 +351,13 @@
  * \note	N/A
  *************************************************************************************
  */
-int32_t WelsInitDecoder (PWelsDecoderContext pCtx) {
+int32_t WelsInitDecoder (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
   if (pCtx == NULL) {
     return ERR_INFO_INVALID_PTR;
   }
 
   // default
-  WelsDecoderDefaults (pCtx);
+  WelsDecoderDefaults (pCtx, pLogCtx);
 
   // open decoder
   WelsOpenDecoder (pCtx);
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -103,11 +103,10 @@
   m_pWelsTrace	= new welsCodecTrace();
   if (m_pWelsTrace != NULL) {
     m_pWelsTrace->SetTraceLevel (WELS_LOG_ERROR);
-    WelsSetLogCallback (welsCodecTrace::CODEC_TRACE);
+
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::CWelsDecoder() entry");
   }
 
-  WelsLog (NULL, WELS_LOG_INFO, "CWelsDecoder::CWelsDecoder() entry");
-
 #ifdef OUTPUT_BIT_STREAM
   SWelsTime sCurTime;
 
@@ -161,7 +160,9 @@
 *	return: none
 ***************************************************************************/
 CWelsDecoder::~CWelsDecoder() {
-  WelsLog (NULL, WELS_LOG_INFO, "CWelsDecoder::~CWelsDecoder()");
+  if (m_pWelsTrace != NULL) {
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::~CWelsDecoder()");
+  }
 
   UninitDecoder();
 
@@ -183,8 +184,12 @@
 }
 
 long CWelsDecoder::Initialize (const SDecodingParam* pParam) {
+  if (m_pWelsTrace == NULL) {
+    return cmMallocMemeError;
+  }
+
   if (pParam == NULL) {
-    WelsLog (NULL, WELS_LOG_INFO, "CWelsDecoder::Initialize(), invalid input argument.");
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::Initialize(), invalid input argument.");
     return cmInitParaError;
   }
 
@@ -206,7 +211,7 @@
   if (NULL == m_pDecContext)
     return;
 
-  WelsLog (NULL, WELS_LOG_INFO, "into CWelsDecoder::uninit_decoder()..");
+  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "into CWelsDecoder::uninit_decoder()..");
 
   WelsEndDecoder (m_pDecContext);
 
@@ -216,19 +221,19 @@
     m_pDecContext	= NULL;
   }
 
-  WelsLog (NULL , WELS_LOG_INFO, "left CWelsDecoder::uninit_decoder()..");
+  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "left CWelsDecoder::uninit_decoder()..");
 }
 
 // the return value of this function is not suitable, it need report failure info to upper layer.
 void CWelsDecoder::InitDecoder (void) {
 
-  WelsLog (NULL, WELS_LOG_INFO, "CWelsDecoder::init_decoder()..");
+  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::init_decoder()..");
 
   m_pDecContext	= (PWelsDecoderContext)WelsMalloc (sizeof (SWelsDecoderContext), "m_pDecContext");
 
-  WelsInitDecoder (m_pDecContext);
+  WelsInitDecoder (m_pDecContext, &m_pWelsTrace->m_sLogCtx);
 
-  WelsLog (NULL, WELS_LOG_INFO, "CWelsDecoder::init_decoder().. left");
+  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::init_decoder().. left");
 }
 
 /*
@@ -237,7 +242,8 @@
 long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) {
   int iVal = 0;
 
-  if (m_pDecContext == NULL)
+  if (m_pDecContext == NULL && eOptID != DECODER_OPTION_TRACE_LEVEL &&
+      eOptID != DECODER_OPTION_TRACE_CALLBACK && eOptID != DECODER_OPTION_TRACE_CALLBACK_CONTEXT)
     return dsInitialOptExpected;
 
   if (eOptID == DECODER_OPTION_DATAFORMAT) { // Set color space of decoding output frame
@@ -263,6 +269,24 @@
       iVal = * ((int*)pOption); //EC method
     m_pDecContext->iErrorConMethod = iVal;
     return cmResultSuccess;
+  } else if (eOptID == DECODER_OPTION_TRACE_LEVEL) {
+    if (m_pWelsTrace) {
+      uint32_t level = * ((uint32_t*)pOption);
+      m_pWelsTrace->SetTraceLevel (level);
+    }
+    return cmResultSuccess;
+  } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK) {
+    if (m_pWelsTrace) {
+      CM_WELS_TRACE callback = * ((CM_WELS_TRACE*)pOption);
+      m_pWelsTrace->SetTraceCallback (callback);
+    }
+    return cmResultSuccess;
+  } else if (eOptID == DECODER_OPTION_TRACE_CALLBACK_CONTEXT) {
+    if (m_pWelsTrace) {
+      void* ctx = * ((void**)pOption);
+      m_pWelsTrace->SetTraceCallbackContext (ctx);
+    }
+    return cmResultSuccess;
   }
 
   return cmInitParaError;
@@ -386,7 +410,7 @@
       }
     }
 
-    WelsLog (NULL, WELS_LOG_INFO, "decode failed, failure type:%d \n",
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n",
              m_pDecContext->iErrorCode);
     return (DECODING_STATE)m_pDecContext->iErrorCode;
   }
--- a/codec/encoder/core/inc/encoder_context.h
+++ b/codec/encoder/core/inc/encoder_context.h
@@ -53,6 +53,7 @@
 #include "wels_preprocess.h"
 #include "wels_func_ptr_def.h"
 #include "crt_util_safe_x.h"
+#include "utils.h"
 
 #include "mt_defs.h"	// for multiple threadin,
 #include "WelsThreadLib.h"
@@ -110,6 +111,7 @@
 } SStrideTables;
 
 typedef struct TagWelsEncCtx {
+  SLogContext sLogCtx;
   // Input
   SWelsSvcCodingParam*		pSvcParam;	// SVC parameter, WelsSVCParamConfig in svc_param_settings.h
   SWelsSliceBs*		 	pSliceBs;		// bitstream buffering for various slices, [uiSliceIdx]
--- a/codec/encoder/core/inc/extern.h
+++ b/codec/encoder/core/inc/extern.h
@@ -64,7 +64,7 @@
  * \pParam	pParam		SWelsSvcCodingParam*
  * \return	successful - 0; otherwise none 0 for failed
  */
-int32_t ParamValidationExt (sWelsEncCtx* pCtx, SWelsSvcCodingParam* pParam);
+int32_t ParamValidationExt (SLogContext* pCtx, SWelsSvcCodingParam* pParam);
 
 // GOM based RC related for uiSliceNum decision
 void GomValidCheck (const int32_t kiMbWidth, const int32_t kiMbHeight, int32_t* pSliceNum);
@@ -75,7 +75,7 @@
  * \param	para		SWelsSvcCodingParam*
  * \return	successful - 0; otherwise none 0 for failed
  */
-int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pPara);
+int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pPara, SLogContext* pLogCtx);
 
 /*!
  * \brief	uninitialize Wels encoder core library
@@ -107,7 +107,7 @@
  */
 int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNew);
 void WelsEncoderApplyFrameRate (SWelsSvcCodingParam* pParam);
-void WelsEncoderApplyBitRate (SWelsSvcCodingParam* pParam, int32_t iLayer);
+void WelsEncoderApplyBitRate (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int32_t iLayer);
 
 int32_t FilterLTRRecoveryRequest (sWelsEncCtx* pCtx, SLTRRecoverRequest* pLTRRecoverRequest);
 
--- a/codec/encoder/core/inc/slice_multi_threading.h
+++ b/codec/encoder/core/inc/slice_multi_threading.h
@@ -81,8 +81,8 @@
 
 int32_t CreateSliceThreads (sWelsEncCtx* pCtx);
 
-int32_t FiredSliceThreads (SSliceThreadPrivateData* pPriData, WELS_EVENT* pEventsList, WELS_EVENT* pMasterEventsList,
-                           SLayerBSInfo* pLayerBsInfo,
+int32_t FiredSliceThreads (sWelsEncCtx* pCtx, SSliceThreadPrivateData* pPriData, WELS_EVENT* pEventsList,
+                           WELS_EVENT* pMasterEventsList, SLayerBSInfo* pLayerBsInfo,
                            const uint32_t kuiNumThreads/*, int32_t *iLayerNum*/, SSliceCtx* pSliceCtx, const bool kbIsDynamicSlicingMode);
 
 int32_t DynamicDetectCpuCores();
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -73,7 +73,7 @@
  * \pParam	pParam		SWelsSvcCodingParam*
  * \return	successful - 0; otherwise none 0 for failed
  */
-int32_t ParamValidation (SWelsSvcCodingParam* pCfg) {
+int32_t ParamValidation (SLogContext* pLogCtx, SWelsSvcCodingParam* pCfg) {
   float fMaxFrameRate = 0.0f;
   const float fEpsn = 0.000001f;
   int32_t i = 0;
@@ -81,7 +81,7 @@
   assert (pCfg != NULL);
 
   if ((pCfg->iUsageType != CAMERA_VIDEO_REAL_TIME) && (pCfg->iUsageType != SCREEN_CONTENT_REAL_TIME)) {
-    WelsLog (NULL, WELS_LOG_ERROR, "ParamValidation(),Invalid usage type = %d\n", pCfg->iUsageType);
+    WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidation(),Invalid usage type = %d\n", pCfg->iUsageType);
     return ENC_RETURN_UNSUPPORTED_PARA;
   }
   for (i = 0; i < pCfg->iSpatialLayerNum; ++ i) {
@@ -89,13 +89,13 @@
     if (fDlp->fOutputFrameRate > fDlp->fInputFrameRate || (fDlp->fInputFrameRate >= -fEpsn
         && fDlp->fInputFrameRate <= fEpsn)
         || (fDlp->fOutputFrameRate >= -fEpsn && fDlp->fOutputFrameRate <= fEpsn)) {
-      WelsLog (NULL, WELS_LOG_ERROR,
+      WelsLog (pLogCtx, WELS_LOG_ERROR,
                "Invalid settings in input frame rate(%.6f) or output frame rate(%.6f) of layer #%d config file..\n",
                fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i);
       return ENC_RETURN_INVALIDINPUT;
     }
     if (UINT_MAX == GetLogFactor (fDlp->fOutputFrameRate, fDlp->fInputFrameRate)) {
-      WelsLog (NULL, WELS_LOG_ERROR,
+      WelsLog (pLogCtx, WELS_LOG_ERROR,
                "Invalid settings in input frame rate(%.6f) and output frame rate(%.6f) of layer #%d config file: iResult of output frame rate divided by input frame rate should be power of 2(i.e,in/pOut=2^n)..\n",
                fDlp->fInputFrameRate, fDlp->fOutputFrameRate, i);
       return ENC_RETURN_INVALIDINPUT;
@@ -121,7 +121,7 @@
       iTotalBitrate += fDlp->iSpatialBitrate;
     }
     if (iTotalBitrate > pCfg->iTargetBitrate) {
-      WelsLog (NULL, WELS_LOG_ERROR,
+      WelsLog (pLogCtx, WELS_LOG_ERROR,
                "Invalid settings in bitrate. the sum of each layer bitrate(%d) is larger than total bitrate setting(%d)\n",
                iTotalBitrate, pCfg->iTargetBitrate);
     }
@@ -131,7 +131,7 @@
 }
 
 
-int32_t ParamValidationExt (sWelsEncCtx* pCtx, SWelsSvcCodingParam* pCodingParam) {
+int32_t ParamValidationExt (SLogContext* pCtx, SWelsSvcCodingParam* pCodingParam) {
   int8_t i = 0;
   int32_t iIdx = 0;
 
@@ -383,7 +383,7 @@
     }
   }
 
-  return ParamValidation (pCodingParam);
+  return ParamValidation (pCtx, pCodingParam);
 }
 
 
@@ -412,7 +412,7 @@
 }
 
 
-void WelsEncoderApplyBitRate (SWelsSvcCodingParam* pParam, int iLayer) {
+void WelsEncoderApplyBitRate (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int iLayer) {
   //TODO (Sijia):  this is a temporary solution which keep the ratio between layers
   //but it is also possible to fulfill the bitrate of lower layer first
 
@@ -421,7 +421,7 @@
   int32_t i, iOrigTotalBitrate = 0;
   if (iLayer == SPATIAL_LAYER_ALL) {
     if (pParam->iMaxBitrate < pParam->iTargetBitrate) {
-      WelsLog (NULL, WELS_LOG_WARNING,
+      WelsLog (pLogCtx, WELS_LOG_WARNING,
                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE,overall settting,TargetBitrate = %d,iMaxBitrate = %d\n",
                pParam->iTargetBitrate, pParam->iMaxBitrate);
       pParam->iMaxBitrate  = pParam->iTargetBitrate;
@@ -439,7 +439,7 @@
     }
   } else {
     if (pParam->sSpatialLayers[iLayer].iMaxSpatialBitrate < pParam->sSpatialLayers[iLayer].iSpatialBitrate) {
-      WelsLog (NULL, WELS_LOG_WARNING,
+      WelsLog (pLogCtx, WELS_LOG_WARNING,
                "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE,iLayer = %d,iTargetBitrate = %d,iMaxBitrate = %d\n",
                iLayer, pParam->sSpatialLayers[iLayer].iSpatialBitrate, pParam->sSpatialLayers[iLayer].iMaxSpatialBitrate);
       pParam->sSpatialLayers[iLayer].iMaxSpatialBitrate = pParam->sSpatialLayers[iLayer].iSpatialBitrate;
@@ -1723,7 +1723,7 @@
 #endif//MEMORY_MONITOR
 
     if ((*ppCtx)->pMemAlign != NULL) {
-      WelsLog (NULL, WELS_LOG_INFO, "FreeMemorySvc(), verify memory usage (%d bytes) after free..\n",
+      WelsLog (*ppCtx, WELS_LOG_INFO, "FreeMemorySvc(), verify memory usage (%d bytes) after free..\n",
                (*ppCtx)->pMemAlign->WelsGetMemoryUsage());
       delete (*ppCtx)->pMemAlign;
       (*ppCtx)->pMemAlign = NULL;
@@ -1734,7 +1734,8 @@
   }
 }
 
-int32_t InitSliceSettings (SWelsSvcCodingParam* pCodingParam, const int32_t kiCpuCores, int16_t* pMaxSliceCount) {
+int32_t InitSliceSettings (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingParam, const int32_t kiCpuCores,
+                           int16_t* pMaxSliceCount) {
   int32_t iSpatialIdx = 0, iSpatialNum = pCodingParam->iSpatialLayerNum;
   uint16_t iMaxSliceCount = 0;
 
@@ -1784,7 +1785,7 @@
         pDlp->sSliceCfg.sSliceArgument.uiSliceNum = iMaxSliceCount;
       }
       if (pDlp->sSliceCfg.sSliceArgument.uiSliceNum == 1) {
-        WelsLog (NULL, WELS_LOG_DEBUG,
+        WelsLog (pLogCtx, WELS_LOG_DEBUG,
                  "InitSliceSettings(), uiSliceNum(%d) you set for SM_AUTO_SLICE, now turn to SM_SINGLE_SLICE type!\n",
                  pDlp->sSliceCfg.sSliceArgument.uiSliceNum);
         pDlp->sSliceCfg.uiSliceMode	= SM_SINGLE_SLICE;
@@ -1799,7 +1800,7 @@
       } else if (!CheckFixedSliceNumMultiSliceSetting (kiMbNumInFrame,
                  &pDlp->sSliceCfg.sSliceArgument)) {	// verify interleave mode settings
         //check uiSliceMbNum with current uiSliceNum
-        WelsLog (NULL, WELS_LOG_ERROR,
+        WelsLog (pLogCtx, WELS_LOG_ERROR,
                  "InitSliceSettings(), invalid uiSliceMbNum (%d) settings!,now turn to SM_SINGLE_SLICE type\n",
                  pDlp->sSliceCfg.sSliceArgument.uiSliceMbNum[0]);
         pDlp->sSliceCfg.uiSliceMode	= SM_SINGLE_SLICE;
@@ -1838,9 +1839,10 @@
 /*!
  * \brief	log output for cpu features/capabilities
  */
-void OutputCpuFeaturesLog (uint32_t uiCpuFeatureFlags, uint32_t uiCpuCores, int32_t iCacheLineSize) {
+void OutputCpuFeaturesLog (SLogContext* pLogCtx, uint32_t uiCpuFeatureFlags, uint32_t uiCpuCores,
+                           int32_t iCacheLineSize) {
   // welstracer output
-  WelsLog (NULL, WELS_LOG_INFO, "WELS CPU features/capacities (0x%x) detected: \t"	\
+  WelsLog (pLogCtx, WELS_LOG_INFO, "WELS CPU features/capacities (0x%x) detected: \t"	\
            "HTT:      %c, "	\
            "MMX:      %c, "	\
            "MMXEX:    %c, "	\
@@ -1890,7 +1892,7 @@
  * \pParam	pParam		SWelsSvcCodingParam*
  * \return	successful - 0; otherwise none 0 for failed
  */
-int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingParam) {
+int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingParam, SLogContext* pLogCtx) {
   sWelsEncCtx* pCtx		= NULL;
   int32_t	iRet					= 0;
   uint32_t uiCpuFeatureFlags		= 0;	// CPU features
@@ -1900,14 +1902,14 @@
   int16_t iSliceNum				= 1;	// number of slices used
 
   if (NULL == ppCtx || NULL == pCodingParam) {
-    WelsLog (NULL, WELS_LOG_ERROR, "WelsInitEncoderExt(), NULL == ppCtx(0x%p) or NULL == pCodingParam(0x%p).\n",
+    WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), NULL == ppCtx(0x%p) or NULL == pCodingParam(0x%p).\n",
              (void*)ppCtx, (void*)pCodingParam);
     return 1;
   }
 
-  iRet	=	ParamValidationExt (*ppCtx, pCodingParam);
+  iRet	=	ParamValidationExt (pLogCtx, pCodingParam);
   if (iRet != 0) {
-    WelsLog (NULL, WELS_LOG_ERROR, "WelsInitEncoderExt(), ParamValidationExt failed return %d.\n", iRet);
+    WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), ParamValidationExt failed return %d.\n", iRet);
     return iRet;
   }
 
@@ -1922,7 +1924,7 @@
     iCacheLineSize	= 32;
   else if (uiCpuFeatureFlags & WELS_CPU_CACHELINE_16)
     iCacheLineSize	= 16;
-  OutputCpuFeaturesLog (uiCpuFeatureFlags, uiCpuCores, iCacheLineSize);
+  OutputCpuFeaturesLog (pLogCtx, uiCpuFeatureFlags, uiCpuCores, iCacheLineSize);
 #else
   iCacheLineSize	= 16;	// 16 bytes aligned in default
 #endif//X86_ASM
@@ -1953,8 +1955,8 @@
 
   uiCpuCores	= WELS_CLIP3 (uiCpuCores, 1, MAX_THREADS_NUM);
 
-  if (InitSliceSettings (pCodingParam, uiCpuCores, &iSliceNum)) {
-    WelsLog (NULL, WELS_LOG_ERROR, "WelsInitEncoderExt(), InitSliceSettings failed.\n");
+  if (InitSliceSettings (pLogCtx, pCodingParam, uiCpuCores, &iSliceNum)) {
+    WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), InitSliceSettings failed.\n");
     return 1;
   }
 
@@ -1965,6 +1967,8 @@
   WELS_VERIFY_RETURN_IF (1, (NULL == pCtx))
   memset (pCtx, 0, sizeof (sWelsEncCtx));
 
+  pCtx->sLogCtx = *pLogCtx;
+
   pCtx->pMemAlign = new CMemoryAlign (iCacheLineSize);
   WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pCtx->pMemAlign), FreeMemorySvc (&pCtx))
 
@@ -3133,7 +3137,8 @@
 
           pCtx->iActiveThreadsNum	= iSliceCount;
           // to fire slice coding threads
-          iRet = FiredSliceThreads (&pCtx->pSliceThreading->pThreadPEncCtx[0], &pCtx->pSliceThreading->pReadySliceCodingEvent[0],
+          iRet = FiredSliceThreads (pCtx, &pCtx->pSliceThreading->pThreadPEncCtx[0],
+                                    &pCtx->pSliceThreading->pReadySliceCodingEvent[0],
                                     &pCtx->pSliceThreading->pThreadMasterEvent[0],
                                     pLayerBsInfo, iSliceCount, pCtx->pCurDqLayer->pSliceEncCtx, false);
           if (iRet) {
@@ -3172,7 +3177,8 @@
           iNumThreadsScheduled	= pCtx->iActiveThreadsNum;
           iNumThreadsRunning		= iNumThreadsScheduled;
           // to fire slice coding threads
-          iRet = FiredSliceThreads (&pCtx->pSliceThreading->pThreadPEncCtx[0], &pCtx->pSliceThreading->pReadySliceCodingEvent[0],
+          iRet = FiredSliceThreads (pCtx, &pCtx->pSliceThreading->pThreadPEncCtx[0],
+                                    &pCtx->pSliceThreading->pReadySliceCodingEvent[0],
                                     &pCtx->pSliceThreading->pThreadMasterEvent[0],
                                     pLayerBsInfo, iNumThreadsRunning, pCtx->pCurDqLayer->pSliceEncCtx, false);
           if (iRet) {
@@ -3218,7 +3224,8 @@
         const int32_t kiPartitionCnt	= pCtx->iActiveThreadsNum; //pSvcParam->iCountThreadsNum;
 
         // to fire slice coding threads
-        iRet = FiredSliceThreads (&pCtx->pSliceThreading->pThreadPEncCtx[0], &pCtx->pSliceThreading->pReadySliceCodingEvent[0],
+        iRet = FiredSliceThreads (pCtx, &pCtx->pSliceThreading->pThreadPEncCtx[0],
+                                  &pCtx->pSliceThreading->pReadySliceCodingEvent[0],
                                   &pCtx->pSliceThreading->pThreadMasterEvent[0],
                                   pLayerBsInfo, kiPartitionCnt, pCtx->pCurDqLayer->pSliceEncCtx, true);
         if (iRet) {
@@ -3509,7 +3516,7 @@
   if (NULL == ppCtx || NULL == *ppCtx || NULL == pNewParam)	return 1;
 
   /* Check validation in new parameters */
-  iReturn	= ParamValidationExt (*ppCtx, pNewParam);
+  iReturn	= ParamValidationExt (& (*ppCtx)->sLogCtx, pNewParam);
   if (iReturn != ENC_RETURN_SUCCESS)	return iReturn;
 
   pOldParam	= (*ppCtx)->pSvcParam;
@@ -3574,6 +3581,7 @@
   if (bNeedReset) {
     SParaSetOffsetVariable sTmpPsoVariable[PARA_SET_TYPE];
     uint16_t	          uiTmpIdrPicId;//this is for LTR!
+    SLogContext sLogCtx = (*ppCtx)->sLogCtx;
     memcpy (sTmpPsoVariable, (*ppCtx)->sPSOVector.sParaSetOffsetVariable,
             (PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
     uiTmpIdrPicId = (*ppCtx)->sPSOVector.uiIdrPicId;
@@ -3581,7 +3589,7 @@
     WelsUninitEncoderExt (ppCtx);
 
     /* Update new parameters */
-    if (WelsInitEncoderExt (ppCtx, pNewParam))
+    if (WelsInitEncoderExt (ppCtx, pNewParam, &sLogCtx))
       return 1;
 
     // reset the scaled spatial picture size
--- a/codec/encoder/core/src/slice_multi_threading.cpp
+++ b/codec/encoder/core/src/slice_multi_threading.cpp
@@ -968,8 +968,8 @@
   return 0;
 }
 
-int32_t FiredSliceThreads (SSliceThreadPrivateData* pPriData, WELS_EVENT* pEventsList, WELS_EVENT* pMasterEventsList,
-                           SLayerBSInfo* pLbi,
+int32_t FiredSliceThreads (sWelsEncCtx* pCtx, SSliceThreadPrivateData* pPriData, WELS_EVENT* pEventsList,
+                           WELS_EVENT* pMasterEventsList, SLayerBSInfo* pLbi,
                            const uint32_t uiNumThreads, SSliceCtx* pSliceCtx, const bool bIsDynamicSlicingMode) {
   int32_t iEndMbIdx	= 0;
   int32_t iIdx		= 0;
@@ -976,7 +976,7 @@
   const int32_t kiEventCnt = uiNumThreads;
 
   if (pPriData == NULL || pLbi == NULL || kiEventCnt <= 0 || pEventsList == NULL) {
-    WelsLog (NULL, WELS_LOG_ERROR,
+    WelsLog (pCtx, WELS_LOG_ERROR,
              "FiredSliceThreads(), fail due pPriData == %p || pLbi == %p || iEventCnt(%d) <= 0 || pEventsList == %p!!\n",
              (void*)pPriData, (void*)pLbi, uiNumThreads, (void*)pEventsList);
     return 1;
--- a/codec/encoder/plus/src/welsEncoderExt.cpp
+++ b/codec/encoder/plus/src/welsEncoderExt.cpp
@@ -131,17 +131,15 @@
 }
 
 CWelsH264SVCEncoder::~CWelsH264SVCEncoder() {
-  WelsLog (NULL, WELS_LOG_INFO, "CWelsH264SVCEncoder::~CWelsH264SVCEncoder()\n");
+  if (m_pWelsTrace) {
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsH264SVCEncoder::~CWelsH264SVCEncoder()\n");
 
-  if (m_pWelsTrace != NULL) {
-    delete m_pWelsTrace;
-    m_pWelsTrace = NULL;
-  }
 #ifdef REC_FRAME_COUNT
-  WelsLog (m_pEncContext, WELS_LOG_INFO,
-           "CWelsH264SVCEncoder::~CWelsH264SVCEncoder(), m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum,
-           m_iCspInternal);
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
+             "CWelsH264SVCEncoder::~CWelsH264SVCEncoder(), m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum,
+             m_iCspInternal);
 #endif
+  }
 
 #ifdef REC_FRAME_COUNT
   m_uiCountFrameNum = 0;
@@ -161,20 +159,26 @@
 #endif//OUTPUT_BIT_STREAM
 
   Uninitialize();
+
+  if (m_pWelsTrace) {
+    delete m_pWelsTrace;
+    m_pWelsTrace = NULL;
+  }
 }
 
 void CWelsH264SVCEncoder::InitEncoder (void) {
 
+  m_pWelsTrace	= new welsCodecTrace();
+  if (m_pWelsTrace == NULL) {
+    return;
+  }
+
+  m_pWelsTrace->SetTraceLevel (WELS_LOG_ERROR);
+
 #ifdef REC_FRAME_COUNT
-  WelsLog (m_pEncContext, WELS_LOG_INFO,
+  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
            "CWelsH264SVCEncoder::InitEncoder, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal);
 #endif
-
-  m_pWelsTrace	= new welsCodecTrace();
-  if (m_pWelsTrace != NULL) {
-    m_pWelsTrace->SetTraceLevel (WELS_LOG_ERROR);
-    WelsSetLogCallback (welsCodecTrace::CODEC_TRACE);
-  }
 }
 
 /* Interfaces override from ISVCEncoder */
@@ -188,9 +192,12 @@
  *	SVC Encoder Initialization
  */
 int CWelsH264SVCEncoder::Initialize (const SEncParamBase* argv) {
+  if (m_pWelsTrace == NULL) {
+    return cmMallocMemeError;
+  }
 
   if (NULL == argv) {
-    WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid argv= 0x%p\n",
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid argv= 0x%p\n",
              argv);
     return cmInitParaError;
   }
@@ -198,7 +205,8 @@
   SWelsSvcCodingParam	sConfig;
   // Convert SEncParamBase into WelsSVCParamConfig here..
   if (sConfig.ParamBaseTranscode (*argv)) {
-    WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), parameter_translation failed.\n");
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
+             "CWelsH264SVCEncoder::Initialize(), parameter_translation failed.\n");
     Uninitialize();
     return cmInitParaError;
   }
@@ -207,9 +215,12 @@
 }
 
 int CWelsH264SVCEncoder::InitializeExt (const SEncParamExt* argv) {
+  if (m_pWelsTrace == NULL) {
+    return cmMallocMemeError;
+  }
 
   if (NULL == argv) {
-    WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::InitializeExt(), invalid argv= 0x%p\n",
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::InitializeExt(), invalid argv= 0x%p\n",
              argv);
     return cmInitParaError;
   }
@@ -217,7 +228,8 @@
   SWelsSvcCodingParam	sConfig;
   // Convert SEncParamExt into WelsSVCParamConfig here..
   if (sConfig.ParamTranscode (*argv)) {
-    WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::InitializeExt(), parameter_translation failed.\n");
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
+             "CWelsH264SVCEncoder::InitializeExt(), parameter_translation failed.\n");
     Uninitialize();
     return cmInitParaError;
   }
@@ -227,13 +239,14 @@
 
 int CWelsH264SVCEncoder::InitializeInternal (SWelsSvcCodingParam* pCfg) {
   if (NULL == pCfg) {
-    WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid argv= 0x%p.\n",
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid argv= 0x%p.\n",
              pCfg);
     return cmInitParaError;
   }
 
   if (m_bInitialFlag) {
-    WelsLog (m_pEncContext, WELS_LOG_WARNING, "CWelsH264SVCEncoder::Initialize(), reinitialize, m_bInitialFlag= %d.\n",
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
+             "CWelsH264SVCEncoder::Initialize(), reinitialize, m_bInitialFlag= %d.\n",
              m_bInitialFlag);
     Uninitialize();
   }
@@ -240,9 +253,10 @@
 
 #ifdef REC_FRAME_COUNT
   SWelsSvcCodingParam& sEncodingParam = *pCfg;
-  WelsLog (m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::Initialize, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n",
+  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
+           "CWelsH264SVCEncoder::Initialize, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n",
            m_uiCountFrameNum, m_iCspInternal);
-  WelsLog (m_pEncContext, WELS_LOG_INFO,
+  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
            "coding_param->iPicWidth= %d;coding_param->iPicHeight= %d;coding_param->iTargetBitrate= %d;coding_param->iRCMode= %d;coding_param->iTemporalLayerNum= %d;coding_param->iSpatialLayerNum= %d;coding_param->fFrameRate= %.6ff;coding_param->iInputCsp= %d;coding_param->uiIntraPeriod= %d;coding_param->bEnableSpsPpsIdAddition = %d;coding_param->bPrefixNalAddingCtrl = %d;coding_param->bEnableDenoise= %d;coding_param->bEnableBackgroundDetection= %d;coding_param->bEnableAdaptiveQuant= %d;coding_param->bEnableFrameSkip= %d;coding_param->bEnableCropPic= %d;coding_param->bEnableLongTermReference= %d;coding_param->iLtrMarkPeriod= %d;\n",
            sEncodingParam.iPicWidth,
            sEncodingParam.iPicHeight,
@@ -265,7 +279,7 @@
   int32_t i = 0;
   while (i < sEncodingParam.iSpatialLayerNum) {
     SSpatialLayerConfig* spatial_cfg = &sEncodingParam.sSpatialLayers[i];
-    WelsLog (m_pEncContext, WELS_LOG_INFO,
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
              "coding_param->sSpatialLayers[%d]: .iVideoWidth= %d; .iVideoHeight= %d; .fFrameRate= %.6ff; .iSpatialBitrate= %d; .sSliceCfg.uiSliceMode= %d; .sSliceCfg.sSliceArgument.uiSliceNum= %d; .sSliceCfg.sSliceArgument.uiSliceSizeConstraint= %d;\n",
              i, spatial_cfg->iVideoWidth,
              spatial_cfg->iVideoHeight,
@@ -281,7 +295,8 @@
 
   const int32_t iColorspace = pCfg->iInputCsp;
   if (videoFormatI420 != iColorspace) {
-    WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iInputCsp= %d.\n", iColorspace);
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), invalid iInputCsp= %d.\n",
+             iColorspace);
     Uninitialize();
     return cmInitParaError;
   }
@@ -289,7 +304,7 @@
   // Check valid parameters
   const int32_t iNumOfLayers = pCfg->iSpatialLayerNum;
   if (iNumOfLayers < 1 || iNumOfLayers > MAX_DEPENDENCY_LAYER) {
-    WelsLog (m_pEncContext, WELS_LOG_ERROR,
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
              "CWelsH264SVCEncoder::Initialize(), invalid iSpatialLayerNum= %d, valid at range of [1, %d].\n", iNumOfLayers,
              MAX_DEPENDENCY_LAYER);
     Uninitialize();
@@ -298,7 +313,7 @@
   if (pCfg->iTemporalLayerNum < 1)
     pCfg->iTemporalLayerNum	= 1;
   if (pCfg->iTemporalLayerNum > MAX_TEMPORAL_LEVEL) {
-    WelsLog (m_pEncContext, WELS_LOG_ERROR,
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
              "CWelsH264SVCEncoder::Initialize(), invalid iTemporalLayerNum= %d, valid at range of [1, %d].\n",
              pCfg->iTemporalLayerNum, MAX_TEMPORAL_LEVEL);
     Uninitialize();
@@ -308,7 +323,7 @@
   //	assert( cfg.uiGopSize >= 1 && ( cfg.uiIntraPeriod && (cfg.uiIntraPeriod % cfg.uiGopSize) == 0) );
 
   if (pCfg->uiGopSize < 1 || pCfg->uiGopSize > MAX_GOP_SIZE) {
-    WelsLog (m_pEncContext, WELS_LOG_ERROR,
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
              "CWelsH264SVCEncoder::Initialize(), invalid uiGopSize= %d, valid at range of [1, %d].\n", pCfg->uiGopSize,
              MAX_GOP_SIZE);
     Uninitialize();
@@ -316,7 +331,7 @@
   }
 
   if (!WELS_POWER2_IF (pCfg->uiGopSize)) {
-    WelsLog (m_pEncContext, WELS_LOG_ERROR,
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
              "CWelsH264SVCEncoder::Initialize(), invalid uiGopSize= %d, valid at range of [1, %d] and yield to power of 2.\n",
              pCfg->uiGopSize, MAX_GOP_SIZE);
     Uninitialize();
@@ -324,7 +339,7 @@
   }
 
   if (pCfg->uiIntraPeriod && pCfg->uiIntraPeriod < pCfg->uiGopSize) {
-    WelsLog (m_pEncContext, WELS_LOG_ERROR,
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
              "CWelsH264SVCEncoder::Initialize(), invalid uiIntraPeriod= %d, valid in case it equals to 0 for unlimited intra period or exceeds specified uiGopSize= %d.\n",
              pCfg->uiIntraPeriod, pCfg->uiGopSize);
     Uninitialize();
@@ -332,7 +347,7 @@
   }
 
   if ((pCfg->uiIntraPeriod && (pCfg->uiIntraPeriod & (pCfg->uiGopSize - 1)) != 0)) {
-    WelsLog (m_pEncContext, WELS_LOG_ERROR,
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
              "CWelsH264SVCEncoder::Initialize(), invalid uiIntraPeriod= %d, valid in case it equals to 0 for unlimited intra period or exceeds specified uiGopSize= %d also multiple of it.\n",
              pCfg->uiIntraPeriod, pCfg->uiGopSize);
     Uninitialize();
@@ -371,8 +386,8 @@
   m_iMaxPicWidth	= pCfg->iPicWidth;
   m_iMaxPicHeight	= pCfg->iPicHeight;
 
-  if (WelsInitEncoderExt (&m_pEncContext, pCfg)) {
-    WelsLog (m_pEncContext, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), WelsInitEncoderExt failed.\n");
+  if (WelsInitEncoderExt (&m_pEncContext, pCfg, &m_pWelsTrace->m_sLogCtx)) {
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), WelsInitEncoderExt failed.\n");
     Uninitialize();
     return cmInitParaError;
   }
@@ -391,10 +406,10 @@
     return 0;
   }
 
-  WelsLog (m_pEncContext, WELS_LOG_INFO, "CWelsH264SVCEncoder::Uninitialize()..\n");
+  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsH264SVCEncoder::Uninitialize()..\n");
 
 #ifdef REC_FRAME_COUNT
-  WelsLog (m_pEncContext, WELS_LOG_INFO,
+  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
            "CWelsH264SVCEncoder::Uninitialize, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n", m_uiCountFrameNum, m_iCspInternal);
 #endif//REC_FRAME_COUNT
 
@@ -548,7 +563,8 @@
     return cmInitParaError;
   }
 
-  if (NULL == m_pEncContext || false == m_bInitialFlag) {
+  if ((NULL == m_pEncContext || false == m_bInitialFlag) && eOptionId != ENCODER_OPTION_TRACE_LEVEL
+      && eOptionId != ENCODER_OPTION_TRACE_CALLBACK && eOptionId != ENCODER_OPTION_TRACE_CALLBACK_CONTEXT) {
     return cmInitExpected;
   }
 
@@ -734,7 +750,7 @@
       break;
     }
     //adjust to valid range
-    WelsEncoderApplyBitRate (m_pEncContext->pSvcParam, pInfo->iLayer);
+    WelsEncoderApplyBitRate (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, pInfo->iLayer);
   }
   break;
   case ENCODER_OPTION_MAX_BITRATE: {	// Target bit-rate
@@ -775,7 +791,7 @@
       break;
     }
     //adjust to valid range
-    WelsEncoderApplyBitRate (m_pEncContext->pSvcParam, pInfo->iLayer);
+    WelsEncoderApplyBitRate (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, pInfo->iLayer);
   }
   break;
   case ENCODER_OPTION_RC_MODE: {	// 0:quality mode;1:bit-rate mode;2:bitrate limited mode
@@ -853,6 +869,20 @@
     if (m_pWelsTrace) {
       uint32_t level = * ((uint32_t*)pOption);
       m_pWelsTrace->SetTraceLevel (level);
+    }
+  }
+  break;
+  case ENCODER_OPTION_TRACE_CALLBACK: {
+    if (m_pWelsTrace) {
+      CM_WELS_TRACE callback = * ((CM_WELS_TRACE*)pOption);
+      m_pWelsTrace->SetTraceCallback (callback);
+    }
+  }
+  break;
+  case ENCODER_OPTION_TRACE_CALLBACK_CONTEXT: {
+    if (m_pWelsTrace) {
+      void* ctx = * ((void**)pOption);
+      m_pWelsTrace->SetTraceCallbackContext (ctx);
     }
   }
   break;