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>
26 #include <Ecore_Wayland.h>
29 #define KEY_END "XF86Stop"
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
39 unsigned char sps[100];
40 unsigned char pps[100];
41 unsigned char tmp_buf[1000000];
42 static int sps_len, pps_len;
47 #define PACKAGE "player_es_push_test"
52 #define LOG_TAG "PLAYER_TEST"
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);
60 struct appcore_ops ops = {
62 .terminate = app_terminate,
68 typedef struct appdata {
71 player_h player_handle;
72 media_packet_h video_pkt;
73 media_format_h video_fmt;
75 pthread_t feeding_thread_id;
78 static void win_delete_request_cb(void *data, Evas_Object *obj, void *event_info)
83 static Eina_Bool keydown_cb(void *data, int type, void *event)
85 /* appdata_s *ad = data; */
86 Ecore_Event_Key *ev = event;
90 if (!strcmp(ev->keyname, KEY_END)) {
91 /* Let window go to hide state. */
92 /* elm_win_lower(ad->win); */
96 return ECORE_CALLBACK_DONE;
101 return ECORE_CALLBACK_PASS_ON;
104 static void win_del(void *data, Evas_Object *obj, void *event)
109 static Evas_Object *create_win(const char *name)
111 Evas_Object *eo = NULL;
115 eo = elm_win_add(NULL, name, ELM_WIN_BASIC);
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);
125 elm_win_alpha_set(eo, EINA_TRUE);
131 static Evas_Object *create_render_rect(Evas_Object *pParent)
136 Evas *pEvas = evas_object_evas_get(pParent);
137 Evas_Object *pObj = evas_object_rectangle_add(pEvas);
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);
150 static void create_base_gui(appdata_s *ad)
152 /* Enable GLES Backened */
153 elm_config_preferred_engine_set("3d");
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);
164 /* Show window after base gui is set up */
165 elm_win_activate(ad->win);
166 evas_object_show(ad->win);
169 static int app_create(void *data)
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;
180 ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, keydown_cb, NULL);
183 ad->file_src = fopen(ES_DEFAULT_H264_VIDEO_PATH, "r");
190 static int app_pause(void *data)
192 /* Take necessary actions when application becomes invisible. */
193 appdata_s *ad = (appdata_s *)data;
194 int ret = PLAYER_ERROR_NONE;
199 LOGE("appdata is NULL");
203 if (ad->player_handle == NULL) {
204 g_print("player_handle is NULL");
208 if (ad->feeding_thread_id) {
209 pthread_join(ad->feeding_thread_id, NULL);
210 ad->feeding_thread_id = 0;
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);
218 ret = player_unprepare(ad->player_handle);
219 if (ret != PLAYER_ERROR_NONE) {
220 g_print("player_unprepare failed : 0x%x", ret);
224 /* unref media format */
226 media_format_unref(ad->video_fmt);
228 fclose(ad->file_src);
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);
237 ad->player_handle = NULL;
244 static int app_resume(void *data)
253 static void _player_prepared_cb(void *user_data)
255 int ret = PLAYER_ERROR_NONE;
256 appdata_s *ad = (appdata_s *)user_data;
260 ret = player_start(ad->player_handle);
261 if (ret != PLAYER_ERROR_NONE)
262 LOGE("player start failed : 0x%x", ret);
267 int bytestream2nalunit(FILE * fd, unsigned char *nal)
272 unsigned char buffer[1000000];
273 unsigned char val, zero_count, i;
274 int nal_unit_type = 0;
281 result = fread(buffer, 1, read_size, fd);
283 if (result != read_size)
288 if ((zero_count == 2 || zero_count == 3) && val == 1)
291 result = fread(buffer, 1, read_size, fd);
293 if (result != read_size)
297 nal[nal_length++] = 0;
298 nal[nal_length++] = 0;
299 nal[nal_length++] = 0;
300 nal[nal_length++] = 1;
307 result = fread(buffer, 1, read_size, fd);
308 if (result != read_size) {
316 nal_unit_type = val & 0xf;
322 if ((zero_count == 2 || zero_count == 3 || zero_count == 4) && (val == 1)) {
325 for (i = 0; i < zero_count; i++)
326 nal[nal_length++] = 0;
327 nal[nal_length++] = val;
333 fseek(fd, -(zero_count + 1), SEEK_CUR);
335 if (nal_unit_type == 0x7) {
336 sps_len = nal_length;
337 memcpy(sps, nal, nal_length);
339 } else if (nal_unit_type == 0x8) {
340 pps_len = nal_length;
341 memcpy(pps, nal, nal_length);
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;
354 static void feed_eos_data(appdata_s *appdata)
356 appdata_s *ad = appdata;
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");
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");
369 media_packet_destroy(ad->video_pkt);
370 ad->video_pkt = NULL;
375 static bool feed_video_data(appdata_s *appdata)
379 static unsigned long long pts = 0L;
380 void *buf_data_ptr = NULL;
381 appdata_s *ad = appdata;
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");
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");
393 if (media_packet_set_pts(ad->video_pkt, (uint64_t)pts) != MEDIA_PACKET_ERROR_NONE) {
394 LOGE("media_packet_set_pts failed\n");
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).
401 read = bytestream2nalunit(ad->file_src, buf_data_ptr);
402 LOGD("real length = %d\n", read);
404 LOGE("input file read failed\n");
407 } else if (read < 0) {
409 media_packet_destroy(ad->video_pkt);
410 ad->video_pkt = NULL;
412 if (media_packet_create(ad->video_fmt, NULL, NULL, &ad->video_pkt) != MEDIA_PACKET_ERROR_NONE) {
413 LOGE("media_packet_create failed\n");
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");
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");
427 /* push media packet */
428 player_push_media_stream(ad->player_handle, ad->video_pkt);
429 pts += ES_DEFAULT_VIDEO_PTS_OFFSET;
433 /* destroy media packet after use */
434 media_packet_destroy(ad->video_pkt);
435 ad->video_pkt = NULL;
439 static void feed_video_data_thread_func(void *data)
441 appdata_s *ad = (appdata_s *)data;
444 static int frame_count = 0;
445 if (frame_count < ES_DEFAULT_NUMBER_OF_FEED) {
446 if (!feed_video_data(ad))
456 void _video_buffer_status_cb_ex(player_media_stream_buffer_status_e status, unsigned long long bytes, void *user_data)
458 if (status == PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN) {
459 LOGE("video buffer is underrun state, current level byte = %llu", bytes);
461 else if (status == PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW) {
462 LOGE("video buffer is overrun state, current level byte = %llu", bytes);
466 void _audio_buffer_status_cb_ex(player_media_stream_buffer_status_e status, unsigned long long bytes, void *user_data)
468 if (status == PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN) {
469 LOGE("audio buffer is underrun state, current level byte = %llu", bytes);
471 else if (status == PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW) {
472 LOGE("audio buffer is overrun state, current level byte = %llu", bytes);
476 void _video_seek_data_cb(unsigned long long offset, void *user_data)
478 LOGE("seek offset of video is %llu", offset);
481 void _audio_seek_data_cb(unsigned long long offset, void *user_data)
483 LOGE("seek offset of audio is %llu", offset);
486 static int app_reset(bundle *b, void *data)
488 /* Take necessary actions when application becomes visible. */
489 appdata_s *ad = (appdata_s *)data;
490 int ret = PLAYER_ERROR_NONE;
495 LOGE("appdata is NULL");
499 ret = player_create(&ad->player_handle);
500 if (ret != PLAYER_ERROR_NONE) {
501 LOGE("player_create failed : 0x%x", ret);
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);
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);
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);
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);
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);
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);
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);
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);
548 /* send media packet to player */
549 player_set_media_stream_info(ad->player_handle, PLAYER_STREAM_TYPE_VIDEO, ad->video_fmt);
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);
557 pthread_create(&ad->feeding_thread_id, NULL, (void *)feed_video_data_thread_func, (void *)ad);
564 if (ad->player_handle) {
565 player_destroy(ad->player_handle);
566 ad->player_handle = NULL;
572 static int app_terminate(void *data)
574 /* Release all resources. */
575 appdata_s *ad = (appdata_s *)data;
580 LOGE("appdata is NULL");
591 int main(int argc, char *argv[])
594 static appdata_s ad = {0, };
598 memset(&ad, 0x0, sizeof(appdata_s));
600 LOGD("call appcore_efl_main");
604 ret = appcore_efl_main(PACKAGE, &argc, &argv, &ops);
606 LOGD("appcore_efl_main() ret = 0x%x", ret);