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 INVALID_TRACK_INDEX -1
29 #define LANGUAGE_CODE_SIZE (3 + 1) /* Size of ISO-639-1, and considering the nul-terminator */
31 /*---------------------------------------------------------------------------------------
32 | LOCAL FUNCTION PROTOTYPES: |
33 ---------------------------------------------------------------------------------------*/
34 static int __mmplayer_track_get_language(mmplayer_t *player, mmplayer_track_type_e type, gint stream_index, gchar **code);
37 /*=======================================================================================
38 | FUNCTION DEFINITIONS |
39 =======================================================================================*/
41 _mmplayer_get_track_count(MMHandleType hplayer, mmplayer_track_type_e type, int *count)
43 int ret = MM_ERROR_NONE;
44 mmplayer_t *player = (mmplayer_t *)hplayer;
45 MMHandleType attrs = 0;
49 /* check player handle */
50 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
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);
93 LOGD("track type: %d, index: %d", type, index);
95 MMPLAYER_SUBTITLE_INFO_LOCK(player);
97 if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list) { /* external subtitle */
98 GstElement *subparse = NULL;
99 mmplayer_lang_info_t *temp = NULL;
100 guint num_of_list = 0;
102 if (!player->pipeline || !player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst) {
103 ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
107 num_of_list = g_list_length(player->subtitle_language_list);
108 if (index < 0 || index >= num_of_list) {
109 LOGE("req track index is wrong");
110 ret = MM_ERROR_INVALID_ARGUMENT;
114 temp = g_list_nth_data(player->subtitle_language_list, index);
116 LOGE("fail to get lang from list");
117 ret = MM_ERROR_PLAYER_INTERNAL;
120 subparse = player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst;
121 LOGD("setting to language %s", temp->language_code);
122 g_object_set(G_OBJECT(subparse), "current-language", temp->language_key, NULL);
124 _mmplayer_sync_subtitle_pipeline(player);
126 } else { /* audio or internal subtitle */
127 ret = _mmplayer_change_track_language(hplayer, type, index);
128 if (ret != MM_ERROR_NONE) {
129 LOGE("failed to change track");
134 if (type == MM_PLAYER_TRACK_TYPE_TEXT) {
135 if (mm_player_set_attribute(hplayer, NULL,
136 "current_text_track_index", index, NULL) != MM_ERROR_NONE) {
137 LOGE("failed to set text track index");
138 ret = MM_ERROR_PLAYER_INTERNAL;
143 LOGD("current index is updated");
146 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
152 _mmplayer_get_current_track(MMHandleType hplayer, mmplayer_track_type_e type, int *index)
154 int ret = MM_ERROR_NONE;
155 mmplayer_t *player = (mmplayer_t *)hplayer;
156 MMHandleType attrs = 0;
160 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
161 MMPLAYER_RETURN_VAL_IF_FAIL(index, MM_ERROR_INVALID_ARGUMENT);
163 attrs = MMPLAYER_GET_ATTRS(player);
164 MMPLAYER_RETURN_VAL_IF_FAIL(attrs, MM_ERROR_PLAYER_INTERNAL);
166 MMPLAYER_SUBTITLE_INFO_LOCK(player);
168 LOGD("track type: %d", type);
170 *index = INVALID_TRACK_INDEX;
173 case MM_PLAYER_TRACK_TYPE_AUDIO:
174 if (player->track[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) {
175 LOGW("there is no audio track");
176 ret = MM_ERROR_PLAYER_NO_OP;
180 *index = player->track[MM_PLAYER_TRACK_TYPE_AUDIO].active_track_index;
182 case MM_PLAYER_TRACK_TYPE_TEXT: /* internal or external */
183 mm_attrs_get_int_by_name(attrs, "content_text_track_num", &count);
185 LOGD("there is no text track");
186 ret = MM_ERROR_PLAYER_NO_OP;
190 mm_attrs_get_int_by_name(attrs, "current_text_track_index", index);
193 LOGD("invalid input type");
194 ret = MM_ERROR_INVALID_ARGUMENT;
199 LOGE("invalid track index");
200 ret = MM_ERROR_PLAYER_INTERNAL;
204 LOGD("current track index: %d", *index);
207 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
213 _mmplayer_get_track_language_code(MMHandleType hplayer, mmplayer_track_type_e type, int index, char **code)
215 int ret = MM_ERROR_NONE;
216 mmplayer_t *player = (mmplayer_t *)hplayer;
217 gchar *lang_code = NULL;
220 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
221 MMPLAYER_RETURN_VAL_IF_FAIL(code, MM_ERROR_INVALID_ARGUMENT);
223 MMPLAYER_SUBTITLE_INFO_LOCK(player);
225 if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list) { /* external subtitle */
226 mmplayer_lang_info_t *language_list = NULL;
228 lang_code = (gchar *)g_malloc0(LANGUAGE_CODE_SIZE * sizeof(char));
230 language_list = g_list_nth_data(player->subtitle_language_list, index);
231 if (language_list == NULL) {
232 LOGE("invalid index %d", index);
233 ret = MM_ERROR_INVALID_ARGUMENT;
236 g_strlcpy(lang_code, language_list->language_code, LANGUAGE_CODE_SIZE);
237 } else { /* audio or internal subtitle */
238 if (player->track[type].total_track_num <= 0) {
239 LOGW("language list is not available. [type:%d]", type);
240 ret = MM_ERROR_PLAYER_NO_OP;
244 ret = __mmplayer_track_get_language(player, type, index, &lang_code);
248 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
251 if (ret == MM_ERROR_NONE) {
252 if (g_strcmp0(lang_code, "und"))
253 *code = strndup(lang_code, 2);
255 *code = strndup("und", 3);
257 MMPLAYER_FREEIF(lang_code);
264 _mmplayer_track_initialize(mmplayer_t *player)
266 mmplayer_track_type_e type = MM_PLAYER_TRACK_TYPE_AUDIO;
270 for (; type < MM_PLAYER_TRACK_TYPE_MAX ; type++) {
271 /* active_track_index is initialized when player is created or destroyed.
272 and the value can be set by calling _mmplayer_change_track_language()
273 before pipeline is created.*/
274 player->track[type].total_track_num = 0;
275 player->track[type].streams = g_ptr_array_new();
280 _mmplayer_track_destroy(mmplayer_t *player)
282 mmplayer_track_type_e type = MM_PLAYER_TRACK_TYPE_AUDIO;
285 if (mm_player_set_attribute((MMHandleType)player, NULL, "content_text_track_num", 0,
286 "current_text_track_index", INVALID_TRACK_INDEX, NULL) != MM_ERROR_NONE)
287 LOGE("failed to reset track attr");
289 for (; type < MM_PLAYER_TRACK_TYPE_MAX ; type++) {
290 player->track[type].active_track_index = 0;
291 player->track[type].total_track_num = 0;
293 if (player->track[type].streams)
294 g_ptr_array_free(player->track[type].streams, TRUE);
295 player->track[type].streams = NULL;
300 _mmplayer_track_update_stream(mmplayer_t *player, mmplayer_track_type_e type, void *stream)
304 player->track[type].total_track_num++;
305 g_ptr_array_add(player->track[type].streams, stream);
307 LOGD("type: %d, track cnt: %d", type, player->track[type].total_track_num);
311 _mmplayer_track_update_text_attr_info(mmplayer_t *player, GstMessage *msg)
313 const GValue *lang_list = NULL;
314 mmplayer_lang_info_t *temp = NULL;
315 gchar *current_lang = NULL;
316 gint track_index = INVALID_TRACK_INDEX;
317 guint track_count = 0, index = 0;
320 MMPLAYER_RETURN_IF_FAIL(player && msg);
322 if (!gst_message_get_structure(msg)) {
323 LOGE("failed to get msg structure");
327 lang_list = gst_structure_get_value(gst_message_get_structure(msg), "lang_list");
329 LOGW("language list is null");
333 track_count = g_list_length((GList *)g_value_get_pointer(lang_list));
334 if (track_count == 0) {
335 LOGW("track count is zero");
339 MMPLAYER_SUBTITLE_INFO_LOCK(player);
340 player->subtitle_language_list = (GList *)g_value_get_pointer(lang_list);
341 mm_player_set_attribute((MMHandleType)player, NULL,
342 "content_text_track_num", (gint)track_count, NULL);
343 g_object_get(G_OBJECT(msg->src), "current-language", ¤t_lang, NULL);
345 LOGI("track count: %d, current track lang: %s", track_count, current_lang);
349 for (index = 0 ; index < track_count ; index++) {
350 temp = g_list_nth_data(player->subtitle_language_list, index);
352 LOGI("[%d] lang_key: %s, lang_code: %s",
353 index, temp->language_key, temp->language_code);
355 if (!g_strcmp0(temp->language_key, current_lang)) {
356 LOGD("current track index : %d", index);
363 if (track_index > INVALID_TRACK_INDEX)
364 mm_player_set_attribute((MMHandleType)player, NULL,
365 "current_text_track_index", track_index, NULL);
367 LOGE("failed to find current track index");
370 MMPLAYER_SUBTITLE_INFO_SIGNAL(player);
371 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
377 __mmplayer_track_get_language(mmplayer_t *player, mmplayer_track_type_e type, gint stream_index, gchar **code)
379 GstTagList *tag_list = NULL;
383 MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
384 MMPLAYER_RETURN_VAL_IF_FAIL((code && (stream_index >= 0) &&
385 (stream_index < player->track[type].total_track_num)), MM_ERROR_INVALID_ARGUMENT);
387 LOGD("type: %d, track count: %d, input idx: %d", type, player->track[type].total_track_num, stream_index);
389 *code = (gchar *)g_malloc0(LANGUAGE_CODE_SIZE * sizeof(char));
391 if (MMPLAYER_USE_DECODEBIN(player)) {
392 GstPad *sinkpad = g_ptr_array_index(player->track[type].streams, stream_index);
393 g_object_get(sinkpad, "tags", &tag_list, NULL);
395 GstStream *stream = g_ptr_array_index(player->track[type].streams, stream_index);
396 tag_list = gst_stream_get_tags (stream);
400 gst_tag_list_get_string(tag_list, GST_TAG_LANGUAGE_CODE, &tag);
403 LOGD("language code: %s, len: %zu", tag, strlen(tag));
404 g_strlcpy(*code, tag, LANGUAGE_CODE_SIZE);
405 MMPLAYER_FREEIF(tag);
407 LOGD("no language code info - und");
408 g_strlcpy(*code, "und", LANGUAGE_CODE_SIZE);
412 gst_tag_list_unref(tag_list);
415 return MM_ERROR_NONE;