Files
BPI-CM9-Linux/aml-comp/multimedia/aml_mp_sdk/tests/amlMpMediaPlayerDemo/AmlMpMediaPlayerDemo.cpp
T
2026-08-24 10:03:24 +08:00

2565 lines
86 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 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_NDEBUG 0
#define LOG_TAG "AmlMpMediaPlayerDemo"
#include <utils/AmlMpLog.h>
#include <utils/AmlMpUtils.h>
#include <unistd.h>
#include <getopt.h>
#include "TestUtils.h"
#include <Aml_MP/Aml_MediaPlayer.h>
#include <string>
#include <vector>
#include <inttypes.h>
#include <signal.h>
#include <thread>
#include "../amlMpTestSupporter/TestModule.h"
#include <../../mediaplayer/AmlMediaPlayerBase.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <poll.h>
#include <termios.h>
#include <errno.h>
#include <iostream>
#include <stdexcept>
#include <Aml_MP/Cas.h>
//srand
#include <stdlib.h>
#include <time.h>
///////////////////////////////////////////////////////////////////////////////
//
struct Argument;
struct AmlMpMediaPlayerDemo;
struct playerRoster;
//func
static int tty_reset(int fd);
static int tty_cbreak(int fd);
//Track info
static void printCurTrackInfo(Aml_MP_TrackInfo *trackInfo, Aml_MP_MediaInfo* mediaInfo, Aml_MP_StreamType streamType);
static int getNextTrack(Aml_MP_TrackInfo *trackInfo, Aml_MP_MediaInfo* mediaInfo, Aml_MP_StreamType streamType);
static void printMediaInfo(Aml_MP_MediaInfo *mediaInfo);
//Multi
static int multiPlaybackThread(int id, bool isMain);
static int createMultiPlayback(int id, AML_MP_MEDIAPLAYER* player, struct Argument* argument, AmlMpMediaPlayerDemo* commandsProcess);
static int destroyMultiPlayback(int id);
static void closeMultiPlayback(int id);
static void closeAllMultiPlayback();
//utils
static int isUrlValid(const std::string url, std::string& urlHead, std::string& urlFile);
static int startingPlayCheck();
//callback func
static const char* mediaPlayerMediaErrorType2Str(Aml_MP_MediaPlayerMediaErrorType type);
void demoCallback(void* userData, Aml_MP_MediaPlayerEventType event, int64_t param);
//info
static void showOption();
static void showUsage();
///////////////////////////////////////////////////////////////////////////////
//static
static const char* mName = LOG_TAG;
using namespace aml_mp;
///////////////////////////////////////////////////////////////////////////////
//define
#define WRESET "\033[0m"
#define RED "\033[31m"
#define GREEN "\033[32m"
#define TTY_RESET_FD(fd) \
do { \
if (tty_reset(fd) < 0) { \
printf("\n tty_reset error\n"); \
} \
} while (0)
#define TTY_CBREAK_FD(fd) \
do { \
if (tty_cbreak(fd) < 0) { \
printf("\n tty_cbreak error\n"); \
} \
} while (0)
static bool AMMP_DEBUG_MODE_ENABLE = false;
#define TERMINAL_DEBUG(fmt, ...) \
do { \
if (AMMP_DEBUG_MODE_ENABLE) { \
printf("[%s:%d] " fmt , __FUNCTION__, __LINE__, ##__VA_ARGS__); \
} \
} while (0)
#define TERMINAL_ERROR(fmt, ...) \
do { \
printf(RED "---------------------------ERROR---------------------------\n" WRESET); \
printf(RED "-----------------------------------------------------------\n" WRESET); \
printf(RED fmt "\n", ##__VA_ARGS__); \
printf(RED "-----------------------------------------------------------\n" WRESET); \
printf(RED "---------------------------ERROR---------------------------\n" WRESET); \
} while (0)
#define MIN(A, B) ( (A) > (B) ? (B) : (A) )
#define MAX(A, B) ( (A) > (B) ? (A) : (B) )
#define MEDIAPLAYERDEMO_MAIN (0)
#define MEDIAPLAYERDEMO_PIP (1)
#define ENUM_TO_STR(e) case e: return TO_STR(e); break
#define TO_STR(v) #v
///////////////////////////////////////////////////////////////////////////////
//Argument
//coverity[definition]
struct Argument
{
std::string url;
int x = 0;
int y = 0;
int viewWidth = 0;
int viewHeight = 0;
int channelId = -1;
bool onlyVideo = false;
bool onlyAudio = false;
int tunnelId = -1;
int loopMode = 0;
bool noSignalHandler = 0;
std::string licenseUrl;
uint64_t options = 0;
bool noAutoExit = false;
};
///////////////////////////////////////////////////////////////////////////////
//playerRoster
#define MaxPlayerNum 4
struct playerRoster
{
static playerRoster& instance() {
static playerRoster sInstance;
return sInstance;
}
int registerAll(AML_MP_MEDIAPLAYER player, int id, const struct Argument* argument, const struct AmlMpMediaPlayerDemo* demo) {
if (id < 0 || id >= MaxPlayerNum || argument == NULL) {
printf("%s invalid, id:%d, argument:%p, demo:%p \n", __FUNCTION__, id, argument, demo);
return -1;
}
mLock.lock();
mPlayers[id] = player;
mPlayerArgument[id].url = argument->url;
mPlayerArgument[id].x = argument->x;
mPlayerArgument[id].y = argument->y;
mPlayerArgument[id].viewWidth = argument->viewWidth;
mPlayerArgument[id].viewHeight = argument->viewHeight;
mPlayerArgument[id].channelId = argument->channelId;
mPlayerArgument[id].onlyVideo = argument->onlyVideo;
mPlayerArgument[id].onlyAudio = argument->onlyAudio;
mPlayerArgument[id].tunnelId = argument->tunnelId;
mPlayerArgument[id].loopMode = argument->loopMode;
mPlayerArgument[id].noSignalHandler = argument->noSignalHandler;
mPlayerArgument[id].licenseUrl = argument->licenseUrl;
mPlayerArgument[id].options = argument->options;
mPlayerArgument[id].noAutoExit = argument->noAutoExit;
mPlayerPlayerDemo[id] = const_cast<struct AmlMpMediaPlayerDemo*>(demo);
if (NULL != player) {
++mPlayerHandlerCount;
}
mLock.unlock();
return id;
}
int registerPlayerArgument(int id, const struct Argument* argument) {
if (id < 0 || id >= MaxPlayerNum || argument == NULL) {
printf("%s invalid, id:%d, argument:%p \n", __FUNCTION__, id, argument);
return -1;
}
mLock.lock();
mPlayerArgument[id].url = argument->url;
mPlayerArgument[id].x = argument->x;
mPlayerArgument[id].y = argument->y;
mPlayerArgument[id].viewWidth = argument->viewWidth;
mPlayerArgument[id].viewHeight = argument->viewHeight;
mPlayerArgument[id].channelId = argument->channelId;
mPlayerArgument[id].onlyVideo = argument->onlyVideo;
mPlayerArgument[id].onlyAudio = argument->onlyAudio;
mPlayerArgument[id].tunnelId = argument->tunnelId;
mPlayerArgument[id].loopMode = argument->loopMode;
mPlayerArgument[id].noSignalHandler = argument->noSignalHandler;
mPlayerArgument[id].licenseUrl = argument->licenseUrl;
mPlayerArgument[id].options = argument->options;
mPlayerArgument[id].noAutoExit = argument->noAutoExit;
mLock.unlock();
return id;
}
int registerPlayerThreadHandle(int id, std::thread thread) {
if (id < 0 || id >= MaxPlayerNum) {
printf("%s invalid, id:%d\n", __FUNCTION__, id);
return -1;
}
mLock.lock();
mThread[id] = std::move(thread);
mLock.unlock();
return id;
}
int unregisterPlayer(AML_MP_MEDIAPLAYER player) {
if (player == NULL) {
printf("%s player invalid, player=%p \n", __FUNCTION__, player);
return -1;
}
mLock.lock();
for (size_t i = 0; i < MaxPlayerNum; ++i) {
if (player == mPlayers[i]) {
mPlayers[i] = NULL;
//memset(&mPlayerArgument[i], 0, sizeof(struct Argument));
mPlayerPlayerDemo[i] = NULL;
if (mPlayerHandlerCount > 0) {
--mPlayerHandlerCount;
}
break;
}
}
mLock.unlock();
return 0;
}
bool isMultiPlayerExist(int id) {
bool isExist = false;
if (id < 0 || id >= MaxPlayerNum ) {
printf("%s invalid, id:%d,\n", __FUNCTION__, id);
return isExist;
}
mLock.lock();
if (NULL != mPlayers[id]) {
isExist = true;
}
mLock.unlock();
return isExist;
}
void getPlayerHandle(int id, AML_MP_MEDIAPLAYER *player) {
if (id < 0 || id >= MaxPlayerNum) {
printf("%s invalid, id:%d \n", __FUNCTION__, id);
return;
}
mLock.lock();
if (mPlayers[id] != NULL) {
*player = mPlayers[id];
}
mLock.unlock();
}
void getPlayerArgument(int id, struct Argument** argument) {
if (id < 0 || id >= MaxPlayerNum) {
printf("%s invalid, id:%d \n", __FUNCTION__, id);
return;
}
mLock.lock();
*argument = (&mPlayerArgument[id]);
mLock.unlock();
}
void getPlayerDemoHandle(int id, struct AmlMpMediaPlayerDemo** playerDemo) {
if (id < 0 || id >= MaxPlayerNum) {
printf("%s invalid, id:%d \n", __FUNCTION__, id);
return;
}
mLock.lock();
if (NULL != mPlayerPlayerDemo[id]) {
*playerDemo = (mPlayerPlayerDemo[id]);
}
mLock.unlock();
}
void getPlayerThreadHandle(int id, std::thread** thread) {
if (id < 0 || id >= MaxPlayerNum) {
printf("%s invalid, id:%d \n", __FUNCTION__, id);
return;
}
mLock.lock();
*thread = (&mThread[id]);
mLock.unlock();
}
int playerHandlerCount() {
int count = 0;
mLock.lock();
count = mPlayerHandlerCount;
mLock.unlock();
return count;
}
private:
playerRoster() {
for (int i = 0; i < MaxPlayerNum; ++i) {
mPlayers[i] = NULL;
mPlayerArgument[i].url = "";
mPlayerArgument[i].x = -1;
mPlayerArgument[i].y = -1;
mPlayerArgument[i].viewWidth = -1;
mPlayerArgument[i].viewHeight = -1;
mPlayerArgument[i].channelId = -1;
mPlayerArgument[i].onlyVideo = false;
mPlayerArgument[i].onlyAudio = false;
mPlayerArgument[i].tunnelId = -1;
mPlayerArgument[i].loopMode = 0;
mPlayerArgument[i].noSignalHandler = 0;
mPlayerArgument[i].licenseUrl = "";
mPlayerArgument[i].options = 0;
mPlayerArgument[i].noAutoExit = 0;
mPlayerPlayerDemo[i] = NULL;
mPlayerHandlerCount = 0;
}
}
std::mutex mLock;
int mPlayerHandlerCount = 0;
AML_MP_MEDIAPLAYER mPlayers[MaxPlayerNum];
struct Argument mPlayerArgument[MaxPlayerNum];
struct AmlMpMediaPlayerDemo* mPlayerPlayerDemo[MaxPlayerNum];
std::thread mThread[MaxPlayerNum];
playerRoster(const playerRoster&) = delete;
playerRoster& operator=(const playerRoster&) = delete;
};
///////////////////////////////////////////////////////////////////////////////
//AmlMpMediaPlayerCommandProcessor
struct AmlMpMediaPlayerCommandProcessor : CommandProcessor
{
AmlMpMediaPlayerCommandProcessor(const std::string& prompt = ">");
~AmlMpMediaPlayerCommandProcessor();
virtual int fetchAndProcessCommands();
private:
AmlMpMediaPlayerCommandProcessor(const AmlMpMediaPlayerCommandProcessor&) = delete;
AmlMpMediaPlayerCommandProcessor& operator=(const AmlMpMediaPlayerCommandProcessor&) = delete;
};
AmlMpMediaPlayerCommandProcessor::AmlMpMediaPlayerCommandProcessor(const std::string& prompt)
: CommandProcessor(prompt)
{
MLOGI();
}
AmlMpMediaPlayerCommandProcessor::~AmlMpMediaPlayerCommandProcessor()
{
MLOGI();
}
int AmlMpMediaPlayerCommandProcessor::fetchAndProcessCommands()
{
try {
bool prompt = false;
std::string lastCommand = "-1";
for (;;) {
// 检查mInterrupter是否有效
if (mInterrupter && mInterrupter()) {
break;
}
if (tcgetpgrp(0) != getpid()) {
usleep(10 * 1000);
continue;
}
if (prompt) {
prompt = false;
fprintf(stderr, "%s", mPrompt.c_str());
}
struct pollfd fds;
fds.fd = STDIN_FILENO;
fds.events = POLL_IN;
fds.revents = 0;
// change the wait time from 1s to 100ms to avoid
// the situation that the signal change is not detected in time
int ret = ::poll(&fds, 1, 100);
if (ret < 0) {
//printf("poll STDIN_FILENO failed! %d\n", -errno);
} else if (ret > 0) {
if (fds.revents & POLL_ERR) {
MLOGE("poll error!");
continue;
} else if (!(fds.revents & POLL_IN)) {
continue;
}
prompt = true;
char buffer[100]{0};
int len = ::read(STDIN_FILENO, buffer, sizeof(buffer));
if (len <= 0) {
MLOGE("read failed! %d", -errno);
continue;
}
if (len > -1)
buffer[(len < 100 ? len : 99)] = '\0';
{
//debug
TERMINAL_DEBUG("read buf:%s, %d, size:%d\n", buffer, buffer[0], len);
int i = 0;
for (i = 0; i < len; i++) {
TERMINAL_DEBUG("%c(%d)\n", buffer[i], buffer[i]);
}
}
//check for whitespace characters
std::string buf(buffer);
size_t b = 0;
size_t e = buf.size();
while (b < e) {
if (isspace(buf[b]) || iscntrl(buf[b])) ++b;
else if (isspace(buf[e]) || iscntrl(buf[e])) --e;
else break;
}
TERMINAL_DEBUG("read b:%zu, e:%zu\n", b, e);
if (b < e) {
buf = buf.substr(b, e - b + 1);
lastCommand = buf;
} else if (b == e && buf.size() > 0) {
//direct choice buf[0] - safe access with bounds checking
buf = std::string(1, buf[0]);
} else {
continue;
}
// Safe split with empty result handling
std::vector<std::string> args = split(buf);
if (!args.empty()) {
mCommandVisitor(args);
}
}
}
} catch (const std::bad_function_call& e) {
MLOGE("Bad function call exception: %s", e.what());
} catch (const std::length_error& e) {
MLOGE("Length error exception: %s", e.what());
} catch (const std::exception& e) {
MLOGE("Standard exception: %s", e.what());
} catch (...) {
MLOGE("Unknown exception caught");
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////
//AmlMpMediaPlayerDemo
static const int forwardRateFactorMap[] = {
8,
16,
32,
64,
1,
};
static const int rewindRateFactorMap[] = {
-8,
-16,
-32,
-64,
};
struct AmlMpMediaPlayerDemo : public TestModule
{
AmlMpMediaPlayerDemo(int id);
~AmlMpMediaPlayerDemo();
int fetchAndProcessCommands();
virtual void* getCommandHandle() const;
void setCommandHandle(void * handle);
int waitPreparedEvent();
void broadcast(bool result);
static int installSignalHandler();
public:
bool mQuitPending = false;
int mId;
private:
AML_MP_MEDIAPLAYER mPlayer = NULL;
std::condition_variable mCondition;
std::mutex mMutex;
bool mPrepared = false;
protected:
const TestModule::Command* getCommandTable() const;
bool processCommand(const std::vector<std::string>& args);
private:
//Rewind Forward
char mRewindStateIndex = 0, mForwardStateIndex = 0;
bool isRewindOrForward = false;
std::string RewindOrForward = "";
void resetRewindAndForwardState() { mRewindStateIndex = 0; mForwardStateIndex = 0; }
private:
sptr<CommandProcessor> mCommandProcessor;
static std::thread mSignalHandleThread;
};
std::thread AmlMpMediaPlayerDemo::mSignalHandleThread;
AmlMpMediaPlayerDemo::AmlMpMediaPlayerDemo(int id)
: mId(id)
{
MLOGI("mId:%d", mId);
}
AmlMpMediaPlayerDemo::~AmlMpMediaPlayerDemo()
{
MLOGI();
}
int AmlMpMediaPlayerDemo::fetchAndProcessCommands()
{
char promptBuf[50];
snprintf(promptBuf, sizeof(promptBuf), "AmlMpMediaPlayerDemo (press 'h' for help) > ");
mCommandProcessor = new AmlMpMediaPlayerCommandProcessor(promptBuf);
if (mCommandProcessor == nullptr) {
return -1;
}
mCommandProcessor->setCommandVisitor(std::bind(&AmlMpMediaPlayerDemo::processCommand, this, std::placeholders::_1));
mCommandProcessor->setInterrupter([this]() {return mQuitPending;});
return mCommandProcessor->fetchAndProcessCommands();
}
bool AmlMpMediaPlayerDemo::processCommand(const std::vector<std::string>& args)
{
try {
bool ret = true;
if (args.empty()) {
MLOGE("%s, %d: args is empty", __FUNCTION__, __LINE__);
return false;
}
std::string cmd = *args.begin();
if (cmd == "q") {
MLOGI("%s,%d set mQuitPending = true", __FUNCTION__, __LINE__);
//mQuitPending = true;
Argument* argument = nullptr;
playerRoster::instance().getPlayerArgument(MEDIAPLAYERDEMO_MAIN, &argument);
if (argument && argument->loopMode) {
TERMINAL_DEBUG("q command, reset loop mode!\n");
argument->loopMode = 0;
}
closeAllMultiPlayback();
} else {
if (isRewindOrForward && (RewindOrForward != cmd || (cmd.compare("<") && cmd.compare(">")))) {
isRewindOrForward = false;
resetRewindAndForwardState();
}
if (">" == cmd) {
isRewindOrForward = true;
//coverity[copy_assignment_call]
RewindOrForward = cmd;
mRewindStateIndex = 0;
const_cast<std::vector<std::string>&>(args).emplace_back(std::to_string(forwardRateFactorMap[mForwardStateIndex]));
if (++mForwardStateIndex >= sizeof(forwardRateFactorMap) / sizeof(forwardRateFactorMap[0])) {
mForwardStateIndex = 0;
}
} else if ("<" == cmd) {
isRewindOrForward = true;
//coverity[copy_assignment_call]
RewindOrForward = cmd;
mForwardStateIndex = 0;
const_cast<std::vector<std::string>&>(args).emplace_back(std::to_string(rewindRateFactorMap[mRewindStateIndex]));
if (++mRewindStateIndex >= sizeof(rewindRateFactorMap) / sizeof(rewindRateFactorMap[0])) {
mRewindStateIndex = 0;
}
}
{//debug
int i = 0, size = args.size();
TERMINAL_DEBUG("processCommand: size:%d\n", size);
for (size_t j = 0; j < args.size(); j++) {
const std::string& pStr = args[j];
TERMINAL_DEBUG("%s\n", pStr.c_str());
}
}
TestModule::processCommand(args);
}
return ret;
} catch (const std::length_error& e) {
MLOGE("Length error exception in processCommand: %s", e.what());
return false;
} catch (const std::exception& e) {
MLOGE("Standard exception in processCommand: %s", e.what());
return false;
} catch (...) {
MLOGE("Unknown exception caught in processCommand");
return false;
}
}
///////////////////////////////////////////////////////////////////////////////
static void save2BitmapFile(const char *filename, uint32_t *bitmap, int w, int h) {
FILE *f;
char fname[100];
snprintf(fname, sizeof(fname), "%s.ppm", filename);
f = fopen(fname, "w");
if (!f) {
ALOGE("Error cannot open file %s!", fname);
return;
}
fprintf(f, "P6\n" "%d %d\n" "%d\n", w, h, 255);
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int v = bitmap[y * w + x];
putc((v >> 16) & 0xff, f);
putc((v >> 8) & 0xff, f);
putc((v >> 0) & 0xff, f);
}
}
printf("save2BitmapFile filename:%s\n", filename);
fclose(f);
}
static Aml_MP_MediaPlayerInvokeReply* newMediaPlayerInvokeReply(void)
{
Aml_MP_MediaPlayerInvokeReply* ptr = new Aml_MP_MediaPlayerInvokeReply;
if (ptr == nullptr) {
printf("new Aml_MP_MediaPlayerInvokeReply fail\n");
return nullptr;
}
memset(ptr, 0, sizeof(Aml_MP_MediaPlayerInvokeReply));
return ptr;
}
static void delMediaPlayerInvokeReply(Aml_MP_MediaPlayerInvokeReply *ptr)
{
if (ptr == nullptr) {
return;
}
delete ptr;
return;
}
static struct TestModule::Command g_commandTable[] = {
{
"h", 0, "help",
[](AML_MP_MEDIAPLAYER player __unused, const std::vector<std::string>& args __unused) -> int {
showOption();//TestModule::printCommands(g_commandTable, true);
return 0;
}
},
{
"p", 0, "pause player",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = Aml_MP_MediaPlayer_Pause(player);
printf("call pause player, ret:%d\n", ret);
return ret;
}
},
{
"r", 0, "resume player",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = Aml_MP_MediaPlayer_Resume(player);
printf("call resume player, ret:%d\n", ret);
return ret;
}
},
/*
{
"u", 0, "set data source",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
TTY_RESET_FD(STDIN_FILENO);
printf("call setdatasource,url address: ");
int ret=0;
std::string urlStr;
const char* url;
try {
std::getline (std::cin, urlStr);
url = urlStr.c_str();
} catch (const std::invalid_argument & ia) {
printf("Invalid argument: %s. \n", ia.what());
}
if (url < 0) {
ret = -1;
goto exit;
}
ret = Aml_MP_MediaPlayer_SetDataSource(player, url);
exit:
printf("call set data source:%s ret: %d\n", url, ret);
TTY_CBREAK_FD(STDIN_FILENO);
return ret;
}
},
*/
{
"d", 0, "hide video",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = Aml_MP_MediaPlayer_HideVideo(player);
printf("call hide video, ret : %d\n",ret);
return ret;
}
},
{
"D", 0, "show video",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = Aml_MP_MediaPlayer_ShowVideo(player);
printf("call show video,ret : %d\n",ret);
return ret;
}
},
{
"t", 0, "hide Subtitle",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = Aml_MP_MediaPlayer_HideSubtitle(player);
printf("call hide Subtitle, ret : %d\n",ret);
return ret;
}
},
{
"T", 0, "show Subtitle",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = Aml_MP_MediaPlayer_ShowSubtitle(player);
printf("call show Subtitle,ret : %d\n",ret);
return ret;
}
},
{
"K", 0, "call seek",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
TTY_RESET_FD(STDIN_FILENO);
printf("call seek, press position [milliseconds] : ");
int ret = 0;
std::string msecStr;
int msec = -1;
try {
std::getline (std::cin, msecStr);
msec = std::stoi(msecStr);
} catch (const std::invalid_argument & ia) {
printf("Invalid argument: %s. \n", ia.what());
msec = -1;
} catch (const std::length_error & ia) {
printf("length_error: %s. \n", ia.what());
msec = -1;
}
if (msec < 0) {
ret = -1;
goto exit;
}
ret = Aml_MP_MediaPlayer_SeekTo(player, msec);
exit:
printf("call seek, msec:%d, ret:%d\n", msec, ret);
TTY_CBREAK_FD(STDIN_FILENO);
return ret;
}
},
{
"v", 0, "get volume",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
float volume = -1;
int ret = Aml_MP_MediaPlayer_GetVolume(player, &volume);
printf("Current volume: %f, ret: %d\n", volume, ret);
return ret;
}
},
{
"V", 0, "set volume",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
TTY_RESET_FD(STDIN_FILENO);
printf("set volume, press volume [0 ~ 100] : ");
int ret = 0;
std::string volumeStr;
float volume = -1;
try {
std::getline (std::cin, volumeStr);
volume = std::stof(volumeStr);
} catch (const std::invalid_argument & ia) {
printf("Invalid argument: %s. \n", ia.what());
volume = -1;
} catch (const std::length_error & ia) {
printf("length_error: %s. \n", ia.what());
volume = -1;
}
if (volume < 0 || volume > 100) {
ret = -1;
goto exit;
}
ret = Aml_MP_MediaPlayer_SetVolume(player, volume);
exit:
printf("set volume: %f, ret: %d\n", volume, ret);
TTY_CBREAK_FD(STDIN_FILENO);
return ret;
}
},
{
"F", 0, "set Fast rate",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
TTY_RESET_FD(STDIN_FILENO);
printf("call set Fast rate, press rate [0.25/0.5/1/1.25/1.5/2] : ");
int ret = 0;
std::string rateStr;
float rate = -1;
try {
std::getline (std::cin, rateStr);
rate = std::stof(rateStr);
} catch (const std::invalid_argument & ia) {
printf("Invalid argument: %s. \n", ia.what());
rate = -1;
} catch (const std::length_error & ia) {
printf("length_error: %s. \n", ia.what());
rate = -1;
}
if (rate < 0 || rate > 2) {
ret = -1;
goto exit;
}
ret = Aml_MP_MediaPlayer_SetPlaybackRate(player, rate);
exit:
printf("call set Fast rate, rate:%f, ret:%d\n", rate, ret);
TTY_CBREAK_FD(STDIN_FILENO);
return ret;
}
},
{
"W", 0, "set video window",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
TTY_RESET_FD(STDIN_FILENO);
int ret = 0;
std::string xStr;
std::string yStr;
std::string widthStr;
std::string heightStr;
int x = -1;
int y = -1;
int width = -1;
int height = -1;
try {
printf("call set video window, press X pos : ");
std::getline (std::cin, xStr);
printf("call set video window, press Y pos : ");
std::getline (std::cin, yStr);
printf("call set video window, press width pos : ");
std::getline (std::cin, widthStr);
printf("call set video window, press height pos : ");
std::getline (std::cin, heightStr);
x = std::stoi(xStr);
y = std::stoi(yStr);
width = std::stoi(widthStr);
height = std::stoi(heightStr);
} catch (const std::invalid_argument & ia) {
printf("Invalid argument: %s. \n", ia.what());
x = -1;
} catch (const std::length_error & ia) {
printf("length_error: %s. \n", ia.what());
x = -1;
}
if (x < 0 || y < 0 || width < 0 || height < 0) {
ret = -1;
goto exit;
}
ret = Aml_MP_MediaPlayer_SetVideoWindow(player, x, y, width, height);
exit:
printf("call set video window, x:%d, y:%d, width:%d, height:%d, ret:%d\n",x, y, width, height, ret);
TTY_CBREAK_FD(STDIN_FILENO);
return ret;
}
},
{
"sOnlyHint", 0, "set only hint",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = 0;
if (args.size() < 2) {
printf("Error: missing parameter for set only hint\n");
return -1;
}
try {
Aml_MP_MediaPlayerOnlyHintType type = (Aml_MP_MediaPlayerOnlyHintType)atoi(args.at(1).c_str());
ret = Aml_MP_MediaPlayer_SetParameter(player, AML_MP_MEDIAPLAYER_PARAMETER_ONLYHINT_TYPE, (void*)&type);
printf("AML_MP_MEDIAPLAYER_PARAMETER_ONLYHINT_TYPE set type: %d, ret: %d\n", type, ret);
} catch (const std::out_of_range& e) {
printf("out_of_range exception : %s", e.what());
}
return ret;
}
},
/*
{
"y", 0, "set AVSync Source",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = 0;
Aml_MP_MediaPlayerAVSyncSource syncSource;
memset(&syncSource, 0, sizeof(Aml_MP_MediaPlayerAVSyncSource));
syncSource = AML_MP_AVSYNC_SOURCE_VIDEO;
ret = Aml_MP_MediaPlayer_SetAVSyncSource(player,syncSource);
printf("AML_MP_AVSYNC_SOURCE_VIDEO set SyncSource: 0x%x,ret: %d\n\n", syncSource, ret);
return ret;
}
},
*/
{
"M", 0, "set mute umute",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
TTY_RESET_FD(STDIN_FILENO);
printf("call set mute/umute, press mute/umute [1/0] : ");
int ret = 0;
std::string muteStr;
int mute = -1;
try {
std::getline (std::cin, muteStr);
mute = std::stoi(muteStr, NULL, 10);
} catch (const std::invalid_argument & ia) {
printf("Invalid argument: %s. \n", ia.what());
mute = -1;
} catch (const std::length_error & ia) {
printf("length_error: %s. \n", ia.what());
mute = -1;
}
if (mute < 0 || mute > 1) {
ret = -1;
goto exit;
}
ret = Aml_MP_MediaPlayer_SetMute(player, mute);
exit:
printf("Set mute: %d, ret: %d\n", mute, ret);
TTY_CBREAK_FD(STDIN_FILENO);
return ret;
}
},
{
"<", 0, "set Rewind",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
TTY_RESET_FD(STDIN_FILENO);
int ret = -1;
float rewind = 0;
if (args.size() >= 2) {
try {
rewind = stof(args.at(1));
} catch (const std::out_of_range & ia) {
printf("out_of_range exception %s.", ia.what());
}
}
if (rewind >= 0) {
goto exit;
}
if (-1 == rewind) {
rewind = 1;//maybe we need speed=1
}
ret = Aml_MP_MediaPlayer_SetPlaybackRate(player, rewind);
exit:
printf("call set Rewind, rateFactor:%f, ret:%d\n", rewind, ret);
TTY_CBREAK_FD(STDIN_FILENO);
return ret;
}
},
{
">", 0, "set Forward",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
TTY_RESET_FD(STDIN_FILENO);
int ret = -1;
float forward = 0;
if (args.size() >= 2) {
try {
forward = stof(args.at(1));
} catch (const std::out_of_range & ia) {
printf("out_of_range exception %s.", ia.what());
}
}
if (forward <= 0) {
goto exit;
}
ret = Aml_MP_MediaPlayer_SetPlaybackRate(player, forward);
exit:
printf("call set Forward, rateFactor:%f, ret:%d\n", forward, ret);
TTY_CBREAK_FD(STDIN_FILENO);
return ret;
}
},
{
"a", 0, "Get Audio Info Channels",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = 0;
printf("\n\n Available Audios : \n");
Aml_MP_MediaPlayerInvokeRequest trackRequest;
//the size of Aml_MP_MediaPlayerInvokeReply is 14416 bytes.
//so we not use stack memory, use heap memory.
Aml_MP_MediaPlayerInvokeReply *trackReply = newMediaPlayerInvokeReply();
if (trackReply == nullptr) {
return -1;
}
memset(&trackRequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
trackRequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_GET_TRACK_INFO;
ret = Aml_MP_MediaPlayer_Invoke(player, &trackRequest, trackReply);
Aml_MP_MediaPlayerInvokeRequest mediaRequest;
Aml_MP_MediaPlayerInvokeReply *mediaReply = newMediaPlayerInvokeReply();
if (mediaReply == nullptr) {
delMediaPlayerInvokeReply(trackReply);
return -1;
}
memset(&mediaRequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
mediaRequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_GET_MEDIA_INFO;
//coverity[value_overwrite]
ret = Aml_MP_MediaPlayer_Invoke(player, &mediaRequest, mediaReply);
printCurTrackInfo(&(trackReply->u.trackInfo), &(mediaReply->u.mediaInfo), AML_MP_STREAM_TYPE_AUDIO);
delMediaPlayerInvokeReply(trackReply);
delMediaPlayerInvokeReply(mediaReply);
return ret;
}
},
{
"A", 0, "Set Next Audio component",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = 0;
Aml_MP_MediaPlayerInvokeRequest selectrequest;
Aml_MP_MediaPlayerInvokeReply *selectreply = nullptr;
Aml_MP_MediaPlayerInvokeRequest trackRequest;
Aml_MP_MediaPlayerInvokeReply *trackReply = newMediaPlayerInvokeReply();
if (trackReply == nullptr) {
return -1;
}
memset(&trackRequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
trackRequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_GET_TRACK_INFO;
ret = Aml_MP_MediaPlayer_Invoke(player, &trackRequest, trackReply);
Aml_MP_MediaPlayerInvokeRequest mediaRequest;
Aml_MP_MediaPlayerInvokeReply *mediaReply = newMediaPlayerInvokeReply();
if (mediaReply == nullptr) {
delMediaPlayerInvokeReply(trackReply);
return -1;
}
memset(&mediaRequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
mediaRequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_GET_MEDIA_INFO;
//coverity[value_overwrite]
ret = Aml_MP_MediaPlayer_Invoke(player, &mediaRequest, mediaReply);
int index = getNextTrack(&(trackReply->u.trackInfo), &(mediaReply->u.mediaInfo), AML_MP_STREAM_TYPE_AUDIO);
if (index < 0) {
goto exit;
}
selectreply = newMediaPlayerInvokeReply();
if (selectreply == nullptr) {
delMediaPlayerInvokeReply(trackReply);
delMediaPlayerInvokeReply(mediaReply);
return -1;
}
memset(&selectrequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
selectrequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_SELECT_TRACK;
selectrequest.u.data32 = index;
//coverity[value_overwrite]
ret = Aml_MP_MediaPlayer_Invoke(player, &selectrequest, selectreply);
exit:
printf("Set Next Audio component, ret:%d, index:%d\n", ret, index);
delMediaPlayerInvokeReply(trackReply);
delMediaPlayerInvokeReply(mediaReply);
delMediaPlayerInvokeReply(selectreply);
return ret;
}
},
{
"U", 0, "Unselect CurAudio component",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = 0;
Aml_MP_MediaPlayerInvokeRequest selectrequest;
Aml_MP_MediaPlayerInvokeReply *selectreply = nullptr;
Aml_MP_MediaPlayerInvokeRequest mediaRequest;
Aml_MP_MediaPlayerInvokeReply *mediaReply = newMediaPlayerInvokeReply();
if (mediaReply == nullptr) {
return -1;
}
memset(&mediaRequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
mediaRequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_GET_MEDIA_INFO;
ret = Aml_MP_MediaPlayer_Invoke(player, &mediaRequest, mediaReply);
int index = mediaReply->u.mediaInfo.curAudioIndex;
if (index < 0) {
goto exit;
}
selectreply = newMediaPlayerInvokeReply();
if (selectreply == nullptr) {
delMediaPlayerInvokeReply(mediaReply);
return -1;
}
memset(&selectrequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
selectrequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_UNSELECT_TRACK;
selectrequest.u.data32 = index;
//coverity[value_overwrite]
ret = Aml_MP_MediaPlayer_Invoke(player, &selectrequest, selectreply);
exit:
printf("Unselect Current Audio component, ret:%d, index:%d\n", ret, index);
delMediaPlayerInvokeReply(mediaReply);
delMediaPlayerInvokeReply(selectreply);
return ret;
}
},
{
"s", 0, "Get Subtitles Info channels",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = 0;
printf("\n\n Available Subtitles : \n");
Aml_MP_MediaPlayerInvokeRequest trackRequest;
Aml_MP_MediaPlayerInvokeReply *trackReply = newMediaPlayerInvokeReply();
if (trackReply == nullptr) {
return -1;
}
memset(&trackRequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
trackRequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_GET_TRACK_INFO;
ret = Aml_MP_MediaPlayer_Invoke(player, &trackRequest, trackReply);
Aml_MP_MediaPlayerInvokeRequest mediaRequest;
Aml_MP_MediaPlayerInvokeReply *mediaReply = newMediaPlayerInvokeReply();
if (mediaReply == nullptr) {
delMediaPlayerInvokeReply(trackReply);
return -1;
}
memset(&mediaRequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
mediaRequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_GET_MEDIA_INFO;
//coverity[value_overwrite]
ret = Aml_MP_MediaPlayer_Invoke(player, &mediaRequest, mediaReply);
printCurTrackInfo(&(trackReply->u.trackInfo), &(mediaReply->u.mediaInfo), AML_MP_STREAM_TYPE_SUBTITLE);
delMediaPlayerInvokeReply(trackReply);
delMediaPlayerInvokeReply(mediaReply);
return ret;
}
},
{
"S", 0, "Set Next Subtitle component",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = 0;
Aml_MP_MediaPlayerInvokeRequest selectrequest;
Aml_MP_MediaPlayerInvokeReply *selectreply = nullptr;
Aml_MP_MediaPlayerInvokeRequest trackRequest;
Aml_MP_MediaPlayerInvokeReply *trackReply = newMediaPlayerInvokeReply();
if (trackReply == nullptr) {
return -1;
}
memset(&trackRequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
trackRequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_GET_TRACK_INFO;
ret = Aml_MP_MediaPlayer_Invoke(player, &trackRequest, trackReply);
Aml_MP_MediaPlayerInvokeRequest mediaRequest;
Aml_MP_MediaPlayerInvokeReply *mediaReply = newMediaPlayerInvokeReply();
if (mediaReply == nullptr) {
delMediaPlayerInvokeReply(trackReply);
return -1;
}
memset(&mediaRequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
mediaRequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_GET_MEDIA_INFO;
//coverity[value_overwrite]
ret = Aml_MP_MediaPlayer_Invoke(player, &mediaRequest, mediaReply);
int index = getNextTrack(&(trackReply->u.trackInfo), &(mediaReply->u.mediaInfo), AML_MP_STREAM_TYPE_SUBTITLE);
if (index < 0) {
goto exit;
}
selectreply = newMediaPlayerInvokeReply();
if (selectreply == nullptr) {
delMediaPlayerInvokeReply(trackReply);
delMediaPlayerInvokeReply(mediaReply);
return -1;
}
memset(&selectrequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
selectrequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_SELECT_TRACK;
selectrequest.u.data32 = index;
//coverity[value_overwrite]
ret = Aml_MP_MediaPlayer_Invoke(player, &selectrequest, selectreply);
exit:
printf("Set Next Subtitle component, ret:%d, index:%d\n", ret, index);
delMediaPlayerInvokeReply(trackReply);
delMediaPlayerInvokeReply(mediaReply);
delMediaPlayerInvokeReply(selectreply);
return ret;
}
},
{
"u", 0, "Unselect CurSubtitle component",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = 0;
Aml_MP_MediaPlayerInvokeRequest selectrequest;
Aml_MP_MediaPlayerInvokeReply *selectreply = nullptr;
Aml_MP_MediaPlayerInvokeRequest mediaRequest;
Aml_MP_MediaPlayerInvokeReply *mediaReply = newMediaPlayerInvokeReply();
if (mediaReply == nullptr) {
return -1;
}
memset(&mediaRequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
mediaRequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_GET_MEDIA_INFO;
ret = Aml_MP_MediaPlayer_Invoke(player, &mediaRequest, mediaReply);
int index = mediaReply->u.mediaInfo.curSubIndex;
if (index < 0) {
goto exit;
}
selectreply = newMediaPlayerInvokeReply();
if (selectreply == nullptr) {
delMediaPlayerInvokeReply(mediaReply);
return -1;
}
memset(&selectrequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
selectrequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_UNSELECT_TRACK;
selectrequest.u.data32 = index;
//coverity[value_overwrite]
ret = Aml_MP_MediaPlayer_Invoke(player, &selectrequest, selectreply);
exit:
printf("Unselect Current Audio component, ret:%d, index:%d\n", ret, index);
delMediaPlayerInvokeReply(mediaReply);
delMediaPlayerInvokeReply(selectreply);
return ret;
}
},
{
"n", 0, "get current position",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = 0, position = 0;
ret = Aml_MP_MediaPlayer_GetCurrentPosition(player, &position);
printf("Aml_MP_MediaPlayer_GetCurrentPosition get position: %d(ms), ret: %d\n", position, ret);
return ret;
}
},
{
"N", 0, "get duration",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = 0, duration = 0;
ret = Aml_MP_MediaPlayer_GetDuration(player, &duration);
printf("Aml_MP_MediaPlayer_GetDuration get duration: %d(ms), ret: %d\n", duration, ret);
return ret;
}
},
{
"i", 0, "invoke generic method",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = 0;
Aml_MP_MediaPlayerInvokeRequest trackRequest;
Aml_MP_MediaPlayerInvokeReply *trackReply = newMediaPlayerInvokeReply();
if (trackReply == nullptr) {
return -1;
}
memset(&trackRequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
trackRequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_GET_TRACK_INFO;
ret = Aml_MP_MediaPlayer_Invoke(player, &trackRequest, trackReply);
printf("\nAML_MP_MEDIAPLAYER_INVOKE_ID_GET_TRACK_INFO, reply id:0x%x ret: %d\n",trackReply->requestId, ret);
Aml_MP_MediaPlayerInvokeRequest mediaRequest;
Aml_MP_MediaPlayerInvokeReply *mediaReply = newMediaPlayerInvokeReply();
if (mediaReply == nullptr) {
delMediaPlayerInvokeReply(trackReply);
return -1;
}
memset(&mediaRequest, 0, sizeof(Aml_MP_MediaPlayerInvokeRequest));
mediaRequest.requestId = AML_MP_MEDIAPLAYER_INVOKE_ID_GET_MEDIA_INFO;
//coverity[value_overwrite]
ret = Aml_MP_MediaPlayer_Invoke(player, &mediaRequest, mediaReply);
printf("\nAML_MP_MEDIAPLAYER_INVOKE_ID_GET_MEDIA_INFO,reply id:0x%x ret: %d\n",mediaReply->requestId, ret);
printCurTrackInfo(&(trackReply->u.trackInfo), &(mediaReply->u.mediaInfo), AML_MP_STREAM_TYPE_VIDEO);
printCurTrackInfo(&(trackReply->u.trackInfo), &(mediaReply->u.mediaInfo), AML_MP_STREAM_TYPE_AUDIO);
printCurTrackInfo(&(trackReply->u.trackInfo), &(mediaReply->u.mediaInfo), AML_MP_STREAM_TYPE_SUBTITLE);
printMediaInfo(&(mediaReply->u.mediaInfo));
Aml_MP_MediaPlayerID3Info ID3Info;
memset(&ID3Info, 0, sizeof(Aml_MP_MediaPlayerID3Info));
//coverity[value_overwrite]
ret = Aml_MP_MediaPlayer_GetParameter(player, AML_MP_MEDIAPLAYER_PARAMETER_ID3_INFO, (void*)&ID3Info);
if (ret == 0)
{
printf("ID3Info title: %s\n", ID3Info.title);
printf("ID3Info author: %s\n", ID3Info.author);
printf("ID3Info album: %s\n", ID3Info.album);
printf("ID3Info comment: %s\n", ID3Info.comment);
printf("ID3Info year: %s\n", ID3Info.year);
printf("ID3Info track: %d\n", ID3Info.track);
printf("ID3Info genre: %s\n", ID3Info.genre);
printf("ID3Info copyright: %s\n", ID3Info.copyright);
printf("ID3Info pic_type: %s\n", ID3Info.pic_type);
printf("ID3Info pic_size: %d\n", ID3Info.pic_size);
printf("ID3Info pic_data: %p\n", ID3Info.pic_data);
}
delMediaPlayerInvokeReply(trackReply);
delMediaPlayerInvokeReply(mediaReply);
return ret;
}
},
{
"O", 0, "Open PIP",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
TTY_RESET_FD(STDIN_FILENO);
int ret = -1;
std::thread thread;
struct Argument argument;
printf("Open PIP url : ");
try {
argument.url = "-1";
argument.x = 0;
argument.y = 0;
argument.viewWidth = 960;
argument.viewHeight = 540;
argument.channelId = MEDIAPLAYERDEMO_PIP;//maybe need demux=1
argument.tunnelId = 1;
argument.onlyVideo = false;
argument.onlyAudio = false;
argument.licenseUrl = "";
argument.options = 0;
std::getline (std::cin, argument.url);
if (argument.url.compare("-1") == 0 || playerRoster::instance().isMultiPlayerExist(MEDIAPLAYERDEMO_PIP)) {
ret = -1;
goto exit;
}
playerRoster::instance().registerPlayerArgument(MEDIAPLAYERDEMO_PIP, &argument);//only register argument
playerRoster::instance().registerPlayerThreadHandle(MEDIAPLAYERDEMO_PIP, std::thread(multiPlaybackThread, MEDIAPLAYERDEMO_PIP, false));
ret = 0;
} catch (const std::invalid_argument & ia) {
printf("Invalid argument: %s. \n", ia.what());
} catch (const std::length_error & ia) {
printf("length_error exception : %s. \n", ia.what());
}
exit:
printf("call Open PIP, id:%d ret:%d\n", argument.channelId, ret);
TTY_CBREAK_FD(STDIN_FILENO);
return ret;
}
},
{
"C", 0, "Close PIP",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
try {
closeMultiPlayback(MEDIAPLAYERDEMO_PIP);
printf("call Close PIP\n");
return 0;
} catch (const std::exception& e) {
printf("Error in Close PIP: %s\n", e.what());
return -1;
}
}
},
/*
{
"Y", 0, "call reset",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = Aml_MP_MediaPlayer_Reset(player);
printf("call reset ret: %d\n", ret);
return ret;
}
},
{
"y", 0, "call prepare",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = Aml_MP_MediaPlayer_Prepare(player);
printf("call prepare ret: %d\n", ret);
return ret;
}
},
{
"U", 0, "call start",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = Aml_MP_MediaPlayer_Start(player);
printf("call start ret: %d\n", ret);
return ret;
}
},
{
"u", 0, "call stop",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
int ret = Aml_MP_MediaPlayer_Stop(player);
printf("call stop ret: %d\n", ret);
return ret;
}
},
*/
{
"q", 0, "exit playback",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
printf("exit playback\n");
return 0;
}
},
{
"\n", 0, "\n",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
printf("\n");
return 0;
}
},
{
"cas_ioctl", 0, "trigger CAS ioctl (Interactive mode)",
[](AML_MP_MEDIAPLAYER player, const std::vector<std::string>& args __unused) -> int {
char out_json[8192] = {0};
std::string real_input;
printf("\n===== Trigger CAS Ioctl (Interactive) =====\n");
printf("Please input your JSON string and press Enter:\n> ");
fflush(stdout);
if (!(std::cin >> std::ws && std::getline(std::cin, real_input))) {
std::cin.clear();
printf("Error: Input failed or interrupted.\n");
return -1;
}
if (real_input.length() < 2 || real_input.front() != '{' || real_input.back() != '}') {
printf("Error: Invalid JSON format. Must start with '{' and end with '}'.\n");
return -1;
}
printf("Executing command: %s\n", real_input.c_str());
int ret = Aml_MP_CAS_Ioctl(0, real_input.c_str(), out_json, sizeof(out_json));
if (ret != 0) {
printf("Ioctl execution failed with code: %d\nOutput: %s\n", ret, out_json);
} else {
printf("Execution successful!\nOutput: %s\n", out_json);
}
return ret;
}
},
{nullptr, 0, nullptr, nullptr}
};
const TestModule::Command* AmlMpMediaPlayerDemo::getCommandTable() const
{
return g_commandTable;
}
void* AmlMpMediaPlayerDemo::getCommandHandle() const
{
return mPlayer;
}
void AmlMpMediaPlayerDemo::setCommandHandle(void * handle)
{
if (handle != NULL)
mPlayer = handle;
}
int AmlMpMediaPlayerDemo::waitPreparedEvent()
{
printf("waitPreparedEvent \n");
std::unique_lock<std::mutex> autoLock(mMutex);
mCondition.wait(autoLock);
printf("waitPreparedEvent mPrepared:%d\n", mPrepared);
return (mPrepared == true ? 0 : -1);
}
void AmlMpMediaPlayerDemo::broadcast(bool result)
{
printf("broadcast result:%d\n", result);
std::unique_lock<std::mutex> autoLock(mMutex);
mPrepared = result;
mCondition.notify_all();
}
int AmlMpMediaPlayerDemo::installSignalHandler()
{
int ret = 0;
sigset_t blockSet, oldMask;
sigemptyset(&blockSet);
sigaddset(&blockSet, SIGINT);
sigaddset(&blockSet, SIGQUIT);
ret = pthread_sigmask(SIG_SETMASK, &blockSet, &oldMask);
if (ret != 0) {
MLOGE("pthread_sigmask failed! %d", ret);
return -1;
}
mSignalHandleThread = std::thread([blockSet, oldMask] {
int signo = 0;
int err;
for (;;) {
err = sigwait(&blockSet, &signo);
if (err != 0) {
MLOGE("sigwait error! %d", err);
exit(0);
}
printf("Signal Capture:%s\n", strsignal(signo));
MLOGI("Signal Capture:%s\n", strsignal(signo));
switch (signo) {
case SIGINT:
case SIGQUIT:
{
//quit
//mQuitPending = true;
Argument* argument = nullptr;
playerRoster::instance().getPlayerArgument(MEDIAPLAYERDEMO_MAIN, &argument);
if (argument && argument->loopMode) {
TERMINAL_DEBUG("reset loop mode!\n");
argument->loopMode = 0;
}
closeAllMultiPlayback();
}
break;
default:
break;
}
if (pthread_sigmask(SIG_SETMASK, &oldMask, nullptr) != 0) {
MLOGE("restore sigmask failed!");
}
}
});
mSignalHandleThread.detach();
return ret;
}
///////////////////////////////////////////////////////////////////////////////
//
static void printCurTrackInfo(Aml_MP_TrackInfo *trackInfo, Aml_MP_MediaInfo* mediaInfo, Aml_MP_StreamType streamType)
{
if (trackInfo == NULL || mediaInfo == NULL)
return;
int index = 0;
Aml_MP_TrackInfo *info = trackInfo;
char isSelect[5] = " ";
//printf("nb_streams:%d \n", info->nb_streams);
for (index = 0; index < info->nb_streams; ++index) {
memset(isSelect, 0, sizeof(isSelect));
strncpy(isSelect, " ", 1);
if (info->streamInfo[index].streamType == streamType && streamType == AML_MP_STREAM_TYPE_VIDEO) {
if (index == mediaInfo->curVideoIndex) {
snprintf(isSelect, 5, "%s", ">");
}
printf(" %s array index:%d, actual index:%d [video] id:%d, videoCodec:%d(%s), frameRate:%f, width:%d, height:%d, mine:%s\n"
,isSelect
,index
,info->streamInfo[index].u.vInfo.index
,info->streamInfo[index].u.vInfo.id
,info->streamInfo[index].u.vInfo.videoCodec
,mpCodecId2Str(info->streamInfo[index].u.vInfo.videoCodec)
,info->streamInfo[index].u.vInfo.frameRate
,info->streamInfo[index].u.vInfo.width
,info->streamInfo[index].u.vInfo.height
,info->streamInfo[index].u.vInfo.mine);
} else if (info->streamInfo[index].streamType == streamType && streamType == AML_MP_STREAM_TYPE_AUDIO) {
if (index == mediaInfo->curAudioIndex) {
snprintf(isSelect, 5, "%s", ">");
}
printf(" %s array index:%d, actual index:%d [audio] id:%d, audioCodec:%d(%s), nChannels:%d, nSampleRate:%d, mine:%s, language:%s\n"
,isSelect
,index
,info->streamInfo[index].u.aInfo.index
,info->streamInfo[index].u.aInfo.id
,info->streamInfo[index].u.aInfo.audioCodec
,mpCodecId2Str(info->streamInfo[index].u.aInfo.audioCodec)
,info->streamInfo[index].u.aInfo.nChannels
,info->streamInfo[index].u.aInfo.nSampleRate
,info->streamInfo[index].u.aInfo.mine
,info->streamInfo[index].u.aInfo.language);
} else if (info->streamInfo[index].streamType == streamType && streamType == AML_MP_STREAM_TYPE_SUBTITLE) {
if (index == mediaInfo->curSubIndex) {
snprintf(isSelect, 5, "%s", ">");
}
printf(" %s array index:%d, actual index:%d(0x:%x) [subtitle] id:%d, subtitleCodec:%d(%s), mine:%s, language:%s\n"
,isSelect
,index
,info->streamInfo[index].u.sInfo.index
,info->streamInfo[index].u.sInfo.index
,info->streamInfo[index].u.sInfo.id
,info->streamInfo[index].u.sInfo.subtitleCodec
,mpCodecId2Str(info->streamInfo[index].u.sInfo.subtitleCodec)
,info->streamInfo[index].u.sInfo.mine
,info->streamInfo[index].u.sInfo.language);
} else {
;
}
}
printf("\n");
}
static int getNextTrack(Aml_MP_TrackInfo *trackInfo, Aml_MP_MediaInfo* mediaInfo, Aml_MP_StreamType streamType)
{
if (trackInfo == NULL || mediaInfo == NULL)
return -1;
Aml_MP_TrackInfo *info = trackInfo;
bool isReachFirst = false;
int preTrackIndex = streamType == AML_MP_STREAM_TYPE_VIDEO ? mediaInfo->curVideoIndex :
(streamType == AML_MP_STREAM_TYPE_AUDIO ? mediaInfo->curAudioIndex : mediaInfo->curSubIndex);
int findTrackIndex = preTrackIndex;
if (info->nb_streams > 0) {
do {
if (++findTrackIndex >= info->nb_streams) {
findTrackIndex = 0;
if (isReachFirst) {
//printf("loop again break:%d \n", info->nb_streams);
findTrackIndex = preTrackIndex;
break;
}
isReachFirst = true;
}
if (streamType == info->streamInfo[findTrackIndex].streamType) {
break;
}
} while (1);
}
return findTrackIndex;
}
static void printMediaInfo(Aml_MP_MediaInfo *mediaInfo)
{
if (mediaInfo == NULL)
return;
int index = 0;
Aml_MP_MediaInfo *info = mediaInfo;
printf("[mediaInfo] filename:%s, duration:%" PRId64 ", file_size:%" PRId64 ", bitrate:%" PRId64 ", nb_streams:%d" \
", curVideoIndex:%" PRId64 ", curAudioIndex:%" PRId64 ", curSubIndex:%" PRId64 ", subtitleShowState:%d\n"
,info->filename
,info->duration
,info->file_size
,info->bitrate
,info->nb_streams
,info->curVideoIndex
,info->curAudioIndex
,info->curSubIndex
,info->subtitleShowState);
printf("\n");
}
///////////////////////////////////////////////////////////////////////////////
//serial
static struct termios save_termios;
static int ttysavefd = -1;
static enum { RESET, RAW, CBREAK } ttystate = RESET;
static int tty_cbreak(int fd) /* put terminal into a cbreak mode */
{
int err;
struct termios buf;
if (ttystate != RESET) {
errno = EINVAL;
return(-1);
}
if (tcgetattr(fd, &buf) < 0)
return(-1);
save_termios = buf; /* structure copy */
/*
* Echo off, canonical mode off.
*/
buf.c_lflag &= ~(ECHO | ICANON);
/*
* Case B: 1 byte at a time, no timer.
*/
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSAFLUSH, &buf) < 0)
return(-1);
/*
* Verify that the changes stuck. tcsetattr can return 0 on
* partial success.
*/
if (tcgetattr(fd, &buf) < 0) {
err = errno;
tcsetattr(fd, TCSAFLUSH, &save_termios);
errno = err;
return(-1);
}
if ((buf.c_lflag & (ECHO | ICANON)) || buf.c_cc[VMIN] != 1 ||
buf.c_cc[VTIME] != 0) {
/*
* Only some of the changes were made. Restore the
* original settings.
*/
tcsetattr(fd, TCSAFLUSH, &save_termios);
errno = EINVAL;
return(-1);
}
ttystate = CBREAK;
ttysavefd = fd;
return(0);
}
static int tty_reset(int fd) /* restore terminal’s mode */
{
if (ttystate == RESET)
return(0);
if (tcsetattr(fd, TCSAFLUSH, &save_termios) < 0)
return(-1);
ttystate = RESET;
return(0);
}
///////////////////////////////////////////////////////////////////////////////
//PIP/MAIN
static int multiPlaybackThread(int id, bool isMain)
{
printf("\nAmlMpMediaPlayerDemo:%d ----------play enter! isMain:%d\n", id, isMain);
int ret = -1;
std::string urlHead;
std::string urlFile;
struct Argument* argument = NULL;
AML_MP_MEDIAPLAYER player = NULL;
playerRoster::instance().getPlayerArgument(id, &argument);
if (argument == NULL || argument->url.empty() || 0 != isUrlValid(argument->url, urlHead, urlFile)) {
showUsage();
return ret;
}
sptr<AmlMpMediaPlayerDemo> commandsProcess = new AmlMpMediaPlayerDemo(id);
if (commandsProcess == NULL) {
return ret;
}
//create
ret = createMultiPlayback(id, &player, argument, commandsProcess.get());
if (ret < 0) {
goto error;
}
if (isMain) {
//commands process
printf("\nAmlMpMediaPlayerDemo:%d ----------fetchAndProcessCommands\n", id);
commandsProcess->setCommandHandle(player);
commandsProcess->fetchAndProcessCommands();
} else {
//sleep
do {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
} while (commandsProcess->mQuitPending == false);
}
error:
//destroy
ret = destroyMultiPlayback(id);
printf("\nAmlMpMediaPlayerDemo:%d ----------play exited!\n", id);
return ret;
}
static int createMultiPlayback(int id, AML_MP_MEDIAPLAYER* player, struct Argument* argument, AmlMpMediaPlayerDemo* commandsProcess)
{
if (argument == NULL) {
return -1;
}
//create
Aml_MP_MediaPlayer_Create(player);
//prre-registration
playerRoster::instance().registerAll(*player, id, argument, commandsProcess);//register player/commandsProcess
//only settings
// channelid is used for pip function which start the demo in a different process.
// it means different play channels,0 : main, else pip
if (argument->channelId != -1)
Aml_MP_MediaPlayer_SetParameter(*player, AML_MP_MEDIAPLAYER_PARAMETER_CHANNEL_ID, (void*)(&argument->channelId));
Aml_MP_MediaPlayerOnlyHintType type = AML_MP_MEDIAPLAYER_ONLYNONE;
if (argument->onlyVideo)
type = AML_MP_MEDIAPLAYER_VIDEO_ONLYHIT;
if (argument->onlyAudio)
type = AML_MP_MEDIAPLAYER_AUDIO_ONLYHIT;
Aml_MP_MediaPlayer_SetParameter(*player, AML_MP_MEDIAPLAYER_PARAMETER_ONLYHINT_TYPE, (void*)&type);
if (argument->loopMode == 2) {
Aml_MP_MediaPlayer_SetLooping(*player, argument->loopMode);
}
if (argument->licenseUrl.size() > 0)
Aml_MP_MediaPlayer_SetParameter(*player, AML_MP_MEDIAPLAYER_PARAMETER_SET_LICENSE_URL, (void*)argument->licenseUrl.c_str());
//player options
//Aml_MP_Option
if (argument->options) {
Aml_MP_MediaPlayer_SetParameter(*player, AML_MP_MEDIAPLAYER_PARAMETER_PLAYER_OPTIONS, (void*)(&argument->options));
}
//setdatasource
Aml_MP_MediaPlayer_SetDataSource(*player, argument->url.c_str());
printf("\nAmlMpMediaPlayerDemo:%d ----------url: %s\n", id, argument->url.c_str());
//registerEventCallBack
Aml_MP_MediaPlayer_RegisterEventCallBack(*player, demoCallback, reinterpret_cast<void*>(commandsProcess));
//set video window after setting datasource and before starting, take effect after starting.
//or use --size options when amlMpMediaPlayerDemo
//passing (0, 0, 0, 0) is necessary to enable full-screen display by default.
Aml_MP_MediaPlayer_SetVideoWindow(*player, argument->x, argument->y, argument->viewWidth, argument->viewHeight);
//prepare
Aml_MP_MediaPlayer_PrepareAsync(*player);
int ret = commandsProcess->waitPreparedEvent();
if (ret < 0) {
return ret;
}
int iD = argument->tunnelId == -1 ? 0 : argument->tunnelId;
Aml_MP_MediaPlayer_SetParameter(*player, AML_MP_MEDIAPLAYER_PARAMETER_VIDEO_TUNNEL_ID, (void*)(&iD));
//start
Aml_MP_MediaPlayer_Start(*player);
printf("\nAmlMpMediaPlayerDemo:%d ----------Aml_MP_MediaPlayer_Start\n", id);
return 0;
}
static int destroyMultiPlayback(int id)
{
int ret = -1;
AML_MP_MEDIAPLAYER player = NULL;
playerRoster::instance().getPlayerHandle(id, &player);
if (player != NULL) {
//stop
ret = Aml_MP_MediaPlayer_Stop(player);
//reset
ret = Aml_MP_MediaPlayer_Reset(player);
playerRoster::instance().unregisterPlayer(player);
//destroy
ret= Aml_MP_MediaPlayer_Destroy(player);
printf("\nAmlMpMediaPlayerDemo:%d ----------Aml_MP_MediaPlayer_Destroy\n", id);
} else {
printf("\nAmlMpMediaPlayerDemo:%d ----------is NULl\n", id);
}
return 0;
}
static void closeMultiPlayback(int id)
{
printf("closeMultiPlayback id:%d\n", id);
if (id < 0) {
return;
}
struct AmlMpMediaPlayerDemo* playerDemo = NULL;
playerRoster::instance().getPlayerDemoHandle(id, &playerDemo);
if (playerDemo != NULL)
playerDemo->mQuitPending = true;
//join pip threads
std::thread *thread = NULL;
playerRoster::instance().getPlayerThreadHandle(id, &thread);
if (thread != NULL && thread->joinable()) {
thread->join();
printf("join multiPlaybackThread id:%d\n", id);
}
}
static void closeAllMultiPlayback()
{
//close pip first
closeMultiPlayback(MEDIAPLAYERDEMO_PIP);
closeMultiPlayback(MEDIAPLAYERDEMO_MAIN);
}
///////////////////////////////////////////////////////////////////////////////
static int isUrlValid(const std::string url, std::string& urlHead, std::string& urlFile)
{
int ret = -1;
std::size_t pos = std::string::npos;
urlHead = "-1";
urlFile = "-1";
if ((pos = url.find(":")) != std::string::npos) {
urlHead = url.substr(0, pos);
}
if (urlHead.compare("dclr") == 0) {
//coverity[overflow_const]
urlFile = url.substr(pos + 1);
//if (1 || access(urlFile.c_str(), F_OK) == 0) {
ret = 0;
//}
} else if (urlHead.compare("hclr") == 0 ||
urlHead.compare("vstb") == 0 ||
urlHead.compare("vwch") == 0 ||
urlHead.compare("nwch") == 0 ||
urlHead.compare("wcas") == 0 ||
urlHead.compare("ncas") == 0 ||
urlHead.compare("icas") == 0 ||
urlHead.compare("wdrm") == 0) {
ret = 0;
}
//printf("isUrlValid, ret:%d, url:%s, urlHead:%s, urlHead:%s\n", ret, url.c_str(), urlHead.c_str(), urlFile.c_str());
return ret;
}
static int startingPlayCheck()
{
int ret = 0;
char errorInfo[50] = {0};
#ifndef ANDROID
#define YOCTO_libAmIptvMedia "/usr/lib/libAmIptvMedia.so"
if (access(YOCTO_libAmIptvMedia, F_OK) != 0) {
ret = -1;
strcpy(errorInfo, YOCTO_libAmIptvMedia);
goto EXIT;
}
#define YOCTO_libaml_mp_mediaplayer "/usr/lib/libaml_mp_mediaplayer.so"
if (access(YOCTO_libaml_mp_mediaplayer, F_OK) != 0) {
ret = -1;
strcpy(errorInfo, YOCTO_libaml_mp_mediaplayer);
goto EXIT;
}
#define YOCTO_libaml_mp_sdk "/usr/lib/libaml_mp_sdk.so"
if (access(YOCTO_libaml_mp_sdk, F_OK) != 0) {
ret = -1;
strcpy(errorInfo, YOCTO_libaml_mp_sdk);
goto EXIT;
}
#define YOCTO_libffmpeg_ctc "/usr/lib/libffmpeg_ctc.so"
if (access(YOCTO_libffmpeg_ctc, F_OK) != 0) {
ret = -1;
strcpy(errorInfo, YOCTO_libffmpeg_ctc);
goto EXIT;
}
#endif
return ret;
//coverity[unreachable]
EXIT:
TERMINAL_ERROR("%s%s", errorInfo, " No Exist!!!");
return ret;
}
///////////////////////////////////////////////////////////////////////////////
//Command Line
static int parseCommandArgs(int argc, char* argv[], Argument* argument)
{
static const struct option longopts[] = {
{"help", no_argument, nullptr, 'h'},
{"size", required_argument, nullptr, 's'},
{"pos", required_argument, nullptr, 'p'},
{"channelId", required_argument, nullptr, 'c'},
{"debug", required_argument, nullptr, 'd'},
{"onlyVideo", no_argument, nullptr, 'V'},
{"onlyAudio", no_argument, nullptr, 'A'},
{"id", required_argument, nullptr, 't'},
{"loopMode", required_argument, nullptr, 'L'},
{"noSignalHandler", no_argument, nullptr, 'S'},
{"licenseUrl", required_argument, nullptr, 'l'},
{"options", required_argument, nullptr, 'o'},
{"loopMode", required_argument, nullptr, 'L'},
{"noSignalHandler", no_argument, nullptr, 'S'},
{"noAutoExit", no_argument, nullptr, 'E'},
{nullptr, no_argument, nullptr, 0},
};
int opt, longindex = 0;
while ((opt = getopt_long(argc, argv, "", longopts, &longindex)) != -1) {
//printf("opt = %d\n", opt);
switch (opt) {
case 's':
{
int width, height;
if (sscanf(optarg, "%dx%d", &width, &height) != 2) {
printf("parse %s failed! %s\n", longopts[longindex].name, optarg);
} else {
argument->viewWidth = width;
argument->viewHeight = height;
printf("size:%dx%d\n", width, height);
}
}
break;
case 'p':
{
int x, y;
//printf("optarg:%s\n", optarg);
if (sscanf(optarg, "%dx%d", &x, &y) != 2) {
printf("parse %s failed! %s\n", longopts[longindex].name, optarg);
} else {
argument->x = x;
argument->y = y;
printf("pos:%dx%d\n", x, y);
}
}
break;
case 'c':
{
int channelId = strtol(optarg, nullptr, 0);
printf("channel id:%d\n", channelId);
argument->channelId = channelId;
}
break;
case 'd':
{
int debuglevel = strtol(optarg, nullptr, 0);
printf("debug level:%d\n", debuglevel);
AMMP_DEBUG_MODE_ENABLE = (bool)debuglevel;
}
break;
case 'V':
{
argument->onlyVideo = true;
printf("onlyVideo\n");
}
break;
case 'A':
{
argument->onlyAudio = true;
printf("onlyAudio\n");
}
break;
case 't':
{
int tunnelId = strtol(optarg, nullptr, 0);
printf("tunnel id:%d\n", tunnelId);
argument->tunnelId = tunnelId;
}
break;
case 'L':
{
int loopMode = strtol(optarg, nullptr, 0);
printf("loop mode:%d\n", loopMode);
argument->loopMode = loopMode;
}
break;
case 'S':
{
printf("no signal handler will be installed!\n");
argument->noSignalHandler = true;
}
break;
case 'l':
{
argument->licenseUrl = std::string(optarg);
printf("licenseUrl:%s\n", argument->licenseUrl.c_str());
}
break;
case 'o':
{
uint64_t options = strtoul(optarg, nullptr, 0);
printf("options :0x%" PRIx64 "\n", options);
argument->options = options;
}
break;
case 'E':
{
printf("noAutoExit is set!\n");
argument->noAutoExit = true;
}
break;
case 'h':
default:
return -1;
}
}
//printf("optind:%d, argc:%d\n", optind, argc);
if (optind < argc) {
argument->url = argv[argc-1];
printf("url:%s\n", argument->url.c_str());
}
return 0;
}
static const char* mediaPlayerMediaErrorType2Str(Aml_MP_MediaPlayerMediaErrorType type)
{
switch (type) {
ENUM_TO_STR(AML_MP_MEDIAPLAYER_MEDIA_ERROR_UNKNOWN);
ENUM_TO_STR(AML_MP_MEDIAPLAYER_MEDIA_ERROR_HTTP_BAD_REQUEST);
ENUM_TO_STR(AML_MP_MEDIAPLAYER_MEDIA_ERROR_HTTP_UNAUTHORIZED);
ENUM_TO_STR(AML_MP_MEDIAPLAYER_MEDIA_ERROR_HTTP_FORBIDDEN);
ENUM_TO_STR(AML_MP_MEDIAPLAYER_MEDIA_ERROR_HTTP_NOT_FOUND);
ENUM_TO_STR(AML_MP_MEDIAPLAYER_MEDIA_ERROR_HTTP_OTHER_4XX);
ENUM_TO_STR(AML_MP_MEDIAPLAYER_MEDIA_ERROR_HTTP_SERVER_ERROR);
ENUM_TO_STR(AML_MP_MEDIAPLAYER_MEDIA_ERROR_ENOENT);
ENUM_TO_STR(AML_MP_MEDIAPLAYER_MEDIA_ERROR_ETIMEDOUT);
ENUM_TO_STR(AML_MP_MEDIAPLAYER_MEDIA_ERROR_EIO);
ENUM_TO_STR(AML_MP_MEDIAPLAYER_MEDIA_ERROR_INVALID_KEY);
ENUM_TO_STR(AML_MP_MEDIAPLAYER_MEDIA_ERROR_LICENSE_ERR);
ENUM_TO_STR(AML_MP_MEDIAPLAYER_MEDIA_ERROR_DECRYPT_FAILED);
default:
return "unknowmn media error type";
}
}
void demoCallback(void* userData, Aml_MP_MediaPlayerEventType event, int64_t param)
{
try {
AmlMpMediaPlayerDemo* demo = (AmlMpMediaPlayerDemo*)(userData);
struct Argument* argument = NULL;
switch (event) {
case AML_MP_PLAYER_EVENT_SUBTITLE_DATA:
{
Aml_MP_SubtitleData *subtitleData = (Aml_MP_SubtitleData *)param;
static char cnt = 0;
++cnt;
cnt &= 0x7;
if (subtitleData) {
char bitmapFileName[50];
// Safe snprintf with bounds checking to avoid potential std::length_error
int result = snprintf(bitmapFileName, sizeof(bitmapFileName), "%s-%d", "/data/subtitle", cnt);
if (result < 0 || result >= (int)sizeof(bitmapFileName)) {
printf("Warning: snprintf failed or truncated in subtitle data event\n");
break;
}
char *data = const_cast<char *>(subtitleData->data);
save2BitmapFile(bitmapFileName, (uint32_t *)data, subtitleData->width, subtitleData->height);
}
break;
}
case AML_MP_MEDIAPLAYER_EVENT_PLAYBACK_COMPLETE:
{
if (demo == nullptr) {
break;
}
playerRoster::instance().getPlayerArgument(demo->mId, &argument);
if (argument == NULL || !argument->noAutoExit) {
closeMultiPlayback(demo->mId);
}
printf("%s at #%d AML_MP_MEDIAPLAYER_EVENT_PLAYBACK_COMPLETE, id:%d, noAutoExit:%d\n",__FUNCTION__,__LINE__, demo->mId, argument == NULL ? -1 : argument->noAutoExit);
break;
}
case AML_MP_MEDIAPLAYER_EVENT_PLAYBACK_SOF:
{
if (demo == nullptr) {
break;
}
playerRoster::instance().getPlayerArgument(demo->mId, &argument);
if (argument == NULL || !argument->noAutoExit) {
closeMultiPlayback(demo->mId);
}
printf("%s at #%d AML_MP_MEDIAPLAYER_EVENT_PLAYBACK_SOF, id:%d, noAutoExit:%d\n",__FUNCTION__,__LINE__, demo->mId, argument == NULL ? -1 : argument->noAutoExit);
break;
}
case AML_MP_MEDIAPLAYER_EVENT_PREPARED:
{
if (demo) {
demo->broadcast(true);
printf("id:%d\n", demo->mId);
}
printf("%s at #%d AML_MP_MEDIAPLAYER_EVENT_PREPARED\n",__FUNCTION__,__LINE__);
break;
}
case AML_MP_MEDIAPLAYER_EVENT_MEDIA_ERROR:
{
if (demo) {
demo->broadcast(false);
closeMultiPlayback(demo->mId);
printf("%s at #%d AML_MP_MEDIAPLAYER_EVENT_MEDIA_ERROR, id:%d, type:%s\n",__FUNCTION__,__LINE__, demo->mId, mediaPlayerMediaErrorType2Str(static_cast<Aml_MP_MediaPlayerMediaErrorType>(param)));
}
break;
}
case AML_MP_MEDIAPLAYER_EVENT_STOPPED:
{
printf("%s at #%d AML_MP_MEDIAPLAYER_EVENT_STOPPED\n",__FUNCTION__,__LINE__);
if (demo) {
printf("id:%d\n", demo->mId);
}
break;
}
case AML_MP_MEDIAPLAYER_EVENT_FIRST_FRAME_TOGGLED:
{
printf("%s at #%d AML_MP_MEDIAPLAYER_EVENT_FIRST_FRAME_TOGGLE\n",__FUNCTION__,__LINE__);
if (demo) {
printf("id:%d\n", demo->mId);
}
break;
}
case AML_MP_MEDIAPLAYER_EVENT_VIDEO_UNSUPPORT:
{
TERMINAL_ERROR("%s at #%d AML_MP_MEDIAPLAYER_EVENT_VIDEO_UNSUPPORT\n", __FUNCTION__, __LINE__);
if (demo) {
printf("id:%d, format:%" PRId64 "\n", demo->mId, param);
}
break;
}
case AML_MP_MEDIAPLAYER_EVENT_AUDIO_UNSUPPORT:
{
TERMINAL_ERROR("%s at #%d AML_MP_MEDIAPLAYER_EVENT_AUDIO_UNSUPPORT\n", __FUNCTION__, __LINE__);
if (demo) {
printf("id:%d, format:%" PRId64 "\n", demo->mId, param);
}
break;
}
default:
break;
}
} catch (const std::length_error& e) {
printf("Length error exception in demoCallback: %s", e.what());
} catch (const std::exception& e) {
printf("Standard exception in demoCallback: %s", e.what());
} catch (...) {
printf("Unknown exception caught in demoCallback");
}
}
static void showOption()
{
printf(
"AmlMpMediaPlayerDemo\n"
"Type one option\n"
"\n"
"Main:\n"
" o.................Open URL\n"
" c.................Close URL\n"
" +.................Zap To Following URL\n"
" -.................Zap To Previous URL\n"
" CHANNEL LIST\n"
" ------------\n"
" - igmp://239.0.0.185:8208\n"
" - igmp://239.0.0.183:8208\n"
" - igmp://239.0.0.186:8208\n"
" - igmp://239.0.0.177:8208\n"
" - igmp://239.0.0.176:8208\n"
" - igmp://239.0.0.187:8208\n"
" - igmp://239.0.5.246:8208\n"
" - igmp://239.0.5.111:8208\n"
" - igmp://239.0.5.114:8208\n"
" p.................Pause\n"
" r.................Resume\n"
" K.................Seek\n"
" v.................Get Volume\n"
" V.................Set Volume\n"
" F.................Set fast rate\n"
" M.................Set mute\n"
" <.................Rewind -> -x8 -> -x16 -> -x32 -> -x64\n"
" >.................Forward -> x8 -> x16 -> x32 -> x64 -> x1\n"
" a.................Get Audio Info Channels\n"
" A.................Set Next Audio component\n"
" s.................Get Subtitles Info channels\n"
" S.................Set Next Subtitle component\n"
" U.................Unselect CurAudio component\n"
" u.................Unselect CurSubtitle component\n"
" i.................Get Track/Media info\n"
" n.................Get Position [milliseconds]\n"
" N.................Get Duration [milliseconds]\n"
" w.................Get Main Window Position\n"
" W.................Set Main Window Position\n"
" D.................Show Video\n"
" d.................Hide Video\n"
" T.................Show Subtitle\n"
" t.................Hide Subtitle\n"
"\n"
"PIP:\n"
" O.................Open PIP\n"
" C.................Close PIP\n"
" e.................Get PIP Window Position\n"
" E.................Set PIP Window Position\n"
"\n"
" q................ Exit\n"
"\n"
);
}
static void showUsage()
{
printf("Usage: amlMpMediaPlayerDemo <options> <url>\n"
"options:\n"
" --size: eg: 1920x1080\n"
" --pos: eg: 0x0\n"
" --debug: eg: 1\n"
" --channelId: eg: 0 main, others: pip\n"
" --id: specify the corresponding ui channel id\n"
" --onlyVideo \n"
" --onlyAudio \n"
" --loopMode <value> \n"
" 1: wait play completed, then destroy player and recreate player\n"
" 2: seek to beginning internally when play completed\n"
" --noSignalHandler don't install signal handler\n"
" --licenseUrl eg: --licenseUrl=\"https://widevine-proxy.appspot.com/proxy\" \n"
" --options set options, eg: 3, 3 equals with 0b0011, so it means \"prefer tunerhal\" and \"monitor pid change\"\n"
" 0-bit set 1 means prefer tunerhal: AML_MP_OPTION_PREFER_TUNER_HAL\n"
" 1-bit set 1 means monitor pid change: AML_MP_OPTION_MONITOR_PID_CHANGE\n"
" 2-bit set 1 means prefer CTC: AML_MP_OPTION_PREFER_CTC\n"
" 3-bit set 1 means report subtitle data: AML_MP_OPTION_REPORT_SUBTITLE_DATA\n"
" --loopMode <value> \n"
" 1: wait play completed, then destroy player and recreate player\n"
" 2: seek to beginning internally when play completed\n"
" --noSignalHandler don't install signal handler\n"
" --noAutoExit don't exit at the end of playback\n"
"\n"
"url format:\n"
" clear ts, eg: dclr:http://10.28.8.30:8881/data/a.ts\n"
" clear local file, eg: dclr:/data/a.ts\n"
"\n"
);
}
int main(int argc, char *argv[])
{
// support run in background
signal(SIGTTIN, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
int ret = -1;
try {
if (startingPlayCheck() < 0) {
return ret;
}
Argument argument{};
try {
if (parseCommandArgs(argc, argv, &argument) < 0) {
showUsage();
return ret;
}
} catch (const std::length_error& e) {
printf("Length error in parseCommandArgs: %s\n", e.what());
showUsage();
return ret;
}
if (tty_reset(STDIN_FILENO) < 0) {
printf("\n tty_reset error\n");
return 0;
}
if (tty_cbreak(STDIN_FILENO) < 0) {
printf("\n tty_cbreak error\n");
}
try {
playerRoster::instance().registerPlayerArgument(MEDIAPLAYERDEMO_MAIN, &argument);//only register argument
} catch (const std::length_error& e) {
printf("Length error in registerPlayerArgument: %s\n", e.what());
return ret;
}
if (!argument.noSignalHandler) {
AmlMpMediaPlayerDemo::installSignalHandler();
}
int loopCount = 0;
begin:
try {
ret = multiPlaybackThread(MEDIAPLAYERDEMO_MAIN, true/*isMain*/);
if (ret < 0) {
printf("\n multiPlaybackThread id:%d error\n", (int)MEDIAPLAYERDEMO_MAIN);
}
} catch (const std::length_error& e) {
printf("Length error in multiPlaybackThread: %s\n", e.what());
return ret;
}
{
try {
++loopCount;
Argument* argument = nullptr;
playerRoster::instance().getPlayerArgument(MEDIAPLAYERDEMO_MAIN, &argument);
if (argument && argument->loopMode == 1) {
printf("loop play count:%d\n", loopCount);
goto begin;
}
} catch (const std::length_error& e) {
printf("Length error in getPlayerArgument: %s\n", e.what());
}
}
if (tty_reset(STDIN_FILENO) < 0)
printf("\n tty_reset error\n");
} catch (const std::length_error& e) {
printf("Length error in main: %s\n", e.what());
} catch (const std::exception& e) {
printf("Standard exception in main: %s\n", e.what());
} catch (...) {
printf("Unknown exception in main\n");
}
return ret;
}