_mmplayer_realize(MMHandleType hplayer)
{
mmplayer_t *player = (mmplayer_t *)hplayer;
+ int ret = MM_ERROR_NONE;
char *uri = NULL;
void *param = NULL;
MMHandleType attrs = 0;
- int ret = MM_ERROR_NONE;
-
+ int video_codec_type = 0;
+ int audio_codec_type = 0;
+ int default_codec_type = 0;
MMPLAYER_FENTER();
/* check player handle */
player->streamer->buffering_req.rebuffer_time);
}
+ mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, &audio_codec_type);
+ if (!strcmp(player->ini.audiocodec_default_type, "hw"))
+ default_codec_type = MM_PLAYER_CODEC_TYPE_HW;
+ else
+ default_codec_type = MM_PLAYER_CODEC_TYPE_SW;
+
+ if (audio_codec_type != default_codec_type) {
+ LOGD("audio dec sorting is required");
+ player->need_audio_dec_sorting = TRUE;
+ }
+
+ mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_VIDEO_CODEC_TYPE, &video_codec_type);
+ if (video_codec_type != MM_PLAYER_CODEC_TYPE_DEFAULT) {
+ LOGD("video dec sorting is required");
+ player->need_video_dec_sorting = TRUE;
+ }
+
/* realize pipeline */
ret = __mmplayer_gst_realize(player);
if (ret != MM_ERROR_NONE)
_mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), (gpointer)player);
+ if (player->need_video_dec_sorting || player->need_audio_dec_sorting)
+ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort",
+ G_CALLBACK(_mmplayer_gst_decode_autoplug_sort), (gpointer)player);
+
/* This signal is emitted whenever decodebin finds a new stream. It is emitted
before looking for any elements that can handle that stream.*/
_mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
__mmplayer_check_codec_info(mmplayer_t *player, const char *klass, GstCaps *caps, char *factory_name)
{
GstAutoplugSelectResult ret = GST_AUTOPLUG_SELECT_TRY;
- int idx = 0;
- int codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT;
int audio_offload = 0;
if ((g_strrstr(klass, "Codec/Decoder/Audio"))) {
And need to consider the multi-track audio content.
There is no HW audio decoder in public. */
- mm_attrs_get_int_by_name(player->attrs, "audio_codec_type", &codec_type);
-
- LOGD("audio codec type: %d", codec_type);
- if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
- /* sw codec will be skipped */
- for (idx = 0; player->ini.audiocodec_element_sw[idx][0] != '\0'; idx++) {
- if (strstr(factory_name, player->ini.audiocodec_element_sw[idx])) {
- LOGW("skipping sw acodec:[%s] by codec type", factory_name);
- ret = GST_AUTOPLUG_SELECT_SKIP;
- goto DONE;
- }
- }
- } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
- /* hw codec will be skipped */
- if (strcmp(player->ini.audiocodec_element_hw, "") &&
- g_strrstr(factory_name, player->ini.audiocodec_element_hw)) {
- LOGW("skipping hw acodec:[%s] by codec type", factory_name);
- ret = GST_AUTOPLUG_SELECT_SKIP;
- goto DONE;
- }
- }
-
/* set stream information */
if (!player->audiodec_linked)
__mmplayer_set_audio_attrs(player, caps);
} else if (g_strrstr(klass, "Codec/Decoder/Video")) {
- mm_attrs_get_int_by_name(player->attrs, "video_codec_type", &codec_type);
-
- LOGD("video codec type: %d", codec_type);
- if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
- /* sw codec is skipped */
- for (idx = 0; player->ini.videocodec_element_sw[idx][0] != '\0'; idx++) {
- if (strstr(factory_name, player->ini.videocodec_element_sw[idx])) {
- LOGW("skipping sw vcodec:[%s] by codec type", factory_name);
- ret = GST_AUTOPLUG_SELECT_SKIP;
- goto DONE;
- }
- }
- } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
- /* hw codec is skipped */
- if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) {
- LOGW("skipping hw vcodec:[%s] by codec type", factory_name);
- ret = GST_AUTOPLUG_SELECT_SKIP;
- goto DONE;
- }
- }
-
if ((strlen(player->ini.videocodec_element_hw) > 0) &&
(g_strrstr(factory_name, player->ini.videocodec_element_hw))) {
return ret;
}
+GValueArray *
+_mmplayer_gst_decode_autoplug_sort(GstElement *bin,
+ GstPad *pad, GstCaps *caps, GValueArray *factories, gpointer data)
+{
+#define DEFAULT_IDX 0xFFFF
+#define MIN_FACTORY_NUM 2
+ mmplayer_t *player = (mmplayer_t *)data;
+ GValueArray *new_factories = NULL;
+ GValue val = { 0, };
+ GstElementFactory *factory = NULL;
+ const gchar *klass = NULL;
+ gchar *factory_name = NULL;
+ guint hw_dec_idx = DEFAULT_IDX;
+ guint first_sw_dec_idx = DEFAULT_IDX;
+ guint last_sw_dec_idx = DEFAULT_IDX;
+ guint new_pos = DEFAULT_IDX;
+ guint rm_pos = DEFAULT_IDX;
+ int audio_codec_type;
+ int video_codec_type;
+ mmplayer_codec_type_e codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT;
+
+ if (factories->n_values < MIN_FACTORY_NUM)
+ return NULL;
+
+ mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_VIDEO_CODEC_TYPE, &video_codec_type);
+ mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, &audio_codec_type);
+
+#ifdef __DEBUG__
+ LOGD("num of factory : %d, codec type %d, %d", factories->n_values, video_codec_type, audio_codec_type);
+#endif
+ for (int i = 0 ; i < factories->n_values ; i++) {
+ gchar *hw_dec_info = NULL;
+ gchar (*sw_dec_info)[PLAYER_INI_MAX_STRLEN] = {NULL, };
+
+ factory = g_value_get_object(g_value_array_get_nth(factories, i));
+ klass = gst_element_factory_get_klass(factory);
+ factory_name = GST_OBJECT_NAME(factory);
+
+#ifdef __DEBUG__
+ LOGD("Klass [%s] Factory [%s]", klass, factory_name);
+#endif
+ if (g_strrstr(klass, "Codec/Decoder/Audio")) {
+ if (!player->need_audio_dec_sorting) {
+ LOGD("sorting is not required");
+ return NULL;
+ }
+ codec_type = audio_codec_type;
+ hw_dec_info = player->ini.audiocodec_element_hw;
+ sw_dec_info = player->ini.audiocodec_element_sw;
+ } else if (g_strrstr(klass, "Codec/Decoder/Video")) {
+ if (!player->need_video_dec_sorting) {
+ LOGD("sorting is not required");
+ return NULL;
+ }
+ codec_type = video_codec_type;
+ hw_dec_info = player->ini.videocodec_element_hw;
+ sw_dec_info = player->ini.videocodec_element_sw;
+ } else {
+ continue;
+ }
+
+ if (g_strrstr(factory_name, hw_dec_info)) {
+ hw_dec_idx = i;
+ } else {
+ for (int j = 0; sw_dec_info[j][0] != '\0'; j++) {
+ if (strstr(factory_name, sw_dec_info[j])) {
+ last_sw_dec_idx = i;
+ if (first_sw_dec_idx == DEFAULT_IDX) {
+ first_sw_dec_idx = i;
+ }
+ }
+ }
+
+ if (first_sw_dec_idx == DEFAULT_IDX)
+ LOGW("unknown codec %s", factory_name);
+ }
+ }
+
+ if (hw_dec_idx == DEFAULT_IDX || first_sw_dec_idx == DEFAULT_IDX)
+ return NULL;
+
+ if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
+ if (hw_dec_idx < first_sw_dec_idx)
+ return NULL;
+ new_pos = first_sw_dec_idx - 1;
+ rm_pos = hw_dec_idx + 1;
+ } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
+ if (last_sw_dec_idx < hw_dec_idx)
+ return NULL;
+ new_pos = last_sw_dec_idx + 1;
+ rm_pos = hw_dec_idx;
+ } else {
+ return NULL;
+ }
+
+ /* change position - insert H/W decoder according to the new position */
+ new_factories = g_value_array_copy(factories);
+ factory = g_value_get_object(g_value_array_get_nth(factories, hw_dec_idx));
+ g_value_init (&val, G_TYPE_OBJECT);
+ g_value_set_object (&val, factory);
+ g_value_array_insert(new_factories, new_pos, &val);
+ g_value_unset (&val);
+ g_value_array_remove(new_factories, rm_pos); /* remove previous H/W element */
+
+ for (int i = 0 ; i < new_factories->n_values ; i++) {
+ factory = g_value_get_object(g_value_array_get_nth(new_factories, i));
+
+ LOGD("[Re-arranged] Klass [%s] Factory [%s]",
+ gst_element_factory_get_klass(factory), GST_OBJECT_NAME (factory));
+ }
+
+ return new_factories;
+}
+
gint
_mmplayer_gst_decode_autoplug_select(GstElement *bin, GstPad *pad,
GstCaps *caps, GstElementFactory *factory, gpointer data)