1523 lines
52 KiB
C++
1523 lines
52 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 "AmlMpPlayerDemo_Playback"
|
|
#include <utils/AmlMpLog.h>
|
|
#include "Playback.h"
|
|
#include <Aml_MP/Aml_MP.h>
|
|
#include <utils/AmlMpUtils.h>
|
|
#include <cutils/properties.h>
|
|
#include <vector>
|
|
#include <string>
|
|
#include <fcntl.h>
|
|
#include <utils/json/json.h>
|
|
|
|
static const char* mName = LOG_TAG;
|
|
|
|
namespace aml_mp {
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
CasPlugin::CasPlugin(Aml_MP_DemuxId demuxId, Aml_MP_InputSourceType sourceType, const sptr<ProgramInfo>& programInfo)
|
|
: mDemuxId(demuxId)
|
|
, mSourceType(sourceType)
|
|
, mProgramInfo(programInfo)
|
|
{
|
|
Aml_MP_CAS_Initialize();
|
|
}
|
|
|
|
CasPlugin::~CasPlugin()
|
|
{
|
|
Aml_MP_CAS_Terminate();
|
|
}
|
|
|
|
int CasPlugin::start()
|
|
{
|
|
if (mSourceType == AML_MP_INPUT_SOURCE_TS_DEMOD ||
|
|
(mProgramInfo && mProgramInfo->caSystemId >= 0x1800 && mProgramInfo->caSystemId <= 0x18FF)) {
|
|
return startDVBDescrambling();
|
|
} else if (mSourceType == AML_MP_INPUT_SOURCE_TS_MEMORY) {
|
|
return startIPTVDescrambling();
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int CasPlugin::stop()
|
|
{
|
|
if (mSourceType == AML_MP_INPUT_SOURCE_TS_DEMOD ||
|
|
(mProgramInfo && mProgramInfo->caSystemId >= 0x1800 && mProgramInfo->caSystemId <= 0x18FF)) {
|
|
return stopDVBDescrambling();
|
|
} else if (mSourceType == AML_MP_INPUT_SOURCE_TS_MEMORY) {
|
|
return stopIPTVDescrambling();
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
void CasPlugin::setPMTSectionData(const sptr<SectionData>& pmt)
|
|
{
|
|
if (pmt == nullptr || pmt->size == 0 || pmt->data == nullptr) {
|
|
return;
|
|
}
|
|
|
|
if (Aml_MP_CAS_IsNeedWholeSection())
|
|
{
|
|
Aml_MP_CASSectionReportAttr attr;
|
|
|
|
memset(&attr, 0, sizeof(attr));
|
|
attr.dmxDev = mDemuxId;
|
|
// attr.serviceId;
|
|
attr.sectionType = AML_MP_CAS_SECTION_PMT;
|
|
Aml_MP_CAS_ReportSection(&attr, pmt->data, pmt->size);
|
|
}
|
|
}
|
|
|
|
void CasPlugin::setCATSectionData(const sptr<SectionData>& cat)
|
|
{
|
|
if (cat == nullptr || cat->size == 0 || cat->data == nullptr) {
|
|
return;
|
|
}
|
|
|
|
if (Aml_MP_CAS_IsNeedWholeSection())
|
|
{
|
|
Aml_MP_CASSectionReportAttr attr;
|
|
|
|
memset(&attr, 0, sizeof(attr));
|
|
attr.dmxDev = mDemuxId;
|
|
// attr.serviceId;
|
|
attr.sectionType = AML_MP_CAS_SECTION_CAT;
|
|
Aml_MP_CAS_ReportSection(&attr, cat->data, cat->size);
|
|
}
|
|
}
|
|
|
|
int CasPlugin::startDVBDescrambling()
|
|
{
|
|
MLOG();
|
|
|
|
Aml_MP_CAS_SetEmmPid(mDemuxId, mProgramInfo->emmPid);
|
|
|
|
if (!Aml_MP_CAS_IsSystemIdSupported(mProgramInfo->caSystemId)) {
|
|
MLOGE("unsupported caSystemId:%#x", mProgramInfo->caSystemId);
|
|
return -1;
|
|
}
|
|
|
|
int ret = Aml_MP_CAS_OpenSession(&mCasSession, AML_MP_CAS_SERVICE_LIVE_PLAY);
|
|
if (ret < 0) {
|
|
MLOGE("open session failed!");
|
|
return -1;
|
|
}
|
|
|
|
|
|
Aml_MP_CAS_RegisterEventCallback(mCasSession, [](AML_MP_CASSESSION session __unused, const char* json) {
|
|
MLOGI("ca_cb:%s", json);
|
|
return 0;
|
|
}, this);
|
|
|
|
Aml_MP_CASServiceInfo casServiceInfo;
|
|
memset(&casServiceInfo, 0, sizeof(casServiceInfo));
|
|
casServiceInfo.service_id = mProgramInfo->serviceNum;
|
|
casServiceInfo.serviceType = AML_MP_CAS_SERVICE_LIVE_PLAY;
|
|
casServiceInfo.dmx_dev = mDemuxId;
|
|
casServiceInfo.ecm_pid = mProgramInfo->ecmPid[0];
|
|
casServiceInfo.stream_pids[0] = mProgramInfo->audioPid;
|
|
casServiceInfo.stream_pids[1] = mProgramInfo->videoPid;
|
|
casServiceInfo.stream_num = 2;
|
|
casServiceInfo.ca_private_data_len = 0;
|
|
ret = Aml_MP_CAS_StartDescrambling(mCasSession, &casServiceInfo);
|
|
if (ret < 0) {
|
|
MLOGE("start descrambling failed with %d", ret);
|
|
return ret;
|
|
}
|
|
|
|
mSecMem = Aml_MP_CAS_CreateSecmem(mCasSession, AML_MP_CAS_SERVICE_LIVE_PLAY, nullptr, nullptr);
|
|
if (mSecMem == nullptr) {
|
|
MLOGE("create secmem failed!");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CasPlugin::stopDVBDescrambling()
|
|
{
|
|
MLOG("mCasSession:%p", mCasSession);
|
|
|
|
if (mCasSession == nullptr) {
|
|
return 0;
|
|
}
|
|
|
|
Aml_MP_CAS_DestroySecmem(mCasSession, mSecMem);
|
|
mSecMem = nullptr;
|
|
|
|
Aml_MP_CAS_StopDescrambling(mCasSession);
|
|
|
|
Aml_MP_CAS_CloseSession(mCasSession);
|
|
mCasSession = nullptr;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CasPlugin::startIPTVDescrambling()
|
|
{
|
|
MLOG();
|
|
|
|
Aml_MP_CASServiceType serviceType{AML_MP_CAS_SERVICE_TYPE_INVALID};
|
|
Aml_MP_IptvCASParams casParams;
|
|
int ret = 0;
|
|
|
|
switch (mProgramInfo->caSystemId) {
|
|
case 0x5601:
|
|
{
|
|
MLOGI("verimatrix iptv!");
|
|
serviceType = AML_MP_CAS_SERVICE_VERIMATRIX_IPTV;
|
|
|
|
casParams.videoCodec = mProgramInfo->videoCodec;
|
|
casParams.audioCodec = mProgramInfo->audioCodec;
|
|
casParams.videoPid = mProgramInfo->videoPid;
|
|
casParams.audioPid = mProgramInfo->audioPid;
|
|
casParams.ecmPid[0] = mProgramInfo->ecmPid[0];
|
|
casParams.ecmPid[1] = mProgramInfo->ecmPid[1];
|
|
casParams.demuxId = mDemuxId;
|
|
|
|
char value[PROPERTY_VALUE_MAX];
|
|
memset(value, 0, PROPERTY_VALUE_MAX);
|
|
//coverity[check_return]
|
|
property_get("media.vmx.storepath", value, "/data/mediadrm");
|
|
strncpy(casParams.keyPath, value, sizeof(casParams.keyPath)-1);
|
|
|
|
//coverity[check_return]
|
|
property_get("media.vmx.serveraddr", value, "client-test-3.verimatrix.com");
|
|
strncpy(casParams.serverAddress, value, sizeof(casParams.serverAddress)-1);
|
|
|
|
casParams.serverPort = property_get_int32("media.vmx.port", 12686);
|
|
}
|
|
break;
|
|
|
|
case 0x1724:
|
|
{
|
|
MLOGI("VMX DVB");
|
|
}
|
|
break;
|
|
|
|
case 0x4AD4:
|
|
case 0x4AD5:
|
|
{
|
|
MLOGI("wvcas iptv, systemid=0x%x!", mProgramInfo->caSystemId);
|
|
serviceType = AML_MP_CAS_SERVICE_WIDEVINE;
|
|
|
|
casParams.caSystemId = mProgramInfo->caSystemId;
|
|
casParams.videoCodec = mProgramInfo->videoCodec;
|
|
casParams.audioCodec = mProgramInfo->audioCodec;
|
|
casParams.videoPid = mProgramInfo->videoPid;
|
|
casParams.audioPid = mProgramInfo->audioPid;
|
|
casParams.ecmPid[0] = mProgramInfo->ecmPid[0];
|
|
casParams.ecmPid[1] = mProgramInfo->ecmPid[1];
|
|
casParams.demuxId = mDemuxId;
|
|
|
|
casParams.private_size = 0;
|
|
if (mProgramInfo->privateDataLength > 0) {
|
|
memcpy(casParams.private_data, mProgramInfo->privateData, mProgramInfo->privateDataLength);
|
|
casParams.private_size = mProgramInfo->privateDataLength;
|
|
}
|
|
MLOGI("wvcas iptv, private_size=%zu", casParams.private_size);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
MLOGI("unknown caSystemId:%#x", mProgramInfo->caSystemId);
|
|
break;
|
|
}
|
|
|
|
if (serviceType != AML_MP_CAS_SERVICE_TYPE_INVALID) {
|
|
ret = Aml_MP_CAS_OpenSession(&mCasSession, serviceType);
|
|
if (ret < 0) {
|
|
MLOGE("Aml_MP_CAS_OpenSession failed!");
|
|
}
|
|
ret = Aml_MP_CAS_StartDescramblingIPTV(mCasSession, &casParams);
|
|
if (ret < 0) {
|
|
MLOGE("start iptv cas session failed!");
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int CasPlugin::stopIPTVDescrambling()
|
|
{
|
|
int ret = 0;
|
|
|
|
ret = Aml_MP_CAS_StopDescrambling(mCasSession);
|
|
if (ret < 0) {
|
|
MLOGE("Aml_MP_CAS_StopDescrambling failed!");
|
|
}
|
|
ret = Aml_MP_CAS_CloseSession(mCasSession);
|
|
if (ret < 0) {
|
|
MLOGE("Aml_MP_CAS_CloseSession failed!");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
TsDemuxer::TsDemuxer(Aml_MP_DemuxType demuxType, Aml_MP_DemuxId demuxId)
|
|
{
|
|
mDemux = AmlDemuxBase::create(demuxType);
|
|
mDemux->open(false, demuxId, false);
|
|
mDemux->start();
|
|
}
|
|
|
|
TsDemuxer::~TsDemuxer()
|
|
{
|
|
MLOG();
|
|
|
|
for (int i = AML_MP_STREAM_TYPE_UNKNOWN + 1; i < AML_MP_STREAM_TYPE_NB; ++i) {
|
|
stopStream((Aml_MP_StreamType)i);
|
|
closeStream((Aml_MP_StreamType)i);
|
|
}
|
|
|
|
mPids.clear();
|
|
|
|
if (mDemux) {
|
|
mDemux->stop();
|
|
mDemux->close();
|
|
mDemux.clear();
|
|
}
|
|
|
|
MLOGI("TsDemuxer destructor end.");
|
|
}
|
|
|
|
int TsDemuxer::feedTs(const uint8_t* data, size_t size)
|
|
{
|
|
if (mDemux == nullptr) {
|
|
return -1;
|
|
}
|
|
|
|
int ret = mDemux->feedTs(data, size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void TsDemuxer::getFlowStatus(bool* underflow, bool* overflow)
|
|
{
|
|
bool streamUnderflow = false;
|
|
bool streamOverflow = false;
|
|
|
|
for (auto& stream: mStreams) {
|
|
stream.second.bufferQueue->getFlowStatus(&streamUnderflow, &streamOverflow);
|
|
|
|
if (underflow) {
|
|
*underflow |= streamUnderflow;
|
|
}
|
|
|
|
if (overflow) {
|
|
*overflow |= streamOverflow;
|
|
}
|
|
}
|
|
}
|
|
|
|
int TsDemuxer::openStream(Aml_MP_StreamType streamType, size_t bufferCount, size_t bufferSize, bool isSVP, const std::function<StreamConsumer>& consumerCb)
|
|
{
|
|
Stream& stream = mStreams[streamType];
|
|
stream.consumerCb = consumerCb;
|
|
|
|
if (stream.bufferQueue == nullptr) {
|
|
stream.bufferQueue = new BufferQueue(streamType, bufferCount, bufferSize, isSVP);
|
|
}
|
|
|
|
if (stream.bufferQueueConsumer == nullptr) {
|
|
const char* streamName = mpStreamType2Str(streamType);
|
|
stream.bufferQueueConsumer = new BufferQueue::Consumer(streamType, streamName);
|
|
stream.bufferQueueConsumer->connectQueue(stream.bufferQueue.get());
|
|
stream.bufferQueueConsumer->connectSink([this, streamType](const uint8_t* data, size_t size, int64_t pts) {
|
|
Stream& stream = mStreams[streamType];
|
|
return stream.consumerCb(streamType, data, size, pts);
|
|
});
|
|
}
|
|
|
|
stream.dumpFd = -1;
|
|
|
|
stream.streamParser = new StreamParser(streamType, StreamParser::PES);
|
|
stream.filterCbCount = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int TsDemuxer::closeStream(Aml_MP_StreamType streamType)
|
|
{
|
|
MLOG();
|
|
Stream* stream = getStream(streamType);
|
|
if (stream == nullptr) {
|
|
return -1;
|
|
}
|
|
|
|
MLOG();
|
|
if (stream->bufferQueueConsumer) {
|
|
stream->bufferQueueConsumer->stop();
|
|
stream->bufferQueueConsumer.clear();
|
|
}
|
|
MLOG();
|
|
|
|
stream->bufferQueue.clear();
|
|
|
|
if (stream->dumpFd >= 0) {
|
|
::close(stream->dumpFd);
|
|
stream->dumpFd = -1;
|
|
}
|
|
|
|
stream->streamParser.clear();
|
|
stream->filterCbCount = 0;
|
|
|
|
MLOG();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int TsDemuxer::startStream(Aml_MP_StreamType streamType, int pid, Aml_MP_CodecID codec)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (mPids.find(pid) != mPids.end()) {
|
|
MLOGW("stream(%d) started already!", pid);
|
|
return -1;
|
|
}
|
|
|
|
Stream* stream = getStream(streamType);
|
|
if (stream == nullptr) {
|
|
MLOGW("stream hasn't been open! type:%s", mpStreamType2Str(streamType));
|
|
return -1;
|
|
}
|
|
|
|
Aml_MP_DemuxFilterParams params;
|
|
memset(¶ms, 0, sizeof(params));
|
|
if (streamType == AML_MP_STREAM_TYPE_AUDIO) {
|
|
params.type = AML_MP_DEMUX_FILTER_AUDIO;
|
|
} else if (streamType == AML_MP_STREAM_TYPE_VIDEO) {
|
|
params.type = AML_MP_DEMUX_FILTER_VIDEO;
|
|
}
|
|
params.codecType = codec;
|
|
stream->channel = mDemux->createChannel(pid, ¶ms);
|
|
ret = mDemux->openChannel(stream->channel);
|
|
if (ret < 0) {
|
|
MLOGE("openChannel failed!");
|
|
return ret;
|
|
}
|
|
|
|
stream->filter = mDemux->createFilter([](int pid, size_t size, const uint8_t* data, void* userData) -> int {
|
|
int ret = 0;
|
|
TsDemuxer* demuxer = (TsDemuxer*)userData;
|
|
Aml_MP_StreamType streamType = demuxer->mPids[pid];
|
|
Stream* stream = demuxer->getStream(streamType);
|
|
if (stream == nullptr) {
|
|
MLOGI("[%s] filter get stream failed", mpStreamType2Str(streamType));
|
|
return -1;
|
|
}
|
|
|
|
if (stream->bufferQueue) {
|
|
MLOGV("filter(%d) size:%zu(%zu), cbCount:%zu", pid, size, size-14, ++stream->filterCbCount);
|
|
stream->streamParser->append(data, size);
|
|
|
|
int ret = 0;
|
|
StreamParser::Frame frame;
|
|
while (true) {
|
|
BufferQueue::Buffer* buffer = nullptr;
|
|
ret = stream->bufferQueue->dequeueBuffer(&buffer);
|
|
if (ret < 0) {
|
|
MLOGI("[%s] filter dequeueBuffer failed, streamParser current BufferSize:%zu", mpStreamType2Str(streamType), stream->streamParser->totalBufferSize());
|
|
return -1;
|
|
}
|
|
|
|
//coverity[tainted_argument]
|
|
ret = stream->streamParser->lockFrame(&frame);
|
|
if (ret < 0) {
|
|
stream->bufferQueue->cancelBuffer(buffer);
|
|
break;
|
|
}
|
|
|
|
if (stream->dumpFd >= 0) {
|
|
int wlen = ::write(stream->dumpFd, frame.data, frame.size);
|
|
if (wlen != (int)frame.size) {
|
|
MLOGE("write dump file failed!");
|
|
}
|
|
}
|
|
|
|
buffer->append(frame.data, frame.size);
|
|
buffer->setPts(frame.pts);
|
|
stream->bufferQueue->queueBuffer(buffer);
|
|
|
|
stream->streamParser->unlockFrame(&frame);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}, this);
|
|
|
|
ret = mDemux->attachFilter(stream->filter, stream->channel);
|
|
if (ret < 0) {
|
|
MLOGE("attachFilter failed, pid:%#x, stream:%s", pid, mpStreamType2Str(streamType));
|
|
}
|
|
|
|
stream->pid = pid;
|
|
mPids.emplace(pid, streamType);
|
|
|
|
#if 0
|
|
std::string filename = "/data/dump_stream_";
|
|
filename.append(std::to_string(pid));
|
|
filename.append(".es");
|
|
stream->dumpFd = ::open(filename.c_str(), O_WRONLY|O_TRUNC|O_CREAT, 0644);
|
|
if (stream->dumpFd < 0) {
|
|
MLOGE("open dumpFd %s failed!", filename.c_str());
|
|
}
|
|
#endif
|
|
|
|
stream->bufferQueueConsumer->start();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int TsDemuxer::stopStream(Aml_MP_StreamType streamType)
|
|
{
|
|
Stream* stream = getStream(streamType);
|
|
if (stream == nullptr) {
|
|
return -1;
|
|
}
|
|
|
|
stream->bufferQueueConsumer->pause();
|
|
stream->bufferQueueConsumer->flush();
|
|
|
|
mPids.erase(stream->pid);
|
|
stream->pid = AML_MP_INVALID_PID;
|
|
|
|
if (stream->filter != AML_MP_INVALID_HANDLE) {
|
|
mDemux->detachFilter(stream->filter, stream->channel);
|
|
mDemux->destroyFilter(stream->filter);
|
|
stream->filter = AML_MP_INVALID_HANDLE;
|
|
}
|
|
|
|
if (stream->channel != AML_MP_INVALID_HANDLE) {
|
|
mDemux->closeChannel(stream->channel);
|
|
mDemux->destroyChannel(stream->channel);
|
|
stream->channel = AML_MP_INVALID_HANDLE;
|
|
}
|
|
|
|
MLOG();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int TsDemuxer::pauseStream(Aml_MP_StreamType streamType)
|
|
{
|
|
Stream* stream = getStream(streamType);
|
|
if (stream == nullptr) {
|
|
return -1;
|
|
}
|
|
|
|
stream->bufferQueueConsumer->pause();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int TsDemuxer::resumeStream(Aml_MP_StreamType streamType)
|
|
{
|
|
Stream* stream = getStream(streamType);
|
|
if (stream == nullptr) {
|
|
return -1;
|
|
}
|
|
|
|
stream->bufferQueueConsumer->start();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int TsDemuxer::notifyStreamInputBufferDone(Aml_MP_StreamType streamType, int64_t handle)
|
|
{
|
|
Stream* stream = getStream(streamType);
|
|
if (stream == nullptr) {
|
|
return -1;
|
|
}
|
|
|
|
stream->bufferQueueConsumer->notifyBufferReleased(handle);
|
|
|
|
return 0;
|
|
}
|
|
|
|
TsDemuxer::Stream* TsDemuxer::getStream(Aml_MP_StreamType streamType)
|
|
{
|
|
auto it = mStreams.find(streamType);
|
|
if (it != mStreams.end()) {
|
|
return &it->second;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
Playback::Playback(Aml_MP_DemuxId demuxId, Aml_MP_InputSourceType sourceType, Aml_MP_InputStreamType inputStreamType, uint64_t options)
|
|
: mDemuxId(demuxId)
|
|
, mDrmMode(inputStreamType)
|
|
, mOptions(options)
|
|
{
|
|
MLOGI("Playback structure,sourceType:%d\n", sourceType);
|
|
Aml_MP_PlayerCreateParams createParams;
|
|
memset(&createParams, 0, sizeof(createParams));
|
|
createParams.channelId = AML_MP_CHANNEL_ID_AUTO;
|
|
createParams.demuxId = demuxId;
|
|
createParams.sourceType = sourceType;
|
|
createParams.drmMode = inputStreamType;
|
|
createParams.options = options;
|
|
int ret = Aml_MP_Player_Create(&createParams, &mPlayer);
|
|
if (ret < 0) {
|
|
MLOGE("create player failed!");
|
|
return;
|
|
}
|
|
|
|
if (sourceType == AML_MP_INPUT_SOURCE_ES_MEMORY) {
|
|
mDemuxer = new TsDemuxer(AML_MP_DEMUX_TYPE_SOFTWARE, demuxId);
|
|
}
|
|
}
|
|
|
|
Playback::~Playback()
|
|
{
|
|
MLOGI("~Playback\n");
|
|
stop();
|
|
|
|
if (mDemuxer) {
|
|
mDemuxer.clear();
|
|
}
|
|
|
|
if (mPlayer != AML_MP_INVALID_HANDLE) {
|
|
Aml_MP_Player_Destroy(mPlayer);
|
|
mPlayer = AML_MP_INVALID_HANDLE;
|
|
}
|
|
|
|
MLOGI("dtor playback end!");
|
|
}
|
|
|
|
int Playback::setAVSyncSource(Aml_MP_AVSyncSource syncSource)
|
|
{
|
|
AML_MP_TRACE(10);
|
|
std::unique_lock<std::mutex> _l(mLock);
|
|
|
|
mSyncSource = syncSource;
|
|
MLOGI("mSyncSource is %d", mSyncSource);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Playback::setPcrPid(int pid)
|
|
{
|
|
AML_MP_TRACE(10);
|
|
std::unique_lock<std::mutex> _l(mLock);
|
|
|
|
mPcrPid = pid;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Playback::setSubtitleDisplayWindow(int x, int y, int width, int height) {
|
|
MLOGI("setSubtitleDisplayWindow, x:%d, y: %d, width: %d, height: %d", x, y, width, height);
|
|
int ret = Aml_MP_Player_SetSubtitleWindow(mPlayer, x, y,width, height);
|
|
return ret;
|
|
}
|
|
|
|
int Playback::setVideoWindow(int x, int y, int width, int height)
|
|
{
|
|
MLOGI("setVideoWindow, x:%d, y: %d, width: %d, height: %d", x, y, width, height);
|
|
int ret = Aml_MP_Player_SetVideoWindow(mPlayer, x, y,width, height);
|
|
return ret;
|
|
}
|
|
|
|
int Playback::setParameter(Aml_MP_PlayerParameterKey key, void* parameter)
|
|
{
|
|
int ret = Aml_MP_Player_SetParameter(mPlayer, key, parameter);
|
|
return ret;
|
|
}
|
|
|
|
#ifdef ANDROID
|
|
void Playback::setANativeWindow(const android::sp<ANativeWindow>& window)
|
|
{
|
|
MLOGI("setANativeWindow");
|
|
Aml_MP_Player_SetANativeWindow(mPlayer, window.get());
|
|
}
|
|
#endif
|
|
|
|
void Playback::playerRegisterEventCallback(Aml_MP_PlayerEventCallback cb, void* userData)
|
|
{
|
|
mEventCallback = cb;
|
|
mUserData = userData;
|
|
}
|
|
|
|
void Playback::eventCallback(Aml_MP_PlayerEventType eventType, int64_t param)
|
|
{
|
|
MLOGD("Playback eventCallback event: %d, %s, param %" PRIx64 "\n", eventType, mpPlayerEventType2Str(eventType), param);
|
|
switch (eventType) {
|
|
case AML_MP_PLAYER_EVENT_VIDEO_OVERFLOW:
|
|
{
|
|
uint32_t video_overflow_num;
|
|
video_overflow_num = *(uint32_t*)param;
|
|
MLOGI("%s %d\n", mpPlayerEventType2Str(eventType), video_overflow_num);
|
|
}
|
|
break;
|
|
|
|
case AML_MP_PLAYER_EVENT_VIDEO_UNDERFLOW:
|
|
{
|
|
uint32_t video_underflow_num;
|
|
video_underflow_num = *(uint32_t*)param;
|
|
MLOGI("%s %d\n", mpPlayerEventType2Str(eventType), video_underflow_num);
|
|
}
|
|
break;
|
|
|
|
case AML_MP_PLAYER_EVENT_AUDIO_OVERFLOW:
|
|
{
|
|
uint32_t audio_overflow_num;
|
|
audio_overflow_num = *(uint32_t*)param;
|
|
MLOGI("%s %d\n", mpPlayerEventType2Str(eventType), audio_overflow_num);
|
|
}
|
|
break;
|
|
|
|
case AML_MP_PLAYER_EVENT_AUDIO_UNDERFLOW:
|
|
{
|
|
uint32_t audio_underflow_num;
|
|
audio_underflow_num = *(uint32_t*)param;
|
|
MLOGI("%s %d\n", mpPlayerEventType2Str(eventType), audio_underflow_num);
|
|
}
|
|
break;
|
|
|
|
case AML_MP_PLAYER_EVENT_VIDEO_INPUT_BUFFER_DONE:
|
|
{
|
|
if (mDemuxer) {
|
|
mDemuxer->notifyStreamInputBufferDone(AML_MP_STREAM_TYPE_VIDEO, param);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case AML_MP_PLAYER_EVENT_AUDIO_INPUT_BUFFER_DONE:
|
|
{
|
|
if (mDemuxer) {
|
|
mDemuxer->notifyStreamInputBufferDone(AML_MP_STREAM_TYPE_AUDIO, param);
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (mEventCallback) {
|
|
mEventCallback(mUserData, eventType, param);
|
|
}
|
|
}
|
|
|
|
int Playback::start(const sptr<ProgramInfo>& programInfo, AML_MP_CASSESSION casSession, PlayMode playMode)
|
|
{
|
|
mProgramInfo = programInfo;
|
|
|
|
//printStreamsInfo();
|
|
MLOGI(">>>> Playback start\n");
|
|
mPlayMode = playMode;
|
|
MLOGI("Playback start mPlayMode:%d\n", mPlayMode);
|
|
int ret = 0;
|
|
|
|
if (mPlayer == AML_MP_INVALID_HANDLE) {
|
|
return -1;
|
|
}
|
|
|
|
bool useTif = false;
|
|
Aml_MP_Player_SetParameter(mPlayer, AML_MP_PLAYER_PARAMETER_USE_TIF, &useTif);
|
|
|
|
Aml_MP_Player_RegisterEventCallBack(mPlayer, [](void* userData, Aml_MP_PlayerEventType eventType, int64_t param) {
|
|
static_cast<Playback*>(userData)->eventCallback(eventType, param);
|
|
}, this);
|
|
|
|
if (mProgramInfo->scrambled) {
|
|
Aml_MP_Player_SetCasSession(mPlayer, casSession);
|
|
}
|
|
Aml_MP_Player_SetAVSyncSource(mPlayer, mSyncSource);
|
|
if (mSyncSource == AML_MP_AVSYNC_SOURCE_PCR && mPcrPid != AML_MP_INVALID_PID) {
|
|
Aml_MP_Player_SetPcrPid(mPlayer, mPcrPid);
|
|
}
|
|
|
|
if (mPlayMode == PlayMode::START_AUDIO_START_VIDEO) {
|
|
if (setAudioParams()) {
|
|
ret |= Aml_MP_Player_StartAudioDecoding(mPlayer);
|
|
}
|
|
|
|
if (setADParams()) {
|
|
ret |= Aml_MP_Player_StartADDecoding(mPlayer);
|
|
}
|
|
|
|
if (setVideoParams()) {
|
|
ret |= Aml_MP_Player_StartVideoDecoding(mPlayer);
|
|
}
|
|
|
|
if (setSubtitleParams()) {
|
|
ret |= Aml_MP_Player_StartSubtitleDecoding(mPlayer);
|
|
}
|
|
} else if (mPlayMode == PlayMode::START_VIDEO_START_AUDIO) {
|
|
if (setVideoParams()) {
|
|
ret |= Aml_MP_Player_StartVideoDecoding(mPlayer);
|
|
}
|
|
|
|
if (setAudioParams()) {
|
|
ret |= Aml_MP_Player_StartAudioDecoding(mPlayer);
|
|
}
|
|
|
|
if (setADParams()) {
|
|
ret |= Aml_MP_Player_StartADDecoding(mPlayer);
|
|
}
|
|
|
|
if (setSubtitleParams()) {
|
|
ret |= Aml_MP_Player_StartSubtitleDecoding(mPlayer);
|
|
}
|
|
} else if (mPlayMode == PlayMode::START_ALL_STOP_ALL || mPlayMode == PlayMode::START_ALL_STOP_SEPARATELY) {
|
|
setAudioParams();
|
|
setADParams();
|
|
setVideoParams();
|
|
setSubtitleParams();
|
|
MLOGI(">>> Aml_MP_Player_Start\n");
|
|
ret = Aml_MP_Player_Start(mPlayer);
|
|
} else if (mPlayMode == PlayMode::START_SEPARATELY_STOP_ALL ||
|
|
mPlayMode == PlayMode::START_SEPARATELY_STOP_SEPARATELY ||
|
|
playMode == PlayMode::START_SEPARATELY_STOP_SEPARATELY_V2) {
|
|
setAudioParams();
|
|
setADParams();
|
|
setVideoParams();
|
|
setSubtitleParams();
|
|
if (playMode == PlayMode::START_SEPARATELY_STOP_SEPARATELY_V2) {
|
|
ret |= Aml_MP_Player_StartVideoDecoding(mPlayer);
|
|
ret |= Aml_MP_Player_StartAudioDecoding(mPlayer);
|
|
ret |= Aml_MP_Player_StartADDecoding(mPlayer);
|
|
} else {
|
|
ret |= Aml_MP_Player_StartAudioDecoding(mPlayer);
|
|
ret |= Aml_MP_Player_StartADDecoding(mPlayer);
|
|
ret |= Aml_MP_Player_StartVideoDecoding(mPlayer);
|
|
}
|
|
ret |= Aml_MP_Player_StartSubtitleDecoding(mPlayer);
|
|
} else {
|
|
MLOGE("unknown playmode:%d", mPlayMode);
|
|
}
|
|
|
|
if (mProgramInfo->subtitleCodec == AML_MP_SUBTITLE_CODEC_TELETEXT && mProgramInfo->magazine != -1 && mProgramInfo->page != -1) {
|
|
// teletext need call ttControl after start
|
|
AML_MP_TeletextCtrlParam teletextCtrlParam = {
|
|
.magazine = mProgramInfo->magazine,
|
|
.page = mProgramInfo->page,
|
|
.event = AML_MP_TT_EVENT_GO_TO_SUBTITLE,
|
|
};
|
|
Aml_MP_Player_SetParameter(mPlayer, AML_MP_PLAYER_PARAMETER_TELETEXT_CONTROL, &teletextCtrlParam);
|
|
}
|
|
|
|
if (mDemuxer) {
|
|
if (mProgramInfo->videoPid != AML_MP_INVALID_PID) {
|
|
mDemuxer->openStream(AML_MP_STREAM_TYPE_VIDEO, 16, 3 * 1024 * 1024, mDrmMode == AML_MP_INPUT_STREAM_SECURE_MEMORY,
|
|
[this](Aml_MP_StreamType streamType, const uint8_t* data, size_t size, int64_t pts) {
|
|
return Aml_MP_Player_WriteEsData(mPlayer, streamType, data, size, pts);
|
|
});
|
|
mDemuxer->startStream(AML_MP_STREAM_TYPE_VIDEO, mProgramInfo->videoPid, mProgramInfo->videoCodec);
|
|
}
|
|
|
|
if (mProgramInfo->audioPid != AML_MP_INVALID_PID) {
|
|
mDemuxer->openStream(AML_MP_STREAM_TYPE_AUDIO, 128, 4 * 1024, false,
|
|
[this](Aml_MP_StreamType streamType, const uint8_t* data, size_t size, int64_t pts) {
|
|
return Aml_MP_Player_WriteEsData(mPlayer, streamType, data, size, pts);
|
|
});
|
|
mDemuxer->startStream(AML_MP_STREAM_TYPE_AUDIO, mProgramInfo->audioPid, mProgramInfo->audioCodec);
|
|
}
|
|
}
|
|
|
|
if (ret != 0) {
|
|
MLOGE("player start failed!");
|
|
}
|
|
|
|
MLOGI("<<<< Playback start\n");
|
|
usleep(350 * 1000);
|
|
return ret;
|
|
}
|
|
|
|
bool Playback::setAudioParams()
|
|
{
|
|
Aml_MP_AudioParams audioParams;
|
|
memset(&audioParams, 0, sizeof(audioParams));
|
|
audioParams.audioCodec = mProgramInfo->audioCodec;
|
|
audioParams.pid = mProgramInfo->audioPid;
|
|
MLOGI("setAudioParams apid:%d\n", audioParams.pid);
|
|
Aml_MP_Player_SetAudioParams(mPlayer, &audioParams);
|
|
|
|
return audioParams.pid != AML_MP_INVALID_PID;
|
|
}
|
|
|
|
bool Playback::setADParams()
|
|
{
|
|
|
|
Aml_MP_AudioParams adParams;
|
|
memset(&adParams, 0, sizeof(adParams));
|
|
adParams.audioCodec = mProgramInfo->adCodec;
|
|
adParams.pid = mProgramInfo->adPid;
|
|
MLOGI("setADParams apid:%d\n", adParams.pid);
|
|
Aml_MP_Player_SetADParams(mPlayer, &adParams);
|
|
|
|
Aml_MP_Player_SetADVolume(mPlayer, 100);
|
|
|
|
Aml_MP_ADVolume adVolume{50, 50};
|
|
Aml_MP_Player_SetParameter(mPlayer, AML_MP_PLAYER_PARAMETER_AD_MIX_LEVEL, &adVolume);
|
|
|
|
return adParams.pid != AML_MP_INVALID_PID;
|
|
}
|
|
|
|
bool Playback::setVideoParams()
|
|
{
|
|
Aml_MP_VideoParams videoParams;
|
|
memset(&videoParams, 0, sizeof(videoParams));
|
|
videoParams.videoCodec = mProgramInfo->videoCodec;
|
|
videoParams.pid = mProgramInfo->videoPid;
|
|
MLOGI("setVideoParams vpid:%d\n", videoParams.pid);
|
|
Aml_MP_Player_SetVideoParams(mPlayer, &videoParams);
|
|
|
|
return videoParams.pid != AML_MP_INVALID_PID;
|
|
}
|
|
|
|
bool Playback::setSubtitleParams()
|
|
{
|
|
Aml_MP_SubtitleParams subtitleParams{};
|
|
subtitleParams.subtitleCodec = mProgramInfo->subtitleCodec;
|
|
switch (subtitleParams.subtitleCodec) {
|
|
case AML_MP_SUBTITLE_CODEC_DVB:
|
|
subtitleParams.pid = mProgramInfo->subtitlePid;
|
|
subtitleParams.compositionPageId = mProgramInfo->compositionPageId;
|
|
subtitleParams.ancillaryPageId = mProgramInfo->ancillaryPageId;
|
|
break;
|
|
|
|
case AML_MP_SUBTITLE_CODEC_TELETEXT:
|
|
subtitleParams.pid = mProgramInfo->subtitlePid;
|
|
break;
|
|
|
|
case AML_MP_SUBTITLE_CODEC_SCTE27:
|
|
subtitleParams.pid = mProgramInfo->subtitlePid;
|
|
break;
|
|
|
|
case AML_MP_SUBTITLE_CODEC_ASS:
|
|
subtitleParams.pid = mProgramInfo->subtitlePid;
|
|
break;
|
|
|
|
case AML_MP_SUBTITLE_CODEC_SUBRIP:
|
|
subtitleParams.pid = mProgramInfo->subtitlePid;
|
|
break;
|
|
|
|
case AML_MP_SUBTITLE_CODEC_TTML://TTML Subtitle Support
|
|
subtitleParams.pid = mProgramInfo->subtitlePid;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (subtitleParams.subtitleCodec != AML_MP_CODEC_UNKNOWN) {
|
|
Aml_MP_Player_SetSubtitleParams(mPlayer, &subtitleParams);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int Playback::stop()
|
|
{
|
|
int ret = 0;
|
|
|
|
if (mDemuxer) {
|
|
mDemuxer->stopStream(AML_MP_STREAM_TYPE_VIDEO);
|
|
mDemuxer->stopStream(AML_MP_STREAM_TYPE_AUDIO);
|
|
}
|
|
|
|
if (mPlayMode == PlayMode::START_ALL_STOP_ALL || mPlayMode == PlayMode::START_SEPARATELY_STOP_ALL) {
|
|
ret = Aml_MP_Player_Stop(mPlayer);
|
|
if (ret < 0) {
|
|
MLOGE("player stop failed!");
|
|
}
|
|
} else {
|
|
if (mPlayMode == PlayMode::START_VIDEO_START_AUDIO) {
|
|
ret |= Aml_MP_Player_StopVideoDecoding(mPlayer);
|
|
ret |= Aml_MP_Player_StopAudioDecoding(mPlayer);
|
|
ret |= Aml_MP_Player_StopADDecoding(mPlayer);
|
|
} else {
|
|
ret |= Aml_MP_Player_StopAudioDecoding(mPlayer);
|
|
ret |= Aml_MP_Player_StopADDecoding(mPlayer);
|
|
ret |= Aml_MP_Player_StopVideoDecoding(mPlayer);
|
|
}
|
|
ret |= Aml_MP_Player_StopSubtitleDecoding(mPlayer);
|
|
|
|
if (ret != 0) {
|
|
MLOGE("player stop separately failed!");
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void Playback::signalQuit()
|
|
{
|
|
MLOGI("signalQuit!");
|
|
}
|
|
|
|
int Playback::writeData(const uint8_t* buffer, size_t size)
|
|
{
|
|
int wlen = -1;
|
|
|
|
if (mDemuxer) {
|
|
bool overflow = false;
|
|
mDemuxer->getFlowStatus(nullptr, &overflow);
|
|
if (overflow) {
|
|
//MLOGI("overflow!");
|
|
return -1;
|
|
}
|
|
//coverity[value_overwrite]
|
|
wlen = mDemuxer->feedTs(buffer, size);
|
|
if (wlen != (int)size) {
|
|
MLOGW("feedTs return %d, expected:%zu", wlen, size);
|
|
}
|
|
} else {
|
|
//coverity[value_overwrite]
|
|
wlen = Aml_MP_Player_WriteData(mPlayer, buffer, size);
|
|
}
|
|
|
|
return wlen;
|
|
}
|
|
|
|
void Playback::printStreamsInfo()
|
|
{
|
|
if (mProgramInfo == nullptr) {
|
|
return;
|
|
}
|
|
|
|
for (size_t i = 0; i < mProgramInfo->videoStreams.size(); i++) {
|
|
if (i == 0) {
|
|
printf("Video Streams:\n");
|
|
}
|
|
|
|
printf("\tVideo[%zu] pid: %d, codec: %d\n", i, mProgramInfo->videoStreams.at(i).pid, mProgramInfo->videoStreams.at(i).codecId);
|
|
}
|
|
|
|
for (size_t i = 0; i < mProgramInfo->audioStreams.size(); i++) {
|
|
if (i == 0) {
|
|
printf("Audio streams:\n");
|
|
}
|
|
printf("\tAudio[%zu] pid: %d, codec: %d\n", i, mProgramInfo->audioStreams.at(i).pid, mProgramInfo->audioStreams.at(i).codecId);
|
|
}
|
|
|
|
for (size_t i = 0; i < mProgramInfo->subtitleStreams.size(); i++) {
|
|
if (i == 0) {
|
|
printf("Subtitle streams:\n");
|
|
}
|
|
printf("\tSubtitle[%zu] pid: %d, codec: %d", i, mProgramInfo->subtitleStreams.at(i).pid, mProgramInfo->subtitleStreams.at(i).codecId);
|
|
if (mProgramInfo->subtitleStreams.at(i).codecId == AML_MP_SUBTITLE_CODEC_DVB) {
|
|
printf("[%d, %d]\n", mProgramInfo->subtitleStreams.at(i).compositionPageId, mProgramInfo->subtitleStreams.at(i).ancillaryPageId);
|
|
} else {
|
|
printf("\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
static struct TestModule::Command g_commandTable[] = {
|
|
{
|
|
"help", 0, "help",
|
|
[](AML_MP_PLAYER player __unused, const std::vector<std::string>& args __unused) -> int {
|
|
TestModule::printCommands(g_commandTable, true);
|
|
return 0;
|
|
}
|
|
},
|
|
|
|
{
|
|
"pause", 0, "pause player",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
return Aml_MP_Player_Pause(player);
|
|
}
|
|
},
|
|
|
|
{
|
|
"resume", 0, "resume player",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
return Aml_MP_Player_Resume(player);
|
|
}
|
|
},
|
|
|
|
{
|
|
"hide", 0, "hide video",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
return Aml_MP_Player_HideVideo(player);
|
|
}
|
|
},
|
|
|
|
{
|
|
"show", 0, "show video",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
return Aml_MP_Player_ShowVideo(player);
|
|
}
|
|
},
|
|
|
|
{
|
|
"gShowState", 0, "get show state",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
bool state;
|
|
int ret = Aml_MP_Player_GetParameter(player, AML_MP_PLAYER_PARAMETER_VIDEO_SHOW_STATE, &state);
|
|
//coverity[uninit_use]
|
|
printf("now video show state: %s(%d)\n", state ? "show" : "hide", ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"flush", 0, "call flush",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
int ret = Aml_MP_Player_Flush(player);
|
|
printf("call flush ret: %d\n", ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"switchAudio", 0, "switch audio",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
Aml_MP_AudioParams audioParams;
|
|
int ret;
|
|
int audioCodec, audioPid;
|
|
if (args.size() != 3) {
|
|
printf("Input example: switchAudio Pid codec_ID\n");
|
|
return -1;
|
|
}
|
|
printf("String input: %s %s\n", args[1].data(), args[2].data());
|
|
audioPid = stof(args[1]);
|
|
audioCodec = stof(args[2]);
|
|
memset(&audioParams, 0, sizeof(audioParams));
|
|
audioParams.audioCodec = (Aml_MP_CodecID)audioCodec;
|
|
audioParams.pid = audioPid;
|
|
ret = Aml_MP_Player_SwitchAudioTrack(player, &audioParams);
|
|
printf("Switch audio param[%d, %d], ret: %d\n", audioParams.pid, audioParams.audioCodec, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"switchSubtitle", 0, "switch subtitle",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
Aml_MP_SubtitleParams subtitleParams;
|
|
int ret;
|
|
int subtitleCodec, subtitlePid, compositionPageId, ancillaryPageId;
|
|
if (args.size() != 5) {
|
|
printf("Input example: switchSubtitle Pid codec_ID compositionPageId ancillaryPageId\n");
|
|
return -1;
|
|
}
|
|
printf("String input: %s %s\n", args[1].data(), args[2].data());
|
|
subtitlePid = stof(args[1]);
|
|
subtitleCodec = stof(args[2]);
|
|
compositionPageId = stof(args[3]);
|
|
ancillaryPageId = stof(args[4]);
|
|
memset(&subtitleParams, 0, sizeof(subtitleParams));
|
|
subtitleParams.subtitleCodec = (Aml_MP_CodecID)subtitleCodec;
|
|
subtitleParams.pid = subtitlePid;
|
|
if (subtitleParams.subtitleCodec == AML_MP_SUBTITLE_CODEC_DVB) {
|
|
subtitleParams.compositionPageId = compositionPageId;
|
|
subtitleParams.ancillaryPageId = ancillaryPageId;
|
|
}
|
|
ret = Aml_MP_Player_SwitchSubtitleTrack(player, &subtitleParams);
|
|
printf("Switch audio param[%d, %d], ret: %d\n", subtitleParams.pid, subtitleParams.subtitleCodec, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"gPts", 0, "get Pts",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
int64_t pts = 0;
|
|
int ret = Aml_MP_Player_GetCurrentPts(player, AML_MP_STREAM_TYPE_VIDEO, &pts);
|
|
printf("Current video pts: 0x%" PRIx64 ", ret: %d\n", pts, ret);
|
|
ret = Aml_MP_Player_GetCurrentPts(player, AML_MP_STREAM_TYPE_AUDIO, &pts);
|
|
printf("Current audio pts: 0x%" PRIx64 ", ret: %d\n", pts, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"gFPts", 0, "get FPts",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
int64_t pts = 0;
|
|
int ret = Aml_MP_Player_GetFirstPts(player, AML_MP_STREAM_TYPE_VIDEO, &pts);
|
|
printf("first video pts: 0x%" PRIx64 ", ret: %d\n", pts, ret);
|
|
ret = Aml_MP_Player_GetFirstPts(player, AML_MP_STREAM_TYPE_AUDIO, &pts);
|
|
printf("first audio pts: 0x%" PRIx64 ", ret: %d\n", pts, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"gVolume", 0, "get volume",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
float volume = 0.0f;
|
|
int ret = Aml_MP_Player_GetVolume(player, &volume);
|
|
printf("Current volume: %f, ret: %d\n", volume, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"sVolume", 0, "set volume",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
float volume = 0.0f, volume2 = 0.0f;
|
|
if (args.size() != 2) {
|
|
printf("Input example: sVolume volume\n");
|
|
return -1;
|
|
}
|
|
printf("String input: %s\n", args[1].data());
|
|
volume = stof(args[1]);
|
|
int ret = Aml_MP_Player_SetVolume(player,volume);
|
|
//coverity[value_overwrite]
|
|
ret = Aml_MP_Player_GetVolume(player, &volume2);
|
|
printf("Get volume: %f, set volume: %f, ret: %d\n", volume2, volume, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"gMute", 0, "get audio mute/unmute state",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
int mute = 0;
|
|
int ret = Aml_MP_Player_GetParameter(player, AML_MP_PLAYER_PARAMETER_AUDIO_MUTE, &mute);
|
|
printf("Current mute state: %d, ret: %d\n", mute, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"sMute", 0, "set audio mute/unmute state",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
int mute = 0, mute2 = 0;
|
|
if (args.size() != 2) {
|
|
printf("Input example: sMute mute\n");
|
|
return -1;
|
|
}
|
|
printf("String input: %s\n", args[1].data());
|
|
mute = stod(args[1]);
|
|
int ret = Aml_MP_Player_SetParameter(player, AML_MP_PLAYER_PARAMETER_AUDIO_MUTE, &mute);
|
|
//coverity[value_overwrite]
|
|
ret = Aml_MP_Player_GetParameter(player, AML_MP_PLAYER_PARAMETER_AUDIO_MUTE, &mute2);
|
|
printf("Get mute state: %d, set mute: %d, ret: %d\n", mute2, mute, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"sFast", 0, "set Fast rate",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
float fastRate, getRate = -1;
|
|
int ret;
|
|
if (args.size() != 2) {
|
|
printf("Input example: sFast rate\n");
|
|
return -1;
|
|
}
|
|
printf("String input: %s\n", args[1].data());
|
|
fastRate = stof(args[1]);
|
|
ret = Aml_MP_Player_SetPlaybackRate(player, fastRate);
|
|
Aml_MP_Player_GetPlaybackRate(player, &getRate);
|
|
printf("set rate: %f(%f), ret: %d\n", fastRate, getRate, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"gFast", 0, "get Fast rate",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
float fastRate = -1;
|
|
int ret;
|
|
ret = Aml_MP_Player_GetPlaybackRate(player, &fastRate);
|
|
printf("get rate: %f, ret: %d\n", fastRate, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"gDecodingState", 0, "get a/v decoding state",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
int ret;
|
|
AML_MP_DecodingState decodingState = AML_MP_DECODING_STATE_STOPPED;
|
|
ret = Aml_MP_Player_GetDecodingState(player, AML_MP_STREAM_TYPE_VIDEO, &decodingState);
|
|
printf("get video decoding state: %d, ret: %d\n", decodingState, ret);
|
|
ret = Aml_MP_Player_GetDecodingState(player, AML_MP_STREAM_TYPE_AUDIO, &decodingState);
|
|
printf("get audio decoding state: %d, ret: %d\n", decodingState, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"gBuffer", 0, "get Buffer state",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
Aml_MP_BufferStat bufferStat;
|
|
memset(&bufferStat, 0, sizeof(Aml_MP_BufferStat));
|
|
int ret = Aml_MP_Player_GetBufferStat(player, &bufferStat);
|
|
printf("Audio buffer stat: size: %d, dataLen: %d, bufferedMs: %d\n", bufferStat.audioBuffer.size, bufferStat.audioBuffer.dataLen, bufferStat.audioBuffer.bufferedMs);
|
|
printf("Video buffer stat: size: %d, dataLen: %d, bufferedMs: %d\n", bufferStat.videoBuffer.size, bufferStat.videoBuffer.dataLen, bufferStat.videoBuffer.bufferedMs);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"sWindow", 0, "set video window",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
int32_t x, y, width, height;
|
|
if (args.size() != 5) {
|
|
printf("Input example: sWindow x y width height\n");
|
|
return -1;
|
|
}
|
|
printf("String input x: %s, y: %s, width: %s, height: %s\n", args[1].data(), args[2].data(), args[3].data(), args[4].data());
|
|
x = stoi(args[1]);
|
|
y = stoi(args[2]);
|
|
width = stoi(args[3]);
|
|
height = stoi(args[4]);
|
|
int ret = Aml_MP_Player_SetVideoWindow(player, x, y,width, height);
|
|
printf("set x: %d, y: %d, width: %d, height: %d, ret: %d\n", x, y, width, height, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"sZorder", 0, "set zorder",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
int32_t zorder;
|
|
if (args.size() != 2) {
|
|
printf("Input example: sZorder zorder\n");
|
|
return -1;
|
|
}
|
|
printf("String input zorder: %s\n", args[1].data());
|
|
zorder = stoi(args[1]);
|
|
int ret = Aml_MP_Player_SetParameter(player, AML_MP_PLAYER_PARAMETER_VIDEO_WINDOW_ZORDER, &zorder);
|
|
printf("set zorder: %d, ret: %d\n", zorder, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"sDspMode", 0, "set display mode",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
Aml_MP_VideoDisplayMode videoMode = AML_MP_VIDEO_DISPLAY_MODE_NORMAL;
|
|
if (args.size() != 2) {
|
|
printf("Input example: sDspMode display_mode\n");
|
|
return -1;
|
|
}
|
|
videoMode = (Aml_MP_VideoDisplayMode)stoi(args[1]);
|
|
int ret = Aml_MP_Player_SetParameter(player, AML_MP_PLAYER_PARAMETER_VIDEO_DISPLAY_MODE, &videoMode);
|
|
printf("AML_MP_PLAYER_PARAMETER_VIDEO_DISPLAY_MODE set mode: %d, ret: %d\n", videoMode, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"sAfdMode", 0, "set afd aspect mode",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
Aml_MP_VideoAFDAspectMode aspectMode = AML_MP_VIDEO_AFD_ASPECT_MODE_AUTO;
|
|
if (args.size() != 2) {
|
|
printf("Input example: sAfdMode aspect_mode\n");
|
|
return -1;
|
|
}
|
|
aspectMode = (Aml_MP_VideoAFDAspectMode)stoi(args[1]);
|
|
int ret = Aml_MP_Player_SetParameter(player, AML_MP_PLAYER_PARAMETER_VIDEO_AFD_ASPECT_MODE, &aspectMode);
|
|
printf("AML_MP_PLAYER_PARAMETER_VIDEO_AFD_ASPECT_MODE set mode: %d, ret: %d\n", aspectMode, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"sParam", 0, "set param",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
Aml_MP_VideoDisplayMode videoMode = AML_MP_VIDEO_DISPLAY_MODE_NORMAL;
|
|
int ret = Aml_MP_Player_SetParameter(player, AML_MP_PLAYER_PARAMETER_VIDEO_DISPLAY_MODE, &videoMode);
|
|
printf("AML_MP_PLAYER_PARAMETER_VIDEO_DISPLAY_MODE set mode: %d, ret: %d\n", videoMode, ret);
|
|
bool blackOut = true;
|
|
ret = Aml_MP_Player_SetParameter(player, AML_MP_PLAYER_PARAMETER_BLACK_OUT, &blackOut);
|
|
printf("AML_MP_PLAYER_PARAMETER_BLACK_OUT set mode: %d, ret: %d\n", blackOut, ret);
|
|
Aml_MP_AudioOutputMode audioMode = AML_MP_AUDIO_OUTPUT_PCM;
|
|
ret = Aml_MP_Player_SetParameter(player, AML_MP_PLAYER_PARAMETER_AUDIO_OUTPUT_MODE, &audioMode);
|
|
printf("AML_MP_PLAYER_PARAMETER_AUDIO_OUTPUT_MODE set mode: %d, ret: %d\n", audioMode, ret);
|
|
Aml_MP_ADVolume adVolume = {50, 50};
|
|
ret = Aml_MP_Player_SetParameter(player, AML_MP_PLAYER_PARAMETER_AD_MIX_LEVEL, &adVolume);
|
|
printf("AML_MP_PLAYER_PARAMETER_AD_MIX_LEVEL set mode: %d, %d, ret: %d\n", adVolume.masterVolume, adVolume.slaveVolume, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"gParam", 0, "get param",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
Aml_MP_VideoInfo videoInfo;
|
|
memset(&videoInfo, 0, sizeof(Aml_MP_VideoInfo));
|
|
int ret = Aml_MP_Player_GetParameter(player, AML_MP_PLAYER_PARAMETER_VIDEO_INFO, &videoInfo);
|
|
printf("AML_MP_PLAYER_PARAMETER_VIDEO_INFO, width: %d, height: %d, framerate: %d, bitrate: %d, ratio64: %d, ret: %d\n", videoInfo.width, videoInfo.height, videoInfo.frameRate, videoInfo.bitrate, videoInfo.ratio64, ret);
|
|
printf("AML_MP_PLAYER_PARAMETER_VIDEO_INFO, dar.numerator: %ld, dar.denominator: %ld, ret: %d\n", videoInfo.dar.numerator, videoInfo.dar.denominator, ret);
|
|
Aml_MP_VdecStat vdecStat;
|
|
memset(&vdecStat, 0, sizeof(Aml_MP_VdecStat));
|
|
ret = Aml_MP_Player_GetParameter(player, AML_MP_PLAYER_PARAMETER_VIDEO_DECODE_STAT, &vdecStat);
|
|
printf("AML_MP_PLAYER_PARAMETER_VIDEO_DECODE_STAT, frame_width: %d, frame_height: %d, frame_rate: %d, ret: %d\n", vdecStat.frame_width, vdecStat.frame_height, vdecStat.frame_rate, ret);
|
|
Aml_MP_AudioInfo audioInfo;
|
|
memset(&audioInfo, 0, sizeof(Aml_MP_AudioInfo));
|
|
ret = Aml_MP_Player_GetParameter(player, AML_MP_PLAYER_PARAMETER_AUDIO_INFO, &audioInfo);
|
|
printf("AML_MP_PLAYER_PARAMETER_AUDIO_INFO, sample_rate: %d, channels: %d, channel_mask: %d, bitrate: %d, ret: %d\n", audioInfo.sample_rate, audioInfo.channels, audioInfo.channel_mask, audioInfo.bitrate, ret);
|
|
Aml_MP_AdecStat adecStat;
|
|
memset(&adecStat, 0, sizeof(Aml_MP_AdecStat));
|
|
ret = Aml_MP_Player_GetParameter(player, AML_MP_PLAYER_PARAMETER_AUDIO_DECODE_STAT, &adecStat);
|
|
printf("AML_MP_PLAYER_PARAMETER_AUDIO_DECODE_STAT get audio decode stat frame_count: %d, error_frame_count: %d, drop_frame_count: %d, ret: %d\n", adecStat.frame_count, adecStat.error_frame_count, adecStat.drop_frame_count, ret);
|
|
Aml_MP_AudioInfo adInfo;
|
|
memset(&adInfo, 0, sizeof(Aml_MP_AudioInfo));
|
|
ret = Aml_MP_Player_GetParameter(player, AML_MP_PLAYER_PARAMETER_AD_INFO, &adInfo);
|
|
printf("AML_MP_PLAYER_PARAMETER_AD_INFO, sample_rate: %d, channels: %d, channel_mask: %d, bitrate: %d, ret: %d\n", adInfo.sample_rate, adInfo.channels, adInfo.channel_mask, adInfo.bitrate, ret);
|
|
Aml_MP_AdecStat adStat;
|
|
memset(&adStat, 0, sizeof(Aml_MP_AdecStat));
|
|
ret = Aml_MP_Player_GetParameter(player, AML_MP_PLAYER_PARAMETER_AD_DECODE_STAT, &adStat);
|
|
printf("AML_MP_PLAYER_PARAMETER_AD_DECODE_STAT get audio decode stat frame_count: %d, error_frame_count: %d, drop_frame_count: %d, ret: %d\n", adStat.frame_count, adStat.error_frame_count, adStat.drop_frame_count, ret);
|
|
uint32_t instanceId = 0;
|
|
ret = Aml_MP_Player_GetParameter(player, AML_MP_PLAYER_PARAMETER_INSTANCE_ID, &instanceId);
|
|
printf("AML_MP_PLAYER_PARAMETER_INSTANCE_ID get instance id: %d\n", instanceId);
|
|
int32_t syncId = -1;
|
|
ret = Aml_MP_Player_GetParameter(player, AML_MP_PLAYER_PARAMETER_SYNC_ID, &syncId);
|
|
printf("AML_MP_PLAYER_PARAMETER_SYNC_ID get sync id: %d\n", syncId);
|
|
|
|
Aml_MP_AvInfo avInfo;
|
|
memset(&avInfo, 0, sizeof(Aml_MP_AvInfo));
|
|
avInfo.dataLength = 1024;
|
|
avInfo.streamTypeMask = AML_MP_STREAM_TYPE_MASK_VIDEO | AML_MP_STREAM_TYPE_MASK_AUDIO;
|
|
avInfo.data = (uint8_t *)malloc(avInfo.dataLength);
|
|
ret = Aml_MP_Player_GetParameter(player, AML_MP_PLAYER_PARAMETER_AV_INFO_JSON, &avInfo);
|
|
printf("AML_MP_PLAYER_PARAMETER_AV_INFO_JSON, json[%zu]:\n%s\n", avInfo.actualLength, avInfo.data);
|
|
free(avInfo.data);
|
|
//coverity[assigned_pointer]
|
|
avInfo.data = NULL;
|
|
|
|
Aml_MP_AvStat avStat;
|
|
avStat.dataLength = 1024;
|
|
avStat.streamTypeMask = AML_MP_STREAM_TYPE_MASK_VIDEO | AML_MP_STREAM_TYPE_MASK_AUDIO;
|
|
avStat.data = (uint8_t *)malloc(avStat.dataLength);
|
|
ret = Aml_MP_Player_GetParameter(player, AML_MP_PLAYER_PARAMETER_AV_STAT_JSON, &avStat);
|
|
if (ret != AML_MP_OK) {
|
|
free(avStat.data);
|
|
//coverity[assigned_pointer]
|
|
avStat.data = NULL;
|
|
return ret;
|
|
}
|
|
|
|
printf("AML_MP_PLAYER_PARAMETER_AV_STAT_JSON, json[%zu]:\n%s\n", avStat.actualLength, avStat.data);
|
|
|
|
Json::Value root;
|
|
Json::CharReaderBuilder builder;
|
|
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
|
std::string errors;
|
|
std::string jsonString(reinterpret_cast<const char*>(avStat.data), avStat.actualLength);
|
|
|
|
free(avStat.data);
|
|
//coverity[assigned_pointer]
|
|
avStat.data = NULL;
|
|
|
|
// parse JSON
|
|
if (!reader->parse(jsonString.c_str(), jsonString.c_str() + jsonString.size(), &root, &errors)) {
|
|
printf("Parsed JSON failed! error:%s\n", errors.c_str());
|
|
return -1;
|
|
}
|
|
|
|
if (!root.isArray()) {
|
|
return -1;
|
|
}
|
|
|
|
if (avStat.streamTypeMask & AML_MP_STREAM_TYPE_MASK_VIDEO) {
|
|
const Json::Value& item = root[0];
|
|
|
|
printf("video stat:\n");
|
|
for (const auto& key : item.getMemberNames()) {
|
|
printf(" %s:%s\n", key.c_str(), item[key].toStyledString().c_str());
|
|
}
|
|
}
|
|
|
|
if (avStat.streamTypeMask & AML_MP_STREAM_TYPE_MASK_AUDIO) {
|
|
const Json::Value& item = root[1];
|
|
|
|
printf("audio stat:\n");
|
|
for (const auto& key : item.getMemberNames()) {
|
|
printf(" %s:%s\n", key.c_str(), item[key].toStyledString().c_str());
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"sSync", 0, "set sync mode",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
int ret = Aml_MP_Player_SetAVSyncSource(player, AML_MP_AVSYNC_SOURCE_PCR);
|
|
printf("set sync mode: %d, ret: %d\n", AML_MP_AVSYNC_SOURCE_PCR, ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"start", 0, "call start",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
int ret = Aml_MP_Player_Start(player);
|
|
printf("call start ret: %d\n", ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"stop", 0, "call stop",
|
|
[](AML_MP_PLAYER player, const std::vector<std::string>& args __unused) -> int {
|
|
int ret = Aml_MP_Player_Stop(player);
|
|
printf("call stop ret: %d\n", ret);
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"gDecCap", 0, "get decoder capability",
|
|
[](AML_MP_PLAYER player __unused, const std::vector<std::string>& args __unused) -> int {
|
|
int32_t decType;
|
|
char jsonInfo[1000]{0};
|
|
int ret;
|
|
if (args.size() != 2) {
|
|
printf("Input example: gDecCap decoder_id\n");
|
|
printf("Run getDecCapDemo\n");
|
|
ret = Aml_MP_GetCodecCapability(AML_MP_VIDEO_CODEC_H264, jsonInfo, 1000);
|
|
printf("Aml_MP_GetCodecCapability video AML_MP_VIDEO_CODEC_H264 json(%d): %s\n", ret, jsonInfo);
|
|
ret = Aml_MP_GetCodecCapability(AML_MP_AUDIO_CODEC_MP3, jsonInfo, 1000);
|
|
printf("Aml_MP_GetCodecCapability audio AML_MP_AUDIO_CODEC_MP3 json(%d): %s\n", ret, jsonInfo);
|
|
} else {
|
|
decType = stoi(args[1]);
|
|
ret = Aml_MP_GetCodecCapability((Aml_MP_CodecID)decType, jsonInfo, 1000);
|
|
printf("Aml_MP_GetCodecCapability json(%d): %s\n", ret, jsonInfo);
|
|
}
|
|
return ret;
|
|
}
|
|
},
|
|
|
|
{
|
|
"destroy", 0, "amlMpPlayerDemo quit",
|
|
[](AML_MP_PLAYER player __unused, const std::vector<std::string>& args __unused) -> int {
|
|
//Here we do nothing, amlMpPlayerDemo will quit at
|
|
//AmlMpTestSupporter::processCommand when run destroy command
|
|
//int ret = Aml_MP_Player_Destroy(player);
|
|
//printf("call destroy ret: %d\n", ret);
|
|
return 0;
|
|
}
|
|
},
|
|
|
|
{nullptr, 0, nullptr, nullptr}
|
|
};
|
|
|
|
const TestModule::Command* Playback::getCommandTable() const
|
|
{
|
|
return g_commandTable;
|
|
}
|
|
|
|
void* Playback::getCommandHandle() const
|
|
{
|
|
return mPlayer;
|
|
}
|
|
|
|
}
|