2565 lines
86 KiB
C++
2565 lines
86 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_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;
|
||
}
|