Preface
CedarX is an open source multimedia SDK of Shizhi Technologies. The invocation of its decoding is based on self-developed decoder interface and MediaPlayer interface can be docked up. This paper records and analyses the application of code technology in C language in its source code for reference only.
Source Referencehttps://github.com/FREEWING-JP/OrangePi_CedarX
problem
Knowing how to create a Parser and what interfaces a Parser has, the problem arises, such as where the internal variables and objects of the FLV parser are located, because there is only one CdxParserTypeE and one CdxParserOpsS in the CdxParserT definition.
//cedarx\libcore\parser\include\CdxParser.h typedef struct CdxParserS CdxParserT; //Ops Type, Function Pointer, Interface Unified struct CdxParserOpsS { cdx_int32 (*control)(CdxParserT *, cdx_int32 /* cmd */, void * /* param */); cdx_int32 (*prefetch)(CdxParserT *, CdxPacketT * /* pkt */); cdx_int32 (*read)(CdxParserT *, CdxPacketT * /* pkt */); cdx_int32 (*getMediaInfo)(CdxParserT *, CdxMediaInfoT * /* MediaInfo */); cdx_int32 (*seekTo)(CdxParserT *, cdx_int64 /* timeUs */); cdx_uint32 (*attribute)(CdxParserT *); /*return falgs define as open's falgs*/ cdx_int32 (*getStatus)(CdxParserT *); /*return enum CdxPrserStatusE*/ cdx_int32 (*close)(CdxParserT *); cdx_int32 (*init)(CdxParserT *); }; //Definition of Parser struct CdxParserS { enum CdxParserTypeE type; struct CdxParserOpsS *ops; };
Use of CdxContainerOf with Impl
Let's look at the u CdxFlvParserCreate function. When you create a Parser, you create a CdxFlvParserImplT object, and if everything goes well, you return the member base of the CdxFlvParserImplT object, which is of type CdxParserT.
static CdxParserT *__CdxFlvParserCreate(CdxStreamT *stream, cdx_uint32 flags) { CdxFlvParserImplT *impl; cdx_int32 result; impl = FlvInit(&result); CDX_FORCE_CHECK(impl); if(result < 0) { CDX_LOGE("Initiate flv file parser lib module error."); goto failure; } impl->base.ops = &flvParserOps; impl->stream = stream; impl->nVidPtsOffset = 0; impl->nAudPtsOffset = 0; impl->nSubPtsOffset = 0; impl->hasSyncVideo = 0; impl->hasSyncAudio = 0; impl->bFirstVidFrm = 1; impl->curChunkInfo.nChkType = 0; impl->curChunkInfo.nTotSize = 0; impl->curChunkInfo.nReadSize = 0; pthread_mutex_init(&impl->lock, NULL); pthread_cond_init(&impl->cond, NULL); impl->mStatus = CDX_FLV_INITIALIZED; impl->mErrno = PSR_INVALID; return &impl->base; failure: if(impl) { __CdxFlvParserClose(&impl->base); impl = NULL; } return NULL; }
Let's take a look at the definition of CdxFlvParserImplT. It is clear that members of the internal implementation of FLV Parser are in this CdxFlvParserImplT object. Then, how do internal implementations of other interfaces get this CdxFlvParserImplT object? After all, the parameters given to each interface do not directly see the CdxFlvSerParserImplT type parameters, only the CdxParserT type parameters.
typedef struct CdxFlvParserImplS { CdxParserT base;//Key point, containing CdxParserT object, named base CdxStreamT *stream; CdxPacketT pkt; void *privData; cdx_int32 exitFlag; cdx_int32 mErrno; cdx_int32 mStatus; cdx_int32 flags; cdx_bool hasVideo; cdx_bool hasAudio; cdx_bool hasSubTitle; cdx_int8 bFirstVidFrm; cdx_int8 bDiscardAud; // 1:discard, 0:transport cdx_int8 videoStreamIndex; cdx_int8 audioStreamIndex; cdx_int8 subTitleStreamIndex; cdx_uint32 totalFrames; cdx_uint32 pictureNum; cdx_uint32 nPreFRSpeed; //previous ff/rr speed, for dynamic adjust cdx_uint32 nFRSpeed; //fast forward and fast backward speed, //multiple of normal speed cdx_uint32 nFRPicShowTime; //picture show time under fast forward and backward cdx_uint32 nFRPicCnt; //picture count under ff/rr, for check if need delay cdx_uint32 nVidPtsOffset; //video time offset cdx_uint32 nAudPtsOffset; //audio time offset cdx_uint32 nSubPtsOffset; //subtitle time offset cdx_int8 hasSyncVideo; //flag, mark that if has sync video cdx_int8 hasSyncAudio; //flag, mark that if has sync audio cdx_uint32 startPos; cdx_int64 fileSize; cdx_int64 firstVideoTagPos; //for xunlei 265 seek to first keyframe. AudioStreamInfo aFormat; VideoStreamInfo vFormat; SubtitleStreamInfo tFormat; VideoStreamInfo tempVformat; cdx_uint8 *tempBuf; cdx_uint32 tempBufLen; FlvChunkInfoT curChunkInfo; //current chunk information cdx_int32 h265_vps_sps_pps_state; //3: read vps 2: read sps 1: read pps, //0: back seek , -1: invalid cdx_uint32 h265_start_pos_stored; cdx_uint32 h265_data_size_stored; pthread_mutex_t lock; pthread_cond_t cond; cdx_int32 bNoAvcSequenceHeader; }CdxFlvParserImplT;
Let's look at the u CdxFlvParserInit interface and see how the impl object is internally obtained.
static int __CdxFlvParserInit(CdxParserT *parser) { cdx_int32 result, ret = 0; CdxFlvParserImplT *impl; CDX_CHECK(parser); impl = CdxContainerOf(parser, CdxFlvParserImplT, base);//key point result = FlvOpen(impl); if(result < 0) { CDX_LOGE("Open flv failed."); impl->mErrno = PSR_OPEN_FAIL; ret = -1; goto __exit; } CDX_LOGI("read flv head finish."); impl->mErrno = PSR_OK; ret = 0; __exit: pthread_mutex_lock(&impl->lock); impl->mStatus = CDX_FLV_IDLE; pthread_mutex_unlock(&impl->lock); pthread_cond_signal(&impl->cond); return ret; }
The key point is that CdxContainerOf, essentially identical to the container_of macro of the Linux kernel. Pass parser to find impl of type CdxFlvParserImplT, and get other internal variables and structure objects! Thus, CdxParserTThe definition does not need to contain specific Parser member objects. When each specific Parser is created, it creates its own ParserImplT and uses CdxParserT as the first member of ParserImplT, named base, so that CdxParserT is associated with ParserImplT and ParserImplT can be found through CdxParserT!
For the container_of macro of the Linux kernel, the function of this macro is simply to get a pointer to the container (structure) through a pointer to a member of a container (structure). Simply, to find a container through a member, in this case, CdxFlvParserImplT can be found through CdxParserT!
For an explanation of container_of, refer to the following article.
Detailed Linux Kernel container_of (illustration)