Classes | Macros | Typedefs | Enumerations | Functions | Variables
lz4frame.c File Reference
#include <stdlib.h>
#include <string.h>
#include "lz4frame_static.h"
#include "lz4.h"
#include "lz4hc.h"
#include "xxhash.h"
Include dependency graph for lz4frame.c:

Go to the source code of this file.

Classes

struct  LZ4F_cctx_s
 
struct  LZ4F_dctx_s
 

Macros

#define _1BIT   0x01
 
#define _2BITS   0x03
 
#define _3BITS   0x07
 
#define _4BITS   0x0F
 
#define _8BITS   0xFF
 
#define ALLOCATOR(s)   calloc(1,s)
 
#define FREEMEM   free
 
#define GB   *(1<<30)
 
#define KB   *(1<<10)
 
#define LZ4_STATIC_ASSERT(c)   { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
 
#define LZ4F_BLOCKSIZEID_DEFAULT   LZ4F_max64KB
 
#define LZ4F_BLOCKUNCOMPRESSED_FLAG   0x80000000U
 
#define LZ4F_GENERATE_STRING(STRING)   #STRING,
 
#define LZ4F_MAGIC_SKIPPABLE_START   0x184D2A50U
 
#define LZ4F_MAGICNUMBER   0x184D2204U
 
#define MB   *(1<<20)
 
#define MEM_INIT   memset
 
#define MIN(a, b)   ( (a) < (b) ? (a) : (b) )
 
#define XXH_STATIC_LINKING_ONLY
 

Typedefs

typedef unsigned char BYTE
 
typedef int(* compressFunc_t) (void *ctx, const char *src, char *dst, int srcSize, int dstSize, int level)
 
typedef struct LZ4F_cctx_s LZ4F_cctx_t
 
typedef signed int S32
 
typedef unsigned short U16
 
typedef unsigned int U32
 
typedef unsigned long long U64
 

Enumerations

enum  dStage_t {
  dstage_getHeader =0, dstage_storeHeader, dstage_init, dstage_getCBlockSize,
  dstage_storeCBlockSize, dstage_copyDirect, dstage_getCBlock, dstage_storeCBlock,
  dstage_decodeCBlock, dstage_decodeCBlock_intoDst, dstage_decodeCBlock_intoTmp, dstage_flushOut,
  dstage_getSuffix, dstage_storeSuffix, dstage_getSFrameSize, dstage_storeSFrameSize,
  dstage_skipSkippable
}
 
enum  LZ4F_lastBlockStatus { notDone, fromTmpBuffer, fromSrcBuffer }
 

Functions

static LZ4F_errorCode_t err0r (LZ4F_errorCodes code)
 
size_t LZ4F_compressBegin (LZ4F_cctx *cctxPtr, void *dstBuffer, size_t dstCapacity, const LZ4F_preferences_t *preferencesPtr)
 
static size_t LZ4F_compressBlock (void *dst, const void *src, size_t srcSize, compressFunc_t compress, void *lz4ctx, int level)
 
size_t LZ4F_compressBound (size_t srcSize, const LZ4F_preferences_t *preferencesPtr)
 
static size_t LZ4F_compressBound_internal (size_t srcSize, const LZ4F_preferences_t *preferencesPtr, size_t alreadyBuffered)
 
size_t LZ4F_compressEnd (LZ4F_cctx *cctxPtr, void *dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t *compressOptionsPtr)
 
size_t LZ4F_compressFrame (void *dstBuffer, size_t dstCapacity, const void *srcBuffer, size_t srcSize, const LZ4F_preferences_t *preferencesPtr)
 
size_t LZ4F_compressFrameBound (size_t srcSize, const LZ4F_preferences_t *preferencesPtr)
 
size_t LZ4F_compressUpdate (LZ4F_cctx *cctxPtr, void *dstBuffer, size_t dstCapacity, const void *srcBuffer, size_t srcSize, const LZ4F_compressOptions_t *compressOptionsPtr)
 
LZ4F_errorCode_t LZ4F_createCompressionContext (LZ4F_compressionContext_t *LZ4F_compressionContextPtr, unsigned version)
 
LZ4F_errorCode_t LZ4F_createDecompressionContext (LZ4F_dctx **LZ4F_decompressionContextPtr, unsigned versionNumber)
 
static size_t LZ4F_decodeHeader (LZ4F_dctx *dctxPtr, const void *src, size_t srcSize)
 
size_t LZ4F_decompress (LZ4F_dctx *dctxPtr, void *dstBuffer, size_t *dstSizePtr, const void *srcBuffer, size_t *srcSizePtr, const LZ4F_decompressOptions_t *decompressOptionsPtr)
 
static int LZ4F_decompress_safe (const char *src, char *dst, int compressedSize, int dstCapacity, const char *dictStart, int dictSize)
 
size_t LZ4F_flush (LZ4F_cctx *cctxPtr, void *dstBuffer, size_t dstCapacity, const LZ4F_compressOptions_t *compressOptionsPtr)
 
LZ4F_errorCode_t LZ4F_freeCompressionContext (LZ4F_compressionContext_t LZ4F_compressionContext)
 
LZ4F_errorCode_t LZ4F_freeDecompressionContext (LZ4F_dctx *dctxPtr)
 
static size_t LZ4F_getBlockSize (unsigned blockSizeID)
 
LZ4F_errorCodes LZ4F_getErrorCode (size_t functionResult)
 
const char * LZ4F_getErrorName (LZ4F_errorCode_t code)
 
LZ4F_errorCode_t LZ4F_getFrameInfo (LZ4F_dctx *dctxPtr, LZ4F_frameInfo_t *frameInfoPtr, const void *srcBuffer, size_t *srcSizePtr)
 
unsigned LZ4F_getVersion (void)
 
static BYTE LZ4F_headerChecksum (const void *header, size_t length)
 
static size_t LZ4F_headerSize (const void *src, size_t srcSize)
 
unsigned LZ4F_isError (LZ4F_errorCode_t code)
 
static int LZ4F_localLZ4_compress_limitedOutput_continue (void *ctx, const char *src, char *dst, int srcSize, int dstCapacity, int level)
 
static int LZ4F_localLZ4_compress_limitedOutput_withState (void *ctx, const char *src, char *dst, int srcSize, int dstCapacity, int level)
 
static int LZ4F_localLZ4_compressHC_limitedOutput_continue (void *ctx, const char *src, char *dst, int srcSize, int dstSize, int level)
 
static int LZ4F_localSaveDict (LZ4F_cctx_t *cctxPtr)
 
static LZ4F_blockSizeID_t LZ4F_optimalBSID (const LZ4F_blockSizeID_t requestedBSID, const size_t srcSize)
 
static U32 LZ4F_readLE32 (const void *src)
 
static U64 LZ4F_readLE64 (const void *src)
 
void LZ4F_resetDecompressionContext (LZ4F_dctx *dctx)
 
static compressFunc_t LZ4F_selectCompression (LZ4F_blockMode_t blockMode, int level)
 
static void LZ4F_updateDict (LZ4F_dctx *dctxPtr, const BYTE *dstPtr, size_t dstSize, const BYTE *dstPtr0, unsigned withinTmp)
 
static void LZ4F_writeLE32 (void *dst, U32 value32)
 
static void LZ4F_writeLE64 (void *dst, U64 value64)
 

Variables

static const size_t BHSize = 4
 
static const char * LZ4F_errorStrings [] = { LZ4F_LIST_ERRORS(LZ4F_GENERATE_STRING) }
 
static const size_t maxFHSize = LZ4F_HEADER_SIZE_MAX
 
static const size_t minFHSize = 7
 

Macro Definition Documentation

#define _1BIT   0x01

Definition at line 149 of file lz4frame.c.

#define _2BITS   0x03

Definition at line 150 of file lz4frame.c.

#define _3BITS   0x07

Definition at line 151 of file lz4frame.c.

#define _4BITS   0x0F

Definition at line 152 of file lz4frame.c.

#define _8BITS   0xFF

Definition at line 153 of file lz4frame.c.

#define ALLOCATOR (   s)    calloc(1,s)

Definition at line 53 of file lz4frame.c.

#define FREEMEM   free

Definition at line 54 of file lz4frame.c.

#define GB   *(1<<30)

Definition at line 147 of file lz4frame.c.

#define KB   *(1<<10)

Definition at line 145 of file lz4frame.c.

#define LZ4_STATIC_ASSERT (   c)    { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */

Definition at line 72 of file lz4frame.c.

#define LZ4F_BLOCKSIZEID_DEFAULT   LZ4F_max64KB

Definition at line 158 of file lz4frame.c.

#define LZ4F_BLOCKUNCOMPRESSED_FLAG   0x80000000U

Definition at line 157 of file lz4frame.c.

#define LZ4F_GENERATE_STRING (   STRING)    #STRING,

Definition at line 188 of file lz4frame.c.

#define LZ4F_MAGIC_SKIPPABLE_START   0x184D2A50U

Definition at line 155 of file lz4frame.c.

#define LZ4F_MAGICNUMBER   0x184D2204U

Definition at line 156 of file lz4frame.c.

#define MB   *(1<<20)

Definition at line 146 of file lz4frame.c.

#define MEM_INIT   memset

Definition at line 56 of file lz4frame.c.

#define MIN (   a,
  b 
)    ( (a) < (b) ? (a) : (b) )

Definition at line 223 of file lz4frame.c.

#define XXH_STATIC_LINKING_ONLY

Definition at line 65 of file lz4frame.c.

Typedef Documentation

typedef unsigned char BYTE

Definition at line 86 of file lz4frame.c.

typedef int(* compressFunc_t) (void *ctx, const char *src, char *dst, int srcSize, int dstSize, int level)

Definition at line 505 of file lz4frame.c.

typedef struct LZ4F_cctx_s LZ4F_cctx_t
typedef signed int S32

Definition at line 89 of file lz4frame.c.

typedef unsigned short U16

Definition at line 87 of file lz4frame.c.

typedef unsigned int U32

Definition at line 88 of file lz4frame.c.

typedef unsigned long long U64

Definition at line 90 of file lz4frame.c.

Enumeration Type Documentation

enum dStage_t
Enumerator
dstage_getHeader 
dstage_storeHeader 
dstage_init 
dstage_getCBlockSize 
dstage_storeCBlockSize 
dstage_copyDirect 
dstage_getCBlock 
dstage_storeCBlock 
dstage_decodeCBlock 
dstage_decodeCBlock_intoDst 
dstage_decodeCBlock_intoTmp 
dstage_flushOut 
dstage_getSuffix 
dstage_storeSuffix 
dstage_getSFrameSize 
dstage_storeSFrameSize 
dstage_skipSkippable 

Definition at line 788 of file lz4frame.c.

Enumerator
notDone 
fromTmpBuffer 
fromSrcBuffer 

Definition at line 557 of file lz4frame.c.

Function Documentation

static LZ4F_errorCode_t err0r ( LZ4F_errorCodes  code)
static

Definition at line 210 of file lz4frame.c.

size_t LZ4F_compressBegin ( LZ4F_cctx cctxPtr,
void dstBuffer,
size_t  dstCapacity,
const LZ4F_preferences_t preferencesPtr 
)

LZ4F_compressBegin() : will write the frame header into dstBuffer. dstBuffer must be large enough to accommodate a header (dstCapacity). Maximum header size is LZ4F_HEADER_SIZE_MAX bytes.

Returns
: number of bytes written into dstBuffer for the header or an error code (can be tested using LZ4F_isError())

Definition at line 416 of file lz4frame.c.

static size_t LZ4F_compressBlock ( void dst,
const void src,
size_t  srcSize,
compressFunc_t  compress,
void lz4ctx,
int  level 
)
static

Definition at line 507 of file lz4frame.c.

size_t LZ4F_compressBound ( size_t  srcSize,
const LZ4F_preferences_t prefsPtr 
)

LZ4F_compressBound() : Provides dstCapacity given a srcSize to guarantee operation success in worst case situations. prefsPtr is optional : you can provide NULL as argument, preferences will be set to cover worst case scenario. Result is always the same for a srcSize and prefsPtr, so it can be trusted to size reusable buffers. When srcSize==0, LZ4F_compressBound() provides an upper bound for LZ4F_flush() and LZ4F_compressEnd() operations.

Definition at line 499 of file lz4frame.c.

static size_t LZ4F_compressBound_internal ( size_t  srcSize,
const LZ4F_preferences_t preferencesPtr,
size_t  alreadyBuffered 
)
static

Definition at line 265 of file lz4frame.c.

size_t LZ4F_compressEnd ( LZ4F_cctx cctxPtr,
void dstBuffer,
size_t  dstMaxSize,
const LZ4F_compressOptions_t compressOptionsPtr 
)

LZ4F_compressEnd() : When you want to properly finish the compressed frame, just call LZ4F_compressEnd(). It will flush whatever data remained within compressionContext (like LZ4_flush()) but also properly finalize the frame, with an endMark and a checksum. The result of the function is the number of bytes written into dstBuffer (necessarily >= 4 (endMark size)) The function outputs an error code if it fails (can be tested using LZ4F_isError()) The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument. compressionContext can then be used again, starting with LZ4F_compressBegin(). The preferences will remain the same.

Definition at line 702 of file lz4frame.c.

size_t LZ4F_compressFrame ( void dstBuffer,
size_t  dstCapacity,
const void srcBuffer,
size_t  srcSize,
const LZ4F_preferences_t preferencesPtr 
)

LZ4F_compressFrame() : Compress an entire srcBuffer into a valid LZ4 frame, as defined by specification v1.5.0, in a single step. The most important rule is that dstBuffer MUST be large enough (dstCapacity) to ensure compression completion even in worst case. If this condition is not respected, LZ4F_compressFrame() will fail (result is an errorCode) Get the minimum value of dstCapacity by using LZ4F_compressFrameBound(). The LZ4F_preferences_t structure is optional : if NULL is provided as argument, preferences will be set to default. The result of the function is the number of bytes written into dstBuffer. The function outputs an error code if it fails (can be tested using LZ4F_isError())

Definition at line 313 of file lz4frame.c.

size_t LZ4F_compressFrameBound ( size_t  srcSize,
const LZ4F_preferences_t preferencesPtr 
)

LZ4F_compressFrameBound() : Returns the maximum possible size of a frame compressed with LZ4F_compressFrame() given srcSize content and preferences. Note : this result is only usable with LZ4F_compressFrame(), not with multi-segments compression.

Definition at line 291 of file lz4frame.c.

size_t LZ4F_compressUpdate ( LZ4F_cctx cctxPtr,
void dstBuffer,
size_t  dstCapacity,
const void srcBuffer,
size_t  srcSize,
const LZ4F_compressOptions_t compressOptionsPtr 
)

LZ4F_compressUpdate() : LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary. The most important rule is that dstBuffer MUST be large enough (dstCapacity) to ensure compression completion even in worst case. If this condition is not respected, LZ4F_compress() will fail (result is an errorCode) You can get the minimum value of dstCapacity by using LZ4F_compressBound() The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument. The result of the function is the number of bytes written into dstBuffer : it can be zero, meaning input data was just buffered. The function outputs an error code if it fails (can be tested using LZ4F_isError())

Definition at line 568 of file lz4frame.c.

LZ4F_errorCode_t LZ4F_createCompressionContext ( LZ4F_compressionContext_t LZ4F_compressionContextPtr,
unsigned  version 
)

LZ4F_createCompressionContext() : The first thing to do is to create a compressionContext object, which will be used in all compression operations. This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure. The version provided MUST be LZ4F_VERSION. It is intended to track potential version differences between different binaries. The function will provide a pointer to an allocated LZ4F_compressionContext_t object. If the result LZ4F_errorCode_t is not OK_NoError, there was an error during context creation. Object can release its memory using LZ4F_freeCompressionContext();

Definition at line 382 of file lz4frame.c.

LZ4F_errorCode_t LZ4F_createDecompressionContext ( LZ4F_dctx **  LZ4F_decompressionContextPtr,
unsigned  versionNumber 
)

LZ4F_createDecompressionContext() : Create a decompressionContext object, which will track all decompression operations. Provides a pointer to a fully allocated and initialized LZ4F_decompressionContext object. Object can later be released using LZ4F_freeDecompressionContext().

Returns
: if != 0, there was an error during context creation.

Definition at line 763 of file lz4frame.c.

static size_t LZ4F_decodeHeader ( LZ4F_dctx dctxPtr,
const void src,
size_t  srcSize 
)
static

LZ4F_decodeHeader() : input : src points at the beginning of the frame output : set internal values of dctx, such as dctxPtr->frameInfo and dctxPtr->dStage. Also allocates internal buffers.

Returns
: nb Bytes read from src (necessarily <= srcSize) or an error code (testable with LZ4F_isError())

Definition at line 838 of file lz4frame.c.

size_t LZ4F_decompress ( LZ4F_dctx dctxPtr,
void dstBuffer,
size_t dstSizePtr,
const void srcBuffer,
size_t srcSizePtr,
const LZ4F_decompressOptions_t decompressOptionsPtr 
)

LZ4F_decompress() : Call this function repetitively to regenerate data compressed within srcBuffer. The function will attempt to decode up to *srcSizePtr bytes from srcBuffer, into dstBuffer of capacity *dstSizePtr.

The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).

The number of bytes effectively read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value). If the number of bytes read is < number of bytes provided, then the decompression operation is not complete. Remaining data will have to be presented again in a subsequent invocation.

The function result is an hint of the better srcSize to use for next call to LZ4F_decompress. Basically, it's the size of the current (or remaining) compressed block + header of next block. Respecting the hint provides some boost to performance, since it allows less buffer shuffling. Note that this is just a hint, it's always possible to any srcSize value. When a frame is fully decoded,

Returns
will be 0. If decompression failed,
is an error code which can be tested using LZ4F_isError().

Definition at line 1059 of file lz4frame.c.

static int LZ4F_decompress_safe ( const char *  src,
char *  dst,
int  compressedSize,
int  dstCapacity,
const char *  dictStart,
int  dictSize 
)
static

Definition at line 971 of file lz4frame.c.

size_t LZ4F_flush ( LZ4F_cctx cctxPtr,
void dstBuffer,
size_t  dstCapacity,
const LZ4F_compressOptions_t compressOptionsPtr 
)

LZ4F_flush() : Should you need to create compressed data immediately, without waiting for a block to be filled, you can call LZ4_flush(), which will immediately compress any remaining data stored within compressionContext. The result of the function is the number of bytes written into dstBuffer (it can be zero, this means there was no data left within compressionContext) The function outputs an error code if it fails (can be tested using LZ4F_isError()) The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.

Definition at line 664 of file lz4frame.c.

LZ4F_errorCode_t LZ4F_freeCompressionContext ( LZ4F_compressionContext_t  LZ4F_compressionContext)

Definition at line 396 of file lz4frame.c.

LZ4F_errorCode_t LZ4F_freeDecompressionContext ( LZ4F_dctx dctxPtr)

Definition at line 773 of file lz4frame.c.

static size_t LZ4F_getBlockSize ( unsigned  blockSizeID)
static

Definition at line 225 of file lz4frame.c.

LZ4F_errorCodes LZ4F_getErrorCode ( size_t  functionResult)

Definition at line 204 of file lz4frame.c.

const char* LZ4F_getErrorName ( LZ4F_errorCode_t  code)

return error code string; useful for debugging

Definition at line 197 of file lz4frame.c.

LZ4F_errorCode_t LZ4F_getFrameInfo ( LZ4F_dctx dctxPtr,
LZ4F_frameInfo_t frameInfoPtr,
const void srcBuffer,
size_t srcSizePtr 
)

LZ4F_getFrameInfo() : This function extracts frame parameters (max blockSize, frame checksum, etc.). Usage is optional. Objective is to provide relevant information for allocation purposes. This function works in 2 situations :

  • At the beginning of a new frame, in which case it will decode this information from srcBuffer, and start the decoding process. Amount of input data provided must be large enough to successfully decode the frame header. A header size is variable, but is guaranteed to be <= LZ4F_HEADER_SIZE_MAX bytes. It's possible to provide more input data than this minimum.
  • After decoding has been started. In which case, no input is read, frame parameters are extracted from dctx. The number of bytes consumed from srcBuffer will be updated within *srcSizePtr (necessarily <= original value). Decompression must resume from (srcBuffer + *srcSizePtr).
    Returns
    : an hint about how many srcSize bytes LZ4F_decompress() expects for next call, or an error code which can be tested using LZ4F_isError() note 1 : in case of error, dctx is not modified. Decoding operations can resume from where they stopped. note 2 : frame parameters are copied into an already allocated LZ4F_frameInfo_t structure.

Definition at line 933 of file lz4frame.c.

unsigned LZ4F_getVersion ( void  )

Definition at line 217 of file lz4frame.c.

static BYTE LZ4F_headerChecksum ( const void header,
size_t  length 
)
static

Definition at line 235 of file lz4frame.c.

static size_t LZ4F_headerSize ( const void src,
size_t  srcSize 
)
static

LZ4F_headerSize() :

Returns
: size of frame header or an error code, which can be tested using LZ4F_isError()

Definition at line 811 of file lz4frame.c.

unsigned LZ4F_isError ( LZ4F_errorCode_t  code)

tells if a LZ4F_errorCode_t function result is an error code

Definition at line 192 of file lz4frame.c.

static int LZ4F_localLZ4_compress_limitedOutput_continue ( void ctx,
const char *  src,
char *  dst,
int  srcSize,
int  dstCapacity,
int  level 
)
static

Definition at line 528 of file lz4frame.c.

static int LZ4F_localLZ4_compress_limitedOutput_withState ( void ctx,
const char *  src,
char *  dst,
int  srcSize,
int  dstCapacity,
int  level 
)
static

Definition at line 522 of file lz4frame.c.

static int LZ4F_localLZ4_compressHC_limitedOutput_continue ( void ctx,
const char *  src,
char *  dst,
int  srcSize,
int  dstSize,
int  level 
)
static

Definition at line 534 of file lz4frame.c.

static int LZ4F_localSaveDict ( LZ4F_cctx_t cctxPtr)
static

Definition at line 550 of file lz4frame.c.

static LZ4F_blockSizeID_t LZ4F_optimalBSID ( const LZ4F_blockSizeID_t  requestedBSID,
const size_t  srcSize 
)
static

Definition at line 245 of file lz4frame.c.

static U32 LZ4F_readLE32 ( const void src)
static

Definition at line 95 of file lz4frame.c.

static U64 LZ4F_readLE64 ( const void src)
static

Definition at line 114 of file lz4frame.c.

void LZ4F_resetDecompressionContext ( LZ4F_dctx dctx)

LZ4F_resetDecompressionContext() : v1.8.0 In case of an error, the context is left in "undefined" state. In which case, it's necessary to reset it, before re-using it. This method can also be used to abruptly stop an unfinished decompression, and start a new one using the same context.

Definition at line 801 of file lz4frame.c.

static compressFunc_t LZ4F_selectCompression ( LZ4F_blockMode_t  blockMode,
int  level 
)
static

Definition at line 540 of file lz4frame.c.

static void LZ4F_updateDict ( LZ4F_dctx dctxPtr,
const BYTE dstPtr,
size_t  dstSize,
const BYTE dstPtr0,
unsigned  withinTmp 
)
static

Definition at line 983 of file lz4frame.c.

static void LZ4F_writeLE32 ( void dst,
U32  value32 
)
static

Definition at line 105 of file lz4frame.c.

static void LZ4F_writeLE64 ( void dst,
U64  value64 
)
static

Definition at line 128 of file lz4frame.c.

Variable Documentation

const size_t BHSize = 4
static

Definition at line 162 of file lz4frame.c.

const char* LZ4F_errorStrings[] = { LZ4F_LIST_ERRORS(LZ4F_GENERATE_STRING) }
static

Definition at line 189 of file lz4frame.c.

const size_t maxFHSize = LZ4F_HEADER_SIZE_MAX
static

Definition at line 161 of file lz4frame.c.

const size_t minFHSize = 7
static

Definition at line 160 of file lz4frame.c.



librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:50:27