source: svn/newcon3bcm2_21bu/nexus/lib/playback_ip/src/b_playback_ip.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 61.3 KB
Line 
1/***************************************************************************
2*     (c)2003-2011 Broadcom Corporation
3*
4*  This program is the proprietary software of Broadcom Corporation and/or its licensors,
5*  and may only be used, duplicated, modified or distributed pursuant to the terms and
6*  conditions of a separate, written license agreement executed between you and Broadcom
7*  (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
8*  no license (express or implied), right to use, or waiver of any kind with respect to the
9*  Software, and Broadcom expressly reserves all rights in and to the Software and all
10*  intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
11*  HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
12*  NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
13*
14*  Except as expressly set forth in the Authorized License,
15*
16*  1.     This program, including its structure, sequence and organization, constitutes the valuable trade
17*  secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
18*  and to use this information only in connection with your use of Broadcom integrated circuit products.
19*
20*  2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
21*  AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
22*  WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
23*  THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
24*  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
25*  LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
26*  OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
27*  USE OR PERFORMANCE OF THE SOFTWARE.
28*
29*  3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
30*  LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
31*  EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
32*  USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
33*  THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
34*  ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
35*  LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
36*  ANY LIMITED REMEDY.
37*
38* $brcm_Workfile: b_playback_ip.c $
39* $brcm_Revision: 106 $
40* $brcm_Date: 11/23/11 2:10p $
41*
42* Description: IP Applib Implementation
43*
44* Revision History:
45*
46* $brcm_Log: /nexus/lib/playback_ip/src/b_playback_ip.c $
47*
48* 106   11/23/11 2:10p ssood
49* SW7408-109: RVU Trickplay support: added FFWD & FRWD
50*
51* 105   10/21/11 2:22p ssood
52* SW7231-405: add debug print about stream video info
53*
54* 104   8/26/11 4:15p dliu
55* SW7425-1077: In ptsCallback, always check for videoDecoder handle valid
56*
57* 103   8/25/11 6:04p ssood
58* SW7425-1077: dont overwrite firstPts in the firstPtsPassed callback as
59*  it happens upon each discontinuity
60*
61* 102   8/8/11 10:46a mward
62* SW7125-1038: Power on/off DMA if using Netaccel.
63*
64* 101   8/4/11 4:45p ssood
65* SW7425-1040: add fast channel change support to IP Sessions
66*
67* 100   6/6/11 7:34p ssood
68* SW7231-166: fix avgBitRate calculations for fragmented mp4 streams +
69*  allow dataReadCallback for streams w/o index data
70*
71* 99   6/6/11 1:28a ssood
72* SW7231-166: added support for Slow Fwd, STC Based trick play at 2X, and
73*  eventCallback support for end of stream playback
74*
75* 98   5/26/11 11:31p ssood
76* SW7231-166: dont create Nexus File Handle for cases where Nexus
77*  playpump will get used
78*
79* 97   5/25/11 3:35p ssood
80* SW7231-166: fixed some bugs during failing trickplay cases
81*
82* 96   5/23/11 3:44p ssood
83* SW7231-166: Extend Playback IP trickmodes to be compatible with latest
84*  DLNA Guidelines
85*
86* 95   3/28/11 10:59a ssood
87* SW7420-502: increase the waittime to allow media probe to
88*  finish/timeout
89*
90* 94   2/23/11 11:48a ssood
91* SW7420-502: clock recovery support for RVU client
92*
93* 93   2/18/11 5:15p zhangjq
94* SW7420-1419:Clean up Android Media Player code
95*
96* 92   12/14/10 12:07p ssood
97* SW7420-1217: add support for encryption key parsing, downloading and
98*  receiving encrypted content
99*
100* 91   8/27/10 3:59p ssood
101* SW7420-502: added partial support to play RVU sessions in live mode
102*
103* 90   6/16/10 5:05p ssood
104* SW7420-716: initial RVU trickmode related check-ins
105*
106* 89   4/16/10 5:02p ssood
107* SW7420-561: Added support for Additional Philips RTSP features:
108*  configurable keepalive timer, allow apps to send custom headers to
109*  servers, generate EOF events to app upon RTSP heartbeat failures
110*
111* 88   4/2/10 4:18p ssood
112* SW7420-561: add support to handle large URLs (HTML5 URLs can be over
113*  256bytes)
114*
115* 87   3/4/10 12:17p ssood
116* SW7420-561: merge from branch to mainline
117*
118* SW7420-561/3   2/18/10 12:43a ssood
119* SW7420-561: added checks to validate IP state during IP API calls
120*
121* SW7420-561/2   2/16/10 10:42p ssood
122* SW7420-561: Changes to support basic RTSP w/o trickmodes
123*
124* SW7420-561/1   2/16/10 10:10a ssood
125* SW7420-561: initial cut of new APIs to meet Media Browser, DMR, &
126*  Philips RTSP requirements
127*
128* 86   2/5/10 7:04p ismailk
129* SW7420-570: open() returns -1 if unable to access the bcmrgshim driver.
130*
131* 85   1/29/10 6:13p ismailk
132* SW7420-559: Enable EROUTER_SUPPORT flag to enable the WAN unicast
133*  ioctl.
134*
135* 84   1/23/10 10:17a ssood
136* SW7420-454: further changes to condense the ip playback log
137*
138* 83   1/20/10 4:13p ssood
139* SW7420-454: more changes to compress the verbose output
140*
141* 82   1/19/10 4:55p ssood
142* SW7420-454: convert verbose output to be available via msg modules
143*  flags
144*
145* 81   12/23/09 3:28p erickson
146* SW7420-516: convert non-error BDBG_ERR to BDBG_WRN
147*
148* 80   11/24/09 10:48a ssood
149* SW7420-454: add option to allow apps to specify a specific interface
150*  name to receive live IP content
151*
152* 79   11/20/09 10:04a ssood
153* SW7420-454: set IP playback position to 0 if we dont get the valid
154*  position (haven't started the playback or some other error)
155*
156* 78   11/18/09 7:16p ssood
157* SW7420-340: set playback position to duration if playback reports
158*  incorrect value
159*
160* 77   10/21/09 3:03p ssood
161* SW7420-340: clear the status field before setting it
162*
163* 76   10/20/09 6:33p ssood
164* SW7420-340: remove nexus playback, audio, video decoder dependencies
165*  for SMS compilation
166*
167* 75   10/1/09 11:00a jjordan
168* SW7405-3107: add IP recv timeout status to Settop API
169*
170* 74   9/18/09 9:49a lwhite
171* SW7420-340: Set playing state before launching proccessing thread
172*
173* 73   8/24/09 3:23p ssood
174* SW7405-1689: adapting server based trickmodes to Nexus playback changes
175*  due to OTF support
176*
177* 72   8/14/09 5:00p ssood
178* PR50202: First check-in for clientside trickmode support for MPEG2 TS
179*  format
180*
181* 71   8/6/09 7:32p ssood
182* PR48146: commented out a debug message
183*
184* 70   8/6/09 3:38p ssood
185* PR48146: add HTTP redirect support
186*
187* 69   8/6/09 10:18a ssood
188* PR43746: added support for calculating more precise bitrates for TS &
189*  VOB files (support index reads from middle & end of content)
190*
191* 68   7/30/09 10:31a ssood
192* PR43746: provide current playback position via the IP GetStatus
193*
194* 67   7/29/09 6:14p ssood
195* PR43746: extend IP trick modes to support Disconnect And Seek based
196*  paused operations (DLNA requirement)
197*
198* 66   7/24/09 12:01p ssood
199* PR56519: Allow apps to provide additional HTTP headers fields for
200*  outgoing GET requests
201*
202* 65   7/21/09 4:18p ssood
203* PR43746: Further work for Server based HTTP trick mode support
204*
205* 64   7/16/09 12:59p ssood
206* PR43746: Add Server based HTTP trick mode support
207*
208* 63   6/25/09 11:14a ssood
209* PR53773: removing a debug comment
210*
211* 62   6/25/09 2:30a ssood
212* PR55417: added option to allocate HTTP precharge buffer either at init
213*  or run time
214*
215* 61   6/23/09 11:55p ssood
216* PR56279: Coverity error of reverse NULL
217*
218* 60   6/22/09 6:31p ssood
219* PR55417: set HTTP index cache size also based on the user provided size
220*  (otherwise, default size is too small) + fix for n/w timeout during
221*  index cache reading
222*
223* 59   6/22/09 1:44p ssood
224* PR55417: Precharging support for TS/VOB formats: moved the HTTP
225*  data/index cache allocations to IP Applib Open time, lowered default
226*  cache sizes
227*
228* 58   6/18/09 10:24a ssood
229* PR55417: provide http return code code via the GetStatus to app
230*
231* 57   6/16/09 3:00p ssood
232* PR55417: accounting for fudge factor in max buffer depth calculations
233*
234* 56   6/15/09 11:31p ssood
235* PR55417: fixing rewind related bug
236*
237* 55   6/12/09 9:16p ssood
238* PR55908: Add IPv6 Support to IP Applib
239*
240* 54   6/7/09 11:45p ssood
241* PR55417: Adding support for runtime buffering of HTTP content (used
242*  during seeks & n/w loss events)
243*
244* 53   6/5/09 1:35p ssood
245* PR55626: DLNA guidelines mandate client to only maintain no more than 1
246*  connection to server, we had one connx per data cache, changed that to
247*  closing/opening 1 connx
248*
249* 52   6/4/09 5:55p ssood
250* PR55325: return buffer depth in GetStatus only if max bitrate is
251*  available
252*
253* 51   5/29/09 6:17p ssood
254* PR55325: cleanup in debug code
255*
256* 50   5/28/09 4:54p ssood
257* PR55325: allow app to specify n/w timeout & buffer cache size
258*
259* 49   5/28/09 11:38a ssood
260* PR55325: added additional states to IP Applib to provide flexibility in
261*  the order of API calls
262*
263* 48   5/26/09 11:49a ssood
264* PR53773: added debug code to track a crash during quit
265*
266* 47   5/25/09 11:30p ssood
267* PR55325: Add support for pre-charging network buffer for HTTP playback
268*
269* 46   5/15/09 1:08p ssood
270* PR53773: adding support for skipping Media probe: needed for RAD/EA
271*  playback where app apriori have media info
272*
273* 45   5/8/09 4:35p jjordan
274* PR54886: fix TTS initial buffer depth
275*
276* 44   5/1/09 4:50p ssood
277* PR53773: adding support for WMA playback over HTTP
278*
279* 43   4/21/09 3:32p ssood
280* PR53773: handle cases where some security protocols dont encrypt HTTP
281*  response header
282*
283* 42   4/21/09 10:59a lwhite
284* PR53373: Add extern for securityContextOpen
285*
286* 41   4/17/09 2:58p lwhite
287* PR53373: Cleanup ssl init
288*
289* 40   4/16/09 5:18p lwhite
290* PR53373: Clone session support
291*
292* 39   4/14/09 5:02p lwhite
293* PR54157: Fixed memory leak
294*
295* 38   4/6/09 6:09p ssood
296* PR53773 : refactored basic TCP socket functions for reuse by other
297*  internal modules
298*
299* 37   4/3/09 9:13a ssood
300* PR53773 : code cleanup
301*
302* 36   4/2/09 11:36p ssood
303* PR53773 : changes to support security framework for SSL, DTCP-IP,
304*  RAD/ES protocols
305*
306* 35   3/2/09 2:44p ssood
307* PR50311: brutus quit crashes when we quit from a HTTP channel where
308*  connect attempt had failed
309*
310* 34   2/27/09 11:55a ssood
311* PR50311: Adding support for HTTP Chunk Transfer Encoding
312*
313* 33   12/4/08 10:13a jjordan
314* PR49937: Add support for RTP over TTS
315*
316* 32   11/7/08 5:30p ssood
317* PR48146: HTTP processing now happens in the content of Nexus Playback
318*  Player thread, so removing the local thread logic (as it was causing
319*  sync issues during quit)
320*
321* 31   11/7/08 2:54p jrubio
322* PR48782: modify stop
323*
324* 30   11/5/08 7:46p ssood
325* PR48146: fixed a core dump during failure path
326*
327* 29   11/5/08 4:12p ssood
328* PR48146: more work on support needed for MP4/ASF playback
329*
330* 29   11/5/08 3:37p ssood
331* PR48146: more work on support needed for MP4/ASF playback
332*
333* 28   10/31/08 1:12p jjordan
334* PR47230: fix warning
335*
336* 27   10/31/08 12:30p jjordan
337* PR47230: Add TTS Pacing
338*
339* 26   10/27/08 11:57a ssood
340* PR45431: adding MP4 & ASF playback support over HTTP
341*
342* 25   10/13/08 5:46p ssood
343* PR47521: improved support for low-bit rate streams + handle unmarked
344*  discontinuity condition
345*
346* 25   10/13/08 5:42p ssood
347* PR47521: improved support for low-bit rate streams + handle unmarked
348*  discontinuity condition
349*
350* 24   10/10/08 6:53p lwhite
351* PR47685: Coverity fixes
352*
353* 23   10/7/08 11:32p erickson
354* PR47232: ---------------------------
355*
356* 22   10/3/08 3:32p lwhite
357* PR42739: Added RTSP timeline support
358*
359* 21   9/3/08 1:59p lwhite
360* PR42739: Http standard socket fixes
361*
362* 20   8/18/08 11:05a ssood
363* PR45431: Fixed RTP to work standard sockets
364*
365* 19   8/14/08 12:29p ssood
366* PR45431: fixed compilation errors w/ LIVEMEDIA_SUPPORT=n
367*
368* 18   8/11/08 10:13a ssood
369* PR45431: Add HTTP playback support for ASF content
370*
371* 17   8/5/08 1:12p ssood
372* PR42739: splitting up UDP & RTP Processing code into separate sub-
373*  modules
374*
375* 16   8/5/08 7:59a ssood
376* PR45400: make code compilable with -std=c89 for maximum compatibility
377*
378* PR45400/1   8/5/08 12:44p dyzhang
379* PR45400: kylin should compile with -std=c89 for maximum compatibility
380*
381* 15   7/31/08 10:42a ssood
382* PR42739: Fixing macroblocking issue which happens during PSI discovery
383*
384* 14   7/29/08 3:49p ssood
385* PR42739: fixing HTTP decode related errors
386*
387* 13   7/28/08 4:19p ssood
388* PR42739: fixed a core dump during close
389*
390* 12   7/28/08 3:27p ssood
391* PR42739: further changes for supporting example app for IP Applib
392*
393* 11   7/24/08 1:23p ssood
394* PR42739: changes for supporting example app for IP Applib
395*
396* 10   7/21/08 4:06p ssood
397* PR42739: code changes to simplify ip app lib interface
398*
399* 9   7/14/08 7:12p ssood
400* PR42739: added option to disable netdma filter to fix macroblocking
401*  issue after pid discovery
402*
403* 8   7/14/08 5:37p ssood
404* PR42739: RTCP stats function was not using correct pkt offset
405*
406* 7   7/14/08 4:28p lwhite
407* PR42739: Added RTCP support
408*
409* 6   7/9/08 9:53p ssood
410* PR42739: added support for high jitter + receiving variable size UDP
411*  packets
412*
413* 5   6/18/08 7:38a ssood
414* PR43744: Channel Change script fails on IP channels after 5-10min
415*
416* 5   6/18/08 7:35a ssood
417* PR43744: Channel Change script fails on IP channels after 5-10min
418*
419* 4   6/13/08 9:52p ssood
420* PR42739: Added check to monitor CDB depth & throttle sender for HTTP
421*  playback
422*
423* 3   6/13/08 7:28p ssood
424* PR42739: Adding support for HTTP & RTSP playback
425*
426* 2   6/12/08 8:30a ssood
427* PR42739: Enabling RTP support using LiveMedia library
428*
429* 1   6/11/08 6:21p ssood
430* PR42739: adding IP Applib files
431*
432***************************************************************************/
433
434 /**
435 * Note this file is currently only compiled for LINUX platforms. Even though it
436 * has VxWorks & WinCE related hash defines, the code needs more porting
437 * work for these OS platforms.
438 * If the feature isn't compiled in, then the only functions in this .c file
439 * should be the public stubs.
440 **/
441#if defined(LINUX) || defined(__vxworks)
442
443#include "b_playback_ip_lib.h"
444#include "b_playback_ip_priv.h"
445#include "b_playback_ip_utils.h"
446#include "b_playback_ip_lm_helper.h"
447#include <sys/ioctl.h>
448#include <net/if.h>
449#include "nexus_power_management.h"
450
451BDBG_MODULE(b_playback_ip);
452
453/**
454* Playback IP module can receive IP encapsulated AV data from
455* network using following 3 compile options:
456*       -use normal sockets (true when B_HAS_NETACCEL &
457*        B_HAS_PLAYPUMP_IP is not defined)
458*       -use legacy IP Playpump (true when B_HAS_PLAYPUMP_IP is
459*        defined), this i/f is being deprecated)
460*       -use recommended accelerated sockets (which uses
461*        Broadcom's Accelerated Sockets i/f) (true when
462*        B_HAS_NETACCEL is defined & B_HAS_PLAYPUMP_IP is not
463*        defined).
464*/
465
466/***************************************************************************
467Summary:
468Private handle for each Playback IP App Lib context
469***************************************************************************/
470
471/* forward declarations: */
472#ifndef B_HAS_SMS_GATEWAY
473/* When SMS Gateway is configured, IP Applib is used only for receiving Live IP traffic which is mainly using UDP/RTP traffic. So we dont need any of the HTTP module. */
474extern B_PlaybackIpError B_PlaybackIp_HttpSessionOpen( B_PlaybackIpHandle playback_ip, B_PlaybackIpSessionOpenSettings *openSettings, B_PlaybackIpSessionOpenStatus *openStatus);
475extern B_PlaybackIpError B_PlaybackIp_HttpSessionSetup(B_PlaybackIpHandle playback_ip, B_PlaybackIpSessionSetupSettings *setupSettings, B_PlaybackIpSessionSetupStatus *setupStatus);
476extern B_PlaybackIpError B_PlaybackIp_HttpSessionSetup(B_PlaybackIpHandle playback_ip, B_PlaybackIpSessionSetupSettings *setupSettings, B_PlaybackIpSessionSetupStatus *setupStatus);
477extern B_PlaybackIpError B_PlaybackIp_HttpSessionStart(B_PlaybackIpHandle playback_ip, B_PlaybackIpSessionStartSettings *startSettings, B_PlaybackIpSessionStartStatus *startStatus);
478extern void B_PlaybackIp_HttpSessionStop(B_PlaybackIpHandle playback_ip);
479extern void B_PlaybackIp_HttpSessionClose(B_PlaybackIpHandle playback_ip);
480B_PlaybackIpError B_PlaybackIp_HttpGetCurrentPlaybackPosition(B_PlaybackIpHandle playback_ip, NEXUS_PlaybackPosition *currentPosition);
481#endif
482extern B_PlaybackIpError B_PlaybackIp_UdpSessionOpen( B_PlaybackIpHandle playback_ip, B_PlaybackIpSessionOpenSettings *openSettings, B_PlaybackIpSessionOpenStatus *openStatus);
483extern B_PlaybackIpError B_PlaybackIp_UdpSessionStart(B_PlaybackIpHandle playback_ip, B_PlaybackIpSessionStartSettings *startSettings, B_PlaybackIpSessionStartStatus *startStatus);
484extern void B_PlaybackIp_UdpSessionClose(B_PlaybackIpHandle playback_ip);
485
486/* remove RTP temporaroly, zhangjq,  20101221 */
487#ifndef ANDROID
488extern B_PlaybackIpError B_PlaybackIp_RtpSessionOpen( B_PlaybackIpHandle playback_ip, B_PlaybackIpSessionOpenSettings *openSettings, B_PlaybackIpSessionOpenStatus *openStatus);
489extern B_PlaybackIpError B_PlaybackIp_RtpSessionStart(B_PlaybackIpHandle playback_ip, B_PlaybackIpSessionStartSettings *startSettings, B_PlaybackIpSessionStartStatus *startStatus);
490extern void B_PlaybackIp_RtpSessionStop(B_PlaybackIpHandle playback_ip);
491extern void B_PlaybackIp_RtpSessionClose(B_PlaybackIpHandle playback_ip);
492#endif
493
494extern B_PlaybackIpError B_PlaybackIp_RtspSessionOpen( B_PlaybackIpHandle playback_ip, B_PlaybackIpSessionOpenSettings *openSettings, B_PlaybackIpSessionOpenStatus *openStatus);
495extern B_PlaybackIpError B_PlaybackIp_RtspSessionStart(B_PlaybackIpHandle playback_ip, B_PlaybackIpSessionStartSettings *startSettings, B_PlaybackIpSessionStartStatus *startStatus);
496extern B_PlaybackIpError B_PlaybackIp_RtspSessionSetup(B_PlaybackIpHandle playback_ip, B_PlaybackIpSessionSetupSettings *setupSettings, B_PlaybackIpSessionSetupStatus *setupStatus);
497
498/* TODO: look into using a per IP session context mutext to prevent multiple threads invoking the same/different APIs for a given IP session context */
499
500/***************************************************************************
501Summary:
502This function initializes an Playback IP channel on the settings selected. A shallow
503copy of the B_PlaybackIp_Settings structure is made in this call. The private App Lib
504structure is malloc'ed.
505***************************************************************************/
506B_PlaybackIpHandle B_PlaybackIp_Open(
507    const B_PlaybackIpOpenSettings *pSettings
508    )
509{
510    B_PlaybackIpHandle playback_ip = NULL;
511
512    BDBG_MSG(("%s: PKTS_PER_READ %d\n", __FUNCTION__, PKTS_PER_READ));
513    BSTD_UNUSED(pSettings);
514
515    /* allocate playback_ip context */
516    playback_ip = (B_PlaybackIpHandle) BKNI_Malloc(sizeof(B_PlaybackIp));
517    if (NULL == playback_ip)
518        return NULL;
519    BKNI_Memset(playback_ip, 0, sizeof(B_PlaybackIp));
520
521    /* move to open state */
522    playback_ip->playback_state = B_PlaybackIpState_eOpened;
523
524    return (B_PlaybackIpHandle) playback_ip;
525}
526
527/*
528Summary:
529    Close an IP playback channel.
530    This function de-initializes the Playback IP App Lib. The private App Lib structure is freed.
531*/
532B_PlaybackIpError
533B_PlaybackIp_Close(
534    B_PlaybackIpHandle playback_ip
535    )
536{
537    if (!playback_ip) {
538        BDBG_ERR(("%s: NULL playback_ip handle\n", __FUNCTION__));
539        return B_ERROR_INVALID_PARAMETER;
540    }
541
542    BDBG_MSG(("%s: ", __FUNCTION__));
543
544    switch (playback_ip->playback_state) {
545    case B_PlaybackIpState_eSessionSetupInProgress:
546    case B_PlaybackIpState_eSessionSetup:
547    case B_PlaybackIpState_eSessionStartInProgress:
548    case B_PlaybackIpState_ePlaying:
549    case B_PlaybackIpState_eStopping:
550    case B_PlaybackIpState_eBuffering:
551    case B_PlaybackIpState_ePaused:
552    case B_PlaybackIpState_eEnteringTrickMode:
553    case B_PlaybackIpState_eTrickMode:
554        B_PlaybackIp_SessionStop(playback_ip);
555        /* continue w/ session close cleanup */
556    case B_PlaybackIpState_eSessionOpenInProgress:
557    case B_PlaybackIpState_eSessionOpened:
558    /* case B_PlaybackIpState_eStopped: */
559        B_PlaybackIp_SessionClose(playback_ip);
560        /* continue w/ playback ip channel cleanup */
561    case B_PlaybackIpState_eOpened:
562    default:
563        break;
564        /* do the playback channel related cleanup */
565    }
566
567    BKNI_Free(playback_ip);
568
569    return BERR_SUCCESS;
570}
571
572B_PlaybackIpError
573B_PlaybackIp_SessionOpen(
574    B_PlaybackIpHandle playback_ip,
575        B_PlaybackIpSessionOpenSettings *openSettings,
576        B_PlaybackIpSessionOpenStatus *openStatus /* [out] */
577    )
578{
579    B_PlaybackIpError errorCode = B_ERROR_PROTO;
580    B_PlaybackIpSocketState *socketState;
581
582    if (!playback_ip || !openSettings || !openStatus) {
583        BDBG_ERR(("%s: invalid params, playback_ip %p, openSettings %p, openStatus %p\n", __FUNCTION__, playback_ip, openSettings, openStatus));
584        return B_ERROR_INVALID_PARAMETER;
585    }
586
587    /* Validate if app can call this API in the current IP Playback State */
588    switch (playback_ip->playback_state) {
589    case B_PlaybackIpState_eOpened:
590    case B_PlaybackIpState_eSessionOpenInProgress:
591        /* continue below with this API */
592        break;
593    default:
594        /* In all other states, app can't call this API */
595        BDBG_ERR(("ERROR: Can't call %s() in this state %d\n", __FUNCTION__, playback_ip->playback_state));
596        return B_ERROR_NOT_SUPPORTED;
597    }
598
599    if (openSettings->nonBlockingMode) {
600        if (!openSettings->eventCallback) {
601            BDBG_ERR(("%s: invalid param: eventCallback must be specified for nonBlockingMode operation", __FUNCTION__));
602            return B_ERROR_INVALID_PARAMETER;
603        }
604
605        /* if the API is already in progress, return INCOMPLETE */
606        if (playback_ip->apiInProgress) {
607            return B_ERROR_IN_PROGRESS;
608        }
609
610        /* So Api is not in progress, check if it is completed, them jump to returning results to app */
611        if (playback_ip->apiCompleted) {
612            BDBG_WRN(("%s: previously started session open operation completed, playback_ip %p", __FUNCTION__, playback_ip));
613            goto apiDone;
614        }
615       
616        /* else fall below to perform session initialization */
617    }
618
619#ifdef B_HAS_NETACCEL
620        NEXUS_PowerManagement_SetCoreState(NEXUS_PowerManagementCore_eDma, true);
621#endif
622    /* reset playback ip context */
623    memset(playback_ip, 0, sizeof(B_PlaybackIp));
624    B_PlaybackIp_GetDefaultSettings(&playback_ip->settings);
625
626    /* now API is progress, update state to reflect that */
627    playback_ip->playback_state = B_PlaybackIpState_eSessionOpenInProgress;
628
629    BDBG_WRN(("%s: playback_ip %p, openSettings %p, openStatus %p, state %d, proto %d\n", 
630                __FUNCTION__, playback_ip, openSettings, openStatus, playback_ip->playback_state, openSettings->socketOpenSettings.protocol));
631
632    playback_ip->openSettings = *openSettings;
633    if (openSettings->socketOpenSettings.url != NULL) {
634        /* cache a copy of the URL */
635        if ((playback_ip->openSettings.socketOpenSettings.url = strdup(openSettings->socketOpenSettings.url)) == NULL) {
636            BDBG_ERR(("%s: Failed to duplicate URL string due to out of memory condition", __FUNCTION__));
637            goto error;
638        }
639    }
640    socketState = &openStatus->socketState;
641    memset(openStatus, 0, sizeof(B_PlaybackIpSessionOpenStatus));
642
643    /* create events */
644    if (BKNI_CreateEvent(&playback_ip->playback_halt_event)) {
645        BDBG_ERR(("%s: Failed to create an event\n", __FUNCTION__));
646        goto error;
647    }
648    if (BKNI_CreateEvent(&playback_ip->read_callback_event)) {
649        BDBG_ERR(("%s: Failed to create an event\n", __FUNCTION__));
650        goto error;
651    }
652    if (BKNI_CreateEvent(&playback_ip->preChargeBufferEvent)) {
653        BDBG_ERR(("%s: Failed to create an event\n", __FUNCTION__));
654        goto error;
655    }
656    if (BKNI_CreateEvent(&playback_ip->newJobEvent)) {
657        BDBG_ERR(("%s: Failed to create an event\n", __FUNCTION__));
658        goto error;
659    }
660    if (BKNI_CreateEvent(&playback_ip->liveMediaSyncEvent)) {
661        BDBG_ERR(("%s: Failed to create an event\n", __FUNCTION__));
662        goto error;
663    }
664    /* create mutex for serializing flow among different flows invoking a IP playback session */
665    if (BKNI_CreateMutex(&playback_ip->lock) != 0) {
666        BDBG_ERR(("Failed to create BKNI mutex at %d", __LINE__));
667        errorCode = B_ERROR_OUT_OF_MEMORY;
668        goto error;
669    }
670
671
672apiDone:
673    switch (openSettings->socketOpenSettings.protocol) {
674#ifndef B_HAS_SMS_GATEWAY
675    case B_PlaybackIpProtocol_eHttp:
676        errorCode = B_PlaybackIp_HttpSessionOpen(playback_ip, openSettings, openStatus);
677        break;
678#endif
679    case B_PlaybackIpProtocol_eUdp:
680    case B_PlaybackIpProtocol_eRtpFec:
681        errorCode = B_PlaybackIp_UdpSessionOpen(playback_ip, openSettings, openStatus);
682        break;
683    case B_PlaybackIpProtocol_eRtsp:
684#ifdef LIVEMEDIA_SUPPORT
685        errorCode = B_PlaybackIp_RtspSessionOpen(playback_ip, openSettings, openStatus);
686#else
687        errorCode = B_ERROR_INVALID_PARAMETER;
688        BDBG_ERR(("%s: RTSP protocol requires compilation of Live Media library (build w/ LIVEMEDIA_SUPPORT=y)"));
689#endif
690        break;
691       
692#ifndef ANDROID         
693    case B_PlaybackIpProtocol_eRtp:
694#ifdef LIVEMEDIA_SUPPORT
695        errorCode = B_PlaybackIp_RtpSessionOpen(playback_ip, openSettings, openStatus);
696#else
697        errorCode = B_ERROR_INVALID_PARAMETER;
698        BDBG_ERR(("%s: RTP protocol requires compilation of Live Media library (build w/ LIVEMEDIA_SUPPORT=y)"));
699#endif
700        break;
701    case B_PlaybackIpProtocol_eRtpNoRtcp:
702        errorCode = B_PlaybackIp_RtpSessionOpen(playback_ip, openSettings, openStatus);
703        break;
704#endif 
705     
706    default:
707        errorCode = B_ERROR_INVALID_PARAMETER;
708        break;
709    }
710    if (errorCode == B_ERROR_IN_PROGRESS)
711        return B_ERROR_IN_PROGRESS;
712    else if (errorCode != B_ERROR_SUCCESS) 
713        goto error;
714   
715    /* now this API is successfully completed, update state to reflect that */
716    playback_ip->playback_state = B_PlaybackIpState_eSessionOpened;
717    playback_ip->protocol = openSettings->socketOpenSettings.protocol;
718    playback_ip->socketState = openStatus->socketState;
719    playback_ip->settings.ipMode = openSettings->ipMode;
720    playback_ip->settings.networkTimeout = openSettings->networkTimeout;
721    BDBG_MSG(("%s: Session Open completed: socket fd %d\n", __FUNCTION__, playback_ip->socketState.fd));
722    return B_ERROR_SUCCESS;
723
724error:
725    if (playback_ip->openSettings.socketOpenSettings.url)
726        free(playback_ip->openSettings.socketOpenSettings.url);
727    if (playback_ip->playback_halt_event)
728        BKNI_DestroyEvent(playback_ip->playback_halt_event);
729    if (playback_ip->preChargeBufferEvent)
730        BKNI_DestroyEvent(playback_ip->preChargeBufferEvent);
731    if (playback_ip->newJobEvent)
732        BKNI_DestroyEvent(playback_ip->newJobEvent);
733    if (playback_ip->read_callback_event)
734        BKNI_DestroyEvent(playback_ip->read_callback_event);
735    if (playback_ip->liveMediaSyncEvent)
736        BKNI_DestroyEvent(playback_ip->liveMediaSyncEvent);
737    if (playback_ip->lock) {
738        BKNI_DestroyMutex(playback_ip->lock);
739        playback_ip->lock = NULL;
740    }
741
742    /* back to Opened state */
743    playback_ip->playback_state = B_PlaybackIpState_eOpened;
744    playback_ip->openSettings.eventCallback = NULL;
745    BDBG_ERR(("%s() ERRRO: playback_ip %p, errorCode %d, fd %d\n", __FUNCTION__, playback_ip, errorCode, playback_ip->socketState.fd));
746    return errorCode;
747}
748
749B_PlaybackIpError
750B_PlaybackIp_SessionSetup(
751    B_PlaybackIpHandle playback_ip,
752        B_PlaybackIpSessionSetupSettings *setupSettings,
753        B_PlaybackIpSessionSetupStatus *setupStatus /* [out] */
754    )
755{
756    B_PlaybackIpError errorCode = B_ERROR_PROTO;
757
758    BDBG_MSG(("%s: playback_ip %p, setupSettings %p, setupStatus %p\n", __FUNCTION__, playback_ip, setupSettings, setupStatus));
759    if (!playback_ip || !setupSettings || !setupStatus) {
760        BDBG_ERR(("%s: invalid params, playback_ip %p, setupSettings %p, setupStatus %p\n", __FUNCTION__, playback_ip, setupSettings, setupStatus));
761        return B_ERROR_INVALID_PARAMETER;
762    }
763
764    /* Validate if app can call this API in the current IP Playback State */
765    switch (playback_ip->playback_state) {
766    case B_PlaybackIpState_eSessionOpened:
767    case B_PlaybackIpState_eSessionSetupInProgress:
768        /* continue below with this API */
769        break;
770    default:
771        /* In all other states, app can't call this API */
772        BDBG_ERR(("ERROR: Can't call %s() in this state %d\n", __FUNCTION__, playback_ip->playback_state));
773        return B_ERROR_NOT_SUPPORTED;
774    }
775
776    /* now API is progress, update state to reflect that */
777    playback_ip->playback_state = B_PlaybackIpState_eSessionSetupInProgress;
778
779    memset(setupStatus, 0, sizeof(B_PlaybackIpSessionSetupStatus));
780    playback_ip->setupSettings = *setupSettings;
781
782    switch (playback_ip->openSettings.socketOpenSettings.protocol) {
783#ifndef B_HAS_SMS_GATEWAY
784    case B_PlaybackIpProtocol_eHttp:
785        errorCode = B_PlaybackIp_HttpSessionSetup(playback_ip, setupSettings, setupStatus);
786        break;
787#endif
788#ifdef LIVEMEDIA_SUPPORT
789    case B_PlaybackIpProtocol_eRtsp:
790        errorCode = B_PlaybackIp_RtspSessionSetup(playback_ip, setupSettings, setupStatus);
791        break;
792#endif
793    default:
794        /* this function is NOP for rest of the protocols */
795        errorCode = B_ERROR_SUCCESS;
796        break;
797    }
798
799    if (errorCode == B_ERROR_IN_PROGRESS)
800        return B_ERROR_IN_PROGRESS;
801    else if (errorCode != B_ERROR_SUCCESS) 
802        goto error;
803
804    /* now this API is successfully completed, update state to reflect that */
805    playback_ip->playback_state = B_PlaybackIpState_eSessionSetup;
806    playback_ip->sessionSetupCompleted = true;
807    BDBG_MSG(("%s: Session Setup completed: socket fd %d\n", __FUNCTION__, playback_ip->socketState.fd));
808    return B_ERROR_SUCCESS;
809
810error:
811    BDBG_ERR(("%s() ERRRO: playback_ip %p, errorCode %d, fd %d\n", __FUNCTION__, playback_ip, errorCode, playback_ip->socketState.fd));
812    playback_ip->playback_state = B_PlaybackIpState_eSessionOpened;
813    return errorCode;
814}
815
816static void 
817firstPtsCallback(void *context, int param)
818{
819    NEXUS_VideoDecoderSettings videoDecoderSettings;
820    B_PlaybackIpHandle playback_ip = (B_PlaybackIpHandle)context;
821    BSTD_UNUSED(param);
822    if (playback_ip->nexusHandles.videoDecoder) {
823        NEXUS_VideoDecoderStatus status;
824        if (NEXUS_VideoDecoder_GetStatus(playback_ip->nexusHandles.videoDecoder, &status) != NEXUS_SUCCESS) {
825            BDBG_ERR(("%s: Failed to get current vidoe currentPts\n", __FUNCTION__));
826            return;
827        }
828        playback_ip->firstPts = status.pts;
829        playback_ip->lastUsedPts = status.pts;
830        BDBG_MSG(("%s: first decoded pts 0x%x, ptsStcDifference 0x%x, type %d, tsm %d", __FUNCTION__, status.pts, status.ptsStcDifference, status.ptsType, status.tsm));
831        NEXUS_VideoDecoder_GetSettings(playback_ip->nexusHandles.videoDecoder, &videoDecoderSettings);
832        videoDecoderSettings.firstPts.callback = NULL;
833        videoDecoderSettings.firstPts.context = NULL;
834        if (NEXUS_VideoDecoder_SetSettings(playback_ip->nexusHandles.videoDecoder, &videoDecoderSettings) != NEXUS_SUCCESS) {
835            BDBG_ERR(("%s: Failed to set the 1st pts callback\n", __FUNCTION__));
836            return;
837        }
838
839    }
840    B_Time_Get(&playback_ip->mediaStartTime);
841    playback_ip->mediaStartTimeNoted = true;
842}
843
844static void 
845firstPtsPassedCallback(void *context, int param)
846{
847    B_PlaybackIpHandle playback_ip = (B_PlaybackIpHandle)context;
848    BSTD_UNUSED(param);
849    if (playback_ip->nexusHandles.videoDecoder) {
850        NEXUS_VideoDecoderStatus status;
851        if (NEXUS_VideoDecoder_GetStatus(playback_ip->nexusHandles.videoDecoder, &status) != NEXUS_SUCCESS) {
852            BDBG_ERR(("%s: Failed to get current vidoe currentPts\n", __FUNCTION__));
853            return;
854        }
855        BDBG_MSG(("%s: first passed pts 0x%x, ptsStcDifference 0x%x, type %d, tsm %d", __FUNCTION__, status.pts, status.ptsStcDifference, status.ptsType, status.tsm));
856    }
857    B_Time_Get(&playback_ip->mediaStartTime);
858    playback_ip->mediaStartTimeNoted = true;
859}
860
861static void 
862sourceChangedCallback(void *context, int param)
863{
864    B_PlaybackIpHandle playback_ip = (B_PlaybackIpHandle)context;
865    BSTD_UNUSED(param);
866    if (playback_ip->nexusHandles.videoDecoder) {
867        NEXUS_VideoDecoderStatus status;
868        if (NEXUS_VideoDecoder_GetStatus(playback_ip->nexusHandles.videoDecoder, &status) != NEXUS_SUCCESS) {
869            BDBG_ERR(("%s: NEXUS_VideoDecoder_GetStatus() Failed", __FUNCTION__));
870            return;
871        }
872        BDBG_WRN(("%s: res: source %dx%d, coded %dx%d, display %dx%d, ar %d, fr %d, interlaced %d video format %d, muted %d", __FUNCTION__,
873                    status.source.width, status.source.height, 
874                    status.coded.width, status.coded.height, 
875                    status.display.width, status.display.height, 
876                    status.aspectRatio, 
877                    status.frameRate, 
878                    status.interlaced, 
879                    status.format, 
880                    status.muted
881                    ));
882    }
883}
884
885B_PlaybackIpError
886B_PlaybackIp_SessionStart(
887    B_PlaybackIpHandle playback_ip,
888        B_PlaybackIpSessionStartSettings *startSettings,
889        B_PlaybackIpSessionStartStatus *startStatus /* [out] */
890    )
891{
892    B_PlaybackIpError errorCode = B_ERROR_PROTO;
893    NEXUS_VideoDecoderSettings videoDecoderSettings;
894
895    BDBG_MSG(("%s: playback_ip %p, startSettings %p, startStatus %p\n", __FUNCTION__, playback_ip, startSettings, startStatus));
896    if (!playback_ip || !startSettings || !startStatus) {
897        BDBG_ERR(("%s: invalid params, playback_ip %p, startSettings %p, startStatus %p\n", __FUNCTION__, playback_ip, startSettings, startStatus));
898        return B_ERROR_INVALID_PARAMETER;
899    }
900
901    /* Validate if app can call this API in the current IP Playback State */
902    switch (playback_ip->playback_state) {
903    case B_PlaybackIpState_eSessionOpened:
904        if (playback_ip->openSettings.socketOpenSettings.protocol == B_PlaybackIpProtocol_eHttp ||
905            playback_ip->openSettings.socketOpenSettings.protocol == B_PlaybackIpProtocol_eRtsp) {
906            /* SessionSetup needs to be called at least once for the HTTP/RTSP protocols */
907            if (!playback_ip->sessionSetupCompleted) {
908                BDBG_ERR(("%s: ERROR: Ip_SessionSetup() needs to be called before Ip_SessionStart() for HTTP/RTSP protocols, ip state %d", 
909                        __FUNCTION__, playback_ip->playback_state));
910                return B_ERROR_NOT_SUPPORTED;
911            }
912            else {
913                /* session setup has been completed atleast once for this session, so we can proceed w/ start below */
914                break;
915            }
916        }
917        else {
918            /* For all other protocols, app can call SessionStart w/o calling SessionSetup */
919            /* so continue below with this API */
920            break;
921        }
922    case B_PlaybackIpState_eSessionSetup:
923    case B_PlaybackIpState_eSessionStartInProgress:
924        /* continue below with this API */
925        break;
926    default:
927        /* In all other states, app can't call this API */
928        BDBG_ERR(("ERROR: Can't call %s() in this state %d\n", __FUNCTION__, playback_ip->playback_state));
929        return B_ERROR_NOT_SUPPORTED;
930    }
931
932    /* now API is progress, update state to reflect that */
933    playback_ip->playback_state = B_PlaybackIpState_eSessionStartInProgress;
934
935    memset(startStatus, 0, sizeof(B_PlaybackIpSessionStartStatus));
936    playback_ip->startSettings = *startSettings;
937    if (startSettings->nexusHandlesValid)
938        playback_ip->nexusHandles = startSettings->nexusHandles;
939    playback_ip->byte_count = 0;
940    playback_ip->numRecvTimeouts = 0;
941
942    if (playback_ip->nexusHandles.videoDecoder) {
943        NEXUS_VideoDecoder_GetSettings(playback_ip->nexusHandles.videoDecoder, &videoDecoderSettings);
944        videoDecoderSettings.firstPts.callback = firstPtsCallback;
945        videoDecoderSettings.firstPts.context = playback_ip;
946        videoDecoderSettings.firstPtsPassed.callback = firstPtsPassedCallback;
947        videoDecoderSettings.firstPtsPassed.context = playback_ip;
948        videoDecoderSettings.sourceChanged.callback = sourceChangedCallback;
949        videoDecoderSettings.sourceChanged.context = playback_ip;
950        if (NEXUS_VideoDecoder_SetSettings(playback_ip->nexusHandles.videoDecoder, &videoDecoderSettings) != NEXUS_SUCCESS) {
951            BDBG_ERR(("%s: Failed to set the 1st pts callback\n", __FUNCTION__));
952            goto error;
953        }
954    }
955
956    switch (playback_ip->openSettings.socketOpenSettings.protocol) {
957#ifndef B_HAS_SMS_GATEWAY
958    case B_PlaybackIpProtocol_eHttp:
959        errorCode = B_PlaybackIp_HttpSessionStart(playback_ip, startSettings, startStatus);
960        break;
961#endif
962#ifdef LIVEMEDIA_SUPPORT
963    case B_PlaybackIpProtocol_eRtsp:
964        errorCode = B_PlaybackIp_RtspSessionStart(playback_ip, startSettings, startStatus);
965        break;
966#endif
967
968#ifndef ANDROID
969    case B_PlaybackIpProtocol_eRtp:
970    case B_PlaybackIpProtocol_eRtpNoRtcp:
971        errorCode = B_PlaybackIp_RtpSessionStart(playback_ip, startSettings, startStatus);
972        break;
973#endif
974       
975    case B_PlaybackIpProtocol_eUdp:
976        errorCode = B_PlaybackIp_UdpSessionStart(playback_ip, startSettings, startStatus);
977        break;
978    case B_PlaybackIpProtocol_eRtpFec:
979    default:
980        BDBG_MSG(("%s: Session start failed: protocol %d not supported", __FUNCTION__, playback_ip->openSettings.socketOpenSettings.protocol));
981        errorCode = B_ERROR_INVALID_PARAMETER;
982        break;
983    }
984
985    if (errorCode == B_ERROR_IN_PROGRESS)
986        return B_ERROR_IN_PROGRESS;
987    else if (errorCode != B_ERROR_SUCCESS) 
988        goto error;
989
990    /* now this API is successfully completed, update state to reflect that */
991    playback_ip->playback_state = B_PlaybackIpState_ePlaying;
992    BDBG_MSG(("%s() completed successfully, playback_ip %p\n", __FUNCTION__, playback_ip));
993    return B_ERROR_SUCCESS;
994
995error:
996    playback_ip->playback_state = B_PlaybackIpState_eSessionSetup;
997    return errorCode;
998}
999
1000/*
1001Summary:
1002    Stops IP playback.
1003Description:
1004    This function must be called when app no longer wants to tune to a live IP or a playback channel over network.
1005    Depending on the current state of the playback IP channel, this function stops the IP internal thread
1006    and does some protocol specific cleanup (stop reading data from socket, etc.). It then changes
1007    state to eStopped.
1008Note:
1009    Socket is not closed in this call. Thus, App can temporarily stop receiving live data and then
1010    restart receiving data on this socket using the B_PlaybackIp_Start().
1011    App must call B_PlaybackIp_SessionClose() to free up the socket related resources.
1012    Also, this is a blocking function call.
1013*/
1014B_PlaybackIpError B_PlaybackIp_SessionStop(
1015    B_PlaybackIpHandle playback_ip
1016    )
1017{
1018    BERR_Code rc;
1019#ifdef B_HAS_NETACCEL
1020    STRM_SockSetFilterState_t sockFilterState;
1021#endif
1022
1023    BDBG_MSG(("%s: playback ip state %d\n", __FUNCTION__, playback_ip->playback_state));
1024    switch (playback_ip->playback_state) {
1025    case B_PlaybackIpState_eOpened:
1026    case B_PlaybackIpState_eSessionOpenInProgress:
1027    case B_PlaybackIpState_eSessionOpened:
1028    case B_PlaybackIpState_eSessionSetup:
1029    case B_PlaybackIpState_eStopping:
1030    case B_PlaybackIpState_eSessionSetupInProgress:
1031    /* case B_PlaybackIpState_eStopped:*/
1032    default:
1033        BDBG_WRN(("%s: nothing to stop in this state %d... ", __FUNCTION__, playback_ip->playback_state));
1034        return B_ERROR_SUCCESS;
1035
1036    case B_PlaybackIpState_eSessionStartInProgress:
1037    case B_PlaybackIpState_ePlaying:
1038    case B_PlaybackIpState_eBuffering:
1039    case B_PlaybackIpState_ePaused:
1040    case B_PlaybackIpState_eEnteringTrickMode:
1041    case B_PlaybackIpState_eTrickMode:
1042        /* Continue below to Stop the IP Session */
1043        break;
1044    }
1045
1046    /* change to stopping state as stopping the IP thread can take some time */
1047    playback_ip->playback_state = B_PlaybackIpState_eStopping;
1048
1049    rc = BKNI_WaitForEvent(playback_ip->playback_halt_event, IP_HALT_TASK_TIMEOUT_MSEC);
1050    if (rc == BERR_TIMEOUT) {
1051        BDBG_WRN(("%s: playback_halt_event was timed out", __FUNCTION__));
1052    } else if (rc!=0) {
1053        BDBG_ERR(("%s: failed to stop the IP thread: playback_halt_event timed out due to error rc = %d", __FUNCTION__, rc));
1054        goto error;
1055    }
1056    B_Thread_Destroy(playback_ip->playbackIpThread);
1057    BDBG_MSG(("%s: Playback IP thread is stopped \n", __FUNCTION__));
1058
1059    switch (playback_ip->openSettings.socketOpenSettings.protocol) {
1060    case B_PlaybackIpProtocol_eUdp:
1061    case B_PlaybackIpProtocol_eRtpFec:
1062        break;
1063#ifndef B_HAS_SMS_GATEWAY
1064    case B_PlaybackIpProtocol_eHttp:
1065        B_PlaybackIp_HttpSessionStop(playback_ip);
1066        break;
1067#endif
1068
1069#ifndef ANDROID
1070    case B_PlaybackIpProtocol_eRtp:
1071    case B_PlaybackIpProtocol_eRtsp:
1072    case B_PlaybackIpProtocol_eRtpNoRtcp:
1073        B_PlaybackIp_RtpSessionStop(playback_ip);
1074        break;
1075#endif       
1076       
1077    default:
1078        BDBG_WRN(("%s: Bad protocol", __FUNCTION__));
1079        break;
1080    }
1081
1082    if (playback_ip->protocol != B_PlaybackIpProtocol_eHttp) {
1083#ifdef B_HAS_NETACCEL
1084        /* filter only needs to be disbled for live protocols */
1085        sockFilterState.filterEnable = 0;
1086        if (setsockopt(playback_ip->socketState.fd, SOCK_BRCM_DGRAM, STRM_SOCK_SET_FILTER_STATE, &sockFilterState, sizeof(sockFilterState)) != 0)
1087        {
1088            BDBG_ERR(("%s: setsockopt() ERROR:", __FUNCTION__));
1089        }
1090        BDBG_ERR(("%s: Disabled Net DMA filter\n", __FUNCTION__));
1091#endif
1092    }
1093
1094    playback_ip->playback_state = B_PlaybackIpState_eStopped; /* Note: this state is same as eSessionOpened, this duplicate name is aimed to provide clarity */
1095    return B_ERROR_SUCCESS;
1096
1097error:
1098    BDBG_ERR(("%s: error", __FUNCTION__));
1099    return B_ERROR_UNKNOWN;
1100}
1101
1102/*
1103Summary:
1104    Close a IP playback socket.
1105Description:
1106    Close a IP playback socket opened by bplayback_socketState_open(). Playback
1107    must be stopped BEFORE socket is closed
1108*/
1109B_PlaybackIpError B_PlaybackIp_SessionClose(
1110    B_PlaybackIpHandle playback_ip /* Handle returned by bplayback_ip_open */
1111    )
1112{
1113    BERR_Code rc;
1114
1115    /* TODO: if state is SessionOpenInProgress, need to cancel that action */
1116
1117    switch (playback_ip->playback_state) {
1118    case B_PlaybackIpState_eOpened:
1119        /* since session is not yet started, there is nothing to close, return */
1120        return B_ERROR_SUCCESS;
1121
1122    case B_PlaybackIpState_eSessionStartInProgress:
1123    case B_PlaybackIpState_ePlaying:
1124    case B_PlaybackIpState_eBuffering:
1125    case B_PlaybackIpState_ePaused:
1126    case B_PlaybackIpState_eEnteringTrickMode:
1127    case B_PlaybackIpState_eTrickMode:
1128        B_PlaybackIp_SessionStop(playback_ip);
1129        /* continue below w/ session close cleanup */
1130       
1131    case B_PlaybackIpState_eSessionSetupInProgress:
1132        /* temporarily change state to Stopping to allow media probing to fail & return */
1133        playback_ip->playback_state = B_PlaybackIpState_eStopping;
1134        rc = BKNI_WaitForEvent(playback_ip->playback_halt_event, IP_HALT_TASK_TIMEOUT_MSEC);
1135        if (rc == BERR_TIMEOUT) {
1136            BDBG_WRN(("%s: playback_halt_event was timed out", __FUNCTION__));
1137        } else if (rc!=0) {
1138            BDBG_ERR(("%s: failed to stop the media probe thread: playback_halt_event timed out due to error rc = %d", __FUNCTION__, rc));
1139        }
1140    case B_PlaybackIpState_eSessionOpenInProgress:
1141    case B_PlaybackIpState_eSessionSetup:
1142    case B_PlaybackIpState_eStopped:
1143    /* case B_PlaybackIpState_eSessionOpened: */
1144        /* continue below w/ session close cleanup */
1145        break;
1146    default:
1147    case B_PlaybackIpState_eStopping:
1148        /* error */
1149        BDBG_ERR(("ERROR: can't call %s() in this state %d as another thread is concurrently calling Ip_SessionStop()", __FUNCTION__, playback_ip->playback_state));
1150        return B_ERROR_NOT_SUPPORTED;
1151    }
1152
1153    BDBG_MSG(("%s: ip state %d", __FUNCTION__, playback_ip->playback_state));
1154
1155    /* switch to the opened state, this channel can be used for another session */
1156    playback_ip->playback_state = B_PlaybackIpState_eOpened;
1157
1158    /* do socket related cleanup */
1159    close(playback_ip->socketState.fd);
1160    memset(&playback_ip->socketState, 0, sizeof(playback_ip->socketState));
1161    BDBG_WRN(("%s: closed fd %d (cur state %d)", __FUNCTION__, playback_ip->socketState.fd, playback_ip->playback_state));
1162    playback_ip->socketState.fd = 0;
1163
1164    switch (playback_ip->protocol) {
1165#ifndef B_HAS_SMS_GATEWAY
1166    case B_PlaybackIpProtocol_eHttp:
1167        B_PlaybackIp_HttpSessionClose(playback_ip);
1168        break;
1169#endif
1170    case B_PlaybackIpProtocol_eUdp:
1171        B_PlaybackIp_UdpSessionClose(playback_ip);
1172        break;
1173       
1174#ifndef ANDROID         
1175    case B_PlaybackIpProtocol_eRtp:
1176    case B_PlaybackIpProtocol_eRtsp:
1177    case B_PlaybackIpProtocol_eRtpNoRtcp:
1178        B_PlaybackIp_RtpSessionClose(playback_ip);
1179        break;
1180#endif
1181       
1182    default:
1183        break;
1184    }
1185
1186    if (playback_ip->openSettings.socketOpenSettings.url)
1187        free(playback_ip->openSettings.socketOpenSettings.url);
1188    BKNI_DestroyEvent(playback_ip->playback_halt_event);
1189    playback_ip->playback_halt_event = NULL;
1190    BKNI_DestroyEvent(playback_ip->preChargeBufferEvent);
1191    BKNI_DestroyEvent(playback_ip->newJobEvent);
1192    BKNI_DestroyEvent(playback_ip->read_callback_event);
1193    BKNI_DestroyEvent(playback_ip->liveMediaSyncEvent);
1194    if (playback_ip->lock) {
1195        BKNI_DestroyMutex(playback_ip->lock);
1196        playback_ip->lock = NULL;
1197    }
1198#ifdef B_HAS_NETACCEL
1199        NEXUS_PowerManagement_SetCoreState(NEXUS_PowerManagementCore_eDma, false);
1200#endif
1201    return B_ERROR_SUCCESS;
1202}
1203
1204/* routine to return the Playback IP Status */
1205B_PlaybackIpError
1206B_PlaybackIp_GetStatus(
1207    B_PlaybackIpHandle playback_ip,
1208    B_PlaybackIpStatus *ipStatus
1209    )
1210{
1211    B_PlaybackIpError rc = B_ERROR_SUCCESS;
1212    if (ipStatus) {
1213        int cacheIndex;
1214        BKNI_Memset(ipStatus, 0, sizeof(*ipStatus));
1215        ipStatus->ipState = playback_ip->playback_state;
1216#ifndef B_HAS_SMS_GATEWAY
1217        cacheIndex = playback_ip->lastUsedCacheIndex;
1218        if (playback_ip->dataCache[cacheIndex].inUse && playback_ip->psi.avgBitRate) {
1219            ipStatus->maxBufferDuration = ((playback_ip->dataCache[cacheIndex].size - playback_ip->cacheDepthFudgeFactor)*8*1000) / playback_ip->psi.avgBitRate;  /* in msec */
1220            if (playback_ip->lastSeekOffset < playback_ip->dataCache[cacheIndex].startOffset || playback_ip->lastSeekOffset > playback_ip->dataCache[cacheIndex].endOffset) {
1221                /* we have seeked or are trying to play from outside the current cache range, so our buffer duration is 0 */
1222                ipStatus->curBufferDuration = 0;
1223            }
1224            else {
1225                /* seek/play point is in the cache */
1226                ipStatus->curBufferDuration = ((playback_ip->dataCache[cacheIndex].endOffset - playback_ip->lastSeekOffset)*8*1000) / playback_ip->psi.avgBitRate;  /* in msec */
1227            }
1228        }
1229        ipStatus->numRecvTimeouts = playback_ip->numRecvTimeouts;
1230        ipStatus->serverClosed = playback_ip->serverClosed;
1231        ipStatus->httpStatusCode = playback_ip->statusCode;
1232
1233        if (B_PlaybackIp_HttpGetCurrentPlaybackPosition(playback_ip, &ipStatus->position) != B_ERROR_SUCCESS) {
1234            BDBG_MSG(("%s: Failed to determine the current playback position, setting it to 0\n", __FUNCTION__));
1235            ipStatus->position = 0;
1236        }
1237
1238#if 0
1239        BDBG_MSG(("%s: buffer duration: cur %d, max %d, state %d, closed %d, offsets: last seeked %lld, end %lld, start %lld, current position %u\n",
1240                    __FUNCTION__, ipStatus->curBufferDuration ,ipStatus->maxBufferDuration, ipStatus->ipState, playback_ip->serverClosed, playback_ip->lastSeekOffset, playback_ip->dataCache[cacheIndex].endOffset, playback_ip->dataCache[cacheIndex].startOffset, ipStatus->position));
1241#endif
1242#else
1243        BSTD_UNUSED(cacheIndex);
1244#endif
1245    }
1246
1247#ifdef LIVEMEDIA_SUPPORT
1248    if((playback_ip->protocol == B_PlaybackIpProtocol_eRtp) || (playback_ip->protocol == B_PlaybackIpProtocol_eRtsp)) {
1249        B_PlaybackIp_liveMediaSessionRange(playback_ip->lm_context, &ipStatus->position, &ipStatus->last);
1250        ipStatus->first = 0;
1251    }
1252#endif
1253
1254    rc = B_ERROR_SUCCESS;
1255    return rc;
1256}
1257
1258#ifndef B_HAS_SMS_GATEWAY
1259void print_av_pipeline_buffering_status(
1260    B_PlaybackIpHandle playback_ip
1261    )
1262{
1263    NEXUS_VideoDecoderStatus videoStatus;
1264    NEXUS_AudioDecoderStatus audioStatus;
1265    NEXUS_PlaybackStatus playbackStatus;
1266
1267    if (playback_ip->nexusHandles.videoDecoder) {
1268        if (NEXUS_VideoDecoder_GetStatus(playback_ip->nexusHandles.videoDecoder, &videoStatus) == NEXUS_SUCCESS) {
1269            BDBG_WRN(("Video Decoder Status: pts %u, fifoSize %d, fifoDepth %d, fullness %d%%",
1270                videoStatus.pts, videoStatus.fifoSize, videoStatus.fifoDepth, videoStatus.fifoSize?(videoStatus.fifoDepth*100)/videoStatus.fifoSize:0));
1271        }
1272    }
1273    if (playback_ip->nexusHandles.primaryAudioDecoder) {
1274        if (NEXUS_AudioDecoder_GetStatus(playback_ip->nexusHandles.primaryAudioDecoder, &audioStatus) == NEXUS_SUCCESS) {
1275            BDBG_WRN(("Audio Decoder Status: pts %u, fifoSize %d, fifoDepth %d, fullness %d%%",
1276                audioStatus.pts, audioStatus.fifoSize, audioStatus.fifoDepth, audioStatus.fifoSize?(audioStatus.fifoDepth*100)/audioStatus.fifoSize:0));
1277        }
1278    }
1279    if (playback_ip->nexusHandles.playback) {
1280        if (NEXUS_Playback_GetStatus(playback_ip->nexusHandles.playback, &playbackStatus) == NEXUS_SUCCESS) {
1281            BDBG_WRN(("Playback Status: PB buffer depth %d, size %d, fullness %d%%, played bytes %lld",
1282                    playbackStatus.fifoDepth, playbackStatus.fifoSize, (playbackStatus.fifoDepth*100)/playbackStatus.fifoSize, playbackStatus.bytesPlayed));
1283        }
1284    }
1285}
1286#endif
1287
1288/***************************************************************************
1289Summary:
1290This function returns the default and recommended values for the Playback IP App Lib
1291public settings. A pointer to a valid B_PlaybackIpSettings structure must be
1292provide or an error will be returned.
1293***************************************************************************/
1294B_PlaybackIpError B_PlaybackIp_GetDefaultSettings(
1295    B_PlaybackIpSettings *pSettings)
1296{
1297    if (NULL == pSettings)
1298        return B_ERROR_INVALID_PARAMETER;
1299    BKNI_Memset( pSettings, 0, sizeof(B_PlaybackIpSettings) );
1300
1301    pSettings->ipMode = B_PlaybackIpClockRecoveryMode_ePushWithPcrSyncSlip;
1302    pSettings->maxNetworkJitter = 300;
1303    pSettings->preChargeBuffer = false;
1304    pSettings->networkTimeout = HTTP_SELECT_TIMEOUT;
1305    pSettings->networkBufferSize = HTTP_DATA_CACHE_SIZE;
1306    pSettings->useNexusPlaypump = false;
1307    B_PlaybackIp_TtsThrottle_ParamsInit(&pSettings->ttsParams.throttleParams);
1308    return B_ERROR_SUCCESS;
1309}
1310
1311/***************************************************************************
1312Summary:
1313This function returns the current values for the Playback IP App Lib
1314public settings.
1315***************************************************************************/
1316B_PlaybackIpError B_PlaybackIp_GetSettings(
1317    B_PlaybackIpHandle playback_ip,
1318    B_PlaybackIpSettings *pSettings)
1319{
1320    if (NULL == pSettings)
1321        return B_ERROR_INVALID_PARAMETER;
1322
1323    BKNI_Memcpy(pSettings, &playback_ip->settings, sizeof(B_PlaybackIpSettings) );
1324    return B_ERROR_SUCCESS;
1325}
1326
1327/***************************************************************************
1328Summary:
1329This function updates the current values for the Playback IP App Lib
1330public settings.
1331***************************************************************************/
1332B_PlaybackIpError B_PlaybackIp_SetSettings(
1333    B_PlaybackIpHandle playback_ip,
1334    B_PlaybackIpSettings *pSettings)
1335{
1336    BERR_Code rc;
1337
1338    BDBG_ASSERT(playback_ip);
1339    if (NULL == pSettings)
1340        return B_ERROR_INVALID_PARAMETER;
1341
1342    /* update Nexus Handles if app has supplied them */
1343    if (pSettings->nexusHandlesValid) {
1344        if (pSettings->nexusHandles.playpump)
1345            playback_ip->nexusHandles.playpump = pSettings->nexusHandles.playpump;
1346        if (pSettings->nexusHandles.playback)
1347            playback_ip->nexusHandles.playback = pSettings->nexusHandles.playback;
1348        if (pSettings->nexusHandles.videoDecoder)
1349            playback_ip->nexusHandles.videoDecoder = pSettings->nexusHandles.videoDecoder;
1350        if (pSettings->nexusHandles.primaryAudioDecoder)
1351            playback_ip->nexusHandles.primaryAudioDecoder = pSettings->nexusHandles.primaryAudioDecoder;
1352        if (pSettings->nexusHandles.secondaryAudioDecoder)
1353            playback_ip->nexusHandles.secondaryAudioDecoder = pSettings->nexusHandles.secondaryAudioDecoder;
1354        if (pSettings->nexusHandles.stcChannel)
1355            playback_ip->nexusHandles.stcChannel = pSettings->nexusHandles.stcChannel;
1356    }
1357
1358    BDBG_MSG(("%s: preChargeBuffer %d, ipState %d", __FUNCTION__, pSettings->preChargeBuffer, playback_ip->playback_state));
1359    switch (playback_ip->playback_state) {
1360    case B_PlaybackIpState_ePlaying:
1361        if (pSettings->preChargeBuffer) {
1362            if (!playback_ip->psi.avgBitRate) {
1363                BDBG_ERR(("%s: Can't enable Runtime Buffering since we dont know the avg stream bitrate", __FUNCTION__));
1364                return B_ERROR_INVALID_PARAMETER;
1365            }
1366
1367            /* user set the preChargeBuffer flag, tell Http thread to start pre-charging work */
1368            playback_ip->preChargeBuffer = true;
1369            /* send event to let http thread know app would like it to start buffering */
1370            BKNI_SetEvent(playback_ip->newJobEvent);
1371
1372            /* now wait for http thread to acknowledge start of buffering */
1373            rc = BKNI_WaitForEvent(playback_ip->preChargeBufferEvent, HTTP_PRE_CHARGE_EVENT_TIMEOUT);
1374            if (rc == BERR_TIMEOUT) {
1375                BDBG_WRN(("%s: timed out for pre-charging complete event", __FUNCTION__));
1376                return B_ERROR_UNKNOWN;
1377            } else if (rc!=0) {
1378                BDBG_WRN(("%s: got error while trying to wait for pre-charging complete event, rc %d", __FUNCTION__, rc));
1379                return B_ERROR_UNKNOWN;
1380            }
1381            BDBG_WRN(("%s: Enabled pre-charging of network buffer", __FUNCTION__));
1382        }
1383        /* can't change any settings in playing state, we ignore the settings */
1384        return B_ERROR_SUCCESS;
1385    case B_PlaybackIpState_eBuffering:
1386        if (!pSettings->preChargeBuffer) {
1387            /* we are currently pre-charging and user wants us to stop pre-charging */
1388            playback_ip->preChargeBuffer = false;
1389            rc = BKNI_WaitForEvent(playback_ip->preChargeBufferEvent, HTTP_PRE_CHARGE_EVENT_TIMEOUT);
1390            if (rc == BERR_TIMEOUT) {
1391                BDBG_WRN(("%s: timed out for pre-charging complete event", __FUNCTION__));
1392                return B_ERROR_UNKNOWN;
1393            } else if (rc!=0) {
1394                BDBG_WRN(("%s: got error while trying to wait for pre-charging complete event, rc %d", __FUNCTION__, rc));
1395                return B_ERROR_UNKNOWN;
1396            }
1397            BDBG_WRN(("%s: Stopped pre-charging of network buffer", __FUNCTION__));
1398        }
1399        /* can't change any settings in buffering state, we ignore the settings */
1400        return B_ERROR_SUCCESS;
1401    break;
1402    default:
1403        if (pSettings->preChargeBuffer) {
1404            BDBG_ERR(("%s: IP Playback Channel is not yet setup to be able to pre-charge network buffer (current state %d)\n", __FUNCTION__, playback_ip->playback_state));
1405            return B_ERROR_INVALID_PARAMETER;
1406        }
1407        /* states other than ePlaying or eBuffering, update settings */
1408        if (pSettings->useNexusPlaypump)
1409            playback_ip->useNexusPlaypump = true;
1410        BKNI_Memcpy(&playback_ip->settings, pSettings, sizeof(B_PlaybackIpSettings) );
1411        return B_ERROR_SUCCESS;
1412    }
1413}
1414
1415/***************************************************************************
1416Summary:
1417This function detects if the stream is TTS or not
1418***************************************************************************/
1419B_PlaybackIpError B_PlaybackIp_DetectTts(
1420    B_PlaybackIpHandle playback_ip,
1421    bool *isTts
1422    )
1423{
1424    int i;
1425    int ret;
1426    fd_set fds;
1427    struct timeval socketTimeout;
1428    struct sockaddr *from;
1429    socklen_t   fromLen;
1430    int bytesRecv = 0;
1431    B_PlaybackIpError rc = B_ERROR_SUCCESS;
1432    int offset = 0;
1433    int pktCount = 0;
1434    int tsHdrCount = 0;
1435    char *buf = &playback_ip->temp_buf[0];
1436
1437#ifdef B_HAS_NETACCEL
1438    STRM_SockRecvParams_t sockRecvParams;
1439    STRM_SockSetFilterState_t filterState;
1440
1441    memset(&sockRecvParams, 0, sizeof(sockRecvParams));
1442    sockRecvParams.pktsPerRecv = 1;
1443
1444    switch(playback_ip->protocol) {
1445    case B_PlaybackIpProtocol_eUdp:
1446    sockRecvParams.hdrOffset = sizeof(struct udp_hdr);
1447        break;
1448    case B_PlaybackIpProtocol_eRtp:
1449    case B_PlaybackIpProtocol_eRtpNoRtcp:
1450        sockRecvParams.hdrOffset = 0;
1451        buf = &playback_ip->temp_buf[8];
1452        break;
1453    default:
1454        sockRecvParams.hdrOffset = 0;
1455        break;
1456    }
1457    if (setsockopt(playback_ip->socketState.fd, SOCK_BRCM_DGRAM, STRM_SOCK_RECV_PARAMS, &sockRecvParams, sizeof(sockRecvParams)))
1458    {
1459        BDBG_ERR(("%s: setsockopt() ERROR:", __FUNCTION__));
1460        return B_ERROR_OS_ERROR;
1461    }
1462#endif
1463
1464    BDBG_WRN(("%s: entering: %p", __FUNCTION__, playback_ip));
1465
1466    if( IN_MULTICAST(ntohl(playback_ip->socketState.local_addr.sin_addr.s_addr)) ) {
1467        from = (struct sockaddr *) &playback_ip->socketState.remote_addr;
1468        fromLen = sizeof(struct sockaddr);
1469    }
1470    else {
1471        from = NULL;
1472        fromLen = 0;
1473    }
1474
1475    for(i=0; ; i++) {
1476        if(i>=20) {
1477            rc = B_ERROR_UNKNOWN;
1478            goto error;
1479        }
1480
1481        bytesRecv = recvfrom(playback_ip->socketState.fd,
1482                              (void *)playback_ip->temp_buf,
1483                              IP_MAX_PKT_SIZE,
1484                              0,
1485                              from,
1486                              &fromLen);
1487
1488        if (bytesRecv==0) {
1489            BDBG_WRN(("server has closed connection"));
1490            goto wait;
1491        } else if (bytesRecv > 0) {
1492            /* got some data */
1493            goto done;
1494        } /* bytesRecv < 0 */
1495
1496        if (errno == EINTR) {
1497            continue;
1498        }
1499#if defined(__vxworks)
1500        else if(errno != EWOULDBLOCK) {
1501            BDBG_ERR(("recvfrom error"));
1502        }
1503#else
1504        else if (errno != EAGAIN) {
1505            BDBG_ERR(("recvfrom error"));
1506            /* JJ - removed code: this is a normal condition that can occur when the server is overloaded */
1507        }
1508#endif
1509
1510wait:
1511        /* no data received: wait for some */
1512        FD_ZERO(&fds);
1513        FD_SET(playback_ip->socketState.fd, &fds);
1514        socketTimeout.tv_sec = 0;
1515        socketTimeout.tv_usec = IP_RECV_TIMEOUT_USEC;
1516        /* BDBG_MSG_FLOW(("select")); */
1517        ret = select(playback_ip->socketState.fd+1, &fds, NULL, NULL, &socketTimeout);
1518
1519        if (ret == 0) {
1520            BDBG_WRN(("Receive timeout"));
1521        } else if (ret<0 && errno != EINTR) {
1522            BDBG_ERR(("select error"));
1523            rc = B_ERROR_UNKNOWN;
1524            goto error;
1525        }
1526    }
1527
1528done:
1529
1530/* JJ - debug */
1531#if 0
1532    BDBG_WRN(("0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
1533              buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9],buf[10],buf[11],buf[12],buf[13],buf[14],buf[15]));
1534#endif
1535
1536    switch(playback_ip->protocol) {
1537    case B_PlaybackIpProtocol_eUdp:
1538        offset = 0;
1539        break;
1540    case B_PlaybackIpProtocol_eRtp:
1541    case B_PlaybackIpProtocol_eRtpNoRtcp:
1542    case B_PlaybackIpProtocol_eRtsp:
1543        {
1544            int cc;
1545            int ext_len = 0;
1546            bool ext = false;
1547
1548            /* b_play_ip_parse_rtp_header(playback_ip->temp_buf); */
1549            if(((buf[0] & 0xC0) >> 6) != 2) goto error;
1550            if(buf[0] & 0x10) ext = true;
1551            cc = buf[0] & 0x0F;
1552            offset = 12+(cc*4);
1553            if(ext) {
1554                ext_len = ((buf[offset+2]<<8)+buf[offset+3]*4)+4;
1555                offset += ext_len;
1556            }
1557            BDBG_MSG(("RTP header size: %d", offset));
1558        }
1559        break;
1560    default:
1561        BDBG_WRN(("Bad protocol"));
1562        break;
1563    }
1564
1565#ifdef B_HAS_NETACCEL
1566    switch(playback_ip->protocol) {
1567    case B_PlaybackIpProtocol_eUdp:
1568        break;
1569    case B_PlaybackIpProtocol_eRtp:
1570    case B_PlaybackIpProtocol_eRtpNoRtcp:
1571        bytesRecv -= 8;
1572        break;
1573    default:
1574        break;
1575    }
1576#endif
1577
1578    for(i=offset; i<bytesRecv; i+=188) {
1579        pktCount++;
1580        if(buf[i] == 0x47) {
1581            tsHdrCount++;
1582        }
1583    }
1584    if(tsHdrCount==pktCount) {
1585        /* it's a TS stream */
1586        BDBG_MSG(("it's a TS stream"));
1587        *isTts = false;
1588    }
1589    else {
1590        pktCount = 0;
1591        tsHdrCount = 0;
1592        for(i=offset; i<bytesRecv; i+=192) {
1593            pktCount++;
1594            if(buf[i+4] == 0x47) {
1595                tsHdrCount++;
1596            }
1597        }
1598        if(tsHdrCount==pktCount) {
1599            /* it's a TTS stream */
1600            BDBG_MSG(("it's a TTS stream"));
1601            *isTts = true;
1602        }
1603        else {
1604            BDBG_WRN(("TS/TTS auto-detect fail!"));
1605            *isTts = false;
1606        }
1607    }
1608
1609error:
1610
1611#ifdef B_HAS_NETACCEL
1612    /* now disable the net dma filter */
1613    memset(&filterState, 0, sizeof(filterState));
1614    filterState.filterEnable = 0;
1615    sockRecvParams.pktsPerRecv = 1;
1616
1617    if (setsockopt(playback_ip->socketState.fd, SOCK_BRCM_DGRAM, STRM_SOCK_SET_FILTER_STATE, &filterState, sizeof(filterState)))
1618    {
1619        BDBG_ERR(("%s: setsockopt() ERROR:", __FUNCTION__));
1620        return B_ERROR_OS_ERROR;
1621    }
1622
1623    /* TODO: may need to drain any remaining packets from the recvq or */
1624    /* throw away 1 queue size worth (~256) initial packets in B_PlaybackIp_RtpProcessing() */
1625#endif
1626
1627    return rc;
1628}
1629
1630#endif /* LINUX || VxWorks */
Note: See TracBrowser for help on using the repository browser.