* @since_tizen 3.0
*/
int __ms_demux_element_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *demux_node);
+
+/**
+ * @brief Finds type of media
+ *
+ * @since_tizen 3.0
+ */
+int __ms_find_type(media_streamer_s *ms_streamer, GstElement *src_element);
/* adaptive streaming default */
#define DEFAULT_ADAPTIVE_SOURCE "hlsdemux"
+#define DEFAULT_ADAPTIVE_SINK "hlssink"
#define MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT "video/x-raw,format=I420,width=352,height=288"
#define MEDIA_STREAMER_DEFAULT_AUDIO_RAW_FORMAT "audio/x-raw,channels=1,rate=8000,format=S16LE"
#define MEDIASTREAMER_DECODEBIN_TYPE_DECODER "video_decoder"
+typedef enum {
+ MEDIA_STREAMER_SINK_BIN_NORMAL,
+ MEDIA_STREAMER_SINK_BIN_RTP_SERVER,
+ MEDIA_STREAMER_SINK_BIN_ADAPTIVE,
+} media_streamer_sink_bin_type_e;
+
+static int __ms_adaptive_sink_prepare(media_streamer_s * ms_streamer);
+
void __ms_generate_dots(GstElement *bin, gchar *name_tag)
{
gchar *dot_name;
g_mutex_unlock(&ms_streamer->mutex_lock);
}
-static void __decodebin_nomore_pads_combine(GstPad *src_pad, media_streamer_s *ms_streamer, gboolean is_server_part)
+static void __decodebin_nomore_pads_combine(GstPad *src_pad, media_streamer_s *ms_streamer, media_streamer_sink_bin_type_e sink_bin_type)
{
GstElement *found_element = gst_pad_get_parent_element(src_pad);
const gchar *new_pad_type = __ms_get_pad_type(src_pad);
found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY);
src_pad = NULL;
}
- if (is_server_part) {
+ if (sink_bin_type == MEDIA_STREAMER_SINK_BIN_RTP_SERVER) {
found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY);
found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
+ } else if (sink_bin_type == MEDIA_STREAMER_SINK_BIN_ADAPTIVE) {
+ found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
+ found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_MUXER);
+ found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
} else {
found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER);
found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
}
} else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) {
- if (is_server_part) {
+ if (sink_bin_type == MEDIA_STREAMER_SINK_BIN_RTP_SERVER) {
found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY);
found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
+ } else if (sink_bin_type == MEDIA_STREAMER_SINK_BIN_ADAPTIVE) {
+ found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
+ found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_MUXER);
+ found_element = __ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
} else {
found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
}
g_mutex_lock(&ms_streamer->mutex_lock);
- gboolean is_server_part = FALSE;
+ media_streamer_sink_bin_type_e sink_bin_type = MEDIA_STREAMER_SINK_BIN_NORMAL;
media_streamer_node_s *rtp_node = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "rtp_container");
+ media_streamer_node_s *adaptive_sink = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "adaptive_sink");
if (rtp_node) {
char *decodebin_name = NULL;
/* FIXME: This case may be not general */
if (g_strrstr(decodebin_name, MEDIASTREAMER_DECODEBIN_TYPE_DECODER)) {
- is_server_part = FALSE;
+ sink_bin_type = MEDIA_STREAMER_SINK_BIN_NORMAL;
MS_SAFE_FREE(decodebin_name);
} else {
/* It`s server part of Streaming Scenario*/
char *param_value = NULL;
media_streamer_node_get_param(rtp_node, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT, ¶m_value);
if (param_value && (strtol(param_value, NULL, 10) > 0))
- is_server_part = TRUE;
+ sink_bin_type = MEDIA_STREAMER_SINK_BIN_RTP_SERVER;
MS_SAFE_FREE(param_value);
}
+ } else if (adaptive_sink) {
+ __ms_adaptive_sink_prepare(ms_streamer);
+ sink_bin_type = MEDIA_STREAMER_SINK_BIN_ADAPTIVE;
}
GList *iterator = NULL;
GList *list = ms_streamer->pads_types_list;
for (iterator = list; iterator; iterator = iterator->next) {
GstPad *src_pad = GST_PAD(iterator->data);
- __decodebin_nomore_pads_combine(src_pad, ms_streamer, is_server_part);
+ __decodebin_nomore_pads_combine(src_pad, ms_streamer, sink_bin_type);
}
g_mutex_unlock(&ms_streamer->mutex_lock);
gst_ghost_pad_set_target (GST_GHOST_PAD(gp), pad);
}
+static int __ms_adaptive_sink_prepare(media_streamer_s * ms_streamer)
+{
+ node_info_s nodes_info[] = {
+ {"Codec/Encoder/Video", "video_encoder"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER */
+ {"Codec/Encoder/Audio", "audio_encoder"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER */
+ {"Codec/Muxer", "mpegtsmux"}, /* MEDIA_STREAMER_NODE_TYPE_MUXER */
+ };
+
+ GstCaps *video_enc_src_caps = gst_caps_new_empty_simple("video/x-h264");
+ GstCaps *video_enc_sink_caps = gst_caps_new_empty_simple("video/x-raw");
+ node_plug_s video_enc_plug_info = {&(nodes_info[0]), video_enc_src_caps, video_enc_sink_caps, NULL};
+ GstElement *video_enc = __ms_node_element_create(&video_enc_plug_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
+
+ GstCaps *audio_enc_src_caps = gst_caps_new_simple("audio/mpeg", "mpegversion", G_TYPE_INT, 4, NULL);
+ GstCaps *audio_enc_sink_caps = gst_caps_new_empty_simple("audio/x-raw");
+ node_plug_s audio_enc_plug_info = {&(nodes_info[1]), audio_enc_src_caps, audio_enc_sink_caps, NULL};
+ GstElement *audio_enc = __ms_node_element_create(&audio_enc_plug_info, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
+
+ GstCaps *muxer_src_caps = gst_caps_new_empty_simple("video/mpegts");
+ node_plug_s mux_plug_info = {&(nodes_info[2]), muxer_src_caps, NULL, NULL};
+ GstElement *muxer = __ms_node_element_create(&mux_plug_info, MEDIA_STREAMER_NODE_TYPE_MUXER);
+
+ __ms_bin_add_element(ms_streamer->topology_bin, muxer, FALSE);
+ gst_element_sync_state_with_parent(muxer);
+ __ms_bin_add_element(ms_streamer->topology_bin, video_enc, FALSE);
+ gst_element_sync_state_with_parent(video_enc);
+ __ms_bin_add_element(ms_streamer->topology_bin, audio_enc, FALSE);
+ gst_element_sync_state_with_parent(audio_enc);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
GstElement *__ms_adaptive_element_create(void)
{
GstElement *adaptive_bin = gst_bin_new("adaptive_src");
if (!audio_encoder)
audio_encoder = __ms_element_create_by_registry(&plug_info_encoder, type);
+ if (g_strrstr(gst_element_get_name(audio_encoder), "aac")) {
+ g_object_set(audio_encoder, "compliance", -2, NULL);
+ }
+
/* Creating bin - Audio Encoder */
GstElement *audio_enc_bin = gst_bin_new("audio_encoder");
ms_retvm_if(!audio_convert || !audio_postenc_convert || !audio_filter || !audio_encoder || !audio_enc_bin, (GstElement *) NULL, "Error: creating elements for encoder bin");
return MEDIA_STREAMER_ERROR_NONE;
}
+
+static void __ms_typefound_cb(GstElement *typefind, guint probability, GstCaps *caps, gpointer data)
+{
+ GstElement *decodebin = NULL;
+ media_streamer_s *ms_streamer = (media_streamer_s *) data;
+ media_streamer_node_s *adaptive_sink = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "adaptive_sink");
+ gchar *type;
+ GstPad *src_pad = gst_element_get_static_pad(typefind, "src");
+
+ type = gst_caps_to_string (caps);
+ if (g_strrstr(type, "video/mpegts") && adaptive_sink) {
+ __ms_link_two_elements(typefind, src_pad, adaptive_sink->gst_element);
+ } else {
+ decodebin = __ms_decodebin_create(ms_streamer, NULL);
+ __ms_link_two_elements(typefind, src_pad, decodebin);
+ }
+
+ MS_SAFE_UNREF(src_pad);
+ g_free (type);
+}
+
+int __ms_find_type(media_streamer_s *ms_streamer, GstElement *src_element)
+{
+ GstElement *typefind = NULL;
+ GstPad *src_pad = gst_element_get_static_pad(src_element, "src");
+
+ typefind = gst_element_factory_make ("typefind", "typefinder");
+ __ms_bin_add_element(ms_streamer->topology_bin, typefind, TRUE);
+ gst_element_sync_state_with_parent(typefind);
+
+ g_signal_connect (typefind, "have-type", G_CALLBACK (__ms_typefound_cb), ms_streamer);
+
+ __ms_link_two_elements(src_element, src_pad, typefind);
+
+ MS_SAFE_UNREF(src_pad);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
__ms_signal_create(&node->sig_list, node->gst_element, "eos", G_CALLBACK(sink_eos), node);
}
break;
+ case MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE:
+ plugin_name = __ms_ini_get_string("node type 2:adaptive", DEFAULT_ADAPTIVE_SINK);
+ node->gst_element = __ms_element_create(plugin_name, "adaptive_sink");
+
+ /* FIXME: need to be modified about path and the name of files */
+ g_object_set(G_OBJECT(node->gst_element),
+ "max-files", 0,
+ "playlist-length", 0,
+ "playlist-location", "/tmp/playlist.m3u8",
+ "location", "/tmp/segment%05d.ts", NULL);
+ break;
default:
ms_error("Error: invalid Sink node Type [%d]", node->subtype);
break;
GstElement *found_element = NULL;
if (__ms_src_need_typefind(src_pad)) {
- found_element = __ms_decodebin_create(ms_streamer, NULL);
- __ms_link_two_elements(src_element, src_pad, found_element);
+ __ms_find_type(ms_streamer,src_element);
MS_SAFE_UNREF(src_element);
} else {
/* Check the source element`s pad type */
SCENARIO_MODE_HTTP_VIDEO_AUDIO,
SCENARIO_MODE_APPSRC_APPSINK,
SCENARIO_MODE_ADAPTIVE_SERVER,
+ SCENARIO_MODE_ADAPTIVE_SERVER_MANUAL,
SCENARIO_MODE_ADAPTIVE_CLIENT_AUTO,
SCENARIO_MODE_ADAPTIVE_CLIENT_MANUAL,
} scenario_mode_e;
media_format_h afmt_encoded = NULL;
media_format_h afmt_aenc = NULL;
media_format_h tsfmt = NULL;
+media_format_h qtfmt = NULL;
static void streamer_error_cb(media_streamer_h streamer, media_streamer_error_e error, void *user_data)
{
media_format_create(&tsfmt);
if (media_format_set_container_mime(tsfmt, MEDIA_FORMAT_CONTAINER_MPEG2TS) != MEDIA_FORMAT_ERROR_NONE)
g_print("media_format_set_container_mime failed!");
+ /* Define MP4 stream format */
+ media_format_create(&qtfmt);
+ if (media_format_set_container_mime(qtfmt, MEDIA_FORMAT_CONTAINER_MP4) != MEDIA_FORMAT_ERROR_NONE)
+ g_print("media_format_set_container_mime failed!");
}
static void set_rtp_params(media_streamer_node_h rtp_node, const char *ip, int video_port, int audio_port, gboolean port_reverse)
return rtp_bin;
}
+static void _create_adaptive_server()
+{
+ g_print("\n _create_adaptive_server \n");
+ media_streamer_node_h file_src = NULL;
+ media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_FILE, &file_src);
+ media_streamer_node_set_param(file_src, MEDIA_STREAMER_PARAM_URI, g_uri);
+ media_streamer_node_add(current_media_streamer, file_src);
+ APPEND_NODE(file_src);
+
+ /*********************** videosink *********************************** */
+ media_streamer_node_h adaptive_sink = NULL;
+ media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE, &adaptive_sink);
+ media_streamer_node_add(current_media_streamer, adaptive_sink);
+ APPEND_NODE(adaptive_sink);
+}
+
+static void _create_adaptive_server_manual()
+{
+ g_print("\n _create_adaptive_server manual \n");
+ media_streamer_node_h file_src = NULL;
+ media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_FILE, &file_src);
+ media_streamer_node_set_param(file_src, MEDIA_STREAMER_PARAM_URI, g_uri);
+ media_streamer_node_add(current_media_streamer, file_src);
+ APPEND_NODE(file_src);
+
+ media_streamer_node_h qt_demux = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_DEMUXER, qtfmt, NULL, &qt_demux);
+ media_streamer_node_add(current_media_streamer, qt_demux);
+ APPEND_NODE(qt_demux);
+
+ media_streamer_node_h video_dec = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER, vfmt_aenc, vfmt_raw, &video_dec);
+ media_streamer_node_add(current_media_streamer, video_dec);
+ APPEND_NODE(video_dec);
+
+ media_streamer_node_h audio_dec = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER, afmt_aenc, afmt_raw, &audio_dec);
+ media_streamer_node_add(current_media_streamer, audio_dec);
+ APPEND_NODE(audio_dec);
+
+ media_streamer_node_h video_enc = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER, vfmt_raw, vfmt_aenc, &video_enc);
+ media_streamer_node_add(current_media_streamer, video_enc);
+ APPEND_NODE(video_enc);
+
+ media_streamer_node_h audio_enc = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER, afmt_raw, afmt_aenc, &audio_enc);
+ media_streamer_node_add(current_media_streamer, audio_enc);
+ APPEND_NODE(audio_enc);
+
+ media_streamer_node_h ts_mux = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_MUXER, NULL, tsfmt, &ts_mux);
+ media_streamer_node_add(current_media_streamer, ts_mux);
+ APPEND_NODE(ts_mux);
+
+ media_streamer_node_h adaptive_sink = NULL;
+ media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE, &adaptive_sink);
+ media_streamer_node_add(current_media_streamer, adaptive_sink);
+ APPEND_NODE(adaptive_sink);
+
+ media_streamer_node_link(file_src, "src", qt_demux, "sink");
+ media_streamer_node_link(video_dec, "src", video_enc, "sink");
+ media_streamer_node_link(audio_dec, "src", audio_enc, "sink");
+ media_streamer_node_link(video_enc, "src", ts_mux, "sink_%d");
+ media_streamer_node_link(audio_enc, "src", ts_mux, "sink_%d");
+ media_streamer_node_link(ts_mux, "src", adaptive_sink, "sink");
+}
+
static void _create_adaptive_playing()
{
g_print("\n _create_adaptive_playing \n");
g_print("\n");
g_print("Please select Adaptive Scenario mode\n");
g_print("By default will be used [%d] mode\n", g_scenario_mode);
- g_print("1. [Server] Create Video http file segment \n");
- g_print("2. [Client] Adaptive playing auto-plug mode\n");
- g_print("3. [Client] Adaptive playing manual plug mode\n");
+ g_print("1. [Server] Create Adaptive content generation auto mode \n");
+ g_print("2. [Server] Create Adaptive content generation manual mode \n");
+ g_print("3. [Client] Adaptive playing auto-plug mode\n");
+ g_print("4. [Client] Adaptive playing manual plug mode\n");
g_print("b. back \n");
g_print("----------------------------------------------------\n");
g_print("====================================================\n");
g_print("%s:%d, %d %d %d", __FUNCTION__, __LINE__, g_menu_state, g_sub_menu_state, g_scenario_mode);
if (g_scenario_mode == SCENARIO_MODE_ADAPTIVE_SERVER)
- g_print("Adaptive server scenario");
+ _create_adaptive_server();
+ else if (g_scenario_mode == SCENARIO_MODE_ADAPTIVE_SERVER_MANUAL)
+ _create_adaptive_server_manual();
else if (g_scenario_mode == SCENARIO_MODE_ADAPTIVE_CLIENT_AUTO)
- _create_adaptive_playing(); /* temp */
+ _create_adaptive_playing();
else if (g_scenario_mode == SCENARIO_MODE_ADAPTIVE_CLIENT_MANUAL)
- _create_adaptive_playing_manual(); /* temp */
+ _create_adaptive_playing_manual();
else
g_print("Invalid adaptive menu preset was selected!");
}
g_sub_menu_state = SUBMENU_STATE_GETTING_VIDEOFILE_URI;
return;
} else if (!strncmp(cmd, "2", len)) {
- g_scenario_mode = SCENARIO_MODE_ADAPTIVE_CLIENT_AUTO;
+ g_scenario_mode = SCENARIO_MODE_ADAPTIVE_SERVER_MANUAL;
g_sub_menu_state = SUBMENU_STATE_GETTING_VIDEOFILE_URI;
return;
} else if (!strncmp(cmd, "3", len)) {
+ g_scenario_mode = SCENARIO_MODE_ADAPTIVE_CLIENT_AUTO;
+ g_sub_menu_state = SUBMENU_STATE_GETTING_VIDEOFILE_URI;
+ return;
+ } else if (!strncmp(cmd, "4", len)) {
g_scenario_mode = SCENARIO_MODE_ADAPTIVE_CLIENT_MANUAL;
g_sub_menu_state = SUBMENU_STATE_GETTING_VIDEOFILE_URI;
return;
_create_file_streaming();
_create_rtp(VIDEO_PORT, AUDIO_PORT, FALSE);
} else if (g_scenario_mode == SCENARIO_MODE_ADAPTIVE_SERVER ||
+ g_scenario_mode == SCENARIO_MODE_ADAPTIVE_SERVER_MANUAL ||
g_scenario_mode == SCENARIO_MODE_ADAPTIVE_CLIENT_AUTO ||
g_scenario_mode == SCENARIO_MODE_ADAPTIVE_CLIENT_MANUAL) {
run_adaptive_preset();