diff options
-rwxr-xr-x | configure.ac | 5 | ||||
-rwxr-xr-x | packaging/libmm-player.spec | 9 | ||||
-rwxr-xr-x | src/Makefile.am | 21 | ||||
-rwxr-xr-x | src/include/mm_player.h | 307 | ||||
-rwxr-xr-x | src/include/mm_player_asm.h | 64 | ||||
-rwxr-xr-x | src/include/mm_player_es.h | 79 | ||||
-rwxr-xr-x | src/include/mm_player_ini.h | 53 | ||||
-rwxr-xr-x | src/include/mm_player_internal.h | 112 | ||||
-rwxr-xr-x | src/include/mm_player_priv.h | 130 | ||||
-rwxr-xr-x | src/include/mm_player_utils.h | 7 | ||||
-rwxr-xr-x | src/mm_player.c | 282 | ||||
-rwxr-xr-x | src/mm_player_asm.c | 390 | ||||
-rwxr-xr-x | src/mm_player_attrs.c | 18 | ||||
-rwxr-xr-x | src/mm_player_audioeffect.c | 197 | ||||
-rwxr-xr-x | src/mm_player_capture.c | 122 | ||||
-rwxr-xr-x | src/mm_player_es.c | 708 | ||||
-rwxr-xr-x | src/mm_player_ini.c | 39 | ||||
-rwxr-xr-x | src/mm_player_priv.c | 1892 | ||||
-rwxr-xr-x | src/mm_player_utils.c | 20 |
19 files changed, 3431 insertions, 1024 deletions
diff --git a/configure.ac b/configure.ac index 9df2ed4..647c5f1 100755 --- a/configure.ac +++ b/configure.ac @@ -117,6 +117,11 @@ PKG_CHECK_MODULES(ICU, icu-i18n) AC_SUBST(ICU_CFLAGS) AC_SUBST(ICU_LIBS) + +PKG_CHECK_MODULES(MEDIAPACKET, capi-media-tool) +AC_SUBST(MEDIAPACKET_CFLAGS) +AC_SUBST(MEDIAPACKET_LIBS) + AC_ARG_ENABLE(sdk, AC_HELP_STRING([--enable-sdk], [sdk build]), [ case "${enableval}" in diff --git a/packaging/libmm-player.spec b/packaging/libmm-player.spec index 1a5349e..b737804 100755 --- a/packaging/libmm-player.spec +++ b/packaging/libmm-player.spec @@ -3,8 +3,8 @@ Name: libmm-player Summary: Multimedia Framework Player Library -Version: 0.5.56 -Release: 3 +Version: 0.5.60 +Release: 0 Group: Multimedia/Libraries License: Apache-2.0 URL: http://source.tizen.org @@ -28,6 +28,7 @@ BuildRequires: pkgconfig(evas) BuildRequires: pkgconfig(iniparser) BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(icu-i18n) +BuildRequires: pkgconfig(capi-media-tool) %description Multimedia Framework Player Library files. @@ -46,10 +47,10 @@ cp %{SOURCE1001} . %build %if %{with x} -CFLAGS+=" -Wall -D_FILE_OFFSET_BITS=64 -DHAVE_X11 -DEXPORT_API=\"__attribute__((visibility(\\\"default\\\")))\" "; export CFLAGS +CFLAGS+=" -Wall -D_FILE_OFFSET_BITS=64 -DTEST_ES -DHAVE_X11 -DEXPORT_API=\"__attribute__((visibility(\\\"default\\\")))\" "; export CFLAGS %endif %if %{with wayland} -CFLAGS+=" -Wall -D_FILE_OFFSET_BITS=64 -DHAVE_WAYLAND -DEXPORT_API=\"__attribute__((visibility(\\\"default\\\")))\" "; export CFLAGS +CFLAGS+=" -Wall -D_FILE_OFFSET_BITS=64 -DTEST_ES -DHAVE_WAYLAND -DEXPORT_API=\"__attribute__((visibility(\\\"default\\\")))\" "; export CFLAGS %endif LDFLAGS+="-Wl,--rpath=%{_prefix}/lib -Wl,--hash-style=both -Wl,--as-needed"; export LDFLAGS ./autogen.sh diff --git a/src/Makefile.am b/src/Makefile.am index f60a38f..22a2cf7 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,12 +10,14 @@ libmmfplayer_la_SOURCES = mm_player.c \ mm_player_priv.c \ mm_player_ini.c \ mm_player_utils.c \ + mm_player_asm.c \ mm_player_attrs.c \ mm_player_capture.c \ mm_player_pd.c \ mm_player_streaming.c \ mm_player_tracks.c \ - mm_player_audioeffect.c + mm_player_audioeffect.c \ + mm_player_es.c libmmfplayer_la_CFLAGS = -I$(srcdir)/include \ $(MMCOMMON_CFLAGS) \ @@ -23,18 +25,25 @@ libmmfplayer_la_CFLAGS = -I$(srcdir)/include \ $(GST_CFLAGS) \ $(GST_VIDEO_CFLAGS) \ $(GST_APP_CFLAGS) \ + $(MMSESSION_CFLAGS) \ $(MMSOUND_CFLAGS) \ + $(AUDIOSESSIONMGR_CFLAGS) \ $(VCONF_CFLAGS) \ - $(ICU_CFLAGS) + $(ICU_CFLAGS) \ + $(UTILX_CFLAGS) \ + $(MEDIAPACKET_CFLAGS) \ + -Wno-deprecated -Wno-deprecated-declarations noinst_HEADERS = include/mm_player_utils.h \ include/mm_player_ini.h \ include/mm_player_priv.h \ + include/mm_player_asm.h \ include/mm_player_attrs.h \ include/mm_player_capture.h \ include/mm_player_pd.h \ include/mm_player_tracks.h \ - include/mm_player_streaming.h + include/mm_player_streaming.h \ + include/mm_player_es.h libmmfplayer_la_LIBADD = $(GST_LIBS) \ $(MMCOMMON_LIBS) \ @@ -43,9 +52,13 @@ libmmfplayer_la_LIBADD = $(GST_LIBS) \ $(GST_VIDEO_LIBS) \ $(GST_APP_LIBS) \ $(INIPARSER_LIBS) \ + $(MMSESSION_LIBS) \ $(MMSOUND_LIBS) \ + $(AUDIOSESSIONMGR_LIBS) \ $(VCONF_LIBS) \ - $(ICU_LIBS) + $(ICU_LIBS) \ + $(MEDIAPACKET_LIBS) \ + $(UTILX_LIBS) libmmfplayer_la_CFLAGS += $(MMLOG_CFLAGS) -DMMF_LOG_OWNER=0x008 -DMMF_DEBUG_PREFIX=\"MMF-PLAYER\" -D_INTERNAL_SESSION_MANAGER_ libmmfplayer_la_LIBADD += $(MMLOG_LIBS) diff --git a/src/include/mm_player.h b/src/include/mm_player.h index 0a88670..7db7ba2 100755 --- a/src/include/mm_player.h +++ b/src/include/mm_player.h @@ -34,6 +34,7 @@ #include <mm_types.h> #include <mm_message.h> +#include <media_packet.h> #ifdef __cplusplus extern "C" { @@ -659,9 +660,11 @@ typedef struct { int height; /**< height of video buffer */ unsigned int timestamp; /**< timestamp of stream buffer (msec)*/ unsigned int length_total; /**< total length of stream buffer (in byte)*/ - void *data; + void *data[BUFFER_MAX_PLANE_NUM]; void *bo[BUFFER_MAX_PLANE_NUM]; /**< TBM buffer object */ void *internal_buffer; /**< Internal buffer pointer */ + int stride[BUFFER_MAX_PLANE_NUM]; /**< stride of plane */ + int elevation[BUFFER_MAX_PLANE_NUM]; /**< elevation of plane */ }MMPlayerVideoStreamDataType; /** @@ -738,9 +741,7 @@ typedef enum { */ typedef enum { MM_PLAYER_TRACK_TYPE_AUDIO = 0, -#ifdef _USE_M_V_INPUT_SELECTOR_ MM_PLAYER_TRACK_TYPE_VIDEO, -#endif MM_PLAYER_TRACK_TYPE_TEXT, MM_PLAYER_TRACK_TYPE_MAX }MMPlayerTrackType; @@ -773,6 +774,7 @@ typedef enum MM_PLAYER_SOUND_RESOURCE_PRELISTENING_MEDIA, } MMPlayerSoundResource; + /** * Edge Properties of the text. */ @@ -784,6 +786,26 @@ typedef enum { MM_PLAYER_EDGE_DROPSHADOW } MMPlayerSubtitleEdge; +/** + * Enumeration of media stream buffer status + */ +typedef enum +{ + MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, + MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, +} MMPlayerMediaStreamBufferStatus; + +/** + * Enumeration for stream type. + */ +typedef enum +{ + MM_PLAYER_STREAM_TYPE_DEFAULT, /**< Container type */ + MM_PLAYER_STREAM_TYPE_AUDIO, /**< Audio element stream type */ + MM_PLAYER_STREAM_TYPE_VIDEO, /**< Video element stream type */ + MM_PLAYER_STREAM_TYPE_TEXT, /**< Text type */ + MM_PLAYER_STREAM_TYPE_MAX, +} MMPlayerStreamType; /** * Attribute validity structure @@ -842,6 +864,57 @@ typedef struct { float level[MM_VOLUME_CHANNEL_NUM]; /**< Relative volume factor for each channels */ } MMPlayerVolumeType; +#ifdef TEST_ES +/** + * Video stream info in external demux case + * +**/ +typedef struct _VideoStreamInfo +{ + const char *mime; + unsigned int framerate_num; + unsigned int framerate_den; + unsigned int width; + unsigned int height; + unsigned char *codec_extradata; + unsigned int extradata_size; + unsigned int version; +}MMPlayerVideoStreamInfo; + +/** + * Audio stream info in external demux case + * +**/ +typedef struct _AudioStreamInfo +{ + const char *mime; + unsigned int channels; + unsigned int sample_rate; + unsigned char *codec_extradata; + unsigned int extradata_size; + unsigned int version; + unsigned int user_info; + + /* for pcm */ +// unsigned int width; +// unsigned int depth; +// unsigned int endianness; +// bool signedness; +}MMPlayerAudioStreamInfo; + +/** + * Subtitle stream info in external demux case + * +**/ +typedef struct _SubtitleStreamInfo +{ + const char *mime; + unsigned int codec_tag; + void *context; //for smpte text +}MMPlayerSubtitleStreamInfo; + +#endif + /** * Audio stream callback function type. * @@ -866,6 +939,37 @@ typedef bool (*mm_player_audio_stream_callback) (void *stream, int stream_size, */ typedef bool (*mm_player_track_selected_subtitle_language_callback)(int track_num, void *user_param); +/** + * Buffer underrun / overflow data callback function type. + * + * @param status [in] buffer status + * @param user_param [in] User defined parameter which is passed when set + * to enough data callback or need data callback + * + * @return This callback function have to return MM_ERROR_NONE. + */ +typedef bool (*mm_player_media_stream_buffer_status_callback) (MMPlayerStreamType type, MMPlayerMediaStreamBufferStatus status, void *user_param); + +/** + * Buffer seek data callback function type. + * + * @param offset [in] offset for the buffer playback + * @param user_param [in] User defined parameter which is passed when set + * to seek data callback + * + * @return This callback function have to return MM_ERROR_NONE. + */ +typedef bool (*mm_player_media_stream_seek_data_callback) (MMPlayerStreamType type, unsigned long long offset, void *user_param); + +/** + * Called to notify the stream changed. + * + * @param user_data [in] The user data passed from the callback registration function + * + * @return This callback function have to return MM_ERROR_NONE. + */ +typedef bool (*mm_player_stream_changed_callback) (void *user_param); + /*=========================================================================================== | | @@ -1934,6 +2038,203 @@ int mm_player_get_next_uri(MMHandleType player, char **uri); int mm_player_enable_media_packet_video_stream(MMHandleType player, bool enable); +/** + * This function is to increase reference count of internal buffer. + * + * @param buffer [in] video callback internal buffer + * @return This function returns buffer point; + * + * @see + * @remark None + */ +void * mm_player_media_packet_video_stream_internal_buffer_ref(void *buffer); + +/** + * This function is to decrease reference count of internal buffer. + * + * @param buffer [in] video callback internal buffer + * @return None; + * + * @see + * @remark None + */ +void mm_player_media_packet_video_stream_internal_buffer_unref(void *buffer); + +#ifdef TEST_ES + +/**mm_player_submit_packet + * This function is to submit buffer to appsrc. \n + * @param player [in] Handle of player. + * @param buf [in] buffer to be submit in appsrc in external feeder case. + * @param len [in] length of buffer. + * @param pts [in] timestamp of buffer. + * @param streamtype [in] stream type of buffer. + * @return This function returns zero on success, or negative value with error code. + * @par Example + * + * @endcode + */ +int mm_player_submit_packet(MMHandleType player, media_packet_h packet); + +/**mm_player_set_video_info + * This function is to set caps of src pad of video appsrc in external feeder case. \n + * @param player [in] Handle of player. + * @param media_format_h [in] Video stream info. + * @return This function returns zero on success, or negative value with error code. + * @par Example + * + * @endcode + */ + +int mm_player_set_video_info (MMHandleType player, media_format_h format); + +/**mm_player_set_audio_info + * This function is to set caps of src pad of Audio appsrc in external feeder case. \n + * @param player [in] Handle of player. + * @param media_format_h [in] Audio stream info. + * @return This function returns zero on success, or negative value with error code. + * @par Example + * + * @endcode + */ + +int mm_player_set_audio_info (MMHandleType player, media_format_h format); + +/**mm_player_set_subtitle_info + * This function is to set caps of src pad of subtitle appsrc in external feeder case. \n + * @param player [in] Handle of player. + * @param subtitle_stream_info [in] Subtitle stream info. + * @return This function returns zero on success, or negative value with error code. + * @par Example + * + * @endcode + */ + +int mm_player_set_subtitle_info (MMHandleType player, MMPlayerSubtitleStreamInfo *info); + +/** + * This function set callback function for receiving need or enough data message from player. + * + * @param player [in] Handle of player. + * @param type [in] stream type + * @param callback [in] data callback function for stream type. + * @param user_param [in] User parameter. + * + * @return This function returns zero on success, or negative value with error + * code. + * @remark + * @see + * @since + */ +int mm_player_set_media_stream_buffer_status_callback(MMHandleType player, MMPlayerStreamType type, mm_player_media_stream_buffer_status_callback callback, void * user_param); + +/** + * This function set callback function for receiving seek data message from player. + * + * @param player [in] Handle of player. + * @param type [in] stream type + * @param callback [in] Seek data callback function for stream type. + * @param user_param [in] User parameter. + * + * @return This function returns zero on success, or negative value with error + * code. + * @remark + * @see + * @since + */ +int mm_player_set_media_stream_seek_data_callback(MMHandleType player, MMPlayerStreamType type, mm_player_media_stream_seek_data_callback callback, void * user_param); + +/** + * This function is to set max size of buffer(appsrc). + * + * @param player [in] Handle of player. + * @param type [in] stream type + * @param max_size [in] max bytes of buffer. + * + * @return This function returns zero on success, or negative value with error + * code. + * @remark + * @see + * @since + */ +int mm_player_set_media_stream_buffer_max_size(MMHandleType player, MMPlayerStreamType type, unsigned long long max_size); + +/** + * This function is to get max size of buffer(appsrc). + * + * @param player [in] Handle of player. + * @param type [in] stream type + * @param max_size [out] max bytes of buffer. + * + * @return This function returns zero on success, or negative value with error + * code. + * @remark + * @see + * @since + */ +int mm_player_get_media_stream_buffer_max_size(MMHandleType player, MMPlayerStreamType type, unsigned long long *max_size); + +/** + * This function is to set min percent of buffer(appsrc). + * + * @param player [in] Handle of player. + * @param type [in] stream type + * @param min_percent [in] min percent of buffer. + * + * @return This function returns zero on success, or negative value with error + * code. + * @remark + * @see + * @since + */ +int mm_player_set_media_stream_buffer_min_percent(MMHandleType player, MMPlayerStreamType type, unsigned min_percent); + +/** + * This function is to get min percent of buffer(appsrc). + * + * @param player [in] Handle of player. + * @param type [in] stream type + * @param min_percent [out] min percent of buffer. + * + * @return This function returns zero on success, or negative value with error + * code. + * @remark + * @see + * @since + */ +int mm_player_get_media_stream_buffer_min_percent(MMHandleType player, MMPlayerStreamType type, unsigned int *min_percent); + +/** + * This function set callback function for changing audio stream from player. \n + * It's only supported when audio stream is included in file. \n + * + * @param player [in] Handle of player. + * @param callback [in] Audio stream changed callback function. + * @param user_param [in] User parameter. + * + * @return This function returns zero on success, or negative value with error + * code. + * @see mm_player_stream_changed_callback + * @since + */ +int mm_player_set_audio_stream_changed_callback(MMHandleType player, mm_player_stream_changed_callback callback, void *user_param); + +/** + * This function set callback function for changing video stream from player. \n + * It's only supported when video stream is included in file. \n + * + * @param player [in] Handle of player. + * @param callback [in] Video stream changed callback function. + * @param user_param [in] User parameter. + * + * @return This function returns zero on success, or negative value with error + * code. + * @see mm_player_stream_changed_callback + * @since + */ +int mm_player_set_video_stream_changed_callback(MMHandleType player, mm_player_stream_changed_callback callback, void *user_param); + +#endif /** @} diff --git a/src/include/mm_player_asm.h b/src/include/mm_player_asm.h new file mode 100755 index 0000000..4ff18cf --- /dev/null +++ b/src/include/mm_player_asm.h @@ -0,0 +1,64 @@ +/* + * libmm-player + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>, + * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __MM_PLAYER_ASM_H__ +#define __MM_PLAYER_ASM_H__ + +#include <glib.h> +#include <mm_types.h> + +#include <mm_session.h> +#include <mm_session_private.h> +#include <audio-session-manager.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int handle; + int pid; + bool by_asm_cb; + int antishock; + int event_src; + int skip_session; + bool keep_last_pos; + int user_route_policy; + ASM_sound_states_t state; + ASM_sound_events_t event; + ASM_resource_t resource; + bool exit_cb; + bool cb_pending; +} MMPlayerASM; + +gint _mmplayer_asm_register(MMPlayerASM* sm, ASM_sound_cb_t callback, void* param); +gint _mmplayer_asm_unregister(MMPlayerASM* sm); +gint _mmplayer_asm_set_state(MMHandleType player, ASM_sound_states_t state, gboolean enable_safety_vol); +gint _mmplayer_asm_ignore_session(MMHandleType player); +gint _mmplayer_asm_set_sound_resource(MMHandleType player, MMPlayerSoundResource mode); +ASM_cb_result_t __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data); + +#ifdef __cplusplus +} +#endif + +#endif /* __MM_PLAYER_ASM_H__ */ diff --git a/src/include/mm_player_es.h b/src/include/mm_player_es.h new file mode 100755 index 0000000..977e6b6 --- /dev/null +++ b/src/include/mm_player_es.h @@ -0,0 +1,79 @@ +/* + * libmm-player + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, heechul jeon <heechul.jeon@samsung.co>, + * YoungHwan An <younghwan_.an@samsung.com>, Eunhae Choi <eunhae1.choi@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __MM_PLAYER_ES_H__ +#define __MM_PLAYER_ES_H__ + +/*======================================================================================= +| INCLUDE FILES | +========================================================================================*/ +#include <mm_types.h> +#include "mm_player_priv.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*======================================================================================= +| GLOBAL FUNCTION PROTOTYPES | +========================================================================================*/ + +int _mmplayer_set_video_info (MMHandleType player, media_format_h format); + +int _mmplayer_set_audio_info (MMHandleType player, media_format_h format); + +int _mmplayer_set_subtitle_info (MMHandleType player, MMPlayerSubtitleStreamInfo * info); + +int _mmplayer_submit_packet (MMHandleType player, media_packet_h packet); + +int _mmplayer_set_media_stream_buffer_status_cb (MMHandleType player, + MMPlayerStreamType type, + mm_player_media_stream_buffer_status_callback callback, + void * user_param); + +int _mmplayer_set_media_stream_seek_data_cb (MMHandleType player, + MMPlayerStreamType type, + mm_player_media_stream_seek_data_callback callback, + void * user_param); + +int _mmplayer_set_media_stream_max_size (MMHandleType hplayer, + MMPlayerStreamType type, + guint64 max_size); + +int _mmplayer_get_media_stream_max_size(MMHandleType hplayer, + MMPlayerStreamType type, + guint64 *max_size); + +int _mmplayer_set_media_stream_min_percent(MMHandleType hplayer, + MMPlayerStreamType type, + guint min_percent); + +int _mmplayer_get_media_stream_min_percent(MMHandleType hplayer, + MMPlayerStreamType type, + guint *min_percent); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/mm_player_ini.h b/src/include/mm_player_ini.h index 952c839..6726f59 100755 --- a/src/include/mm_player_ini.h +++ b/src/include/mm_player_ini.h @@ -62,7 +62,6 @@ typedef struct __mm_player_ini gchar videosink_element_fake[PLAYER_INI_MAX_STRLEN]; gchar name_of_audio_resampler[PLAYER_INI_MAX_STRLEN]; gchar name_of_audiosink[PLAYER_INI_MAX_STRLEN]; - gchar name_of_drmsrc[PLAYER_INI_MAX_STRLEN]; gchar name_of_video_converter[PLAYER_INI_MAX_STRLEN]; gboolean skip_rescan; gboolean generate_dot; @@ -72,7 +71,6 @@ typedef struct __mm_player_ini gint localplayback_state_change_timeout; gint delay_before_repeat; gint eos_delay; - gboolean multiple_codec_supported; gchar gst_param[5][PLAYER_INI_MAX_PARAM_STRLEN]; gchar exclude_element_keyword[PLAYER_INI_MAX_ELEMENT][PLAYER_INI_MAX_STRLEN]; @@ -114,17 +112,6 @@ typedef struct __mm_player_ini guint rtsp_buffering_time; guint rtsp_rebuffering_time; gboolean rtsp_do_typefinding; - gboolean rtsp_error_concealment; /* testing purpose */ - - /* hw accelation */ - gboolean use_video_hw_accel; - - /* priority */ - gboolean use_priority_setting; - gint demux_priority; - gint audiosink_priority; - gint videosink_priority; - gint ringbuffer_priority; /* dump buffer for debug */ gchar dump_element_keyword[PLAYER_INI_MAX_ELEMENT][PLAYER_INI_MAX_STRLEN]; @@ -157,18 +144,16 @@ typedef struct __mm_player_ini #define DEFAULT_PROVIDE_CLOCK_FOR_MOVIE FALSE #define DEFAULT_DELAY_BEFORE_REPEAT 50 /* msec */ #define DEFAULT_EOS_DELAY 150 /* msec */ -#define DEFAULT_DRMSRC "drmsrc" #define DEFAULT_VIDEOSINK_X "xvimagesink" #define DEFAULT_VIDEOSINK_EVAS "evasimagesink" #define DEFAULT_VIDEOSINK_FAKE "fakesink" #define DEFAULT_AUDIORESAMPLER "audioresample" -#define DEFAULT_AUDIOSINK "avsysaudiosink" +#define DEFAULT_AUDIOSINK "pulsesink" #define DEFAULT_GST_PARAM "" #define DEFAULT_EXCLUDE_KEYWORD "" #define DEFAULT_ASYNC_START TRUE #define DEFAULT_DISABLE_SEGTRAP TRUE #define DEFAULT_VIDEO_CONVERTER "" -#define DEFAULT_MULTIPLE_CODEC_SUPPORTED TRUE #define DEFAULT_LIVE_STATE_CHANGE_TIMEOUT 30 /* sec */ #define DEFAULT_LOCALPLAYBACK_STATE_CHANGE_TIMEOUT 10 /* sec */ /* http streaming */ @@ -183,15 +168,6 @@ typedef struct __mm_player_ini #define DEFAULT_RTSP_BUFFERING 5000 /* msec */ #define DEFAULT_RTSP_REBUFFERING 15000 /* msec */ #define DEFAULT_RTSP_DO_TYPEFINDING FALSE -#define DEFAULT_RTSP_ERROR_CONCEALMENT TRUE -/* hw accel */ -#define DEFAULT_USE_VIDEO_HW_ACCEL FALSE -/* priority */ -#define DEFAULT_USE_PRIORITY_SETTING FALSE -#define DEFAULT_PRIORITY_DEMUX 96 -#define DEFAULT_PRIORITY_VIDEO_SINK 97 -#define DEFAULT_PRIORITY_AUDIO_SINK 98 -#define DEFAULT_PRIORITY_RINGBUFFER 99 /* dump buffer for debug */ #define DEFAULT_DUMP_ELEMENT_KEYWORD "" @@ -204,8 +180,6 @@ typedef struct __mm_player_ini "\ [general] \n\ \n\ -use sink handler = yes \n\ -\n\ disable segtrap = yes ; same effect with --gst-disable-segtrap \n\ \n\ ; set default video sink but, it can be replaced with others selected by application\n\ @@ -214,9 +188,7 @@ videosink element = 2 \n\ \n\ video converter element = \n\ \n\ -audiosink element = avsysaudiosink \n\ -\n\ -drmsrc element = drmsrc \n\ +audiosink element = pulsesink \n\ \n\ ; if yes. gstreamer will not update registry \n\ skip rescan = yes \n\ @@ -228,8 +200,6 @@ element exclude keyword = \n\ \n\ async start = yes \n\ \n\ -multiple codec supported = yes \n\ -\n\ ; parameters for initializing gstreamer \n\ gstparam1 = \n\ gstparam2 = \n\ @@ -278,25 +248,6 @@ rtsp rebuffering time = 15000; msec \n\ \n\ rtsp do typefinding = no; if no, caps on rtspsrc:src pad will be used for autoplugging \n\ \n\ -rtsp error concealment = yes \n\ -\n\ -\n\ -[hw accelation] \n\ -use video hw accel = yes \n\ -\n\ -\n\ -[priority] \n\ -\n\ -use priority setting = no \n\ -\n\ -demux = 95 \n\ -\n\ -videosink = 96 \n\ -\n\ -audiosink = 97\n\ -\n\ -ringbuffer = 98 \n\ -\n\ " int diff --git a/src/include/mm_player_internal.h b/src/include/mm_player_internal.h index e298fbf..33734f7 100755 --- a/src/include/mm_player_internal.h +++ b/src/include/mm_player_internal.h @@ -112,37 +112,16 @@ typedef struct unsigned int orientation; /* content orientation */ }MMPlayerVideoCapture; -/** - * Buffer need data callback function type. - * - * @param size [in] size required for the buffer playback - * @param user_param [in] User defined parameter which is passed when set - * to need data callback - * - * @return This callback function have to return MM_ERROR_NONE. - */ -typedef bool (*mm_player_buffer_need_data_callback) (unsigned int size, void *user_param); - -/** - * Buffer enough data callback function type. - * - * @param user_param [in] User defined parameter which is passed when set - * to enough data callback - * - * @return This callback function have to return MM_ERROR_NONE. - */ -typedef bool (*mm_player_buffer_enough_data_callback) (void *user_param); - -/** - * Buffer seek data callback function type. - * - * @param offset [in] offset for the buffer playback - * @param user_param [in] User defined parameter which is passed when set - * to seek data callback - * - * @return This callback function have to return MM_ERROR_NONE. - */ -typedef bool (*mm_player_buffer_seek_data_callback) (unsigned long long offset, void *user_param); +typedef struct +{ + void *data; + int data_size; + int channel; + int bitrate; + int depth; + bool is_little_endian; + guint64 channel_mask; +}MMPlayerAudioStreamDataType; /** * Video stream callback function type. @@ -182,6 +161,16 @@ typedef bool (*mm_player_video_capture_callback) (void *stream, int stream_size, typedef bool (*mm_player_video_frame_render_error_callback) (void *error_id, void *user_param); /** + * Audio stream callback function type. + * + * @param stream [in] Reference pointer to audio frame data + * @param user_param [in] User defined parameter which is passed when set + * audio stream callback + * + * @return This callback function have to return MM_ERROR_NONE. + */ +typedef bool (*mm_player_audio_stream_callback_ex) (MMPlayerAudioStreamDataType *stream, void *user_param); +/** * This function is to set play speed for playback. * * @param player [in] Handle of player. @@ -213,6 +202,22 @@ int mm_player_set_play_speed(MMHandleType player, float rate); int mm_player_set_video_stream_callback(MMHandleType player, mm_player_video_stream_callback callback, void *user_param); /** + * This function set callback function for receiving audio stream from player. + * + * @param player [in] Handle of player. + * @param sync [in] sync Sync on the clock. + * @param callback [in] audio stream callback function. + * @param user_param [in] User parameter. + * + * @return This function returns zero on success, or negative value with error + * code. + * @remark + * @see mm_player_audio_stream_callback_ex + * @since + */ +int mm_player_set_audio_stream_callback_ex(MMHandleType player, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param); + +/** * This function set callback function for rendering error information of video render plug-in. * * @param player [in] Handle of player. @@ -244,51 +249,6 @@ int mm_player_set_video_frame_render_error_callback(MMHandleType player, mm_play int mm_player_do_video_capture(MMHandleType player); /** - * This function set callback function for receiving need data message from player. - * - * @param player [in] Handle of player. - * @param callback [in] Need data callback function. - * @param user_param [in] User parameter. - * - * @return This function returns zero on success, or negative value with error - * code. - * @remark - * @see mm_player_set_buffer_enough_data_callback - * @since - */ -int mm_player_set_buffer_need_data_callback(MMHandleType player, mm_player_buffer_need_data_callback callback , void *user_param); - -/** - * This function set callback function for receiving enough data message from player. - * - * @param player [in] Handle of player. - * @param callback [in] Enough data callback function. - * @param user_param [in] User parameter. - * - * @return This function returns zero on success, or negative value with error - * code. - * @remark - * @see mm_player_set_buffer_need_data_callback - * @since - */ -int mm_player_set_buffer_enough_data_callback(MMHandleType player, mm_player_buffer_enough_data_callback callback, void *user_param); - -/** - * This function set callback function for receiving seek data message from player. - * - * @param player [in] Handle of player. - * @param callback [in] Seek data callback function. - * @param user_param [in] User parameter. - * - * @return This function returns zero on success, or negative value with error - * code. - * @remark - * @see - * @since - */ -int mm_player_set_buffer_seek_data_callback(MMHandleType player, mm_player_buffer_seek_data_callback callback, void *user_param); - -/** * This function set callback function for putting data into player. * * @param player [in] Handle of player. diff --git a/src/include/mm_player_priv.h b/src/include/mm_player_priv.h index 2553e7a..457d263 100755 --- a/src/include/mm_player_priv.h +++ b/src/include/mm_player_priv.h @@ -42,7 +42,7 @@ #include "mm_player_audioeffect.h" #include "mm_message.h" #include "mm_player_ini.h" -//#include "mm_player_asm.h" +#include "mm_player_asm.h" #include "mm_player_pd.h" #include "mm_player_streaming.h" @@ -131,6 +131,9 @@ enum MMPlayerUriType { MM_PLAYER_URI_TYPE_FILE, /**< Player URI type File */ MM_PLAYER_URI_TYPE_URL, /**< Player URI type URL */ MM_PLAYER_URI_TYPE_BUFF, /**< Player URI type Buffer */ +#ifdef TEST_ES + MM_PLAYER_URI_TYPE_ES_BUFF, /**< Player URI type ES Buffer */ +#endif MM_PLAYER_URI_TYPE_HLS, /**< Player URI type http live streaming */ MM_PLAYER_URI_TYPE_SS, /**< Player URI type Smooth streaming */ MM_PLAYER_URI_TYPE_DASH, /**< Player URI type Mpeg Dash */ @@ -171,12 +174,20 @@ enum MainElementID { MMPLAYER_M_PIPE = 0, /* NOTE : MMPLAYER_M_PIPE should be zero */ MMPLAYER_M_SRC, +#ifdef TEST_ES + MMPLAYER_M_2ND_SRC, /* 2nd Source Element for es buff src */ +#endif MMPLAYER_M_SUBSRC, /* it could be a decodebin or could be a typefind. depends on player ini */ MMPLAYER_M_TYPEFIND, MMPLAYER_M_AUTOPLUG, +#ifdef TEST_ES + MMPLAYER_M_AUTOPLUG_V_DEC, + MMPLAYER_M_AUTOPLUG_A_DEC, +#endif + /* NOTE : we need two fakesink to autoplug without decodebin. * first one will hold whole pipeline state. and second one will hold state of * a sink-decodebin for an elementary stream. no metter if there's more then one @@ -190,6 +201,13 @@ enum MainElementID MMPLAYER_M_DEMUXED_S_BUFFER, MMPLAYER_M_ID3DEMUX, +#ifdef TEST_ES + /* es buff src queue */ + MMPLAYER_M_V_BUFFER, + MMPLAYER_M_A_BUFFER, + MMPLAYER_M_S_BUFFER, +#endif + /* FIXIT : if there's really no usage for following IDs. remove it */ MMPLAYER_M_DEC1, MMPLAYER_M_DEC2, @@ -226,6 +244,7 @@ enum AudioElementID MMPLAYER_A_CAPS_DEFAULT, MMPLAYER_A_SINK, MMPLAYER_A_RESAMPLER, + MMPLAYER_A_DEINTERLEAVE, MMPLAYER_A_NUM }; @@ -402,69 +421,6 @@ typedef struct { GList *uri_list; }MMPlayerUriList; -/* image buffer definition *************************************************** - - +------------------------------------------+ --- - | | ^ - | a[], p[] | | - | +---------------------------+ --- | | - | | | ^ | | - | |<---------- w[] ---------->| | | | - | | | | | | - | | | | - | | | h[] | e[] - | | | | - | | | | | | - | | | | | | - | | | v | | - | +---------------------------+ --- | | - | | v - +------------------------------------------+ --- - - |<----------------- s[] ------------------>| -*/ -typedef struct -{ - /* width of each image plane */ - int w[MM_PLAYER_IMGB_MPLANE_MAX]; - /* height of each image plane */ - int h[MM_PLAYER_IMGB_MPLANE_MAX]; - /* stride of each image plane */ - int s[MM_PLAYER_IMGB_MPLANE_MAX]; - /* elevation of each image plane */ - int e[MM_PLAYER_IMGB_MPLANE_MAX]; - /* user space address of each image plane */ - void *a[MM_PLAYER_IMGB_MPLANE_MAX]; - /* physical address of each image plane, if needs */ - void *p[MM_PLAYER_IMGB_MPLANE_MAX]; - /* color space type of image */ - int cs; - /* left postion, if needs */ - int x; - /* top position, if needs */ - int y; - /* to align memory */ - int __dummy2; - /* arbitrary data */ - int data[16]; - /* dmabuf or ion fd */ - int fd[MM_PLAYER_IMGB_MPLANE_MAX]; - /* flag for buffer share */ - int buf_share_method; - /* Y plane size */ - int y_size; - /* UV plane size */ - int uv_size; - /* Tizen buffer object of each image plane */ - void *bo[MM_PLAYER_IMGB_MPLANE_MAX]; - /* JPEG data */ - void *jpeg_data; - /* JPEG size */ - int jpeg_size; - /* tzmem buffer */ - int tz_enable; -} MMPlayerMPlaneImage; - typedef struct { gint active_pad_index; gint total_track_num; @@ -521,7 +477,7 @@ typedef struct { GMutex capture_thread_mutex; MMPlayerVideoCapture capture; MMPlayerVideoColorspace video_cs; - MMPlayerMPlaneImage captured; + MMVideoBuffer captured; /* fakesink handling lock */ GMutex fsink_lock; @@ -548,13 +504,23 @@ typedef struct { /* pad */ GstPad *ghost_pad_for_videobin; - /* buffering support cbs*/ - mm_player_buffer_need_data_callback need_data_cb; - mm_player_buffer_enough_data_callback enough_data_cb; - mm_player_buffer_seek_data_callback seek_data_cb; +#ifdef TEST_ES + guint64 media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_MAX]; + guint media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_MAX]; + mm_player_media_stream_buffer_status_callback media_stream_buffer_status_cb[MM_PLAYER_STREAM_TYPE_MAX]; + mm_player_media_stream_seek_data_callback media_stream_seek_data_cb[MM_PLAYER_STREAM_TYPE_MAX]; +#endif void* buffer_cb_user_param; + /* video stream changed callback */ + mm_player_stream_changed_callback video_stream_changed_cb; + void* video_stream_changed_cb_user_param; + + /* audio stream changed callback */ + mm_player_stream_changed_callback audio_stream_changed_cb; + void* audio_stream_changed_cb_user_param; + /* video stream callback */ mm_player_video_stream_callback video_stream_cb; void* video_stream_cb_user_param; @@ -563,6 +529,10 @@ typedef struct { /* audio stram callback */ mm_player_audio_stream_callback audio_stream_cb; void* audio_stream_cb_user_param; + bool audio_stream_sink_sync; + + /* audio buffer callback */ + mm_player_audio_stream_callback_ex audio_stream_render_cb_ex; /* video capture callback*/ gulong video_capture_cb_probe_id; @@ -676,7 +646,7 @@ typedef struct { gboolean is_nv12_tiled; gboolean is_drm_file; - //MMPlayerASM sm; + MMPlayerASM sm; gboolean is_subtitle_off; gboolean is_external_subtitle_present; @@ -760,6 +730,17 @@ typedef struct { gboolean has_closed_caption; GstElement *video_fakesink; +#ifdef TEST_ES + /* audio stream caps parsed by demuxer or set by external demuxer */ + GstCaps* a_stream_caps; + + /* subtitle stream caps parsed by demuxer or set by external demuxer */ + GstCaps* s_stream_caps; + + /*es player using feed-data callback or calling app_src_push_buffer directly*/ + gboolean es_player_push_mode; + +#endif } mm_player_t; typedef struct @@ -805,12 +786,11 @@ int _mmplayer_adjust_video_postion(MMHandleType hplayer,int offset); int _mmplayer_activate_section_repeat(MMHandleType hplayer, unsigned long start, unsigned long end); int _mmplayer_deactivate_section_repeat(MMHandleType hplayer); int _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size); -int _mmplayer_set_buffer_need_data_cb(MMHandleType hplayer,mm_player_buffer_need_data_callback callback, void *user_param); -int _mmplayer_set_buffer_enough_data_cb(MMHandleType hplayer,mm_player_buffer_enough_data_callback callback, void *user_param); -int _mmplayer_set_buffer_seek_data_cb(MMHandleType hplayer,mm_player_buffer_seek_data_callback callback, void *user_param); int _mmplayer_set_playspeed(MMHandleType hplayer, float rate); int _mmplayer_set_playspeed_ex(MMHandleType hplayer, gdouble rate); int _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, void *user_param); +int _mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param); +int _mmplayer_set_audiostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param); int _mmplayer_set_videostream_cb(MMHandleType hplayer,mm_player_video_stream_callback callback, void *user_param); int _mmplayer_set_audiostream_cb(MMHandleType hplayer,mm_player_audio_stream_callback callback, void *user_param); int _mmplayer_set_videoframe_render_error_cb(MMHandleType hplayer, mm_player_video_frame_render_error_callback callback, void *user_param); @@ -828,6 +808,7 @@ int _mmplayer_set_audiobuffer_cb(MMHandleType hplayer, mm_player_audio_stream_ca int _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay); int _mmplayer_audio_effect_custom_apply(mm_player_t *player); +int _mmplayer_set_audiostream_cb_ex(MMHandleType hplayer, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param); gboolean __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param); gboolean __mmplayer_is_streaming(mm_player_t* player); @@ -850,6 +831,9 @@ int _mmplayer_set_next_uri(MMHandleType hplayer, const char* uri, bool is_first_ int _mmplayer_get_next_uri(MMHandleType hplayer, char** uri); int _mmplayer_has_closed_caption(MMHandleType hplayer, bool* exist); int _mmplayer_enable_media_packet_video_stream(MMHandleType hplayer, bool enable); +void * _mm_player_media_packet_video_stream_internal_buffer_ref(void *buffer); +void _mm_player_media_packet_video_stream_internal_buffer_unref(void *buffer); + #ifdef __cplusplus } #endif diff --git a/src/include/mm_player_utils.h b/src/include/mm_player_utils.h index 662e7d9..51d00f3 100755 --- a/src/include/mm_player_utils.h +++ b/src/include/mm_player_utils.h @@ -233,7 +233,10 @@ debug_log("-- prev %s, current %s, pending %s, target %s --\n", \ #define MMPLAYER_IS_HTTP_LIVE_STREAMING(x_player) __is_http_live_streaming(x_player) #define MMPLAYER_IS_LIVE_STREAMING(x_player) __is_live_streaming(x_player) #define MMPLAYER_IS_DASH_STREAMING(x_player) __is_dash_streaming(x_player) -#define MMPLAYER_IS_SMOOTH_STREAMING(x_player) __is_smooth_streaming(x_player) +#define MMPLAYER_IS_SMOOTH_STREAMING(x_player) __is_smooth_streaming(x_player) +#ifdef TEST_ES +#define MMPLAYER_IS_ES_BUFF_SRC(x_player) __is_es_buff_src(x_player) +#endif #define MMPLAYER_URL_HAS_DASH_SUFFIX(x_player) __has_suffix(x_player, "mpd") #define MMPLAYER_URL_HAS_HLS_SUFFIX(x_player) __has_suffix(x_player, "m3u8") @@ -261,7 +264,6 @@ enum }; bool util_is_sdp_file ( const char *path ); -int64_t uti_get_time ( void ); int util_get_rank_increase ( const char *factory_class ); int util_factory_rank_compare(GstPluginFeature *f1, GstPluginFeature *f2); // @ int util_exist_file_path(const char *file_path); @@ -274,7 +276,6 @@ bool util_check_valid_url ( const char *proxy ); const char* util_get_charset(const char *file_path); int util_get_is_connected_external_display(void); -gboolean util_is_miracast_connected(void); int util_get_pixtype(unsigned int fourcc); #ifdef __cplusplus diff --git a/src/mm_player.c b/src/mm_player.c index d801a98..277096c 100755 --- a/src/mm_player.c +++ b/src/mm_player.c @@ -34,6 +34,7 @@ #include "mm_debug.h" #include "mm_player_capture.h" #include "mm_player_tracks.h" +#include "mm_player_es.h" int mm_player_create(MMHandleType *player) { @@ -42,8 +43,6 @@ int mm_player_create(MMHandleType *player) return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); -// if (!g_thread_supported ()) -// g_thread_init (NULL); g_thread_init has been deprecated since version 2.32 and should not be used in newly-written code. This function is no longer necessary. The GLib threading system is automatically initialized at the start of your program. /* alloc player structure */ new_player = g_malloc(sizeof(mm_player_t)); @@ -97,11 +96,10 @@ ERROR: if ( new_player ) { + _mmplayer_destroy( (MMHandleType)new_player ); g_mutex_clear(&new_player->cmd_lock); g_mutex_clear(&new_player->playback_lock); - _mmplayer_destroy( (MMHandleType)new_player ); - MMPLAYER_FREEIF( new_player ); } @@ -203,7 +201,7 @@ int mm_player_set_audio_stream_callback(MMHandleType player, mm_player_audio_str return result; } -int mm_player_set_video_stream_callback(MMHandleType player, mm_player_video_stream_callback callback, void *user_param) +int mm_player_set_audio_stream_callback_ex(MMHandleType player, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param) { int result = MM_ERROR_NONE; @@ -211,44 +209,14 @@ int mm_player_set_video_stream_callback(MMHandleType player, mm_player_video_str MMPLAYER_CMD_LOCK( player ); - result = _mmplayer_set_videostream_cb(player, callback, user_param); + result = _mmplayer_set_audiostream_cb_ex(player, sync, callback, user_param); MMPLAYER_CMD_UNLOCK( player ); return result; } -int mm_player_set_video_frame_render_error_callback(MMHandleType player, mm_player_video_frame_render_error_callback callback, void *user_param) -{ - int result = MM_ERROR_NONE; - - return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); - - MMPLAYER_CMD_LOCK( player ); - - result = _mmplayer_set_videoframe_render_error_cb(player, callback, user_param); - - MMPLAYER_CMD_UNLOCK( player ); - - return result; -} - -int mm_player_do_video_capture(MMHandleType player) -{ - int result = MM_ERROR_NONE; - - return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); - - MMPLAYER_CMD_LOCK( player ); - - result = _mmplayer_do_video_capture(player); - - MMPLAYER_CMD_UNLOCK( player ); - - return result; -} - -int mm_player_set_prepare_buffering_time(MMHandleType player, int second) +int mm_player_set_video_stream_callback(MMHandleType player, mm_player_video_stream_callback callback, void *user_param) { int result = MM_ERROR_NONE; @@ -256,14 +224,14 @@ int mm_player_set_prepare_buffering_time(MMHandleType player, int second) MMPLAYER_CMD_LOCK( player ); - result = _mmplayer_set_prepare_buffering_time(player, second); + result = _mmplayer_set_videostream_cb(player, callback, user_param); MMPLAYER_CMD_UNLOCK( player ); return result; } -int mm_player_set_runtime_buffering_mode(MMHandleType player, MMPlayerBufferingMode mode, int second) +int mm_player_set_video_frame_render_error_callback(MMHandleType player, mm_player_video_frame_render_error_callback callback, void *user_param) { int result = MM_ERROR_NONE; @@ -271,14 +239,14 @@ int mm_player_set_runtime_buffering_mode(MMHandleType player, MMPlayerBufferingM MMPLAYER_CMD_LOCK( player ); - result = _mmplayer_set_runtime_buffering_mode(player, mode, second); + result = _mmplayer_set_videoframe_render_error_cb(player, callback, user_param); MMPLAYER_CMD_UNLOCK( player ); return result; } -int mm_player_set_buffer_need_data_callback(MMHandleType player, mm_player_buffer_need_data_callback callback, void * user_param) +int mm_player_do_video_capture(MMHandleType player) { int result = MM_ERROR_NONE; @@ -286,14 +254,14 @@ int mm_player_set_buffer_need_data_callback(MMHandleType player, mm_player_buffe MMPLAYER_CMD_LOCK( player ); - result = _mmplayer_set_buffer_need_data_cb(player, callback, user_param); + result = _mmplayer_do_video_capture(player); MMPLAYER_CMD_UNLOCK( player ); return result; } -int mm_player_set_buffer_enough_data_callback(MMHandleType player, mm_player_buffer_enough_data_callback callback, void * user_param) +int mm_player_set_prepare_buffering_time(MMHandleType player, int second) { int result = MM_ERROR_NONE; @@ -301,15 +269,14 @@ int mm_player_set_buffer_enough_data_callback(MMHandleType player, mm_player_buf MMPLAYER_CMD_LOCK( player ); - result = _mmplayer_set_buffer_enough_data_cb(player, callback, user_param); + result = _mmplayer_set_prepare_buffering_time(player, second); MMPLAYER_CMD_UNLOCK( player ); return result; } - -int mm_player_set_buffer_seek_data_callback(MMHandleType player, mm_player_buffer_seek_data_callback callback, void * user_param) +int mm_player_set_runtime_buffering_mode(MMHandleType player, MMPlayerBufferingMode mode, int second) { int result = MM_ERROR_NONE; @@ -317,7 +284,7 @@ int mm_player_set_buffer_seek_data_callback(MMHandleType player, mm_player_buffe MMPLAYER_CMD_LOCK( player ); - result = _mmplayer_set_buffer_seek_data_cb(player, callback, user_param); + result = _mmplayer_set_runtime_buffering_mode(player, mode, second); MMPLAYER_CMD_UNLOCK( player ); @@ -843,7 +810,7 @@ int mm_player_ignore_session(MMHandleType player) return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); -// result = _mmplayer_asm_ignore_session(player); + result = _mmplayer_asm_ignore_session(player); return result; } @@ -1077,3 +1044,222 @@ int mm_player_enable_media_packet_video_stream(MMHandleType player, bool enable) return result; } + +void * mm_player_media_packet_video_stream_internal_buffer_ref(void *buffer) +{ + void * result; + result = _mm_player_media_packet_video_stream_internal_buffer_ref(buffer); + + return result; +} + +void mm_player_media_packet_video_stream_internal_buffer_unref(void *buffer) +{ + _mm_player_media_packet_video_stream_internal_buffer_unref(buffer); +} + +#ifdef TEST_ES +int mm_player_submit_packet(MMHandleType player, media_packet_h packet) +{ + + int result = MM_ERROR_NONE; + + return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + /* no lock here, otherwise callback for the "need-data" signal of appsrc will be blocking */ + //MMPLAYER_CMD_LOCK( player ); + + result = _mmplayer_submit_packet(player, packet); + + //MMPLAYER_CMD_UNLOCK( player ); + + return result; +} + +int mm_player_set_video_info (MMHandleType player, media_format_h format) +{ + int result = MM_ERROR_NONE; + + debug_log("\n"); + + return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + MMPLAYER_CMD_LOCK( player ); + + result = _mmplayer_set_video_info(player, format); + + MMPLAYER_CMD_UNLOCK( player ); + + return result; + +} + +int mm_player_set_audio_info (MMHandleType player, media_format_h format) +{ + int result = MM_ERROR_NONE; + + debug_log("\n"); + + return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + MMPLAYER_CMD_LOCK( player ); + + result = _mmplayer_set_audio_info(player, format); + + MMPLAYER_CMD_UNLOCK( player ); + + return result; +} + +int mm_player_set_subtitle_info (MMHandleType player, MMPlayerSubtitleStreamInfo *subtitle_stream_info) +{ + int result = MM_ERROR_NONE; + + debug_log("\n"); + + return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + MMPLAYER_CMD_LOCK( player ); + + result = _mmplayer_set_subtitle_info(player, subtitle_stream_info); + + MMPLAYER_CMD_UNLOCK( player ); + + return result; +} + +int mm_player_set_media_stream_buffer_max_size(MMHandleType player, MMPlayerStreamType type, unsigned long long max_size) +{ + int result = MM_ERROR_NONE; + + debug_log("\n"); + + return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + MMPLAYER_CMD_LOCK( player ); + + result = _mmplayer_set_media_stream_max_size(player, type, max_size); + + MMPLAYER_CMD_UNLOCK( player ); + + return result; +} + +int mm_player_get_media_stream_buffer_max_size(MMHandleType player, MMPlayerStreamType type, unsigned long long *max_size) +{ + int result = MM_ERROR_NONE; + + debug_log("\n"); + + return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + return_val_if_fail(max_size, MM_ERROR_INVALID_ARGUMENT); + + MMPLAYER_CMD_LOCK( player ); + + result = _mmplayer_get_media_stream_max_size(player, type, max_size); + + MMPLAYER_CMD_UNLOCK( player ); + + return result; +} + +int mm_player_set_media_stream_buffer_min_percent(MMHandleType player, MMPlayerStreamType type, unsigned min_percent) +{ + int result = MM_ERROR_NONE; + + debug_log("\n"); + + return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + MMPLAYER_CMD_LOCK( player ); + + result = _mmplayer_set_media_stream_min_percent(player, type, min_percent); + + MMPLAYER_CMD_UNLOCK( player ); + + return result; +} + +int mm_player_get_media_stream_buffer_min_percent(MMHandleType player, MMPlayerStreamType type, unsigned int *min_percent) +{ + int result = MM_ERROR_NONE; + + debug_log("\n"); + + return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + return_val_if_fail(min_percent, MM_ERROR_INVALID_ARGUMENT); + + MMPLAYER_CMD_LOCK( player ); + + result = _mmplayer_get_media_stream_min_percent(player, type, min_percent); + + MMPLAYER_CMD_UNLOCK( player ); + + return result; +} + +int mm_player_set_media_stream_buffer_status_callback(MMHandleType player, MMPlayerStreamType type, mm_player_media_stream_buffer_status_callback callback, void * user_param) +{ + int result = MM_ERROR_NONE; + + debug_log("\n"); + + return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + MMPLAYER_CMD_LOCK( player ); + + result = _mmplayer_set_media_stream_buffer_status_cb(player, type, callback, user_param); + + MMPLAYER_CMD_UNLOCK( player ); + + return result; +} + +int mm_player_set_media_stream_seek_data_callback(MMHandleType player, MMPlayerStreamType type, mm_player_media_stream_seek_data_callback callback, void * user_param) +{ + int result = MM_ERROR_NONE; + + debug_log("\n"); + + return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + MMPLAYER_CMD_LOCK( player ); + + result = _mmplayer_set_media_stream_seek_data_cb(player, type, callback, user_param); + + MMPLAYER_CMD_UNLOCK( player ); + + return result; +} + +int mm_player_set_audio_stream_changed_callback(MMHandleType player, mm_player_stream_changed_callback callback, void *user_param) +{ + int result = MM_ERROR_NONE; + + return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + MMPLAYER_CMD_LOCK( player ); + + result = _mmplayer_set_audiostream_changed_cb(player, callback, user_param); + + MMPLAYER_CMD_UNLOCK( player ); + + return result; +} + +int mm_player_set_video_stream_changed_callback(MMHandleType player, mm_player_stream_changed_callback callback, void *user_param) +{ + int result = MM_ERROR_NONE; + + return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + MMPLAYER_CMD_LOCK( player ); + + result = _mmplayer_set_videostream_changed_cb(player, callback, user_param); + + MMPLAYER_CMD_UNLOCK( player ); + + return result; +} + +#endif diff --git a/src/mm_player_asm.c b/src/mm_player_asm.c new file mode 100755 index 0000000..6638363 --- /dev/null +++ b/src/mm_player_asm.c @@ -0,0 +1,390 @@ +/* + * libmm-player + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>, + * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <mm_debug.h> +#include <mm_error.h> +#include "mm_player_utils.h" +#include "mm_player_priv.h" +#include "mm_player_asm.h" +#include <vconf.h> +#include <vconf-internal-sound-keys.h> + +#define MMPLAYER_CHECK_SESSION_SKIP(x_player_asm) \ +do \ +{ \ + if (x_player_asm->skip_session == TRUE) \ + { \ + debug_log("skip session"); \ + return MM_ERROR_NONE; \ + } \ +}while(0); + +#define MMPLAYER_CHECK_SESSION_INSTANCE(x_player_asm) \ +do \ +{ \ + if (!x_player_asm) \ + { \ + debug_log("no session instance");\ + return MM_ERROR_SOUND_NOT_INITIALIZED; \ + } \ +}while(0); + +static ASM_sound_events_t __mmplayer_asm_get_event_type(gint type); + +const gchar * +__mmplayer_asm_get_state_name ( int state ) +{ + switch ( state ) + { + case ASM_STATE_NONE: + return "NONE"; + case ASM_STATE_PLAYING: + return "PLAYING"; + case ASM_STATE_PAUSE: + return "PAUSED"; + case ASM_STATE_STOP: + return "STOP"; + case ASM_STATE_WAITING: + return "BUFFERING"; + default: + return "INVAID"; + } +} + +#define MMPLAYER_ASM_STATE_GET_NAME(state) __mmplayer_asm_get_state_name(state) + +gint +_mmplayer_asm_register(MMPlayerASM* sm, ASM_sound_cb_t callback, void* param) +{ + return MM_ERROR_NONE; + + gint session_type = MM_SESSION_TYPE_MEDIA; + gint session_options = 0; + gint errorcode = MM_ERROR_NONE; + gint asm_handle = -1; + gint event_type = ASM_EVENT_NONE; + gint pid = -1; + + MMPLAYER_FENTER(); + + MMPLAYER_CHECK_SESSION_INSTANCE(sm); + MMPLAYER_CHECK_SESSION_SKIP(sm); + + /* check if it's running on the media_server */ + if ( sm->pid > 0 ) + { + pid = sm->pid; + debug_log("mm-player is running on different process. Just faking pid to [%d]. :-p\n", pid); + } + + /* read session information */ + errorcode = _mm_session_util_read_information(pid, &session_type, &session_options); + if ( errorcode ) + { + debug_warning("Read Session Type failed. use default \"media\" type\n"); + session_type = MM_SESSION_TYPE_MEDIA; + } + + /* interpret session information */ + event_type = __mmplayer_asm_get_event_type(session_type); + + /* check if it's one of CALL series */ + if ( event_type == ASM_EVENT_CALL || + event_type == ASM_EVENT_VIDEOCALL || + event_type == ASM_EVENT_VOIP) + { + debug_warning("session type is one of CALL series(%d), skip registering ASM\n", session_type); + sm->event = event_type; + sm->skip_session = TRUE; + return MM_ERROR_NONE; + } + + /* register audio-session-manager handle and callback */ + if( ! ASM_register_sound(pid, &asm_handle, event_type, ASM_STATE_NONE, callback, (void*)param, ASM_RESOURCE_NONE, &errorcode)) + { + debug_error("ASM_register_sound() failed, error(%x)\n", errorcode); + return errorcode; + } + /* set session options */ + if (session_options) + { + if( ! ASM_set_session_option(asm_handle, session_options, &errorcode)) + { + debug_error("ASM_set_session_options() failed, error(%x)\n", errorcode); + return errorcode; + } + } + + /* now succeed to register our callback. take result */ + sm->handle = asm_handle; + sm->state = ASM_STATE_NONE; + sm->event = event_type; + + MMPLAYER_FLEAVE(); + + return MM_ERROR_NONE; +} + +gint +_mmplayer_asm_unregister(MMPlayerASM* sm) +{ + gint event_type = ASM_EVENT_NONE; + gint errorcode = 0; + gint pid = -1; + + MMPLAYER_FENTER(); + + MMPLAYER_CHECK_SESSION_INSTANCE(sm); + MMPLAYER_CHECK_SESSION_SKIP(sm); + + /* check if it's running on the media_server */ + if ( sm->pid > 0 ) + { + pid = sm->pid; + debug_log("mm-player is running on different process. Just faking pid to [%d]. :-p\n", pid); + } + + event_type = sm->event; + + if (sm->handle) + { + if( ! ASM_unregister_sound( sm->handle, event_type, &errorcode) ) + { + debug_error("Unregister sound failed 0x%X\n", errorcode); + return MM_ERROR_POLICY_INTERNAL; + } + } + debug_warning("asm unregistered"); + + MMPLAYER_FLEAVE(); + + return MM_ERROR_NONE; +} + +gint _mmplayer_asm_set_state(MMHandleType hplayer, ASM_sound_states_t state, gboolean enable_safety_vol) +{ + return MM_ERROR_NONE; + + gint event_type = ASM_EVENT_NONE; + gint pid = -1; +// int vconf_safety_vol_val = 0; + ASM_resource_t resource = ASM_RESOURCE_NONE; + mm_player_t *player = (mm_player_t *)hplayer; + MMPlayerASM* sm = &player->sm; + MMPLAYER_FENTER(); + +#if 0 + if (player->set_mode.safety_volume) + { + /* get safety volume */ + if (vconf_get_int(VCONFKEY_SOUND_ENABLE_SAFETY_VOL, &vconf_safety_vol_val)) + { + debug_error ("failed to get safety volume"); + } + + if (enable_safety_vol) + { + vconf_safety_vol_val = vconf_safety_vol_val | VCONFKEY_SOUND_SAFETY_VOL_FW_MMPLAYER; + } + else + { + vconf_safety_vol_val = vconf_safety_vol_val & ~VCONFKEY_SOUND_SAFETY_VOL_FW_MMPLAYER; + } + + /* set safety volume */ + if (vconf_set_int(VCONFKEY_SOUND_ENABLE_SAFETY_VOL, vconf_safety_vol_val)) + { + debug_error ("failed to set safety volume"); + } + debug_log("safety vol : %d(0:false, 1:true), current result of vconf val : 0x%x", enable_safety_vol, vconf_safety_vol_val); + } +#endif + MMPLAYER_CHECK_SESSION_INSTANCE(sm); + MMPLAYER_CHECK_SESSION_SKIP(sm); + + /* check if it's running on the media_server */ + if ( sm->pid > 0 ) + { + pid = sm->pid; + debug_log("mm-player is running on different process. Just faking pid to [%d]. :-p\n", pid); + } + + /* in case of stop, it should be stop first and post interrupt message to application */ + if ( !sm->by_asm_cb || state == ASM_STATE_STOP)//|| sm->state == ASM_STATE_PLAYING ) + { + int ret = 0; + event_type = sm->event; + resource = sm->resource; + + /* check if there is video */ + /* NOTE: resource can be set as NONE when it's not occupied or unknown resource is used. */ + if(ASM_STATE_PLAYING == state || ASM_STATE_PAUSE == state || ASM_STATE_WAITING == state) + { + int surface_type = 0; + mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type); + debug_log("surface type = %d", surface_type); + + if (player->pipeline && player->pipeline->videobin) + { + if(surface_type == MM_DISPLAY_SURFACE_X) + { + resource = ASM_RESOURCE_VIDEO_OVERLAY | ASM_RESOURCE_HW_DECODER; + } + else if (surface_type == MM_DISPLAY_SURFACE_EVAS) + { + resource = ASM_RESOURCE_HW_DECODER; + } + } + + if( __mmplayer_is_streaming (player)) + resource = resource | ASM_RESOURCE_STREAMING; + + /* reset */ + sm->keep_last_pos = FALSE; + } + + if( ((sm->state != state) || (sm->resource != resource)) && ! ASM_set_sound_state( sm->handle, event_type, state, resource, &ret) ) + { + gint retval = MM_ERROR_POLICY_INTERNAL; + + debug_error("Set state to [%d] failed 0x%X\n", state, ret); + switch(ret) + { + case ERR_ASM_POLICY_CANNOT_PLAY: + case ERR_ASM_POLICY_CANNOT_PLAY_BY_CALL: + case ERR_ASM_POLICY_CANNOT_PLAY_BY_ALARM: + retval = MM_ERROR_POLICY_BLOCKED; + break; + default: + retval = MM_ERROR_POLICY_INTERNAL; + break; + } + + return retval; + } + } + else + { + sm->by_asm_cb = FALSE; + } + + sm->state = state; + + /* waiting to be changed because callback can be called */ + if (ASM_STATE_STOP == state) + { + ASM_sound_states_t session_state; + ASM_get_sound_state(sm->handle, event_type, &session_state, NULL); + } + + debug_error("ASM state changed to [%s]", MMPLAYER_ASM_STATE_GET_NAME(state)); + MMPLAYER_FLEAVE(); + return MM_ERROR_NONE; +} + +static ASM_sound_events_t +__mmplayer_asm_get_event_type(gint type) +{ + gint event_type = ASM_EVENT_NONE; + + /* interpret session type */ + switch(type) + { + case MM_SESSION_TYPE_CALL: + event_type = ASM_EVENT_CALL; + break; + + case MM_SESSION_TYPE_VIDEOCALL: + event_type = ASM_EVENT_VIDEOCALL; + break; + + case MM_SESSION_TYPE_VOIP: + event_type = ASM_EVENT_VOIP; + break; + + case MM_SESSION_TYPE_MEDIA: +// case MM_SESSION_TYPE_MEDIA_RECORD: + event_type = ASM_EVENT_MEDIA_MMPLAYER; + break; + + case MM_SESSION_TYPE_NOTIFY: + event_type = ASM_EVENT_NOTIFY; + break; + + case MM_SESSION_TYPE_ALARM: + event_type = ASM_EVENT_ALARM; + break; + + case MM_SESSION_TYPE_EMERGENCY: + event_type = ASM_EVENT_EMERGENCY; + break; +#if 0 + case MM_SESSION_TYPE_RECORD_VIDEO: + case MM_SESSION_TYPE_RECORD_AUDIO: + event_type = ASM_EVENT_MEDIA_MMPLAYER; + break; +#endif + + default: + debug_msg("unexpected case!\n"); + event_type = ASM_EVENT_MEDIA_MMPLAYER; + break; + } + + return event_type; +} + +gint +_mmplayer_asm_ignore_session(MMHandleType hplayer) +{ + mm_player_t *player = (mm_player_t *)hplayer; + + MMPLAYER_FENTER(); + + return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + /* check state */ + if (player->state != MM_PLAYER_STATE_NULL) + { + debug_log("invalid state to make session mix"); + return MM_ERROR_PLAYER_INVALID_STATE; + } + + if (player->sm.skip_session == FALSE && player->sm.handle) + { + int error_code = 0; + + if (!ASM_unregister_sound(player->sm.handle, player->sm.event, &error_code)) + { + debug_error("Unregister sound failed 0x%X", error_code); + return MM_ERROR_POLICY_INTERNAL; + } + player->sm.skip_session = TRUE; + player->sm.handle = 0; + + debug_log("session skip enabled"); + } + + MMPLAYER_FLEAVE(); + + return MM_ERROR_NONE; +} diff --git a/src/mm_player_attrs.c b/src/mm_player_attrs.c index 7cd8867..aa1ecfd 100755 --- a/src/mm_player_attrs.c +++ b/src/mm_player_attrs.c @@ -865,6 +865,24 @@ _mmplayer_construct_attribute(MMHandleType handle) MMPLAYER_MAX_INT }, { + "sound_stream_type", + MM_ATTRS_TYPE_STRING, + MM_ATTRS_FLAG_RW, + (void *) NULL, + MM_ATTRS_VALID_TYPE_NONE, + 0, + 0 + }, + { + "sound_stream_index", + MM_ATTRS_TYPE_INT, + MM_ATTRS_FLAG_RW, + 0, + MM_ATTRS_VALID_TYPE_INT_RANGE, + 0, + MMPLAYER_MAX_INT + }, + { "sound_route", MM_ATTRS_TYPE_INT, MM_ATTRS_FLAG_RW, diff --git a/src/mm_player_audioeffect.c b/src/mm_player_audioeffect.c index 62d7e00..ab90b2d 100755 --- a/src/mm_player_audioeffect.c +++ b/src/mm_player_audioeffect.c @@ -32,8 +32,10 @@ mm_player_get_foreach_present_supported_effect_type(MMHandleType hplayer, MMAudi { mm_player_t *player = NULL; int result = MM_ERROR_NONE; - mm_sound_device_in device_in = MM_SOUND_DEVICE_IN_NONE; - mm_sound_device_out device_out = MM_SOUND_DEVICE_OUT_NONE; + mm_sound_device_flags_e flags = MM_SOUND_DEVICE_IO_DIRECTION_OUT_FLAG | MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG; + MMSoundDeviceList_t device_list; + MMSoundDevice_t device_h = NULL; + mm_sound_device_type_e device_type; int i = 0; MMPLAYER_FENTER(); @@ -43,10 +45,30 @@ mm_player_get_foreach_present_supported_effect_type(MMHandleType hplayer, MMAudi player = MM_PLAYER_CAST(hplayer); /* get status if speaker is activated */ - result = mm_sound_get_active_device(&device_in, &device_out); + /* (1) get current device list */ + result = mm_sound_get_current_device_list(flags, &device_list); + + if ( result ) { + debug_error("mm_sound_get_current_device_list() failed [%x]!!", result); + MMPLAYER_FLEAVE(); + return result; + } + + /* (2) get device handle of device list */ + result = mm_sound_get_next_device (device_list, &device_h); + + if ( result ) { + debug_error("mm_sound_get_next_device() failed [%x]!!", result); + MMPLAYER_FLEAVE(); + return result; + } + + /* (3) get device type */ + result = mm_sound_get_device_type(device_h, &device_type); + if ( result ) { + debug_error("mm_sound_get_device_type() failed [%x]!!", result); MMPLAYER_FLEAVE(); - debug_error("mm_sound_get_active_device() failed [%x]!!", result); return result; } @@ -57,7 +79,7 @@ mm_player_get_foreach_present_supported_effect_type(MMHandleType hplayer, MMAudi { if (player->ini.audio_effect_preset_list[i] ) { - if (device_out == MM_SOUND_DEVICE_OUT_SPEAKER && + if (device_type == MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER && player->ini.audio_effect_preset_earphone_only_list[i]) { continue; @@ -76,7 +98,7 @@ mm_player_get_foreach_present_supported_effect_type(MMHandleType hplayer, MMAudi { if (player->ini.audio_effect_custom_list[i] ) { - if (device_out == MM_SOUND_DEVICE_OUT_SPEAKER && + if (device_type == MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER && player->ini.audio_effect_custom_earphone_only_list[i]) { continue; @@ -232,8 +254,10 @@ int __mmplayer_audio_set_output_type (mm_player_t *player, MMAudioEffectType effect_type, int effect) { GstElement *audio_effect_element = NULL; - mm_sound_device_in device_in = MM_SOUND_DEVICE_IN_NONE; - mm_sound_device_out device_out = MM_SOUND_DEVICE_OUT_NONE; + mm_sound_device_flags_e flags = MM_SOUND_DEVICE_ALL_FLAG; + MMSoundDeviceList_t device_list; + MMSoundDevice_t device_h = NULL; + mm_sound_device_type_e device_type; int output_type = 0; int result = MM_ERROR_NONE; @@ -243,16 +267,35 @@ __mmplayer_audio_set_output_type (mm_player_t *player, MMAudioEffectType effect_ audio_effect_element = player->pipeline->audiobin[MMPLAYER_A_FILTER].gst; - result = mm_sound_get_active_device(&device_in, &device_out); + /* (1) get current device list */ + result = mm_sound_get_current_device_list(flags, &device_list); if ( result ) { - debug_error("mm_sound_get_active_device() failed [%x]!!", result); + debug_error("mm_sound_get_current_device_list() failed [%x]!!", result); + MMPLAYER_FLEAVE(); + return result; + } + + /* (2) get device handle of device list */ + result = mm_sound_get_next_device (device_list, &device_h); + + if ( result ) { + debug_error("mm_sound_get_next_device() failed [%x]!!", result); + MMPLAYER_FLEAVE(); + return result; + } + + /* (3) get device type */ + result = mm_sound_get_device_type(device_h, &device_type); + + if ( result ) { + debug_error("mm_sound_get_device_type() failed [%x]!!", result); MMPLAYER_FLEAVE(); return result; } /* SPEAKER case */ - if (device_out == MM_SOUND_DEVICE_OUT_SPEAKER) + if (device_type == MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER) { if ( MM_AUDIO_EFFECT_TYPE_SQUARE != effect_type ) { if (__mmplayer_is_earphone_only_effect_type(player, effect_type, effect)) @@ -265,27 +308,19 @@ __mmplayer_audio_set_output_type (mm_player_t *player, MMAudioEffectType effect_ output_type = MM_AUDIO_EFFECT_OUTPUT_SPK; } -// else if (device_out == MM_SOUND_DEVICE_OUT_MIRRORING) -// { -// output_type = MM_AUDIO_EFFECT_OUTPUT_OTHERS; -// } - else if (device_out == MM_SOUND_DEVICE_OUT_HDMI) + else if (device_type == MM_SOUND_DEVICE_TYPE_MIRRORING) + { + output_type = MM_AUDIO_EFFECT_OUTPUT_OTHERS; + } + else if (device_type == MM_SOUND_DEVICE_TYPE_HDMI) { output_type = MM_AUDIO_EFFECT_OUTPUT_HDMI; } - else if(device_out == MM_SOUND_DEVICE_OUT_BT_A2DP) + else if (device_type == MM_SOUND_DEVICE_TYPE_BLUETOOTH) { output_type = MM_AUDIO_EFFECT_OUTPUT_BT; } -// else if(device_out == MM_SOUND_DEVICE_OUT_DOCK) -// { -// output_type = MM_AUDIO_EFFECT_OUTPUT_DOCK; -// } -// else if(device_out == MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK) -// { -// output_type = MM_AUDIO_EFFECT_OUTPUT_MULTIMEDIA_DOCK; -// } - else if(device_out == MM_SOUND_DEVICE_OUT_USB_AUDIO) + else if (device_type == MM_SOUND_DEVICE_TYPE_USB_AUDIO) { output_type = MM_AUDIO_EFFECT_OUTPUT_USB_AUDIO; } @@ -306,85 +341,105 @@ gboolean _mmplayer_is_supported_effect_type(mm_player_t* player, MMAudioEffectType effect_type, int effect) { gboolean result = TRUE; - mm_sound_device_in device_in = MM_SOUND_DEVICE_IN_NONE; - mm_sound_device_out device_out = MM_SOUND_DEVICE_OUT_NONE; + mm_sound_device_flags_e flags = MM_SOUND_DEVICE_ALL_FLAG; + MMSoundDeviceList_t device_list; + MMSoundDevice_t device_h = NULL; + mm_sound_device_type_e device_type; int ret = MM_ERROR_NONE; MMPLAYER_FENTER(); /* get status if speaker is activated */ - ret = mm_sound_get_active_device(&device_in, &device_out); - if ( ret ) { + /* (1) get current device list */ + ret = mm_sound_get_current_device_list(flags, &device_list); + if (ret) { MMPLAYER_FLEAVE(); - debug_error("mm_sound_get_active_device() failed [%x]!!", ret); - result = FALSE; + debug_error("mm_sound_get_current_device_list() failed [%x]!!", ret); + return FALSE; } - else + + /* (2) get device handle of device list */ + ret = mm_sound_get_next_device (device_list, &device_h); + + if (ret) { + debug_error("mm_sound_get_next_device() failed [%x]!!", ret); + MMPLAYER_FLEAVE(); + return FALSE; + } + + /* (3) get device type */ + ret = mm_sound_get_device_type(device_h, &device_type); + + if (ret) { + debug_error("mm_sound_get_device_type() failed [%x]!!", ret); + MMPLAYER_FLEAVE(); + return FALSE; + } + + /* preset */ + if (effect_type == MM_AUDIO_EFFECT_TYPE_PRESET) { - /* preset */ - if (effect_type == MM_AUDIO_EFFECT_TYPE_PRESET) + if ( effect < MM_AUDIO_EFFECT_PRESET_AUTO || effect >= MM_AUDIO_EFFECT_PRESET_NUM ) + { + debug_error("out of range, preset effect(%d)", effect); + result = FALSE; + } + else { - if ( effect < MM_AUDIO_EFFECT_PRESET_AUTO || effect >= MM_AUDIO_EFFECT_PRESET_NUM ) + if (!player->ini.audio_effect_preset_list[effect]) { - debug_error("out of range, preset effect(%d)", effect); + debug_error("this effect(%d) is not supported", effect); result = FALSE; } else { - if (!player->ini.audio_effect_preset_list[effect]) + if (device_type == MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER && + player->ini.audio_effect_preset_earphone_only_list[effect]) { - debug_error("this effect(%d) is not supported", effect); result = FALSE; } - else - { - if (device_out == MM_SOUND_DEVICE_OUT_SPEAKER && - player->ini.audio_effect_preset_earphone_only_list[effect]) - { - result = FALSE; - } - } } } - /* custom */ - else if (effect_type == MM_AUDIO_EFFECT_TYPE_CUSTOM) + } + /* custom */ + else if (effect_type == MM_AUDIO_EFFECT_TYPE_CUSTOM) + { + if ( effect < MM_AUDIO_EFFECT_CUSTOM_EQ || effect >= MM_AUDIO_EFFECT_CUSTOM_NUM ) { - if ( effect < MM_AUDIO_EFFECT_CUSTOM_EQ || effect >= MM_AUDIO_EFFECT_CUSTOM_NUM ) + debug_error("out of range, custom effect(%d)", effect); + result = FALSE; + } + else + { + if (!player->ini.audio_effect_custom_list[effect]) { - debug_error("out of range, custom effect(%d)", effect); + debug_error("this custom effect(%d) is not supported", effect); result = FALSE; } else { - if (!player->ini.audio_effect_custom_list[effect]) + if (device_type == MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER && + player->ini.audio_effect_custom_earphone_only_list[effect]) { - debug_error("this custom effect(%d) is not supported", effect); result = FALSE; } - else - { - if (device_out == MM_SOUND_DEVICE_OUT_SPEAKER && - player->ini.audio_effect_custom_earphone_only_list[effect]) - { - result = FALSE; - } - } } } - else if (effect_type == MM_AUDIO_EFFECT_TYPE_SQUARE) - { - if (!player->ini.use_audio_effect_custom) - { - debug_error("Square effect is not supported"); - result = FALSE; - } - } - else + } + else if (effect_type == MM_AUDIO_EFFECT_TYPE_SQUARE) + { + if (!player->ini.use_audio_effect_custom) { - debug_error("invalid effect type(%d)", effect_type); + debug_error("Square effect is not supported"); result = FALSE; } } + else + { + debug_error("invalid effect type(%d)", effect_type); + result = FALSE; + } + MMPLAYER_FLEAVE(); diff --git a/src/mm_player_capture.c b/src/mm_player_capture.c index e4b1083..d22cdeb 100755 --- a/src/mm_player_capture.c +++ b/src/mm_player_capture.c @@ -67,7 +67,7 @@ _mmplayer_initialize_video_capture(mm_player_t* player) /* create video capture thread */ player->capture_thread = - g_thread_try_new ("capture_thread",__mmplayer_capture_thread, (gpointer)player, NULL); + g_thread_try_new ("capture_thread",__mmplayer_capture_thread, (gpointer)player, NULL); if ( ! player->capture_thread ) { @@ -90,19 +90,16 @@ _mmplayer_release_video_capture(mm_player_t* player) { return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED ); /* release capture thread */ - if (player->capture_thread) - { - g_mutex_lock(&player->capture_thread_mutex); - player->capture_thread_exit = TRUE; - g_cond_signal( &player->capture_thread_cond ); - g_mutex_unlock(&player->capture_thread_mutex); + g_mutex_lock(&player->capture_thread_mutex); + player->capture_thread_exit = TRUE; + g_cond_signal( &player->capture_thread_cond ); + g_mutex_unlock(&player->capture_thread_mutex); - debug_log("waitting for capture thread exit"); - g_thread_join ( player->capture_thread ); - g_mutex_clear(&player->capture_thread_mutex ); - g_cond_clear(&player->capture_thread_cond ); - debug_log("capture thread released"); - } + debug_log("waitting for capture thread exit"); + g_thread_join ( player->capture_thread ); + g_mutex_clear(&player->capture_thread_mutex ); + g_cond_clear(&player->capture_thread_cond ); + debug_log("capture thread released"); return MM_ERROR_NONE; } @@ -119,7 +116,9 @@ _mmplayer_do_video_capture(MMHandleType hplayer) return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED); /* capturing or not */ - if (player->video_capture_cb_probe_id || player->capture.data || player->captured.a[0] || player->captured.a[1]) + if (player->video_capture_cb_probe_id || player->capture.data + || player->captured.data[0] || player->captured.data[1] + ) { debug_warning("capturing... we can't do any more"); return MM_ERROR_PLAYER_INVALID_STATE; @@ -202,20 +201,20 @@ __mmplayer_handle_orientation (mm_player_t* player, int orientation, int format) if (orientation == 90 || orientation == 270) { - dst_width = player->captured.h[0]; - dst_height = player->captured.w[0]; + dst_width = player->captured.height[0]; + dst_height = player->captured.width[0]; debug_log ("interchange width & height"); } else if (orientation == 180) { - dst_width = player->captured.w[0]; - dst_height = player->captured.h[0]; + dst_width = player->captured.width[0]; + dst_height = player->captured.height[0]; } else if (orientation == 0) { debug_error ("no need handle orientation : %d", orientation); - player->capture.width = player->captured.w[0]; - player->capture.height = player->captured.h[0]; + player->capture.width = player->captured.width[0]; + player->capture.height = player->captured.height[0]; return MM_ERROR_NONE; } else @@ -264,8 +263,9 @@ __mmplayer_handle_orientation (mm_player_t* player, int orientation, int format) debug_log ("source buffer for rotation = %p and rotation = %d", src_buffer, rot_enum); - ret = mm_util_rotate_image (src_buffer, player->captured.w[0], player->captured.h[0], format, - dst_frame, &dst_width, &dst_height, rot_enum); + ret = mm_util_rotate_image (src_buffer, + player->captured.width[0], player->captured.height[0], format, + dst_frame, &dst_width, &dst_height, rot_enum); if (ret != MM_ERROR_NONE) { debug_error("failed to do rotate image"); @@ -282,8 +282,8 @@ __mmplayer_handle_orientation (mm_player_t* player, int orientation, int format) player->capture.width = dst_width; player->capture.height= dst_height; - player->captured.w[0] = player->captured.s[0] = dst_width; - player->captured.h[0] = player->captured.e[0] = dst_height; + player->captured.width[0] = player->captured.stride_width[0] = dst_width; + player->captured.height[0] = player->captured.stride_height[0] = dst_height; return ret; } @@ -301,12 +301,11 @@ __mmplayer_capture_thread(gpointer data) return_val_if_fail(player, NULL); - g_mutex_lock(&player->capture_thread_mutex); - while (!player->capture_thread_exit) { debug_log("capture thread started. waiting for signal"); + g_mutex_lock(&player->capture_thread_mutex); g_cond_wait(&player->capture_thread_cond, &player->capture_thread_mutex ); if ( player->capture_thread_exit ) @@ -325,10 +324,12 @@ __mmplayer_capture_thread(gpointer data) int ret = 0; int linear_y_plane_size; int linear_uv_plane_size; + int width = player->captured.width[0]; + int height = player->captured.height[0]; unsigned char * src_buffer = NULL; - linear_y_plane_size = (player->captured.w[0] * player->captured.h[0]); - linear_uv_plane_size = (player->captured.w[0] * player->captured.h[0]/2); + linear_y_plane_size = (width * height); + linear_uv_plane_size = (width * height / 2); linear_y_plane = (unsigned char*) g_try_malloc(linear_y_plane_size); if (linear_y_plane == NULL) @@ -344,11 +345,13 @@ __mmplayer_capture_thread(gpointer data) goto ERROR; } /* NV12 tiled to linear */ - __csc_tiled_to_linear_crop(linear_y_plane, player->captured.a[0], player->captured.w[0], player->captured.h[0], 0,0,0,0); - __csc_tiled_to_linear_crop(linear_uv_plane, player->captured.a[1], player->captured.w[0], player->captured.h[0]/2, 0,0,0,0); + __csc_tiled_to_linear_crop(linear_y_plane, + player->captured.data[0], width, height, 0,0,0,0); + __csc_tiled_to_linear_crop(linear_uv_plane, + player->captured.data[1], width, height / 2, 0,0,0,0); - MMPLAYER_FREEIF(player->captured.a[0]); - MMPLAYER_FREEIF(player->captured.a[1]); + MMPLAYER_FREEIF(player->captured.data[0]); + MMPLAYER_FREEIF(player->captured.data[1]); src_buffer = (unsigned char*) g_try_malloc(linear_y_plane_size+linear_uv_plane_size); @@ -363,7 +366,7 @@ __mmplayer_capture_thread(gpointer data) /* NV12 linear to RGB888 */ ret = __mm_player_convert_colorspace(player, src_buffer, MM_UTIL_IMG_FMT_NV12, - player->captured.w[0], player->captured.h[0], MM_UTIL_IMG_FMT_RGB888); + width, height, MM_UTIL_IMG_FMT_RGB888); if (ret != MM_ERROR_NONE) { @@ -379,8 +382,8 @@ __mmplayer_capture_thread(gpointer data) int ret = 0; char *src_buffer = NULL; /* using original width otherwises, app can't know aligned to resize */ - int width_align = player->captured.w[0];//MM_ALIGN(player->captured.w[0], 8); - int src_buffer_size = width_align * player->captured.h[0] * 3/2; + int width_align = player->captured.width[0]; + int src_buffer_size = width_align * player->captured.height[0] * 3/2; int i, j; char*temp = NULL; char*dst_buf = NULL; @@ -399,32 +402,32 @@ __mmplayer_capture_thread(gpointer data) memset(src_buffer, 0x00, src_buffer_size); - temp = player->captured.a[0]; + temp = player->captured.data[0]; dst_buf = src_buffer; /* set Y plane */ - for (i = 0; i < player->captured.h[0]; i++) { + for (i = 0; i < player->captured.height[0]; i++) { memcpy(dst_buf, temp, width_align); dst_buf += width_align; - temp += player->captured.s[0]; + temp += player->captured.stride_width[0]; } - temp = player->captured.a[1]; + temp = player->captured.data[1]; /* set UV plane*/ - for (j = 0; j < player->captured.h[1]; j++) { + for (j = 0; j < player->captured.height[1]; j++) { memcpy(dst_buf, temp, width_align); dst_buf += width_align; - temp += player->captured.s[0]; + temp += player->captured.stride_width[0]; } /* free captured buf */ - MMPLAYER_FREEIF(player->captured.a[0]); - MMPLAYER_FREEIF(player->captured.a[1]); + MMPLAYER_FREEIF(player->captured.data[0]); + MMPLAYER_FREEIF(player->captured.data[1]); /* NV12 -> RGB888 */ ret = __mm_player_convert_colorspace(player, (unsigned char*)src_buffer, MM_UTIL_IMG_FMT_NV12, - width_align, player->captured.h[0], MM_UTIL_IMG_FMT_RGB888); + width_align, player->captured.height[0], MM_UTIL_IMG_FMT_RGB888); if (ret != MM_ERROR_NONE) { debug_error("failed to convert nv12 linear"); @@ -472,8 +475,8 @@ ERROR: /* clean */ MMPLAYER_FREEIF(linear_y_plane); MMPLAYER_FREEIF(linear_uv_plane); - MMPLAYER_FREEIF(player->captured.a[0]); - MMPLAYER_FREEIF(player->captured.a[1]); + MMPLAYER_FREEIF(player->captured.data[0]); + MMPLAYER_FREEIF(player->captured.data[1]); } msg.union_type = MM_MSG_UNION_CODE; @@ -533,39 +536,38 @@ __mmplayer_get_video_frame_from_buffer(mm_player_t* player, GstPad *pad, GstBuff { debug_msg ("captured format is ST12\n"); - MMPlayerMPlaneImage *proved = NULL; + MMVideoBuffer *proved = NULL; player->video_cs = MM_PLAYER_COLORSPACE_NV12_TILED; /* get video frame info from proved buffer */ -// memory = gst_buffer_get_memory(buffer, 1); memory = gst_buffer_get_all_memory(buffer); gst_memory_map(memory, &mapinfo, GST_MAP_READ); - proved = (MMPlayerMPlaneImage *)mapinfo.data; + proved = (MMVideoBuffer *)mapinfo.data; - if ( !proved || !proved->a[0] || !proved->a[1] ) + if ( !proved || !proved->data[0] || !proved->data[1] ) return MM_ERROR_PLAYER_INTERNAL; - yplane_size = proved->y_size; - uvplane_size = proved->uv_size; + yplane_size = proved->size[0]; + uvplane_size = proved->size[1]; debug_msg ("yplane_size=%d, uvplane_size=%d\n", yplane_size, uvplane_size); - memset(&player->captured, 0x00, sizeof(MMPlayerMPlaneImage)); - memcpy(&player->captured, proved, sizeof(MMPlayerMPlaneImage)); + memset(&player->captured, 0x00, sizeof(MMVideoBuffer)); + memcpy(&player->captured, proved, sizeof(MMVideoBuffer)); - player->captured.a[0] = g_try_malloc(yplane_size); - if ( !player->captured.a[0] ) { + player->captured.data[0] = g_try_malloc(yplane_size); + if ( !player->captured.data[0] ) { gst_memory_unmap(memory, &mapinfo); return MM_ERROR_SOUND_NO_FREE_SPACE; } - player->captured.a[1] = g_try_malloc(uvplane_size); - if ( !player->captured.a[1] ) { + player->captured.data[1] = g_try_malloc(uvplane_size); + if ( !player->captured.data[1] ) { gst_memory_unmap(memory, &mapinfo); return MM_ERROR_SOUND_NO_FREE_SPACE; } - memcpy(player->captured.a[0], proved->a[0], yplane_size); - memcpy(player->captured.a[1], proved->a[1], uvplane_size); + memcpy(player->captured.data[0], proved->data[0], yplane_size); + memcpy(player->captured.data[1], proved->data[1], uvplane_size); gst_memory_unmap(memory, &mapinfo); diff --git a/src/mm_player_es.c b/src/mm_player_es.c new file mode 100755 index 0000000..c8f9823 --- /dev/null +++ b/src/mm_player_es.c @@ -0,0 +1,708 @@ +/* + * libmm-player + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, heechul jeon <heechul.jeon@samsung.co>, + * YoungHwan An <younghwan_.an@samsung.com>, Eunhae Choi <eunhae1.choi@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/*=========================================================================================== +| | +| INCLUDE FILES | +| | +========================================================================================== */ +#include "mm_player_es.h" +#include "mm_player_utils.h" +#include "mm_player_internal.h" + +#include <gst/app/gstappsrc.h> + +/*--------------------------------------------------------------------------- +| LOCAL VARIABLE DEFINITIONS for internal | +---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- +| LOCAL FUNCTION PROTOTYPES: | +---------------------------------------------------------------------------*/ +static int _parse_media_format (MMPlayerVideoStreamInfo * video, MMPlayerAudioStreamInfo * audio, media_format_h format); +static int _convert_media_format_video_mime_to_str (MMPlayerVideoStreamInfo * video, media_format_mimetype_e mime); +static int _convert_media_format_audio_mime_to_str (MMPlayerAudioStreamInfo * audio, media_format_mimetype_e mime); + +/*=========================================================================================== +| | +| FUNCTION DEFINITIONS | +| | +========================================================================================== */ + +static int +_convert_media_format_video_mime_to_str (MMPlayerVideoStreamInfo * video, + media_format_mimetype_e mime) +{ + return_val_if_fail (video, MM_ERROR_INVALID_ARGUMENT); + + switch (mime) { + case MEDIA_FORMAT_MPEG4_SP: + video->mime = g_strdup ("video/mpeg"); + video->version = 4; + break; + case MEDIA_FORMAT_H264_SP: + case MEDIA_FORMAT_H264_MP: + case MEDIA_FORMAT_H264_HP: + video->mime = g_strdup ("video/x-h264"); + break; + default: + video->mime = g_strdup ("unknown"); + break; + } + + return MM_ERROR_NONE; +} + +static int +_convert_media_format_audio_mime_to_str (MMPlayerAudioStreamInfo * audio, + media_format_mimetype_e mime) +{ + return_val_if_fail (audio, MM_ERROR_INVALID_ARGUMENT); + + switch (mime) { + case MEDIA_FORMAT_AAC: + audio->mime = g_strdup ("audio/mpeg"); + audio->version = 2; + break; + default: + audio->mime = g_strdup ("unknown"); + break; + } + + return MM_ERROR_NONE; +} + +static int +_parse_media_format (MMPlayerVideoStreamInfo * video, + MMPlayerAudioStreamInfo * audio, media_format_h format) +{ + if (audio) { + media_format_mimetype_e mime; + int channel; + int samplerate; + int avg_bps; + + if (media_format_get_audio_info (format, &mime, &channel, &samplerate, NULL, + &avg_bps) != MEDIA_FORMAT_ERROR_NONE) { + debug_error ("media_format_get_audio_info failed"); + return MM_ERROR_PLAYER_INTERNAL; + } + + _convert_media_format_audio_mime_to_str (audio, mime); + audio->sample_rate = samplerate; + audio->channels = channel; +//video->user_info = ; + } + + if (video) { + media_format_mimetype_e mime; + int width; + int height; + int avg_bps; + + if (media_format_get_video_info (format, &mime, &width, &height, &avg_bps, + NULL) != MEDIA_FORMAT_ERROR_NONE) { + debug_error ("media_format_get_video_info failed"); + return MM_ERROR_PLAYER_INTERNAL; + } + + _convert_media_format_video_mime_to_str (video, mime); + video->width = width; + video->height = height; + } + + return MM_ERROR_NONE; +} + +static gboolean +_mmplayer_update_video_info(MMHandleType hplayer, media_format_h fmt) +{ + mm_player_t *player = (mm_player_t *) hplayer; + gboolean ret = FALSE; + GstStructure *str = NULL; + media_format_mimetype_e mimetype = 0; + gint cur_width = 0, width = 0; + gint cur_height = 0, height = 0; + + MMPLAYER_FENTER (); + + return_val_if_fail (player, FALSE); + return_val_if_fail (fmt, FALSE); + + if (player->v_stream_caps) + { + str = gst_caps_get_structure (player->v_stream_caps, 0); + if ( !gst_structure_get_int (str, "width", &cur_width)) + { + debug_log ("missing 'width' field in video caps"); + } + + if ( !gst_structure_get_int (str, "height", &cur_height)) + { + debug_log ("missing 'height' field in video caps"); + } + + media_format_get_video_info(fmt, &mimetype, &width, &height, NULL, NULL); + if ((cur_width != width) || (cur_height != height)) + { + debug_warning ("resolution is changed %dx%d -> %dx%d", + cur_width, cur_height, width, height); + _mmplayer_set_video_info(hplayer, fmt); + ret = TRUE; + } + } + + MMPLAYER_FLEAVE (); + return ret; +} + + +int +_mmplayer_set_media_stream_buffer_status_cb(MMHandleType hplayer, + MMPlayerStreamType type, + mm_player_media_stream_buffer_status_callback callback, + void *user_param) +{ + mm_player_t *player = (mm_player_t *) hplayer; + + MMPLAYER_FENTER (); + + return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + if ((type < MM_PLAYER_STREAM_TYPE_DEFAULT) || (type > MM_PLAYER_STREAM_TYPE_TEXT)) + return MM_ERROR_INVALID_ARGUMENT; + + if (player->media_stream_buffer_status_cb[type]) + { + if (!callback) + { + debug_log ("[type:%d] will be clear.\n", type); + } + else + { + debug_log ("[type:%d] will be overwritten.\n", type); + } + } + + player->media_stream_buffer_status_cb[type] = callback; + player->buffer_cb_user_param = user_param; + + debug_log ("player handle %p, type %d, callback %p\n", player, type, + player->media_stream_buffer_status_cb[type]); + + MMPLAYER_FLEAVE (); + + return MM_ERROR_NONE; +} + +int +_mmplayer_set_media_stream_seek_data_cb(MMHandleType hplayer, + MMPlayerStreamType type, + mm_player_media_stream_seek_data_callback callback, + void *user_param) +{ + mm_player_t *player = (mm_player_t *) hplayer; + + MMPLAYER_FENTER (); + + return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + if ((type < MM_PLAYER_STREAM_TYPE_DEFAULT) || (type > MM_PLAYER_STREAM_TYPE_TEXT)) + return MM_ERROR_INVALID_ARGUMENT; + + if (player->media_stream_seek_data_cb[type]) + { + if (!callback) + { + debug_log ("[type:%d] will be clear.\n", type); + } + else + { + debug_log ("[type:%d] will be overwritten.\n", type); + } + } + + player->media_stream_seek_data_cb[type] = callback; + player->buffer_cb_user_param = user_param; + + debug_log ("player handle %p, type %d, callback %p\n", player, type, + player->media_stream_seek_data_cb[type]); + + MMPLAYER_FLEAVE (); + + return MM_ERROR_NONE; +} + +int +_mmplayer_set_media_stream_max_size(MMHandleType hplayer, MMPlayerStreamType type, guint64 max_size) +{ + mm_player_t *player = (mm_player_t *) hplayer; + + MMPLAYER_FENTER (); + + return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + if ((type < MM_PLAYER_STREAM_TYPE_DEFAULT) || (type > MM_PLAYER_STREAM_TYPE_TEXT)) + return MM_ERROR_INVALID_ARGUMENT; + + player->media_stream_buffer_max_size[type] = max_size; + + debug_log ("type %d, max_size %llu\n", + type, player->media_stream_buffer_max_size[type]); + + MMPLAYER_FLEAVE (); + + return MM_ERROR_NONE; +} + +int +_mmplayer_get_media_stream_max_size(MMHandleType hplayer, MMPlayerStreamType type, guint64 *max_size) +{ + mm_player_t *player = (mm_player_t *) hplayer; + + MMPLAYER_FENTER (); + + return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED); + return_val_if_fail (max_size, MM_ERROR_INVALID_ARGUMENT); + + if ((type < MM_PLAYER_STREAM_TYPE_DEFAULT) || (type > MM_PLAYER_STREAM_TYPE_TEXT)) + return MM_ERROR_INVALID_ARGUMENT; + + *max_size = player->media_stream_buffer_max_size[type]; + + MMPLAYER_FLEAVE (); + + return MM_ERROR_NONE; +} + +int +_mmplayer_set_media_stream_min_percent(MMHandleType hplayer, MMPlayerStreamType type, guint min_percent) +{ + mm_player_t *player = (mm_player_t *) hplayer; + + MMPLAYER_FENTER (); + + return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + if ((type < MM_PLAYER_STREAM_TYPE_DEFAULT) || (type > MM_PLAYER_STREAM_TYPE_TEXT)) + return MM_ERROR_INVALID_ARGUMENT; + + player->media_stream_buffer_min_percent[type] = min_percent; + + debug_log ("type %d, min_per %u\n", + type, player->media_stream_buffer_min_percent[type]); + + MMPLAYER_FLEAVE (); + + return MM_ERROR_NONE; +} + +int +_mmplayer_get_media_stream_min_percent(MMHandleType hplayer, MMPlayerStreamType type, guint *min_percent) +{ + mm_player_t *player = (mm_player_t *) hplayer; + + MMPLAYER_FENTER (); + + return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED); + return_val_if_fail (min_percent, MM_ERROR_INVALID_ARGUMENT); + + if ((type < MM_PLAYER_STREAM_TYPE_DEFAULT) || (type > MM_PLAYER_STREAM_TYPE_TEXT)) + return MM_ERROR_INVALID_ARGUMENT; + + *min_percent = player->media_stream_buffer_min_percent[type]; + + MMPLAYER_FLEAVE (); + + return MM_ERROR_NONE; +} + +int +_mmplayer_submit_packet (MMHandleType hplayer, media_packet_h packet) +{ + int ret = MM_ERROR_NONE; + GstBuffer *_buffer; + mm_player_t *player = (mm_player_t *) hplayer; + guint8 *buf = NULL; + MMPlayerTrackType streamtype = MM_PLAYER_TRACK_TYPE_AUDIO; + media_format_h fmt = NULL; + + return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED); + return_val_if_fail (packet, MM_ERROR_INVALID_ARGUMENT); + + /* get data */ + media_packet_get_buffer_data_ptr (packet, (void **) &buf); + + if (buf != NULL) { + GstMapInfo buff_info = GST_MAP_INFO_INIT; + uint64_t size = 0; + uint64_t pts = 0; + bool flag = FALSE; + + /* get size */ + media_packet_get_buffer_size (packet, &size); + + _buffer = gst_buffer_new_and_alloc (size); + if (gst_buffer_map (_buffer, &buff_info, GST_MAP_READWRITE)) { + + memcpy (buff_info.data, buf, size); + buff_info.size = size; + + gst_buffer_unmap (_buffer, &buff_info); + } + + /* get pts */ + media_packet_get_pts (packet, &pts); + GST_BUFFER_PTS (_buffer) = (GstClockTime) (pts * 1000000); + + /* get stream type if audio or video */ + media_packet_is_audio (packet, &flag); + if (flag) { + streamtype = MM_PLAYER_TRACK_TYPE_AUDIO; + } else { + media_packet_is_video (packet, &flag); + + if (flag) + streamtype = MM_PLAYER_TRACK_TYPE_VIDEO; + else + streamtype = MM_PLAYER_TRACK_TYPE_TEXT; + } + + if (streamtype == MM_PLAYER_TRACK_TYPE_AUDIO) { +#if 0 // TO CHECK : has gone (set to pad) + if (GST_CAPS_IS_SIMPLE (player->a_stream_caps)) + GST_BUFFER_CAPS (_buffer) = gst_caps_copy (player->a_stream_caps); + else + debug_error ("External Demuxer case: Audio Buffer Caps not set."); +#endif + if (player->pipeline->mainbin[MMPLAYER_M_2ND_SRC].gst) + gst_app_src_push_buffer (GST_APP_SRC (player->pipeline->mainbin[MMPLAYER_M_2ND_SRC].gst), _buffer); + else if (g_strrstr (GST_ELEMENT_NAME (player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "audio_appsrc")) + gst_app_src_push_buffer (GST_APP_SRC (player->pipeline->mainbin[MMPLAYER_M_SRC].gst), _buffer); + } else if (streamtype == MM_PLAYER_TRACK_TYPE_VIDEO) { +#if 0 // TO CHECK : has gone (set to pad) + if (GST_CAPS_IS_SIMPLE (player->v_stream_caps)) + GST_BUFFER_CAPS (_buffer) = gst_caps_copy (player->v_stream_caps); + else + debug_error ("External Demuxer case: Video Buffer Caps not set."); +#endif + /* get format to check video format */ + media_packet_get_format (packet, &fmt); + if (fmt) + { + gboolean ret = FALSE; + ret = _mmplayer_update_video_info(hplayer, fmt); + if (ret) + { + g_object_set(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), + "caps", player->v_stream_caps, NULL); + } + } + + gst_app_src_push_buffer (GST_APP_SRC (player->pipeline->mainbin[MMPLAYER_M_SRC].gst), _buffer); + } else if (streamtype == MM_PLAYER_TRACK_TYPE_TEXT) { +#if 0 // TO CHECK : has gone (set to pad) + if (GST_CAPS_IS_SIMPLE (player->s_stream_caps)) + GST_BUFFER_CAPS (_buffer) = gst_caps_copy (player->s_stream_caps); + else + debug_error ("External Demuxer case: Subtitle Buffer Caps not set."); +#endif + gst_app_src_push_buffer (GST_APP_SRC (player->pipeline->mainbin[MMPLAYER_M_SUBSRC].gst), _buffer); + } else { + debug_error ("Not a valid packet from external demux"); + return FALSE; + } + } else { + debug_log ("Sending EOS on pipeline..."); + if (streamtype == MM_PLAYER_TRACK_TYPE_AUDIO) { + if (player->pipeline->mainbin[MMPLAYER_M_2ND_SRC].gst) + g_signal_emit_by_name (player->pipeline-> + mainbin[MMPLAYER_M_2ND_SRC].gst, "end-of-stream", &ret); + else + g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, + "end-of-stream", &ret); + } else if (streamtype == MM_PLAYER_TRACK_TYPE_VIDEO) { + g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, + "end-of-stream", &ret); + } else if (streamtype == MM_PLAYER_TRACK_TYPE_TEXT) { + g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SUBSRC].gst, + "end-of-stream", &ret); + } + } + + if (MMPLAYER_PENDING_STATE (player) == MM_PLAYER_STATE_PLAYING) { + //ret = __mmplayer_set_state(player, MM_PLAYER_STATE_PLAYING); + } + + return ret; +} + +int +_mmplayer_video_caps_new (MMHandleType hplayer, MMPlayerVideoStreamInfo * video, + const char *fieldname, ...) +{ + int cap_size; + GstCaps *caps = NULL; + GstStructure *structure = NULL; + va_list var_args; + mm_player_t *player = MM_PLAYER_CAST (hplayer); + + MMPLAYER_FENTER (); + return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED); + return_val_if_fail (video, MM_ERROR_PLAYER_NOT_INITIALIZED); + + debug_log ("width=%d height=%d framerate num=%d, den=%d", + video->width, video->height, video->framerate_num, video->framerate_den); + + caps = gst_caps_new_simple (video->mime, + "width", G_TYPE_INT, video->width, + "height", G_TYPE_INT, video->height, + "framerate", GST_TYPE_FRACTION, video->framerate_num, video->framerate_den, NULL); + + for (cap_size = 0; cap_size < gst_caps_get_size (caps); cap_size++) { + va_start (var_args, fieldname); + structure = gst_caps_get_structure (caps, cap_size); + gst_structure_set_valist (structure, fieldname, var_args); + va_end (var_args); + } + + if (video->extradata_size) { + GstBuffer *buf = NULL; + GstMapInfo buff_info = GST_MAP_INFO_INIT; + + buf = gst_buffer_new_and_alloc (video->extradata_size); + + if (gst_buffer_map (buf, &buff_info, GST_MAP_READ)) { + memcpy (buff_info.data, video->codec_extradata, video->extradata_size); + buff_info.size = video->extradata_size; + gst_buffer_unmap (buf, &buff_info); + } + + gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL); + gst_buffer_unref (buf); + } + + if (player->v_stream_caps) + { + debug_warning ("caps will be updated "); + + gst_caps_unref(player->v_stream_caps); + player->v_stream_caps = NULL; + } + + player->v_stream_caps = gst_caps_copy (caps); + MMPLAYER_LOG_GST_CAPS_TYPE (player->v_stream_caps); + gst_caps_unref (caps); + + MMPLAYER_FLEAVE (); + + return MM_ERROR_NONE; +} + +int +_mmplayer_set_video_info (MMHandleType hplayer, media_format_h format) +{ + mm_player_t *player = MM_PLAYER_CAST (hplayer); + MMPlayerVideoStreamInfo video = { 0, }; + int ret = MM_ERROR_NONE; + + MMPLAYER_FENTER (); + + return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + ret = _parse_media_format (&video, NULL, format); + if(ret != MM_ERROR_NONE) + return ret; + + if (strstr (video.mime, "video/mpeg")) { + _mmplayer_video_caps_new (hplayer, &video, + "mpegversion", G_TYPE_INT, video.version, + "systemstream", G_TYPE_BOOLEAN, FALSE, NULL); + } else if (strstr (video.mime, "video/x-h264")) { + //if (info.colordepth) + { + // _mmplayer_video_caps_new(hplayer, &info, + // "colordepth", G_TYPE_INT, info.colordepth, NULL); + } + //else + { + _mmplayer_video_caps_new (hplayer, &video, + "stream-format", G_TYPE_STRING, "byte-stream", + "alignment", G_TYPE_STRING, "au", NULL); + } + } +#if 0 + else if (strstr (info->mime, "video/x-wmv")) { + _mmplayer_video_caps_new (hplayer, &info, + "wmvversion", G_TYPE_INT, info.version, NULL); + } else if (strstr (info.mime, "video/x-pn-realvideo")) { + _mmplayer_video_caps_new (hplayer, &info, + "rmversion", G_TYPE_INT, info.version, NULL); + } else if (strstr (info.mime, "video/x-msmpeg")) { + _mmplayer_video_caps_new (hplayer, &info, + "msmpegversion", G_TYPE_INT, info.version, NULL); + } else if (strstr (info.mime, "video/x-h265")) { + if (info.colordepth) { + _mmplayer_video_caps_new (hplayer, &info, + "colordepth", G_TYPE_INT, info.colordepth, NULL); + } else { + _mmplayer_video_caps_new (hplayer, &info, NULL); + } + } else { + _mmplayer_video_caps_new (hplayer, &info, NULL); + } +#endif + g_free ((char *) video.mime); + + MMPLAYER_FLEAVE (); + + return MM_ERROR_NONE; +} + +int +_mmplayer_set_audio_info (MMHandleType hplayer, media_format_h format) +{ + mm_player_t *player = MM_PLAYER_CAST (hplayer); + GstCaps *caps = NULL; + MMPlayerAudioStreamInfo audio = { 0, }; + int ret = MM_ERROR_NONE; + + MMPLAYER_FENTER (); + + return_val_if_fail (hplayer, MM_ERROR_PLAYER_NOT_INITIALIZED); + + ret = _parse_media_format (NULL, &audio, format); + if(ret != MM_ERROR_NONE) + return ret; + + audio.user_info = 0; //test + + debug_log ("set audio player[%p] info [%p] version=%d rate=%d channel=%d", + player, audio, audio.version, audio.sample_rate, audio.channels); + + if (strstr (audio.mime, "audio/mpeg")) { + if (audio.version == 1) { // mp3 + caps = gst_caps_new_simple ("audio/mpeg", + "channels", G_TYPE_INT, audio.channels, + "rate", G_TYPE_INT, audio.sample_rate, + "mpegversion", G_TYPE_INT, audio.version, + "layer", G_TYPE_INT, audio.user_info, NULL); + } else { // aac + gchar *format = NULL; + + if (audio.user_info == 0) + format = g_strdup ("raw"); + else if (audio.user_info == 1) + format = g_strdup ("adts"); + else if (audio.user_info == 2) + format = g_strdup ("adif"); + + caps = gst_caps_new_simple ("audio/mpeg", + "channels", G_TYPE_INT, audio.channels, + "rate", G_TYPE_INT, audio.sample_rate, + "mpegversion", G_TYPE_INT, audio.version, + "stream-format", G_TYPE_STRING, format, NULL); + + g_free (format); + format = NULL; + } + } +#if 0 + else if (strstr (audio.mime, "audio/x-raw-int")) { + caps = gst_caps_new_simple ("audio/x-raw-int", + "width", G_TYPE_INT, audio.width, + "depth", G_TYPE_INT, audio.depth, + "endianness", G_TYPE_INT, audio.endianness, + "signed", G_TYPE_BOOLEAN, audio.signedness, + "channels", G_TYPE_INT, audio.channels, + "rate", G_TYPE_INT, audio.sample_rate, NULL); + } else { + caps = gst_caps_new_simple (audio.mime, + "channels", G_TYPE_INT, audio.channels, + "rate", G_TYPE_INT, audio.sample_rate, NULL); + } +#endif + + if (audio.extradata_size) { + GstBuffer *buf = NULL; + GstMapInfo buff_info = GST_MAP_INFO_INIT; + + buf = gst_buffer_new_and_alloc (audio.extradata_size); + + if (gst_buffer_map (buf, &buff_info, GST_MAP_READ)) { + memcpy (buff_info.data, audio.codec_extradata, audio.extradata_size); + gst_buffer_unmap (buf, &buff_info); + } + + gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL); + gst_buffer_unref (buf); + } + + g_free ((char *) audio.mime); + + player->a_stream_caps = gst_caps_copy (caps); + gst_caps_unref (caps); + + MMPLAYER_FLEAVE (); + + return MM_ERROR_NONE; +} + +int +_mmplayer_set_subtitle_info (MMHandleType hplayer, + MMPlayerSubtitleStreamInfo * subtitle) +{ +#if 0 //todo + + mm_player_t *player = MM_PLAYER_CAST (hplayer); + GstCaps *caps = NULL; + + MMPLAYER_FENTER (); + + return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED); + return_val_if_fail (info, MM_ERROR_PLAYER_NOT_INITIALIZED); + + debug_log ("set subtitle player[%p] info [%p]", player, info); + + + caps = gst_caps_new_simple (info->mime, NULL, NULL); // TO CHECK + if (NULL == caps) + return FALSE; + + if (strstr (info->mime, "application/x-xsub")) { + gst_caps_set_simple (caps, "codec_tag", G_TYPE_UINT, info->codec_tag, NULL); + } else if (strstr (info->mime, "application/x-smpte-text")) { + if (info->context) { + gst_caps_set_simple (caps, "ttml_priv_data", G_TYPE_POINTER, + info->context, NULL); + } + } + + player->s_stream_caps = gst_caps_copy (caps); + + gst_caps_unref (caps); +#endif + + MMPLAYER_FLEAVE (); + + return MM_ERROR_NONE; +} diff --git a/src/mm_player_ini.c b/src/mm_player_ini.c index 8c3ca4c..ec85f19 100755 --- a/src/mm_player_ini.c +++ b/src/mm_player_ini.c @@ -176,14 +176,12 @@ mm_player_ini_load(mm_player_ini_t* ini) ini->localplayback_state_change_timeout = iniparser_getint(dict, "general:localplayback state change timeout", DEFAULT_LOCALPLAYBACK_STATE_CHANGE_TIMEOUT); ini->eos_delay = iniparser_getint(dict, "general:eos delay", DEFAULT_EOS_DELAY); ini->async_start = iniparser_getboolean(dict, "general:async start", DEFAULT_ASYNC_START); - ini->multiple_codec_supported = iniparser_getboolean(dict, "general:multiple codec supported", DEFAULT_MULTIPLE_CODEC_SUPPORTED); ini->delay_before_repeat = iniparser_getint(dict, "general:delay before repeat", DEFAULT_DELAY_BEFORE_REPEAT); MMPLAYER_INI_GET_STRING(dict, ini->videosink_element_x, "general:videosink element x", DEFAULT_VIDEOSINK_X); MMPLAYER_INI_GET_STRING(dict, ini->videosink_element_evas, "general:videosink element evas", DEFAULT_VIDEOSINK_EVAS); MMPLAYER_INI_GET_STRING(dict, ini->videosink_element_fake, "general:videosink element fake", DEFAULT_VIDEOSINK_FAKE); - MMPLAYER_INI_GET_STRING(dict, ini->name_of_drmsrc, "general:drmsrc element", DEFAULT_DRMSRC ); MMPLAYER_INI_GET_STRING(dict, ini->name_of_audio_resampler, "general:audio resampler element", DEFAULT_AUDIORESAMPLER ); MMPLAYER_INI_GET_STRING(dict, ini->name_of_audiosink, "general:audiosink element", DEFAULT_AUDIOSINK ); MMPLAYER_INI_GET_STRING(dict, ini->name_of_video_converter, "general:video converter element", DEFAULT_VIDEO_CONVERTER ); @@ -210,17 +208,6 @@ mm_player_ini_load(mm_player_ini_t* ini) ini->rtsp_buffering_time = iniparser_getint(dict, "rtsp streaming:rtsp buffering time", DEFAULT_RTSP_BUFFERING); ini->rtsp_rebuffering_time = iniparser_getint(dict, "rtsp streaming:rtsp rebuffering time", DEFAULT_RTSP_REBUFFERING); ini->rtsp_do_typefinding = iniparser_getboolean(dict, "rtsp streaming:rtsp do typefinding", DEFAULT_RTSP_DO_TYPEFINDING); - ini->rtsp_error_concealment = iniparser_getboolean(dict, "rtsp streaming:rtsp error concealment", DEFAULT_RTSP_ERROR_CONCEALMENT); - - /* hw accelation */ - ini->use_video_hw_accel = iniparser_getboolean(dict, "hw accelation:use video hw accel", DEFAULT_USE_VIDEO_HW_ACCEL); - - /* priority */ - ini->use_priority_setting = iniparser_getboolean(dict, "priority:use priority setting", DEFAULT_USE_PRIORITY_SETTING); - ini->demux_priority = iniparser_getint(dict, "priority:demux", DEFAULT_PRIORITY_DEMUX); - ini->videosink_priority = iniparser_getint(dict, "priority:videosink", DEFAULT_PRIORITY_VIDEO_SINK); - ini->audiosink_priority = iniparser_getint(dict, "priority:audiosink", DEFAULT_PRIORITY_AUDIO_SINK); - ini->ringbuffer_priority = iniparser_getint(dict, "priority:ringbuffer", DEFAULT_PRIORITY_RINGBUFFER); /* dump buffer for debug */ __get_element_list(ini, @@ -244,11 +231,9 @@ mm_player_ini_load(mm_player_ini_t* ini) ini->live_state_change_timeout = DEFAULT_LIVE_STATE_CHANGE_TIMEOUT; ini->localplayback_state_change_timeout = DEFAULT_LOCALPLAYBACK_STATE_CHANGE_TIMEOUT; ini->eos_delay = DEFAULT_EOS_DELAY; - ini->multiple_codec_supported = DEFAULT_MULTIPLE_CODEC_SUPPORTED; ini->async_start = DEFAULT_ASYNC_START; ini->delay_before_repeat = DEFAULT_DELAY_BEFORE_REPEAT; - strncpy( ini->name_of_drmsrc, DEFAULT_DRMSRC, PLAYER_INI_MAX_STRLEN - 1 ); strncpy( ini->name_of_audio_resampler, DEFAULT_AUDIORESAMPLER, PLAYER_INI_MAX_STRLEN -1 ); strncpy( ini->name_of_audiosink, DEFAULT_AUDIOSINK, PLAYER_INI_MAX_STRLEN -1 ); strncpy( ini->name_of_video_converter, DEFAULT_VIDEO_CONVERTER, PLAYER_INI_MAX_STRLEN -1 ); @@ -277,17 +262,6 @@ mm_player_ini_load(mm_player_ini_t* ini) ini->rtsp_buffering_time = DEFAULT_RTSP_BUFFERING; ini->rtsp_rebuffering_time = DEFAULT_RTSP_REBUFFERING; ini->rtsp_do_typefinding = DEFAULT_RTSP_DO_TYPEFINDING; - ini->rtsp_error_concealment = DEFAULT_RTSP_ERROR_CONCEALMENT; - - /* hw accelation */ - ini->use_video_hw_accel = DEFAULT_USE_VIDEO_HW_ACCEL; - - /* priority */ - ini->use_priority_setting = DEFAULT_USE_PRIORITY_SETTING; - ini->demux_priority = DEFAULT_PRIORITY_DEMUX; - ini->videosink_priority = DEFAULT_PRIORITY_VIDEO_SINK; - ini->audiosink_priority = DEFAULT_PRIORITY_AUDIO_SINK; - ini->ringbuffer_priority = DEFAULT_PRIORITY_RINGBUFFER; /* dump buffer for debug */ __get_element_list(ini, DEFAULT_DUMP_ELEMENT_KEYWORD, KEYWORD_DUMP); @@ -313,12 +287,10 @@ mm_player_ini_load(mm_player_ini_t* ini) debug_log("localplayback_state_change_timeout(sec) : %d\n", ini->localplayback_state_change_timeout); debug_log("eos_delay(msec) : %d\n", ini->eos_delay); debug_log("delay_before_repeat(msec) : %d\n", ini->delay_before_repeat); - debug_log("name_of_drmsrc : %s\n", ini->name_of_drmsrc); debug_log("name_of_audioresampler : %s\n", ini->name_of_audio_resampler); debug_log("name_of_audiosink : %s\n", ini->name_of_audiosink); debug_log("name_of_video_converter : %s\n", ini->name_of_video_converter); debug_log("async_start : %d\n", ini->async_start); - debug_log("multiple_codec_supported : %d\n", ini->multiple_codec_supported); debug_log("gst_param1 : %s\n", ini->gst_param[0]); debug_log("gst_param2 : %s\n", ini->gst_param[1]); @@ -349,17 +321,6 @@ mm_player_ini_load(mm_player_ini_t* ini) debug_log("rtsp_buffering_time(msec) : %d\n", ini->rtsp_buffering_time); debug_log("rtsp_rebuffering_time(msec) : %d\n", ini->rtsp_rebuffering_time); debug_log("rtsp_do_typefinding : %d \n", ini->rtsp_do_typefinding); - debug_log("rtsp_error_concealment : %d \n", ini->rtsp_error_concealment); - - /* hw accel */ - debug_log("use_video_hw_accel : %d\n", ini->use_video_hw_accel); - - /* priority */ - debug_log("use_priority_setting : %d\n", ini->use_priority_setting); - debug_log("demux_priority : %d\n", ini->demux_priority); - debug_log("audiosink_priority : %d\n", ini->audiosink_priority); - debug_log("videosink_priority : %d\n", ini->videosink_priority); - debug_log("ringbuffer_priority : %d\n", ini->ringbuffer_priority); return MM_ERROR_NONE; } diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index bada487..e92c5d0 100755 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -32,6 +32,7 @@ #ifdef HAVE_WAYLAND #include <gst/wayland/wayland.h> #endif +#include <gst/audio/gstaudiobasesink.h> #include <unistd.h> #include <sys/stat.h> #include <string.h> @@ -50,6 +51,7 @@ #include "mm_player_utils.h" #include "mm_player_tracks.h" #include <sched.h> + #include <mm_sound.h> #define MM_SMOOTH_STREAMING @@ -105,6 +107,13 @@ #define LAZY_PAUSE_TIMEOUT_MSEC 700 #define MM_PLAYER_NAME "mmplayer" +#define SMOOTH_STREAMING_DEMUX "mssdemux" +/* + * g_array_index(a,t,i) does not calculate gst private structure. + * It replaces the g_array_index(a,t,i) + */ +#define g_array_undef_struct_idx_p(a,t,i) ((t *)(void *)((a)->data + ((i) * (a)->len))) + //#define ENABLE_DRMSRC /*--------------------------------------------------------------------------- @@ -242,8 +251,8 @@ static int __mmplayer_set_pcm_extraction(mm_player_t* player); static gboolean __mmplayer_can_extract_pcm( mm_player_t* player ); /*fadeout */ -//static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time); -//static void __mmplayer_undo_sound_fadedown(mm_player_t* player); +static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time); +static void __mmplayer_undo_sound_fadedown(mm_player_t* player); static void __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data); static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps); @@ -259,6 +268,9 @@ static gboolean __is_http_live_streaming( mm_player_t* player ); static gboolean __is_dash_streaming( mm_player_t* player ); static gboolean __is_smooth_streaming( mm_player_t* player ); static gboolean __is_http_progressive_down(mm_player_t* player); +#ifdef TEST_ES +static gboolean __is_es_buff_src(mm_player_t* player); +#endif static gboolean __has_suffix(mm_player_t * player, const gchar * suffix); static GstBusSyncReply __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data); @@ -275,14 +287,13 @@ 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 int __mmplayer_ignore_current_external_display_mode(mm_player_t* player); #if 0 // We'll need this in future. static int __mmplayer_gst_switching_element(mm_player_t *player, GstElement *search_from, const gchar *removal_name, const gchar *new_element_name); #endif static void __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg); static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name); -//static gboolean __mmplayer_can_do_interrupt(mm_player_t *player); +static gboolean __mmplayer_can_do_interrupt(mm_player_t *player); /* device change post proc */ void __mmplayer_device_change_post_process(gpointer user); @@ -293,8 +304,16 @@ void __mmplayer_device_change_trigger_post_process(mm_player_t* player); static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player); static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name); - - +#ifdef TEST_ES +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); +#endif /*=========================================================================================== | | | FUNCTION DEFINITIONS | @@ -555,7 +574,7 @@ __mmplayer_gst_set_state (mm_player_t* player, GstElement * element, GstState s debug_error("failed to set [%s] state\n", GST_ELEMENT_NAME(element)); /* dump state of all element */ - //__mmplayer_dump_pipeline_state( player ); + __mmplayer_dump_pipeline_state( player ); return MM_ERROR_PLAYER_INTERNAL; } @@ -582,7 +601,7 @@ __mmplayer_gst_set_state (mm_player_t* player, GstElement * element, GstState s gst_element_state_get_name(element_pending_state) ); /* dump state of all element */ - //__mmplayer_dump_pipeline_state( player ); + __mmplayer_dump_pipeline_state( player ); return MM_ERROR_PLAYER_INTERNAL; } @@ -618,7 +637,7 @@ int width, int height, gpointer user_data) // @ /* clear stream data structure */ memset(&stream, 0x0, sizeof(MMPlayerVideoStreamDataType)); - stream.data = data; + stream.data[0] = data; stream.length_total = width * height * 4; // for rgb 32bit stream.height = height; stream.width = width; @@ -800,8 +819,8 @@ __mmplayer_device_change_trigger_post_process(mm_player_t* player) static void __mmplayer_sound_device_info_changed_cb_func (MMSoundDevice_t device_h, int changed_info_type, void *user_data) { - int ret; - mm_sound_device_type_e device_type; + int ret; + mm_sound_device_type_e device_type; mm_player_t* player = (mm_player_t*) user_data; return_if_fail( player ); @@ -1121,13 +1140,7 @@ gint __mmplayer_get_stream_service_type( mm_player_t* player ) if ( ! MMPLAYER_IS_STREAMING(player) ) return STREAMING_SERVICE_NONE; - if (MMPLAYER_IS_RTSP_STREAMING(player)) - { - /* get property from rtspsrc element */ - g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), - "service_type", &streaming_type, NULL); - } - else if (MMPLAYER_IS_HTTP_STREAMING(player)) + if (MMPLAYER_IS_HTTP_STREAMING(player)) { streaming_type = (player->duration == 0) ? STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD; @@ -1162,9 +1175,9 @@ static int __mmplayer_set_state(mm_player_t* player, int state) // @ { MMMessageParamType msg = {0, }; -// int asm_result = MM_ERROR_NONE; + int asm_result = MM_ERROR_NONE; gboolean post_bos = FALSE; -// gboolean interrupted_by_asm = FALSE; + gboolean interrupted_by_asm = FALSE; int ret = MM_ERROR_NONE; return_val_if_fail ( player, FALSE ); @@ -1192,7 +1205,7 @@ __mmplayer_set_state(mm_player_t* player, int state) // @ MMPLAYER_PRINT_STATE(player); /* do some FSM stuffs before posting new state to application */ -// interrupted_by_asm = player->sm.by_asm_cb; + interrupted_by_asm = player->sm.by_asm_cb; switch ( MMPLAYER_CURRENT_STATE(player) ) { @@ -1201,12 +1214,12 @@ __mmplayer_set_state(mm_player_t* player, int state) // @ { if (player->cmd == MMPLAYER_COMMAND_STOP) { -// asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_STOP, FALSE); -// if ( asm_result != MM_ERROR_NONE ) -// { -// debug_error("failed to set asm state to stop\n"); -// return MM_ERROR_POLICY_INTERNAL; -// } + asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_STOP, FALSE); + if ( asm_result != MM_ERROR_NONE ) + { + debug_error("failed to set asm state to stop\n"); + return MM_ERROR_POLICY_INTERNAL; + } } } break; @@ -1235,7 +1248,7 @@ __mmplayer_set_state(mm_player_t* player, int state) // @ } /* add audio callback probe if condition is satisfied */ - if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction ) + 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 */ @@ -1243,12 +1256,12 @@ __mmplayer_set_state(mm_player_t* player, int state) // @ if (!MMPLAYER_IS_STREAMING(player) || (player->streamer && !player->streamer->is_buffering)) { -// asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PAUSE, FALSE); -// if ( asm_result ) -// { -// debug_error("failed to set asm state to PAUSE\n"); -// return MM_ERROR_POLICY_INTERNAL; -// } + asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PAUSE, FALSE); + if ( asm_result ) + { + debug_error("failed to set asm state to PAUSE\n"); + return MM_ERROR_POLICY_INTERNAL; + } } } break; @@ -1270,7 +1283,7 @@ __mmplayer_set_state(mm_player_t* player, int state) // @ { __mmplayer_handle_missed_plugin ( player ); } -#if 0 + /* update ASM state for video and streaming buffering */ asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PLAYING, TRUE); if (asm_result != MM_ERROR_NONE) @@ -1296,7 +1309,6 @@ __mmplayer_set_state(mm_player_t* player, int state) // @ return MM_ERROR_POLICY_INTERNAL; } -#endif } if ( player->resumed_by_rewind && player->playback_rate < 0.0 ) @@ -1366,14 +1378,14 @@ __mmplayer_set_state(mm_player_t* player, int state) // @ debug_log ("player reach the target state (%s)", MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player))); /* state changed by asm callback */ -// if ( interrupted_by_asm ) -// { -// msg.union_type = MM_MSG_UNION_CODE; -// msg.code = player->sm.event_src; -// MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg ); -// } -// /* state changed by usecase */ -// else + if ( interrupted_by_asm ) + { + msg.union_type = MM_MSG_UNION_CODE; + msg.code = player->sm.event_src; + MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg ); + } + /* state changed by usecase */ + else { MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_CHANGED, &msg ); } @@ -1419,7 +1431,6 @@ static gpointer __mmplayer_next_play_thread(gpointer data) return_val_if_fail ( player, NULL ); g_mutex_lock(&player->next_play_thread_mutex); - while ( ! player->next_play_thread_exit ) { debug_log("next play thread started. waiting for signal.\n"); @@ -1429,8 +1440,11 @@ static gpointer __mmplayer_next_play_thread(gpointer data) if ( player->next_play_thread_exit ) { - MMPLAYER_PLAYBACK_UNLOCK(player); - + if(player->pp_rebuilding) + { + player->pp_rebuilding = false; + MMPLAYER_PLAYBACK_UNLOCK(player); + } debug_log("exiting next play thread\n"); break; } @@ -1445,7 +1459,6 @@ static gpointer __mmplayer_next_play_thread(gpointer data) __mmplayer_activate_next_source(player, GST_STATE_PLAYING); } - g_mutex_unlock(&player->next_play_thread_mutex); return NULL; @@ -1461,11 +1474,10 @@ static gpointer __mmplayer_repeat_thread(gpointer data) return_val_if_fail ( player, NULL ); g_mutex_lock(&player->repeat_thread_mutex); - while ( ! player->repeat_thread_exit ) { debug_log("repeat thread started. waiting for signal.\n"); - g_cond_wait(&player->repeat_thread_cond, &player->repeat_thread_mutex); + g_cond_wait(&player->repeat_thread_cond, &player->repeat_thread_mutex ); if ( player->repeat_thread_exit ) { @@ -1473,12 +1485,6 @@ static gpointer __mmplayer_repeat_thread(gpointer data) break; } - if (!(&player->cmd_lock) ) - { - debug_log("can't get cmd lock\n"); - g_mutex_unlock(&player->repeat_thread_mutex); - return NULL; - } /* lock */ g_mutex_lock(&player->cmd_lock); @@ -1538,7 +1544,6 @@ static gpointer __mmplayer_repeat_thread(gpointer data) } g_mutex_unlock(&player->repeat_thread_mutex); - return NULL; } @@ -1827,7 +1832,7 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @ __mmplayer_drop_subtitle(player, TRUE); - if ( (player->audio_stream_cb) && (player->set_mode.pcm_extraction) ) + if ( (player->audio_stream_cb) && (player->set_mode.pcm_extraction) && (!player->audio_stream_render_cb_ex)) { GstPad *pad = NULL; @@ -1988,7 +1993,7 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @ case GST_MESSAGE_BUFFERING: { MMMessageParamType msg_param = {0, }; -// int asm_result = MM_ERROR_NONE; + int asm_result = MM_ERROR_NONE; if (!MMPLAYER_IS_STREAMING(player)) break; @@ -2011,14 +2016,14 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @ /* update ASM state to ASM_STATE_PLAYING */ /* fixed ASM_STATE_WAITING -> ASM_STATE_PLAYING for Samsunlink issue*/ -// if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED)) -// { -// asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_WAITING, TRUE); -// if ( asm_result != MM_ERROR_NONE ) -// { -// debug_warning("failed to set asm state to waiting, but keep going...\n"); -// } -// } + if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED)) + { + asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_WAITING, TRUE); + if ( asm_result != MM_ERROR_NONE ) + { + debug_warning("failed to set asm state to waiting, but keep going...\n"); + } + } __mmplayer_update_buffer_setting(player, msg); @@ -2099,7 +2104,7 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @ gboolean prepare_async = FALSE; gboolean is_drm = FALSE; - if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction) + if ( ! player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex) __mmplayer_configure_audio_callback(player); if ( ! player->sent_bos && oldstate == GST_STATE_READY) // managed prepare async case @@ -2293,48 +2298,45 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @ if( msg->src != (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst ) break; - if( !MMPLAYER_IS_RTSP_STREAMING(player) ) + if (player->doing_seek) { - if (player->doing_seek) + if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) { - if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) - { - player->doing_seek = FALSE; - MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL ); - } - else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) + player->doing_seek = FALSE; + MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL ); + } + else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) + { + if ((MMPLAYER_IS_HTTP_STREAMING(player)) && + (player->streamer) && + (player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) && + (player->streamer->is_buffering == FALSE)) { - if ((MMPLAYER_IS_HTTP_STREAMING(player)) && - (player->streamer) && - (player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) && - (player->streamer->is_buffering == FALSE)) - { - GstQuery *query = NULL; - gboolean busy = FALSE; - gint percent = 0; + GstQuery *query = NULL; + gboolean busy = FALSE; + gint percent = 0; - if (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer) + if (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer) + { + query = gst_query_new_buffering ( GST_FORMAT_PERCENT ); + if ( gst_element_query (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer, query ) ) { - query = gst_query_new_buffering ( GST_FORMAT_PERCENT ); - if ( gst_element_query (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer, query ) ) - { - gst_query_parse_buffering_percent ( query, &busy, &percent); - } - gst_query_unref (query); - - debug_log("buffered percent(%s): %d\n", - GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent); + gst_query_parse_buffering_percent ( query, &busy, &percent); } + gst_query_unref (query); - if (percent >= 100) - { - player->streamer->is_buffering = FALSE; - __mmplayer_handle_buffering_message(player); - } + debug_log("buffered percent(%s): %d\n", + GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent); } - async_done = TRUE; + if (percent >= 100) + { + player->streamer->is_buffering = FALSE; + __mmplayer_handle_buffering_message(player); + } } + + async_done = TRUE; } } } @@ -2808,7 +2810,7 @@ __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) /* clear previous result*/ player->have_dynamic_pad = FALSE; - if ( ! __mmplayer_try_to_plug( player, pad, caps ) ) + if ( !__mmplayer_try_to_plug_decodebin(player, pad, caps)) { debug_error("failed to autoplug for caps"); goto ERROR; @@ -3098,6 +3100,13 @@ __mmplayer_gst_decode_pad_added (GstElement *elem, GstPad *pad, gpointer data) if (stype == MM_DISPLAY_SURFACE_NULL) { debug_log ("no video sink by null surface or multiple track"); + gchar *caps_str = gst_caps_to_string(caps); + if (strstr(caps_str, "ST12") || strstr(caps_str, "SN12")) + { + player->set_mode.video_zc = TRUE; + } + MMPLAYER_FREEIF( caps_str ); + if (player->v_stream_caps) { gst_caps_unref(player->v_stream_caps); @@ -3151,7 +3160,13 @@ __mmplayer_gst_decode_pad_added (GstElement *elem, GstPad *pad, gpointer data) { gint samplerate = 0; gint channels = 0; - +#ifdef TEST_ES + if (MMPLAYER_IS_ES_BUFF_SRC(player)) + { + __mmplayer_gst_decode_callback (elem, pad, player); + return; + } +#endif debug_log ("audio selector \n"); elemId = MMPLAYER_M_A_INPUT_SELECTOR; stream_type = MM_PLAYER_TRACK_TYPE_AUDIO; @@ -3207,16 +3222,14 @@ __mmplayer_gst_decode_pad_added (GstElement *elem, GstPad *pad, gpointer data) if (selector == NULL) { - if (strstr(name, "audio") || strstr(name, "video")) { - selector = gst_element_factory_make ("input-selector", NULL); - debug_log ("Creating input-selector\n"); - if (selector == NULL) - { - debug_error ("ERROR : input-selector create error\n"); - goto ERROR; - } - g_object_set (selector, "sync-streams", TRUE, NULL); + selector = gst_element_factory_make ("input-selector", NULL); + debug_log ("Creating input-selector\n"); + if (selector == NULL) + { + debug_error ("ERROR : input-selector create error\n"); + goto ERROR; } + g_object_set (selector, "sync-streams", TRUE, NULL); gst_bin_add (GST_BIN(pipeline), selector); gst_element_set_state (selector, GST_STATE_PAUSED); @@ -3254,18 +3267,10 @@ __mmplayer_gst_decode_pad_added (GstElement *elem, GstPad *pad, gpointer data) goto ERROR; } - if (first_track && (strstr(name, "audio") || strstr(name, "video"))) + if (first_track) { debug_log ("this is first track --> active track \n"); g_object_set (selector, "active-pad", sinkpad, NULL); - } else { - debug_log ("subtitle is of internal type \n"); - if(!player->textsink_linked) { - g_object_set (selector, "is-internal", TRUE, NULL); - } else { - debug_log ("this is first track --> active track \n"); - g_object_set (selector, "active-pad", sinkpad, NULL); - } } _mmplayer_track_update_info(player, stream_type, sinkpad); @@ -3964,11 +3969,21 @@ __mmplayer_gst_decode_no_more_pads (GstElement *elem, gpointer data) MMPLAYER_RELEASE_ELEMENT ( player, player->pipeline->audiobin, MMPLAYER_A_BIN ); MMPLAYER_FREEIF ( player->pipeline->audiobin ) } + + if (player->num_dynamic_pad == 0) + { + __mmplayer_pipeline_complete (NULL, player); + } } - if (text_selector) +#ifdef TEST_ES + if (!MMPLAYER_IS_ES_BUFF_SRC(player)) +#endif { - __mmplayer_handle_text_decode_path(player, text_selector); + if (text_selector) + { + __mmplayer_handle_text_decode_path(player, text_selector); + } } MMPLAYER_FLEAVE(); @@ -4180,7 +4195,7 @@ __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data) // } sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst; - debug_log("creating textink bin success\n"); + debug_log("creating textsink bin success\n"); /* FIXIT : track number shouldn't be hardcoded */ mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1); @@ -4233,6 +4248,7 @@ __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data) // text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst; } } + else { if (!player->textsink_linked) @@ -4277,32 +4293,6 @@ __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data) // } } - if (text_selector) - { - GstPad *srcpad = NULL; - - srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst,"src"); - if (!srcpad) - { - debug_error ("failed to get source pad"); - goto ERROR; - } - - /* link input selector & textbin */ - if (gst_pad_link(srcpad,sinkpad)!= 0) - { - debug_warning("failed to link input selector and textbin ghost pad\n"); - goto ERROR; - } - - sinkpad = gst_element_get_request_pad (player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst, "sink_%u"); - if (sinkpad == NULL) - { - debug_error ("failed to get request pad from input selector");; - goto ERROR; - } - } - /* link */ if (GST_PAD_LINK_OK != GST_PAD_LINK (pad, sinkpad)) { @@ -4985,6 +4975,15 @@ __mmplayer_gst_element_link_bucket(GList* element_bucket) // @ if ( element && element->gst ) { +#ifdef TEST_ES + /* If next element is audio appsrc then make a seprate 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; + } +#endif if ( GST_ELEMENT_LINK(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst)) ) { debug_log("linking [%s] to [%s] success\n", @@ -5043,6 +5042,73 @@ __mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket) // return successful_add_count; } +static void __mmplayer_gst_caps_notify_cb (GstPad * pad, GParamSpec * unused, gpointer data) +{ + mm_player_t* player = (mm_player_t*) data; + GstCaps *caps = NULL; + GstStructure *str = NULL; + const char *name; + + MMPLAYER_FENTER(); + + return_if_fail ( pad ) + return_if_fail ( unused ) + return_if_fail ( data ) + + caps = gst_pad_query_caps(pad, NULL); + if ( !caps ) + { + return; + } + + str = gst_caps_get_structure(caps, 0); + if ( !str ) + { + goto ERROR; + } + + name = gst_structure_get_name(str); + if ( !name ) + { + goto ERROR; + } + + debug_log("name = %s\n", name); + + if (strstr(name, "audio")) + { + _mmplayer_update_content_attrs (player, ATTR_AUDIO); + + if (player->audio_stream_changed_cb) + { + debug_error("call the audio stream changed cb\n"); + 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) + { + debug_error("call the video stream changed cb\n"); + player->video_stream_changed_cb(player->video_stream_changed_cb_user_param); + } + } + else + { + goto ERROR; + } + +ERROR: + + gst_caps_unref(caps); + + MMPLAYER_FLEAVE(); + + return; +} + /** @@ -5104,12 +5170,203 @@ do \ element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\ } while(0); +static void +__mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data) +{ + mm_player_t* player = (mm_player_t*) data; + + gint channel = 0; + gint rate = 0; + gint depth = 0; + gint endianness = 0; + guint64 channel_mask = 0; + + MMPlayerAudioStreamDataType audio_stream = { 0, }; + GstMapInfo mapinfo = GST_MAP_INFO_INIT; + + MMPLAYER_FENTER(); + return_if_fail(player->audio_stream_render_cb_ex); + + debug_log ("__mmplayer_audio_stream_decoded_render_cb new pad: %s", GST_PAD_NAME (pad)); + + gst_buffer_map(buffer, &mapinfo, GST_MAP_READ); + audio_stream.data = mapinfo.data; + audio_stream.data_size = mapinfo.size; + + GstCaps *caps = gst_pad_get_current_caps( pad ); + GstStructure *structure = gst_caps_get_structure (caps, 0); + + MMPLAYER_LOG_GST_CAPS_TYPE(caps); + gst_structure_get_int (structure, "rate", &rate); + gst_structure_get_int (structure, "channels", &channel); + gst_structure_get_int (structure, "depth", &depth); + gst_structure_get_int (structure, "endianness", &endianness); + gst_structure_get (structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL); + + gst_caps_unref(GST_CAPS(caps)); + + audio_stream.bitrate = rate; + audio_stream.channel = channel; + audio_stream.depth = depth; + audio_stream.is_little_endian = (endianness == 1234 ? 1 : 0); + audio_stream.channel_mask = channel_mask; + debug_log ("bitrate : %d channel : %d depth: %d ls_little_endian : %d channel_mask: %d, %p", rate, channel, depth, endianness, channel_mask, player->audio_stream_cb_user_param); + player->audio_stream_render_cb_ex(&audio_stream, player->audio_stream_cb_user_param); + gst_buffer_unmap(buffer, &mapinfo); + + MMPLAYER_FLEAVE(); +} + +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; + GstElement *queue = NULL, *sink = NULL; + + MMPLAYER_FENTER(); + return_if_fail (player && player->pipeline && player->pipeline->mainbin); + + queue = gst_element_factory_make ("queue", NULL); + if (queue == NULL) + { + debug_log ("fail make queue\n"); + goto ERROR; + } + + sink = gst_element_factory_make ("fakesink", NULL); + if (sink == NULL) + { + debug_log ("fail make fakesink\n"); + 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)) + { + debug_warning("failed to link queue & sink\n"); + goto ERROR; + } + + sinkpad = gst_element_get_static_pad (queue, "sink"); + + if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) + { + debug_warning ("failed to link [%s:%s] to queue\n", GST_DEBUG_PAD_NAME(pad)); + goto ERROR; + } + + debug_error("player->audio_stream_sink_sync: %d\n", player->audio_stream_sink_sync); + + gst_object_unref (sinkpad); + g_object_set (sink, "sync", player->audio_stream_sink_sync, NULL); + g_object_set (sink, "signal-handoffs", TRUE, NULL); + + gst_element_set_state (sink, GST_STATE_PAUSED); + gst_element_set_state (queue, GST_STATE_PAUSED); + + MMPLAYER_SIGNAL_CONNECT( player, + G_OBJECT(sink), + MM_PLAYER_SIGNAL_TYPE_AUDIOBIN, + "handoff", + G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb), + (gpointer)player ); + + MMPLAYER_FLEAVE(); + return ; + +ERROR: + debug_error("__mmplayer_gst_audio_deinterleave_pad_added ERROR\n"); + if (queue) + { + gst_object_unref(GST_OBJECT(queue)); + queue = NULL; + } + if (sink) + { + gst_object_unref(GST_OBJECT(sink)); + sink = NULL; + } + if (sinkpad) + { + gst_object_unref ( GST_OBJECT(sinkpad) ); + sinkpad = NULL; + } + + return; +} + + /** * AUDIO PIPELINE * - Local playback : audiotp !audioconvert ! volume ! capsfilter ! audioeffect ! audioeffect_sec ! audiosink * - Streaming : audiotp !audioconvert !volume ! audiosink * - PCM extraction : audiotp !audioconvert ! audioresample ! capsfilter ! fakesink */ +void __mmplayer_gst_create_audiosink_configure(mm_player_t* player, MMHandleType attrs) +{ +#define MAX_PROPS_LEN 64 + gint volume_type = 0; + gint route_path = 0; + gint latency_mode = 0; + gchar *stream_type = NULL; + gint stream_id = 0; + gchar stream_props[MAX_PROPS_LEN] = {0,}; + GstStructure *props = NULL; + + /* set volume table + * It should be set after player creation through attribute. + * 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 ); + + if ( stream_id < 1 || !stream_type || strlen(stream_type) < 1) + { + debug_error("stream_id[%d] or stream_type[%s] is not valid.\n", stream_id, stream_type); + } + else + { + snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d", stream_type, stream_id); + props = gst_structure_from_string(stream_props, NULL); + g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL); + } + + debug_log("stream_id[%d], stream_type[%s], result[%s].\n", stream_id, stream_type, stream_props); + +/* for audio tunning */ +#ifndef IS_SDK + if (player->profile.play_mode == MM_PLAYER_MODE_MIDI) + { + volume_type |= MM_SOUND_VOLUME_GAIN_MIDI; + } +#endif + /* hook sound_type if emergency case */ + if (player->sm.event == ASM_EVENT_EMERGENCY) + { + debug_log ("This is emergency session, hook sound_type from [%d] to [%d]\n", volume_type, MM_SOUND_VOLUME_TYPE_EMERGENCY); + volume_type = MM_SOUND_VOLUME_TYPE_EMERGENCY; + } + + mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode); + + if (player->sm.user_route_policy != 0) + { + route_path = player->sm.user_route_policy; + } + + g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, + "latency", latency_mode, + NULL); + + debug_log("audiosink property status...volume type:%d, user-route=%d, latency=%d \n", + volume_type, route_path, latency_mode); + MMPLAYER_FLEAVE(); +} + static int __mmplayer_gst_create_audio_pipeline(mm_player_t* player) { @@ -5161,51 +5418,58 @@ __mmplayer_gst_create_audio_pipeline(mm_player_t* player) if (player->set_mode.pcm_extraction) // pcm extraction only and no sound output { - 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); + if(player->audio_stream_render_cb_ex) + { + MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_DEINTERLEAVE, "deinterleave", "deinterleave", TRUE, player); - /* 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); - debug_log("new caps : %s\n", caps_str); + 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; - g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", 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); + debug_log("new caps : %s\n", caps_str); - /* clean */ - gst_caps_unref( caps ); - MMPLAYER_FREEIF( caps_str ); + g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL ); - /* fake sink */ - MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, player); + /* clean */ + gst_caps_unref( caps ); + MMPLAYER_FREEIF( caps_str ); - /* set sync */ - g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL); + /* fake sink */ + MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, player); + + /* set sync */ + g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL); + } } else // normal playback { - typedef enum - { - GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE = 0, - GST_BASE_AUDIO_SINK_SLAVE_SKEW, - GST_BASE_AUDIO_SINK_SLAVE_NONE - } GstBaseAudioSinkSlaveMethod; - //GstCaps* caps = NULL; gint channels = 0; @@ -5289,7 +5553,7 @@ __mmplayer_gst_create_audio_pipeline(mm_player_t* player) /* 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_BASE_AUDIO_SINK_SLAVE_NONE, NULL); + g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL); /* FIXIT : using system clock. isn't there another way? */ if (player->videodec_linked) @@ -5303,53 +5567,9 @@ __mmplayer_gst_create_audio_pipeline(mm_player_t* player) g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", player->ini.provide_clock_for_music, NULL); } - if ( g_strrstr(player->ini.name_of_audiosink, "avsysaudiosink") || g_strrstr(player->ini.name_of_audiosink, "pulsesink") ) + if ( g_strrstr(player->ini.name_of_audiosink, "pulsesink") ) { - gint volume_type = 0; - gint audio_route = 0; - gint sound_priority = FALSE; - gint route_path = 0; - gint latency_mode = 0; - gint close_handle = 0; - - /* set volume table - * It should be set after player creation through attribute. - * But, it can not be changed during playing. - */ - mm_attrs_get_int_by_name(attrs, "sound_volume_type", &volume_type); - mm_attrs_get_int_by_name(attrs, "sound_route", &audio_route); - mm_attrs_get_int_by_name(attrs, "sound_priority", &sound_priority); - mm_attrs_get_int_by_name(attrs, "sound_spk_out_only", &route_path); - mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode); - mm_attrs_get_int_by_name(attrs, "sound_close_resource", &close_handle); -/* for audio tunning */ -#ifndef IS_SDK - if (player->profile.play_mode == MM_PLAYER_MODE_MIDI) { - volume_type |= MM_SOUND_VOLUME_GAIN_MIDI; - } -#endif -#if 0 - /* hook sound_type if emergency case */ - if (player->sm.event == ASM_EVENT_EMERGENCY) { - debug_log ("This is emergency session, hook sound_type from [%d] to [%d]\n", volume_type, MM_SOUND_VOLUME_TYPE_EMERGENCY); - volume_type = MM_SOUND_VOLUME_TYPE_EMERGENCY; - } - - if (player->sm.user_route_policy != 0) { - route_path = player->sm.user_route_policy; - } -#endif - g_object_set(audiobin[MMPLAYER_A_SINK].gst, - "volumetype", volume_type, - "audio-route", audio_route, - "priority", sound_priority, - "user-route", route_path, - "latency", latency_mode, - "close-handle-on-prepare", close_handle, - NULL); - - debug_log("audiosink property status...volume type:%d, route:%d, priority=%d, user-route=%d, latency=%d, close-resource=%d\n", - volume_type, audio_route, sound_priority, route_path, latency_mode, close_handle); + __mmplayer_gst_create_audiosink_configure(player, attrs); } /* Antishock can be enabled when player is resumed by soundCM. @@ -5359,6 +5579,15 @@ __mmplayer_gst_create_audio_pipeline(mm_player_t* player) __mmplayer_set_antishock( player , FALSE ); } + 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)); + } + __mmplayer_add_sink( player, audiobin[MMPLAYER_A_SINK].gst ); /* adding created elements to bin */ @@ -5377,10 +5606,10 @@ __mmplayer_gst_create_audio_pipeline(mm_player_t* player) goto ERROR; } - /* get first element's sinkpad for creating ghostpad */ - first_element = (MMPlayerGstElement *)element_bucket->data; + /* get first element's sinkpad for creating ghostpad */ + first_element = (MMPlayerGstElement *)element_bucket->data; - pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink"); + pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink"); if ( ! pad ) { debug_error("failed to get pad from first element of audiobin\n"); @@ -5480,7 +5709,7 @@ __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer user { GstCaps *caps = NULL; MMPlayerVideoStreamDataType stream; - MMPlayerMPlaneImage *scmn_imgb = NULL; + MMVideoBuffer *video_buffer = NULL; GstMemory *dataBlock = NULL; GstMemory *metaBlock = NULL; GstMapInfo mapinfo = GST_MAP_INFO_INIT; @@ -5532,26 +5761,29 @@ __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer user gst_buffer_n_memory(buffer) > 1) { metaBlock = gst_buffer_peek_memory(buffer, 1); gst_memory_map(metaBlock, &mapinfo, GST_MAP_READ); - scmn_imgb = (MMPlayerMPlaneImage *)mapinfo.data; + video_buffer = (MMVideoBuffer *)mapinfo.data; } - /* set tbm bo */ - if (scmn_imgb) { - /* copy pointer of tbm bo */ - memcpy(stream.bo, scmn_imgb->bo, sizeof(void *) * MM_PLAYER_IMGB_MPLANE_MAX); - - /* - int i = 0; - for (i = 0 ; i < BUFFER_MAX_PLANE_NUM ; i++) { - debug_log("scmn bo %p, stream bo %p", scmn_imgb->bo[i], stream.bo[i]); + if (video_buffer) { + /* set tbm bo */ + if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) { + /* copy pointer of tbm bo, stride, elevation */ + memcpy(stream.bo, video_buffer->handle.bo, + sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX); } - */ - + else if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) { + memcpy(stream.data, video_buffer->data, + sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX); + } + 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); /* set gst buffer */ stream.internal_buffer = buffer; } else { gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE); - stream.data = mapinfo.data; + stream.data[0] = mapinfo.data; } if (player->video_stream_cb) { @@ -5820,9 +6052,18 @@ __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDispl } } - if ( _mmplayer_update_video_param(player) != MM_ERROR_NONE) + if (_mmplayer_update_video_param(player) != MM_ERROR_NONE) goto ERROR; + if (videobin[MMPLAYER_V_SINK].gst) + { + GstPad *sink_pad = NULL; + sink_pad = gst_element_get_static_pad(videobin[MMPLAYER_V_SINK].gst, "sink"); + MMPLAYER_SIGNAL_CONNECT (player, sink_pad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN, + "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player); + gst_object_unref (GST_OBJECT(sink_pad)); + } + /* store it as it's sink element */ __mmplayer_add_sink( player, videobin[MMPLAYER_V_SINK].gst ); @@ -6221,26 +6462,14 @@ __mmplayer_gst_create_subtitle_src(mm_player_t* player) } debug_log ("link text input selector and textbin ghost pad"); - if (!gst_element_link_pads (subparse, "src", player->pipeline->textbin[MMPLAYER_T_BIN].gst, "text_sink")) - { - debug_warning("failed to link subparse and textbin\n"); - goto ERROR; - } - player->textsink_linked = 1; + player->textsink_linked = 1; player->external_text_idx = 0; debug_msg("player->textsink_linked set to 1\n"); } else { debug_log("text bin has been created. reuse it."); - - if (!gst_element_link_pads (subparse, "src", player->pipeline->textbin[MMPLAYER_T_BIN].gst, "text_sink")) - { - debug_warning("failed to link subparse and textbin\n"); - goto ERROR; - } - player->external_text_idx = 1; } @@ -6270,6 +6499,7 @@ __mmplayer_gst_create_subtitle_src(mm_player_t* player) return MM_ERROR_NONE; ERROR: + player->textsink_linked = 0; return MM_ERROR_PLAYER_INTERNAL; } @@ -6493,27 +6723,29 @@ __gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data static void __gst_appsrc_feed_data(GstElement *element, guint size, gpointer user_data) // @ { - mm_player_t *player = (mm_player_t*)user_data; + mm_player_t *player = (mm_player_t*)user_data; + MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT; return_if_fail ( player ); debug_msg("app-src: feed data\n"); - if(player->need_data_cb) - player->need_data_cb(size, player->buffer_cb_user_param); + if (player->media_stream_buffer_status_cb[type]) + player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param); } static gboolean __gst_appsrc_seek_data(GstElement *element, guint64 offset, gpointer user_data) // @ { mm_player_t *player = (mm_player_t*)user_data; + MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT; return_val_if_fail ( player, FALSE ); debug_msg("app-src: seek data\n"); - if(player->seek_data_cb) - player->seek_data_cb(offset, player->buffer_cb_user_param); + if(player->media_stream_seek_data_cb[type]) + player->media_stream_seek_data_cb[type](type, offset, player->buffer_cb_user_param); return TRUE; } @@ -6523,13 +6755,14 @@ static gboolean __gst_appsrc_enough_data(GstElement *element, gpointer user_data) // @ { mm_player_t *player = (mm_player_t*)user_data; + MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_DEFAULT; return_val_if_fail ( player, FALSE ); - debug_msg("app-src: enough data:%p\n", player->enough_data_cb); + debug_msg("app-src: enough data:%p\n", player->media_stream_buffer_status_cb[type]); - if(player->enough_data_cb) - player->enough_data_cb(player->buffer_cb_user_param); + if (player->media_stream_buffer_status_cb[type]) + player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param); return TRUE; } @@ -6717,6 +6950,113 @@ __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data) return reply; } +#ifdef TEST_ES +#if 0 // TO CHECK +static void +__mm_player_src_pad_block_cb (GstPad *pad, gboolean blocked, gpointer user_data) +{ + if (blocked) + { + debug_log("src pad is blocked"); + } + else + { + debug_log("src pad is unblocked"); + } +} +#endif +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(); + + return_val_if_fail( player && + player->pipeline && + player->pipeline->mainbin, FALSE); + return_val_if_fail((track == MM_PLAYER_TRACK_TYPE_AUDIO || track == MM_PLAYER_TRACK_TYPE_VIDEO), FALSE); + return_val_if_fail(srcpad, FALSE); + 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) + { + debug_error("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 decodebin2 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)) + { + debug_error("failed to add new decodebin\n"); + ret = FALSE; + goto ERROR; + } + + dec_caps = gst_pad_query_caps (srcpad, NULL); + if (dec_caps) + { + //debug_log ("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)) + { + debug_warning ("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)) + { + debug_error("failed to sync second level decodebin state with parent\n"); + } + + debug_log ("unblocking %" GST_PTR_FORMAT, srcpad); +// TO CHECK : gst_pad_set_blocked_async (srcpad, FALSE, __mm_player_src_pad_block_cb, NULL); + + debug_log("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; +} +#endif /** * This function is to create audio or video pipeline for playing. @@ -6734,6 +7074,13 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @ MMPlayerGstElement *mainbin = NULL; MMHandleType attrs = 0; GstElement* element = NULL; +#ifdef TEST_ES + 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; +#endif GList* element_bucket = NULL; gboolean need_state_holder = TRUE; gint i = 0; @@ -6817,15 +7164,9 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @ secure_debug_log("user_agent : %s\n", user_agent); secure_debug_log("wap_profile : %s\n", wap_profile); - debug_log("network_bandwidth : %d\n", network_bandwidth); - debug_log("buffering time : %d\n", player->ini.rtsp_buffering_time); - debug_log("rebuffering time : %d\n", player->ini.rtsp_rebuffering_time); /* setting property to streaming source */ g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL); - g_object_set(G_OBJECT(element), "bandwidth", network_bandwidth, NULL); - g_object_set(G_OBJECT(element), "buffering_time", player->ini.rtsp_buffering_time, NULL); - g_object_set(G_OBJECT(element), "rebuffering_time", player->ini.rtsp_rebuffering_time, NULL); if ( user_agent ) g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL); if ( wap_profile ) @@ -6977,19 +7318,6 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @ case MM_PLAYER_URI_TYPE_FILE: { -#ifdef ENABLE_DRMSRC - - char* drmsrc = player->ini.name_of_drmsrc; - - debug_log("using [%s] for 'file://' handler.\n", drmsrc); - - element = gst_element_factory_make(drmsrc, "source"); - if ( !element ) - { - debug_error("failed to create %s\n", drmsrc); - break; - } -#else debug_log("using filesrc for 'file://' handler.\n"); element = gst_element_factory_make("filesrc", "source"); @@ -6999,7 +7327,7 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @ debug_error("failed to create filesrc\n"); break; } -#endif + g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL); /* uri+7 -> remove "file:// */ //g_object_set(G_OBJECT(element), "use-mmap", TRUE, NULL); } @@ -7056,7 +7384,154 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @ G_CALLBACK(__gst_appsrc_enough_data), player); } break; +#ifdef TEST_ES + case MM_PLAYER_URI_TYPE_ES_BUFF: + { + debug_log("es buff src is selected\n"); + + if (player->v_stream_caps) + { + element = gst_element_factory_make("appsrc", "video_appsrc"); + if ( !element ) + { + debug_critical("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 ) + { + debug_critical("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 ) + { + debug_critical("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 ) + { + debug_critical("failed to create subtitle app source element[appsrc].\n" ); + break; + } + } + + debug_log("setting app sources properties.\n"); + debug_log("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->es_player_push_mode) + { + 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, element, 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; + } + break; +#endif /* appsrc */ case MM_PLAYER_URI_TYPE_MEM: { @@ -7140,10 +7615,79 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @ NULL, 0); } +#ifdef TEST_ES + if (MMPLAYER_IS_ES_BUFF_SRC(player)) + { + if (player->v_stream_caps) + { + es_video_queue = gst_element_factory_make("queue2", "video_queue"); + if (!es_video_queue) + { + debug_error ("create es_video_queue for es player failed\n"); + goto INIT_ERROR; + } + 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) + { + debug_error ("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]); + } + } + /* Only audio stream, no video */ + else if (player->a_stream_caps) + { + es_audio_queue = gst_element_factory_make("queue2", "audio_queue"); + if (!es_audio_queue) + { + debug_error ("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) + { + debug_error ("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]); + } + } +#endif /* 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_URL_WFD)) + (player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_WFD) +#ifdef TEST_ES + && (player->profile.uri_type != MM_PLAYER_URI_TYPE_ES_BUFF) +#endif + ) { element = NULL; enum MainElementID elemId = MMPLAYER_M_NUM; @@ -7223,6 +7767,51 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @ /* now we have completed mainbin. take it */ player->pipeline->mainbin = mainbin; +#ifdef TEST_ES + if (MMPLAYER_IS_ES_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); + } + } +#endif + + /* connect bus callback */ bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst)); if ( !bus ) @@ -7356,7 +7945,6 @@ __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @ __mmplayer_cancel_eos_timer( player ); /* remove sound cb */ - /* remove sound cb */ if ( MM_ERROR_NONE != mm_sound_remove_device_information_changed_callback()) { debug_error("failed to mm_sound_remove_device_information_changed_callback()"); @@ -7423,7 +8011,18 @@ __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @ gst_caps_unref(player->v_stream_caps); player->v_stream_caps = NULL; } - +#ifdef TEST_ES + if (player->a_stream_caps) + { + gst_caps_unref(player->a_stream_caps); + player->a_stream_caps = NULL; + } + if (player->s_stream_caps) + { + gst_caps_unref(player->s_stream_caps); + player->s_stream_caps = NULL; + } +#endif _mmplayer_track_destroy(player); if ( player->sink_elements ) @@ -7556,7 +8155,9 @@ static int __gst_start(mm_player_t* player) // @ { gboolean sound_extraction = 0; int ret = MM_ERROR_NONE; - +#ifdef TEST_ES + gboolean async = FALSE; +#endif MMPLAYER_FENTER(); return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED ); @@ -7603,9 +8204,20 @@ static int __gst_start(mm_player_t* player) // @ MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING; MMPLAYER_PRINT_STATE(player); +#ifdef TEST_ES + /* set pipeline state to PLAYING */ + if (player->es_player_push_mode) + { + async = TRUE; + } + /* set pipeline state to PLAYING */ + ret = __mmplayer_gst_set_state(player, + player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player) ); +#else /* set pipeline state to PLAYING */ ret = __mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, FALSE, MMPLAYER_STATE_CHANGE_TIMEOUT(player) ); +#endif if (ret == MM_ERROR_NONE) { MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING); @@ -7623,7 +8235,7 @@ static int __gst_start(mm_player_t* player) // @ return ret; } -#if 0 + static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time) { MMPLAYER_FENTER(); @@ -7653,7 +8265,6 @@ static void __mmplayer_undo_sound_fadedown(mm_player_t* player) MMPLAYER_FLEAVE(); } -#endif static int __gst_stop(mm_player_t* player) // @ { @@ -7664,7 +8275,9 @@ static int __gst_stop(mm_player_t* player) // @ gint timeout = 0; int ret = MM_ERROR_NONE; GstState state; - +#ifdef TEST_ES + gboolean async = FALSE; +#endif MMPLAYER_FENTER(); return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED); @@ -7684,8 +8297,8 @@ static int __gst_stop(mm_player_t* player) // @ mm_attrs_get_int_by_name(attrs, "sound_fadedown", &fadedown); /* enable fadedown */ -// if (fadedown || player->sm.by_asm_cb) -// __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT); + if (fadedown || player->sm.by_asm_cb) + __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT); /* Just set state to PAUESED and the rewind. it's usual player behavior. */ timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player ); @@ -7704,13 +8317,21 @@ static int __gst_stop(mm_player_t* player) // @ rewind = TRUE; } } - +#ifdef TEST_ES + if (player->es_player_push_mode) + { + async = TRUE; + } + /* set gst state */ + ret = __mmplayer_gst_set_state( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, state, async, timeout ); +#else /* set gst state */ ret = __mmplayer_gst_set_state( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, state, FALSE, timeout ); +#endif /* disable fadeout */ -// if (fadedown || player->sm.by_asm_cb) -// __mmplayer_undo_sound_fadedown(player); + if (fadedown || player->sm.by_asm_cb) + __mmplayer_undo_sound_fadedown(player); /* return if set_state has failed */ if ( ret != MM_ERROR_NONE ) @@ -7734,6 +8355,12 @@ static int __gst_stop(mm_player_t* player) // @ /* initialize */ player->sent_bos = FALSE; +#ifdef TEST_ES + if (player->es_player_push_mode) //for cloudgame + { + timeout = 0; + } +#endif /* wait for seek to complete */ change_ret = gst_element_get_state (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND); if ( change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL ) @@ -7935,32 +8562,36 @@ __gst_set_position(mm_player_t* player, int format, unsigned long position, gboo && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED ) goto PENDING; - /* check duration */ - /* NOTE : duration cannot be zero except live streaming. - * Since some element could have some timing problemn with quering duration, try again. - */ - if ( !player->duration ) +#ifdef TEST_ES + if( !MMPLAYER_IS_ES_BUFF_SRC(player) ) +#endif { - if ( !gst_element_query_duration( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec )) + /* check duration */ + /* NOTE : duration cannot be zero except live streaming. + * Since some element could have some timing problemn with quering duration, try again. + */ + if ( !player->duration ) { - goto SEEK_ERROR; + if ( !gst_element_query_duration( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec )) + { + goto SEEK_ERROR; + } + player->duration = dur_nsec; } - player->duration = dur_nsec; - } - if ( player->duration ) - { - dur_msec = GST_TIME_AS_MSECONDS(player->duration); - } - else - { - debug_error("could not get the duration. fail to seek.\n"); - goto SEEK_ERROR; + if ( player->duration ) + { + dur_msec = GST_TIME_AS_MSECONDS(player->duration); + } + else + { + debug_error("could not get the duration. fail to seek.\n"); + goto SEEK_ERROR; + } } - debug_log("playback rate: %f\n", player->playback_rate); - mm_attrs_get_int_by_name(player->attrs,"accurate_seek", &accurated); + mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated); if (accurated) { seek_flags |= GST_SEEK_FLAG_ACCURATE; @@ -7975,19 +8606,24 @@ __gst_set_position(mm_player_t* player, int format, unsigned long position, gboo { case MM_PLAYER_POS_FORMAT_TIME: { - /* check position is valid or not */ - if ( position > dur_msec ) - goto INVALID_ARGS; +#ifdef TEST_ES + if( !MMPLAYER_IS_ES_BUFF_SRC(player) ) +#endif + { + /* check position is valid or not */ + if ( position > dur_msec ) + goto INVALID_ARGS; - debug_log("seeking to (%lu) msec, duration is %d msec\n", position, dur_msec); + debug_log("seeking to (%lu) msec, duration is %d msec\n", position, dur_msec); - if (player->doing_seek) - { - debug_log("not completed seek"); - return MM_ERROR_PLAYER_DOING_SEEK; + if ( player->doing_seek ) + { + debug_log("not completed seek"); + return MM_ERROR_PLAYER_DOING_SEEK; + } } - if ( !internal_called) + if ( !internal_called ) player->doing_seek = TRUE; pos_nsec = position * G_GINT64_CONSTANT(1000000); @@ -8136,13 +8772,13 @@ __gst_get_position(mm_player_t* player, int format, unsigned long* position) // pos_msec = player->duration; } -// if (player->sm.keep_last_pos) { -// debug_log("return last pos as stop by asm, %"GST_TIME_FORMAT, GST_TIME_ARGS(player->last_position)); -// pos_msec = player->last_position; -// } -// else { -// player->last_position = pos_msec; -// } + if (player->sm.keep_last_pos) { + debug_log("return last pos as stop by asm, %"GST_TIME_FORMAT, GST_TIME_ARGS(player->last_position)); + pos_msec = player->last_position; + } + else { + player->last_position = pos_msec; + } } switch (format) { @@ -8395,6 +9031,17 @@ static int __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParse debug_warning("could access %s.\n", path); } } +#ifdef TEST_ES + else if ((path = strstr(uri, "es_buff://"))) + { + if (strlen(path)) + { + strcpy(data->uri, uri); + data->uri_type = MM_PLAYER_URI_TYPE_ES_BUFF; + ret = MM_ERROR_NONE; + } + } +#endif else if ((path = strstr(uri, "buff://"))) { data->uri_type = MM_PLAYER_URI_TYPE_BUFF; @@ -8582,7 +9229,7 @@ static int __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParse return ret; } -#if 0 + gboolean _asm_postmsg(gpointer *data) { mm_player_t* player = (mm_player_t*)data; @@ -8665,9 +9312,9 @@ __mmplayer_can_do_interrupt(mm_player_t *player) goto FAILED; } - if (/*(player->sm.exit_cb) ||*/ (player->set_mode.pcm_extraction)) + if ((player->sm.exit_cb) || (player->set_mode.pcm_extraction)) { -// debug_warning("leave from asm cb right now, %d, %d", player->sm.exit_cb, player->set_mode.pcm_extraction); + debug_warning("leave from asm cb right now, %d, %d", player->sm.exit_cb, player->set_mode.pcm_extraction); goto FAILED; } @@ -8683,27 +9330,24 @@ __mmplayer_can_do_interrupt(mm_player_t *player) } /* check other thread */ - if (player->cmd_lock) + if (!g_mutex_trylock(&player->cmd_lock)) { - if (!g_mutex_trylock(player->cmd_lock)) - { - debug_warning("locked already, cmd state : %d", player->cmd); + debug_warning("locked already, cmd state : %d", player->cmd); - /* check application command */ - if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) - { - debug_warning("playing.. should wait cmd lock then, will be interrupted"); - g_mutex_lock(player->cmd_lock); - goto INTERRUPT; - } - debug_warning("nothing to do"); - goto FAILED; - } - else + /* check application command */ + if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) { - debug_warning("can interrupt immediately"); + debug_warning("playing.. should wait cmd lock then, will be interrupted"); + g_mutex_lock(&player->cmd_lock); goto INTERRUPT; } + debug_warning("nothing to do"); + goto FAILED; + } + else + { + debug_warning("can interrupt immediately"); + goto INTERRUPT; } FAILED: @@ -8749,18 +9393,9 @@ __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_com /* video resource conflict */ if(player->pipeline->videobin) { - if (player->ini.multiple_codec_supported) - { - debug_log("video conflict but, can support multiple video"); - result = _mmplayer_pause((MMHandleType)player); - cb_res = ASM_CB_RES_PAUSE; - } - else - { - debug_log("video conflict, can't support multiple video"); - result = _mmplayer_unrealize((MMHandleType)player); - cb_res = ASM_CB_RES_STOP; - } + debug_log("video conflict but, can support multiple video"); + result = _mmplayer_pause((MMHandleType)player); + cb_res = ASM_CB_RES_PAUSE; } else if (player->pipeline->audiobin) { @@ -8895,7 +9530,7 @@ EXIT: debug_warning("dispatched"); return cb_res; } -#endif + int _mmplayer_create_player(MMHandleType handle) // @ { @@ -8976,12 +9611,13 @@ _mmplayer_create_player(MMHandleType handle) // @ debug_error("failed to register asm server\n"); return MM_ERROR_POLICY_INTERNAL; } -#endif + /* to add active device callback */ if ( MM_ERROR_NONE != mm_sound_add_device_information_changed_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, __mmplayer_sound_device_info_changed_cb_func, (void*)player)) { debug_error("failed mm_sound_add_device_information_changed_callback \n"); } +#endif if (MMPLAYER_IS_HTTP_PD(player)) { @@ -9241,8 +9877,6 @@ _mmplayer_destroy(MMHandleType handle) // @ /* release next play thread */ if ( player->next_play_thread ) { - - MMPLAYER_PLAYBACK_LOCK(player); player->next_play_thread_exit = TRUE; g_cond_signal( &player->next_play_thread_cond ); @@ -9254,7 +9888,7 @@ _mmplayer_destroy(MMHandleType handle) // @ } _mmplayer_release_video_capture(player); -#if 0 + /* flush any pending asm_cb */ if (player->sm.cb_pending) { @@ -9267,14 +9901,13 @@ _mmplayer_destroy(MMHandleType handle) // @ sched_yield(); MMPLAYER_CMD_LOCK(player); } - +#if 0 /* withdraw asm */ if ( MM_ERROR_NONE != _mmplayer_asm_unregister(&player->sm) ) { debug_error("failed to deregister asm server\n"); } #endif - #ifdef USE_LAZY_PAUSE if (player->lazy_pause_event_id) { @@ -9389,7 +10022,7 @@ _mmplayer_realize(MMHandleType hplayer) // @ } mm_attrs_get_int_by_name(attrs, "sound_application_pid", &application_pid ); -// player->sm.pid = application_pid; + player->sm.pid = application_pid; mm_attrs_get_string_by_name(attrs, "profile_uri", &uri); mm_attrs_get_data_by_name(attrs, "profile_user_param", ¶m); @@ -9410,6 +10043,19 @@ _mmplayer_realize(MMHandleType hplayer) // @ player->mem_buf.offset = 0; } +#ifdef TEST_ES // es_player_push_mode is needed? + if (player->profile.uri_type == MM_PLAYER_URI_TYPE_ES_BUFF) + { + if (strstr(uri, "es_buff://push_mode")) + { + player->es_player_push_mode = TRUE; + } + else + { + player->es_player_push_mode = FALSE; + } + } +#endif if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS) { debug_warning("mms protocol is not supported format.\n"); @@ -9499,7 +10145,6 @@ _mmplayer_unrealize(MMHandleType hplayer) /* set asm stop if success */ if (MM_ERROR_NONE == ret) { -#if 0 if (player->sm.state != ASM_STATE_STOP) { /* NOTE : Stop asm after pipeline unrealize. Keep this sequence. */ @@ -9510,7 +10155,6 @@ _mmplayer_unrealize(MMHandleType hplayer) return ret; } } -#endif } else { @@ -9697,7 +10341,7 @@ _mmplayer_get_mute(MMHandleType hplayer, int* pmute) // @ } int -_mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback 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; @@ -9705,10 +10349,9 @@ _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callba return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED ); - player->video_stream_cb = callback; - player->video_stream_cb_user_param = user_param; - player->use_video_stream = TRUE; - debug_log("Stream cb Handle value is %p : %p\n", player, player->video_stream_cb); + player->video_stream_changed_cb = callback; + player->video_stream_changed_cb_user_param = user_param; + debug_log("Handle value is %p : %p\n", player, player->video_stream_changed_cb); MMPLAYER_FLEAVE(); @@ -9716,7 +10359,7 @@ _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callba } int -_mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_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; @@ -9724,9 +10367,9 @@ _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callba return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED ); - player->audio_stream_cb = callback; - player->audio_stream_cb_user_param = user_param; - debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb); + player->audio_stream_changed_cb = callback; + player->audio_stream_changed_cb_user_param = user_param; + debug_log("Handle value is %p : %p\n", player, player->audio_stream_changed_cb); MMPLAYER_FLEAVE(); @@ -9734,19 +10377,18 @@ _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callba } int -_mmplayer_set_buffer_need_data_cb(MMHandleType hplayer, mm_player_buffer_need_data_callback callback, void *user_param) // @ +_mmplayer_set_audiostream_cb_ex(MMHandleType hplayer, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param) // @ { mm_player_t* player = (mm_player_t*) hplayer; MMPLAYER_FENTER(); - return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED ); - return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT); - - player->need_data_cb = callback; - player->buffer_cb_user_param = user_param; + return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED ); - debug_log("buffer need dataHandle value is %p : %p\n", player, player->need_data_cb); + player->audio_stream_render_cb_ex = callback; + player->audio_stream_cb_user_param = user_param; + player->audio_stream_sink_sync = sync; + debug_log("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); MMPLAYER_FLEAVE(); @@ -9754,19 +10396,36 @@ _mmplayer_set_buffer_need_data_cb(MMHandleType hplayer, mm_player_buffer_need_da } int -_mmplayer_set_buffer_enough_data_cb(MMHandleType hplayer, mm_player_buffer_enough_data_callback callback, void *user_param) // @ +_mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param) // @ { mm_player_t* player = (mm_player_t*) hplayer; MMPLAYER_FENTER(); - return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED ); - return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT); + return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED ); - player->enough_data_cb = callback; - player->buffer_cb_user_param = user_param; + player->video_stream_cb = callback; + player->video_stream_cb_user_param = user_param; + player->use_video_stream = TRUE; + debug_log("Stream cb Handle value is %p : %p\n", player, player->video_stream_cb); - debug_log("buffer enough data cb Handle value is %p : %p\n", player, player->enough_data_cb); + MMPLAYER_FLEAVE(); + + return MM_ERROR_NONE; +} + +int +_mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @ +{ + mm_player_t* player = (mm_player_t*) hplayer; + + MMPLAYER_FENTER(); + + return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED ); + + player->audio_stream_cb = callback; + player->audio_stream_cb_user_param = user_param; + debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb); MMPLAYER_FLEAVE(); @@ -9842,26 +10501,6 @@ _mmplayer_set_runtime_buffering_mode(MMHandleType hplayer, MMPlayerBufferingMode } int -_mmplayer_set_buffer_seek_data_cb(MMHandleType hplayer, mm_player_buffer_seek_data_callback callback, void *user_param) // @ -{ - mm_player_t* player = (mm_player_t*) hplayer; - - MMPLAYER_FENTER(); - - return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED ); - return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT); - - player->seek_data_cb = callback; - player->buffer_cb_user_param = user_param; - - debug_log("buffer seek data cb Handle value is %p : %p\n", player, player->seek_data_cb); - - MMPLAYER_FLEAVE(); - - return MM_ERROR_NONE; -} - -int _mmplayer_set_videoframe_render_error_cb(MMHandleType hplayer, mm_player_video_frame_render_error_callback callback, void *user_param) // @ { mm_player_t* player = (mm_player_t*) hplayer; @@ -9931,12 +10570,12 @@ _mmplayer_start(MMHandleType hplayer) // @ /* check current state */ MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START ); -// ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE); -// if ( ret != MM_ERROR_NONE ) -// { -// debug_error("failed to set asm state to PLAYING\n"); -// return ret; -// } + ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE); + if ( ret != MM_ERROR_NONE ) + { + debug_error("failed to set asm state to PLAYING\n"); + return ret; + } /* NOTE : we should check and create pipeline again if not created as we destroy * whole pipeline when stopping in streamming playback @@ -10197,17 +10836,24 @@ _mmplayer_resume(MMHandleType hplayer) return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED ); -// ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE); -// if ( ret ) -// { -// debug_error("failed to set asm state to PLAYING\n"); -// return ret; -// } + ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE); + if ( ret ) + { + debug_error("failed to set asm state to PLAYING\n"); + return ret; + } /* check current state */ MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_RESUME ); /* resume pipeline */ +#if 0 +#ifdef TEST_ES + if(MMPLAYER_IS_ES_BUFF_SRC(player)) + //async = TRUE; +#endif +#endif + ret = __gst_resume( player, async ); if ( ret != MM_ERROR_NONE ) @@ -10753,7 +11399,7 @@ __mmplayer_create_decodebin (mm_player_t* player) MMPLAYER_FENTER(); /* create decodebin */ - decodebin = gst_element_factory_make("decodebin", "decodebin"); + decodebin = gst_element_factory_make("decodebin", NULL); if (!decodebin) { @@ -10806,28 +11452,6 @@ ERROR: return decodebin; } -static void -__mmplayer_gst_id3_pad_added(GstElement *element, GstPad *pad, gpointer data) -{ - mm_player_t* player = (mm_player_t*)data; - GstCaps *caps = NULL; - gchar *caps_str = NULL; - - MMPLAYER_FENTER(); - return_if_fail (player && pad); - - caps = gst_pad_query_caps(pad, NULL); - caps_str = gst_caps_to_string(caps); - - debug_log("pad %s:%s, caps %s", GST_DEBUG_PAD_NAME(pad), caps_str); - __mmplayer_try_to_plug_decodebin(player, pad, caps); - - MMPLAYER_FREEIF( caps_str ); - gst_caps_unref(caps); - - MMPLAYER_FLEAVE(); -} - static gboolean __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps) { @@ -10861,56 +11485,6 @@ __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstC } else { - if (!mainbin[MMPLAYER_M_ID3DEMUX].gst) - { - caps_str = gst_caps_to_string(caps); - if (g_strrstr(caps_str, "application/x-id3")) - { - debug_log("create id3demux in front of queue2 \n"); - - id3demux = gst_element_factory_make ("id3demux", NULL); - if (!id3demux) - { - debug_error ("failed to create buffering id3demux element\n"); - goto ERROR; - } - - MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(id3demux), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added", - G_CALLBACK(__mmplayer_gst_id3_pad_added), player); - - if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), id3demux)) - { - debug_error("failed to add id3demux\n"); - goto ERROR; - } - - sinkpad = gst_element_get_static_pad(id3demux, "sink"); - - if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) - { - debug_error("failed to link buffering queue\n"); - goto ERROR; - } - - if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent (id3demux)) - { - debug_error("failed to sync id3demux state with parent\n"); - goto ERROR; - } - - mainbin[MMPLAYER_M_ID3DEMUX].id = MMPLAYER_M_ID3DEMUX; - mainbin[MMPLAYER_M_ID3DEMUX].gst = id3demux; - - gst_object_unref(GST_OBJECT(sinkpad)); - MMPLAYER_FREEIF( caps_str ); - - MMPLAYER_FLEAVE(); - return TRUE; - } - - MMPLAYER_FREEIF( caps_str ); - } - queue2 = gst_element_factory_make ("queue2", "queue2"); if (!queue2) { @@ -11247,6 +11821,11 @@ __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // /* check factory class for filtering */ klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(factory)); +#ifdef TEST_ES + /*parsers are not required in case of external feeder*/ + if (g_strrstr(klass, "Codec/Parser") && MMPLAYER_IS_ES_BUFF_SRC(player)) + continue; +#endif /* NOTE : msl don't need to use image plugins. * So, those plugins should be skipped for error handling. */ @@ -11589,7 +12168,7 @@ __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_c } DONE: - MMPLAYER_FLEAVE(); + MMPLAYER_FLEAVE(); return MM_ERROR_NONE; } @@ -11605,8 +12184,8 @@ __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data) return_if_fail( player ); /* remove fakesink. */ - if ( ! __mmplayer_gst_remove_fakesink( player, - &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) ) + 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 @@ -11618,7 +12197,7 @@ __mmplayer_pipeline_complete(GstElement *decodebin, gpointer data) debug_log("pipeline has completely constructed\n"); - if ( ( player->ini.async_start ) && + if (( player->ini.async_start ) && ( player->msg_posted == FALSE ) && ( player->cmd >= MMPLAYER_COMMAND_START )) { @@ -11930,20 +12509,6 @@ __mmplayer_activate_next_source(mm_player_t *player, GstState target) /* file source */ case MM_PLAYER_URI_TYPE_FILE: { - -#ifdef ENABLE_DRMSRC - - char* drmsrc = player->ini.name_of_drmsrc; - - debug_log("using [%s] for 'file://' handler.\n", drmsrc); - - element = gst_element_factory_make(drmsrc, "source"); - if ( !element ) - { - debug_error("failed to create %s\n", drmsrc); - break; - } -#else debug_log("using filesrc for 'file://' handler.\n"); element = gst_element_factory_make("filesrc", "source"); @@ -11953,7 +12518,7 @@ __mmplayer_activate_next_source(mm_player_t *player, GstState target) debug_error("failed to create filesrc\n"); break; } -#endif + g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL); /* uri+7 -> remove "file:// */ break; } @@ -12511,6 +13076,17 @@ GstCaps* caps, GstElementFactory* factory, gpointer data) goto DONE; } +#ifdef TEST_ES + if ((MMPLAYER_IS_ES_BUFF_SRC(player)) && + (g_strrstr(klass, "Codec/Demuxer") || (g_strrstr(klass, "Codec/Parser")))) + { + // TO CHECK : subtitle ÇÊ¿äÇÏ¸é ¿©±â¿¡ subparse exception Ãß°¡ + debug_log("skipping parser/demuxer [%s] in es player by not required\n", factory_name); + result = GST_AUTOPLUG_SELECT_SKIP; + goto DONE; + } +#endif + if (g_strrstr(factory_name, "mpegpsdemux")) { debug_log("skipping PS container - not support\n"); @@ -12518,9 +13094,9 @@ GstCaps* caps, GstElementFactory* factory, gpointer data) goto DONE; } - if (g_strrstr(factory_name, "mpegtsdemux") || g_strrstr(factory_name, "ssdemux")) + if (g_strrstr(factory_name, "mpegtsdemux") || g_strrstr(factory_name, SMOOTH_STREAMING_DEMUX)) { - if (g_strrstr(factory_name, "ssdemux")) + if (g_strrstr(factory_name, SMOOTH_STREAMING_DEMUX)) player->smooth_streaming = TRUE; if (g_strrstr(caps_str, "video/x-h264")) @@ -12598,10 +13174,6 @@ GstCaps* caps, GstElementFactory* factory, gpointer data) gst_structure_get_int (str, "width", &width); if (width != 0) { - #define UHD_SIZE 3840*2160 - gint height = 0; - gst_structure_get_int (str, "height", &height); - if (player->v_stream_caps) { gst_caps_unref(player->v_stream_caps); player->v_stream_caps = NULL; @@ -12610,30 +13182,8 @@ GstCaps* caps, GstElementFactory* factory, gpointer data) player->v_stream_caps = gst_caps_copy(caps); debug_log ("take caps for video state tune"); MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps); - - /* check video resolution */ - if (width*height == UHD_SIZE) { - if ((util_is_miracast_connected()) && (player->msg_posted == FALSE)) { - MMMessageParamType msg = {0,}; - /*post error*/ - msg.code = MM_ERROR_PLAYER_RESOURCE_LIMIT; - debug_error("can't play in miracast"); - MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg); - player->msg_posted = TRUE; - } - } } } - if ((g_strrstr(klass, "Codec/Parser/Audio"))) - { - if (player->smooth_streaming && (g_strrstr(caps_str, "audio/mpeg"))) - { - debug_log ("ssdemux can't use audio parse"); - result = GST_AUTOPLUG_SELECT_SKIP; - goto DONE; - } - - } if (g_strrstr(klass, "Decoder")) { @@ -12681,8 +13231,8 @@ GstCaps * caps, gpointer data) #endif static GValueArray* -__mmplayer_gst_decode_autoplug_sort(GstElement *bin, GstPad* pad, -GstCaps* caps, GValueArray* factories, gpointer data) // @ + __mmplayer_gst_decode_autoplug_sort(GstElement *bin, GstPad* pad, + GstCaps* caps, GValueArray* factories, gpointer data) // @ { #define DEFAULT_IDX 0xFFFF @@ -12710,10 +13260,9 @@ GstCaps* caps, GValueArray* factories, gpointer data) // @ MMPLAYER_FREEIF(caps_str); - for(idx=0; idx < factories->n_values;idx++) + for(idx=0; idx < factories->n_values; idx++) { - factory = g_value_get_object (g_value_array_get_nth (factories, idx)); - + factory = g_value_get_object(g_value_array_get_nth(factories, idx)); klass = gst_element_factory_get_klass(factory); factory_name = GST_OBJECT_NAME (factory); @@ -12764,22 +13313,22 @@ GstCaps* caps, GValueArray* factories, gpointer data) // @ { debug_log("[Re-arrange] factories sequence, new_pos : %d, elem_idx : %d\n", new_pos, elem_idx); - new_factories = g_value_array_copy (factories); + new_factories = g_value_array_copy(factories); // insert omx decoder in front of other decoders - factory = g_value_get_object (g_value_array_get_nth (factories, elem_idx)); + factory = g_value_get_object(g_value_array_get_nth(factories, elem_idx)); g_value_init (&val, G_TYPE_OBJECT); g_value_set_object (&val, factory); - g_value_array_insert (new_factories, new_pos, &val); + g_value_array_insert(new_factories, new_pos, &val); g_value_unset (&val); // remove duplicated omx element g_value_array_remove(new_factories, elem_idx+1); - for(idx=0; idx < new_factories->n_values;idx++) + for(idx=0; idx < new_factories->n_values; idx++) { - factory = g_value_get_object (g_value_array_get_nth (new_factories, idx)); + factory = g_value_get_object(g_value_array_get_nth(new_factories, idx)); debug_log("[Re-arranged] Klass [%s] Factory [%s]\n", gst_element_factory_get_klass(factory), GST_OBJECT_NAME (factory)); @@ -12906,12 +13455,14 @@ __mmplayer_gst_element_added (GstElement *bin, GstElement *element, gpointer dat mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type); +#if 0 // this is for 0.10 plugin with downstream modification /* playback protection if drm file */ if (player->use_video_stream || surface_type == MM_DISPLAY_SURFACE_EVAS || surface_type == MM_DISPLAY_SURFACE_X_EXT) { debug_log("playback can be protected if playready drm"); g_object_set (G_OBJECT(element), "playback-protection", TRUE, NULL); } +#endif } // to support trust-zone only @@ -12925,9 +13476,9 @@ __mmplayer_gst_element_added (GstElement *bin, GstElement *element, gpointer dat g_object_set (G_OBJECT(element), "downloading-mode", player->video_hub_download_mode, NULL); } } - else if (g_strrstr(factory_name, "legacyh264parse")) // ssdemux + else if (g_strrstr(factory_name, "legacyh264parse")) // SMOOTH_STREAMING_DEMUX { - debug_log ("[ssdemux] output-format to legacyh264parse\n"); + debug_log ("[%s] output-format to legacyh264parse\n", SMOOTH_STREAMING_DEMUX); g_object_set (G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */ } else if (g_strrstr(factory_name, "mpegaudioparse")) @@ -12939,7 +13490,7 @@ __mmplayer_gst_element_added (GstElement *bin, GstElement *element, gpointer dat g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL); } } - else if (g_strrstr(factory_name, "omx_")) + else if (g_strrstr(factory_name, "omx")) { if (g_strrstr(klass, "Codec/Decoder/Video")) { @@ -13077,7 +13628,15 @@ __mmplayer_release_misc(mm_player_t* player) player->video_stream_cb_user_param = NULL; 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->video_stream_changed_cb = NULL; + player->video_stream_changed_cb_user_param = NULL; + + player->audio_stream_changed_cb = NULL; + player->audio_stream_changed_cb_user_param = NULL; player->sent_bos = FALSE; player->playback_rate = DEFAULT_PLAYBACK_RATE; @@ -13105,7 +13664,7 @@ __mmplayer_release_misc(mm_player_t* player) player->max_audio_channels = 0; player->video_share_api_delta = 0; player->video_share_clock_delta = 0; -// player->sm.keep_last_pos = FALSE; + player->sm.keep_last_pos = FALSE; player->is_subtitle_force_drop = FALSE; player->play_subtitle = FALSE; player->use_textoverlay = FALSE; @@ -13124,6 +13683,13 @@ __mmplayer_release_misc(mm_player_t* player) player->maximum_bitrate[i] = 0; } + /* remove media stream cb (appsrc cb) */ + for (i = 0; i < MM_PLAYER_STREAM_TYPE_MAX; i++) + { + player->media_stream_buffer_status_cb[i] = NULL; + player->media_stream_seek_data_cb[i] = NULL; + } + /* free memory related to audio effect */ MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin); @@ -13371,7 +13937,7 @@ const char *padname, const GList *templlist) { gchar *name = g_strdup(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ))); - if (g_strrstr(name, "mpegtsdemux")|| g_strrstr(name, "ssdemux")) + if (g_strrstr(name, "mpegtsdemux")|| g_strrstr(name, SMOOTH_STREAMING_DEMUX)) { gchar *src_demux_caps_str = NULL; gchar *needed_parser = NULL; @@ -13385,7 +13951,7 @@ const char *padname, const GList *templlist) if (g_strrstr(src_demux_caps_str, "video/x-h264")) { - if (g_strrstr(name, "ssdemux")) + if (g_strrstr(name, SMOOTH_STREAMING_DEMUX)) { needed_parser = g_strdup("legacyh264parse"); smooth_streaming = TRUE; @@ -14989,12 +15555,12 @@ static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_f } mm_attrs_get_int_by_name(attrs, "sound_fadeup", &antishock); -/* + if (player->sm.antishock) { antishock = TRUE; player->sm.antishock = 0; } -*/ + debug_log("setting antishock as (%d)\n", antishock); if ( disable_by_force ) @@ -15162,7 +15728,15 @@ __gst_send_event_to_sink( mm_player_t* player, GstEvent* event ) { debug_log("sending event[%s] to sink element [%s] success!\n", GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) ); - break; +#ifdef TEST_ES + if( MMPLAYER_IS_ES_BUFF_SRC(player)) + { + sinks = g_list_next (sinks); + continue; + } + else +#endif + break; } debug_log("sending event[%s] to sink element [%s] failed. try with next one.\n", @@ -16232,7 +16806,7 @@ __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int } /*To get the new pad from the selector*/ - change_pad_name = g_strdup_printf ("sink%d", index); + change_pad_name = g_strdup_printf ("sink_%u", index); if (change_pad_name == NULL) { result = MM_ERROR_PLAYER_INTERNAL; @@ -16245,6 +16819,7 @@ __mmplayer_change_selector_pad (mm_player_t* player, MMPlayerTrackType type, int sinkpad = gst_element_get_static_pad (mainbin[elemId].gst, change_pad_name); if (sinkpad == NULL) { + debug_log ("sinkpad is NULL"); result = MM_ERROR_PLAYER_INTERNAL; goto EXIT; } @@ -16412,7 +16987,7 @@ __is_streaming ( mm_player_t* player ) { return_val_if_fail ( player, FALSE ); - return ( __is_rtsp_streaming ( player ) || __is_wfd_streaming ( player ) || __is_http_streaming ( player ) + return ( __is_http_progressive_down( player ) || __is_rtsp_streaming ( player ) || __is_wfd_streaming ( player ) || __is_http_streaming ( player ) || __is_http_live_streaming ( player ) || __is_dash_streaming ( player ) || __is_smooth_streaming(player) ) ? TRUE : FALSE; } @@ -16457,6 +17032,16 @@ __is_http_progressive_down(mm_player_t* player) return ((player->pd_mode) ? TRUE:FALSE); } +#ifdef TEST_ES +gboolean +__is_es_buff_src( mm_player_t* player ) +{ + return_val_if_fail ( player, FALSE ); + + return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_ES_BUFF) ? TRUE : FALSE; +} +#endif + gboolean __has_suffix(mm_player_t* player, const gchar* suffix) { @@ -16934,3 +17519,160 @@ _mmplayer_enable_media_packet_video_stream(MMHandleType hplayer, bool enable) return MM_ERROR_NONE; } + +void * _mm_player_media_packet_video_stream_internal_buffer_ref(void *buffer) +{ + void * ret = NULL + MMPLAYER_FENTER(); + /* increase ref count of gst buffer */ + if (buffer) + ret = gst_buffer_ref((GstBuffer *)buffer); + + MMPLAYER_FLEAVE(); + return ret; +} + +void _mm_player_media_packet_video_stream_internal_buffer_unref(void *buffer) +{ + MMPLAYER_FENTER(); + if (buffer) { + gst_buffer_unref((GstBuffer *)buffer); + buffer = NULL; + } + MMPLAYER_FLEAVE(); +} + +void +__gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data) +{ + mm_player_t *player = (mm_player_t*)user_data; + MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO; + + return_if_fail ( player ); + + debug_msg("app-src: feed audio\n"); + + if (player->media_stream_buffer_status_cb[type]) + { + player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param); + } +} + +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; + + return_if_fail ( player ); + + debug_msg("app-src: feed video\n"); + + if (player->media_stream_buffer_status_cb[type]) + { + player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param); + } +} + +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; + + return_if_fail ( player ); + + debug_msg("app-src: feed subtitle\n"); + + if (player->media_stream_buffer_status_cb[type]) + { + player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, player->buffer_cb_user_param); + } +} + +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; + + return_if_fail ( player ); + + debug_msg("app-src: audio buffer is full.\n"); + + if (player->media_stream_buffer_status_cb[type]) + { + player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param); + } +} + +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; + + return_if_fail ( player ); + + debug_msg("app-src: video buffer is full.\n"); + + if (player->media_stream_buffer_status_cb[type]) + { + player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, player->buffer_cb_user_param); + } +} + +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; + + return_val_if_fail( player, FALSE ); + + debug_log("app-src: seek audio data\n"); + + if (player->media_stream_seek_data_cb[type]) + { + player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param); + } + + 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; + + return_val_if_fail( player, FALSE ); + + debug_log("app-src: seek video data\n"); + + if (player->media_stream_seek_data_cb[type]) + { + player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param); + } + + 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; + + return_val_if_fail( player, FALSE ); + + debug_log("app-src: seek subtitle data\n"); + + if (player->media_stream_seek_data_cb[type]) + { + player->media_stream_seek_data_cb[type](type, position, player->buffer_cb_user_param); + } + + return TRUE; +} + diff --git a/src/mm_player_utils.c b/src/mm_player_utils.c index 1e02984..d3414a5 100755 --- a/src/mm_player_utils.c +++ b/src/mm_player_utils.c @@ -510,23 +510,6 @@ util_get_is_connected_external_display(void) return -1; } -gboolean util_is_miracast_connected(void) -{ - int is_connected = 0; - - if (vconf_get_bool(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS, &is_connected) ) { - debug_error("failed to get miracast status key"); - return FALSE; - } - - if (VCONFKEY_MIRACAST_WFD_SOURCE_ON == is_connected) { - debug_warning("miracast connected"); - return TRUE; - } - - return FALSE; -} - int util_get_pixtype(unsigned int fourcc) { int pixtype = MM_PIXEL_FORMAT_INVALID; @@ -544,6 +527,9 @@ int util_get_pixtype(unsigned int fourcc) case GST_MAKE_FOURCC ('N', 'V', '1', '2'): pixtype = MM_PIXEL_FORMAT_NV12; break; + case GST_MAKE_FOURCC ('S', 'T', '1', '2'): + pixtype = MM_PIXEL_FORMAT_NV12T; + break; case GST_MAKE_FOURCC ('S', 'N', '2', '1'): case GST_MAKE_FOURCC ('N', 'V', '2', '1'): pixtype = MM_PIXEL_FORMAT_NV21; |