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>
22 #include <appcore-efl.h>
24 #define KEY_END "XF86Stop"
25 #define MEDIA_FILE_PATH "/home/owner/content/Color.mp4"
29 #define PACKAGE "player_test"
34 #define LOG_TAG "PLAYER_TEST"
36 static int app_create(void *data);
37 static int app_reset(bundle *b, void *data);
38 static int app_resume(void *data);
39 static int app_pause(void *data);
40 static int app_terminate(void *data);
42 struct appcore_ops ops = {
44 .terminate = app_terminate,
50 typedef struct appdata {
53 media_packet_h packet;
55 player_h player_handle;
61 static void win_delete_request_cb(void *data, Evas_Object *obj, void *event_info)
66 static Eina_Bool keydown_cb(void *data, int type, void *event)
68 /* appdata_s *ad = data; */
69 Ecore_Event_Key *ev = event;
73 if (!strcmp(ev->keyname, KEY_END)) {
74 /* Let window go to hide state. */
75 /* elm_win_lower(ad->win); */
79 return ECORE_CALLBACK_DONE;
84 return ECORE_CALLBACK_PASS_ON;
87 static void create_base_gui(appdata_s *ad)
89 /* Enable GLES Backend */
90 elm_config_accel_preference_set("opengl");
93 ad->win = elm_win_util_standard_add(PACKAGE, PACKAGE);
94 /* This is not supported in 3.0
95 elm_win_wm_desktop_layout_support_set(ad->win, EINA_TRUE); */
96 elm_win_autodel_set(ad->win, EINA_TRUE);
98 if (elm_win_wm_rotation_supported_get(ad->win)) {
99 int rots[4] = { 0, 90, 180, 270 };
100 elm_win_wm_rotation_available_rotations_set(ad->win, (const int *)(&rots), 4);
103 evas_object_smart_callback_add(ad->win, "delete,request", win_delete_request_cb, ad);
105 Evas *e = evas_object_evas_get(ad->win);
107 elm_win_screen_size_get(ad->win, NULL, NULL, &ad->w, &ad->h);
108 LOGD("surface size (%d x %d)\n", ad->w, ad->h);
111 ad->img = evas_object_image_filled_add(e);
112 evas_object_image_size_set(ad->img, ad->w, ad->h);
113 evas_object_size_hint_weight_set(ad->img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
114 evas_object_show(ad->img);
116 elm_win_resize_object_add(ad->win, ad->img);
118 /* Show window after base gui is set up */
119 evas_object_show(ad->win);
122 static void _media_packet_video_decoded_cb(media_packet_h packet, void *user_data)
124 /* This callback function would be called on different thread */
125 appdata_s *ad = user_data;
128 LOGE("appdata is NULL");
132 g_mutex_lock(&ad->buffer_lock);
134 if (ad->pipe == NULL) {
135 media_packet_destroy(packet);
136 LOGW("release media packet immediately");
137 g_mutex_unlock(&ad->buffer_lock);
141 /* add packet list */
142 ad->packet_list = g_list_prepend(ad->packet_list, (gpointer)packet);
144 LOGD("packet %p", packet);
146 /* Send packet to main thread */
147 ecore_pipe_write(ad->pipe, &packet, sizeof(media_packet_h));
149 g_mutex_unlock(&ad->buffer_lock);
154 static void pipe_cb(void *data, void *buf, unsigned int len)
156 /* Now, we get a player surface to be set here. */
157 appdata_s *ad = data;
158 tbm_surface_h surface;
159 #ifdef _CAN_USE_NATIVE_SURFACE_TBM
160 Evas_Native_Surface surf;
162 tbm_surface_info_s suf_info;
165 GList *last_item = NULL;
169 g_mutex_lock(&ad->buffer_lock);
171 /* Destroy previous packet */
173 ret = media_packet_destroy(ad->packet);
174 if (ret != MEDIA_PACKET_ERROR_NONE)
175 LOGE("Failed to destroy media packet. ret (%d)", ret);
179 /* remove packet from list */
180 last_item = g_list_last(ad->packet_list);
183 ad->packet = (media_packet_h)last_item->data;;
184 ad->packet_list = g_list_remove(ad->packet_list, ad->packet);
185 LOGD("ad->packet %p", ad->packet);
188 if (ad->packet == NULL) {
190 g_mutex_unlock(&ad->buffer_lock);
194 ret = media_packet_get_tbm_surface(ad->packet, &surface);
195 if (ret != MEDIA_PACKET_ERROR_NONE) {
196 LOGE("Failed to get surface from media packet. ret(0x%x)", ret);
198 media_packet_destroy(ad->packet);
201 g_mutex_unlock(&ad->buffer_lock);
206 LOGD("surface %p", surface);
208 g_mutex_unlock(&ad->buffer_lock);
210 #ifdef _CAN_USE_NATIVE_SURFACE_TBM
211 /* Set tbm surface to image native surface */
212 memset(&surf, 0x0, sizeof(surf));
213 surf.version = EVAS_NATIVE_SURFACE_VERSION;
214 surf.type = EVAS_NATIVE_SURFACE_TBM;
215 surf.data.tizen.buffer = surface;
216 surf.data.tizen.rot = 270;
217 evas_object_image_native_surface_set(ad->img, &surf);
219 /* Set dirty image region to be redrawn */
220 evas_object_image_data_update_add(ad->img, 0, 0, ad->w, ad->h);
222 unsigned char *ptr = NULL;
223 unsigned char *buf_data = NULL;
224 media_format_h format = NULL;
225 media_format_mimetype_e mimetype;
227 media_packet_get_format(ad->packet, &format);
228 media_format_get_video_info(format, &mimetype, NULL, NULL, NULL, NULL);
229 media_format_unref(format);
231 if (mimetype == MEDIA_FORMAT_I420 || mimetype == MEDIA_FORMAT_NV12 || mimetype == MEDIA_FORMAT_NV12T) {
233 tbm_surface_get_info(surface, &suf_info);
234 buf_data = (unsigned char *)g_malloc0(suf_info.size);
236 LOGE("no free space");
241 for (plane_idx = 0; plane_idx < suf_info.num_planes; plane_idx++) {
242 memcpy(ptr, suf_info.planes[plane_idx].ptr, suf_info.planes[plane_idx].size);
243 ptr += suf_info.planes[plane_idx].size;
245 /* dump buf data here, if needed */
255 static int app_create(void *data)
257 /* Hook to take necessary actions before main event loop starts
258 Initialize UI resources and application's data
259 If this function returns true, the main loop of application starts
260 If this function returns false, the application is terminated */
261 appdata_s *ad = data;
266 ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, keydown_cb, NULL);
268 g_mutex_init(&ad->buffer_lock);
275 static int app_pause(void *data)
277 /* Take necessary actions when application becomes invisible. */
278 appdata_s *ad = (appdata_s *)data;
280 media_packet_h packet = NULL;
281 int ret = PLAYER_ERROR_NONE;
286 LOGE("appdata is NULL");
290 if (ad->player_handle == NULL) {
291 g_print("player_handle is NULL");
295 /* stop render last set frame */
296 evas_object_image_native_surface_set(ad->img, NULL);
298 g_mutex_lock(&ad->buffer_lock);
300 /* remove ecore pipe */
301 ecore_pipe_del(ad->pipe);
304 /* remove packet list */
305 list = ad->packet_list;
308 list = g_list_next(list);
311 LOGW("packet is NULL");
313 LOGD("destroy packet %p", packet);
314 media_packet_destroy(packet);
316 ad->packet_list = g_list_remove(ad->packet_list, packet);
320 if (ad->packet_list) {
321 g_list_free(ad->packet_list);
322 ad->packet_list = NULL;
325 /* Destroy previous packet */
327 LOGD("destroy packet %p", ad->packet);
328 ret = media_packet_destroy(ad->packet);
329 if (ret != MEDIA_PACKET_ERROR_NONE)
330 LOGE("Failed to destroy media packet. ret (%d)", ret);
334 g_mutex_unlock(&ad->buffer_lock);
336 ret = player_unset_media_packet_video_frame_decoded_cb(ad->player_handle);
337 if (ret != PLAYER_ERROR_NONE) {
338 g_print("player_unset_media_packet_video_frame_decoded_cb failed : 0x%x", ret);
342 ret = player_unprepare(ad->player_handle);
343 if (ret != PLAYER_ERROR_NONE) {
344 g_print("player_unprepare failed : 0x%x", ret);
348 ret = player_destroy(ad->player_handle);
349 if (ret != PLAYER_ERROR_NONE) {
350 g_print("player_destroy failed : 0x%x", ret);
354 ad->player_handle = NULL;
361 static int app_resume(void *data)
370 static int app_reset(bundle *b, void *data)
372 /* Take necessary actions when application becomes visible. */
373 appdata_s *ad = (appdata_s *)data;
374 int ret = PLAYER_ERROR_NONE;
379 LOGE("appdata is NULL");
383 /* create ecore pipe */
384 ad->pipe = ecore_pipe_add(pipe_cb, ad);
386 ret = player_create(&ad->player_handle);
387 if (ret != PLAYER_ERROR_NONE) {
388 LOGE("player_create failed : 0x%x", ret);
392 ret = player_set_media_packet_video_frame_decoded_cb(ad->player_handle, _media_packet_video_decoded_cb, ad);
393 if (ret != PLAYER_ERROR_NONE) {
394 LOGE("player_set_media_packet_video_frame_decoded_cb failed : 0x%x", ret);
398 ret = player_set_display(ad->player_handle, PLAYER_DISPLAY_TYPE_NONE, NULL);
399 if (ret != PLAYER_ERROR_NONE) {
400 LOGE("player_set_display failed : 0x%x", ret);
404 ret = player_set_uri(ad->player_handle, MEDIA_FILE_PATH);
405 if (ret != PLAYER_ERROR_NONE) {
406 LOGE("player_set_uri failed : 0x%x", ret);
410 ret = player_prepare(ad->player_handle);
411 if (ret != PLAYER_ERROR_NONE) {
412 LOGE("player prepare failed : 0x%x", ret);
416 ret = player_start(ad->player_handle);
417 if (ret != PLAYER_ERROR_NONE) {
418 LOGE("player start failed : 0x%x", ret);
427 if (ad->player_handle) {
428 player_destroy(ad->player_handle);
429 ad->player_handle = NULL;
436 static int app_terminate(void *data)
438 /* Release all resources. */
439 appdata_s *ad = (appdata_s *)data;
444 LOGE("appdata is NULL");
450 g_mutex_clear(&ad->buffer_lock);
457 int main(int argc, char *argv[])
460 static appdata_s ad = {0, };
464 memset(&ad, 0x0, sizeof(appdata_s));
466 LOGD("call appcore_efl_main");
470 ret = appcore_efl_main(PACKAGE, &argc, &argv, &ops);
472 LOGD("appcore_efl_main() ret = 0x%x", ret);