CODEC_STATE HantroHwEncOmx_encoder_frame_rate_vp8(ENCODER_PROTOTYPE* arg, OMX_U32 xFramerate) { ENCODER_VP8* this = (ENCODER_VP8*)arg; this->nEstTimeInc = (OMX_U32) (TIME_RESOLUTION / Q16_FLOAT(xFramerate)); return CODEC_OK; }
CODEC_STATE HantroHwEncOmx_encoder_frame_rate_mpeg4(ENCODER_PROTOTYPE* arg, OMX_U32 xFramerate) { ENCODER_MPEG4* this = (ENCODER_MPEG4*)arg; this->nTickIncrement = (OMX_U32) (TIME_RESOLUTION_MPEG4 / Q16_FLOAT(xFramerate)); return CODEC_OK; }
// 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 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; }