2 * This file is part of QMAFW
4 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights
7 * Contact: Visa Smolander <visa.smolander@nokia.com>
9 * This software, including documentation, is protected by copyright controlled
10 * by Nokia Corporation. All rights are reserved. Copying, including
11 * reproducing, storing, adapting or translating, any or all of this material
12 * requires the prior written consent of Nokia Corporation. This material also
13 * contains confidential information which may not be disclosed to others
14 * without the prior written consent of Nokia.
18 #include "mafw-gst-renderer-seeker.h"
23 #define MOVE_FORWARD 10
31 struct _MafwGstRendererSeeker {
33 seek_request last_request;
36 gint64 _get_current_pos(GstElement* pipeline)
38 GstFormat format = GST_FORMAT_TIME;
42 gst_element_query_position(pipeline, &format, &time))
44 return (time + (GST_SECOND/2)) / GST_SECOND;
52 gint64 _get_duration(GstElement *pipeline)
55 GstFormat format = GST_FORMAT_TIME;
57 gboolean success = gst_element_query_duration(pipeline, &format, &value);
60 return (value + (GST_SECOND/2)) / GST_SECOND;
68 gboolean _try_seek_required_pos(MafwGstRendererSeeker *seeker)
72 GstSeekFlags flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT;
75 spos = (seeker->last_request.required_pos) * GST_SECOND;
76 g_debug("seek target: %lld", spos);
78 ret = gst_element_seek(seeker->pipeline,
90 gboolean _is_position_close_enough(gint64 pos, gint64 required_pos)
92 return ABS((pos - required_pos)) < CLOSE_LIMIT;
95 gboolean _has_position_changed_enough(gint64 pos, gint64 required_pos)
97 return !_is_position_close_enough(pos, required_pos);
100 MafwGstRendererSeeker* mafw_gst_renderer_seeker_new()
102 return g_new0(MafwGstRendererSeeker, 1);
105 void mafw_gst_renderer_seeker_free(MafwGstRendererSeeker *seeker)
110 void mafw_gst_renderer_seeker_set_pipeline(MafwGstRendererSeeker *seeker, GstElement *pipeline)
112 seeker->pipeline = pipeline;
113 mafw_gst_renderer_seeker_cancel(seeker);
116 gboolean mafw_gst_renderer_seeker_seek_to(MafwGstRendererSeeker *seeker, gint64 seek_pos)
120 g_critical("Seeker is NULL!");
124 seek_request *request = &(seeker->last_request);
125 request->required_pos = seek_pos;
126 request->starting_pos = _get_current_pos(seeker->pipeline);
127 request->current_pos = request->starting_pos;
129 return _try_seek_required_pos(seeker);
133 void mafw_gst_renderer_seeker_cancel(MafwGstRendererSeeker *seeker)
135 seek_request *request = &(seeker->last_request);
136 request->current_pos = -1;
137 request->required_pos = -1;
138 request->starting_pos = -1;
141 gint64 mafw_gst_renderer_seeker_process(MafwGstRendererSeeker *seeker)
145 g_critical("Seeker is NULL!");
149 seek_request *request = &(seeker->last_request);
151 if(request->required_pos < 0)
153 g_debug("[Seeker] No valid request set! Doing nothing,");
154 return request->required_pos;
157 request->current_pos = _get_current_pos(seeker->pipeline);
158 if( request->current_pos < 0 )
160 mafw_gst_renderer_seeker_cancel(seeker);
161 g_warning("[Seeker] Could not get position! Cannot refine seek!");
162 return seeker->last_request.current_pos;
165 gboolean forward_seek = ( request->required_pos >= request->starting_pos );
167 if( _is_position_close_enough(request->current_pos, request->required_pos)
169 ((_has_position_changed_enough(request->current_pos, request->starting_pos)
171 && request->current_pos > request->starting_pos)) )
173 g_debug("Got good enough seek result: Current pos: %lld, Required pos: %lld", request->current_pos, request->required_pos);
174 mafw_gst_renderer_seeker_cancel(seeker);
180 request->required_pos += MOVE_FORWARD;
181 gint64 duration = _get_duration(seeker->pipeline);
182 if( request->required_pos > duration )
184 g_debug("[Seeker] Cancelling increased seek target beyond media length!");
185 mafw_gst_renderer_seeker_cancel(seeker);
190 g_debug("Backward seek done, cannot do better...");
191 mafw_gst_renderer_seeker_cancel(seeker);
195 if( request->required_pos >= 0 )
197 _try_seek_required_pos(seeker);
200 return request->required_pos;