1334de520b0369215b7931fefa424fb92d295f0ebJames Dong/* ------------------------------------------------------------------ 2334de520b0369215b7931fefa424fb92d295f0ebJames Dong * Copyright (C) 1998-2009 PacketVideo 3334de520b0369215b7931fefa424fb92d295f0ebJames Dong * 4334de520b0369215b7931fefa424fb92d295f0ebJames Dong * Licensed under the Apache License, Version 2.0 (the "License"); 5334de520b0369215b7931fefa424fb92d295f0ebJames Dong * you may not use this file except in compliance with the License. 6334de520b0369215b7931fefa424fb92d295f0ebJames Dong * You may obtain a copy of the License at 7334de520b0369215b7931fefa424fb92d295f0ebJames Dong * 8334de520b0369215b7931fefa424fb92d295f0ebJames Dong * http://www.apache.org/licenses/LICENSE-2.0 9334de520b0369215b7931fefa424fb92d295f0ebJames Dong * 10334de520b0369215b7931fefa424fb92d295f0ebJames Dong * Unless required by applicable law or agreed to in writing, software 11334de520b0369215b7931fefa424fb92d295f0ebJames Dong * distributed under the License is distributed on an "AS IS" BASIS, 12334de520b0369215b7931fefa424fb92d295f0ebJames Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13334de520b0369215b7931fefa424fb92d295f0ebJames Dong * express or implied. 14334de520b0369215b7931fefa424fb92d295f0ebJames Dong * See the License for the specific language governing permissions 15334de520b0369215b7931fefa424fb92d295f0ebJames Dong * and limitations under the License. 16334de520b0369215b7931fefa424fb92d295f0ebJames Dong * ------------------------------------------------------------------- 17334de520b0369215b7931fefa424fb92d295f0ebJames Dong */ 18334de520b0369215b7931fefa424fb92d295f0ebJames Dong/* 19334de520b0369215b7931fefa424fb92d295f0ebJames Dong * Copyright (c) 2008 The Khronos Group Inc. 20334de520b0369215b7931fefa424fb92d295f0ebJames Dong * 21334de520b0369215b7931fefa424fb92d295f0ebJames Dong * Permission is hereby granted, free of charge, to any person obtaining 22334de520b0369215b7931fefa424fb92d295f0ebJames Dong * a copy of this software and associated documentation files (the 23334de520b0369215b7931fefa424fb92d295f0ebJames Dong * "Software"), to deal in the Software without restriction, including 24334de520b0369215b7931fefa424fb92d295f0ebJames Dong * without limitation the rights to use, copy, modify, merge, publish, 25334de520b0369215b7931fefa424fb92d295f0ebJames Dong * distribute, sublicense, and/or sell copies of the Software, and to 26334de520b0369215b7931fefa424fb92d295f0ebJames Dong * permit persons to whom the Software is furnished to do so, subject 27334de520b0369215b7931fefa424fb92d295f0ebJames Dong * to the following conditions: 28334de520b0369215b7931fefa424fb92d295f0ebJames Dong * The above copyright notice and this permission notice shall be included 29334de520b0369215b7931fefa424fb92d295f0ebJames Dong * in all copies or substantial portions of the Software. 30334de520b0369215b7931fefa424fb92d295f0ebJames Dong * 31334de520b0369215b7931fefa424fb92d295f0ebJames Dong * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 32334de520b0369215b7931fefa424fb92d295f0ebJames Dong * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 33334de520b0369215b7931fefa424fb92d295f0ebJames Dong * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 34334de520b0369215b7931fefa424fb92d295f0ebJames Dong * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 35334de520b0369215b7931fefa424fb92d295f0ebJames Dong * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 36334de520b0369215b7931fefa424fb92d295f0ebJames Dong * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 37334de520b0369215b7931fefa424fb92d295f0ebJames Dong * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 38334de520b0369215b7931fefa424fb92d295f0ebJames Dong * 39334de520b0369215b7931fefa424fb92d295f0ebJames Dong */ 40334de520b0369215b7931fefa424fb92d295f0ebJames Dong 41334de520b0369215b7931fefa424fb92d295f0ebJames Dong/** OMX_ContentPipe.h - OpenMax IL version 1.1.2 42334de520b0369215b7931fefa424fb92d295f0ebJames Dong * The OMX_ContentPipe header file contains the definitions used to define 43334de520b0369215b7931fefa424fb92d295f0ebJames Dong * the public interface for content piples. This header file is intended to 44334de520b0369215b7931fefa424fb92d295f0ebJames Dong * be used by the component. 45334de520b0369215b7931fefa424fb92d295f0ebJames Dong */ 46334de520b0369215b7931fefa424fb92d295f0ebJames Dong 47334de520b0369215b7931fefa424fb92d295f0ebJames Dong#ifndef OMX_CONTENTPIPE_H 48334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define OMX_CONTENTPIPE_H 49334de520b0369215b7931fefa424fb92d295f0ebJames Dong 50334de520b0369215b7931fefa424fb92d295f0ebJames Dong#ifndef KD_EACCES 51334de520b0369215b7931fefa424fb92d295f0ebJames Dong/* OpenKODE error codes. CPResult values may be zero (indicating success 52334de520b0369215b7931fefa424fb92d295f0ebJames Dong or one of the following values) */ 53334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EACCES (1) 54334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EADDRINUSE (2) 55334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EAGAIN (5) 56334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EBADF (7) 57334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EBUSY (8) 58334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_ECONNREFUSED (9) 59334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_ECONNRESET (10) 60334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EDEADLK (11) 61334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EDESTADDRREQ (12) 62334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_ERANGE (35) 63334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EEXIST (13) 64334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EFBIG (14) 65334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EHOSTUNREACH (15) 66334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EINVAL (17) 67334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EIO (18) 68334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EISCONN (20) 69334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EISDIR (21) 70334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EMFILE (22) 71334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_ENAMETOOLONG (23) 72334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_ENOENT (24) 73334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_ENOMEM (25) 74334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_ENOSPC (26) 75334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_ENOSYS (27) 76334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_ENOTCONN (28) 77334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EPERM (33) 78334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_ETIMEDOUT (36) 79334de520b0369215b7931fefa424fb92d295f0ebJames Dong#define KD_EILSEQ (19) 80334de520b0369215b7931fefa424fb92d295f0ebJames Dong#endif 81334de520b0369215b7931fefa424fb92d295f0ebJames Dong 82334de520b0369215b7931fefa424fb92d295f0ebJames Dong/** Map types from OMX standard types only here so interface is as generic as possible. */ 83334de520b0369215b7931fefa424fb92d295f0ebJames Dongtypedef OMX_U32 CPresult; 84334de520b0369215b7931fefa424fb92d295f0ebJames Dongtypedef char * CPstring; 85334de520b0369215b7931fefa424fb92d295f0ebJames Dongtypedef void * CPhandle; 86334de520b0369215b7931fefa424fb92d295f0ebJames Dongtypedef OMX_U32 CPuint; 87334de520b0369215b7931fefa424fb92d295f0ebJames Dongtypedef OMX_S32 CPint; 88334de520b0369215b7931fefa424fb92d295f0ebJames Dongtypedef char CPbyte; 89334de520b0369215b7931fefa424fb92d295f0ebJames Dongtypedef OMX_BOOL CPbool; 90334de520b0369215b7931fefa424fb92d295f0ebJames Dong 91334de520b0369215b7931fefa424fb92d295f0ebJames Dong/** enumeration of origin types used in the CP_PIPETYPE's Seek function 92334de520b0369215b7931fefa424fb92d295f0ebJames Dong * @ingroup cp 93334de520b0369215b7931fefa424fb92d295f0ebJames Dong */ 94334de520b0369215b7931fefa424fb92d295f0ebJames Dongtypedef enum CP_ORIGINTYPE { 95334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_OriginBegin, 96334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_OriginCur, 97334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_OriginEnd, 98334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_OriginKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 99334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_OriginVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ 100334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_OriginMax = 0X7FFFFFFF 101334de520b0369215b7931fefa424fb92d295f0ebJames Dong} CP_ORIGINTYPE; 102334de520b0369215b7931fefa424fb92d295f0ebJames Dong 103334de520b0369215b7931fefa424fb92d295f0ebJames Dong/** enumeration of contact access types used in the CP_PIPETYPE's Open function 104334de520b0369215b7931fefa424fb92d295f0ebJames Dong * @ingroup cp 105334de520b0369215b7931fefa424fb92d295f0ebJames Dong */ 106334de520b0369215b7931fefa424fb92d295f0ebJames Dongtypedef enum CP_ACCESSTYPE { 107334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_AccessRead, 108334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_AccessWrite, 109334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_AccessReadWrite , 110334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_AccessKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 111334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_AccessVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ 112334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_AccessMax = 0X7FFFFFFF 113334de520b0369215b7931fefa424fb92d295f0ebJames Dong} CP_ACCESSTYPE; 114334de520b0369215b7931fefa424fb92d295f0ebJames Dong 115334de520b0369215b7931fefa424fb92d295f0ebJames Dong/** enumeration of results returned by the CP_PIPETYPE's CheckAvailableBytes function 116334de520b0369215b7931fefa424fb92d295f0ebJames Dong * @ingroup cp 117334de520b0369215b7931fefa424fb92d295f0ebJames Dong */ 118334de520b0369215b7931fefa424fb92d295f0ebJames Dongtypedef enum CP_CHECKBYTESRESULTTYPE 119334de520b0369215b7931fefa424fb92d295f0ebJames Dong{ 120334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_CheckBytesOk, /**< There are at least the request number 121334de520b0369215b7931fefa424fb92d295f0ebJames Dong of bytes available */ 122334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_CheckBytesNotReady, /**< The pipe is still retrieving bytes 123334de520b0369215b7931fefa424fb92d295f0ebJames Dong and presently lacks sufficient bytes. 124334de520b0369215b7931fefa424fb92d295f0ebJames Dong Client will be called when they are 125334de520b0369215b7931fefa424fb92d295f0ebJames Dong sufficient bytes are available. */ 126334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_CheckBytesInsufficientBytes , /**< The pipe has retrieved all bytes 127334de520b0369215b7931fefa424fb92d295f0ebJames Dong but those available are less than those 128334de520b0369215b7931fefa424fb92d295f0ebJames Dong requested */ 129334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_CheckBytesAtEndOfStream, /**< The pipe has reached the end of stream 130334de520b0369215b7931fefa424fb92d295f0ebJames Dong and no more bytes are available. */ 131334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_CheckBytesOutOfBuffers, /**< All read/write buffers are currently in use. */ 132334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_CheckBytesKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 133334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_CheckBytesVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ 134334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_CheckBytesMax = 0X7FFFFFFF 135334de520b0369215b7931fefa424fb92d295f0ebJames Dong} CP_CHECKBYTESRESULTTYPE; 136334de520b0369215b7931fefa424fb92d295f0ebJames Dong 137334de520b0369215b7931fefa424fb92d295f0ebJames Dong/** enumeration of content pipe events sent to the client callback. 138334de520b0369215b7931fefa424fb92d295f0ebJames Dong * @ingroup cp 139334de520b0369215b7931fefa424fb92d295f0ebJames Dong */ 140334de520b0369215b7931fefa424fb92d295f0ebJames Dongtypedef enum CP_EVENTTYPE{ 141334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_BytesAvailable, /** bytes requested in a CheckAvailableBytes call are now available*/ 142334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_Overflow, /** enumeration of content pipe events sent to the client callback*/ 143334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_PipeDisconnected , /** enumeration of content pipe events sent to the client callback*/ 144334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_EventKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 145334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_EventVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ 146334de520b0369215b7931fefa424fb92d295f0ebJames Dong CP_EventMax = 0X7FFFFFFF 147334de520b0369215b7931fefa424fb92d295f0ebJames Dong} CP_EVENTTYPE; 148334de520b0369215b7931fefa424fb92d295f0ebJames Dong 149334de520b0369215b7931fefa424fb92d295f0ebJames Dong/** content pipe definition 150334de520b0369215b7931fefa424fb92d295f0ebJames Dong * @ingroup cp 151334de520b0369215b7931fefa424fb92d295f0ebJames Dong */ 152334de520b0369215b7931fefa424fb92d295f0ebJames Dongtypedef struct CP_PIPETYPE 153334de520b0369215b7931fefa424fb92d295f0ebJames Dong{ 154334de520b0369215b7931fefa424fb92d295f0ebJames Dong /** Open a content stream for reading or writing. */ 155334de520b0369215b7931fefa424fb92d295f0ebJames Dong CPresult (*Open)( CPhandle* hContent, CPstring szURI, CP_ACCESSTYPE eAccess ); 156334de520b0369215b7931fefa424fb92d295f0ebJames Dong 157334de520b0369215b7931fefa424fb92d295f0ebJames Dong /** Close a content stream. */ 158334de520b0369215b7931fefa424fb92d295f0ebJames Dong CPresult (*Close)( CPhandle hContent ); 159334de520b0369215b7931fefa424fb92d295f0ebJames Dong 160334de520b0369215b7931fefa424fb92d295f0ebJames Dong /** Create a content source and open it for writing. */ 161334de520b0369215b7931fefa424fb92d295f0ebJames Dong CPresult (*Create)( CPhandle *hContent, CPstring szURI ); 162334de520b0369215b7931fefa424fb92d295f0ebJames Dong 163334de520b0369215b7931fefa424fb92d295f0ebJames Dong /** Check the that specified number of bytes are available for reading or writing (depending on access type).*/ 164334de520b0369215b7931fefa424fb92d295f0ebJames Dong CPresult (*CheckAvailableBytes)( CPhandle hContent, CPuint nBytesRequested, CP_CHECKBYTESRESULTTYPE *eResult ); 165334de520b0369215b7931fefa424fb92d295f0ebJames Dong 166334de520b0369215b7931fefa424fb92d295f0ebJames Dong /** Seek to certain position in the content relative to the specified origin. */ 167334de520b0369215b7931fefa424fb92d295f0ebJames Dong CPresult (*SetPosition)( CPhandle hContent, CPint nOffset, CP_ORIGINTYPE eOrigin); 168334de520b0369215b7931fefa424fb92d295f0ebJames Dong 169334de520b0369215b7931fefa424fb92d295f0ebJames Dong /** Retrieve the current position relative to the start of the content. */ 170334de520b0369215b7931fefa424fb92d295f0ebJames Dong CPresult (*GetPosition)( CPhandle hContent, CPuint *pPosition); 171334de520b0369215b7931fefa424fb92d295f0ebJames Dong 172334de520b0369215b7931fefa424fb92d295f0ebJames Dong /** Retrieve data of the specified size from the content stream (advance content pointer by size of data). 173334de520b0369215b7931fefa424fb92d295f0ebJames Dong Note: pipe client provides pointer. This function is appropriate for small high frequency reads. */ 174334de520b0369215b7931fefa424fb92d295f0ebJames Dong CPresult (*Read)( CPhandle hContent, CPbyte *pData, CPuint nSize); 175334de520b0369215b7931fefa424fb92d295f0ebJames Dong 176334de520b0369215b7931fefa424fb92d295f0ebJames Dong /** Retrieve a buffer allocated by the pipe that contains the requested number of bytes. 177334de520b0369215b7931fefa424fb92d295f0ebJames Dong Buffer contains the next block of bytes, as specified by nSize, of the content. nSize also 178334de520b0369215b7931fefa424fb92d295f0ebJames Dong returns the size of the block actually read. Content pointer advances the by the returned size. 179334de520b0369215b7931fefa424fb92d295f0ebJames Dong Note: pipe provides pointer. This function is appropriate for large reads. The client must call 180334de520b0369215b7931fefa424fb92d295f0ebJames Dong ReleaseReadBuffer when done with buffer. 181334de520b0369215b7931fefa424fb92d295f0ebJames Dong 182334de520b0369215b7931fefa424fb92d295f0ebJames Dong In some cases the requested block may not reside in contiguous memory within the 183334de520b0369215b7931fefa424fb92d295f0ebJames Dong pipe implementation. For instance if the pipe leverages a circular buffer then the requested 184334de520b0369215b7931fefa424fb92d295f0ebJames Dong block may straddle the boundary of the circular buffer. By default a pipe implementation 185334de520b0369215b7931fefa424fb92d295f0ebJames Dong performs a copy in this case to provide the block to the pipe client in one contiguous buffer. 186334de520b0369215b7931fefa424fb92d295f0ebJames Dong If, however, the client sets bForbidCopy, then the pipe returns only those bytes preceding the memory 187334de520b0369215b7931fefa424fb92d295f0ebJames Dong boundary. Here the client may retrieve the data in segments over successive calls. */ 188334de520b0369215b7931fefa424fb92d295f0ebJames Dong CPresult (*ReadBuffer)( CPhandle hContent, CPbyte **ppBuffer, CPuint *nSize, CPbool bForbidCopy); 189334de520b0369215b7931fefa424fb92d295f0ebJames Dong 190334de520b0369215b7931fefa424fb92d295f0ebJames Dong /** Release a buffer obtained by ReadBuffer back to the pipe. */ 191334de520b0369215b7931fefa424fb92d295f0ebJames Dong CPresult (*ReleaseReadBuffer)(CPhandle hContent, CPbyte *pBuffer); 192334de520b0369215b7931fefa424fb92d295f0ebJames Dong 193334de520b0369215b7931fefa424fb92d295f0ebJames Dong /** Write data of the specified size to the content (advance content pointer by size of data). 194334de520b0369215b7931fefa424fb92d295f0ebJames Dong Note: pipe client provides pointer. This function is appropriate for small high frequency writes. */ 195334de520b0369215b7931fefa424fb92d295f0ebJames Dong CPresult (*Write)( CPhandle hContent, CPbyte *data, CPuint nSize); 196334de520b0369215b7931fefa424fb92d295f0ebJames Dong 197334de520b0369215b7931fefa424fb92d295f0ebJames Dong /** Retrieve a buffer allocated by the pipe used to write data to the content. 198334de520b0369215b7931fefa424fb92d295f0ebJames Dong Client will fill buffer with output data. Note: pipe provides pointer. This function is appropriate 199334de520b0369215b7931fefa424fb92d295f0ebJames Dong for large writes. The client must call WriteBuffer when done it has filled the buffer with data.*/ 200334de520b0369215b7931fefa424fb92d295f0ebJames Dong CPresult (*GetWriteBuffer)( CPhandle hContent, CPbyte **ppBuffer, CPuint nSize); 201334de520b0369215b7931fefa424fb92d295f0ebJames Dong 202334de520b0369215b7931fefa424fb92d295f0ebJames Dong /** Deliver a buffer obtained via GetWriteBuffer to the pipe. Pipe will write the 203334de520b0369215b7931fefa424fb92d295f0ebJames Dong the contents of the buffer to content and advance content pointer by the size of the buffer */ 204334de520b0369215b7931fefa424fb92d295f0ebJames Dong CPresult (*WriteBuffer)( CPhandle hContent, CPbyte *pBuffer, CPuint nFilledSize); 205334de520b0369215b7931fefa424fb92d295f0ebJames Dong 206334de520b0369215b7931fefa424fb92d295f0ebJames Dong /** Register a per-handle client callback with the content pipe. */ 207334de520b0369215b7931fefa424fb92d295f0ebJames Dong CPresult (*RegisterCallback)( CPhandle hContent, CPresult (*ClientCallback)(CP_EVENTTYPE eEvent, CPuint iParam)); 208334de520b0369215b7931fefa424fb92d295f0ebJames Dong 209334de520b0369215b7931fefa424fb92d295f0ebJames Dong} CP_PIPETYPE; 210334de520b0369215b7931fefa424fb92d295f0ebJames Dong 211334de520b0369215b7931fefa424fb92d295f0ebJames Dong#endif 212334de520b0369215b7931fefa424fb92d295f0ebJames Dong 213