RDK Documentation (Open Sourced RDK Components)
AampcliPlaybackCommand.cpp
Go to the documentation of this file.
1 /*
2  * If not stated otherwise in this file or this component's license file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2022 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 /**
21  * @file AampcliPlaybackCommand.cpp
22  * @brief Aampcli Playback Commands handler
23  */
24 
25 #include <iomanip>
26 #include "AampcliPlaybackCommand.h"
27 
28 extern VirtualChannelMap mVirtualChannelMap;
29 extern Aampcli mAampcli;
30 extern void tsdemuxer_InduceRollover( bool enable );
31 
32 std::map<string,string> PlaybackCommand::playbackCommands = std::map<string,string>();
33 std::vector<std::string> PlaybackCommand::commands(0);
34 
35 /**
36  * @brief Process command
37  * @param cmd command
38  */
39 bool PlaybackCommand::execute(char *cmd, PlayerInstanceAAMP *playerInstanceAamp)
40 {
41  bool eventChange = false;
42  char lang[MAX_LANGUAGE_TAG_LENGTH];
43  char cacheUrl[200];
44  int keepPaused = 0;
45  int rate = 0;
46  double seconds = 0;
47  long unlockSeconds = 0;
48  long grace = 0;
49  long time = -1;
50  int ms = 0;
51  int playerIndex = -1;
52 
53  trim(&cmd);
54  while( *cmd==' ' ) cmd++;
55 
56  if( cmd[0]=='#' )
57  {
58  printf( "skipping comment\n" );
59  }
60  else if(cmd[0] == 0)
61  {
62  if (playerInstanceAamp->aamp->mpStreamAbstractionAAMP)
63  {
64  playerInstanceAamp->aamp->mpStreamAbstractionAAMP->DumpProfiles();
65  }
66  printf("[AAMPCLI] current network bandwidth ~= %ld\n", playerInstanceAamp->aamp->GetPersistedBandwidth());
67  }
68  else if (strcmp(cmd, "help") == 0)
69  {
70  showHelp();
71  }
72  else if( strcmp(cmd,"rollover")==0 )
73  {
74  printf( "enabling artificial pts rollover (10s after next tune)\n" );
75  tsdemuxer_InduceRollover( true );
76  }
77  else if (strcmp(cmd, "list") == 0)
78  {
79  mVirtualChannelMap.showList();
80  }
81  else if( strcmp(cmd,"autoplay") == 0 )
82  {
83  mAampcli.mbAutoPlay = !mAampcli.mbAutoPlay;
84  printf( "autoplay = %s\n", mAampcli.mbAutoPlay?"true":"false" );
85  }
86  else if( strcmp(cmd,"new") == 0 )
87  {
88  mAampcli.newPlayerInstance();
89  }
90  else if( sscanf(cmd, "sleep %d", &ms ) == 1 )
91  {
92  if( ms>0 )
93  {
94  printf( "sleeping for %f seconds\n", ms/1000.0 );
95  g_usleep (ms * 1000);
96  printf( "sleep complete\n" );
97  }
98  }
99  else if( sscanf(cmd, "select %d", &playerIndex ) == 1 )
100  {
101  try {
102  playerInstanceAamp = mAampcli.mPlayerInstances.at(playerIndex);
103  if (playerInstanceAamp->aamp)
104  {
105  printf( "selected player %d (at %p)\n", playerInstanceAamp->aamp->mPlayerId, playerInstanceAamp);
106  mAampcli.mSingleton=playerInstanceAamp;
107  }
108  else
109  {
110  printf( "error - player exists but is not valid/ready, playerInstanceAamp->aamp is not a valid ptr\n");
111  }
112  } catch (std::out_of_range const& exc) {
113  if (mAampcli.mPlayerInstances.size() == 0)
114  {
115  printf( "error - no player instances\n" );
116  }
117  else
118  {
119  printf( "valid range = 0..%lu\n", mAampcli.mPlayerInstances.size()-1 );
120  }
121  }
122  }
123  else if (strcmp(cmd, "select") == 0)
124  { // List available player instances
125  printf( "player instances:\n" );
126  playerIndex = 0;
127  for( auto playerInstance : mAampcli.mPlayerInstances )
128  {
129  printf( "\t%d", playerIndex++ );
130  if( playerInstance == playerInstanceAamp )
131  {
132  printf( " (selected)");
133  }
134  printf( "\n ");
135  }
136  }
137  else if( strcmp(cmd,"detach") == 0 )
138  {
139  playerInstanceAamp->detach();
140  }
141  else if (isTuneScheme(cmd))
142  {
143  {
144  if (memcmp(cmd, "live", 4) == 0)
145  {
146  playerInstanceAamp->SeekToLive();
147  }
148  else
149  {
150  playerInstanceAamp->Tune(cmd,mAampcli.mbAutoPlay);
151  }
152  }
153  }
154  else if( memcmp(cmd, "next", 4) == 0 )
155  {
156  VirtualChannelInfo *pNextChannel = mVirtualChannelMap.next();
157  if (pNextChannel)
158  {
159  printf("[AAMPCLI] next %d: %s\n", pNextChannel->channelNumber, pNextChannel->name.c_str());
160  mVirtualChannelMap.tuneToChannel( *pNextChannel, playerInstanceAamp);
161  }
162  else
163  {
164  printf("[AAMPCLI] can not fetch 'next' channel, empty virtual channel map\n");
165  }
166  }
167  else if( memcmp(cmd, "prev", 4) == 0 )
168  {
169  VirtualChannelInfo *pPrevChannel = mVirtualChannelMap.prev();
170  if (pPrevChannel)
171  {
172  printf("[AAMPCLI] next %d: %s\n", pPrevChannel->channelNumber, pPrevChannel->name.c_str());
173  mVirtualChannelMap.tuneToChannel( *pPrevChannel, playerInstanceAamp);
174  }
175  else
176  {
177  printf("[AAMPCLI] can not fetch 'prev' channel, empty virtual channel map\n");
178  }
179  }
180  else if (isNumber(cmd))
181  {
182  int channelNumber = atoi(cmd); // invalid input results in 0 -- will not be found
183 
184  VirtualChannelInfo *pChannelInfo = mVirtualChannelMap.find(channelNumber);
185  if (pChannelInfo != NULL)
186  {
187  printf("[AAMPCLI] channel number: %d\n", channelNumber);
188  mVirtualChannelMap.tuneToChannel( *pChannelInfo, playerInstanceAamp);
189  }
190  else
191  {
192  printf("[AAMPCLI] channel number: %d was not found\n", channelNumber);
193  }
194  }
195  else if (sscanf(cmd, "seek %lf %d", &seconds, &keepPaused) >= 1)
196  {
197  bool seekWhilePaused = (keepPaused==1);
198  {
199  playerInstanceAamp->Seek(seconds, (keepPaused==1) );
200  }
201  keepPaused = 0;
202  }
203  else if (strcmp(cmd, "sf") == 0)
204  {
205  playerInstanceAamp->SetRate((float)0.5);
206  }
207  else if (sscanf(cmd, "ff%d", &rate) == 1)
208  {
209  playerInstanceAamp->SetRate((float)rate);
210  }
211  else if (strcmp(cmd, "play") == 0)
212  {
213  playerInstanceAamp->SetRate(1);
214  }
215  else if (sscanf(cmd, "pause%lf", &seconds) == 1)
216  {
217  playerInstanceAamp->PauseAt(seconds);
218  }
219  else if (strcmp(cmd, "pause") == 0)
220  {
221  playerInstanceAamp->SetRate(0);
222  }
223  else if (sscanf(cmd, "rw%d", &rate) == 1)
224  {
225  playerInstanceAamp->SetRate((float)(-rate));
226  }
227  else if (sscanf(cmd, "bps %d", &rate) == 1)
228  {
229  printf("[AAMPCLI] Set video bitrate %d.\n", rate);
230  playerInstanceAamp->SetVideoBitrate(rate);
231  }
232  else if (strcmp(cmd, "flush") == 0)
233  {
234  playerInstanceAamp->aamp->mStreamSink->Flush();
235  }
236  else if (strcmp(cmd, "stop") == 0)
237  {
238  playerInstanceAamp->Stop();
239  tsdemuxer_InduceRollover(false);
240  }
241  else if (strcmp(cmd, "underflow") == 0)
242  {
244  }
245  else if (strcmp(cmd, "retune") == 0)
246  {
248  }
249  else if (strcmp(cmd, "status") == 0)
250  {
251  playerInstanceAamp->aamp->mStreamSink->DumpStatus();
252  }
253  else if (strcmp(cmd, "live") == 0)
254  {
255  playerInstanceAamp->SeekToLive();
256  }
257  else if (strcmp(cmd, "exit") == 0)
258  {
259  playerInstanceAamp = NULL;
260  for( auto playerInstance : mAampcli.mPlayerInstances )
261  {
262  playerInstance->Stop();
263  SAFE_DELETE( playerInstance );
264  }
265  termPlayerLoop();
266  return false; //to exit
267  }
268  else if (memcmp(cmd, "rect", 4) == 0)
269  {
270  int x, y, w, h;
271  if (sscanf(cmd, "rect %d %d %d %d", &x, &y, &w, &h) == 4)
272  {
273  playerInstanceAamp->SetVideoRectangle(x, y, w, h);
274  }
275  }
276  else if (memcmp(cmd, "zoom", 4) == 0)
277  {
278  int zoom;
279  if (sscanf(cmd, "zoom %d", &zoom) == 1)
280  {
281  if (zoom)
282  {
283  printf("[AAMPCLI] Set zoom to full\n");
284  playerInstanceAamp->SetVideoZoom(VIDEO_ZOOM_FULL);
285  }
286  else
287  {
288  printf("[AAMPCLI] Set zoom to none\n");
289  playerInstanceAamp->SetVideoZoom(VIDEO_ZOOM_NONE);
290  }
291  }
292  }
293  else if( sscanf(cmd, "sap %s",lang ) )
294  {
295  size_t len = strlen(lang);
296  printf("[AAMPCLI] aamp cli sap called for language %s\n",lang);
297  if( len>0 )
298  {
299  playerInstanceAamp->SetLanguage( lang );
300  }
301  else
302  {
303  printf("[AAMPCLI] GetCurrentAudioLanguage: '%s'\n", playerInstanceAamp->GetCurrentAudioLanguage() );
304  }
305  }
306  else if( strcmp(cmd,"getplaybackrate") == 0 )
307  {
308  printf("[AAMPCLI] Playback Rate: %d\n", playerInstanceAamp->GetPlaybackRate());
309  }
310  else if (memcmp(cmd, "islive", 6) == 0 )
311  {
312  printf("[AAMPCLI] VIDEO IS %s\n",
313  (playerInstanceAamp->IsLive() == true )? "LIVE": "NOT LIVE");
314  }
315  else if (memcmp(cmd, "customheader", 12) == 0 )
316  {
317  //Dummy implimenations
318  std::vector<std::string> headerValue;
319  printf("[AAMPCLI] customheader Command is %s\n" , cmd);
320  playerInstanceAamp->AddCustomHTTPHeader("", headerValue, false);
321  }
322  else if (sscanf(cmd, "unlock %ld", &unlockSeconds) >= 1)
323  {
324  printf("[AAMPCLI] unlocking for %ld seconds\n" , unlockSeconds);
325  if(-1 == unlockSeconds)
326  grace = -1;
327  else
328  time = unlockSeconds;
329  playerInstanceAamp->DisableContentRestrictions(grace, time, eventChange);
330  }
331  else if (memcmp(cmd, "unlock", 6) == 0 )
332  {
333  printf("[AAMPCLI] unlocking till next program change\n");
334  eventChange = true;
335  playerInstanceAamp->DisableContentRestrictions(grace, time, eventChange);
336  }
337  else if (memcmp(cmd, "lock", 4) == 0 )
338  {
339  playerInstanceAamp->EnableContentRestrictions();
340  }
341  else if (strcmp(cmd, "progress") == 0)
342  {
343  mAampcli.mEnableProgressLog = mAampcli.mEnableProgressLog ? false : true;
344  }
345  else if(strcmp(cmd, "stats") == 0)
346  {
347  printf("[AAMPCLI] Playback stats: %s", playerInstanceAamp->GetPlaybackStats().c_str());
348  }
349 
350  return true;
351 }
352 
353 /**
354  * @brief check if the char array is having numbers only
355  * @param s
356  * @retval true or false
357  */
358 bool PlaybackCommand::isNumber(const char *s)
359 {
360  if (*s)
361  {
362  if (*s == '-')
363  { // skip leading minus
364  s++;
365  }
366  for (;;)
367  {
368  if (*s >= '0' && *s <= '9')
369  {
370  s++;
371  continue;
372  }
373  if (*s == 0x00)
374  {
375  return true;
376  }
377  break;
378  }
379  }
380  return false;
381 }
382 
383 /**
384  * @brief Decide if input command consists of supported URI scheme to be tuned.
385  * @param cmd cmd to parse
386  */
387 bool PlaybackCommand::isTuneScheme(const char *cmd)
388 {
389  bool isTuneScheme = false;
390  const char *protocol[5] = { "http:","https:","live:","hdmiin:","file:" };
391  for( int i=0; i<5; i++ )
392  {
393  size_t len = strlen(protocol[i]);
394  if( memcmp( cmd, protocol[i],len )==0 )
395  {
396  isTuneScheme=true;
397  break;
398  }
399  }
400  return isTuneScheme;
401 }
402 
403 /**
404  * @brief trim a string
405  * @param[in][out] cmd Buffer containing string
406  */
407 void PlaybackCommand::trim(char **cmd)
408 {
409  std::string src = *cmd;
410  size_t first = src.find_first_not_of(' ');
411  if (first != std::string::npos)
412  {
413  size_t last = src.find_last_not_of(" \r\n");
414  std::string dst = src.substr(first, (last - first + 1));
415  strncpy(*cmd, (char*)dst.c_str(), dst.size());
416  (*cmd)[dst.size()] = '\0';
417  }
418 }
419 
420 /**
421  * @brief Stop mainloop execution (for standalone mode)
422  */
424 {
425  if(mAampcli.mAampGstPlayerMainLoop)
426  {
427  g_main_loop_quit(mAampcli.mAampGstPlayerMainLoop);
428  g_thread_join(mAampcli.mAampMainLoopThread);
429  gst_deinit ();
430  printf("[AAMPCLI] %s(): Exit\n", __FUNCTION__);
431  }
432 }
433 
434 void PlaybackCommand::registerPlaybackCommands()
435 {
436  addCommand("list","Type list to view virtual channel map");
437  addCommand("get help","Show help of get command");
438  addCommand("set help","Show help of set command");
439  addCommand("<channelNumber>","Play selected channel from guide");
440  addCommand("<url>","Play arbitrary stream");
441  addCommand("sleep <ms>","Sleep <ms> milliseconds");
442  addCommand("autoplay","Toggle tune autoplay (default = true)");
443  addCommand("new","Create new player instance");
444  addCommand("select","Enumerate available player instances");
445  addCommand("select <index>","Select player instance for use");
446  addCommand("detach","Detach (lightweight stop) selected player instance");
447  addCommand("pause","Pause the existing playback");
448  addCommand("pause <seconds>","Pause at specified position, negative value to cancel");
449  addCommand("play","Continue existing playback");
450  addCommand("stop","Stop the existing playback");
451  addCommand("status","get the status of existing playback");
452  addCommand("flush","Flush the existing playback");
453  addCommand("sf","slow");
454  addCommand("ff<x>","Trickmodes (x <= 128. y <= 128)");
455  addCommand("rw<y>","Trickmodes (x <= 128. y <= 128)");
456  addCommand("bps <x>","set bitrate (x= bitrate)");
457  addCommand("sap","Use SAP track (if avail)");
458  addCommand("seek <seconds>","Specify start time within manifest");
459  addCommand("live","Seek to live point");
460  addCommand("underflow","Simulate underflow");
461  addCommand("retune","schedule retune");
462  addCommand("unlock <cond>","unlock a channel <long int - time in seconds>");
463  addCommand("lock","lock the current channel");
464  addCommand("next","Play next virtual channel");
465  addCommand("rollover","Schedule artificial pts rollover 10s after next tune");
466  addCommand("prev","Play previous virtual channel");
467  addCommand("exit","Exit from application");
468  addCommand("help","Show this list again");
469  addCommand("progress","Enable/disable Progress event logging");
470  addCommand("auto <opt params>",
471  "startChan=500 endChan=1000 maxTuneTime=6 playTime=15 betweenTime=15" );
472 }
473 
474 void PlaybackCommand::addCommand(string command,string description)
475 {
476  playbackCommands.insert(make_pair(command,description));
477  commands.push_back(command);
478 }
479 
480 /**
481  * @brief Show help menu with aamp command line interface
482  */
484 {
485 
486  std::map<string,string>::iterator playbackCmdItr;
487 
488  printf("******************************************************************************************\n");
489  printf("* <command> [<arguments>]\n");
490  printf("* Usage of Commands, and arguments expected\n");
491  printf("******************************************************************************************\n");
492 
493  for(auto itr:commands)
494  {
495  playbackCmdItr = playbackCommands.find(itr);
496 
497  if(playbackCmdItr != playbackCommands.end())
498  {
499  std::cout << std::setw(20) << std::left << (playbackCmdItr->first).c_str() << "// "<< (playbackCmdItr->second).c_str() << "\n";
500  }
501  }
502 
503  printf("******************************************************************************************\n");
504 }
505 
506 char * PlaybackCommand::commandRecommender(const char *text, int state)
507 {
508  char *name;
509  static int len;
510  static std::vector<std::string>::iterator itr;
511 
512  if (!state)
513  {
514  itr = commands.begin();
515  len = strlen(text);
516  }
517 
518  while (itr != commands.end())
519  {
520  name = (char *) itr->c_str();
521  itr++;
522  if (strncmp(name, text, len) == 0)
523  {
524  return strdup(name);
525  }
526  }
527 
528  return NULL;
529 }
PlaybackCommand::trim
void trim(char **cmd)
trim a string
Definition: AampcliPlaybackCommand.cpp:407
PlayerInstanceAAMP::aamp
class PrivateInstanceAAMP * aamp
Definition: main_aamp.h:1943
VIDEO_ZOOM_FULL
@ VIDEO_ZOOM_FULL
Definition: main_aamp.h:131
PlaybackCommand::showHelp
void showHelp(void)
Show help menu with aamp command line interface.
Definition: AampcliPlaybackCommand.cpp:483
VirtualChannelInfo
Holds information of a virtual channel.
Definition: AampcliVirtualChannelMap.h:39
PrivateInstanceAAMP::mpStreamAbstractionAAMP
class StreamAbstractionAAMP * mpStreamAbstractionAAMP
Definition: priv_aamp.h:807
PlayerInstanceAAMP::EnableContentRestrictions
void EnableContentRestrictions()
Enable Content Restrictions - lock.
Definition: main_aamp.cpp:2751
eMEDIATYPE_VIDEO
@ eMEDIATYPE_VIDEO
Definition: AampMediaType.h:39
PlayerInstanceAAMP::SetVideoZoom
void SetVideoZoom(VideoZoomMode zoom)
Set video zoom.
Definition: main_aamp.cpp:1282
VIDEO_ZOOM_NONE
@ VIDEO_ZOOM_NONE
Definition: main_aamp.h:132
PlayerInstanceAAMP::IsLive
bool IsLive()
To check whether the asset is live or not.
Definition: main_aamp.cpp:1503
Aampcli
Definition: Aampcli.h:61
PlayerInstanceAAMP::GetPlaybackRate
int GetPlaybackRate(void)
To get the current playback rate.
Definition: main_aamp.cpp:1884
PlayerInstanceAAMP::SetVideoRectangle
void SetVideoRectangle(int x, int y, int w, int h)
Set video rectangle.
Definition: main_aamp.cpp:1270
PlayerInstanceAAMP::GetPlaybackStats
std::string GetPlaybackStats()
Get playback statistics formated for partner apps.
Definition: main_aamp.cpp:3016
eDASH_ERROR_STARTTIME_RESET
@ eDASH_ERROR_STARTTIME_RESET
Definition: priv_aamp.h:178
StreamAbstractionAAMP::DumpProfiles
virtual void DumpProfiles(void)=0
Dump profiles for debugging. To be implemented by sub classes.
PrivateInstanceAAMP::ScheduleRetune
void ScheduleRetune(PlaybackErrorType errorType, MediaType trackType)
Schedules retune or discontinuity processing based on state.
Definition: priv_aamp.cpp:7559
AampcliPlaybackCommand.h
AAMPcliPlaybackCommand header file.
PlayerInstanceAAMP::SetLanguage
void SetLanguage(const char *language)
Set Audio language.
Definition: main_aamp.cpp:1389
PlaybackCommand::termPlayerLoop
void termPlayerLoop()
Stop mainloop execution (for standalone mode)
Definition: AampcliPlaybackCommand.cpp:423
PlaybackCommand::isNumber
bool isNumber(const char *s)
check if the char array is having numbers only
Definition: AampcliPlaybackCommand.cpp:358
StreamSink::DumpStatus
virtual void DumpStatus(void)
Dump the sink status for debugging purpose.
Definition: main_aamp.h:456
PlayerInstanceAAMP::Seek
void Seek(double secondsRelativeToTuneTime, bool keepPaused=false)
Seek to a time.
Definition: main_aamp.cpp:971
PlayerInstanceAAMP::PauseAt
void PauseAt(double position)
Set PauseAt position.
Definition: main_aamp.cpp:837
eGST_ERROR_UNDERFLOW
@ eGST_ERROR_UNDERFLOW
Definition: priv_aamp.h:175
PlayerInstanceAAMP
Player interface class for the JS pluggin.
Definition: main_aamp.h:692
VirtualChannelMap
Holds all of the virtual channels.
Definition: AampcliVirtualChannelMap.h:54
PlayerInstanceAAMP::detach
void detach()
Soft stop the player instance.
Definition: main_aamp.cpp:385
PlayerInstanceAAMP::SetRate
void SetRate(float rate, int overshootcorrection=0)
Set playback rate.
Definition: main_aamp.cpp:561
PlayerInstanceAAMP::GetCurrentAudioLanguage
const char * GetCurrentAudioLanguage()
Get current audio language.
Definition: main_aamp.cpp:1523
PlayerInstanceAAMP::Tune
void Tune(const char *mainManifestUrl, const char *contentType, bool bFirstAttempt, bool bFinalAttempt, const char *traceUUID, bool audioDecoderStreamSync)
Tune to a URL. DEPRECATED! This is included for backwards compatibility with current Sky AS integrati...
Definition: main_aamp.cpp:312
PlaybackCommand::execute
bool execute(char *cmd, PlayerInstanceAAMP *playerInstanceAamp)
Process command.
Definition: AampcliPlaybackCommand.cpp:39
PlaybackCommand::isTuneScheme
bool isTuneScheme(const char *cmd)
Decide if input command consists of supported URI scheme to be tuned.
Definition: AampcliPlaybackCommand.cpp:387
StreamSink::Flush
virtual void Flush(double position=0, int rate=1, bool shouldTearDown=true)
Flush the pipeline.
Definition: main_aamp.h:466
PlayerInstanceAAMP::DisableContentRestrictions
void DisableContentRestrictions(long grace, long time, bool eventChange)
Disable Content Restrictions - unlock.
Definition: main_aamp.cpp:2742
PlayerInstanceAAMP::Stop
void Stop(bool sendStateChangeEvent=true)
Stop playback and release resources.
Definition: main_aamp.cpp:282
PlayerInstanceAAMP::SetVideoBitrate
void SetVideoBitrate(long bitrate)
To set a preferred bitrate for video profile.
Definition: main_aamp.cpp:1805
PlayerInstanceAAMP::SeekToLive
void SeekToLive(bool keepPaused=false)
Seek to live point.
Definition: main_aamp.cpp:1144
PlayerInstanceAAMP::AddCustomHTTPHeader
void AddCustomHTTPHeader(std::string headerName, std::vector< std::string > headerValue, bool isLicenseHeader=false)
Add/Remove a custom HTTP header and value.
Definition: main_aamp.cpp:1579
PrivateInstanceAAMP::GetPersistedBandwidth
long GetPersistedBandwidth()
Get persisted bandwidth.
Definition: priv_aamp.h:1517