|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <gst.h> |
|
19 #include "unistd.h" |
|
20 #include <pthread.h> |
|
21 #include "xamediaplayeradaptctx.h" |
|
22 #include "xaplayitfadaptation.h" |
|
23 #include "xaadaptationgst.h" |
|
24 #include "xacameraadaptctx.h" |
|
25 |
|
26 extern XAboolean cameraRealized; |
|
27 extern XACameraAdaptationCtx_* cameraCtx; |
|
28 |
|
29 /*forward declaration of position updater callback*/ |
|
30 gboolean XAPlayItfAdapt_PositionUpdate(gpointer ctx); |
|
31 |
|
32 /* |
|
33 * XAresult XAPlayItfAdaptGST_SetPlayState(XAAdaptationGstCtx *bCtx, XAuint32 state) |
|
34 * Sets play state to GStreamer. |
|
35 * @param XAAdaptationGstCtx *bCtx - Adaptation context, this will be casted to correct type regarding to contextID |
|
36 * XAuint32 state - Play state to be set |
|
37 * @return XAresult ret - Success value |
|
38 */ |
|
39 XAresult XAPlayItfAdaptGST_SetPlayState(XAAdaptationBaseCtx *ctx, XAuint32 state) |
|
40 { |
|
41 XAresult ret = XA_RESULT_SUCCESS; |
|
42 XAboolean requestStateChange = XA_BOOLEAN_FALSE; |
|
43 GstStateChangeReturn gstRet = GST_STATE_CHANGE_SUCCESS; |
|
44 XAMediaPlayerAdaptationCtx* mCtx = NULL; |
|
45 XAuint32 locType = 0; |
|
46 GstState gstOrigState = GST_STATE_PLAYING; |
|
47 XADataLocator_Address *address = NULL; |
|
48 XAboolean playing = XA_BOOLEAN_FALSE; |
|
49 XAAdaptationGstCtx *bCtx = (XAAdaptationGstCtx *)ctx; |
|
50 |
|
51 DEBUG_API_A1("->XAPlayItfAdaptGST_SetPlayState %s",PLAYSTATENAME(state)); |
|
52 |
|
53 |
|
54 if(!bCtx || bCtx->baseObj.ctxId != XAMediaPlayerAdaptation) |
|
55 { |
|
56 DEBUG_ERR("XA_RESULT_PARAMETER_INVALID"); |
|
57 return XA_RESULT_PARAMETER_INVALID; |
|
58 } |
|
59 |
|
60 mCtx = (XAMediaPlayerAdaptationCtx*) bCtx; |
|
61 switch ( state ) |
|
62 { |
|
63 case XA_PLAYSTATE_STOPPED: |
|
64 { |
|
65 if ( cameraCtx && cameraRealized && mCtx->isobjsrc && mCtx->source ) |
|
66 { |
|
67 cameraCtx->playing = XA_BOOLEAN_FALSE; |
|
68 if(!cameraCtx->recording && !cameraCtx->snapshotting) |
|
69 { |
|
70 /* Future improvement: We could block MPObjSrc pad from tee-eleement here, when |
|
71 * tee-element supports sending stream to one pad when others are blocked */ |
|
72 |
|
73 /* Neither view finder or recorder is running -> pause camera */ |
|
74 if ( GST_STATE( GST_ELEMENT(mCtx->source)) == GST_STATE_PLAYING ) |
|
75 { |
|
76 GstStateChangeReturn gret; |
|
77 DEBUG_INFO("Stop camera source"); |
|
78 gret = gst_element_set_state( GST_ELEMENT(mCtx->source), GST_STATE_PAUSED ); |
|
79 if(gret == GST_STATE_CHANGE_SUCCESS) |
|
80 gret = gst_element_get_state( GST_ELEMENT(mCtx->source), NULL,NULL, XA_ADAPT_ASYNC_TIMEOUT_SHORT_NSEC ); |
|
81 } |
|
82 } |
|
83 } |
|
84 |
|
85 gstOrigState = GST_STATE(bCtx->bin); |
|
86 if ( gstOrigState != GST_STATE_READY ) |
|
87 { |
|
88 DEBUG_INFO("Set gst-bin to GST_STATE_READY"); |
|
89 bCtx->binWantedState = GST_STATE_READY; |
|
90 XAAdaptationGst_PrepareAsyncWait(bCtx); |
|
91 gstRet = gst_element_set_state( GST_ELEMENT(bCtx->bin), GST_STATE_READY); |
|
92 switch ( gstRet ) |
|
93 { |
|
94 case GST_STATE_CHANGE_FAILURE: |
|
95 DEBUG_ERR_A1("FAILED to change state (target %s)", |
|
96 gst_element_state_get_name(bCtx->binWantedState)); |
|
97 bCtx->binWantedState = GST_STATE(bCtx->bin); |
|
98 ret = XA_RESULT_INTERNAL_ERROR; |
|
99 break; |
|
100 case GST_STATE_CHANGE_ASYNC: |
|
101 DEBUG_INFO_A1("Change state will happen asyncronously (target %s)", |
|
102 gst_element_state_get_name(bCtx->binWantedState)); |
|
103 XAAdaptationGst_StartAsyncWait(bCtx); |
|
104 ret = XA_RESULT_SUCCESS; |
|
105 break; |
|
106 case GST_STATE_CHANGE_SUCCESS: |
|
107 DEBUG_INFO_A1("Successfully changed state (target %s)", |
|
108 gst_element_state_get_name(bCtx->binWantedState)); |
|
109 break; |
|
110 default: |
|
111 DEBUG_ERR_A1("Unhandled error (%d)",gstRet); |
|
112 break; |
|
113 } |
|
114 bCtx->waitingasyncop = XA_BOOLEAN_FALSE; |
|
115 DEBUG_INFO_A1("Setted gst-bin to state %s", gst_element_state_get_name(GST_STATE(bCtx->bin))); |
|
116 |
|
117 DEBUG_INFO_A1("Restoring gst-bin state to state %s", gst_element_state_get_name(gstOrigState)); |
|
118 bCtx->binWantedState = gstOrigState; |
|
119 XAAdaptationGst_PrepareAsyncWait(bCtx); |
|
120 gstRet = gst_element_set_state( GST_ELEMENT(bCtx->bin), gstOrigState); |
|
121 switch ( gstRet ) |
|
122 { |
|
123 case GST_STATE_CHANGE_FAILURE: |
|
124 DEBUG_ERR_A1("FAILED to change state (target %s)", |
|
125 gst_element_state_get_name(bCtx->binWantedState)); |
|
126 bCtx->binWantedState = GST_STATE(bCtx->bin); |
|
127 ret = XA_RESULT_INTERNAL_ERROR; |
|
128 break; |
|
129 case GST_STATE_CHANGE_ASYNC: |
|
130 DEBUG_INFO_A1("Change state will happen asyncronously (target %s)", |
|
131 gst_element_state_get_name(bCtx->binWantedState)); |
|
132 XAAdaptationGst_StartAsyncWait(bCtx); |
|
133 ret = XA_RESULT_SUCCESS; |
|
134 break; |
|
135 case GST_STATE_CHANGE_SUCCESS: |
|
136 DEBUG_INFO_A1("Successfully changed state (target %s)", |
|
137 gst_element_state_get_name(bCtx->binWantedState)); |
|
138 break; |
|
139 default: |
|
140 DEBUG_ERR_A1("Unhandled error (%d)",gstRet); |
|
141 break; |
|
142 } |
|
143 bCtx->waitingasyncop = XA_BOOLEAN_FALSE; |
|
144 gstOrigState = GST_STATE(bCtx->bin); |
|
145 DEBUG_INFO_A1("Restored gst-bin to state %s", gst_element_state_get_name(gstOrigState)); |
|
146 } |
|
147 |
|
148 |
|
149 /* if( bCtx->pipeSrcThrCtx.dataHandle ) |
|
150 { |
|
151 XAresult retVal = XA_RESULT_SUCCESS; |
|
152 if ( bCtx->pipeSrcThrCtx.state != CPStateNull ) |
|
153 { |
|
154 bCtx->pipeSrcThrCtx.state = CPStateStopped; |
|
155 } |
|
156 |
|
157 retVal = XAImpl_PostSemaphore( bCtx->pipeSrcThrCtx.stateSem ); |
|
158 if ( retVal != XA_RESULT_SUCCESS ) |
|
159 { |
|
160 DEBUG_ERR("Could not post content pipe semaphore!"); |
|
161 } |
|
162 |
|
163 }*/ |
|
164 /* stop head and drive head to beginning */ |
|
165 bCtx->binWantedState = GST_STATE_PAUSED; |
|
166 if(mCtx->runpositiontimer > 0) |
|
167 { |
|
168 g_source_remove(mCtx->runpositiontimer); |
|
169 mCtx->runpositiontimer=0; |
|
170 } |
|
171 |
|
172 gst_element_send_event(bCtx->bin,gst_event_new_flush_start()); |
|
173 gst_element_send_event(bCtx->bin,gst_event_new_flush_stop()); |
|
174 |
|
175 locType = *((XAuint32*)( mCtx->xaSource->pLocator )); |
|
176 if( locType == XA_DATALOCATOR_ADDRESS ) |
|
177 { |
|
178 address = (XADataLocator_Address*)(mCtx->xaSource->pLocator); |
|
179 |
|
180 /* init gst buffer from datalocator */ |
|
181 if( mCtx->source ) |
|
182 { |
|
183 GstBuffer* userBuf = NULL; |
|
184 |
|
185 /* init GST buffer from XADataLocator*/ |
|
186 userBuf = gst_buffer_new(); |
|
187 if( userBuf ) |
|
188 { |
|
189 userBuf->size = address->length; |
|
190 userBuf->data = address->pAddress; |
|
191 /* push the whole buffer to appsrc so it is ready for preroll */ |
|
192 DEBUG_INFO("Pushing buffer"); |
|
193 gst_app_src_push_buffer( GST_APP_SRC(mCtx->source), userBuf ); |
|
194 DEBUG_INFO_A1("Sent buffer at 0x%x to appsrc", userBuf ); |
|
195 gst_app_src_end_of_stream( GST_APP_SRC(mCtx->source) ); |
|
196 } |
|
197 else |
|
198 { |
|
199 DEBUG_ERR("Failure allocating buffer!"); |
|
200 } |
|
201 } |
|
202 } |
|
203 break; |
|
204 } |
|
205 case XA_PLAYSTATE_PAUSED: |
|
206 |
|
207 if ( cameraCtx && cameraRealized && mCtx->isobjsrc && mCtx->source ) |
|
208 { |
|
209 cameraCtx->playing = XA_BOOLEAN_FALSE; |
|
210 |
|
211 /* Future improvement: We could block MPObjSrc pad from tee-eleement here, when |
|
212 * tee-element supports sending stream to one pad when others are blocked */ |
|
213 |
|
214 if(!cameraCtx->recording && !cameraCtx->snapshotting) |
|
215 { |
|
216 /* Neither view finder or recorder is running -> pause camera */ |
|
217 if ( GST_STATE( GST_ELEMENT(mCtx->source)) == GST_STATE_PLAYING ) |
|
218 { |
|
219 GstStateChangeReturn gret; |
|
220 DEBUG_INFO("Stop camera source"); |
|
221 gret = gst_element_set_state( GST_ELEMENT(mCtx->source), GST_STATE_PAUSED ); |
|
222 if(gret == GST_STATE_CHANGE_SUCCESS) |
|
223 gret = gst_element_get_state( GST_ELEMENT(mCtx->source), NULL,NULL, XA_ADAPT_ASYNC_TIMEOUT_SHORT_NSEC ); |
|
224 } |
|
225 } |
|
226 } |
|
227 |
|
228 /* if ( bCtx->pipeSrcThrCtx.state != CPStateNull ) |
|
229 { |
|
230 bCtx->pipeSrcThrCtx.state = CPStatePaused; |
|
231 }*/ |
|
232 bCtx->binWantedState = GST_STATE_PAUSED; |
|
233 if(mCtx->runpositiontimer > 0) |
|
234 { |
|
235 g_source_remove(mCtx->runpositiontimer); |
|
236 mCtx->runpositiontimer=0; |
|
237 } |
|
238 break; |
|
239 case XA_PLAYSTATE_PLAYING: |
|
240 { |
|
241 if ( cameraCtx && mCtx->isobjsrc ) |
|
242 { |
|
243 cameraCtx->playing = XA_BOOLEAN_TRUE; |
|
244 } |
|
245 |
|
246 if ( mCtx->videoppBScrbin ) |
|
247 { |
|
248 gst_element_set_state( GST_ELEMENT(mCtx->videoppBScrbin), GST_STATE_PAUSED); |
|
249 } |
|
250 if (mCtx->isobjsrc && !mCtx->cameraSinkSynced && cameraCtx ) |
|
251 { /* create videosink now */ |
|
252 mCtx->cameraSinkSynced = XA_BOOLEAN_TRUE; |
|
253 if ( mCtx->videosink ) |
|
254 { |
|
255 gst_element_unlink( mCtx->filter,mCtx->videosink ); |
|
256 gst_element_set_state( GST_ELEMENT(mCtx->videosink), GST_STATE_NULL); |
|
257 gst_bin_remove( GST_BIN(mCtx->baseObj.bin), mCtx->videosink); |
|
258 mCtx->videosink = XAAdaptationGst_CreateGstSink( mCtx->xaVideoSink, "videosink", &(mCtx->isobjvsink) ); |
|
259 gst_bin_add(GST_BIN(mCtx->baseObj.bin), mCtx->videosink); |
|
260 if (! gst_element_link(mCtx->filter, mCtx->videosink)) |
|
261 { |
|
262 DEBUG_ERR("Could not link Filter to videosink!!"); |
|
263 return XA_RESULT_INTERNAL_ERROR; |
|
264 } |
|
265 } |
|
266 } |
|
267 |
|
268 /* if ( bCtx->pipeSrcThrCtx.state != CPStateNull ) |
|
269 { |
|
270 XAresult retVal = XA_RESULT_SUCCESS; |
|
271 |
|
272 if ( bCtx->pipeSrcThrCtx.state == CPStateInitialized ) |
|
273 { Start thread if it's not running |
|
274 retVal = XAImpl_StartThread( &(bCtx->pipeSrcThr), NULL, &XAAdaptationGst_ContentPipeScrThrFunc, &(bCtx->pipeSrcThrCtx) ); |
|
275 if ( retVal != XA_RESULT_SUCCESS ) |
|
276 { |
|
277 DEBUG_ERR("Could not start content pipe thread!"); |
|
278 } |
|
279 } |
|
280 if ( bCtx->pipeSrcThrCtx.state == CPStatePaused || |
|
281 bCtx->pipeSrcThrCtx.state == CPStateInitialized || |
|
282 bCtx->pipeSrcThrCtx.state == CPStateStarted ) |
|
283 retVal = XAImpl_PostSemaphore( bCtx->pipeSrcThrCtx.stateSem ); |
|
284 if ( retVal != XA_RESULT_SUCCESS ) |
|
285 { |
|
286 DEBUG_ERR("Could not post content pipe semaphore!"); |
|
287 } |
|
288 }*/ |
|
289 |
|
290 bCtx->binWantedState = GST_STATE_PLAYING; |
|
291 if(mCtx->playrate!=1 && !mCtx->isobjsrc) |
|
292 { /*set seek element for ff, rew and slow*/ |
|
293 XAAdaptationGst_PrepareAsyncWait(bCtx); |
|
294 DEBUG_INFO_A1("Apply new playrate %f.", mCtx->playrate); |
|
295 if(!gst_element_seek( bCtx->bin, mCtx->playrate, GST_FORMAT_TIME, |
|
296 (GstSeekFlags)(GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_ACCURATE), |
|
297 GST_SEEK_TYPE_NONE, 0, |
|
298 GST_SEEK_TYPE_NONE, -1)) |
|
299 { |
|
300 DEBUG_ERR("WARN: gst reports seek not handled"); |
|
301 } |
|
302 /* flushed seeks always asynchronous */ |
|
303 XAAdaptationGst_StartAsyncWait(bCtx); |
|
304 DEBUG_INFO("New playrate handled."); |
|
305 bCtx->waitingasyncop = XA_BOOLEAN_FALSE; |
|
306 } |
|
307 |
|
308 playing = XA_BOOLEAN_TRUE; |
|
309 break; |
|
310 } |
|
311 default: |
|
312 ret = XA_RESULT_PARAMETER_INVALID; |
|
313 break; |
|
314 } |
|
315 /* launch Gstreamer state change only if necessary */ |
|
316 if( GST_STATE_TARGET(bCtx->bin) == bCtx->binWantedState ) |
|
317 { |
|
318 DEBUG_INFO("Gst already in or transitioning to wanted state"); |
|
319 requestStateChange = XA_BOOLEAN_FALSE; |
|
320 } |
|
321 else |
|
322 { |
|
323 if( (GST_STATE(bCtx->bin) == bCtx->binWantedState) && |
|
324 (GST_STATE_PENDING(bCtx->bin) == GST_STATE_VOID_PENDING) ) |
|
325 { |
|
326 DEBUG_ERR_A3("WARNING : gststate %d == wanted %d != gsttarget %d and no statechange pending", |
|
327 GST_STATE(bCtx->bin), bCtx->binWantedState, GST_STATE_TARGET(bCtx->bin)); |
|
328 } |
|
329 requestStateChange = XA_BOOLEAN_TRUE; |
|
330 } |
|
331 |
|
332 if( requestStateChange ) |
|
333 { |
|
334 XAAdaptationGst_PrepareAsyncWait(bCtx); |
|
335 DEBUG_INFO_A1("Sending change state request to state %d", bCtx->binWantedState); |
|
336 gstRet = gst_element_set_state( GST_ELEMENT(bCtx->bin), bCtx->binWantedState); |
|
337 switch ( gstRet ) |
|
338 { |
|
339 case GST_STATE_CHANGE_FAILURE: |
|
340 DEBUG_ERR_A1("FAILED to change state (target %s)", |
|
341 gst_element_state_get_name(bCtx->binWantedState)); |
|
342 bCtx->binWantedState = GST_STATE(bCtx->bin); |
|
343 ret = XA_RESULT_INTERNAL_ERROR; |
|
344 break; |
|
345 case GST_STATE_CHANGE_ASYNC: |
|
346 DEBUG_INFO_A1("Change state will happen asyncronously (target %s)", |
|
347 gst_element_state_get_name(bCtx->binWantedState)); |
|
348 XAAdaptationGst_StartAsyncWait(bCtx); |
|
349 ret = XA_RESULT_SUCCESS; |
|
350 break; |
|
351 case GST_STATE_CHANGE_NO_PREROLL: |
|
352 DEBUG_INFO("GST_STATE_CHANGE_NO_PREROLL"); |
|
353 /* deliberate fall-through */ |
|
354 case GST_STATE_CHANGE_SUCCESS: |
|
355 DEBUG_INFO_A1("Successfully changed state (target %s)", |
|
356 gst_element_state_get_name(bCtx->binWantedState)); |
|
357 ret = XA_RESULT_SUCCESS; |
|
358 break; |
|
359 default: |
|
360 DEBUG_ERR_A1("Unhandled error (%d)",gstRet); |
|
361 ret = XA_RESULT_UNKNOWN_ERROR; |
|
362 break; |
|
363 } |
|
364 bCtx->waitingasyncop = XA_BOOLEAN_FALSE; |
|
365 } |
|
366 |
|
367 if (playing && mCtx->isobjsrc && cameraCtx ) |
|
368 { |
|
369 GstPad* moSrc=NULL ; |
|
370 |
|
371 playing = XA_BOOLEAN_FALSE; |
|
372 moSrc = gst_element_get_static_pad( mCtx->source, "MPObjSrc"); |
|
373 if( moSrc && gst_pad_is_linked(moSrc) ) |
|
374 { |
|
375 DEBUG_INFO_A2("unblock element:%s pad:%s", |
|
376 gst_element_get_name( mCtx->source), |
|
377 gst_pad_get_name(moSrc)); |
|
378 gst_pad_set_blocked_async(moSrc, FALSE, XAAdaptationGst_PadBlockCb, NULL); |
|
379 } |
|
380 |
|
381 if ( GST_STATE( GST_ELEMENT(mCtx->source)) != GST_STATE_PLAYING ) |
|
382 { |
|
383 GstStateChangeReturn gret; |
|
384 DEBUG_INFO("Start camera source"); |
|
385 gret = gst_element_set_state( GST_ELEMENT(mCtx->source), GST_STATE_PLAYING ); |
|
386 if(gret == GST_STATE_CHANGE_SUCCESS) |
|
387 gret = gst_element_get_state( GST_ELEMENT(mCtx->source), NULL,NULL, XA_ADAPT_ASYNC_TIMEOUT_SHORT_NSEC ); |
|
388 } |
|
389 } |
|
390 DEBUG_API("<-XAPlayItfAdaptGST_SetPlayState"); |
|
391 return ret; |
|
392 } |
|
393 |
|
394 /* |
|
395 * XAresult XAPlayItfAdaptGST_GetDuration(XAAdaptationGstCtx *bCtx, XAmillisecond *pMsec) |
|
396 * @param XAAdaptationGstCtx *bCtx - Adaptation context, this will be casted to correct type regarding to contextID |
|
397 * XAmillisecond *pMsec - Pointer where to store duration of stream. |
|
398 * @return XAresult ret - Success value |
|
399 */ |
|
400 XAresult XAPlayItfAdaptGST_GetDuration(XAAdaptationGstCtx *bCtx, XAmillisecond *pMsec) |
|
401 { |
|
402 XAresult ret = XA_RESULT_SUCCESS; |
|
403 GstFormat format = GST_FORMAT_TIME; |
|
404 gint64 duration; |
|
405 DEBUG_API("->XAPlayItfAdaptGST_GetDuration"); |
|
406 |
|
407 if(!bCtx || bCtx->baseObj.ctxId != XAMediaPlayerAdaptation || !pMsec) |
|
408 { |
|
409 DEBUG_ERR("XA_RESULT_PARAMETER_INVALID"); |
|
410 /* invalid parameter */ |
|
411 return XA_RESULT_PARAMETER_INVALID; |
|
412 } |
|
413 |
|
414 if( gst_element_query_duration( GST_ELEMENT(bCtx->bin), &format, &duration ) ) |
|
415 { |
|
416 DEBUG_INFO_A1("Duration: %"GST_TIME_FORMAT, GST_TIME_ARGS(duration)); |
|
417 ret = XA_RESULT_SUCCESS; |
|
418 *pMsec = GST_TIME_AS_MSECONDS(duration);/*Warning ok due to used API specification*/ |
|
419 } |
|
420 else |
|
421 { |
|
422 DEBUG_ERR("WARNING: Gst: could not get duration"); |
|
423 *pMsec = XA_TIME_UNKNOWN; |
|
424 ret = XA_RESULT_SUCCESS; |
|
425 } |
|
426 |
|
427 DEBUG_API("<-XAPlayItfAdaptGST_GetDuration"); |
|
428 return ret; |
|
429 } |
|
430 |
|
431 /* |
|
432 * XAresult XAPlayItfAdaptGST_GetPosition(XAAdaptationGstCtx *bCtx, XAmillisecond *pMsec) |
|
433 * @param XAAdaptationGstCtx *bCtx - Adaptation context, this will be casted to correct type regarding to contextID value |
|
434 * XAmillisecond *pMsec - Pointer where to store current position in stream. |
|
435 * @return XAresult ret - Success value |
|
436 */ |
|
437 XAresult XAPlayItfAdaptGST_GetPosition(XAAdaptationGstCtx *bCtx, XAmillisecond *pMsec) |
|
438 { |
|
439 XAresult ret = XA_RESULT_SUCCESS; |
|
440 gint64 position; |
|
441 GstFormat format = GST_FORMAT_TIME; |
|
442 DEBUG_API("->XAPlayItfAdapGSTt_GetPosition"); |
|
443 |
|
444 if(!bCtx || bCtx->baseObj.ctxId != XAMediaPlayerAdaptation) |
|
445 { |
|
446 DEBUG_ERR("XA_RESULT_PARAMETER_INVALID"); |
|
447 /* invalid parameter */ |
|
448 return XA_RESULT_PARAMETER_INVALID; |
|
449 } |
|
450 |
|
451 if ( gst_element_query_position( GST_ELEMENT(bCtx->bin), &format, &position ) ) |
|
452 { |
|
453 DEBUG_INFO_A1("Current position %"GST_TIME_FORMAT, GST_TIME_ARGS(position)); |
|
454 ret = XA_RESULT_SUCCESS; |
|
455 *pMsec = GST_TIME_AS_MSECONDS(position);/*Warning ok due to used API specification*/ |
|
456 } |
|
457 else |
|
458 { |
|
459 DEBUG_ERR("WARNING: Gst: could not get position"); |
|
460 /* probably not fully prerolled - safe assumption for position = 0 */ |
|
461 *pMsec = 0; |
|
462 ret = XA_RESULT_SUCCESS; |
|
463 } |
|
464 |
|
465 DEBUG_API("<-XAPlayItfAdaptGST_GetPosition"); |
|
466 return ret; |
|
467 } |
|
468 |
|
469 /* |
|
470 * XAresult XAPlayItfAdapt_EnablePositionTracking |
|
471 * Enable/disable periodic position tracking callbacks |
|
472 */ |
|
473 XAresult XAPlayItfAdapt_EnablePositionTracking(XAAdaptationGstCtx *bCtx, XAboolean enable) |
|
474 { |
|
475 XAMediaPlayerAdaptationCtx* mCtx; |
|
476 |
|
477 DEBUG_API_A1("->XAPlayItfAdapt_EnablePositionTracking (enable: %d)", (int)enable); |
|
478 if(!bCtx || bCtx->baseObj.ctxId != XAMediaPlayerAdaptation) |
|
479 { |
|
480 DEBUG_ERR("XA_RESULT_PARAMETER_INVALID"); |
|
481 /* invalid parameter */ |
|
482 return XA_RESULT_PARAMETER_INVALID; |
|
483 } |
|
484 mCtx = (XAMediaPlayerAdaptationCtx*) bCtx; |
|
485 if(enable && !(mCtx->trackpositionenabled)) |
|
486 { |
|
487 mCtx->trackpositionenabled = XA_BOOLEAN_TRUE; |
|
488 XAMediaPlayerAdapt_UpdatePositionCbTimer(mCtx); |
|
489 } |
|
490 else if (!enable && (mCtx->trackpositionenabled)) |
|
491 { |
|
492 mCtx->trackpositionenabled = XA_BOOLEAN_FALSE; |
|
493 XAMediaPlayerAdapt_UpdatePositionCbTimer(mCtx); |
|
494 } |
|
495 |
|
496 DEBUG_API("<-XAPlayItfAdapt_EnablePositionTracking"); |
|
497 return XA_RESULT_SUCCESS; |
|
498 } |
|
499 |