[1.1.3] Support EVAS display type 02/315802/7
authorGilbok Lee <gilbok.lee@samsung.com>
Thu, 8 Aug 2024 02:24:12 +0000 (11:24 +0900)
committerGilbok Lee <gilbok.lee@samsung.com>
Wed, 14 Aug 2024 04:28:57 +0000 (13:28 +0900)
Change-Id: I95f425daf1288d4df07092027271bbc1461b9777

include/MediaTransporterDisplay.h
include/MediaTransporterGst.h
include/MediaTransporterReceiver.h
packaging/capi-media-transporter.spec
src/MediaTransporterDisplay.cpp
src/MediaTransporterReceiver.cpp
test/mtpr_test.c

index c79b7a4e22fec3d4028c3c2cb77ed90d906f9f33..5b62473ece89b91e2f26aaf0bca8475ac4b889a2 100644 (file)
@@ -46,6 +46,10 @@ public:
        void setMode(mtprDisplayMode mode);
        mtprDisplayMode getMode() { std::lock_guard<std::mutex> mutex(_mutex); return _mode; };
 
+       GstElement* getSinkElement() { std::lock_guard<std::mutex> mutex(_mutex); return _sinkElement; }
+
+       mm_display_interface_h getMmDisplayHandle() { std::lock_guard<std::mutex> mutex(_mutex); return _mmDisplay; }
+
 private:
        void applyVisibleProperty();
        void applyModeProperty();
index 16a564f610e76fc2fc147d35ec41c66700bbe4e9..b95fd1330a170d66433b31a9ae72c0369ef34a12 100644 (file)
@@ -59,6 +59,7 @@ const std::string MEDIA_TYPE_AUDIO_ALAW   = "audio/x-alaw";
 const std::string MEDIA_TYPE_AUDIO_OPUS   = "audio/x-opus";
 const std::string MEDIA_TYPE_AUDIO_VORBIS = "audio/x-vorbis";
 const std::string MEDIA_TYPE_AUDIO_AAC    = "audio/mpeg";
+
 const std::string MEDIA_TYPE_VIDEO_RAW    = "video/x-raw";
 const std::string MEDIA_TYPE_VIDEO_VP8    = "video/x-vp8";
 const std::string MEDIA_TYPE_VIDEO_VP9    = "video/x-vp9";
@@ -68,6 +69,10 @@ const std::string MEDIA_TYPE_VIDEO_H265   = "video/x-h265";
 const std::string MEDIA_TYPE_VIDEO_JPEG   = "image/jpeg";
 const std::string MEDIA_TYPE_VIDEO_MPEG   = "video/mpeg";
 
+const std::string MEDIA_VIDEO_RAW_FORMAT_I420   = "I420";
+const std::string MEDIA_VIDEO_RAW_FORMAT_NV12   = "NV12";
+const std::string MEDIA_VIDEO_RAW_FORMAT_SN12   = "SN12";
+
 const std::string DEFAULT_DOT_FILE_NAME_PREFIX = "mtpr";
 
 struct mtprSignal {
index 46f71085fa12491303e70a1c929743ed04dc6ac4..d9573f01af515f10fc9b595f786b89047f7c025b 100644 (file)
@@ -84,8 +84,10 @@ protected:
        std::string _streamInfo;
 
 private:
+       media_format_h _evasMediaFormat { nullptr };
        static media_packet_h _makeMediaPacket(GstBuffer* buffer, GstPad* pad, media_format_h* format);
 
+       static void _evasVideoCallback(GstElement* object, GstBuffer* buffer, GstPad* pad, gpointer data);
        void _buildForwardingSink(gst::GstElements& elements, GstPad* pad, GCallback callback);
        void _buildAudioRenderingSink(gst::GstElements& elements);
        void _buildVideoRenderingSink(gst::GstElements& elements);
index 29ae15c5a6047eb9767bfd62653546be3bc5a416..75258e299f9e88358cd39964278052002df3709d 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-transporter
 Summary:    A Media Transporter library in Tizen Native API
-Version:    1.1.2
+Version:    1.1.3
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index db9da738c91ff44652700d820abce4ce795c5693..2030833a4b486989d630f8809c3940b39ddd70d1 100644 (file)
@@ -60,29 +60,38 @@ MediaTransporterDisplay::~MediaTransporterDisplay()
 GstElement* MediaTransporterDisplay::videoSink()
 {
        std::lock_guard<std::mutex> mutex(_mutex);
-
+       mm_display_type_e displayType = MM_DISPLAY_TYPE_NONE;
        try {
+               std::string videoSinkName;
+
                switch (_type) {
                case MTPR_DISPLAY_TYPE_OVERLAY:
+                       displayType = MM_DISPLAY_TYPE_OVERLAY;
+                       videoSinkName = MediaTransporterIni::get().renderingSink().videoSinkElement;
                        LOG_INFO("it's OVERLAY type");
                        break;
+               case MTPR_DISPLAY_TYPE_EVAS:
+                       LOG_INFO("it's EVAS type");
+                       displayType = MM_DISPLAY_TYPE_EVAS;
+                       videoSinkName = gst::DEFAULT_ELEMENT_FAKESINK;
+                       break;
                default:
                        LOG_ERROR_IF_REACHED("type(%d)", _type);
                        throw MediaTransporterException(MTPR_ERROR_INVALID_PARAMETER, "_display is NULL");
-                       break;
                }
 
-               std::string videoSinkName = MediaTransporterIni::get().renderingSink().videoSinkElement;
                _sinkElement = gst::_createElement(videoSinkName);
-               applyModeProperty();
-               applyVisibleProperty();
 
                int overlaySurfaceId = -1;
-               if (mm_display_interface_set_display_mainloop_sync(_mmDisplay, MM_DISPLAY_TYPE_OVERLAY, _surface, &overlaySurfaceId) != MM_ERROR_NONE)
+               if (mm_display_interface_set_display_mainloop_sync(_mmDisplay, displayType, _surface, &overlaySurfaceId) != MM_ERROR_NONE)
                        throw MediaTransporterException(MTPR_ERROR_INVALID_OPERATION, "failed to mm_display_interface_set_display_mainloop_sync()");
 
+               applyModeProperty();
+               applyVisibleProperty();
+
                LOG_INFO("surface[%p], got overlaySurfaceId[%d]", _surface, overlaySurfaceId);
-               gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(_sinkElement), overlaySurfaceId);
+               if (_type == MTPR_DISPLAY_TYPE_OVERLAY)
+                       gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(_sinkElement), overlaySurfaceId);
 
                return GST_ELEMENT(gst_object_ref(_sinkElement));
        } catch (const MediaTransporterException& e) {
@@ -90,7 +99,6 @@ GstElement* MediaTransporterDisplay::videoSink()
                        gst_object_unref(_sinkElement);
                        _sinkElement = nullptr;
                }
-
                throw;
        }
 }
@@ -117,15 +125,27 @@ void MediaTransporterDisplay::setMode(mtprDisplayMode mode)
 
 void MediaTransporterDisplay::applyVisibleProperty()
 {
-       if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(_sinkElement)), "visible"))
-               g_object_set(G_OBJECT(_sinkElement),
-                               "visible", _visible, NULL);
+       if (_type == MTPR_DISPLAY_TYPE_OVERLAY) {
+               if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(_sinkElement)), "visible"))
+                       g_object_set(G_OBJECT(_sinkElement),
+                                       "visible", _visible, NULL);
+       } else {
+               int ret = mm_display_interface_evas_set_visible(_mmDisplay, _visible);
+               if (ret != MM_ERROR_NONE)
+                       LOG_ERROR("mm_display_interface_evas_set_visible failed 0x%x", ret);
+       }
 }
 
 void MediaTransporterDisplay::applyModeProperty()
 {
-       if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(_sinkElement)), "display-geometry-method"))
-               g_object_set(G_OBJECT(_sinkElement),
-                               "display-geometry-method", (gint)_mode, /* 0: letter box, 1: origin size, 2: full screen */
-                               NULL);
+       if (_type == MTPR_DISPLAY_TYPE_OVERLAY) {
+               if (g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(_sinkElement)), "display-geometry-method"))
+                       g_object_set(G_OBJECT(_sinkElement),
+                                       "display-geometry-method", (gint)_mode, /* 0: letter box, 1: origin size, 2: full screen */
+                                       NULL);
+       } else {
+               int ret = mm_display_interface_evas_set_mode(_mmDisplay, static_cast<int>(_mode));
+               if (ret != MM_ERROR_NONE)
+                       LOG_ERROR("mm_display_interface_evas_set_mode failed 0x%x", ret);
+       }
 }
\ No newline at end of file
index 760dbc68712acb9a77dbb95c0cbe3b7dcc0173e5..0e99de341fcc01ab8dd2a6c6e9def271c08769ac 100644 (file)
@@ -26,6 +26,8 @@
 #include <sound_manager_internal.h>
 #include <pulse/proplist.h>
 #include <sstream>
+#include <gst/allocators/gsttizenmemory.h>
+#include <tbm_surface_internal.h>
 
 using namespace tizen_media_transporter;
 
@@ -69,24 +71,40 @@ void MediaTransporterReceiver::unsetAudioPacketCallback()
        _audioCallback._callback = nullptr;
 }
 
-static media_format_mimetype_e _getMediaFormatMimeType(const std::string& mime)
+static media_format_mimetype_e _getMediaFormatMimeType(const std::string& mime, GstStructure* structure = nullptr)
 {
        if (mime.find(gst::MEDIA_TYPE_AUDIO_AAC) != std::string::npos)
                return MEDIA_FORMAT_AAC;
-       else if (mime.find(gst::MEDIA_TYPE_AUDIO_OPUS) != std::string::npos)
+       if (mime.find(gst::MEDIA_TYPE_AUDIO_OPUS) != std::string::npos)
                return MEDIA_FORMAT_OPUS;
-       else if (mime.find(gst::MEDIA_TYPE_AUDIO_VORBIS) != std::string::npos)
+       if (mime.find(gst::MEDIA_TYPE_AUDIO_VORBIS) != std::string::npos)
                return MEDIA_FORMAT_VORBIS;
-       else if (mime.find(gst::MEDIA_TYPE_VIDEO_MPEG) != std::string::npos)
+       if (mime.find(gst::MEDIA_TYPE_VIDEO_MPEG) != std::string::npos)
                return MEDIA_FORMAT_MPEG4_SP; /* FIXME: need to check format , MEDIA_FORMAT_MPEG4_ASP */
-       else if (mime.find(gst::MEDIA_TYPE_VIDEO_VP8) != std::string::npos)
+       if (mime.find(gst::MEDIA_TYPE_VIDEO_VP8) != std::string::npos)
                return MEDIA_FORMAT_VP8;
-       else if (mime.find(gst::MEDIA_TYPE_VIDEO_VP9) != std::string::npos)
+       if (mime.find(gst::MEDIA_TYPE_VIDEO_VP9) != std::string::npos)
                return MEDIA_FORMAT_VP9;
-       else if (mime.find(gst::MEDIA_TYPE_VIDEO_H264) != std::string::npos)
+       if (mime.find(gst::MEDIA_TYPE_VIDEO_H264) != std::string::npos)
                return MEDIA_FORMAT_H264_HP;
-       else if (mime.find(gst::MEDIA_TYPE_VIDEO_JPEG) != std::string::npos)
+       if (mime.find(gst::MEDIA_TYPE_VIDEO_JPEG) != std::string::npos)
                return MEDIA_FORMAT_MJPEG;
+       if ((mime.find(gst::MEDIA_TYPE_VIDEO_RAW) != std::string::npos) && (structure != nullptr)) {
+               std::string format = gst_structure_get_string(structure, "format");
+               if (format.empty()) {
+                       LOG_ERROR("format is empty");
+                       return MEDIA_FORMAT_MAX;
+               }
+
+               if (format.find(gst::MEDIA_VIDEO_RAW_FORMAT_I420) != std::string::npos)
+                       return MEDIA_FORMAT_I420;
+               if (format.find(gst::MEDIA_VIDEO_RAW_FORMAT_NV12) != std::string::npos
+                               || format.find(gst::MEDIA_VIDEO_RAW_FORMAT_SN12) != std::string::npos)
+                       return MEDIA_FORMAT_NV12;
+
+               LOG_ERROR("not supported format[%s]", format.c_str());
+               return MEDIA_FORMAT_MAX;
+       }
 
        LOG_ERROR("not supported mime[%s]", mime.c_str());
        return MEDIA_FORMAT_MAX;
@@ -106,7 +124,7 @@ static media_format_h _makeMediaFormat(GstPad* pad)
        GstStructure* structure = gst_caps_get_structure(caps, 0);
        std::string mime = gst_structure_get_name(structure);
 
-       media_format_mimetype_e mimetype = _getMediaFormatMimeType(mime);
+       media_format_mimetype_e mimetype = _getMediaFormatMimeType(mime, structure);
        LOG_INFO("media format mimetype[0x%x]", mimetype);
 
        if (mimetype & MEDIA_FORMAT_VIDEO) {
@@ -503,7 +521,8 @@ void MediaTransporterReceiver::_buildVideoRenderingSink(gst::GstElements& elemen
 
        try {
                // display RM acquire
-               _resourceManager->acquire(RES_TYPE_VIDEO_OVERLAY);
+               if (_display->getType() == MTPR_DISPLAY_TYPE_OVERLAY)
+                       _resourceManager->acquire(RES_TYPE_VIDEO_OVERLAY);
                converter = gst::_createElement(gst::DEFAULT_ELEMENT_VIDEOCONVERT);
                elements.push_back(converter);
                sink = _display->videoSink();
@@ -521,6 +540,216 @@ void MediaTransporterReceiver::_buildVideoRenderingSink(gst::GstElements& elemen
        }
 }
 
+static uint32_t __convertToTbmFormat(const gchar *data)
+{
+       uint32_t fourcc = GST_STR_FOURCC(data);
+
+       switch (fourcc) {
+       case GST_STR_FOURCC("S420"):
+       case GST_STR_FOURCC("I420"):
+               return TBM_FORMAT_YUV420;
+       case GST_STR_FOURCC("BGRA"):
+               return TBM_FORMAT_BGRA8888;
+       case GST_STR_FOURCC("BGRx"):
+               return TBM_FORMAT_BGRX8888;
+       case GST_STR_FOURCC("SR32"):
+               return TBM_FORMAT_ARGB8888;
+       default:
+               LOG_ERROR("Not supported format %" GST_FOURCC_FORMAT,
+                               GST_FOURCC_ARGS(fourcc));
+               return 0;
+       }
+}
+
+constexpr int kMaxPlane = 4;
+static tbm_surface_h __createTbmSurface(GstMemory* mem, GstCaps* caps)
+{
+       int ret = 0;
+       bool is_mapped = false;
+       int width = 0;
+       int height = 0;
+       uint32_t bo_format = 0;
+       const gchar* string_format = nullptr;
+       GstStructure* structure = nullptr;
+       GstMapInfo mapinfo = GST_MAP_INFO_INIT;
+       tbm_surface_h tbmSurf = nullptr;
+       tbm_surface_info_s info;
+       tbm_bo bo = nullptr;
+       uint32_t bo_size = 0;
+       tbm_bo_handle thandle = {nullptr, };
+
+       int plane_stride[kMaxPlane] = { 0, };
+       int plane_elevation[kMaxPlane] = { 0, };
+       int src_stride[kMaxPlane] = { 0, };
+       int src_offset[kMaxPlane] = { 0, };
+       int dest_offset[kMaxPlane] = { 0, };
+       int i = 0;
+       int j = 0;
+       int k = 0;
+       unsigned char *src = NULL;
+       unsigned char *dest = NULL;
+
+       if (!caps) {
+               LOG_ERROR("invalid caps");
+               return nullptr;
+       }
+
+       is_mapped = gst_memory_map(mem, &mapinfo, GST_MAP_READ);
+       if (!is_mapped) {
+               LOG_ERROR("gst_memory_map fail");
+               return nullptr;
+       }
+
+       if (!mapinfo.data) {
+               LOG_ERROR("data pointer is wrong");
+               goto ERROR_CREATE;
+       }
+
+       structure = gst_caps_get_structure(caps, 0);
+       gst_structure_get_int(structure, "width", &width);
+       gst_structure_get_int(structure, "height", &height);
+       string_format = gst_structure_get_string(structure, "format");
+
+       bo_format = __convertToTbmFormat(string_format);
+       if (!bo_format) {
+               LOG_ERROR("not supported video format (%s)", string_format);
+               goto ERROR_CREATE;
+       }
+
+       tbmSurf = tbm_surface_create(width, height, bo_format);
+       if (!tbmSurf) {
+               LOG_ERROR("fail to create tbm surface");
+               goto ERROR_CREATE;
+       }
+
+       ret = tbm_surface_get_info(tbmSurf, &info);
+       if (ret != TBM_SURFACE_ERROR_NONE) {
+               LOG_ERROR("fail to get tbm surface info");
+               goto ERROR_CREATE;
+       }
+
+       bo = tbm_surface_internal_get_bo(tbmSurf, 0);
+       bo_size = tbm_bo_size(bo);
+       thandle = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
+       if (!thandle.ptr) {
+               LOG_ERROR("thandle pointer is wrong");
+               goto ERROR_CREATE;
+       }
+
+       LOG_DEBUG("width %d, height %d, bo_size %d", width, height, bo_size);
+
+       switch (bo_format) {
+       case TBM_FORMAT_YUV420:
+               plane_stride[0] = info.planes[0].stride;
+               plane_elevation[0] = info.planes[0].size / info.planes[0].stride;
+               plane_stride[1] = info.planes[1].stride;
+               plane_elevation[1] = info.planes[1].size / info.planes[1].stride;
+               plane_stride[2] = info.planes[2].stride;
+               plane_elevation[2] = info.planes[2].size / info.planes[2].stride;
+
+               src_stride[0] = GST_ROUND_UP_4(width);
+               src_stride[1] = src_stride[2] = GST_ROUND_UP_4(width >> 1);
+               src_offset[1] = src_stride[0] * GST_ROUND_UP_2(height);
+               src_offset[2] = src_offset[1] + (src_stride[1] * (GST_ROUND_UP_2(height) >> 1));
+
+               dest_offset[0] = 0;
+               dest_offset[1] = plane_stride[0] * plane_elevation[0];
+               dest_offset[2] = dest_offset[1] + plane_stride[1] * plane_elevation[1];
+
+               for (i = 0; i < 3; i++) {
+                       src = mapinfo.data + src_offset[i];
+                       dest = static_cast<unsigned char*>(thandle.ptr) + dest_offset[i];
+
+                       if (i > 0)
+                               k = 1;
+
+                       for (j = 0; j < height >> k; j++) {
+                               memcpy(dest, src, width>>k);
+                               src += src_stride[i];
+                               dest += plane_stride[i];
+                       }
+               }
+               break;
+       case TBM_FORMAT_BGRA8888:
+       case TBM_FORMAT_BGRX8888:
+       case TBM_FORMAT_ARGB8888:
+               memcpy(thandle.ptr, mapinfo.data, bo_size);
+               break;
+       default:
+               LOG_ERROR("not supported format");
+               goto ERROR_CREATE;
+       }
+
+       tbm_bo_unmap(bo);
+       gst_memory_unmap(mem, &mapinfo);
+
+       return tbmSurf;
+
+ERROR_CREATE:
+       if (bo)
+               tbm_bo_unmap(bo);
+
+       if (tbmSurf)
+               tbm_surface_destroy(tbmSurf);
+
+       gst_memory_unmap(mem, &mapinfo);
+       return nullptr;
+}
+
+static void __mediaPacketDisposeCallBack(media_packet_h pkt, void *user_data)
+{
+       int ret = 0;
+       tbm_surface_h tsurf = NULL;
+       GstBuffer* buffer = static_cast<GstBuffer*>(user_data);
+
+       if (!pkt || !buffer) {
+               LOG_ERROR("pkt or buffer is nullptr");
+               return;
+       }
+
+       ret = media_packet_get_tbm_surface(pkt, &tsurf);
+       if ((ret == MEDIA_PACKET_ERROR_NONE) && tsurf)
+               tbm_surface_destroy(tsurf);
+
+       gst_buffer_unref(buffer);
+}
+
+void MediaTransporterReceiver::_evasVideoCallback(GstElement* object, GstBuffer* buffer, GstPad* pad, gpointer data)
+{
+       MediaTransporterReceiver* mtprReceiver = static_cast<MediaTransporterReceiver*>(data);
+       if (mtprReceiver->_evasMediaFormat == nullptr) {
+               mtprReceiver->_evasMediaFormat = _makeMediaFormat(pad);
+               if (mtprReceiver->_evasMediaFormat == nullptr) {
+                       LOG_ERROR("Failed to make evas media format");
+                       return;
+               }
+       }
+
+       GstMemory* mem = gst_buffer_peek_memory(buffer, 0);
+       RET_IF(!mem, "Failed to get memory from buffer");
+       tbm_surface_h tbmSurf = nullptr;
+       if (gst_is_tizen_memory(mem)) {
+               tbmSurf = static_cast<tbm_surface_h>(gst_tizen_memory_get_surface(mem));
+               tbm_surface_internal_ref(tbmSurf);
+       } else {
+               GstCaps* caps = gst_pad_has_current_caps(pad) ? gst_pad_get_current_caps(pad) : gst_pad_query_caps(pad, NULL);
+               tbmSurf = __createTbmSurface(mem, caps);
+               gst_caps_unref(caps);
+       }
+
+       RET_IF(!tbmSurf, "tbm surface is nullptr");
+
+       media_packet_h packet = nullptr;
+       if (media_packet_new_from_tbm_surface(mtprReceiver->_evasMediaFormat, tbmSurf, __mediaPacketDisposeCallBack, buffer, &packet) != MEDIA_PACKET_ERROR_NONE) {
+               LOG_ERROR("media_packet_new_from_tbm_surface() failed");
+               tbm_surface_destroy(tbmSurf);
+               return;
+       }
+
+       gst_buffer_ref(buffer);
+       mm_display_interface_evas_render(mtprReceiver->_display->getMmDisplayHandle(), packet);
+}
+
 int MediaTransporterReceiver::_buildRenderingElements(GstElement* demux, GstPad* pad, bool isAudio)
 {
        gst::GstElements elements;
@@ -568,6 +797,15 @@ int MediaTransporterReceiver::_buildRenderingElements(GstElement* demux, GstPad*
        else
                _buildVideoRenderingSink(elements);
 
+       if (_display->getType() == MTPR_DISPLAY_TYPE_EVAS) {
+               // g_object_set(_display->getSinkElement(), "sync", TRUE, "signal-handoffs", TRUE, NULL);
+               g_object_set(_display->getSinkElement(), "signal-handoffs", TRUE, NULL);
+               gst::_connectAndAppendSignal(&_gst.signals, G_OBJECT(_display->getSinkElement()),
+                       "preroll-handoff", G_CALLBACK(_evasVideoCallback), this);
+               gst::_connectAndAppendSignal(&_gst.signals, G_OBJECT(_display->getSinkElement()),
+                       "handoff", G_CALLBACK(_evasVideoCallback), this);
+       }
+
        std::string binName = isAudio ? "renderingAudioBin" : "renderingVideoBin";
 
        GstBin* bin = GST_BIN(gst_bin_new(binName.c_str()));
index d941b431241aa93f2e1cf07b277f446d1dae68fa..9424f2459eb19aff5681676205d78f293aa65f33 100644 (file)
@@ -424,13 +424,15 @@ static void _mtpr_test_stop()
 
 static void _mtpr_test_set_display(unsigned int type)
 {
+       int ret = 0;
 #ifdef TIZEN_FEATURE_ESPP
        if (g_use_espp) {
                _espp_set_display(type, g_win_id);
                return;
        }
 #endif
-       int ret = mtpr_set_display(g_mtpr, (mtpr_display_type_e)type, g_win_id);
+       ret = mtpr_set_display(g_mtpr, (mtpr_display_type_e)type, type == 0 ? g_win_id : g_eo);
+
        if (ret != MTPR_ERROR_NONE)
                g_print("             => failed to mtpr_set_display() returned [0x%x]\n", ret);
        else
@@ -1227,7 +1229,7 @@ static void displaymenu()
                display_sub_basic();
        } else if (g_menu_state == CURRENT_STATUS_CONNECTION_TYPE) {
                g_print("*** Input connection type.\n\
-    (0:RIST_SENDER, 1:RIST_RECEIVER, 2:SRT_SENDER, 3:SRT_RECEIVER, 4:RTSP_SENDER, 5:RTS_RECEIVER, 6:RTSP_SENDER_TO_SERVER)\n");
+    (0:RIST_SENDER, 1:RIST_RECEIVER, 2:SRT_SENDER, 3:SRT_RECEIVER, 4:RTSP_SENDER, 5:RTSP_RECEIVER, 6:RTSP_SENDER_TO_SERVER)\n");
        } else if (g_menu_state == CURRENT_STATUS_SENDER_ADDRESS) {
                g_print("*** Input sender address:\n");
        } else if (g_menu_state == CURRENT_STATUS_RECEIVER_ADDRESS) {
@@ -1527,4 +1529,3 @@ int main(int argc, char *argv[])
 
        return appcore_efl_main(PACKAGE, &argc, &argv, &ops);
 }
-