/*------------------------------------------------------------------------------ OSAL_MutexCreate ------------------------------------------------------------------------------*/ OSAL_ERRORTYPE OSAL_MutexCreate(OSAL_PTR *phMutex) { pthread_mutex_t *pMutex = (pthread_mutex_t *) OSAL_Malloc(sizeof(pthread_mutex_t)); static pthread_mutexattr_t oAttr; static pthread_mutexattr_t *pAttr = NULL; if (pAttr == NULL && !pthread_mutexattr_init(&oAttr) && !pthread_mutexattr_settype(&oAttr, PTHREAD_MUTEX_RECURSIVE)) { pAttr = &oAttr; } if (pMutex == NULL) { LOGE("OSAL_ERROR_INSUFFICIENT_RESOURCES\n"); return OSAL_ERROR_INSUFFICIENT_RESOURCES; } if (pthread_mutex_init(pMutex, pAttr)) { LOGE("OSAL_ERROR_INSUFFICIENT_RESOURCES\n"); OSAL_Free(pMutex); return OSAL_ERROR_INSUFFICIENT_RESOURCES; } *phMutex = (void *)pMutex; return OSAL_ERRORNONE; }
/*------------------------------------------------------------------------------ OSAL_EventCreate ------------------------------------------------------------------------------*/ OSAL_ERRORTYPE OSAL_EventCreate(OSAL_PTR *phEvent) { OSAL_THREAD_EVENT *pEvent = OSAL_Malloc(sizeof(OSAL_THREAD_EVENT)); if (pEvent == NULL) return OSAL_ERROR_INSUFFICIENT_RESOURCES; pEvent->bSignaled = 0; if (pipe(pEvent->fd) == -1) { OSAL_Free(pEvent); return OSAL_ERROR_INSUFFICIENT_RESOURCES; } if (pthread_mutex_init(&pEvent->mutex, NULL)) { close(pEvent->fd[0]); close(pEvent->fd[1]); OSAL_Free(pEvent); return OSAL_ERROR_INSUFFICIENT_RESOURCES; } *phEvent = (OSAL_PTR)pEvent; return OSAL_ERRORNONE; }
/* Event Create Method */ OSAL_ERROR OSAL_CreateEvent(void **pEvents) { OSAL_ERROR bRet = OSAL_ErrUnKnown; OSAL_ThreadEvent *plEvent = (OSAL_ThreadEvent *) OSAL_Malloc(sizeof(OSAL_ThreadEvent)); if (NULL == plEvent) { bRet = OSAL_ErrAlloc; goto EXIT; } plEvent->bSignaled = OSAL_FALSE; plEvent->eFlags = 0; if (SUCCESS != pthread_mutex_init(&(plEvent->mutex), NULL)) { OSAL_ErrorTrace("Event Create:Mutex Init failed !"); bRet = OSAL_ErrMutexCreate; goto EXIT; } if (SUCCESS != pthread_cond_init(&(plEvent->condition), NULL)) { OSAL_ErrorTrace("Event Create:Conditional Variable Init failed !"); pthread_mutex_destroy(&(plEvent->mutex)); bRet = OSAL_ErrEventCreate; } else { *pEvents = (void *) plEvent; bRet = OSAL_ErrNone; } EXIT: if ((OSAL_ErrNone != bRet) && (NULL != plEvent)) { OSAL_Free(plEvent); } return bRet; }
OMX_BOOL HantroOmx_port_allocate_next_buffer(PORT* p, BUFFER** buff) { BUFFER* next = (BUFFER*)OSAL_Malloc(sizeof(BUFFER)); if (next==NULL) return OMX_FALSE; memset(next, 0, sizeof(BUFFER)); next->flags |= BUFFER_FLAG_IN_USE; // hack for tunneling. // The buffer header is always accessed through a pointer. In normal case // it just points to the header object within the buffer. But in case // of tunneling it can be made to point to a header allocated by the tunneling component. next->header = &next->headerdata; OMX_BOOL ret = HantroOmx_bufferlist_push_back(&p->buffers, next); if (ret == OMX_FALSE) { OMX_ERRORTYPE err; OMX_U32 capacity = HantroOmx_bufferlist_get_capacity(&p->buffers); if (capacity == 0) capacity = 5; err = HantroOmx_bufferlist_reserve(&p->buffers, capacity * 2); if (err != OMX_ErrorNone) { OSAL_Free(next); return OMX_FALSE; } HantroOmx_bufferlist_push_back(&p->buffers, next); } *buff = next; return OMX_TRUE; }
OMX_ERRORTYPE HantroOmx_bufferlist_init(BUFFERLIST* list, OMX_U32 size) { assert(list); list->list = (BUFFER**)OSAL_Malloc(sizeof(BUFFER*) * size); if (!list->list) return OMX_ErrorInsufficientResources; memset(list->list, 0, sizeof(BUFFER*) * size); list->size = 0; list->capacity = size; return OMX_ErrorNone; }
// create codec instance and initialize it CODEC_PROTOTYPE *HantroHwDecOmx_decoder_create_h264(OMX_BOOL conceal_errors) { CODEC_H264 *this = OSAL_Malloc(sizeof(CODEC_H264)); memset(this, 0, sizeof(CODEC_H264)); CALLSTACK; this->base.destroy = decoder_destroy_h264; this->base.decode = decoder_decode_h264; this->base.getinfo = decoder_getinfo_h264; this->base.getframe = decoder_getframe_h264; this->base.scanframe = decoder_scanframe_h264; this->base.setppargs = decoder_setppargs_h264; #ifdef DYNAMIC_SCALING this->base.setscaling = decoder_setscaling_h264; #endif this->instance = 0; this->picId++; #ifdef IS_G1_DECODER H264DecRet ret = H264DecInit(&this->instance, DISABLE_OUTPUT_REORDER, USE_VIDEO_FREEZE_CONCEALMENT, USE_DISPLAY_SMOOTHING, DEC_REF_FRM_RASTER_SCAN); #ifdef MVC_SUPPORT if(ret == H264DEC_OK) ret = H264DecSetMvc(this->instance); #endif #endif #ifdef IS_8190 H264DecRet ret = H264DecInit(&this->instance, DISABLE_OUTPUT_REORDER, USE_VIDEO_FREEZE_CONCEALMENT, USE_DISPLAY_SMOOTHING); #endif #if !defined (IS_8190) && !defined (IS_G1_DECODER) H264DecRet ret = H264DecInit(&this->instance, DISABLE_OUTPUT_REORDER); #endif if(ret != H264DEC_OK) { decoder_destroy_h264((CODEC_PROTOTYPE *) this); return NULL; } #ifdef H264_DECODE_STATISTICS this->stat_file = fopen("/tmp/h264_stat.txt", "w"); #endif return (CODEC_PROTOTYPE *) this; }
OMX_ERRORTYPE HantroOmx_msgque_push_back(OMX_IN msgque* q, OMX_IN OMX_PTR ptr) { assert(q); assert(ptr); msg_node* tail = (msg_node*)OSAL_Malloc(sizeof(msg_node)); if(!tail) return OMX_ErrorInsufficientResources; tail->next = q->tail; tail->prev = 0; tail->data = ptr; // get mutex now OMX_ERRORTYPE err = OMX_ErrorNone; err = OSAL_MutexLock(q->mutex); if (err != OMX_ErrorNone) { OSAL_Free(tail); return err; } // first set the signal if needed and once that is allright // only then change the queue, cause that cant fail if (q->size == 0) { err = OSAL_EventSet(q->event); if (err != OMX_ErrorNone) { OSAL_MutexUnlock(q->mutex); return err; } } q->size += 1; if (q->tail) q->tail->prev = tail; q->tail = tail; if (!q->head) q->head = q->tail; err = OSAL_MutexUnlock(q->mutex); assert(err == OMX_ErrorNone); return OMX_ErrorNone; }
OMX_ERRORTYPE HantroOmx_bufferlist_reserve(BUFFERLIST* list, OMX_U32 newsize) { assert(list); if (newsize < list->capacity) return OMX_ErrorBadParameter; BUFFER** data = (BUFFER**)OSAL_Malloc(sizeof(BUFFER**) * newsize); if (!data) return OMX_ErrorInsufficientResources; memset(data, 0, sizeof(BUFFER*) * newsize); memcpy(data, list->list, list->size * sizeof(BUFFER*)); swap_ptr(&data, &list->list); list->capacity = newsize; OSAL_Free(data); return OMX_ErrorNone; }
// create codec instance and initialize it CODEC_PROTOTYPE *HantroHwDecOmx_decoder_create_mpeg2(void) { CALLSTACK; CODEC_MPEG2 *this = OSAL_Malloc(sizeof(CODEC_MPEG2)); memset(this, 0, sizeof(CODEC_MPEG2)); this->base.destroy = decoder_destroy_mpeg2; this->base.decode = decoder_decode_mpeg2; this->base.getinfo = decoder_getinfo_mpeg2; this->base.getframe = decoder_getframe_mpeg2; this->base.scanframe = decoder_scanframe_mpeg2; this->base.setppargs = decoder_setppargs_mpeg2; #ifdef DYNAMIC_SCALING this->base.setscaling = decoder_setscaling_mpeg2; #endif this->instance = 0; this->update_pp_out = OMX_FALSE; this->picId = 0; //this->extraEosLoopDone = OMX_FALSE; #ifdef IS_G1_DECODER Mpeg2DecRet ret = Mpeg2DecInit(&this->instance, USE_VIDEO_FREEZE_CONCEALMENT, FRAME_BUFFERS, DEC_REF_FRM_RASTER_SCAN); #else Mpeg2DecRet ret = Mpeg2DecInit(&this->instance, USE_VIDEO_FREEZE_CONCEALMENT, FRAME_BUFFERS); #endif if(ret != MPEG2DEC_OK) { decoder_destroy_mpeg2((CODEC_PROTOTYPE *) this); return NULL; } #ifdef MPEG2_DECODE_STATISTICS this->stat_file = fopen("/tmp/mpeg2_stat.txt", "w"); #endif return (CODEC_PROTOTYPE *) this; }
/*------------------------------------------------------------------------------ OSAL_ThreadCreate ------------------------------------------------------------------------------*/ OSAL_ERRORTYPE OSAL_ThreadCreate( OSAL_U32 (*pFunc)(OSAL_PTR pParam), OSAL_PTR pParam, OSAL_U32 nPriority, OSAL_PTR *phThread ) { OSAL_THREADDATATYPE *pThreadData; struct sched_param sched; pThreadData = (OSAL_THREADDATATYPE*)OSAL_Malloc(sizeof(OSAL_THREADDATATYPE)); if (pThreadData == NULL) { LOGE("OSAL_ERROR_INSUFFICIENT_RESOURCES\n"); return OSAL_ERROR_INSUFFICIENT_RESOURCES; } pThreadData->pFunc = pFunc; pThreadData->pParam = pParam; pThreadData->uReturn = 0; pthread_attr_init(&pThreadData->oThreadAttr); pthread_attr_getschedparam(&pThreadData->oThreadAttr, &sched); sched.sched_priority += nPriority; pthread_attr_setschedparam(&pThreadData->oThreadAttr, &sched); if (pthread_create(&pThreadData->oPosixThread, &pThreadData->oThreadAttr, threadFunc, pThreadData)) { LOGE("OSAL_ERROR_INSUFFICIENT_RESOURCES\n"); OSAL_Free(pThreadData); return OSAL_ERROR_INSUFFICIENT_RESOURCES; } BlockSIGIO(); *phThread = (OSAL_PTR)pThreadData; return OSAL_ERRORNONE; }
// create codec instance and initialize it CODEC_PROTOTYPE *HantroHwDecOmx_decoder_create_vp8() { CALLSTACK; CODEC_VP8 *this = OSAL_Malloc(sizeof(CODEC_VP8)); memset(this, 0, sizeof(CODEC_VP8)); this->base.destroy = decoder_destroy_vp8; this->base.decode = decoder_decode_vp8; this->base.getinfo = decoder_getinfo_vp8; this->base.getframe = decoder_getframe_vp8; this->base.scanframe = decoder_scanframe_vp8; this->base.setppargs = decoder_setppargs_vp8; #ifdef DYNAMIC_SCALING this->base.setscaling = decoder_setscaling_vp8; #endif this->instance = 0; this->picId = 0; this->headersDecoded = OMX_FALSE; #ifdef IS_G1_DECODER VP8DecRet ret = VP8DecInit(&this->instance, VP8DEC_VP8, USE_VIDEO_FREEZE_CONCEALMENT, FRAME_BUFFERS, DEC_REF_FRM_RASTER_SCAN); #else VP8DecRet ret = VP8DecInit(&this->instance, VP8DEC_VP8, USE_VIDEO_FREEZE_CONCEALMENT, FRAME_BUFFERS); #endif if(ret != VP8DEC_OK) { decoder_destroy_vp8((CODEC_PROTOTYPE *) this); return NULL; } return (CODEC_PROTOTYPE *) this; }
// create codec instance and initialize it ENCODER_PROTOTYPE* HantroHwEncOmx_encoder_create_vp8(const VP8_CONFIG* params) { VP8EncConfig cfg; memset(&cfg,0,sizeof(VP8EncConfig)); cfg.width = params->common_config.nOutputWidth; cfg.height = params->common_config.nOutputHeight; //cfg.frameRateDenom = 1; //cfg.frameRateNum = cfg.frameRateDenom * Q16_FLOAT(params->common_config.nInputFramerate); cfg.frameRateNum = TIME_RESOLUTION; cfg.frameRateDenom = cfg.frameRateNum / Q16_FLOAT(params->common_config.nInputFramerate); cfg.refFrameAmount = REFERENCE_FRAME_AMOUNT; ENCODER_VP8* this = OSAL_Malloc(sizeof(ENCODER_VP8)); this->instance = 0; memset( &this->encIn, 0, sizeof(VP8EncIn)); this->origWidth = params->pp_config.origWidth; this->origHeight = params->pp_config.origHeight; this->base.stream_start = encoder_stream_start_vp8; this->base.stream_end = encoder_stream_end_vp8; this->base.encode = encoder_encode_vp8; this->base.destroy = encoder_destroy_vp8; this->bStabilize = params->pp_config.frameStabilization; this->nIFrameCounter = 0; this->nEstTimeInc = cfg.frameRateDenom; VP8EncRet ret = VP8EncInit(&cfg, &this->instance); // Setup coding control if (ret == VP8ENC_OK) { VP8EncCodingCtrl coding_ctrl; ret = VP8EncGetCodingCtrl(this->instance, &coding_ctrl); if (ret == VP8ENC_OK) { coding_ctrl.filterLevel = VP8ENC_FILTER_LEVEL_AUTO; coding_ctrl.filterSharpness = VP8ENC_FILTER_SHARPNESS_AUTO; coding_ctrl.filterType = 0; switch (params->vp8_config.eLevel) { case OMX_VIDEO_VP8Level_Version0: coding_ctrl.interpolationFilter = 0; break; case OMX_VIDEO_VP8Level_Version1: coding_ctrl.interpolationFilter = 1; coding_ctrl.filterType = 1; break; case OMX_VIDEO_VP8Level_Version2: coding_ctrl.interpolationFilter = 1; coding_ctrl.filterLevel = 0; break; case OMX_VIDEO_VP8Level_Version3: coding_ctrl.interpolationFilter = 2; coding_ctrl.filterLevel = 0; break; default: printf("Invalid VP8 eLevel\n"); coding_ctrl.interpolationFilter = 0; break; } coding_ctrl.dctPartitions = params->vp8_config.nDCTPartitions; coding_ctrl.errorResilient = params->vp8_config.bErrorResilientMode; coding_ctrl.quarterPixelMv = 1; ret = VP8EncSetCodingCtrl(this->instance, &coding_ctrl); } } // Setup rate control if (ret == VP8ENC_OK) { VP8EncRateCtrl rate_ctrl; ret = VP8EncGetRateCtrl(this->instance, &rate_ctrl); if (ret == VP8ENC_OK) { // Optional. Set to -1 to use default. if (params->rate_config.nPictureRcEnabled >= 0) { rate_ctrl.pictureRc = params->rate_config.nPictureRcEnabled; } // Optional settings. Set to -1 to use default. if (params->rate_config.nQpDefault >= 0) { rate_ctrl.qpHdr = params->rate_config.nQpDefault; } // Optional settings. Set to -1 to use default. if (params->rate_config.nQpMin >= 0) { rate_ctrl.qpMin = params->rate_config.nQpMin; if(rate_ctrl.qpHdr != -1 && rate_ctrl.qpHdr < rate_ctrl.qpMin) { rate_ctrl.qpHdr = rate_ctrl.qpMin; } } // Optional settings. Set to -1 to use default. if (params->rate_config.nQpMax > 0) { rate_ctrl.qpMax = params->rate_config.nQpMax; if(rate_ctrl.qpHdr > rate_ctrl.qpMax) { rate_ctrl.qpHdr = rate_ctrl.qpMax; } } // Optional. Set to -1 to use default. if (params->rate_config.nTargetBitrate >= 0) { rate_ctrl.bitPerSecond = params->rate_config.nTargetBitrate; } switch (params->rate_config.eRateControl) { case OMX_Video_ControlRateDisable: rate_ctrl.pictureSkip = 0; break; case OMX_Video_ControlRateVariable: rate_ctrl.pictureSkip = 0; break; case OMX_Video_ControlRateConstant: rate_ctrl.pictureSkip = 0; break; case OMX_Video_ControlRateVariableSkipFrames: rate_ctrl.pictureSkip = 1; break; case OMX_Video_ControlRateConstantSkipFrames: rate_ctrl.pictureSkip = 1; break; case OMX_Video_ControlRateMax: rate_ctrl.pictureSkip = 0; break; default: break; } ret = VP8EncSetRateCtrl(this->instance, &rate_ctrl); } } // Setup preprocessing if (ret == VP8ENC_OK) { VP8EncPreProcessingCfg pp_config; ret = VP8EncGetPreProcessing(this->instance, &pp_config); // input image size pp_config.origWidth = params->pp_config.origWidth; pp_config.origHeight = params->pp_config.origHeight; // cropping offset pp_config.xOffset = params->pp_config.xOffset; pp_config.yOffset = params->pp_config.yOffset; switch (params->pp_config.formatType) { case OMX_COLOR_FormatYUV420PackedPlanar: case OMX_COLOR_FormatYUV420Planar: pp_config.inputType = VP8ENC_YUV420_PLANAR; break; case OMX_COLOR_FormatYUV420PackedSemiPlanar: case OMX_COLOR_FormatYUV420SemiPlanar: pp_config.inputType = VP8ENC_YUV420_SEMIPLANAR; break; case OMX_COLOR_FormatYCbYCr: pp_config.inputType = VP8ENC_YUV422_INTERLEAVED_YUYV; break; case OMX_COLOR_FormatCbYCrY: pp_config.inputType = VP8ENC_YUV422_INTERLEAVED_UYVY; break; case OMX_COLOR_Format16bitRGB565: pp_config.inputType = VP8ENC_RGB565; break; case OMX_COLOR_Format16bitBGR565: pp_config.inputType = VP8ENC_BGR565; break; case OMX_COLOR_Format12bitRGB444: pp_config.inputType = VP8ENC_RGB444; break; case OMX_COLOR_Format16bitARGB4444: pp_config.inputType = VP8ENC_RGB444; break; case OMX_COLOR_Format16bitARGB1555: pp_config.inputType = VP8ENC_RGB555; break; case OMX_COLOR_Format24bitRGB888: case OMX_COLOR_Format25bitARGB1888: case OMX_COLOR_Format32bitARGB8888: pp_config.inputType = VP8ENC_RGB888; break; case OMX_COLOR_Format24bitBGR888: pp_config.inputType = VP8ENC_BGR888; break; default: ret = VP8ENC_INVALID_ARGUMENT; break; } switch (params->pp_config.angle) { case 0: pp_config.rotation = VP8ENC_ROTATE_0; break; case 90: pp_config.rotation = VP8ENC_ROTATE_90R; break; case 270: pp_config.rotation = VP8ENC_ROTATE_90L; break; default: ret = VP8ENC_INVALID_ARGUMENT; break; } // Enables or disables the video stabilization function. Set to a non-zero value will // enable the stabilization. The input image dimensions (origWidth, origHeight) // have to be at least 8 pixels bigger than the final encoded image dimensions. Also when // enabled the cropping offset (xOffset, yOffset) values are ignored. this->bStabilize = params->pp_config.frameStabilization; pp_config.videoStabilization = params->pp_config.frameStabilization; if (ret == VP8ENC_OK) { ret = VP8EncSetPreProcessing(this->instance, &pp_config); } } if (ret != VP8ENC_OK) { OSAL_Free(this); return NULL; } return (ENCODER_PROTOTYPE*) this; }
// Create JPEG codec instance and initialize it. ENCODER_PROTOTYPE* HantroHwEncOmx_encoder_create_jpeg(const JPEG_CONFIG* params) { assert(params); JpegEncCfg cfg; JpegEncRet ret; cfg.qLevel = params->qLevel; // quantization level. #if defined (ENC8270) || defined (ENC8290) || defined (ENCH1) cfg.qTableLuma = NULL; cfg.qTableChroma = NULL; #endif switch (params->pp_config.formatType) { case OMX_COLOR_FormatYUV420PackedPlanar: case OMX_COLOR_FormatYUV420Planar: cfg.frameType = JPEGENC_YUV420_PLANAR; break; case OMX_COLOR_FormatYUV420PackedSemiPlanar: case OMX_COLOR_FormatYUV420SemiPlanar: cfg.frameType = JPEGENC_YUV420_SEMIPLANAR; break; #if !defined (ENC8270) && !defined (ENC8290) && !defined (ENCH1) case OMX_COLOR_FormatYUV422Planar: cfg.frameType = JPEGENC_YUV422_PLANAR; cfg.codingMode = JPEGENC_422_MODE; break; #endif case OMX_COLOR_FormatYCbYCr: cfg.frameType = JPEGENC_YUV422_INTERLEAVED_YUYV; break; case OMX_COLOR_FormatCbYCrY: cfg.frameType = JPEGENC_YUV422_INTERLEAVED_UYVY; break; case OMX_COLOR_Format16bitRGB565: cfg.frameType = JPEGENC_RGB565; break; case OMX_COLOR_Format16bitBGR565: cfg.frameType = JPEGENC_BGR565; break; case OMX_COLOR_Format16bitARGB4444: cfg.frameType = JPEGENC_RGB444; break; case OMX_COLOR_Format16bitARGB1555: cfg.frameType = JPEGENC_RGB555; break; #ifdef ENCH1 case OMX_COLOR_Format12bitRGB444: cfg.frameType = JPEGENC_RGB444; case OMX_COLOR_Format24bitRGB888: case OMX_COLOR_Format25bitARGB1888: case OMX_COLOR_Format32bitARGB8888: cfg.frameType = JPEGENC_RGB888; break; case OMX_COLOR_Format24bitBGR888: cfg.frameType = JPEGENC_BGR888; #endif default: ret = JPEGENC_INVALID_ARGUMENT; break; } switch (params->pp_config.angle) { case 0: cfg.rotation = JPEGENC_ROTATE_0; break; case 90: cfg.rotation = JPEGENC_ROTATE_90R; break; case 270: cfg.rotation = JPEGENC_ROTATE_90L; break; default: ret = JPEGENC_INVALID_ARGUMENT; break; } if (params->bAddHeaders) { cfg.unitsType = params->unitsType; cfg.xDensity = params->xDensity; cfg.yDensity = params->yDensity; cfg.markerType = params->markerType; cfg.comLength = 0; // no comment header cfg.pCom = 0; // no header data } else { cfg.unitsType = JPEGENC_NO_UNITS; cfg.markerType = JPEGENC_SINGLE_MARKER; cfg.xDensity = 1; cfg.yDensity = 1; cfg.comLength = 0; // no comment header cfg.pCom = 0; // no header data } #if !defined (ENC8270) && !defined (ENC8290) && !defined (ENCH1) cfg.thumbnail = 0; // no thumbnails cfg.cfgThumb.inputWidth = 0; cfg.cfgThumb.inputHeight = 0; cfg.cfgThumb.xOffset = 0; cfg.cfgThumb.yOffset = 0; cfg.cfgThumb.codingWidth = 0; #endif // set encoder mode parameters cfg.inputWidth = params->pp_config.origWidth; cfg.inputHeight = params->pp_config.origHeight; cfg.xOffset = params->pp_config.xOffset; cfg.yOffset = params->pp_config.yOffset; cfg.codingType = params->codingType; ENCODER_JPEG* this = OSAL_Malloc(sizeof(ENCODER_JPEG)); this->croppedWidth = cfg.codingWidth = params->codingWidth; this->croppedHeight = cfg.codingHeight = params->codingHeight; // encIn struct init this->instance = 0; memset( &this->encIn, 0, sizeof(JpegEncIn)); this->origWidth = params->pp_config.origWidth; this->origHeight = params->pp_config.origHeight; this->frameHeader = params->bAddHeaders; this->sliceNumber = 1; this->leftoverCrop = 0; this->frameType = params->pp_config.formatType; // initialize static methods this->base.stream_start = encoder_stream_start_jpeg; this->base.stream_end = encoder_stream_end_jpeg; this->base.encode = encoder_encode_jpeg; this->base.destroy = encoder_destroy_jpeg; // slice mode configuration if (params->codingType > 0) { if (params->sliceHeight > 0) { this->sliceMode = OMX_TRUE; if (this->frameType == OMX_COLOR_FormatYUV422Planar) { cfg.restartInterval = params->sliceHeight / 8; } else { cfg.restartInterval = params->sliceHeight / 16; } this->sliceHeight = params->sliceHeight; } else { ret = JPEGENC_INVALID_ARGUMENT; } } else { this->sliceMode = OMX_FALSE; cfg.restartInterval = 0; this->sliceHeight = 0; } ret = JpegEncInit(&cfg, &this->instance); if (ret == JPEGENC_OK) { #if defined (ENC8270) || defined (ENC8290) || defined (ENCH1) ret = JpegEncSetPictureSize(this->instance, &cfg); #else ret = JpegEncSetFullResolutionMode(this->instance, &cfg); #endif } if (ret != JPEGENC_OK) { OSAL_Free(this); return NULL; } return (ENCODER_PROTOTYPE*) this; }
// create codec instance and initialize it ENCODER_PROTOTYPE* HantroHwEncOmx_encoder_create_mpeg4(const MPEG4_CONFIG* params) { MP4EncCfg cfg; cfg.strmType = MPEG4_PLAIN_STRM; if (params->mp4_config.bSVH) { cfg.strmType = MPEG4_SVH_STRM; } else { if (params->mp4_config.bReversibleVLC) { cfg.strmType = MPEG4_VP_DP_RVLC_STRM; } else if (params->error_ctrl_config.bEnableDataPartitioning) { cfg.strmType = MPEG4_VP_DP_STRM; } else if (params->error_ctrl_config.bEnableResync) { cfg.strmType = MPEG4_VP_STRM; } } LOGV("---> init strmType = %d", cfg.strmType); // Find out correct profile and level switch (params->mp4_config.eProfile) { case OMX_VIDEO_MPEG4ProfileSimple: { switch (params->mp4_config.eLevel) { case OMX_VIDEO_MPEG4Level0: cfg.profileAndLevel = MPEG4_SIMPLE_PROFILE_LEVEL_0; break; case OMX_VIDEO_MPEG4Level0b: cfg.profileAndLevel = MPEG4_SIMPLE_PROFILE_LEVEL_0B; break; case OMX_VIDEO_MPEG4Level1: cfg.profileAndLevel = MPEG4_SIMPLE_PROFILE_LEVEL_1; break; case OMX_VIDEO_MPEG4Level2: cfg.profileAndLevel = MPEG4_SIMPLE_PROFILE_LEVEL_2; break; case OMX_VIDEO_MPEG4Level3: cfg.profileAndLevel = MPEG4_SIMPLE_PROFILE_LEVEL_3; break; case OMX_VIDEO_MPEG4Level4a: cfg.profileAndLevel = MPEG4_SIMPLE_PROFILE_LEVEL_4A; break; case OMX_VIDEO_MPEG4Level5: case OMX_VIDEO_MPEG4LevelMax: cfg.profileAndLevel = MPEG4_SIMPLE_PROFILE_LEVEL_5; break; default: return NULL; break; } } break; case OMX_VIDEO_MPEG4ProfileAdvancedRealTime: { switch (params->mp4_config.eLevel) { case OMX_VIDEO_MPEG4Level3: cfg.profileAndLevel = MPEG4_ADV_SIMPLE_PROFILE_LEVEL_3; break; case OMX_VIDEO_MPEG4Level4: cfg.profileAndLevel = MPEG4_ADV_SIMPLE_PROFILE_LEVEL_4; break; case OMX_VIDEO_MPEG4Level5: case OMX_VIDEO_MPEG4LevelMax: cfg.profileAndLevel = MPEG4_ADV_SIMPLE_PROFILE_LEVEL_5; break; default: return NULL; break; } } break; case OMX_VIDEO_MPEG4ProfileMain: case OMX_VIDEO_MPEG4ProfileMax: { switch (params->mp4_config.eLevel) { case OMX_VIDEO_MPEG4Level4: case OMX_VIDEO_MPEG4LevelMax: cfg.profileAndLevel = MPEG4_MAIN_PROFILE_LEVEL_4; break; default: return NULL; break; } } break; default: return NULL; } cfg.width = params->common_config.nOutputWidth; cfg.height = params->common_config.nOutputHeight; // The numerator part of the input frame rate. The frame rate is defined by the // frmRateNum/frmRateDenom ratio. This value is also used as the time resolution or // the number of subunits (ticks) within a second. // Valid value range: [1, 65535] cfg.frmRateNum = params->mp4_config.nTimeIncRes; // The denominator part of the input frame rate. This value has to be equal or less // than the numerator part frmRateNum. // Valid value range: [1, 65535] cfg.frmRateDenom = cfg.frmRateNum / Q16_FLOAT(params->common_config.nInputFramerate); ENCODER_MPEG4* this = OSAL_Malloc(sizeof(ENCODER_MPEG4)); this->instance = 0; memset( &this->encIn, 0, sizeof(MP4EncIn)); this->origWidth = params->pp_config.origWidth; this->origHeight = params->pp_config.origHeight; this->base.stream_start = encoder_stream_start_mpeg4; this->base.stream_end = encoder_stream_end_mpeg4; this->base.encode = encoder_encode_mpeg4; this->base.destroy = encoder_destroy_mpeg4; // calculate per frame tick increment this->nTickIncrement = cfg.frmRateDenom; MP4EncRet ret = MP4EncInit(&cfg, &this->instance); // Setup coding control if (ret == ENC_OK) { MP4EncCodingCtrl coding_ctrl; ret = MP4EncGetCodingCtrl(this->instance, &coding_ctrl); if (ret == ENC_OK) { // Header extension codes enable/disable // Not supported, use defaults. if (params->error_ctrl_config.bEnableHEC) { coding_ctrl.insHEC = 1; } else if (params->mp4_config.nHeaderExtension > 0) { coding_ctrl.insHEC = 1; } else { coding_ctrl.insHEC = 0; } // GOV header insertion enable/disable if ((params->mp4_config.bGov) && (params->mp4_config.nPFrames > 0)) { coding_ctrl.insGOV = 0; this->bGovEnabled = OMX_TRUE; } else { coding_ctrl.insGOV = 0; this->bGovEnabled = OMX_FALSE; } this->nFrameCounter = 0; if (params->mp4_config.nPFrames > 0) { this->nPFrames = params->mp4_config.nPFrames; } // Video package (VP) size if (params->error_ctrl_config.nResynchMarkerSpacing > 0) { coding_ctrl.vpSize = params->error_ctrl_config.nResynchMarkerSpacing; } else if (params->mp4_config.nMaxPacketSize > 0) { coding_ctrl.vpSize = params->mp4_config.nMaxPacketSize; } // else use default value ret = MP4EncSetCodingCtrl(this->instance, &coding_ctrl); } } // Setup rate control if (ret == ENC_OK) { MP4EncRateCtrl rate_ctrl; ret = MP4EncGetRateCtrl(this->instance, &rate_ctrl); if (ret == ENC_OK) { rate_ctrl.gopLen = params->mp4_config.nPFrames; // Optional. Set to -1 to use default. if (params->rate_config.nPictureRcEnabled >= 0) { rate_ctrl.vopRc = params->rate_config.nPictureRcEnabled; } // Optional. Set to -1 to use default. if (params->rate_config.nMbRcEnabled >= 0) { rate_ctrl.mbRc = params->rate_config.nMbRcEnabled; } // Optional settings. Set to -1 to use default. if (params->rate_config.nQpDefault >= 0) { rate_ctrl.qpHdr = params->rate_config.nQpDefault; } // Optional settings. Set to -1 to use default. if (params->rate_config.nQpMin >= 0) { rate_ctrl.qpMin = params->rate_config.nQpMin; if(rate_ctrl.qpHdr != -1 && rate_ctrl.qpHdr < rate_ctrl.qpMin) { rate_ctrl.qpHdr = rate_ctrl.qpMin; } } // Optional settings. Set to -1 to use default. if (params->rate_config.nQpMax > 0) { rate_ctrl.qpMax = params->rate_config.nQpMax; if(rate_ctrl.qpHdr > rate_ctrl.qpMax) { rate_ctrl.qpHdr = rate_ctrl.qpMax; } } // Optional. Set to -1 to use default. if (params->rate_config.nTargetBitrate >= 0) { rate_ctrl.bitPerSecond = params->rate_config.nTargetBitrate; } // Optional. Set to -1 to use default. if (params->rate_config.nVbvEnabled >= 0) { rate_ctrl.vbv = params->rate_config.nVbvEnabled; } switch (params->rate_config.eRateControl) { case OMX_Video_ControlRateDisable: rate_ctrl.vopSkip = 0; break; case OMX_Video_ControlRateVariable: rate_ctrl.vopSkip = 0; break; case OMX_Video_ControlRateConstant: rate_ctrl.vopSkip = 0; break; case OMX_Video_ControlRateVariableSkipFrames: rate_ctrl.vopSkip = 1; break; case OMX_Video_ControlRateConstantSkipFrames: rate_ctrl.vopSkip = 1; break; case OMX_Video_ControlRateMax: rate_ctrl.vopSkip = 0; break; default: break; } ret = MP4EncSetRateCtrl(this->instance, &rate_ctrl); } } // Setup preprocessing if (ret == ENC_OK) { MP4EncPreProcessingCfg pp_config; ret = MP4EncGetPreProcessing(this->instance, &pp_config); // input image size pp_config.origWidth = params->pp_config.origWidth; pp_config.origHeight = params->pp_config.origHeight; // cropping offset pp_config.xOffset = params->pp_config.xOffset; pp_config.yOffset = params->pp_config.yOffset; switch (params->pp_config.formatType) { case OMX_COLOR_FormatYUV420PackedPlanar: case OMX_COLOR_FormatYUV420Planar: #ifdef ENC6280 pp_config.yuvType = ENC_YUV420_PLANAR; #endif #ifdef ENC7280 pp_config.inputType = ENC_YUV420_PLANAR; #endif break; case OMX_COLOR_FormatYUV420PackedSemiPlanar: case OMX_COLOR_FormatYUV420SemiPlanar: #ifdef ENC6280 pp_config.yuvType = ENC_YUV420_SEMIPLANAR; #endif #ifdef ENC7280 pp_config.inputType = ENC_YUV420_SEMIPLANAR; #endif break; case OMX_COLOR_FormatYCbYCr: #ifdef ENC6280 pp_config.yuvType = ENC_YUV422_INTERLEAVED_YUYV; #endif #ifdef ENC7280 pp_config.inputType = ENC_YUV422_INTERLEAVED_YUYV; #endif break; case OMX_COLOR_FormatCbYCrY: #ifdef ENC6280 pp_config.yuvType = ENC_YUV422_INTERLEAVED_UYVY; #endif #ifdef ENC7280 pp_config.inputType = ENC_YUV422_INTERLEAVED_UYVY; #endif break; case OMX_COLOR_Format16bitRGB565: #ifdef ENC6280 pp_config.yuvType = ENC_RGB565; #endif #ifdef ENC7280 pp_config.inputType = ENC_RGB565; #endif break; case OMX_COLOR_Format16bitBGR565: #ifdef ENC6280 pp_config.yuvType = ENC_BGR565; #endif #ifdef ENC7280 pp_config.inputType = ENC_BGR565; #endif break; case OMX_COLOR_Format16bitARGB4444: #ifdef ENC6280 pp_config.yuvType = ENC_RGB444; #endif #ifdef ENC7280 pp_config.inputType = ENC_RGB444; #endif break; case OMX_COLOR_Format16bitARGB1555: #ifdef ENC6280 pp_config.yuvType = ENC_RGB555; #endif #ifdef ENC7280 pp_config.inputType = ENC_RGB555; #endif break; default: ret = ENC_INVALID_ARGUMENT; break; } switch (params->pp_config.angle) { case 0: pp_config.rotation = ENC_ROTATE_0; break; case 90: pp_config.rotation = ENC_ROTATE_90R; break; case 270: pp_config.rotation = ENC_ROTATE_90L; break; default: ret = ENC_INVALID_ARGUMENT; break; } // Enables or disables the video stabilization function. Set to a non-zero value will // enable the stabilization. The input image’s dimensions (origWidth, origHeight) // have to be at least 8 pixels bigger than the final encoded image’s. Also when // enabled the cropping offset (xOffset, yOffset) values are ignored. this->bStabilize = params->pp_config.frameStabilization; pp_config.videoStabilization = params->pp_config.frameStabilization; if (ret == ENC_OK) { ret = MP4EncSetPreProcessing(this->instance, &pp_config); } } if (ret != ENC_OK) { OSAL_Free(this); return NULL; } return (ENCODER_PROTOTYPE*) this; }