gstreamer如何實現視頻的快進和快退。

 

一、環境

i.MX6平臺+gstreamer。

二、實現

封裝3個函數,play_fast_forward、play_fast_reverse、play_normal_speed

分別對應快進、快退、正常播放。

gstreamer使用playbin管道。

1、play_fast_forward

void play_fast_forward(GstElement *playbin_em)
{
    int64_t pos = 0;
    gboolean ret = gst_element_query_position(playbin_em,GST_FORMAT_TIME,&pos);
    if (0 == ret)
    {
        printf("gst_element_query_position fail\n");
        return;
    }
    printf("get pos=%lld\n",pos);

    gint64 duration = 0;
    ret = gst_element_query_duration(playbin_em,GST_FORMAT_TIME,&duration);
    if (0 == ret)
    {
        printf("gst_element_query_duration fail\n");
        return;
    }
    printf("get duration=%lld\n",duration);

    ret = gst_element_seek(playbin_em,4.0,GST_FORMAT_TIME,
                                    GST_SEEK_FLAG_FLUSH |GST_SEEK_FLAG_KEY_UNIT,
                                    GST_SEEK_TYPE_SET,
                                    pos,
                                    GST_SEEK_TYPE_SET,
                                    duration);
    if (0 == ret)
    {
        printf("play_fast_forward fail\n");
    }
    else
    {
        printf("play_fast_forward succ\n");
    }
}

2、play_fast_reverse

void play_fast_reverse(GstElement *playbin_em)
{
    gint64 pos = 0;
    gboolean ret = gst_element_query_position(playbin_em,GST_FORMAT_TIME,&pos);
    if (0 == ret)
    {
        printf("gst_element_query_position fail\n");
        return;
    }
    printf("get pos=%lld\n",pos);

    ret = gst_element_seek(playbin_em,-4.0,GST_FORMAT_TIME,
                                    GST_SEEK_FLAG_FLUSH |GST_SEEK_FLAG_KEY_UNIT,
                                    GST_SEEK_TYPE_SET,
                                    0*GST_SECOND,
                                    GST_SEEK_TYPE_SET,
                                    pos);
    if (0 == ret)
    {
        printf("play_fast_reverse fail\n");
    }
    else
    {
        printf("play_fast_reverse succ\n");
    }
}

3、 play_normal_speed

void play_normal_speed(GstElement *playbin_em)
{
    gint64 pos = 0;
    gboolean ret = gst_element_query_position(playbin_em,GST_FORMAT_TIME,&pos);
    if (0 == ret)
    {
        printf("gst_element_query_position fail\n");
        return;
    }
    printf("get pos=%lld\n",pos);

    gint64 duration = 0;
    ret = gst_element_query_duration(playbin_em,GST_FORMAT_TIME,&duration);
    if (0 == ret)
    {
        printf("gst_element_query_duration fail\n");
        return;
    }
    printf("get duration=%lld\n",duration);

    ret = gst_element_seek(playbin_em,1.0,GST_FORMAT_TIME,
                                    GST_SEEK_FLAG_FLUSH |GST_SEEK_FLAG_KEY_UNIT,
                                    GST_SEEK_TYPE_SET,
                                    pos,
                                    GST_SEEK_TYPE_SET,
                                    duration);
    if (0 == ret)
    {
        printf("play_normal_speed fail\n");
    }
    else
    {
        printf("play_normal_speed succ\n");
    }
}

三、原理

使用gstreamer的事件機制。

gst_element_query_position和gst_element_query_duration可以得到當前播放的位置以及視頻的總時長,單位秒。

gst_element_seek是實現倍速播放的關鍵,我們看下函數聲明,

gboolean                gst_element_seek                (GstElement *element, gdouble rate,
                                                         GstFormat format, GstSeekFlags flags,
                                                         GstSeekType start_type, gint64 start,
                                                         GstSeekType stop_type, gint64 stop);

rate是播放速率,1.0是1倍速,即正常播放,4.0是4倍速,-4.0是快退4倍速。

start_type和stop_type是指後面緊跟的start和stop採用相對時間還是絕對時間,我們使用絕對時間GST_SEEK_TYPE_SET。

/**
 * GstSeekType:
 * @GST_SEEK_TYPE_NONE: no change in position is required
 * @GST_SEEK_TYPE_SET: absolute position is requested
 * @GST_SEEK_TYPE_END: relative position to duration is requested
 *
 * The different types of seek events. When constructing a seek event with
 * gst_event_new_seek() or when doing gst_segment_do_seek ().
 */
typedef enum {
  /* one of these */
  GST_SEEK_TYPE_NONE            = 0,
  GST_SEEK_TYPE_SET             = 1,
  GST_SEEK_TYPE_END             = 2
} GstSeekType;

start和stop永遠遵守start<stop的原則,這點在快退播放時也是如此。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章