/* * 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 #include #include #include #include "TestUtils.h" #include #include #include #include #include #include #include "../amlMpTestSupporter/TestModule.h" #include <../../mediaplayer/AmlMediaPlayerBase.h> #include #include #include #include #include #include #include #include //srand #include #include /////////////////////////////////////////////////////////////////////////////// // 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(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 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& args); private: //Rewind Forward char mRewindStateIndex = 0, mForwardStateIndex = 0; bool isRewindOrForward = false; std::string RewindOrForward = ""; void resetRewindAndForwardState() { mRewindStateIndex = 0; mForwardStateIndex = 0; } private: sptr 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& 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&>(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&>(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& args __unused) -> int { showOption();//TestModule::printCommands(g_commandTable, true); return 0; } }, { "p", 0, "pause player", [](AML_MP_MEDIAPLAYER player, const std::vector& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& args __unused) -> int { printf("exit playback\n"); return 0; } }, { "\n", 0, "\n", [](AML_MP_MEDIAPLAYER player, const std::vector& args __unused) -> int { printf("\n"); return 0; } }, { "cas_ioctl", 0, "trigger CAS ioctl (Interactive mode)", [](AML_MP_MEDIAPLAYER player, const std::vector& 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 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 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 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(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(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(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 \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 \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 \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; }