4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, naveen cherukuri <naveen.ch@samsung.com>,
7 * YeJin Cho <cho.yejin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
24 #include "mm_player_pd.h"
25 #include "mm_player_utils.h"
26 #include "mm_player_priv.h"
28 /*---------------------------------------------------------------------------------------
29 | LOCAL FUNCTION PROTOTYPES: |
30 ---------------------------------------------------------------------------------------*/
32 /* It's callback to process whenever there is some changes in PD downloader. */
33 static gboolean __pd_downloader_callback(GstBus *bus, GstMessage *msg, gpointer data);
35 /* This function posts messages to application. */
36 /* Currently, MM_MESSAGE_PD_DOWNLOADER_START and MM_MESSAGE_PD_DOWNLOADER_END are used. */
37 static gboolean __pd_downloader_post_message(mm_player_t * player, enum MMMessageType msgtype, MMMessageParamType* param);
39 /*=======================================================================================
40 | FUNCTION DEFINITIONS |
41 =======================================================================================*/
43 __pd_downloader_callback(GstBus *bus, GstMessage *msg, gpointer data)
45 mm_player_t * player = NULL;
46 mm_player_pd_t *pd = NULL;
51 /* chech player handle */
52 MMPLAYER_RETURN_VAL_IF_FAIL(data, MM_ERROR_INVALID_ARGUMENT);
54 player = MM_PLAYER_CAST((MMHandleType)data);
56 /* get PD downloader handle */
57 pd = MM_PLAYER_GET_PD((MMHandleType)data);
59 MMPLAYER_RETURN_VAL_IF_FAIL(pd, MM_ERROR_INVALID_ARGUMENT);
61 // g_print("%s\n", GST_MESSAGE_TYPE_NAME(msg));
63 switch (GST_MESSAGE_TYPE(msg)) {
66 LOGD("PD Downloader EOS received....\n");
68 g_object_set(G_OBJECT(pd->playback_pipeline_src), "eos", TRUE, NULL);
70 /* notify application that download is completed */
71 __pd_downloader_post_message(player, MM_MESSAGE_PD_DOWNLOADER_END, NULL);
73 #ifdef PD_SELF_DOWNLOAD
74 _mmplayer_unrealize_pd_downloader((MMHandleType)data);
79 case GST_MESSAGE_ERROR:
83 GstMessage *new_msg = NULL;
86 gst_message_parse_error(msg, &error, &debug);
87 LOGE("GST_MESSAGE_ERROR = %s\n", debug);
89 new_msg = gst_message_new_error(GST_OBJECT_CAST(pd->playback_pipeline_src), error, debug);
91 /* notify application that pd has any error */
92 gst_element_post_message(pd->playback_pipeline_src, new_msg);
94 _mmplayer_unrealize_pd_downloader((MMHandleType)data);
95 MMPLAYER_FREEIF(debug);
100 case GST_MESSAGE_WARNING:
103 GError* error = NULL;
105 gst_message_parse_warning(msg, &error, &debug);
106 LOGW("warning : %s\n", error->message);
107 LOGW("debug : %s\n", debug);
109 MMPLAYER_FREEIF(debug);
114 case GST_MESSAGE_STATE_CHANGED:
116 GstState old_state, new_state;
119 /* get old and new state */
120 gst_message_parse_state_changed(msg, &old_state, &new_state, NULL);
122 if (old_state == new_state)
125 /* we only care about pipeline state changes */
126 if (GST_MESSAGE_SRC(msg) != GST_OBJECT(pd->downloader_pipeline))
129 src_name = gst_object_get_name(msg->src);
130 LOGD("%s changed state from %s to %s", src_name,
131 gst_element_state_get_name(old_state),
132 gst_element_state_get_name(new_state));
136 case GST_STATE_VOID_PENDING:
138 case GST_STATE_READY:
139 case GST_STATE_PAUSED:
142 case GST_STATE_PLAYING:
143 /* notify application that download is stated */
144 __pd_downloader_post_message(player, MM_MESSAGE_PD_DOWNLOADER_START, NULL);
153 case GST_MESSAGE_DURATION:
157 /* get total size of download file, (bytes) */
158 if (!gst_element_query_duration(pd->downloader_pipeline, GST_FORMAT_BYTES, &size)) {
160 GstMessage *new_msg = NULL;
162 err = g_error_new(GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED, "can't get total size");
163 new_msg = gst_message_new_error(GST_OBJECT_CAST(pd->playback_pipeline_src), err, NULL);
164 gst_element_post_message(pd->playback_pipeline_src, new_msg);
168 // TODO: check if playback pipeline is closed well or not
169 g_object_set(G_OBJECT(pd->playback_pipeline_src), "eos", TRUE, NULL);
171 _mmplayer_unrealize_pd_downloader((MMHandleType)data);
173 LOGE("failed to query total size for download\n");
177 pd->total_size = size;
179 LOGD("PD total size : %lld bytes\n", size);
184 LOGW("unhandled message\n");
194 gboolean __pd_downloader_post_message(mm_player_t * player, enum MMMessageType msgtype, MMMessageParamType* param)
198 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
200 if (!player->pd_msg_cb) {
201 LOGW("no msg callback. can't post\n");
205 player->pd_msg_cb(msgtype, param, player->pd_msg_cb_param);
213 int _mmplayer_get_pd_downloader_status(MMHandleType handle, guint64 *current_pos, guint64 *total_size)
217 mm_player_pd_t * pd = NULL;
220 MMPLAYER_RETURN_VAL_IF_FAIL(handle, MM_ERROR_INVALID_ARGUMENT);
222 pd = MM_PLAYER_GET_PD(handle);
224 MMPLAYER_RETURN_VAL_IF_FAIL(pd, MM_ERROR_INVALID_ARGUMENT);
225 MMPLAYER_RETURN_VAL_IF_FAIL(pd->downloader_pipeline, MM_ERROR_PLAYER_INVALID_STATE);
227 if (!pd->total_size) {
228 LOGW("not ready to get total size\n");
229 return MM_ERROR_PLAYER_INTERNAL;
232 g_object_get(pd->downloader_sink, "current-bytes", &bytes, NULL);
234 LOGD("PD status : %lld / %lld\n", bytes, pd->total_size);
236 *current_pos = bytes;
237 *total_size = pd->total_size;
241 return MM_ERROR_NONE;
245 mm_player_pd_t * _mmplayer_create_pd_downloader()
249 mm_player_pd_t * pd = NULL;
251 /* create PD handle */
252 pd = (mm_player_pd_t *) malloc(sizeof(mm_player_pd_t));
254 LOGE("Failed to create pd downloader handle...\n");
257 memset(pd, 0, sizeof(mm_player_pd_t));
265 gboolean _mmplayer_destroy_pd_downloader(MMHandleType handle)
269 mm_player_pd_t * pd = NULL;
271 MMPLAYER_RETURN_VAL_IF_FAIL(handle, MM_ERROR_INVALID_ARGUMENT);
273 pd = MM_PLAYER_GET_PD(handle);
275 if (pd && pd->downloader_pipeline)
276 _mmplayer_unrealize_pd_downloader(handle);
278 /* release PD handle */
287 gboolean _mmplayer_realize_pd_downloader(MMHandleType handle, gchar *src_uri, gchar *dst_uri, GstElement *pushsrc)
291 mm_player_pd_t * pd = NULL;
293 MMPLAYER_RETURN_VAL_IF_FAIL(handle, MM_ERROR_INVALID_ARGUMENT);
294 MMPLAYER_RETURN_VAL_IF_FAIL(src_uri, MM_ERROR_INVALID_ARGUMENT);
295 MMPLAYER_RETURN_VAL_IF_FAIL(dst_uri, MM_ERROR_INVALID_ARGUMENT);
296 MMPLAYER_RETURN_VAL_IF_FAIL(pushsrc, MM_ERROR_INVALID_ARGUMENT);
298 pd = MM_PLAYER_GET_PD(handle);
301 pd->path_read_from = g_strdup(src_uri);
302 pd->location_to_save = g_strdup(dst_uri);
303 pd->playback_pipeline_src = pushsrc;
304 pd->total_size = 0LL;
312 gboolean _mmplayer_start_pd_downloader(MMHandleType handle)
315 gboolean bret = FALSE;
316 GstStateChangeReturn sret = GST_STATE_CHANGE_SUCCESS;
318 GstState pending_state;
322 mm_player_pd_t * pd = NULL;
324 MMPLAYER_RETURN_VAL_IF_FAIL(handle, MM_ERROR_INVALID_ARGUMENT);
326 pd = MM_PLAYER_GET_PD(handle);
329 pd->downloader_pipeline = gst_pipeline_new("PD Downloader");
330 if (NULL == pd->downloader_pipeline) {
331 LOGE("Can't create PD download pipeline...");
336 pd->downloader_src = gst_element_factory_make("souphttpsrc", "PD HTTP download source");
337 if (NULL == pd->downloader_src) {
338 LOGE("Can't create PD download src...");
343 pd->downloader_queue = gst_element_factory_make("queue", "PD download queue");
344 if (NULL == pd->downloader_queue) {
345 LOGE("Can't create PD download queue...");
350 pd->downloader_sink = gst_element_factory_make("filesink", "PD download sink");
351 if (NULL == pd->downloader_sink) {
352 LOGE("Can't create PD download sink...");
356 g_object_set(pd->downloader_sink, "sync", FALSE, NULL);
358 /* Add to bin and link */
359 gst_bin_add_many(GST_BIN(pd->downloader_pipeline),
360 pd->downloader_src, pd->downloader_queue, pd->downloader_sink,
363 bret = gst_element_link_many(pd->downloader_src, pd->downloader_queue, pd->downloader_sink, NULL);
365 LOGE("Can't link elements src and sink...");
369 /* Get Bus and set callback to watch */
370 bus = gst_pipeline_get_bus(GST_PIPELINE(pd->downloader_pipeline));
371 gst_bus_add_watch(bus, __pd_downloader_callback, (gpointer)handle);
372 gst_object_unref(bus);
374 /* Set URI on HTTP source */
375 g_object_set(G_OBJECT(pd->downloader_src), "location", pd->path_read_from, NULL);
377 /* set file download location on filesink*/
378 g_object_set(G_OBJECT(pd->downloader_sink), "location", pd->location_to_save, NULL);
380 SECURE_LOGD("src location = %s, save location = %s\n", pd->path_read_from, pd->location_to_save);
382 /* Start to download */
383 sret = gst_element_set_state(pd->downloader_pipeline, GST_STATE_PLAYING);
384 if (GST_STATE_CHANGE_FAILURE == sret) {
385 LOGE("PD download pipeline failed to go to PLAYING state...");
389 LOGD("set_state :: sret = %d\n", sret);
391 sret = gst_element_get_state(pd->downloader_pipeline, &cur_state, &pending_state, GST_CLOCK_TIME_NONE);
392 if (GST_STATE_CHANGE_FAILURE == sret) {
393 LOGE("PD download pipeline failed to do get_state...");
397 LOGD("get-state :: sret = %d\n", sret);
405 gboolean _mmplayer_unrealize_pd_downloader(MMHandleType handle)
409 mm_player_pd_t * pd = NULL;
411 MMPLAYER_RETURN_VAL_IF_FAIL(handle, FALSE);
413 pd = MM_PLAYER_GET_PD(handle);
415 MMPLAYER_RETURN_VAL_IF_FAIL(pd && pd->downloader_pipeline, FALSE);
417 gst_element_set_state(pd->downloader_pipeline, GST_STATE_NULL);
418 gst_element_get_state(pd->downloader_pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
420 gst_object_unref(G_OBJECT(pd->downloader_pipeline));
421 pd->downloader_pipeline = NULL;
424 MMPLAYER_FREEIF(pd->path_read_from);
425 MMPLAYER_FREEIF(pd->location_to_save);
433 gint _mm_player_set_pd_downloader_message_cb(MMHandleType handle, MMMessageCallback callback, gpointer user_param)
437 mm_player_t * player = NULL;
439 MMPLAYER_RETURN_VAL_IF_FAIL(handle, MM_ERROR_INVALID_ARGUMENT);
441 player = MM_PLAYER_CAST((MMHandleType)handle);
443 /* PD callback can be set as soon as player handle is created.
444 * So, player handle must have it.
446 player->pd_msg_cb = callback;
447 player->pd_msg_cb_param = user_param;
449 LOGD("msg_cb : %p msg_cb_param : %p\n", callback, user_param);
453 return MM_ERROR_NONE;