RDK Documentation (Open Sourced RDK Components)
playbintest.cpp
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 2018 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 #include <gst/gst.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <pthread.h>
23 #include <string.h>
24 
25 
26 #define DEFAULT_URI "aamps://tungsten.aaplimg.com/VOD/bipbop_adv_example_v2/master.m3u8"
27 #define DEFAULT_URI2 "aamp://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"
28 #define DEFAULT_VIDEO_RECT "0,0,1280,720"
29 
30 #define PLAYBINTEST_NUMBER_OF_VID 1
31 #define PLAYBINTEST_MAX_NUMBER_OF_VID 2
32 
33 GST_DEBUG_CATEGORY_STATIC (playbintest);
34 #define GST_CAT_DEFAULT playbintest
35 
36 GstElement *playbin[PLAYBINTEST_NUMBER_OF_VID];
37 GMainLoop *main_loop;
38 pthread_t uiThreadID;
39 const char* uri[2];
40 const char* playbin_names[PLAYBINTEST_MAX_NUMBER_OF_VID] = {"playbin-0", "playbin-1"};
41 const char* video_rectangle[PLAYBINTEST_MAX_NUMBER_OF_VID] = {"0,0,640,360","640,0,640,360"};
42 gboolean g_print_states = FALSE;
43 
44 #define PLAYBINFLAG_BUFFERING 0x00000100
45 
46 static void info(int idx = 0)
47 {
48  gint64 position=0, duration=0;
49  if (FALSE == gst_element_query_position(playbin[idx], GST_FORMAT_TIME, &position))
50  {
51  g_printerr("**PLAYBINTEST: gst_element_query_position failed\n");
52  }
53 
54  if (FALSE == gst_element_query_duration(playbin[idx], GST_FORMAT_TIME, &duration))
55  {
56  g_printerr("*******PLAYBINTEST: ** gst_element_query_duration failed\n");
57  }
58  g_print("**PLAYBINTEST: Position:%" G_GINT64_FORMAT " Duration:%" G_GINT64_FORMAT "\n", position, duration);
59 
60 }
61 
62 static void setRate(gdouble rate, int idx=0)
63 {
64  gint64 cur = GST_CLOCK_TIME_NONE;
65  gboolean ret;
66  if (!gst_element_query_position(playbin[idx], GST_FORMAT_TIME, &cur))
67  {
68  g_print("**PLAYBINTEST: query failed\n");
69  }
70  g_print("**PLAYBINTEST: setting rate %f\n", rate);
71  if (rate < 0)
72  {
73  ret = gst_element_seek(playbin[idx], rate, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
74  GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE, GST_SEEK_TYPE_SET, cur);
75  }
76  else
77  {
78  ret = gst_element_seek(playbin[idx], rate, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, cur,
79  GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
80  }
81  if (!ret)
82  {
83  g_print("**PLAYBINTEST: seek failed\n");
84  }
85  else
86  {
87  g_print("**PLAYBINTEST: seek setrate success\n");
88  }
89 }
90 
91 static void seek(int seconds, int idx=0)
92 {
93  gint64 cur = GST_SECOND*seconds;
94 
95  if (!gst_element_seek(playbin[idx], 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
96  GST_SEEK_TYPE_SET, cur,
97  GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE))
98  {
99  g_print("**PLAYBINTEST: seek failed\n");
100  }
101  else
102  {
103  g_print("**PLAYBINTEST: seek success\n");
104  }
105 }
106 
107 static void setPause(bool pause, int idx= 0)
108 {
109 
110  GstStateChangeReturn ret;
111  GstState state = pause?GST_STATE_PAUSED:GST_STATE_PLAYING;
112  ret = gst_element_set_state(playbin[idx], state);
113  if (ret == GST_STATE_CHANGE_FAILURE)
114  {
115  g_printerr("gst_element_set_state failed\n");
116  }
117 }
118 
119 static void stop(int idx = 0)
120 {
121  GstStateChangeReturn ret;
122  ret = gst_element_set_state(playbin[idx], GST_STATE_NULL);
123  if (ret == GST_STATE_CHANGE_FAILURE)
124  {
125  g_printerr("gst_element_set_state failed\n");
126  }
127 }
128 
129 static void changeChannel(const char* uri, int idx= 0)
130 {
131  //CID:100649 - Remoed the local variable which has been initialized but not used
132  stop(idx);
133  g_object_set(playbin[idx], "uri", uri, NULL);
134  setPause(false);
135 }
136 
137 static void stressTest(int idx= 0)
138 {
139  int count = 0;
140  g_print("**PLAYBINTEST: start stressTest\n");
141  while (1)
142  {
143  changeChannel(uri[0], idx);
144  g_usleep(10*1000*1000);
145  changeChannel(uri[1], idx);
146  g_usleep(10*1000*1000);
147  count += 2;
148  g_print("\n\n**PLAYBINTEST: ChannelChange Count %d\n\n",count);
149  }
150 }
151 
152 static void process_command(char* cmd)
153 {
154  int value;
155  if (strcmp(cmd, "info") == 0)
156  {
157  info();
158  }
159  else if (strcmp(cmd, "ff8") == 0)
160  {
161  setRate(8);
162  }
163  else if (strcmp(cmd, "ff16") == 0)
164  {
165  setRate(16);
166  }
167  else if (strcmp(cmd, "ff32") == 0)
168  {
169  setRate(32);
170  }
171  else if (strcmp(cmd, "ff") == 0)
172  {
173  setRate(4);
174  }
175  else if (strcmp(cmd, "rw32") == 0)
176  {
177  setRate(-32);
178  }
179  else if (strcmp(cmd, "rw16") == 0)
180  {
181  setRate(-16);
182  }
183  else if (strcmp(cmd, "rw8") == 0)
184  {
185  setRate(-8);
186  }
187  else if (strcmp(cmd, "rw") == 0)
188  {
189  setRate(-4);
190  }
191  else if (strcmp(cmd, "play") == 0)
192  {
193  setPause(false);
194  }
195  else if (strcmp(cmd, "pause") == 0)
196  {
197  setPause(true);
198  }
199  else if (strcmp(cmd, "1") == 0)
200  {
201  changeChannel(uri[1]);
202  }
203  else if (strcmp(cmd, "0") == 0)
204  {
205  changeChannel(uri[0]);
206  }
207  else if (strcmp(cmd, "stress") == 0)
208  {
209  stressTest();
210  }
211  else if (sscanf(cmd, "seek %d", &value) == 1)
212  {
213  seek(value);
214  }
215  else if (strcmp(cmd, "stop") == 0)
216  {
217  stop();
218  }
219 }
220 
221 static void* ui_thread(void * arg)
222 {
223  char cmd[1024];
224  g_print("**PLAYBINTEST: start ui_thread\n");
225  while (fgets(cmd, sizeof(cmd), stdin))
226  {
227  char *dst = cmd;
228  while (*dst >= ' ')
229  {
230  dst++;
231  }
232  *dst = 0x00; // NUL terminator
233  process_command(cmd);
234  }
235  g_print("**PLAYBINTEST: exit ui_thread\n");
236  return NULL;
237 }
238 
239 static gboolean handle_bus_message(GstBus *bus, GstMessage *msg, void* arg)
240 {
241  GError *error;
242  gchar *info;
243  //g_print("**PLAYBINTEST: Enter\n" );
244 
245  switch (GST_MESSAGE_TYPE(msg))
246  {
247  case GST_MESSAGE_EOS:
248  {
249  g_print("EOS\n");
250  //g_main_loop_quit(main_loop);
251  break;
252  }
253  case GST_MESSAGE_ERROR:
254  {
255  gst_message_parse_error(msg, &error, &info);
256  g_printerr("**PLAYBINTEST: Error received from element %s: %s\n", GST_OBJECT_NAME(msg->src), error->message);
257  g_printerr("**PLAYBINTEST: Debugging information: %s\n", info ? info : "none");
258  g_free(info);
259  g_main_loop_quit(main_loop);
260  break;
261  }
262  case GST_MESSAGE_STATE_CHANGED:
263  {
264  GstState old, now, pending;
265  gst_message_parse_state_changed(msg, &old, &now, &pending);
266  if (g_print_states || memcmp(GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)), "playbin", 7) == 0)
267  {
268  g_print( "**PLAYBINTEST: element %s state change : %s -> %s . pending state %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)),
269  gst_element_state_get_name(old), gst_element_state_get_name(now), gst_element_state_get_name(pending) );
270  }
271  GST_DEBUG_BIN_TO_DOT_FILE((GstBin *)playbin[0], GST_DEBUG_GRAPH_SHOW_ALL, "playbintest");
272 
273  if (now == GST_STATE_PLAYING && memcmp(GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)), "brcmvideosink", 13) == 0)
274  { // video scaling patch
275  /*
276  brcmvideosink doesn't sets the rectangle property correct by default
277  gst-inspect-1.0 brcmvideosink
278  g_object_get(_this->privateContext->pipeline, "video-sink", &videoSink, NULL); - reports NULL
279  note: alternate "window-set" works as well
280  */
281  GstElement *pbin = GST_ELEMENT(GST_MESSAGE_SRC(msg));
282  if(pbin != NULL)
283  {
284  while(GST_ELEMENT_PARENT(pbin))
285  {
286  pbin = GST_ELEMENT_PARENT(pbin);
287  }
288  const char * rect = DEFAULT_VIDEO_RECT;
289  int zorder = 0;
290  if (PLAYBINTEST_NUMBER_OF_VID > 1 )
291  {
292  for (int i=0; i< PLAYBINTEST_NUMBER_OF_VID; i++)
293  {
294  if (strcmp(GST_OBJECT_NAME(pbin), playbin_names[i]) == 0)
295  {
296  rect = video_rectangle[i];
297  zorder = i;
298  break;
299  }
300  }
301  }
302  g_print("*%s : setting rectangle to %s zorder to %d*\n", GST_OBJECT_NAME(pbin), rect, zorder);
303  g_object_set(GST_MESSAGE_SRC(msg), "rectangle", rect, NULL);
304  g_object_set(GST_MESSAGE_SRC(msg), "zorder", zorder, NULL);
305  }
306  else
307  {
308  g_printerr("%s:%d : pbin is null", __FUNCTION__, __LINE__); //CID:82519 - Null Returns
309  }
310  }
311  break;
312  }
313  case GST_MESSAGE_BUFFERING:
314  {
315  gint percent;
316  gst_message_parse_buffering(msg, &percent);
317  g_print("**PLAYBINTEST: eBuffering %d\n", percent);
318 #ifdef PLAYBINTEST_BUFFERING
319  if (percent == 100 )
320  setPause(false);
321  else if(percent < 10)
322  setPause(true);
323 #endif
324  break;
325  }
326  case GST_MESSAGE_TAG:
327  break;
328  default:
329  g_print("Bus msg type: %s\n", gst_message_type_get_name(msg->type));
330  break;
331  }
332  //g_print("**PLAYBINTEST: Exit\n" );
333  return TRUE;
334 }
335 
336 int main(int argc, char *argv[])
337 {
338  GstBus *bus;
339  GstStateChangeReturn ret;
340  gint flags;
341 
342  gst_init(&argc, &argv);
343  GST_DEBUG_CATEGORY_INIT (playbintest, "playbin test", 0, "Debug Category for Playbin Test");
344 
345  GST_FIXME( "Start\n");
346 
347  if (argc > 1)
348  {
349  uri[0] = g_strdup(argv[1]);
350  g_print("Using uri provided in command line : ");
351  }
352  else
353  {
354  uri[0] = DEFAULT_URI;
355  g_print("Using default uri : ");
356  }
357  if (argc > 2)
358  {
359  uri[1] = g_strdup(argv[2]);
360  }
361  else
362  {
363  uri[1] = DEFAULT_URI2;
364  }
365  g_print("uri[0] %s uri[1] %s\n", uri[0], uri[1]);
366 
367  if (NULL != g_getenv("PLAYBINTEST_DEBUG_STATES"))
368  {
369  g_print_states = TRUE;
370  }
371  for(int i = 0; i <PLAYBINTEST_NUMBER_OF_VID; i++)
372  {
373  playbin[i] = gst_element_factory_make("playbin", playbin_names[i]);
374  if (!playbin[i])
375  {
376  g_printerr("playbin couldn't be created.\n");
377  return -1;
378  }
379  g_object_set(playbin[i], "uri", uri[i], NULL);
380 
381  g_object_get(playbin[i], "flags", &flags, NULL);
382  flags |= 0x03 | 0x00000040;
383 #ifdef PLAYBINTEST_BUFFERING
384  flags |= PLAYBINFLAG_BUFFERING;
385  //g_object_set(playbin[i], "buffer-duration", 500*GST_MSECOND, NULL);
386 #endif
387  g_object_set(playbin[i], "flags", flags, NULL);
388 //#define PLAYBINTEST_WESTEROSSINK
389 #ifdef PLAYBINTEST_WESTEROSSINK
390  GstElement* west = gst_element_factory_make("westerossink", NULL);
391  if (!west)
392  {
393  g_printerr("westeros-sink couldn't be created.\n");
394  return -1;
395  }
396  g_object_set(playbin[i], "video-sink", west, NULL);
397 #endif
398 
399  bus = gst_element_get_bus(playbin[i]);
400  gst_bus_add_watch(bus, (GstBusFunc) handle_bus_message, NULL);
401 
402 #ifdef PLAYBINTEST_BUFFERING
403  ret = gst_element_set_state(playbin[i], GST_STATE_PAUSED);
404 #else
405  GST_FIXME( "Setting to Playing State\n");
406  ret = gst_element_set_state(playbin[i], GST_STATE_PLAYING);
407  GST_FIXME( "Set to Playing State\n");
408 #endif
409  if (ret == GST_STATE_CHANGE_FAILURE)
410  {
411  g_printerr("Play failed\n");
412  gst_object_unref(playbin[i]);
413  return -1;
414  }
415  }
416  if(0 != pthread_create(&uiThreadID, NULL, &ui_thread, NULL))
417  {
418  g_printerr("%s:%d: Error at pthread_create", __FUNCTION__, __LINE__); //CID:83354 - checked return
419  }
420  main_loop = g_main_loop_new(NULL, FALSE);
421  g_main_loop_run(main_loop);
422 
423  /* Free resources */
424  g_main_loop_unref(main_loop);
425  gst_object_unref(bus);
426 
427  for(int i = 0; i <PLAYBINTEST_NUMBER_OF_VID; i++)
428  {
429  gst_element_set_state(playbin[i], GST_STATE_NULL);
430  gst_object_unref(playbin[i]);
431  }
432  return 0;
433 }
434 
435 
TRUE
#define TRUE
Defines for TRUE/FALSE/ENABLE flags.
Definition: wifi_common_hal.h:199