📄 playback.c
字号:
//////////////////////////////////////////////////////////////////////descriptor: this is streaming media playback function, which is support audio // and video process by gstreamer.////////////////////////////////////////////////////////////////////#include "playback.h"GstAudioVideo media;//////////////////////////////////////////////////////////////////////////////////////for gstreamer playback./////////////////////////////////////////////////////descriptor: //para://return value://////////////////////////////////////////////////void gst_local_init(){ printf(" ++++ %s ++++\n", __func__); media.stream_length = 0; media.play_state = GST_PLAY; media.g_pipe = NULL; media.speakersetup = AUDIO_SOUND_STEREO; media.lock = g_mutex_new(); }/////////////////////////////////////////////////////descriptor: search colorbalance element.//para: fold function to pick the best colorspace element //return value://////////////////////////////////////////////////static gboolean find_colorbalance_element (GstElement *element, GValue * ret, GstElement **cb){ printf(" ++++ %s ++++\n", __func__); GstColorBalanceClass *cb_class; g_print ("Checking element %s ...", GST_OBJECT_NAME (element)); if (!GST_IS_COLOR_BALANCE (element)) return TRUE; g_print ("Element %s is a color balance", GST_OBJECT_NAME (element)); cb_class = GST_COLOR_BALANCE_GET_CLASS (element); if (GST_COLOR_BALANCE_TYPE (cb_class) == GST_COLOR_BALANCE_HARDWARE) { gst_object_replace ((GstObject **) cb, (GstObject *) element); /* shortcuts the fold */ return FALSE; } else if (*cb == NULL) { gst_object_replace ((GstObject **) cb, (GstObject *) element); return TRUE; } else { return TRUE; }}/////////////////////////////////////////////////////descriptor: update video interface.//para: //return value://////////////////////////////////////////////////static void update_interface(){ GstColorBalance *old_balance = media.balance; GstXOverlay *old_xoverlay = media.xoverlay; GstElement *video_sink = NULL; GstElement *element = NULL; GstIteratorResult ires; GstIterator *iter; guint i; //g_object_get (media.videosink, "sink", &video_sink, NULL); //g_assert (video_sink != NULL); /* We try to get an element supporting XOverlay interface */ if (GST_IS_BIN (media.videosink)) { GST_DEBUG ("Retrieving xoverlay from bin ..."); element = gst_bin_get_by_interface (GST_BIN (media.videosink), GST_TYPE_X_OVERLAY); } else { element = media.videosink; } if (GST_IS_X_OVERLAY (element)) { g_print ("Found xoverlay: %s\n", GST_OBJECT_NAME (element)); media.xoverlay = GST_X_OVERLAY (element); } else { g_print ("No xoverlay found\n"); media.xoverlay = NULL; } /* Find best color balance element (using custom iterator so * we can prefer hardware implementations to software ones) */ /* FIXME: this doesn't work reliably yet, most of the time * the fold function doesn't even get called, while sometimes * it does ... */ iter = gst_bin_iterate_all_by_interface (GST_BIN (media.g_pipe), GST_TYPE_COLOR_BALANCE); /* naively assume no resync */ element = NULL; ires = gst_iterator_fold (iter, (GstIteratorFoldFunction) find_colorbalance_element, NULL, &element); gst_iterator_free (iter); if (element) { media.balance = GST_COLOR_BALANCE (element); g_print ("Best colorbalance found: %s", GST_OBJECT_NAME (media.balance)); } else if (GST_IS_COLOR_BALANCE (media.xoverlay)) { media.balance = GST_COLOR_BALANCE (media.xoverlay); gst_object_ref (media.balance); g_print ("Colorbalance backup found: %s", GST_OBJECT_NAME (media.balance)); } else { g_print ("No colorbalance found\n"); media.balance = NULL; } /* Setup brightness and contrast */ //for (i = 0; i < G_N_ELEMENTS (video_props_str); i++) { // confvalue = gconf_client_get_without_default (bvw->priv->gc, // video_props_str[i], NULL); // if (confvalue != NULL) { // bacon_video_widget_set_video_property (bvw, i, // gconf_value_get_int (confvalue)); // gconf_value_free (confvalue); // } //} if (old_xoverlay) gst_object_unref (GST_OBJECT (old_xoverlay)); if (old_balance) gst_object_unref (GST_OBJECT (old_balance)); gst_object_unref (video_sink);}//#endif/////////////////////////////////////////////////////descriptor: create video pad//para://return value://////////////////////////////////////////////////static voidgot_new_video_sink_bin_element (GstBin *video_sink, GstElement *element, gpointer data){ printf("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\n"); //BaconVideoWidget *bvw = BACON_VIDEO_WIDGET (data); g_mutex_lock (media.lock); update_interface (); g_mutex_unlock (media.lock);}/////////////////////////////////////////////////////descriptor: create video pad//para://return value://////////////////////////////////////////////////static GstElement *video_create(){ GstElement *element; GstElement *conv; GstElement *sink; GstPad *pad; printf(" ++++ %s ++++\n", __func__); element = gst_bin_new ("vbin"); conv = gst_element_factory_make ("ffmpegcolorspace", "conv"); //sink = gst_element_factory_make ("xvimagesink", "sink"); sink = gst_element_factory_make("autovideosink", "sink"); media.videosink = sink; gst_bin_add (GST_BIN (element), conv); gst_bin_add (GST_BIN (element), sink); gst_element_link_pads (conv, "src", sink, "sink"); pad = gst_element_get_pad (conv, "sink"); gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad)); if (GST_IS_BIN (sink)) { g_signal_connect (sink, "element-added", G_CALLBACK (got_new_video_sink_bin_element), NULL); } gst_object_unref (pad); return element;}/////////////////////////////////////////////////////descriptor: create audio pad.//para://return value://////////////////////////////////////////////////static GstElement *audio_create(){ GstElement *element; GstElement *conv; GstElement *sink; GstPad *pad; printf(" ++++ %s ++++\n", __func__); element = gst_bin_new ("abin"); conv = gst_element_factory_make ("audioconvert", "conv"); sink = gst_element_factory_make ("alsasink", "sink"); gst_bin_add (GST_BIN (element), conv); gst_bin_add (GST_BIN (element), sink); gst_element_link_pads (conv, "src", sink, "sink"); pad = gst_element_get_pad (conv, "sink"); gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad)); gst_object_unref (pad); return element;}/////////////////////////////////////////////////////descriptor: make pad for audio and video.//para://return value://////////////////////////////////////////////////static void create_pad (GstElement * decodebin, GstPad * pad, gboolean last, gpointer data){ GstCaps *caps; GstStructure *str; GstPad *sinkpad; GstElement *sink; GstElement *pipeline; const gchar *name; GstStateChangeReturn ret; GstPadLinkReturn lret; printf(" ++++ %s ++++\n", __func__); /* check media type */ caps = gst_pad_get_caps (pad); str = gst_caps_get_structure (caps, 0); name = gst_structure_get_name (str); g_print ("name: %s\n", name); if (g_strrstr (name, "audio")) { sink = audio_create (); } else if (g_strrstr (name, "video")) { sink = video_create(); } else { sink = NULL; } gst_caps_unref (caps); if (sink) { pipeline = GST_ELEMENT_CAST (data); /* add new sink to the pipeline */ gst_bin_add (GST_BIN_CAST (pipeline), sink); /* set the new sink tp PAUSED as well */ ret = gst_element_set_state (sink, GST_STATE_PAUSED); if (ret == GST_STATE_CHANGE_FAILURE) goto gsterror; /* get the ghostpad of the sink bin */ sinkpad = gst_element_get_pad (sink, "sink"); /* link'n'play */ lret = gst_pad_link (pad, sinkpad); if (lret != GST_PAD_LINK_OK) goto linkfail; gst_object_unref (sinkpad); } return; /* ERRORS */gsterror: { gst_bin_remove (GST_BIN_CAST (pipeline), sink); g_warning ("could not change state of new sink (%d)", ret); return; } linkfail: { g_warning ("could not link pad and sink (%d)", lret); return; }}/////////////////////////////////////////////////////descriptor: event process.//para://return value://////////////////////////////////////////////////static void event_loop (){ GstBus *bus; GstMessage *message = NULL; printf(" ++++ %s ++++\n", __func__); bus = gst_element_get_bus (GST_ELEMENT (media.g_pipe)); while (TRUE) { message = gst_bus_poll (bus, GST_MESSAGE_ANY, -1); g_assert (message != NULL); switch (message->type) { case GST_MESSAGE_EOS: gst_message_unref (message); return; case GST_MESSAGE_WARNING: case GST_MESSAGE_ERROR:{ GError *gerror; gchar *debug; gst_message_parse_error (message, &gerror, &debug); gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug); gst_message_unref (message); g_error_free (gerror); g_free (debug); return; } default: gst_message_unref (message); break; } }}/////////////////////////////////////////////////////descriptor: init gstreamer and make a pipeline//para://return value://////////////////////////////////////////////////gint start_gstreamer(gchar *filename){ GstElement *filesrc, *decodebin; GstStateChangeReturn res; static GMainLoop *loop; printf(" ++++ %s ++++\n", __func__); //g_printf("your file name is: %s. \n", filename); //gst_init (&argc, &argv); gst_init(NULL, NULL); gst_local_init(); // for audio and video. media.g_pipe = gst_pipeline_new ("pipeline"); filesrc = gst_element_factory_make ("filesrc", "filesrc"); g_assert (filesrc); decodebin = gst_element_factory_make ("decodebin", "decodebin"); g_assert (decodebin); g_signal_connect (G_OBJECT(decodebin), "new-decoded-pad", G_CALLBACK(create_pad), media.g_pipe); gst_bin_add_many (GST_BIN (media.g_pipe), filesrc, decodebin, NULL); gst_element_link (filesrc, decodebin); //if (argc < 2) //{ // g_print ("usage: %s <uri>\n", argv[0]); // exit (-1); //} //g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL); g_object_set (G_OBJECT (filesrc), "location", filename, NULL); /* set to paused, decodebin will autoplug and signal new_pad callbacks */ res = gst_element_set_state (media.g_pipe, GST_STATE_PAUSED); if (res == GST_STATE_CHANGE_FAILURE) { g_print ("could not pause\n"); return -1; } /* wait for paused to complete */ res = gst_element_get_state (media.g_pipe, NULL, NULL, GST_CLOCK_TIME_NONE); if (res == GST_STATE_CHANGE_FAILURE) { g_print ("could not pause\n"); return -1; } /* play, now all the sinks are added to the pipeline and are prerolled and ready to play. */ res = gst_element_set_state (media.g_pipe, GST_STATE_PLAYING); if (res == GST_STATE_CHANGE_FAILURE) { g_print ("could not play\n"); return -1; } //set video parameter. //gst_set_video_parameter(); #ifdef DEBUG_GST g_timeout_add(6000, (GSourceFunc)check_other_function, filename); //event_loop ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -