/* * Copyright (C) 2017 Advanced Driver Information Technology GmbH, Advanced Driver Information Technology Corporation, Robert Bosch GmbH, Robert Bosch Car Multimedia GmbH, DENSO Corporation * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include #include #include #include "compositor.h" #include "transmitter_api.h" #include "waltham-renderer.h" #include "plugin.h" struct waltham_renderer { struct renderer base; }; struct GstAppContext { GMainLoop *loop; GstBus *bus; GstElement *pipeline; GstElement *appsrc; GstBuffer *gstbuffer; }; gboolean bus_message(GstBus *bus, GstMessage *message, gpointer p) { struct GstAppContext *gstctx = p; switch( GST_MESSAGE_TYPE(message)) { case GST_MESSAGE_ERROR: { GError *err; gchar *debug; gst_message_parse_error(message, &err, &debug); g_print("ERROR: %s\n", err->message); g_error_free(err); g_free(debug); g_main_loop_quit(gstctx->loop); break; } case GST_MESSAGE_STATE_CHANGED: { GstState oldstate, newstate; gst_message_parse_state_changed(message, &oldstate, &newstate, NULL); switch (newstate){ case GST_STATE_NULL: fprintf(stderr, "%s: state is NULL\n", GST_MESSAGE_SRC_NAME(message)); } break; } default: fprintf(stderr, "Unhandled message\n"); break; } } static int gst_pipe_init(struct weston_transmitter_output *output, struct gst_settings *settings) { struct GstAppContext *gstctx; gstctx=zalloc(sizeof (*gstctx)); if(!gstctx){ weston_log("Enable to allocate memory\n"); return -1; } GstCaps *caps; int ret = 0; GError *gerror = NULL; FILE * pFile; long lSize; char * pipe = NULL; size_t res; /* create gstreamer pipeline */ gst_init(NULL, NULL); gstctx->loop = g_main_loop_new(NULL, FALSE); /* read pipeline from file */ pFile = fopen ( "/etc/xdg/weston/pipeline.cfg" , "rb" ); if (pFile==NULL) { weston_log("File open error\n"); return -1; } /* obtain file size */ fseek (pFile , 0 , SEEK_END); lSize = ftell (pFile); rewind (pFile); /* allocate memory to contain the whole file: */ pipe = (char*) zalloc (sizeof(char)*lSize); if (pipe == NULL) { weston_log("Cannot allocate memory\n"); return -1; } /* copy the file into the buffer: */ res = fread (pipe,1,lSize,pFile); if (res != lSize) { weston_log("File read error\n"); return -1; } /* close file */ fclose (pFile); weston_log("Parsing GST pipeline:%s",pipe); gstctx->pipeline = gst_parse_launch(pipe, &gerror); free(pipe); if(!gstctx->pipeline) weston_log("Could not create gstreamer pipeline.\n"); gstctx->bus = gst_pipeline_get_bus((GstPipeline*)((void*)gstctx->pipeline)); gst_bus_add_watch(gstctx->bus, bus_message, &gstctx); gstctx->appsrc = (GstAppSrc*) gst_bin_get_by_name(GST_BIN(gstctx->pipeline), "src"); if (!gstctx->appsrc) return -1; caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "BGRx", "width", G_TYPE_INT, settings->width, "height", G_TYPE_INT, settings->height, NULL); if (!caps) return -1; g_object_set(G_OBJECT(gstctx->appsrc), "caps", caps, "stream-type", 0, "format", GST_FORMAT_TIME, "is-live", TRUE, NULL); gst_caps_unref(caps); gst_element_set_state((GstElement*)((void*)gstctx->pipeline), GST_STATE_PLAYING); output->renderer->ctx = gstctx; return 0; } static int recorder_enable(struct weston_transmitter_output *output) { struct gst_settings *settings; struct weston_output* base = &output->base; struct weston_compositor *compositor = base->compositor; struct weston_transmitter_remote* remote = output->remote; /* * Limitation: * Hard coding bitrate and crop params. * In case of gst-recorder case these were taken from weston.ini */ int32_t bitrate = 3000000; settings = malloc(sizeof(* settings)); settings->ip = remote->addr; settings->port = atoi(remote->port); settings->bitrate = bitrate; settings->width = output->renderer->surface_width; settings->height = output->renderer->surface_height; weston_log("gst-setting are :-->\n"); weston_log("ip = %s \n",settings->ip); weston_log("port = %d \n",settings->port); weston_log("bitrate = %d \n",settings->bitrate); weston_log("width = %d \n",settings->width); weston_log("height = %d \n",settings->height); gst_pipe_init(output, settings); return 0; err: weston_log("[gst recorder] %s:" " invalid settings\n", output->base.name); free(settings); return -1; } static void waltham_renderer_repaint_output(struct weston_transmitter_output *output) { GstBuffer *gstbuffer; GstMemory *mem; GstAllocator *allocator; int stride = output->renderer->surface_width * 4; gsize offset = 0; if(!output->renderer->recorder_enabled) { recorder_enable(&output->base); output->renderer->recorder_enabled = 1; } gstbuffer = gst_buffer_new(); allocator = gst_dmabuf_allocator_new(); mem = gst_dmabuf_allocator_alloc(allocator, output->renderer->dmafd, stride * output->renderer->surface_height); gst_buffer_append_memory(gstbuffer, mem); gst_buffer_add_video_meta_full(gstbuffer, GST_VIDEO_FRAME_FLAG_NONE, GST_VIDEO_FORMAT_BGRx, output->renderer->surface_width, output->renderer->surface_height, 1, &offset, &stride); gst_app_src_push_buffer(output->renderer->ctx->appsrc, gstbuffer); gst_object_unref(allocator); } static int waltham_renderer_display_create(struct weston_transmitter_output *output) { struct waltham_renderer *wth_renderer; wth_renderer = zalloc(sizeof *wth_renderer); if (wth_renderer == NULL) return -1; wth_renderer->base.repaint_output = waltham_renderer_repaint_output; output->renderer = &wth_renderer->base; return 0; } WL_EXPORT struct waltham_renderer_interface waltham_renderer_interface = { .display_create = waltham_renderer_display_create };