[player_test] set accel engine to opengl for evas
[platform/core/api/player.git] / test / player_es_push_test.c
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <Elementary.h>
18 #include <tbm_surface.h>
19 #include <dlog.h>
20 #include <player.h>
21 #include <player_internal.h>
22 #include <glib.h>
23 #include <appcore-efl.h>
24 #ifdef HAVE_WAYLAND
25 #include <Ecore.h>
26 #include <Ecore_Wayland.h>
27 #endif
28
29 #define KEY_END "XF86Stop"
30
31 #define ES_DEFAULT_DIR_PATH                     "/home/owner/content/"
32 #define ES_DEFAULT_H264_VIDEO_PATH              ES_DEFAULT_DIR_PATH"Simpsons.h264"
33 #define ES_DEFAULT_VIDEO_FORMAT_TYPE    MEDIA_FORMAT_H264_SP
34 #define ES_DEFAULT_VIDEO_FORMAT_WIDTH   1280
35 #define ES_DEFAULT_VIDEO_FORMAT_HEIGHT 544
36 #define ES_DEFAULT_VIDEO_PTS_OFFSET     20000000
37 #define ES_DEFAULT_NUMBER_OF_FEED               2000
38
39 unsigned char sps[100];
40 unsigned char pps[100];
41 unsigned char tmp_buf[1000000];
42 static int sps_len, pps_len;
43
44 #ifdef PACKAGE
45 #undef PACKAGE
46 #endif
47 #define PACKAGE "player_es_push_test"
48
49 #ifdef LOG_TAG
50 #undef LOG_TAG
51 #endif
52 #define LOG_TAG "PLAYER_TEST"
53
54 static int app_create(void *data);
55 static int app_reset(bundle *b, void *data);
56 static int app_resume(void *data);
57 static int app_pause(void *data);
58 static int app_terminate(void *data);
59
60 struct appcore_ops ops = {
61         .create = app_create,
62         .terminate = app_terminate,
63         .pause = app_pause,
64         .resume = app_resume,
65         .reset = app_reset,
66 };
67
68 typedef struct appdata {
69         Evas_Object *win;
70         Evas_Object *rect;
71         player_h player_handle;
72         media_packet_h video_pkt;
73         media_format_h video_fmt;
74         FILE *file_src;
75         pthread_t feeding_thread_id;
76 } appdata_s;
77
78 static void win_delete_request_cb(void *data, Evas_Object *obj, void *event_info)
79 {
80         elm_exit();
81 }
82
83 static Eina_Bool keydown_cb(void *data, int type, void *event)
84 {
85         /* appdata_s *ad = data; */
86         Ecore_Event_Key *ev = event;
87
88         LOGD("start");
89
90         if (!strcmp(ev->keyname, KEY_END)) {
91                 /* Let window go to hide state. */
92                 /* elm_win_lower(ad->win); */
93                 LOGD("elm exit");
94                 elm_exit();
95
96                 return ECORE_CALLBACK_DONE;
97         }
98
99         LOGD("done");
100
101         return ECORE_CALLBACK_PASS_ON;
102 }
103
104 static void win_del(void *data, Evas_Object *obj, void *event)
105 {
106         elm_exit();
107 }
108
109 static Evas_Object *create_win(const char *name)
110 {
111         Evas_Object *eo = NULL;
112         int w = 0;
113         int h = 0;
114
115         eo = elm_win_add(NULL, name, ELM_WIN_BASIC);
116         if (eo) {
117                 elm_win_title_set(eo, name);
118                 elm_win_borderless_set(eo, EINA_TRUE);
119                 evas_object_smart_callback_add(eo, "delete,request", win_del, NULL);
120                 elm_win_screen_size_get(eo, NULL, NULL, &w, &h);
121                 g_print("window size :%d,%d", w, h);
122                 evas_object_resize(eo, w, h);
123                 elm_win_autodel_set(eo, EINA_TRUE);
124 #ifdef HAVE_WAYLAND
125                 elm_win_alpha_set(eo, EINA_TRUE);
126 #endif
127         }
128         return eo;
129 }
130
131 static Evas_Object *create_render_rect(Evas_Object *pParent)
132 {
133         if (!pParent)
134                 return NULL;
135
136         Evas *pEvas = evas_object_evas_get(pParent);
137         Evas_Object *pObj = evas_object_rectangle_add(pEvas);
138         if (pObj == NULL)
139                 return NULL;
140
141         evas_object_size_hint_weight_set(pObj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
142         evas_object_color_set(pObj, 0, 0, 0, 0);
143         evas_object_render_op_set(pObj, EVAS_RENDER_COPY);
144         evas_object_show(pObj);
145         elm_win_resize_object_add(pParent, pObj);
146
147         return pObj;
148 }
149
150 static void create_base_gui(appdata_s *ad)
151 {
152         /* Enable GLES Backened */
153         elm_config_accel_preference_set("opengl");
154
155         /* Window */
156         /* elm_win_util_standard_add(PACKAGE, PACKAGE); */
157         ad->win = create_win(PACKAGE);
158         ad->rect = create_render_rect(ad->win);
159         /* This is not supported in 3.0
160            elm_win_wm_desktop_layout_support_set(ad->win, EINA_TRUE); */
161         elm_win_autodel_set(ad->win, EINA_TRUE);
162         evas_object_smart_callback_add(ad->win, "delete,request", win_delete_request_cb, ad);
163
164         /* Show window after base gui is set up */
165         elm_win_activate(ad->win);
166         evas_object_show(ad->win);
167 }
168
169 static int app_create(void *data)
170 {
171         /* Hook to take necessary actions before main event loop starts
172            Initialize UI resources and application's data
173            If this function returns true, the main loop of application starts
174            If this function returns false, the application is terminated */
175         appdata_s *ad = data;
176
177         LOGD("start");
178
179         create_base_gui(ad);
180         ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, keydown_cb, NULL);
181
182         /* open test file */
183         ad->file_src = fopen(ES_DEFAULT_H264_VIDEO_PATH, "r");
184
185         LOGD("done");
186
187         return 0;
188 }
189
190 static int app_pause(void *data)
191 {
192         /* Take necessary actions when application becomes invisible. */
193         appdata_s *ad = (appdata_s *)data;
194         int ret = PLAYER_ERROR_NONE;
195
196         LOGD("start");
197
198         if (ad == NULL) {
199                 LOGE("appdata is NULL");
200                 return -1;
201         }
202
203         if (ad->player_handle == NULL) {
204                 g_print("player_handle is NULL");
205                 return -1;
206         }
207
208         if (ad->feeding_thread_id) {
209                 pthread_join(ad->feeding_thread_id, NULL);
210                 ad->feeding_thread_id = 0;
211         }
212
213         player_unset_media_stream_buffer_status_cb_ex(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO);
214         player_unset_media_stream_buffer_status_cb_ex(ad->player_handle, PLAYER_STREAM_TYPE_AUDIO);
215         player_unset_media_stream_seek_cb(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO);
216         player_unset_media_stream_seek_cb(ad->player_handle, PLAYER_STREAM_TYPE_AUDIO);
217
218         ret = player_unprepare(ad->player_handle);
219         if (ret != PLAYER_ERROR_NONE) {
220                 g_print("player_unprepare failed : 0x%x", ret);
221                 return false;
222         }
223
224         /* unref media format */
225         if (ad->video_fmt)
226                 media_format_unref(ad->video_fmt);
227
228         fclose(ad->file_src);
229
230         /* destroy player handle */
231         ret = player_destroy(ad->player_handle);
232         if (ret != PLAYER_ERROR_NONE) {
233                 g_print("player_destroy failed : 0x%x", ret);
234                 return false;
235         }
236
237         ad->player_handle = NULL;
238
239         LOGD("done");
240
241         return 0;
242 }
243
244 static int app_resume(void *data)
245 {
246         LOGD("start");
247
248         LOGD("done");
249
250         return 0;
251 }
252
253 static void _player_prepared_cb(void *user_data)
254 {
255         int ret = PLAYER_ERROR_NONE;
256         appdata_s *ad = (appdata_s *)user_data;
257
258         LOGD("prepared");
259
260         ret = player_start(ad->player_handle);
261         if (ret != PLAYER_ERROR_NONE)
262                 LOGE("player start failed : 0x%x", ret);
263
264         LOGD("done");
265 }
266
267 int bytestream2nalunit(FILE * fd, unsigned char *nal)
268 {
269         int nal_length = 0;
270         size_t result;
271         int read_size = 1;
272         unsigned char buffer[1000000];
273         unsigned char val, zero_count, i;
274         int nal_unit_type = 0;
275         int init;
276
277         zero_count = 0;
278         if (feof(fd))
279                 return -1;
280
281         result = fread(buffer, 1, read_size, fd);
282
283         if (result != read_size)
284         return -1;
285
286         val = buffer[0];
287         while (!val) {
288                 if ((zero_count == 2 || zero_count == 3) && val == 1)
289                         break;
290                 zero_count++;
291                 result = fread(buffer, 1, read_size, fd);
292
293                 if (result != read_size)
294                         break;
295                 val = buffer[0];
296         }
297         nal[nal_length++] = 0;
298         nal[nal_length++] = 0;
299         nal[nal_length++] = 0;
300         nal[nal_length++] = 1;
301         zero_count = 0;
302         init = 1;
303         while (1) {
304                 if (feof(fd))
305                         return -1;
306
307                 result = fread(buffer, 1, read_size, fd);
308                 if (result != read_size) {
309                         if (init == 1)
310                                 return -1;
311                         break;
312                 }
313                 val = buffer[0];
314
315                 if (init) {
316                         nal_unit_type = val & 0xf;
317                         init = 0;
318                 }
319                 if (!val) {
320                         zero_count++;
321                 } else {
322                         if ((zero_count == 2 || zero_count == 3 || zero_count == 4) && (val == 1)) {
323                                 break;
324                         } else {
325                                 for (i = 0; i < zero_count; i++)
326                                         nal[nal_length++] = 0;
327                                 nal[nal_length++] = val;
328                                 zero_count = 0;
329                         }
330                 }
331         }
332
333         fseek(fd, -(zero_count + 1), SEEK_CUR);
334
335         if (nal_unit_type == 0x7) {
336                 sps_len = nal_length;
337                 memcpy(sps, nal, nal_length);
338                 return 0;
339         } else if (nal_unit_type == 0x8) {
340                 pps_len = nal_length;
341                 memcpy(pps, nal, nal_length);
342                 return 0;
343         } else if (nal_unit_type == 0x5) {
344                 memcpy(tmp_buf, nal, nal_length);
345                 memcpy(nal, sps, sps_len);
346                 memcpy(nal + sps_len, pps, pps_len);
347                 memcpy(nal + sps_len + pps_len, tmp_buf, nal_length);
348                 nal_length += sps_len + pps_len;
349         }
350
351         return nal_length;
352 }
353
354 static void feed_eos_data(appdata_s *appdata)
355 {
356         appdata_s *ad = appdata;
357
358         LOGD("push EOS");
359
360         if (media_packet_create(ad->video_fmt, NULL, NULL, &ad->video_pkt) != MEDIA_PACKET_ERROR_NONE) {
361                 LOGE("media_packet_create_alloc failed\n");
362                 return;
363         }
364
365         media_packet_set_flags(ad->video_pkt, MEDIA_PACKET_END_OF_STREAM);
366         if (player_push_media_stream(ad->player_handle, ad->video_pkt) != PLAYER_ERROR_NONE)
367                 LOGE("fail to push media packet\n");
368
369         media_packet_destroy(ad->video_pkt);
370         ad->video_pkt = NULL;
371
372         return;
373 }
374
375 static bool feed_video_data(appdata_s *appdata)
376 {
377         bool ret = FALSE;
378         int read = 0;
379         static guint64 pts = 0L;
380         void *buf_data_ptr = NULL;
381         appdata_s *ad = appdata;
382
383         if (media_packet_create_alloc(ad->video_fmt, NULL, NULL, &ad->video_pkt) != MEDIA_PACKET_ERROR_NONE) {
384                 LOGE("media_packet_create_alloc failed\n");
385                 return FALSE;
386         }
387
388         if (media_packet_get_buffer_data_ptr(ad->video_pkt, &buf_data_ptr) != MEDIA_PACKET_ERROR_NONE) {
389                 LOGE("media_packet_get_buffer_data_ptr failed\n");
390                 goto ERROR;
391         }
392
393         if (media_packet_set_pts(ad->video_pkt, (uint64_t)pts) != MEDIA_PACKET_ERROR_NONE) {
394                 LOGE("media_packet_set_pts failed\n");
395                 goto ERROR;
396         }
397
398         /* NOTE: In case of H.264 video, stream format for feeding is NAL unit.
399          * And, SPS(0x67) and PPS(0x68) should be located before IDR.(0x65).
400          */
401         read = bytestream2nalunit(ad->file_src, buf_data_ptr);
402         LOGD("real length = %d\n", read);
403         if (read == 0) {
404                 LOGE("input file read failed\n");
405                 ret = TRUE;
406                 goto ERROR;
407         } else if (read < 0) {
408                 LOGD("push EOS");
409                 media_packet_destroy(ad->video_pkt);
410                 ad->video_pkt = NULL;
411
412                 if (media_packet_create(ad->video_fmt, NULL, NULL, &ad->video_pkt) != MEDIA_PACKET_ERROR_NONE) {
413                         LOGE("media_packet_create failed\n");
414                         goto ERROR;
415                 }
416                 media_packet_set_flags(ad->video_pkt, MEDIA_PACKET_END_OF_STREAM);
417                 if (player_push_media_stream(ad->player_handle, ad->video_pkt) != PLAYER_ERROR_NONE)
418                         LOGE("fail to push media packet\n");
419                 goto ERROR;
420         }
421
422         if (media_packet_set_buffer_size(ad->video_pkt, (uint64_t)read) != MEDIA_PACKET_ERROR_NONE) {
423                 LOGE("media_packet_set_buffer_size failed\n");
424                 goto ERROR;
425         }
426
427         /* push media packet */
428         player_push_media_stream(ad->player_handle, ad->video_pkt);
429         pts += ES_DEFAULT_VIDEO_PTS_OFFSET;
430         ret = TRUE;
431
432 ERROR:
433         /* destroy media packet after use */
434         media_packet_destroy(ad->video_pkt);
435         ad->video_pkt = NULL;
436         return ret;
437 }
438
439 static void feed_video_data_thread_func(void *data)
440 {
441         appdata_s *ad = (appdata_s *)data;
442
443         while (TRUE) {
444                 static int frame_count = 0;
445                 if (frame_count < ES_DEFAULT_NUMBER_OF_FEED) {
446                         if (!feed_video_data(ad))
447                                 break;
448                         frame_count++;
449                 } else {
450                         feed_eos_data(ad);
451                         break;
452                 }
453         }
454 }
455
456 void _video_buffer_status_cb_ex(player_media_stream_buffer_status_e status, unsigned long long bytes, void *user_data)
457 {
458         if (status == PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN) {
459                 LOGE("video buffer is underrun state, current level byte = %llu", bytes);
460         }
461         else if (status == PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW) {
462                 LOGE("video buffer is overrun state, current level byte = %llu", bytes);
463         }
464 }
465
466 void _audio_buffer_status_cb_ex(player_media_stream_buffer_status_e status, unsigned long long bytes, void *user_data)
467 {
468         if (status == PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN) {
469                 LOGE("audio buffer is underrun state, current level byte = %llu", bytes);
470         }
471         else if (status == PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW) {
472                 LOGE("audio buffer is overrun state, current level byte = %llu", bytes);
473         }
474 }
475
476 void _video_seek_data_cb(unsigned long long offset, void *user_data)
477 {
478         LOGE("seek offset of video is %llu", offset);
479 }
480
481 void _audio_seek_data_cb(unsigned long long offset, void *user_data)
482 {
483         LOGE("seek offset of audio is %llu", offset);
484 }
485
486 static int app_reset(bundle *b, void *data)
487 {
488         /* Take necessary actions when application becomes visible. */
489         appdata_s *ad = (appdata_s *)data;
490         int ret = PLAYER_ERROR_NONE;
491
492         LOGD("start");
493
494         if (ad == NULL) {
495                 LOGE("appdata is NULL");
496                 return -1;
497         }
498
499         ret = player_create(&ad->player_handle);
500         if (ret != PLAYER_ERROR_NONE) {
501                 LOGE("player_create failed : 0x%x", ret);
502                 return -1;
503         }
504
505         ret = player_set_display(ad->player_handle, PLAYER_DISPLAY_TYPE_OVERLAY, GET_DISPLAY(ad->win));
506         if (ret != PLAYER_ERROR_NONE) {
507                 LOGE("player_set_display failed : 0x%x", ret);
508                 goto FAILED;
509         }
510
511         /* get media format format */
512         ret = media_format_create(&ad->video_fmt);
513         if (ret != MEDIA_FORMAT_ERROR_NONE) {
514                 LOGE("media_format_create : 0x%x", ret);
515                 goto FAILED;
516         }
517
518         /* set video format */
519         media_format_set_video_mime(ad->video_fmt, ES_DEFAULT_VIDEO_FORMAT_TYPE);
520         media_format_set_video_width(ad->video_fmt, ES_DEFAULT_VIDEO_FORMAT_WIDTH);
521         media_format_set_video_height(ad->video_fmt, ES_DEFAULT_VIDEO_FORMAT_HEIGHT);
522
523         player_set_media_stream_buffer_max_size(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, (unsigned long long)3*1024*1024);
524         player_set_media_stream_buffer_min_threshold(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, 50);
525
526         ret = player_set_media_stream_buffer_status_cb_ex(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, _video_buffer_status_cb_ex, (void *)ad);
527         if (ret != PLAYER_ERROR_NONE) {
528                 LOGE("player set video buffer status cb failed : 0x%x", ret);
529                 goto FAILED;
530         }
531         ret = player_set_media_stream_buffer_status_cb_ex(ad->player_handle, PLAYER_STREAM_TYPE_AUDIO, _audio_buffer_status_cb_ex, (void *)ad);
532         if (ret != PLAYER_ERROR_NONE) {
533                 LOGE("player set audio buffer status cb failed : 0x%x", ret);
534                 goto FAILED;
535         }
536
537         ret = player_set_media_stream_seek_cb(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, _video_seek_data_cb, (void *)ad);
538         if (ret != PLAYER_ERROR_NONE) {
539                 LOGE("player set seek data cb for video failed : 0x%x", ret);
540                 goto FAILED;
541         }
542         ret = player_set_media_stream_seek_cb(ad->player_handle, PLAYER_STREAM_TYPE_AUDIO, _audio_seek_data_cb, (void *)ad);
543         if (ret != PLAYER_ERROR_NONE) {
544                 LOGE("player set seek data cb for audio failed : 0x%x", ret);
545                 goto FAILED;
546         }
547
548         /* send media packet to player */
549         player_set_media_stream_info(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, ad->video_fmt);
550
551         ret = player_prepare_async(ad->player_handle, _player_prepared_cb, (void *)ad);
552         if (ret != PLAYER_ERROR_NONE) {
553                 LOGE("player prepare failed : 0x%x", ret);
554                 goto FAILED;
555         }
556
557         pthread_create(&ad->feeding_thread_id, NULL, (void *)feed_video_data_thread_func, (void *)ad);
558
559         LOGD("done");
560
561         return 0;
562
563 FAILED:
564         if (ad->player_handle) {
565                 player_destroy(ad->player_handle);
566                 ad->player_handle = NULL;
567         }
568
569         return -1;
570 }
571
572 static int app_terminate(void *data)
573 {
574         /* Release all resources. */
575         appdata_s *ad = (appdata_s *)data;
576
577         LOGD("start");
578
579         if (ad == NULL) {
580                 LOGE("appdata is NULL");
581                 return -1;
582         }
583
584         app_pause(data);
585
586         LOGD("done");
587
588         return 0;
589 }
590
591 int main(int argc, char *argv[])
592 {
593         int ret = 0;
594         static appdata_s ad = {0, };
595
596         LOGD("start");
597
598         memset(&ad, 0x0, sizeof(appdata_s));
599
600         LOGD("call appcore_efl_main");
601
602         ops.data = &ad;
603
604         ret = appcore_efl_main(PACKAGE, &argc, &argv, &ops);
605
606         LOGD("appcore_efl_main() ret = 0x%x", ret);
607
608         return ret;
609 }