/* * Copyright (c) 2020 Amlogic, Inc. All rights reserved. * * This source code is subject to the terms and conditions defined in the * file 'LICENSE' which is part of this source code package. * * Description: */ #define LOG_TAG "AmlWVIptvCas" #include #include "AmlWVIptvCas.h" #include #include #include "utils/Amlsysfsutils.h" #include #include "wvcas/include/amCasIPTV.h" #include const int convertToAmlMPErrorCode(AmCasCode_t casResult) { switch (casResult) { case AM_CAS_SUCCESS: return AML_MP_OK; case AM_CAS_ERROR: return AML_MP_ERROR; case AM_CAS_ERR_SYS: return AML_MP_ERROR_PERMISSION_DENIED; default: return AML_MP_ERROR; } } namespace aml_mp { AmlWVIptvCas::AmlWVIptvCas(Aml_MP_CASServiceType serviceType) :AmlCasBase(serviceType) { snprintf(mName, sizeof(mName), "%s_%d", LOG_TAG, mInstanceId); MLOGI("ctor AmlWVIptvCas"); } AmlWVIptvCas::~AmlWVIptvCas() { MLOGI("dtor AmlWVIptvCas"); int ret = 0; if (pIptvCas) { delete pIptvCas; pIptvCas = nullptr; } } int AmlWVIptvCas::startDescrambling(const Aml_MP_IptvCASParams* param) { MLOG(); AmlCasBase::startDescrambling(params); int ret = 0; CasStreamInfo initPara; initPara.ca_system_id = param->caSystemId; initPara.video_pid = param->videoPid; initPara.audio_pid = param->audioPid; initPara.ecm_pid[0] = param->ecmPid[0]; initPara.ecm_pid[1] = param->ecmPid[1]; initPara.av_diff_ecm = false; if (initPara.ecm_pid[0] != 0x1FFF && initPara.ecm_pid[1] != 0x1FFF && initPara.ecm_pid[0] != initPara.ecm_pid[1]) { initPara.av_diff_ecm = true; } MLOGI("%s,vpid=0x%x,apid=0x%x,ecmpid=0x%x,0x%x", __func__, initPara.video_pid, initPara.audio_pid, initPara.ecm_pid[0], initPara.ecm_pid[1]); bool useThirdPartyLicServer = false; char value[PROPERTY_VALUE_MAX] = {0}; property_get("wvcas.proxy.vendor", value, "GOOGLE"); if (!memcmp(value, "GOOGLE",6) && param->private_size == 0) { useThirdPartyLicServer = false; MLOGI("wvcas use google default license server.\n"); } else { useThirdPartyLicServer = true; MLOGI("wvcas use third-party license server.\n"); } if (useThirdPartyLicServer) { uint8_t *pdata = const_cast(param->private_data); initPara.private_data = pdata; //get from pmt initPara.pri_data_len = param->private_size; MLOGI("wvcas use third private data: 0x%x,0x%x, len=%d", initPara.private_data[0],initPara.private_data[1], initPara.pri_data_len); } else { initPara.private_data = NULL; initPara.pri_data_len = 0; } initPara.headers = NULL; //initPara->headers = cas_stream_info->headers; pIptvCas = new AmCasIPTV(); if (pIptvCas == nullptr) { MLOGE(" call AmCasIPTV() failed"); return; } mFirstEcm = 0; pIptvCas->mCasObjIdx = mInstanceId; int ret = 0; ret = pIptvCas->setPrivateData((void *)&initPara, sizeof(CasStreamInfo)); MLOGE(" after call AmCasIPTV() setPrivateData, ret=%d", ret); if (ret != 0) { MLOGI("setPrivateData failed, ret =%d", ret); return; } ret = pIptvCas->provision(); MLOGE(" after call AmCasIPTV() provision, ret=%d", ret); if (ret != 0) { MLOGI("provision failed, ret =%d", ret); return; } if (pIptvCas) { setDscSource(); MLOGI("%s, vpid=0x%x, apid=0x%x", __func__, mIptvCasParam.videoPid, mIptvCasParam.audioPid); pIptvCas->setPids(mIptvCasParam.videoPid, mIptvCasParam.audioPid); ret = pIptvCas->openSession(&sessionId[0]); } return convertToAmlMPErrorCode((AmCasCode_t)ret); } int AmlWVIptvCas::stopDescrambling() { MLOGI("closeSession"); int ret = 0; if (pIptvCas) { ret = pIptvCas->closeSession(&sessionId[0]); } return convertToAmlMPErrorCode((AmCasCode_t)ret); } int AmlWVIptvCas::setPrivateData(const uint8_t* data, size_t size) { int ret = 0; if (pIptvCas) { uint8_t *pdata = const_cast(data); ret = pIptvCas->setPrivateData((void*)pdata, size); if (ret != 0) { MLOGI("setPrivateData failed, ret =%d", ret); return convertToAmlMPErrorCode((AmCasCode_t)ret); } } return convertToAmlMPErrorCode((AmCasCode_t)ret); } int AmlWVIptvCas::checkEcmProcess(uint8_t* pBuffer, uint32_t vEcmPid, uint32_t aEcmPid,size_t * nSize) { int ret = 0; int len = 0,pid = 0; unsigned int rem = *nSize; uint8_t * psync = pBuffer; uint8_t * current = NULL; while (rem >= TS_PACKET_SIZE) { if (*psync != 0x47) { ++psync; --rem; continue; } if ((*(psync) == 0x47) && ((rem == TS_PACKET_SIZE) || (*(psync+TS_PACKET_SIZE) == 0x47))) { current = psync; pid = (( current[1] << 8 | current[2]) & 0x1FFF); if (pid == vEcmPid || pid == aEcmPid) { if (memcmp(mEcmTsPacket + 4,psync + 4,TS_PACKET_SIZE- 4)) { memcpy(mEcmTsPacket, psync, TS_PACKET_SIZE); std::string ecmDataStr; char hex[3]; for (int i = 0; i < 64; i++) { snprintf(hex, sizeof(hex), "%02X", mEcmTsPacket[i]); ecmDataStr.append(hex); ecmDataStr.append(" "); } MLOGI("checkEcmProcess, ecmDataStr.c_str()=%s", ecmDataStr.c_str()); if (pIptvCas) ret = pIptvCas->processEcm(0, pid, mEcmTsPacket, TS_PACKET_SIZE); } if (mFirstEcm != 1) { MLOGI("first_SetECM find\n"); mFirstEcm = 1; } } } psync += TS_PACKET_SIZE; rem -= TS_PACKET_SIZE; } return convertToAmlMPErrorCode((AmCasCode_t)ret); } int AmlWVIptvCas::processEcm(bool isSection, int ecmPid, const uint8_t* data, size_t size) { int ret = 0; //==============FIXME============= if (pIptvCas) { uint8_t *pdata = const_cast(data); MLOGV("%s, pid=0x%x, size=%zu", __func__, mIptvCasParam.videoPid, size); if (size < 188) { MLOGI("%s, pid=0x%x, size=%zu", __func__, mIptvCasParam.videoPid, size); ret = pIptvCas->processEcm(1, mIptvCasParam.ecmPid[0] ,pdata, size); } else { // checkEcmProcess(pdata, mIptvCasParam.ecmPid[0], mIptvCasParam.ecmPid[1], &size); } } return convertToAmlMPErrorCode((AmCasCode_t)ret); } int AmlWVIptvCas::processEmm(bool isSection, int emmPid, const uint8_t* data, size_t size) { int ret = 0; if (pIptvCas) { uint8_t *pdata = const_cast(data); ret = pIptvCas->processEmm(isSection, emmPid, pdata, size); } return convertToAmlMPErrorCode((AmCasCode_t)ret); } int AmlWVIptvCas::dscDevOpen(const char *port_addr, int flags) { int r; int retry_open_times = 0; retry_open: r = open(port_addr, flags); if (r < 0 /*&& r == EBUSY */) { retry_open_times++; usleep(10*1000); if (retry_open_times < 100) { goto retry_open; } MLOGI("retry_open [%s] failed,ret = %d error=%d used_times=%d*10(ms)\n", port_addr, r, errno, retry_open_times); return r; } if (retry_open_times > 0) { MLOGI("retry_open [%s] success\n", port_addr); } return (int)r; } int AmlWVIptvCas::setDscSource() { int ret = 0; bool use_hw_multi_demux = false; if (isSupportMultiHwDemux()) { MLOGI("Work with Hw Multi Demux."); use_hw_multi_demux = true; } else { MLOGI("Work with Hw Demux."); use_hw_multi_demux = false; } #if 1 if (!use_hw_multi_demux) { ret = amsysfs_set_sysfs_str(DMX0_SOURCE_PATH, DMX_SRC); if (ret) MLOGI("Error ret 0x%x\n", ret); ret = amsysfs_set_sysfs_str(DSC0_SOURCE_PATH, DSC_SRC); if (ret) MLOGI("Error ret 0x%x\n", ret); } #endif return convertToAmlMPErrorCode((AmCasCode_t)ret); } }