2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <Elementary.h>
18 #include <tbm_surface.h>
21 #include <player_internal.h>
23 #include <appcore-efl.h>
25 #include <Ecore_Wayland.h>
27 #define KEY_END "XF86Stop"
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
37 unsigned char sps[100];
38 unsigned char pps[100];
39 unsigned char tmp_buf[1000000];
40 static int sps_len, pps_len;
45 #define PACKAGE "player_es_push_test"
50 #define LOG_TAG "PLAYER_TEST"
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);
58 struct appcore_ops ops = {
60 .terminate = app_terminate,
66 typedef struct appdata {
69 player_h player_handle;
70 media_packet_h video_pkt;
71 media_format_h video_fmt;
73 pthread_t feeding_thread_id;
76 static void win_delete_request_cb(void *data, Evas_Object * obj, void *event_info)
81 static Eina_Bool keydown_cb(void *data, int type, void *event)
83 /* appdata_s *ad = data; */
84 Ecore_Event_Key *ev = event;
88 if (!strcmp(ev->keyname, KEY_END)) {
89 /* Let window go to hide state. */
90 /* elm_win_lower(ad->win); */
94 return ECORE_CALLBACK_DONE;
99 return ECORE_CALLBACK_PASS_ON;
102 static void win_del(void *data, Evas_Object * obj, void *event)
107 static Evas_Object *create_win(const char *name)
109 Evas_Object *eo = NULL;
113 eo = elm_win_add(NULL, name, ELM_WIN_BASIC);
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);
127 static Evas_Object *create_render_rect(Evas_Object * pParent)
132 Evas *pEvas = evas_object_evas_get(pParent);
133 Evas_Object *pObj = evas_object_rectangle_add(pEvas);
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);
146 static void create_base_gui(appdata_s * ad)
148 /* Enable GLES Backened */
149 elm_config_accel_preference_set("opengl");
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);
160 /* Show window after base gui is set up */
161 elm_win_activate(ad->win);
162 evas_object_show(ad->win);
165 static int app_create(void *data)
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;
176 ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, keydown_cb, NULL);
179 ad->file_src = fopen(ES_DEFAULT_H264_VIDEO_PATH, "r");
186 static int app_pause(void *data)
188 /* Take necessary actions when application becomes invisible. */
189 appdata_s *ad = (appdata_s *) data;
190 int ret = PLAYER_ERROR_NONE;
195 LOGE("appdata is NULL");
199 if (ad->player_handle == NULL) {
200 g_print("player_handle is NULL");
204 if (ad->feeding_thread_id) {
205 pthread_join(ad->feeding_thread_id, NULL);
206 ad->feeding_thread_id = 0;
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);
214 ret = player_unprepare(ad->player_handle);
215 if (ret != PLAYER_ERROR_NONE) {
216 g_print("player_unprepare failed : 0x%x", ret);
220 /* unref media format */
222 media_format_unref(ad->video_fmt);
224 fclose(ad->file_src);
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);
233 ad->player_handle = NULL;
240 static int app_resume(void *data)
249 static void _player_prepared_cb(void *user_data)
251 int ret = PLAYER_ERROR_NONE;
252 appdata_s *ad = (appdata_s *) user_data;
256 ret = player_start(ad->player_handle);
257 if (ret != PLAYER_ERROR_NONE)
258 LOGE("player start failed : 0x%x", ret);
263 int bytestream2nalunit(FILE * fd, unsigned char *nal)
268 unsigned char buffer[1000000];
269 unsigned char val, zero_count, i;
270 int nal_unit_type = 0;
277 result = fread(buffer, 1, read_size, fd);
279 if (result != read_size)
284 if ((zero_count == 2 || zero_count == 3) && val == 1)
287 result = fread(buffer, 1, read_size, fd);
289 if (result != read_size)
293 nal[nal_length++] = 0;
294 nal[nal_length++] = 0;
295 nal[nal_length++] = 0;
296 nal[nal_length++] = 1;
303 result = fread(buffer, 1, read_size, fd);
304 if (result != read_size) {
312 nal_unit_type = val & 0xf;
318 if ((zero_count == 2 || zero_count == 3 || zero_count == 4) && (val == 1)) {
321 for (i = 0; i < zero_count; i++)
322 nal[nal_length++] = 0;
323 nal[nal_length++] = val;
329 fseek(fd, -(zero_count + 1), SEEK_CUR);
331 if (nal_unit_type == 0x7) {
332 sps_len = nal_length;
333 memcpy(sps, nal, nal_length);
335 } else if (nal_unit_type == 0x8) {
336 pps_len = nal_length;
337 memcpy(pps, nal, nal_length);
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;
350 static void feed_eos_data(appdata_s * appdata)
352 appdata_s *ad = appdata;
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");
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");
365 media_packet_destroy(ad->video_pkt);
366 ad->video_pkt = NULL;
371 static bool feed_video_data(appdata_s * appdata)
375 static guint64 pts = 0L;
376 void *buf_data_ptr = NULL;
377 appdata_s *ad = appdata;
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");
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");
389 if (media_packet_set_pts(ad->video_pkt, (uint64_t) pts) != MEDIA_PACKET_ERROR_NONE) {
390 LOGE("media_packet_set_pts failed\n");
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).
397 read = bytestream2nalunit(ad->file_src, buf_data_ptr);
398 LOGD("real length = %d\n", read);
400 LOGE("input file read failed\n");
403 } else if (read < 0) {
405 media_packet_destroy(ad->video_pkt);
406 ad->video_pkt = NULL;
408 if (media_packet_create(ad->video_fmt, NULL, NULL, &ad->video_pkt) != MEDIA_PACKET_ERROR_NONE) {
409 LOGE("media_packet_create failed\n");
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");
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");
423 /* push media packet */
424 player_push_media_stream(ad->player_handle, ad->video_pkt);
425 pts += ES_DEFAULT_VIDEO_PTS_OFFSET;
429 /* destroy media packet after use */
430 media_packet_destroy(ad->video_pkt);
431 ad->video_pkt = NULL;
435 static void feed_video_data_thread_func(void *data)
437 appdata_s *ad = (appdata_s *) data;
440 static int frame_count = 0;
441 if (frame_count < ES_DEFAULT_NUMBER_OF_FEED) {
442 if (!feed_video_data(ad))
452 void _video_buffer_status_cb_ex(player_media_stream_buffer_status_e status, unsigned long long bytes, void *user_data)
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);
460 void _audio_buffer_status_cb_ex(player_media_stream_buffer_status_e status, unsigned long long bytes, void *user_data)
462 if (status == PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN)
463 LOGE("audio buffer is underrun state, current level byte = %llu", bytes);
464 else if (status == PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW)
465 LOGE("audio buffer is overrun state, current level byte = %llu", bytes);
468 void _video_seek_data_cb(unsigned long long offset, void *user_data)
470 LOGE("seek offset of video is %llu", offset);
473 void _audio_seek_data_cb(unsigned long long offset, void *user_data)
475 LOGE("seek offset of audio is %llu", offset);
478 static int app_reset(bundle * b, void *data)
480 /* Take necessary actions when application becomes visible. */
481 appdata_s *ad = (appdata_s *) data;
482 int ret = PLAYER_ERROR_NONE;
487 LOGE("appdata is NULL");
491 ret = player_create(&ad->player_handle);
492 if (ret != PLAYER_ERROR_NONE) {
493 LOGE("player_create failed : 0x%x", ret);
497 ret = player_set_display(ad->player_handle, PLAYER_DISPLAY_TYPE_OVERLAY, GET_DISPLAY(ad->win));
498 if (ret != PLAYER_ERROR_NONE) {
499 LOGE("player_set_display failed : 0x%x", ret);
503 /* get media format format */
504 ret = media_format_create(&ad->video_fmt);
505 if (ret != MEDIA_FORMAT_ERROR_NONE) {
506 LOGE("media_format_create : 0x%x", ret);
510 /* set video format */
511 media_format_set_video_mime(ad->video_fmt, ES_DEFAULT_VIDEO_FORMAT_TYPE);
512 media_format_set_video_width(ad->video_fmt, ES_DEFAULT_VIDEO_FORMAT_WIDTH);
513 media_format_set_video_height(ad->video_fmt, ES_DEFAULT_VIDEO_FORMAT_HEIGHT);
515 player_set_media_stream_buffer_max_size(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, (unsigned long long)3 * 1024 * 1024);
516 player_set_media_stream_buffer_min_threshold(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, 50);
518 ret = player_set_media_stream_buffer_status_cb_ex(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, _video_buffer_status_cb_ex, (void *)ad);
519 if (ret != PLAYER_ERROR_NONE) {
520 LOGE("player set video buffer status cb failed : 0x%x", ret);
523 ret = player_set_media_stream_buffer_status_cb_ex(ad->player_handle, PLAYER_STREAM_TYPE_AUDIO, _audio_buffer_status_cb_ex, (void *)ad);
524 if (ret != PLAYER_ERROR_NONE) {
525 LOGE("player set audio buffer status cb failed : 0x%x", ret);
529 ret = player_set_media_stream_seek_cb(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, _video_seek_data_cb, (void *)ad);
530 if (ret != PLAYER_ERROR_NONE) {
531 LOGE("player set seek data cb for video failed : 0x%x", ret);
534 ret = player_set_media_stream_seek_cb(ad->player_handle, PLAYER_STREAM_TYPE_AUDIO, _audio_seek_data_cb, (void *)ad);
535 if (ret != PLAYER_ERROR_NONE) {
536 LOGE("player set seek data cb for audio failed : 0x%x", ret);
540 /* send media packet to player */
541 player_set_media_stream_info(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, ad->video_fmt);
543 ret = player_prepare_async(ad->player_handle, _player_prepared_cb, (void *)ad);
544 if (ret != PLAYER_ERROR_NONE) {
545 LOGE("player prepare failed : 0x%x", ret);
549 pthread_create(&ad->feeding_thread_id, NULL, (void *)feed_video_data_thread_func, (void *)ad);
556 if (ad->player_handle) {
557 player_destroy(ad->player_handle);
558 ad->player_handle = NULL;
564 static int app_terminate(void *data)
566 /* Release all resources. */
567 appdata_s *ad = (appdata_s *) data;
572 LOGE("appdata is NULL");
583 int main(int argc, char *argv[])
586 static appdata_s ad = { 0, };
590 memset(&ad, 0x0, sizeof(appdata_s));
592 LOGD("call appcore_efl_main");
596 ret = appcore_efl_main(PACKAGE, &argc, &argv, &ops);
598 LOGD("appcore_efl_main() ret = 0x%x", ret);