Can you try out the example program I attached? Just run it like this:

GST_DEBUG=2,*imx*:5 ./loop-videos -i 5000 -v "imxipuvideotransform ! imxeglvivsink" /home/root/B01_Baseline1.0_1280_720.MP4

This will run the mp4 video for 5 seconds and then start again. Note that you have to build it with the -std=c++11 compiler flag.


On 2015-12-21 16:18, Vikas Patil wrote:
Hi Carlos,

I have checked with following pipeline playing it via application for
5 second and restating playing (in loop), however still see the memory
failure issues. Could you please give some inputs? Also allocation and
deallocation from VPU kernel driver seems ok. Attached here the logs
with eglvivsink.

Also tried with updated version and new front end for vpu and observer
the same behavior.

i.e.
https://github.com/Freescale/gstreamer-imx/commits/master
(sha:813756a0cb70d7aa609c3d35427179e75ca10013)

https://github.com/Freescale/libimxvpuapi/commit/dba696e9775444eb1ff4ddbf2799a8a47a505527
(with memory leak fix)

gst-launch-1.0 -m filesrc
location=/home/root/B01_Baseline1.0_1280_720.MP4 ! qtdemux ! h264parse
! imxvpudec ! imxipuvideotransform ! imxeglvivsink (gets memory
allocation failure in between 6th to 9th loop)
gst-launch-1.0 filesrc
location=/home/root/B01_Baseline1.0_1280_720.MP4 ! qtdemux ! h264parse
! imxvpudec ! imxipuvideotransform ! imxg2dvideosink (gets memory
allocation failure on 62nd loop iteration)


Thanks & Regards,
Vikas

On Wed, Nov 18, 2015 at 10:28 PM, Carlos Rafael Giani
<[email protected]> wrote:
This actually looks more like a problem in imx-vpu or in the VPU driver's
DMA memory pool. DMA buffer allocation fails.
Perhaps this affects other allocators as well. Try these pipelines:

GST_DEBUG=2,*imx*:5 gst-launch-1.0 videotestsrc ! imxg2dvideosink
GST_DEBUG=2,*imx*:5 gst-launch-1.0 videotestsrc ! imxipuvideosink

If they fail, post logs.


On 11/18/2015 04:00 PM, Vikas Patil wrote:
I changed the setup now. so don't have log with latest master.
Attaching log which was missing.

Regards,
Vikash

>

#include <stdexcept>
#include <vector>
#include <string>
#include <iostream>
#include <unistd.h>
#include <gst/gst.h>
#include <glib-unix.h>


gboolean sigint(gpointer ptr)
{
	g_main_loop_quit(static_cast < GMainLoop* > (ptr));
	return TRUE;
}


class video_carousel
{
public:
	typedef std::vector < std::string > uris;

	explicit video_carousel(uris const &p_uris, guint const p_interval, std::string const &p_video_sink, std::string const &p_audio_sink, GMainLoop *p_loop)
		: m_pipeline(nullptr)
		, m_uris(p_uris)
		, m_interval(p_interval)
		, m_loop(p_loop)
		, m_timeout_source(nullptr)
	{
		GError *error;

		g_assert(!(m_uris.empty()));
	
		m_pipeline = gst_element_factory_make("playbin", "pipeline");

		g_object_set(G_OBJECT(m_pipeline), "flags", gint(0x57), nullptr);

		if (!(p_video_sink.empty()))
		{
			GstElement *sink = gst_parse_bin_from_description(p_video_sink.c_str(), TRUE, &error);
			if (sink == nullptr)
			{
				gst_object_unref(GST_OBJECT(m_pipeline));
				std::string str = std::string("Could not create video sink element: ") + error->message;
				g_clear_error(&error);
				throw std::runtime_error(str);
			}

			g_object_set(G_OBJECT(m_pipeline), "video-sink", sink, nullptr);
		}

		if (!(p_audio_sink.empty()))
		{
			GstElement *sink = gst_element_factory_make(p_audio_sink.c_str(), "audio-sink");
			if (sink == nullptr)
			{
				gst_object_unref(GST_OBJECT(m_pipeline));
				std::string str = std::string("Could not create audio sink element: ") + error->message;
				g_clear_error(&error);
				throw std::runtime_error(str);
			}

			g_object_set(G_OBJECT(m_pipeline), "audio-sink", sink, nullptr);
		}

		GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipeline));
		gst_bus_add_watch(bus, static_bus_watch, this);
		gst_object_unref(GST_OBJECT(bus));

	}

	void start()
	{
		gst_element_set_state(m_pipeline, GST_STATE_NULL);
		m_cur_uri = m_uris.begin();
		g_object_set(G_OBJECT(m_pipeline), "uri", m_cur_uri->c_str(), nullptr);
		gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
	}

	gint64 get_current_position() const
	{
		gint64 position;
		gboolean success = gst_element_query_position(GST_ELEMENT(m_pipeline), GST_FORMAT_TIME, &position);
		return success ? position : -1;
	}

	~video_carousel()
	{
		if (m_pipeline != nullptr)
		{
			stop_timeout();
			gst_element_set_state(m_pipeline, GST_STATE_NULL);
			gst_object_unref(GST_OBJECT(m_pipeline));
		}
	}


private:
	void start_timeout()
	{
		if ((m_timeout_source != nullptr) || (m_interval == 0))
			return;

		m_timeout_source = g_timeout_source_new(250);
		g_source_set_callback(m_timeout_source, static_timeout_cb, gpointer(this), nullptr);
		g_source_attach(m_timeout_source, nullptr);
	}


	void stop_timeout()
	{
		if (m_timeout_source == nullptr)
			return;

		g_source_destroy(m_timeout_source);
		g_source_unref(m_timeout_source);

		m_timeout_source = nullptr;
	}


	void advance_uri()
	{
		m_cur_uri++;
		if (m_cur_uri == m_uris.end())
			m_cur_uri = m_uris.begin();
	}


	void move_to_next_video()
	{
		gst_element_set_state(m_pipeline, GST_STATE_READY);
		advance_uri();
		std::cerr << "=========== next URI: " << m_cur_uri->c_str() << " ===========\n";
		g_object_set(G_OBJECT(m_pipeline), "uri", m_cur_uri->c_str(), nullptr);
		gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
	}


	void update_duration()
	{
		gint64 duration;
		gboolean success = gst_element_query_duration(GST_ELEMENT(m_pipeline), GST_FORMAT_TIME, &duration);
		m_duration = success ? duration : -1;
	}


	static gboolean static_timeout_cb(gpointer p_user_data)
	{
		video_carousel *self = static_cast < video_carousel* > (p_user_data);

		gint64 cur_pos = self->get_current_position();
		if (cur_pos != -1)
		{
			if ((cur_pos) >= (GST_MSECOND * self->m_interval))
			{
				GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(self->m_pipeline));
				gst_bus_post(
					bus,
					gst_message_new_application(
						GST_OBJECT(self->m_pipeline),
						gst_structure_new_empty("switch")
					)
				);
				gst_object_unref(GST_OBJECT(bus));
			}
		}

		return G_SOURCE_CONTINUE;
	}


	static gboolean static_bus_watch(GstBus *, GstMessage *p_msg, gpointer p_user_data)
	{
		video_carousel *self = static_cast < video_carousel* > (p_user_data);
	
		switch (GST_MESSAGE_TYPE(p_msg))
		{
			case GST_MESSAGE_STATE_CHANGED:
			{
				if (GST_MESSAGE_SRC(p_msg) != GST_OBJECT(self->m_pipeline))
					break;

				GstState old_gstreamer_state, new_gstreamer_state, pending_gstreamer_state;
				gst_message_parse_state_changed(
					p_msg,
					&old_gstreamer_state,
					&new_gstreamer_state,
					&pending_gstreamer_state
				);

				std::string dot_fn = std::string("pipeline") +
				                     "__old-" + gst_element_state_get_name(old_gstreamer_state) +
				                     "__new-" + gst_element_state_get_name(new_gstreamer_state) +
				                     "__pending-" + gst_element_state_get_name(pending_gstreamer_state);
				GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(self->m_pipeline), GST_DEBUG_GRAPH_SHOW_ALL, dot_fn.c_str());

				switch (new_gstreamer_state)
				{
					case GST_STATE_PAUSED:
						self->stop_timeout();
						break;
					case GST_STATE_PLAYING:
						self->start_timeout();
						break;
					default:
						break;
				}

				break;
			}

			case GST_MESSAGE_STREAM_START:
				self->m_duration = -1;
				self->update_duration();
				break;

			case GST_MESSAGE_APPLICATION:
			{
				if (gst_message_has_name(p_msg, "switch"))
					self->move_to_next_video();

				break;
			}

			case GST_MESSAGE_EOS:
			{
				self->move_to_next_video();
				break;
			}

			case GST_MESSAGE_BUFFERING:
			{
				gint percent = 0;
				gst_message_parse_buffering(p_msg, &percent);

				if (percent < 100)
					gst_element_set_state(self->m_pipeline, GST_STATE_PAUSED);
				else
					gst_element_set_state(self->m_pipeline, GST_STATE_PLAYING);

				break;
			}

			case GST_MESSAGE_LATENCY:
				gst_bin_recalculate_latency(GST_BIN(self->m_pipeline));
				break;

			case GST_MESSAGE_REQUEST_STATE:
			{
				GstState requested_state;
				gst_message_parse_request_state(p_msg, &requested_state);
				gst_element_set_state(self->m_pipeline, requested_state);
				break;
			}

			case GST_MESSAGE_DURATION:
				self->update_duration();
				break;

			case GST_MESSAGE_INFO:
			case GST_MESSAGE_WARNING:
			case GST_MESSAGE_ERROR:
			{
				GError *error = nullptr;
				gchar *debug_info = nullptr;
				gchar const *desc;

				switch (GST_MESSAGE_TYPE(p_msg))
				{
					case GST_MESSAGE_INFO:
						desc = "info";
						gst_message_parse_info(p_msg, &error, &debug_info);
						break;
					case GST_MESSAGE_WARNING:
						desc = "warning";
						gst_message_parse_warning(p_msg, &error, &debug_info);
						break;
					case GST_MESSAGE_ERROR:
					{
						desc = "error";
						gst_message_parse_error(p_msg, &error, &debug_info);
						GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(self->m_pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pipeline-error");
						g_main_loop_quit(self->m_loop);
						break;
					}
					default:
						break;
				}

				std::cerr << "GStreamer " << desc;
				if (error != nullptr)
					std::cerr << " message: " << error->message;
				else
					std::cerr << " <no message>";
				if (debug_info != nullptr)
					std::cerr << " " << debug_info;
				else
					std::cerr << " <no debug info>";
				std::cerr << std::endl;

				if (error != nullptr)
					g_error_free(error);
				if (debug_info != nullptr)
				g_free(debug_info);

				break;
			}

			default:
				break;
		}

		return TRUE;
	}


	GstElement *m_pipeline;
	uris m_uris;
	uris::iterator m_cur_uri;
	guint m_interval;
	GMainLoop *m_loop;
	gint64 m_duration;
	GSource *m_timeout_source;
};


int main(int argc, char *argv[])
{
	GError *error = nullptr;
	if (!gst_init_check(&argc, &argv, &error))
	{
		std::cerr << "Could not initialize GStreamer: " << error->message << "\n";
		return -1;
	}

	GMainLoop *loop = nullptr;

	try
	{
		guint interval = 0;
		std::string video_sink, audio_sink;

		int c;
		while ((c = getopt(argc, argv, "i:v:a:h")) != -1)
		{
			switch (c)
			{
				case 'i':
					interval = std::stoul(optarg);
					break;
				case 'v':
					video_sink = optarg;
					break;
				case 'a':
					audio_sink = optarg;
					break;
				case 'h':
					std::cerr << "Usage: " << argv[0] << " [OPTION]... [URI/FILE]...\n"
						     "Plays a list of videos specified via URI or filename in a loop,\n"
						     "optionally with a fixed interval.\n"
						     "\n"
						     "Options:\n"
						     "  -h            This help\n"
						     "  -i INTERVAL   Use fixed interval of INTERVAL milliseconds.\n"
						     "                Default value 0 plays the videos until they end.\n"
						     "  -v VIDEOSINK  Use the specified GStreamer video sink element.\n"
						     "                Default: let GStreamer pick one automatically\n"
						     "  -a AUDIOSINK  Use the specified GStreamer audio sink element.\n"
						     "                Default: let GStreamer pick one automatically\n"
						     ;
					return -1;
				default:
					break;
			}
		}

		if (optind >= argc)
		{
			std::cerr << "At least one URI/filename must be specified\n";
			return -1;
		}

		video_carousel::uris uris;
		while (optind < argc)
		{
			std::string uri = argv[optind++];
			if (!gst_uri_is_valid(uri.c_str()))
			{
				error = nullptr;
				gchar *uri_cstr = gst_filename_to_uri(uri.c_str(), &error);
				if (uri_cstr != nullptr)
				{
					uri = uri_cstr;
					g_free(uri_cstr);
				}

				if (error != nullptr)
				{
					std::string message = error->message;
					g_error_free(error);
					throw std::invalid_argument(message);
				}
			}

			uris.push_back(uri);
		}

		loop = g_main_loop_new(nullptr, TRUE);
		g_unix_signal_add(SIGINT, sigint, loop);

		video_carousel carousel(uris, interval, video_sink, audio_sink, loop);
		carousel.start();
		g_main_loop_run(loop);
	}
	catch (std::exception const &p_exc)
	{
		std::cerr << "Exception raised: " << p_exc.what() << "\n";
	}

	if (loop != nullptr)
		g_main_loop_unref(loop);

	std::cerr << "Quitting\n";

	return 0;
}


-- 
_______________________________________________
meta-freescale mailing list
[email protected]
https://lists.yoctoproject.org/listinfo/meta-freescale

Reply via email to