302 lines
8.2 KiB
C++
302 lines
8.2 KiB
C++
/*
|
|
* 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 <utils/AmlMpUtils.h>
|
|
#include "AmlWVIptvCas.h"
|
|
#include <dlfcn.h>
|
|
#include <cutils/properties.h>
|
|
#include "utils/Amlsysfsutils.h"
|
|
#include <unistd.h>
|
|
#include "wvcas/include/amCasIPTV.h"
|
|
#include <utils/AmlMpLog.h>
|
|
|
|
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<uint8_t *>(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<uint8_t *>(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<uint8_t *>(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<uint8_t *>(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);
|
|
}
|
|
|
|
}
|