Files
BPI-CM9-Linux/aml-comp/multimedia/aml_mp_sdk/player/Aml_MP_PlayerClient.cpp
T

1551 lines
50 KiB
C++
Raw Normal View History

2026-08-13 11:28:40 +08:00
/*
* Copyright (c) 2026 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: Amlogic MP SDK Player Client Implementation
*/
#ifdef CONFIG_AMP_SERVER
#define LOG_TAG "Aml_MP_PlayerClient"
#include "Aml_MP/Aml_MP.h"
#include "Aml_MP_PlayerClient.h"
#include "utils/AmlMpUtils.h"
#include "utils/AmlMpLog.h"
#include "cas/AmlDvbCasHal.h"
#include "cas/AmlCasBase.h"
#include "AmlTsParser.h"
#include "AmlMpAidlConvert.h"
#include "Amlsysfsutils.h"
#include <vector>
#include <ctime>
#include <cutils/properties.h>
#include <binder/IServiceManager.h>
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <utils/String16.h>
#include <android/binder_manager.h>
#include <android/binder_interface_utils.h>
#include <aidl/com/amlogic/aml_mp/player/IAmlMpPlayer.h>
#define TEMP_BUFFER_SIZE (188 * 100)
using android::sp;
using android::IBinder;
using android::IServiceManager;
using android::defaultServiceManager;
using android::String16;
using namespace com::amlogic::aml_mp::player;
void AmpMpPlayerDumpFile(const char *name, const uint8_t* data, int32_t len)
{
if (!property_get_bool("vendor.media.aml_mp.client.dump", false)) {
return;
}
char saveName[100] = { 0 };
snprintf(saveName, sizeof(saveName), "/data/%s_client.ts", name);
FILE *dumpFile = fopen(saveName, "ab");
if (dumpFile == nullptr) {
ALOGE("%s open dump ts failed:%s", name, strerror(errno));
return;
}
fwrite(data, 1, len, dumpFile);
fflush(dumpFile);
fclose(dumpFile);
}
Aml_MP_PlayerClient::Aml_MP_PlayerClient(const Aml_MP_PlayerCreateParams* createParams)
: mCreateParams(*createParams),
mServiceConnected(false) {
snprintf(mName, sizeof(mName), "%s", LOG_TAG);
MLOGI("enter %s", __FUNCTION__);
int32_t result = -1;
if (mCreateParams.drmMode != AML_MP_INPUT_STREAM_SECURE_MEMORY) {
InitBufPool();
}
connectToService();
if (!mServiceConnected) {
MLOGE("connect server fail");
return;
}
mWriteBuffer = new aml_mp::AmlMpBuffer(TEMP_BUFFER_SIZE);
mWriteBuffer->setRange(0, 0);
mTsBuffer.init(aml_mp::AmlMpConfig::instance().mWriteBufferSize * 1024 * 1024); // 2M
AmlMpPlayerCreateParams aidlParams{};
convertToAidl(aidlParams, &mCreateParams);
auto status = mPlayerService->createPlayer(aidlParams, &result);
if (status.isOk()) {
player_id = result;
snprintf(mName, sizeof(mName), "%s_%p_%d", LOG_TAG, this, player_id);
} else {
MLOGE("server create player fail");
}
if (mBufPoolHasInit && !setBufPool2Servier()) {
MLOGI("set buf pool to server success.");
} else {
MLOGE("set buf pool to server fail.");
}
mWaitingEcmMode = (aml_mp::WaitingEcmMode)aml_mp::AmlMpConfig::instance().mWaitingEcmMode;
mWaitingEcmAtServer = property_get_bool("vendor.media.waitEcmServer.enable", mWaitingEcmAtServer);
MLOGI("ecmMode:%d, waitEcm from %s", mWaitingEcmMode, mWaitingEcmAtServer ? "server" : "client");
if (mWaitingEcmAtServer) {
if (makeCallbackToServer() != 0) {
MLOGE("why make callback fail");
}
}
MLOGI("exit %s, ", __FUNCTION__);
}
Aml_MP_PlayerClient::~Aml_MP_PlayerClient() {
std::lock_guard<std::mutex> lock(mutex);
MLOGI("call ~Aml_MP_PlayerClient");
int32_t result = -1;
if (mServiceConnected && mPlayerService && player_id > 0) {
MLOGI("[%s] destroy player %d", mName, player_id);
auto status = mPlayerService->destroyPlayer(player_id, &result);
}
if (mRawBinder && mRecipient) {
AIBinder_unlinkToDeath(mRawBinder, mRecipient, this);
}
if (mRecipient) {
AIBinder_DeathRecipient_delete(mRecipient);
}
mRawBinder = nullptr;
mRecipient = nullptr;
FreeBufPool();
clearTunnelId();
stopDescrambling_l();
mIsStandaloneCas = false;
mCasHandle.clear();
}
bool Aml_MP_PlayerClient::connectToService() {
if (!mBufPoolHasInit) {
MLOGE("not alloc buf pool, please check it.");
return false;
}
if (mServiceDead) {
return false;
}
if (mServiceConnected) {
return true;
}
std::lock_guard<std::mutex> lock(mutex);
const std::string serverName = std::string(IAmlMpPlayer::descriptor) + "/default";
MLOGI("connect to the service:%s", serverName.c_str());
mRawBinder = AServiceManager_waitForService(serverName.c_str());
if (!mRawBinder) {
MLOGE("service not found");
return false;
}
ndk::SpAIBinder binder(mRawBinder);
mPlayerService = IAmlMpPlayer::fromBinder(binder);
if (mPlayerService == nullptr) {
MLOGE("[%s] failed to obtain IAmlMpPlayer", mName);
return false;
}
if (!mRecipient) {
mRecipient = AIBinder_DeathRecipient_new(Aml_MP_PlayerClient::onBinderDied);
int ret = AIBinder_linkToDeath(mRawBinder, mRecipient, this);
if (ret != STATUS_OK) {
MLOGE("linkToDeath failed: %d", ret);
}
}
mServiceConnected = true;
MLOGI("connect to the service:%s successful", serverName.c_str());
return true;
}
void Aml_MP_PlayerClient::onBinderDied(void *cookie) {
ALOGE("IAmlMpPlayerService died!");
auto* self = static_cast<Aml_MP_PlayerClient*>(cookie);
std::lock_guard<std::mutex> _l(self->mutex);
self->mServiceDead = true;
self->mRawBinder = nullptr;
self->mServiceConnected = false;
}
int Aml_MP_PlayerClient::start() {
std::lock_guard<std::mutex> lock(mutex);
MLOG();
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
startDescrambling_l();
int32_t result = -1;
auto status = mPlayerService->start(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::stop() {
std::lock_guard<std::mutex> lock(mutex);
MLOG();
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->stop(player_id, &result);
stopDescrambling_l();
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::pause() {
std::lock_guard<std::mutex> lock(mutex);
MLOG();
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->pause(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::resume() {
std::lock_guard<std::mutex> lock(mutex);
MLOG();
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->resume(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::setVideoParams(const Aml_MP_VideoParams* params) {
MLOG();
RETURN_IF(-1, params == nullptr);
AmlMpVideoParams aidlParams{};
convertToAidl(aidlParams, params);
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->setVideoParams(player_id, aidlParams, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::setAudioParams(const Aml_MP_AudioParams* params) {
MLOG();
RETURN_IF(-1, params == nullptr);
AmlMpAudioParams aidlParams{};
convertToAidl(aidlParams, params);
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->setAudioParams(player_id, aidlParams, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::setSubtitleParams(const Aml_MP_SubtitleParams* params) {
MLOG();
RETURN_IF(-1, params == nullptr);
AmlMpSubtitleParams aidlParams{};
convertToAidl(aidlParams, params);
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->setSubtitleParams(player_id, aidlParams, &result);
return status.isOk() ? result : -1;
}
void Aml_MP_PlayerClient::setEcmPidToServer() {
if (mServiceDead || !mServiceConnected) {
MLOGE("sever not connect");
return;
}
if (!mWaitingEcmAtServer) {
return;
}
if (mEcmPids.empty()) {
MLOGE("why ecm pids is empty?");
return;
}
std::string dump;
for (auto pid : mEcmPids) {
dump += std::to_string(pid) + " ";
}
MLOGI("client will ecm pids:%s", dump.c_str());
AmlMpPlayerInvokeParams inParams{};
AmlMpPlayerInvokeParams outParams{};
inParams.invokeId = AML_MP_SERVER_PLAYER_ID_SET_ECM_PIDS;
inParams.intPayload = mEcmPids;
auto status = mPlayerService->invoke(player_id, inParams, &outParams);
if (!status.isOk()) {
MLOGE("invoke set ecm pids fail");
}
}
void Aml_MP_PlayerClient::startDescrambling_l()
{
if (mHasStartCas) {
return;
}
if (mIsStandaloneCas) {
return;
}
MLOG();
if (mCasServiceType == AML_MP_CAS_SERVICE_TYPE_INVALID) {
MLOGE("unknown cas type!");
return;
}
#ifndef __ANDROID_RECOVERY__
if (mCasHandle == nullptr) {
mCasHandle = AmlCasBase::create(mCasServiceType);
}
#endif
if (mCasHandle == nullptr) {
MLOGE("create CAS handle failed!");
return;
}
int ret = mCasHandle->startDescrambling(&mIptvCasParams);
if (ret == 0) {
mHasStartCas = true;
MLOGI("start cas success.");
}
#ifndef __ANDROID_RECOVERY__
mCasHandle->getEcmPids(mEcmPids);
setEcmPidToServer();
#endif
}
void Aml_MP_PlayerClient::stopDescrambling_l()
{
resetEcmVariables();
if (!mHasStartCas) {
return;
}
if (mIsStandaloneCas) {
return;
}
MLOG();
if (mCasHandle) {
mCasHandle->stopDescrambling();
mCasHandle.clear();
}
}
int Aml_MP_PlayerClient::setCasSession(AML_MP_CASSESSION casSession) {
std::lock_guard<std::mutex> lock(mutex);
MLOG();
sptr<AmlCasBase> casBase = aml_handle_cast<aml_mp::AmlCasBase>(casSession);
RETURN_IF(-1, casBase == nullptr);
if (casBase->serviceType() < AML_MP_CAS_SERVICE_TYPE_IPTV) {
MLOGE("do not support bind DVB caseSession!");
} else if (casBase->serviceType() == AML_MP_CAS_SERVICE_VERIMATRIX_WEB) {
MLOGW("verimatrix web casSession don't need bind!");
} else if (casBase->serviceType() == AML_MP_CAS_SERVICE_NAGRA_WEB) {
MLOGW("nagra web casSession don't need bind!");
}
mCasHandle = casBase;
#ifndef __ANDROID_RECOVERY__
casBase->getEcmPids(mEcmPids);
setEcmPidToServer();
#endif
mIsStandaloneCas = true;
return 0;
}
int Aml_MP_PlayerClient::setIptvCASParams(Aml_MP_CASServiceType serviceType, const Aml_MP_IptvCASParams* params) {
std::lock_guard<std::mutex> lock(mutex);
MLOG();
mCasServiceType = serviceType;
mIptvCasParams = *params;
return 0;
}
int Aml_MP_PlayerClient::flush() {
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->flush(player_id, &result);
resetEcmVariables();
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::setPlaybackRate(float rate) {
std::lock_guard<std::mutex> lock(mutex);
MLOG();
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status =
mPlayerService->setPlaybackRate(player_id, rate, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::setPlaybackRate2(float rate, Aml_MP_VideoDecodeMode decodeMode) {
int aidlDecodeMode = static_cast<Aml_MP_VideoDecodeMode>(decodeMode);
MLOG();
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->setPlaybackRate2(player_id, rate, aidlDecodeMode, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::getPlaybackRate(float* rate) {
RETURN_IF(-1, rate == nullptr);
MLOG();
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
auto status =
mPlayerService->getPlaybackRate(player_id, rate);
return status.isOk() ? 0 : -1;
}
int Aml_MP_PlayerClient::switchAudioTrack(const Aml_MP_AudioParams* params) {
RETURN_IF(-1, params == nullptr);
MLOG();
AmlMpAudioParams aidlParams{};
convertToAidl(aidlParams, params);
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status =
mPlayerService->switchAudioTrack(
player_id, aidlParams, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::switchSubtitleTrack(const Aml_MP_SubtitleParams* params) {
RETURN_IF(-1, params == nullptr);
MLOG();
AmlMpSubtitleParams aidlParams{};
convertToAidl(aidlParams, params);
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status =
mPlayerService->switchSubtitleTrack(
player_id, aidlParams, &result);
return status.isOk() ? result : -1;
}
void Aml_MP_PlayerClient::FreeBufPool() {
if (!mBufPoolHasInit) {
return;
}
MLOGI("enter %s", __FUNCTION__);
if (mBufPoolBufs != nullptr) {
free(mBufPoolBufs);
mBufPoolBufs = nullptr;
}
if (mBufPoolPtr != nullptr) {
munmap(mBufPoolPtr, mBufPoolBufCnt * mBufPoolBufOne);
mBufPoolPtr = nullptr;
}
if (mBufPoolFd >= 0) {
close(mBufPoolFd);
mBufPoolFd = -1;
}
MLOGI("exit %s", __FUNCTION__);
}
void Aml_MP_PlayerClient::InitBufPool() {
if (mBufPoolHasInit) {
return;
}
MLOGI("enter %s", __FUNCTION__);
mBufPoolHasInit = false;
mBufPoolBufCnt = property_get_int32("vendor.media.buf_pool.cnt", 16);
mBufPoolBufOne = property_get_int32("vendor.media.buf_pool.once", 1 * 1024 * 1024);
if (mBufPoolBufCnt <= 0 || mBufPoolBufOne <= 0) {
return;
}
BufPoolNode *bufs = (BufPoolNode *)malloc(sizeof(BufPoolNode) * mBufPoolBufCnt);
if (bufs == nullptr) {
MLOGE("malloc fail");
return;
}
std::unique_ptr<DataQueueMQ> bufPoolDataMq = std::make_unique<DataQueueMQ>(mBufPoolBufCnt, /*configureEventFlagWord=*/true);
std::unique_ptr<FreeQueueMQ> bufPoolFreeMq = std::make_unique<FreeQueueMQ>(mBufPoolBufCnt, /*configureEventFlagWord=*/true);
char bufPoolName[100] = { 0 };
snprintf(bufPoolName, sizeof(bufPoolName) - 1, "aml_mp_sdk_buf_pool_%p", this);
int fd = ashmem_create_region(bufPoolName, mBufPoolBufCnt * mBufPoolBufOne);
if (fd < 0) {
free(bufs);
MLOGE("alloc buf pool fail");
return;
}
void* base = (uint8_t *)mmap(nullptr, mBufPoolBufCnt * mBufPoolBufOne, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (base == MAP_FAILED) {
free(bufs);
MLOGE("mmap fail");
close(fd);
return;
}
mBufPoolBufs = bufs;
for (int i = 0; i < mBufPoolBufCnt; i++) {
mBufPoolBufs[i].ptr = (uint8_t *)base + i * mBufPoolBufOne;
mBufPoolBufs[i].size = mBufPoolBufOne;
}
mBufPoolDataMq = std::move(bufPoolDataMq);
mBufPoolFreeMq = std::move(bufPoolFreeMq);
mBufPoolFd = fd;
mBufPoolPtr = base;
mBufPoolHasInit = true;
MLOGI("init buf pool success, name:%s, fd:%d, ptr:%p", bufPoolName, fd, base);
}
int32_t Aml_MP_PlayerClient::setBufPool2Servier() {
MLOGI("enter %s", __FUNCTION__);
int32_t result = -1;
ndk::ScopedFileDescriptor fd(dup(mBufPoolFd));
auto dataDesc = mBufPoolDataMq->dupeDesc();
auto freeDesc = mBufPoolFreeMq->dupeDesc();
auto status = mPlayerService->setBuffs(player_id, fd, mBufPoolBufCnt, mBufPoolBufOne,
dataDesc, freeDesc, &result);
return status.isOk() ? result : -1;
}
void Aml_MP_PlayerClient::resetEcmVariables()
{
mFirstEcmWritten = false;
mTsBuffer.reset();
mWriteBuffer->setRange(0, 0);
mCacheEcmSize = 0;
}
/*
* > 0: cache data
* == 0: send cache to player
* < 0: cache send all, so continue send buffer to player
*/
int Aml_MP_PlayerClient::processEcmBeforeWrite(const uint8_t* buffer, size_t size) {
if (mCasHandle == nullptr || mWaitingEcmAtServer) {
return -1;
}
if (mCasHandle && mCreateParams.drmMode == AML_MP_INPUT_STREAM_ENCRYPTED && !mFirstEcmWritten) {
size_t ecmOffset = size;
size_t ecmSize = 188;
ecmOffset = aml_mp::findEcmPacket(buffer, size, mEcmPids, &ecmSize);
if (ecmSize > 0) {
mCasHandle->processEcm(false, 0, buffer + ecmOffset, ecmSize);
mFirstEcmWritten = true;
MLOGI("first ECM written, offset:%zu", mTsBuffer.size() + ecmOffset);
}
if (mTsBuffer.empty()) {
MLOGI("encrypted stream, not find ecm, will cache.");
}
if (mTsBuffer.space() < size) {
MLOGE("mTsBuffer full!, why not find ecm data?");
mTsBuffer.reset();
}
return mTsBuffer.put(buffer, size);
}
if (mTsBuffer.empty() || mWriteBuffer->size() == 0) {
return -1;
}
int written = 0;
int retry = 0;
MLOGI("encrypted stream, find ecm, stop cache. will send data %d - %d", mTsBuffer.size(), mWriteBuffer->size());
while (!mTsBuffer.empty() || mWriteBuffer->size() != 0) {
if (mWriteBuffer->size() == 0) {
size_t readSize = mTsBuffer.get(mWriteBuffer->base(), mWriteBuffer->capacity());
mWriteBuffer->setRange(0, readSize);
}
written = doWriteTsData(mWriteBuffer->data(), mWriteBuffer->size());
if (written > 0) {
//coverity[overflow_const]
mWriteBuffer->setRange(mWriteBuffer->offset()+written, mWriteBuffer->size()-written);
mCacheEcmSize += written;
} else {
if (retry >= 5) {
break;
}
retry++;
usleep(10 * 1000);
}
}
if ((mWriteBuffer->size() != 0) || (!mTsBuffer.empty())) {
MLOGI("encrypted stream, find ecm, stop cache. has send:%d, still send data %d - %d",
mCacheEcmSize, mTsBuffer.size(), mWriteBuffer->size());
return 0;
}
MLOGI("encrypted stream, find ecm, stop cache. all has send data:%d", mCacheEcmSize);
return -1;
}
int Aml_MP_PlayerClient::doWriteTsData(const uint8_t* buffer, size_t size) {
int ecmCount = 0;
size_t leftSize = size;
while (leftSize > 0) {
int32_t index = -1;
if (!mBufPoolFreeMq->read(&index)) {
usleep(10 * 1000);
break;
}
if (index < 0 || index >= mBufPoolBufCnt) {
MLOGE("why here?????");
break;
}
const uint8_t *curBuf = buffer + (size - leftSize);
size_t ecmSize = 0;
size_t ecmOffset = leftSize;
if (!mWaitingEcmAtServer &&
mCreateParams.drmMode == AML_MP_INPUT_STREAM_ENCRYPTED && mCasHandle != nullptr) {
ecmOffset = aml_mp::findEcmPacket(curBuf, leftSize, mEcmPids, &ecmSize);
}
uint8_t *data = mBufPoolBufs[index].ptr;
size_t maxSize = mBufPoolBufs[index].size;
size_t cpySize = std::min(leftSize, maxSize);
if (ecmOffset > 0) {
cpySize = std::min(ecmOffset, cpySize);
}
if (ecmSize > 0) {
cpySize += ecmSize;
}
memcpy(data, curBuf, cpySize);
AmlMpBufPoolDataPacket pkt; //BufPoolDataPacket
pkt.isTsData = true;
pkt.index = index;
pkt.size = cpySize;
if (!mBufPoolDataMq->write(&pkt)) {
MLOGE("why client write fail, data and free MQ is same");
}
//MLOGI("client write idx:%d, size:%d", index, cpySize);
leftSize -= cpySize;
if (ecmSize > 0) {
ecmCount++;
mCasHandle->processEcm(false, 0, curBuf + ecmOffset, ecmSize);
}
}
//MLOGI("client write ret:%d", size - leftSize);
return size - leftSize;
}
/*
* -1: not write data
* 0: write all data
* > 0 : write ret data;
*/
int Aml_MP_PlayerClient::writeData(const uint8_t* buffer, size_t size) {
RETURN_IF(-1, buffer == nullptr || size == 0);
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
if (mCreateParams.drmMode == AML_MP_INPUT_STREAM_SECURE_MEMORY) {
int32_t result = -1;
AmlMpWriteBuffer aidlBuf;
aidlBuf.isSecBuf = true;
aidlBuf.isTs = true;
aidlBuf.secData = static_cast<int64_t>(reinterpret_cast<intptr_t>(buffer));
aidlBuf.size = size;
auto status = mPlayerService->writeData(player_id, aidlBuf, &result);
int32_t ret = status.isOk() ? result : -1;
return ret <= 0 ? -1 : ret;
};
int32_t ret = processEcmBeforeWrite(buffer, size);
if (ret < 0) {
ret = doWriteTsData(buffer, size);
}
if (ret > 0) {
// AmpMpPlayerDumpFile(mName, buffer, ret);
}
return ret <= 0 ? -1 : ret;
}
int Aml_MP_PlayerClient::writeEsData(Aml_MP_StreamType streamType, const uint8_t* buffer, size_t size, int64_t pts) {
RETURN_IF(-1, buffer == nullptr || size == 0);
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
if (mCreateParams.drmMode == AML_MP_INPUT_STREAM_SECURE_MEMORY) {
int32_t result = -1;
AmlMpWriteBuffer aidlBuf;
aidlBuf.isSecBuf = true;
aidlBuf.isTs = false;
aidlBuf.secData = static_cast<int64_t>(reinterpret_cast<intptr_t>(buffer));
aidlBuf.size = size;
aidlBuf.streamType = streamType;
aidlBuf.pts = pts;
auto status = mPlayerService->writeData(player_id, aidlBuf, &result);
int32_t ret = status.isOk() ? result : -1;
return ret <= 0 ? -1 : ret;
};
int32_t index = -1;
if (!mBufPoolFreeMq->read(&index)) {
usleep(10 * 1000);
return -1;
}
if (index < 0 || index >= mBufPoolBufCnt) {
MLOGE("why here?????");
return -1;
}
uint8_t *data = mBufPoolBufs[index].ptr;
size_t maxSize = mBufPoolBufs[index].size;
if (size > maxSize) {
MLOGE("cur es size:%d > bufpool node:%d", size, maxSize);
return -1;
}
size_t cpySize = std::min(size, maxSize);
memcpy(data, buffer, cpySize);
AmlMpBufPoolDataPacket pkt; //BufPoolDataPacket
pkt.isTsData = false;
pkt.index = index;
pkt.size = cpySize;
pkt.pts = pts;
pkt.streamType = streamType;
mBufPoolDataMq->write(&pkt);
return size;
}
int Aml_MP_PlayerClient::getCurrentPts(Aml_MP_StreamType streamType, int64_t* pts) {
RETURN_IF(-1, pts == nullptr);
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int64_t result = -1;
auto status = mPlayerService->getCurrentPts(player_id, static_cast<int32_t>(streamType), &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::getFirstPts(Aml_MP_StreamType streamType, int64_t* pts) {
RETURN_IF(-1, pts == nullptr);
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int64_t result = -1;
auto status = mPlayerService->getCurrentPts(player_id, static_cast<int32_t>(streamType), &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::getBufferStat(Aml_MP_BufferStat* bufferStat) {
RETURN_IF(-1, bufferStat == nullptr);
AmlMpBufferStat aidlStat{};
int32_t result = -1;
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
auto status = mPlayerService->getBufferStat(player_id, &aidlStat, &result);
if (status.isOk()) {
convertFromAidl(*bufferStat, aidlStat);
return result;
}
return -1;
}
void Aml_MP_PlayerClient::clearTunnelId() {
if (mMesonVtFd >= 0) {
if (mTunnelId >= 0) {
MLOGI("%s: free Id:%d", __FUNCTION__, mTunnelId);
meson_vt_free_id(mMesonVtFd, mTunnelId);
}
meson_vt_close(mMesonVtFd);
mTunnelId = -1;
mMesonVtFd = -1;
}
}
int32_t Aml_MP_PlayerClient::allocTunnelId() {
int type = AM_FIXED_TUNNEL;
if (mMesonVtFd < 0) {
mMesonVtFd = meson_vt_open();
if (mMesonVtFd < 0) {
MLOGE("meson_vt_open failed!");
return -1;
}
}
if (mTunnelId >= 0) {
return mTunnelId;
}
if (mTunnelId < 0) {
int tunnelId = -1;
if (meson_vt_alloc_id(mMesonVtFd, &tunnelId) < 0) {
MLOGE("meson_vt_alloc_id failed!");
meson_vt_close(mMesonVtFd);
mMesonVtFd = -1;
return -1;
}
MLOGI("allocTunnelId: %d", tunnelId);
mTunnelId = tunnelId;
}
if (mSidebandHandle == nullptr) {
native_handle_t *sidebandHandle = am_gralloc_create_sideband_handle(type, mTunnelId);
mSidebandHandle = android::NativeHandle::create(sidebandHandle, true);
}
return mTunnelId;
}
int Aml_MP_PlayerClient::setANativeWindow(ANativeWindow* nativeWindow) {
RETURN_IF(-1, nativeWindow == nullptr);
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
if (mNativeWindow == nativeWindow) {
return 0;
}
if (allocTunnelId() < 0) {
MLOGE("alloc tunnel id fail");
return -1;
}
MLOGI("setAnativeWindow:%p, sidebandHandle:%p, videoTunnelId: %d",
nativeWindow, (native_handle_t*)mSidebandHandle->handle(), mTunnelId);
int32_t ret = native_window_set_sideband_stream(nativeWindow, (native_handle_t*)mSidebandHandle->handle());
if (ret < 0) {
MLOGE("set sideband stream failed!");
return ret;
}
mNativeWindow = nativeWindow;
AmlMpPlayerParam param{};
param.key = static_cast<int32_t>(AML_MP_PLAYER_PARAMETER_VIDEO_TUNNEL_ID);
param.intValue = mTunnelId;
auto status = mPlayerService->setParameter(player_id, param);
return status.isOk() ? 0 : -EIO;
}
int Aml_MP_PlayerClient::setVideoWindow(int32_t x, int32_t y, int32_t width, int32_t height) {
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->setVideoWindow(player_id, x, y, width, height, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::setVolume(float volume) {
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->setVolume(player_id, volume, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::getVolume(float* volume) {
RETURN_IF(-1, volume == nullptr);
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->getVolume(player_id, volume);
return status.isOk() ? 0 : -1;
}
int Aml_MP_PlayerClient::showVideo() {
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->showVideo(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::hideVideo() {
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->hideVideo(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::showSubtitle() {
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->showSubtitle(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::hideSubtitle() {
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->hideSubtitle(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::setParameter(
Aml_MP_PlayerParameterKey key,
void* parameter) {
RETURN_IF(-EINVAL, parameter == nullptr);
AmlMpPlayerParam param{};
param.key = static_cast<int32_t>(key);
{
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-ENODEV, (mServiceDead || !mServiceConnected)); // Binder init MUST be outside lock
}
switch (key) {
case AML_MP_PLAYER_PARAMETER_VIDEO_PTS_OFFSET:
case AML_MP_PLAYER_PARAMETER_AUDIO_PTS_OFFSET:
case AML_MP_PLAYER_PARAMETER_NETWORK_JITTER:
case AML_MP_PLAYER_PARAMETER_VIDEO_WINDOW_ZORDER:
case AML_MP_PLAYER_PARAMETER_VENDOR_ID:
case AML_MP_PLAYER_PARAMETER_VIDEO_TUNNEL_ID:
case AML_MP_PLAYER_PARAMETER_AUDIO_PRESENTATION_ID:
case AML_MP_PLAYER_PARAMETER_LIBDVR_FAKE_PID:
case AML_MP_PLAYER_PARAMETER_AUDIO_BLOCK_ALIGN:
case AML_MP_PLAYER_PARAMETER_AUDIO_PATCH_ADDRESS:
case AML_MP_PLAYER_PARAMETER_VIDEO_DISPLAY_MODE:
case AML_MP_PLAYER_PARAMETER_VIDEO_DECODE_MODE:
case AML_MP_PLAYER_PARAMETER_AUDIO_OUTPUT_MODE:
case AML_MP_PLAYER_PARAMETER_AUDIO_OUTPUT_DEVICE:
case AML_MP_PLAYER_PARAMETER_AUDIO_BALANCE:
case AML_MP_PLAYER_PARAMETER_AD_STATE:
case AML_MP_PLAYER_PARAMETER_WORK_MODE:
case AML_MP_PLAYER_PARAMETER_SPDIF_PROTECTION:
case AML_MP_PLAYER_PARAMETER_VIDEO_ERROR_RECOVERY_MODE:
case AML_MP_PLAYER_PARAMETER_VIDEO_AFD_ASPECT_MODE:
param.intValue = *static_cast<const int32_t*>(parameter);
break;
case AML_MP_PLAYER_PARAMETER_BLACK_OUT:
case AML_MP_PLAYER_PARAMETER_AUDIO_MUTE:
case AML_MP_PLAYER_PARAMETER_USE_TIF:
param.boolValue = *static_cast<const bool*>(parameter);
break;
case AML_MP_PLAYER_PARAMETER_AD_MIX_LEVEL:
setToHolder<AmlMpADVolume>(param, parameter);
break;
case AML_MP_PLAYER_PARAMETER_TELETEXT_CONTROL:
setToHolder<AmlMpTeletextCtrl>(param, parameter);
break;
case AML_MP_PLAYER_PARAMETER_VIDEO_CROP:
setToHolder<AmlMpRect>(param, parameter);
break;
case AML_MP_PLAYER_PARAMETER_AUDIO_LANGUAGE:
setToHolder<AmlMpAudioLanguage>(param, parameter);
break;
case AML_MP_PLAYER_PARAMETER_CREATE_PARAMS:
setToHolder<AmlMpPlayerCreateParams>(param, parameter);
break;
case AML_MP_PLAYER_PARAMETER_SURFACE_HANDLE:
// not impl
break;
default:
MLOGE("SetParameter: unsupported key %d", key);
return -EINVAL;
}
std::lock_guard<std::mutex> lock(mutex);
auto status = mPlayerService->setParameter(player_id, param);
return status.isOk() ? 0 : -EIO;
}
int Aml_MP_PlayerClient::getParameter( Aml_MP_PlayerParameterKey key, void* parameter) {
RETURN_IF(-EINVAL, parameter == nullptr);
{
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-ENODEV, (mServiceDead || !mServiceConnected)); // Binder init MUST be outside lock
}
AmlMpPlayerParam inParam{};
inParam.key = static_cast<int32_t>(key);
AmlMpPlayerParam param{};
{
std::lock_guard<std::mutex> lock(mutex);
if (key == AML_MP_PLAYER_PARAMETER_AV_INFO_JSON) { // Aml_MP_AvInfo
setToHolder<AmlMpAvInfo>(inParam, parameter);
} else if (key == AML_MP_PLAYER_PARAMETER_AV_STAT_JSON) { // Aml_MP_AvStat Aml_MP_AvInfo
setToHolder<AmlMpAvInfo>(inParam, parameter);
}
auto status = mPlayerService->getParameter(player_id, inParam, &param);
if (!status.isOk()) {
MLOGE("GetParameter: binder call failed for key %d", key);
return -EIO;
}
}
switch (key) {
case AML_MP_PLAYER_PARAMETER_VIDEO_PTS_OFFSET:
case AML_MP_PLAYER_PARAMETER_AUDIO_PTS_OFFSET:
case AML_MP_PLAYER_PARAMETER_NETWORK_JITTER:
case AML_MP_PLAYER_PARAMETER_VIDEO_WINDOW_ZORDER:
case AML_MP_PLAYER_PARAMETER_VENDOR_ID:
case AML_MP_PLAYER_PARAMETER_VIDEO_TUNNEL_ID:
case AML_MP_PLAYER_PARAMETER_AUDIO_PRESENTATION_ID:
case AML_MP_PLAYER_PARAMETER_LIBDVR_FAKE_PID:
case AML_MP_PLAYER_PARAMETER_AUDIO_BLOCK_ALIGN:
case AML_MP_PLAYER_PARAMETER_AUDIO_PATCH_ADDRESS:
case AML_MP_PLAYER_PARAMETER_VIDEO_DISPLAY_MODE:
case AML_MP_PLAYER_PARAMETER_VIDEO_DECODE_MODE:
case AML_MP_PLAYER_PARAMETER_AUDIO_OUTPUT_MODE:
case AML_MP_PLAYER_PARAMETER_AUDIO_OUTPUT_DEVICE:
case AML_MP_PLAYER_PARAMETER_AUDIO_BALANCE:
case AML_MP_PLAYER_PARAMETER_AD_STATE:
case AML_MP_PLAYER_PARAMETER_WORK_MODE:
case AML_MP_PLAYER_PARAMETER_SPDIF_PROTECTION:
case AML_MP_PLAYER_PARAMETER_VIDEO_ERROR_RECOVERY_MODE:
case AML_MP_PLAYER_PARAMETER_VIDEO_AFD_ASPECT_MODE:
case AML_MP_PLAYER_PARAMETER_INSTANCE_ID:
case AML_MP_PLAYER_PARAMETER_SYNC_ID:
*(int32_t*)(parameter) = param.intValue;
break;
case AML_MP_PLAYER_PARAMETER_BLACK_OUT:
case AML_MP_PLAYER_PARAMETER_AUDIO_MUTE:
case AML_MP_PLAYER_PARAMETER_USE_TIF:
case AML_MP_PLAYER_PARAMETER_VIDEO_SHOW_STATE:
*(bool*)(parameter) = param.boolValue;
break;
case AML_MP_PLAYER_PARAMETER_CREATE_PARAMS:
getFromHolder<AmlMpPlayerCreateParams>(player_id, param.holder, *(Aml_MP_PlayerCreateParams *)parameter, key);
break;
case AML_MP_PLAYER_PARAMETER_AD_MIX_LEVEL:
getFromHolder<AmlMpADVolume>(player_id, param.holder, *(Aml_MP_ADVolume *)parameter, key);
break;
case AML_MP_PLAYER_PARAMETER_TELETEXT_CONTROL:
getFromHolder<AmlMpTeletextCtrl>(player_id, param.holder, *(AML_MP_TeletextCtrlParam *)parameter, key);
break;
case AML_MP_PLAYER_PARAMETER_VIDEO_CROP:
getFromHolder<AmlMpRect>(player_id, param.holder, *(Aml_MP_Rect *)parameter, key);
break;
case AML_MP_PLAYER_PARAMETER_AUDIO_LANGUAGE:
getFromHolder<AmlMpAudioLanguage>(player_id, param.holder, *(Aml_MP_AudioLanguage *)parameter, key);
break;
case AML_MP_PLAYER_PARAMETER_VIDEO_INFO:
getFromHolder<AmlMpVideoInfo>(player_id, param.holder, *(Aml_MP_VideoInfo *)parameter, key);
break;
case AML_MP_PLAYER_PARAMETER_VIDEO_DECODE_STAT:
getFromHolder<AmlMpVdecStat>(player_id, param.holder, *(Aml_MP_VdecStat *)parameter, key);
break;
case AML_MP_PLAYER_PARAMETER_AUDIO_INFO:
getFromHolder<AmlMpAudioInfo>(player_id, param.holder, *(Aml_MP_AudioInfo *)parameter, key);
break;
case AML_MP_PLAYER_PARAMETER_AUDIO_DECODE_STAT:
getFromHolder<AmlMpAdecStat>(player_id, param.holder, *(Aml_MP_AdecStat *)parameter, key);
break;
case AML_MP_PLAYER_PARAMETER_SUBTITLE_INFO:
getFromHolder<AmlMpSubtitleInfo>(player_id, param.holder, *(Aml_MP_SubtitleInfo *)parameter, key);
break;
case AML_MP_PLAYER_PARAMETER_SUBTITLE_DECODE_STAT:
getFromHolder<AmlMpSubDecStat>(player_id, param.holder, *(Aml_MP_SubDecStat *)parameter, key);
break;
case AML_MP_PLAYER_PARAMETER_AD_INFO:
getFromHolder<AmlMpAudioInfo>(player_id, param.holder, *(Aml_MP_AudioInfo *)parameter, key);
break;
case AML_MP_PLAYER_PARAMETER_AD_DECODE_STAT:
getFromHolder<AmlMpAdecStat>(player_id, param.holder, *(Aml_MP_AdecStat *)parameter, key);
break;
case AML_MP_PLAYER_PARAMETER_AV_INFO_JSON: { // Aml_MP_AvInfo
getFromHolder<AmlMpAvInfo>(player_id, param.holder, *(Aml_MP_AvInfo *)parameter, key);
break;
}
case AML_MP_PLAYER_PARAMETER_AV_STAT_JSON: { // Aml_MP_AvStat
getFromHolder<AmlMpAvInfo>(player_id, param.holder, *(Aml_MP_AvStat *)parameter, key);
break;
}
case AML_MP_PLAYER_PARAMETER_TSPLAYER_HANDLE: //getTsPlayerHandle(am_tsplayer_handle*)
// not impl
break;
case AML_MP_PLAYER_PARAMETER_SURFACE_HANDLE:
// not impl
break;
default:
MLOGE("GetParameter: unsupported key %d", key);
return -EINVAL;
}
return 0;
}
int Aml_MP_PlayerClient::setSubtitleWindow(int x, int y, int width, int height) {
RETURN_IF(-1, width <= 0 || height <= 0);
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->setSubtitleWindow(player_id, x, y, width, height, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::setAVSyncSource(Aml_MP_AVSyncSource syncSource) {
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->setAVSyncSource(
player_id, static_cast<int32_t>(syncSource), &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::setPcrPid(int pid) {
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->setPcrPid(player_id, pid, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::startVideoDecoding() {
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
MLOG();
startDescrambling_l();
int32_t result = -1;
auto status = mPlayerService->startVideoDecoding(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::stopVideoDecoding() {
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
std::lock_guard<std::mutex> lock(mutex);
int32_t result = -1;
MLOG();
auto status = mPlayerService->stopVideoDecoding(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::startAudioDecoding() {
std::lock_guard<std::mutex> lock(mutex);
MLOG();
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
startDescrambling_l();
int32_t result = -1;
auto status = mPlayerService->startAudioDecoding(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::stopAudioDecoding() {
std::lock_guard<std::mutex> lock(mutex);
MLOG();
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->stopAudioDecoding(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::startSubtitleDecoding() {
std::lock_guard<std::mutex> lock(mutex);
MLOG();
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->startSubtitleDecoding(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::stopSubtitleDecoding() {
std::lock_guard<std::mutex> lock(mutex);
MLOG();
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->stopSubtitleDecoding(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::setADParams(Aml_MP_AudioParams* params) {
RETURN_IF(-1, params == nullptr);
AmlMpAudioParams aidlParams{};
convertToAidl(aidlParams, params);
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->setADParams(player_id, aidlParams, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::startADDecoding() {
std::lock_guard<std::mutex> lock(mutex);
MLOG();
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
startDescrambling_l();
int32_t result = -1;
auto status = mPlayerService->startADDecoding(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::stopADDecoding() {
std::lock_guard<std::mutex> lock(mutex);
MLOG();
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->stopADDecoding(player_id, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::getDecodingState(Aml_MP_StreamType streamType, AML_MP_DecodingState* decodingState) {
RETURN_IF(-1, decodingState == nullptr);
int32_t aidlState = 0;
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
auto status = mPlayerService->getDecodingState(
player_id, static_cast<int32_t>(streamType), &aidlState);
if (status.isOk()) {
*decodingState = static_cast<AML_MP_DecodingState>(aidlState);
return 0;
}
return -1;
}
int Aml_MP_PlayerClient::setADVolume(float volume) {
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->setADVolume(player_id, volume, &result);
return status.isOk() ? result : -1;
}
int Aml_MP_PlayerClient::getADVolume(float* volume) {
RETURN_IF(-1, volume == nullptr);
std::lock_guard<std::mutex> lock(mutex);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
int32_t result = -1;
auto status = mPlayerService->getADVolume(player_id, volume);
return status.isOk() ? result : -1;
}
Aml_MP_PlayerClient::ClientEventCallBack::ClientEventCallBack(aml_mp::wptr<Aml_MP_PlayerClient>& weakThis,
int32_t playerId, Aml_MP_PlayerEventCallback cb, void* userData) {
std::lock_guard<std::mutex> lock(mutex);
mCb = cb;
mUserData = userData;
mClient = weakThis;
snprintf(mName, sizeof(mName), "%s_%p_%d", "Aml_MP_PlayerClientEventCallBack", this, playerId);
}
int32_t Aml_MP_PlayerClient::ClientEventCallBack::setCallBack(Aml_MP_PlayerEventCallback cb, void *userData) {
std::lock_guard<std::mutex> lock(mutex);
if (mCb != nullptr) {
MLOGE("why register call again.");
return -1;
}
mCb = cb;
mUserData = userData;
MLOGI("register callback:%p - %p success", cb, userData);
return 0;
}
Aml_MP_PlayerClient::status Aml_MP_PlayerClient::ClientEventCallBack::onPlayerEvent(const AmlMpPlayerEvent& event) {
sptr<Aml_MP_PlayerClient> clientRemote = mClient.promote();
if (clientRemote == nullptr) {
// client already dec
return status::ok();
}
Aml_MP_PlayerClient* client = clientRemote.get();
Aml_MP_PlayerEventCallback cb = nullptr;
aml_mp::sptr<aml_mp::AmlCasBase> casHandle = nullptr;
void* userData = nullptr;
{
std::lock_guard<std::mutex> lock(mutex);
cb = mCb;
userData = mUserData;
casHandle = client->mCasHandle;
}
Aml_MP_PlayerEventType eventType = (Aml_MP_PlayerEventType)event.eventType;
if (eventType == AML_MP_PLAYER_EVENT_ECM_NOTIFY) {
if (casHandle != nullptr) {
bool async = event.boolValue;
int32_t pid = event.intValue;
const uint8_t *data = event.payload.data();
int32_t size = event.payload.size();
std::string ecmDataStr;
char hex[3];
for (int i = 0; i < size; i++) {
snprintf(hex, sizeof(hex), "%02X", data[i]);
ecmDataStr.append(hex);
ecmDataStr.append(" ");
}
MLOGI("programEventCallback: ecmPid: %d, ecmData: size:%d, hexStr:%s", pid, size, ecmDataStr.c_str());
casHandle->processEcm(event.boolValue, event.intValue, event.payload.data(), event.payload.size());
}
return status::ok();
}
if (cb == nullptr) {
return status::ok();
}
void *value = nullptr;
int32_t cpySize = 0;
Aml_MP_PlayerEventScrambling scrambling{};
Aml_MP_PlayerEventPidChangeInfo pidChanged{};
Aml_MP_PlayerEventVideoFormat videoFormat{};
Aml_MP_PlayerEventAudioFormat audioFormat{};
Aml_MP_SubtitleInfo subInfo{};
Aml_MP_SubtitleDimension subDimension{};
Aml_MP_SubtitleChannelUpdate subChannelUpdate{};
std::string subLang;
Aml_MP_PlayerEventMpegUserData mpegUserData{};
Aml_MP_SubtitleData subData{};
switch (eventType) {
case AML_MP_PLAYER_EVENT_FIRST_FRAME: // only event, no param.
case AML_MP_PLAYER_EVENT_AV_SYNC_DONE:
case AML_MP_PLAYER_EVENT_DATA_LOSS:
case AML_MP_PLAYER_EVENT_DATA_RESUME:
case AML_MP_PLAYER_EVENT_DECODER_DATA_LOSS:
case AML_MP_PLAYER_EVENT_DECODER_DATA_RESUME:
case AML_MP_PLAYER_EVENT_VIDEO_DECODE_FIRST_FRAME:
case AML_MP_PLAYER_EVENT_VIDEO_INVALID_TIMESTAMP:
case AML_MP_PLAYER_EVENT_VIDEO_INVALID_DATA:
case AML_MP_PLAYER_EVENT_VIDEO_ERROR_FRAME_COUNT:
case AML_MP_PLAYER_EVENT_AUDIO_INVALID_TIMESTAMP:
case AML_MP_PLAYER_EVENT_AUDIO_INVALID_DATA:
case AML_MP_PLAYER_EVENT_VIDEO_UNSUPPORT:
case AML_MP_PLAYER_EVENT_AUDIO_DECODE_FIRST_FRAME:
break;
case AML_MP_PLAYER_EVENT_SUBTITLE_AVAIL: // int32_t
case AML_MP_PLAYER_EVENT_SUBTITLE_LOSEDATA:
case AML_MP_PLAYER_EVENT_SUBTITLE_TIMEOUT:
case AML_MP_PLAYER_EVENT_SUBTITLE_INVALID_TIMESTAMP:
case AML_MP_PLAYER_EVENT_SUBTITLE_INVALID_DATA:
case AML_MP_PLAYER_EVENT_SUBTITLE_AFD_EVENT:
value = (void *)&event.intValue;
break;
case AML_MP_PLAYER_EVENT_VIDEO_OVERFLOW: // uint32_t
case AML_MP_PLAYER_EVENT_VIDEO_UNDERFLOW:
case AML_MP_PLAYER_EVENT_AUDIO_OVERFLOW:
case AML_MP_PLAYER_EVENT_AUDIO_UNDERFLOW:
value = (void *)&event.longValue;
break;
case AML_MP_PLAYER_EVENT_VIDEO_INPUT_BUFFER_DONE: // free handle from drive
case AML_MP_PLAYER_EVENT_AUDIO_INPUT_BUFFER_DONE:
value = (void *)event.longValue;
break;
case AML_MP_PLAYER_EVENT_SCRAMBLING: // Aml_MP_PlayerEventScrambling
value = getFromHolder<AmlMpPlayerEventScrambling>(client->player_id, event.holder, scrambling, eventType);
break;
case AML_MP_PLAYER_EVENT_PID_CHANGED: //Aml_MP_PlayerEventPidChangeInfo
value = getFromHolder<AmlMpPlayerEventPidChanged>(client->player_id, event.holder, pidChanged, eventType);
break;
case AML_MP_PLAYER_EVENT_VIDEO_CHANGED: // Aml_MP_PlayerEventVideoFormat
value = getFromHolder<AmlMpPlayerEventVideoFormat>(client->player_id, event.holder, videoFormat, eventType);
break;
case AML_MP_PLAYER_EVENT_AUDIO_CHANGED: // Aml_MP_PlayerEventAudioFormat
value = getFromHolder<AmlMpPlayerEventAudioFormat>(client->player_id, event.holder, audioFormat, eventType);
break;
case AML_MP_PLAYER_EVENT_SUBTITLE_DIMENSION: // Aml_MP_SubtitleDimension
value = getFromHolder<AmlMpSubtitleDimension>(client->player_id, event.holder, subDimension, eventType);
break;
case AML_MP_PLAYER_EVENT_SUBTITLE_CHANNEL_UPDATE: // Aml_MP_SubtitleChannelUpdate
value = getFromHolder<AmlMpSubtitleChannelUpdate>(client->player_id, event.holder, subChannelUpdate, eventType);
break;
case AML_MP_PLAYER_EVENT_SUBTITLE_LANGUAGE: // char[4]
getFromHolder<AmlMpSubtitleLanguage>(client->player_id, event.holder, subLang, eventType);
value = (void *)subLang.c_str();
break;
case AML_MP_PLAYER_EVENT_SUBTITLE_INFO: // Aml_MP_SubtitleInfo
value = getFromHolder<AmlMpSubtitleInfo>(client->player_id, event.holder, subInfo, eventType);
break;
case AML_MP_PLAYER_EVENT_USERDATA_AFD:
case AML_MP_PLAYER_EVENT_USERDATA_CC: // Aml_MP_PlayerEventMpegUserData
value = getFromHolder<AmlMpPlayerEventMpegUserData>(client->player_id, event.holder, mpegUserData, eventType);
break;
case AML_MP_PLAYER_EVENT_SUBTITLE_DATA: // Aml_MP_SubtitleData
value = getFromHolder<AmlMpSubtitleData>(client->player_id, event.holder, subData, eventType);
break;
case AML_MP_MEDIAPLAYER_EVENT_PLAYBACK_COMPLETE: // mediaplayer
case AML_MP_MEDIAPLAYER_EVENT_PLAYBACK_SOF:
case AML_MP_MEDIAPLAYER_EVENT_PREPARED:
case AML_MP_MEDIAPLAYER_EVENT_STOPPED:
case AML_MP_MEDIAPLAYER_EVENT_MEDIA_ERROR:
case AML_MP_MEDIAPLAYER_EVENT_FIRST_FRAME_TOGGLED:
case AML_MP_MEDIAPLAYER_EVENT_BUFFERING_START:
case AML_MP_MEDIAPLAYER_EVENT_BUFFERING_END:
case AML_MP_MEDIAPLAYER_EVENT_VIDEO_UNSUPPORT:
case AML_MP_MEDIAPLAYER_EVENT_AUDIO_UNSUPPORT:
case AML_MP_DVRPLAYER_EVENT_ERROR: // drvpalyer will impl on client
case AML_MP_DVRPLAYER_EVENT_TRANSITION_OK:
case AML_MP_DVRPLAYER_EVENT_TRANSITION_FAILED:
case AML_MP_DVRPLAYER_EVENT_KEY_FAILURE:
case AML_MP_DVRPLAYER_EVENT_NO_KEY:
case AML_MP_DVRPLAYER_EVENT_REACHED_BEGIN:
case AML_MP_DVRPLAYER_EVENT_REACHED_END:
case AML_MP_DVRPLAYER_EVENT_NOTIFY_PLAYTIME:
case AML_MP_DVRPLAYER_EVENT_TIMESHIFT_FR_REACHED_BEGIN:
case AML_MP_DVRPLAYER_EVENT_TIMESHIFT_FF_REACHED_END:
case AML_MP_DVRPLAYER_EVENT_AUTO_RESUMED:
break;
default:
MLOGE("not support the event:%d", eventType);
return status::ok();;
}
cb(userData, eventType, (int64_t)value);
return status::ok();
}
int Aml_MP_PlayerClient::makeCallbackToServer(Aml_MP_PlayerEventCallback cb, void* userData) {
if (mCallback != nullptr) {
return -1;
}
MLOG();
aml_mp::wptr<Aml_MP_PlayerClient> weakThis = this;
mCallback = ::ndk::SharedRefBase::make<ClientEventCallBack>(weakThis, player_id, cb, userData);
if (mCallback == nullptr) {
MLOGE("make event callback fail");
return -1;
}
if (mPlayerService == nullptr) {
MLOGE("mPlayerService is null");
return -1;
}
auto status = mPlayerService->registerPlayerCallback(player_id, mCallback);
if (!status.isOk()) {
mCallback = nullptr;
MLOGE("register event callback to server fail");
return -1;
}
return 0;
}
int Aml_MP_PlayerClient::registerEventCallback(Aml_MP_PlayerEventCallback cb, void* userData) {
std::lock_guard<std::mutex> lock(mutex);
MLOGI("enter %s", __FUNCTION__);
RETURN_IF(-1, (mServiceDead || !mServiceConnected));
RETURN_IF(-1, (cb == nullptr));
if (mCallback != nullptr) {
MLOGI("set callback:%p - %p", cb, userData);
return mCallback->setCallBack(cb, userData);
}
int32_t ret = makeCallbackToServer(cb, userData);
MLOGI("exit %s, ret:%d", __FUNCTION__, ret);
return ret;
}
#endif