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_utils.h"
25 #include "mm_player_tracks.h"
26 #include "mm_player_attrs.h"
28 #define LANGUAGE_CODE_SIZE (3 + 1) /* Size of ISO-639-1, and considering the nul-terminator */
30 /*---------------------------------------------------------------------------------------
31 | LOCAL FUNCTION PROTOTYPES: |
32 ---------------------------------------------------------------------------------------*/
33 static int __mmplayer_track_get_language(mmplayer_t *player, mmplayer_track_type_e type, gint stream_index, gchar **code);
36 /*=======================================================================================
37 | FUNCTION DEFINITIONS |
38 =======================================================================================*/
40 _mmplayer_get_track_count(MMHandleType hplayer, mmplayer_track_type_e type, int *count)
42 int ret = MM_ERROR_NONE;
43 mmplayer_t *player = (mmplayer_t *)hplayer;
44 MMHandleType attrs = 0;
48 /* check player handle */
49 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
50 MMPLAYER_RETURN_VAL_IF_FAIL(type < MM_PLAYER_TRACK_TYPE_MAX, MM_ERROR_INVALID_ARGUMENT);
51 MMPLAYER_RETURN_VAL_IF_FAIL(count, MM_ERROR_INVALID_ARGUMENT);
52 MMPLAYER_RETURN_VAL_IF_FAIL((MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED)
53 || (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING),
54 MM_ERROR_PLAYER_INVALID_STATE);
56 attrs = MMPLAYER_GET_ATTRS(player);
58 LOGE("cannot get content attribute");
59 return MM_ERROR_PLAYER_INTERNAL;
65 case MM_PLAYER_TRACK_TYPE_AUDIO:
66 if (player->track[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num > 0)
67 *count = player->track[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num;
69 case MM_PLAYER_TRACK_TYPE_TEXT: /* internal or external */
70 ret = mm_attrs_get_int_by_name(attrs, "content_text_track_num", count);
73 ret = MM_ERROR_INVALID_ARGUMENT;
77 LOGD("type: %d, the num of track: %d", type, *count);
85 _mmplayer_select_track(MMHandleType hplayer, mmplayer_track_type_e type, int index)
87 int ret = MM_ERROR_NONE;
88 mmplayer_t *player = (mmplayer_t *)hplayer;
91 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
92 MMPLAYER_RETURN_VAL_IF_FAIL(type < MM_PLAYER_TRACK_TYPE_MAX, MM_ERROR_INVALID_ARGUMENT);
94 LOGD("track type: %d, index: %d", type, index);
96 MMPLAYER_SUBTITLE_INFO_LOCK(player);
98 if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list) { /* external subtitle */
99 GstElement *subparse = NULL;
100 mmplayer_lang_info_t *temp = NULL;
101 guint num_of_list = 0;
103 if (!player->pipeline || !player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst) {
104 ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
108 num_of_list = g_list_length(player->subtitle_language_list);
109 if (index < 0 || index >= num_of_list) {
110 LOGE("req track index is wrong");
111 ret = MM_ERROR_INVALID_ARGUMENT;
115 temp = g_list_nth_data(player->subtitle_language_list, index);
117 LOGE("fail to get lang from list");
118 ret = MM_ERROR_PLAYER_INTERNAL;
121 subparse = player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst;
122 LOGD("setting to language %s", temp->language_code);
123 g_object_set(G_OBJECT(subparse), "current-language", temp->language_key, NULL);
125 _mmplayer_sync_subtitle_pipeline(player);
127 } else { /* audio or internal subtitle */
128 ret = _mmplayer_change_track_language(hplayer, type, index);
129 if (ret != MM_ERROR_NONE) {
130 LOGE("failed to change track");
135 if (type == MM_PLAYER_TRACK_TYPE_TEXT) {
136 if (mm_player_set_attribute(hplayer, NULL,
137 "current_text_track_index", index, NULL) != MM_ERROR_NONE) {
138 LOGE("failed to set text track index");
139 ret = MM_ERROR_PLAYER_INTERNAL;
144 LOGD("current index is updated");
147 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
153 _mmplayer_get_current_track(MMHandleType hplayer, mmplayer_track_type_e type, int *index)
155 int ret = MM_ERROR_NONE;
156 mmplayer_t *player = (mmplayer_t *)hplayer;
157 MMHandleType attrs = 0;
161 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
162 MMPLAYER_RETURN_VAL_IF_FAIL(type < MM_PLAYER_TRACK_TYPE_MAX, MM_ERROR_INVALID_ARGUMENT);
163 MMPLAYER_RETURN_VAL_IF_FAIL(index, MM_ERROR_INVALID_ARGUMENT);
165 attrs = MMPLAYER_GET_ATTRS(player);
166 MMPLAYER_RETURN_VAL_IF_FAIL(attrs, MM_ERROR_PLAYER_INTERNAL);
168 MMPLAYER_SUBTITLE_INFO_LOCK(player);
170 LOGD("track type: %d", type);
172 *index = INVALID_TRACK_INDEX;
175 case MM_PLAYER_TRACK_TYPE_AUDIO:
176 if (player->track[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) {
177 LOGW("there is no audio track");
178 ret = MM_ERROR_PLAYER_NO_OP;
182 *index = player->track[MM_PLAYER_TRACK_TYPE_AUDIO].active_track_index;
184 case MM_PLAYER_TRACK_TYPE_TEXT: /* internal or external */
185 mm_attrs_get_int_by_name(attrs, "content_text_track_num", &count);
187 LOGD("there is no text track");
188 ret = MM_ERROR_PLAYER_NO_OP;
192 mm_attrs_get_int_by_name(attrs, "current_text_track_index", index);
195 LOGD("invalid input type");
196 ret = MM_ERROR_INVALID_ARGUMENT;
201 LOGE("invalid track index");
202 ret = MM_ERROR_PLAYER_INTERNAL;
206 LOGD("current track index: %d", *index);
209 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
215 _mmplayer_get_track_language_code(MMHandleType hplayer, mmplayer_track_type_e type, int index, char **code)
217 int ret = MM_ERROR_NONE;
218 mmplayer_t *player = (mmplayer_t *)hplayer;
219 gchar *lang_code = NULL;
222 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
223 MMPLAYER_RETURN_VAL_IF_FAIL(type < MM_PLAYER_TRACK_TYPE_MAX, MM_ERROR_INVALID_ARGUMENT);
224 MMPLAYER_RETURN_VAL_IF_FAIL(code, MM_ERROR_INVALID_ARGUMENT);
226 MMPLAYER_SUBTITLE_INFO_LOCK(player);
228 if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list) { /* external subtitle */
229 mmplayer_lang_info_t *language_list = NULL;
231 lang_code = (gchar *)g_malloc0(LANGUAGE_CODE_SIZE * sizeof(char));
233 language_list = g_list_nth_data(player->subtitle_language_list, index);
234 if (language_list == NULL) {
235 LOGE("invalid index %d", index);
236 ret = MM_ERROR_INVALID_ARGUMENT;
239 g_strlcpy(lang_code, language_list->language_code, LANGUAGE_CODE_SIZE);
240 } else { /* audio or internal subtitle */
241 if (player->track[type].total_track_num <= 0) {
242 LOGW("language list is not available. [type:%d]", type);
243 ret = MM_ERROR_PLAYER_NO_OP;
247 ret = __mmplayer_track_get_language(player, type, index, &lang_code);
251 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
254 if (ret == MM_ERROR_NONE) {
255 if (g_strcmp0(lang_code, "und"))
256 *code = strndup(lang_code, 2);
258 *code = strndup("und", 3);
260 MMPLAYER_FREEIF(lang_code);
267 _mmplayer_track_initialize(mmplayer_t *player)
269 mmplayer_track_type_e type = MM_PLAYER_TRACK_TYPE_AUDIO;
273 for (; type < MM_PLAYER_TRACK_TYPE_MAX ; type++) {
274 player->track[type].active_track_index = INVALID_TRACK_INDEX;
275 player->track[type].total_track_num = 0;
276 player->track[type].streams = g_ptr_array_new_with_free_func(gst_object_unref);
281 _mmplayer_track_destroy(mmplayer_t *player)
283 mmplayer_track_type_e type = MM_PLAYER_TRACK_TYPE_AUDIO;
286 if (mm_player_set_attribute((MMHandleType)player, NULL, "content_text_track_num", 0,
287 "current_text_track_index", INVALID_TRACK_INDEX, NULL) != MM_ERROR_NONE)
288 LOGE("failed to reset track attr");
290 for (; type < MM_PLAYER_TRACK_TYPE_MAX ; type++) {
291 player->track[type].active_track_index = 0;
292 player->track[type].total_track_num = 0;
294 if (player->track[type].streams)
295 g_ptr_array_free(player->track[type].streams, TRUE);
296 player->track[type].streams = NULL;
301 _mmplayer_get_track_index(mmplayer_t *player, mmplayer_track_type_e type, void* stream, int *index)
303 guint found_index = 0;
306 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
307 MMPLAYER_RETURN_VAL_IF_FAIL(type < MM_PLAYER_TRACK_TYPE_MAX, MM_ERROR_INVALID_ARGUMENT);
308 MMPLAYER_RETURN_VAL_IF_FAIL(index, MM_ERROR_INVALID_ARGUMENT);
310 if (g_ptr_array_find(player->track[type].streams, stream, &found_index)) {
311 LOGD("Find same stream (%u)", found_index);
312 *index = (int)found_index;
313 return MM_ERROR_NONE;
316 *index = INVALID_TRACK_INDEX;
317 LOGD("Stream not found : type %d, stream %p", type, stream);
318 return MM_ERROR_PLAYER_INTERNAL;
322 __mmplayer_stream_equal(gconstpointer stream1, gconstpointer stream2)
324 return (g_strcmp0(gst_stream_get_stream_id((GstStream *)stream1),
325 gst_stream_get_stream_id((GstStream *)stream2)) == 0);
329 _mmplayer_track_update_stream(mmplayer_t *player, mmplayer_track_type_e type, void *stream)
332 MMPLAYER_RETURN_IF_FAIL(player);
333 MMPLAYER_RETURN_IF_FAIL(type < MM_PLAYER_TRACK_TYPE_MAX);
335 if (g_ptr_array_find_with_equal_func(player->track[type].streams, stream, __mmplayer_stream_equal, NULL)) {
336 LOGD("Already added stream, not updated");
340 player->track[type].total_track_num++;
341 g_ptr_array_add(player->track[type].streams, gst_object_ref(stream));
343 LOGD("type: %d, track cnt: %d", type, player->track[type].total_track_num);
347 _mmplayer_track_update_text_attr_info(mmplayer_t *player, GstMessage *msg)
349 const GValue *lang_list = NULL;
350 mmplayer_lang_info_t *temp = NULL;
351 gchar *current_lang = NULL;
352 gint track_index = INVALID_TRACK_INDEX;
353 guint track_count = 0, index = 0;
356 MMPLAYER_RETURN_IF_FAIL(player && msg);
358 if (!gst_message_get_structure(msg)) {
359 LOGE("failed to get msg structure");
363 lang_list = gst_structure_get_value(gst_message_get_structure(msg), "lang_list");
365 LOGW("language list is null");
369 track_count = g_list_length((GList *)g_value_get_pointer(lang_list));
370 if (track_count == 0) {
371 LOGW("track count is zero");
375 MMPLAYER_SUBTITLE_INFO_LOCK(player);
376 player->subtitle_language_list = (GList *)g_value_get_pointer(lang_list);
377 mm_player_set_attribute((MMHandleType)player, NULL,
378 "content_text_track_num", (gint)track_count, NULL);
379 g_object_get(G_OBJECT(msg->src), "current-language", ¤t_lang, NULL);
381 LOGI("track count: %d, current track lang: %s", track_count, current_lang);
385 for (index = 0 ; index < track_count ; index++) {
386 temp = g_list_nth_data(player->subtitle_language_list, index);
388 LOGI("[%d] lang_key: %s, lang_code: %s",
389 index, temp->language_key, temp->language_code);
391 if (!g_strcmp0(temp->language_key, current_lang)) {
392 LOGD("current track index : %d", index);
399 if (track_index > INVALID_TRACK_INDEX)
400 mm_player_set_attribute((MMHandleType)player, NULL,
401 "current_text_track_index", track_index, NULL);
403 LOGE("failed to find current track index");
406 MMPLAYER_SUBTITLE_INFO_SIGNAL(player);
407 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
413 __mmplayer_track_get_language(mmplayer_t *player, mmplayer_track_type_e type, gint stream_index, gchar **code)
415 GstTagList *tag_list = NULL;
419 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
420 MMPLAYER_RETURN_VAL_IF_FAIL(type < MM_PLAYER_TRACK_TYPE_MAX, MM_ERROR_INVALID_ARGUMENT);
421 MMPLAYER_RETURN_VAL_IF_FAIL((code && (stream_index >= 0) &&
422 (stream_index < player->track[type].total_track_num)), MM_ERROR_INVALID_ARGUMENT);
424 LOGD("type: %d, track count: %d, input idx: %d", type, player->track[type].total_track_num, stream_index);
426 *code = (gchar *)g_malloc0(LANGUAGE_CODE_SIZE * sizeof(char));
428 if (MMPLAYER_USE_DECODEBIN(player)) {
429 GstPad *sinkpad = g_ptr_array_index(player->track[type].streams, stream_index);
430 g_object_get(sinkpad, "tags", &tag_list, NULL);
432 GstStream *stream = g_ptr_array_index(player->track[type].streams, stream_index);
433 tag_list = gst_stream_get_tags (stream);
437 gst_tag_list_get_string(tag_list, GST_TAG_LANGUAGE_CODE, &tag);
440 LOGD("language code: %s, len: %zu", tag, strlen(tag));
441 g_strlcpy(*code, tag, LANGUAGE_CODE_SIZE);
442 MMPLAYER_FREEIF(tag);
444 LOGD("no language code info - und");
445 g_strlcpy(*code, "und", LANGUAGE_CODE_SIZE);
449 gst_tag_list_unref(tag_list);
452 return MM_ERROR_NONE;