運行效果(音頻)
?
簡介
?????上一個教程演示了GStreamer工具。本教程介紹視頻播放控制。快進、反向播放和慢動作都是技術 統稱為 Trick Modes,它們都有一個共同點 修改 Normal playback rate。本教程介紹如何實現 這些效果并在交易中添加了幀步進。特別是,它 顯示:
??????????? 如何更改播放速率,比正常更快和更慢, 前進和向后。
??????????? 如何逐幀推進視頻
?
?????快進是一種以高于 它的正常(預期)速度;而慢動作使用低于 預期的那個。反向播放執行相同的作,但向后播放, 從流的結尾到開頭。所有這些技術所做的只是更改播放速率,這是一個變量 等于 1.0 表示正常播放,大于 1.0(絕對值) 對于快速模式,對于慢速模式,低于 1.0(絕對值), positive 表示正向播放,negative 表示反向播放。GStreamer 提供了兩種機制來更改播放速率:步進 事件 (Events) 和查找事件 (Seek Events)。Step Events 允許跳過給定數量的 媒體,除了更改后續播放速率(僅為正數 值)。此外,Seek Events 還允許跳轉到 流式傳輸并設置正播放速率和負播放速率。
?
GStreamer相關運行庫
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include/gstreamer-1.0/gst
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include/gstreamer-1.0
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include/glib-2.0
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/lib/glib-2.0/includeLIBS += D:/Software/GStreamer/1.0/mingw_x86_64/lib/gstreamer-1.0.lib
LIBS += D:/Software/GStreamer/1.0/mingw_x86_64/lib/glib-2.0.lib
LIBS += D:/Software/GStreamer/1.0/mingw_x86_64/lib/gobject-2.0.lib
?
完整源碼
#include <string.h>
#include <stdio.h>
#include <gst/gst.h>#ifdef __APPLE__
#include <TargetConditionals.h>
#endiftypedef struct _CustomData
{GstElement *pipeline;GstElement *video_sink;GMainLoop *loop;gboolean playing; /* 播放或暫停 */gdouble rate; /* 當前播放速率(可以為負) */
} CustomData;/* Send seek event to change rate */
static void
send_seek_event (CustomData * data)
{gint64 position;GstEvent *seek_event;/* Obtain the current position, needed for the seek event */if (!gst_element_query_position (data->pipeline, GST_FORMAT_TIME, &position)) {g_printerr ("Unable to retrieve current position.\n");return;}/* Create the seek event */if (data->rate > 0) {seek_event =gst_event_new_seek (data->rate, GST_FORMAT_TIME,(GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE), GST_SEEK_TYPE_SET,position, GST_SEEK_TYPE_END, 0);} else {seek_event =gst_event_new_seek (data->rate, GST_FORMAT_TIME,GstSeekFlags(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE), GST_SEEK_TYPE_SET, 0,GST_SEEK_TYPE_SET, position);}if (data->video_sink == NULL) {/* If we have not done so, obtain the sink through which we will send the seek events */g_object_get (data->pipeline, "video-sink", &data->video_sink, NULL);}/* Send the event */gst_element_send_event (data->video_sink, seek_event);g_print ("Current rate: %g\n", data->rate);
}/* 處理鍵盤輸入 */
static gboolean
handle_keyboard (GIOChannel * source, GIOCondition cond, CustomData * data)
{gchar *str = NULL;if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) != G_IO_STATUS_NORMAL) { return TRUE; }switch (g_ascii_tolower (str[0])){case 'p':data->playing = !data->playing;gst_element_set_state (data->pipeline, data->playing ? GST_STATE_PLAYING : GST_STATE_PAUSED);g_print ("Setting state to %s\n", data->playing ? "PLAYING" : "PAUSE"); break;case 's':if (g_ascii_isupper (str[0])){data->rate *= 2.0;}else{data->rate /= 2.0;}send_seek_event (data); break;case 'd':data->rate *= -1.0; send_seek_event (data); break;case 'n':if (data->video_sink == NULL){/* If we have not done so, obtain the sink through which we will send the step events */g_object_get (data->pipeline, "video-sink", &data->video_sink, NULL);}gst_element_send_event (data->video_sink,gst_event_new_step (GST_FORMAT_BUFFERS, 1, ABS (data->rate), TRUE,FALSE));g_print ("Stepping one frame\n");break;case 'q':g_main_loop_quit (data->loop);break;default:break;}g_free (str);return TRUE;
}int tutorial_main (int argc, char *argv[])
{/* 初始化GStreamer */gst_init (&argc, &argv);/* 初始化自定義數據 */CustomData data;memset (&data, 0, sizeof (data));/* 輸出使用方式 */g_print ("USAGE: Choose one of the following options, then press enter:\n"" 'P' to toggle between PAUSE and PLAY\n"" 'S' to increase playback speed, 's' to decrease playback speed\n"" 'D' to toggle playback direction\n"" 'N' to move to next frame (in the current direction, better in PAUSE)\n"" 'Q' to quit\n");/* 構建管道 */data.pipeline =gst_parse_launch("playbin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm", NULL);/* 增加鍵盤輸入以進行控制 */
#ifdef G_OS_WIN32GIOChannel *io_stdin = g_io_channel_win32_new_fd (fileno (stdin));
#elseGIOChannel *io_stdin = g_io_channel_unix_new (fileno (stdin));
#endifg_io_add_watch (io_stdin, G_IO_IN, (GIOFunc) handle_keyboard, &data);/* 開始播放 */GstStateChangeReturn ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);if (ret == GST_STATE_CHANGE_FAILURE){g_printerr ("Unable to set the pipeline to the playing state.\n");gst_object_unref (data.pipeline); return -1;}data.playing = TRUE;data.rate = 1.0;/* 創建GLib主循環并將其設置為運行 */data.loop = g_main_loop_new (NULL, FALSE);g_main_loop_run (data.loop);/* 釋放資源 */g_main_loop_unref (data.loop);g_io_channel_unref (io_stdin);gst_element_set_state (data.pipeline, GST_STATE_NULL);if (data.video_sink != NULL)gst_object_unref (data.video_sink);gst_object_unref (data.pipeline);return 0;
}int main (int argc, char *argv[])
{
#if defined(__APPLE__) && TARGET_OS_MAC && !TARGET_OS_IPHONEreturn gst_macos_main ((GstMainFunc) tutorial_main, argc, argv, NULL);
#elsereturn tutorial_main (argc, argv);
#endif
}
?
關注
筆者 - jxd