RDK Documentation (Open Sourced RDK Components)
main.cpp
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2017 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 #include <string>
21 #include <cstring>
22 #include <cstdlib>
23 
24 #include <essos.h>
25 
26 #include <unistd.h>
27 #include <linux/input.h>
28 #include <cstdio>
29 #include <libgen.h>
30 #include "glib_tools.h"
31 #include <glib-unix.h>
32 
33 #include <rtRemote.h>
34 #include <rtLog.h>
35 
36 #include <glib/gstdio.h>
37 #include "mediasourcepipeline.h"
38 
39 #include "wayland-client.h"
40 
41 
42 #define UNUSED( x ) ((void)(x))
43 
44 std::string files_path_;
45 int gPipefd[2];
46 
47 bool ParseCommandLine(int argc, char** argv) {
48  if (argc > 2) {
49  printf(
50  "Please specify a directory containing raw frame files for media "
51  "source playback!\n");
52  return false;
53  } else if (argc == 2) {
54  files_path_ = argv[1];
55  }
56 
57  return true;
58 }
59 
60 static void keyPressed( void* data, unsigned int key )
61 {
63  pi->HandleKeyboardInput(key);
64 }
65 
66 static void keyReleased( void *, unsigned int )
67 {
68 }
69 
70 static EssKeyListener keyListener=
71 {
72  keyPressed,
73  keyReleased
74 };
75 void rtMainLoopCb(void*)
76 {
77  // This will be called on the glib main loop thread
78  rtError err;
79  err = rtRemoteProcessSingleItem();
80  if (err == RT_ERROR_QUEUE_EMPTY) {
81  //printf("queue was empty upon processing event\n");
82  }
83  else if (err != RT_OK) {
84  fprintf(stderr,"rtRemoteProcessSingleItem() returned %d\n", err);
85  }
86 }
87 
88 void rtRemoteCallback(void*)
89 {
90  //printf("queueReadyHandler entered\n");
91  static char temp[1];
92  int ret = HANDLE_EINTR_EAGAIN(write(gPipefd[PIPE_WRITE], temp, 1));
93  if (ret == -1)
94  fprintf(stderr,"can't write to pipe");
95 }
96 
97 bool initRt(GMainLoop* main_loop, GSource* source, rtObjectRef pipeline)
98 {
99  rtError rc;
100  // Use pipe mechanism to process rt events efficiently
101  source = pipe_source_new(gPipefd, rtMainLoopCb, nullptr);
102  g_source_attach(source, g_main_loop_get_context(main_loop));
103 
104  rtRemoteRegisterQueueReadyHandler( rtEnvironmentGetGlobal(), rtRemoteCallback, nullptr );
105 
106  rc = rtRemoteInit();
107  if(rc != RT_OK) return false;
108 
109  const char* objectName = getenv("PX_WAYLAND_CLIENT_REMOTE_OBJECT_NAME");
110  if (!objectName) objectName = "MEDIASOURCE_PIPELINE_RT";
111  printf("Register RT object: %s\n", objectName);
112 
113  rc = rtRemoteRegisterObject(objectName, pipeline);
114 
115  return (rc == RT_OK);
116 }
117 
118 std::string getExePath()
119 {
120  char result[255];
121  ssize_t count = readlink("/proc/self/exe", result, 255);
122  std::string full_path = std::string( result, (count > 0) ? count : 0 );
123  return dirname((char*) full_path.c_str());
124 }
125 
126 gboolean essosIteration(gint fd,GIOCondition condition,gpointer user_data)
127 {
128  // This will be called on the glib main loop thread
129  EssCtx* ctx = (EssCtx*) user_data;
130  EssContextRunEventLoopOnce( ctx );
131 
132  return TRUE;
133 }
134 
135 gboolean runEssosEventLoop(EssCtx* ctx)
136 {
137  EssContextRunEventLoopOnce( ctx );
138  return TRUE;
139 }
140 
141 int main(int argc, char** argv) {
142 
143  // Use Essos to simplify connecting to a wayland display and getting keyboard input from wayland
144  EssCtx* ctx = EssContextCreate();
145  GMainLoop* g_main_loop = NULL;
146  GSource* source = NULL;
147 
148  if (!ParseCommandLine(argc, argv)) {
149  fprintf(stderr, "Failed to parse command line\n");
150  return -1;
151  }
152 
153  gst_init(&argc, &argv);
154 
155  //Tell Essos to use wayland so it connects to a wayland display
156  if ( !EssContextSetUseWayland( ctx, true ) )
157  {
158  printf("Failed to connect to wayland display, exiting...\n");
159  exit(1);
160  }
161 
162  bool have_folder = false;
163  struct stat st;
164  lstat(files_path_.c_str(), &st);
165  if (S_ISDIR(st.st_mode))
166  have_folder = true;
167 
168  if (!have_folder) {
169  files_path_ = getExePath() + "/mse_frames";
170  printf("No directory passed or directory invalid, using default path:%s\n",files_path_.c_str());
171 
172  lstat(files_path_.c_str(), &st);
173  if (!S_ISDIR(st.st_mode))
174  {
175  printf("Default path:%s not found, exiting...\n",files_path_.c_str());
176  return 1;
177  }
178  }
179  else {
180  printf("Using path:%s\n",files_path_.c_str());
181  }
182 
183  MediaSourcePipeline* pi = new MediaSourcePipeline(files_path_);
184  //rtObjectRef piRef = pi;
185 
186  if (!pi->Start()) {
187  fprintf(stderr, "Failed to start pipeline!\n");
188  return 1;
189  }
190 
191  if ( !EssContextSetKeyListener( ctx, pi, &keyListener ) )
192  {
193  printf("Failed to connect to essos key listener\n");
194  }
195 
196  if ( !EssContextStart( ctx ) )
197  {
198  printf("Failed to start essos context\n");
199  return 1;
200  }
201 
202  // Create a GLib Main Loop and set it to run
203  g_main_loop = g_main_loop_new(NULL, FALSE);
204 
205  if(!initRt(g_main_loop,source,pi))
206  {
207  fprintf(stderr, "Failed to init rt!\n");
208  return 1;
209  }
210 
211  // use the display fd to know when to process, so we don't waste cpu cycles
212  // running on idle, doesn't seem to work on raspberry pi though...
213  /*
214  GIOCondition cond = (GIOCondition) (G_IO_IN | G_IO_ERR | G_IO_HUP);
215  gint fd = wl_display_get_fd((wl_display*)EssContextGetWaylandDisplay(ctx));
216  g_unix_fd_add (fd,cond,essosIteration,ctx);
217  */
218 
219  // works on pi and comcast devices but not as cpu effiecient
220  g_idle_add ((GSourceFunc) runEssosEventLoop, ctx);
221 
222  g_main_loop_run(g_main_loop);
223 
224  /* Free resources */
225  g_main_loop_unref(g_main_loop);
226 
227  rtRemoteShutdown();
228  gst_deinit();
229  g_source_unref(source);
230 
231  EssContextDestroy( ctx );
232 
233  return 0;
234 }
pipe_source_new
GSource * pipe_source_new(int pipefd[2], PipeSourceCallback cb, void *ctx)
This API creates a new event source "rtRemoteSource".
Definition: glib_tools.cpp:81
MediaSourcePipeline
Definition: mediasourcepipeline.h:51
TRUE
#define TRUE
Defines for TRUE/FALSE/ENABLE flags.
Definition: wifi_common_hal.h:199