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