========================================================================================== */
#include <glib.h>
#include <gst/gst.h>
-#include <gst/app/gstappsrc.h>
#include <gst/video/videooverlay.h>
#include <gst/audio/gstaudiobasesink.h>
#include <unistd.h>
#include <sys/time.h>
#include <stdlib.h>
#include <dlog.h>
+#include <gio/gio.h>
#include <mm_error.h>
#include <mm_attrs.h>
-#include <mm_attrs_private.h>
+#include <mm_sound.h>
#include "mm_player_priv.h"
#include "mm_player_ini.h"
#include <system_info.h>
#include <sound_manager.h>
+#include <gst/allocators/gsttizenmemory.h>
+#include <tbm_surface_internal.h>
/*===========================================================================================
| |
#define DEFAULT_PLAYBACK_RATE 1.0
#define DEFAULT_NUM_OF_V_OUT_BUFFER 3
-#define MMPLAYER_USE_FILE_FOR_BUFFERING(player) \
- (((player)->profile.uri_type != MM_PLAYER_URI_TYPE_HLS) && \
- (player->ini.http_use_file_buffer) && \
- (player->http_file_buffering_path) && \
- (strlen(player->http_file_buffering_path) > 0))
-
#define PLAYER_DISPLAY_MODE_DST_ROI 5
#define ADAPTIVE_VARIANT_DEFAULT_VALUE -1 /* auto */
-/* For PD mode */
-#define PLAYER_PD_EXT_MAX_SIZE_BYTE 1024 * 1024 * 3
-
#define PLAYER_SPHERICAL_DEFAULT_YAW 0 /* sync from video360 plugin */
#define PLAYER_SPHERICAL_DEFAULT_PITCH 0
#define PLAYER_SPHERICAL_DEFAULT_H_FOV 120
#define SPATIAL_AUDIO_CAPS "audio/x-raw,format=S16LE,channels=4"
#define FEATURE_NAME_SPHERICAL_VIDEO "http://tizen.org/feature/multimedia.player.spherical_video"
+#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: |
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
| LOCAL DATA TYPE DEFINITIONS: |
---------------------------------------------------------------------------*/
+/* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
+ We are defining our own and will be removed when it actually exposed */
+typedef enum {
+ GST_AUTOPLUG_SELECT_TRY,
+ GST_AUTOPLUG_SELECT_EXPOSE,
+ GST_AUTOPLUG_SELECT_SKIP
+} GstAutoplugSelectResult;
/*---------------------------------------------------------------------------
| GLOBAL VARIABLE DEFINITIONS: |
/*---------------------------------------------------------------------------
| LOCAL FUNCTION PROTOTYPES: |
---------------------------------------------------------------------------*/
-static int __mmplayer_gst_create_pipeline(mm_player_t* player);
-static int __mmplayer_gst_destroy_pipeline(mm_player_t* player);
-static int __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps *caps, MMDisplaySurfaceType surface_type);
-static int __mmplayer_gst_create_audio_pipeline(mm_player_t* player);
-static int __mmplayer_gst_create_text_pipeline(mm_player_t* player);
-static int __mmplayer_gst_create_text_sink_bin(mm_player_t* player);
-static int __mmplayer_gst_element_link_bucket(GList* element_bucket);
-
-static GstPadProbeReturn __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data);
-static void __mmplayer_gst_decode_pad_added(GstElement* elem, GstPad* pad, gpointer data);
-static void __mmplayer_gst_decode_no_more_pads(GstElement* elem, gpointer data);
-static void __mmplayer_gst_decode_callback(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 gint __mmplayer_gst_decode_autoplug_select(GstElement *bin, GstPad* pad, GstCaps * caps, GstElementFactory* factory, gpointer data);
-static void __mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad* new_pad, gpointer data);
+static int __mmplayer_gst_create_pipeline(mmplayer_t *player);
+static int __mmplayer_gst_destroy_pipeline(mmplayer_t *player);
+static int __mmplayer_gst_create_text_pipeline(mmplayer_t *player);
+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_gst_element_added(GstElement* bin, GstElement* element, gpointer data);
-static GstElement * __mmplayer_create_decodebin(mm_player_t* player);
-static gboolean __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps);
-static void __mmplayer_typefind_have_type(GstElement *tf, guint probability, GstCaps *caps, gpointer data);
static void __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data);
-static gboolean __mmplayer_is_midi_type(gchar* str_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(mm_player_t* player, GstCaps* caps);
-
-static void __mmplayer_gst_rtp_no_more_pads(GstElement *element, gpointer data);
-static void __mmplayer_gst_rtp_dynamic_pad(GstElement *element, GstPad *pad, gpointer data);
-static gboolean __mmplayer_update_subtitle(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
-static void __mmplayer_release_misc(mm_player_t* player);
-static void __mmplayer_release_misc_post(mm_player_t* player);
-static gboolean __mmplayer_init_gstreamer(mm_player_t* player);
-static gboolean __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink);
-static GstPadProbeReturn __mmplayer_audio_stream_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
-static void __mmplayer_video_stream_decoded_preroll_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
-static void __mmplayer_video_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
+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 void __mmplayer_release_misc_post(mmplayer_t *player);
+static gboolean __mmplayer_init_gstreamer(mmplayer_t *player);
+static void __mmplayer_video_stream_decoded_preroll_cb(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer data);
+static void __mmplayer_video_stream_decoded_render_cb(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer data);
static GstPadProbeReturn __mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
-static int __mmplayer_change_selector_pad(mm_player_t* player, MMPlayerTrackType type, int index);
-
-static gboolean __mmplayer_check_subtitle(mm_player_t* player);
-static int __mmplayer_handle_missed_plugin(mm_player_t* player);
-static int __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime);
-static void __mmplayer_add_sink(mm_player_t* player, GstElement* sink);
-static void __mmplayer_del_sink(mm_player_t* player, GstElement* sink);
-static void __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type);
-static gpointer __mmplayer_next_play_thread(gpointer data);
-static gboolean __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element);
+static int __mmplayer_change_selector_pad(mmplayer_t *player, mmplayer_track_type_e type, int index);
+
+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_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);
+static gboolean __mmplayer_add_dump_buffer_probe(mmplayer_t *player, GstElement *element);
static GstPadProbeReturn __mmplayer_dump_buffer_probe_cb(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
static void __mmplayer_release_dump_list(GList *dump_list);
-static int __gst_realize(mm_player_t* player);
-static int __gst_unrealize(mm_player_t* player);
-static int __gst_adjust_subtitle_position(mm_player_t* player, int format, int position);
-static int __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param);
-static gboolean __mmplayer_can_extract_pcm(mm_player_t* player);
+static int __mmplayer_gst_realize(mmplayer_t *player);
+static int __mmplayer_gst_unrealize(mmplayer_t *player);
+static int __mmplayer_gst_adjust_subtitle_position(mmplayer_t *player, int position);
+static int __mmplayer_gst_set_message_callback(mmplayer_t *player, MMMessageCallback callback, gpointer user_param);
/* util */
-static int __mmplayer_realize_streaming_ext(mm_player_t* player);
-static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
-static int __mmplayer_start_streaming_ext(mm_player_t *player);
-static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
-static int __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay);
-static gboolean __mmplayer_verify_next_play_path(mm_player_t *player);
-static void __mmplayer_activate_next_source(mm_player_t *player, GstState target);
-static void __mmplayer_check_pipeline(mm_player_t* player);
-static gboolean __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type);
-static void __mmplayer_deactivate_old_path(mm_player_t *player);
-static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name);
-static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player);
-static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name);
-static void __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data);
-static void __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data);
-static void __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data);
-static void __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data);
-static void __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data);
-static gboolean __gst_seek_audio_data(GstElement * appsrc, guint64 position, gpointer user_data);
-static gboolean __gst_seek_video_data(GstElement * appsrc, guint64 position, gpointer user_data);
-static gboolean __gst_seek_subtitle_data(GstElement * appsrc, guint64 position, gpointer user_data);
-static void __mmplayer_gst_caps_notify_cb(GstPad * pad, GParamSpec * unused, gpointer data);
-static void __mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer);
-static void __mmplayer_initialize_storage_info(mm_player_t* player, MMPlayerPathType path_type);
+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 gboolean __mmplayer_deactivate_selector(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);
+static gboolean __mmplayer_update_bitrate_attrs(mmplayer_t *player, MMHandleType attrs);
+
+static void __mmplayer_copy_uri_and_set_type(mmplayer_parse_profile_t *data, const char *uri, int uri_type);
+static int __mmplayer_set_mem_uri(mmplayer_parse_profile_t *data, char *path, void *param);
+static int __mmplayer_set_file_uri(mmplayer_parse_profile_t *data, const char *uri);
+
+static mmplayer_video_decoded_data_info_t *__mmplayer_create_stream_from_pad(GstPad *pad);
+static void __mmplayer_zerocopy_set_stride_elevation_bo(mmplayer_video_decoded_data_info_t *stream, GstMemory *mem);
+static gboolean __mmplayer_swcodec_set_stride_elevation(mmplayer_video_decoded_data_info_t *stream);
+static gboolean __mmplayer_swcodec_set_bo(mmplayer_t *player, mmplayer_video_decoded_data_info_t *stream, GstMemory *mem);
+
+static void __mmplayer_set_pause_state(mmplayer_t *player);
+static void __mmplayer_set_playing_state(mmplayer_t *player);
/*===========================================================================================
| |
| FUNCTION DEFINITIONS |
#if 0 //debug
static void
-print_tag(const GstTagList * list, const gchar * tag, gpointer unused)
+print_tag(const GstTagList *list, const gchar *tag, gpointer unused)
{
gint i, count;
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
+ } else {
str = g_strdup_value_contents(gst_tag_list_get_value_index(list, tag, i));
+ }
if (i == 0)
- g_print(" %15s: %s\n", gst_tag_get_nick(tag), str);
+ g_print(" %15s: %s", gst_tag_get_nick(tag), str);
else
- g_print(" : %s\n", str);
+ g_print(" : %s", str);
g_free(str);
}
/* This function should be called after the pipeline goes PAUSED or higher
state. */
gboolean
-__mmplayer_update_content_attrs(mm_player_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;
static gboolean has_bitrate = FALSE;
gboolean missing_only = FALSE;
gboolean all = FALSE;
- gint64 dur_nsec = 0;
- GstStructure* p = NULL;
MMHandleType attrs = 0;
- gchar *path = NULL;
- struct stat sb;
MMPLAYER_FENTER();
missing_only = FALSE;
}
- if ((flag & ATTR_DURATION) || (!has_duration && missing_only) || all) {
- LOGD("try to update duration");
- has_duration = FALSE;
-
- if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec) && (dur_nsec > 0)) {
- player->duration = dur_nsec;
- LOGW("duration : %"G_GINT64_FORMAT" msec", GST_TIME_AS_MSECONDS(dur_nsec));
- has_duration = TRUE;
- }
-
- if (player->duration < 0) {
- LOGW("duration is Non-Initialized !!!");
- player->duration = 0;
- }
-
- /* update streaming service type */
- player->streaming_type = __mmplayer_get_stream_service_type(player);
-
- /* check duration is OK */
- if (dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING(player)) {
- /* FIXIT : find another way to get duration here. */
- LOGW("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
- }
- }
-
- if ((flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all) {
- /* update audio params
- NOTE : We need original audio params and it can be only obtained from src pad of audio
- decoder. Below code only valid when we are not using 'resampler' just before
- 'audioconverter'. */
-
- LOGD("try to update audio attrs");
- has_audio_attrs = FALSE;
-
- if (player->pipeline->audiobin &&
- player->pipeline->audiobin[MMPLAYER_A_SINK].gst) {
- GstCaps *caps_a = NULL;
- GstPad* pad = NULL;
- gint samplerate = 0, channels = 0;
-
- pad = gst_element_get_static_pad(
- player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink");
-
- if (pad) {
- caps_a = gst_pad_get_current_caps(pad);
-
- if (caps_a) {
- p = gst_caps_get_structure(caps_a, 0);
-
- 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);
-
- SECURE_LOGD("samplerate : %d channels : %d", samplerate, channels);
-
- gst_caps_unref(caps_a);
- caps_a = NULL;
-
- has_audio_attrs = TRUE;
- } else
- LOGW("not ready to get audio caps");
-
- gst_object_unref(pad);
- } else
- LOGW("failed to get pad from audiosink");
- }
- }
-
- if ((flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all) {
- LOGD("try to update video attrs");
- has_video_attrs = FALSE;
-
- if (player->pipeline->videobin &&
- player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
- GstCaps *caps_v = NULL;
- GstPad* pad = NULL;
- gint tmpNu, tmpDe;
- gint width, height;
-
- pad = gst_element_get_static_pad(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink");
- if (pad) {
- caps_v = gst_pad_get_current_caps(pad);
-
- /* Use v_stream_caps, if fail to get video_sink sink pad*/
- if (!caps_v && player->v_stream_caps) {
- caps_v = player->v_stream_caps;
- gst_caps_ref(caps_v);
- }
-
- if (caps_v) {
- 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);
-
- gst_structure_get_fraction(p, "framerate", &tmpNu, &tmpDe);
-
- SECURE_LOGD("width : %d height : %d", width, height);
-
- gst_caps_unref(caps_v);
- caps_v = NULL;
-
- if (tmpDe > 0) {
- mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
- SECURE_LOGD("fps : %d", tmpNu / tmpDe);
- }
-
- has_video_attrs = TRUE;
- } else
- LOGD("no negitiated caps from videosink");
- gst_object_unref(pad);
- pad = NULL;
- } else {
- LOGD("no videosink sink pad");
- }
- }
- }
-
-
- if ((flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all) {
- has_bitrate = FALSE;
-
- /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
- if (player->duration) {
- guint64 data_size = 0;
+ if ((flag & ATTR_DURATION) || (!has_duration && missing_only) || all)
+ has_duration = __mmplayer_update_duration_value(player);
- if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
- mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
+ if ((flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all)
+ has_audio_attrs = __mmplayer_update_audio_attrs(player, attrs);
- if (stat(path, &sb) == 0)
- data_size = (guint64)sb.st_size;
- } else if (MMPLAYER_IS_HTTP_STREAMING(player)) {
- data_size = player->http_content_size;
- }
- LOGD("try to update bitrate : data_size = %"G_GUINT64_FORMAT, data_size);
-
- if (data_size) {
- guint64 bitrate = 0;
- guint64 msec_dur = 0;
-
- msec_dur = GST_TIME_AS_MSECONDS(player->duration);
- if (msec_dur > 0) {
- bitrate = data_size * 8 * 1000 / msec_dur;
- SECURE_LOGD("file size : %u, video bitrate = %llu", data_size, bitrate);
- mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
-
- has_bitrate = TRUE;
- } else {
- LOGD("player duration is less than 0");
- }
- }
+ if ((flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all)
+ has_video_attrs = __mmplayer_update_video_attrs(player, attrs);
- if (MMPLAYER_IS_RTSP_STREAMING(player)) {
- if (player->total_bitrate) {
- mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate);
- has_bitrate = TRUE;
- }
- }
- }
- }
+ if ((flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all)
+ has_bitrate = __mmplayer_update_bitrate_attrs(player, attrs);
/* validate all */
- if (mmf_attrs_commit(attrs)) {
- LOGE("failed to update attributes\n");
+ if (mm_attrs_commit_all(attrs)) {
+ LOGE("failed to update attributes");
return FALSE;
}
return TRUE;
}
-MMStreamingType __mmplayer_get_stream_service_type(mm_player_t* player)
+MMStreamingType
+__mmplayer_get_stream_service_type(mmplayer_t *player)
{
MMStreamingType streaming_type = STREAMING_SERVICE_NONE;
if (!MMPLAYER_IS_STREAMING(player))
return STREAMING_SERVICE_NONE;
- if (MMPLAYER_IS_HTTP_STREAMING(player))
- streaming_type = (player->duration == 0) ?
- STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
+ streaming_type = (player->duration == 0) ?
+ STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
switch (streaming_type) {
case STREAMING_SERVICE_LIVE:
return streaming_type;
}
-
/* this function sets the player state and also report
* it to applicaton by calling callback function
*/
void
-__mmplayer_set_state(mm_player_t* player, int state)
+__mmplayer_set_state(mmplayer_t *player, int state)
{
MMMessageParamType msg = {0, };
- gboolean post_bos = FALSE;
MMPLAYER_RETURN_IF_FAIL(player);
if (MMPLAYER_CURRENT_STATE(player) == state) {
- LOGW("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
+ LOGW("already same state(%s)", MMPLAYER_STATE_GET_NAME(state));
MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
return;
}
case MM_PLAYER_STATE_NULL:
case MM_PLAYER_STATE_READY:
break;
-
case MM_PLAYER_STATE_PAUSED:
- {
- if (!player->sent_bos) {
- /* rtsp case, get content attrs by GstMessage */
- if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
- /* it's first time to update all content attrs. */
- __mmplayer_update_content_attrs(player, ATTR_ALL);
- }
- }
-
- /* add audio callback probe if condition is satisfied */
- if (!player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
- __mmplayer_configure_audio_callback(player);
-
- /* FIXIT : handle return value */
- }
+ __mmplayer_set_pause_state(player);
break;
-
case MM_PLAYER_STATE_PLAYING:
- {
- /* try to get content metadata */
- if (!player->sent_bos) {
- /* 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
- * legacy mmfw-player api */
- __mmplayer_update_content_attrs(player, ATTR_MISSING_ONLY);
- }
-
- if ((player->cmd == MMPLAYER_COMMAND_START) || (player->cmd == MMPLAYER_COMMAND_RESUME)) {
- if (!player->sent_bos)
- __mmplayer_handle_missed_plugin(player);
- }
-
- if (player->resumed_by_rewind && player->playback_rate < 0.0) {
- /* initialize because auto resume is done well. */
- player->resumed_by_rewind = FALSE;
- player->playback_rate = 1.0;
- }
-
- if (!player->sent_bos) {
- /* check audio codec field is set or not
- * we can get it from typefinder or codec's caps.
- */
- gchar *audio_codec = NULL;
- mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
-
- /* The codec format can't be sent for audio only case like amr, mid etc.
- * Because, parser don't make related TAG.
- * So, if it's not set yet, fill it with found data.
- */
- if (!audio_codec) {
- if (g_strrstr(player->type, "audio/midi"))
- audio_codec = g_strdup("MIDI");
- else if (g_strrstr(player->type, "audio/x-amr"))
- audio_codec = g_strdup("AMR");
- else if (g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion= (int)1"))
- audio_codec = g_strdup("AAC");
- else
- audio_codec = g_strdup("unknown");
- mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
-
- MMPLAYER_FREEIF(audio_codec);
- if (mmf_attrs_commit(player->attrs))
- LOGE("failed to update attributes\n");
-
- LOGD("set audio codec type with caps\n");
- }
-
- post_bos = TRUE;
- }
- }
+ __mmplayer_set_playing_state(player);
break;
-
case MM_PLAYER_STATE_NONE:
default:
- LOGW("invalid target state, there is nothing to do.\n");
+ LOGW("invalid target state, there is nothing to do.");
break;
}
LOGD("player reach the target state (%s)", MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
/* state changed by resource callback */
- if (player->interrupted_by_resource) {
- MMPLAYER_POST_MSG(player, MM_MESSAGE_STATE_INTERRUPTED, NULL);
- } else { /* state changed by usecase */
+ if (player->interrupted_by_resource)
+ MMPLAYER_POST_MSG(player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
+ else /* state changed by usecase */
MMPLAYER_POST_MSG(player, MM_MESSAGE_STATE_CHANGED, &msg);
- }
+
} else {
- LOGD("intermediate state, do nothing.\n");
+ LOGD("intermediate state, do nothing.");
MMPLAYER_PRINT_STATE(player);
return;
}
- if (post_bos) {
+ if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING
+ && !player->sent_bos) {
MMPLAYER_POST_MSG(player, MM_MESSAGE_BEGIN_OF_STREAM, NULL);
player->sent_bos = TRUE;
}
}
int
-__mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
+__mmplayer_check_state(mmplayer_t *player, mmplayer_command_state_e command)
{
- MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
- MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
+ 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 \n", command);
+ //LOGD("incomming command : %d ", command);
current_state = MMPLAYER_CURRENT_STATE(player);
pending_state = MMPLAYER_PENDING_STATE(player);
goto ALREADY_GOING;
} else if (pending_state == MM_PLAYER_STATE_PAUSED) {
LOGD("player is going to paused state, just change the pending state as playing");
- } else
+ } else {
goto INVALID_STATE;
+ }
}
break;
goto ALREADY_GOING;
} else if (pending_state == MM_PLAYER_STATE_PAUSED) {
LOGD("player is going to paused state, just change the pending state as playing");
- } else
+ } else {
goto INVALID_STATE;
+ }
}
break;
return MM_ERROR_PLAYER_NO_OP;
}
-static gpointer __mmplayer_next_play_thread(gpointer data)
+static gpointer
+__mmplayer_gapless_play_thread(gpointer data)
{
- mm_player_t* player = (mm_player_t*) data;
- MMPlayerGstElement *mainbin = NULL;
+ mmplayer_t *player = (mmplayer_t *)data;
+ mmplayer_gst_element_t *mainbin = NULL;
MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
- MMPLAYER_NEXT_PLAY_THREAD_LOCK(player);
- while (!player->next_play_thread_exit) {
- LOGD("next play thread started. waiting for signal.\n");
- MMPLAYER_NEXT_PLAY_THREAD_WAIT(player);
+ MMPLAYER_GAPLESS_PLAY_THREAD_LOCK(player);
+ while (!player->gapless_play_thread_exit) {
+ LOGD("gapless play thread started. waiting for signal.");
+ MMPLAYER_GAPLESS_PLAY_THREAD_WAIT(player);
- LOGD("reconfigure pipeline for gapless play.\n");
+ LOGD("reconfigure pipeline for gapless play.");
- if (player->next_play_thread_exit) {
+ if (player->gapless_play_thread_exit) {
if (player->gapless.reconfigure) {
player->gapless.reconfigure = false;
MMPLAYER_PLAYBACK_UNLOCK(player);
}
- LOGD("exiting gapless play thread\n");
+ LOGD("exiting gapless play thread");
break;
}
__mmplayer_activate_next_source(player, GST_STATE_PLAYING);
}
- MMPLAYER_NEXT_PLAY_THREAD_UNLOCK(player);
+ MMPLAYER_GAPLESS_PLAY_THREAD_UNLOCK(player);
return NULL;
}
MMPLAYER_FENTER();
source = g_main_context_find_source_by_id(context, source_id);
-
if (source != NULL) {
LOGW("context: %p, source id: %d, source: %p", context, source_id, source);
g_source_destroy(source);
MMPLAYER_FLEAVE();
}
-void __mmplayer_bus_msg_thread_destroy(MMHandleType hplayer)
+void
+__mmplayer_bus_msg_thread_destroy(MMHandleType hplayer)
{
- mm_player_t* player = (mm_player_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
GstMessage *msg = NULL;
GQueue *queue = NULL;
queue = player->bus_msg_q;
while (!g_queue_is_empty(queue)) {
msg = (GstMessage *)g_queue_pop_head(queue);
- LOGW("remove remained %s msg", GST_MESSAGE_TYPE_NAME(msg));
- gst_message_unref(msg);
- }
- g_mutex_unlock(&player->bus_msg_q_lock);
-
- MMPLAYER_FLEAVE();
-}
-
-gboolean __mmplayer_gst_msg_push(GstBus *bus, GstMessage *msg, gpointer data)
-{
- mm_player_t *player = (mm_player_t *) data;
-
- g_return_val_if_fail(player, FALSE);
- g_return_val_if_fail(msg && GST_IS_MESSAGE(msg), FALSE);
-
- gst_message_ref(msg);
-
- g_mutex_lock(&player->bus_msg_q_lock);
- g_queue_push_tail(player->bus_msg_q, msg);
- g_mutex_unlock(&player->bus_msg_q_lock);
-
- MMPLAYER_BUS_MSG_THREAD_LOCK(player);
- MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
- MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
- return TRUE;
-}
-
-static gpointer __mmplayer_gst_bus_msg_thread(gpointer data)
-{
- mm_player_t *player = (mm_player_t*)(data);
- GstMessage *msg = NULL;
- GstBus *bus = NULL;
-
- MMPLAYER_FENTER();
- MMPLAYER_RETURN_VAL_IF_FAIL(player &&
- player->pipeline &&
- player->pipeline->mainbin &&
- player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
- NULL);
-
- bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
- if (!bus) {
- LOGE("cannot get BUS from the pipeline");
- return NULL;
- }
-
- MMPLAYER_BUS_MSG_THREAD_LOCK(player);
-
- LOGD("[handle: %p] gst bus msg thread will be started.", player);
- while (!player->bus_msg_thread_exit) {
- g_mutex_lock(&player->bus_msg_q_lock);
- msg = g_queue_pop_head(player->bus_msg_q);
- g_mutex_unlock(&player->bus_msg_q_lock);
- if (msg == NULL) {
- MMPLAYER_BUS_MSG_THREAD_WAIT(player);
+ if (!msg) {
+ LOGW("msg is null");
continue;
}
- MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
- /* handle the gst msg */
- __mmplayer_gst_bus_msg_callback(msg, player);
- MMPLAYER_BUS_MSG_THREAD_LOCK(player);
+ LOGW("remove remained %s msg", GST_MESSAGE_TYPE_NAME(msg));
gst_message_unref(msg);
}
-
- MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
- gst_object_unref(GST_OBJECT(bus));
-
- MMPLAYER_FLEAVE();
- return NULL;
-}
-
-static void
-__mmplayer_gst_rtp_no_more_pads(GstElement *element, gpointer data)
-{
- mm_player_t* player = (mm_player_t*) data;
-
- MMPLAYER_FENTER();
-
- /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
- * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
- * num_dynamic_pad. and this is no-more-pad situation which means no more pad will be added.
- * So we can say this. if num_dynamic_pad is zero, it must be one of followings
-
- * [1] audio and video will be dumped with filesink.
- * [2] autoplugging is done by just using pad caps.
- * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
- * and the video will be dumped via filesink.
- */
- if (player->num_dynamic_pad == 0) {
- LOGD("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
-
- if (!__mmplayer_gst_remove_fakesink(player,
- &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]))
- /* 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.
- */
- return;
- }
-
- /* create dot before error-return. for debugging */
- MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-no-more-pad");
-
- player->no_more_pad = TRUE;
+ g_mutex_unlock(&player->bus_msg_q_lock);
MMPLAYER_FLEAVE();
}
-static gboolean
-__mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink)
+gboolean
+__mmplayer_gst_remove_fakesink(mmplayer_t *player, mmplayer_gst_element_t *fakesink)
{
- GstElement* parent = NULL;
+ 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);
+ parent = (GstElement *)gst_object_get_parent((GstObject *)fakesink->gst);
if (!parent) {
- LOGD("fakesink already removed\n");
+ LOGD("fakesink already removed");
goto ERROR;
}
* so no need to wait for completion of state transiton
*/
if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(fakesink->gst, GST_STATE_NULL))
- LOGE("fakesink state change failure!\n");
+ LOGE("fakesink state change failure!");
/* FIXIT : should I return here? or try to proceed to next? */
/* return FALSE; */
/* remove fakesink from it's parent */
if (!gst_bin_remove(GST_BIN(parent), fakesink->gst)) {
- LOGE("failed to remove fakesink\n");
+ LOGE("failed to remove fakesink");
gst_object_unref(parent);
gst_object_unref(parent);
- LOGD("state-holder removed\n");
+ LOGD("state-holder removed");
gst_element_set_locked_state(fakesink->gst, FALSE);
return FALSE;
}
+static GstPadProbeReturn
+__mmplayer_gst_selector_blocked(GstPad *pad, GstPadProbeInfo *info, gpointer data)
+{
+ LOGD("pad(%s:%s) is blocked", GST_DEBUG_PAD_NAME(pad));
+ return GST_PAD_PROBE_OK;
+}
static void
-__mmplayer_gst_rtp_dynamic_pad(GstElement *element, GstPad *pad, gpointer data)
+__mmplayer_gst_selector_update_start_time(mmplayer_t *player, mmplayer_track_type_e stream_type)
{
- GstPad *sinkpad = NULL;
- GstCaps* caps = NULL;
- GstElement* new_element = NULL;
- GstStructure* str = NULL;
- const gchar* name = NULL;
-
- mm_player_t* player = (mm_player_t*) data;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_IF_FAIL(element && pad);
- MMPLAYER_RETURN_IF_FAIL(player &&
- player->pipeline &&
- player->pipeline->mainbin);
-
-
- /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
- * num_dynamic_pad will decreased after creating a sinkbin.
- */
- player->num_dynamic_pad++;
- LOGD("stream count inc : %d\n", player->num_dynamic_pad);
-
- caps = gst_pad_query_caps(pad, NULL);
-
- MMPLAYER_CHECK_NULL(caps);
-
- /* clear previous result*/
- player->have_dynamic_pad = FALSE;
-
- str = gst_caps_get_structure(caps, 0);
-
- if (!str) {
- LOGE("cannot get structure from caps.\n");
- goto ERROR;
- }
-
- name = gst_structure_get_name(str);
- if (!name) {
- LOGE("cannot get mimetype from structure.\n");
- goto ERROR;
- }
-
- if (strstr(name, "video")) {
- gint stype = 0;
- mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
-
- if (stype == MM_DISPLAY_SURFACE_NULL || stype == MM_DISPLAY_SURFACE_REMOTE) {
- if (player->v_stream_caps) {
- gst_caps_unref(player->v_stream_caps);
- player->v_stream_caps = NULL;
- }
-
- new_element = gst_element_factory_make("fakesink", NULL);
- player->num_dynamic_pad--;
- goto NEW_ELEMENT;
- }
- }
-
- /* clear previous result*/
- player->have_dynamic_pad = FALSE;
-
- if (!__mmplayer_try_to_plug_decodebin(player, pad, caps)) {
- LOGE("failed to autoplug for caps");
- goto ERROR;
- }
-
- /* check if there's dynamic pad*/
- if (player->have_dynamic_pad) {
- LOGE("using pad caps assums there's no dynamic pad !\n");
- goto ERROR;
- }
-
- gst_caps_unref(caps);
- caps = NULL;
-
-NEW_ELEMENT:
-
- /* excute new_element if created*/
- if (new_element) {
- LOGD("adding new element to pipeline\n");
-
- /* set state to READY before add to bin */
- MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_READY);
+ gint64 stop_running_time = 0;
+ gint64 position_running_time = 0;
+ gint64 position = 0;
+ gint idx = 0;
- /* add new element to the pipeline */
- if (FALSE == gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)) {
- LOGE("failed to add autoplug element to bin\n");
- goto ERROR;
+ 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); */
+ continue;
}
- /* get pad from element */
- sinkpad = gst_element_get_static_pad(GST_ELEMENT(new_element), "sink");
- if (!sinkpad) {
- LOGE("failed to get sinkpad from autoplug element\n");
- goto ERROR;
+ if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].stop)) {
+ stop_running_time =
+ gst_segment_to_running_time(&player->gapless.segment[idx],
+ GST_FORMAT_TIME, player->gapless.segment[idx].stop);
+ } else if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].duration)) {
+ stop_running_time =
+ gst_segment_to_running_time(&player->gapless.segment[idx],
+ GST_FORMAT_TIME, player->gapless.segment[idx].duration);
+ } else {
+ LOGD("duration: %"GST_TIME_FORMAT, GST_TIME_ARGS(player->duration));
+ stop_running_time =
+ gst_segment_to_running_time(&player->gapless.segment[idx],
+ GST_FORMAT_TIME, player->duration);
}
- /* link it */
- if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
- LOGE("failed to link autoplug element\n");
- goto ERROR;
- }
+ position_running_time =
+ gst_segment_to_running_time(&player->gapless.segment[idx],
+ GST_FORMAT_TIME, player->gapless.segment[idx].position);
- gst_object_unref(sinkpad);
- sinkpad = NULL;
+ LOGD("[type:%d] time info %" GST_TIME_FORMAT " , %"
+ GST_TIME_FORMAT" , %" GST_TIME_FORMAT,
+ idx,
+ GST_TIME_ARGS(stop_running_time),
+ GST_TIME_ARGS(position_running_time),
+ GST_TIME_ARGS(gst_segment_to_running_time(&player->gapless.segment[idx],
+ GST_FORMAT_TIME, player->gapless.segment[idx].start)));
- /* run. setting PLAYING here since streamming source is live source */
- MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_PLAYING);
+ position_running_time = MAX(position_running_time, stop_running_time);
+ position_running_time -= gst_segment_to_running_time(&player->gapless.segment[idx],
+ GST_FORMAT_TIME, player->gapless.segment[idx].start);
+ position_running_time = MAX(0, position_running_time);
+ position = MAX(position, position_running_time);
}
- if (caps)
- gst_caps_unref(caps);
+ if (position != 0) {
+ LOGD("[%d]GST_EVENT_STREAM_START: start_time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
+ stream_type, GST_TIME_ARGS(player->gapless.start_time[stream_type]),
+ GST_TIME_ARGS(player->gapless.start_time[stream_type] + position));
- MMPLAYER_FLEAVE();
+ player->gapless.start_time[stream_type] += position;
+ }
return;
-
-STATE_CHANGE_FAILED:
-ERROR:
- /* FIXIT : take care if new_element has already added to pipeline */
- if (new_element)
- gst_object_unref(GST_OBJECT(new_element));
-
- if (sinkpad)
- gst_object_unref(GST_OBJECT(sinkpad));
-
- if (caps)
- gst_caps_unref(caps);
-
- /* FIXIT : how to inform this error to MSL ????? */
- /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
- * then post an error to application
- */
-}
-
-static GstPadProbeReturn
-__mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data)
-{
- LOGD("pad(%s:%s) is blocked", GST_DEBUG_PAD_NAME(pad));
- return GST_PAD_PROBE_OK;
}
static GstPadProbeReturn
-__mmplayer_gst_selector_event_probe(GstPad * pad, GstPadProbeInfo * info, gpointer data)
+__mmplayer_gst_selector_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer data)
{
GstPadProbeReturn ret = GST_PAD_PROBE_OK;
GstEvent *event = GST_PAD_PROBE_INFO_DATA(info);
- mm_player_t* player = (mm_player_t*)data;
- GstCaps* caps = NULL;
- GstStructure* str = NULL;
- const gchar* name = NULL;
- MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
-
-
- if (GST_EVENT_IS_DOWNSTREAM(event)) {
- 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)
- return ret;
- } else if (GST_EVENT_IS_UPSTREAM(event)) {
- if (GST_EVENT_TYPE(event) != GST_EVENT_QOS)
- return ret;
- }
-
- caps = gst_pad_query_caps(pad, NULL);
- if (!caps) {
- LOGE("failed to get caps from pad[%s:%s]", GST_DEBUG_PAD_NAME(pad));
+ mmplayer_t *player = (mmplayer_t *)data;
+ GstCaps *caps = NULL;
+ GstStructure *str = NULL;
+ const gchar *name = NULL;
+ 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) {
+ return ret;
+ } else if (GST_EVENT_IS_UPSTREAM(event) &&
+ GST_EVENT_TYPE(event) != GST_EVENT_QOS) {
return ret;
}
- str = gst_caps_get_structure(caps, 0);
- if (!str) {
- LOGE("failed to get structure from caps");
- goto ERROR;
- }
-
- name = gst_structure_get_name(str);
- if (!name) {
- LOGE("failed to get name from str");
+ MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
+ if (!caps_ret)
goto ERROR;
- }
if (strstr(name, "audio")) {
stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
}
case GST_EVENT_STREAM_START:
{
- gint64 stop_running_time = 0;
- gint64 position_running_time = 0;
- gint64 position = 0;
- gint idx = 0;
-
- 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); */
- continue;
- }
-
- if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].stop)) {
- stop_running_time =
- gst_segment_to_running_time(&player->gapless.segment[idx],
- GST_FORMAT_TIME, player->gapless.segment[idx].stop);
- } else if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].duration)) {
- stop_running_time =
- gst_segment_to_running_time(&player->gapless.segment[idx],
- GST_FORMAT_TIME, player->gapless.segment[idx].duration);
- } else {
- LOGD("duration: %"GST_TIME_FORMAT, GST_TIME_ARGS(player->duration));
- stop_running_time =
- gst_segment_to_running_time(&player->gapless.segment[idx],
- GST_FORMAT_TIME, player->duration);
- }
-
- position_running_time =
- gst_segment_to_running_time(&player->gapless.segment[idx],
- GST_FORMAT_TIME, player->gapless.segment[idx].position);
-
- LOGD("[type:%d] time info %" GST_TIME_FORMAT " , %"
- GST_TIME_FORMAT" , %" GST_TIME_FORMAT,
- idx,
- GST_TIME_ARGS(stop_running_time),
- GST_TIME_ARGS(position_running_time),
- GST_TIME_ARGS(gst_segment_to_running_time(&player->gapless.segment[idx],
- GST_FORMAT_TIME, player->gapless.segment[idx].start)));
-
- position_running_time = MAX(position_running_time, stop_running_time);
- position_running_time -= gst_segment_to_running_time(&player->gapless.segment[idx],
- GST_FORMAT_TIME, player->gapless.segment[idx].start);
- position_running_time = MAX(0, position_running_time);
- position = MAX(position, position_running_time);
- }
-
- if (position != 0) {
- LOGD("[%d]GST_EVENT_STREAM_START: start_time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
- stream_type, GST_TIME_ARGS(player->gapless.start_time[stream_type]),
- GST_TIME_ARGS(player->gapless.start_time[stream_type] + position));
-
- player->gapless.start_time[stream_type] += position;
- }
+ __mmplayer_gst_selector_update_start_time(player, stream_type);
break;
}
case GST_EVENT_FLUSH_STOP:
LOGD("[%d] GST_EVENT_SEGMENT", stream_type);
gst_event_copy_segment(event, &segment);
- if (segment.format == GST_FORMAT_TIME) {
- LOGD("segment base:%" GST_TIME_FORMAT ", offset:%" GST_TIME_FORMAT
- ", start:%" GST_TIME_FORMAT ", stop: %" GST_TIME_FORMAT
- ", time: %" GST_TIME_FORMAT ", pos: %" GST_TIME_FORMAT ", dur: %" GST_TIME_FORMAT,
- GST_TIME_ARGS(segment.base), GST_TIME_ARGS(segment.offset),
- GST_TIME_ARGS(segment.start), GST_TIME_ARGS(segment.stop),
- GST_TIME_ARGS(segment.time), GST_TIME_ARGS(segment.position), GST_TIME_ARGS(segment.duration));
+ if (segment.format != GST_FORMAT_TIME)
+ break;
- /* keep the all the segment ev to cover the seeking */
- gst_segment_copy_into(&segment, &player->gapless.segment[stream_type]);
- player->gapless.update_segment[stream_type] = TRUE;
+ LOGD("segment base:%" GST_TIME_FORMAT ", offset:%" GST_TIME_FORMAT
+ ", start:%" GST_TIME_FORMAT ", stop: %" GST_TIME_FORMAT
+ ", time: %" GST_TIME_FORMAT ", pos: %" GST_TIME_FORMAT ", dur: %" GST_TIME_FORMAT,
+ GST_TIME_ARGS(segment.base), GST_TIME_ARGS(segment.offset),
+ GST_TIME_ARGS(segment.start), GST_TIME_ARGS(segment.stop),
+ GST_TIME_ARGS(segment.time), GST_TIME_ARGS(segment.position), GST_TIME_ARGS(segment.duration));
- if (!player->gapless.running)
- break;
+ /* keep the all the segment ev to cover the seeking */
+ gst_segment_copy_into(&segment, &player->gapless.segment[stream_type]);
+ player->gapless.update_segment[stream_type] = TRUE;
- player->gapless.segment[stream_type].base = player->gapless.start_time[stream_type];
+ if (!player->gapless.running)
+ break;
- LOGD("[%d] new base: %" GST_TIME_FORMAT, stream_type, GST_TIME_ARGS(player->gapless.segment[stream_type].base));
+ player->gapless.segment[stream_type].base = player->gapless.start_time[stream_type];
+
+ LOGD("[%d] new base: %" GST_TIME_FORMAT, stream_type, GST_TIME_ARGS(player->gapless.segment[stream_type].base));
+
+ tmpev = gst_event_new_segment(&player->gapless.segment[stream_type]);
+ gst_event_set_seqnum(tmpev, gst_event_get_seqnum(event));
+ gst_event_unref(event);
+ GST_PAD_PROBE_INFO_DATA(info) = tmpev;
- tmpev = gst_event_new_segment(&player->gapless.segment[stream_type]);
- gst_event_set_seqnum(tmpev, gst_event_get_seqnum(event));
- gst_event_unref(event);
- GST_PAD_PROBE_INFO_DATA(info) = tmpev;
- }
break;
}
case GST_EVENT_QOS:
return ret;
}
+/* create fakesink for audio or video path witout audiobin or videobin */
static void
-__mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
+__mmplayer_gst_make_fakesink(mmplayer_t *player, GstPad *pad, const gchar *name)
{
- mm_player_t* player = NULL;
- GstElement* pipeline = NULL;
- GstElement* selector = NULL;
- GstElement* fakesink = NULL;
- GstCaps* caps = NULL;
- GstStructure* str = NULL;
- const gchar* name = NULL;
- GstPad* sinkpad = NULL;
- GstPad* srcpad = NULL;
- gboolean first_track = FALSE;
-
- enum MainElementID elemId = MMPLAYER_M_NUM;
- MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
-
- /* check handles */
- player = (mm_player_t*)data;
+ GstElement *pipeline = NULL;
+ GstElement *fakesink = NULL;
+ GstPad *sinkpad = NULL;
- MMPLAYER_RETURN_IF_FAIL(elem && pad);
+ MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
- //LOGD("pad-added signal handling\n");
-
pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
- /* get mimetype from caps */
- caps = gst_pad_query_caps(pad, NULL);
- if (!caps) {
- LOGE("cannot get caps from pad.\n");
- goto ERROR;
+ /* fake sink */
+ fakesink = gst_element_factory_make("fakesink", NULL);
+ if (fakesink == NULL) {
+ LOGE("failed to create fakesink");
+ goto EXIT;
}
- str = gst_caps_get_structure(caps, 0);
- if (!str) {
- LOGE("cannot get structure from caps.\n");
- goto ERROR;
- }
+ /* store it as it's sink element */
+ __mmplayer_add_sink(player, fakesink);
- name = gst_structure_get_name(str);
- if (!name) {
- LOGE("cannot get mimetype from structure.\n");
- goto ERROR;
- }
+ gst_bin_add(GST_BIN(pipeline), fakesink);
- MMPLAYER_LOG_GST_CAPS_TYPE(caps);
- //LOGD("detected mimetype : %s\n", name);
+ /* link */
+ sinkpad = gst_element_get_static_pad(fakesink, "sink");
+
+ 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 fakesink");
+ gst_object_unref(GST_OBJECT(fakesink));
+ goto EXIT;
+ }
if (strstr(name, "video")) {
- gint stype = 0;
+ if (player->v_stream_caps) {
+ gst_caps_unref(player->v_stream_caps);
+ player->v_stream_caps = NULL;
+ }
+ if (player->ini.set_dump_element_flag)
+ __mmplayer_add_dump_buffer_probe(player, fakesink);
+ }
- mm_attrs_set_int_by_name(player->attrs, "content_video_found", TRUE);
- mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
+ g_object_set(G_OBJECT(fakesink), "sync", TRUE, NULL);
+ gst_element_set_state(fakesink, GST_STATE_PAUSED);
- /* don't make video because of not required, and not support multiple track */
- if (stype == MM_DISPLAY_SURFACE_NULL) {
- LOGD("no video sink by null surface");
+EXIT:
+ if (sinkpad)
+ gst_object_unref(GST_OBJECT(sinkpad));
- gchar *caps_str = gst_caps_to_string(caps);
- if (caps_str && (strstr(caps_str, "ST12") || strstr(caps_str, "SN12") ||
- strstr(caps_str, "SN21") || strstr(caps_str, "S420") || strstr(caps_str, "SR32")))
- player->set_mode.video_zc = TRUE;
+ MMPLAYER_FLEAVE();
+ return;
+}
- MMPLAYER_FREEIF(caps_str);
+static GstElement *
+__mmplayer_gst_make_selector(mmplayer_t *player, main_element_id_e elem_idx, mmplayer_track_type_e stream_type)
+{
+ GstElement *pipeline = NULL;
+ GstElement *selector = NULL;
+ GstPad *srcpad = NULL;
- if (player->v_stream_caps) {
- gst_caps_unref(player->v_stream_caps);
- player->v_stream_caps = NULL;
- }
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, NULL);
- LOGD("create fakesink instead of videobin");
+ selector = gst_element_factory_make("input-selector", NULL);
+ if (!selector) {
+ LOGE("failed to create input-selector");
+ return NULL;
+ }
+ g_object_set(selector, "sync-streams", TRUE, NULL);
- /* fake sink */
- fakesink = gst_element_factory_make("fakesink", NULL);
- if (fakesink == NULL) {
- LOGE("ERROR : fakesink create error\n");
- goto ERROR;
- }
+ player->pipeline->mainbin[elem_idx].id = elem_idx;
+ player->pipeline->mainbin[elem_idx].gst = selector;
- if (player->ini.set_dump_element_flag)
- __mmplayer_add_dump_buffer_probe(player, fakesink);
+ /* player->selector[stream_type].active_pad_index = DEFAULT_TRACK; */
- player->video_fakesink = fakesink;
+ srcpad = gst_element_get_static_pad(selector, "src");
- /* store it as it's sink element */
- __mmplayer_add_sink(player, player->video_fakesink);
+ 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,
+ __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,
+ __mmplayer_gst_selector_event_probe, player, NULL);
- gst_bin_add(GST_BIN(pipeline), fakesink);
+ gst_element_set_state(selector, GST_STATE_PAUSED);
- // link
- sinkpad = gst_element_get_static_pad(fakesink, "sink");
+ pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
+ gst_bin_add(GST_BIN(pipeline), selector);
- if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
- LOGW("failed to link fakesink\n");
- gst_object_unref(GST_OBJECT(fakesink));
- goto ERROR;
- }
+ gst_object_unref(GST_OBJECT(srcpad));
- if (stype == MM_DISPLAY_SURFACE_REMOTE) {
- MMPLAYER_SIGNAL_CONNECT(player, sinkpad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
- "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
- }
+ MMPLAYER_FLEAVE();
+ return selector;
+}
- if (player->set_mode.media_packet_video_stream) {
- g_object_set(G_OBJECT(fakesink), "signal-handoffs", TRUE, NULL);
-
- MMPLAYER_SIGNAL_CONNECT(player,
- G_OBJECT(fakesink),
- MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
- "handoff",
- G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
- (gpointer)player);
-
- MMPLAYER_SIGNAL_CONNECT(player,
- G_OBJECT(fakesink),
- MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
- "preroll-handoff",
- G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
- (gpointer)player);
- }
+void
+__mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
+{
+ mmplayer_t *player = (mmplayer_t *)data;
+ GstElement *selector = NULL;
+ GstCaps *caps = NULL;
+ GstStructure *str = NULL;
+ const gchar *name = NULL;
+ GstPad *sinkpad = NULL;
+ gboolean first_track = FALSE;
+ gboolean caps_ret = TRUE;
- g_object_set(G_OBJECT(fakesink), "async", TRUE, "sync", TRUE, NULL);
- gst_element_set_state(fakesink, GST_STATE_PAUSED);
- goto DONE;
- }
+ main_element_id_e elem_idx = MMPLAYER_M_NUM;
+ mmplayer_track_type_e stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
- if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
- __mmplayer_gst_decode_callback(elem, pad, player);
- goto DONE;
- }
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(elem && pad);
+ MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
- LOGD("video selector \n");
- elemId = MMPLAYER_M_V_INPUT_SELECTOR;
- stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
- } else {
- if (strstr(name, "audio")) {
- gint samplerate = 0;
- gint channels = 0;
+ LOGD("pad-added signal handling");
- if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
- __mmplayer_gst_decode_callback(elem, pad, player);
- goto DONE;
- }
+ /* get mimetype from caps */
+ MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
+ if (!caps_ret)
+ goto ERROR;
- LOGD("audio selector \n");
- elemId = MMPLAYER_M_A_INPUT_SELECTOR;
- stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
+ MMPLAYER_LOG_GST_CAPS_TYPE(caps);
+ /* LOGD("detected mimetype : %s", name); */
- gst_structure_get_int(str, "rate", &samplerate);
- gst_structure_get_int(str, "channels", &channels);
+ if (strstr(name, "video")) {
+ gint stype = 0;
+ gchar *caps_str = NULL;
- if ((channels > 0 && samplerate == 0)) {//exclude audio decoding
- /* fake sink */
- fakesink = gst_element_factory_make("fakesink", NULL);
- if (fakesink == NULL) {
- LOGE("ERROR : fakesink create error\n");
- goto ERROR;
- }
+ caps_str = gst_caps_to_string(caps);
+ if (caps_str && (strstr(caps_str, "ST12") || strstr(caps_str, "SN12") ||
+ strstr(caps_str, "SN21") || strstr(caps_str, "S420") || strstr(caps_str, "SR32")))
+ player->set_mode.video_zc = true;
- gst_bin_add(GST_BIN(pipeline), fakesink);
+ MMPLAYER_FREEIF(caps_str);
- /* link */
- sinkpad = gst_element_get_static_pad(fakesink, "sink");
+ mm_attrs_set_int_by_name(player->attrs, "content_video_found", TRUE);
+ mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
- if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
- LOGW("failed to link fakesink\n");
- gst_object_unref(GST_OBJECT(fakesink));
- goto ERROR;
- }
+ LOGD("surface type : %d", stype);
- g_object_set(G_OBJECT(fakesink), "sync", TRUE, NULL);
- gst_element_set_state(fakesink, GST_STATE_PAUSED);
+ if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
+ __mmplayer_gst_create_sinkbin(elem, pad, player);
+ goto DONE;
+ }
- goto DONE;
- }
- } else if (strstr(name, "text")) {
- LOGD("text selector \n");
- elemId = MMPLAYER_M_T_INPUT_SELECTOR;
- stream_type = MM_PLAYER_TRACK_TYPE_TEXT;
- } else {
- LOGE("wrong elem id \n");
- goto ERROR;
+ /* 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.video_export)) {
+ __mmplayer_gst_make_fakesink(player, pad, name);
+ goto DONE;
}
- }
- selector = player->pipeline->mainbin[elemId].gst;
- if (selector == NULL) {
- selector = gst_element_factory_make("input-selector", NULL);
- LOGD("Creating input-selector\n");
- if (selector == NULL) {
- LOGE("ERROR : input-selector create error\n");
- goto ERROR;
+ LOGD("video selector is required");
+ elem_idx = MMPLAYER_M_V_INPUT_SELECTOR;
+ stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
+ } else if (strstr(name, "audio")) {
+ gint samplerate = 0;
+ gint channels = 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);
+ goto DONE;
}
- g_object_set(selector, "sync-streams", TRUE, NULL);
- player->pipeline->mainbin[elemId].id = elemId;
- player->pipeline->mainbin[elemId].gst = selector;
+ gst_structure_get_int(str, "rate", &samplerate);
+ gst_structure_get_int(str, "channels", &channels);
- first_track = TRUE;
- // player->selector[stream_type].active_pad_index = DEFAULT_TRACK; // default
+ if ((channels > 0 && samplerate == 0)) { /* exclude audio decoding */
+ __mmplayer_gst_make_fakesink(player, pad, name);
+ goto DONE;
+ }
- srcpad = gst_element_get_static_pad(selector, "src");
+ LOGD("audio selector is required");
+ elem_idx = MMPLAYER_M_A_INPUT_SELECTOR;
+ stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
- 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,
- __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,
- __mmplayer_gst_selector_event_probe, player, NULL);
+ } else if (strstr(name, "text")) {
+ LOGD("text selector is required");
+ elem_idx = MMPLAYER_M_T_INPUT_SELECTOR;
+ stream_type = MM_PLAYER_TRACK_TYPE_TEXT;
+ } else {
+ LOGE("invalid caps info");
+ goto ERROR;
+ }
- gst_element_set_state(selector, GST_STATE_PAUSED);
- gst_bin_add(GST_BIN(pipeline), selector);
- } else
- LOGD("input-selector is already created.\n");
+ /* 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)
+ goto ERROR;
+ first_track = TRUE;
+ } else {
+ LOGD("input-selector is already created.");
+ }
- // link
- LOGD("Calling request pad with selector %p \n", selector);
+ /* link */
sinkpad = gst_element_get_request_pad(selector, "sink_%u");
- LOGD("got pad %s:%s from selector", GST_DEBUG_PAD_NAME(sinkpad));
+ LOGD("pad link: %s:%s - %s:%s", GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(sinkpad));
- if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
- LOGW("failed to link selector\n");
+ if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) {
+ LOGE("failed to link selector");
gst_object_unref(GST_OBJECT(selector));
goto ERROR;
}
if (first_track) {
- LOGD("this is first track --> active track \n");
+ LOGD("this track will be activated");
g_object_set(selector, "active-pad", sinkpad, NULL);
}
- _mmplayer_track_update_info(player, stream_type, sinkpad);
-
+ __mmplayer_track_update_selector_info(player, stream_type, sinkpad);
DONE:
ERROR:
sinkpad = NULL;
}
- if (srcpad) {
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
- }
-
return;
}
-static void __mmplayer_handle_text_decode_path(mm_player_t* player, GstElement* text_selector)
+static gboolean
+__mmplayer_create_sink_path(mmplayer_t *player, GstElement *selector, mmplayer_track_type_e type)
{
- GstPad* srcpad = NULL;
- MMHandleType attrs = 0;
- gint active_index = 0;
+ GstPad *srcpad = NULL;
- // [link] input-selector :: textbin
- srcpad = gst_element_get_static_pad(text_selector, "src");
- if (!srcpad) {
- LOGE("failed to get srcpad from selector\n");
- return;
- }
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, FALSE);
- LOGD("got pad %s:%s from text selector\n", GST_DEBUG_PAD_NAME(srcpad));
+ LOGD("type %d", type);
- active_index = player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index;
- if ((active_index != DEFAULT_TRACK) &&
- (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_TEXT, active_index) != MM_ERROR_NONE)) {
- LOGW("failed to change text track\n");
- player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index = DEFAULT_TRACK;
+ if (!selector) {
+ LOGD("there is no %d track", type);
+ return TRUE;
}
- player->no_more_pad = TRUE;
- __mmplayer_gst_decode_callback(text_selector, srcpad, player);
-
- LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
- if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id) {
- gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id);
- player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id = 0;
+ srcpad = gst_element_get_static_pad(selector, "src");
+ if (!srcpad) {
+ LOGE("failed to get srcpad from selector");
+ return FALSE;
}
- LOGD("Total text tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
+ LOGD("got pad %s:%s from selector", GST_DEBUG_PAD_NAME(srcpad));
- if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
- player->has_closed_caption = TRUE;
+ __mmplayer_gst_create_sinkbin(selector, srcpad, player);
- attrs = MMPLAYER_GET_ATTRS(player);
- if (attrs) {
- mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
- if (mmf_attrs_commit(attrs))
- LOGE("failed to commit.\n");
- } else
- LOGE("cannot get content attribute");
+ 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 (srcpad) {
gst_object_unref(GST_OBJECT(srcpad));
srcpad = NULL;
}
+
+ MMPLAYER_FLEAVE();
+ return TRUE;
}
static void
-__mmplayer_gst_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
+__mmplayer_set_decode_track_info(mmplayer_t *player, mmplayer_track_type_e type)
{
- mm_player_t* player = (mm_player_t*)data;
- GstElement* selector = NULL;
- GstElement* queue = NULL;
-
- GstPad* srcpad = NULL;
- GstPad* sinkpad = NULL;
- GstCaps* caps = NULL;
- gchar* caps_str = NULL;
+ MMHandleType attrs = 0;
+ gint active_index = 0;
MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
+ MMPLAYER_RETURN_IF_FAIL(player);
- caps = gst_pad_get_current_caps(pad);
- caps_str = gst_caps_to_string(caps);
- LOGD("deinterleave new caps : %s\n", caps_str);
- MMPLAYER_FREEIF(caps_str);
- gst_caps_unref(caps);
+ LOGD("type: %d, the num of track: %d", type, player->selector[type].total_track_num);
- if ((queue = __mmplayer_element_create_and_link(player, pad, "queue")) == NULL) {
- LOGE("ERROR : queue create error\n");
- goto ERROR;
+ /* change track to active pad */
+ active_index = player->selector[type].active_pad_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;
+ return;
}
- g_object_set(G_OBJECT(queue),
- "max-size-buffers", 10,
- "max-size-bytes", 0,
- "max-size-time", (guint64)0,
- NULL);
-
- selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
+ 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 (!selector) {
- LOGE("there is no audio channel selector.\n");
- goto ERROR;
+ if (mm_attrs_commit_all(attrs))
+ LOGW("failed to commit attrs.");
+ } else {
+ LOGW("cannot get content attribute");
+ }
}
- srcpad = gst_element_get_static_pad(queue, "src");
- sinkpad = gst_element_get_request_pad(selector, "sink_%u");
+ MMPLAYER_FLEAVE();
+ return;
+}
- LOGD("link(%s:%s - %s:%s)\n", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
+static gboolean
+__mmplayer_create_audio_sink_path(mmplayer_t *player, GstElement *audio_selector)
+{
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, FALSE);
- if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
- LOGW("failed to link deinterleave - selector\n");
- goto ERROR;
- }
+ if (!audio_selector) {
+ LOGD("there is no audio track, num_dynamic_pad %d", player->num_dynamic_pad);
- gst_element_set_state(queue, GST_STATE_PAUSED);
- player->audio_mode.total_track_num++;
+ /* in case the source is changed, output can be changed. */
+ if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst)) {
+ LOGD("remove previous audiobin if it exist");
-ERROR:
+ __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
+ __mmplayer_del_sink(player, player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
- if (srcpad) {
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
+ MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->audiobin, MMPLAYER_A_BIN);
+ MMPLAYER_FREEIF(player->pipeline->audiobin);
+ }
+
+ if (player->num_dynamic_pad == 0) /* FIXME: num_dynamic_pad is only for rtsp? */
+ __mmplayer_pipeline_complete(NULL, player);
+
+ return TRUE;
}
- if (sinkpad) {
- gst_object_unref(GST_OBJECT(sinkpad));
- sinkpad = NULL;
+ /* apply the audio track information */
+ __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)) {
+ LOGE("failed to create audio sink path");
+ return FALSE;
}
MMPLAYER_FLEAVE();
- return;
+ return TRUE;
}
-static void
-__mmplayer_gst_deinterleave_no_more_pads(GstElement *elem, gpointer data)
+static gboolean
+__mmplayer_create_text_sink_path(mmplayer_t *player, GstElement *text_selector)
{
- mm_player_t* player = NULL;
- GstElement* selector = NULL;
- GstPad* sinkpad = NULL;
- gint active_index = 0;
- gchar* change_pad_name = NULL;
- GstCaps* caps = NULL; // no need to unref
- gint default_audio_ch = 0;
-
MMPLAYER_FENTER();
- player = (mm_player_t*) data;
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && text_selector, FALSE);
- selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
-
- if (!selector) {
- LOGE("there is no audio channel selector.\n");
- goto ERROR;
+ if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
+ LOGD("text path is not supproted");
+ return TRUE;
}
- active_index = player->audio_mode.active_pad_index;
+ /* apply the text track information */
+ __mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_TEXT);
- if (active_index != default_audio_ch) {
- gint audio_ch = default_audio_ch;
+ if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
+ player->has_closed_caption = TRUE;
- /*To get the new pad from the selector*/
- change_pad_name = g_strdup_printf("sink%d", active_index);
- if (change_pad_name != NULL) {
- sinkpad = gst_element_get_static_pad(selector, change_pad_name);
- if (sinkpad != NULL) {
- LOGD("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
- g_object_set(selector, "active-pad", sinkpad, NULL);
+ /* create text decode path */
+ player->no_more_pad = TRUE;
- audio_ch = active_index;
+ if (!__mmplayer_create_sink_path(player, text_selector, MM_PLAYER_TRACK_TYPE_TEXT)) {
+ LOGE("failed to create text sink path");
+ return FALSE;
+ }
- caps = gst_pad_get_current_caps(sinkpad);
- MMPLAYER_LOG_GST_CAPS_TYPE(caps);
+ MMPLAYER_FLEAVE();
+ return TRUE;
+}
- __mmplayer_set_audio_attrs(player, caps);
- gst_caps_unref(caps);
- }
- MMPLAYER_FREEIF(change_pad_name);
- }
+static gboolean
+__mmplayer_gst_set_queue2_buffering(mmplayer_t *player)
+{
+ gint64 dur_bytes = 0L;
- player->audio_mode.active_pad_index = audio_ch;
- LOGD("audio LR info(0:stereo) = %d\n", player->audio_mode.active_pad_index);
- }
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
+ player->pipeline->mainbin && player->streamer, FALSE);
-ERROR:
+ if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
+ LOGE("fail to get duration.");
- if (sinkpad)
- gst_object_unref(sinkpad);
+ /* 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,
+ player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
+ TRUE, /* use_buffering */
+ MUXED_BUFFER_TYPE_MAX, /* use previous buffer type setting */
+ ((dur_bytes > 0) ? ((guint64)dur_bytes) : 0));
MMPLAYER_FLEAVE();
- return;
+ return TRUE;
}
static void
-__mmplayer_gst_build_deinterleave_path(GstElement *elem, GstPad *pad, gpointer data)
+__mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data)
{
- mm_player_t* player = NULL;
- MMPlayerGstElement *mainbin = NULL;
-
- GstElement* tee = NULL;
- GstElement* stereo_queue = NULL;
- GstElement* mono_queue = NULL;
- GstElement* conv = NULL;
- GstElement* filter = NULL;
- GstElement* deinterleave = NULL;
- GstElement* selector = NULL;
-
- GstPad* srcpad = NULL;
- GstPad* selector_srcpad = NULL;
- GstPad* sinkpad = NULL;
- GstCaps* caps = NULL;
- gulong block_id = 0;
+ mmplayer_t *player = NULL;
+ GstElement *video_selector = NULL;
+ GstElement *audio_selector = NULL;
+ GstElement *text_selector = NULL;
MMPLAYER_FENTER();
+ player = (mmplayer_t *)data;
- /* check handles */
- player = (mm_player_t*) data;
-
- MMPLAYER_RETURN_IF_FAIL(elem && pad);
- MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
-
- mainbin = player->pipeline->mainbin;
+ LOGD("no-more-pad signal handling");
- /* tee */
- if ((tee = __mmplayer_element_create_and_link(player, pad, "tee")) == NULL) {
- LOGE("ERROR : tee create error\n");
- goto ERROR;
+ if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
+ (player->cmd == MMPLAYER_COMMAND_UNREALIZE)) {
+ LOGW("player is shutting down");
+ goto EXIT;
}
- mainbin[MMPLAYER_M_A_TEE].id = MMPLAYER_M_A_TEE;
- mainbin[MMPLAYER_M_A_TEE].gst = tee;
-
- gst_element_set_state(tee, GST_STATE_PAUSED);
-
- /* queue */
- srcpad = gst_element_get_request_pad(tee, "src_%u");
- if ((stereo_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL) {
- LOGE("ERROR : stereo queue create error\n");
- goto ERROR;
- }
-
- g_object_set(G_OBJECT(stereo_queue),
- "max-size-buffers", 10,
- "max-size-bytes", 0,
- "max-size-time", (guint64)0,
- NULL);
-
- player->pipeline->mainbin[MMPLAYER_M_A_Q1].id = MMPLAYER_M_A_Q1;
- player->pipeline->mainbin[MMPLAYER_M_A_Q1].gst = stereo_queue;
-
- if (srcpad) {
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
- }
-
- srcpad = gst_element_get_request_pad(tee, "src_%u");
-
- if ((mono_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL) {
- LOGE("ERROR : mono queue create error\n");
- goto ERROR;
- }
-
- g_object_set(G_OBJECT(mono_queue),
- "max-size-buffers", 10,
- "max-size-bytes", 0,
- "max-size-time", (guint64)0,
- NULL);
-
- player->pipeline->mainbin[MMPLAYER_M_A_Q2].id = MMPLAYER_M_A_Q2;
- player->pipeline->mainbin[MMPLAYER_M_A_Q2].gst = mono_queue;
-
- gst_element_set_state(stereo_queue, GST_STATE_PAUSED);
- gst_element_set_state(mono_queue, GST_STATE_PAUSED);
-
- /* audioconvert */
- srcpad = gst_element_get_static_pad(mono_queue, "src");
- if ((conv = __mmplayer_element_create_and_link(player, srcpad, "audioconvert")) == NULL) {
- LOGE("ERROR : audioconvert create error\n");
- goto ERROR;
- }
-
- player->pipeline->mainbin[MMPLAYER_M_A_CONV].id = MMPLAYER_M_A_CONV;
- player->pipeline->mainbin[MMPLAYER_M_A_CONV].gst = conv;
-
- /* caps filter */
- if (srcpad) {
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
- }
- srcpad = gst_element_get_static_pad(conv, "src");
-
- if ((filter = __mmplayer_element_create_and_link(player, srcpad, "capsfilter")) == NULL) {
- LOGE("ERROR : capsfilter create error\n");
- goto ERROR;
- }
-
- player->pipeline->mainbin[MMPLAYER_M_A_FILTER].id = MMPLAYER_M_A_FILTER;
- player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst = filter;
-
- caps = gst_caps_from_string("audio/x-raw-int, "
- "width = (int) 16, "
- "depth = (int) 16, "
- "channels = (int) 2");
-
- g_object_set(GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst), "caps", caps, NULL);
- gst_caps_unref(caps);
-
- gst_element_set_state(conv, GST_STATE_PAUSED);
- gst_element_set_state(filter, GST_STATE_PAUSED);
-
- /* deinterleave */
- if (srcpad) {
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
- }
- srcpad = gst_element_get_static_pad(filter, "src");
-
- if ((deinterleave = __mmplayer_element_create_and_link(player, srcpad, "deinterleave")) == NULL) {
- LOGE("ERROR : deinterleave create error\n");
- goto ERROR;
- }
-
- g_object_set(deinterleave, "keep-positions", TRUE, NULL);
-
- MMPLAYER_SIGNAL_CONNECT(player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
- G_CALLBACK(__mmplayer_gst_deinterleave_pad_added), player);
-
- MMPLAYER_SIGNAL_CONNECT(player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
- G_CALLBACK(__mmplayer_gst_deinterleave_no_more_pads), player);
-
- player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].id = MMPLAYER_M_A_DEINTERLEAVE;
- player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].gst = deinterleave;
-
- /* selector */
- selector = gst_element_factory_make("input-selector", "audio-channel-selector");
- if (selector == NULL) {
- LOGE("ERROR : audio-selector create error\n");
- goto ERROR;
- }
-
- g_object_set(selector, "sync-streams", TRUE, NULL);
- gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), selector);
-
- player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].id = MMPLAYER_M_A_SELECTOR;
- player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst = selector;
-
- selector_srcpad = gst_element_get_static_pad(selector, "src");
-
- LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(selector_srcpad));
- block_id =
- gst_pad_add_probe(selector_srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
- __mmplayer_gst_selector_blocked, NULL, NULL);
-
- if (srcpad) {
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
+ if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
+ (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
+ (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)) {
+ if (!__mmplayer_gst_set_queue2_buffering(player)) {
+ LOGE("failed to set queue2 buffering");
+ goto EXIT;
+ }
}
- srcpad = gst_element_get_static_pad(stereo_queue, "src");
- sinkpad = gst_element_get_request_pad(selector, "sink_%u");
+ video_selector = player->pipeline->mainbin[MMPLAYER_M_V_INPUT_SELECTOR].gst;
+ audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
+ text_selector = player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
- if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
- LOGW("failed to link queue_stereo - selector\n");
- goto ERROR;
+ if (!video_selector && !audio_selector && !text_selector) {
+ LOGW("there is no selector");
+ player->no_more_pad = TRUE;
+ goto EXIT;
}
- player->audio_mode.total_track_num++;
-
- g_object_set(selector, "active-pad", sinkpad, NULL);
- gst_element_set_state(deinterleave, GST_STATE_PAUSED);
- gst_element_set_state(selector, GST_STATE_PAUSED);
-
- __mmplayer_gst_decode_callback(selector, selector_srcpad, player);
+ /* create video path followed by video-select */
+ if (video_selector && !audio_selector && !text_selector)
+ player->no_more_pad = TRUE;
-ERROR:
+ if (!__mmplayer_create_sink_path(player, video_selector, MM_PLAYER_TRACK_TYPE_VIDEO))
+ goto EXIT;
- LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(selector_srcpad));
- if (block_id != 0) {
- gst_pad_remove_probe(selector_srcpad, block_id);
- block_id = 0;
- }
+ /* create audio path followed by audio-select */
+ if (audio_selector && !text_selector)
+ player->no_more_pad = TRUE;
- if (sinkpad) {
- gst_object_unref(GST_OBJECT(sinkpad));
- sinkpad = NULL;
- }
+ if (!__mmplayer_create_audio_sink_path(player, audio_selector))
+ goto EXIT;
- if (srcpad) {
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
- }
+ /* create text path followed by text-select */
+ __mmplayer_create_text_sink_path(player, text_selector);
- if (selector_srcpad) {
- gst_object_unref(GST_OBJECT(selector_srcpad));
- selector_srcpad = NULL;
+EXIT:
+ if (player->gapless.reconfigure) {
+ player->gapless.reconfigure = FALSE;
+ MMPLAYER_PLAYBACK_UNLOCK(player);
}
MMPLAYER_FLEAVE();
- return;
}
-static void
-__mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data)
+static gboolean
+__mmplayer_gst_add_sinkbin_to_pipeline(mmplayer_t *player, GstElement *sinkbin, GstPad *pad, gboolean reusing, gchar *sink_pad_name)
{
- mm_player_t* player = NULL;
- GstPad* srcpad = NULL;
- GstElement* video_selector = NULL;
- GstElement* audio_selector = NULL;
- GstElement* text_selector = NULL;
- MMHandleType attrs = 0;
- gint active_index = 0;
- gint64 dur_bytes = 0L;
-
- player = (mm_player_t*) data;
-
- LOGD("no-more-pad signal handling\n");
-
- if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
- (player->cmd == MMPLAYER_COMMAND_UNREALIZE)) {
- LOGW("no need to go more");
-
- if (player->gapless.reconfigure) {
- player->gapless.reconfigure = FALSE;
- MMPLAYER_PLAYBACK_UNLOCK(player);
- }
-
- return;
- }
-
- if ((!MMPLAYER_IS_HTTP_PD(player)) &&
- (MMPLAYER_IS_HTTP_STREAMING(player)) &&
- (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
- (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)) {
- #define ESTIMATED_BUFFER_UNIT (1*1024*1024)
-
- if (NULL == player->streamer) {
- LOGW("invalid state for buffering");
- goto ERROR;
- }
-
- gint init_buffering_time = player->streamer->buffering_req.prebuffer_time;
- guint buffer_bytes = (guint)(init_buffering_time/1000) * ESTIMATED_BUFFER_UNIT;
-
- buffer_bytes = MAX(buffer_bytes, player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffering_bytes);
- LOGD("[Decodebin2] set use-buffering on Q2(pre buffer time: %d ms, buffer size : %d)\n", init_buffering_time, buffer_bytes);
+ gboolean ret = FALSE;
+ GstElement *pipeline = NULL;
+ GstPad *sinkpad = NULL;
- init_buffering_time = (init_buffering_time != 0) ? (init_buffering_time) : (player->ini.http_buffering_time);
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(sinkbin && pad, FALSE);
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, FALSE);
- if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
- LOGE("fail to get duration.\n");
+ pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
- /* 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,
- player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
- TRUE, /* use_buffering */
- buffer_bytes,
- init_buffering_time,
- 1.0, /* low percent */
- player->ini.http_buffering_limit, /* high percent */
- MUXED_BUFFER_TYPE_MAX, /* use previous buffer type setting */
- NULL,
- ((dur_bytes > 0) ? ((guint64)dur_bytes) : 0));
+ sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), sink_pad_name);
+ if (!sinkpad) {
+ LOGE("failed to get pad from sinkbin");
+ goto EXIT;
}
- video_selector = player->pipeline->mainbin[MMPLAYER_M_V_INPUT_SELECTOR].gst;
- audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
- text_selector = player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
- if (video_selector) {
- // [link] input-selector :: videobin
- srcpad = gst_element_get_static_pad(video_selector, "src");
- if (!srcpad) {
- LOGE("failed to get srcpad from video selector\n");
- goto ERROR;
- }
-
- LOGD("got pad %s:%s from video selector\n", GST_DEBUG_PAD_NAME(srcpad));
- if (!text_selector && !audio_selector)
- player->no_more_pad = TRUE;
-
- __mmplayer_gst_decode_callback(video_selector, srcpad, player);
-
- LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
- if (player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id) {
- gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id);
- player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id = 0;
+ if (reusing) {
+ /* link only */
+ if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) {
+ LOGE("failed to link sinkbin for reusing");
+ goto EXIT; /* exit either pass or fail */
}
- }
-
- if (audio_selector) {
- active_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
- if ((active_index != DEFAULT_TRACK) &&
- (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_AUDIO, active_index) != MM_ERROR_NONE)) {
- LOGW("failed to change audio track\n");
- player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index = DEFAULT_TRACK;
+ } else {
+ /* warm up */
+ if (gst_element_set_state(sinkbin, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) {
+ LOGE("failed to set state(READY) to sinkbin");
+ goto EXIT;
}
- // [link] input-selector :: audiobin
- srcpad = gst_element_get_static_pad(audio_selector, "src");
- if (!srcpad) {
- LOGE("failed to get srcpad from selector\n");
- goto ERROR;
+ /* add */
+ if (!gst_bin_add(GST_BIN(pipeline), sinkbin)) {
+ LOGE("failed to add sinkbin to pipeline");
+ goto EXIT;
}
- LOGD("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
- if (!text_selector)
- player->no_more_pad = TRUE;
-
- if ((player->use_deinterleave == TRUE) && (player->max_audio_channels >= 2)) {
- LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
- if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id) {
- gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id);
- player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id = 0;
- }
-
- __mmplayer_gst_build_deinterleave_path(audio_selector, srcpad, player);
- } else {
- __mmplayer_gst_decode_callback(audio_selector, srcpad, player);
-
- LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
- if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id) {
- gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id);
- player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id = 0;
- }
+ /* link */
+ if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) {
+ LOGE("failed to link %s:%s - %s:%s", GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(sinkpad));
+ goto EXIT;
}
- LOGD("Total audio tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
-
- attrs = MMPLAYER_GET_ATTRS(player);
- if (attrs) {
- mm_attrs_set_int_by_name(attrs, "content_audio_track_num", (gint)player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
- if (mmf_attrs_commit(attrs))
- LOGE("failed to commit.\n");
- } else
- LOGE("cannot get content attribute");
- } else {
- if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst)) {
- LOGD("There is no audio track : remove audiobin");
-
- __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
- __mmplayer_del_sink(player, player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
-
- MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->audiobin, MMPLAYER_A_BIN);
- MMPLAYER_FREEIF(player->pipeline->audiobin);
+ /* run */
+ if (gst_element_set_state(sinkbin, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
+ LOGE("failed to set state(PAUSED) to sinkbin");
+ goto EXIT;
}
-
- if (player->num_dynamic_pad == 0)
- __mmplayer_pipeline_complete(NULL, player);
- }
-
- if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
- if (text_selector)
- __mmplayer_handle_text_decode_path(player, text_selector);
}
- MMPLAYER_FLEAVE();
+ ret = TRUE;
-ERROR:
- if (srcpad) {
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
- }
+EXIT:
+ if (sinkpad)
+ gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
- if (player->gapless.reconfigure) {
- player->gapless.reconfigure = FALSE;
- MMPLAYER_PLAYBACK_UNLOCK(player);
- }
+ MMPLAYER_FLEAVE();
+ return ret;
}
static void
-__mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data)
+__mmplayer_gst_create_sinkbin(GstElement *elem, GstPad *pad, gpointer data)
{
- mm_player_t* player = NULL;
- MMHandleType attrs = 0;
- GstElement* pipeline = NULL;
- GstCaps* caps = NULL;
- gchar* caps_str = NULL;
- GstStructure* str = NULL;
- const gchar* name = NULL;
- GstPad* sinkpad = NULL;
- GstElement* sinkbin = NULL;
+ mmplayer_t *player = NULL;
+ GstCaps *caps = NULL;
+ gchar *caps_str = NULL;
+ GstStructure *str = NULL;
+ const gchar *name = NULL;
+ GstElement *sinkbin = NULL;
gboolean reusing = FALSE;
- GstElement *text_selector = NULL;
+ gboolean caps_ret = TRUE;
+ gchar *sink_pad_name = "sink";
/* check handles */
- player = (mm_player_t*) data;
+ player = (mmplayer_t *)data;
+ MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(elem && pad);
- MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
+ MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && MMPLAYER_GET_ATTRS(player));
- pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
-
- attrs = MMPLAYER_GET_ATTRS(player);
- if (!attrs) {
- LOGE("cannot get content attribute\n");
+ MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
+ if (!caps_ret)
goto ERROR;
- }
- /* get mimetype from caps */
- caps = gst_pad_query_caps(pad, NULL);
- if (!caps) {
- LOGE("cannot get caps from pad.\n");
- goto ERROR;
- }
caps_str = gst_caps_to_string(caps);
- str = gst_caps_get_structure(caps, 0);
- if (!str) {
- LOGE("cannot get structure from caps.\n");
- goto ERROR;
- }
-
- name = gst_structure_get_name(str);
- if (!name) {
- LOGE("cannot get mimetype from structure.\n");
- goto ERROR;
- }
-
- //LOGD("detected mimetype : %s\n", name);
-
+ /* LOGD("detected mimetype : %s", name); */
if (strstr(name, "audio")) {
if (player->pipeline->audiobin == NULL) {
- if (MM_ERROR_NONE != __mmplayer_gst_create_audio_pipeline(player)) {
- LOGE("failed to create audiobin. continuing without audio\n");
+ const gchar *audio_format = gst_structure_get_string(str, "format");
+ if (audio_format) {
+ LOGD("original audio format %s", audio_format);
+ mm_attrs_set_string_by_name(player->attrs, "content_audio_format", audio_format);
+ }
+
+ if (__mmplayer_gst_create_audio_sink_bin(player) != MM_ERROR_NONE) {
+ LOGE("failed to create audiobin. continuing without audio");
goto ERROR;
}
sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
- LOGD("creating audiosink bin success\n");
+ LOGD("creating audiobin success");
} else {
reusing = TRUE;
sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
- LOGD("reusing audiobin\n");
+ LOGD("reusing audiobin");
__mmplayer_update_content_attrs(player, ATTR_AUDIO);
}
-
- if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) // should not update if content have multi audio tracks
- mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
-
- player->audiosink_linked = 1;
-
- sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "sink");
- if (!sinkpad) {
- LOGE("failed to get pad from sinkbin\n");
- goto ERROR;
- }
} else if (strstr(name, "video")) {
- if (caps_str && (strstr(caps_str, "ST12") || strstr(caps_str, "SN12") ||
- strstr(caps_str, "SN21") || strstr(caps_str, "S420") || strstr(caps_str, "SR32")))
- player->set_mode.video_zc = TRUE;
-
+ /* 1. zero copy is updated at _decode_pad_added()
+ * 2. NULL surface type is handled in _decode_pad_added() */
+ LOGD("zero copy %d", player->set_mode.video_zc);
if (player->pipeline->videobin == NULL) {
- /* NOTE : not make videobin because application dose not want to play it even though file has video stream. */
- /* get video surface type */
int surface_type = 0;
mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
- LOGD("display_surface_type(%d)\n", surface_type);
-
- if (surface_type == MM_DISPLAY_SURFACE_NULL) {
- LOGD("not make videobin because it dose not want\n");
- goto ERROR;
- }
+ LOGD("display_surface_type (%d)", surface_type);
- if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
- /* mark video overlay for acquire */
- if (player->video_overlay_resource == NULL) {
- 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\n");
- goto ERROR;
- }
+ 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;
}
}
player->interrupted_by_resource = FALSE;
- /* acquire resources for video overlay */
+
if (mm_resource_manager_commit(player->resource_manager) !=
MM_RESOURCE_MANAGER_ERROR_NONE) {
- LOGE("could not acquire resources for video playing\n");
+ LOGE("could not acquire resources for video playing");
goto ERROR;
}
- if (MM_ERROR_NONE != __mmplayer_gst_create_video_pipeline(player, caps, surface_type)) {
- LOGE("failed to create videobin. continuing without video\n");
+ if (__mmplayer_gst_create_video_sink_bin(player, caps, surface_type) != MM_ERROR_NONE) {
+ LOGE("failed to create videobin. continuing without video");
goto ERROR;
}
sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
- LOGD("creating videosink bin success\n");
+ LOGD("creating videosink bin success");
} else {
reusing = TRUE;
sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
- LOGD("re-using videobin\n");
+ LOGD("re-using videobin");
__mmplayer_update_content_attrs(player, ATTR_VIDEO);
}
-
- player->videosink_linked = 1;
-
- sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "sink");
- if (!sinkpad) {
- LOGE("failed to get pad from sinkbin\n");
- goto ERROR;
- }
} else if (strstr(name, "text")) {
if (player->pipeline->textbin == NULL) {
- MMPlayerGstElement* mainbin = NULL;
-
- if (MM_ERROR_NONE != __mmplayer_gst_create_text_sink_bin(player)) {
- LOGE("failed to create text sink bin. continuing without text\n");
+ if (__mmplayer_gst_create_text_sink_bin(player) != MM_ERROR_NONE) {
+ LOGE("failed to create text sink bin. continuing without text");
goto ERROR;
}
sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
- LOGD("creating textsink bin success\n");
-
- /* FIXIT : track number shouldn't be hardcoded */
- mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
-
player->textsink_linked = 1;
- LOGI("player->textsink_linked set to 1\n");
-
- sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "text_sink");
- if (!sinkpad) {
- LOGE("failed to get pad from sinkbin\n");
- goto ERROR;
- }
-
- mainbin = player->pipeline->mainbin;
-
- if (!mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst) {
- /* input selector */
- text_selector = gst_element_factory_make("input-selector", "subtitle_inselector");
- if (!text_selector) {
- LOGE("failed to create subtitle input selector element\n");
- goto ERROR;
- }
- g_object_set(text_selector, "sync-streams", TRUE, NULL);
-
- mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
- mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = text_selector;
-
- /* warm up */
- if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(text_selector, GST_STATE_READY)) {
- LOGE("failed to set state(READY) to sinkbin\n");
- goto ERROR;
- }
-
- if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), text_selector)) {
- LOGW("failed to add subtitle input selector\n");
- goto ERROR;
- }
-
- LOGD("created element input-selector");
-
- } else {
- LOGD("already having subtitle input selector");
- text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
- }
+ LOGD("creating textsink bin success");
} else {
if (!player->textsink_linked) {
- LOGD("re-using textbin\n");
-
+ LOGD("re-using textbin");
reusing = TRUE;
sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
-
player->textsink_linked = 1;
- LOGI("player->textsink_linked set to 1\n");
- } else
- LOGD("ignoring internal subtutle since external subtitle is available");
+ } else {
+ /* linked textbin exist which means that the external subtitle path exist already */
+ LOGW("ignoring internal subtutle since external subtitle is available");
+ }
}
+ sink_pad_name = "text_sink";
} else {
- LOGW("unknown type of elementary stream!ignoring it...\n");
+ LOGW("unknown mime type %s, ignoring it", name);
goto ERROR;
}
- if (sinkbin) {
- if (!reusing) {
- /* warm up */
- if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkbin, GST_STATE_READY)) {
- LOGE("failed to set state(READY) to sinkbin\n");
- goto ERROR;
- }
-
- /* Added for multi audio support to avoid adding audio bin again*/
- /* add */
- if (FALSE == gst_bin_add(GST_BIN(pipeline), sinkbin)) {
- LOGE("failed to add sinkbin to pipeline\n");
- goto ERROR;
- }
- }
+ if (!__mmplayer_gst_add_sinkbin_to_pipeline(player, sinkbin, pad, reusing, sink_pad_name))
+ goto ERROR;
- /* link */
- if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
- LOGE("failed to get pad from sinkbin\n");
- goto ERROR;
- }
-
- if (!reusing) {
- /* run */
- if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkbin, GST_STATE_PAUSED)) {
- LOGE("failed to set state(PAUSED) to sinkbin\n");
- goto ERROR;
- }
-
- if (text_selector) {
- if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(text_selector, GST_STATE_PAUSED)) {
- LOGE("failed to set state(PAUSED) to sinkbin\n");
- goto ERROR;
- }
- }
- }
-
- gst_object_unref(sinkpad);
- sinkpad = NULL;
- }
-
- LOGD("[handle: %p] linking sink bin success", player);
+ LOGD("[handle: %p] success to create and link sink bin", player);
/* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
* streaming task. if the task blocked, then buffer will not flow to the next element
if (player->num_dynamic_pad)
player->num_dynamic_pad--;
- LOGD("no more pads: %d stream count dec : %d(num of dynamic pad)\n", player->no_more_pad, player->num_dynamic_pad);
+ 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);
if (caps)
gst_caps_unref(caps);
- if (sinkpad)
- gst_object_unref(GST_OBJECT(sinkpad));
-
- /* flusing out new attributes */
- if (mmf_attrs_commit(attrs))
- LOGE("failed to comit attributes\n");
-
return;
}
static gboolean
-__mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
+__mmplayer_get_property_value_for_rotation(mmplayer_t *player, int display_angle, int orientation, int *value)
{
- int pro_value = 0; // in the case of expection, default will be returned.
- int dest_angle = rotation_angle;
- int rotation_type = -1;
+ int required_angle = 0; /* Angle required for straight view */
+ int rotation_angle = 0;
MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
MMPLAYER_RETURN_VAL_IF_FAIL(value, FALSE);
- MMPLAYER_RETURN_VAL_IF_FAIL(rotation_angle >= 0, FALSE);
+ /* Counter clockwise */
+ switch (orientation) {
+ case 0:
+ required_angle = 0;
+ break;
+ case 90:
+ required_angle = 270;
+ break;
+ case 180:
+ required_angle = 180;
+ break;
+ case 270:
+ required_angle = 90;
+ break;
+ }
+
+ rotation_angle = display_angle + required_angle;
if (rotation_angle >= 360)
- dest_angle = rotation_angle - 360;
+ rotation_angle -= 360;
/* chech if supported or not */
- if (dest_angle % 90) {
+ if (rotation_angle % 90) {
LOGD("not supported rotation angle = %d", rotation_angle);
return FALSE;
}
- /*
- * tizenwlsink (A)
- * custom_convert - none (B)
- * videoflip - none (C)
- */
- if (player->set_mode.video_zc) {
- if (player->pipeline->videobin[MMPLAYER_V_CONV].gst) // B
- rotation_type = ROTATION_USING_CUSTOM;
- else // A
- rotation_type = ROTATION_USING_SINK;
- } else {
- int surface_type = 0;
- rotation_type = ROTATION_USING_FLIP;
-
- mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
- LOGD("check display surface type attribute: %d", surface_type);
-
- if (surface_type == MM_DISPLAY_SURFACE_OVERLAY)
- rotation_type = ROTATION_USING_SINK;
- else
- rotation_type = ROTATION_USING_FLIP; //C
-
- LOGD("using %d type for rotation", rotation_type);
- }
-
- /* get property value for setting */
- switch (rotation_type) {
- case ROTATION_USING_SINK: // tizenwlsink
- {
- switch (dest_angle) {
- case 0:
- break;
- case 90:
- pro_value = 3; // clockwise 90
- break;
- case 180:
- pro_value = 2;
- break;
- case 270:
- pro_value = 1; // counter-clockwise 90
- break;
- }
- }
+ switch (rotation_angle) {
+ case 0:
+ *value = MM_DISPLAY_ROTATION_NONE;
break;
- case ROTATION_USING_CUSTOM:
- {
- gchar *ename = NULL;
- ename = GST_OBJECT_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
-
- if (g_strrstr(ename, "fimcconvert")) {
- switch (dest_angle) {
- case 0:
- break;
- case 90:
- pro_value = 90; // clockwise 90
- break;
- case 180:
- pro_value = 180;
- break;
- case 270:
- pro_value = 270; // counter-clockwise 90
- break;
- }
- }
- }
+ case 90:
+ *value = MM_DISPLAY_ROTATION_90;
break;
- case ROTATION_USING_FLIP: // videoflip
- {
- switch (dest_angle) {
- case 0:
- break;
- case 90:
- pro_value = 1; // clockwise 90
- break;
- case 180:
- pro_value = 2;
- break;
- case 270:
- pro_value = 3; // counter-clockwise 90
- break;
- }
- }
+ case 180:
+ *value = MM_DISPLAY_ROTATION_180;
+ break;
+ case 270:
+ *value = MM_DISPLAY_ROTATION_270;
break;
}
- LOGD("setting rotation property value : %d, used rotation type : %d", pro_value, rotation_type);
-
- *value = pro_value;
+ LOGD("setting rotation property value : %d", *value);
return TRUE;
}
int
-__mmplayer_video_param_check_video_sink_bin(mm_player_t* player)
+__mmplayer_video_param_check_video_sink_bin(mmplayer_t *player)
{
/* check video sinkbin is created */
MMPLAYER_RETURN_VAL_IF_FAIL(player &&
}
int
-__mmplayer_get_video_angle(mm_player_t* player, int *user_angle, int *org_angle)
+__mmplayer_get_video_angle(mmplayer_t *player, int *display_angle, int *orientation)
{
- int user_angle_type = 0;
+ int display_rotation = 0;
gchar *org_orient = NULL;
MMHandleType attrs = MMPLAYER_GET_ATTRS(player);
return MM_ERROR_PLAYER_INTERNAL;
}
- if (user_angle) {
+ if (display_angle) {
/* update user roation */
- mm_attrs_get_int_by_name(attrs, "display_rotation", &user_angle_type);
+ mm_attrs_get_int_by_name(attrs, "display_rotation", &display_rotation);
- /* get angle with user type */
- switch (user_angle_type) {
+ /* Counter clockwise */
+ switch (display_rotation) {
case MM_DISPLAY_ROTATION_NONE:
- *user_angle = 0;
+ *display_angle = 0;
break;
- case MM_DISPLAY_ROTATION_90: /* counter-clockwise 90 */
- *user_angle = 270;
+ case MM_DISPLAY_ROTATION_90:
+ *display_angle = 90;
break;
case MM_DISPLAY_ROTATION_180:
- *user_angle = 180;
+ *display_angle = 180;
break;
- case MM_DISPLAY_ROTATION_270: /* clockwise 90 */
- *user_angle = 90;
+ case MM_DISPLAY_ROTATION_270:
+ *display_angle = 270;
break;
default:
- LOGW("wrong angle type : %d", user_angle_type);
+ LOGW("wrong angle type : %d", display_rotation);
break;
}
- LOGD("check user angle: %d", *user_angle);
+ LOGD("check user angle: %d", *display_angle);
}
- if (org_angle) {
- /* get original orientation */
+ if (orientation) {
+ /* Counter clockwise */
mm_attrs_get_string_by_name(attrs, "content_video_orientation", &org_orient);
if (org_orient) {
if (!strcmp(org_orient, "rotate-90"))
- *org_angle = 90;
+ *orientation = 90;
else if (!strcmp(org_orient, "rotate-180"))
- *org_angle = 180;
+ *orientation = 180;
else if (!strcmp(org_orient, "rotate-270"))
- *org_angle = 270;
+ *orientation = 270;
else
LOGD("original rotation is %s", org_orient);
} else {
LOGD("content_video_orientation get fail");
}
- LOGD("check orientation: %d", *org_angle);
+ LOGD("check orientation: %d", *orientation);
}
return MM_ERROR_NONE;
}
void
-__mmplayer_video_param_set_display_rotation(mm_player_t* player)
+__mmplayer_video_param_set_display_rotation(mmplayer_t *player)
{
int rotation_value = 0;
- int org_angle = 0; // current supported angle values are 0, 90, 180, 270
- int user_angle = 0;
+ int orientations = 0; // current supported angle values are 0, 90, 180, 270
+ int display_angle = 0;
MMPLAYER_FENTER();
/* check video sinkbin is created */
if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
return;
- __mmplayer_get_video_angle(player, &user_angle, &org_angle);
+ __mmplayer_get_video_angle(player, &display_angle, &orientations);
/* get rotation value to set */
- __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
+ __mmplayer_get_property_value_for_rotation(player, display_angle, orientations, &rotation_value);
g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "rotate", rotation_value, NULL);
LOGD("set video param : rotate %d", rotation_value);
}
void
-__mmplayer_video_param_set_display_visible(mm_player_t* player)
+__mmplayer_video_param_set_display_visible(mmplayer_t *player)
{
MMHandleType attrs = 0;
int visible = 0;
}
void
-__mmplayer_video_param_set_display_method(mm_player_t* player)
+__mmplayer_video_param_set_display_method(mmplayer_t *player)
{
MMHandleType attrs = 0;
int display_method = 0;
}
void
-__mmplayer_video_param_set_roi_area(mm_player_t* player)
+__mmplayer_video_param_set_video_roi_area(mmplayer_t *player)
+{
+ MMHandleType attrs = 0;
+ void *handle = NULL;
+ 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");
+ 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);
+ }
+}
+
+void
+__mmplayer_video_param_set_roi_area(mmplayer_t *player)
{
MMHandleType attrs = 0;
void *handle = NULL;
MMPLAYER_FENTER();
/* check video sinkbin is created */
- if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
+ if (__mmplayer_video_param_check_video_sink_bin(player) != MM_ERROR_NONE) {
+ LOGW("There is no video sink");
return;
+ }
attrs = MMPLAYER_GET_ATTRS(player);
MMPLAYER_RETURN_IF_FAIL(attrs);
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(mm_player_t* player)
+__mmplayer_video_param_set_display_overlay(mmplayer_t *player)
{
MMHandleType attrs = 0;
void *handle = NULL;
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 %p", wl_surface_id, *(int*)handle);
+ 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
+ *(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.");
+ }
}
-
int
-__mmplayer_update_wayland_videosink_video_param(mm_player_t* player, char *param_name)
+__mmplayer_update_wayland_videosink_video_param(mmplayer_t *player, char *param_name)
{
- bool update_all_param = FALSE;
+ gboolean update_all_param = FALSE;
MMPLAYER_FENTER();
/* check video sinkbin is created */
__mmplayer_video_param_set_display_rotation(player);
if (update_all_param || !g_strcmp0(param_name, "display_win_roi_x"))
__mmplayer_video_param_set_roi_area(player);
+ if (update_all_param)
+ __mmplayer_video_param_set_video_roi_area(player);
return MM_ERROR_NONE;
}
int
-_mmplayer_update_video_param(mm_player_t* player, char *param_name)
+_mmplayer_update_video_param(mmplayer_t *player, char *param_name)
{
MMHandleType attrs = 0;
int surface_type = 0;
_mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only)
{
gboolean disable_overlay = FALSE;
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
int ret = MM_ERROR_NONE;
MMPLAYER_FENTER();
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)\n", ret);
+ 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)\n", ret);
+ LOGE("failed to commit acquiring of overlay resource, ret(0x%x)", ret);
goto ERROR;
}
} else {
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\n");
+ LOGE("could not prepare for video_overlay resource");
goto ERROR;
}
}
/* 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\n");
+ LOGE("could not acquire resources for video playing");
goto ERROR;
}
int
_mmplayer_get_audio_only(MMHandleType hplayer, bool *paudio_only)
{
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
gboolean disable_overlay = FALSE;
MMPLAYER_FENTER();
g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
- *paudio_only = (bool)(disable_overlay);
+ *paudio_only = (bool)disable_overlay;
LOGD("audio_only : %d", *paudio_only);
return MM_ERROR_NONE;
}
-static int
-__mmplayer_gst_element_link_bucket(GList* element_bucket)
+int
+__mmplayer_gst_element_link_bucket(GList *element_bucket)
{
- GList* bucket = element_bucket;
- MMPlayerGstElement* element = NULL;
- MMPlayerGstElement* prv_element = NULL;
+ 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();
MMPLAYER_RETURN_VAL_IF_FAIL(element_bucket, -1);
- prv_element = (MMPlayerGstElement*)bucket->data;
+ prv_element = (mmplayer_gst_element_t *)bucket->data;
bucket = bucket->next;
for (; bucket; bucket = bucket->next) {
- element = (MMPlayerGstElement*)bucket->data;
+ element = (mmplayer_gst_element_t *)bucket->data;
if (element && element->gst) {
- /* If next element is audio appsrc then make a separate audio pipeline */
- if (!strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)), "audio_appsrc") ||
- !strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)), "subtitle_appsrc")) {
- prv_element = element;
- continue;
- }
-
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\n",
+ 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\n",
+ LOGD("linking [%s] to [%s] failed",
GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
return -1;
return successful_link_count;
}
-static int
-__mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket)
+int
+__mmplayer_gst_element_add_bucket_to_bin(GstBin *bin, GList *element_bucket)
{
- GList* bucket = element_bucket;
- MMPlayerGstElement* element = NULL;
+ GList *bucket = element_bucket;
+ mmplayer_gst_element_t *element = NULL;
int successful_add_count = 0;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(bin, 0);
for (; bucket; bucket = bucket->next) {
- element = (MMPlayerGstElement*)bucket->data;
+ element = (mmplayer_gst_element_t *)bucket->data;
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\n",
+ 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;
return successful_add_count;
}
-static void __mmplayer_gst_caps_notify_cb(GstPad * pad, GParamSpec * unused, gpointer data)
+static void
+__mmplayer_gst_caps_notify_cb(GstPad *pad, GParamSpec *unused, gpointer data)
{
- mm_player_t* player = (mm_player_t*) data;
+ mmplayer_t *player = (mmplayer_t *)data;
GstCaps *caps = NULL;
GstStructure *str = NULL;
const char *name;
+ gboolean caps_ret = TRUE;
MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(pad)
- MMPLAYER_RETURN_IF_FAIL(unused)
- MMPLAYER_RETURN_IF_FAIL(data)
+ MMPLAYER_RETURN_IF_FAIL(pad);
+ MMPLAYER_RETURN_IF_FAIL(unused);
+ MMPLAYER_RETURN_IF_FAIL(data);
caps = gst_pad_get_current_caps(pad);
if (!caps)
return;
- str = gst_caps_get_structure(caps, 0);
- if (!str)
- goto ERROR;
-
- name = gst_structure_get_name(str);
- if (!name)
+ MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
+ if (!caps_ret)
goto ERROR;
- LOGD("name = %s\n", name);
+ LOGD("name = %s", name);
if (strstr(name, "audio")) {
__mmplayer_update_content_attrs(player, ATTR_AUDIO);
if (player->audio_stream_changed_cb) {
- LOGE("call the audio stream changed cb\n");
+ LOGE("call the audio stream changed cb");
player->audio_stream_changed_cb(player->audio_stream_changed_cb_user_param);
}
} else if (strstr(name, "video")) {
__mmplayer_update_content_attrs(player, ATTR_VIDEO);
if (player->video_stream_changed_cb) {
- LOGE("call the video stream changed cb\n");
+ LOGE("call the video stream changed cb");
player->video_stream_changed_cb(player->video_stream_changed_cb_user_param);
}
- } else
- goto ERROR;
+ } else {
+ LOGW("invalid caps info");
+ }
ERROR:
-
- gst_caps_unref(caps);
+ if (caps)
+ gst_caps_unref(caps);
MMPLAYER_FLEAVE();
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_pipeline
- */
-/* 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 \n", 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(mm_player_t* player, gboolean send_all)
+__mmplayer_audio_stream_clear_buffer(mmplayer_t *player, gboolean send_all)
{
GList *l = NULL;
if (player->audio_stream_buff_list) {
for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) {
- mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data;
+ mmplayer_audio_stream_buff_t *tmp = (mmplayer_audio_stream_buff_t *)l->data;
if (tmp) {
if (send_all) {
LOGD("[%"G_GUINT64_FORMAT"] send remained data.", tmp->channel_mask);
__mmplayer_audio_stream_send_data(player, tmp);
}
- if (tmp->pcm_data)
- g_free(tmp->pcm_data);
- g_free(tmp);
+ MMPLAYER_FREEIF(tmp->pcm_data);
+ MMPLAYER_FREEIF(tmp);
}
}
g_list_free(player->audio_stream_buff_list);
}
static void
-__mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer)
+__mmplayer_audio_stream_send_data(mmplayer_t *player, mmplayer_audio_stream_buff_t *a_buffer)
{
- MMPlayerAudioStreamDataType audio_stream = { 0, };
+ mmplayer_audio_decoded_data_info_t audio_stream = { 0, };
MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb_ex);
+ MMPLAYER_RETURN_IF_FAIL(player && player->audio_decoded_cb);
audio_stream.bitrate = a_buffer->bitrate;
audio_stream.channel = a_buffer->channel;
audio_stream.channel_mask = a_buffer->channel_mask;
audio_stream.data_size = a_buffer->data_size;
audio_stream.data = a_buffer->pcm_data;
+ audio_stream.pcm_format = a_buffer->pcm_format;
- /* 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_ex(&audio_stream, player->audio_stream_cb_user_param);
+ /* LOGD("[%"G_GUINT64_FORMAT"] send data size:%d, %p", audio_stream.channel_mask, audio_stream.data_size, player->audio_decoded_cb_user_param); */
+ player->audio_decoded_cb(&audio_stream, player->audio_decoded_cb_user_param);
MMPLAYER_FLEAVE();
}
static void
-__mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
+__mmplayer_audio_stream_decoded_render_cb(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer data)
{
- mm_player_t* player = (mm_player_t*) data;
-
+ mmplayer_t *player = (mmplayer_t *)data;
+ const gchar *pcm_format = NULL;
gint channel = 0;
gint rate = 0;
gint depth = 0;
guint64 channel_mask = 0;
void *a_data = NULL;
gint a_size = 0;
- mm_player_audio_stream_buff_t *a_buffer = NULL;
+ mmplayer_audio_stream_buff_t *a_buffer = NULL;
GstMapInfo mapinfo = GST_MAP_INFO_INIT;
GList *l = NULL;
MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb_ex);
+ MMPLAYER_RETURN_IF_FAIL(player && player->audio_decoded_cb);
gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
a_data = mapinfo.data;
GstStructure *structure = gst_caps_get_structure(caps, 0);
/* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
+ 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);
* The num of buffer list depends on the num of audio channels */
if (player->audio_stream_buff_list) {
for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) {
- mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data;
+ 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); */
}
}
- /* create new audio stream data */
- a_buffer = (mm_player_audio_stream_buff_t*)g_malloc0(sizeof(mm_player_audio_stream_buff_t));
+ /* 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.");
goto DONE;
a_buffer->bitrate = rate;
a_buffer->channel = channel;
a_buffer->depth = depth;
- a_buffer->is_little_endian = (endianness == 1234 ? 1 : 0);
+ 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 = util_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_malloc(a_buffer->buff_size);
+ a_buffer->pcm_data = g_try_malloc(a_buffer->buff_size);
if (a_buffer->pcm_data == NULL) {
LOGE("failed to alloc data.");
- g_free(a_buffer);
+ MMPLAYER_FREEIF(a_buffer);
goto DONE;
}
memcpy(a_buffer->pcm_data, a_data, a_size);
/* If sync is TRUE, send data directly. */
a_buffer->pcm_data = a_data;
__mmplayer_audio_stream_send_data(player, a_buffer);
- g_free(a_buffer);
+ MMPLAYER_FREEIF(a_buffer);
}
DONE:
static void
__mmplayer_gst_audio_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
{
- mm_player_t* player = (mm_player_t*)data;
- MMPlayerGstElement* audiobin = player->pipeline->audiobin;
- GstPad* sinkpad = NULL;
+ mmplayer_t *player = (mmplayer_t *)data;
+ mmplayer_gst_element_t *audiobin = player->pipeline->audiobin;
+ GstPad *sinkpad = NULL;
GstElement *queue = NULL, *sink = NULL;
MMPLAYER_FENTER();
queue = gst_element_factory_make("queue", NULL);
if (queue == NULL) {
- LOGD("fail make queue\n");
+ LOGD("fail make queue");
goto ERROR;
}
sink = gst_element_factory_make("fakesink", NULL);
if (sink == NULL) {
- LOGD("fail make fakesink\n");
+ LOGD("fail make fakesink");
goto ERROR;
}
gst_bin_add_many(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), queue, sink, NULL);
if (!gst_element_link_pads_full(queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING)) {
- LOGW("failed to link queue & sink\n");
+ LOGW("failed to link queue & sink");
goto ERROR;
}
sinkpad = gst_element_get_static_pad(queue, "sink");
if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
- LOGW("failed to link [%s:%s] to queue\n", GST_DEBUG_PAD_NAME(pad));
+ LOGW("failed to link [%s:%s] to queue", GST_DEBUG_PAD_NAME(pad));
goto ERROR;
}
- LOGE("player->audio_stream_sink_sync: %d\n", 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);
+ /* 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;
+ }
+
gst_element_set_state(sink, GST_STATE_PAUSED);
gst_element_set_state(queue, GST_STATE_PAUSED);
- MMPLAYER_SIGNAL_CONNECT(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);
+
MMPLAYER_FLEAVE();
return;
ERROR:
- LOGE("__mmplayer_gst_audio_deinterleave_pad_added ERROR\n");
+ LOGE("__mmplayer_gst_audio_deinterleave_pad_added ERROR");
if (queue) {
gst_object_unref(GST_OBJECT(queue));
queue = NULL;
return;
}
-void __mmplayer_gst_set_audiosink_property(mm_player_t* player, MMHandleType attrs)
+void
+__mmplayer_gst_set_pulsesink_property(mmplayer_t *player)
{
#define MAX_PROPS_LEN 128
gint latency_mode = 0;
* But, it can not be changed during playing.
*/
MMPLAYER_FENTER();
- mm_attrs_get_int_by_name(attrs, "sound_stream_index", &stream_id);
- mm_attrs_get_string_by_name(attrs, "sound_stream_type", &stream_type);
+ MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->audiobin);
+
+ 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) {
- LOGE("stream_type is null.\n");
+ 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);
+ 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].\n",
- stream_type, stream_id, player->sound.focus_id, stream_props);
+ LOGI("stream_type[%s], stream_id[%d], result[%s].", stream_type, stream_id, stream_props);
gst_structure_free(props);
}
- mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
+ mm_attrs_get_int_by_name(player->attrs, "sound_latency_mode", &latency_mode);
switch (latency_mode) {
case AUDIO_LATENCY_MODE_LOW:
"latency", latency,
NULL);
- LOGD("audiosink property - latency=%s \n", latency);
+ LOGD("audiosink property - latency=%s", latency);
- g_free(latency);
+ MMPLAYER_FREEIF(latency);
MMPLAYER_FLEAVE();
}
-static int
-__mmplayer_gst_create_audio_pipeline(mm_player_t* player)
+void
+__mmplayer_gst_set_openalsink_property(mmplayer_t *player)
{
- MMPlayerGstElement* first_element = NULL;
- MMPlayerGstElement* audiobin = NULL;
- MMHandleType attrs = 0;
- GstPad *pad = NULL;
- GstPad *ghostpad = NULL;
- GList* element_bucket = NULL;
- gboolean link_audio_sink_now = TRUE;
- int i = 0;
- GstCaps *acaps;
+ 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, MM_ERROR_PLAYER_NOT_INITIALIZED);
+ audiobin = player->pipeline->audiobin;
- /* alloc handles */
- audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
- if (!audiobin) {
- LOGE("failed to allocate memory for audiobin\n");
- return MM_ERROR_PLAYER_NO_FREE_SPACE;
+ 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);
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "stream-info", stream_info, NULL);
+
+ if (player->video360_yaw_radians <= M_PI &&
+ player->video360_yaw_radians >= -M_PI &&
+ player->video360_pitch_radians <= M_PI_2 &&
+ player->video360_pitch_radians >= -M_PI_2) {
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst),
+ "source-orientation-y", (int)(player->video360_yaw_radians * 180.0 / M_PI),
+ "source-orientation-x", (int)(player->video360_pitch_radians * 180.0 / M_PI), NULL);
+ } else if (player->video360_metadata.init_view_heading || player->video360_metadata.init_view_pitch) {
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst),
+ "source-orientation-y", player->video360_metadata.init_view_heading,
+ "source-orientation-x", player->video360_metadata.init_view_pitch, NULL);
}
- attrs = MMPLAYER_GET_ATTRS(player);
+ MMPLAYER_FLEAVE();
+}
- /* create bin */
- audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
- audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
- if (!audiobin[MMPLAYER_A_BIN].gst) {
- LOGE("failed to create audiobin\n");
- goto ERROR;
- }
+static int
+__mmplayer_gst_make_audio_playback_sink(mmplayer_t *player, GList **bucket)
+{
+ mmplayer_gst_element_t *audiobin = NULL;
+ GstPad *sink_pad = NULL;
+ GstCaps *acaps = NULL;
+ gint channels = 0;
+ int pitch_control = 0;
+ double pitch_value = 1.0;
- /* take it */
- player->pipeline->audiobin = audiobin;
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
+ player->pipeline->audiobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
+
+ audiobin = player->pipeline->audiobin;
+
+ LOGD("make element for normal audio playback");
+
+ /* audio bin structure for playback. {} means optional.
+ optional : pitch, audioeq, custom audioeq, openalsink for 360 audio content
+
+ * 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,
+ NULL);
+
+ LOGD("pitch %d / %1.3f", pitch_control, pitch_value);
+ if (pitch_control && (player->videodec_linked == 0)) {
+ GstElementFactory *factory;
- player->set_mode.pcm_extraction = __mmplayer_can_extract_pcm(player);
+ factory = gst_element_factory_find("pitch");
+ if (factory) {
+ gst_object_unref(factory);
- /* Adding audiotp plugin for reverse trickplay feature */
-// MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audio trickplay", TRUE, player);
+ /* converter */
+ 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", *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->set_mode.pcm_extraction) {
- // pcm extraction only and no sound output
- if (player->audio_stream_render_cb_ex) {
- char *caps_str = NULL;
- GstCaps* caps = NULL;
- gchar *format = NULL;
+ /* for logical volume control */
+ 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);
- /* capsfilter */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
+ if (player->sound.mute) {
+ LOGD("mute enabled");
+ g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
+ }
- mm_attrs_get_string_by_name(player->attrs, "pcm_audioformat", &format);
+ mm_attrs_get_int_by_name(player->attrs, "content_audio_channels", &channels);
- LOGD("contents : format: %s samplerate : %d pcm_channel: %d", format, player->pcm_samplerate, player->pcm_channel);
+ /* 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 = gst_caps_new_simple("audio/x-raw",
- "format", G_TYPE_STRING, format,
- "rate", G_TYPE_INT, player->pcm_samplerate,
- "channels", G_TYPE_INT, player->pcm_channel,
- NULL);
- caps_str = gst_caps_to_string(caps);
- LOGD("new caps : %s\n", 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);
- /* raw pad handling signal */
- MMPLAYER_SIGNAL_CONNECT(player,
- (audiobin[MMPLAYER_A_DEINTERLEAVE].gst),
- MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
- G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), player);
- } else {
- int dst_samplerate = 0;
- int dst_channels = 0;
- int dst_depth = 0;
- char *caps_str = NULL;
- GstCaps* caps = NULL;
-
- /* get conf. values */
- mm_attrs_multiple_get(player->attrs,
- NULL,
- "pcm_extraction_samplerate", &dst_samplerate,
- "pcm_extraction_channels", &dst_channels,
- "pcm_extraction_depth", &dst_depth,
- NULL);
-
- /* capsfilter */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
- caps = gst_caps_new_simple("audio/x-raw",
- "rate", G_TYPE_INT, dst_samplerate,
- "channels", G_TYPE_INT, dst_channels,
- "depth", G_TYPE_INT, dst_depth,
- NULL);
- caps_str = gst_caps_to_string(caps);
- LOGD("new caps : %s\n", caps_str);
+ /* 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) {
- g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
+ strncpy(player->ini.audiosink_element, "openalsink", PLAYER_INI_MAX_STRLEN - 1);
- /* clean */
- gst_caps_unref(caps);
- MMPLAYER_FREEIF(caps_str);
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV_BFORMAT, "audioconvert", "audio-converter-bformat", *bucket, player);
- /* fake sink */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, 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);
- /* set sync */
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
- }
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "openalsink", "audiosink", *bucket, player);
+
+ player->is_openal_plugin_used = TRUE;
} else {
- // normal playback
- //GstCaps* caps = NULL;
- gint channels = 0;
+ 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);
+ }
- /* 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 ((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);
+ }
- if (player->sound.mute) {
- LOGD("mute enabled\n");
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
- }
+ if (g_strrstr(player->ini.audiosink_element, "pulsesink"))
+ __mmplayer_gst_set_pulsesink_property(player);
+ else if (g_strrstr(player->ini.audiosink_element, "openalsink"))
+ __mmplayer_gst_set_openalsink_property(player);
-#if 0
- /*capsfilter */
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE, player);
- caps = gst_caps_from_string("audio/x-raw-int, "
- "endianness = (int) LITTLE_ENDIAN, "
- "signed = (boolean) true, "
- "width = (int) 16, "
- "depth = (int) 16");
- g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
- gst_caps_unref(caps);
-#endif
+ /* 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);
- /* check if multi-channels */
- if (player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) {
- GstPad *srcpad = NULL;
- GstCaps *caps = NULL;
-
- if ((srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "src"))) {
- if ((caps = gst_pad_query_caps(srcpad, NULL))) {
- //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
- GstStructure *str = gst_caps_get_structure(caps, 0);
- if (str)
- gst_structure_get_int(str, "channels", &channels);
- gst_caps_unref(caps);
- }
- gst_object_unref(srcpad);
- }
- }
+ 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);
- 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 (MM_AUDIO_EFFECT_TYPE_CUSTOM == player->audio_effect_info.effect_type) {
- if (!_mmplayer_audio_effect_custom_apply(player))
- LOGI("apply audio effect(custom) setting success\n");
- }
- }
+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);
- }
-
- /* 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);
-
- /* 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) {
-
- strncpy(player->ini.audiosink_element, "openalsink", PLAYER_INI_MAX_STRLEN - 1);
-
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV_BFORMAT, "audioconvert", "audio-converter-bformat", link_audio_sink_now, player);
-
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_360, "capsfilter", "audio-caps-filter", link_audio_sink_now, 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", link_audio_sink_now, player);
- 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);
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "stream-info", stream_info, NULL);
-
- player->is_openal_plugin_used = TRUE;
-
- if (player->video360_yaw_radians <= M_PI &&
- player->video360_yaw_radians >= -M_PI &&
- player->video360_pitch_radians <= M_PI_2 &&
- player->video360_pitch_radians >= -M_PI_2) {
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst),
- "source-orientation-y", (int) (player->video360_yaw_radians * 180.0 / M_PI),
- "source-orientation-x", (int) (player->video360_pitch_radians * 180.0 / M_PI), NULL);
- } else if (player->video360_metadata.init_view_heading || player->video360_metadata.init_view_pitch) {
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst),
- "source-orientation-y", player->video360_metadata.init_view_heading,
- "source-orientation-x", player->video360_metadata.init_view_pitch, NULL);
- }
- } 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.\n");
- MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.audiosink_element, "audiosink", link_audio_sink_now, 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;
- /* 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);
+ gchar *dst_format = NULL;
+ int dst_len = 0;
+ int dst_samplerate = 0;
+ int dst_channels = 0;
+ GstCaps *caps = NULL;
+ char *caps_str = NULL;
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
+ player->pipeline->audiobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
- if ((MMPLAYER_IS_RTSP_STREAMING(player)) ||
- (player->videodec_linked && player->ini.use_system_clock)) {
- LOGD("system clock will be used.\n");
- g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE, NULL);
- }
+ audiobin = player->pipeline->audiobin;
- if (g_strrstr(player->ini.audiosink_element, "pulsesink"))
- __mmplayer_gst_set_audiosink_property(player, attrs);
- }
+ LOGD("make element for audio extract, option = 0x%X", player->audio_extract_opt);
- if (audiobin[MMPLAYER_A_SINK].gst) {
- GstPad *sink_pad = NULL;
- sink_pad = gst_element_get_static_pad(audiobin[MMPLAYER_A_SINK].gst, "sink");
- MMPLAYER_SIGNAL_CONNECT(player, sink_pad, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
- "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
- gst_object_unref(GST_OBJECT(sink_pad));
- }
+ /* audio bin structure according to the mmplayer_audio_extract_opt_e.
- __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst);
+ [case 1] extract interleave audio pcm without playback
+ : MM_PLAYER_AUDIO_EXTRACT_DEFAULT (sync)
+ MM_PLAYER_AUDIO_EXTRACT_NO_SYNC_WITH_CLOCK (non sync)
- /* adding created elements to bin */
- LOGD("adding created elements to bin\n");
- if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket)) {
- LOGE("failed to add elements\n");
- goto ERROR;
- }
+ * src - ... - aconv - resample - capsfilter - fakesink (sync or not)
- /* linking elements in the bucket by added order. */
- LOGD("Linking elements in the bucket by added order.\n");
- if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
- LOGE("failed to link elements\n");
- goto ERROR;
- }
+ [case 2] deinterleave for each channel without playback
+ : MM_PLAYER_AUDIO_EXTRACT_DEINTERLEAVE (sync)
+ MM_PLAYER_AUDIO_EXTRACT_NO_SYNC_AND_DEINTERLEAVE (non sync)
- /* get first element's sinkpad for creating ghostpad */
- first_element = (MMPlayerGstElement *)element_bucket->data;
- if (!first_element) {
- LOGE("failed to get first elem\n");
- goto ERROR;
- }
+ * src - ... - aconv - resample - capsfilter - deinterleave - fakesink (sync or not)
+ - fakesink (sync or not)
+ - ... (sync or not)
- pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
- if (!pad) {
- LOGE("failed to get pad from first element of audiobin\n");
- goto ERROR;
- }
+ [case 3] [case 1(sync only)] + playback
+ : MM_PLAYER_AUDIO_EXTRACT_WITH_PLAYBACK
- ghostpad = gst_ghost_pad_new("sink", pad);
- if (!ghostpad) {
- LOGE("failed to create ghostpad\n");
- goto ERROR;
- }
+ * src - ... - tee - queue1 - playback path
+ - queue2 - [case1 pipeline with sync]
- if (FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad)) {
- LOGE("failed to add ghostpad to audiobin\n");
- goto ERROR;
- }
+ [case 4] [case 2(sync only)] + playback
+ : MM_PLAYER_AUDIO_EXTRACT_DEINTERLEAVE_WITH_PLAYBACK
- gst_object_unref(pad);
+ * src - ... - tee - queue1 - playback path
+ - queue2 - [case2 pipeline with sync]
- g_list_free(element_bucket);
- MMPLAYER_FLEAVE();
+ */
- return MM_ERROR_NONE;
+ /* 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);
-ERROR:
+ /* 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);
- LOGD("ERROR : releasing audiobin\n");
+ /* 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 (pad)
- gst_object_unref(GST_OBJECT(pad));
+ /* 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);
- if (ghostpad)
- gst_object_unref(GST_OBJECT(ghostpad));
+ /* resampler */
+ MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_EXTRACT_RESAMPLER, player->ini.audioresampler_element, "audio-ext-resampler", *bucket, player);
- if (element_bucket)
- g_list_free(element_bucket);
+ /* 2. decide the extract pcm format */
+ mm_attrs_multiple_get(player->attrs, NULL,
+ "pcm_audioformat", &dst_format, &dst_len,
+ "pcm_extraction_samplerate", &dst_samplerate,
+ "pcm_extraction_channels", &dst_channels,
+ NULL);
- /* release element which are not added to bin */
- for (i = 1; i < MMPLAYER_A_NUM; i++) {
- /* NOTE : skip bin */
- if (audiobin[i].gst) {
- GstObject* parent = NULL;
- parent = gst_element_get_parent(audiobin[i].gst);
+ LOGD("required extract pcm format - format: %s(%d), samplerate : %d, channel: %d",
+ dst_format, dst_len, dst_samplerate, dst_channels);
- if (!parent) {
- gst_object_unref(GST_OBJECT(audiobin[i].gst));
- audiobin[i].gst = NULL;
- } else
- gst_object_unref(GST_OBJECT(parent));
+ 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 || util_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;
}
- /* release audiobin with it's childs */
- if (audiobin[MMPLAYER_A_BIN].gst)
- gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
+ /* 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);
- MMPLAYER_FREEIF(audiobin);
+ caps_str = gst_caps_to_string(caps);
+ LOGD("new caps : %s", caps_str);
- player->pipeline->audiobin = NULL;
+ g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_EXTRACT_CAPS].gst), "caps", caps, NULL);
- return MM_ERROR_PLAYER_INTERNAL;
-}
+ /* clean */
+ gst_caps_unref(caps);
+ MMPLAYER_FREEIF(caps_str);
-static GstPadProbeReturn
-__mmplayer_audio_stream_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
-{
- mm_player_t* player = (mm_player_t*) u_data;
- GstBuffer *pad_buffer = gst_pad_probe_info_get_buffer(info);
- GstMapInfo probe_info = GST_MAP_INFO_INIT;
+ /* 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);
- gst_buffer_map(pad_buffer, &probe_info, GST_MAP_READ);
+ /* 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);
+ } 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);
- if (player->audio_stream_cb && probe_info.size && probe_info.data)
- player->audio_stream_cb((void *)probe_info.data, probe_info.size, player->audio_stream_cb_user_param);
+ __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);
- return GST_PAD_PROBE_OK;
+ __mmplayer_add_sink(player, audiobin[extract_sink_id].gst);
+ }
+
+ 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);
+ 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;
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_PLAYER_INTERNAL;
+}
+
+static int
+__mmplayer_gst_create_audio_sink_bin(mmplayer_t *player)
+{
+ mmplayer_gst_element_t *first_element = NULL;
+ mmplayer_gst_element_t *audiobin = NULL;
+ GstPad *pad = NULL;
+ GstPad *ghostpad = NULL;
+ GList *element_bucket = NULL;
+ int i = 0;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
+
+ /* alloc handles */
+ audiobin = (mmplayer_gst_element_t *)g_try_malloc0(sizeof(mmplayer_gst_element_t) * MMPLAYER_A_NUM);
+ if (!audiobin) {
+ LOGE("failed to allocate memory for audiobin");
+ return MM_ERROR_PLAYER_NO_FREE_SPACE;
+ }
+
+ /* create bin */
+ audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
+ audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
+ if (!audiobin[MMPLAYER_A_BIN].gst) {
+ LOGE("failed to create audiobin");
+ goto ERROR;
+ }
+
+ /* take it */
+ player->pipeline->audiobin = audiobin;
+
+ /* create audio filters and audiosink */
+ 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))
+ 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)
+ goto ERROR;
+
+ /* get first element's sinkpad for creating ghostpad */
+ first_element = (mmplayer_gst_element_t *)element_bucket->data;
+ if (!first_element) {
+ LOGE("failed to get first elem");
+ goto ERROR;
+ }
+
+ pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
+ if (!pad) {
+ LOGE("failed to get pad from first element of audiobin");
+ goto ERROR;
+ }
+
+ ghostpad = gst_ghost_pad_new("sink", pad);
+ if (!ghostpad) {
+ LOGE("failed to create ghostpad");
+ goto ERROR;
+ }
+
+ if (!gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad)) {
+ LOGE("failed to add ghostpad to audiobin");
+ goto ERROR;
+ }
+
+ gst_object_unref(pad);
+
+ g_list_free(element_bucket);
+ MMPLAYER_FLEAVE();
+
+ return MM_ERROR_NONE;
+
+ERROR:
+ LOGD("ERROR : releasing audiobin");
+
+ if (pad)
+ gst_object_unref(GST_OBJECT(pad));
+
+ if (ghostpad)
+ gst_object_unref(GST_OBJECT(ghostpad));
+
+ if (element_bucket)
+ g_list_free(element_bucket);
+
+ /* release element which are not added to bin */
+ for (i = 1; i < MMPLAYER_A_NUM; i++) {
+ /* NOTE : skip bin */
+ if (audiobin[i].gst) {
+ GstObject *parent = NULL;
+ parent = gst_element_get_parent(audiobin[i].gst);
+
+ if (!parent) {
+ gst_object_unref(GST_OBJECT(audiobin[i].gst));
+ audiobin[i].gst = NULL;
+ } else
+ gst_object_unref(GST_OBJECT(parent));
+ }
+ }
+
+ /* release audiobin with it's childs */
+ if (audiobin[MMPLAYER_A_BIN].gst)
+ gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
+
+ MMPLAYER_FREEIF(audiobin);
+
+ player->pipeline->audiobin = NULL;
+
+ return MM_ERROR_PLAYER_INTERNAL;
}
-static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name)
+static guint32
+_mmplayer_convert_fourcc_string_to_value(const gchar *format_name)
{
return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24);
}
-int _mmplayer_video_stream_release_bo(mm_player_t* player, void* bo)
+int
+_mmplayer_video_stream_release_bo(mmplayer_t *player, void *bo)
{
int ret = MM_ERROR_NONE;
GList *l = NULL;
if (player->video_bo_list) {
for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
- mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
+ mmplayer_video_bo_info_t *tmp = (mmplayer_video_bo_info_t *)l->data;
if (tmp && tmp->bo == bo) {
- tmp->using = FALSE;
+ tmp->used = FALSE;
LOGD("release bo %p", bo);
tbm_bo_unref(tmp->bo);
MMPLAYER_VIDEO_BO_UNLOCK(player);
}
static void
-__mmplayer_video_stream_destroy_bo_list(mm_player_t* player)
+__mmplayer_video_stream_destroy_bo_list(mmplayer_t *player)
{
GList *l = NULL;
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)) {
- mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
+ mmplayer_video_bo_info_t *tmp = (mmplayer_video_bo_info_t *)l->data;
if (tmp) {
if (tmp->bo)
tbm_bo_unref(tmp->bo);
return;
}
-static void*
-__mmplayer_video_stream_get_bo(mm_player_t* player, int size)
+static void *
+__mmplayer_video_stream_get_bo(mmplayer_t *player, int size)
{
GList *l = NULL;
MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
}
for (; idx < player->ini.num_of_video_bo; idx++) {
- mm_player_video_bo_info_t* bo_info = g_new(mm_player_video_bo_info_t, 1);
+ mmplayer_video_bo_info_t *bo_info = g_new(mmplayer_video_bo_info_t, 1);
if (!bo_info) {
LOGE("Fail to alloc bo_info.");
break;
bo_info->bo = tbm_bo_alloc(player->bufmgr, size, TBM_BO_DEFAULT);
if (!bo_info->bo) {
LOGE("Fail to tbm_bo_alloc.");
- g_free(bo_info);
+ MMPLAYER_FREEIF(bo_info);
break;
}
- bo_info->using = FALSE;
+ bo_info->used = FALSE;
player->video_bo_list = g_list_append(player->video_bo_list, bo_info);
}
while (TRUE) {
/* get bo from list*/
for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
- mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
- if (tmp && (tmp->using == FALSE)) {
+ mmplayer_video_bo_info_t *tmp = (mmplayer_video_bo_info_t *)l->data;
+ if (tmp && (tmp->used == FALSE)) {
LOGD("found bo %p to use", tmp->bo);
- tmp->using = TRUE;
+ tmp->used = TRUE;
MMPLAYER_VIDEO_BO_UNLOCK(player);
return tbm_bo_ref(tmp->bo);
}
if (player->ini.video_bo_timeout <= 0) {
MMPLAYER_VIDEO_BO_WAIT(player);
} else {
- gint64 timeout = g_get_monotonic_time() + player->ini.video_bo_timeout*G_TIME_SPAN_SECOND;
+ gint64 timeout = g_get_monotonic_time() + player->ini.video_bo_timeout * G_TIME_SPAN_SECOND;
ret = MMPLAYER_VIDEO_BO_WAIT_UNTIL(player, timeout);
}
continue;
}
static void
-__mmplayer_video_stream_decoded_preroll_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
+__mmplayer_video_stream_decoded_preroll_cb(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer data)
{
- mm_player_t* player = (mm_player_t*)data;
+ 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;
+ player->video_stream_prerolled = false;
__mmplayer_video_stream_decoded_render_cb(object, buffer, pad, data);
/* not to send prerolled pkt again */
- player->video_stream_prerolled = TRUE;
+ player->video_stream_prerolled = true;
}
static void
-__mmplayer_video_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
+__mmplayer_video_stream_decoded_render_cb(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer data)
{
- mm_player_t* player = (mm_player_t*)data;
- GstCaps *caps = NULL;
- MMPlayerVideoStreamDataType *stream = NULL;
- MMVideoBuffer *video_buffer = NULL;
- GstMemory *dataBlock = NULL;
- GstMemory *metaBlock = NULL;
- GstMapInfo mapinfo = GST_MAP_INFO_INIT;
- GstStructure *structure = NULL;
- const gchar *string_format = NULL;
- unsigned int fourcc = 0;
+ mmplayer_t *player = (mmplayer_t *)data;
+ mmplayer_video_decoded_data_info_t *stream = NULL;
+ GstMemory *mem = NULL;
MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(player && player->video_stream_cb);
+ MMPLAYER_RETURN_IF_FAIL(player);
+ MMPLAYER_RETURN_IF_FAIL(player->video_decoded_cb);
if (player->video_stream_prerolled) {
- player->video_stream_prerolled = FALSE;
+ player->video_stream_prerolled = false;
LOGD("skip the prerolled pkt not to send it again");
return;
}
- caps = gst_pad_get_current_caps(pad);
- if (caps == NULL) {
- LOGE("Caps is NULL.");
- return;
- }
-
- /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
-
/* clear stream data structure */
- stream = (MMPlayerVideoStreamDataType *)g_malloc0(sizeof(MMPlayerVideoStreamDataType));
+ stream = __mmplayer_create_stream_from_pad(pad);
if (!stream) {
- LOGE("failed to alloc mem for video data");
+ LOGE("failed to alloc stream");
return;
}
- structure = gst_caps_get_structure(caps, 0);
- gst_structure_get_int(structure, "width", &(stream->width));
- gst_structure_get_int(structure, "height", &(stream->height));
- string_format = gst_structure_get_string(structure, "format");
- if (string_format)
- fourcc = _mmplayer_convert_fourcc_string_to_value(string_format);
- stream->format = util_get_pixtype(fourcc);
- gst_caps_unref(caps);
- caps = NULL;
-
__mmplayer_get_video_angle(player, NULL, &stream->orientation);
- /*
- LOGD("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
- GST_BUFFER_DATA(buffer), stream.width, stream.height, stream.format);
- */
-
- if (stream->width == 0 || stream->height == 0 || stream->format == MM_PIXEL_FORMAT_INVALID) {
- LOGE("Wrong condition!!");
- goto ERROR;
- }
-
/* set size and timestamp */
- dataBlock = gst_buffer_peek_memory(buffer, 0);
- stream->length_total = gst_memory_get_sizes(dataBlock, NULL, NULL);
+ 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 */
/* check zero-copy */
if (player->set_mode.video_zc &&
- player->set_mode.media_packet_video_stream &&
- gst_buffer_n_memory(buffer) > 1) {
- metaBlock = gst_buffer_peek_memory(buffer, 1);
- gst_memory_map(metaBlock, &mapinfo, GST_MAP_READ);
- video_buffer = (MMVideoBuffer *)mapinfo.data;
- }
-
- if (video_buffer) { /* hw codec */
- /* set tbm bo */
- if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
- int i = 0;
-
- /* copy pointer of tbm bo, stride, elevation */
- while (i < MM_VIDEO_BUFFER_PLANE_MAX && video_buffer->handle.bo[i]) {
- stream->bo[i] = tbm_bo_ref(video_buffer->handle.bo[i]);
- i++;
- }
- } else {
- LOGE("Not support video buffer format");
- goto ERROR;
- }
- memcpy(stream->stride, video_buffer->stride_width,
- sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
- memcpy(stream->elevation, video_buffer->stride_height,
- sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
-
- /* will be released, by calling _mm_player_video_stream_internal_buffer_unref() */
+ 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);
} else { /* sw codec */
- int i = 0;
- int j = 0;
- int k = 0;
- int ret = TBM_SURFACE_ERROR_NONE;
- int src_stride[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
- int src_offset[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
- int size = 0;
- unsigned char *src = NULL;
- unsigned char *dest = NULL;
- tbm_bo_handle thandle;
- tbm_surface_h surface;
- tbm_surface_info_s info;
- gboolean gst_ret;
-
- gst_ret = gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE);
- if (!gst_ret) {
- LOGE("fail to gst_memory_map");
- goto ERROR;
- }
-
-
- if (stream->format == MM_PIXEL_FORMAT_I420) {
- surface = tbm_surface_create(stream->width, stream->height, TBM_FORMAT_YUV420);
-
- ret = tbm_surface_get_info(surface, &info);
-
- if (ret != TBM_SURFACE_ERROR_NONE) {
- tbm_surface_destroy(surface);
- goto ERROR;
- }
- tbm_surface_destroy(surface);
-
- src_stride[0] = GST_ROUND_UP_4(stream->width);
- src_stride[1] = src_stride[2] = GST_ROUND_UP_4(stream->width>>1);
- src_offset[1] = src_stride[0] * GST_ROUND_UP_2(stream->height);
- src_offset[2] = src_offset[1] + (src_stride[1] * (GST_ROUND_UP_2(stream->height)>>1));
- stream->stride[0] = info.planes[0].stride;
- stream->elevation[0] = info.planes[0].size / info.planes[0].stride;
- stream->stride[1] = info.planes[1].stride;
- stream->elevation[1] = info.planes[1].size / info.planes[1].stride;
- stream->stride[2] = info.planes[2].stride;
- stream->elevation[2] = info.planes[2].size / info.planes[2].stride;
- size = info.planes[0].size + info.planes[1].size + info.planes[2].size;
- } else if (stream->format == MM_PIXEL_FORMAT_RGBA) {
- stream->stride[0] = stream->width * 4;
- stream->elevation[0] = stream->height;
- size = stream->stride[0] * stream->height;
- } else {
- LOGE("Not support format %d", stream->format);
- goto ERROR;
- }
-
- stream->bo[0] = __mmplayer_video_stream_get_bo(player, size);
- if (!stream->bo[0]) {
- LOGE("Fail to tbm_bo_alloc!!");
+ if (!__mmplayer_swcodec_set_stride_elevation(stream))
goto ERROR;
- }
-
- thandle = tbm_bo_map(stream->bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
- if (thandle.ptr && mapinfo.data) {
- if (stream->format == MM_PIXEL_FORMAT_I420) {
- for (i = 0; i < 3; i++) {
- src = mapinfo.data + src_offset[i];
- dest = thandle.ptr + info.planes[i].offset;
- if (i > 0) k = 1;
- for (j = 0; j < stream->height>>k; j++) {
- memcpy(dest, src, stream->width>>k);
- src += src_stride[i];
- dest += stream->stride[i];
- }
- }
- } else if (stream->format == MM_PIXEL_FORMAT_RGBA) {
- memcpy(thandle.ptr, mapinfo.data, size);
- } else {
- LOGE("Not support format %d", stream->format);
- goto ERROR;
- }
- } else {
- LOGE("data pointer is wrong. dest : %p, src : %p",
- thandle.ptr, mapinfo.data);
+ if (!__mmplayer_swcodec_set_bo(player, stream, mem))
goto ERROR;
- }
- tbm_bo_unmap(stream->bo[0]);
}
- if (player->video_stream_cb) { /* This has been already checked at the entry */
- if (!player->video_stream_cb(stream, player->video_stream_cb_user_param)) {
- LOGE("failed to send video stream data.");
- goto ERROR;
- }
+ if (!player->video_decoded_cb(stream, player->video_decoded_cb_user_param)) {
+ LOGE("failed to send video decoded data.");
+ goto ERROR;
}
- if (metaBlock)
- gst_memory_unmap(metaBlock, &mapinfo);
- else
- gst_memory_unmap(dataBlock, &mapinfo);
-
return;
ERROR:
LOGE("release video stream resource.");
- if (metaBlock) {
+ if (gst_is_tizen_memory(mem)) {
int i = 0;
for (i = 0 ; i < MM_VIDEO_BUFFER_PLANE_MAX ; i++) {
if (stream->bo[i])
tbm_bo_unref(stream->bo[i]);
}
- gst_memory_unmap(metaBlock, &mapinfo);
/* unref gst buffer */
if (stream->internal_buffer)
gst_buffer_unref(stream->internal_buffer);
- } else if (dataBlock) {
+ } else {
if (stream->bo[0])
_mmplayer_video_stream_release_bo(player, stream->bo[0]);
- gst_memory_unmap(dataBlock, &mapinfo);
}
-
- g_free(stream);
+ MMPLAYER_FREEIF(stream);
return;
}
+static void
+__mmplayer_gst_set_video360_property(mmplayer_t *player)
+{
+ mmplayer_gst_element_t *videobin = NULL;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->videobin);
+
+ videobin = player->pipeline->videobin;
+
+ /* Set spatial media metadata and/or user settings to the element.
+ * */
+ g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
+ "projection-type", player->video360_metadata.projection_type, NULL);
+
+ g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
+ "stereo-mode", player->video360_metadata.stereo_mode, NULL);
+
+ if (player->video360_metadata.full_pano_width_pixels &&
+ player->video360_metadata.full_pano_height_pixels &&
+ player->video360_metadata.cropped_area_image_width &&
+ player->video360_metadata.cropped_area_image_height) {
+ g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
+ "projection-bounds-top", player->video360_metadata.cropped_area_top,
+ "projection-bounds-bottom", player->video360_metadata.full_pano_height_pixels -
+ player->video360_metadata.cropped_area_top - player->video360_metadata.cropped_area_image_height,
+ "projection-bounds-left", player->video360_metadata.cropped_area_left,
+ "projection-bounds-right", player->video360_metadata.full_pano_width_pixels -
+ player->video360_metadata.cropped_area_left - player->video360_metadata.cropped_area_image_width,
+ NULL);
+ }
+
+ if (player->video360_horizontal_fov && player->video360_vertical_fov) {
+ g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
+ "horizontal-fov", player->video360_horizontal_fov,
+ "vertical-fov", player->video360_vertical_fov, NULL);
+ }
+
+ if (player->video360_zoom <= VIDEO360_MAX_ZOOM && player->video360_zoom > 1.0f) {
+ g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
+ "zoom", 1.0f / player->video360_zoom, NULL);
+ }
+
+ if (player->video360_yaw_radians <= M_PI &&
+ player->video360_yaw_radians >= -M_PI &&
+ player->video360_pitch_radians <= M_PI_2 &&
+ player->video360_pitch_radians >= -M_PI_2) {
+ g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
+ "pose-yaw", (int)(player->video360_yaw_radians * 180.0 / M_PI),
+ "pose-pitch", (int)(player->video360_pitch_radians * 180.0 / M_PI), NULL);
+ } else if (player->video360_metadata.init_view_heading || player->video360_metadata.init_view_pitch) {
+ g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
+ "pose-yaw", player->video360_metadata.init_view_heading,
+ "pose-pitch", player->video360_metadata.init_view_pitch, NULL);
+ }
+
+ g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
+ "passthrough", !player->is_video360_enabled, NULL);
+
+
+ MMPLAYER_FLEAVE();
+}
+
static int
-__mmplayer_gst_create_video_filters(mm_player_t* player, GList** bucket)
+__mmplayer_gst_create_video_filters(mmplayer_t *player, MMDisplaySurfaceType surface_type, GList **bucket)
{
- gchar* video_csc = "videoconvert"; /* default colorspace converter */
- GList* element_bucket = NULL;
+ gchar *video_csc = "videoconvert"; /* default colorspace converter */
+ GList *element_bucket = NULL;
+ MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_FENTER();
+ /* 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", element_bucket, player);
+ __mmplayer_gst_set_video360_property(player);
+ goto EXIT;
+ }
- if (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical)) {
- LOGD("do not need to add video filters.");
+ if (surface_type != MM_DISPLAY_SURFACE_OVERLAY || player->set_mode.video_zc) {
+ LOGD("skip creating the videoconv and rotator");
return MM_ERROR_NONE;
}
- /* in case of sw codec except 360 playback,
+ /* 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. */
- MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
- LOGD("using video converter: %s", video_csc);
-
- /* set video rotator */
- MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
+ LOGD("create video converter: %s", video_csc);
+ MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", element_bucket, player);
+EXIT:
*bucket = element_bucket;
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
return MM_ERROR_PLAYER_INTERNAL;
}
-/**
- * This function is to create video pipeline.
- *
- * @param player [in] handle of player
- * caps [in] src caps of decoder
- * surface_type [in] surface type for video rendering
- *
- * @return This function returns zero on success.
- * @remark
- * @see __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
- */
-/**
- * VIDEO PIPELINE
- * - video overlay surface(arm/x86) : tizenwlsink
- */
-static int
-__mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
+static gchar *
+__mmplayer_get_videosink_factory_name(mmplayer_t *player, MMDisplaySurfaceType surface_type)
{
- GstPad *pad = NULL;
- MMHandleType attrs;
- GList*element_bucket = NULL;
- MMPlayerGstElement* first_element = NULL;
- MMPlayerGstElement* videobin = NULL;
- gchar *videosink_element = NULL;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- /* alloc handles */
- videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
- if (!videobin)
- return MM_ERROR_PLAYER_NO_FREE_SPACE;
+ gchar *factory_name = NULL;
- player->pipeline->videobin = videobin;
-
- attrs = MMPLAYER_GET_ATTRS(player);
- if (!attrs) {
- LOGE("cannot get content attribute");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* create bin */
- videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
- videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
- if (!videobin[MMPLAYER_V_BIN].gst) {
- LOGE("failed to create videobin");
- goto ERROR;
- }
-
- int enable_video_decoded_cb = 0;
- mm_attrs_get_int_by_name(player->attrs, "enable_video_decoded_cb", &enable_video_decoded_cb);
-
- if (player->is_360_feature_enabled && player->is_content_spherical) {
- LOGD("video360 elem will be added.");
-
- MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_360, "video360",
- "video-360", TRUE, player);
-
- /* Set spatial media metadata and/or user settings to the element.
- * */
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "projection-type", player->video360_metadata.projection_type, NULL);
-
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "stereo-mode", player->video360_metadata.stereo_mode, NULL);
-
- if (player->video360_metadata.full_pano_width_pixels &&
- player->video360_metadata.full_pano_height_pixels &&
- player->video360_metadata.cropped_area_image_width &&
- player->video360_metadata.cropped_area_image_height) {
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "projection-bounds-top", player->video360_metadata.cropped_area_top,
- "projection-bounds-bottom", player->video360_metadata.full_pano_height_pixels -
- player->video360_metadata.cropped_area_top - player->video360_metadata.cropped_area_image_height,
- "projection-bounds-left", player->video360_metadata.cropped_area_left,
- "projection-bounds-right", player->video360_metadata.full_pano_width_pixels -
- player->video360_metadata.cropped_area_left - player->video360_metadata.cropped_area_image_width,
- NULL);
- }
-
- if (player->video360_horizontal_fov && player->video360_vertical_fov) {
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "horizontal-fov", player->video360_horizontal_fov,
- "vertical-fov", player->video360_vertical_fov, NULL);
- }
-
- if (player->video360_zoom <= VIDEO360_MAX_ZOOM && player->video360_zoom > 1.0f) {
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "zoom", 1.0f / player->video360_zoom, NULL);
- }
-
- if (player->video360_yaw_radians <= M_PI &&
- player->video360_yaw_radians >= -M_PI &&
- player->video360_pitch_radians <= M_PI_2 &&
- player->video360_pitch_radians >= -M_PI_2) {
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "pose-yaw", (int) (player->video360_yaw_radians * 180.0 / M_PI),
- "pose-pitch", (int) (player->video360_pitch_radians * 180.0 / M_PI), NULL);
- } else if (player->video360_metadata.init_view_heading || player->video360_metadata.init_view_pitch) {
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "pose-yaw", player->video360_metadata.init_view_heading,
- "pose-pitch", player->video360_metadata.init_view_pitch, NULL);
- }
-
- g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
- "passthrough", !player->is_video360_enabled, NULL);
- }
-
- /* set video sink */
switch (surface_type) {
case MM_DISPLAY_SURFACE_OVERLAY:
- if (__mmplayer_gst_create_video_filters(player, &element_bucket) != MM_ERROR_NONE)
- goto ERROR;
if (strlen(player->ini.videosink_element_overlay) > 0)
- videosink_element = player->ini.videosink_element_overlay;
- else
- goto ERROR;
- break;
- case MM_DISPLAY_SURFACE_NULL:
- if (strlen(player->ini.videosink_element_fake) > 0)
- videosink_element = player->ini.videosink_element_fake;
- else
- goto ERROR;
+ factory_name = player->ini.videosink_element_overlay;
break;
case MM_DISPLAY_SURFACE_REMOTE:
+ case MM_DISPLAY_SURFACE_NULL:
if (strlen(player->ini.videosink_element_fake) > 0)
- videosink_element = player->ini.videosink_element_fake;
- else
- goto ERROR;
+ factory_name = player->ini.videosink_element_fake;
break;
default:
LOGE("unidentified surface type");
- goto ERROR;
+ break;
}
- LOGD("surface_type %d, selected videosink name: %s", surface_type, videosink_element);
- MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, "videosink", TRUE, player);
+ LOGD("surface_type %d, videosink is %s", surface_type, factory_name);
+ return factory_name;
+}
- /* additional setting for sink plug-in */
- switch (surface_type) {
- case MM_DISPLAY_SURFACE_OVERLAY:
- {
+static int
+__mmplayer_gst_set_videosink_property(mmplayer_t *player, MMDisplaySurfaceType surface_type)
+{
+ gchar *factory_name = NULL;
+ mmplayer_gst_element_t *videobin = NULL;
+ MMHandleType attrs;
+ int gapless = 0;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
+
+ videobin = player->pipeline->videobin;
+ factory_name = GST_OBJECT_NAME(gst_element_get_factory(videobin[MMPLAYER_V_SINK].gst));
+
+ attrs = MMPLAYER_GET_ATTRS(player);
+ if (!attrs) {
+ LOGE("cannot get content attribute");
+ 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) {
- LOGD("selected videosink name: %s", videosink_element);
-
/* support shard memory with S/W codec on HawkP */
- if (strncmp(videosink_element, "tizenwlsink", strlen(videosink_element)) == 0) {
+ if (strncmp(factory_name, "tizenwlsink", strlen(factory_name)) == 0) {
g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
"use-tbm", use_tbm, NULL);
}
- } else {
- if (attrs) {
- int gapless = 0;
-
- mm_attrs_get_int_by_name(attrs, "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) {
- int enable = 0;
- mm_attrs_get_int_by_name(player->attrs, "enable_video_decoded_cb", &enable);
- if (enable)
- g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "signal-handoffs", TRUE, NULL);
-
- MMPLAYER_SIGNAL_CONNECT(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_SIGNAL_CONNECT(player,
- G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
- MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
- "preroll-handoff",
- G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
- (gpointer)player);
- }
- break;
+ } else {
+ g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
+ "sync", TRUE, "max-lateness", FAKE_SINK_MAX_LATENESS, NULL);
}
- case MM_DISPLAY_SURFACE_REMOTE:
- {
- if (player->set_mode.media_packet_video_stream) {
- LOGE("add data probe at videosink");
- g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
- "sync", TRUE, "signal-handoffs", TRUE, NULL);
-
- MMPLAYER_SIGNAL_CONNECT(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_SIGNAL_CONNECT(player,
- G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
- MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
- "preroll-handoff",
- G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
- (gpointer)player);
- if (attrs) {
- int gapless = 0;
- mm_attrs_get_int_by_name(attrs, "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);
- }
- }
- }
- break;
+ mm_attrs_get_int_by_name(attrs, "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);
}
- default:
- break;
+
+ 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,
+ 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,
+ G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
+ MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
+ "preroll-handoff",
+ G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
+ (gpointer)player);
}
if (_mmplayer_update_video_param(player, "update_all_param") != MM_ERROR_NONE)
- goto ERROR;
+ 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_SIGNAL_CONNECT(player, sink_pad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
- "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
+ __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
- LOGW("failed to get sink pad from videosink\n");
+ } else {
+ LOGE("failed to get sink pad from videosink");
+ }
+ }
+
+ return MM_ERROR_NONE;
+}
+
+/**
+ * VIDEO BIN
+ * - video overlay surface(arm/x86) : tizenwlsink
+ */
+static int
+__mmplayer_gst_create_video_sink_bin(mmplayer_t *player, GstCaps *caps, MMDisplaySurfaceType surface_type)
+{
+ GstPad *pad = NULL;
+ GList *element_bucket = NULL;
+ mmplayer_gst_element_t *first_element = NULL;
+ mmplayer_gst_element_t *videobin = NULL;
+ gchar *videosink_factory_name = NULL;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
+
+ /* alloc handles */
+ videobin = (mmplayer_gst_element_t *)g_try_malloc0(sizeof(mmplayer_gst_element_t) * MMPLAYER_V_NUM);
+ if (!videobin)
+ return MM_ERROR_PLAYER_NO_FREE_SPACE;
+
+ player->pipeline->videobin = videobin;
+
+ /* create bin */
+ videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
+ videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
+ if (!videobin[MMPLAYER_V_BIN].gst) {
+ LOGE("failed to create videobin");
+ goto ERROR;
+ }
+
+ if (__mmplayer_gst_create_video_filters(player, surface_type, &element_bucket) != MM_ERROR_NONE)
+ goto ERROR;
+
+ videosink_factory_name = __mmplayer_get_videosink_factory_name(player, surface_type);
+ 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) {
+ LOGE("failed to set video property");
+ goto ERROR;
}
/* store it as it's sink element */
/* adding created elements to bin */
if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket)) {
- LOGE("failed to add elements\n");
+ LOGE("failed to add elements");
goto ERROR;
}
/* Linking elements in the bucket by added order */
if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
- LOGE("failed to link elements\n");
+ LOGE("failed to link elements");
goto ERROR;
}
/* get first element's sinkpad for creating ghostpad */
- if (element_bucket)
- first_element = (MMPlayerGstElement *)element_bucket->data;
+ first_element = (mmplayer_gst_element_t *)element_bucket->data;
if (!first_element) {
- LOGE("failed to get first element from bucket\n");
+ LOGE("failed to get first element from bucket");
goto ERROR;
}
pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
if (!pad) {
- LOGE("failed to get pad from first element\n");
+ LOGE("failed to get pad from first element");
goto ERROR;
}
/* create ghostpad */
player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", pad);
- if (FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin)) {
- LOGE("failed to add ghostpad to videobin\n");
+ if (!gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin)) {
+ LOGE("failed to add ghostpad to videobin");
goto ERROR;
}
gst_object_unref(pad);
/* done. free allocated variables */
- if (element_bucket)
- g_list_free(element_bucket);
+ g_list_free(element_bucket);
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
ERROR:
- LOGE("ERROR : releasing videobin\n");
-
+ LOGE("ERROR : releasing videobin");
g_list_free(element_bucket);
if (pad)
if (videobin[MMPLAYER_V_BIN].gst)
gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
-
MMPLAYER_FREEIF(videobin);
-
player->pipeline->videobin = NULL;
return MM_ERROR_PLAYER_INTERNAL;
}
-static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player)
+static int
+__mmplayer_gst_create_plain_text_elements(mmplayer_t *player)
{
GList *element_bucket = NULL;
- MMPlayerGstElement *textbin = player->pipeline->textbin;
+ 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_SIGNAL_CONNECT(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",
G_CALLBACK(__mmplayer_update_subtitle),
(gpointer)player);
- g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
- g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
+ g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE,
+ "signal-handoffs", TRUE, "max-lateness", FAKE_SINK_MAX_LATENESS, NULL);
if (!player->play_subtitle) {
- LOGD("add textbin sink as sink element of whole pipeline.\n");
+ LOGD("add textbin sink as sink element of whole pipeline.");
__mmplayer_add_sink(player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
}
/* adding created elements to bin */
- LOGD("adding created elements to bin\n");
+ LOGD("adding created elements to bin");
if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket)) {
- LOGE("failed to add elements\n");
+ LOGE("failed to add elements");
goto ERROR;
}
GST_OBJECT_FLAG_UNSET(textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_FLAG_SINK);
/* linking elements in the bucket by added order. */
- LOGD("Linking elements in the bucket by added order.\n");
+ LOGD("Linking elements in the bucket by added order.");
if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
- LOGE("failed to link elements\n");
+ LOGE("failed to link elements");
goto ERROR;
}
gst_object_unref(pad);
if (!ghostpad) {
- LOGE("failed to create ghostpad of textbin\n");
+ LOGE("failed to create ghostpad of textbin");
goto ERROR;
}
if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad)) {
- LOGE("failed to add ghostpad to textbin\n");
+ LOGE("failed to add ghostpad to textbin");
gst_object_unref(ghostpad);
goto ERROR;
}
return MM_ERROR_PLAYER_INTERNAL;
}
-static int __mmplayer_gst_create_text_sink_bin(mm_player_t* player)
+static int
+__mmplayer_gst_create_text_sink_bin(mmplayer_t *player)
{
- MMPlayerGstElement *textbin = NULL;
+ mmplayer_gst_element_t *textbin = NULL;
GList *element_bucket = NULL;
int surface_type = 0;
gint i = 0;
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
/* alloc handles */
- textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
+ textbin = (mmplayer_gst_element_t *)g_try_malloc0(sizeof(mmplayer_gst_element_t) * MMPLAYER_T_NUM);
if (!textbin) {
- LOGE("failed to allocate memory for textbin\n");
+ LOGE("failed to allocate memory for textbin");
return MM_ERROR_PLAYER_NO_FREE_SPACE;
}
textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
if (!textbin[MMPLAYER_T_BIN].gst) {
- LOGE("failed to create textbin\n");
+ LOGE("failed to create textbin");
goto ERROR;
}
case MM_DISPLAY_SURFACE_NULL:
case MM_DISPLAY_SURFACE_REMOTE:
if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE) {
- LOGE("failed to make plain text elements\n");
+ LOGE("failed to make plain text elements");
goto ERROR;
}
break;
ERROR:
- LOGD("ERROR : releasing textbin\n");
+ LOGD("ERROR : releasing textbin");
g_list_free(element_bucket);
for (i = 1; i < MMPLAYER_T_NUM; i++) {
/* NOTE : skip bin */
if (textbin[i].gst) {
- GstObject* parent = NULL;
+ GstObject *parent = NULL;
parent = gst_element_get_parent(textbin[i].gst);
if (!parent) {
return MM_ERROR_PLAYER_INTERNAL;
}
-
static int
-__mmplayer_gst_create_text_pipeline(mm_player_t* player)
+__mmplayer_gst_create_text_pipeline(mmplayer_t *player)
{
- MMPlayerGstElement* mainbin = NULL;
- MMPlayerGstElement* textbin = NULL;
+ mmplayer_gst_element_t *mainbin = NULL;
+ mmplayer_gst_element_t *textbin = NULL;
MMHandleType attrs = 0;
GstElement *subsrc = NULL;
GstElement *subparse = NULL;
attrs = MMPLAYER_GET_ATTRS(player);
if (!attrs) {
- LOGE("cannot get content attribute\n");
+ LOGE("cannot get content attribute");
return MM_ERROR_PLAYER_INTERNAL;
}
mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
if (!subtitle_uri || strlen(subtitle_uri) < 1) {
- LOGE("subtitle uri is not proper filepath.\n");
+ LOGE("subtitle uri is not proper filepath.");
return MM_ERROR_PLAYER_INVALID_URI;
}
return MM_ERROR_PLAYER_INVALID_URI;
}
- SECURE_LOGD("subtitle file path is [%s].\n", subtitle_uri);
+ SECURE_LOGD("subtitle file path is [%s].", subtitle_uri);
MMPLAYER_SUBTITLE_INFO_LOCK(player);
player->subtitle_language_list = NULL;
/* create the subtitle source */
subsrc = gst_element_factory_make("filesrc", "subtitle_source");
if (!subsrc) {
- LOGE("failed to create filesrc element\n");
+ LOGE("failed to create filesrc element");
goto ERROR;
}
g_object_set(G_OBJECT(subsrc), "location", subtitle_uri, NULL);
mainbin[MMPLAYER_M_SUBSRC].gst = subsrc;
if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc)) {
- LOGW("failed to add queue\n");
+ LOGW("failed to add queue");
gst_object_unref(mainbin[MMPLAYER_M_SUBSRC].gst);
mainbin[MMPLAYER_M_SUBSRC].gst = NULL;
mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_NUM;
/* subparse */
subparse = gst_element_factory_make("subparse", "subtitle_parser");
if (!subparse) {
- LOGE("failed to create subparse element\n");
+ LOGE("failed to create subparse element");
goto ERROR;
}
charset = util_get_charset(subtitle_uri);
if (charset) {
- LOGD("detected charset is %s\n", charset);
+ LOGD("detected charset is %s", charset);
g_object_set(G_OBJECT(subparse), "subtitle-encoding", charset, NULL);
}
mainbin[MMPLAYER_M_SUBPARSE].gst = subparse;
if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse)) {
- LOGW("failed to add subparse\n");
+ LOGW("failed to add subparse");
gst_object_unref(mainbin[MMPLAYER_M_SUBPARSE].gst);
mainbin[MMPLAYER_M_SUBPARSE].gst = NULL;
mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_NUM;
}
if (!gst_element_link_pads(subsrc, "src", subparse, "sink")) {
- LOGW("failed to link subsrc and subparse\n");
+ LOGW("failed to link subsrc and subparse");
goto ERROR;
}
player->play_subtitle = TRUE;
player->adjust_subtitle_pos = 0;
- LOGD("play subtitle using subtitle file\n");
+ LOGD("play subtitle using subtitle file");
if (player->pipeline->textbin == NULL) {
if (MM_ERROR_NONE != __mmplayer_gst_create_text_sink_bin(player)) {
- LOGE("failed to create text sink bin. continuing without text\n");
+ LOGE("failed to create text sink bin. continuing without text");
goto ERROR;
}
textbin = player->pipeline->textbin;
if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(textbin[MMPLAYER_T_BIN].gst))) {
- LOGW("failed to add textbin\n");
+ LOGW("failed to add textbin");
/* release signal */
__mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
player->textsink_linked = 1;
player->external_text_idx = 0;
- LOGI("player->textsink_linked set to 1\n");
+ LOGI("textsink is linked");
} else {
textbin = player->pipeline->textbin;
LOGD("text bin has been created. reuse it.");
}
if (!gst_element_link_pads(subparse, "src", textbin[MMPLAYER_T_BIN].gst, "text_sink")) {
- LOGW("failed to link subparse and textbin\n");
+ LOGW("failed to link subparse and textbin");
goto ERROR;
}
}
gboolean
-__mmplayer_update_subtitle(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
+__mmplayer_update_subtitle(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer data)
{
- mm_player_t* player = (mm_player_t*) data;
+ mmplayer_t *player = (mmplayer_t *)data;
MMMessageParamType msg = {0, };
GstClockTime duration = 0;
gpointer text = NULL;
gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
text = mapinfo.data;
text_size = mapinfo.size;
- duration = GST_BUFFER_DURATION(buffer);
if (player->set_mode.subtitle_off) {
- LOGD("subtitle is OFF.\n");
+ LOGD("subtitle is OFF.");
return TRUE;
}
if (!text || (text_size == 0)) {
- LOGD("There is no subtitle to be displayed.\n");
+ LOGD("There is no subtitle to be displayed.");
return TRUE;
}
- msg.data = (void *) text;
+ msg.data = (void *)text;
+
+ duration = GST_BUFFER_DURATION(buffer);
+
+ if (!GST_CLOCK_TIME_IS_VALID(duration)) {
+ if (player->duration > GST_BUFFER_PTS(buffer))
+ duration = player->duration - GST_BUFFER_PTS(buffer);
+ else
+ duration = 0;
+ LOGI("subtitle duration is invalid, subtitle duration change "
+ "GST_CLOCK_TIME_NONE -> %" GST_TIME_FORMAT, GST_TIME_ARGS(duration));
+ }
msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
- LOGD("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data);
+ LOGD("update subtitle : [%ld msec] %s", msg.subtitle.duration, (char *)msg.data);
MMPLAYER_POST_MSG(player, MM_MESSAGE_UPDATE_SUBTITLE, &msg);
gst_buffer_unmap(buffer, &mapinfo);
static GstPadProbeReturn
__mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
{
- mm_player_t *player = (mm_player_t *) u_data;
+ mmplayer_t *player = (mmplayer_t *)u_data;
GstClockTime cur_timestamp = 0;
gint64 adjusted_timestamp = 0;
GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
if (player->set_mode.subtitle_off) {
- LOGD("subtitle is OFF.\n");
+ LOGD("subtitle is OFF.");
return TRUE;
}
}
cur_timestamp = GST_BUFFER_TIMESTAMP(buffer);
- adjusted_timestamp = (gint64) cur_timestamp +((gint64) player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
+ adjusted_timestamp = (gint64)cur_timestamp + ((gint64)player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
if (adjusted_timestamp < 0) {
LOGD("adjusted_timestamp under zero");
return GST_PAD_PROBE_OK;
}
-static int __gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
+
+static int
+__mmplayer_gst_adjust_subtitle_position(mmplayer_t *player, int position)
{
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player->play_subtitle, MM_ERROR_NOT_SUPPORT_API);
if (position == 0) {
- LOGD("nothing to do\n");
+ LOGD("nothing to do");
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
}
- switch (format) {
- case MM_PLAYER_POS_FORMAT_TIME:
- {
- /* check current postion */
- player->adjust_subtitle_pos = position;
-
- LOGD("save adjust_subtitle_pos in player") ;
- }
- break;
+ /* check current postion */
+ player->adjust_subtitle_pos = position;
- default:
- {
- LOGW("invalid format.\n");
- MMPLAYER_FLEAVE();
- return MM_ERROR_INVALID_ARGUMENT;
- }
- }
+ LOGD("save adjust_subtitle_pos in player");
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
}
-static void
-__gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data)
-{
- GstElement *appsrc = element;
- MMPlayerInputBuffer *buf = (MMPlayerInputBuffer *)user_data;
- GstBuffer *buffer = NULL;
- GstFlowReturn ret = GST_FLOW_OK;
- gint len = size;
-
- MMPLAYER_RETURN_IF_FAIL(element);
- MMPLAYER_RETURN_IF_FAIL(buf);
-
- buffer = gst_buffer_new();
-
- if (buf->offset >= buf->len) {
- LOGD("call eos appsrc\n");
- g_signal_emit_by_name(appsrc, "end-of-stream", &ret);
- return;
- }
-
- if (buf->len - buf->offset < size)
- len = buf->len - buf->offset;
-
- gst_buffer_insert_memory(buffer, -1, gst_memory_new_wrapped(0, (guint8 *)(buf->buf + buf->offset), len, 0, len, NULL, NULL));
- GST_BUFFER_OFFSET(buffer) = (guint64)buf->offset;
- GST_BUFFER_OFFSET_END(buffer) = (guint64)(buf->offset + len);
-
- //LOGD("feed buffer %p, offset %u-%u length %u", buffer, buf->offset, (buf->offset+len), len);
- g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
-
- buf->offset += len;
-}
-
-static gboolean
-__gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data)
-{
- MMPlayerInputBuffer *buf = (MMPlayerInputBuffer *)user_data;
-
- MMPLAYER_RETURN_VAL_IF_FAIL(buf, FALSE);
-
- buf->offset = (int)size;
-
- return TRUE;
-}
-
-static gboolean
-__mmplayer_gst_create_decoder(mm_player_t *player,
- MMPlayerTrackType track,
- GstPad* srcpad,
- enum MainElementID elemId,
- const gchar* name)
-{
- gboolean ret = TRUE;
- GstPad *sinkpad = NULL;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player &&
- player->pipeline &&
- player->pipeline->mainbin, FALSE);
- MMPLAYER_RETURN_VAL_IF_FAIL((track == MM_PLAYER_TRACK_TYPE_AUDIO || track == MM_PLAYER_TRACK_TYPE_VIDEO), FALSE);
- MMPLAYER_RETURN_VAL_IF_FAIL(srcpad, FALSE);
- MMPLAYER_RETURN_VAL_IF_FAIL((player->pipeline->mainbin[elemId].gst == NULL), FALSE);
-
- GstElement *decodebin = NULL;
- GstCaps *dec_caps = NULL;
-
- /* create decodebin */
- decodebin = gst_element_factory_make("decodebin", name);
-
- if (!decodebin) {
- LOGE("error : fail to create decodebin for %d decoder\n", track);
- ret = FALSE;
- goto ERROR;
- }
-
- /* raw pad handling signal */
- MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
- G_CALLBACK(__mmplayer_gst_decode_pad_added), 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_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
- G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
-
- /* This signal is emitted when a element is added to the bin.*/
- MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
- G_CALLBACK(__mmplayer_gst_element_added), player);
-
- if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
- LOGE("failed to add new decodebin\n");
- ret = FALSE;
- goto ERROR;
- }
-
- dec_caps = gst_pad_query_caps(srcpad, NULL);
- if (dec_caps) {
- //LOGD("got pad %s:%s , dec_caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME(srcpad), dec_caps);
- g_object_set(G_OBJECT(decodebin), "sink-caps", dec_caps, NULL);
- gst_caps_unref(dec_caps);
- }
-
- player->pipeline->mainbin[elemId].id = elemId;
- player->pipeline->mainbin[elemId].gst = decodebin;
-
- sinkpad = gst_element_get_static_pad(decodebin, "sink");
-
- if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
- LOGW("failed to link [%s:%s] to decoder\n", GST_DEBUG_PAD_NAME(srcpad));
- gst_object_unref(GST_OBJECT(decodebin));
- }
-
- if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin))
- LOGE("failed to sync second level decodebin state with parent\n");
-
- LOGD("Total num of %d tracks = %d \n", track, player->selector[track].total_track_num);
-
-ERROR:
- if (sinkpad) {
- gst_object_unref(GST_OBJECT(sinkpad));
- sinkpad = NULL;
- }
- MMPLAYER_FLEAVE();
-
- return ret;
-}
-
/**
* This function is to create audio or video pipeline for playing.
*
* @see
*/
static int
-__mmplayer_gst_create_pipeline(mm_player_t* player)
+__mmplayer_gst_create_pipeline(mmplayer_t *player)
{
- GstBus *bus = NULL;
- MMPlayerGstElement *mainbin = NULL;
+ int ret = MM_ERROR_NONE;
+ mmplayer_gst_element_t *mainbin = NULL;
MMHandleType attrs = 0;
- GstElement* element = NULL;
- GstElement* elem_src_audio = NULL;
- GstElement* elem_src_subtitle = NULL;
- GstElement* es_video_queue = NULL;
- GstElement* es_audio_queue = NULL;
- GstElement* es_subtitle_queue = NULL;
- GList* element_bucket = NULL;
- gboolean need_state_holder = TRUE;
- gint i = 0;
-#ifdef SW_CODEC_ONLY
- int surface_type = 0;
-#endif
- MMPLAYER_FENTER();
+ MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
/* get profile attribute */
attrs = MMPLAYER_GET_ATTRS(player);
if (!attrs) {
- LOGE("cannot get content attribute\n");
+ LOGE("failed to get content attribute");
goto INIT_ERROR;
}
/* create pipeline handles */
if (player->pipeline) {
- LOGW("pipeline should be released before create new one\n");
+ LOGE("pipeline should be released before create new one");
goto INIT_ERROR;
}
- player->video360_metadata.is_spherical = -1;
- player->is_openal_plugin_used = FALSE;
-
- player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0(sizeof(MMPlayerGstPipelineInfo));
+ player->pipeline = (mmplayer_pipeline_info_t *)g_malloc0(sizeof(mmplayer_pipeline_info_t));
if (player->pipeline == NULL)
goto INIT_ERROR;
- memset(player->pipeline, 0, sizeof(MMPlayerGstPipelineInfo)); /* g_malloc0 did this job already */
-
/* create mainbin */
- mainbin = (MMPlayerGstElement*) g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
+ mainbin = (mmplayer_gst_element_t *)g_try_malloc0(sizeof(mmplayer_gst_element_t) * MMPLAYER_M_NUM);
if (mainbin == NULL)
goto INIT_ERROR;
- memset(mainbin, 0, sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM); /* g_malloc0 did this job already */
-
/* create pipeline */
mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
if (!mainbin[MMPLAYER_M_PIPE].gst) {
- LOGE("failed to create pipeline\n");
+ LOGE("failed to create pipeline");
+ g_free(mainbin);
goto INIT_ERROR;
}
- player->demux_pad_index = 0;
- player->subtitle_language_list = NULL;
- player->is_subtitle_force_drop = FALSE;
- player->last_multiwin_status = FALSE;
+ player->pipeline->mainbin = mainbin;
- _mmplayer_track_initialize(player);
- __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
+ /* 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);
- /* create source element */
- switch (player->profile.uri_type) {
- /* rtsp streamming */
- case MM_PLAYER_URI_TYPE_URL_RTSP:
- {
- gchar *user_agent;
+ if (ret != MM_ERROR_NONE) {
+ LOGE("failed to create some elements");
+ goto INIT_ERROR;
+ }
- element = gst_element_factory_make("rtspsrc", "rtsp source");
+ /* Note : check whether subtitle atrribute 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");
- if (!element) {
- LOGE("failed to create streaming source element\n");
- break;
- }
+ /* add bus watch */
+ ret = __mmplayer_gst_add_bus_watch(player);
+ if (ret != MM_ERROR_NONE) {
+ LOGE("failed to add bus watch");
+ goto INIT_ERROR;
+ }
- /* make it zero */
- user_agent = NULL;
-
- /* get attribute */
- mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
-
- SECURE_LOGD("user_agent : %s\n", user_agent);
-
- /* setting property to streaming source */
- g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
- if (user_agent)
- g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
-
- MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
- G_CALLBACK(__mmplayer_gst_rtp_dynamic_pad), player);
- MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
- G_CALLBACK(__mmplayer_gst_rtp_no_more_pads), player);
- }
- break;
-
- /* http streaming*/
- case MM_PLAYER_URI_TYPE_URL_HTTP:
- {
- gchar *user_agent, *cookies, **cookie_list;
- gint http_timeout = DEFAULT_HTTP_TIMEOUT;
- user_agent = cookies = NULL;
- cookie_list = NULL;
- gint mode = MM_PLAYER_PD_MODE_NONE;
-
- mm_attrs_get_int_by_name(attrs, "pd_mode", &mode);
-
- player->pd_mode = mode;
-
- LOGD("http playback, PD mode : %d\n", player->pd_mode);
-
- if (!MMPLAYER_IS_HTTP_PD(player)) {
- element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
- if (!element) {
- LOGE("failed to create http streaming source element[%s].\n", player->ini.httpsrc_element);
- break;
- }
- LOGD("using http streamming source [%s].\n", player->ini.httpsrc_element);
-
- /* get attribute */
- mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
- mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
-
- if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT) {
- LOGD("get timeout from ini\n");
- http_timeout = player->ini.http_timeout;
- }
-
- /* get attribute */
- SECURE_LOGD("location : %s\n", player->profile.uri);
- SECURE_LOGD("cookies : %s\n", cookies);
- SECURE_LOGD("user_agent : %s\n", user_agent);
- LOGD("timeout : %d\n", http_timeout);
-
- /* setting property to streaming source */
- g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
- g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
- g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
-
- /* parsing cookies */
- if ((cookie_list = util_get_cookie_list((const char*)cookies))) {
- g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
- g_strfreev(cookie_list);
- }
- if (user_agent)
- g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
-
- if (MMPLAYER_URL_HAS_DASH_SUFFIX(player))
- LOGW("it's dash. and it's still experimental feature.");
- } else {
- // progressive download
- gchar* location = NULL;
-
- if (player->pd_mode == MM_PLAYER_PD_MODE_URI) {
- gchar *path = NULL;
-
- mm_attrs_get_string_by_name(attrs, "pd_location", &path);
-
- MMPLAYER_FREEIF(player->pd_file_save_path);
-
- LOGD("PD Location : %s\n", path);
-
- if (path) {
- if (!util_get_storage_info(path, &player->storage_info[MMPLAYER_PATH_VOD])) {
- LOGE("failed to get storage info");
- break;
- }
- player->pd_file_save_path = g_strdup(path);
- } else {
- LOGE("can't find pd location so, it should be set \n");
- break;
- }
- }
-
- element = gst_element_factory_make("pdpushsrc", "PD pushsrc");
- if (!element) {
- LOGE("failed to create PD push source element[%s].\n", "pdpushsrc");
- break;
- }
-
- if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
- g_object_set(G_OBJECT(element), "location", player->pd_file_save_path, NULL);
- else
- g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
- g_object_get(element, "location", &location, NULL);
- LOGD("PD_LOCATION [%s].\n", location);
- if (location)
- g_free(location);
- }
- }
- break;
-
- /* file source */
- case MM_PLAYER_URI_TYPE_FILE:
- {
- LOGD("using filesrc for 'file://' handler.\n");
- if (!util_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
- LOGE("failed to get storage info");
- break;
- }
-
- element = gst_element_factory_make("filesrc", "source");
- if (!element) {
- LOGE("failed to create filesrc\n");
- break;
- }
-
- g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL); /* uri+7 -> remove "file:// */
- }
- break;
-
- case MM_PLAYER_URI_TYPE_SS:
- {
- gint http_timeout = DEFAULT_HTTP_TIMEOUT;
- element = gst_element_factory_make("souphttpsrc", "http streaming source");
- if (!element) {
- LOGE("failed to create http streaming source element[%s]", player->ini.httpsrc_element);
- break;
- }
-
- if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT) {
- LOGD("get timeout from ini\n");
- http_timeout = player->ini.http_timeout;
- }
-
- /* setting property to streaming source */
- g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
- g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
- }
- break;
- case MM_PLAYER_URI_TYPE_MS_BUFF:
- {
- LOGD("MS buff src is selected\n");
-
- if (player->v_stream_caps) {
- element = gst_element_factory_make("appsrc", "video_appsrc");
- if (!element) {
- LOGF("failed to create video app source element[appsrc].\n");
- break;
- }
-
- if (player->a_stream_caps) {
- elem_src_audio = gst_element_factory_make("appsrc", "audio_appsrc");
- if (!elem_src_audio) {
- LOGF("failed to create audio app source element[appsrc].\n");
- break;
- }
- }
- } else if (player->a_stream_caps) {
- /* no video, only audio pipeline*/
- element = gst_element_factory_make("appsrc", "audio_appsrc");
- if (!element) {
- LOGF("failed to create audio app source element[appsrc].\n");
- break;
- }
- }
-
- if (player->s_stream_caps) {
- elem_src_subtitle = gst_element_factory_make("appsrc", "subtitle_appsrc");
- if (!elem_src_subtitle) {
- LOGF("failed to create subtitle app source element[appsrc].\n");
- break;
- }
- }
-
- LOGD("setting app sources properties.\n");
- LOGD("location : %s\n", player->profile.uri);
-
- if (player->v_stream_caps && element) {
- g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
- "blocksize", (guint)1048576, /* size of many video frames are larger than default blocksize as 4096 */
- "caps", player->v_stream_caps, NULL);
-
- if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
- g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
- if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
- g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
-
- /*Fix Seek External Demuxer: set audio and video appsrc as seekable */
- gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
- MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
- G_CALLBACK(__gst_seek_video_data), player);
-
- if (player->a_stream_caps && elem_src_audio) {
- g_object_set(G_OBJECT(elem_src_audio), "format", GST_FORMAT_TIME,
- "caps", player->a_stream_caps, NULL);
-
- if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
- g_object_set(G_OBJECT(elem_src_audio), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
- if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
- g_object_set(G_OBJECT(elem_src_audio), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
-
- /*Fix Seek External Demuxer: set audio and video appsrc as seekable */
- gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_audio), GST_APP_STREAM_TYPE_SEEKABLE);
- MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
- G_CALLBACK(__gst_seek_audio_data), player);
- }
- } else if (player->a_stream_caps && element) {
- g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
- "caps", player->a_stream_caps, NULL);
-
- if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
- g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
- if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
- g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
-
- /*Fix Seek External Demuxer: set audio and video appsrc as seekable */
- gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
- MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
- G_CALLBACK(__gst_seek_audio_data), player);
- }
-
- if (player->s_stream_caps && elem_src_subtitle) {
- g_object_set(G_OBJECT(elem_src_subtitle), "format", GST_FORMAT_TIME,
- "caps", player->s_stream_caps, NULL);
-
- if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
- g_object_set(G_OBJECT(elem_src_subtitle), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
- if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
- g_object_set(G_OBJECT(elem_src_subtitle), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
-
- gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_subtitle), GST_APP_STREAM_TYPE_SEEKABLE);
-
- MMPLAYER_SIGNAL_CONNECT(player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
- G_CALLBACK(__gst_seek_subtitle_data), player);
- }
-
- if (player->v_stream_caps && element) {
- MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
- G_CALLBACK(__gst_appsrc_feed_video_data), player);
- MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
- G_CALLBACK(__gst_appsrc_enough_video_data), player);
-
- if (player->a_stream_caps && elem_src_audio) {
- MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
- G_CALLBACK(__gst_appsrc_feed_audio_data), player);
- MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
- G_CALLBACK(__gst_appsrc_enough_audio_data), player);
- }
- } else if (player->a_stream_caps && element) {
- MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
- G_CALLBACK(__gst_appsrc_feed_audio_data), player);
- MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
- G_CALLBACK(__gst_appsrc_enough_audio_data), player);
- }
-
- if (player->s_stream_caps && elem_src_subtitle)
- MMPLAYER_SIGNAL_CONNECT(player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
- G_CALLBACK(__gst_appsrc_feed_subtitle_data), player);
-
- need_state_holder = FALSE;
-
- mm_attrs_set_int_by_name(attrs, "profile_prepare_async", TRUE);
- if (mmf_attrs_commit(attrs)) /* return -1 if error */
- LOGE("failed to commit\n");
- }
- break;
- /* appsrc */
- case MM_PLAYER_URI_TYPE_MEM:
- {
- guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
-
- LOGD("mem src is selected\n");
-
- element = gst_element_factory_make("appsrc", "mem-source");
- if (!element) {
- LOGE("failed to create appsrc element\n");
- break;
- }
-
- g_object_set(element, "stream-type", stream_type, NULL);
- g_object_set(element, "size", player->profile.input_mem.len, NULL);
- g_object_set(element, "blocksize", (guint64)20480, NULL);
-
- MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
- G_CALLBACK(__gst_appsrc_seek_data_mem), &player->profile.input_mem);
- MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
- G_CALLBACK(__gst_appsrc_feed_data_mem), &player->profile.input_mem);
- }
- break;
- case MM_PLAYER_URI_TYPE_URL:
- break;
-
- case MM_PLAYER_URI_TYPE_TEMP:
- break;
-
- case MM_PLAYER_URI_TYPE_NONE:
- default:
- break;
- }
-
- /* check source element is OK */
- if (!element) {
- LOGE("no source element was created.\n");
- goto INIT_ERROR;
- }
-
- /* take source element */
- mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
- mainbin[MMPLAYER_M_SRC].gst = element;
- element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
-
- if ((MMPLAYER_IS_STREAMING(player)) && (player->streamer == NULL)) {
- player->streamer = __mm_player_streaming_create();
- __mm_player_streaming_initialize(player->streamer);
- }
-
- if (MMPLAYER_IS_HTTP_PD(player)) {
- gint pre_buffering_time = player->streamer->buffering_req.prebuffer_time;
-
- LOGD("Picked queue2 element(pre buffer : %d ms)....\n", pre_buffering_time);
- element = gst_element_factory_make("queue2", "queue2");
- if (!element) {
- LOGE("failed to create http streaming buffer element\n");
- goto INIT_ERROR;
- }
-
- /* take it */
- mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
- mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
- element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_MUXED_S_BUFFER]);
-
- pre_buffering_time = (pre_buffering_time > 0) ? (pre_buffering_time) : (player->ini.http_buffering_time);
-
- player->streamer->is_pd_mode = TRUE;
-
- __mm_player_streaming_set_queue2(player->streamer,
- element,
- TRUE,
- player->ini.http_max_size_bytes, // + PLAYER_PD_EXT_MAX_SIZE_BYTE,
- pre_buffering_time,
- 1.0,
- player->ini.http_buffering_limit,
- MUXED_BUFFER_TYPE_MEM_QUEUE,
- NULL,
- 0);
- }
- if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
- if (player->v_stream_caps) {
- es_video_queue = gst_element_factory_make("queue2", "video_queue");
- if (!es_video_queue) {
- LOGE("create es_video_queue for es player failed\n");
- goto INIT_ERROR;
- }
- g_object_set(G_OBJECT(es_video_queue), "max-size-buffers", 2, NULL);
- mainbin[MMPLAYER_M_V_BUFFER].id = MMPLAYER_M_V_BUFFER;
- mainbin[MMPLAYER_M_V_BUFFER].gst = es_video_queue;
- element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_V_BUFFER]);
-
- /* Adding audio appsrc to bucket */
- if (player->a_stream_caps && elem_src_audio) {
- mainbin[MMPLAYER_M_2ND_SRC].id = MMPLAYER_M_2ND_SRC;
- mainbin[MMPLAYER_M_2ND_SRC].gst = elem_src_audio;
- element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_2ND_SRC]);
-
- es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
- if (!es_audio_queue) {
- LOGE("create es_audio_queue for es player failed\n");
- goto INIT_ERROR;
- }
- g_object_set(G_OBJECT(es_audio_queue), "max-size-buffers", 2, NULL);
-
- mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
- mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
- element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
- }
- } else if (player->a_stream_caps) {
- /* Only audio stream, no video */
- es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
- if (!es_audio_queue) {
- LOGE("create es_audio_queue for es player failed\n");
- goto INIT_ERROR;
- }
- mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
- mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
- element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
- }
-
- if (player->s_stream_caps && elem_src_subtitle) {
- mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
- mainbin[MMPLAYER_M_SUBSRC].gst = elem_src_subtitle;
- element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SUBSRC]);
-
- es_subtitle_queue = gst_element_factory_make("queue2", "subtitle_queue");
- if (!es_subtitle_queue) {
- LOGE("create es_subtitle_queue for es player failed\n");
- goto INIT_ERROR;
- }
- mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_V_BUFFER;
- mainbin[MMPLAYER_M_S_BUFFER].gst = es_subtitle_queue;
- element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_S_BUFFER]);
- }
- }
-
- /* create autoplugging element if src element is not a rtsp src */
- if ((player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_RTSP) &&
- (player->profile.uri_type != MM_PLAYER_URI_TYPE_MS_BUFF)) {
- element = NULL;
- enum MainElementID elemId = MMPLAYER_M_NUM;
-
- if (((MMPLAYER_IS_HTTP_PD(player)) ||
- (!MMPLAYER_IS_HTTP_STREAMING(player)))) {
- elemId = MMPLAYER_M_AUTOPLUG;
- element = __mmplayer_create_decodebin(player);
- if (element) {
- /* default size of mq in decodebin is 2M
- * but it can cause blocking issue during seeking depends on content. */
- g_object_set(G_OBJECT(element), "max-size-bytes", (5*1024*1024), NULL);
- }
- need_state_holder = FALSE;
- } else {
- elemId = MMPLAYER_M_TYPEFIND;
- element = gst_element_factory_make("typefind", "typefinder");
- MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
- G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player);
- }
-
- /* check autoplug element is OK */
- if (!element) {
- LOGE("can not create element(%d)\n", elemId);
- goto INIT_ERROR;
- }
-
- mainbin[elemId].id = elemId;
- mainbin[elemId].gst = element;
-
- element_bucket = g_list_append(element_bucket, &mainbin[elemId]);
- }
-
- /* add elements to pipeline */
- if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket)) {
- LOGE("Failed to add elements to pipeline\n");
- goto INIT_ERROR;
- }
-
-
- /* linking elements in the bucket by added order. */
- if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
- LOGE("Failed to link some elements\n");
- goto INIT_ERROR;
- }
-
-
- /* create fakesink element for keeping the pipeline state PAUSED. if needed */
- if (need_state_holder) {
- /* create */
- mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
- mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make("fakesink", "state-holder");
-
- if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst) {
- LOGE("fakesink element could not be created\n");
- goto INIT_ERROR;
- }
- GST_OBJECT_FLAG_UNSET(mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
-
- /* take ownership of fakesink. we are reusing it */
- gst_object_ref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
-
- /* add */
- if (FALSE == gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),
- mainbin[MMPLAYER_M_SRC_FAKESINK].gst)) {
- LOGE("failed to add fakesink to bin\n");
- goto INIT_ERROR;
- }
- }
-
- /* now we have completed mainbin. take it */
- player->pipeline->mainbin = mainbin;
-
- if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
- GstPad *srcpad = NULL;
-
- if (mainbin[MMPLAYER_M_V_BUFFER].gst) {
- srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_V_BUFFER].gst, "src");
- if (srcpad) {
- __mmplayer_gst_create_decoder(player,
- MM_PLAYER_TRACK_TYPE_VIDEO,
- srcpad,
- MMPLAYER_M_AUTOPLUG_V_DEC,
- "video_decodebin");
-
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
- }
- }
-
- if ((player->a_stream_caps) && (mainbin[MMPLAYER_M_A_BUFFER].gst)) {
- srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_A_BUFFER].gst, "src");
- if (srcpad) {
- __mmplayer_gst_create_decoder(player,
- MM_PLAYER_TRACK_TYPE_AUDIO,
- srcpad,
- MMPLAYER_M_AUTOPLUG_A_DEC,
- "audio_decodebin");
-
- gst_object_unref(GST_OBJECT(srcpad));
- srcpad = NULL;
- } // else error
- } // else error
-
- if (mainbin[MMPLAYER_M_S_BUFFER].gst)
- __mmplayer_try_to_plug_decodebin(player, gst_element_get_static_pad(mainbin[MMPLAYER_M_S_BUFFER].gst, "src"), player->s_stream_caps);
- }
-
- /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
- if (__mmplayer_check_subtitle(player)) {
- if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player))
- LOGE("fail to create text pipeline");
- }
-
- /* connect bus callback */
- bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
- if (!bus) {
- LOGE("cannot get bus from pipeline.\n");
- goto INIT_ERROR;
- }
-
- player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_msg_push, player);
-
- player->context.thread_default = g_main_context_get_thread_default();
-
- if (player->context.thread_default == NULL) {
- player->context.thread_default = g_main_context_default();
- LOGD("thread-default context is the global default context");
- }
- LOGW("bus watcher thread context = %p, watcher : %d", player->context.thread_default, player->bus_watcher);
-
- /* set sync handler to get tag synchronously */
- gst_bus_set_sync_handler(bus, __mmplayer_gst_bus_sync_callback, player, NULL);
-
- /* finished */
- gst_object_unref(GST_OBJECT(bus));
- g_list_free(element_bucket);
-
- /* create gst bus_msb_cb thread */
- g_mutex_init(&player->bus_msg_thread_mutex);
- g_cond_init(&player->bus_msg_thread_cond);
- player->bus_msg_thread_exit = FALSE;
- player->bus_msg_thread =
- g_thread_try_new("gst_bus_msg_thread", __mmplayer_gst_bus_msg_thread, (gpointer)player, NULL);
- if (!player->bus_msg_thread) {
- LOGE("failed to create gst BUS msg thread");
- g_mutex_clear(&player->bus_msg_thread_mutex);
- g_cond_clear(&player->bus_msg_thread_cond);
- goto INIT_ERROR;
- }
-
- MMPLAYER_FLEAVE();
-
- return MM_ERROR_NONE;
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
INIT_ERROR:
__mmplayer_gst_destroy_pipeline(player);
- g_list_free(element_bucket);
-
- if (mainbin) {
- /* release element which are not added to bin */
- for (i = 1; i < MMPLAYER_M_NUM; i++) {
- /* NOTE : skip pipeline */
- if (mainbin[i].gst) {
- GstObject* parent = NULL;
- parent = gst_element_get_parent(mainbin[i].gst);
-
- if (!parent) {
- gst_object_unref(GST_OBJECT(mainbin[i].gst));
- mainbin[i].gst = NULL;
- } else
- gst_object_unref(GST_OBJECT(parent));
- }
- }
-
- /* release pipeline with it's childs */
- if (mainbin[MMPLAYER_M_PIPE].gst)
- gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
-
- MMPLAYER_FREEIF(mainbin);
- }
-
- MMPLAYER_FREEIF(player->pipeline);
return MM_ERROR_PLAYER_INTERNAL;
}
static void
-__mmplayer_reset_gapless_state(mm_player_t* player)
+__mmplayer_reset_gapless_state(mmplayer_t *player)
{
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player
&& player->pipeline->audiobin
&& player->pipeline->audiobin[MMPLAYER_A_BIN].gst);
- memset(&player->gapless, 0, sizeof(mm_player_gapless_t));
+ memset(&player->gapless, 0, sizeof(mmplayer_gapless_t));
MMPLAYER_FLEAVE();
return;
}
static int
-__mmplayer_gst_destroy_pipeline(mm_player_t* player)
+__mmplayer_gst_destroy_pipeline(mmplayer_t *player)
{
gint timeout = 0;
int ret = MM_ERROR_NONE;
/* cleanup stuffs */
MMPLAYER_FREEIF(player->type);
- player->have_dynamic_pad = FALSE;
player->no_more_pad = FALSE;
player->num_dynamic_pad = 0;
player->demux_pad_index = 0;
- player->use_deinterleave = FALSE;
- player->max_audio_channels = 0;
- player->video_share_api_delta = 0;
- player->video_share_clock_delta = 0;
- player->video_hub_download_mode = 0;
MMPLAYER_SUBTITLE_INFO_LOCK(player);
player->subtitle_language_list = NULL;
__mmplayer_reset_gapless_state(player);
if (player->streamer) {
- __mm_player_streaming_deinitialize(player->streamer);
+ __mm_player_streaming_initialize(player->streamer, FALSE);
__mm_player_streaming_destroy(player->streamer);
player->streamer = NULL;
}
/* cleanup gst stuffs */
if (player->pipeline) {
- MMPlayerGstElement* mainbin = player->pipeline->mainbin;
- GstTagList* tag_list = player->pipeline->tag_list;
+ mmplayer_gst_element_t *mainbin = player->pipeline->mainbin;
+ GstTagList *tag_list = player->pipeline->tag_list;
/* first we need to disconnect all signal hander */
__mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_ALL);
if (mainbin) {
- MMPlayerGstElement* audiobin = player->pipeline->audiobin;
- MMPlayerGstElement* videobin = player->pipeline->videobin;
- MMPlayerGstElement* textbin = player->pipeline->textbin;
+ mmplayer_gst_element_t *audiobin = player->pipeline->audiobin;
+ mmplayer_gst_element_t *videobin = player->pipeline->videobin;
+ mmplayer_gst_element_t *textbin = player->pipeline->textbin;
GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
gst_bus_set_sync_handler(bus, NULL, NULL, NULL);
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);
if (ret != MM_ERROR_NONE) {
- LOGE("fail to change state to NULL\n");
+ LOGE("fail to change state to NULL");
return MM_ERROR_PLAYER_INTERNAL;
}
- LOGW("succeeded in changing state to NULL\n");
+ LOGW("succeeded in changing state to NULL");
gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
}
if (tag_list)
- gst_tag_list_free(tag_list);
+ gst_tag_list_unref(tag_list);
MMPLAYER_FREEIF(player->pipeline);
}
gst_caps_unref(player->v_stream_caps);
player->v_stream_caps = NULL;
}
+
if (player->a_stream_caps) {
gst_caps_unref(player->a_stream_caps);
player->a_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);
player->bufmgr = NULL;
}
- LOGW("finished destroy pipeline\n");
+ LOGW("finished destroy pipeline");
MMPLAYER_FLEAVE();
return ret;
}
-static int __gst_realize(mm_player_t* player)
+static int
+__mmplayer_gst_realize(mmplayer_t *player)
{
gint timeout = 0;
int ret = MM_ERROR_NONE;
ret = __mmplayer_gst_create_pipeline(player);
if (ret) {
- LOGE("failed to create pipeline\n");
+ LOGE("failed to create pipeline");
return ret;
}
return ret;
}
-static int __gst_unrealize(mm_player_t* player)
+static int
+__mmplayer_gst_unrealize(mmplayer_t *player)
{
int ret = MM_ERROR_NONE;
/* destroy pipeline */
ret = __mmplayer_gst_destroy_pipeline(player);
if (ret != MM_ERROR_NONE) {
- LOGE("failed to destory pipeline\n");
+ LOGE("failed to destory pipeline");
return ret;
}
}
static int
-__gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param)
+__mmplayer_gst_set_message_callback(mmplayer_t *player, MMMessageCallback callback, gpointer user_param)
{
MMPLAYER_FENTER();
if (!player) {
- LOGW("set_message_callback is called with invalid player handle\n");
+ LOGW("set_message_callback is called with invalid player handle");
return MM_ERROR_PLAYER_NOT_INITIALIZED;
}
player->msg_cb = callback;
player->msg_cb_param = user_param;
- LOGD("msg_cb : %p msg_cb_param : %p\n", callback, user_param);
+ LOGD("msg_cb : %p msg_cb_param : %p", callback, user_param);
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
}
-static int __mmplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data)
+int
+__mmplayer_parse_profile(const char *uri, void *param, mmplayer_parse_profile_t *data)
{
- int ret = MM_ERROR_PLAYER_INVALID_URI;
+ int ret = MM_ERROR_NONE;
char *path = NULL;
MMPLAYER_FENTER();
- MMPLAYER_RETURN_VAL_IF_FAIL(uri , FALSE);
- MMPLAYER_RETURN_VAL_IF_FAIL(data , FALSE);
- MMPLAYER_RETURN_VAL_IF_FAIL((strlen(uri) <= MM_MAX_URL_LEN), FALSE);
-
- memset(data, 0, sizeof(MMPlayerParseProfile));
-
- if ((path = strstr(uri, "es_buff://"))) {
- if (strlen(path)) {
- strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
- data->uri_type = MM_PLAYER_URI_TYPE_MS_BUFF;
- ret = MM_ERROR_NONE;
- }
- } else if ((path = strstr(uri, "rtsp://")) || (path = strstr(uri, "rtsps://"))) {
- if (strlen(path)) {
- strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
- data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
- ret = MM_ERROR_NONE;
- }
- } else if ((path = strstr(uri, "http://")) || (path = strstr(uri, "https://"))) {
- if (strlen(path)) {
- gchar *tmp = NULL;
- strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
- tmp = g_ascii_strdown(uri, strlen(uri));
-
- if (tmp && (g_str_has_suffix(tmp, ".ism/manifest") || g_str_has_suffix(tmp, ".isml/manifest")))
- data->uri_type = MM_PLAYER_URI_TYPE_SS;
- else
- data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
-
- ret = MM_ERROR_NONE;
- g_free(tmp);
- }
- } else if ((path = strstr(uri, "rtspu://"))) {
- if (strlen(path)) {
- strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
- data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
- ret = MM_ERROR_NONE;
- }
- } else if ((path = strstr(uri, "rtspr://"))) {
- strncpy(data->uri, path, MM_MAX_URL_LEN-1);
- char *separater = strstr(path, "*");
-
- if (separater) {
- int urgent_len = 0;
- char *urgent = separater + strlen("*");
-
- if ((urgent_len = strlen(urgent))) {
- data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
- strncpy(data->urgent, urgent, MM_MAX_FILENAME_LEN-1);
- data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
- ret = MM_ERROR_NONE;
- }
- }
- } else if ((path = strstr(uri, "mms://"))) {
- if (strlen(path)) {
- strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
- data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
- ret = MM_ERROR_NONE;
- }
+ MMPLAYER_RETURN_VAL_IF_FAIL(uri, MM_ERROR_PLAYER_INVALID_URI);
+ MMPLAYER_RETURN_VAL_IF_FAIL(data, MM_ERROR_PLAYER_INTERNAL);
+ MMPLAYER_RETURN_VAL_IF_FAIL((strlen(uri) <= MM_MAX_URL_LEN), MM_ERROR_PLAYER_INVALID_URI);
+
+ memset(data, 0, sizeof(mmplayer_parse_profile_t));
+
+ if (strstr(uri, "es_buff://")) {
+ __mmplayer_copy_uri_and_set_type(data, uri, MM_PLAYER_URI_TYPE_MS_BUFF);
+ } else if (strstr(uri, "rtsp://") || strstr(uri, "rtsps://") || strstr(uri, "rtspu://")) {
+ __mmplayer_copy_uri_and_set_type(data, uri, MM_PLAYER_URI_TYPE_URL_RTSP);
+ } else if (strstr(uri, "http://") || strstr(uri, "https://")) {
+ gchar *tmp = NULL;
+ tmp = g_ascii_strdown(uri, strlen(uri));
+ if (tmp && (g_str_has_suffix(tmp, ".ism/manifest") || g_str_has_suffix(tmp, ".isml/manifest")))
+ __mmplayer_copy_uri_and_set_type(data, uri, MM_PLAYER_URI_TYPE_SS);
+ else
+ __mmplayer_copy_uri_and_set_type(data, uri, MM_PLAYER_URI_TYPE_URL_HTTP);
+ g_free(tmp);
+ } else if (strstr(uri, "mms://")) {
+ __mmplayer_copy_uri_and_set_type(data, uri, MM_PLAYER_URI_TYPE_URL_MMS);
} else if ((path = strstr(uri, "mem://"))) {
- if (strlen(path)) {
- int mem_size = 0;
- char *buffer = NULL;
- char *seperator = strchr(path, ',');
- char ext[100] = {0,}, size[100] = {0,};
-
- if (seperator) {
- if ((buffer = strstr(path, "ext="))) {
- buffer += strlen("ext=");
-
- if (strlen(buffer)) {
- strncpy(ext, buffer, 99);
-
- if ((seperator = strchr(ext, ','))
- || (seperator = strchr(ext, ' '))
- || (seperator = strchr(ext, '\0'))) {
- seperator[0] = '\0';
- }
- }
- }
+ ret = __mmplayer_set_mem_uri(data, path, param);
+ } else {
+ ret = __mmplayer_set_file_uri(data, uri);
+ }
- if ((buffer = strstr(path, "size="))) {
- buffer += strlen("size=");
+ if (data->uri_type == MM_PLAYER_URI_TYPE_NONE)
+ ret = MM_ERROR_PLAYER_FILE_NOT_FOUND;
+ else if (data->uri_type == MM_PLAYER_URI_TYPE_NO_PERMISSION)
+ ret = MM_ERROR_PLAYER_PERMISSION_DENIED;
- if (strlen(buffer) > 0) {
- strncpy(size, buffer, 99);
+ /* dump parse result */
+ SECURE_LOGW("incoming uri : %s", uri);
+ LOGD("uri_type : %d, mem : %p, mem_size : %d, urgent : %s",
+ data->uri_type, data->input_mem.buf, data->input_mem.len, data->urgent);
- if ((seperator = strchr(size, ','))
- || (seperator = strchr(size, ' '))
- || (seperator = strchr(size, '\0'))) {
- seperator[0] = '\0';
- }
+ MMPLAYER_FLEAVE();
- mem_size = atoi(size);
- }
- }
- }
+ return ret;
+}
- LOGD("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
- if (mem_size && param) {
- if (data->input_mem.buf)
- free(data->input_mem.buf);
- data->input_mem.buf = malloc(mem_size);
+static gboolean
+__mmplayer_can_do_interrupt(mmplayer_t *player)
+{
+ if (!player || !player->pipeline || !player->attrs) {
+ LOGW("not initialized");
+ goto FAILED;
+ }
- if (data->input_mem.buf) {
- memcpy(data->input_mem.buf, param, mem_size);
- data->input_mem.len = mem_size;
- ret = MM_ERROR_NONE;
- } else {
- LOGE("failed to alloc mem %d", mem_size);
- ret = MM_ERROR_PLAYER_INTERNAL;
- }
-
- data->input_mem.offset = 0;
- data->uri_type = MM_PLAYER_URI_TYPE_MEM;
- }
- }
- } else {
- gchar *location = NULL;
- GError *err = NULL;
-
- if ((path = strstr(uri, "file://"))) {
-
- location = g_filename_from_uri(uri, NULL, &err);
-
- if (!location || (err != NULL)) {
- LOGE("Invalid URI '%s' for filesrc: %s", path,
- (err != NULL) ? err->message : "unknown error");
-
- if (err) g_error_free(err);
- if (location) g_free(location);
-
- data->uri_type = MM_PLAYER_URI_TYPE_NONE;
- goto exit;
- }
-
- LOGD("path from uri: %s", location);
- }
-
- path = (location != NULL) ? (location) : ((char*)uri);
- int file_stat = MM_ERROR_NONE;
-
- file_stat = util_exist_file_path(path);
-
- /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
- if (file_stat == MM_ERROR_NONE) {
- g_snprintf(data->uri, MM_MAX_URL_LEN, "file://%s", path);
-
- if (util_is_sdp_file(path)) {
- LOGD("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
- data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
- } else {
- data->uri_type = MM_PLAYER_URI_TYPE_FILE;
- }
- ret = MM_ERROR_NONE;
- } else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED) {
- data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
- } else {
- LOGE("invalid uri, could not play..\n");
- data->uri_type = MM_PLAYER_URI_TYPE_NONE;
- }
-
- if (location) g_free(location);
- }
-
-exit:
- if (data->uri_type == MM_PLAYER_URI_TYPE_NONE)
- ret = MM_ERROR_PLAYER_FILE_NOT_FOUND;
- else if (data->uri_type == MM_PLAYER_URI_TYPE_NO_PERMISSION)
- ret = MM_ERROR_PLAYER_PERMISSION_DENIED;
-
- /* dump parse result */
- SECURE_LOGW("incomming uri : %s\n", uri);
- LOGD("uri_type : %d, mem : %p, mem_size : %d, urgent : %s\n",
- data->uri_type, data->input_mem.buf, data->input_mem.len, data->urgent);
-
- MMPLAYER_FLEAVE();
-
- return ret;
-}
-
-static gboolean
-__mmplayer_can_do_interrupt(mm_player_t *player)
-{
- if (!player || !player->pipeline || !player->attrs) {
- LOGW("not initialized");
- goto FAILED;
- }
-
- if (player->set_mode.pcm_extraction) {
- LOGW("leave right now, %d", player->set_mode.pcm_extraction);
+ if (player->audio_decoded_cb) {
+ LOGW("not support in pcm extraction mode");
goto FAILED;
}
__resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res,
void *user_data)
{
- mm_player_t *player = NULL;
+ mmplayer_t *player = NULL;
MMPLAYER_FENTER();
if (user_data == NULL) {
- LOGE("- user_data is null\n");
+ LOGE("- user_data is null");
return FALSE;
}
- player = (mm_player_t *)user_data;
+ player = (mmplayer_t *)user_data;
/* do something to release resource here.
* player stop and interrupt forwarding */
player->interrupted_by_resource = TRUE;
/* get last play position */
- if (_mmplayer_get_position((MMHandleType)player, MM_PLAYER_POS_FORMAT_TIME, &pos) != MM_ERROR_NONE) {
+ if (_mmplayer_get_position((MMHandleType)player, &pos) != MM_ERROR_NONE) {
LOGW("failed to get play position.");
} else {
msg.union_type = MM_MSG_UNION_TIME;
return FALSE;
}
+static void
+__mmplayer_initialize_video_roi(mmplayer_t *player)
+{
+ player->video_roi.scale_x = 0.0;
+ player->video_roi.scale_y = 0.0;
+ player->video_roi.scale_width = 1.0;
+ player->video_roi.scale_height = 1.0;
+}
+
int
_mmplayer_create_player(MMHandleType handle)
{
int ret = MM_ERROR_PLAYER_INTERNAL;
bool enabled = false;
- mm_player_t* player = MM_PLAYER_CAST(handle);
+ mmplayer_t *player = MM_PLAYER_CAST(handle);
MMPLAYER_FENTER();
player->attrs = _mmplayer_construct_attribute(handle);
if (!player->attrs) {
- LOGE("Failed to construct attributes\n");
+ LOGE("Failed to construct attributes");
return ret;
}
/* initialize gstreamer with configured parameter */
if (!__mmplayer_init_gstreamer(player)) {
- LOGE("Initializing gstreamer failed\n");
+ LOGE("Initializing gstreamer failed");
_mmplayer_deconstruct_attribute(handle);
return ret;
}
/* create update tag lock */
g_mutex_init(&player->update_tag_lock);
- /* create next play mutex */
- g_mutex_init(&player->next_play_thread_mutex);
+ /* create gapless play mutex */
+ g_mutex_init(&player->gapless_play_thread_mutex);
- /* create next play cond */
- g_cond_init(&player->next_play_thread_cond);
+ /* create gapless play cond */
+ g_cond_init(&player->gapless_play_thread_cond);
- /* create next play thread */
- player->next_play_thread =
- g_thread_try_new("next_play_thread", __mmplayer_next_play_thread, (gpointer)player, NULL);
- if (!player->next_play_thread) {
- LOGE("failed to create next play thread");
+ /* create gapless play thread */
+ player->gapless_play_thread =
+ g_thread_try_new("gapless_play_thread", __mmplayer_gapless_play_thread, (gpointer)player, NULL);
+ if (!player->gapless_play_thread) {
+ LOGE("failed to create gapless play thread");
ret = MM_ERROR_PLAYER_RESOURCE_LIMIT;
- g_mutex_clear(&player->next_play_thread_mutex);
- g_cond_clear(&player->next_play_thread_cond);
+ g_mutex_clear(&player->gapless_play_thread_mutex);
+ g_cond_clear(&player->gapless_play_thread_cond);
goto ERROR;
}
ret = _mmplayer_initialize_video_capture(player);
if (ret != MM_ERROR_NONE) {
- LOGE("failed to initialize video capture\n");
+ LOGE("failed to initialize video capture");
goto ERROR;
}
/* initialize resource manager */
- if (MM_RESOURCE_MANAGER_ERROR_NONE != mm_resource_manager_create(
- MM_RESOURCE_MANAGER_APP_CLASS_MEDIA, __resource_release_cb, player,
- &player->resource_manager)) {
- LOGE("failed to initialize resource manager\n");
+ 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");
+ ret = MM_ERROR_PLAYER_INTERNAL;
goto ERROR;
}
- if (MMPLAYER_IS_HTTP_PD(player)) {
- player->pd_downloader = NULL;
- player->pd_file_save_path = NULL;
- }
-
/* create video bo lock and cond */
g_mutex_init(&player->video_bo_mutex);
g_cond_init(&player->video_bo_cond);
player->playback_rate = DEFAULT_PLAYBACK_RATE;
player->play_subtitle = FALSE;
- player->use_deinterleave = FALSE;
- player->max_audio_channels = 0;
- player->video_share_api_delta = 0;
- player->video_share_clock_delta = 0;
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->video360_horizontal_fov = PLAYER_SPHERICAL_DEFAULT_H_FOV;
player->video360_vertical_fov = PLAYER_SPHERICAL_DEFAULT_V_FOV;
+ __mmplayer_initialize_video_roi(player);
+
/* set player state to null */
MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_NULL);
+ MMPLAYER_FLEAVE();
+
return MM_ERROR_NONE;
ERROR:
/* free lock */
g_mutex_clear(&player->fsink_lock);
-
/* free update tag lock */
g_mutex_clear(&player->update_tag_lock);
-
g_queue_free(player->bus_msg_q);
+ /* free gapless play thread */
+ if (player->gapless_play_thread) {
+ MMPLAYER_GAPLESS_PLAY_THREAD_LOCK(player);
+ player->gapless_play_thread_exit = TRUE;
+ MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player);
+ MMPLAYER_GAPLESS_PLAY_THREAD_UNLOCK(player);
- /* free next play thread */
- if (player->next_play_thread) {
- MMPLAYER_NEXT_PLAY_THREAD_LOCK(player);
- player->next_play_thread_exit = TRUE;
- MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
- MMPLAYER_NEXT_PLAY_THREAD_UNLOCK(player);
+ g_thread_join(player->gapless_play_thread);
+ player->gapless_play_thread = NULL;
- g_thread_join(player->next_play_thread);
- player->next_play_thread = NULL;
-
- g_mutex_clear(&player->next_play_thread_mutex);
- g_cond_clear(&player->next_play_thread_cond);
+ g_mutex_clear(&player->gapless_play_thread_mutex);
+ g_cond_clear(&player->gapless_play_thread_cond);
}
/* release attributes */
}
static gboolean
-__mmplayer_init_gstreamer(mm_player_t* player)
+__mmplayer_init_gstreamer(mmplayer_t *player)
{
static gboolean initialized = FALSE;
static const int max_argc = 50;
- gint* argc = NULL;
- gchar** argv = NULL;
- gchar** argv2 = NULL;
+ gint *argc = NULL;
+ gchar **argv = NULL;
+ gchar **argv2 = NULL;
GError *err = NULL;
int i = 0;
int arg_count = 0;
if (initialized) {
- LOGD("gstreamer already initialized.\n");
+ LOGD("gstreamer already initialized.");
return TRUE;
}
/* alloc */
argc = malloc(sizeof(int));
- argv = malloc(sizeof(gchar*) * max_argc);
- argv2 = malloc(sizeof(gchar*) * max_argc);
+ argv = malloc(sizeof(gchar *) * max_argc);
+ argv2 = malloc(sizeof(gchar *) * max_argc);
if (!argc || !argv || !argv2)
goto ERROR;
- memset(argv, 0, sizeof(gchar*) * max_argc);
- memset(argv2, 0, sizeof(gchar*) * max_argc);
+ memset(argv, 0, sizeof(gchar *) * max_argc);
+ memset(argv2, 0, sizeof(gchar *) * max_argc);
/* add initial */
*argc = 1;
(*argc)++;
}
- LOGD("initializing gstreamer with following parameter\n");
- LOGD("argc : %d\n", *argc);
+ LOGD("initializing gstreamer with following parameter");
+ LOGD("argc : %d", *argc);
arg_count = *argc;
for (i = 0; i < arg_count; i++) {
argv2[i] = argv[i];
- LOGD("argv[%d] : %s\n", i, argv2[i]);
+ LOGD("argv[%d] : %s", i, argv2[i]);
}
/* initializing gstreamer */
if (!gst_init_check(argc, &argv, &err)) {
- LOGE("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
+ LOGE("Could not initialize GStreamer: %s", err ? err->message : "unknown error occurred");
if (err)
g_error_free(err);
}
/* release */
for (i = 0; i < arg_count; i++) {
- //LOGD("release - argv[%d] : %s\n", i, argv2[i]);
+ //LOGD("release - argv[%d] : %s", i, argv2[i]);
MMPLAYER_FREEIF(argv2[i]);
}
/* release */
for (i = 0; i < arg_count; i++) {
- LOGD("free[%d] : %s\n", i, argv2[i]);
+ LOGD("free[%d] : %s", i, argv2[i]);
MMPLAYER_FREEIF(argv2[i]);
}
return FALSE;
}
-int
-__mmplayer_destroy_streaming_ext(mm_player_t* player)
-{
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- if (player->pd_downloader || MMPLAYER_IS_HTTP_PD(player)) {
- _mmplayer_destroy_pd_downloader((MMHandleType)player);
- MMPLAYER_FREEIF(player->pd_file_save_path);
- }
-
- return MM_ERROR_NONE;
-}
-
static void
-__mmplayer_check_async_state_transition(mm_player_t* player)
+__mmplayer_check_async_state_transition(mmplayer_t *player)
{
GstState element_state = GST_STATE_VOID_PENDING;
GstState element_pending_state = GST_STATE_VOID_PENDING;
GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
- GstElement * element = NULL;
+ GstElement *element = NULL;
gboolean async = FALSE;
/* check player handle */
/* wait for state transition */
element = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
- ret = gst_element_get_state(element, &element_state, &element_pending_state, 1*GST_SECOND);
+ ret = gst_element_get_state(element, &element_state, &element_pending_state, 1 * GST_SECOND);
if (ret == GST_STATE_CHANGE_FAILURE) {
- LOGE(" [%s] state : %s pending : %s \n",
+ LOGE(" [%s] state : %s pending : %s",
GST_ELEMENT_NAME(element),
gst_element_state_get_name(element_state),
gst_element_state_get_name(element_pending_state));
return;
}
- LOGD("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
+ LOGD("[%s] element state has changed", GST_ELEMENT_NAME(element));
return;
}
int
_mmplayer_destroy(MMHandleType handle)
{
- mm_player_t* player = MM_PLAYER_CAST(handle);
+ mmplayer_t *player = MM_PLAYER_CAST(handle);
MMPLAYER_FENTER();
/* check async state transition */
__mmplayer_check_async_state_transition(player);
- __mmplayer_destroy_streaming_ext(player);
-
- /* release next play thread */
- if (player->next_play_thread) {
- MMPLAYER_NEXT_PLAY_THREAD_LOCK(player);
- player->next_play_thread_exit = TRUE;
- MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
- MMPLAYER_NEXT_PLAY_THREAD_UNLOCK(player);
+ /* release gapless play thread */
+ if (player->gapless_play_thread) {
+ MMPLAYER_GAPLESS_PLAY_THREAD_LOCK(player);
+ player->gapless_play_thread_exit = TRUE;
+ MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player);
+ MMPLAYER_GAPLESS_PLAY_THREAD_UNLOCK(player);
- LOGD("waitting for next play thread exit\n");
- g_thread_join(player->next_play_thread);
- g_mutex_clear(&player->next_play_thread_mutex);
- g_cond_clear(&player->next_play_thread_cond);
- LOGD("next play thread released\n");
+ LOGD("waitting 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);
+ LOGD("gapless play thread released");
}
_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\n");
+ LOGE("failed to deinitialize resource manager");
/* release pipeline */
if (MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline(player)) {
- LOGE("failed to destory pipeline\n");
+ LOGE("failed to destory pipeline");
return MM_ERROR_PLAYER_INTERNAL;
}
}
int
-__mmplayer_realize_streaming_ext(mm_player_t* player)
-{
- int ret = MM_ERROR_NONE;
-
- MMPLAYER_FENTER();
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- if (MMPLAYER_IS_HTTP_PD(player)) {
- gboolean bret = FALSE;
-
- player->pd_downloader = _mmplayer_create_pd_downloader();
- if (!player->pd_downloader) {
- LOGE("Unable to create PD Downloader...");
- ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
- }
-
- bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
-
- if (FALSE == bret) {
- LOGE("Unable to create PD Downloader...");
- ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
- }
- }
-
- MMPLAYER_FLEAVE();
- return ret;
-}
-
-int
_mmplayer_realize(MMHandleType hplayer)
{
- mm_player_t* player = (mm_player_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
char *uri = NULL;
void *param = NULL;
MMHandleType attrs = 0;
MMPLAYER_FENTER();
/* check player handle */
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED)
+ MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
/* check current state */
MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_REALIZE);
attrs = MMPLAYER_GET_ATTRS(player);
if (!attrs) {
- LOGE("fail to get attributes.\n");
+ LOGE("fail to get attributes.");
return MM_ERROR_PLAYER_INTERNAL;
}
mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
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\n");
+ LOGE("failed to parse profile");
return ret;
}
}
}
if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS) {
- LOGW("mms protocol is not supported format.\n");
+ LOGW("mms protocol is not supported format.");
return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
}
player->smooth_streaming = FALSE;
player->videodec_linked = 0;
- player->videosink_linked = 0;
player->audiodec_linked = 0;
- player->audiosink_linked = 0;
player->textsink_linked = 0;
player->is_external_subtitle_present = FALSE;
player->is_external_subtitle_added_now = FALSE;
- /* set the subtitle ON default */
- player->is_subtitle_off = FALSE;
+ 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_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);
+
+ 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);
+
+ if (prebuffer_ms > 0) {
+ prebuffer_ms = MAX(prebuffer_ms, 1000);
+ player->streamer->buffering_req.prebuffer_time = prebuffer_ms;
+ }
+
+ if (rebuffer_ms > 0) {
+ player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
+ rebuffer_ms = MAX(rebuffer_ms, 1000);
+ player->streamer->buffering_req.rebuffer_time = rebuffer_ms;
+ }
+
+ LOGD("buffering time %d ms, %d ms", player->streamer->buffering_req.prebuffer_time,
+ player->streamer->buffering_req.rebuffer_time);
+ }
/* realize pipeline */
- ret = __gst_realize(player);
+ ret = __mmplayer_gst_realize(player);
if (ret != MM_ERROR_NONE)
- LOGE("fail to realize the player.\n");
- else
- ret = __mmplayer_realize_streaming_ext(player);
+ LOGE("fail to realize the player.");
MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
}
int
-__mmplayer_unrealize_streaming_ext(mm_player_t *player)
-{
- MMPLAYER_FENTER();
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- /* destroy can called at anytime */
- if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
- _mmplayer_unrealize_pd_downloader((MMHandleType)player);
-
- MMPLAYER_FLEAVE();
- return MM_ERROR_NONE;
-}
-
-int
_mmplayer_unrealize(MMHandleType hplayer)
{
- mm_player_t* player = (mm_player_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
int ret = MM_ERROR_NONE;
MMPLAYER_FENTER();
/* check async state transition */
__mmplayer_check_async_state_transition(player);
- __mmplayer_unrealize_streaming_ext(player);
-
/* unrealize pipeline */
- ret = __gst_unrealize(player);
+ ret = __mmplayer_gst_unrealize(player);
/* set asm stop if success */
if (MM_ERROR_NONE == ret) {
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)\n", ret);
+ LOGE("failed to mark decoder resource for release, ret(0x%x)", ret);
else
player->video_decoder_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)\n", ret);
+ 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)\n", ret);
+ LOGE("failed to commit resource releases, ret(0x%x)", ret);
}
} else
LOGE("failed and don't change asm state to stop");
int
_mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param)
{
- mm_player_t* player = (mm_player_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- return __gst_set_message_callback(player, callback, user_param);
+ return __mmplayer_gst_set_message_callback(player, callback, user_param);
}
int
-_mmplayer_get_state(MMHandleType hplayer, int* state)
+_mmplayer_get_state(MMHandleType hplayer, int *state)
{
- mm_player_t *player = (mm_player_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_RETURN_VAL_IF_FAIL(state, MM_ERROR_INVALID_ARGUMENT);
return MM_ERROR_NONE;
}
-
-int
-_mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume)
+static int
+__mmplayer_gst_set_volume_property(mmplayer_t *player, const char *prop_name)
{
- mm_player_t* player = (mm_player_t*) hplayer;
- GstElement* vol_element = NULL;
- int i = 0;
+ GstElement *vol_element = NULL;
+ 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\n",
- 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)\n");
- 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\n");
- LOGD("but, current stored volume will be set when it's created.\n");
+ 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 (vol_element) {
- LOGD("volume is set [%f]\n", player->sound.volume);
- g_object_set(vol_element, "volume", player->sound.volume, NULL);
+ if (player->build_audio_offload) {
+ LOGD("offload pipeline");
+ volume_elem_id = MMPLAYER_A_SINK;
}
- MMPLAYER_FLEAVE();
-
- return MM_ERROR_NONE;
-}
-
-
-int
-_mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
-{
- mm_player_t* player = (mm_player_t*) hplayer;
- int i = 0;
-
- MMPLAYER_FENTER();
+ 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_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(volume, MM_ERROR_INVALID_ARGUMENT);
+ LOGD("set '%s' property to element[%s]", prop_name, GST_ELEMENT_NAME(vol_element));
- /* returning stored volume */
- for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
- volume->level[i] = player->sound.volume;
+ 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;
+ }
- MMPLAYER_FLEAVE();
+ 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_set_mute(MMHandleType hplayer, int mute)
+_mmplayer_set_volume(MMHandleType hplayer, float volume)
{
- mm_player_t* player = (mm_player_t*) hplayer;
- GstElement* vol_element = NULL;
+ int ret = MM_ERROR_NONE;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
-
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- /* mute value shoud 0 or 1 */
- if (mute != 0 && mute != 1) {
- LOGE("bad mute value\n");
+ LOGD("volume = %f", volume);
- /* FIXIT : definitly, we need _BAD_PARAM error code */
+ /* 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;
}
- 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\n");
- return MM_ERROR_NONE;
- }
-
- vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
+ player->sound.volume = volume;
- /* NOTE : volume will only created when the bt is enabled */
- if (vol_element) {
- LOGD("mute : %d\n", mute);
- g_object_set(vol_element, "mute", mute, NULL);
- } else
- LOGD("volume elemnet is not created. using volume in audiosink\n");
+ ret = __mmplayer_gst_set_volume_property(player, "volume");
MMPLAYER_FLEAVE();
-
- return MM_ERROR_NONE;
+ return ret;
}
int
-_mmplayer_get_mute(MMHandleType hplayer, int* pmute)
+_mmplayer_get_volume(MMHandleType hplayer, float *volume)
{
- mm_player_t* player = (mm_player_t*) hplayer;
+ 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);
+ MMPLAYER_RETURN_VAL_IF_FAIL(volume, 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\n");
- *pmute = player->sound.mute;
- return MM_ERROR_NONE;
- }
+ *volume = player->sound.volume;
- *pmute = player->sound.mute;
+ LOGD("current vol = %f", *volume);
MMPLAYER_FLEAVE();
-
return MM_ERROR_NONE;
}
int
-_mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
+_mmplayer_set_mute(MMHandleType hplayer, bool mute)
{
- mm_player_t* player = (mm_player_t*) hplayer;
+ int ret = MM_ERROR_NONE;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
-
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- player->video_stream_changed_cb = callback;
- player->video_stream_changed_cb_user_param = user_param;
- LOGD("Handle value is %p : %p\n", player, player->video_stream_changed_cb);
+ LOGD("mute = %d", mute);
- MMPLAYER_FLEAVE();
+ player->sound.mute = mute;
- return MM_ERROR_NONE;
+ ret = __mmplayer_gst_set_volume_property(player, "mute");
+
+ MMPLAYER_FLEAVE();
+ return ret;
}
int
-_mmplayer_set_audiostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
+_mmplayer_get_mute(MMHandleType hplayer, bool *mute)
{
- mm_player_t* player = (mm_player_t*) hplayer;
+ 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);
- player->audio_stream_changed_cb = callback;
- player->audio_stream_changed_cb_user_param = user_param;
- LOGD("Handle value is %p : %p\n", player, player->audio_stream_changed_cb);
+ *mute = player->sound.mute;
+
+ LOGD("current mute = %d", *mute);
MMPLAYER_FLEAVE();
}
int
-_mmplayer_set_audiostream_cb_ex(MMHandleType hplayer, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param)
+_mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
{
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- player->audio_stream_render_cb_ex = callback;
- player->audio_stream_cb_user_param = user_param;
- player->audio_stream_sink_sync = sync;
- LOGD("Audio Stream cb Handle value is %p : %p audio_stream_sink_sync : %d\n", player, player->audio_stream_render_cb_ex, player->audio_stream_sink_sync);
+ 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);
MMPLAYER_FLEAVE();
}
int
-_mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param)
+_mmplayer_set_audiostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
{
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- 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;
-
- LOGD("Stream cb Handle value is %p : %p, enable:%d\n", player, player->video_stream_cb, player->set_mode.media_packet_video_stream);
+ player->audio_stream_changed_cb = callback;
+ player->audio_stream_changed_cb_user_param = user_param;
+ LOGD("Handle value is %p : %p", player, player->audio_stream_changed_cb);
MMPLAYER_FLEAVE();
}
int
-_mmplayer_set_audiostream_cb(MMHandleType hplayer, 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)
{
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- player->audio_stream_cb = callback;
- player->audio_stream_cb_user_param = user_param;
- LOGD("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
+ 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();
return MM_ERROR_NONE;
}
-static int
-__mmplayer_start_streaming_ext(mm_player_t *player)
+int
+_mmplayer_set_video_decoded_cb(MMHandleType hplayer, mm_player_video_decoded_callback callback, void *user_param)
{
- gint ret = MM_ERROR_NONE;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
+
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- if (MMPLAYER_IS_HTTP_PD(player)) {
- if (!player->pd_downloader) {
- ret = __mmplayer_realize_streaming_ext(player);
+ if (callback && !player->bufmgr)
+ player->bufmgr = tbm_bufmgr_init(-1);
- if (ret != MM_ERROR_NONE) {
- LOGE("failed to realize streaming ext\n");
- return ret;
- }
- }
+ player->set_mode.video_export = (callback) ? true : false;
+ player->video_decoded_cb = callback;
+ player->video_decoded_cb_user_param = user_param;
- if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI) {
- ret = _mmplayer_start_pd_downloader((MMHandleType)player);
- if (!ret) {
- LOGE("ERROR while starting PD...\n");
- return MM_ERROR_PLAYER_NOT_INITIALIZED;
- }
- ret = MM_ERROR_NONE;
- }
- }
+ LOGD("Stream cb Handle value is %p : %p, enable:%d", player, player->video_decoded_cb, player->set_mode.video_export);
MMPLAYER_FLEAVE();
- return ret;
+
+ return MM_ERROR_NONE;
}
int
_mmplayer_start(MMHandleType hplayer)
{
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
gint ret = MM_ERROR_NONE;
MMPLAYER_FENTER();
/* check current state */
MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_START);
- /* PD - start streaming */
- ret = __mmplayer_start_streaming_ext(player);
- if (ret != MM_ERROR_NONE) {
- LOGE("failed to start streaming ext 0x%X", ret);
- return ret;
- }
-
/* start pipeline */
ret = __mmplayer_gst_start(player);
if (ret != MM_ERROR_NONE)
- LOGE("failed to start player.\n");
+ LOGE("failed to start player.");
if ((player->streamer) && (player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
LOGD("force playing start even during buffering");
* Because GST_ERROR_MESSAGE is posted by other plugin internally.
*/
int
-__mmplayer_handle_missed_plugin(mm_player_t* player)
+__mmplayer_handle_missed_plugin(mmplayer_t *player)
{
MMMessageParamType msg_param;
memset(&msg_param, 0, sizeof(MMMessageParamType));
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- LOGD("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
+ LOGD("not_supported_codec = 0x%02x, can_support_codec = 0x%02x",
player->not_supported_codec, player->can_support_codec);
if (player->not_found_demuxer) {
memset(&msg_param, 0, sizeof(MMMessageParamType));
if (player->not_supported_codec == MISSING_PLUGIN_AUDIO) {
- LOGW("not found AUDIO codec, posting error code to application.\n");
+ LOGW("not found AUDIO codec, posting error code to application.");
msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
} else if (player->not_supported_codec == MISSING_PLUGIN_VIDEO) {
- LOGW("not found VIDEO codec, posting error code to application.\n");
+ LOGW("not found VIDEO codec, posting error code to application.");
msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
return MM_ERROR_NONE;
} else {
// no any supported codec case
- LOGW("not found any codec, posting error code to application.\n");
+ LOGW("not found any codec, posting error code to application.");
if (player->not_supported_codec == MISSING_PLUGIN_AUDIO) {
msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
return MM_ERROR_NONE;
}
-static void __mmplayer_check_pipeline(mm_player_t* player)
+static void
+__mmplayer_check_pipeline(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;
- if (player->gapless.reconfigure) {
- LOGW("pipeline is under construction.\n");
+ if (!player->gapless.reconfigure)
+ return;
- MMPLAYER_PLAYBACK_LOCK(player);
- MMPLAYER_PLAYBACK_UNLOCK(player);
+ LOGW("pipeline is under construction.");
- timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
+ MMPLAYER_PLAYBACK_LOCK(player);
+ MMPLAYER_PLAYBACK_UNLOCK(player);
- /* wait for state transition */
- ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND);
+ timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
- if (ret == GST_STATE_CHANGE_FAILURE)
- LOGE("failed to change pipeline state within %d sec\n", 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);
}
/* NOTE : it should be able to call 'stop' anytime*/
int
_mmplayer_stop(MMHandleType hplayer)
{
- mm_player_t* player = (mm_player_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
int ret = MM_ERROR_NONE;
MMPLAYER_FENTER();
/* NOTE : application should not wait for EOS after calling STOP */
__mmplayer_cancel_eos_timer(player);
- __mmplayer_unrealize_streaming_ext(player);
-
/* reset */
player->seek_state = MMPLAYER_SEEK_NONE;
ret = __mmplayer_gst_stop(player);
if (ret != MM_ERROR_NONE)
- LOGE("failed to stop player.\n");
+ LOGE("failed to stop player.");
MMPLAYER_FLEAVE();
int
_mmplayer_pause(MMHandleType hplayer)
{
- mm_player_t* player = (mm_player_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
gint64 pos_nsec = 0;
gboolean async = FALSE;
gint ret = MM_ERROR_NONE;
* elements
*/
if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
- LOGW("getting current position failed in paused\n");
+ LOGW("getting current position failed in paused");
player->last_position = pos_nsec;
ret = __mmplayer_gst_pause(player, async);
if (ret != MM_ERROR_NONE)
- LOGE("failed to pause player. ret : 0x%x\n", ret);
+ LOGE("failed to pause player. ret : 0x%x", 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"))
int
_mmplayer_abort_pause(MMHandleType hplayer)
{
- mm_player_t* player = (mm_player_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
int ret = MM_ERROR_NONE;
MMPLAYER_FENTER();
return ret;
}
-
int
_mmplayer_resume(MMHandleType hplayer)
{
- mm_player_t* player = (mm_player_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
int ret = MM_ERROR_NONE;
gboolean async = FALSE;
ret = __mmplayer_gst_resume(player, async);
if (ret != MM_ERROR_NONE)
- LOGE("failed to resume player.\n");
+ LOGE("failed to resume player.");
if ((player->streamer) && (player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
LOGD("force resume even during buffering");
int
_mmplayer_set_playspeed(MMHandleType hplayer, float rate, bool streaming)
{
- mm_player_t* player = (mm_player_t*)hplayer;
+ 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;
- MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
+ mmplayer_state_e current_state = MM_PLAYER_STATE_NONE;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
/* 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);
/* If the position is reached at start potion during fast backward, EOS is posted.
* So, This EOS have to be classified with it which is posted at reaching the end of stream.
- * */
+ */
player->playback_rate = rate;
current_state = MMPLAYER_CURRENT_STATE(player);
(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
GST_SEEK_TYPE_SET, start,
GST_SEEK_TYPE_SET, stop)) {
- LOGE("failed to set speed playback\n");
+ LOGE("failed to set speed playback");
return MM_ERROR_PLAYER_SEEK;
}
- LOGD("succeeded to set speed playback as %0.1f\n", rate);
+ LOGD("succeeded to set speed playback as %0.1f", rate);
MMPLAYER_FLEAVE();
}
int
-_mmplayer_set_position(MMHandleType hplayer, int format, gint64 position)
+_mmplayer_set_position(MMHandleType hplayer, gint64 position)
{
- mm_player_t* player = (mm_player_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
int ret = MM_ERROR_NONE;
MMPLAYER_FENTER();
/* check pipline building state */
__mmplayer_check_pipeline(player);
- ret = __mmplayer_gst_set_position(player, format, position, FALSE);
+ ret = __mmplayer_gst_set_position(player, position, FALSE);
MMPLAYER_FLEAVE();
}
int
-_mmplayer_get_position(MMHandleType hplayer, int format, gint64 *position)
+_mmplayer_get_position(MMHandleType hplayer, gint64 *position)
{
- mm_player_t* player = (mm_player_t*)hplayer;
+ 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, format, position);
+ ret = __mmplayer_gst_get_position(player, position);
return ret;
}
int
_mmplayer_get_duration(MMHandleType hplayer, gint64 *duration)
{
- mm_player_t* player = (mm_player_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
int ret = MM_ERROR_NONE;
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
MMPLAYER_RETURN_VAL_IF_FAIL(duration, MM_ERROR_COMMON_INVALID_ARGUMENT);
+ if (g_strrstr(player->type, "video/mpegts"))
+ __mmplayer_update_duration_value(player);
+
*duration = player->duration;
return ret;
}
int
-_mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos)
+_mmplayer_get_buffer_position(MMHandleType hplayer, int *start_pos, int *end_pos)
{
- mm_player_t* player = (mm_player_t*)hplayer;
+ 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_buffer_position(player, format, start_pos, stop_pos);
+ ret = __mmplayer_gst_get_buffer_position(player, start_pos, end_pos);
return ret;
}
int
-_mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position)
+_mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int position)
{
- mm_player_t* player = (mm_player_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
int ret = MM_ERROR_NONE;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- ret = __gst_adjust_subtitle_position(player, format, position);
+ ret = __mmplayer_gst_adjust_subtitle_position(player, position);
MMPLAYER_FLEAVE();
}
static gboolean
-__mmplayer_is_midi_type(gchar* str_caps)
+__mmplayer_is_midi_type(gchar *str_caps)
{
if ((g_strrstr(str_caps, "audio/midi")) ||
(g_strrstr(str_caps, "application/x-gst_ff-mmf")) ||
(g_strrstr(str_caps, "audio/mobile-xmf")) ||
(g_strrstr(str_caps, "audio/xmf")) ||
(g_strrstr(str_caps, "audio/mxmf"))) {
- LOGD("midi\n");
+ LOGD("midi");
return TRUE;
}
__mmplayer_is_only_mp3_type(gchar *str_caps)
{
if (g_strrstr(str_caps, "application/x-id3") ||
- (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion= (int)1")))
+ (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion=(int)1")))
return TRUE;
return FALSE;
}
static void
-__mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps)
+__mmplayer_set_audio_attrs(mmplayer_t *player, GstCaps *caps)
{
- GstStructure* caps_structure = NULL;
+ GstStructure *caps_structure = NULL;
gint samplerate = 0;
gint channels = 0;
gst_structure_get_int(caps_structure, "channels", &channels);
mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
- LOGD("audio samplerate : %d channels : %d\n", samplerate, channels);
+ LOGD("audio samplerate : %d channels : %d", samplerate, channels);
}
static void
-__mmplayer_update_content_type_info(mm_player_t* player)
+__mmplayer_update_content_type_info(mmplayer_t *player)
{
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player && player->type);
if (__mmplayer_is_midi_type(player->type)) {
player->bypass_audio_effect = TRUE;
- } else if (g_strrstr(player->type, "application/x-hls")) {
+ return;
+ }
+
+ if (!player->streamer) {
+ LOGD("no need to check streaming type");
+ return;
+ }
+
+ if (g_strrstr(player->type, "application/x-hls")) {
/* If it can't know exact type when it parses uri because of redirection case,
* it will be fixed by typefinder or when doing autoplugging.
*/
player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
- if (player->streamer) {
- player->streamer->is_adaptive_streaming = TRUE;
- player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
- player->streamer->buffering_req.rebuffer_time = 5 * 1000;
- }
+ player->streamer->is_adaptive_streaming = TRUE;
} else if (g_strrstr(player->type, "application/dash+xml")) {
player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
- if (player->streamer) {
- player->streamer->is_adaptive_streaming = TRUE;
- player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
+ player->streamer->is_adaptive_streaming = TRUE;
+ }
+
+ /* in case of TS, fixed buffering mode should be used because player can not get exact duration time */
+ if ((player->streamer->is_adaptive_streaming) || (g_strrstr(player->type, "video/mpegts"))) {
+ player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
+
+ if (player->streamer->buffering_req.rebuffer_time <= MIN_BUFFERING_TIME) { /* if user did not set the rebuffer value */
+ if (player->streamer->is_adaptive_streaming)
+ player->streamer->buffering_req.rebuffer_time = DEFAULT_ADAPTIVE_REBUFFER_TIME;
+ else
+ player->streamer->buffering_req.rebuffer_time = DEFAULT_REBUFFERING_TIME;
}
}
- LOGD("uri type : %d", player->profile.uri_type);
+ LOGD("uri type : %d, %d", player->profile.uri_type, player->streamer->buffering_req.rebuffer_time);
MMPLAYER_FLEAVE();
}
-static void
+void
__mmplayer_typefind_have_type(GstElement *tf, guint probability,
-GstCaps *caps, gpointer data)
+ GstCaps *caps, gpointer data)
{
- mm_player_t* player = (mm_player_t*)data;
- GstPad* pad = NULL;
+ mmplayer_t *player = (mmplayer_t *)data;
+ GstPad *pad = NULL;
MMPLAYER_FENTER();
/* store type string */
MMPLAYER_FREEIF(player->type);
player->type = gst_caps_to_string(caps);
- if (player->type) {
- LOGD("[handle: %p] media type %s found, probability %d%% / %d\n",
+ if (player->type)
+ LOGD("[handle: %p] media type %s found, probability %d%% / %d",
player, player->type, probability, gst_caps_get_size(caps));
- }
if ((!MMPLAYER_IS_RTSP_STREAMING(player)) &&
(g_strrstr(player->type, "audio/x-raw-int"))) {
- LOGE("not support media format\n");
+ LOGE("not support media format");
if (player->msg_posted == FALSE) {
MMMessageParamType msg_param;
pad = gst_element_get_static_pad(tf, "src");
if (!pad) {
- LOGE("fail to get typefind src pad.\n");
+ LOGE("fail to get typefind src pad.");
return;
}
- if (!__mmplayer_try_to_plug_decodebin(player, pad, caps)) {
+ if (!__mmplayer_gst_create_decoder(player, pad, caps)) {
gboolean async = FALSE;
- LOGE("failed to autoplug %s\n", player->type);
+ LOGE("failed to autoplug %s", player->type);
mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
if (async && player->msg_posted == FALSE)
__mmplayer_handle_missed_plugin(player);
- goto DONE;
}
-DONE:
gst_object_unref(GST_OBJECT(pad));
MMPLAYER_FLEAVE();
return;
}
-static GstElement *
-__mmplayer_create_decodebin(mm_player_t* player)
+GstElement *
+__mmplayer_gst_make_decodebin(mmplayer_t *player)
{
GstElement *decodebin = NULL;
decodebin = gst_element_factory_make("decodebin", NULL);
if (!decodebin) {
- LOGE("fail to create decodebin\n");
+ LOGE("fail to create decodebin");
goto ERROR;
}
/* raw pad handling signal */
- MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
- G_CALLBACK(__mmplayer_gst_decode_pad_added), 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_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
- G_CALLBACK(__mmplayer_gst_decode_no_more_pads), 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_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
- G_CALLBACK(__mmplayer_gst_decode_pad_removed), 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_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
- G_CALLBACK(__mmplayer_gst_decode_unknown_type), 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_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
- G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), 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);
/* This signal is emitted whenever decodebin finds a new stream. It is emitted
before looking for any elements that can handle that stream.*/
- MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
- G_CALLBACK(__mmplayer_gst_decode_autoplug_select), 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_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
- G_CALLBACK(__mmplayer_gst_decode_drained), 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_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
- G_CALLBACK(__mmplayer_gst_element_added), 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;
}
-static gboolean
-__mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps)
+static GstElement *
+__mmplayer_gst_make_queue2(mmplayer_t *player)
{
- MMPlayerGstElement* mainbin = NULL;
- GstElement* decodebin = NULL;
- GstElement* queue2 = NULL;
- GstPad* sinkpad = NULL;
- GstPad* qsrcpad = NULL;
+ GstElement *queue2 = NULL;
gint64 dur_bytes = 0L;
-
- guint max_buffer_size_bytes = 0;
- gint init_buffering_time = player->streamer->buffering_req.prebuffer_time;
+ mmplayer_gst_element_t *mainbin = NULL;
+ muxed_buffer_type_e type = MUXED_BUFFER_TYPE_MEM_QUEUE;
MMPLAYER_FENTER();
- MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, FALSE);
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, NULL);
mainbin = player->pipeline->mainbin;
- if ((!MMPLAYER_IS_HTTP_PD(player)) &&
- (MMPLAYER_IS_HTTP_STREAMING(player))) {
- LOGD("creating http streaming buffering queue(queue2)\n");
+ queue2 = gst_element_factory_make("queue2", "queue2");
+ if (!queue2) {
+ LOGE("failed to create buffering queue element");
+ return NULL;
+ }
- if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst) {
- LOGE("MMPLAYER_M_MUXED_S_BUFFER is not null\n");
- } else {
- queue2 = gst_element_factory_make("queue2", "queue2");
- if (!queue2) {
- LOGE("failed to create buffering queue element\n");
- goto ERROR;
- }
+ if (!gst_element_query_duration(mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
+ LOGW("failed to get duration from source %s", GST_ELEMENT_NAME(mainbin[MMPLAYER_M_SRC].gst));
- if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2)) {
- LOGE("failed to add buffering queue\n");
- goto ERROR;
- }
+ LOGD("dur_bytes = %"G_GINT64_FORMAT, dur_bytes);
- sinkpad = gst_element_get_static_pad(queue2, "sink");
- qsrcpad = gst_element_get_static_pad(queue2, "src");
+ /* NOTE : in case of ts streaming, player could not get the correct duration info *
+ * skip the pull mode(file or ring buffering) setting. */
+ if (dur_bytes > 0) {
+ if (!g_strrstr(player->type, "video/mpegts")) {
+ type = MUXED_BUFFER_TYPE_MEM_RING_BUFFER;
+ player->streamer->ring_buffer_size = player->ini.http_ring_buffer_size;
+ }
+ } else {
+ dur_bytes = 0;
+ }
- if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
- LOGE("failed to link buffering queue");
- goto ERROR;
- }
+ __mm_player_streaming_set_queue2(player->streamer,
+ queue2,
+ FALSE,
+ type,
+ (guint64)dur_bytes); /* no meaning at the moment */
- if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
- LOGE("fail to get duration");
+ return queue2;
+}
- LOGD("dur_bytes = %"G_GINT64_FORMAT, dur_bytes);
+gboolean
+__mmplayer_gst_create_decoder(mmplayer_t *player, GstPad *srcpad, const GstCaps *caps)
+{
+ mmplayer_gst_element_t *mainbin = NULL;
+ GstElement *decodebin = NULL;
+ GstElement *queue2 = NULL;
+ GstPad *sinkpad = NULL;
+ GstPad *qsrcpad = NULL;
- MuxedBufferType type = MUXED_BUFFER_TYPE_MEM_QUEUE;
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, FALSE);
- if (dur_bytes > 0) {
- if (MMPLAYER_USE_FILE_FOR_BUFFERING(player)) {
- type = MUXED_BUFFER_TYPE_FILE;
- } else {
- type = MUXED_BUFFER_TYPE_MEM_RING_BUFFER;
- player->streamer->ring_buffer_size = player->ini.http_ring_buffer_size;
- }
- } else {
- dur_bytes = 0;
- }
+ mainbin = player->pipeline->mainbin;
- /* NOTE : in case of ts streaming, player cannot get the correct duration info *
- * skip the pull mode(file or ring buffering) setting. */
- if (!g_strrstr(player->type, "video/mpegts")) {
- max_buffer_size_bytes = (type == MUXED_BUFFER_TYPE_FILE) ? (player->ini.http_max_size_bytes) : (5*1024*1024);
- LOGD("max_buffer_size_bytes = %d", max_buffer_size_bytes);
-
- __mm_player_streaming_set_queue2(player->streamer,
- queue2,
- FALSE,
- max_buffer_size_bytes,
- player->ini.http_buffering_time,
- 1.0, /* no meaning */
- player->ini.http_buffering_limit, /* no meaning */
- type,
- player->http_file_buffering_path,
- (guint64)dur_bytes);
- }
+ if (MMPLAYER_IS_HTTP_STREAMING(player)) {
- if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(queue2)) {
- LOGE("failed to sync queue2 state with parent\n");
- goto ERROR;
- }
+ if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst) {
+ LOGW("need to check: muxed buffer is not null");
+ }
+
+ queue2 = __mmplayer_gst_make_queue2(player);
+ if (!queue2) {
+ LOGE("failed to make queue2");
+ goto ERROR;
+ }
- srcpad = qsrcpad;
+ if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2)) {
+ LOGE("failed to add buffering queue");
+ goto ERROR;
+ }
- gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = gst_element_get_static_pad(queue2, "sink");
+ qsrcpad = gst_element_get_static_pad(queue2, "src");
+
+ if (gst_pad_link(srcpad, sinkpad) != GST_PAD_LINK_OK) {
+ LOGE("failed to link [%s:%s]-[%s:%s]",
+ GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
+ goto ERROR;
+ }
- mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
- mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue2;
+ if (gst_element_sync_state_with_parent(queue2) == GST_STATE_CHANGE_FAILURE) {
+ LOGE("failed to sync queue2 state with parent");
+ goto ERROR;
}
+
+ mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
+ mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue2;
+
+ srcpad = qsrcpad;
+
+ gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
}
/* create decodebin */
- decodebin = __mmplayer_create_decodebin(player);
-
+ decodebin = __mmplayer_gst_make_decodebin(player);
if (!decodebin) {
- LOGE("can not create autoplug element\n");
+ LOGE("failed to make decodebin");
goto ERROR;
}
if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
- LOGE("failed to add decodebin\n");
+ LOGE("failed to add decodebin");
goto ERROR;
}
sinkpad = gst_element_get_static_pad(decodebin, "sink");
if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
- LOGE("failed to link decodebin\n");
+ LOGE("failed to link [%s:%s]-[%s:%s]",
+ GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
goto ERROR;
}
gst_object_unref(GST_OBJECT(sinkpad));
+ sinkpad = NULL;
+ gst_object_unref(GST_OBJECT(qsrcpad));
+ qsrcpad = NULL;
mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
mainbin[MMPLAYER_M_AUTOPLUG].gst = decodebin;
/* set decodebin property about buffer in streaming playback. *
* in case of HLS/DASH, it does not need to have big buffer *
* because it is kind of adaptive streaming. */
- if (!MMPLAYER_IS_HTTP_PD(player) &&
- (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING(player) || MMPLAYER_IS_DASH_STREAMING(player))) {
- gdouble high_percent = 0.0;
+ if (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING(player) || MMPLAYER_IS_DASH_STREAMING(player)) {
+ gint init_buffering_time = DEFAULT_PREBUFFERING_TIME;
+ gint high_percent = 0;
+
+ if (player->streamer->buffering_req.prebuffer_time > MIN_BUFFERING_TIME)
+ init_buffering_time = player->streamer->buffering_req.prebuffer_time;
- init_buffering_time = (init_buffering_time != 0) ? (init_buffering_time) : (player->ini.http_buffering_time);
- high_percent = (gdouble)(init_buffering_time * 100) / GET_MAX_BUFFER_TIME(player->streamer);
+ high_percent = (gint)ceil((gdouble)(init_buffering_time * 100) / MAX_BUFFER_SIZE_TIME);
- LOGD("decodebin setting - bytes: %d, time: %d ms, per: 1~%d",
- GET_MAX_BUFFER_BYTES(player->streamer), GET_MAX_BUFFER_TIME(player->streamer), (gint)high_percent);
+ LOGD("buffering time %d, per: 1~%d", init_buffering_time, high_percent);
g_object_set(G_OBJECT(decodebin), "use-buffering", TRUE,
- "high-percent", (gint)high_percent,
- "low-percent", (gint)DEFAULT_BUFFER_LOW_PERCENT,
- "max-size-bytes", GET_MAX_BUFFER_BYTES(player->streamer),
- "max-size-time", (guint64)(GET_MAX_BUFFER_TIME(player->streamer) * GST_MSECOND),
+ "high-percent", high_percent,
+ "max-size-bytes", MAX_BUFFER_SIZE_BYTES,
+ "max-size-time", (guint64)(MAX_BUFFER_SIZE_TIME * GST_MSECOND),
"max-size-buffers", 0, NULL); // disable or automatic
}
- if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin)) {
- LOGE("failed to sync decodebin state with parent\n");
+ if (gst_element_sync_state_with_parent(decodebin) == GST_STATE_CHANGE_FAILURE) {
+ LOGE("failed to sync decodebin state with parent");
goto ERROR;
}
if (sinkpad)
gst_object_unref(GST_OBJECT(sinkpad));
+ if (qsrcpad)
+ gst_object_unref(GST_OBJECT(qsrcpad));
+
if (queue2) {
/* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
* You need to explicitly set elements to the NULL state before
}
static int
-__mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime)
+__mmplayer_check_not_supported_codec(mmplayer_t *player, const gchar *factory_class, const gchar *mime)
{
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
MMPLAYER_RETURN_VAL_IF_FAIL(mime, MM_ERROR_INVALID_ARGUMENT);
- LOGD("class : %s, mime : %s \n", factory_class, mime);
+ LOGD("class : %s, mime : %s", factory_class, mime);
/* add missing plugin */
/* NOTE : msl should check missing plugin for image mime type.
*/
if (!(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst)) {
if (!(player->can_support_codec | player->videodec_linked | player->audiodec_linked)) {
- LOGD("not found demuxer\n");
+ LOGD("not found demuxer");
player->not_found_demuxer = TRUE;
player->unlinked_demuxer_mime = g_strdup_printf("%s", mime);
if (!g_strrstr(factory_class, "Demuxer")) {
if ((g_str_has_prefix(mime, "video")) || (g_str_has_prefix(mime, "image"))) {
- LOGD("can support codec=0x%X, vdec_linked=%d, adec_linked=%d\n",
+ LOGD("can support codec=0x%X, vdec_linked=%d, adec_linked=%d",
player->can_support_codec, player->videodec_linked, player->audiodec_linked);
/* check that clip have multi tracks or not */
if ((player->can_support_codec & FOUND_PLUGIN_VIDEO) && (player->videodec_linked)) {
- LOGD("video plugin is already linked\n");
+ LOGD("video plugin is already linked");
} else {
- LOGW("add VIDEO to missing plugin\n");
+ LOGW("add VIDEO to missing plugin");
player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
player->unlinked_video_mime = g_strdup_printf("%s", mime);
}
} else if (g_str_has_prefix(mime, "audio")) {
if ((player->can_support_codec & FOUND_PLUGIN_AUDIO) && (player->audiodec_linked)) {
- LOGD("audio plugin is already linked\n");
+ LOGD("audio plugin is already linked");
} else {
- LOGW("add AUDIO to missing plugin\n");
+ LOGW("add AUDIO to missing plugin");
player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
player->unlinked_audio_mime = g_strdup_printf("%s", mime);
}
return MM_ERROR_NONE;
}
-
static void
__mmplayer_pipeline_complete(GstElement *decodebin, gpointer data)
{
- mm_player_t* player = (mm_player_t*)data;
+ mmplayer_t *player = (mmplayer_t *)data;
MMPLAYER_FENTER();
MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-complete");
}
+static int
+__mmplayer_check_profile(void)
+{
+ char *profileName;
+ static int profile_tv = -1;
+
+ if (__builtin_expect(profile_tv != -1, 1))
+ return profile_tv;
+
+ system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
+ switch (*profileName) {
+ case 't':
+ case 'T':
+ profile_tv = 1;
+ break;
+ default:
+ profile_tv = 0;
+ break;
+ }
+ free(profileName);
+
+ return profile_tv;
+}
+
static gboolean
-__mmplayer_verify_next_play_path(mm_player_t *player)
+__mmplayer_get_next_uri(mmplayer_t *player)
{
- MMHandleType attrs = 0;
- MMPlayerParseProfile profile;
- gint uri_idx = 0, check_cnt = 0;
+ mmplayer_parse_profile_t profile;
+ gint uri_idx = 0;
+ guint num_of_list = 0;
char *uri = NULL;
- gint mode = MM_PLAYER_PD_MODE_NONE;
+
+ num_of_list = g_list_length(player->uri_info.uri_list);
+ uri_idx = player->uri_info.uri_idx;
+
+ LOGD("num of uri list = %d, current uri idx %d", num_of_list, uri_idx);
+ for (uri_idx++; uri_idx < num_of_list; uri_idx++) {
+ uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
+ if (!uri) {
+ LOGW("next uri does not exist");
+ continue;
+ }
+
+ if (__mmplayer_parse_profile((const char *)uri, NULL, &profile) != MM_ERROR_NONE) {
+ LOGE("failed to parse profile");
+ continue;
+ }
+
+ if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) &&
+ (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP)) {
+ LOGW("uri type is not supported(%d)", profile.uri_type);
+ continue;
+ }
+
+ LOGD("success to find next uri %d", uri_idx);
+ break;
+ }
+
+ if (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");
+ return FALSE;
+ }
+
+ SECURE_LOGD("next playback uri: %s", uri);
+ return TRUE;
+}
+
+static gboolean
+__mmplayer_verify_gapless_play_path(mmplayer_t *player)
+{
+#define REPEAT_COUNT_INFINITELY -1
+#define REPEAT_COUNT_MIN 2
+
+ MMHandleType attrs = 0;
gint video = 0;
gint count = 0;
gint gapless = 0;
guint num_of_list = 0;
- static int profile_tv = -1;
+ int profile_tv = -1;
MMPLAYER_FENTER();
- LOGD("checking for gapless play");
+ LOGD("checking for gapless play option");
if (player->pipeline->textbin) {
- LOGE("subtitle path is enabled. gapless play is not supported.\n");
+ LOGE("subtitle path is enabled. gapless play is not supported.");
goto ERROR;
}
attrs = MMPLAYER_GET_ATTRS(player);
if (!attrs) {
- LOGE("fail to get attributes.\n");
+ LOGE("fail to get attributes.");
goto ERROR;
}
mm_attrs_get_int_by_name(attrs, "content_video_found", &video);
- if (__builtin_expect(profile_tv == -1, 0)) {
- char *profileName;
- system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
- switch (*profileName) {
- case 't':
- case 'T':
- profile_tv = 1;
- break;
- default:
- profile_tv = 0;
- }
- free(profileName);
- }
/* gapless playback is not supported in case of video at TV profile. */
+ profile_tv = __mmplayer_check_profile();
if (profile_tv && video) {
LOGW("not support video gapless playback");
goto ERROR;
}
- if (mm_attrs_get_int_by_name(attrs, "pd_mode", &mode) == MM_ERROR_NONE) {
- if (mode == TRUE) {
- LOGW("pd mode\n");
- goto ERROR;
- }
- }
-
if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
- LOGE("can not get play count\n");
+ LOGE("failed to get play count");
if (mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless) != MM_ERROR_NONE)
- LOGE("can not get gapless mode\n");
+ LOGE("failed to get gapless mode");
- if (video && !gapless) {
- LOGW("not enabled video gapless playback");
- goto ERROR;
- }
-
- if ((count == -1 || count > 1)) /* enable gapless when looping or repeat */
- gapless = 1;
-
- if (!gapless) {
- LOGW("gapless is disabled\n"); /* FIXME: playlist(without gapless) is not implemented. */
+ /* check repeat count in case of audio */
+ if (!gapless &&
+ (video || (count != REPEAT_COUNT_INFINITELY && count < REPEAT_COUNT_MIN))) {
+ LOGW("gapless is disabled");
goto ERROR;
}
num_of_list = g_list_length(player->uri_info.uri_list);
- LOGD("repeat count = %d, num_of_list = %d\n", count, num_of_list);
+ LOGD("repeat count = %d, num_of_list = %d", count, num_of_list);
if (num_of_list == 0) {
- if (mm_attrs_get_string_by_name(player->attrs, "profile_uri", &uri) != MM_ERROR_NONE) {
- LOGE("can not get profile_uri\n");
- goto ERROR;
- }
-
- if (!uri) {
- LOGE("uri list is empty.\n");
+ /* 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) {
+ LOGD("there is no next uri and no repeat");
goto ERROR;
}
-
- player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
- LOGD("add original path : %s ", uri);
-
- num_of_list = 1;
- uri = NULL;
- }
-
- uri_idx = player->uri_info.uri_idx;
-
- while (TRUE) {
- check_cnt++;
-
- if (check_cnt > num_of_list) {
- LOGE("there is no valid uri.");
+ LOGD("looping cnt %d", count);
+ } else {
+ /* gapless playback path */
+ if (!__mmplayer_get_next_uri(player)) {
+ LOGE("failed to get next uri");
goto ERROR;
}
-
- LOGD("uri idx : %d / %d\n", uri_idx, num_of_list);
-
- if (uri_idx < num_of_list-1) {
- uri_idx++;
- } else {
- if ((count <= 1) && (count != -1)) {
- LOGD("no repeat.");
- goto ERROR;
- } else if (count > 1) {
- /* 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 (mmf_attrs_commit(attrs))
- LOGE("failed to commit attribute\n");
- }
-
- /* count < 0 : repeat continually */
- uri_idx = 0;
- }
-
- uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
- LOGD("uri idx : %d, uri = %s\n", uri_idx, uri);
-
- if (uri == NULL) {
- LOGW("next uri does not exist\n");
- continue;
- }
-
- if (__mmplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE) {
- LOGE("failed to parse profile\n");
- continue;
- }
-
- if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) &&
- (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP)) {
- LOGW("uri type is not supported(%d).", profile.uri_type);
- continue;
- }
-
- break;
- }
-
- player->uri_info.uri_idx = uri_idx;
- mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
-
- if (mmf_attrs_commit(player->attrs)) {
- LOGE("failed to commit.\n");
- goto ERROR;
}
-
- LOGD("next uri %s(%d)\n", uri, uri_idx);
-
return TRUE;
ERROR:
-
- LOGE("unable to play next path. EOS will be posted soon.\n");
+ LOGE("unable to play gapless path. EOS will be posted soon");
return FALSE;
}
static void
-__mmplayer_initialize_next_play(mm_player_t *player)
+__mmplayer_initialize_gapless_play(mmplayer_t *player)
{
int i;
player->smooth_streaming = FALSE;
player->videodec_linked = 0;
player->audiodec_linked = 0;
- player->videosink_linked = 0;
- player->audiosink_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.format = MM_PLAYER_POS_FORMAT_TIME;
+ 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->max_audio_channels = 0;
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_track_initialize(player);
__mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) {
mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
- /* clean found parsers */
- if (player->parsers) {
- GList *parsers = player->parsers;
- for (; parsers; parsers = g_list_next(parsers)) {
- gchar *name = parsers->data;
- MMPLAYER_FREEIF(name);
- }
- g_list_free(player->parsers);
- player->parsers = NULL;
- }
-
/* clean found audio decoders */
if (player->audio_decoders) {
GList *a_dec = player->audio_decoders;
}
static void
-__mmplayer_activate_next_source(mm_player_t *player, GstState target)
+__mmplayer_activate_next_source(mmplayer_t *player, GstState target)
{
- MMPlayerGstElement *mainbin = NULL;
+ mmplayer_gst_element_t *mainbin = NULL;
MMMessageParamType msg_param = {0,};
GstElement *element = NULL;
MMHandleType attrs = 0;
char *uri = NULL;
- enum MainElementID elemId = MMPLAYER_M_NUM;
+ main_element_id_e elem_idx = MMPLAYER_M_NUM;
MMPLAYER_FENTER();
- if ((player == NULL) ||
- (player->pipeline == NULL) ||
- (player->pipeline->mainbin == NULL)) {
- LOGE("player is null.\n");
+ if (!player || !player->pipeline || !player->pipeline->mainbin) {
+ LOGE("player is not initialized");
goto ERROR;
}
attrs = MMPLAYER_GET_ATTRS(player);
if (!attrs) {
- LOGE("fail to get attributes.\n");
+ LOGE("fail to get attributes");
goto ERROR;
}
/* Initialize Player values */
- __mmplayer_initialize_next_play(player);
+ __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\n");
+ 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("it's dash or hls. not support.");
+ LOGE("dash or hls is not supportable");
msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
goto ERROR;
}
- /* setup source */
- switch (player->profile.uri_type) {
- /* file source */
- case MM_PLAYER_URI_TYPE_FILE:
- {
- LOGD("using filesrc for 'file://' handler.\n");
- if (!util_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
- LOGE("failed to get storage info");
- break;
- }
-
- element = gst_element_factory_make("filesrc", "source");
-
- if (!element) {
- LOGE("failed to create filesrc\n");
- break;
- }
-
- g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL); /* uri+7 -> remove "file:// */
- break;
- }
- case MM_PLAYER_URI_TYPE_URL_HTTP:
- {
- gchar *user_agent, *cookies, **cookie_list;
- gint http_timeout = DEFAULT_HTTP_TIMEOUT;
- user_agent = cookies = NULL;
- cookie_list = NULL;
-
- element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
- if (!element) {
- LOGE("failed to create http streaming source element[%s].\n", player->ini.httpsrc_element);
- break;
- }
- LOGD("using http streamming source [%s].\n", player->ini.httpsrc_element);
-
- /* get attribute */
- mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
- mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
-
- if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT) {
- LOGD("get timeout from ini\n");
- http_timeout = player->ini.http_timeout;
- }
-
- /* get attribute */
- SECURE_LOGD("location : %s\n", player->profile.uri);
- SECURE_LOGD("cookies : %s\n", cookies);
- SECURE_LOGD("user_agent : %s\n", user_agent);
- LOGD("timeout : %d\n", http_timeout);
-
- /* setting property to streaming source */
- g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
- g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
- g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
-
- /* parsing cookies */
- if ((cookie_list = util_get_cookie_list((const char*)cookies)))
- g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
- if (user_agent)
- g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
- break;
- }
- default:
- LOGE("not support uri type %d\n", player->profile.uri_type);
- break;
- }
-
+ element = __mmplayer_gst_create_source(player);
if (!element) {
- LOGE("no source element was created.\n");
+ 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\n");
+ LOGE("failed to add source element to pipeline");
gst_object_unref(GST_OBJECT(element));
element = NULL;
goto ERROR;
if (MMPLAYER_IS_HTTP_STREAMING(player)) {
if (player->streamer == NULL) {
player->streamer = __mm_player_streaming_create();
- __mm_player_streaming_initialize(player->streamer);
+ __mm_player_streaming_initialize(player->streamer, TRUE);
}
- elemId = MMPLAYER_M_TYPEFIND;
+ elem_idx = MMPLAYER_M_TYPEFIND;
element = gst_element_factory_make("typefind", "typefinder");
- MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
- G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player);
+ __mmplayer_add_signal_connection(player, G_OBJECT(element),
+ MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type", G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player);
} else {
- elemId = MMPLAYER_M_AUTOPLUG;
- element = __mmplayer_create_decodebin(player);
+ elem_idx = MMPLAYER_M_AUTOPLUG;
+ element = __mmplayer_gst_make_decodebin(player);
}
/* check autoplug element is OK */
if (!element) {
- LOGE("can not create element(%d)\n", elemId);
+ 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\n");
+ LOGE("failed to add sinkbin to pipeline");
gst_object_unref(GST_OBJECT(element));
element = NULL;
goto ERROR;
}
- mainbin[elemId].id = elemId;
- mainbin[elemId].gst = element;
+ mainbin[elem_idx].id = elem_idx;
+ mainbin[elem_idx].gst = element;
- if (gst_element_link(mainbin[MMPLAYER_M_SRC].gst, mainbin[elemId].gst) == FALSE) {
- LOGE("Failed to link src - autoplug(or typefind)\n");
+ if (gst_element_link(mainbin[MMPLAYER_M_SRC].gst, mainbin[elem_idx].gst) == FALSE) {
+ LOGE("Failed to link src - autoplug(or typefind)");
goto ERROR;
}
if (gst_element_set_state(mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE) {
- LOGE("Failed to change state of src element\n");
+ LOGE("Failed to change state of src element");
goto ERROR;
}
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\n");
+ 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\n");
+ LOGE("Failed to change state of src element");
goto ERROR;
}
}
}
static gboolean
-__mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type)
+__mmplayer_deactivate_selector(mmplayer_t *player, mmplayer_track_type_e type)
{
- mm_player_selector_t *selector = &player->selector[type];
- MMPlayerGstElement *sinkbin = NULL;
- enum MainElementID selectorId = MMPLAYER_M_NUM;
- enum MainElementID sinkId = MMPLAYER_M_NUM;
+ mmplayer_selector_t *selector = &player->selector[type];
+ mmplayer_gst_element_t *sinkbin = NULL;
+ main_element_id_e selectorId = MMPLAYER_M_NUM;
+ main_element_id_e sinkId = MMPLAYER_M_NUM;
GstPad *srcpad = NULL;
GstPad *sinkpad = NULL;
gboolean send_notice = FALSE;
/* 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("application/flush-buffer");
+ 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);
}
}
static void
-__mmplayer_deactivate_old_path(mm_player_t *player)
+__mmplayer_deactivate_old_path(mmplayer_t *player)
{
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player);
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_deinitialize(player->streamer);
+ __mm_player_streaming_initialize(player->streamer, FALSE);
__mm_player_streaming_destroy(player->streamer);
player->streamer = NULL;
}
MMPLAYER_PLAYBACK_LOCK(player);
- MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
+ MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player);
MMPLAYER_FLEAVE();
return;
/*post error*/
msg.code = MM_ERROR_PLAYER_INTERNAL;
- LOGE("next_uri_play> deactivate error");
+ LOGE("gapless_uri_play> deactivate error");
MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
player->msg_posted = TRUE;
return;
}
-int _mmplayer_set_file_buffering_path(MMHandleType hplayer, const char* file_path)
-{
- int result = MM_ERROR_NONE;
- mm_player_t* player = (mm_player_t*) hplayer;
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- if (file_path) {
- player->http_file_buffering_path = (gchar*)file_path;
- LOGD("temp file path: %s\n", player->http_file_buffering_path);
- }
- MMPLAYER_FLEAVE();
- return result;
-}
-
-int _mmplayer_set_uri(MMHandleType hplayer, const char* uri)
+int
+_mmplayer_set_uri(MMHandleType hplayer, const char *uri)
{
int result = MM_ERROR_NONE;
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
- if (mmf_attrs_commit(player->attrs)) {
- LOGE("failed to commit the original uri.\n");
+ if (mm_attrs_commit_all(player->attrs)) {
+ LOGE("failed to commit the original uri.");
result = MM_ERROR_PLAYER_INTERNAL;
} else {
if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE)
- LOGE("failed to add the original uri in the uri list.\n");
+ LOGE("failed to add the original uri in the uri list.");
}
MMPLAYER_FLEAVE();
return result;
}
-int _mmplayer_set_next_uri(MMHandleType hplayer, const char* uri, bool is_first_path)
+int
+_mmplayer_set_next_uri(MMHandleType hplayer, const char *uri, bool is_first_path)
{
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
guint num_of_list = 0;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(uri, MM_ERROR_INVALID_ARGUMENT);
if (player->pipeline && player->pipeline->textbin) {
- LOGE("subtitle path is enabled.\n");
+ LOGE("subtitle path is enabled.");
return MM_ERROR_PLAYER_INVALID_STATE;
}
num_of_list = g_list_length(player->uri_info.uri_list);
- if (is_first_path == TRUE) {
+ if (is_first_path) {
if (num_of_list == 0) {
player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
- LOGD("add original path : %s", uri);
+ SECURE_LOGD("add original path : %s", uri);
} else {
player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0));
player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0);
- LOGD("change original path : %s", uri);
+ SECURE_LOGD("change original path : %s", uri);
}
} else {
MMHandleType attrs = 0;
player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(original_uri));
player->uri_info.uri_idx = 0;
- LOGD("add original path at first : %s(%d)", original_uri);
+ SECURE_LOGD("add original path at first : %s", original_uri);
}
}
player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
- LOGD("add new path : %s(total num of list = %d)", uri, g_list_length(player->uri_info.uri_list));
+ SECURE_LOGD("add new path : %s(total num of list = %d)", uri, g_list_length(player->uri_info.uri_list));
}
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
}
-int _mmplayer_get_next_uri(MMHandleType hplayer, char** uri)
+int
+_mmplayer_get_next_uri(MMHandleType hplayer, char **uri)
{
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
char *next_uri = NULL;
guint num_of_list = 0;
uri_idx = 0;
next_uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
- LOGE("next uri idx : %d, uri = %s\n", uri_idx, next_uri);
+ LOGE("next uri idx : %d, uri = %s", uri_idx, next_uri);
*uri = g_strdup(next_uri);
}
}
static void
-__mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad* pad,
-GstCaps *caps, gpointer data)
+__mmplayer_gst_decode_unknown_type(GstElement *elem, GstPad *pad,
+ GstCaps *caps, gpointer data)
{
- mm_player_t* player = (mm_player_t*)data;
- const gchar* klass = NULL;
- const gchar* mime = NULL;
- gchar* caps_str = NULL;
+ mmplayer_t *player = (mmplayer_t *)data;
+ const gchar *klass = NULL;
+ const gchar *mime = NULL;
+ gchar *caps_str = NULL;
klass = gst_element_factory_get_metadata(gst_element_get_factory(elem), GST_ELEMENT_METADATA_KLASS);
mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
}
static gboolean
-__mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad* pad,
-GstCaps * caps, gpointer data)
+__mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad,
+ GstCaps *caps, gpointer data)
{
- mm_player_t* player = (mm_player_t*)data;
- const char* mime = NULL;
+ mmplayer_t *player = (mmplayer_t *)data;
+ const char *mime = NULL;
gboolean ret = TRUE;
MMPLAYER_LOG_GST_CAPS_TYPE(caps);
mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
if (g_str_has_prefix(mime, "audio")) {
- GstStructure* caps_structure = NULL;
+ GstStructure *caps_structure = NULL;
gint samplerate = 0;
gint channels = 0;
gchar *caps_str = NULL;
return ret;
}
-static int
-__mmplayer_check_codec_info(mm_player_t* player, const char* klass, GstCaps* caps, char* factory_name)
+static gboolean
+__mmplayer_is_audio_offload_device_type(mmplayer_t *player)
{
- int ret = MM_ERROR_NONE;
- int idx = 0;
- int codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT;
+ gboolean ret = TRUE;
+ GDBusConnection *conn = NULL;
+ GError *err = NULL;
+ GVariant *result = NULL;
+ const gchar *dbus_device_type = NULL;
+ const gchar *dbus_ret = NULL;
+ gint idx = 0;
- if ((g_strrstr(klass, "Codec/Decoder/Audio"))) {
- GstStructure* str = NULL;
- gint channels = 0;
- mm_attrs_get_int_by_name(player->attrs, "audio_codec_type", &codec_type);
+ 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);
+ g_error_free(err);
+ ret = FALSE;
+ goto DONE;
+ }
- 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 = MM_ERROR_PLAYER_INTERNAL;
- 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 = MM_ERROR_PLAYER_INTERNAL;
- goto DONE;
- }
- }
+ result = g_dbus_connection_call_sync(conn,
+ "org.pulseaudio.Server",
+ "/org/pulseaudio/StreamManager",
+ "org.pulseaudio.StreamManager",
+ "GetCurrentMediaRoutingPath",
+ g_variant_new("(s)", "out"),
+ G_VARIANT_TYPE("(ss)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ 2000,
+ NULL,
+ &err);
+ if (!result || err) {
+ LOGE("failed g_dbus_connection_call_sync() (%s)", err ? err->message : NULL);
+ g_error_free(err);
+ ret = FALSE;
+ goto DONE;
+ }
- str = gst_caps_get_structure(caps, 0);
- if (str) {
- gst_structure_get_int(str, "channels", &channels);
+ /* device type is listed in stream-map.json at mmfw-sysconf */
+ 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;
+ goto DONE;
+ }
- LOGD("check audio ch : %d %d\n", player->max_audio_channels, channels);
- if (player->max_audio_channels < channels)
- player->max_audio_channels = channels;
+ /* 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++) {
+ if (strstr(dbus_device_type, player->ini.audio_offload_device_type[idx])) {
+ LOGD("audio offload is supportable");
+ ret = TRUE;
+ goto DONE;
}
- /* set stream information */
- if (!player->audiodec_linked)
- __mmplayer_set_audio_attrs(player, caps);
+ }
- /* update codec info */
- player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
- player->can_support_codec |= FOUND_PLUGIN_AUDIO;
+ LOGD("audio offload is not supportable");
+ ret = FALSE;
+
+DONE:
+ g_variant_unref(result);
+ g_object_unref(conn);
+
+ return ret;
+}
+
+static void __mmplayer_rebuild_audio_pipeline(mmplayer_t *player)
+{
+ mmplayer_state_e current_state = MM_PLAYER_STATE_NONE;
+ gint64 position = 0;
+
+ MMPLAYER_RETURN_IF_FAIL(player && player->attrs &&
+ player->pipeline && player->pipeline->mainbin);
+
+ MMPLAYER_CMD_LOCK(player);
+ current_state = MMPLAYER_CURRENT_STATE(player);
+
+ if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position))
+ LOGW("getting current position failed in paused");
+
+ _mmplayer_unrealize((MMHandleType)player);
+ _mmplayer_realize((MMHandleType)player);
+
+ _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");
+
+ _mmplayer_pause((MMHandleType)player);
+
+ if (current_state == MM_PLAYER_STATE_PLAYING)
+ _mmplayer_start((MMHandleType)player);
+ MMPLAYER_CMD_UNLOCK(player);
+
+ LOGD("rebuilding audio pipeline is completed.");
+}
+
+void __mmplayer_audio_device_connected_cb(MMSoundDevice_t device_h, bool is_connected, void *user_data)
+{
+ mmplayer_t *player = (mmplayer_t *)user_data;
+ mm_sound_device_type_e dev_type = MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER;
+ gboolean is_supportable = FALSE;
+
+ if (mm_sound_get_device_type(device_h, &dev_type) != MM_ERROR_NONE)
+ LOGW("failed to get device type");
+ else
+ LOGD("dev type (%d), connected (%d)", dev_type, is_connected);
+
+ if ((dev_type != MM_SOUND_DEVICE_TYPE_BLUETOOTH_A2DP) &&
+ (dev_type != MM_SOUND_DEVICE_TYPE_AUDIOJACK) &&
+ (dev_type != MM_SOUND_DEVICE_TYPE_USB_AUDIO)) {
+ LOGD("ignore this dev connected info");
+ return;
+ }
+
+ is_supportable = __mmplayer_is_audio_offload_device_type(player);
+ if (player->build_audio_offload == is_supportable) {
+ LOGD("keep current pipeline without re-building");
+ return;
+ }
+
+ /* rebuild pipeline */
+ LOGD("re-build pipeline - offload: %d", is_supportable);
+ player->build_audio_offload = FALSE;
+ __mmplayer_rebuild_audio_pipeline(player);
+
+ return;
+}
+
+static gboolean
+__mmplayer_add_audio_device_connected_cb(mmplayer_t *player)
+{
+ unsigned int id = 0;
+
+ if (player->audio_device_cb_id != 0) {
+ LOGW("audio device connected cb was already added (%u)", player->audio_device_cb_id);
+ return TRUE;
+ }
+
+ if (mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_IO_DIRECTION_OUT_FLAG,
+ __mmplayer_audio_device_connected_cb, player, &id) == MM_ERROR_NONE) {
+ LOGD("added device connected cb (%u)", id);
+ player->audio_device_cb_id = id;
+ } else {
+ LOGW("failed to add device connected cb");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+__mmplayer_can_build_audio_offload_path(mmplayer_t *player)
+{
+ gboolean ret = FALSE;
+ GstElementFactory *factory = NULL;
+
+ MMPLAYER_FENTER();
+ 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))
+ goto DONE;
+
+ if (!strcmp(player->ini.audio_offload_sink_element, "")) {
+ LOGD("there is no audio offload sink");
+ goto DONE;
+ }
+
+ if (player->ini.audio_offload_device_type[0][0] == '\0') {
+ LOGW("there is no audio device type to support offload");
+ goto DONE;
+ }
+
+ factory = gst_element_factory_find(player->ini.audio_offload_sink_element);
+ if (!factory) {
+ LOGW("there is no installed audio offload sink element");
+ goto DONE;
+ }
+ gst_object_unref(factory);
+
+ if (!__mmplayer_add_audio_device_connected_cb(player))
+ goto DONE;
+
+ if (!__mmplayer_is_audio_offload_device_type(player))
+ goto DONE;
+
+ LOGD("audio offload can be built");
+ ret = TRUE;
+
+DONE:
+ MMPLAYER_FLEAVE();
+ return ret;
+}
+
+static GstAutoplugSelectResult
+__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"))) {
+ mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_OFFLOAD, &audio_offload); /* user requirement */
+
+ if (audio_offload && __mmplayer_can_build_audio_offload_path(player)) {
+ LOGD("expose audio path to build offload output path");
+ player->build_audio_offload = TRUE;
+ /* update codec info */
+ player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
+ player->can_support_codec |= FOUND_PLUGIN_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;
+ }
+ }
+
+ /* set stream information */
+ if (!player->audiodec_linked)
+ __mmplayer_set_audio_attrs(player, caps);
+
+ /* 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")) {
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 = MM_ERROR_PLAYER_INTERNAL;
+ ret = GST_AUTOPLUG_SELECT_SKIP;
goto DONE;
}
}
/* 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 = MM_ERROR_PLAYER_INTERNAL;
+ ret = GST_AUTOPLUG_SELECT_SKIP;
goto DONE;
}
}
&player->video_decoder_resource)
!= MM_RESOURCE_MANAGER_ERROR_NONE) {
LOGE("could not mark video_decoder resource for acquire");
- ret = MM_ERROR_PLAYER_INTERNAL;
+ ret = GST_AUTOPLUG_SELECT_SKIP;
goto DONE;
}
} else {
LOGW("video decoder resource is already acquired, skip it.");
- ret = MM_ERROR_PLAYER_INTERNAL;
+ ret = GST_AUTOPLUG_SELECT_SKIP;
goto DONE;
}
/* 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\n");
- ret = MM_ERROR_PLAYER_INTERNAL;
+ LOGE("could not acquire resources for video decoding");
+ ret = GST_AUTOPLUG_SELECT_SKIP;
goto DONE;
}
}
return ret;
}
-static gint
-__mmplayer_gst_decode_autoplug_select(GstElement *bin, GstPad* pad,
-GstCaps* caps, GstElementFactory* factory, gpointer data)
+gint
+__mmplayer_gst_decode_autoplug_select(GstElement *bin, GstPad *pad,
+ GstCaps *caps, GstElementFactory *factory, gpointer data)
{
- /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
- We are defining our own and will be removed when it actually exposed */
- typedef enum {
- GST_AUTOPLUG_SELECT_TRY,
- GST_AUTOPLUG_SELECT_EXPOSE,
- GST_AUTOPLUG_SELECT_SKIP
- } GstAutoplugSelectResult;
-
GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
- mm_player_t* player = (mm_player_t*)data;
+ mmplayer_t *player = (mmplayer_t *)data;
- gchar* factory_name = NULL;
- gchar* caps_str = NULL;
- const gchar* klass = NULL;
+ gchar *factory_name = NULL;
+ gchar *caps_str = NULL;
+ const gchar *klass = NULL;
gint idx = 0;
factory_name = GST_OBJECT_NAME(factory);
/* 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]\n",
+ LOGW("skipping [%s] by exculde keyword [%s]",
factory_name, player->ini.exclude_element_keyword[idx]);
result = GST_AUTOPLUG_SELECT_SKIP;
}
}
+ for (idx = 0; player->ini.unsupported_codec_keyword[idx][0] != '\0'; idx++) {
+ if (caps_str && strstr(caps_str, player->ini.unsupported_codec_keyword[idx])) {
+ LOGW("skipping [%s] by unsupported codec keyword [%s]",
+ factory_name, player->ini.unsupported_codec_keyword[idx]);
+ result = GST_AUTOPLUG_SELECT_SKIP;
+ goto DONE;
+ }
+ }
+
/* exclude webm format */
/* NOTE : MSL have to post MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT
* because webm format is not supportable.
* So, those plugins should be skipped for error handling.
*/
if (g_strrstr(klass, "Codec/Decoder/Image")) {
- LOGD("skipping [%s] by not required\n", factory_name);
+ LOGD("skipping [%s] by not required", factory_name);
result = GST_AUTOPLUG_SELECT_SKIP;
goto DONE;
}
if ((MMPLAYER_IS_MS_BUFF_SRC(player)) &&
(g_strrstr(klass, "Codec/Demuxer") || (g_strrstr(klass, "Codec/Parser")))) {
// TO CHECK : subtitle if needed, add subparse exception.
- LOGD("skipping parser/demuxer [%s] in es player by not required\n", factory_name);
+ LOGD("skipping parser/demuxer [%s] in es player by not required", factory_name);
result = GST_AUTOPLUG_SELECT_SKIP;
goto DONE;
}
if (g_strrstr(factory_name, "mpegpsdemux")) {
- LOGD("skipping PS container - not support\n");
+ LOGD("skipping PS container - not support");
result = GST_AUTOPLUG_SELECT_SKIP;
goto DONE;
}
/* don't make video because of not required */
if ((stype == MM_DISPLAY_SURFACE_NULL) &&
- (player->set_mode.media_packet_video_stream == FALSE)) {
- LOGD("no video because it's not required. -> return expose");
+ (!player->set_mode.video_export)) {
+ LOGD("no need video decoding, expose pad");
result = GST_AUTOPLUG_SELECT_EXPOSE;
goto DONE;
}
}
if (g_strrstr(klass, "Codec/Decoder")) {
- if (__mmplayer_check_codec_info(player, klass, caps, factory_name) != MM_ERROR_NONE) {
- LOGD("skipping %s codec", factory_name);
- result = GST_AUTOPLUG_SELECT_SKIP;
+ result = __mmplayer_check_codec_info(player, klass, caps, factory_name);
+ if (result != GST_AUTOPLUG_SELECT_TRY) {
+ LOGW("skip add decoder");
goto DONE;
}
}
}
static void
-__mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad* new_pad,
-gpointer data)
+__mmplayer_gst_decode_pad_removed(GstElement *elem, GstPad *new_pad,
+ gpointer data)
{
- //mm_player_t* player = (mm_player_t*)data;
- GstCaps* caps = NULL;
+ //mmplayer_t *player = (mmplayer_t *)data;
+ GstCaps *caps = NULL;
- LOGD("[Decodebin2] pad-removed signal\n");
+ LOGD("[Decodebin2] pad-removed signal");
caps = gst_pad_query_caps(new_pad, NULL);
- if (caps) {
- gchar* caps_str = NULL;
- caps_str = gst_caps_to_string(caps);
+ if (!caps) {
+ LOGW("query caps is NULL");
+ return;
+ }
- LOGD("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem));
+ gchar *caps_str = NULL;
+ caps_str = gst_caps_to_string(caps);
- MMPLAYER_FREEIF(caps_str);
- gst_caps_unref(caps);
- }
+ LOGD("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem));
+
+ MMPLAYER_FREEIF(caps_str);
+ gst_caps_unref(caps);
}
static void
__mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
{
- mm_player_t* player = (mm_player_t*)data;
+ mmplayer_t *player = (mmplayer_t *)data;
GstIterator *iter = NULL;
GValue item = { 0, };
GstPad *pad = NULL;
LOGD("__mmplayer_gst_decode_drained");
- if (player->use_deinterleave == TRUE) {
- LOGD("group playing mode.");
- return;
- }
-
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_next_play_path(player)) {
+ !__mmplayer_verify_gapless_play_path(player)) {
LOGD("decoding is finished.");
__mmplayer_reset_gapless_state(player);
MMPLAYER_CMD_UNLOCK(player);
MMPLAYER_FLEAVE();
}
-static void
+void
__mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
{
- mm_player_t* player = (mm_player_t*)data;
- const gchar* klass = NULL;
- gchar* factory_name = NULL;
+ mmplayer_t *player = (mmplayer_t *)data;
+ const gchar *klass = NULL;
+ gchar *factory_name = NULL;
klass = gst_element_factory_get_metadata(gst_element_get_factory(element), GST_ELEMENT_METADATA_KLASS);
factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
- LOGD("new elem klass: %s, factory_name: %s, new elem name : %s\n", klass, factory_name, GST_ELEMENT_NAME(element));
+ LOGD("new elem klass: %s, factory_name: %s, new elem name : %s", klass, factory_name, GST_ELEMENT_NAME(element));
if (__mmplayer_add_dump_buffer_probe(player, element))
LOGD("add buffer probe");
- //<-
if (g_strrstr(klass, "Codec/Decoder/Audio")) {
- gchar* selected = NULL;
+ gchar *selected = NULL;
selected = g_strdup(GST_ELEMENT_NAME(element));
player->audio_decoders = g_list_append(player->audio_decoders, selected);
}
- //-> temp code
-
- if (g_strrstr(klass, "Parser")) {
- gchar* selected = NULL;
-
- selected = g_strdup(factory_name);
- player->parsers = g_list_append(player->parsers, selected);
- }
if (g_strrstr(klass, "Demuxer/Adaptive")) {
player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].id = MMPLAYER_M_ADAPTIVE_DEMUX;
"max-video-width", player->adaptive_info.limit.width,
"max-video-height", player->adaptive_info.limit.height, NULL);
- } else if (g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse")) {
- /* FIXIT : first value will be overwritten if there's more
- * than 1 demuxer/parser
- */
-
- //LOGD("plugged element is demuxer. take it\n");
+ } else if (g_strrstr(klass, "Demuxer")) {
+ //LOGD("plugged element is demuxer. take it");
player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
-
- /*Added for multi audio support */ // Q. del?
- if (g_strrstr(klass, "Demux")) {
- player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
- player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].gst = element;
- }
}
if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux")) {
// to support trust-zone only
if (g_strrstr(factory_name, "asfdemux")) {
- LOGD("set file-location %s\n", player->profile.uri);
+ LOGD("set file-location %s", player->profile.uri);
g_object_set(G_OBJECT(element), "file-location", player->profile.uri, NULL);
-
- if (player->video_hub_download_mode == TRUE)
- g_object_set(G_OBJECT(element), "downloading-mode", player->video_hub_download_mode, NULL);
} else if (g_strrstr(factory_name, "legacyh264parse")) {
- LOGD("[%s] output-format to legacyh264parse\n", "mssdemux");
+ LOGD("[%s] output-format to legacyh264parse", "mssdemux");
g_object_set(G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
} else if (g_strrstr(factory_name, "mpegaudioparse")) {
if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
- if (!MMPLAYER_IS_HTTP_PD(player) &&
- ((MMPLAYER_IS_HTTP_STREAMING(player)) ||
+ if ((MMPLAYER_IS_HTTP_STREAMING(player)) ||
(MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) ||
- (MMPLAYER_IS_DASH_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, player->ini.http_buffering_time, 1.0, player->ini.http_buffering_limit);
+ __mm_player_streaming_set_multiqueue(player->streamer, element);
__mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
}
return;
}
-gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
-{
- MMPLAYER_FENTER();
- MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
-
- if (MMPLAYER_IS_STREAMING(player))
- return FALSE;
-
- /* This callback can be set to music player only. */
- if ((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO) {
- LOGW("audio callback is not supported for video");
- return FALSE;
- }
-
- if (player->audio_stream_cb) {
- GstPad *pad = NULL;
-
- pad = gst_element_get_static_pad(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
-
- if (!pad) {
- LOGE("failed to get sink pad from audiosink to probe data\n");
- return FALSE;
- }
- player->audio_cb_probe_id = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER,
- __mmplayer_audio_stream_probe, player, NULL);
-
- gst_object_unref(pad);
-
- pad = NULL;
- } else {
- LOGE("There is no audio callback to configure.\n");
- return FALSE;
- }
-
- MMPLAYER_FLEAVE();
-
- return TRUE;
-}
-
static void
-__mmplayer_release_misc(mm_player_t* player)
+__mmplayer_release_misc(mmplayer_t *player)
{
int i;
bool cur_mode = player->set_mode.rich_audio;
MMPLAYER_RETURN_IF_FAIL(player);
- player->video_stream_cb = NULL;
- player->video_stream_cb_user_param = NULL;
- player->video_stream_prerolled = FALSE;
+ player->video_decoded_cb = NULL;
+ player->video_decoded_cb_user_param = NULL;
+ player->video_stream_prerolled = false;
- player->audio_stream_cb = NULL;
- player->audio_stream_render_cb_ex = NULL;
- player->audio_stream_cb_user_param = NULL;
- player->audio_stream_sink_sync = false;
+ player->audio_decoded_cb = NULL;
+ player->audio_decoded_cb_user_param = NULL;
+ player->audio_extract_opt = MM_PLAYER_AUDIO_EXTRACT_DEFAULT;
player->video_stream_changed_cb = NULL;
player->video_stream_changed_cb_user_param = NULL;
player->http_content_size = 0;
player->not_supported_codec = MISSING_PLUGIN_NONE;
player->can_support_codec = FOUND_PLUGIN_NONE;
- player->pending_seek.is_pending = FALSE;
- player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
+ player->pending_seek.is_pending = false;
player->pending_seek.pos = 0;
player->msg_posted = FALSE;
player->has_many_types = FALSE;
- player->max_audio_channels = 0;
- player->video_share_api_delta = 0;
- player->video_share_clock_delta = 0;
player->is_subtitle_force_drop = FALSE;
player->play_subtitle = FALSE;
player->adjust_subtitle_pos = 0;
- player->last_multiwin_status = FALSE;
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(MMPlayerSetMode));
+ memset(&player->set_mode, 0, sizeof(mmplayer_setting_mode_t));
/* recover mode */
player->set_mode.rich_audio = cur_mode;
+ 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;
+
for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) {
player->bitrate[i] = 0;
player->maximum_bitrate[i] = 0;
player->sound.rg_enable = false;
+ __mmplayer_initialize_video_roi(player);
MMPLAYER_FLEAVE();
}
static void
-__mmplayer_release_misc_post(mm_player_t* player)
+__mmplayer_release_misc_post(mmplayer_t *player)
{
char *original_uri = NULL;
MMPLAYER_FENTER();
mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
- /* clean found parsers */
- if (player->parsers) {
- GList *parsers = player->parsers;
- for (; parsers; parsers = g_list_next(parsers)) {
- gchar *name = parsers->data;
- MMPLAYER_FREEIF(name);
- }
- g_list_free(player->parsers);
- player->parsers = NULL;
- }
-
/* clean found audio decoders */
if (player->audio_decoders) {
GList *a_dec = player->audio_decoders;
if (player->attrs) {
mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri);
- LOGD("restore original uri = %s\n", original_uri);
+ LOGD("restore original uri = %s", original_uri);
- if (mmf_attrs_commit(player->attrs))
- LOGE("failed to commit the original uri.\n");
+ if (mm_attrs_commit_all(player->attrs))
+ LOGE("failed to commit the original uri.");
}
GList *uri_list = player->uri_info.uri_list;
MMPLAYER_FLEAVE();
}
-static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
-{
- GstElement *element = NULL;
- GstPad *sinkpad;
-
- LOGD("creating %s to plug\n", name);
-
- element = gst_element_factory_make(name, NULL);
- if (!element) {
- LOGE("failed to create queue\n");
- return NULL;
- }
-
- if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY)) {
- LOGE("failed to set state READY to %s\n", name);
- gst_object_unref(element);
- return NULL;
- }
-
- if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element)) {
- LOGE("failed to add %s\n", name);
- gst_object_unref(element);
- return NULL;
- }
-
- sinkpad = gst_element_get_static_pad(element, "sink");
-
- if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
- LOGE("failed to link %s\n", name);
- gst_object_unref(sinkpad);
- gst_object_unref(element);
- return NULL;
- }
-
- LOGD("linked %s to pipeline successfully\n", name);
-
- gst_object_unref(sinkpad);
-
- return element;
-}
-
gboolean
-__mmplayer_check_subtitle(mm_player_t* player)
+__mmplayer_check_subtitle(mmplayer_t *player)
{
MMHandleType attrs = 0;
char *subtitle_uri = NULL;
if (!subtitle_uri || !strlen(subtitle_uri))
return FALSE;
- SECURE_LOGD("subtitle uri is %s[%d]", subtitle_uri, strlen(subtitle_uri));
+ SECURE_LOGD("subtitle uri is %s[%zu]", subtitle_uri, strlen(subtitle_uri));
player->is_external_subtitle_present = TRUE;
MMPLAYER_FLEAVE();
return TRUE;
}
-static gboolean
-__mmplayer_can_extract_pcm(mm_player_t* player)
-{
- MMHandleType attrs = 0;
- gboolean sound_extraction = FALSE;
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
-
- attrs = MMPLAYER_GET_ATTRS(player);
- if (!attrs) {
- LOGE("fail to get attributes.");
- return FALSE;
- }
-
- /* get sound_extraction property */
- mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
-
- if (!sound_extraction) {
- LOGD("checking pcm extraction mode : %d ", sound_extraction);
- return FALSE;
- }
-
- return TRUE;
-}
-
void
-__mmplayer_cancel_eos_timer(mm_player_t* player)
+__mmplayer_cancel_eos_timer(mmplayer_t *player)
{
MMPLAYER_RETURN_IF_FAIL(player);
}
static void
-__mmplayer_add_sink(mm_player_t* player, GstElement* sink)
+__mmplayer_add_sink(mmplayer_t *player, GstElement *sink)
{
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player);
MMPLAYER_RETURN_IF_FAIL(sink);
- player->sink_elements =
- g_list_append(player->sink_elements, sink);
+ player->sink_elements = g_list_append(player->sink_elements, sink);
MMPLAYER_FLEAVE();
}
static void
-__mmplayer_del_sink(mm_player_t* player, GstElement* sink)
+__mmplayer_del_sink(mmplayer_t *player, GstElement *sink)
{
MMPLAYER_FENTER();
MMPLAYER_RETURN_IF_FAIL(player);
MMPLAYER_RETURN_IF_FAIL(sink);
- player->sink_elements =
- g_list_remove(player->sink_elements, sink);
+ player->sink_elements = g_list_remove(player->sink_elements, sink);
MMPLAYER_FLEAVE();
}
+void
+__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;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(player);
+
+ if (type >= MM_PLAYER_SIGNAL_TYPE_MAX) {
+ LOGE("invalid signal type [%d]", type);
+ return;
+ }
+
+ item = (mmplayer_signal_item_t *)g_try_malloc(sizeof(mmplayer_signal_item_t));
+ if (!item) {
+ LOGE("cannot connect signal [%s]", signal);
+ return;
+ }
+
+ item->obj = object;
+ item->sig = g_signal_connect(object, signal, cb_funct, u_data);
+ player->signals[type] = g_list_append(player->signals[type], item);
+
+ MMPLAYER_FLEAVE();
+ return;
+}
+
/* NOTE : be careful with calling this api. please refer to below glib comment
* glib comment : Note that there is a bug in GObject that makes this function much
* less useful than it might seem otherwise. Once gobject is disposed, the callback
* g_signal_handler_disconnect(instance, id);
*/
static void
-__mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type)
+__mmplayer_release_signal_connection(mmplayer_t *player, mmplayer_signal_type_e type)
{
- GList* sig_list = NULL;
- MMPlayerSignalItem* item = NULL;
+ GList *sig_list = NULL;
+ mmplayer_signal_item_t *item = NULL;
MMPLAYER_FENTER();
return;
}
-int _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
+int
+_mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
{
- mm_player_t* player = 0;
+ mmplayer_t *player = 0;
int prev_display_surface_type = 0;
void *prev_display_overlay = NULL;
- const gchar *klass = NULL;
- gchar *cur_videosink_name = NULL;
- int ret = 0;
- int i = 0;
- int num_of_dec = 2; /* DEC1, DEC2 */
MMPLAYER_FENTER();
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");
+ return MM_ERROR_NONE;
+ }
+
+ LOGD("videosink element is not yet ready");
+
if (surface_type >= MM_DISPLAY_SURFACE_NUM) {
LOGE("Not support this surface type(%d) for changing vidoesink", surface_type);
MMPLAYER_FLEAVE();
return MM_ERROR_PLAYER_INTERNAL;
}
- /* check videosink element is created */
- if (!player->pipeline || !player->pipeline->videobin ||
- !player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
- LOGD("videosink element is not yet ready");
-
- /* 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 (mmf_attrs_commit(player->attrs)) {
- LOGE("failed to commit attribute");
- MMPLAYER_FLEAVE();
- return MM_ERROR_PLAYER_INTERNAL;
- }
- MMPLAYER_FLEAVE();
- return MM_ERROR_NONE;
- } else {
- /* get player command status */
- if (!(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME || player->cmd == MMPLAYER_COMMAND_PAUSE)) {
- LOGE("invalid player command status(%d), __mmplayer_do_change_videosink() is only available with START/RESUME/PAUSE command", player->cmd);
- MMPLAYER_FLEAVE();
- return MM_ERROR_PLAYER_INVALID_STATE;
- }
-
- /* surface change */
- for (i = 0 ; i < num_of_dec ; i++) {
- if (player->pipeline->mainbin &&
- player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst) {
- GstElementFactory *decfactory;
- decfactory = gst_element_get_factory(player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst);
-
- klass = gst_element_factory_get_metadata(decfactory, GST_ELEMENT_METADATA_KLASS);
- if ((g_strrstr(klass, "Codec/Decoder/Video"))) {
- if ((prev_display_surface_type == MM_DISPLAY_SURFACE_OVERLAY) && (surface_type == MM_DISPLAY_SURFACE_REMOTE)) {
- ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, "fakesink", surface_type, display_overlay);
- if (ret) {
- goto ERROR_CASE;
- } else {
- LOGW("success to changing display surface(%d)", surface_type);
- MMPLAYER_FLEAVE();
- return MM_ERROR_NONE;
- }
- } else if ((prev_display_surface_type == MM_DISPLAY_SURFACE_REMOTE) && (surface_type == MM_DISPLAY_SURFACE_OVERLAY)) {
- ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_overlay, surface_type, display_overlay);
- if (ret) {
- goto ERROR_CASE;
- } else {
- LOGW("success to changing display surface(%d)", surface_type);
- MMPLAYER_FLEAVE();
- return MM_ERROR_NONE;
- }
- } else {
- LOGE("invalid incoming surface type(%d) and current videosink_name(%s) for changing display surface", surface_type, cur_videosink_name);
- ret = MM_ERROR_PLAYER_INTERNAL;
- goto ERROR_CASE;
- }
- }
- }
- }
- }
-
-ERROR_CASE:
- /* rollback to previous attributes */
- mm_attrs_set_int_by_name(player->attrs, "display_surface_type", prev_display_surface_type);
- mm_attrs_set_data_by_name(player->attrs, "display_overlay", prev_display_overlay, sizeof(void*));
- if (mmf_attrs_commit(player->attrs)) {
- LOGE("failed to commit attributes to rollback");
- MMPLAYER_FLEAVE();
- return MM_ERROR_PLAYER_INTERNAL;
- }
- MMPLAYER_FLEAVE();
- return ret;
-}
-
-/* NOTE : It does not support some use cases, eg using colorspace converter */
-int
-__mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay)
-{
- GstPad *src_pad_dec = NULL;
- GstPad *sink_pad_videosink = NULL;
- GstPad *sink_pad_videobin = NULL;
- GstClock *clock = NULL;
- MMPlayerStateType previous_state = MM_PLAYER_STATE_NUM;
- int ret = MM_ERROR_NONE;
- gboolean is_audiobin_created = TRUE;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_COMMON_INVALID_ARGUMENT);
- MMPLAYER_RETURN_VAL_IF_FAIL(videosink_element, MM_ERROR_COMMON_INVALID_ARGUMENT);
- MMPLAYER_RETURN_VAL_IF_FAIL(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
-
- LOGD("video dec is found(idx:%d), we are going to change videosink to %s", dec_index, videosink_element);
- LOGD("surface type(%d), display overlay(%x)", surface_type, display_overlay);
-
- /* get information whether if audiobin is created */
- if (!player->pipeline->audiobin ||
- !player->pipeline->audiobin[MMPLAYER_A_SINK].gst) {
- LOGW("audiobin is null, this video content may not have audio data");
- is_audiobin_created = FALSE;
- }
-
- /* get current state of player */
- previous_state = MMPLAYER_CURRENT_STATE(player);
- LOGD("previous state(%d)", previous_state);
-
-
- /* get src pad of decoder and block it */
- src_pad_dec = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), "src");
- if (!src_pad_dec) {
- LOGE("failed to get src pad from decode in mainbin");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- if (player->seek_state == MMPLAYER_SEEK_NONE && previous_state == MM_PLAYER_STATE_PLAYING) {
- LOGW("trying to block pad(video)");
-// if (!gst_pad_set_blocked(src_pad_dec, TRUE))
- gst_pad_add_probe(src_pad_dec, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
- NULL, NULL, NULL);
- {
- LOGE("failed to set block pad(video)");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- LOGW("pad is blocked(video)");
- } else {
- /* no data flows, so no need to do pad_block */
- if (player->seek_state != MMPLAYER_SEEK_NONE)
- LOGW("not completed seek(%d), do nothing", player->seek_state);
-
- LOGD("MM_PLAYER_STATE is not PLAYING now, skip pad-block(TRUE)");
- }
-
- /* remove pad */
- if (!gst_element_remove_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst,
- GST_PAD_CAST(GST_GHOST_PAD(player->ghost_pad_for_videobin)))) {
- LOGE("failed to remove previous ghost_pad for videobin");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* change state of videobin to NULL */
- LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_NULL);
- ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_NULL);
- if (ret != GST_STATE_CHANGE_SUCCESS) {
- LOGE("failed to change state of videobin to NULL");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* unlink between decoder and videobin and remove previous videosink from videobin */
- gst_element_unlink(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst));
- if (!gst_bin_remove(GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst))) {
- LOGE("failed to remove former videosink from videobin");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- __mmplayer_del_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
-
- /* create a new videosink and add it to videobin */
- player->pipeline->videobin[MMPLAYER_V_SINK].gst = gst_element_factory_make(videosink_element, "videosink");
- if (!player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
- LOGE("failed to create videosink element\n");
- MMPLAYER_FLEAVE();
- return MM_ERROR_PLAYER_INTERNAL;
- }
- gst_bin_add(GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst));
- __mmplayer_add_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
- g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
-
- /* save attributes */
- if (player->attrs) {
- /* set a new display surface type */
- mm_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type);
- /* set a new diplay overlay */
- switch (surface_type) {
- case MM_DISPLAY_SURFACE_OVERLAY:
- LOGD("save attributes related to video display surface : id = %d", *(int*)display_overlay);
- mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
- break;
- default:
- LOGE("invalid type(%d) for changing display surface", surface_type);
- MMPLAYER_FLEAVE();
- return MM_ERROR_INVALID_ARGUMENT;
- }
- if (mmf_attrs_commit(player->attrs)) {
- LOGE("failed to commit");
- MMPLAYER_FLEAVE();
- return MM_ERROR_PLAYER_INTERNAL;
- }
- } else {
- LOGE("player->attrs is null, failed to save attributes");
+ /* 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;
}
- /* update video param */
- if (MM_ERROR_NONE != _mmplayer_update_video_param(player, "update_all_param")) {
- LOGE("failed to update video param");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* change state of videobin to READY */
- LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_READY);
- ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_READY);
- if (ret != GST_STATE_CHANGE_SUCCESS) {
- LOGE("failed to change state of videobin to READY");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* change ghostpad */
- sink_pad_videosink = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sink");
- if (!sink_pad_videosink) {
- LOGE("failed to get sink pad from videosink element");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", sink_pad_videosink);
- if (!gst_pad_set_active(player->ghost_pad_for_videobin, TRUE)) {
- LOGE("failed to set active to ghost_pad");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- if (FALSE == gst_element_add_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin)) {
- LOGE("failed to change ghostpad for videobin");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- gst_object_unref(sink_pad_videosink);
-
- /* link decoder with videobin */
- sink_pad_videobin = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst), "sink");
- if (!sink_pad_videobin) {
- LOGE("failed to get sink pad from videobin");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- if (GST_PAD_LINK_OK != gst_pad_link(src_pad_dec, sink_pad_videobin)) {
- LOGE("failed to link");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- gst_object_unref(sink_pad_videobin);
-
- /* clock setting for a new videosink plugin */
- /* NOTE : Below operation is needed, because a new videosink plugin doesn't have clock for basesink,
- so we set it from audiosink plugin or pipeline(system clock) */
- if (!is_audiobin_created) {
- LOGW("audiobin is not created, get clock from pipeline..");
- clock = GST_ELEMENT_CLOCK(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
- } else {
- clock = GST_ELEMENT_CLOCK(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
- }
- if (clock) {
- GstClockTime now;
- GstClockTime base_time;
- LOGD("set the clock to videosink");
- gst_element_set_clock(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), clock);
- clock = GST_ELEMENT_CLOCK(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
- if (clock) {
- LOGD("got clock of videosink");
- now = gst_clock_get_time(clock);
- base_time = GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst)->base_time;
- LOGD("at time %" GST_TIME_FORMAT ", base %"
- GST_TIME_FORMAT, GST_TIME_ARGS(now), GST_TIME_ARGS(base_time));
- } else {
- LOGE("failed to get clock of videosink after setting clock");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- } else
- LOGW("failed to get clock, maybe it is the time before first playing");
-
- if (player->seek_state == MMPLAYER_SEEK_NONE && previous_state == MM_PLAYER_STATE_PLAYING) {
- /* change state of videobin to PAUSED */
- LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PLAYING);
- ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PLAYING);
- if (ret != GST_STATE_CHANGE_FAILURE) {
- LOGW("change state of videobin to PLAYING, ret(%d)", ret);
- } else {
- LOGE("failed to change state of videobin to PLAYING");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* release blocked and unref src pad of video decoder */
- #if 0
- if (!gst_pad_set_blocked(src_pad_dec, FALSE)) {
- LOGE("failed to set pad blocked FALSE(video)");
- return MM_ERROR_PLAYER_INTERNAL;
- }
- #endif
- LOGW("pad is unblocked(video)");
- } else {
- if (player->seek_state != MMPLAYER_SEEK_NONE)
- LOGW("not completed seek(%d)", player->seek_state);
- /* change state of videobin to PAUSED */
- LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PAUSED);
- ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PAUSED);
- if (ret != GST_STATE_CHANGE_FAILURE) {
- LOGW("change state of videobin to PAUSED, ret(%d)", ret);
- } else {
- LOGE("failed to change state of videobin to PLAYING");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-
- /* already skipped pad block */
- LOGD("previous MM_PLAYER_STATE is not PLAYING, skip pad-block(FALSE)");
- }
-
- /* do get/set position for new videosink plugin */
- {
- gint64 position = 0;
-
- LOGD("do get/set position for new videosink plugin");
- if (__mmplayer_gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position)) {
- LOGE("failed to get position");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-#ifdef SINKCHANGE_WITH_ACCURATE_SEEK
- /* accurate seek */
- if (__mmplayer_gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE)) {
- LOGE("failed to set position");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-#else
- /* key unit seek */
- ret = __mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
- GST_FORMAT_TIME, (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),
- GST_SEEK_TYPE_SET, position,
- GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
- if (!ret) {
- LOGE("failed to set position");
- return MM_ERROR_PLAYER_INTERNAL;
- }
-#endif
- }
-
- if (src_pad_dec)
- gst_object_unref(src_pad_dec);
- LOGD("success to change sink");
-
MMPLAYER_FLEAVE();
-
return MM_ERROR_NONE;
}
-
/* Note : if silent is true, then subtitle would not be displayed. :*/
-int _mmplayer_set_subtitle_silent(MMHandleType hplayer, int silent)
+int
+_mmplayer_set_subtitle_silent(MMHandleType hplayer, int silent)
{
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
player->set_mode.subtitle_off = silent;
- LOGD("subtitle is %s.\n", player->set_mode.subtitle_off ? "ON" : "OFF");
+ LOGD("subtitle is %s.", player->set_mode.subtitle_off ? "ON" : "OFF");
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
}
-int _mmplayer_sync_subtitle_pipeline(mm_player_t* player)
+int
+_mmplayer_sync_subtitle_pipeline(mmplayer_t *player)
{
- MMPlayerGstElement* mainbin = NULL;
- MMPlayerGstElement* textbin = NULL;
+ mmplayer_gst_element_t *mainbin = NULL;
+ mmplayer_gst_element_t *textbin = NULL;
GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
GstState current_state = GST_STATE_VOID_PENDING;
GstState element_state = GST_STATE_VOID_PENDING;
ret = gst_element_get_state(mainbin[MMPLAYER_M_SUBSRC].gst, &element_state, &element_pending_state, 5 * GST_SECOND);
if (GST_STATE_CHANGE_FAILURE == ret) {
- LOGE("fail to state change.\n");
+ LOGE("fail to state change.");
result = MM_ERROR_PLAYER_INTERNAL;
goto ERROR;
}
}
-
gst_element_set_base_time(textbin[MMPLAYER_T_BIN].gst, base_time);
gst_element_set_start_time(textbin[MMPLAYER_T_BIN].gst, start_time);
// seek to current position
if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time)) {
result = MM_ERROR_PLAYER_INVALID_STATE;
- LOGE("gst_element_query_position failed, invalid state\n");
+ LOGE("gst_element_query_position failed, invalid state");
goto ERROR;
}
}
static int
-__mmplayer_change_external_subtitle_language(mm_player_t* player, const char* filepath)
+__mmplayer_change_external_subtitle_language(mmplayer_t *player, const char *filepath)
{
GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
GstState current_state = GST_STATE_VOID_PENDING;
MMHandleType attrs = 0;
- MMPlayerGstElement* mainbin = NULL;
- MMPlayerGstElement* textbin = NULL;
+ mmplayer_gst_element_t *mainbin = NULL;
+ mmplayer_gst_element_t *textbin = NULL;
- gchar* subtitle_uri = NULL;
+ gchar *subtitle_uri = NULL;
int result = MM_ERROR_NONE;
const gchar *charset = NULL;
current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
if (current_state < GST_STATE_READY) {
result = MM_ERROR_PLAYER_INVALID_STATE;
- LOGE("Pipeline is not in proper state\n");
+ LOGE("Pipeline is not in proper state");
goto EXIT;
}
attrs = MMPLAYER_GET_ATTRS(player);
if (!attrs) {
- LOGE("cannot get content attribute\n");
+ LOGE("cannot get content attribute");
result = MM_ERROR_PLAYER_INTERNAL;
goto EXIT;
}
mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
if (!subtitle_uri || strlen(subtitle_uri) < 1) {
- LOGE("subtitle uri is not proper filepath\n");
+ LOGE("subtitle uri is not proper filepath");
result = MM_ERROR_PLAYER_INVALID_URI;
goto EXIT;
}
goto EXIT;
}
- LOGD("old subtitle file path is [%s]\n", subtitle_uri);
- LOGD("new subtitle file path is [%s]\n", filepath);
+ LOGD("old subtitle file path is [%s]", subtitle_uri);
+ 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\n");
+ LOGD("No need to swtich subtitle, as input filepath is same as current filepath");
goto EXIT;
} else {
mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
- if (mmf_attrs_commit(player->attrs)) {
- LOGE("failed to commit.\n");
+ if (mm_attrs_commit_all(player->attrs)) {
+ LOGE("failed to commit.");
goto EXIT;
}
}
charset = util_get_charset(filepath);
if (charset) {
- LOGD("detected charset is %s\n", charset);
+ LOGD("detected charset is %s", charset);
g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBPARSE].gst), "subtitle-encoding", charset, NULL);
}
}
/* API to switch between external subtitles */
-int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filepath)
+int
+_mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char *filepath)
{
int result = MM_ERROR_NONE;
- mm_player_t* player = (mm_player_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
char *path = NULL;
MMPLAYER_FENTER();
if (!player->pipeline) {
/* IDLE state */
mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
- if (mmf_attrs_commit(player->attrs)) {
+ if (mm_attrs_commit_all(player->attrs)) {
LOGE("failed to commit"); /* subtitle path will not be created */
return MM_ERROR_PLAYER_INTERNAL;
}
if (!__mmplayer_check_subtitle(player)) {
mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
- if (mmf_attrs_commit(player->attrs)) {
+ if (mm_attrs_commit_all(player->attrs)) {
LOGE("failed to commit");
return MM_ERROR_PLAYER_INTERNAL;
}
}
static int
-__mmplayer_change_selector_pad(mm_player_t* player, MMPlayerTrackType type, int index)
+__mmplayer_change_selector_pad(mmplayer_t *player, mmplayer_track_type_e type, int index)
{
int result = MM_ERROR_NONE;
- gchar* change_pad_name = NULL;
- GstPad* sinkpad = NULL;
- MMPlayerGstElement* mainbin = NULL;
- enum MainElementID elemId = MMPLAYER_M_NUM;
- GstCaps* caps = NULL;
+ gchar *change_pad_name = NULL;
+ GstPad *sinkpad = NULL;
+ mmplayer_gst_element_t *mainbin = NULL;
+ main_element_id_e elem_idx = MMPLAYER_M_NUM;
+ GstCaps *caps = NULL;
gint total_track_num = 0;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin,
MM_ERROR_PLAYER_NOT_INITIALIZED);
- LOGD("Change Track(%d) to %d\n", type, index);
+ LOGD("Change Track(%d) to %d", type, index);
mainbin = player->pipeline->mainbin;
if (type == MM_PLAYER_TRACK_TYPE_AUDIO) {
- elemId = MMPLAYER_M_A_INPUT_SELECTOR;
+ elem_idx = MMPLAYER_M_A_INPUT_SELECTOR;
} else if (type == MM_PLAYER_TRACK_TYPE_TEXT) {
- elemId = MMPLAYER_M_T_INPUT_SELECTOR;
+ elem_idx = MMPLAYER_M_T_INPUT_SELECTOR;
} else {
/* Changing Video Track is not supported. */
- LOGE("Track Type Error\n");
+ LOGE("Track Type Error");
goto EXIT;
}
- if (mainbin[elemId].gst == NULL) {
+ if (mainbin[elem_idx].gst == NULL) {
result = MM_ERROR_PLAYER_NO_OP;
- LOGD("Req track doesn't exist\n");
+ LOGD("Req track doesn't exist");
goto EXIT;
}
total_track_num = player->selector[type].total_track_num;
if (total_track_num <= 0) {
result = MM_ERROR_PLAYER_NO_OP;
- LOGD("Language list is not available \n");
+ LOGD("Language list is not available");
goto EXIT;
}
if ((index < 0) || (index >= total_track_num)) {
result = MM_ERROR_INVALID_ARGUMENT;
- LOGD("Not a proper index : %d \n", index);
+ LOGD("Not a proper index : %d", index);
goto EXIT;
}
change_pad_name = g_strdup_printf("sink_%u", index);
if (change_pad_name == NULL) {
result = MM_ERROR_PLAYER_INTERNAL;
- LOGD("Pad does not exists\n");
+ LOGD("Pad does not exists");
goto EXIT;
}
- LOGD("new active pad name: %s\n", change_pad_name);
+ LOGD("new active pad name: %s", change_pad_name);
- sinkpad = gst_element_get_static_pad(mainbin[elemId].gst, change_pad_name);
+ sinkpad = gst_element_get_static_pad(mainbin[elem_idx].gst, change_pad_name);
if (sinkpad == NULL) {
LOGD("sinkpad is NULL");
result = MM_ERROR_PLAYER_INTERNAL;
goto EXIT;
}
- LOGD("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
- g_object_set(mainbin[elemId].gst, "active-pad", sinkpad, NULL);
+ LOGD("Set Active Pad - %s:%s", GST_DEBUG_PAD_NAME(sinkpad));
+ g_object_set(mainbin[elem_idx].gst, "active-pad", sinkpad, NULL);
caps = gst_pad_get_current_caps(sinkpad);
MMPLAYER_LOG_GST_CAPS_TYPE(caps);
__mmplayer_set_audio_attrs(player, caps);
EXIT:
-
MMPLAYER_FREEIF(change_pad_name);
return result;
}
-int _mmplayer_change_track_language(MMHandleType hplayer, MMPlayerTrackType type, int index)
+int
+_mmplayer_change_track_language(MMHandleType hplayer, mmplayer_track_type_e type, int index)
{
int result = MM_ERROR_NONE;
- mm_player_t* player = NULL;
- MMPlayerGstElement* mainbin = NULL;
+ mmplayer_t *player = NULL;
+ mmplayer_gst_element_t *mainbin = NULL;
gint current_active_index = 0;
GstState current_state = GST_STATE_VOID_PENDING;
- GstEvent* event = NULL;
+ GstEvent *event = NULL;
gint64 time = 0;
MMPLAYER_FENTER();
- player = (mm_player_t*)hplayer;
+ player = (mmplayer_t *)hplayer;
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
if (!player->pipeline) {
- LOGE("Track %d pre setting -> %d\n", type, index);
+ LOGE("Track %d pre setting -> %d", type, index);
player->selector[type].active_pad_index = index;
goto EXIT;
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\n");
+ LOGW("Pipeline not in porper state");
goto EXIT;
}
result = __mmplayer_change_selector_pad(player, type, index);
if (result != MM_ERROR_NONE) {
- LOGE("change selector pad error\n");
+ LOGE("change selector pad error");
goto EXIT;
}
player->selector[type].active_pad_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);
+ 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 {
return result;
}
-int _mmplayer_get_subtitle_silent(MMHandleType hplayer, int* silent)
+int
+_mmplayer_get_subtitle_silent(MMHandleType hplayer, int *silent)
{
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
*silent = player->set_mode.subtitle_off;
- LOGD("subtitle is %s.\n", silent ? "ON" : "OFF");
-
- MMPLAYER_FLEAVE();
-
- return MM_ERROR_NONE;
-}
-
-int
-_mmplayer_set_video_hub_download_mode(MMHandleType hplayer, bool mode)
-{
- mm_player_t* player = (mm_player_t*) hplayer;
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_NULL) {
- MMPLAYER_PRINT_STATE(player);
- LOGE("wrong-state : can't set the download mode to parse");
- return MM_ERROR_PLAYER_INVALID_STATE;
- }
-
- LOGD("set video hub download mode to %s", (mode) ? "ON" : "OFF");
- player->video_hub_download_mode = mode;
-
- return MM_ERROR_NONE;
-}
-
-int
-_mmplayer_enable_sync_handler(MMHandleType hplayer, bool enable)
-{
- mm_player_t* player = (mm_player_t*) hplayer;
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- LOGD("enable sync handler : %s", (enable) ? "ON" : "OFF");
- player->sync_handler = enable;
-
- return MM_ERROR_NONE;
-}
-
-int
-_mmplayer_set_video_share_master_clock(MMHandleType hplayer, gint64 clock, gint64 clock_delta,
- gint64 video_time, gint64 media_clock, gint64 audio_time)
-{
- mm_player_t* player = (mm_player_t*) hplayer;
- MMPlayerGstElement* mainbin = NULL;
- GstClockTime start_time_audio = 0, start_time_video = 0;
- GstClockTimeDiff base_time = 0, new_base_time = 0;
- MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
- gint64 api_delta = 0;
- gint64 position = 0, position_delta = 0;
- gint64 adj_base_time = 0;
- GstClock *curr_clock = NULL;
- GstClockTime curr_time = 0;
- gboolean query_ret = TRUE;
- int result = MM_ERROR_NONE;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- /* LOGD("in(us) : %"G_GINT64_FORMAT", %"G_GINT64_FORMAT", %"G_GINT64_FORMAT", %"G_GINT64_FORMAT", %"G_GINT64_FORMAT,
- clock, clock_delta, video_time, media_clock, audio_time); */
-
- if ((video_time < 0) || (player->seek_state != MMPLAYER_SEEK_NONE)) {
- LOGD("skip setting master clock. %lld", video_time);
- goto EXIT;
- }
-
- mainbin = player->pipeline->mainbin;
-
- curr_clock = gst_pipeline_get_clock(GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
- curr_time = gst_clock_get_time(curr_clock);
-
- current_state = MMPLAYER_CURRENT_STATE(player);
-
- if (current_state == MM_PLAYER_STATE_PLAYING)
- query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
-
- if ((current_state != MM_PLAYER_STATE_PLAYING) ||
- (!query_ret)) {
- position = player->last_position;
- LOGD("query fail. %"G_GINT64_FORMAT, position);
- }
-
- clock *= GST_USECOND;
- clock_delta *= GST_USECOND;
-
- api_delta = clock - curr_time;
- if ((player->video_share_api_delta == 0) || (player->video_share_api_delta > api_delta))
- player->video_share_api_delta = api_delta;
- else
- clock_delta += (api_delta - player->video_share_api_delta);
-
- if ((player->video_share_clock_delta == 0) || (player->video_share_clock_delta > clock_delta)) {
- player->video_share_clock_delta = (gint64)clock_delta;
-
- position_delta = (position/GST_USECOND) - video_time;
- position_delta *= GST_USECOND;
-
- adj_base_time = position_delta;
- LOGD("video_share_clock_delta = %"G_GINT64_FORMAT", adj = %"G_GINT64_FORMAT, player->video_share_clock_delta, adj_base_time);
-
- } else {
- gint64 new_play_time = 0;
- gint64 network_delay = 0;
-
- video_time *= GST_USECOND;
-
- network_delay = clock_delta - player->video_share_clock_delta;
- new_play_time = video_time + network_delay;
-
- adj_base_time = position - new_play_time;
-
- LOGD("%"G_GINT64_FORMAT"(delay) = %"G_GINT64_FORMAT" - %"G_GINT64_FORMAT" / %"G_GINT64_FORMAT
- "(adj) = %"G_GINT64_FORMAT"(slave_pos) - %"G_GINT64_FORMAT"(master_pos) - %"G_GINT64_FORMAT"(delay)",
- network_delay, clock_delta, player->video_share_clock_delta, adj_base_time, position, video_time, network_delay);
- }
-
- /* Adjust Current Stream Time with base_time of sink
- * 1. Set Start time to CLOCK NONE, to control the base time by MSL
- * 2. Set new base time
- * if adj_base_time is positive value, the stream time will be decreased.
- * 3. If seek event is occurred, the start time will be reset. */
- if ((player->pipeline->audiobin) &&
- (player->pipeline->audiobin[MMPLAYER_A_SINK].gst)) {
- start_time_audio = gst_element_get_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
-
- if (start_time_audio != GST_CLOCK_TIME_NONE) {
- LOGD("audio sink : gst_element_set_start_time -> NONE");
- gst_element_set_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, GST_CLOCK_TIME_NONE);
- }
-
- base_time = gst_element_get_base_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
- }
-
- if ((player->pipeline->videobin) &&
- (player->pipeline->videobin[MMPLAYER_V_SINK].gst)) {
- start_time_video = gst_element_get_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
-
- if (start_time_video != GST_CLOCK_TIME_NONE) {
- LOGD("video sink : gst_element_set_start_time -> NONE");
- gst_element_set_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst, GST_CLOCK_TIME_NONE);
- }
-
- // if videobin exist, get base_time from videobin.
- base_time = gst_element_get_base_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
- }
-
- new_base_time = base_time + adj_base_time;
-
- if ((player->pipeline->audiobin) &&
- (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
- gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), (GstClockTime)new_base_time);
-
- if ((player->pipeline->videobin) &&
- (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
- gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), (GstClockTime)new_base_time);
-
-EXIT:
- MMPLAYER_FLEAVE();
-
- return result;
-}
-
-int
-_mmplayer_get_video_share_master_clock(MMHandleType hplayer, gint64 *video_time, gint64 *media_clock, gint64 *audio_time)
-{
- mm_player_t* player = (mm_player_t*) hplayer;
- MMPlayerGstElement* mainbin = NULL;
- GstClock *curr_clock = NULL;
- MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
- gint64 position = 0;
- gboolean query_ret = TRUE;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- MMPLAYER_RETURN_VAL_IF_FAIL(video_time, MM_ERROR_COMMON_INVALID_ARGUMENT);
- MMPLAYER_RETURN_VAL_IF_FAIL(media_clock, MM_ERROR_COMMON_INVALID_ARGUMENT);
- MMPLAYER_RETURN_VAL_IF_FAIL(audio_time, MM_ERROR_COMMON_INVALID_ARGUMENT);
-
- mainbin = player->pipeline->mainbin;
-
- curr_clock = gst_pipeline_get_clock(GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
-
- current_state = MMPLAYER_CURRENT_STATE(player);
-
- if (current_state != MM_PLAYER_STATE_PAUSED)
- query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
-
- if ((current_state == MM_PLAYER_STATE_PAUSED) ||
- (!query_ret))
- position = player->last_position;
-
- *media_clock = *video_time = *audio_time = (position/GST_USECOND);
-
- LOGD("media_clock: %"G_GINT64_FORMAT", video_time: %"G_GINT64_FORMAT"(us)", *media_clock, *video_time);
-
- if (curr_clock)
- gst_object_unref(curr_clock);
+ LOGD("subtitle is %s.", silent ? "ON" : "OFF");
MMPLAYER_FLEAVE();
}
static gboolean
-__mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element)
+__mmplayer_add_dump_buffer_probe(mmplayer_t *player, GstElement *element)
{
MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
MMPLAYER_RETURN_VAL_IF_FAIL(element, FALSE);
for (idx = 0; player->ini.dump_element_keyword[idx][0] != '\0'; idx++) {
if (g_strrstr(factory_name, player->ini.dump_element_keyword[idx])) {
LOGD("dump [%s] sink pad", player->ini.dump_element_keyword[idx]);
- mm_player_dump_t *dump_s;
- dump_s = g_malloc(sizeof(mm_player_dump_t));
-
+ mmplayer_dump_t *dump_s;
+ dump_s = g_try_malloc(sizeof(mmplayer_dump_t));
if (dump_s == NULL) {
LOGE("malloc fail");
return FALSE;
dump_s->dump_pad = gst_element_get_static_pad(element, "sink");
if (dump_s->dump_pad) {
- memset(dump_file_name, 0x00, PLAYER_INI_MAX_STRLEN*2);
- snprintf(dump_file_name, PLAYER_INI_MAX_STRLEN*2, "%s/%s_sink_pad.dump", player->ini.dump_element_path, player->ini.dump_element_keyword[idx]);
+ memset(dump_file_name, 0x00, PLAYER_INI_MAX_STRLEN * 2);
+ snprintf(dump_file_name, PLAYER_INI_MAX_STRLEN * 2, "%s/%s_sink_pad.dump", player->ini.dump_element_path, player->ini.dump_element_keyword[idx]);
dump_s->dump_element_file = fopen(dump_file_name, "w+");
dump_s->probe_handle_id = gst_pad_add_probe(dump_s->dump_pad, GST_PAD_PROBE_TYPE_BUFFER, __mmplayer_dump_buffer_probe_cb, dump_s->dump_element_file, NULL);
/* add list for removed buffer probe and close FILE */
LOGD("%s sink pad added buffer probe for dump", factory_name);
return TRUE;
} else {
- g_free(dump_s);
- dump_s = NULL;
+ MMPLAYER_FREEIF(dump_s);
LOGE("failed to get %s sink pad added", factory_name);
}
-
-
}
}
return FALSE;
static GstPadProbeReturn
__mmplayer_dump_buffer_probe_cb(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
{
- FILE *dump_data = (FILE *) u_data;
+ FILE *dump_data = (FILE *)u_data;
// int written = 0;
GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
GstMapInfo probe_info = GST_MAP_INFO_INIT;
- MMPLAYER_RETURN_VAL_IF_FAIL(dump_data, FALSE);
+ MMPLAYER_RETURN_VAL_IF_FAIL(dump_data, GST_PAD_PROBE_PASS);
gst_buffer_map(buffer, &probe_info, GST_MAP_READ);
fwrite(probe_info.data, 1, probe_info.size , dump_data);
+ gst_buffer_unmap(buffer, &probe_info);
+
return GST_PAD_PROBE_OK;
}
static void
__mmplayer_release_dump_list(GList *dump_list)
{
- if (dump_list) {
- GList *d_list = dump_list;
- for (; d_list; d_list = g_list_next(d_list)) {
- mm_player_dump_t *dump_s = d_list->data;
- if (dump_s->dump_pad) {
- if (dump_s->probe_handle_id)
- gst_pad_remove_probe(dump_s->dump_pad, dump_s->probe_handle_id);
- }
- if (dump_s->dump_element_file) {
- fclose(dump_s->dump_element_file);
- dump_s->dump_element_file = NULL;
- }
- MMPLAYER_FREEIF(dump_s);
+ GList *d_list = dump_list;
+
+ if (!d_list)
+ return;
+
+ for (; d_list; d_list = g_list_next(d_list)) {
+ mmplayer_dump_t *dump_s = d_list->data;
+ if (dump_s->dump_pad) {
+ if (dump_s->probe_handle_id)
+ gst_pad_remove_probe(dump_s->dump_pad, dump_s->probe_handle_id);
+ gst_object_unref(GST_OBJECT(dump_s->dump_pad));
+ }
+ if (dump_s->dump_element_file) {
+ fclose(dump_s->dump_element_file);
+ dump_s->dump_element_file = NULL;
}
- g_list_free(dump_list);
- dump_list = NULL;
+ MMPLAYER_FREEIF(dump_s);
}
+ g_list_free(dump_list);
+ dump_list = NULL;
}
int
-_mmplayer_has_closed_caption(MMHandleType hplayer, bool* exist)
+_mmplayer_has_closed_caption(MMHandleType hplayer, bool *exist)
{
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
MMPLAYER_RETURN_VAL_IF_FAIL(exist, MM_ERROR_INVALID_ARGUMENT);
- *exist = player->has_closed_caption;
+ *exist = (bool)player->has_closed_caption;
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
}
-void _mm_player_video_stream_internal_buffer_unref(void *buffer)
+void
+_mm_player_video_stream_internal_buffer_unref(void *buffer)
{
MMPLAYER_FENTER();
if (buffer) {
MMPLAYER_FLEAVE();
}
-void
-__gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data)
+int
+_mmplayer_get_timeout(MMHandleType hplayer, int *timeout)
{
- mm_player_t *player = (mm_player_t*)user_data;
- MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
- guint64 current_level_bytes = 0;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
- MMPLAYER_RETURN_IF_FAIL(player);
+ MMPLAYER_FENTER();
- g_object_get(G_OBJECT(element), "current-level-bytes", ¤t_level_bytes, NULL);
+ MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+ MMPLAYER_RETURN_VAL_IF_FAIL(timeout, MM_ERROR_COMMON_INVALID_ARGUMENT);
- LOGI("app-src: feed audio(%llu)", current_level_bytes);
- MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
+ if (MMPLAYER_IS_STREAMING(player))
+ *timeout = (int)player->ini.live_state_change_timeout;
+ else
+ *timeout = (int)player->ini.localplayback_state_change_timeout;
- if (player->media_stream_buffer_status_cb[type])
- player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param[type]);
- MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
+ LOGD("timeout = %d", *timeout);
-}
-
-void
-__gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data)
-{
- mm_player_t *player = (mm_player_t*)user_data;
- MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
- guint64 current_level_bytes = 0;
-
- MMPLAYER_RETURN_IF_FAIL(player);
-
- g_object_get(G_OBJECT(element), "current-level-bytes", ¤t_level_bytes, NULL);
-
- LOGI("app-src: feed video(%llu)", current_level_bytes);
-
- MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
- if (player->media_stream_buffer_status_cb[type])
- player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param[type]);
- MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
-}
-
-void
-__gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data)
-{
- mm_player_t *player = (mm_player_t*)user_data;
- MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
- guint64 current_level_bytes = 0;
-
- MMPLAYER_RETURN_IF_FAIL(player);
-
- LOGI("app-src: feed subtitle");
-
- g_object_get(G_OBJECT(element), "current-level-bytes", ¤t_level_bytes, NULL);
-
- MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
- if (player->media_stream_buffer_status_cb[type])
- player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param[type]);
-
- MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
-}
-
-void
-__gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data)
-{
- mm_player_t *player = (mm_player_t*)user_data;
- MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
- guint64 current_level_bytes = 0;
-
- MMPLAYER_RETURN_IF_FAIL(player);
-
- LOGI("app-src: audio buffer is full");
-
- g_object_get(G_OBJECT(element), "current-level-bytes", ¤t_level_bytes, NULL);
-
- MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
-
- if (player->media_stream_buffer_status_cb[type])
- player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, current_level_bytes, player->buffer_cb_user_param[type]);
-
- MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
-}
-
-void
-__gst_appsrc_enough_video_data(GstElement *element, gpointer user_data)
-{
- mm_player_t *player = (mm_player_t*)user_data;
- MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
- guint64 current_level_bytes = 0;
-
- MMPLAYER_RETURN_IF_FAIL(player);
-
- LOGI("app-src: video buffer is full");
-
- g_object_get(G_OBJECT(element), "current-level-bytes", ¤t_level_bytes, NULL);
-
- MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
- if (player->media_stream_buffer_status_cb[type])
- player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, current_level_bytes, player->buffer_cb_user_param[type]);
-
- MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
-}
-
-gboolean
-__gst_seek_audio_data(GstElement * appsrc, guint64 position, gpointer user_data)
-{
- mm_player_t *player = (mm_player_t*)user_data;
- MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
-
- LOGD("app-src: seek audio data %llu", position);
- MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
-
- if (player->media_stream_seek_data_cb[type])
- player->media_stream_seek_data_cb[type](type, position, player->seek_cb_user_param[type]);
- MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
-
- return TRUE;
-}
-
-gboolean
-__gst_seek_video_data(GstElement * appsrc, guint64 position, gpointer user_data)
-{
- mm_player_t *player = (mm_player_t*)user_data;
- MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
-
- LOGD("app-src: seek video data %llu", position);
- MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
- if (player->media_stream_seek_data_cb[type])
- player->media_stream_seek_data_cb[type](type, position, player->seek_cb_user_param[type]);
- MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
-
- return TRUE;
-}
-
-gboolean
-__gst_seek_subtitle_data(GstElement * appsrc, guint64 position, gpointer user_data)
-{
- mm_player_t *player = (mm_player_t*)user_data;
- MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
-
- LOGD("app-src: seek subtitle data");
- MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
-
- if (player->media_stream_seek_data_cb[type])
- player->media_stream_seek_data_cb[type](type, position, player->seek_cb_user_param[type]);
- MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
-
- return TRUE;
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
}
int
-_mmplayer_set_pcm_spec(MMHandleType hplayer, int samplerate, int channel)
-{
- mm_player_t* player = (mm_player_t*) hplayer;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- player->pcm_samplerate = samplerate;
- player->pcm_channel = channel;
-
- MMPLAYER_FLEAVE();
- return MM_ERROR_NONE;
-}
-
-int _mmplayer_get_timeout(MMHandleType hplayer, int *timeout)
-{
- mm_player_t* player = (mm_player_t*) hplayer;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(timeout, MM_ERROR_COMMON_INVALID_ARGUMENT);
-
- if (MMPLAYER_IS_HTTP_PD(player))
- *timeout = player->ini.live_state_change_timeout*2;
- else if (MMPLAYER_IS_STREAMING(player))
- *timeout = player->ini.live_state_change_timeout;
- else
- *timeout = player->ini.localplayback_state_change_timeout;
-
- LOGD("timeout = %d\n", *timeout);
-
- MMPLAYER_FLEAVE();
- return MM_ERROR_NONE;
-}
-
-int _mmplayer_get_num_of_video_out_buffers(MMHandleType hplayer, int *num, int *extra_num)
+_mmplayer_get_num_of_video_out_buffers(MMHandleType hplayer, int *num, int *extra_num)
{
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
*num = player->video_num_buffers;
*extra_num = player->video_extra_num_buffers;
- LOGD("state %d, num %d(%d)\n", MMPLAYER_CURRENT_STATE(player), *num, *extra_num);
+ 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(mm_player_t* player, MMPlayerPathType path_type)
+__mmplayer_initialize_storage_info(mmplayer_t *player, mmplayer_path_type_e path_type)
{
int i = 0;
MMPLAYER_FENTER();
MMPLAYER_FLEAVE();
}
-int _mmplayer_manage_external_storage_state(MMHandleType hplayer, int id, int state)
+int
+_mmplayer_manage_external_storage_state(MMHandleType hplayer, int id, int state)
{
int ret = MM_ERROR_NONE;
- mm_player_t* player = (mm_player_t*)hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMMessageParamType msg_param = {0, };
MMPLAYER_FENTER();
return MM_ERROR_NONE;
/* FIXME: text path should be handled seperately. */
- 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) && (player->storage_info[MMPLAYER_PATH_TEXT].id == id))) {
+ 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)
+ && (player->storage_info[MMPLAYER_PATH_TEXT].id == id))) {
LOGW("external storage is removed");
if (player->msg_posted == FALSE) {
return ret;
}
-int _mmplayer_get_adaptive_variant_info(MMHandleType hplayer, int *num, char **var_info)
+int
+_mmplayer_get_adaptive_variant_info(MMHandleType hplayer, int *num, char **var_info)
{
int ret = MM_ERROR_NONE;
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
int idx = 0, total = 0;
gchar *result = NULL, *tmp = NULL;
result = g_strdup("");
for (idx = 0 ; idx < total ; idx++) {
- VariantData *v_data = NULL;
+ stream_variant_t *v_data = NULL;
v_data = g_list_nth_data(player->adaptive_info.var_list, idx);
if (v_data) {
return ret;
}
-int _mmplayer_set_max_adaptive_variant_limit(MMHandleType hplayer, int bandwidth, int width, int height)
+int
+_mmplayer_set_max_adaptive_variant_limit(MMHandleType hplayer, int bandwidth, int width, int height)
{
int ret = MM_ERROR_NONE;
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
}
-int _mmplayer_get_max_adaptive_variant_limit(MMHandleType hplayer, int *bandwidth, int *width, int *height)
+int
+_mmplayer_get_max_adaptive_variant_limit(MMHandleType hplayer, int *bandwidth, int *width, int *height)
{
int ret = MM_ERROR_NONE;
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
return ret;
}
-int _mmplayer_set_streaming_buffering_time(MMHandleType hplayer, int buffer_ms, int rebuffer_ms)
-{
- int ret = MM_ERROR_NONE;
- mm_player_t* player = (mm_player_t*) hplayer;
-
- MMPLAYER_FENTER();
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_NULL)
- LOGW("buffer_ms will not be applied.");
-
-
- LOGD("set buffering time %d ms / %d ms", buffer_ms, rebuffer_ms);
-
- if (player->streamer == NULL) {
- player->streamer = __mm_player_streaming_create();
- __mm_player_streaming_initialize(player->streamer);
- }
-
- if (buffer_ms >= 0)
- player->streamer->buffering_req.prebuffer_time = buffer_ms;
-
- if (rebuffer_ms >= 0)
- player->streamer->buffering_req.rebuffer_time = rebuffer_ms;
-
- MMPLAYER_FLEAVE();
- return ret;
-
-}
-
-int _mmplayer_get_streaming_buffering_time(MMHandleType hplayer, int *buffer_ms, int *rebuffer_ms)
+int
+_mmplayer_get_streaming_buffering_time(MMHandleType hplayer, int *prebuffer_ms, int *rebuffer_ms)
{
int ret = MM_ERROR_NONE;
- mm_player_t* player = (mm_player_t*) hplayer;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
MMPLAYER_FENTER();
- MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
- MMPLAYER_RETURN_VAL_IF_FAIL(buffer_ms && rebuffer_ms, MM_ERROR_COMMON_INVALID_ARGUMENT);
+ MMPLAYER_RETURN_VAL_IF_FAIL(player && player->streamer, MM_ERROR_PLAYER_NOT_INITIALIZED);
+ MMPLAYER_RETURN_VAL_IF_FAIL(prebuffer_ms && rebuffer_ms, MM_ERROR_COMMON_INVALID_ARGUMENT);
+ MMPLAYER_RETURN_VAL_IF_FAIL(MMPLAYER_IS_STREAMING(player), MM_ERROR_PLAYER_NO_OP);
- if (player->streamer == NULL) {
- player->streamer = __mm_player_streaming_create();
- __mm_player_streaming_initialize(player->streamer);
- }
+ *prebuffer_ms = player->streamer->buffering_req.prebuffer_time;
- *buffer_ms = player->streamer->buffering_req.prebuffer_time;
- *rebuffer_ms = player->streamer->buffering_req.rebuffer_time;
+ if (player->streamer->buffering_req.rebuffer_time > MIN_BUFFERING_TIME)
+ *rebuffer_ms = player->streamer->buffering_req.rebuffer_time;
+ else /* live case */
+ *rebuffer_ms = DEFAULT_LIVE_REBUFFER_TIME;
- LOGD("buffering time %d ms / %d ms", *buffer_ms, *rebuffer_ms);
+ LOGD("buffering time %d ms / %d ms", *prebuffer_ms, *rebuffer_ms);
MMPLAYER_FLEAVE();
return ret;
}
-int _mmplayer_set_codec_type(MMHandleType hplayer, MMPlayerStreamType stream_type, MMPlayerVideoCodecType codec_type)
+int
+_mmplayer_set_codec_type(MMHandleType hplayer, mmplayer_stream_type_e stream_type, mmplayer_video_codec_type_e codec_type)
{
#define IDX_FIRST_SW_CODEC 0
- mm_player_t* player = (mm_player_t*) hplayer;
- const char* attr_name = (stream_type == MM_PLAYER_STREAM_TYPE_AUDIO) ? (MM_PLAYER_AUDIO_CODEC_TYPE) : (MM_PLAYER_VIDEO_CODEC_TYPE);
+ 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;
MMPLAYER_FENTER();
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 a codec for codec_type %d", codec_type);
+ LOGE("There is no audio codec info for codec_type %d", codec_type);
return MM_ERROR_PLAYER_NO_OP;
}
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 v codec for codec_type %d", codec_type);
+ LOGE("There is no video codec info for codec_type %d", codec_type);
return MM_ERROR_PLAYER_NO_OP;
}
-
break;
default:
LOGE("Invalid stream type %s", MMPLAYER_STREAM_TYPE_GET_NAME(stream_type));
attrs = MMPLAYER_GET_ATTRS(player);
mm_attrs_set_int_by_name(attrs, attr_name, codec_type);
- if (mmf_attrs_commit(player->attrs)) {
+ if (mm_attrs_commit_all(player->attrs)) {
LOGE("failed to commit codec_type attributes");
return MM_ERROR_PLAYER_INTERNAL;
}
int
_mmplayer_set_replaygain_enabled(MMHandleType hplayer, bool enabled)
{
- mm_player_t* player = (mm_player_t*) hplayer;
- GstElement* rg_vol_element = NULL;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
+ GstElement *rg_vol_element = NULL;
MMPLAYER_FENTER();
/* just hold rgvolume enable value if pipeline is not ready */
if (!player->pipeline || !player->pipeline->audiobin) {
- LOGD("pipeline is not ready. holding rgvolume enable value\n");
+ LOGD("pipeline is not ready. holding rgvolume enable value");
return MM_ERROR_NONE;
}
int
_mmplayer_is_replaygain_enabled(MMHandleType hplayer, bool *enabled)
{
- mm_player_t* player = (mm_player_t*) hplayer;
- GstElement* rg_vol_element = NULL;
+ mmplayer_t *player = (mmplayer_t *)hplayer;
+ GstElement *rg_vol_element = NULL;
gboolean enable = FALSE;
MMPLAYER_FENTER();
/* just hold enable_rg value if pipeline is not ready */
if (!player->pipeline || !player->pipeline->audiobin) {
- LOGD("pipeline is not ready. holding rgvolume value (%d)\n", player->sound.rg_enable);
+ LOGD("pipeline is not ready. holding rgvolume value (%d)", player->sound.rg_enable);
*enabled = player->sound.rg_enable;
return MM_ERROR_NONE;
}
}
g_object_get(rg_vol_element, "enable-rgvolume", &enable, NULL);
- *enabled = enable;
+ *enabled = (bool)enable;
MMPLAYER_FLEAVE();
return MM_ERROR_NONE;
}
+
+int
+_mmplayer_set_video_roi_area(MMHandleType hplayer, double scale_x, double scale_y, double scale_width, double scale_height)
+{
+ mmplayer_t *player = (mmplayer_t *)hplayer;
+ MMHandleType attrs = 0;
+ void *handle = NULL;
+ int ret = MM_ERROR_NONE;
+
+ MMPLAYER_FENTER();
+
+ MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+
+ 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);
+ if (!handle) {
+ LOGE("Display handle is NULL, after setting window handle, set video roi area");
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+
+ player->video_roi.scale_x = scale_x;
+ player->video_roi.scale_y = scale_y;
+ player->video_roi.scale_width = scale_width;
+ player->video_roi.scale_height = scale_height;
+
+ /* check video sinkbin is created */
+ if (__mmplayer_video_param_check_video_sink_bin(player) != MM_ERROR_NONE)
+ return MM_ERROR_NONE;
+
+ if (!gst_video_overlay_set_video_roi_area(
+ GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
+ scale_x, scale_y, scale_width, scale_height))
+ ret = MM_ERROR_PLAYER_INTERNAL;
+ else
+ LOGD("set video param : video roi area scale value: x(%f) y(%f) width(%f) height(%f)",
+ scale_x, scale_y, scale_width, scale_height);
+
+ MMPLAYER_FLEAVE();
+
+ return ret;
+}
+
+int
+_mmplayer_get_video_roi_area(MMHandleType hplayer, double *scale_x, double *scale_y, double *scale_width, double *scale_height)
+{
+ mmplayer_t *player = (mmplayer_t *)hplayer;
+ int ret = MM_ERROR_NONE;
+
+ MMPLAYER_FENTER();
+
+ MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+ MMPLAYER_RETURN_VAL_IF_FAIL(scale_x && scale_y && scale_width && scale_height, MM_ERROR_INVALID_ARGUMENT);
+
+ *scale_x = player->video_roi.scale_x;
+ *scale_y = player->video_roi.scale_y;
+ *scale_width = player->video_roi.scale_width;
+ *scale_height = player->video_roi.scale_height;
+
+ LOGD("get video param : video roi area scale value: x(%f) y(%f) width(%f) height(%f)",
+ *scale_x, *scale_y, *scale_width, *scale_height);
+
+ return ret;
+}
+
+static gboolean
+__mmplayer_update_duration_value(mmplayer_t *player)
+{
+ gboolean ret = FALSE;
+ gint64 dur_nsec = 0;
+ LOGD("try to update duration");
+
+ if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec) && (dur_nsec > 0)) {
+ player->duration = dur_nsec;
+ LOGW("duration : %"G_GINT64_FORMAT" msec", GST_TIME_AS_MSECONDS(dur_nsec));
+ ret = TRUE;
+ }
+
+ if (player->duration < 0) {
+ LOGW("duration is Non-Initialized !!!");
+ player->duration = 0;
+ }
+
+ /* update streaming service type */
+ player->streaming_type = __mmplayer_get_stream_service_type(player);
+
+ /* check duration is OK */
+ if (dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING(player))
+ /* FIXIT : find another way to get duration here. */
+ LOGW("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
+
+ return ret;
+}
+
+static gboolean
+__mmplayer_update_audio_attrs(mmplayer_t *player, MMHandleType attrs)
+{
+ /* update audio params
+ NOTE : We need original audio params and it can be only obtained from src pad of audio
+ decoder. Below code only valid when we are not using 'resampler' just before
+ 'audioconverter'. */
+ GstCaps *caps_a = NULL;
+ 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);
+
+ 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 audio converter");
+ return FALSE;
+ }
+
+ caps_a = gst_pad_get_current_caps(pad);
+ if (!caps_a) {
+ LOGW("not ready to get audio caps");
+ gst_object_unref(pad);
+ return FALSE;
+ }
+
+ p = gst_caps_get_structure(caps_a, 0);
+
+ 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);
+
+ SECURE_LOGD("samplerate : %d channels : %d", samplerate, channels);
+
+ gst_caps_unref(caps_a);
+ gst_object_unref(pad);
+
+ return TRUE;
+}
+
+static gboolean
+__mmplayer_update_video_attrs(mmplayer_t *player, MMHandleType attrs)
+{
+ LOGD("try to update video attrs");
+
+ GstCaps *caps_v = NULL;
+ GstPad *pad = NULL;
+ gint tmpNu, tmpDe;
+ gint width, height;
+ GstStructure *p = NULL;
+
+ MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin, FALSE);
+ MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin[MMPLAYER_V_SINK].gst, FALSE);
+
+ pad = gst_element_get_static_pad(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink");
+ if (!pad) {
+ LOGD("no videosink sink pad");
+ return FALSE;
+ }
+
+ caps_v = gst_pad_get_current_caps(pad);
+ /* Use v_stream_caps, if fail to get video_sink sink pad*/
+ if (!caps_v && player->v_stream_caps) {
+ caps_v = player->v_stream_caps;
+ gst_caps_ref(caps_v);
+ }
+
+ if (!caps_v) {
+ LOGD("no negitiated 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);
+
+ gst_structure_get_fraction(p, "framerate", &tmpNu, &tmpDe);
+
+ SECURE_LOGD("width : %d height : %d", width, height);
+
+ gst_caps_unref(caps_v);
+ gst_object_unref(pad);
+
+ if (tmpDe > 0) {
+ mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
+ SECURE_LOGD("fps : %d", tmpNu / tmpDe);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+__mmplayer_update_bitrate_attrs(mmplayer_t *player, MMHandleType attrs)
+{
+ gboolean ret = FALSE;
+ guint64 data_size = 0;
+ gchar *path = NULL;
+ struct stat sb;
+
+ /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
+ if (!player->duration)
+ return FALSE;
+
+ if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
+ mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
+ if (stat(path, &sb) == 0)
+ data_size = (guint64)sb.st_size;
+
+ } else if (MMPLAYER_IS_HTTP_STREAMING(player)) {
+ data_size = player->http_content_size;
+ }
+
+ LOGD("try to update bitrate : data_size = %"G_GUINT64_FORMAT, data_size);
+
+ if (data_size) {
+ guint64 bitrate = 0;
+ guint64 msec_dur = 0;
+
+ 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);
+
+ 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);
+ ret = TRUE;
+ }
+ }
+
+ return ret;
+}
+
+static void
+__mmplayer_copy_uri_and_set_type(mmplayer_parse_profile_t *data, const char *uri, int uri_type)
+{
+ strncpy(data->uri, uri, MM_MAX_URL_LEN - 1);
+ data->uri_type = uri_type;
+}
+
+static int
+__mmplayer_set_mem_uri(mmplayer_parse_profile_t *data, char *path, void *param)
+{
+ int ret = MM_ERROR_PLAYER_INVALID_URI;
+ int mem_size = 0;
+ char *buffer = NULL;
+ char *seperator = strchr(path, ',');
+ char ext[100] = {0,}, size[100] = {0,};
+
+ if (seperator) {
+ if ((buffer = strstr(path, "ext="))) {
+ buffer += strlen("ext=");
+
+ if (strlen(buffer)) {
+ strncpy(ext, buffer, 99);
+
+ if ((seperator = strchr(ext, ','))
+ || (seperator = strchr(ext, ' '))
+ || (seperator = strchr(ext, '\0'))) {
+ seperator[0] = '\0';
+ }
+ }
+ }
+
+ if ((buffer = strstr(path, "size="))) {
+ buffer += strlen("size=");
+
+ if (strlen(buffer) > 0) {
+ strncpy(size, buffer, 99);
+
+ if ((seperator = strchr(size, ','))
+ || (seperator = strchr(size, ' '))
+ || (seperator = strchr(size, '\0'))) {
+ seperator[0] = '\0';
+ }
+
+ mem_size = atoi(size);
+ }
+ }
+ }
+
+ LOGD("ext: %s, mem_size: %d, mmap(param): %p", ext, mem_size, param);
+
+ if (mem_size && param) {
+ if (data->input_mem.buf)
+ free(data->input_mem.buf);
+ data->input_mem.buf = malloc(mem_size);
+
+ if (data->input_mem.buf) {
+ memcpy(data->input_mem.buf, param, mem_size);
+ data->input_mem.len = mem_size;
+ ret = MM_ERROR_NONE;
+ } else {
+ LOGE("failed to alloc mem %d", mem_size);
+ ret = MM_ERROR_PLAYER_INTERNAL;
+ }
+
+ data->input_mem.offset = 0;
+ data->uri_type = MM_PLAYER_URI_TYPE_MEM;
+ }
+
+ return ret;
+}
+
+static int
+__mmplayer_set_file_uri(mmplayer_parse_profile_t *data, const char *uri)
+{
+ gchar *location = NULL;
+ GError *err = NULL;
+ char *path = NULL;
+ int ret = MM_ERROR_NONE;
+
+ if ((path = strstr(uri, "file://"))) {
+ location = g_filename_from_uri(uri, NULL, &err);
+ if (!location || (err != NULL)) {
+ LOGE("Invalid URI '%s' for filesrc: %s", path,
+ (err != NULL) ? err->message : "unknown error");
+ if (err)
+ g_error_free(err);
+
+ MMPLAYER_FREEIF(location);
+
+ data->uri_type = MM_PLAYER_URI_TYPE_NONE;
+ return MM_ERROR_PLAYER_INVALID_URI;
+ }
+ LOGD("path from uri: %s", location);
+ }
+
+ path = (location != NULL) ? (location) : ((char *)uri);
+
+
+ ret = util_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)) {
+ LOGD("uri is actually a file but it's sdp file. giving it to rtspsrc");
+ data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
+ } else {
+ data->uri_type = MM_PLAYER_URI_TYPE_FILE;
+ }
+ } else if (ret == MM_ERROR_PLAYER_PERMISSION_DENIED) {
+ data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
+ } else {
+ LOGE("invalid uri, could not play..");
+ data->uri_type = MM_PLAYER_URI_TYPE_NONE;
+ }
+
+ MMPLAYER_FREEIF(location);
+
+ return ret;
+}
+
+static mmplayer_video_decoded_data_info_t *
+__mmplayer_create_stream_from_pad(GstPad *pad)
+{
+ GstCaps *caps = NULL;
+ GstStructure *structure = NULL;
+ unsigned int fourcc = 0;
+ const gchar *string_format = NULL;
+ mmplayer_video_decoded_data_info_t *stream = NULL;
+ gint width, height;
+ MMPixelFormatType format;
+ GstVideoInfo info;
+
+ caps = gst_pad_get_current_caps(pad);
+ if (!caps) {
+ LOGE("Caps is NULL.");
+ return NULL;
+ }
+
+ /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
+ 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);
+ gst_video_info_from_caps(&info, caps);
+ gst_caps_unref(caps);
+
+ /* moved here */
+ if (width == 0 || height == 0 || format == MM_PIXEL_FORMAT_INVALID) {
+ LOGE("Wrong condition!!");
+ return NULL;
+ }
+
+ stream = (mmplayer_video_decoded_data_info_t *)g_try_malloc0(sizeof(mmplayer_video_decoded_data_info_t));
+ if (!stream) {
+ LOGE("failed to alloc mem for video data");
+ return NULL;
+ }
+
+ stream->width = width;
+ stream->height = height;
+ stream->format = format;
+ stream->plane_num = GST_VIDEO_INFO_N_PLANES(&info);
+
+ return stream;
+}
+
+static void
+__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++) {
+ 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;
+ if (pitch)
+ stream->elevation[index] = size / pitch;
+ else
+ stream->elevation[index] = stream->height;
+ }
+}
+
+static gboolean
+__mmplayer_swcodec_set_stride_elevation(mmplayer_video_decoded_data_info_t *stream)
+{
+ if (stream->format == MM_PIXEL_FORMAT_I420) {
+ int ret = TBM_SURFACE_ERROR_NONE;
+ tbm_surface_h surface;
+ tbm_surface_info_s info;
+
+ surface = tbm_surface_create(stream->width, stream->height, TBM_FORMAT_YUV420);
+
+ ret = tbm_surface_get_info(surface, &info);
+ if (ret != TBM_SURFACE_ERROR_NONE) {
+ tbm_surface_destroy(surface);
+ return FALSE;
+ }
+
+ tbm_surface_destroy(surface);
+ stream->stride[0] = info.planes[0].stride;
+ stream->elevation[0] = info.planes[0].size / info.planes[0].stride;
+ stream->stride[1] = info.planes[1].stride;
+ stream->elevation[1] = info.planes[1].size / info.planes[1].stride;
+ stream->stride[2] = info.planes[2].stride;
+ stream->elevation[2] = info.planes[2].size / info.planes[2].stride;
+ stream->bo_size = info.planes[0].size + info.planes[1].size + info.planes[2].size;
+ } else if (stream->format == MM_PIXEL_FORMAT_RGBA) {
+ stream->stride[0] = stream->width * 4;
+ stream->elevation[0] = stream->height;
+ stream->bo_size = stream->stride[0] * stream->height;
+ } else {
+ LOGE("Not support format %d", stream->format);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+__mmplayer_swcodec_set_bo(mmplayer_t *player, mmplayer_video_decoded_data_info_t *stream, GstMemory *mem)
+{
+ tbm_bo_handle thandle;
+ gboolean is_mapped;
+ int src_stride[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
+ int src_offset[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
+ int dest_offset[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
+ int i = 0;
+ int j = 0;
+ int k = 0;
+ unsigned char *src = NULL;
+ unsigned char *dest = NULL;
+ GstMapInfo mapinfo = GST_MAP_INFO_INIT;
+
+ is_mapped = gst_memory_map(mem, &mapinfo, GST_MAP_READWRITE);
+ if (!is_mapped) {
+ LOGE("fail to gst_memory_map");
+ return FALSE;
+ }
+
+ if (!mapinfo.data) {
+ LOGE("data pointer is wrong");
+ goto ERROR;
+ }
+
+ stream->bo[0] = __mmplayer_video_stream_get_bo(player, stream->bo_size);
+ if (!stream->bo[0]) {
+ LOGE("Fail to tbm_bo_alloc!!");
+ goto ERROR;
+ }
+
+ thandle = tbm_bo_map(stream->bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
+ if (!thandle.ptr) {
+ LOGE("thandle pointer is wrong");
+ goto ERROR;
+ }
+
+ if (stream->format == MM_PIXEL_FORMAT_I420) {
+ src_stride[0] = GST_ROUND_UP_4(stream->width);
+ src_stride[1] = src_stride[2] = GST_ROUND_UP_4(stream->width >> 1);
+ src_offset[1] = src_stride[0] * GST_ROUND_UP_2(stream->height);
+ src_offset[2] = src_offset[1] + (src_stride[1] * (GST_ROUND_UP_2(stream->height) >> 1));
+
+ dest_offset[0] = 0;
+ dest_offset[1] = stream->stride[0] * stream->elevation[0];
+ dest_offset[2] = dest_offset[1] + stream->stride[1] * stream->elevation[1];
+
+ for (i = 0; i < 3; i++) {
+ src = mapinfo.data + src_offset[i];
+ dest = thandle.ptr + dest_offset[i];
+
+ if (i > 0)
+ k = 1;
+
+ for (j = 0; j < stream->height >> k; j++) {
+ memcpy(dest, src, stream->width>>k);
+ src += src_stride[i];
+ dest += stream->stride[i];
+ }
+ }
+ } else if (stream->format == MM_PIXEL_FORMAT_RGBA) {
+ memcpy(thandle.ptr, mapinfo.data, stream->bo_size);
+ } else {
+ LOGE("Not support format %d", stream->format);
+ goto ERROR;
+ }
+
+ tbm_bo_unmap(stream->bo[0]);
+ gst_memory_unmap(mem, &mapinfo);
+
+ return TRUE;
+
+ERROR:
+ if (stream->bo[0])
+ tbm_bo_unmap(stream->bo[0]);
+
+ if (is_mapped)
+ gst_memory_unmap(mem, &mapinfo);
+
+ return FALSE;
+}
+
+static void
+__mmplayer_set_pause_state(mmplayer_t *player)
+{
+ if (player->sent_bos)
+ return;
+
+ /* rtsp case, get content attrs by GstMessage */
+ if (MMPLAYER_IS_RTSP_STREAMING(player))
+ return;
+
+ /* it's first time to update all content attrs. */
+ __mmplayer_update_content_attrs(player, ATTR_ALL);
+}
+
+static void
+__mmplayer_set_playing_state(mmplayer_t *player)
+{
+ gchar *audio_codec = NULL;
+
+ if (player->resumed_by_rewind && player->playback_rate < 0.0) {
+ /* initialize because auto resume is done well. */
+ player->resumed_by_rewind = FALSE;
+ player->playback_rate = 1.0;
+ }
+
+ if (player->sent_bos)
+ return;
+
+ /* 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
+ * legacy mmfw-player api
+ */
+ __mmplayer_update_content_attrs(player, ATTR_MISSING_ONLY);
+
+ if ((player->cmd == MMPLAYER_COMMAND_START)
+ || (player->cmd == MMPLAYER_COMMAND_RESUME)) {
+ __mmplayer_handle_missed_plugin(player);
+ }
+
+ /* check audio codec field is set or not
+ * we can get it from typefinder or codec's caps.
+ */
+ mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
+
+ /* The codec format can't be sent for audio only case like amr, mid etc.
+ * Because, parser don't make related TAG.
+ * So, if it's not set yet, fill it with found data.
+ */
+ if (!audio_codec) {
+ if (g_strrstr(player->type, "audio/midi"))
+ audio_codec = "MIDI";
+ else if (g_strrstr(player->type, "audio/x-amr"))
+ audio_codec = "AMR";
+ else if (g_strrstr(player->type, "audio/mpeg")
+ && !g_strrstr(player->type, "mpegversion=(int)1"))
+ audio_codec = "AAC";
+ 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");
+
+ LOGD("set audio codec type with caps");
+ }
+
+ return;
+}