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