MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE, /**< Video capture src type, Camera feature is required */
MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_TEST, /**< Audio test src type */
MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST, /**< Video test src type */
- MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM /**< Custom src type */
+ MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM, /**< Custom src type */
+ MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE /**< Adaptive src type */
} media_streamer_node_src_type_e;
/**
* @brief Gets name of node pads.
* @since_tizen 3.0
* @remark After using the src_pad_name and sink_pad_name, it have to be free.
- * src_pad_name or sink_pad_name can be null accoring to the node type.
+ * src_pad_name or sink_pad_name can be null according to the node type.
* In case of src type node, sink_pad_name will be null.
* In case of sink type node, src_pad_name will be null.
* @param [in] node Media streamer node handle
* The externalstorage privilege(http://tizen.org/privilege/externalstorage) should be added if any video/audio files are written in the external storage devices.
* @param [in] node Media streamer node handle
* @param [in] param_name Param name of node
- * @param [in] param_value Parm value of node
+ * @param [in] param_value Param value of node
* @return @c 0 on success,
* otherwise a negative error value
* @retval #MEDIA_STREAMER_ERROR_NONE Successful
* @since_tizen 3.0
* @param [in] node Media streamer node handle
* @param [in] param_name Param name of node
- * @param [out] param_value Parm value of node
+ * @param [out] param_value Param value of node
* @return @c 0 on success,
* otherwise a negative error value
* @retval #MEDIA_STREAMER_ERROR_NONE Successful
GstElement *__ms_element_create(const char *plugin_name, const char *name);
/**
+ * @brief Creates GstBin name for adaptive streaming.
+ *
+ * @since_tizen 3.0
+ */
+GstElement *__ms_adaptive_element_create(void);
+
+/**
+ * @brief Prepares GstBin for adaptive streaming.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_adaptive_element_prepare(media_streamer_node_s *ms_node, bool auto_plug);
+
+/**
* @brief Creates GstElement from specified node_plug_s structure.
*
* @since_tizen 3.0
GstElement *__ms_audio_encoder_element_create(node_plug_s *plug_info, media_streamer_node_type_e type);
/**
+ * @brief Creates audio decoder GstElement.
+ *
+ * @since_tizen 3.0
+ */
+GstElement *__ms_audio_decoder_element_create(node_plug_s *plug_info, media_streamer_node_type_e type);
+
+/**
* @brief Creates rtp container GstElement.
*
* @since_tizen 3.0
* @since_tizen 3.0
*/
int __ms_element_pull_packet(GstElement *sink_element, media_packet_h *packet);
+
+/**
+ * @brief Prepare demuxer elemetn for playing.
+ *
+ * @since_tizen 3.0
+ */
+int __ms_demux_element_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *demux_node);
#define DEFAULT_AUDIO_RTPPAY "rtpamrpay"
#define DEFAULT_AUDIO_RTPDEPAY "rtpamrdepay"
+/* adaptive streaming default */
+#define DEFAULT_ADAPTIVE_SOURCE "hlsdemux"
+
#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 MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT "video/x-h263,width=352,height=288,framerate = 3/1"
*/
void __ms_param_value_destroy(gpointer data);
+/**
+ * @brief Check URI is valid file
+ *
+ * @since_tizen 3.0
+ */
+int __ms_node_uri_path_check(const char *file_uri);
+
#ifdef __cplusplus
}
#endif
return GST_AUTOPLUG_SELECT_SKIP;
}
}
+
}
return result;
return plugin_elem;
}
+static void __hlsdemux_pad_added_cb(GstElement *demux, GstPad *pad, gpointer data)
+{
+ GstPad *gp = GST_PAD(data);
+ gst_ghost_pad_set_target (GST_GHOST_PAD(gp), pad);
+}
+
+GstElement *__ms_adaptive_element_create(void)
+{
+ GstElement *adaptive_bin = gst_bin_new("adaptive_src");
+ ms_retvm_if(!adaptive_bin, (GstElement *) NULL, "Error: creating elements for adaptive source");
+
+ __ms_add_no_target_ghostpad(adaptive_bin, "src", GST_PAD_SRC);
+
+ /* Add adaptive node parameters as GObject data with destroy function */
+ MS_SET_INT_STATIC_STRING_PARAM(adaptive_bin, MEDIA_STREAMER_PARAM_URI, "http://localhost");
+
+ return adaptive_bin;
+}
+
+static GstElement *__ms_manifest_src_create(media_streamer_node_s *ms_node)
+{
+ char *manifest_src_name = NULL;
+ gchar *location = NULL;
+ GstElement *manifest_src = NULL;
+
+ GValue *val = (GValue *)g_object_get_data(G_OBJECT(ms_node->gst_element), MEDIA_STREAMER_PARAM_URI);
+ const char *uri = g_value_get_string(val);
+ gchar *protocol = gst_uri_is_valid(uri) ? gst_uri_get_protocol(uri) : NULL;
+
+ if (protocol && g_strrstr(protocol, "http")) {
+ manifest_src_name = __ms_ini_get_string("node type 1:http", DEFAULT_HTTP_SOURCE);
+ location = g_strdup(uri);
+ } else if (protocol && g_strrstr(protocol, "file")) {
+ manifest_src_name = __ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
+ location = gst_uri_get_location(uri);
+ } else {
+ ms_error("Unsupported URI protocol... Check URI is file path");
+ if (__ms_node_uri_path_check(uri) == MEDIA_STREAMER_ERROR_NONE) {
+ manifest_src_name = __ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
+ location = g_strdup(uri);
+ } else {
+ g_free(protocol);
+ ms_error("URI is not valid file path");
+ return NULL;
+ }
+ }
+ g_free(protocol);
+ ms_retvm_if(manifest_src_name == NULL, NULL,
+ "Error empty manifest source name for adaprive source");
+ manifest_src = gst_element_factory_make(manifest_src_name, NULL);
+ ms_retvm_if(manifest_src == NULL, NULL,
+ "Error creating manifest source for adaptive source");
+ g_object_set(manifest_src, "location", location, NULL);
+ g_free(location);
+
+ return manifest_src;
+}
+
+int __ms_adaptive_element_prepare(media_streamer_node_s *ms_node, bool auto_plug)
+{
+ char *plugin_name = NULL;
+ GstElement *manifest_src = NULL;
+ GstElement *plugin_elem = NULL;
+ gboolean res = FALSE;
+ GstPad *gp = NULL;
+
+ ms_retvm_if(ms_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ if (!auto_plug) {
+ plugin_name = __ms_ini_get_string("node type 1:adaptive", DEFAULT_ADAPTIVE_SOURCE);
+ ms_retvm_if(plugin_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error empty plugin name for adaprive source");
+ ms_info("Creating [%s] element", plugin_name);
+ plugin_elem = gst_element_factory_make(plugin_name, NULL);
+ ms_retvm_if(plugin_elem == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
+ "Error creating element [%s] for adaptive source", plugin_name);
+
+ res = gst_bin_add(GST_BIN(ms_node->gst_element), plugin_elem);
+ ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
+ "Error adding adaptive element to bin for adaptive source");
+ }
+
+ manifest_src = __ms_manifest_src_create(ms_node);
+ ms_retvm_if(manifest_src == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
+ "Error creating manifest source for adaptive source");
+
+ res = gst_bin_add(GST_BIN(ms_node->gst_element), manifest_src);
+ ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
+ "Error adding manifest source to bin for adaptive source");
+
+ if (!auto_plug) {
+ res = gst_element_link(manifest_src, plugin_elem);
+ ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
+ "Error linking manifest source and element for adaptive source");
+ }
+
+ gp = gst_element_get_static_pad(ms_node->gst_element, "src");
+ ms_retvm_if(gp == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
+ "Error getting source pad for adaptive source");
+
+ if (!auto_plug) {
+ g_signal_connect_object(plugin_elem, "pad-added",
+ G_CALLBACK(__hlsdemux_pad_added_cb), gp, 0);
+ } else {
+ GstPad *manifest_src_pad = gst_element_get_static_pad(manifest_src, "src");
+ gst_ghost_pad_set_target (GST_GHOST_PAD(gp), manifest_src_pad);
+ }
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
static gboolean __ms_feature_node_filter(GstPluginFeature *feature, gpointer data)
{
node_plug_s *plug_info = (node_plug_s*)data;
* element will be created immediately by format ot name */
if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER)
gst_element = __ms_audio_encoder_element_create(plug_info, type);
+ else if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER)
+ gst_element = __ms_audio_decoder_element_create(plug_info, type);
else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER)
gst_element = __ms_video_encoder_element_create(plug_info, type);
else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER)
return audio_enc_bin;
}
+GstElement *__ms_audio_decoder_element_create(node_plug_s *plug_info, media_streamer_node_type_e type)
+{
+ GstCaps *dec_caps = plug_info->sink_caps;
+ if (!dec_caps) {
+ dec_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT);
+ ms_debug("No Audio decoding format is set! Deafault will be: [%s]", MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT);
+ }
+
+ /* Creating Audio Decoder */
+ node_info_s *node_klass_type = __ms_node_get_klass_by_its_type(type);
+ node_plug_s decoder_info = {node_klass_type, plug_info->src_caps, dec_caps, NULL};
+ GstElement *decoder_elem = __ms_element_create_from_ini(&decoder_info, MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER);
+ if (!decoder_elem)
+ decoder_elem = __ms_element_create_by_registry(&decoder_info, MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER);
+
+ /* Creating Audio Parser */
+ node_info_s nodes_info = {MEDIA_STREAMER_PARSER_KLASS, DEFAULT_AUDIO_PARSER};
+ node_plug_s parser_info = {&nodes_info, dec_caps, dec_caps, NULL};
+ GstElement *decoder_parser = __ms_element_create_from_ini(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER);
+ if (!decoder_parser)
+ decoder_parser = __ms_element_create_by_registry(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER);
+
+ /* Creating bin - Audio Decoder */
+ gboolean gst_ret = FALSE;
+ GstElement *decoder_bin = gst_bin_new("audio_decoder");
+ GstElement *decoder_queue = __ms_element_create("queue", NULL);
+ ms_retvm_if(!decoder_elem || !decoder_queue || !decoder_bin || !decoder_parser, (GstElement *) NULL, "Error: creating elements for audio decoder bin");
+
+ /* Adding elements to bin Audio Encoder */
+ gst_bin_add_many(GST_BIN(decoder_bin), decoder_queue, decoder_elem, decoder_parser, NULL);
+ gst_ret = gst_element_link_many(decoder_queue, decoder_parser, decoder_elem, NULL);
+ if (gst_ret != TRUE) {
+ ms_error("Failed to link elements into decoder_bin");
+ MS_SAFE_UNREF(decoder_bin);
+ return NULL;
+ }
+
+ GstElement *audio_conv = __ms_element_create("audioconvert", NULL);
+ GstElement *audio_resample = __ms_element_create("audioresample", NULL);
+ ms_retvm_if(!audio_conv || !audio_resample, (GstElement *) NULL, "Error: creating elements for audio decoder bin");
+ gst_bin_add_many(GST_BIN(decoder_bin), audio_conv, audio_resample, NULL);
+ gst_ret = gst_element_link_many(decoder_elem, audio_conv, audio_resample, NULL);
+ if (gst_ret != TRUE) {
+ ms_error("Failed to link elements into decoder_bin");
+ MS_SAFE_UNREF(decoder_bin);
+ return NULL;
+ }
+
+ __ms_add_ghostpad(audio_resample, "src", decoder_bin, "src");
+ __ms_add_ghostpad(decoder_queue, "sink", decoder_bin, "sink");
+
+ return decoder_bin;
+}
+
GstElement *__ms_rtp_element_create(void)
{
GstElement *rtp_container = gst_bin_new("rtp_container");
caps_name = gst_caps_to_string(caps);
ms_info("Creating Video Caps from media format [%s]", caps_name);
+ } else if (!media_format_get_container_mime(fmt, &mime)) {
+ caps = gst_caps_new_empty_simple(__ms_convert_mime_to_string_format(mime));
+ caps_name = gst_caps_to_string(caps);
+ ms_info("Creating Video Caps from media format [%s]", caps_name);
+
} else
ms_error("Error getting media format information");
gst_sample_unref(sample);
return ret;
}
+
+static void __demux_newpad_cb(GstElement * demux, GstPad * new_pad, gpointer user_data)
+{
+ media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
+ ms_retm_if(ms_streamer == NULL, "Handle is NULL");
+
+ g_mutex_lock(&ms_streamer->mutex_lock);
+
+ g_object_ref(new_pad);
+ ms_streamer->pads_types_list = g_list_insert_sorted(ms_streamer->pads_types_list, new_pad, __pad_type_compare);
+
+ g_mutex_unlock(&ms_streamer->mutex_lock);
+}
+
+static void __demux_nomore_pads_combine(GstPad *src_pad, media_streamer_s *ms_streamer)
+{
+ GstElement *found_element = gst_pad_get_parent_element(src_pad);
+ const gchar *new_pad_type = __ms_get_pad_type(src_pad);
+ if (MS_ELEMENT_IS_VIDEO(new_pad_type)) {
+ found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER);
+ } else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) {
+ found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER);
+ } else if (MS_ELEMENT_IS_TEXT(new_pad_type)) {
+ found_element = __ms_combine_next_element(found_element, src_pad, ms_streamer->topology_bin, MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY);
+ } else {
+ ms_error("Unsupported pad type [%s]!", new_pad_type);
+ }
+ __ms_generate_dots(ms_streamer->pipeline, "after_demux_linked");
+ gst_object_unref(found_element);
+}
+
+static void __demux_nomore_pads_cb(GstElement *demux, gpointer user_data)
+{
+ media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
+ ms_retm_if(ms_streamer == NULL, "Handle is NULL");
+
+ g_mutex_lock(&ms_streamer->mutex_lock);
+
+ GList *iterator = NULL;
+ GList *list = ms_streamer->pads_types_list;
+ for (iterator = list; iterator; iterator = iterator->next) {
+ GstPad *src_pad = GST_PAD(iterator->data);
+ __demux_nomore_pads_combine(src_pad, ms_streamer);
+ }
+
+ g_mutex_unlock(&ms_streamer->mutex_lock);
+}
+
+int __ms_demux_element_prepare(media_streamer_s * ms_streamer, media_streamer_node_s *demux_node)
+{
+ ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ ms_retvm_if(!demux_node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ __ms_signal_create(&ms_streamer->autoplug_sig_list, demux_node->gst_element, "pad-added", G_CALLBACK(__demux_newpad_cb), ms_streamer);
+ __ms_signal_create(&ms_streamer->autoplug_sig_list, demux_node->gst_element, "no-more-pads", G_CALLBACK(__demux_nomore_pads_cb), ms_streamer);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
#include <media_streamer_node.h>
#include <media_streamer_util.h>
#include <media_streamer_gst.h>
-#include <fcntl.h>
-#include <sys/stat.h>
#include <cynara-client.h>
#define SMACK_LABEL_LEN 255
return ret;
}
+static gboolean __ms_adaptive_src_node_has_property(media_streamer_node_s *ms_node, const char * param_name)
+{
+ ms_retvm_if(!ms_node || !ms_node->gst_element, FALSE, "Error: empty node");
+ ms_retvm_if(!param_name, FALSE, "Error: invalid property parameter");
+
+ if (ms_node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
+ ms_node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE) {
+ GValue *val = (GValue *)g_object_get_data(G_OBJECT(ms_node->gst_element), param_name);
+ return val ? TRUE : FALSE;
+ }
+
+ return FALSE;
+}
+
+static int __ms_adaptive_src_node_get_property(media_streamer_node_s *ms_node, param_s *param, GValue *value)
+{
+ ms_retvm_if(!ms_node || !ms_node->gst_element, FALSE, "Error: empty node");
+ ms_retvm_if(ms_node->type != MEDIA_STREAMER_NODE_TYPE_SRC &&
+ ms_node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
+ ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
+
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ GValue *val = (GValue *)g_object_get_data(G_OBJECT(ms_node->gst_element), param->param_name);
+ if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_URI))
+ g_value_init(value, G_TYPE_STRING);
+ else
+ ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+
+ g_value_copy(val, value);
+ return ret;
+}
+
+static int __ms_adaptive_src_node_set_property(media_streamer_node_s *ms_node, param_s *param, const char *param_value)
+{
+ ms_retvm_if(!ms_node || !ms_node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
+ ms_retvm_if(ms_node->type != MEDIA_STREAMER_NODE_TYPE_SRC &&
+ ms_node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
+ ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
+
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+
+ GValue *val = (GValue *)g_object_get_data(G_OBJECT(ms_node->gst_element), param->param_name);
+ if (!val)
+ ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+
+ if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_URI)) {
+ g_value_unset(val);
+ g_value_init(val, G_TYPE_STRING);
+ g_value_set_string(val, param_value);
+ } else
+ ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+
+ return ret;
+}
+
int __ms_node_create(media_streamer_node_s *node, media_format_h in_fmt, media_format_h out_fmt)
{
ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
privilege = "http://tizen.org/privilege/internet";
break;
+ case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
+ privilege = "http://tizen.org/privilege/internet";
+ break;
case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
privilege = "http://tizen.org/privilege/camera";
break;
__ms_signal_create(&node->sig_list, node->gst_element, "need-data", G_CALLBACK(__ms_src_start_feed_cb), node);
__ms_signal_create(&node->sig_list, node->gst_element, "enough-data", G_CALLBACK(__ms_src_stop_feed_cb), node);
break;
+ case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
+ node->gst_element = __ms_adaptive_element_create();
+ break;
default:
ms_error("Error: invalid Src node Type [%d]", node->subtype);
break;
MS_SAFE_UNREF(src_pad);
}
+static gboolean demux_find(gpointer key, gpointer value, gpointer user_data) {
+ return g_strrstr((char *)key, "demux") != NULL;
+}
+
int __ms_pipeline_prepare(media_streamer_s *ms_streamer)
{
ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
int ret = MEDIA_STREAMER_ERROR_NONE;
media_streamer_node_s *rtp_node = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "rtp_container");
+ media_streamer_node_s *demux = (media_streamer_node_s *)g_hash_table_find(ms_streamer->nodes_table, (GHRFunc)demux_find, NULL);
+ media_streamer_node_s *adaptive_src = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "adaptive_src");
if (rtp_node) {
ret = __ms_rtp_element_prepare(rtp_node) ? MEDIA_STREAMER_ERROR_NONE : MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+ } else if (demux) {
+ ret = __ms_demux_element_prepare(ms_streamer, demux) ? MEDIA_STREAMER_ERROR_NONE : MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
} else {
GstBin *nodes_bin = GST_BIN(ms_streamer->src_bin);
if (nodes_bin->numchildren == 0) {
}
}
+ if (adaptive_src) {
+ if (GST_BIN(ms_streamer->topology_bin)->numchildren == 0) {
+ ret = __ms_adaptive_element_prepare(adaptive_src, true);
+ } else {
+ ret = __ms_adaptive_element_prepare(adaptive_src, false);
+ }
+ }
+
MS_BIN_FOREACH_ELEMENTS(ms_streamer->sink_bin, __ms_element_lock_state, ms_streamer);
MS_BIN_FOREACH_ELEMENTS(ms_streamer->src_bin, _src_node_prepare, ms_streamer);
for (it_param = 0; param_table[it_param].param_name != NULL; it_param++) {
if (!g_strcmp0(param_name, param_table[it_param].param_name)) {
param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param_table[it_param].origin_name);
- if (param_spec || __ms_rtp_node_has_property(node, param_name)) {
+ if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].origin_name) ||
+ __ms_adaptive_src_node_has_property(node, param_table[it_param].origin_name)) {
*param = &(param_table[it_param]);
ms_info("Got parameter [%s] for node [%s]", (*param)->param_name, node->name);
found_param = TRUE;
for (it_param = 0; param_table[it_param].param_name != NULL; it_param++) {
param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param_table[it_param].origin_name);
- if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].param_name)) {
+ if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].origin_name) ||
+ __ms_adaptive_src_node_has_property(node, param_table[it_param].origin_name)) {
ms_info("Got parameter [%s] for node [%s]", param_table[it_param].param_name, node->name);
*param_list = g_list_append(*param_list, &(param_table[it_param]));
}
if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP)
ret = __ms_rtp_node_get_property(node, param, &value);
+ else if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
+ node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE)
+ ret = __ms_adaptive_src_node_get_property(node, param, &value);
else {
param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param->origin_name);
if (param_spec) {
return ret;
}
-int __ms_node_uri_path_check(const char *file_uri)
-{
- struct stat stat_results = {0, };
- int file_open = 0;
-
- if (!file_uri || !strlen(file_uri))
- return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
-
- /* We can not check wheter the content is available over http or other protocol
- * Thus, here we have to check occurence of :// */
- if (g_strrstr_len(file_uri, DEFAULT_URI_SCHEME_LENGTH, "://"))
- return MEDIA_STREAMER_ERROR_NONE;
-
- file_open = open(file_uri, O_RDONLY);
- if (file_open < 0) {
- char mes_error[256];
- strerror_r(errno, mes_error, sizeof(mes_error));
- ms_error("Couldn`t open file according to [%s]. Error N [%d]", mes_error, errno);
-
- if (EACCES == errno)
- return MEDIA_STREAMER_ERROR_PERMISSION_DENIED;
-
- return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
- }
-
- if (fstat(file_open, &stat_results) < 0) {
- ms_error("Couldn`t get status of the file [%s]", file_uri);
- } else if (stat_results.st_size == 0) {
- ms_error("The size of file is 0");
- close(file_open);
- return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
- } else {
- ms_debug("Size of file [%lld] bytes", (long long)stat_results.st_size);
- }
-
- close(file_open);
-
- return MEDIA_STREAMER_ERROR_NONE;
-}
-
int __ms_node_set_param_value(media_streamer_node_s *ms_node, param_s *param, const char *param_value)
{
ms_retvm_if(!ms_node || !param || !param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
return ret;
}
+ if (ms_node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
+ ms_node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE) {
+ ret = __ms_adaptive_src_node_set_property(ms_node, param, param_value);
+ return ret;
+ }
+
if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAMERA_ID)) {
int camera_id = (int)strtol(param_value, NULL, 10);
ms_retvm_if(camera_id == -1, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid %s value", param->param_name);
#include <media_streamer.h>
#include <media_streamer_util.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
format_s format_table[] = {
/* Audio - ENCODED */
{MEDIA_FORMAT_L16, "audio/x-raw"},
{MEDIA_FORMAT_RGBA, "RGBA"},
{MEDIA_FORMAT_ARGB, "ARGB"},
{MEDIA_FORMAT_NATIVE_VIDEO, "NATIVE_VIDEO"},
+ /* Container */
+ {MEDIA_FORMAT_CONTAINER_MP4, "video/quicktime"},
+ {MEDIA_FORMAT_CONTAINER_MPEG2TS, "video/mpegts"},
{MEDIA_FORMAT_MAX, NULL}
};
}
MS_SAFE_GFREE(val);
}
+
+int __ms_node_uri_path_check(const char *file_uri)
+{
+ struct stat stat_results = {0, };
+ int file_open = 0;
+
+ if (!file_uri || !strlen(file_uri))
+ return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+
+ file_open = open(file_uri, O_RDONLY);
+ if (file_open < 0) {
+ char mes_error[256];
+ strerror_r(errno, mes_error, sizeof(mes_error));
+ ms_error("Couldn`t open file according to [%s]. Error N [%d]", mes_error, errno);
+
+ if (EACCES == errno)
+ return MEDIA_STREAMER_ERROR_PERMISSION_DENIED;
+
+ return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+ }
+
+ if (fstat(file_open, &stat_results) < 0) {
+ ms_error("Couldn`t get status of the file [%s]", file_uri);
+ } else if (stat_results.st_size == 0) {
+ ms_error("The size of file is 0");
+ close(file_open);
+ return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+ } else {
+ ms_debug("Size of file [%lld] bytes", (long long)stat_results.st_size);
+ }
+
+ close(file_open);
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
MENU_STATE_BROADCAST_MENU,
MENU_STATE_VOIP_MENU,
MENU_STATE_PLAYING_MENU,
- MENU_STATE_PRESET_MENU
+ MENU_STATE_PRESET_MENU,
+ MENU_STATE_ADAPTIVE_MENU,
} menu_state_e;
typedef enum {
SUBMENU_STATE_AUTOPLUG,
SUBMENU_STATE_SCENARIO,
SUBMENU_STATE_PLAYING_SCENARIO,
- SUBMENU_STATE_FORMAT
+ SUBMENU_STATE_FORMAT,
+ SUBMENU_STATE_ADAPTIVE_SCENARIO,
} submenu_state_e;
#define SECOND_VOIP_MASK 0x8
SCENARIO_MODE_FILE_PLAY_VIDEO_AUDIO,
SCENARIO_MODE_FILE_SUBTITLE_VIDEO_AUDIO,
SCENARIO_MODE_HTTP_VIDEO_AUDIO,
- SCENARIO_MODE_APPSRC_APPSINK
+ SCENARIO_MODE_APPSRC_APPSINK,
+ SCENARIO_MODE_ADAPTIVE_SERVER,
+ SCENARIO_MODE_ADAPTIVE_CLIENT_AUTO,
+ SCENARIO_MODE_ADAPTIVE_CLIENT_MANUAL,
} scenario_mode_e;
#define PACKAGE "media_streamer_test"
media_format_h vfmt_raw = NULL;
media_format_h vfmt_encoded = NULL;
+media_format_h vfmt_aenc = NULL;
media_format_h afmt_raw = NULL;
media_format_h afmt_encoded = NULL;
+media_format_h afmt_aenc = NULL;
+media_format_h tsfmt = NULL;
static void streamer_error_cb(media_streamer_h streamer, media_streamer_error_e error, void *user_data)
{
media_format_set_video_avg_bps(vfmt_encoded, VIDEO_AVG_BPS);
media_format_set_video_max_bps(vfmt_encoded, VIDEO_MAX_BPS);
+ /* Define encoded video format for adaptive stream */
+ media_format_create(&vfmt_aenc);
+ if (media_format_set_video_mime(vfmt_aenc, MEDIA_FORMAT_H264_SP) != MEDIA_FORMAT_ERROR_NONE)
+ g_print("media_format_set_video_mime failed!");
+
+ media_format_set_video_width(vfmt_aenc, VIDEO_WIDTH);
+ media_format_set_video_height(vfmt_aenc, VIDEO_HIGHT);
+ media_format_set_video_avg_bps(vfmt_aenc, VIDEO_AVG_BPS);
+ media_format_set_video_max_bps(vfmt_aenc, VIDEO_MAX_BPS);
+
/* Define audio raw format */
media_format_create(&afmt_raw);
if (media_format_set_audio_mime(afmt_raw, MEDIA_FORMAT_PCM) != MEDIA_FORMAT_ERROR_NONE)
media_format_set_audio_channel(afmt_encoded, AUDIO_CHANNEL);
media_format_set_audio_samplerate(afmt_encoded, AUDIO_SAMPLERATE);
+
+ /* Define audio encoded format for adaptive stream */
+ media_format_create(&afmt_aenc);
+ if (media_format_set_audio_mime(afmt_aenc, MEDIA_FORMAT_AAC) != MEDIA_FORMAT_ERROR_NONE)
+ g_print("media_format_set_audio_mime failed!");
+
+ media_format_set_audio_channel(afmt_aenc, AUDIO_CHANNEL);
+ media_format_set_audio_samplerate(afmt_aenc, AUDIO_SAMPLERATE);
+ media_format_set_audio_aac_type(afmt_aenc, TRUE);
+
+ /* Define mpegts stream format */
+ 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!");
}
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_playing()
+{
+ g_print("\n _create_adaptive_playing \n");
+ media_streamer_node_h adaptive_src = NULL;
+ media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE, &adaptive_src);
+ media_streamer_node_set_param(adaptive_src, MEDIA_STREAMER_PARAM_URI, g_uri);
+ media_streamer_node_add(current_media_streamer, adaptive_src);
+ APPEND_NODE(adaptive_src);
+
+ /*********************** videosink *********************************** */
+ media_streamer_node_h video_sink = NULL;
+ media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_OVERLAY, &video_sink);
+ media_streamer_node_add(current_media_streamer, video_sink);
+ APPEND_NODE(video_sink);
+
+ /*********************** audiosink *********************************** */
+ media_streamer_node_h audio_sink = NULL;
+ media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO, &audio_sink);
+ media_streamer_node_add(current_media_streamer, audio_sink);
+ APPEND_NODE(audio_sink);
+}
+
+static void _create_adaptive_playing_manual()
+{
+ g_print("\n _create_adaptive_playing_manual \n");
+ media_streamer_node_h adaptive_src = NULL;
+ media_streamer_node_create_src(MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE, &adaptive_src);
+ media_streamer_node_set_param(adaptive_src, MEDIA_STREAMER_PARAM_URI, g_uri);
+ media_streamer_node_add(current_media_streamer, adaptive_src);
+ APPEND_NODE(adaptive_src);
+
+ media_streamer_node_h ts_demux = NULL;
+ media_streamer_node_create(MEDIA_STREAMER_NODE_TYPE_DEMUXER, tsfmt, NULL, &ts_demux);
+ media_streamer_node_add(current_media_streamer, ts_demux);
+ APPEND_NODE(ts_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);
+
+ /*********************** videosink *********************************** */
+ media_streamer_node_h video_sink = NULL;
+ media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_OVERLAY, &video_sink);
+ media_streamer_node_add(current_media_streamer, video_sink);
+ APPEND_NODE(video_sink);
+
+ /*********************** audiosink *********************************** */
+ media_streamer_node_h audio_sink = NULL;
+ media_streamer_node_create_sink(MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO, &audio_sink);
+ media_streamer_node_add(current_media_streamer, audio_sink);
+ APPEND_NODE(audio_sink);
+
+ /********************** link nodes *********************************** */
+ media_streamer_node_link(adaptive_src, "src", ts_demux, "sink");
+ media_streamer_node_link(video_dec, "src", video_sink, "sink");
+ media_streamer_node_link(audio_dec, "src", audio_sink, "sink");
+}
+
+
/* Application source callback */
static void buffer_status_cb(media_streamer_node_h node, media_streamer_custom_buffer_status_e status, void *user_data)
{
g_print("====================================================\n");
}
+static void display_adaptive_scenario_select_menu(void)
+{
+ g_print("\n");
+ g_print("====================================================\n");
+ g_print(" media streamer test: Adaptive menu v0.3\n");
+ g_print("----------------------------------------------------\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("b. back \n");
+ g_print("----------------------------------------------------\n");
+ g_print("====================================================\n");
+}
+
static void display_preset_menu(void)
{
g_print("\n");
g_print("1. Broadcast \n");
g_print("2. VOIP \n");
g_print("3. Local Playing \n");
+ g_print("4. Adaptive \n");
g_print("q. quit \n");
g_print("----------------------------------------------------\n");
g_print("====================================================\n");
case MENU_STATE_PRESET_MENU:
display_preset_menu();
break;
+ case MENU_STATE_ADAPTIVE_MENU:
+ display_preset_menu();
+ break;
default:
g_print("*** Unknown status.\n");
break;
case SUBMENU_STATE_PLAYING_SCENARIO:
display_playing_scenario_select_menu();
break;
+ case SUBMENU_STATE_ADAPTIVE_SCENARIO:
+ display_adaptive_scenario_select_menu();
+ break;
default:
g_print("*** Unknown Submenu state.\n");
break;
g_print("Invalid playing menu preset was selected!");
}
+void run_adaptive_preset(void)
+{
+ create_formats();
+
+ 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");
+ else if (g_scenario_mode == SCENARIO_MODE_ADAPTIVE_CLIENT_AUTO)
+ _create_adaptive_playing(); /* temp */
+ else if (g_scenario_mode == SCENARIO_MODE_ADAPTIVE_CLIENT_MANUAL)
+ _create_adaptive_playing_manual(); /* temp */
+ else
+ g_print("Invalid adaptive menu preset was selected!");
+}
+
void _interpret_main_menu(char *cmd)
{
int len = strlen(cmd);
g_menu_state = MENU_STATE_VOIP_MENU;
else if (!strncmp(cmd, "3", len))
g_menu_state = MENU_STATE_PLAYING_MENU;
+ else if (!strncmp(cmd, "4", len))
+ g_menu_state = MENU_STATE_ADAPTIVE_MENU;
else if (!strncmp(cmd, "q", len))
quit();
} else {
}
}
+void _interpret_adaptive_scenario_menu(char *cmd)
+{
+ int len = strlen(cmd);
+
+ if (len == 1) {
+ if (!strncmp(cmd, "1", len)) {
+ g_scenario_mode = SCENARIO_MODE_ADAPTIVE_SERVER;
+ 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_sub_menu_state = SUBMENU_STATE_GETTING_VIDEOFILE_URI;
+ return;
+ } else if (!strncmp(cmd, "3", len)) {
+ g_scenario_mode = SCENARIO_MODE_ADAPTIVE_CLIENT_MANUAL;
+ g_sub_menu_state = SUBMENU_STATE_GETTING_VIDEOFILE_URI;
+ return;
+ }
+ }
+ g_sub_menu_state = SUBMENU_STATE_UNKNOWN;
+}
+
void _interpret_playing_scenario_menu(char *cmd)
{
int len = strlen(cmd);
return;
}
+ g_print("_interpret_getting_uri_menu %d %d %d", g_menu_state, g_sub_menu_state, g_scenario_mode);
if (g_menu_state == MENU_STATE_PLAYING_MENU) {
if (g_scenario_mode == SCENARIO_MODE_FILE_SUBTITLE_VIDEO_AUDIO) {
g_sub_menu_state = SUBMENU_STATE_GETTING_SUBFILE_URI;
create_formats();
_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_CLIENT_AUTO ||
+ g_scenario_mode == SCENARIO_MODE_ADAPTIVE_CLIENT_MANUAL) {
+ run_adaptive_preset();
} else {
run_preset();
}
/* call the run_preset function after autoplug mode was selected; */
if (g_menu_state == MENU_STATE_PLAYING_MENU)
g_sub_menu_state = SUBMENU_STATE_PLAYING_SCENARIO;
+ else if (g_menu_state == MENU_STATE_ADAPTIVE_MENU)
+ g_sub_menu_state = SUBMENU_STATE_ADAPTIVE_SCENARIO;
else
g_sub_menu_state = SUBMENU_STATE_AUTOPLUG;
} else if (!strncmp(cmd, "3", len)) {
case MENU_STATE_PRESET_MENU:
_interpret_preset_menu(cmd);
break;
+ case MENU_STATE_ADAPTIVE_MENU:
+ _interpret_preset_menu(cmd);
+ break;
default:
g_print("Invalid command\n");
return;
case SUBMENU_STATE_PLAYING_SCENARIO:
_interpret_playing_scenario_menu(cmd);
break;
+ case SUBMENU_STATE_ADAPTIVE_SCENARIO:
+ _interpret_adaptive_scenario_menu(cmd);
+ break;
default:
g_print("*** Unknown Submenu state.\n");
break;