#include "mm_player_priv.h"
#include "mm_player_ini.h"
-#include "mm_player_attrs.h"
#include "mm_player_capture.h"
#include "mm_player_utils.h"
#include "mm_player_tracks.h"
#define MM_VOLUME_FACTOR_MAX 1.0
/* Don't need to sleep for sound fadeout
- * fadeout related fucntion will be deleted(Deprecated)
+ * fadeout related function will be deleted(Deprecated)
*/
#define MM_PLAYER_FADEOUT_TIME_DEFAULT 0
#define DEFAULT_PLAYBACK_RATE 1.0
-#define DEFAULT_NUM_OF_V_OUT_BUFFER 3
#define PLAYER_DISPLAY_MODE_DST_ROI 5
#define FAKE_SINK_MAX_LATENESS G_GINT64_CONSTANT(20000000) /* set 20ms as waylandsink */
+#define DEFAULT_PCM_OUT_FORMAT "F32LE"
+#define DEFAULT_PCM_OUT_SAMPLERATE 44100
+#define DEFAULT_PCM_OUT_CHANNEL 2
+
/*---------------------------------------------------------------------------
| LOCAL CONSTANT DEFINITIONS: |
---------------------------------------------------------------------------*/
static int __mmplayer_gst_create_video_sink_bin(mmplayer_t *player, GstCaps *caps, MMDisplaySurfaceType surface_type);
static int __mmplayer_gst_create_audio_sink_bin(mmplayer_t *player);
static int __mmplayer_gst_create_text_sink_bin(mmplayer_t *player);
-
-static GstPadProbeReturn __mmplayer_gst_selector_blocked(GstPad *pad, GstPadProbeInfo *info, gpointer data);
-static void __mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data);
-static void __mmplayer_gst_create_sinkbin(GstElement *decodebin, GstPad *pad, gpointer data);
-static void __mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad, GstCaps *caps, gpointer data);
-static gboolean __mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad, GstCaps *caps, gpointer data);
-static void __mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad, gpointer data);
-static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data);
-static void __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data);
+static void __mmplayer_gst_create_sink_bin(GstElement *decodebin, GstPad *pad, GstCaps *ref_caps, gpointer data);
+static gboolean __mmplayer_create_sink_path(mmplayer_t *player, GstElement *combiner, mmplayer_track_type_e type, GstCaps *caps);
static gboolean __mmplayer_is_midi_type(gchar *str_caps);
static gboolean __mmplayer_is_only_mp3_type(gchar *str_caps);
-static void __mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps);
static gboolean __mmplayer_update_subtitle(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer data);
static void __mmplayer_release_misc(mmplayer_t *player);
static gboolean __mmplayer_check_subtitle(mmplayer_t *player);
static int __mmplayer_handle_missed_plugin(mmplayer_t *player);
static int __mmplayer_check_not_supported_codec(mmplayer_t *player, const gchar *factory_class, const gchar *mime);
-static void __mmplayer_add_sink(mmplayer_t *player, GstElement *sink);
+static void __mmplayer_add_sink(mmplayer_t *player, GstElement *sink, gboolean first);
static void __mmplayer_del_sink(mmplayer_t *player, GstElement *sink);
static void __mmplayer_release_signal_connection(mmplayer_t *player, mmplayer_signal_type_e type);
static gpointer __mmplayer_gapless_play_thread(gpointer data);
/* util */
static gboolean __mmplayer_verify_gapless_play_path(mmplayer_t *player);
-static void __mmplayer_activate_next_source(mmplayer_t *player, GstState target);
-static void __mmplayer_check_pipeline(mmplayer_t *player);
+static void __mmplayer_check_pipeline_reconfigure_state(mmplayer_t *player);
static gboolean __mmplayer_deactivate_selector(mmplayer_t *player, mmplayer_track_type_e type);
+static gboolean __mmplayer_deactivate_combiner(mmplayer_t *player, mmplayer_track_type_e type);
static void __mmplayer_deactivate_old_path(mmplayer_t *player);
static int __mmplayer_gst_create_plain_text_elements(mmplayer_t *player);
static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar *format_name);
static void __mmplayer_gst_caps_notify_cb(GstPad *pad, GParamSpec *unused, gpointer data);
static void __mmplayer_audio_stream_send_data(mmplayer_t *player, mmplayer_audio_stream_buff_t *a_buffer);
static void __mmplayer_initialize_storage_info(mmplayer_t *player, mmplayer_path_type_e path_type);
-static int __resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res, void *user_data);
static gboolean __mmplayer_update_duration_value(mmplayer_t *player);
static gboolean __mmplayer_update_audio_attrs(mmplayer_t *player, MMHandleType attrs);
static gboolean __mmplayer_update_video_attrs(mmplayer_t *player, MMHandleType attrs);
| |
========================================================================================== */
-#if 0 //debug
-static void
-print_tag(const GstTagList *list, const gchar *tag, gpointer unused)
-{
- gint i, count;
-
- count = gst_tag_list_get_tag_size(list, tag);
-
- LOGD("count = %d", count);
-
- for (i = 0; i < count; i++) {
- gchar *str;
-
- if (gst_tag_get_type(tag) == G_TYPE_STRING) {
- if (!gst_tag_list_get_string_index(list, tag, i, &str))
- g_assert_not_reached();
- } else {
- str = g_strdup_value_contents(gst_tag_list_get_value_index(list, tag, i));
- }
-
- if (i == 0)
- g_print(" %15s: %s", gst_tag_get_nick(tag), str);
- else
- g_print(" : %s", str);
-
- g_free(str);
- }
-}
-#endif
-
/* This function should be called after the pipeline goes PAUSED or higher
state. */
gboolean
-__mmplayer_update_content_attrs(mmplayer_t *player, enum content_attr_flag flag)
+_mmplayer_update_content_attrs(mmplayer_t *player, enum content_attr_flag flag)
{
static gboolean has_duration = FALSE;
static gboolean has_video_attrs = FALSE;
if ((flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all)
has_bitrate = __mmplayer_update_bitrate_attrs(player, attrs);
- /* validate all */
- if (mm_attrs_commit_all(attrs)) {
- LOGE("failed to update attributes");
- return FALSE;
- }
-
MMPLAYER_FLEAVE();
return TRUE;
}
MMStreamingType
-__mmplayer_get_stream_service_type(mmplayer_t *player)
+_mmplayer_get_stream_service_type(mmplayer_t *player)
{
MMStreamingType streaming_type = STREAMING_SERVICE_NONE;
}
/* this function sets the player state and also report
- * it to applicaton by calling callback function
+ * it to application by calling callback function
*/
void
-__mmplayer_set_state(mmplayer_t *player, int state)
+_mmplayer_set_state(mmplayer_t *player, int state)
{
MMMessageParamType msg = {0, };
}
int
-__mmplayer_check_state(mmplayer_t *player, mmplayer_command_state_e command)
+_mmplayer_check_state(mmplayer_t *player, mmplayer_command_state_e command)
{
mmplayer_state_e current_state = MM_PLAYER_STATE_NUM;
mmplayer_state_e pending_state = MM_PLAYER_STATE_NUM;
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- //LOGD("incomming command : %d ", command);
-
+#ifdef __DEBUG__
+ LOGD("incoming command : %d ", command);
+#endif
current_state = MMPLAYER_CURRENT_STATE(player);
pending_state = MMPLAYER_PENDING_STATE(player);
if (pending_state == MM_PLAYER_STATE_NONE) {
if (current_state == MM_PLAYER_STATE_PAUSED)
goto NO_OP;
- else if (current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY) // support loading state of broswer
+ else if (current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY) // support loading state of browser
goto INVALID_STATE;
} else if (pending_state == MM_PLAYER_STATE_PAUSED) {
goto ALREADY_GOING;
return MM_ERROR_PLAYER_NO_OP;
}
+int _mmplayer_acquire_hw_resource(mmplayer_t *player, mmplayer_resource_type_e type)
+{
+ int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
+ mm_resource_manager_res_type_e rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_MAX;
+
+ switch (type) {
+ case MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER:
+ rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER;
+ break;
+ case MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY:
+ rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY;
+ break;
+ case MMPLAYER_RESOURCE_TYPE_AUDIO_OFFLOAD:
+ rm_res_type = MM_RESOURCE_MANAGER_RES_TYPE_AUDIO_OFFLOAD;
+ break;
+ default:
+ LOGE("invalid mmplayer resource type %d", type);
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+
+ if (player->hw_resource[type] != NULL) {
+ LOGD("[%d type] resource was already acquired", type);
+ return MM_ERROR_NONE;
+ }
+
+ LOGD("mark for acquire [%d type] resource", type);
+ rm_ret = mm_resource_manager_mark_for_acquire(player->resource_manager,
+ rm_res_type, MM_RESOURCE_MANAGER_RES_VOLUME_FULL, &player->hw_resource[type]);
+ if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+ LOGE("failed to mark resource for acquire, ret(0x%x)", rm_ret);
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+
+ LOGD("commit [%d type] resource", type);
+ rm_ret = mm_resource_manager_commit(player->resource_manager);
+ if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+ LOGE("failed to commit of resource, ret(0x%x)", rm_ret);
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
+}
+
+static void __mmplayer_destroy_hw_resource(mmplayer_t *player)
+{
+ int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
+
+ MMPLAYER_RETURN_IF_FAIL(player);
+ MMPLAYER_RETURN_IF_FAIL(player->resource_manager);
+
+ rm_ret = mm_resource_manager_mark_all_for_release(player->resource_manager);
+ if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+ LOGW("failed to mark all for release of resource, ret(0x%x)", rm_ret);
+ goto rm_destroy;
+ }
+
+ rm_ret = mm_resource_manager_commit(player->resource_manager);
+ if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE)
+ LOGW("failed to commit resource, ret(0x%x)", rm_ret);
+
+rm_destroy:
+ /* de-initialize resource manager */
+ rm_ret = mm_resource_manager_destroy(player->resource_manager);
+ if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+ LOGW("failed to destroy resource manager, ret(0x%x)", rm_ret);
+ return;
+ }
+
+ player->resource_manager = NULL;
+
+ LOGD("resource manager is destroyed");
+}
+
+static int __mmplayer_release_hw_resource(mmplayer_t *player, mmplayer_resource_type_e type)
+{
+ int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
+
+ MMPLAYER_FENTER();
+
+ if (player->hw_resource[type] == NULL) {
+ LOGD("there is no acquired [%d type] resource", type);
+ return MM_ERROR_NONE;
+ }
+
+ LOGD("mark for release [%d type] resource", type);
+ rm_ret = mm_resource_manager_mark_for_release(player->resource_manager, player->hw_resource[type]);
+ if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+ LOGE("failed to mark resource for release, ret(0x%x)", rm_ret);
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+
+ player->hw_resource[type] = NULL;
+
+ LOGD("commit [%d type] resource", type);
+ rm_ret = mm_resource_manager_commit(player->resource_manager);
+ if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
+ LOGE("failed to commit resource, ret(0x%x)", rm_ret);
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
+}
+
+static void
+__mmplayer_initialize_gapless_play(mmplayer_t *player)
+{
+ int i;
+
+ MMPLAYER_FENTER();
+
+ player->smooth_streaming = FALSE;
+ player->videodec_linked = 0;
+ player->audiodec_linked = 0;
+ player->textsink_linked = 0;
+ player->is_external_subtitle_present = FALSE;
+ player->is_external_subtitle_added_now = FALSE;
+ player->not_supported_codec = MISSING_PLUGIN_NONE;
+ player->can_support_codec = FOUND_PLUGIN_NONE;
+ player->pending_seek.is_pending = false;
+ player->pending_seek.pos = 0;
+ player->msg_posted = FALSE;
+ player->has_many_types = FALSE;
+ player->no_more_pad = FALSE;
+ player->not_found_demuxer = 0;
+ player->seek_state = MMPLAYER_SEEK_NONE;
+ player->is_subtitle_force_drop = FALSE;
+ player->play_subtitle = FALSE;
+ player->adjust_subtitle_pos = 0;
+
+ player->total_bitrate = 0;
+ player->total_maximum_bitrate = 0;
+
+ _mmplayer_track_initialize(player);
+ __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
+
+ for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) {
+ player->bitrate[i] = 0;
+ player->maximum_bitrate[i] = 0;
+ }
+
+ if (player->v_stream_caps) {
+ gst_caps_unref(player->v_stream_caps);
+ player->v_stream_caps = NULL;
+ }
+
+ mm_player_set_attribute((MMHandleType)player, NULL, "content_video_found", 0, NULL);
+
+ /* clean found audio decoders */
+ if (player->audio_decoders) {
+ g_list_free_full(player->audio_decoders, (GDestroyNotify)g_free);
+ player->audio_decoders = NULL;
+ }
+
+ __mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER);
+
+ MMPLAYER_FLEAVE();
+}
+
+void _mmplayer_set_reconfigure_state(mmplayer_t *player, gboolean state)
+{
+ LOGI("set pipeline reconfigure state %d", state);
+ MMPLAYER_RECONFIGURE_LOCK(player);
+ player->gapless.reconfigure = state;
+ if (!state) /* wake up the waiting job */
+ MMPLAYER_RECONFIGURE_SIGNAL(player);
+ MMPLAYER_RECONFIGURE_UNLOCK(player);
+}
+
static gpointer
__mmplayer_gapless_play_thread(gpointer data)
{
LOGD("reconfigure pipeline for gapless play.");
if (player->gapless_play_thread_exit) {
- if (player->gapless.reconfigure) {
- player->gapless.reconfigure = false;
- MMPLAYER_PLAYBACK_UNLOCK(player);
- }
+ _mmplayer_set_reconfigure_state(player, FALSE);
LOGD("exiting gapless play thread");
break;
}
MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
- __mmplayer_activate_next_source(player, GST_STATE_PLAYING);
+ /* Initialize Player values */
+ __mmplayer_initialize_gapless_play(player);
+
+ _mmplayer_activate_next_source(player, GST_STATE_PLAYING);
}
MMPLAYER_GAPLESS_PLAY_THREAD_UNLOCK(player);
}
void
-__mmplayer_bus_msg_thread_destroy(MMHandleType hplayer)
+_mmplayer_watcher_removed_notify(gpointer data)
{
- mmplayer_t *player = (mmplayer_t *)hplayer;
- GstMessage *msg = NULL;
- GQueue *queue = NULL;
+ mmplayer_t *player = (mmplayer_t *)data;
+ MMPLAYER_RETURN_IF_FAIL(player);
+
+ MMPLAYER_BUS_WATCHER_LOCK(player);
+ player->bus_watcher = 0;
+ MMPLAYER_BUS_WATCHER_SIGNAL(player);
+ MMPLAYER_BUS_WATCHER_UNLOCK(player);
+}
+void
+_mmplayer_bus_watcher_remove(MMHandleType hplayer)
+{
+ mmplayer_t *player = (mmplayer_t *)hplayer;
+ gint64 end_time = 0;
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player);
/* disconnecting bus watch */
- if (player->bus_watcher)
+ if (player->bus_watcher > 0) {
__mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
- player->bus_watcher = 0;
+ MMPLAYER_BUS_WATCHER_LOCK(player);
+ end_time = g_get_monotonic_time () + 2 * G_TIME_SPAN_SECOND;
+ while (player->bus_watcher > 0)
+ MMPLAYER_BUS_WATCHER_WAIT_UNTIL(player, end_time);
+ MMPLAYER_BUS_WATCHER_UNLOCK(player);
+
+ g_mutex_clear(&player->bus_watcher_mutex);
+ g_cond_clear(&player->bus_watcher_cond);
+ }
+
+ MMPLAYER_FLEAVE();
+}
+
+void
+_mmplayer_bus_msg_thread_destroy(MMHandleType hplayer)
+{
+ mmplayer_t *player = (mmplayer_t *)hplayer;
+ GstMessage *msg = NULL;
+ GQueue *queue = NULL;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(player);
/* destroy the gst bus msg thread */
if (player->bus_msg_thread) {
}
gboolean
-__mmplayer_gst_remove_fakesink(mmplayer_t *player, mmplayer_gst_element_t *fakesink)
+_mmplayer_gst_remove_fakesink(mmplayer_t *player, mmplayer_gst_element_t *fakesink)
{
GstElement *parent = NULL;
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, FALSE);
-
- /* if we have no fakesink. this meas we are using decodebin which doesn'
- t need to add extra fakesink */
- MMPLAYER_RETURN_VAL_IF_FAIL(fakesink, TRUE);
+ MMPLAYER_RETURN_VAL_IF_FAIL(fakesink && fakesink->gst, TRUE);
/* lock */
MMPLAYER_FSINK_LOCK(player);
- if (!fakesink->gst)
- goto ERROR;
-
/* get parent of fakesink */
parent = (GstElement *)gst_object_get_parent((GstObject *)fakesink->gst);
if (!parent) {
gst_element_set_locked_state(fakesink->gst, TRUE);
/* setting the state to NULL never returns async
- * so no need to wait for completion of state transiton
+ * so no need to wait for completion of state transition
*/
if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(fakesink->gst, GST_STATE_NULL))
LOGE("fakesink state change failure!");
for (idx = MM_PLAYER_TRACK_TYPE_AUDIO; idx < MM_PLAYER_TRACK_TYPE_TEXT; idx++) {
if ((player->gapless.update_segment[idx] == TRUE) ||
- !(player->selector[idx].event_probe_id)) {
- /* LOGW("[%d] skip", idx); */
+ !(player->track[idx].event_probe_id)) {
+#ifdef __DEBUG__
+ LOGW("[%d] skip", idx);
+#endif
continue;
}
mmplayer_track_type_e stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
gboolean caps_ret = TRUE;
- if (GST_EVENT_IS_DOWNSTREAM(event) &&
- GST_EVENT_TYPE(event) != GST_EVENT_STREAM_START &&
- GST_EVENT_TYPE(event) != GST_EVENT_FLUSH_STOP &&
- GST_EVENT_TYPE(event) != GST_EVENT_SEGMENT &&
- GST_EVENT_TYPE(event) != GST_EVENT_EOS) {
+ if (GST_EVENT_TYPE(event) != GST_EVENT_STREAM_START &&
+ GST_EVENT_TYPE(event) != GST_EVENT_FLUSH_STOP &&
+ GST_EVENT_TYPE(event) != GST_EVENT_SEGMENT &&
+ GST_EVENT_TYPE(event) != GST_EVENT_EOS &&
+ GST_EVENT_TYPE(event) != GST_EVENT_QOS)
return ret;
- } else if (GST_EVENT_IS_UPSTREAM(event) &&
- GST_EVENT_TYPE(event) != GST_EVENT_QOS) {
- return ret;
- }
- MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
+ MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(pad, caps, str, name, caps_ret);
if (!caps_ret)
goto ERROR;
break;
}
+#ifdef __DEBUG__
LOGD("[%d] Adjusting QOS event: %" GST_TIME_FORMAT
" - %" GST_TIME_FORMAT " = %" GST_TIME_FORMAT,
stream_type, GST_TIME_ARGS(timestamp),
GST_TIME_ARGS(running_time_diff),
GST_TIME_ARGS(timestamp - running_time_diff));
+#endif
timestamp -= running_time_diff;
return ret;
}
-/* create fakesink for audio or video path witout audiobin or videobin */
+/* create fakesink for audio or video path without audiobin or videobin */
static void
__mmplayer_gst_make_fakesink(mmplayer_t *player, GstPad *pad, const gchar *name)
{
}
/* store it as it's sink element */
- __mmplayer_add_sink(player, fakesink);
+ __mmplayer_add_sink(player, fakesink, FALSE);
gst_bin_add(GST_BIN(pipeline), fakesink);
}
static GstElement *
+__mmplayer_gst_make_concat(mmplayer_t *player, main_element_id_e elem_idx)
+{
+ GstElement *pipeline = NULL;
+ GstElement *concat = NULL;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, NULL);
+
+ concat = gst_element_factory_make("concat", NULL);
+ if (!concat) {
+ LOGE("failed to create concat");
+ return NULL;
+ }
+
+ LOGD("Create concat [%d] element", elem_idx);
+
+ player->pipeline->mainbin[elem_idx].id = elem_idx;
+ player->pipeline->mainbin[elem_idx].gst = concat;
+
+ gst_element_set_state(concat, GST_STATE_PAUSED);
+
+ pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
+ gst_bin_add(GST_BIN(pipeline), concat);
+
+ MMPLAYER_FLEAVE();
+ return concat;
+}
+
+static GstElement *
__mmplayer_gst_make_selector(mmplayer_t *player, main_element_id_e elem_idx, mmplayer_track_type_e stream_type)
{
GstElement *pipeline = NULL;
player->pipeline->mainbin[elem_idx].id = elem_idx;
player->pipeline->mainbin[elem_idx].gst = selector;
- /* player->selector[stream_type].active_pad_index = DEFAULT_TRACK; */
+ /* player->track[stream_type].active_track_index = DEFAULT_TRACK; */
srcpad = gst_element_get_static_pad(selector, "src");
LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
- player->selector[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
+ player->track[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
__mmplayer_gst_selector_blocked, NULL, NULL);
- player->selector[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH,
+ player->track[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH,
__mmplayer_gst_selector_event_probe, player, NULL);
gst_element_set_state(selector, GST_STATE_PAUSED);
}
void
-__mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
+_mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
{
mmplayer_t *player = (mmplayer_t *)data;
- GstElement *selector = NULL;
+ GstElement *combiner = NULL;
GstCaps *caps = NULL;
GstStructure *str = NULL;
const gchar *name = NULL;
LOGD("pad-added signal handling");
/* get mimetype from caps */
- MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
+ MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(pad, caps, str, name, caps_ret);
if (!caps_ret)
goto ERROR;
MMPLAYER_LOG_GST_CAPS_TYPE(caps);
- /* LOGD("detected mimetype : %s", name); */
+#ifdef __DEBUG__
+ LOGD("detected mimetype : %s", name);
+#endif
if (strstr(name, "video")) {
gint stype = 0;
MMPLAYER_FREEIF(caps_str);
- mm_attrs_set_int_by_name(player->attrs, "content_video_found", TRUE);
+ mm_player_set_attribute((MMHandleType)player, NULL, "content_video_found", TRUE, NULL);
mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
LOGD("surface type : %d", stype);
if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
- __mmplayer_gst_create_sinkbin(elem, pad, player);
+ __mmplayer_gst_create_sink_bin(elem, pad, caps, player);
goto DONE;
}
/* in case of exporting video frame, it requires the 360 video filter.
* it will be handled in _no_more_pads(). */
- if ((stype == MM_DISPLAY_SURFACE_NULL) && (!player->set_mode.media_packet_video_stream)) {
+ if ((stype == MM_DISPLAY_SURFACE_NULL) && (!player->set_mode.video_export)) {
__mmplayer_gst_make_fakesink(player, pad, name);
goto DONE;
}
- LOGD("video selector is required");
- elem_idx = MMPLAYER_M_V_INPUT_SELECTOR;
+ if (MMPLAYER_USE_DECODEBIN(player)) {
+ LOGD("video selector is required");
+ elem_idx = MMPLAYER_M_V_INPUT_SELECTOR;
+ } else {
+ LOGD("video concat is required");
+ elem_idx = MMPLAYER_M_V_CONCAT;
+ }
stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
} else if (strstr(name, "audio")) {
gint samplerate = 0;
if (MMPLAYER_IS_MS_BUFF_SRC(player) || player->build_audio_offload) {
if (player->build_audio_offload)
player->no_more_pad = TRUE; /* remove state holder */
- __mmplayer_gst_create_sinkbin(elem, pad, player);
+ __mmplayer_gst_create_sink_bin(elem, pad, caps, player);
goto DONE;
}
__mmplayer_gst_make_fakesink(player, pad, name);
goto DONE;
}
-
- LOGD("audio selector is required");
- elem_idx = MMPLAYER_M_A_INPUT_SELECTOR;
+ if (MMPLAYER_USE_DECODEBIN(player)) {
+ LOGD("audio selector is required");
+ elem_idx = MMPLAYER_M_A_INPUT_SELECTOR;
+ } else {
+ LOGD("audio concat is required");
+ elem_idx = MMPLAYER_M_A_CONCAT;
+ }
stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
} else if (strstr(name, "text")) {
- LOGD("text selector is required");
- elem_idx = MMPLAYER_M_T_INPUT_SELECTOR;
+ if (MMPLAYER_USE_DECODEBIN(player)) {
+ LOGD("text selector is required");
+ elem_idx = MMPLAYER_M_T_INPUT_SELECTOR;
+ } else {
+ LOGD("text concat is required");
+ elem_idx = MMPLAYER_M_T_CONCAT;
+ }
stream_type = MM_PLAYER_TRACK_TYPE_TEXT;
} else {
LOGE("invalid caps info");
}
/* check selector and create it */
- if (!(selector = player->pipeline->mainbin[elem_idx].gst)) {
- selector = __mmplayer_gst_make_selector(player, elem_idx, stream_type);
- if (!selector)
+ if (!(combiner = player->pipeline->mainbin[elem_idx].gst)) {
+ if (MMPLAYER_USE_DECODEBIN(player))
+ combiner = __mmplayer_gst_make_selector(player, elem_idx, stream_type);
+ else
+ combiner = __mmplayer_gst_make_concat(player, elem_idx);
+
+ if (!combiner)
goto ERROR;
first_track = TRUE;
} else {
- LOGD("input-selector is already created.");
+ LOGD("Combiner element is already created.");
}
/* link */
- sinkpad = gst_element_get_request_pad(selector, "sink_%u");
+ sinkpad = gst_element_get_request_pad(combiner, "sink_%u");
LOGD("pad link: %s:%s - %s:%s", GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(sinkpad));
if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) {
- LOGE("failed to link selector");
- gst_object_unref(GST_OBJECT(selector));
+ LOGE("failed to link combiner");
+ gst_object_unref(GST_OBJECT(combiner));
goto ERROR;
}
if (first_track) {
- LOGD("this track will be activated");
- g_object_set(selector, "active-pad", sinkpad, NULL);
+ if (MMPLAYER_USE_DECODEBIN(player)) {
+ LOGD("this track will be activated");
+ g_object_set(combiner, "active-pad", sinkpad, NULL);
+ }
}
- __mmplayer_track_update_selector_info(player, stream_type, sinkpad);
+ if (MMPLAYER_USE_DECODEBIN(player)) {
+ _mmplayer_track_update_stream(player, stream_type, sinkpad);
+ } else {
+ /* apply the text track information */
+ if (stream_type == MM_PLAYER_TRACK_TYPE_TEXT)
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ "content_text_track_num", player->track[stream_type].total_track_num,
+ "current_text_track_index", player->track[stream_type].active_track_index, NULL);
+ __mmplayer_create_sink_path(player, combiner, stream_type, caps);
+ }
DONE:
ERROR:
}
static gboolean
-__mmplayer_create_sink_path(mmplayer_t *player, GstElement *selector, mmplayer_track_type_e type)
+__mmplayer_create_sink_path(mmplayer_t *player, GstElement *combiner, mmplayer_track_type_e type, GstCaps *caps)
{
GstPad *srcpad = NULL;
LOGD("type %d", type);
- if (!selector) {
+ if (!combiner) {
LOGD("there is no %d track", type);
return TRUE;
}
- srcpad = gst_element_get_static_pad(selector, "src");
+ srcpad = gst_element_get_static_pad(combiner, "src");
if (!srcpad) {
- LOGE("failed to get srcpad from selector");
+ LOGE("failed to get srcpad from combiner");
return FALSE;
}
- LOGD("got pad %s:%s from selector", GST_DEBUG_PAD_NAME(srcpad));
+ LOGD("got pad %s:%s from combiner", GST_DEBUG_PAD_NAME(srcpad));
- __mmplayer_gst_create_sinkbin(selector, srcpad, player);
+ __mmplayer_gst_create_sink_bin(combiner, srcpad, caps, player);
LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
- if (player->selector[type].block_id) {
- gst_pad_remove_probe(srcpad, player->selector[type].block_id);
- player->selector[type].block_id = 0;
+ if (player->track[type].block_id) {
+ gst_pad_remove_probe(srcpad, player->track[type].block_id);
+ player->track[type].block_id = 0;
}
if (srcpad) {
static void
__mmplayer_set_decode_track_info(mmplayer_t *player, mmplayer_track_type_e type)
{
- MMHandleType attrs = 0;
gint active_index = 0;
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player);
- LOGD("type: %d, the num of track: %d", type, player->selector[type].total_track_num);
+ LOGD("type: %d, the num of track: %d", type, player->track[type].total_track_num);
/* change track to active pad */
- active_index = player->selector[type].active_pad_index;
+ active_index = player->track[type].active_track_index;
if ((active_index != DEFAULT_TRACK) &&
(__mmplayer_change_selector_pad(player, type, active_index) != MM_ERROR_NONE)) {
LOGW("failed to change %d type track to %d", type, active_index);
- player->selector[type].active_pad_index = DEFAULT_TRACK;
+ player->track[type].active_track_index = DEFAULT_TRACK;
return;
}
- if (type == MM_PLAYER_TRACK_TYPE_TEXT) {
- attrs = MMPLAYER_GET_ATTRS(player);
- if (attrs) {
- mm_attrs_set_int_by_name(attrs, "content_text_track_num", player->selector[type].total_track_num);
- mm_attrs_set_int_by_name(attrs, "current_text_track_index", player->selector[type].active_pad_index);
-
- if (mm_attrs_commit_all(attrs))
- LOGW("failed to commit attrs.");
- } else {
- LOGW("cannot get content attribute");
- }
- }
+ if (type == MM_PLAYER_TRACK_TYPE_TEXT)
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ "content_text_track_num", player->track[type].total_track_num,
+ "current_text_track_index", player->track[type].active_track_index, NULL);
MMPLAYER_FLEAVE();
return;
}
if (player->num_dynamic_pad == 0) /* FIXME: num_dynamic_pad is only for rtsp? */
- __mmplayer_pipeline_complete(NULL, player);
+ _mmplayer_pipeline_complete(NULL, player);
return TRUE;
}
/* apply the audio track information */
- __mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_AUDIO);
+ if (MMPLAYER_USE_DECODEBIN(player))
+ __mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_AUDIO);
/* create audio sink path */
- if (!__mmplayer_create_sink_path(player, audio_selector, MM_PLAYER_TRACK_TYPE_AUDIO)) {
+ if (!__mmplayer_create_sink_path(player, audio_selector, MM_PLAYER_TRACK_TYPE_AUDIO, NULL)) {
LOGE("failed to create audio sink path");
return FALSE;
}
MMPLAYER_RETURN_VAL_IF_FAIL(player && text_selector, FALSE);
if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
- LOGD("text path is not supproted");
+ LOGD("text path is not supported");
return TRUE;
}
/* apply the text track information */
__mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_TEXT);
- if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
+ if (player->track[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
player->has_closed_caption = TRUE;
/* create text decode path */
player->no_more_pad = TRUE;
- if (!__mmplayer_create_sink_path(player, text_selector, MM_PLAYER_TRACK_TYPE_TEXT)) {
+ if (!__mmplayer_create_sink_path(player, text_selector, MM_PLAYER_TRACK_TYPE_TEXT, NULL)) {
LOGE("failed to create text sink path");
return FALSE;
}
/* there is no mq, enable use-buffering on queue2 (ex) wav streaming
* use file information was already set on Q2 when it was created. */
- __mm_player_streaming_set_queue2(player->streamer,
+ _mm_player_streaming_set_queue2(player->streamer,
player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
TRUE, /* use_buffering */
MUXED_BUFFER_TYPE_MAX, /* use previous buffer type setting */
return TRUE;
}
-static void
-__mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data)
+void
+_mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data)
{
mmplayer_t *player = NULL;
GstElement *video_selector = NULL;
if (video_selector && !audio_selector && !text_selector)
player->no_more_pad = TRUE;
- if (!__mmplayer_create_sink_path(player, video_selector, MM_PLAYER_TRACK_TYPE_VIDEO))
+ if (!__mmplayer_create_sink_path(player, video_selector, MM_PLAYER_TRACK_TYPE_VIDEO, NULL))
goto EXIT;
/* create audio path followed by audio-select */
__mmplayer_create_text_sink_path(player, text_selector);
EXIT:
- if (player->gapless.reconfigure) {
- player->gapless.reconfigure = FALSE;
- MMPLAYER_PLAYBACK_UNLOCK(player);
- }
-
+ _mmplayer_set_reconfigure_state(player, FALSE);
MMPLAYER_FLEAVE();
}
}
static void
-__mmplayer_gst_create_sinkbin(GstElement *elem, GstPad *pad, gpointer data)
+__mmplayer_gst_create_sink_bin(GstElement *elem, GstPad *pad, GstCaps *ref_caps, gpointer data)
{
mmplayer_t *player = NULL;
GstCaps *caps = NULL;
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(elem && pad);
MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && MMPLAYER_GET_ATTRS(player));
-
- MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
- if (!caps_ret)
- goto ERROR;
+ MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(pad, caps, str, name, caps_ret);
+ if (!caps_ret) {
+ MMPLAYER_GST_GET_CAPS_INFO(ref_caps, str, name, caps_ret);
+ if (!caps_ret)
+ goto ERROR;
+ if (caps)
+ gst_caps_unref(caps);
+ caps = gst_caps_ref(ref_caps);
+ }
caps_str = gst_caps_to_string(caps);
-
- /* LOGD("detected mimetype : %s", name); */
+#ifdef __DEBUG__
+ LOGD("detected mimetype : %s", name);
+#endif
if (strstr(name, "audio")) {
if (player->pipeline->audiobin == NULL) {
+ const gchar *audio_format = gst_structure_get_string(str, "format");
+ if (audio_format) {
+ LOGD("original audio format %s", audio_format);
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ "content_audio_format", audio_format, strlen(audio_format), NULL);
+ }
+
if (__mmplayer_gst_create_audio_sink_bin(player) != MM_ERROR_NONE) {
LOGE("failed to create audiobin. continuing without audio");
goto ERROR;
reusing = TRUE;
sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
LOGD("reusing audiobin");
- __mmplayer_update_content_attrs(player, ATTR_AUDIO);
+ _mmplayer_update_content_attrs(player, ATTR_AUDIO);
}
} else if (strstr(name, "video")) {
/* 1. zero copy is updated at _decode_pad_added()
mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
LOGD("display_surface_type (%d)", surface_type);
- if (surface_type == MM_DISPLAY_SURFACE_OVERLAY && player->video_overlay_resource == NULL) {
- LOGD("mark video overlay for acquire");
- if (mm_resource_manager_mark_for_acquire(player->resource_manager,
- MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY,
- MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
- &player->video_overlay_resource)
- != MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("could not mark video_overlay resource for acquire");
- goto ERROR;
- }
+ if ((surface_type == MM_DISPLAY_SURFACE_OVERLAY) &&
+ (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE)) {
+ LOGE("failed to acquire video overlay resource");
+ goto ERROR;
}
player->interrupted_by_resource = FALSE;
- if (mm_resource_manager_commit(player->resource_manager) !=
- MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("could not acquire resources for video playing");
- goto ERROR;
- }
-
if (__mmplayer_gst_create_video_sink_bin(player, caps, surface_type) != MM_ERROR_NONE) {
LOGE("failed to create videobin. continuing without video");
goto ERROR;
reusing = TRUE;
sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
LOGD("re-using videobin");
- __mmplayer_update_content_attrs(player, ATTR_VIDEO);
+ _mmplayer_update_content_attrs(player, ATTR_VIDEO);
}
} else if (strstr(name, "text")) {
if (player->pipeline->textbin == NULL) {
player->textsink_linked = 1;
} else {
/* linked textbin exist which means that the external subtitle path exist already */
- LOGW("ignoring internal subtutle since external subtitle is available");
+ LOGW("ignoring internal subtitle since external subtitle is available");
}
}
sink_pad_name = "text_sink";
LOGD("no more pads: %d, stream count dec : %d(num of dynamic pad)", player->no_more_pad, player->num_dynamic_pad);
if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
- __mmplayer_pipeline_complete(NULL, player);
+ _mmplayer_pipeline_complete(NULL, player);
ERROR:
if (rotation_angle >= 360)
rotation_angle -= 360;
- /* chech if supported or not */
+ /* check if supported or not */
if (rotation_angle % 90) {
LOGD("not supported rotation angle = %d", rotation_angle);
return FALSE;
}
int
-__mmplayer_video_param_check_video_sink_bin(mmplayer_t *player)
-{
- /* check video sinkbin is created */
- MMPLAYER_RETURN_VAL_IF_FAIL(player &&
- player->pipeline &&
- player->pipeline->videobin &&
- player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
- player->pipeline->videobin[MMPLAYER_V_SINK].gst,
- MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- return MM_ERROR_NONE;
-}
-
-int
-__mmplayer_get_video_angle(mmplayer_t *player, int *display_angle, int *orientation)
+_mmplayer_get_video_angle(mmplayer_t *player, int *display_angle, int *orientation)
{
int display_rotation = 0;
gchar *org_orient = NULL;
}
if (display_angle) {
- /* update user roation */
+ /* update user rotation */
mm_attrs_get_int_by_name(attrs, "display_rotation", &display_rotation);
/* Counter clockwise */
return MM_ERROR_NONE;
}
-void
-__mmplayer_video_param_set_display_rotation(mmplayer_t *player)
+static void __mmplayer_video_param_set_display_rotation(mmplayer_t *player)
{
int rotation_value = 0;
int orientations = 0; // current supported angle values are 0, 90, 180, 270
MMPLAYER_FENTER();
/* check video sinkbin is created */
- if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
+ if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY))
return;
- __mmplayer_get_video_angle(player, &display_angle, &orientations);
+ _mmplayer_get_video_angle(player, &display_angle, &orientations);
/* get rotation value to set */
__mmplayer_get_property_value_for_rotation(player, display_angle, orientations, &rotation_value);
LOGD("set video param : rotate %d", rotation_value);
}
-void
-__mmplayer_video_param_set_display_visible(mmplayer_t *player)
+static void __mmplayer_video_param_set_display_visible(mmplayer_t *player)
{
MMHandleType attrs = 0;
int visible = 0;
MMPLAYER_FENTER();
/* check video sinkbin is created */
- if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
+ if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY))
return;
attrs = MMPLAYER_GET_ATTRS(player);
LOGD("set video param : visible %d", visible);
}
-void
-__mmplayer_video_param_set_display_method(mmplayer_t *player)
+static void __mmplayer_video_param_set_display_method(mmplayer_t *player)
{
MMHandleType attrs = 0;
int display_method = 0;
MMPLAYER_FENTER();
/* check video sinkbin is created */
- if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
+ if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY))
return;
attrs = MMPLAYER_GET_ATTRS(player);
LOGD("set video param : method %d", display_method);
}
-void
-__mmplayer_video_param_set_video_roi_area(mmplayer_t *player)
+static void __mmplayer_video_param_set_video_roi_area(mmplayer_t *player)
{
MMHandleType attrs = 0;
- void *handle = NULL;
+ int handle = 0;
MMPLAYER_FENTER();
/* check video sinkbin is created */
- if (__mmplayer_video_param_check_video_sink_bin(player) != MM_ERROR_NONE) {
- LOGW("There is no video sink");
+ if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY))
return;
- }
attrs = MMPLAYER_GET_ATTRS(player);
MMPLAYER_RETURN_IF_FAIL(attrs);
- mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
- if (handle) {
- gst_video_overlay_set_video_roi_area(
- GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
- player->video_roi.scale_x, player->video_roi.scale_y, player->video_roi.scale_width, player->video_roi.scale_height);
- LOGD("set video param : video roi area scale value: x(%f) y(%f) width(%f) height(%f)",
- player->video_roi.scale_x, player->video_roi.scale_y, player->video_roi.scale_width, player->video_roi.scale_height);
- }
+
+ mm_attrs_get_int_by_name(attrs, "display_overlay", &handle);
+ MMPLAYER_RETURN_IF_FAIL(handle);
+
+ gst_video_overlay_set_video_roi_area(
+ GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
+ player->video_roi.scale_x, player->video_roi.scale_y, player->video_roi.scale_width, player->video_roi.scale_height);
+ LOGD("set video param : video roi area scale value: x(%f) y(%f) width(%f) height(%f)",
+ player->video_roi.scale_x, player->video_roi.scale_y, player->video_roi.scale_width, player->video_roi.scale_height);
}
-void
-__mmplayer_video_param_set_roi_area(mmplayer_t *player)
+static void __mmplayer_video_param_set_roi_area(mmplayer_t *player)
{
MMHandleType attrs = 0;
- void *handle = NULL;
+ int handle = 0;
/*set wl_display*/
int win_roi_x = 0;
int win_roi_y = 0;
MMPLAYER_FENTER();
/* check video sinkbin is created */
- if (__mmplayer_video_param_check_video_sink_bin(player) != MM_ERROR_NONE) {
- LOGW("There is no video sink");
+ if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY))
return;
- }
attrs = MMPLAYER_GET_ATTRS(player);
MMPLAYER_RETURN_IF_FAIL(attrs);
- mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
+ mm_attrs_get_int_by_name(attrs, "display_overlay", &handle);
+ MMPLAYER_RETURN_IF_FAIL(handle);
- if (handle) {
- /* It should be set after setting window */
- mm_attrs_get_int_by_name(attrs, "display_win_roi_x", &win_roi_x);
- mm_attrs_get_int_by_name(attrs, "display_win_roi_y", &win_roi_y);
- mm_attrs_get_int_by_name(attrs, "display_win_roi_width", &win_roi_width);
- mm_attrs_get_int_by_name(attrs, "display_win_roi_height", &win_roi_height);
+ /* It should be set after setting window */
+ mm_attrs_multiple_get(attrs, NULL,
+ "display_win_roi_x", &win_roi_x,
+ "display_win_roi_y", &win_roi_y,
+ "display_win_roi_width", &win_roi_width,
+ "display_win_roi_height", &win_roi_height, NULL);
- /* After setting window handle, set display roi area */
- gst_video_overlay_set_display_roi_area(
- GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
- win_roi_x, win_roi_y, win_roi_width, win_roi_height);
- LOGD("set video param : roi area : x(%d) y(%d) width(%d) height(%d)",
- win_roi_x, win_roi_y, win_roi_width, win_roi_height);
- }
+ /* After setting window handle, set display roi area */
+ gst_video_overlay_set_display_roi_area(
+ GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
+ win_roi_x, win_roi_y, win_roi_width, win_roi_height);
+ LOGD("set video param : roi area : x(%d) y(%d) width(%d) height(%d)",
+ win_roi_x, win_roi_y, win_roi_width, win_roi_height);
}
-void
-__mmplayer_video_param_set_display_overlay(mmplayer_t *player)
+static void __mmplayer_video_param_set_display_overlay(mmplayer_t *player)
{
MMHandleType attrs = 0;
- void *handle = NULL;
+ int handle = 0;
/* check video sinkbin is created */
- if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
+ if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY))
return;
attrs = MMPLAYER_GET_ATTRS(player);
MMPLAYER_RETURN_IF_FAIL(attrs);
/* common case if using overlay surface */
- mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
-
- if (handle) {
- /* default is using wl_surface_id */
- unsigned int wl_surface_id = 0;
- wl_surface_id = *(int *)handle;
- LOGD("set video param : wl_surface_id %d", wl_surface_id);
- gst_video_overlay_set_wl_window_wl_surface_id(
- GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
- *(int *)handle);
- } else {
- /* FIXIT : is it error case? */
- LOGW("still we don't have a window handle on player attribute. create it's own surface.");
- }
+ mm_attrs_get_int_by_name(attrs, "display_overlay", &handle);
+ MMPLAYER_RETURN_IF_FAIL(handle);
+
+ /* default is using wl_surface_id */
+ LOGD("set video param : wl_surface_id %d", handle);
+ gst_video_overlay_set_wl_window_wl_surface_id(
+ GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
+ handle);
}
int
-__mmplayer_update_wayland_videosink_video_param(mmplayer_t *player, char *param_name)
+_mmplayer_update_video_overlay_param(mmplayer_t *player, const char *param_name)
{
gboolean update_all_param = FALSE;
+
MMPLAYER_FENTER();
- /* check video sinkbin is created */
- if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
+ if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_OVERLAY)) {
+ LOGW("videosink is not ready yet");
return MM_ERROR_PLAYER_NOT_INITIALIZED;
+ }
if (strcmp(player->ini.videosink_element_overlay, "tizenwlsink")) {
- LOGE("can not find tizenwlsink");
+ LOGE("invalid videosink [%s]", player->ini.videosink_element_overlay);
return MM_ERROR_PLAYER_INTERNAL;
}
if (update_all_param)
__mmplayer_video_param_set_video_roi_area(player);
- return MM_ERROR_NONE;
-}
-
-int
-_mmplayer_update_video_param(mmplayer_t *player, char *param_name)
-{
- MMHandleType attrs = 0;
- int surface_type = 0;
- int ret = MM_ERROR_NONE;
-
- MMPLAYER_FENTER();
-
- /* check video sinkbin is created */
- if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
- return MM_ERROR_PLAYER_NOT_INITIALIZED;
-
- attrs = MMPLAYER_GET_ATTRS(player);
- if (!attrs) {
- LOGE("cannot get content attribute");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- LOGD("param_name : %s", param_name);
-
- /* update display surface */
- mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
- LOGD("check display surface type attribute: %d", surface_type);
-
- /* configuring display */
- switch (surface_type) {
- case MM_DISPLAY_SURFACE_OVERLAY:
- {
- ret = __mmplayer_update_wayland_videosink_video_param(player, param_name);
- if (ret != MM_ERROR_NONE)
- return ret;
- }
- break;
- }
MMPLAYER_FLEAVE();
-
return MM_ERROR_NONE;
}
{
gboolean disable_overlay = FALSE;
mmplayer_t *player = (mmplayer_t *)hplayer;
- int ret = MM_ERROR_NONE;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", TRUE, NULL);
/* release overlay resource */
- if (player->video_overlay_resource != NULL) {
- ret = mm_resource_manager_mark_for_release(player->resource_manager,
- player->video_overlay_resource);
- if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("failed to mark overlay resource for release, ret(0x%x)", ret);
- goto ERROR;
- }
- player->video_overlay_resource = NULL;
- }
-
- ret = mm_resource_manager_commit(player->resource_manager);
- if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("failed to commit acquiring of overlay resource, ret(0x%x)", ret);
+ if (__mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) {
+ LOGE("failed to release overlay resource");
goto ERROR;
}
} else {
- /* mark video overlay for acquire */
- if (player->video_overlay_resource == NULL) {
- ret = mm_resource_manager_mark_for_acquire(player->resource_manager,
- MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY,
- MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
- &player->video_overlay_resource);
- if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("could not prepare for video_overlay resource");
- goto ERROR;
- }
- }
-
- player->interrupted_by_resource = FALSE;
- /* acquire resources for video overlay */
- ret = mm_resource_manager_commit(player->resource_manager);
- if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("could not acquire resources for video playing");
+ if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_OVERLAY) != MM_ERROR_NONE) {
+ LOGE("failed to acquire video overlay resource");
goto ERROR;
}
+ player->interrupted_by_resource = FALSE;
LOGD("enable overlay");
__mmplayer_video_param_set_display_overlay(player);
}
int
-__mmplayer_gst_element_link_bucket(GList *element_bucket)
+_mmplayer_gst_element_link_bucket(GList *element_bucket)
{
GList *bucket = element_bucket;
mmplayer_gst_element_t *element = NULL;
mmplayer_gst_element_t *prv_element = NULL;
+ GstElement *tee_element = NULL;
gint successful_link_count = 0;
MMPLAYER_FENTER();
if (element && element->gst) {
if (prv_element && prv_element->gst) {
+ if (strstr(GST_ELEMENT_NAME(element->gst), "audio-tee-queue") && strcmp(GST_ELEMENT_NAME(prv_element->gst), "audio-tee")) {
+ if (tee_element) {
+ prv_element->gst = tee_element;
+ } else {
+ LOGD("failed to make new audio branch - linking [%s] to [%s] is not supported",
+ GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
+ GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
+ return -1;
+ }
+ }
if (gst_element_link(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst))) {
LOGD("linking [%s] to [%s] success",
GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
successful_link_count++;
+ if (!strcmp(GST_ELEMENT_NAME(prv_element->gst), "audio-tee")) {
+ LOGD("keep audio-tee element for next audio pipeline branch");
+ tee_element = prv_element->gst;
+ }
} else {
LOGD("linking [%s] to [%s] failed",
GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
}
int
-__mmplayer_gst_element_add_bucket_to_bin(GstBin *bin, GList *element_bucket)
+_mmplayer_gst_element_add_bucket_to_bin(GstBin *bin, GList *element_bucket)
{
GList *bucket = element_bucket;
mmplayer_gst_element_t *element = NULL;
if (element && element->gst) {
if (!gst_bin_add(bin, GST_ELEMENT(element->gst))) {
- LOGD("__mmplayer_gst_element_link_bucket : Adding element [%s] to bin [%s] failed",
+ LOGD("_mmplayer_gst_element_link_bucket : Adding element [%s] to bin [%s] failed",
GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
GST_ELEMENT_NAME(GST_ELEMENT(bin)));
return 0;
MMPLAYER_RETURN_IF_FAIL(unused);
MMPLAYER_RETURN_IF_FAIL(data);
- caps = gst_pad_get_current_caps(pad);
- if (!caps)
- return;
-
- MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
+ MMPLAYER_GST_GET_CAPS_INFO_FROM_PAD(pad, caps, str, name, caps_ret);
if (!caps_ret)
goto ERROR;
LOGD("name = %s", name);
if (strstr(name, "audio")) {
- __mmplayer_update_content_attrs(player, ATTR_AUDIO);
+ _mmplayer_update_content_attrs(player, ATTR_AUDIO);
if (player->audio_stream_changed_cb) {
LOGE("call the audio stream changed cb");
if ((name = gst_structure_get_string(str, "format")))
player->set_mode.video_zc = name[0] == 'S';
- __mmplayer_update_content_attrs(player, ATTR_VIDEO);
-
- if (player->video_stream_changed_cb) {
- LOGE("call the video stream changed cb");
- player->video_stream_changed_cb(player->video_stream_changed_cb_user_param);
- }
+ _mmplayer_update_content_attrs(player, ATTR_VIDEO);
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_VIDEO_STREAM_CHANGED, NULL);
} else {
LOGW("invalid caps info");
}
return;
}
-/**
- * This function is to create audio pipeline for playing.
- *
- * @param player [in] handle of player
- *
- * @return This function returns zero on success.
- * @remark
- * @see __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_sink_bin
- */
-/* macro for code readability. just for sinkbin-creation functions */
-#define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket, x_player) \
- do {\
- x_bin[x_id].id = x_id;\
- x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
- if (!x_bin[x_id].gst) {\
- LOGE("failed to create %s", x_factory);\
- goto ERROR;\
- } else {\
- if (x_player->ini.set_dump_element_flag)\
- __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
- } \
- if (x_add_bucket)\
- element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
- } while (0);
-
void
-__mmplayer_audio_stream_clear_buffer(mmplayer_t *player, gboolean send_all)
+_mmplayer_audio_stream_clear_buffer(mmplayer_t *player, gboolean send_all)
{
GList *l = NULL;
mmplayer_audio_decoded_data_info_t audio_stream = { 0, };
MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb);
+ MMPLAYER_RETURN_IF_FAIL(player && player->audio_decoded_cb);
audio_stream.bitrate = a_buffer->bitrate;
audio_stream.channel = a_buffer->channel;
- audio_stream.depth = a_buffer->depth;
- audio_stream.is_little_endian = a_buffer->is_little_endian;
audio_stream.channel_mask = a_buffer->channel_mask;
audio_stream.data_size = a_buffer->data_size;
audio_stream.data = a_buffer->pcm_data;
-
- /* LOGD("[%"G_GUINT64_FORMAT"] send data size:%d, %p", audio_stream.channel_mask, audio_stream.data_size, player->audio_stream_cb_user_param); */
- player->audio_stream_render_cb(&audio_stream, player->audio_stream_cb_user_param);
+ audio_stream.pcm_format = a_buffer->pcm_format;
+#ifdef __DEBUG__
+ LOGD("[%"G_GUINT64_FORMAT"] send data size:%d, %p", audio_stream.channel_mask, audio_stream.data_size, player->audio_decoded_cb_user_param);
+#endif
+ player->audio_decoded_cb(&audio_stream, player->audio_decoded_cb_user_param);
MMPLAYER_FLEAVE();
}
__mmplayer_audio_stream_decoded_render_cb(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer data)
{
mmplayer_t *player = (mmplayer_t *)data;
+ const gchar *pcm_format = NULL;
gint channel = 0;
gint rate = 0;
- gint depth = 0;
- gint endianness = 0;
guint64 channel_mask = 0;
void *a_data = NULL;
gint a_size = 0;
GList *l = NULL;
MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb);
+ MMPLAYER_RETURN_IF_FAIL(player && player->audio_decoded_cb);
gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
a_data = mapinfo.data;
GstCaps *caps = gst_pad_get_current_caps(pad);
GstStructure *structure = gst_caps_get_structure(caps, 0);
-
- /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
+#ifdef __DEBUG__
+ MMPLAYER_LOG_GST_CAPS_TYPE(caps);
+#endif
+ pcm_format = gst_structure_get_string(structure, "format");
gst_structure_get_int(structure, "rate", &rate);
gst_structure_get_int(structure, "channels", &channel);
- gst_structure_get_int(structure, "depth", &depth);
- gst_structure_get_int(structure, "endianness", &endianness);
gst_structure_get(structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL);
gst_caps_unref(GST_CAPS(caps));
mmplayer_audio_stream_buff_t *tmp = (mmplayer_audio_stream_buff_t *)l->data;
if (tmp) {
if (channel_mask == tmp->channel_mask) {
- /* LOGD("[%"G_GUINT64_FORMAT"] total: %d, data: %d, buffer: %d", channel_mask, tmp->data_size, a_size, tmp->buff_size); */
+#ifdef __DEBUG__
+ LOGD("[%"G_GUINT64_FORMAT"] total: %d, data: %d, buffer: %d", channel_mask, tmp->data_size, a_size, tmp->buff_size);
+#endif
if (tmp->data_size + a_size < tmp->buff_size) {
memcpy(tmp->pcm_data + tmp->data_size, a_data, a_size);
tmp->data_size += a_size;
}
}
- /* create new audio stream data */
+ /* create new audio stream data for newly found audio channel */
a_buffer = (mmplayer_audio_stream_buff_t *)g_try_malloc0(sizeof(mmplayer_audio_stream_buff_t));
if (a_buffer == NULL) {
LOGE("failed to alloc data.");
}
a_buffer->bitrate = rate;
a_buffer->channel = channel;
- a_buffer->depth = depth;
- a_buffer->is_little_endian = (endianness == 1234 ? true : false);
a_buffer->channel_mask = channel_mask;
a_buffer->data_size = a_size;
+ a_buffer->pcm_format = _mmplayer_convert_audio_pcm_str_to_media_format_mime(pcm_format);
- if (!player->audio_stream_sink_sync) {
+ if (player->audio_extract_opt & MM_PLAYER_AUDIO_EXTRACT_NO_SYNC_WITH_CLOCK) {
/* If sync is FALSE, use buffer list to reduce the IPC. */
a_buffer->buff_size = (a_size > player->ini.pcm_buffer_size) ? (a_size) : (player->ini.pcm_buffer_size);
a_buffer->pcm_data = g_try_malloc(a_buffer->buff_size);
goto DONE;
}
memcpy(a_buffer->pcm_data, a_data, a_size);
- /* LOGD("new [%"G_GUINT64_FORMAT"] total:%d buff:%d", channel_mask, a_buffer->data_size, a_buffer->buff_size); */
+#ifdef __DEBUG__
+ LOGD("new [%"G_GUINT64_FORMAT"] total:%d buff:%d", channel_mask, a_buffer->data_size, a_buffer->buff_size);
+#endif
player->audio_stream_buff_list = g_list_append(player->audio_stream_buff_list, a_buffer);
} else {
/* If sync is TRUE, send data directly. */
goto ERROR;
}
- LOGE("player->audio_stream_sink_sync: %d", player->audio_stream_sink_sync);
+ LOGE("audio_extract_opt : 0x%X", player->audio_extract_opt);
gst_object_unref(sinkpad);
- g_object_set(sink, "sync", player->audio_stream_sink_sync, NULL);
+ if (!(player->audio_extract_opt & MM_PLAYER_AUDIO_EXTRACT_NO_SYNC_WITH_CLOCK))
+ g_object_set(sink, "sync", TRUE, NULL);
g_object_set(sink, "signal-handoffs", TRUE, NULL);
- gst_element_set_state(sink, GST_STATE_PAUSED);
- gst_element_set_state(queue, GST_STATE_PAUSED);
+ /* keep the first sink reference only */
+ if (!audiobin[MMPLAYER_A_SINK].gst) {
+ audiobin[MMPLAYER_A_SINK].id = MMPLAYER_A_SINK;
+ audiobin[MMPLAYER_A_SINK].gst = sink;
+ }
+
- __mmplayer_add_signal_connection(player,
+ _mmplayer_add_signal_connection(player,
G_OBJECT(sink),
MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
"handoff",
G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb),
(gpointer)player);
+ __mmplayer_add_sink(player, sink, FALSE);
+
+ if (gst_element_sync_state_with_parent(queue) == GST_STATE_CHANGE_FAILURE) {
+ LOGE("failed to sync state");
+ goto ERROR;
+ }
+
+ if (gst_element_sync_state_with_parent(sink) == GST_STATE_CHANGE_FAILURE) {
+ LOGE("failed to sync state");
+ goto ERROR;
+ }
+
MMPLAYER_FLEAVE();
return;
}
void
-__mmplayer_gst_set_pulsesink_property(mmplayer_t *player, MMHandleType attrs)
+__mmplayer_gst_audio_deinterleave_no_more_pads(GstElement* object, gpointer data)
+{
+ mmplayer_t *player = (mmplayer_t *)data;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
+
+ player->no_more_pad = TRUE;
+ _mmplayer_pipeline_complete(NULL, player);
+
+ MMPLAYER_FLEAVE();
+ return;
+}
+
+void
+__mmplayer_gst_set_pulsesink_property(mmplayer_t *player)
{
#define MAX_PROPS_LEN 128
+ mmplayer_gst_element_t *audiobin = NULL;
gint latency_mode = 0;
gchar *stream_type = NULL;
gchar *latency = NULL;
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->audiobin);
- mm_attrs_get_int_by_name(attrs, "sound_stream_index", &stream_id);
- mm_attrs_get_string_by_name(attrs, "sound_stream_type", &stream_type);
+ audiobin = player->pipeline->audiobin;
- if (!stream_type) {
- LOGE("stream_type is null.");
- } else {
- if (player->sound.focus_id)
- snprintf(stream_props, sizeof(stream_props) - 1, "props,media.role=%s, media.parent_id=%d, media.focus_id=%d",
- stream_type, stream_id, player->sound.focus_id);
- else
- snprintf(stream_props, sizeof(stream_props) - 1, "props,media.role=%s, media.parent_id=%d",
- stream_type, stream_id);
- props = gst_structure_from_string(stream_props, NULL);
- g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL);
- LOGI("stream_type[%s], stream_id[%d], focus_id[%d], result[%s].",
- stream_type, stream_id, player->sound.focus_id, stream_props);
- gst_structure_free(props);
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "volume", player->sound.volume, NULL);
+ if (player->sound.mute) {
+ LOGD("mute enabled");
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "mute", player->sound.mute, NULL);
}
- mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
+ mm_attrs_get_int_by_name(player->attrs, "sound_stream_index", &stream_id);
+ mm_attrs_get_string_by_name(player->attrs, "sound_stream_type", &stream_type);
+
+ if (!stream_type)
+ snprintf(stream_props, sizeof(stream_props) - 1,
+ "props,application.process.id.origin=%d", player->client_pid);
+ else
+ snprintf(stream_props, sizeof(stream_props) - 1,
+ "props,media.role=%s, media.parent_id=%d, application.process.id.origin=%d",
+ stream_type, stream_id, player->client_pid);
+
+ props = gst_structure_from_string(stream_props, NULL);
+ g_object_set(audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL);
+ LOGI("props result[%s].", stream_props);
+ gst_structure_free(props);
+
+ mm_attrs_get_int_by_name(player->attrs, "sound_latency_mode", &latency_mode);
switch (latency_mode) {
case AUDIO_LATENCY_MODE_LOW:
- latency = g_strndup("low", 3);
+ latency = g_strdup("low");
break;
case AUDIO_LATENCY_MODE_MID:
- latency = g_strndup("mid", 3);
+ latency = g_strdup("mid");
break;
case AUDIO_LATENCY_MODE_HIGH:
- latency = g_strndup("high", 4);
+ latency = g_strdup("high");
+ break;
+ default:
+ latency = g_strdup("mid");
break;
};
- g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
- "latency", latency,
- NULL);
+ g_object_set(audiobin[MMPLAYER_A_SINK].gst, "latency", latency, NULL);
LOGD("audiosink property - latency=%s", latency);
MMPLAYER_FLEAVE();
}
-void
+int
__mmplayer_gst_set_openalsink_property(mmplayer_t *player)
{
mmplayer_gst_element_t *audiobin = NULL;
MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->audiobin);
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
+ player->pipeline->audiobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
audiobin = player->pipeline->audiobin;
g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "source-ambisonics-type", 1, NULL);
- sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info);
+ if (sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info)) {
+ LOGE("failed to create media stream info");
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+
g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "stream-info", stream_info, NULL);
if (player->video360_yaw_radians <= M_PI &&
}
MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
}
static int
-__mmplayer_gst_fill_audio_bucket(mmplayer_t *player, GList **bucket)
+__mmplayer_gst_make_audio_playback_sink(mmplayer_t *player, GList **bucket)
{
mmplayer_gst_element_t *audiobin = NULL;
- MMHandleType attrs = 0;
- GList *element_bucket = NULL;
- GstCaps *acaps = NULL;
GstPad *sink_pad = NULL;
+ GstCaps *acaps = NULL;
+ gint channels = 0;
int pitch_control = 0;
double pitch_value = 1.0;
player->pipeline->audiobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
audiobin = player->pipeline->audiobin;
- attrs = MMPLAYER_GET_ATTRS(player);
- if (player->build_audio_offload) { /* skip all the audio filters */
- LOGD("create audio offload sink : %s", player->ini.audio_offload_sink_element);
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.audio_offload_sink_element, "audiosink", TRUE, player);
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "sync", TRUE, NULL);
- __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst);
- goto DONE;
- }
+ LOGD("make element for normal audio playback");
+
+ /* audio bin structure for playback. {} means optional.
+ optional : pitch, audioeq, custom audioeq, openalsink for 360 audio content
- /* pitch */
+ * src - ... - {aconv - pitch} - aconv - rgvolume - resample - volume -
+ {audioeq} - {custom audioeq} - pulsesink or {aconv - capsfilter - openalsink}
+ */
+
+ /* for pitch control */
mm_attrs_multiple_get(player->attrs, NULL,
MM_PLAYER_PITCH_CONTROL, &pitch_control,
MM_PLAYER_PITCH_VALUE, &pitch_value,
gst_object_unref(factory);
/* converter */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV_PITCH, "audioconvert", "audio convert pitch", TRUE, player);
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV_PITCH, "audioconvert", "audio convert pitch", *bucket, player);
/* pitch */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_PITCH, "pitch", "audio pitch", TRUE, player);
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_PITCH, "pitch", "audio pitch", *bucket, player);
g_object_set(G_OBJECT(audiobin[MMPLAYER_A_PITCH].gst), "pitch", (gdouble)pitch_value, NULL);
} else {
LOGW("there is no pitch element");
}
/* converter */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", *bucket, player);
/* replaygain volume */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RGVOL, "rgvolume", "audio rgvolume", TRUE, player);
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RGVOL, "rgvolume", "audio rgvolume", *bucket, player);
if (player->sound.rg_enable)
g_object_set(G_OBJECT(audiobin[MMPLAYER_A_RGVOL].gst), "enable-rgvolume", TRUE, NULL);
else
g_object_set(G_OBJECT(audiobin[MMPLAYER_A_RGVOL].gst), "enable-rgvolume", FALSE, NULL);
/* resampler */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER, player->ini.audioresampler_element, "audio resampler", TRUE, player);
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER, player->ini.audioresampler_element, "audio resampler", *bucket, player);
- if (player->audio_stream_render_cb) { /* pcm extraction only, no sound output */
- gchar *dst_format = NULL;
- int dst_len = 0;
- int dst_samplerate = 0;
- int dst_channels = 0;
- GstCaps *caps = NULL;
- char *caps_str = NULL;
+ if (g_strrstr(player->ini.audiosink_element, "openalsink")) {
+ /* currently, only openalsink uses volume element */
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", *bucket, player);
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
- /* get conf. values */
- mm_attrs_multiple_get(player->attrs, NULL,
- "pcm_audioformat", &dst_format, &dst_len,
- "pcm_extraction_samplerate", &dst_samplerate,
- "pcm_extraction_channels", &dst_channels,
- NULL);
+ if (player->sound.mute) {
+ LOGD("mute enabled");
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
+ }
+ }
- LOGD("pcm info - format: %s(%d), samplerate : %d, channel: %d", dst_format, dst_len, dst_samplerate, dst_channels);
+ mm_attrs_get_int_by_name(player->attrs, "content_audio_channels", &channels);
- /* capsfilter */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
- caps = gst_caps_new_simple("audio/x-raw",
- "format", G_TYPE_STRING, dst_format,
- "rate", G_TYPE_INT, dst_samplerate,
- "channels", G_TYPE_INT, dst_channels,
- NULL);
+ /* audio effect element. if audio effect is enabled */
+ if ((strcmp(player->ini.audioeffect_element, ""))
+ && (channels <= 2)
+ && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.audioeffect_element, "audio effect filter", *bucket, player);
- caps_str = gst_caps_to_string(caps);
- LOGD("new caps : %s", caps_str);
+ LOGD("audio effect config. bypass = %d, effect type = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
- g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
+ if ((!player->bypass_audio_effect)
+ && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
+ if (player->audio_effect_info.effect_type == MM_AUDIO_EFFECT_TYPE_CUSTOM) {
+ if (!_mmplayer_audio_effect_custom_apply(player))
+ LOGI("apply audio effect(custom) setting success");
+ }
+ }
- /* clean */
- gst_caps_unref(caps);
- MMPLAYER_FREEIF(caps_str);
+ if ((strcmp(player->ini.audioeffect_element_custom, ""))
+ && (player->set_mode.rich_audio)) {
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.audioeffect_element_custom, "audio effect filter custom", *bucket, player);
+ }
+ }
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_DEINTERLEAVE, "deinterleave", "deinterleave", TRUE, player);
+ /* create audio sink */
+ LOGD("spherical %d, channels %d, ambisonic type %d, format %d, order %d",
+ player->is_content_spherical, channels, player->video360_metadata.ambisonic_type,
+ player->video360_metadata.ambisonic_format, player->video360_metadata.ambisonic_order);
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_DEINTERLEAVE].gst), "keep-positions", TRUE, NULL);
+ /* Note: qtdemux converts audio metadata defaults to openalsink defaults. */
+ if (player->is_360_feature_enabled &&
+ player->is_content_spherical &&
+ channels == 4 &&
+ player->video360_metadata.ambisonic_type == MMFILE_AMBISONIC_TYPE_PERIPHONIC &&
+ player->video360_metadata.ambisonic_format == MMFILE_AMBISONIC_FORMAT_AMB &&
+ player->video360_metadata.ambisonic_order == MMFILE_AMBISONIC_ORDER_FOA) {
- /* raw pad handling signal, audiosink will be added after getting signal */
- __mmplayer_add_signal_connection(player, G_OBJECT(audiobin[MMPLAYER_A_DEINTERLEAVE].gst),
- MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added", G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), (gpointer)player);
+ strncpy(player->ini.audiosink_element, "openalsink", PLAYER_INI_MAX_STRLEN - 1);
+
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV_BFORMAT, "audioconvert", "audio-converter-bformat", *bucket, player);
+
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_360, "capsfilter", "audio-caps-filter", *bucket, player);
+ acaps = gst_caps_from_string(SPATIAL_AUDIO_CAPS);
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_CAPS_360].gst), "caps", acaps, NULL);
+ gst_caps_unref(acaps);
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "openalsink", "audiosink", *bucket, player);
+
+ player->is_openal_plugin_used = TRUE;
} else {
+ if (player->is_360_feature_enabled && player->is_content_spherical)
+ LOGW("Audio track isn't of the ambisonic type and can't be played back as a spatial sound.");
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.audiosink_element, "audiosink", *bucket, player);
+ }
- /* normal playback */
- gint channels = 0;
+ if ((MMPLAYER_IS_RTSP_STREAMING(player)) ||
+ (player->videodec_linked && player->ini.use_system_clock)) {
+ LOGD("system clock will be used.");
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE, NULL);
+ }
- /* for logical volume control */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE, player);
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
+ if (g_strrstr(player->ini.audiosink_element, "pulsesink")) {
+ __mmplayer_gst_set_pulsesink_property(player);
+ } else if (g_strrstr(player->ini.audiosink_element, "openalsink")) {
+ if (__mmplayer_gst_set_openalsink_property(player) != MM_ERROR_NONE)
+ goto ERROR;
+ }
- if (player->sound.mute) {
- LOGD("mute enabled");
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
- }
+ /* qos on */
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL); /* qos on */
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL);
- mm_attrs_get_int_by_name(player->attrs, "content_audio_channels", &channels);
+ sink_pad = gst_element_get_static_pad(audiobin[MMPLAYER_A_SINK].gst, "sink");
+ _mmplayer_add_signal_connection(player, G_OBJECT(sink_pad), MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
+ "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), (gpointer)player);
+ gst_object_unref(GST_OBJECT(sink_pad));
- /* audio effect element. if audio effect is enabled */
- if ((strcmp(player->ini.audioeffect_element, ""))
- && (channels <= 2)
- && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.audioeffect_element, "audio effect filter", TRUE, player);
+ __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst, FALSE);
- LOGD("audio effect config. bypass = %d, effect type = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
- if ((!player->bypass_audio_effect)
- && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
- if (player->audio_effect_info.effect_type == MM_AUDIO_EFFECT_TYPE_CUSTOM) {
- if (!_mmplayer_audio_effect_custom_apply(player))
- LOGI("apply audio effect(custom) setting success");
- }
- }
+ERROR: /* MMPLAYER_CREATE_ELEMENT */
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_PLAYER_INTERNAL;
+}
- if ((strcmp(player->ini.audioeffect_element_custom, ""))
- && (player->set_mode.rich_audio))
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.audioeffect_element_custom, "audio effect filter custom", TRUE, player);
- }
+static int
+__mmplayer_gst_make_audio_extract_sink(mmplayer_t *player, GList **bucket)
+{
+ mmplayer_gst_element_t *audiobin = NULL;
+ enum audio_element_id extract_sink_id = MMPLAYER_A_SINK;
- /* create audio sink */
- LOGD("360 spherical %d, channels %d, ambisonic type %d, format %d, order %d",
- player->is_content_spherical, channels, player->video360_metadata.ambisonic_type,
- player->video360_metadata.ambisonic_format, player->video360_metadata.ambisonic_order);
+ gchar *dst_format = NULL;
+ int dst_len = 0;
+ int dst_samplerate = 0;
+ int dst_channels = 0;
+ GstCaps *caps = NULL;
+ char *caps_str = NULL;
- /* Note: qtdemux converts audio metadata defaults to openalsink defaults. */
- if (player->is_360_feature_enabled &&
- player->is_content_spherical &&
- channels == 4 &&
- player->video360_metadata.ambisonic_type == MMFILE_AMBISONIC_TYPE_PERIPHONIC &&
- player->video360_metadata.ambisonic_format == MMFILE_AMBISONIC_FORMAT_AMB &&
- player->video360_metadata.ambisonic_order == MMFILE_AMBISONIC_ORDER_FOA) {
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
+ player->pipeline->audiobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
+
+ audiobin = player->pipeline->audiobin;
- strncpy(player->ini.audiosink_element, "openalsink", PLAYER_INI_MAX_STRLEN - 1);
+ LOGD("make element for audio extract, option = 0x%X", player->audio_extract_opt);
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV_BFORMAT, "audioconvert", "audio-converter-bformat", TRUE, player);
+ /* audio bin structure according to the mmplayer_audio_extract_opt_e.
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_360, "capsfilter", "audio-caps-filter", TRUE, player);
- acaps = gst_caps_from_string(SPATIAL_AUDIO_CAPS);
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_CAPS_360].gst), "caps", acaps, NULL);
- gst_caps_unref(acaps);
+ [case 1] extract interleave audio pcm without playback
+ : MM_PLAYER_AUDIO_EXTRACT_DEFAULT (sync)
+ MM_PLAYER_AUDIO_EXTRACT_NO_SYNC_WITH_CLOCK (non sync)
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "openalsink", "audiosink", TRUE, player);
+ * src - ... - aconv - resample - capsfilter - fakesink (sync or not)
- player->is_openal_plugin_used = TRUE;
- } else {
- if (player->is_360_feature_enabled && player->is_content_spherical)
- LOGW("Audio track isn't of the ambisonic type and can't be played back as a spatial sound.");
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.audiosink_element, "audiosink", TRUE, player);
- }
+ [case 2] deinterleave for each channel without playback
+ : MM_PLAYER_AUDIO_EXTRACT_DEINTERLEAVE (sync)
+ MM_PLAYER_AUDIO_EXTRACT_NO_SYNC_AND_DEINTERLEAVE (non sync)
+
+ * src - ... - aconv - resample - capsfilter - deinterleave - fakesink (sync or not)
+ - fakesink (sync or not)
+ - ... (sync or not)
+
+ [case 3] [case 1(sync only)] + playback
+ : MM_PLAYER_AUDIO_EXTRACT_WITH_PLAYBACK
+
+ * src - ... - tee - queue1 - playback path
+ - queue2 - [case1 pipeline with sync]
+
+ [case 4] [case 2(sync only)] + playback
+ : MM_PLAYER_AUDIO_EXTRACT_DEINTERLEAVE_WITH_PLAYBACK
+
+ * src - ... - tee - queue1 - playback path
+ - queue2 - [case2 pipeline with sync]
+
+ */
+
+ /* 1. create tee and playback path
+ 'tee' should be added at first to copy the decoded stream
+ */
+ if (player->audio_extract_opt & MM_PLAYER_AUDIO_EXTRACT_WITH_PLAYBACK) {
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TEE, "tee", "audio-tee", *bucket, player);
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_TEE].gst), "num-src-pads", 2, NULL);
+
+ /* tee - path 1 : for playback path */
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TEE_Q1, "queue", "audio-tee-queue1", *bucket, player);
+ __mmplayer_gst_make_audio_playback_sink(player, bucket);
+
+ /* tee - path 2 : for extract path */
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TEE_Q2, "queue", "audio-tee-queue2", *bucket, player);
+ extract_sink_id = MMPLAYER_A_EXTRACT_SINK; /* there is another playback sink */
+ }
+
+ /* if there is tee, 'tee - path 2' is linked here */
+ /* converter */
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_EXTRACT_CONV, "audioconvert", "audio-ext-conv", *bucket, player);
+
+ /* resampler */
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_EXTRACT_RESAMPLER, player->ini.audioresampler_element, "audio-ext-resampler", *bucket, player);
+
+ /* 2. decide the extract pcm format */
+ mm_attrs_multiple_get(player->attrs, NULL,
+ MM_PLAYER_PCM_EXT_FORMAT, &dst_format, &dst_len,
+ MM_PLAYER_PCM_EXT_SAMPLERATE, &dst_samplerate,
+ MM_PLAYER_PCM_EXT_CHANNELS, &dst_channels,
+ NULL);
- if ((MMPLAYER_IS_RTSP_STREAMING(player)) ||
- (player->videodec_linked && player->ini.use_system_clock)) {
- LOGD("system clock will be used.");
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE, NULL);
+ LOGD("required extract pcm format - format: %s(%d), samplerate : %d, channel: %d",
+ dst_format, dst_len, dst_samplerate, dst_channels);
+
+ if (dst_format == NULL || dst_len == 0 || dst_samplerate == 0 || dst_channels == 0) {
+ mm_attrs_multiple_get(player->attrs, NULL,
+ "content_audio_format", &dst_format, &dst_len, /* get string and len */
+ "content_audio_samplerate", &dst_samplerate,
+ "content_audio_channels", &dst_channels,
+ NULL);
+
+ LOGD("apply the decoded pcm format - format: %s(%d), samplerate : %d, channel: %d",
+ dst_format, dst_len, dst_samplerate, dst_channels);
+
+ /* If there is no enough information, set it to platform default value. */
+ if (dst_format == NULL || _mmplayer_convert_audio_pcm_str_to_media_format_mime(dst_format) == MEDIA_FORMAT_MAX) {
+ LOGD("set platform default format");
+ dst_format = DEFAULT_PCM_OUT_FORMAT;
}
+ if (dst_samplerate <= 0) dst_samplerate = DEFAULT_PCM_OUT_SAMPLERATE;
+ if (dst_channels <= 0) dst_channels = DEFAULT_PCM_OUT_CHANNEL;
+ }
- if (g_strrstr(player->ini.audiosink_element, "pulsesink"))
- __mmplayer_gst_set_pulsesink_property(player, attrs);
- else if (g_strrstr(player->ini.audiosink_element, "openalsink"))
- __mmplayer_gst_set_openalsink_property(player);
+ /* 3. create capsfilter */
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_EXTRACT_CAPS, "capsfilter", "audio-ext-caps", *bucket, player);
+ caps = gst_caps_new_simple("audio/x-raw",
+ "format", G_TYPE_STRING, dst_format,
+ "rate", G_TYPE_INT, dst_samplerate,
+ "channels", G_TYPE_INT, dst_channels,
+ NULL);
- /* qos on */
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL); /* qos on */
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL);
+ caps_str = gst_caps_to_string(caps);
+ LOGD("new caps : %s", caps_str);
- sink_pad = gst_element_get_static_pad(audiobin[MMPLAYER_A_SINK].gst, "sink");
- __mmplayer_add_signal_connection(player, G_OBJECT(sink_pad), MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
- "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), (gpointer)player);
- gst_object_unref(GST_OBJECT(sink_pad));
+ g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_EXTRACT_CAPS].gst), "caps", caps, NULL);
+
+ /* clean */
+ gst_caps_unref(caps);
+ MMPLAYER_FREEIF(caps_str);
- __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst);
+ /* 4-1. create deinterleave to extract pcm for each channel */
+ if (player->audio_extract_opt & MM_PLAYER_AUDIO_EXTRACT_DEINTERLEAVE) {
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_EXTRACT_DEINTERLEAVE, "deinterleave", "deinterleave", *bucket, player);
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_EXTRACT_DEINTERLEAVE].gst), "keep-positions", TRUE, NULL);
+
+ /* audiosink will be added after getting signal for each channel */
+ _mmplayer_add_signal_connection(player, G_OBJECT(audiobin[MMPLAYER_A_EXTRACT_DEINTERLEAVE].gst),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added", G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), (gpointer)player);
+ _mmplayer_add_signal_connection(player, G_OBJECT(audiobin[MMPLAYER_A_EXTRACT_DEINTERLEAVE].gst),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads", G_CALLBACK(__mmplayer_gst_audio_deinterleave_no_more_pads), (gpointer)player);
+ player->no_more_pad = FALSE;
+ } else {
+ /* 4-2. create fakesink to extract interlevaed pcm */
+ LOGD("add audio fakesink for interleaved audio");
+ MMPLAYER_CREATE_ELEMENT(audiobin, extract_sink_id, "fakesink", "fakeaudiosink", *bucket, player);
+ if (!(player->audio_extract_opt & MM_PLAYER_AUDIO_EXTRACT_NO_SYNC_WITH_CLOCK))
+ g_object_set(G_OBJECT(audiobin[extract_sink_id].gst), "sync", TRUE, NULL);
+ g_object_set(G_OBJECT(audiobin[extract_sink_id].gst), "signal-handoffs", TRUE, NULL);
+
+ _mmplayer_add_signal_connection(player,
+ G_OBJECT(audiobin[extract_sink_id].gst),
+ MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
+ "handoff",
+ G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb),
+ (gpointer)player);
+
+ __mmplayer_add_sink(player, audiobin[extract_sink_id].gst, FALSE);
}
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
+
+ERROR: /* MMPLAYER_CREATE_ELEMENT */
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_PLAYER_INTERNAL;
+}
+
+static int
+__mmplayer_gst_make_audio_bin_element(mmplayer_t *player, GList **bucket)
+{
+ int ret = MM_ERROR_NONE;
+ mmplayer_gst_element_t *audiobin = NULL;
+ GList *element_bucket = NULL;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
+ player->pipeline->audiobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
+
+ audiobin = player->pipeline->audiobin;
+
+ if (player->build_audio_offload) { /* skip all the audio filters */
+ LOGD("create audio offload sink : %s", player->ini.audio_offload_sink_element);
+
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.audio_offload_sink_element, "audiosink", element_bucket, player);
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "sync", TRUE,
+ "volume", player->sound.volume, "mute", player->sound.mute, NULL);
+
+ __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst, FALSE);
+ goto DONE;
+ }
+
+ /* FIXME: need to mention the supportable condition at API reference */
+ if (player->audio_decoded_cb && (!MMPLAYER_IS_RTSP_STREAMING(player)))
+ ret = __mmplayer_gst_make_audio_extract_sink(player, &element_bucket);
+ else
+ ret = __mmplayer_gst_make_audio_playback_sink(player, &element_bucket);
+
+ if (ret != MM_ERROR_NONE)
+ goto ERROR;
DONE:
+ LOGD("success to make audio bin element");
*bucket = element_bucket;
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
ERROR:
+ LOGE("failed to make audio bin element");
g_list_free(element_bucket);
*bucket = NULL;
player->pipeline->audiobin = audiobin;
/* create audio filters and audiosink */
- if (__mmplayer_gst_fill_audio_bucket(player, &element_bucket) != MM_ERROR_NONE)
+ if (__mmplayer_gst_make_audio_bin_element(player, &element_bucket) != MM_ERROR_NONE)
goto ERROR;
/* adding created elements to bin */
LOGD("adding created elements to bin");
- if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket))
+ if (!_mmplayer_gst_element_add_bucket_to_bin(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket))
goto ERROR;
/* linking elements in the bucket by added order. */
LOGD("Linking elements in the bucket by added order.");
- if (__mmplayer_gst_element_link_bucket(element_bucket) == -1)
+ if (_mmplayer_gst_element_link_bucket(element_bucket) == -1)
goto ERROR;
/* get first element's sinkpad for creating ghostpad */
}
}
- /* release audiobin with it's childs */
+ /* release audiobin with it's children */
if (audiobin[MMPLAYER_A_BIN].gst)
gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
LOGW("failed to find bo %p", bo);
return ret;
}
+static void
+__mmplayer_video_stream_bo_list_free(mmplayer_video_bo_info_t *tmp)
+{
+ if (!tmp)
+ return;
+
+ if (tmp->bo)
+ tbm_bo_unref(tmp->bo);
+ g_free(tmp);
+}
static void
__mmplayer_video_stream_destroy_bo_list(mmplayer_t *player)
{
- GList *l = NULL;
-
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player);
MMPLAYER_VIDEO_BO_LOCK(player);
if (player->video_bo_list) {
LOGD("destroy video_bo_list : %d", g_list_length(player->video_bo_list));
- for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
- mmplayer_video_bo_info_t *tmp = (mmplayer_video_bo_info_t *)l->data;
- if (tmp) {
- if (tmp->bo)
- tbm_bo_unref(tmp->bo);
- g_free(tmp);
- }
- }
- g_list_free(player->video_bo_list);
+ g_list_free_full(player->video_bo_list, (GDestroyNotify)__mmplayer_video_stream_bo_list_free);
player->video_bo_list = NULL;
}
player->video_bo_size = 0;
}
/* update video num buffers */
- player->video_num_buffers = idx;
- if (idx == player->ini.num_of_video_bo)
- player->video_extra_num_buffers = player->ini.num_of_video_bo/2;
+ LOGD("video_num_buffers : %d", idx);
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ MM_PLAYER_VIDEO_BUFFER_TOTAL_SIZE, idx,
+ MM_PLAYER_VIDEO_BUFFER_EXTRA_SIZE, MAX(DEFAULT_NUM_OF_V_OUT_BUFFER, (idx / 2)),
+ NULL);
if (idx == 0) {
MMPLAYER_VIDEO_BO_UNLOCK(player);
return NULL;
}
-
- LOGD("Num of video buffers(%d/%d)", player->video_num_buffers, player->video_extra_num_buffers);
}
while (TRUE) {
{
mmplayer_t *player = (mmplayer_t *)data;
MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->video_stream_cb);
+ MMPLAYER_RETURN_IF_FAIL(player && player->video_decoded_cb);
/* send prerolled pkt */
player->video_stream_prerolled = false;
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player);
- MMPLAYER_RETURN_IF_FAIL(player->video_stream_cb);
+ MMPLAYER_RETURN_IF_FAIL(player->video_decoded_cb);
if (player->video_stream_prerolled) {
player->video_stream_prerolled = false;
return;
}
- __mmplayer_get_video_angle(player, NULL, &stream->orientation);
+ _mmplayer_get_video_angle(player, NULL, &stream->orientation);
/* set size and timestamp */
mem = gst_buffer_peek_memory(buffer, 0);
stream->length_total = gst_memory_get_sizes(mem, NULL, NULL);
- stream->timestamp = (unsigned int)(GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer))); /* nano sec -> mili sec */
+ stream->timestamp = (unsigned int)(GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer))); /* nano sec -> milli sec */
/* check zero-copy */
if (player->set_mode.video_zc &&
- player->set_mode.media_packet_video_stream &&
+ player->set_mode.video_export &&
gst_is_tizen_memory(mem)) {
__mmplayer_zerocopy_set_stride_elevation_bo(stream, mem);
stream->internal_buffer = gst_buffer_ref(buffer);
goto ERROR;
}
- if (!player->video_stream_cb(stream, player->video_stream_cb_user_param)) {
- LOGE("failed to send video stream data.");
+ if (!player->video_decoded_cb(stream, player->video_decoded_cb_user_param)) {
+ LOGE("failed to send video decoded data.");
goto ERROR;
}
/* create video360 filter */
if (player->is_360_feature_enabled && player->is_content_spherical) {
LOGD("create video360 element");
- MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_360, "video360", "video-360", TRUE, player);
+ MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_360, "video360", "video-360", element_bucket, player);
__mmplayer_gst_set_video360_property(player);
goto EXIT;
}
/* in case of sw codec & overlay surface type, except 360 playback.
* if libav video decoder is selected, videoconvert is required to render the shm wl-buffer which support RGB only via tizenwlsink. */
LOGD("create video converter: %s", video_csc);
- MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
+ MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", element_bucket, player);
EXIT:
*bucket = element_bucket;
return MM_ERROR_PLAYER_INTERNAL;
}
- LOGD("surface type %d, videosink factory name is %s", surface_type, factory_name);
if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
bool use_tbm = (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical));
- if (!use_tbm) {
- /* support shard memory with S/W codec on HawkP */
- if (strncmp(factory_name, "tizenwlsink", strlen(factory_name)) == 0) {
- g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
- "use-tbm", use_tbm, NULL);
- }
+ if (strncmp(factory_name, "tizenwlsink", strlen(factory_name)) == 0) {
+ g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
+ "use-tbm", use_tbm, NULL);
}
+
+ if (_mmplayer_update_video_overlay_param(player, "update_all_param") != MM_ERROR_NONE)
+ return MM_ERROR_PLAYER_INTERNAL;
+
+ LOGI("videosink factory name is %s use-tbm : %d", factory_name, use_tbm);
+
} else {
g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
"sync", TRUE, "max-lateness", FAKE_SINK_MAX_LATENESS, NULL);
}
- mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless);
+ mm_attrs_get_int_by_name(attrs, MM_PLAYER_GAPLESS_MODE, &gapless);
if (gapless > 0) {
LOGD("disable last-sample");
g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "enable-last-sample", FALSE, NULL);
}
- if (player->set_mode.media_packet_video_stream) {
+ if (player->set_mode.video_export) {
int enable = 0;
mm_attrs_get_int_by_name(player->attrs, "enable_video_decoded_cb", &enable);
if (enable || (surface_type == MM_DISPLAY_SURFACE_REMOTE) || (surface_type == MM_DISPLAY_SURFACE_NULL))
g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "signal-handoffs", TRUE, NULL);
- __mmplayer_add_signal_connection(player,
+ _mmplayer_add_signal_connection(player,
G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
"handoff",
G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
(gpointer)player);
- __mmplayer_add_signal_connection(player,
+ _mmplayer_add_signal_connection(player,
G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
"preroll-handoff",
(gpointer)player);
}
- if (_mmplayer_update_video_param(player, "update_all_param") != MM_ERROR_NONE)
- return MM_ERROR_PLAYER_INTERNAL;
-
if (videobin[MMPLAYER_V_SINK].gst) {
GstPad *sink_pad = NULL;
sink_pad = gst_element_get_static_pad(videobin[MMPLAYER_V_SINK].gst, "sink");
if (sink_pad) {
- __mmplayer_add_signal_connection(player, G_OBJECT(sink_pad), MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
+ _mmplayer_add_signal_connection(player, G_OBJECT(sink_pad), MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
"notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), (gpointer)player);
gst_object_unref(GST_OBJECT(sink_pad));
} else {
goto ERROR;
videosink_factory_name = __mmplayer_get_videosink_factory_name(player, surface_type);
- MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_factory_name, "videosink", TRUE, player);
+ MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_factory_name, "videosink", element_bucket, player);
/* additional setting for sink plug-in */
if (__mmplayer_gst_set_videosink_property(player, surface_type) != MM_ERROR_NONE) {
}
/* store it as it's sink element */
- __mmplayer_add_sink(player, videobin[MMPLAYER_V_SINK].gst);
+ __mmplayer_add_sink(player, videobin[MMPLAYER_V_SINK].gst, TRUE);
/* adding created elements to bin */
- if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket)) {
+ if (!_mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket)) {
LOGE("failed to add elements");
goto ERROR;
}
/* Linking elements in the bucket by added order */
- if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
+ if (_mmplayer_gst_element_link_bucket(element_bucket) == -1) {
LOGE("failed to link elements");
goto ERROR;
}
if (pad)
gst_object_unref(GST_OBJECT(pad));
- /* release videobin with it's childs */
+ /* release videobin with it's children */
if (videobin[MMPLAYER_V_BIN].gst)
gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
GList *element_bucket = NULL;
mmplayer_gst_element_t *textbin = player->pipeline->textbin;
- MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_QUEUE, "queue", "text_queue", TRUE, player);
- MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_IDENTITY, "identity", "text_identity", TRUE, player);
+ MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_QUEUE, "queue", "text_queue", element_bucket, player);
+ MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_IDENTITY, "identity", "text_identity", element_bucket, player);
g_object_set(G_OBJECT(textbin[MMPLAYER_T_IDENTITY].gst),
"signal-handoffs", FALSE,
NULL);
- MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
- __mmplayer_add_signal_connection(player,
+ MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", element_bucket, player);
+ _mmplayer_add_signal_connection(player,
G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
"handoff",
if (!player->play_subtitle) {
LOGD("add textbin sink as sink element of whole pipeline.");
- __mmplayer_add_sink(player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
+ __mmplayer_add_sink(player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst), FALSE);
}
/* adding created elements to bin */
LOGD("adding created elements to bin");
- if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket)) {
+ if (!_mmplayer_gst_element_add_bucket_to_bin(GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket)) {
LOGE("failed to add elements");
goto ERROR;
}
/* linking elements in the bucket by added order. */
LOGD("Linking elements in the bucket by added order.");
- if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
+ if (_mmplayer_gst_element_link_bucket(element_bucket) == -1) {
LOGE("failed to link elements");
goto ERROR;
}
}
}
- /* release textbin with it's childs */
+ /* release textbin with it's children */
if (textbin[MMPLAYER_T_BIN].gst)
gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
- MMPLAYER_FREEIF(player->pipeline->textbin);
+ MMPLAYER_FREEIF(textbin);
player->pipeline->textbin = NULL;
MMPLAYER_FLEAVE();
return MM_ERROR_PLAYER_INVALID_URI;
}
- if (!util_get_storage_info(subtitle_uri, &player->storage_info[MMPLAYER_PATH_TEXT])) {
+ if (!_mmplayer_get_storage_info(subtitle_uri, &player->storage_info[MMPLAYER_PATH_TEXT])) {
LOGE("failed to get storage info of subtitle path");
return MM_ERROR_PLAYER_INVALID_URI;
}
goto ERROR;
}
- charset = util_get_charset(subtitle_uri);
+ charset = _mmplayer_get_charset(subtitle_uri);
if (charset) {
LOGD("detected charset is %s", charset);
g_object_set(G_OBJECT(subparse), "subtitle-encoding", charset, NULL);
/* release signal */
__mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
- /* release textbin with it's childs */
+ /* release textbin with it's children */
gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
MMPLAYER_FREEIF(player->pipeline->textbin);
player->pipeline->textbin = textbin = NULL;
if (player->pipeline->textbin) {
LOGE("remove textbin");
- /* release textbin with it's childs */
+ /* release textbin with it's children */
MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->textbin, MMPLAYER_T_BIN);
MMPLAYER_FREEIF(player->pipeline->textbin);
player->pipeline->textbin = NULL;
return MM_ERROR_NONE;
}
- /* check current postion */
+ /* check current position */
player->adjust_subtitle_pos = position;
LOGD("save adjust_subtitle_pos in player");
}
player->pipeline = (mmplayer_pipeline_info_t *)g_malloc0(sizeof(mmplayer_pipeline_info_t));
- if (player->pipeline == NULL)
- goto INIT_ERROR;
/* create mainbin */
mainbin = (mmplayer_gst_element_t *)g_try_malloc0(sizeof(mmplayer_gst_element_t) * MMPLAYER_M_NUM);
player->pipeline->mainbin = mainbin;
/* create the source and decoder elements */
- if (MMPLAYER_IS_MS_BUFF_SRC(player))
- ret = __mmplayer_gst_build_es_pipeline(player);
- else
- ret = __mmplayer_gst_build_pipeline(player);
+ if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
+ ret = _mmplayer_gst_build_es_pipeline(player);
+ } else {
+ if (MMPLAYER_USE_DECODEBIN(player))
+ ret = _mmplayer_gst_build_pipeline(player); /* TEMP: previous pipeline, will be removed.*/
+ else
+ ret = _mmplayer_gst_build_pipeline_with_src(player);
+ }
if (ret != MM_ERROR_NONE) {
LOGE("failed to create some elements");
goto INIT_ERROR;
}
- /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
+ /* Note : check whether subtitle attribute uri is set. If uri is set, then try to play subtitle file */
if (__mmplayer_check_subtitle(player)
&& (__mmplayer_gst_create_text_pipeline(player) != MM_ERROR_NONE))
LOGE("failed to create text pipeline");
/* add bus watch */
- ret = __mmplayer_gst_add_bus_watch(player);
+ ret = _mmplayer_gst_add_bus_watch(player);
if (ret != MM_ERROR_NONE) {
LOGE("failed to add bus watch");
goto INIT_ERROR;
return MM_ERROR_NONE;
INIT_ERROR:
+ _mmplayer_bus_watcher_remove(player);
__mmplayer_gst_destroy_pipeline(player);
return MM_ERROR_PLAYER_INTERNAL;
}
MMPLAYER_FREEIF(player->type);
player->no_more_pad = FALSE;
player->num_dynamic_pad = 0;
- player->demux_pad_index = 0;
MMPLAYER_SUBTITLE_INFO_LOCK(player);
player->subtitle_language_list = NULL;
MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
+ MMPLAYER_RECONFIGURE_LOCK(player);
__mmplayer_reset_gapless_state(player);
+ MMPLAYER_RECONFIGURE_UNLOCK(player);
if (player->streamer) {
- __mm_player_streaming_initialize(player->streamer, FALSE);
- __mm_player_streaming_destroy(player->streamer);
+ _mm_player_streaming_initialize(player->streamer, FALSE);
+ _mm_player_streaming_destroy(player->streamer);
player->streamer = NULL;
}
MMPLAYER_FREEIF(player->unlinked_demuxer_mime);
/* cleanup running stuffs */
- __mmplayer_cancel_eos_timer(player);
+ _mmplayer_cancel_eos_timer(player);
/* cleanup gst stuffs */
if (player->pipeline) {
gst_object_unref(bus);
timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
- ret = __mmplayer_gst_set_state(player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout);
+ ret = _mmplayer_gst_set_state(player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout);
if (ret != MM_ERROR_NONE) {
LOGE("fail to change state to NULL");
return MM_ERROR_PLAYER_INTERNAL;
if (mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
- /* free avsysaudiosink
- avsysaudiosink should be unref when destory pipeline just after start play with BT.
- Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
- */
MMPLAYER_FREEIF(audiobin);
MMPLAYER_FREEIF(videobin);
MMPLAYER_FREEIF(textbin);
}
MMPLAYER_FREEIF(player->album_art);
+ if (player->type_caps) {
+ gst_caps_unref(player->type_caps);
+ player->type_caps = NULL;
+ }
+
if (player->v_stream_caps) {
gst_caps_unref(player->v_stream_caps);
player->v_stream_caps = NULL;
gst_caps_unref(player->s_stream_caps);
player->s_stream_caps = NULL;
}
- __mmplayer_track_destroy(player);
+ _mmplayer_track_destroy(player);
if (player->sink_elements)
g_list_free(player->sink_elements);
/* set pipeline state to READY */
/* NOTE : state change to READY must be performed sync. */
timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
- ret = __mmplayer_gst_set_state(player,
+ ret = _mmplayer_gst_set_state(player,
player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
if (ret != MM_ERROR_NONE) {
/* destroy pipeline */
ret = __mmplayer_gst_destroy_pipeline(player);
if (ret != MM_ERROR_NONE) {
- LOGE("failed to destory pipeline");
+ LOGE("failed to destroy pipeline");
return ret;
}
}
int
-__mmplayer_parse_profile(const char *uri, void *param, mmplayer_parse_profile_t *data)
+_mmplayer_parse_profile(const char *uri, void *param, mmplayer_parse_profile_t *data)
{
int ret = MM_ERROR_NONE;
char *path = NULL;
return ret;
}
-static gboolean
-__mmplayer_can_do_interrupt(mmplayer_t *player)
-{
- if (!player || !player->pipeline || !player->attrs) {
- LOGW("not initialized");
- goto FAILED;
- }
-
- if (player->audio_stream_render_cb) {
- LOGW("not support in pcm extraction mode");
- goto FAILED;
- }
-
- /* check if seeking */
- if (player->seek_state != MMPLAYER_SEEK_NONE) {
- MMMessageParamType msg_param;
- memset(&msg_param, 0, sizeof(MMMessageParamType));
- msg_param.code = MM_ERROR_PLAYER_SEEK;
- player->seek_state = MMPLAYER_SEEK_NONE;
- MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
- goto FAILED;
- }
-
- /* check other thread */
- if (!MMPLAYER_CMD_TRYLOCK(player)) {
- LOGW("locked already, cmd state : %d", player->cmd);
-
- /* check application command */
- if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) {
- LOGW("playing.. should wait cmd lock then, will be interrupted");
-
- /* lock will be released at mrp_resource_release_cb() */
- MMPLAYER_CMD_LOCK(player);
- goto INTERRUPT;
- }
- LOGW("nothing to do");
- goto FAILED;
- } else {
- LOGW("can interrupt immediately");
- goto INTERRUPT;
- }
-
-FAILED: /* with CMD UNLOCKED */
- return FALSE;
-
-INTERRUPT: /* with CMD LOCKED, released at mrp_resource_release_cb() */
- return TRUE;
-}
-
static int
__resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res,
void *user_data)
{
mmplayer_t *player = NULL;
+ MMMessageParamType msg = {0, };
+ gint64 pos = 0;
+ mmplayer_resource_type_e res_idx = MMPLAYER_RESOURCE_TYPE_MAX;
MMPLAYER_FENTER();
- if (user_data == NULL) {
- LOGE("- user_data is null");
- return FALSE;
+ if (!user_data) {
+ LOGE("user_data is null");
+ return TRUE;
}
- player = (mmplayer_t *)user_data;
- /* do something to release resource here.
- * player stop and interrupt forwarding */
- if (!__mmplayer_can_do_interrupt(player)) {
- LOGW("no need to interrupt, so leave");
- } else {
- MMMessageParamType msg = {0, };
- gint64 pos = 0;
+ player = (mmplayer_t *)user_data;
- player->interrupted_by_resource = TRUE;
+ if (!player->pipeline || !player->attrs) {
+ LOGW("not initialized");
+ return TRUE;
+ }
- /* get last play position */
- if (_mmplayer_get_position((MMHandleType)player, &pos) != MM_ERROR_NONE) {
- LOGW("failed to get play position.");
- } else {
- msg.union_type = MM_MSG_UNION_TIME;
- msg.time.elapsed = pos;
- MMPLAYER_POST_MSG(player, MM_MESSAGE_PLAY_POSITION, &msg);
- }
- LOGD("video resource conflict so, resource will be freed by unrealizing");
- if (_mmplayer_unrealize((MMHandleType)player))
- LOGW("failed to unrealize");
+ LOGD("cmd lock player, cmd state : %d", player->cmd);
+ MMPLAYER_CMD_LOCK(player);
+ LOGD("cmd locked player");
- /* lock is called in __mmplayer_can_do_interrupt() */
+ if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_NULL
+ || MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_NONE) {
+ LOGW("player already destroyed");
MMPLAYER_CMD_UNLOCK(player);
+ return TRUE;
}
- if (res == player->video_overlay_resource)
- player->video_overlay_resource = FALSE;
- else
- player->video_decoder_resource = FALSE;
+ player->interrupted_by_resource = TRUE;
- MMPLAYER_FLEAVE();
+ /* get last play position */
+ if (_mmplayer_gst_get_position(player, &pos) == MM_ERROR_NONE) {
+ msg.union_type = MM_MSG_UNION_TIME;
+ msg.time.elapsed = pos;
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_PLAY_POSITION, &msg);
+ } else {
+ LOGW("failed to get play position.");
+ }
- return FALSE;
+ LOGD("video resource conflict so, resource will be freed by unrealizing");
+ if (_mmplayer_unrealize((MMHandleType)player) != MM_ERROR_NONE)
+ LOGE("failed to unrealize");
+
+ MMPLAYER_CMD_UNLOCK(player);
+
+ for (res_idx = MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER; res_idx < MMPLAYER_RESOURCE_TYPE_MAX; res_idx++) {
+ player->hw_resource[res_idx] = NULL;
+ }
+
+ MMPLAYER_FLEAVE();
+ return TRUE; /* release all the resources */
}
static void
if (mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
__resource_release_cb, player, &player->resource_manager)
!= MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("failed to initialize resource manager");
+ LOGE("failed to create resource manager");
ret = MM_ERROR_PLAYER_INTERNAL;
goto ERROR;
}
g_mutex_init(&player->video_bo_mutex);
g_cond_init(&player->video_bo_cond);
- /* create media stream callback mutex */
- g_mutex_init(&player->media_stream_cb_lock);
-
/* create subtitle info lock and cond */
g_mutex_init(&player->subtitle_info_mutex);
g_cond_init(&player->subtitle_info_cond);
player->play_subtitle = FALSE;
player->has_closed_caption = FALSE;
- player->video_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER;
- player->video_extra_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER;
player->pending_resume = FALSE;
if (player->ini.dump_element_keyword[0][0] == '\0')
player->ini.set_dump_element_flag = FALSE;
/* free update tag lock */
g_mutex_clear(&player->update_tag_lock);
g_queue_free(player->bus_msg_q);
+ player->bus_msg_q = NULL;
/* free gapless play thread */
if (player->gapless_play_thread) {
MMPLAYER_GAPLESS_PLAY_THREAD_LOCK(player);
}
/* release */
for (i = 0; i < arg_count; i++) {
- //LOGD("release - argv[%d] : %s", i, argv2[i]);
+#ifdef __DEBUG__
+ LOGD("release - argv[%d] : %s", i, argv2[i]);
+#endif
MMPLAYER_FREEIF(argv2[i]);
}
gst_element_state_get_name(element_pending_state));
/* dump state of all element */
- __mmplayer_dump_pipeline_state(player);
+ _mmplayer_dump_pipeline_state(player);
return;
}
MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player);
MMPLAYER_GAPLESS_PLAY_THREAD_UNLOCK(player);
- LOGD("waitting for gapless play thread exit");
+ LOGD("waiting for gapless play thread exit");
g_thread_join(player->gapless_play_thread);
g_mutex_clear(&player->gapless_play_thread_mutex);
g_cond_clear(&player->gapless_play_thread_cond);
_mmplayer_release_video_capture(player);
- /* de-initialize resource manager */
- if (MM_RESOURCE_MANAGER_ERROR_NONE != mm_resource_manager_destroy(
- player->resource_manager))
- LOGE("failed to deinitialize resource manager");
+ /* release miscellaneous information */
+ __mmplayer_release_misc(player);
/* release pipeline */
- if (MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline(player)) {
- LOGE("failed to destory pipeline");
+ if (__mmplayer_gst_destroy_pipeline(player) != MM_ERROR_NONE) {
+ LOGE("failed to destroy pipeline");
return MM_ERROR_PLAYER_INTERNAL;
}
+ __mmplayer_destroy_hw_resource(player);
+
g_queue_free(player->bus_msg_q);
/* release subtitle info lock and cond */
__mmplayer_release_dump_list(player->dump_list);
- /* release miscellaneous information */
- __mmplayer_release_misc(player);
-
/* release miscellaneous information.
these info needs to be released after pipeline is destroyed. */
__mmplayer_release_misc_post(player);
/* release attributes */
_mmplayer_deconstruct_attribute(handle);
+ if (player->uri_info.uri_list) {
+ g_list_free_full(player->uri_info.uri_list, (GDestroyNotify)g_free);
+ player->uri_info.uri_list = NULL;
+ }
+
/* release lock */
g_mutex_clear(&player->fsink_lock);
g_mutex_clear(&player->video_bo_mutex);
g_cond_clear(&player->video_bo_cond);
- /* release media stream callback lock */
- g_mutex_clear(&player->media_stream_cb_lock);
-
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
_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;
MMPLAYER_FENTER();
mm_attrs_get_data_by_name(attrs, "profile_user_param", ¶m);
if (player->profile.uri_type == MM_PLAYER_URI_TYPE_NONE) {
- ret = __mmplayer_parse_profile((const char *)uri, param, &player->profile);
+ ret = _mmplayer_parse_profile((const char *)uri, param, &player->profile);
if (ret != MM_ERROR_NONE) {
LOGE("failed to parse profile");
player->is_subtitle_off = FALSE; /* set the subtitle ON default */
player->video360_metadata.is_spherical = -1;
player->is_openal_plugin_used = FALSE;
- player->demux_pad_index = 0;
player->subtitle_language_list = NULL;
player->is_subtitle_force_drop = FALSE;
- __mmplayer_track_initialize(player);
+ _mmplayer_track_initialize(player);
__mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
if ((MMPLAYER_IS_STREAMING(player)) && (player->streamer == NULL)) {
gint prebuffer_ms = 0, rebuffer_ms = 0;
- player->streamer = __mm_player_streaming_create();
- __mm_player_streaming_initialize(player->streamer, TRUE);
+ player->streamer = _mm_player_streaming_create();
+ _mm_player_streaming_initialize(player->streamer, TRUE);
- mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_PREBUFFER_MS, &prebuffer_ms);
- mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_REBUFFER_MS, &rebuffer_ms);
+ mm_attrs_multiple_get(player->attrs, NULL,
+ MM_PLAYER_PREBUFFER_MS, &prebuffer_ms,
+ MM_PLAYER_REBUFFER_MS, &rebuffer_ms, NULL);
if (prebuffer_ms > 0) {
prebuffer_ms = MAX(prebuffer_ms, 1000);
{
mmplayer_t *player = (mmplayer_t *)hplayer;
int ret = MM_ERROR_NONE;
+ int rm_ret = MM_ERROR_NONE;
+ mmplayer_resource_type_e res_idx = MMPLAYER_RESOURCE_TYPE_MAX;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
MMPLAYER_CMD_UNLOCK(player);
+ _mmplayer_bus_watcher_remove(player);
/* destroy the gst bus msg thread which is created during realize.
this funct have to be called before getting cmd lock. */
- __mmplayer_bus_msg_thread_destroy(player);
+ _mmplayer_bus_msg_thread_destroy(player);
MMPLAYER_CMD_LOCK(player);
/* check current state */
/* unrealize pipeline */
ret = __mmplayer_gst_unrealize(player);
- /* set asm stop if success */
- if (MM_ERROR_NONE == ret) {
- if (!player->interrupted_by_resource) {
- if (player->video_decoder_resource != NULL) {
- ret = mm_resource_manager_mark_for_release(player->resource_manager,
- player->video_decoder_resource);
- if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
- LOGE("failed to mark decoder resource for release, ret(0x%x)", ret);
- else
- player->video_decoder_resource = NULL;
- }
+ for (res_idx = MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER; res_idx < MMPLAYER_RESOURCE_TYPE_MAX; res_idx++) {
+ rm_ret = __mmplayer_release_hw_resource(player, res_idx);
+ if (rm_ret != MM_ERROR_NONE)
+ LOGE("failed to release [%d] resources", res_idx);
+ }
- if (player->video_overlay_resource != NULL) {
- ret = mm_resource_manager_mark_for_release(player->resource_manager,
- player->video_overlay_resource);
- if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
- LOGE("failed to mark overlay resource for release, ret(0x%x)", ret);
- else
- player->video_overlay_resource = NULL;
- }
-
- ret = mm_resource_manager_commit(player->resource_manager);
- if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
- LOGE("failed to commit resource releases, ret(0x%x)", ret);
- }
- } else
- LOGE("failed and don't change asm state to stop");
+ player->interrupted_by_resource = FALSE;
MMPLAYER_FLEAVE();
-
return ret;
}
return MM_ERROR_NONE;
}
-
-int
-_mmplayer_set_volume(MMHandleType hplayer, mmplayer_volume_type_t volume)
+static int
+__mmplayer_gst_set_volume_property(mmplayer_t *player, const char *prop_name)
{
- mmplayer_t *player = (mmplayer_t *)hplayer;
GstElement *vol_element = NULL;
- int i = 0;
+ enum audio_element_id volume_elem_id = MMPLAYER_A_VOL;
MMPLAYER_FENTER();
-
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- LOGD("volume [L]=%f:[R]=%f",
- volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
-
- /* invalid factor range or not */
- for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++) {
- if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
- LOGE("Invalid factor!(valid factor:0~1.0)");
- return MM_ERROR_INVALID_ARGUMENT;
- }
- }
-
- /* not support to set other value into each channel */
- if ((volume.level[MM_VOLUME_CHANNEL_LEFT] != volume.level[MM_VOLUME_CHANNEL_RIGHT]))
- return MM_ERROR_INVALID_ARGUMENT;
-
- /* Save volume to handle. Currently the first array element will be saved. */
- player->sound.volume = volume.level[MM_VOLUME_CHANNEL_LEFT];
+ MMPLAYER_RETURN_VAL_IF_FAIL(prop_name, MM_ERROR_INVALID_ARGUMENT);
/* check pipeline handle */
if (!player->pipeline || !player->pipeline->audiobin) {
- LOGD("audiobin is not created yet");
- LOGD("but, current stored volume will be set when it's created.");
+ LOGD("'%s' will be applied when audiobin is created", prop_name);
- /* NOTE : stored volume will be used in create_audiobin
+ /* NOTE : stored value will be used in create_audiobin
* returning MM_ERROR_NONE here makes application to able to
- * set volume at anytime.
+ * set audio volume or mute at anytime.
*/
return MM_ERROR_NONE;
}
- /* setting volume to volume element */
- vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
+ if (player->build_audio_offload || g_strrstr(player->ini.audiosink_element, "pulsesink"))
+ volume_elem_id = MMPLAYER_A_SINK;
- if (vol_element) {
- LOGD("volume is set [%f]", player->sound.volume);
- g_object_set(vol_element, "volume", player->sound.volume, NULL);
+ vol_element = player->pipeline->audiobin[volume_elem_id].gst;
+ if (!vol_element) {
+ LOGE("failed to get vol element %d", volume_elem_id);
+ return MM_ERROR_PLAYER_INTERNAL;
}
- MMPLAYER_FLEAVE();
+ LOGD("set '%s' property to element[%s]", prop_name, GST_ELEMENT_NAME(vol_element));
+
+ if (!g_object_class_find_property(G_OBJECT_GET_CLASS(vol_element), prop_name)) {
+ LOGE("there is no '%s' property", prop_name);
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+
+ if (!strcmp(prop_name, "volume")) {
+ g_object_set(vol_element, "volume", player->sound.volume, NULL);
+ } else if (!strcmp(prop_name, "mute")) {
+ g_object_set(vol_element, "mute", player->sound.mute, NULL);
+ } else {
+ LOGE("invalid property %s", prop_name);
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
return MM_ERROR_NONE;
}
int
-_mmplayer_get_volume(MMHandleType hplayer, mmplayer_volume_type_t *volume)
+_mmplayer_set_volume(MMHandleType hplayer, float volume)
{
+ int ret = MM_ERROR_NONE;
mmplayer_t *player = (mmplayer_t *)hplayer;
- int i = 0;
MMPLAYER_FENTER();
-
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(volume, MM_ERROR_INVALID_ARGUMENT);
- /* returning stored volume */
- for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
- volume->level[i] = player->sound.volume;
+ LOGD("volume = %f", volume);
- MMPLAYER_FLEAVE();
+ /* invalid factor range or not */
+ if (volume < MM_VOLUME_FACTOR_MIN || volume > MM_VOLUME_FACTOR_MAX) {
+ LOGE("Invalid volume value");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
- return MM_ERROR_NONE;
+ player->sound.volume = volume;
+
+ ret = __mmplayer_gst_set_volume_property(player, "volume");
+
+ MMPLAYER_FLEAVE();
+ return ret;
}
int
-_mmplayer_set_mute(MMHandleType hplayer, int mute)
+_mmplayer_get_volume(MMHandleType hplayer, float *volume)
{
mmplayer_t *player = (mmplayer_t *)hplayer;
- GstElement *vol_element = NULL;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+ MMPLAYER_RETURN_VAL_IF_FAIL(volume, MM_ERROR_INVALID_ARGUMENT);
- /* mute value shoud 0 or 1 */
- if (mute != 0 && mute != 1) {
- LOGE("bad mute value");
-
- /* FIXIT : definitly, we need _BAD_PARAM error code */
- return MM_ERROR_INVALID_ARGUMENT;
- }
-
- player->sound.mute = mute;
-
- /* just hold mute value if pipeline is not ready */
- if (!player->pipeline || !player->pipeline->audiobin) {
- LOGD("pipeline is not ready. holding mute value");
- return MM_ERROR_NONE;
- }
-
- vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
+ *volume = player->sound.volume;
- /* NOTE : volume will only created when the bt is enabled */
- if (vol_element) {
- LOGD("mute : %d", mute);
- g_object_set(vol_element, "mute", mute, NULL);
- } else
- LOGD("volume elemnet is not created. using volume in audiosink");
+ LOGD("current vol = %f", *volume);
MMPLAYER_FLEAVE();
-
return MM_ERROR_NONE;
}
int
-_mmplayer_get_mute(MMHandleType hplayer, int *pmute)
+_mmplayer_set_mute(MMHandleType hplayer, bool mute)
{
+ int ret = MM_ERROR_NONE;
mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
-
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(pmute, MM_ERROR_INVALID_ARGUMENT);
- /* just hold mute value if pipeline is not ready */
- if (!player->pipeline || !player->pipeline->audiobin) {
- LOGD("pipeline is not ready. returning stored value");
- *pmute = player->sound.mute;
- return MM_ERROR_NONE;
- }
+ LOGD("mute = %d", mute);
+
+ player->sound.mute = mute;
- *pmute = player->sound.mute;
+ ret = __mmplayer_gst_set_volume_property(player, "mute");
MMPLAYER_FLEAVE();
-
- return MM_ERROR_NONE;
+ return ret;
}
int
-_mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
+_mmplayer_get_mute(MMHandleType hplayer, bool *mute)
{
mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+ MMPLAYER_RETURN_VAL_IF_FAIL(mute, MM_ERROR_INVALID_ARGUMENT);
+
+ *mute = player->sound.mute;
- player->video_stream_changed_cb = callback;
- player->video_stream_changed_cb_user_param = user_param;
- LOGD("Handle value is %p : %p", player, player->video_stream_changed_cb);
+ LOGD("current mute = %d", *mute);
MMPLAYER_FLEAVE();
}
int
-_mmplayer_set_audiostream_cb(MMHandleType hplayer, bool sync, mm_player_audio_stream_callback callback, void *user_param)
+_mmplayer_set_audio_decoded_cb(MMHandleType hplayer, mmplayer_audio_extract_opt_e opt, mm_player_audio_decoded_callback callback, void *user_param)
{
mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- player->audio_stream_render_cb = callback;
- player->audio_stream_cb_user_param = user_param;
- player->audio_stream_sink_sync = sync;
- LOGD("handle: %p, cb: %p, sync: %d", player, player->audio_stream_render_cb, player->audio_stream_sink_sync);
+ player->audio_decoded_cb = callback;
+ player->audio_decoded_cb_user_param = user_param;
+ player->audio_extract_opt = opt;
+ LOGD("handle: %p, cb: %p, opt: 0x%X", player, player->audio_decoded_cb, player->audio_extract_opt);
MMPLAYER_FLEAVE();
}
int
-_mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param)
+_mmplayer_set_video_decoded_cb(MMHandleType hplayer, mm_player_video_decoded_callback callback, void *user_param)
{
mmplayer_t *player = (mmplayer_t *)hplayer;
if (callback && !player->bufmgr)
player->bufmgr = tbm_bufmgr_init(-1);
- player->set_mode.media_packet_video_stream = (callback) ? true : false;
- player->video_stream_cb = callback;
- player->video_stream_cb_user_param = user_param;
+ player->set_mode.video_export = (callback) ? true : false;
+ player->video_decoded_cb = callback;
+ player->video_decoded_cb_user_param = user_param;
- LOGD("Stream cb Handle value is %p : %p, enable:%d", player, player->video_stream_cb, player->set_mode.media_packet_video_stream);
+ LOGD("Stream cb Handle value is %p : %p, enable:%d", player, player->video_decoded_cb, player->set_mode.video_export);
MMPLAYER_FLEAVE();
MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_START);
/* start pipeline */
- ret = __mmplayer_gst_start(player);
+ ret = _mmplayer_gst_start(player);
if (ret != MM_ERROR_NONE)
LOGE("failed to start player.");
return MM_ERROR_NONE;
}
-static void
-__mmplayer_check_pipeline(mmplayer_t *player)
+static void __mmplayer_check_pipeline_reconfigure_state(mmplayer_t *player)
{
GstState element_state = GST_STATE_VOID_PENDING;
- GstState element_pending_state = GST_STATE_VOID_PENDING;
- gint timeout = 0;
- int ret = MM_ERROR_NONE;
+ GstState element_pending_state = GST_STATE_VOID_PENDING;
+ GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
+ gint timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
- if (!player->gapless.reconfigure)
- return;
+ MMPLAYER_RETURN_IF_FAIL(player && player->pipeline);
- LOGW("pipeline is under construction.");
+ MMPLAYER_RECONFIGURE_LOCK(player);
+ if (!player->gapless.reconfigure) {
+ MMPLAYER_RECONFIGURE_UNLOCK(player);
+ return;
+ }
- MMPLAYER_PLAYBACK_LOCK(player);
- MMPLAYER_PLAYBACK_UNLOCK(player);
+ LOGI("reconfigure is under process");
+ MMPLAYER_RECONFIGURE_WAIT(player);
+ MMPLAYER_RECONFIGURE_UNLOCK(player);
+ LOGI("reconfigure is completed.");
- timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
+ result = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
+ &element_state, &element_pending_state, timeout * GST_SECOND);
+ if (result == GST_STATE_CHANGE_FAILURE)
+ LOGW("failed to get pipeline state in %d sec", timeout);
- /* wait for state transition */
- ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND);
- if (ret == GST_STATE_CHANGE_FAILURE)
- LOGE("failed to change pipeline state within %d sec", timeout);
+ return;
}
/* NOTE : it should be able to call 'stop' anytime*/
/* check current state */
MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_STOP);
- /* check pipline building state */
- __mmplayer_check_pipeline(player);
+ /* need to wait till the rebuilding pipeline is completed */
+ __mmplayer_check_pipeline_reconfigure_state(player);
+ MMPLAYER_RECONFIGURE_LOCK(player);
__mmplayer_reset_gapless_state(player);
+ MMPLAYER_RECONFIGURE_UNLOCK(player);
/* NOTE : application should not wait for EOS after calling STOP */
- __mmplayer_cancel_eos_timer(player);
+ _mmplayer_cancel_eos_timer(player);
/* reset */
player->seek_state = MMPLAYER_SEEK_NONE;
/* stop pipeline */
- ret = __mmplayer_gst_stop(player);
+ ret = _mmplayer_gst_stop(player);
if (ret != MM_ERROR_NONE)
LOGE("failed to stop player.");
/* check current state */
MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_PAUSE);
- /* check pipline building state */
- __mmplayer_check_pipeline(player);
+ /* check pipeline reconfigure state */
+ __mmplayer_check_pipeline_reconfigure_state(player);
switch (MMPLAYER_CURRENT_STATE(player)) {
case MM_PLAYER_STATE_READY:
{
/* check prepare async or not.
- * In the case of streaming playback, it's recommned to avoid blocking wait.
+ * In the case of streaming playback, it's recommended to avoid blocking wait.
*/
mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
LOGD("prepare working mode : %s", (async ? "async" : "sync"));
This causes problem is position calculation during normal pause resume scenarios also.
Currently during pause , we are sending the current position to rtspsrc module for position saving. */
if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
- (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
+ (_mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL);
}
}
}
/* pause pipeline */
- ret = __mmplayer_gst_pause(player, async);
-
- if (ret != MM_ERROR_NONE)
+ ret = _mmplayer_gst_pause(player, async);
+ if (ret != MM_ERROR_NONE) {
LOGE("failed to pause player. ret : 0x%x", ret);
+ MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-pause-err");
+ return ret;
+ }
if (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) {
- if (MM_ERROR_NONE != _mmplayer_update_video_param(player, "display_rotation"))
+ if (_mmplayer_update_video_overlay_param(player, "display_rotation") != MM_ERROR_NONE)
LOGE("failed to update display_rotation");
}
MMPLAYER_FLEAVE();
-
- return ret;
+ return MM_ERROR_NONE;
}
/* in case of streaming, pause could take long time.*/
LOGD("set the pipeline state to READY");
/* set state to READY */
- ret = __mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
+ ret = _mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
GST_STATE_READY, FALSE, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
if (ret != MM_ERROR_NONE) {
LOGE("fail to change state to READY");
/* check current state */
MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_RESUME);
- ret = __mmplayer_gst_resume(player, async);
+ ret = _mmplayer_gst_resume(player, async);
if (ret != MM_ERROR_NONE)
LOGE("failed to resume player.");
mmplayer_t *player = (mmplayer_t *)hplayer;
gint64 pos_nsec = 0;
int ret = MM_ERROR_NONE;
- int mute = FALSE;
+ bool mute = false;
signed long long start = 0, stop = 0;
mmplayer_state_e current_state = MM_PLAYER_STATE_NONE;
MMPLAYER_FENTER();
/* The sound of video is not supported under 0.0 and over 2.0. */
if (rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN) {
if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
- mute = TRUE;
+ mute = true;
}
_mmplayer_set_mute(hplayer, mute);
stop = pos_nsec;
}
- if (!__mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
+ if (!_mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
player->playback_rate,
GST_FORMAT_TIME,
(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- /* check pipline building state */
- __mmplayer_check_pipeline(player);
+ /* check pipeline reconfigure state */
+ __mmplayer_check_pipeline_reconfigure_state(player);
- ret = __mmplayer_gst_set_position(player, position, FALSE);
+ ret = _mmplayer_gst_set_position(player, position, FALSE);
MMPLAYER_FLEAVE();
}
int
-_mmplayer_get_position(MMHandleType hplayer, gint64 *position)
-{
- mmplayer_t *player = (mmplayer_t *)hplayer;
- int ret = MM_ERROR_NONE;
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- ret = __mmplayer_gst_get_position(player, position);
-
- return ret;
-}
-
-int
_mmplayer_get_duration(MMHandleType hplayer, gint64 *duration)
{
mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- ret = __mmplayer_gst_get_buffer_position(player, start_pos, end_pos);
+ ret = _mmplayer_gst_get_buffer_position(player, start_pos, end_pos);
return ret;
}
int
-_mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int position)
+_mmplayer_adjust_subtitle_position(MMHandleType hplayer, int position)
{
mmplayer_t *player = (mmplayer_t *)hplayer;
int ret = MM_ERROR_NONE;
return FALSE;
}
-static void
-__mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps)
+void
+_mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps)
{
GstStructure *caps_structure = NULL;
gint samplerate = 0;
/* set stream information */
gst_structure_get_int(caps_structure, "rate", &samplerate);
- mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
-
gst_structure_get_int(caps_structure, "channels", &channels);
- mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
+
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ "content_audio_samplerate", samplerate,
+ "content_audio_channels", channels, NULL);
LOGD("audio samplerate : %d channels : %d", samplerate, channels);
}
}
void
-__mmplayer_typefind_have_type(GstElement *tf, guint probability,
+_mmplayer_typefind_have_type(GstElement *tf, guint probability,
GstCaps *caps, gpointer data)
{
mmplayer_t *player = (mmplayer_t *)data;
- GstPad *pad = NULL;
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player && tf && caps);
/* store type string */
+ if (player->type_caps) {
+ gst_caps_unref(player->type_caps);
+ player->type_caps = NULL;
+ }
+
+ player->type_caps = gst_caps_copy(caps);
+ MMPLAYER_LOG_GST_CAPS_TYPE(player->type_caps);
+
MMPLAYER_FREEIF(player->type);
player->type = gst_caps_to_string(caps);
if (player->type)
__mmplayer_update_content_type_info(player);
- pad = gst_element_get_static_pad(tf, "src");
- if (!pad) {
- LOGE("fail to get typefind src pad.");
- return;
- }
+ if (!player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst) {
+ GstPad *pad = NULL;
- if (!__mmplayer_gst_create_decoder(player, pad, caps)) {
- gboolean async = FALSE;
- LOGE("failed to autoplug %s", player->type);
+ pad = gst_element_get_static_pad(tf, "src");
+ if (!pad) {
+ LOGE("fail to get typefind src pad.");
+ return;
+ }
- mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
+ if (!_mmplayer_gst_create_decoder(player, pad, caps)) {
+ gboolean async = FALSE;
+ LOGE("failed to autoplug %s", player->type);
- if (async && player->msg_posted == FALSE)
- __mmplayer_handle_missed_plugin(player);
+ mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
+ if (async && player->msg_posted == FALSE)
+ __mmplayer_handle_missed_plugin(player);
+ }
+ gst_object_unref(GST_OBJECT(pad));
}
-
- gst_object_unref(GST_OBJECT(pad));
-
MMPLAYER_FLEAVE();
-
return;
}
GstElement *
-__mmplayer_gst_make_decodebin(mmplayer_t *player)
+_mmplayer_gst_make_decodebin(mmplayer_t *player)
{
GstElement *decodebin = NULL;
}
/* raw pad handling signal */
- __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
- G_CALLBACK(__mmplayer_gst_decode_pad_added), (gpointer)player);
+ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
+ G_CALLBACK(_mmplayer_gst_decode_pad_added), (gpointer)player);
/* no-more-pad pad handling signal */
- __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
- G_CALLBACK(__mmplayer_gst_decode_no_more_pads), (gpointer)player);
+ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
+ G_CALLBACK(_mmplayer_gst_decode_no_more_pads), (gpointer)player);
- __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
- G_CALLBACK(__mmplayer_gst_decode_pad_removed), (gpointer)player);
+ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
+ G_CALLBACK(_mmplayer_gst_decode_pad_removed), (gpointer)player);
/* This signal is emitted when a pad for which there is no further possible
decoding is added to the decodebin.*/
- __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
- G_CALLBACK(__mmplayer_gst_decode_unknown_type), (gpointer)player);
+ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
+ G_CALLBACK(_mmplayer_gst_decode_unknown_type), (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-continue",
- G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), (gpointer)player);
+ _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",
- G_CALLBACK(__mmplayer_gst_decode_autoplug_select), (gpointer)player);
+ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
+ G_CALLBACK(_mmplayer_gst_decode_autoplug_select), (gpointer)player);
/* This signal is emitted once decodebin has finished decoding all the data.*/
- __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
- G_CALLBACK(__mmplayer_gst_decode_drained), (gpointer)player);
+ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
+ G_CALLBACK(_mmplayer_gst_decode_drained), (gpointer)player);
/* This signal is emitted when a element is added to the bin.*/
- __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
- G_CALLBACK(__mmplayer_gst_element_added), (gpointer)player);
+ _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
+ G_CALLBACK(_mmplayer_gst_element_added), (gpointer)player);
ERROR:
return decodebin;
dur_bytes = 0;
}
- __mm_player_streaming_set_queue2(player->streamer,
+ _mm_player_streaming_set_queue2(player->streamer,
queue2,
FALSE,
type,
}
gboolean
-__mmplayer_gst_create_decoder(mmplayer_t *player, GstPad *srcpad, const GstCaps *caps)
+_mmplayer_gst_create_decoder(mmplayer_t *player, GstPad *srcpad, const GstCaps *caps)
{
mmplayer_gst_element_t *mainbin = NULL;
GstElement *decodebin = NULL;
}
/* create decodebin */
- decodebin = __mmplayer_gst_make_decodebin(player);
+ decodebin = _mmplayer_gst_make_decodebin(player);
if (!decodebin) {
LOGE("failed to make decodebin");
goto ERROR;
return MM_ERROR_NONE;
}
-static void
-__mmplayer_pipeline_complete(GstElement *decodebin, gpointer data)
+void
+_mmplayer_pipeline_complete(GstElement *decodebin, gpointer data)
{
mmplayer_t *player = (mmplayer_t *)data;
MMPLAYER_RETURN_IF_FAIL(player);
/* remove fakesink. */
- if (!__mmplayer_gst_remove_fakesink(player,
+ if (!_mmplayer_gst_remove_fakesink(player,
&player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK])) {
- /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
+ /* NOTE : _mmplayer_pipeline_complete() can be called several time. because
* signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various
* source element are not same. To overcome this situation, this function will called
* several places and several times. Therefore, this is not an error case.
LOGD("[handle: %p] pipeline has completely constructed", player);
- if ((player->ini.async_start) &&
- (player->msg_posted == FALSE) &&
+ if ((player->msg_posted == FALSE) &&
(player->cmd >= MMPLAYER_COMMAND_START))
__mmplayer_handle_missed_plugin(player);
continue;
}
- if (__mmplayer_parse_profile((const char *)uri, NULL, &profile) != MM_ERROR_NONE) {
+ if (_mmplayer_parse_profile((const char *)uri, NULL, &profile) != MM_ERROR_NONE) {
LOGE("failed to parse profile");
continue;
}
break;
}
- if (uri_idx == num_of_list) {
+ if (!uri || uri_idx == num_of_list) {
LOGE("failed to find next uri");
return FALSE;
}
player->uri_info.uri_idx = uri_idx;
- mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
-
- if (mm_attrs_commit_all(player->attrs)) {
- LOGE("failed to commit");
+ if (mm_player_set_attribute((MMHandleType)player, NULL,
+ "profile_uri", uri, strlen(uri), NULL) != MM_ERROR_NONE) {
+ LOGE("failed to set attribute");
return FALSE;
}
static gboolean
__mmplayer_verify_gapless_play_path(mmplayer_t *player)
{
-#define REPEAT_COUNT_INFINITELY -1
+#define REPEAT_COUNT_INFINITE -1
#define REPEAT_COUNT_MIN 2
+#define ORIGINAL_URI_ONLY 1
MMHandleType attrs = 0;
gint video = 0;
gint count = 0;
gint gapless = 0;
- guint num_of_list = 0;
+ guint num_of_uri = 0;
int profile_tv = -1;
MMPLAYER_FENTER();
LOGD("checking for gapless play option");
+ if (player->build_audio_offload) {
+ LOGE("offload path is not supportable.");
+ goto ERROR;
+ }
+
if (player->pipeline->textbin) {
LOGE("subtitle path is enabled. gapless play is not supported.");
goto ERROR;
goto ERROR;
}
- mm_attrs_get_int_by_name(attrs, "content_video_found", &video);
+ mm_attrs_multiple_get(player->attrs, NULL,
+ "content_video_found", &video,
+ "profile_play_count", &count,
+ MM_PLAYER_GAPLESS_MODE, &gapless, NULL);
/* gapless playback is not supported in case of video at TV profile. */
profile_tv = __mmplayer_check_profile();
goto ERROR;
}
- if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
- LOGE("failed to get play count");
-
- if (mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless) != MM_ERROR_NONE)
- LOGE("failed to get gapless mode");
-
/* check repeat count in case of audio */
if (!gapless &&
- (video || (count != REPEAT_COUNT_INFINITELY && count < REPEAT_COUNT_MIN))) {
+ (video || (count != REPEAT_COUNT_INFINITE && count < REPEAT_COUNT_MIN))) {
LOGW("gapless is disabled");
goto ERROR;
}
- num_of_list = g_list_length(player->uri_info.uri_list);
+ num_of_uri = g_list_length(player->uri_info.uri_list);
- LOGD("repeat count = %d, num_of_list = %d", count, num_of_list);
+ LOGD("repeat count = %d, num_of_list = %d", count, num_of_uri);
- if (num_of_list == 0) {
+ if (num_of_uri == ORIGINAL_URI_ONLY) {
/* audio looping path */
if (count >= REPEAT_COUNT_MIN) {
/* decrease play count */
/* we succeeded to rewind. update play count and then wait for next EOS */
count--;
- mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
- /* commit attribute */
- if (mm_attrs_commit_all(attrs))
- LOGE("failed to commit attribute");
-
- } else if (count != REPEAT_COUNT_INFINITELY) {
+ mm_player_set_attribute((MMHandleType)player, NULL, "profile_play_count", count, NULL);
+ } else if (count != REPEAT_COUNT_INFINITE) {
LOGD("there is no next uri and no repeat");
goto ERROR;
}
}
static void
-__mmplayer_initialize_gapless_play(mmplayer_t *player)
+__mmplayer_remove_sinkpad (const GValue *item, gpointer user_data)
{
- int i;
-
- MMPLAYER_FENTER();
-
- player->smooth_streaming = FALSE;
- player->videodec_linked = 0;
- player->audiodec_linked = 0;
- player->textsink_linked = 0;
- player->is_external_subtitle_present = FALSE;
- player->is_external_subtitle_added_now = FALSE;
- player->not_supported_codec = MISSING_PLUGIN_NONE;
- player->can_support_codec = FOUND_PLUGIN_NONE;
- player->pending_seek.is_pending = false;
- player->pending_seek.pos = 0;
- player->msg_posted = FALSE;
- player->has_many_types = FALSE;
- player->no_more_pad = FALSE;
- player->not_found_demuxer = 0;
- player->seek_state = MMPLAYER_SEEK_NONE;
- player->is_subtitle_force_drop = FALSE;
- player->play_subtitle = FALSE;
- player->adjust_subtitle_pos = 0;
-
- player->total_bitrate = 0;
- player->total_maximum_bitrate = 0;
-
- __mmplayer_track_initialize(player);
- __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
-
- for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) {
- player->bitrate[i] = 0;
- player->maximum_bitrate[i] = 0;
- }
-
- if (player->v_stream_caps) {
- gst_caps_unref(player->v_stream_caps);
- player->v_stream_caps = NULL;
- }
-
- mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
-
- /* clean found audio decoders */
- if (player->audio_decoders) {
- GList *a_dec = player->audio_decoders;
- for (; a_dec; a_dec = g_list_next(a_dec)) {
- gchar *name = a_dec->data;
- MMPLAYER_FREEIF(name);
- }
- g_list_free(player->audio_decoders);
- player->audio_decoders = NULL;
+ GstPad *sinkpad = g_value_get_object (item);
+ GstElement *element = GST_ELEMENT(user_data);
+ if (!sinkpad || !element) {
+ LOGE("invalid parameter");
+ return;
}
- MMPLAYER_FLEAVE();
+ LOGD("(%s)element release request pad(%s)", GST_ELEMENT_NAME(element), GST_PAD_NAME(sinkpad));
+ gst_element_release_request_pad(element, GST_PAD(sinkpad));
}
-static void
-__mmplayer_activate_next_source(mmplayer_t *player, GstState target)
+static gboolean
+__mmplayer_deactivate_combiner(mmplayer_t *player, mmplayer_track_type_e type)
{
- mmplayer_gst_element_t *mainbin = NULL;
- MMMessageParamType msg_param = {0,};
- GstElement *element = NULL;
- MMHandleType attrs = 0;
- char *uri = NULL;
- main_element_id_e elem_idx = MMPLAYER_M_NUM;
+ mmplayer_gst_element_t *sinkbin = NULL;
+ main_element_id_e concatId = MMPLAYER_M_NUM;
+ main_element_id_e sinkId = MMPLAYER_M_NUM;
+ gboolean send_notice = FALSE;
+ GstElement *element;
+ GstIterator *iter;
MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
- if (!player || !player->pipeline || !player->pipeline->mainbin) {
- LOGE("player is not initialized");
- goto ERROR;
- }
-
- mainbin = player->pipeline->mainbin;
- msg_param.code = MM_ERROR_PLAYER_INTERNAL;
-
- attrs = MMPLAYER_GET_ATTRS(player);
- if (!attrs) {
- LOGE("fail to get attributes");
- goto ERROR;
- }
-
- /* Initialize Player values */
- __mmplayer_initialize_gapless_play(player);
-
- mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
-
- if (__mmplayer_parse_profile((const char *)uri, NULL, &player->profile) != MM_ERROR_NONE) {
- LOGE("failed to parse profile");
- msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
- goto ERROR;
- }
-
- if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
- (MMPLAYER_URL_HAS_HLS_SUFFIX(player))) {
- LOGE("dash or hls is not supportable");
- msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
- goto ERROR;
- }
-
- element = __mmplayer_gst_create_source(player);
- if (!element) {
- LOGE("no source element was created");
- goto ERROR;
- }
-
- if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
- LOGE("failed to add source element to pipeline");
- gst_object_unref(GST_OBJECT(element));
- element = NULL;
- goto ERROR;
- }
-
- /* take source element */
- mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
- mainbin[MMPLAYER_M_SRC].gst = element;
-
- element = NULL;
-
- if (MMPLAYER_IS_HTTP_STREAMING(player)) {
- if (player->streamer == NULL) {
- player->streamer = __mm_player_streaming_create();
- __mm_player_streaming_initialize(player->streamer, TRUE);
- }
-
- elem_idx = MMPLAYER_M_TYPEFIND;
- element = gst_element_factory_make("typefind", "typefinder");
- __mmplayer_add_signal_connection(player, G_OBJECT(element),
- MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type", G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player);
- } else {
- elem_idx = MMPLAYER_M_AUTOPLUG;
- element = __mmplayer_gst_make_decodebin(player);
- }
-
- /* check autoplug element is OK */
- if (!element) {
- LOGE("can not create element(%d)", elem_idx);
- goto ERROR;
- }
-
- if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
- LOGE("failed to add sinkbin to pipeline");
- gst_object_unref(GST_OBJECT(element));
- element = NULL;
- goto ERROR;
- }
-
- mainbin[elem_idx].id = elem_idx;
- mainbin[elem_idx].gst = element;
+ LOGD("type %d", type);
- if (gst_element_link(mainbin[MMPLAYER_M_SRC].gst, mainbin[elem_idx].gst) == FALSE) {
- LOGE("Failed to link src - autoplug(or typefind)");
- goto ERROR;
+ switch (type) {
+ case MM_PLAYER_TRACK_TYPE_AUDIO:
+ concatId = MMPLAYER_M_A_CONCAT;
+ sinkId = MMPLAYER_A_BIN;
+ sinkbin = player->pipeline->audiobin;
+ break;
+ case MM_PLAYER_TRACK_TYPE_VIDEO:
+ concatId = MMPLAYER_M_V_CONCAT;
+ sinkId = MMPLAYER_V_BIN;
+ sinkbin = player->pipeline->videobin;
+ send_notice = TRUE;
+ break;
+ case MM_PLAYER_TRACK_TYPE_TEXT:
+ concatId = MMPLAYER_M_T_CONCAT;
+ sinkId = MMPLAYER_T_BIN;
+ sinkbin = player->pipeline->textbin;
+ break;
+ default:
+ LOGE("requested type is not supportable");
+ return FALSE;
+ break;
}
- if (gst_element_set_state(mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE) {
- LOGE("Failed to change state of src element");
- goto ERROR;
- }
+ element = player->pipeline->mainbin[concatId].gst;
+ if (!element)
+ return TRUE;
- if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
- if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
- LOGE("Failed to change state of decodebin");
- goto ERROR;
- }
- } else {
- if (gst_element_set_state(mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE) {
- LOGE("Failed to change state of src element");
- goto ERROR;
+ if ((sinkbin) && (sinkbin[sinkId].gst)) {
+ GstPad *srcpad = gst_element_get_static_pad(element, "src");
+ GstPad *sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink");
+ if (srcpad && sinkpad) {
+ /* after getting drained signal there is no data flows, so no need to do pad_block */
+ LOGD("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
+ gst_pad_unlink(srcpad, sinkpad);
+
+ /* send custom event to sink pad to handle it at video sink */
+ if (send_notice) {
+ LOGD("send custom event to sinkpad");
+ GstStructure *s = gst_structure_new_empty("tizen/flush-buffer");
+ GstEvent *event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, s);
+ gst_pad_send_event(sinkpad, event);
+ }
}
+ gst_object_unref(srcpad);
+ gst_object_unref(sinkpad);
}
- player->gapless.stream_changed = TRUE;
- player->gapless.running = TRUE;
- MMPLAYER_FLEAVE();
- return;
-
-ERROR:
- if (player) {
- MMPLAYER_PLAYBACK_UNLOCK(player);
+ LOGD("release concat request pad");
+ /* release and unref requests pad from the selector */
+ iter = gst_element_iterate_sink_pads(element);
+ while (gst_iterator_foreach(iter, __mmplayer_remove_sinkpad, element) == GST_ITERATOR_RESYNC)
+ gst_iterator_resync(iter);
+ gst_iterator_free(iter);
- if (!player->msg_posted) {
- MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
- player->msg_posted = TRUE;
- }
- }
- return;
+ return TRUE;
}
static gboolean
__mmplayer_deactivate_selector(mmplayer_t *player, mmplayer_track_type_e type)
{
- mmplayer_selector_t *selector = &player->selector[type];
+ mmplayer_track_t *selector = &player->track[type];
mmplayer_gst_element_t *sinkbin = NULL;
main_element_id_e selectorId = MMPLAYER_M_NUM;
main_element_id_e sinkId = MMPLAYER_M_NUM;
LOGD("selector release");
/* release and unref requests pad from the selector */
- for (n = 0; n < selector->channels->len; n++) {
- GstPad *sinkpad = g_ptr_array_index(selector->channels, n);
+ for (n = 0; n < selector->streams->len; n++) {
+ GstPad *sinkpad = g_ptr_array_index(selector->streams, n);
gst_element_release_request_pad((player->pipeline->mainbin[selectorId].gst), sinkpad);
}
- g_ptr_array_set_size(selector->channels, 0);
+
+ g_ptr_array_set_size(selector->streams, 0);
gst_element_set_state(player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player);
- if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
- (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
- (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT))) {
- LOGE("deactivate selector error");
- goto ERROR;
+ if (MMPLAYER_USE_DECODEBIN(player)) {
+ if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
+ (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
+ (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT))) {
+ LOGE("deactivate selector error");
+ goto ERROR;
+ }
+ } else {
+ if ((!__mmplayer_deactivate_combiner(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
+ (!__mmplayer_deactivate_combiner(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
+ (!__mmplayer_deactivate_combiner(player, MM_PLAYER_TRACK_TYPE_TEXT))) {
+ LOGE("deactivate concat error");
+ goto ERROR;
+ }
}
- __mmplayer_track_destroy(player);
+ _mmplayer_track_destroy(player);
__mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
if (player->streamer) {
- __mm_player_streaming_initialize(player->streamer, FALSE);
- __mm_player_streaming_destroy(player->streamer);
+ _mm_player_streaming_initialize(player->streamer, FALSE);
+ _mm_player_streaming_destroy(player->streamer);
player->streamer = NULL;
}
- MMPLAYER_PLAYBACK_LOCK(player);
MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player);
-
MMPLAYER_FLEAVE();
return;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+ MMPLAYER_RETURN_VAL_IF_FAIL(uri, MM_ERROR_INVALID_ARGUMENT);
- mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
- if (mm_attrs_commit_all(player->attrs)) {
- LOGE("failed to commit the original uri.");
+ if (mm_player_set_attribute(hplayer, NULL,
+ "profile_uri", uri, strlen(uri), NULL) != MM_ERROR_NONE) {
+ LOGE("failed to set attribute");
result = MM_ERROR_PLAYER_INTERNAL;
} else {
if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE)
if (num_of_list > 0) {
gint uri_idx = player->uri_info.uri_idx;
- if (uri_idx < num_of_list-1)
+ if (uri_idx < num_of_list - 1)
uri_idx++;
else
uri_idx = 0;
return MM_ERROR_NONE;
}
-static void
-__mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad,
+void
+_mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad,
GstCaps *caps, gpointer data)
{
mmplayer_t *player = (mmplayer_t *)data;
__mmplayer_check_not_supported_codec(player, klass, mime);
}
-static gboolean
-__mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad,
- GstCaps *caps, gpointer data)
+gboolean
+_mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad,
+ GstCaps *caps, gpointer data)
{
mmplayer_t *player = (mmplayer_t *)data;
const char *mime = NULL;
caps_str = gst_caps_to_string(caps);
/* set it directly because not sent by TAG */
if (g_strrstr(caps_str, "mobile-xmf"))
- mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", "mobile-xmf");
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ "content_audio_codec", "mobile-xmf", strlen("mobile-xmf"), NULL);
+
MMPLAYER_FREEIF(caps_str);
- } else if (g_str_has_prefix(mime, "video") && !player->ini.video_playback_supported) {
- MMMessageParamType msg_param;
- memset(&msg_param, 0, sizeof(MMMessageParamType));
- msg_param.code = MM_ERROR_NOT_SUPPORT_API;
- MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
- LOGD("video file is not supported on this device");
- ret = FALSE;
} else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
LOGD("already video linked");
ret = FALSE;
static gboolean
__mmplayer_is_audio_offload_device_type(mmplayer_t *player)
{
- gboolean ret = TRUE;
+ gboolean ret = FALSE;
GDBusConnection *conn = NULL;
GError *err = NULL;
GVariant *result = NULL;
conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
if (!conn || err) {
- LOGE("failed g_bus_get_sync() (%s)", err ? err->message : NULL);
+ LOGE("failed g_bus_get_sync() (%s)", (err ? err->message : "null"));
g_error_free(err);
- ret = FALSE;
goto DONE;
}
NULL,
&err);
if (!result || err) {
- LOGE("failed g_dbus_connection_call_sync() (%s)", err ? err->message : NULL);
+ LOGE("failed g_dbus_connection_call_sync() (%s)", (err ? err->message : "null"));
g_error_free(err);
- ret = FALSE;
goto DONE;
}
g_variant_get(result, "(&s&s)", &dbus_device_type, &dbus_ret);
LOGI("g_dbus_connection_call_sync() success (%s, %s)", dbus_device_type, dbus_ret);
- if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) {
- ret = FALSE;
+ if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
goto DONE;
- }
/* the device type is listed in ini file among audio-jack, bt-a2dp, usb-audio, builtin-speaker */
for (idx = 0; player->ini.audio_offload_device_type[idx][0] != '\0'; idx++) {
}
LOGD("audio offload is not supportable");
- ret = FALSE;
DONE:
g_variant_unref(result);
- g_object_unref(conn);
+ if (conn)
+ g_object_unref(conn);
return ret;
}
_mmplayer_set_position((MMHandleType)player, position);
/* async not to be blocked in streaming case */
- mm_attrs_set_int_by_name(player->attrs, "profile_prepare_async", TRUE);
- if (mm_attrs_commit_all(player->attrs))
- LOGE("failed to commit");
+ mm_player_set_attribute((MMHandleType)player, NULL, "profile_prepare_async", TRUE, NULL);
_mmplayer_pause((MMHandleType)player);
return TRUE;
}
+int _mmplayer_audio_offload_is_activated(MMHandleType hplayer, bool *activated)
+{
+ mmplayer_t *player = (mmplayer_t *)hplayer;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+ MMPLAYER_RETURN_VAL_IF_FAIL(activated, MM_ERROR_INVALID_ARGUMENT);
+
+ *activated = player->build_audio_offload;
+
+ LOGD("offload activated : %d", (int)*activated);
+
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
+}
+
+static gboolean
+__mmplayer_is_offload_supported_type(mmplayer_t *player)
+{
+ /* NOTE :
+ this function need to be updated according to the supported media format
+ @see player->ini.audio_offload_media_format */
+
+ if (__mmplayer_is_only_mp3_type(player->type)) {
+ LOGD("offload supportable media format type");
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static gboolean
__mmplayer_can_build_audio_offload_path(mmplayer_t *player)
{
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->attrs, FALSE);
LOGD("current stream : %s, sink: %s", player->type, player->ini.audio_offload_sink_element);
- if (!__mmplayer_is_only_mp3_type(player->type))
+ if (!__mmplayer_is_offload_supported_type(player))
goto DONE;
if (!strcmp(player->ini.audio_offload_sink_element, "")) {
}
gst_object_unref(factory);
+ if (_mmplayer_acquire_hw_resource(player,
+ MMPLAYER_RESOURCE_TYPE_AUDIO_OFFLOAD) != MM_ERROR_NONE) {
+ LOGE("failed to acquire audio offload decoder resource");
+ goto DONE;
+ }
+
if (!__mmplayer_add_audio_device_connected_cb(player))
goto DONE;
ret = TRUE;
DONE:
+ if (!ret)
+ __mmplayer_release_hw_resource(player, MMPLAYER_RESOURCE_TYPE_AUDIO_OFFLOAD);
+
MMPLAYER_FLEAVE();
return ret;
}
__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"))) {
player->audiodec_linked = 1;
ret = GST_AUTOPLUG_SELECT_EXPOSE;
- goto DONE;
- }
-
- 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;
- }
+ goto DONE;
}
+ /* FIXME: If HW audio decoder is selected, related resource have to be acquired here.
+ And need to consider the multi-track audio content.
+ There is no HW audio decoder in public. */
+
/* set stream information */
if (!player->audiodec_linked)
- __mmplayer_set_audio_attrs(player, caps);
+ _mmplayer_set_audio_attrs(player, caps);
/* update codec info */
player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
} 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))) {
/* mark video decoder for acquire */
- if (player->video_decoder_resource == NULL) {
- if (mm_resource_manager_mark_for_acquire(player->resource_manager,
- MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER,
- MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
- &player->video_decoder_resource)
- != MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("could not mark video_decoder resource for acquire");
- ret = GST_AUTOPLUG_SELECT_SKIP;
- goto DONE;
- }
- } else {
+ if (player->hw_resource[MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER] != NULL) {
LOGW("video decoder resource is already acquired, skip it.");
ret = GST_AUTOPLUG_SELECT_SKIP;
goto DONE;
}
- player->interrupted_by_resource = FALSE;
- /* acquire resources for video playing */
- if (mm_resource_manager_commit(player->resource_manager)
- != MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("could not acquire resources for video decoding");
+ if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) {
+ LOGE("failed to acquire video decoder resource");
ret = GST_AUTOPLUG_SELECT_SKIP;
goto DONE;
}
+ player->interrupted_by_resource = FALSE;
}
/* update codec info */
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));
+ if (!factory) {
+ LOGW("failed to get factory object");
+ continue;
+ }
+ 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;
+ 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 */
+ factory = g_value_get_object(g_value_array_get_nth(factories, hw_dec_idx));
+ if (!factory) {
+ LOGW("failed to get factory object");
+ return NULL;
+ }
+ new_factories = g_value_array_copy(factories);
+ 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));
+ if (factory)
+ LOGD("[Re-arranged] Klass [%s] Factory [%s]",
+ gst_element_factory_get_klass(factory), GST_OBJECT_NAME (factory));
+ else
+ LOGE("[Re-arranged] failed to get factory object");
+ }
+
+ return new_factories;
+}
+
gint
-__mmplayer_gst_decode_autoplug_select(GstElement *bin, GstPad *pad,
+_mmplayer_gst_decode_autoplug_select(GstElement *bin, GstPad *pad,
GstCaps *caps, GstElementFactory *factory, gpointer data)
{
GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
/* filtering exclude keyword */
for (idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++) {
if (strstr(factory_name, player->ini.exclude_element_keyword[idx])) {
- LOGW("skipping [%s] by exculde keyword [%s]",
+ LOGW("skipping [%s] by exclude keyword [%s]",
factory_name, player->ini.exclude_element_keyword[idx]);
result = GST_AUTOPLUG_SELECT_SKIP;
/* don't make video because of not required */
if ((stype == MM_DISPLAY_SURFACE_NULL) &&
- (!player->set_mode.media_packet_video_stream)) {
+ (!player->set_mode.video_export)) {
LOGD("no need video decoding, expose pad");
result = GST_AUTOPLUG_SELECT_EXPOSE;
goto DONE;
return result;
}
-static void
-__mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad,
+void
+_mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad,
gpointer data)
{
//mmplayer_t *player = (mmplayer_t *)data;
gst_caps_unref(caps);
}
-static void
-__mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
+void
+_mmplayer_gst_about_to_finish(GstElement *bin, gpointer data)
+{
+ mmplayer_t *player = (mmplayer_t *)data;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(player);
+
+ LOGD("got about to finish signal");
+
+ if (!MMPLAYER_CMD_TRYLOCK(player)) {
+ LOGW("Fail to get cmd lock");
+ return;
+ }
+
+ if (!__mmplayer_verify_gapless_play_path(player)) {
+ LOGD("decoding is finished.");
+ MMPLAYER_CMD_UNLOCK(player);
+ return;
+ }
+
+ _mmplayer_set_reconfigure_state(player, TRUE);
+ MMPLAYER_CMD_UNLOCK(player);
+
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_GAPLESS_CONSTRUCTION, NULL);
+ __mmplayer_deactivate_old_path(player);
+
+ MMPLAYER_FLEAVE();
+}
+
+void
+_mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
{
mmplayer_t *player = (mmplayer_t *)data;
GstIterator *iter = NULL;
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player);
- LOGD("__mmplayer_gst_decode_drained");
+ LOGD("got drained signal");
if (!MMPLAYER_CMD_TRYLOCK(player)) {
LOGW("Fail to get cmd lock");
return;
}
- if (!player->gapless.reconfigure && /* If it is already checked, skip verify. */
- !__mmplayer_verify_gapless_play_path(player)) {
+ if (!__mmplayer_verify_gapless_play_path(player)) {
LOGD("decoding is finished.");
- __mmplayer_reset_gapless_state(player);
MMPLAYER_CMD_UNLOCK(player);
return;
}
- player->gapless.reconfigure = TRUE;
+ _mmplayer_set_reconfigure_state(player, TRUE);
+ MMPLAYER_CMD_UNLOCK(player);
/* check decodebin src pads whether they received EOS or not */
iter = gst_element_iterate_src_pads(player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
if (!is_all_drained) {
LOGD("Wait util the all pads get EOS.");
- MMPLAYER_CMD_UNLOCK(player);
MMPLAYER_FLEAVE();
return;
}
/* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/
MMPLAYER_POST_MSG(player, MM_MESSAGE_GAPLESS_CONSTRUCTION, NULL); /* post message for gapless */
__mmplayer_deactivate_old_path(player);
- MMPLAYER_CMD_UNLOCK(player);
MMPLAYER_FLEAVE();
}
void
-__mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
+_mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
{
mmplayer_t *player = (mmplayer_t *)data;
const gchar *klass = NULL;
gchar *selected = NULL;
selected = g_strdup(GST_ELEMENT_NAME(element));
player->audio_decoders = g_list_append(player->audio_decoders, selected);
+
+ /* update codec info */
+ player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
+ player->can_support_codec |= FOUND_PLUGIN_AUDIO;
+ player->audiodec_linked = 1;
+ } else if (g_strrstr(klass, "Codec/Decoder/Video")) {
+ /* update codec info */
+ player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
+ player->can_support_codec |= FOUND_PLUGIN_VIDEO;
+ player->videodec_linked = 1;
}
if (g_strrstr(klass, "Demuxer/Adaptive")) {
"max-video-height", player->adaptive_info.limit.height, NULL);
} else if (g_strrstr(klass, "Demuxer")) {
- //LOGD("plugged element is demuxer. take it");
+#ifdef __DEBUG__
+ LOGD("plugged element is demuxer. take it");
+#endif
player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
}
(MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) ||
(MMPLAYER_IS_DASH_STREAMING(player))) {
/* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h*/
- __mm_player_streaming_set_multiqueue(player->streamer, element);
- __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
+ _mm_player_streaming_set_multiqueue(player->streamer, element);
+ _mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
}
}
MMPLAYER_RETURN_IF_FAIL(player);
- player->video_stream_cb = NULL;
- player->video_stream_cb_user_param = NULL;
- player->video_stream_prerolled = false;
-
- player->audio_stream_render_cb = NULL;
- player->audio_stream_cb_user_param = NULL;
- player->audio_stream_sink_sync = false;
-
- player->video_stream_changed_cb = NULL;
- player->video_stream_changed_cb_user_param = NULL;
-
- player->audio_stream_changed_cb = NULL;
- player->audio_stream_changed_cb_user_param = NULL;
-
player->sent_bos = FALSE;
player->playback_rate = DEFAULT_PLAYBACK_RATE;
player->play_subtitle = FALSE;
player->adjust_subtitle_pos = 0;
player->has_closed_caption = FALSE;
- player->set_mode.media_packet_video_stream = false;
+ player->set_mode.video_export = false;
player->profile.uri_type = MM_PLAYER_URI_TYPE_NONE;
memset(&player->set_mode, 0, sizeof(mmplayer_setting_mode_t));
/* recover mode */
player->set_mode.rich_audio = cur_mode;
- if (mm_sound_remove_device_connected_callback(player->audio_device_cb_id) != MM_ERROR_NONE)
+ if (player->audio_device_cb_id > 0 &&
+ mm_sound_remove_device_connected_callback(player->audio_device_cb_id) != MM_ERROR_NONE)
LOGW("failed to remove audio device_connected_callback");
player->audio_device_cb_id = 0;
player->maximum_bitrate[i] = 0;
}
- MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
-
- /* remove media stream cb(appsrc cb) */
- for (i = 0; i < MM_PLAYER_STREAM_TYPE_MAX; i++) {
- player->media_stream_buffer_status_cb[i] = NULL;
- player->media_stream_seek_data_cb[i] = NULL;
- player->buffer_cb_user_param[i] = NULL;
- player->seek_cb_user_param[i] = NULL;
- }
- MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
-
/* free memory related to audio effect */
MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin);
MMPLAYER_FENTER();
/* player->pipeline is already released before. */
-
MMPLAYER_RETURN_IF_FAIL(player);
- mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
+ player->video_decoded_cb = NULL;
+ player->video_decoded_cb_user_param = NULL;
+ player->video_stream_prerolled = false;
+
+ player->audio_decoded_cb = NULL;
+ player->audio_decoded_cb_user_param = NULL;
+ player->audio_extract_opt = MM_PLAYER_AUDIO_EXTRACT_DEFAULT;
+
+ player->audio_stream_changed_cb = NULL;
+ player->audio_stream_changed_cb_user_param = NULL;
+
+ mm_player_set_attribute((MMHandleType)player, NULL, "content_video_found", 0, NULL);
/* clean found audio decoders */
if (player->audio_decoders) {
- GList *a_dec = player->audio_decoders;
- for (; a_dec; a_dec = g_list_next(a_dec)) {
- gchar *name = a_dec->data;
- MMPLAYER_FREEIF(name);
- }
- g_list_free(player->audio_decoders);
+ g_list_free_full(player->audio_decoders, (GDestroyNotify)g_free);
player->audio_decoders = NULL;
}
/* clean the uri list except original uri */
- if (player->uri_info.uri_list) {
+ if (player->uri_info.uri_list && g_list_length(player->uri_info.uri_list) > 1) {
+ GList *tmp = NULL;
original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
+ tmp = g_list_remove_link(player->uri_info.uri_list, player->uri_info.uri_list);
+ g_list_free_full(tmp, (GDestroyNotify)g_free);
- if (player->attrs) {
- mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri);
- LOGD("restore original uri = %s", original_uri);
+ if (!original_uri)
+ LOGW("failed to get original uri info");
- if (mm_attrs_commit_all(player->attrs))
- LOGE("failed to commit the original uri.");
- }
+ mm_player_set_attribute((MMHandleType)player, NULL, "profile_uri",
+ original_uri, (original_uri) ? strlen(original_uri) : (0), NULL);
- GList *uri_list = player->uri_info.uri_list;
- for (; uri_list; uri_list = g_list_next(uri_list)) {
- gchar *uri = uri_list->data;
- MMPLAYER_FREEIF(uri);
- }
- g_list_free(player->uri_info.uri_list);
- player->uri_info.uri_list = NULL;
}
/* clear the audio stream buffer list */
- __mmplayer_audio_stream_clear_buffer(player, FALSE);
+ _mmplayer_audio_stream_clear_buffer(player, FALSE);
/* clear the video stream bo list */
__mmplayer_video_stream_destroy_bo_list(player);
}
void
-__mmplayer_cancel_eos_timer(mmplayer_t *player)
+_mmplayer_cancel_eos_timer(mmplayer_t *player)
{
MMPLAYER_RETURN_IF_FAIL(player);
}
static void
-__mmplayer_add_sink(mmplayer_t *player, GstElement *sink)
+__mmplayer_add_sink(mmplayer_t *player, GstElement *sink, gboolean first)
{
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player);
MMPLAYER_RETURN_IF_FAIL(sink);
- player->sink_elements = g_list_append(player->sink_elements, sink);
+ if (first)
+ player->sink_elements = g_list_prepend(player->sink_elements, sink);
+ else
+ player->sink_elements = g_list_append(player->sink_elements, sink);
MMPLAYER_FLEAVE();
}
}
void
-__mmplayer_add_signal_connection(mmplayer_t *player, GObject *object,
+_mmplayer_add_signal_connection(mmplayer_t *player, GObject *object,
mmplayer_signal_type_e type, const gchar *signal, GCallback cb_funct, gpointer u_data)
{
mmplayer_signal_item_t *item = NULL;
}
int
-_mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
+_mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, int wl_surface_id)
{
mmplayer_t *player = 0;
int prev_display_surface_type = 0;
- void *prev_display_overlay = NULL;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
- MMPLAYER_RETURN_VAL_IF_FAIL(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
player = MM_PLAYER_CAST(handle);
/* check video sinkbin is created */
- if (__mmplayer_video_param_check_video_sink_bin(player) == MM_ERROR_NONE) {
- LOGE("Videosink is already created");
+ if (_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_NUM)) {
+ LOGW("Videosink is already created");
return MM_ERROR_NONE;
}
/* load previous attributes */
if (player->attrs) {
mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &prev_display_surface_type);
- mm_attrs_get_data_by_name(player->attrs, "display_overlay", &prev_display_overlay);
LOGD("[0: Video surface, 4: EVAS surface] previous surface type(%d), new surface type(%d)", prev_display_surface_type, surface_type);
if (prev_display_surface_type == surface_type) {
LOGD("incoming display surface type is same as previous one, do nothing..");
/* videobin is not created yet, so we just set attributes related to display surface */
LOGD("store display attribute for given surface type(%d)", surface_type);
- mm_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type);
- mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
- if (mm_attrs_commit_all(player->attrs)) {
- LOGE("failed to commit attribute");
- MMPLAYER_FLEAVE();
- return MM_ERROR_PLAYER_INTERNAL;
- }
+ mm_player_set_attribute(handle, NULL, "display_surface_type", surface_type,
+ "display_overlay", wl_surface_id, NULL);
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
LOGD("seek time = %"G_GINT64_FORMAT", rate = %f", time, player->playback_rate);
event = gst_event_new_seek(player->playback_rate, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH), GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1);
if (event) {
- __mmplayer_gst_send_event_to_sink(player, event);
+ _mmplayer_gst_send_event_to_sink(player, event);
} else {
result = MM_ERROR_PLAYER_INTERNAL;
LOGE("gst_event_new_seek failed"); /* pipeline will got error and can not be recovered */
/* release signal */
__mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
- /* release textbin with it's childs */
+ /* release textbin with it's children */
MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->textbin, MMPLAYER_T_BIN);
MMPLAYER_FREEIF(player->pipeline->textbin);
player->pipeline->textbin = NULL;
goto EXIT;
}
- if (!util_get_storage_info(filepath, &player->storage_info[MMPLAYER_PATH_TEXT])) {
+ if (!_mmplayer_get_storage_info(filepath, &player->storage_info[MMPLAYER_PATH_TEXT])) {
LOGE("failed to get storage info of subtitle path");
result = MM_ERROR_PLAYER_INVALID_URI;
goto EXIT;
}
- LOGD("old subtitle file path is [%s]", subtitle_uri);
- LOGD("new subtitle file path is [%s]", filepath);
+ SECURE_LOGD("old subtitle file path is [%s]", subtitle_uri);
+ SECURE_LOGD("new subtitle file path is [%s]", filepath);
if (!strcmp(filepath, subtitle_uri)) {
- LOGD("No need to swtich subtitle, as input filepath is same as current filepath");
+ LOGD("subtitle path is not changed");
goto EXIT;
} else {
- mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
- if (mm_attrs_commit_all(player->attrs)) {
- LOGE("failed to commit.");
+ if (mm_player_set_attribute((MMHandleType)player, NULL,
+ "subtitle_uri", filepath, strlen(filepath), NULL) != MM_ERROR_NONE) {
+ LOGE("failed to set attribute");
goto EXIT;
}
}
g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBSRC].gst), "location", filepath, NULL);
- charset = util_get_charset(filepath);
+ charset = _mmplayer_get_charset(filepath);
if (charset) {
LOGD("detected charset is %s", charset);
g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBPARSE].gst), "subtitle-encoding", charset, NULL);
if (filepath) {
/* check file path */
if ((path = strstr(filepath, "file://")))
- result = util_exist_file_path(path + 7);
+ result = _mmplayer_exist_file_path(path + 7);
else
- result = util_exist_file_path(filepath);
+ result = _mmplayer_exist_file_path(filepath);
if (result != MM_ERROR_NONE) {
LOGE("invalid subtitle path 0x%X", result);
if (!player->pipeline) {
/* IDLE state */
- mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
- if (mm_attrs_commit_all(player->attrs)) {
- LOGE("failed to commit"); /* subtitle path will not be created */
+ if (mm_player_set_attribute(hplayer, NULL, "subtitle_uri", filepath,
+ (filepath)?(strlen(filepath)):(0), NULL) != MM_ERROR_NONE) {
+ LOGE("failed to set attribute");
return MM_ERROR_PLAYER_INTERNAL;
}
} else {
MMPLAYER_RETURN_VAL_IF_FAIL(filepath, MM_ERROR_COMMON_INVALID_ARGUMENT);
if (!__mmplayer_check_subtitle(player)) {
- mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
- if (mm_attrs_commit_all(player->attrs)) {
- LOGE("failed to commit");
+ if (mm_player_set_attribute(hplayer, NULL, "subtitle_uri",
+ filepath, strlen(filepath), NULL) != MM_ERROR_NONE) {
+ LOGE("failed to set attribute");
return MM_ERROR_PLAYER_INTERNAL;
}
- if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player)) {
+ if (__mmplayer_gst_create_text_pipeline(player) != MM_ERROR_NONE) {
LOGE("fail to create text pipeline");
return MM_ERROR_PLAYER_INTERNAL;
}
}
static int
+__mmplayer_switch_stream(mmplayer_t *player, mmplayer_track_type_e type, int index)
+{
+ guint active_idx = 0;
+ GstStream *stream = NULL;
+ GList *streams = NULL;
+ GstEvent *ev = NULL;
+ GstCaps *caps = NULL;
+
+ LOGD("Switching Streams... type: %d, index: %d", type, index);
+
+ player->track[type].active_track_index = index;
+
+ for (int i = 0; i < MM_PLAYER_TRACK_TYPE_MAX; i++) {
+ /* FIXME: need to consider the non display type or audio only in case of MM_PLAYER_TRACK_TYPE_VIDEO */
+ if (player->track[i].total_track_num > 0) {
+ active_idx = player->track[i].active_track_index;
+ stream = g_ptr_array_index(player->track[i].streams, active_idx);
+ streams = g_list_append (streams, (gchar *)gst_stream_get_stream_id(stream));
+ LOGD("Selecting %d type stream : %s\n", i, gst_stream_get_stream_id(stream));
+
+ if (i == MM_PLAYER_TRACK_TYPE_AUDIO) {
+ caps = gst_stream_get_caps(stream);
+ if (caps) {
+ _mmplayer_set_audio_attrs(player, caps);
+ gst_caps_unref(caps);
+ }
+ }
+ }
+ }
+
+ ev = gst_event_new_select_streams(streams);
+ gst_element_send_event(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, ev);
+ g_list_free(streams);
+
+ return MM_ERROR_NONE;
+}
+
+static int
__mmplayer_change_selector_pad(mmplayer_t *player, mmplayer_track_type_e type, int index)
{
int result = MM_ERROR_NONE;
goto EXIT;
}
- total_track_num = player->selector[type].total_track_num;
+ total_track_num = player->track[type].total_track_num;
if (total_track_num <= 0) {
result = MM_ERROR_PLAYER_NO_OP;
LOGD("Language list is not available");
gst_object_unref(sinkpad);
if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
- __mmplayer_set_audio_attrs(player, caps);
+ _mmplayer_set_audio_attrs(player, caps);
+
+ if (caps)
+ gst_caps_unref(caps);
EXIT:
MMPLAYER_FREEIF(change_pad_name);
gint current_active_index = 0;
GstState current_state = GST_STATE_VOID_PENDING;
- GstEvent *event = NULL;
gint64 time = 0;
MMPLAYER_FENTER();
if (!player->pipeline) {
LOGE("Track %d pre setting -> %d", type, index);
- player->selector[type].active_pad_index = index;
+ player->track[type].active_track_index = index;
goto EXIT;
}
mainbin = player->pipeline->mainbin;
- current_active_index = player->selector[type].active_pad_index;
+ current_active_index = player->track[type].active_track_index;
/*If index is same as running index no need to change the pad*/
if (current_active_index == index)
current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
if (current_state < GST_STATE_PAUSED) {
result = MM_ERROR_PLAYER_INVALID_STATE;
- LOGW("Pipeline not in porper state");
+ LOGW("Pipeline not in proper state");
goto EXIT;
}
- result = __mmplayer_change_selector_pad(player, type, index);
+ if (MMPLAYER_USE_DECODEBIN(player))
+ result = __mmplayer_change_selector_pad(player, type, index);
+ else
+ result = __mmplayer_switch_stream(player, type, index);
+
if (result != MM_ERROR_NONE) {
- LOGE("change selector pad error");
+ LOGE("failed to change track");
goto EXIT;
}
- player->selector[type].active_pad_index = index;
+ player->track[type].active_track_index = index;
- if (current_state == GST_STATE_PLAYING) {
- event = gst_event_new_seek(player->playback_rate, GST_FORMAT_TIME,
- (GstSeekFlags)(GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP),
- GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1);
- if (event) {
- __mmplayer_gst_send_event_to_sink(player, event);
- } else {
- result = MM_ERROR_PLAYER_INTERNAL;
- goto EXIT;
+ if (MMPLAYER_USE_DECODEBIN(player)) {
+ GstEvent *event = NULL;
+ if (current_state == GST_STATE_PLAYING) {
+ event = gst_event_new_seek(player->playback_rate, GST_FORMAT_TIME,
+ (GstSeekFlags)(GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP),
+ GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1);
+ if (event) {
+ _mmplayer_gst_send_event_to_sink(player, event);
+ } else {
+ result = MM_ERROR_PLAYER_INTERNAL;
+ goto EXIT;
+ }
}
}
MMPLAYER_RETURN_VAL_IF_FAIL(dump_data, GST_PAD_PROBE_PASS);
gst_buffer_map(buffer, &probe_info, GST_MAP_READ);
-
-// LOGD("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
-
+#ifdef __DEBUG__
+ LOGD("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
+#endif
fwrite(probe_info.data, 1, probe_info.size , dump_data);
+ gst_buffer_unmap(buffer, &probe_info);
+
return GST_PAD_PROBE_OK;
}
{
MMPLAYER_FENTER();
if (buffer) {
- // LOGD("unref internal gst buffer %p", buffer);
+#ifdef __DEBUG__
+ LOGD("unref internal gst buffer %p", buffer);
+#endif
gst_buffer_unref((GstBuffer *)buffer);
buffer = NULL;
}
return MM_ERROR_NONE;
}
-int
-_mmplayer_get_num_of_video_out_buffers(MMHandleType hplayer, int *num, int *extra_num)
-{
- mmplayer_t *player = (mmplayer_t *)hplayer;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(num && extra_num, MM_ERROR_COMMON_INVALID_ARGUMENT);
-
- *num = player->video_num_buffers;
- *extra_num = player->video_extra_num_buffers;
-
- LOGD("state %d, num %d(%d)", MMPLAYER_CURRENT_STATE(player), *num, *extra_num);
-
- MMPLAYER_FLEAVE();
- return MM_ERROR_NONE;
-}
-
static void
__mmplayer_initialize_storage_info(mmplayer_t *player, mmplayer_path_type_e path_type)
{
if (state != STORAGE_STATE_UNMOUNTABLE && state != STORAGE_STATE_REMOVED)
return MM_ERROR_NONE;
- /* FIXME: text path should be handled seperately. */
+ /* FIXME: text path should be handled separately. */
if (((player->storage_info[MMPLAYER_PATH_VOD].type == STORAGE_TYPE_EXTERNAL)
&& (player->storage_info[MMPLAYER_PATH_VOD].id == id)) ||
((player->storage_info[MMPLAYER_PATH_TEXT].type == STORAGE_TYPE_EXTERNAL)
}
int
-_mmplayer_set_codec_type(MMHandleType hplayer, mmplayer_stream_type_e stream_type, mmplayer_video_codec_type_e codec_type)
+_mmplayer_set_codec_type(MMHandleType hplayer, mmplayer_stream_type_e stream_type, mmplayer_codec_type_e codec_type)
{
#define IDX_FIRST_SW_CODEC 0
mmplayer_t *player = (mmplayer_t *)hplayer;
- const char *attr_name = (stream_type == MM_PLAYER_STREAM_TYPE_AUDIO) ? (MM_PLAYER_AUDIO_CODEC_TYPE) : (MM_PLAYER_VIDEO_CODEC_TYPE);
- MMHandleType attrs = 0;
+ int default_codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT;
+ const char *attr_name = NULL;
+ const char *default_type = NULL;
+ const char *element_hw = NULL;
+ const char *element_sw = NULL;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- LOGD("ini setting : [a][h:%s][s:%s] / [v][h:%s][s:%s]",
- player->ini.audiocodec_element_hw, player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC],
- player->ini.videocodec_element_hw, player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC]);
+ LOGD("stream type: %d, codec_type: %d", stream_type, codec_type);
+ /* FIXME: player need to know whether the decoder exist or not about required codec type since 6.0*/
switch (stream_type) {
case MM_PLAYER_STREAM_TYPE_AUDIO:
- /* to support audio codec selection, codec info have to be added in ini file as below.
- audio codec element hw = xxxx
- audio codec element sw = avdec */
- if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) &&
- (!strcmp(player->ini.audiocodec_element_hw, ""))) ||
- ((codec_type == MM_PLAYER_CODEC_TYPE_SW) &&
- (!strcmp(player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC], "")))) {
- LOGE("There is no audio codec info for codec_type %d", codec_type);
- return MM_ERROR_PLAYER_NO_OP;
- }
- break;
+ attr_name = MM_PLAYER_AUDIO_CODEC_TYPE;
+ default_type = player->ini.audiocodec_default_type;
+ element_hw = player->ini.audiocodec_element_hw;
+ element_sw = player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC];
+ break;
case MM_PLAYER_STREAM_TYPE_VIDEO:
- /* to support video codec selection, codec info have to be added in ini file as below.
- video codec element hw = omx
- video codec element sw = avdec */
- if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) &&
- (!strcmp(player->ini.videocodec_element_hw, ""))) ||
- ((codec_type == MM_PLAYER_CODEC_TYPE_SW) &&
- (!strcmp(player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC], "")))) {
- LOGE("There is no video codec info for codec_type %d", codec_type);
- return MM_ERROR_PLAYER_NO_OP;
- }
- break;
+ attr_name = MM_PLAYER_VIDEO_CODEC_TYPE;
+ default_type = player->ini.videocodec_default_type;
+ element_hw = player->ini.videocodec_element_hw;
+ element_sw = player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC];
+ break;
default:
LOGE("Invalid stream type %s", MMPLAYER_STREAM_TYPE_GET_NAME(stream_type));
return MM_ERROR_COMMON_INVALID_ARGUMENT;
- break;
+ break;
}
- LOGD("update %s codec_type to %d", attr_name, codec_type);
+ LOGD("default setting: [%s][%s][h:%s][s:%s]", attr_name, default_type, element_hw, element_sw);
- attrs = MMPLAYER_GET_ATTRS(player);
- mm_attrs_set_int_by_name(attrs, attr_name, codec_type);
+ if (!strcmp(default_type, "sw"))
+ default_codec_type = MM_PLAYER_CODEC_TYPE_SW;
+ else
+ default_codec_type = MM_PLAYER_CODEC_TYPE_HW;
+
+ if (codec_type == MM_PLAYER_CODEC_TYPE_DEFAULT)
+ codec_type = default_codec_type;
+
+ /* to support codec selection, codec info have to be added in ini file.
+ in case of hw codec is selected, filter elements should be applied
+ depending on the hw capabilities. */
+ if (codec_type != default_codec_type) {
+ if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) && (!strcmp(element_hw, ""))) ||
+ ((codec_type == MM_PLAYER_CODEC_TYPE_SW) && (!strcmp(element_sw, "")))) {
+ LOGE("There is no codec for type %d", codec_type);
+ return MM_ERROR_PLAYER_NO_OP;
+ }
- if (mm_attrs_commit_all(player->attrs)) {
- LOGE("failed to commit codec_type attributes");
- return MM_ERROR_PLAYER_INTERNAL;
+ LOGD("sorting is required");
+ if (stream_type == MM_PLAYER_STREAM_TYPE_AUDIO)
+ player->need_audio_dec_sorting = TRUE;
+ else
+ player->need_video_dec_sorting = TRUE;
}
+ LOGD("update %s codec_type to %d", attr_name, codec_type);
+ mm_player_set_attribute(hplayer, NULL, attr_name, codec_type, NULL);
+
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
}
{
mmplayer_t *player = (mmplayer_t *)hplayer;
MMHandleType attrs = 0;
- void *handle = NULL;
+ int handle = 0;
int ret = MM_ERROR_NONE;
MMPLAYER_FENTER();
attrs = MMPLAYER_GET_ATTRS(player);
MMPLAYER_RETURN_VAL_IF_FAIL(attrs, MM_ERROR_PLAYER_INTERNAL);
- mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
+ mm_attrs_get_int_by_name(attrs, "display_overlay", &handle);
if (!handle) {
LOGE("Display handle is NULL, after setting window handle, set video roi area");
return MM_ERROR_PLAYER_INTERNAL;
player->video_roi.scale_height = scale_height;
/* check video sinkbin is created */
- if (__mmplayer_video_param_check_video_sink_bin(player) != MM_ERROR_NONE)
+ if (!_mmplayer_is_videosink_ready(player, MM_DISPLAY_SURFACE_NUM))
return MM_ERROR_NONE;
if (!gst_video_overlay_set_video_roi_area(
return ret;
}
+int
+_mmplayer_set_client_pid(MMHandleType hplayer, int pid)
+{
+ mmplayer_t *player = (mmplayer_t *)hplayer;
+
+ MMPLAYER_FENTER();
+
+ MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+
+ player->client_pid = pid;
+
+ LOGD("client pid[%d] %p", pid, player);
+
+ MMPLAYER_FLEAVE();
+
+ return MM_ERROR_NONE;
+}
+
+int
+_mmplayer_is_audio_control_available(MMHandleType hplayer, mmplayer_audio_control_opt_e opt, bool *available)
+{
+ mmplayer_t *player = (mmplayer_t *)hplayer;
+ mmplayer_codec_type_e codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT;
+ enum audio_element_id elem_id = MMPLAYER_A_NUM;
+
+ MMPLAYER_FENTER();
+
+ MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+ MMPLAYER_RETURN_VAL_IF_FAIL(available, MM_ERROR_INVALID_ARGUMENT);
+
+ *available = true;
+ mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, (int *)&codec_type);
+
+ LOGD("current state %d, codec_type %d", MMPLAYER_CURRENT_STATE(player), codec_type);
+
+ if (codec_type == MM_PLAYER_CODEC_TYPE_SW)
+ return MM_ERROR_NONE;
+
+ /* in case of audio codec default type is HW */
+ switch(opt) {
+ case MM_PLAYER_AUDIO_CONTROL_OPT_EFFECT:
+ if (player->ini.support_audio_effect)
+ return MM_ERROR_NONE;
+ elem_id = MMPLAYER_A_FILTER;
+ break;
+ case MM_PLAYER_AUDIO_CONTROL_OPT_REPLAYGAIN:
+ if (player->ini.support_replaygain_control)
+ return MM_ERROR_NONE;
+ elem_id = MMPLAYER_A_RGVOL;
+ break;
+ case MM_PLAYER_AUDIO_CONTROL_OPT_PITCH:
+ if (player->ini.support_pitch_control)
+ return MM_ERROR_NONE;
+ elem_id = MMPLAYER_A_PITCH;
+ break;
+ case MM_PLAYER_AUDIO_CONTROL_OPT_PCM_EXPORTING:
+ if (player->ini.support_audio_effect)
+ return MM_ERROR_NONE;
+ break;
+ /* default case handling is not required */
+ }
+
+ if (MMPLAYER_CURRENT_STATE(player) < MM_PLAYER_STATE_READY) {
+ LOGW("audio control option [%d] is not available", opt);
+ *available = false;
+ } else {
+ /* setting pcm exporting option is allowed before READY state */
+ if (opt == MM_PLAYER_AUDIO_CONTROL_OPT_PCM_EXPORTING)
+ return MM_ERROR_PLAYER_INVALID_STATE;
+
+ /* check whether the audio filter exist or not after READY state,
+ because the sw codec could be added during auto-plugging in some cases */
+ if (!player->pipeline ||
+ !player->pipeline->audiobin ||
+ !player->pipeline->audiobin[elem_id].gst) {
+ LOGW("there is no audio elem [%d]", elem_id);
+ *available = false;
+ }
+ }
+
+ LOGD("audio control opt %d, available %d", opt, *available);
+
+ MMPLAYER_FLEAVE();
+
+ return MM_ERROR_NONE;
+}
+
static gboolean
__mmplayer_update_duration_value(mmplayer_t *player)
{
}
/* update streaming service type */
- player->streaming_type = __mmplayer_get_stream_service_type(player);
+ player->streaming_type = _mmplayer_get_stream_service_type(player);
/* check duration is OK */
if (dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING(player))
GstPad *pad = NULL;
gint samplerate = 0, channels = 0;
GstStructure *p = NULL;
+ GstElement *aconv = NULL;
LOGD("try to update audio attrs");
MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->audiobin, FALSE);
- MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, FALSE);
- pad = gst_element_get_static_pad(
- player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink");
+ if (player->pipeline->audiobin[MMPLAYER_A_CONV].gst) {
+ aconv = player->pipeline->audiobin[MMPLAYER_A_CONV].gst;
+ } else if (player->pipeline->audiobin[MMPLAYER_A_EXTRACT_CONV].gst) {
+ aconv = player->pipeline->audiobin[MMPLAYER_A_EXTRACT_CONV].gst;
+ } else {
+ LOGE("there is no audio converter");
+ return FALSE;
+ }
+
+ pad = gst_element_get_static_pad(aconv, "sink");
if (!pad) {
- LOGW("failed to get pad from audiosink");
+ LOGW("failed to get pad from audio converter");
return FALSE;
}
mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
gst_structure_get_int(p, "rate", &samplerate);
- mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
-
gst_structure_get_int(p, "channels", &channels);
- mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
+
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ "content_audio_samplerate", samplerate,
+ "content_audio_channels", channels, NULL);
SECURE_LOGD("samplerate : %d channels : %d", samplerate, channels);
}
if (!caps_v) {
- LOGD("no negitiated caps from videosink");
+ LOGD("no negotiated caps from videosink");
gst_object_unref(pad);
return FALSE;
}
p = gst_caps_get_structure(caps_v, 0);
gst_structure_get_int(p, "width", &width);
- mm_attrs_set_int_by_name(attrs, "content_video_width", width);
-
gst_structure_get_int(p, "height", &height);
- mm_attrs_set_int_by_name(attrs, "content_video_height", height);
+
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ MM_PLAYER_VIDEO_WIDTH, width, MM_PLAYER_VIDEO_HEIGHT, height, NULL);
gst_structure_get_fraction(p, "framerate", &tmpNu, &tmpDe);
gst_object_unref(pad);
if (tmpDe > 0) {
- mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ MM_PLAYER_VIDEO_FPS, (tmpNu/tmpDe), NULL);
SECURE_LOGD("fps : %d", tmpNu / tmpDe);
}
gchar *path = NULL;
struct stat sb;
- /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
+ /* FIXIT : please make it clear the dependency with duration/codec/uritype */
if (!player->duration)
return FALSE;
msec_dur = GST_TIME_AS_MSECONDS(player->duration);
if (msec_dur > 0) {
bitrate = data_size * 8 * 1000 / msec_dur;
- SECURE_LOGD("file size : %"G_GUINT64_FORMAT", video bitrate = %"G_GUINT64_FORMAT, data_size, bitrate);
- mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
-
+ SECURE_LOGD("file size : %"G_GUINT64_FORMAT
+ ", video bitrate = %"G_GUINT64_FORMAT, data_size, bitrate);
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ MM_PLAYER_VIDEO_BITRATE, (int)bitrate, NULL);
ret = TRUE;
} else {
LOGD("player duration is less than 0");
if (MMPLAYER_IS_RTSP_STREAMING(player)) {
if (player->total_bitrate) {
- mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate);
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ MM_PLAYER_VIDEO_BITRATE, player->total_bitrate, NULL);
ret = TRUE;
}
}
path = (location != NULL) ? (location) : ((char *)uri);
- ret = util_exist_file_path(path);
+ ret = _mmplayer_exist_file_path(path);
/* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
if (ret == MM_ERROR_NONE) {
- g_snprintf(data->uri, MM_MAX_URL_LEN, "file://%s", path);
- if (util_is_sdp_file(path)) {
+ if (_mmplayer_is_sdp_file(path)) {
LOGD("uri is actually a file but it's sdp file. giving it to rtspsrc");
+ g_snprintf(data->uri, MM_MAX_URL_LEN, "rtsp-sdp://%s", path);
data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
} else {
+ g_snprintf(data->uri, MM_MAX_URL_LEN, "file://%s", path);
data->uri_type = MM_PLAYER_URI_TYPE_FILE;
}
} else if (ret == MM_ERROR_PLAYER_PERMISSION_DENIED) {
mmplayer_video_decoded_data_info_t *stream = NULL;
gint width, height;
MMPixelFormatType format;
+ GstVideoInfo info;
caps = gst_pad_get_current_caps(pad);
if (!caps) {
return NULL;
}
- /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
+#ifdef __DEBUG__
+ MMPLAYER_LOG_GST_CAPS_TYPE(caps);
+#endif
structure = gst_caps_get_structure(caps, 0);
gst_structure_get_int(structure, "width", &width);
gst_structure_get_int(structure, "height", &height);
string_format = gst_structure_get_string(structure, "format");
+
if (string_format)
fourcc = _mmplayer_convert_fourcc_string_to_value(string_format);
- format = util_get_pixtype(fourcc);
+ format = _mmplayer_get_pixtype(fourcc);
+ gst_video_info_from_caps(&info, caps);
gst_caps_unref(caps);
/* moved here */
stream->width = width;
stream->height = height;
stream->format = format;
+ stream->plane_num = GST_VIDEO_INFO_N_PLANES(&info);
return stream;
}
__mmplayer_zerocopy_set_stride_elevation_bo(mmplayer_video_decoded_data_info_t *stream, GstMemory *mem)
{
unsigned int pitch = 0;
+ unsigned int size = 0;
int index = 0;
tbm_surface_h surface = gst_tizen_memory_get_surface(mem);
+ tbm_bo bo = NULL;
for (index = 0; index < gst_tizen_memory_get_num_bos(mem); index++) {
- tbm_surface_internal_get_plane_data(surface, index, NULL, NULL, &pitch);
- stream->bo[index] = tbm_bo_ref(gst_tizen_memory_get_bos(mem, index));
+ bo = gst_tizen_memory_get_bos(mem, index);
+ if (bo)
+ stream->bo[index] = tbm_bo_ref(bo);
+ else
+ LOGE("failed to get bo for index %d", index);
+ }
+
+ for (index = 0; index < stream->plane_num; index++) {
+ tbm_surface_internal_get_plane_data(surface, index, &size, NULL, &pitch);
stream->stride[index] = pitch;
- stream->elevation[index] = stream->height;
+ if (pitch)
+ stream->elevation[index] = size / pitch;
+ else
+ stream->elevation[index] = stream->height;
}
}
return;
/* it's first time to update all content attrs. */
- __mmplayer_update_content_attrs(player, ATTR_ALL);
+ _mmplayer_update_content_attrs(player, ATTR_ALL);
}
static void
/* try to get content metadata */
/* NOTE : giving ATTR_MISSING_ONLY may have dependency with
- * c-api since c-api doesn't use _start() anymore. It may not work propery with
+ * c-api since c-api doesn't use _start() anymore. It may not work properly with
* legacy mmfw-player api
*/
- __mmplayer_update_content_attrs(player, ATTR_MISSING_ONLY);
+ _mmplayer_update_content_attrs(player, ATTR_MISSING_ONLY);
if ((player->cmd == MMPLAYER_COMMAND_START)
|| (player->cmd == MMPLAYER_COMMAND_RESUME)) {
else
audio_codec = "unknown";
- mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
-
- if (mm_attrs_commit_all(player->attrs))
- LOGE("failed to update attributes");
+ if (mm_player_set_attribute((MMHandleType)player, NULL,
+ "content_audio_codec", audio_codec, strlen(audio_codec), NULL) != MM_ERROR_NONE)
+ LOGE("failed to set attribute");
LOGD("set audio codec type with caps");
}