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"
27 #define INVALID_TRACK_INDEX -1
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(count, MM_ERROR_INVALID_ARGUMENT);
51 MMPLAYER_RETURN_VAL_IF_FAIL((MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED)
52 || (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING),
53 MM_ERROR_PLAYER_INVALID_STATE);
55 attrs = MMPLAYER_GET_ATTRS(player);
57 LOGE("cannot get content attribute");
58 return MM_ERROR_PLAYER_INTERNAL;
64 case MM_PLAYER_TRACK_TYPE_AUDIO:
65 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num > 0)
66 *count = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num;
68 case MM_PLAYER_TRACK_TYPE_TEXT: /* internal or external */
69 ret = mm_attrs_get_int_by_name(attrs, "content_text_track_num", count);
72 ret = MM_ERROR_INVALID_ARGUMENT;
76 LOGD("type: %d, the num of track: %d", type, *count);
84 _mmplayer_select_track(MMHandleType hplayer, mmplayer_track_type_e type, int index)
86 int ret = MM_ERROR_NONE;
87 mmplayer_t *player = (mmplayer_t *)hplayer;
90 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
92 LOGD("track type: %d, index: %d", type, index);
94 MMPLAYER_SUBTITLE_INFO_LOCK(player);
96 if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list) { /* external subtitle */
97 GstElement *subparse = NULL;
98 mmplayer_lang_info_t *temp = NULL;
99 guint num_of_list = 0;
101 if (!player->pipeline || !player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst) {
102 ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
106 num_of_list = g_list_length(player->subtitle_language_list);
107 if (index < 0 || index >= num_of_list) {
108 LOGE("req track index is wrong");
109 ret = MM_ERROR_INVALID_ARGUMENT;
113 temp = g_list_nth_data(player->subtitle_language_list, index);
115 LOGE("fail to get lang from list");
116 ret = MM_ERROR_PLAYER_INTERNAL;
119 subparse = player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst;
120 LOGD("setting to language %s", temp->language_code);
121 g_object_set(G_OBJECT(subparse), "current-language", temp->language_key, NULL);
123 _mmplayer_sync_subtitle_pipeline(player);
125 } else { /* audio or internal subtitle */
126 ret = _mmplayer_change_track_language(hplayer, type, index);
127 if (ret != MM_ERROR_NONE) {
128 LOGE("failed to change track");
133 if (type == MM_PLAYER_TRACK_TYPE_TEXT) {
134 MMHandleType attrs = MMPLAYER_GET_ATTRS(player);
136 LOGE("cannot get content attribute");
137 ret = MM_ERROR_PLAYER_INTERNAL;
141 mm_attrs_set_int_by_name(attrs, "current_text_track_index", index);
143 if (mm_attrs_commit_all(attrs)) {
144 LOGE("failed to commit");
145 ret = MM_ERROR_PLAYER_INTERNAL;
150 LOGD("current index is updated");
153 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
159 _mmplayer_get_current_track(MMHandleType hplayer, mmplayer_track_type_e type, int *index)
161 int ret = MM_ERROR_NONE;
162 mmplayer_t *player = (mmplayer_t *)hplayer;
163 MMHandleType attrs = 0;
167 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
168 MMPLAYER_RETURN_VAL_IF_FAIL(index, MM_ERROR_INVALID_ARGUMENT);
170 attrs = MMPLAYER_GET_ATTRS(player);
171 MMPLAYER_RETURN_VAL_IF_FAIL(attrs, MM_ERROR_PLAYER_INTERNAL);
173 MMPLAYER_SUBTITLE_INFO_LOCK(player);
175 LOGD("track type: %d", type);
177 *index = INVALID_TRACK_INDEX;
180 case MM_PLAYER_TRACK_TYPE_AUDIO:
181 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) {
182 LOGW("there is no audio track");
183 ret = MM_ERROR_PLAYER_NO_OP;
187 *index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
189 case MM_PLAYER_TRACK_TYPE_TEXT: /* internal or external */
190 mm_attrs_get_int_by_name(attrs, "content_text_track_num", &count);
192 LOGD("there is no text track");
193 ret = MM_ERROR_PLAYER_NO_OP;
197 mm_attrs_get_int_by_name(attrs, "current_text_track_index", index);
200 LOGD("invalid input type");
201 ret = MM_ERROR_INVALID_ARGUMENT;
206 LOGE("invalid track index");
207 ret = MM_ERROR_PLAYER_INTERNAL;
211 LOGD("current track index: %d", *index);
214 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
220 _mmplayer_get_track_language_code(MMHandleType hplayer, mmplayer_track_type_e type, int index, char **code)
222 int ret = MM_ERROR_NONE;
223 mmplayer_t *player = (mmplayer_t *)hplayer;
224 gchar *lang_code = NULL;
227 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
228 MMPLAYER_RETURN_VAL_IF_FAIL(code, MM_ERROR_INVALID_ARGUMENT);
230 MMPLAYER_SUBTITLE_INFO_LOCK(player);
232 if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list) { /* external subtitle */
233 mmplayer_lang_info_t *language_list = NULL;
235 lang_code = (gchar *)g_malloc0(LANGUAGE_CODE_SIZE * sizeof(char));
237 language_list = g_list_nth_data(player->subtitle_language_list, index);
238 if (language_list == NULL) {
239 LOGE("invalid index %d", index);
240 ret = MM_ERROR_INVALID_ARGUMENT;
243 g_strlcpy(lang_code, language_list->language_code, LANGUAGE_CODE_SIZE);
244 } else { /* audio or internal subtitle */
245 if (player->selector[type].total_track_num <= 0) {
246 LOGW("language list is not available. [type:%d]", type);
247 ret = MM_ERROR_PLAYER_NO_OP;
251 ret = __mmplayer_track_get_language(player, type, index, &lang_code);
255 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
258 if (ret == MM_ERROR_NONE) {
259 if (g_strcmp0(lang_code, "und"))
260 *code = strndup(lang_code, 2);
262 *code = strndup("und", 3);
264 MMPLAYER_FREEIF(lang_code);
271 _mmplayer_track_initialize(mmplayer_t *player)
273 mmplayer_track_type_e type = MM_PLAYER_TRACK_TYPE_AUDIO;
277 for (; type < MM_PLAYER_TRACK_TYPE_MAX ; type++) {
278 /* active_pad_index is initialized when player is created or destroyed.
279 and the value can be set by calling _mmplayer_change_track_language()
280 before pipeline is created.*/
281 player->selector[type].total_track_num = 0;
282 player->selector[type].channels = g_ptr_array_new();
287 _mmplayer_track_destroy(mmplayer_t *player)
289 mmplayer_track_type_e type = MM_PLAYER_TRACK_TYPE_AUDIO;
290 MMHandleType attrs = 0;
293 attrs = MMPLAYER_GET_ATTRS(player);
295 mm_attrs_set_int_by_name(attrs, "content_text_track_num", 0);
296 mm_attrs_set_int_by_name(attrs, "current_text_track_index", INVALID_TRACK_INDEX);
298 if (mm_attrs_commit_all(attrs))
299 LOGE("failed to commit");
302 for (; type < MM_PLAYER_TRACK_TYPE_MAX ; type++) {
303 player->selector[type].active_pad_index = 0;
304 player->selector[type].total_track_num = 0;
306 if (player->selector[type].channels)
307 g_ptr_array_free(player->selector[type].channels, TRUE);
308 player->selector[type].channels = NULL;
313 _mmplayer_track_update_selector_info(mmplayer_t *player, mmplayer_track_type_e type, GstPad *sinkpad)
317 player->selector[type].total_track_num++;
318 g_ptr_array_add(player->selector[type].channels, sinkpad);
320 LOGD("type: %d, track cnt: %d", type, player->selector[type].total_track_num);
324 _mmplayer_track_update_text_attr_info(mmplayer_t *player, GstMessage *msg)
326 MMHandleType attrs = 0;
327 const GValue *lang_list = NULL;
328 mmplayer_lang_info_t *temp = NULL;
329 gchar *current_lang = NULL;
330 gint track_index = INVALID_TRACK_INDEX;
331 guint track_count = 0, index = 0;
334 MMPLAYER_RETURN_IF_FAIL(player && msg);
336 attrs = MMPLAYER_GET_ATTRS(player);
338 LOGE("failed to get content attribute");
342 if (!gst_message_get_structure(msg)) {
343 LOGE("failed to get msg structure");
347 lang_list = gst_structure_get_value(gst_message_get_structure(msg), "lang_list");
349 LOGW("language list is null");
353 track_count = g_list_length((GList *)g_value_get_pointer(lang_list));
354 if (track_count == 0) {
355 LOGW("track count is zero");
359 MMPLAYER_SUBTITLE_INFO_LOCK(player);
360 player->subtitle_language_list = (GList *)g_value_get_pointer(lang_list);
361 mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)track_count);
362 g_object_get(G_OBJECT(msg->src), "current-language", ¤t_lang, NULL);
364 LOGI("track count: %d, current track lang: %s", track_count, current_lang);
368 for (index = 0 ; index < track_count ; index++) {
369 temp = g_list_nth_data(player->subtitle_language_list, index);
371 LOGI("[%d] lang_key: %s, lang_code: %s",
372 index, temp->language_key, temp->language_code);
374 if (!g_strcmp0(temp->language_key, current_lang)) {
375 LOGD("current track index : %d", index);
382 if (track_index > INVALID_TRACK_INDEX)
383 mm_attrs_set_int_by_name(attrs, "current_text_track_index", track_index);
385 LOGE("failed to find current track index");
387 if (mm_attrs_commit_all(attrs))
388 LOGE("failed to commit");
391 MMPLAYER_SUBTITLE_INFO_SIGNAL(player);
392 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
398 __mmplayer_track_get_language(mmplayer_t *player, mmplayer_track_type_e type, gint stream_index, gchar **code)
400 GstTagList *tag_list = NULL;
402 GstPad *sinkpad = NULL;
405 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
406 MMPLAYER_RETURN_VAL_IF_FAIL((code && (stream_index >= 0) &&
407 (stream_index < player->selector[type].total_track_num)), MM_ERROR_INVALID_ARGUMENT);
409 LOGD("type: %d, track count: %d, intput idx: %d", type, player->selector[type].total_track_num, stream_index);
411 *code = (gchar *)g_malloc0(LANGUAGE_CODE_SIZE * sizeof(char));
413 sinkpad = g_ptr_array_index(player->selector[type].channels, stream_index);
415 g_object_get(sinkpad, "tags", &tag_list, NULL);
417 gst_tag_list_get_string(tag_list, GST_TAG_LANGUAGE_CODE, &tag);
420 LOGD("language code: %s, len: %zu", tag, strlen(tag));
421 g_strlcpy(*code, tag, LANGUAGE_CODE_SIZE);
422 MMPLAYER_FREEIF(tag);
424 LOGD("no language code info - und");
425 g_strlcpy(*code, "und", LANGUAGE_CODE_SIZE);
429 gst_tag_list_unref(tag_list);
432 return MM_ERROR_NONE;