Macro qtTrIdx() replaced by tr() and QT_TRANSLATE_NOOP()
[mafwsubrenderer] / qmafw-gst-subtitles-renderer / src / mafw-gst-renderer-seeker.c
1 /*
2  * This file is part of QMAFW
3  *
4  * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights
5  * reserved.
6  *
7  * Contact: Visa Smolander <visa.smolander@nokia.com>
8  *
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.
15  *
16  */
17
18 #include "mafw-gst-renderer-seeker.h"
19
20 #include <gst/gst.h>
21
22 #define CLOSE_LIMIT 2
23 #define MOVE_FORWARD 10
24
25 typedef struct {
26     gint64 required_pos;
27     gint64 starting_pos;
28     gint64 current_pos;
29 } seek_request;
30
31 struct _MafwGstRendererSeeker {
32     GstElement *pipeline;
33     seek_request last_request;
34 };
35
36 gint64 _get_current_pos(GstElement* pipeline)
37 {
38     GstFormat format = GST_FORMAT_TIME;
39     gint64 time = 0;
40
41     if(pipeline &&
42        gst_element_query_position(pipeline, &format, &time))
43     {
44         return (time + (GST_SECOND/2)) / GST_SECOND;
45     }
46     else
47     {
48         return -1;
49     }
50 }
51
52 gint64 _get_duration(GstElement *pipeline)
53 {
54     gint64 value = -1;
55     GstFormat format = GST_FORMAT_TIME;
56
57     gboolean success = gst_element_query_duration(pipeline, &format, &value);
58     if( success )
59     {
60         return (value + (GST_SECOND/2)) / GST_SECOND;
61     }
62     else
63     {
64         return -1;
65     }
66 }
67
68 gboolean _try_seek_required_pos(MafwGstRendererSeeker *seeker)
69 {
70     gboolean ret;
71     gint64 spos;
72     GstSeekFlags flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT;
73
74
75     spos = (seeker->last_request.required_pos) * GST_SECOND;
76     g_debug("seek target: %lld", spos);
77
78     ret = gst_element_seek(seeker->pipeline,
79                            1.0,
80                            GST_FORMAT_TIME,
81                            flags,
82                            GST_SEEK_TYPE_SET,
83                            spos,
84                            GST_SEEK_TYPE_NONE,
85                            GST_CLOCK_TIME_NONE);
86
87     return ret;
88 }
89
90 gboolean _is_position_close_enough(gint64 pos, gint64 required_pos)
91 {
92     return ABS((pos - required_pos)) < CLOSE_LIMIT;
93 }
94
95 gboolean _has_position_changed_enough(gint64 pos, gint64 required_pos)
96 {
97     return !_is_position_close_enough(pos, required_pos);
98 }
99
100 MafwGstRendererSeeker* mafw_gst_renderer_seeker_new()
101 {
102     return g_new0(MafwGstRendererSeeker, 1);
103 }
104
105 void mafw_gst_renderer_seeker_free(MafwGstRendererSeeker *seeker)
106 {
107     g_free(seeker);
108 }
109
110 void mafw_gst_renderer_seeker_set_pipeline(MafwGstRendererSeeker *seeker, GstElement *pipeline)
111 {
112     seeker->pipeline = pipeline;
113     mafw_gst_renderer_seeker_cancel(seeker);
114 }
115
116 gboolean mafw_gst_renderer_seeker_seek_to(MafwGstRendererSeeker *seeker, gint64 seek_pos)
117 {
118     if( seeker == NULL )
119     {
120         g_critical("Seeker is NULL!");
121         return FALSE;
122     }
123
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;
128
129     return _try_seek_required_pos(seeker);
130
131 }
132
133 void mafw_gst_renderer_seeker_cancel(MafwGstRendererSeeker *seeker)
134 {
135     seek_request *request = &(seeker->last_request);
136     request->current_pos = -1;
137     request->required_pos = -1;
138     request->starting_pos = -1;
139 }
140
141 gint64 mafw_gst_renderer_seeker_process(MafwGstRendererSeeker *seeker)
142 {
143     if( seeker == NULL )
144     {
145         g_critical("Seeker is NULL!");
146         return -1;
147     }
148
149     seek_request *request = &(seeker->last_request);
150
151     if(request->required_pos < 0)
152     {
153         g_debug("[Seeker] No valid request set! Doing nothing,");
154         return request->required_pos;
155     }
156
157     request->current_pos = _get_current_pos(seeker->pipeline);
158     if( request->current_pos < 0 )
159     {
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;
163     }
164
165     gboolean forward_seek = ( request->required_pos >= request->starting_pos );
166
167     if( _is_position_close_enough(request->current_pos, request->required_pos)
168         ||
169         ((_has_position_changed_enough(request->current_pos, request->starting_pos)
170           && forward_seek
171           && request->current_pos > request->starting_pos)) )
172     {
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);
175     }
176     else
177     {
178         if( forward_seek )
179         {
180             request->required_pos += MOVE_FORWARD;
181             gint64 duration = _get_duration(seeker->pipeline);
182             if( request->required_pos > duration )
183             {
184                 g_debug("[Seeker] Cancelling increased seek target beyond media length!");
185                 mafw_gst_renderer_seeker_cancel(seeker);
186             }
187         }
188         else
189         {
190             g_debug("Backward seek done, cannot do better...");
191             mafw_gst_renderer_seeker_cancel(seeker);
192         }
193     }
194
195     if( request->required_pos >= 0 )
196     {
197         _try_seek_required_pos(seeker);
198     }
199
200     return request->required_pos;
201 }