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