NVENCSTATUS CNvHWEncoder::NvEncEncodeFrame(EncodeBuffer *pEncodeBuffer, NvEncPictureCommand *encPicCommand, uint32_t width, uint32_t height, NV_ENC_PIC_STRUCT ePicStruct, int8_t *qpDeltaMapArray, uint32_t qpDeltaMapArraySize) { NVENCSTATUS nvStatus = NV_ENC_SUCCESS; NV_ENC_PIC_PARAMS encPicParams; memset(&encPicParams, 0, sizeof(encPicParams)); SET_VER(encPicParams, NV_ENC_PIC_PARAMS); encPicParams.inputBuffer = pEncodeBuffer->stInputBfr.hInputSurface; encPicParams.bufferFmt = pEncodeBuffer->stInputBfr.bufferFmt; encPicParams.inputWidth = width; encPicParams.inputHeight = height; encPicParams.outputBitstream = pEncodeBuffer->stOutputBfr.hBitstreamBuffer; encPicParams.completionEvent = pEncodeBuffer->stOutputBfr.hOutputEvent; encPicParams.inputTimeStamp = m_EncodeIdx; encPicParams.pictureStruct = ePicStruct; encPicParams.qpDeltaMap = qpDeltaMapArray; encPicParams.qpDeltaMapSize = qpDeltaMapArraySize; if (encPicCommand) { if (encPicCommand->bForceIDR) { encPicParams.encodePicFlags |= NV_ENC_PIC_FLAG_FORCEIDR; } if (encPicCommand->bForceIntraRefresh) { if (codecGUID == NV_ENC_CODEC_HEVC_GUID) { encPicParams.codecPicParams.hevcPicParams.forceIntraRefreshWithFrameCnt = encPicCommand->intraRefreshDuration; } else { encPicParams.codecPicParams.h264PicParams.forceIntraRefreshWithFrameCnt = encPicCommand->intraRefreshDuration; } } } #if 0 // иокг encPicParams.codecPicParams.h264PicParams.sliceMode = 3; encPicParams.codecPicParams.h264PicParams.sliceModeData= 5; encPicParams.codecPicParams.h264PicParams.sliceModeDataUpdate=1; #endif nvStatus = m_pEncodeAPI->nvEncEncodePicture(m_hEncoder, &encPicParams); if (nvStatus != NV_ENC_SUCCESS && nvStatus != NV_ENC_ERR_NEED_MORE_INPUT) { assert(0); return nvStatus; } m_EncodeIdx++; return NV_ENC_SUCCESS; }
CNvHWEncoder::CNvHWEncoder() { m_hEncoder = NULL; m_bEncoderInitialized = false; m_pEncodeAPI = NULL; m_hinstLib = NULL; m_fOutput = NULL; m_EncodeIdx = 0; m_uCurWidth = 0; m_uCurHeight = 0; m_uMaxWidth = 0; m_uMaxHeight = 0; memset(&m_stCreateEncodeParams, 0, sizeof(m_stCreateEncodeParams)); SET_VER(m_stCreateEncodeParams, NV_ENC_INITIALIZE_PARAMS); memset(&m_stEncodeConfig, 0, sizeof(m_stEncodeConfig)); SET_VER(m_stEncodeConfig, NV_ENC_CONFIG); }
NVENCSTATUS CNvHWEncoder::NvEncFlushEncoderQueue(void *hEOSEvent) { NVENCSTATUS nvStatus = NV_ENC_SUCCESS; NV_ENC_PIC_PARAMS encPicParams; memset(&encPicParams, 0, sizeof(encPicParams)); SET_VER(encPicParams, NV_ENC_PIC_PARAMS); encPicParams.encodePicFlags = NV_ENC_PIC_FLAG_EOS; encPicParams.completionEvent = hEOSEvent; nvStatus = m_pEncodeAPI->nvEncEncodePicture(m_hEncoder, &encPicParams); if (nvStatus != NV_ENC_SUCCESS) { assert(0); } return nvStatus; }
NVENCSTATUS CNvHWEncoder::ProcessOutput(const EncodeBuffer *pEncodeBuffer) { NVENCSTATUS nvStatus = NV_ENC_SUCCESS; if (pEncodeBuffer->stOutputBfr.hBitstreamBuffer == NULL && pEncodeBuffer->stOutputBfr.bEOSFlag == FALSE) { return NV_ENC_ERR_INVALID_PARAM; } if (pEncodeBuffer->stOutputBfr.bWaitOnEvent == TRUE) { if (!pEncodeBuffer->stOutputBfr.hOutputEvent) { return NV_ENC_ERR_INVALID_PARAM; } #if defined(NV_WINDOWS) WaitForSingleObject(pEncodeBuffer->stOutputBfr.hOutputEvent, INFINITE); #endif } if (pEncodeBuffer->stOutputBfr.bEOSFlag) return NV_ENC_SUCCESS; nvStatus = NV_ENC_SUCCESS; NV_ENC_LOCK_BITSTREAM lockBitstreamData; memset(&lockBitstreamData, 0, sizeof(lockBitstreamData)); SET_VER(lockBitstreamData, NV_ENC_LOCK_BITSTREAM); lockBitstreamData.outputBitstream = pEncodeBuffer->stOutputBfr.hBitstreamBuffer; lockBitstreamData.doNotWait = false; nvStatus = m_pEncodeAPI->nvEncLockBitstream(m_hEncoder, &lockBitstreamData); if (nvStatus == NV_ENC_SUCCESS) { fwrite(lockBitstreamData.bitstreamBufferPtr, 1, lockBitstreamData.bitstreamSizeInBytes, m_fOutput); nvStatus = m_pEncodeAPI->nvEncUnlockBitstream(m_hEncoder, pEncodeBuffer->stOutputBfr.hBitstreamBuffer); } else { PRINTERR("lock bitstream function failed \n"); } return nvStatus; }
NVENCSTATUS CNvHWEncoder::NvEncMapInputResource(void* registeredResource, void** mappedResource) { NVENCSTATUS nvStatus = NV_ENC_SUCCESS; NV_ENC_MAP_INPUT_RESOURCE mapInputResParams; memset(&mapInputResParams, 0, sizeof(mapInputResParams)); SET_VER(mapInputResParams, NV_ENC_MAP_INPUT_RESOURCE); mapInputResParams.registeredResource = registeredResource; nvStatus = m_pEncodeAPI->nvEncMapInputResource(m_hEncoder, &mapInputResParams); if (nvStatus != NV_ENC_SUCCESS) { assert(0); } *mappedResource = mapInputResParams.mappedResource; return nvStatus; }
NVENCSTATUS CNvHWEncoder::NvEncLockInputBuffer(void* inputBuffer, void** bufferDataPtr, uint32_t* pitch) { NVENCSTATUS nvStatus = NV_ENC_SUCCESS; NV_ENC_LOCK_INPUT_BUFFER lockInputBufferParams; memset(&lockInputBufferParams, 0, sizeof(lockInputBufferParams)); SET_VER(lockInputBufferParams, NV_ENC_LOCK_INPUT_BUFFER); lockInputBufferParams.inputBuffer = inputBuffer; nvStatus = m_pEncodeAPI->nvEncLockInputBuffer(m_hEncoder, &lockInputBufferParams); if (nvStatus != NV_ENC_SUCCESS) { assert(0); } *bufferDataPtr = lockInputBufferParams.bufferDataPtr; *pitch = lockInputBufferParams.pitch; return nvStatus; }
//NOT USED UNDER LINUX NVENCSTATUS CNvHWEncoder::NvEncRegisterAsyncEvent(void** completionEvent) { NVENCSTATUS nvStatus = NV_ENC_SUCCESS; NV_ENC_EVENT_PARAMS eventParams; memset(&eventParams, 0, sizeof(eventParams)); SET_VER(eventParams, NV_ENC_EVENT_PARAMS); eventParams.completionEvent = NULL; nvStatus = m_pEncodeAPI->nvEncRegisterAsyncEvent(m_hEncoder, &eventParams); if (nvStatus != NV_ENC_SUCCESS) { assert(0); } *completionEvent = eventParams.completionEvent; return nvStatus; }
NVENCSTATUS CNvHWEncoder::NvEncOpenEncodeSessionEx(void* device, NV_ENC_DEVICE_TYPE deviceType) { NVENCSTATUS nvStatus = NV_ENC_SUCCESS; NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS openSessionExParams; memset(&openSessionExParams, 0, sizeof(openSessionExParams)); SET_VER(openSessionExParams, NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS); openSessionExParams.device = device; openSessionExParams.deviceType = deviceType; openSessionExParams.reserved = NULL; openSessionExParams.apiVersion = NVENCAPI_VERSION; nvStatus = m_pEncodeAPI->nvEncOpenEncodeSessionEx(&openSessionExParams, &m_hEncoder); if (nvStatus != NV_ENC_SUCCESS) { assert(0); } return nvStatus; }
NVENCSTATUS CNvHWEncoder::NvEncCreateBitstreamBuffer(uint32_t size, void** bitstreamBuffer) { NVENCSTATUS nvStatus = NV_ENC_SUCCESS; NV_ENC_CREATE_BITSTREAM_BUFFER createBitstreamBufferParams; memset(&createBitstreamBufferParams, 0, sizeof(createBitstreamBufferParams)); SET_VER(createBitstreamBufferParams, NV_ENC_CREATE_BITSTREAM_BUFFER); createBitstreamBufferParams.size = size; createBitstreamBufferParams.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_CACHED; nvStatus = m_pEncodeAPI->nvEncCreateBitstreamBuffer(m_hEncoder, &createBitstreamBufferParams); if (nvStatus != NV_ENC_SUCCESS) { assert(0); } *bitstreamBuffer = createBitstreamBufferParams.bitstreamBuffer; return nvStatus; }
NVENCSTATUS CNvHWEncoder::NvEncRegisterAsyncEvent(void** completionEvent) { NVENCSTATUS nvStatus = NV_ENC_SUCCESS; NV_ENC_EVENT_PARAMS eventParams; memset(&eventParams, 0, sizeof(eventParams)); SET_VER(eventParams, NV_ENC_EVENT_PARAMS); #if defined (NV_WINDOWS) eventParams.completionEvent = CreateEvent(NULL, FALSE, FALSE, NULL); #else eventParams.completionEvent = NULL; #endif nvStatus = m_pEncodeAPI->nvEncRegisterAsyncEvent(m_hEncoder, &eventParams); if (nvStatus != NV_ENC_SUCCESS) { assert(0); } *completionEvent = eventParams.completionEvent; return nvStatus; }
NVENCSTATUS CNvHWEncoder::NvEncCreateInputBuffer(uint32_t width, uint32_t height, void** inputBuffer, uint32_t isYuv444) { NVENCSTATUS nvStatus = NV_ENC_SUCCESS; NV_ENC_CREATE_INPUT_BUFFER createInputBufferParams; memset(&createInputBufferParams, 0, sizeof(createInputBufferParams)); SET_VER(createInputBufferParams, NV_ENC_CREATE_INPUT_BUFFER); createInputBufferParams.width = width; createInputBufferParams.height = height; createInputBufferParams.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_CACHED; createInputBufferParams.bufferFmt = isYuv444 ? NV_ENC_BUFFER_FORMAT_YUV444_PL : NV_ENC_BUFFER_FORMAT_NV12_PL; nvStatus = m_pEncodeAPI->nvEncCreateInputBuffer(m_hEncoder, &createInputBufferParams); if (nvStatus != NV_ENC_SUCCESS) { assert(0); } *inputBuffer = createInputBufferParams.inputBuffer; return nvStatus; }
NVENCSTATUS CNvHWEncoder::NvEncRegisterResource(NV_ENC_INPUT_RESOURCE_TYPE resourceType, void* resourceToRegister, uint32_t width, uint32_t height, uint32_t pitch, void** registeredResource) { NVENCSTATUS nvStatus = NV_ENC_SUCCESS; NV_ENC_REGISTER_RESOURCE registerResParams; memset(®isterResParams, 0, sizeof(registerResParams)); SET_VER(registerResParams, NV_ENC_REGISTER_RESOURCE); registerResParams.resourceType = resourceType; registerResParams.resourceToRegister = resourceToRegister; registerResParams.width = width; registerResParams.height = height; registerResParams.pitch = pitch; nvStatus = m_pEncodeAPI->nvEncRegisterResource(m_hEncoder, ®isterResParams); if (nvStatus != NV_ENC_SUCCESS) { assert(0); } *registeredResource = registerResParams.registeredResource; return nvStatus; }
NVENCSTATUS CNvHWEncoder::CreateEncoder(const EncodeConfig *pEncCfg) { NVENCSTATUS nvStatus = NV_ENC_SUCCESS; if (pEncCfg == NULL) { return NV_ENC_ERR_INVALID_PARAM; } m_uCurWidth = pEncCfg->width; m_uCurHeight = pEncCfg->height; m_uMaxWidth = (pEncCfg->maxWidth > 0 ? pEncCfg->maxWidth : pEncCfg->width); m_uMaxHeight = (pEncCfg->maxHeight > 0 ? pEncCfg->maxHeight : pEncCfg->height); if ((m_uCurWidth > m_uMaxWidth) || (m_uCurHeight > m_uMaxHeight)) { return NV_ENC_ERR_INVALID_PARAM; } m_fOutput = pEncCfg->fOutput; if (!pEncCfg->width || !pEncCfg->height || !m_fOutput) { return NV_ENC_ERR_INVALID_PARAM; } GUID inputCodecGUID = pEncCfg->codec == NV_ENC_H264 ? NV_ENC_CODEC_H264_GUID : NV_ENC_CODEC_HEVC_GUID; nvStatus = ValidateEncodeGUID(inputCodecGUID); if (nvStatus != NV_ENC_SUCCESS) { PRINTERR("codec not supported \n"); return nvStatus; } codecGUID = inputCodecGUID; m_stCreateEncodeParams.encodeGUID = inputCodecGUID; m_stCreateEncodeParams.presetGUID = pEncCfg->presetGUID; m_stCreateEncodeParams.encodeWidth = pEncCfg->width; m_stCreateEncodeParams.encodeHeight = pEncCfg->height; m_stCreateEncodeParams.darWidth = pEncCfg->width; m_stCreateEncodeParams.darHeight = pEncCfg->height; m_stCreateEncodeParams.frameRateNum = pEncCfg->fps; m_stCreateEncodeParams.frameRateDen = 1; #if defined(NV_WINDOWS) m_stCreateEncodeParams.enableEncodeAsync = 1; #else m_stCreateEncodeParams.enableEncodeAsync = 0; #endif m_stCreateEncodeParams.enablePTD = 1; m_stCreateEncodeParams.reportSliceOffsets = 0; m_stCreateEncodeParams.enableSubFrameWrite = 0; m_stCreateEncodeParams.encodeConfig = &m_stEncodeConfig; m_stCreateEncodeParams.maxEncodeWidth = m_uMaxWidth; m_stCreateEncodeParams.maxEncodeHeight = m_uMaxHeight; // apply preset NV_ENC_PRESET_CONFIG stPresetCfg; memset(&stPresetCfg, 0, sizeof(NV_ENC_PRESET_CONFIG)); SET_VER(stPresetCfg, NV_ENC_PRESET_CONFIG); SET_VER(stPresetCfg.presetCfg, NV_ENC_CONFIG); nvStatus = m_pEncodeAPI->nvEncGetEncodePresetConfig(m_hEncoder, m_stCreateEncodeParams.encodeGUID, m_stCreateEncodeParams.presetGUID, &stPresetCfg); if (nvStatus != NV_ENC_SUCCESS) { PRINTERR("nvEncGetEncodePresetConfig returned failure"); return nvStatus; } memcpy(&m_stEncodeConfig, &stPresetCfg.presetCfg, sizeof(NV_ENC_CONFIG)); m_stEncodeConfig.gopLength = pEncCfg->gopLength; m_stEncodeConfig.frameIntervalP = pEncCfg->numB + 1; if (pEncCfg->pictureStruct == NV_ENC_PIC_STRUCT_FRAME) { m_stEncodeConfig.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME; } else { m_stEncodeConfig.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD; } m_stEncodeConfig.mvPrecision = NV_ENC_MV_PRECISION_QUARTER_PEL; if (pEncCfg->bitrate || pEncCfg->vbvMaxBitrate) { m_stEncodeConfig.rcParams.rateControlMode = (NV_ENC_PARAMS_RC_MODE)pEncCfg->rcMode; m_stEncodeConfig.rcParams.averageBitRate = pEncCfg->bitrate; m_stEncodeConfig.rcParams.maxBitRate = pEncCfg->vbvMaxBitrate; m_stEncodeConfig.rcParams.vbvBufferSize = pEncCfg->vbvSize; m_stEncodeConfig.rcParams.vbvInitialDelay = pEncCfg->vbvSize * 9 / 10; } else { m_stEncodeConfig.rcParams.rateControlMode = NV_ENC_PARAMS_RC_CONSTQP; } if (pEncCfg->rcMode == 0) { m_stEncodeConfig.rcParams.constQP.qpInterP = pEncCfg->presetGUID == NV_ENC_PRESET_LOSSLESS_HP_GUID? 0 : pEncCfg->qp; m_stEncodeConfig.rcParams.constQP.qpInterB = pEncCfg->presetGUID == NV_ENC_PRESET_LOSSLESS_HP_GUID? 0 : pEncCfg->qp; m_stEncodeConfig.rcParams.constQP.qpIntra = pEncCfg->presetGUID == NV_ENC_PRESET_LOSSLESS_HP_GUID? 0 : pEncCfg->qp; } if (pEncCfg->isYuv444) { m_stEncodeConfig.encodeCodecConfig.h264Config.chromaFormatIDC = 3; } else { m_stEncodeConfig.encodeCodecConfig.h264Config.chromaFormatIDC = 1; } if (pEncCfg->intraRefreshEnableFlag) { if (pEncCfg->codec == NV_ENC_HEVC) { m_stEncodeConfig.encodeCodecConfig.hevcConfig.enableIntraRefresh = 1; m_stEncodeConfig.encodeCodecConfig.hevcConfig.intraRefreshPeriod = pEncCfg->intraRefreshPeriod; m_stEncodeConfig.encodeCodecConfig.hevcConfig.intraRefreshCnt = pEncCfg->intraRefreshDuration; } else { m_stEncodeConfig.encodeCodecConfig.h264Config.enableIntraRefresh = 1; m_stEncodeConfig.encodeCodecConfig.h264Config.intraRefreshPeriod = pEncCfg->intraRefreshPeriod; m_stEncodeConfig.encodeCodecConfig.h264Config.intraRefreshCnt = pEncCfg->intraRefreshDuration; } } if (pEncCfg->invalidateRefFramesEnableFlag) { if (pEncCfg->codec == NV_ENC_HEVC) { m_stEncodeConfig.encodeCodecConfig.hevcConfig.maxNumRefFramesInDPB = 16; } else { m_stEncodeConfig.encodeCodecConfig.h264Config.maxNumRefFrames = 16; } } if (pEncCfg->qpDeltaMapFile) { m_stEncodeConfig.rcParams.enableExtQPDeltaMap = 1; } if (pEncCfg->codec == NV_ENC_H264) { m_stEncodeConfig.encodeCodecConfig.h264Config.idrPeriod = pEncCfg->gopLength; } else if (pEncCfg->codec == NV_ENC_HEVC) { m_stEncodeConfig.encodeCodecConfig.hevcConfig.idrPeriod = pEncCfg->gopLength; } nvStatus = m_pEncodeAPI->nvEncInitializeEncoder(m_hEncoder, &m_stCreateEncodeParams); if (nvStatus != NV_ENC_SUCCESS) { PRINTERR("Encode Session Initialization failed"); return nvStatus; } m_bEncoderInitialized = true; return nvStatus; }
static int __init stx7200_audio_devices_setup(void) { int result; int ver; if (cpu_data->type != CPU_STX7200) { BUG(); return -ENODEV; } /* We assume farther that MEM resource is first, let's check it... */ BUG_ON(stx7200_spdif_player.resource[0].flags != IORESOURCE_MEM); BUG_ON(stx7200_hdmi_pcm_player.resource[0].flags != IORESOURCE_MEM); BUG_ON(stx7200_hdmi_spdif_player.resource[0].flags != IORESOURCE_MEM); switch (cpu_data->cut_major) { case 1: SET_VER(snd_stm_pcm_player_info, stx7200_pcm_player_0, 5); SET_VER(snd_stm_pcm_player_info, stx7200_pcm_player_1, 5); SET_VER(snd_stm_pcm_player_info, stx7200_pcm_player_2, 5); SET_VER(snd_stm_pcm_player_info, stx7200_pcm_player_3, 5); SET_VER(snd_stm_spdif_player_info, stx7200_spdif_player, 3); stx7200_spdif_player.resource[0].end += 0x40; SET_VER(snd_stm_pcm_player_info, stx7200_hdmi_pcm_player, 5); stx7200_hdmi_pcm_player.resource[0].start = 0xfd106d00; stx7200_hdmi_pcm_player.resource[0].end = 0xfd106d27; SET_VER(snd_stm_spdif_player_info, stx7200_hdmi_spdif_player, 3); stx7200_hdmi_spdif_player.resource[0].start = 0xfd106c00; stx7200_hdmi_spdif_player.resource[0].end = 0xfd106c3f; SET_VER(snd_stm_pcm_reader_info, stx7200_pcm_reader_0, 3); break; case 2 ... 3: SET_VER(snd_stm_pcm_player_info, stx7200_pcm_player_0, 6); SET_VER(snd_stm_pcm_player_info, stx7200_pcm_player_1, 6); SET_VER(snd_stm_pcm_player_info, stx7200_pcm_player_2, 6); SET_VER(snd_stm_pcm_player_info, stx7200_pcm_player_3, 6); SET_VER(snd_stm_spdif_player_info, stx7200_spdif_player, 4); stx7200_spdif_player.resource[0].end += 0x44; SET_VER(snd_stm_pcm_player_info, stx7200_hdmi_pcm_player, 6); stx7200_hdmi_pcm_player.resource[0].start = 0xfd112d00; stx7200_hdmi_pcm_player.resource[0].end = 0xfd112d27; SET_VER(snd_stm_spdif_player_info, stx7200_hdmi_spdif_player, 4); stx7200_hdmi_spdif_player.resource[0].start = 0xfd112c00; stx7200_hdmi_spdif_player.resource[0].end = 0xfd112c43; ver = (cpu_data->cut_major == 2 ? 5 : 6); SET_VER(snd_stm_pcm_reader_info, stx7200_pcm_reader_0, ver); SET_VER(snd_stm_pcm_reader_info, stx7200_pcm_reader_1, ver); break; default: printk(KERN_ERR "%s(): Not supported STx7200 cut %d detected!" "\n", __func__, cpu_data->cut_major); return -ENODEV; } /* Ugly but quick hack to have HDMI SPDIF player & I2S to SPDIF * converters enabled without loading STMFB... * TODO: do this in some sane way! */ { void *hdmi_gpout; if (cpu_data->cut_major == 1) hdmi_gpout = ioremap(0xfd106020, 4); else hdmi_gpout = ioremap(0xfd112020, 4); writel(readl(hdmi_gpout) | 0x3, hdmi_gpout); iounmap(hdmi_gpout); } result = platform_add_devices(stx7200_audio_devices, ARRAY_SIZE(stx7200_audio_devices)); if (result == 0 && cpu_data->cut_major > 1) result = platform_add_devices(stx7200_cut2_audio_devices, ARRAY_SIZE(stx7200_cut2_audio_devices)); return result; }