source: svn/newcon3bcm2_21bu/BSEAV/api/src/nexus/bsettop_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: 58.5 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2003-2010, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bsettop_playback_ip.c $
11 * $brcm_Revision: 55 $
12 * $brcm_Date: 4/16/10 6:09p $
13 *
14 * Module Description:
15 *
16 * File implements the Settop API Shim layer for Playback IP Interface.
17 * It contains the interface definition of the legacy Settop API implementation
18 * (BSEAV/api/src/pvr/bsettop_playback_ip.c) and makes calls into Nexus IP APPlib.
19 *
20 * Revision History:
21 *
22 * $brcm_Log: /BSEAV/api/src/nexus/bsettop_playback_ip.c $
23 *
24 * 55   4/16/10 6:09p ssood
25 * SW7420-561: Coverity fix
26 *
27 * 54   4/2/10 5:54p ssood
28 * SW7420-561: add support to handle large URLs (HTML5 URLs can be over
29 * 256bytes) + RTSP fixes
30 *
31 * 53   3/4/10 3:18p ssood
32 * SW7420-561: merge to mainline
33 *
34 * SW7420-561/1   2/16/10 10:11a ssood
35 * SW7420-561: initial cut of new APIs to meet Media Browser, DMR, &
36 * Philips RTSP requirements
37 *
38 * 51   12/23/09 3:08p erickson
39 * SW7420-516: convert non-error BDBG_ERR to BDBG_WRN
40 *
41 * 50   10/1/09 11:00a jjordan
42 * SW7405-3107: add IP recv timeout status to Settop API
43 *
44 * 49   9/1/09 6:24p lwhite
45 * SW7405-2176: Configure default SslInit field
46 *
47 * 48   8/24/09 3:23p ssood
48 * SW7405-1689: adapting server based trickmodes to Nexus playback changes
49 * due to OTF support
50 *
51 * 47   8/14/09 7:35a ssood
52 * PR43746: Coverity fix
53 *
54 * 46   7/29/09 6:19p ssood
55 * PR43746: extend IP trick modes to support Disconnect & Seek based pause
56 * operations
57 *
58 * 46   7/29/09 6:14p ssood
59 * PR43746: extend IP trick modes to support Disconnect And Seek based
60 * paused operations (DLNA requirement)
61 *
62 * 46   7/29/09 6:14p ssood
63 * PR43746: extend IP trick modes to support Disconnect And Seek based
64 * paused operations (DLNA requirement)
65 *
66 * 45   7/28/09 3:23p lwhite
67 * PR55693: Fixed DTCP/IP close
68 *
69 * 44   7/28/09 11:52a lwhite
70 * PR55693: Added DTCP/IP intialization
71 *
72 * 43   7/22/09 4:27p ssood
73 * PR43746: return current timestamp & position info to allow playbackbar
74 * to display correct position during server based trick modes
75 *
76 * 42   7/21/09 4:18p ssood
77 * PR43746: Further work for Server based HTTP trick mode support
78 *
79 * 41   7/16/09 1:04p ssood
80 * PR43746: Add Server based HTTP trick mode support
81 *
82 * 41   7/16/09 1:03p ssood
83 * PR43746: Add Server based HTTP trick mode support
84 *
85 * 41   7/16/09 12:59p ssood
86 * PR43746: Add Server based HTTP trick mode support
87 *
88 * 41   7/16/09 12:59p ssood
89 * PR43746: Add Server based HTTP trick mode support
90 *
91 * 40   7/14/09 3:28p leisun
92 * PR 55693: fix segfault when server is not running and channel is tuned
93 * to DTCP
94 *
95 * 39   7/14/09 2:17p leisun
96 * PR 55693: Moved DtcpIpInit() to socketOpen
97 *
98 * 38   7/13/09 11:50a leisun
99 * PR 55693: Re-design interfaces, and other cleanups
100 *
101 * 37   7/1/09 6:30p ssood
102 * PR53773: handle case where DTCP/IP library init may fail
103 *
104 * 36   6/29/09 2:10p lwhite
105 * PR53773: Fixed SSL initialization
106 *
107 * 35   6/26/09 1:46p mward
108 * PR 56277: Coverity Defect ID:16457 UNINIT
109 *
110 * 34   6/26/09 9:29a lwhite
111 * PR53773: Reset SSL context during close
112 *
113 * 33   6/25/09 7:05p ssood
114 * PR53773: Passing in M2M DMA handle for DTCP/IP encryption/decryption
115 * purposes
116 *
117 * 32   6/25/09 10:43a ssood
118 * PR53773: Adding support for setting up DTCP/IP Encrypted HTTP session
119 *
120 * 31   6/25/09 12:58a ssood
121 * PR53773: fixing a compilation error
122 *
123 * 30   6/24/09 6:56p lwhite
124 * PR53773: Adding DTCP/IP + SSL Support in Brutus
125 *
126 * 29   5/26/09 11:50a ssood
127 * PR53773: added debug code to track a crash during quit
128 *
129 * 28   5/25/09 11:33p ssood
130 * PR55325: Add support for pre-charging network buffer for HTTP playback
131 *
132 * 27   3/10/09 3:08p ssood
133 * PR50311: Adding support for pause & loop back
134 *
135 * 26   3/9/09 6:31p lwhite
136 * PR50311: added support for VOB playback
137 *
138 * 25   3/2/09 6:06p ssood
139 * PR50311: cleaned up some left out debug code
140 *
141 * 24   3/2/09 3:19p ssood
142 * PR50311: using proper define for updating the Nexus playpump settings
143 *
144 * 23   3/2/09 2:48p ssood
145 * PR50311: another brutus quit crash when we quit from a HTTP channel
146 * where connect attempt had failed
147 *
148 * 22   3/2/09 9:23a ssood
149 * PR50311: brutus quit crashes when we quit from a HTTP channel where
150 * connect attempt had failed
151 *
152 * 21   3/1/09 10:38a ssood
153 * PR50311: added support for HTTP playback of content w/ extra 4 byte
154 * DLNA timestamps
155 *
156 * 20   11/13/08 5:52p lwhite
157 * PR47685: Coverity fixes
158 *
159 * 19   11/7/08 5:35p ssood
160 * PR48146: fixing another quit related crash
161 *
162 * 18   11/5/08 7:46p ssood
163 * PR48146: fixed a core dump during failure path
164 *
165 * 17   11/5/08 3:27p ssood
166 * PR48146: added support needed for MP4/ASF playback
167 *
168 * 16   10/31/08 12:30p jjordan
169 * PR47230: Add TTS Pacing
170 *
171 * 15   10/15/08 9:22a erickson
172 * PR42739: remove ERR from bplayback_ip_open if IP not on. this is a
173 * normal call to discover IP capabilities.
174 *
175 * 14   10/13/08 5:48p ssood
176 * PR47521: need audio decoder handles for flushing AV pipeline during a
177 * discontinuity due to packet loss
178 *
179 * 13   10/3/08 3:09p lwhite
180 * PR42739: Added RTSP timeline support
181 *
182 * 12   9/19/08 5:05p vishk
183 * PR 47150: Coverity Issues.
184 *
185 * 11   8/11/08 12:49p ssood
186 * PR45431: added cleanup code for ASF playback in error path
187 *
188 * 10   8/11/08 10:13a ssood
189 * PR45431: Add HTTP playback support for ASF content
190 *
191 * 9   8/5/08 12:54p erickson
192 * PR45361: fix c89 builds
193 *
194 * 8   7/28/08 3:30p ssood
195 * PR42739: further changes for supporting example app for IP Applib
196 *
197 * 7   7/21/08 4:03p ssood
198 * PR42739: code changes to simplify ip app lib interface
199 *
200 * 6   7/10/08 3:46p ssood
201 * PR42739: added support for RTSP trickmodes
202 *
203 * 5   6/24/08 4:10p erickson
204 * PR44107: rename to TrickMode
205 *
206 * 4   6/18/08 7:40a ssood
207 * PR43744: Channel Change script fails on IP channels after 5-10min
208 *
209 * 3   6/15/08 7:01p ssood
210 * PR42739: Fixed a core dump due to derefercing the decoder pointer when
211 * it may not be set in the bstream
212 *
213 * 2   6/13/08 7:23p ssood
214 * PR42739: Enabling HTTP & RTSP support
215 *
216 * 1   6/11/08 7:28p ssood
217 * PR42739: Settop API Shim layer implementation of Playback IP Interface
218 *
219 *
220 ***************************************************************************/
221#include "bsettop_impl.h"
222#include <bstd.h>
223#include "bsettop_os.h"
224
225 /*
226    Note this file is currently only compiled for LINUX platforms. Even though it
227    has VxWorks & WinCE related hash defines, the code needs to more porting
228    work for these OS platforms.
229
230    If the feature isn't compiled in, then the only functions in this .c file
231    should be the public stubs.
232  */
233
234BDBG_MODULE(playback_ip);
235#if defined(B_HAS_IP)
236#include <bkni.h>
237#include <bkni_multi.h>
238#include <fcntl.h>
239
240#ifndef _WIN32_WCE
241
242#ifdef __vxworks
243  #include <sysLib.h>
244  #include <string.h>
245  #include <stdlib.h>
246  #include <logLib.h>
247  #include <sys/times.h>
248  #include <selectLib.h>
249  #include <taskLib.h>
250  #include <semLib.h>
251  #include <sys/ioctl.h>
252  #include <hostLib.h>
253#else
254  #include <memory.h>
255  #include <pthread.h>
256  #include <sys/time.h>
257#endif
258
259#include <stdlib.h>
260#include <sys/socket.h>
261#include <netinet/in.h>
262#include <arpa/inet.h>
263#include <unistd.h>
264#include <errno.h>
265#include <signal.h>
266#include <stdio.h>
267#include <netdb.h>
268#else /* _WIN32_WCE */
269#include <windows.h>
270    typedef HANDLE pthread_t;
271    #define close(x) closesocket(x)
272    unsigned long errno = 0;
273    #define EINTR -1
274#endif /* _WIN32_WCE */
275
276#include "bsettop_playpump.h"
277#include "bsettop_playback_ip.h"
278/* SSOOD #include "bsettop_pvr_priv.h"*/
279#include "bpool.h"
280#include "barena.h"
281#include "bioatom.h"
282#include "blst_queue.h"
283#include "brtp_spf.h"
284#include "b_playback_ip_lib.h"
285#ifdef B_HAS_DTCP_IP
286#include "b_dtcp_applib.h"
287#endif
288
289#ifdef B_HAS_NETACCEL
290#include "bnetaccel_info.h"
291#endif
292
293#define IP_MAX_ITEMS                    128         /* max number of packets that can be pending in the filter */
294#define IP_MAX_PKT_SIZE                 1500
295#define RTP_PAYLOAD_TYPE_MP2T           33          /* only support PT=33 */
296#define MAX_READ                        160
297#define TEST_BUFFER_SIZE                65536
298#define IP_MAX_PWM_VALUE                0x7FFF
299#define IP_MIN_PWM_VALUE                (-IP_MAX_PWM_VALUE)
300#define IP_POSTCHARGE_PERIOD_MSEC       5000
301#define IP_MAX_DECODE_POLLS             10
302#define IP_UNDERFLOW_PERIOD_MSEC        100
303
304/* slew 270 Hz (10 ppm) @ 100 Hz/sec,
305 * in steps of 10Hz
306 */
307#define IP_PWM_STEP_PERIOD              100         /* 0.1 second */
308#define IP_PWM_STEP_SIZE                75          /* 10Hz (Hz/bit = 4386/0x7fff = 0.13385 Hz/bit, ie. 0.00494 ppm/bit) */
309#define IP_PWM_STEPS_PER_VIOLATION      27
310
311#if defined (LINUX)
312  #define STATUS_REPORTING_CONSTANT     1
313  #define NEW_RMEM_MAX                  (1024*200)
314#else
315  #define STATUS_REPORTING_CONSTANT     0
316#endif
317
318#if 0
319#define BDBG_MSG_FLOW(x)  printf x; printf("\n");
320#else
321#define BDBG_MSG_FLOW(x)
322#endif
323
324
325
326#ifdef __vxworks
327  #if !defined (USE_PTHREAD)
328    typedef int pthread_t;
329  #endif
330#endif
331
332/**
333Summary:
334    State of bplayback_ip
335**/
336typedef enum bplayback_ip_state {
337    bplayback_ip_state_stopped,
338    bplayback_ip_state_stopping,
339    bplayback_ip_state_playing,
340    bplayback_ip_state_paused,
341    bplayback_ip_state_trickmode
342} bplayback_ip_state;
343
344typedef enum bplayback_ip_buffer_state {
345    bplayback_ip_buffer_precharging,
346    bplayback_ip_buffer_postcharging,
347    bplayback_ip_buffer_playing,
348    bplayback_ip_buffer_overflowing,
349    bplayback_ip_buffer_underflowing
350} bplayback_ip_buffer_state;
351
352struct b_playback_ip_item;
353BLST_Q_HEAD(b_playback_ip_item_queue, b_playback_ip_item);
354
355struct udp_hdr {
356    unsigned short   source;
357    unsigned short   dest;
358    unsigned short   len;
359    unsigned short   checksum;
360};
361
362#if !defined(B_HAS_NETACCEL) || defined(B_HAS_PLAYPUMP_IP)
363#define PKTS_PER_READ 1
364#else
365#define PKTS_PER_READ 32
366#endif
367struct b_playback_ip_item {
368    BLST_Q_ENTRY(b_playback_ip_item) item_queue;
369    BLST_Q_ENTRY(b_playback_ip_item) active_item_queue;
370#if defined(B_HAS_PLAYPUMP_IP) || !defined(B_HAS_NETACCEL)
371    uint8_t data[IP_MAX_PKT_SIZE];  /* max UDP packet size (assuming no fragmentation & 1500 byte MTU) */
372#else
373    uint8_t *data;                  /* max UDP packet size (assuming no fragmentation & 1500 byte MTU) */
374#endif
375    bplayback_ip_t playback_ip;
376#if !defined(B_HAS_PLAYPUMP_IP) && defined(B_HAS_NETACCEL)
377    int item_index;
378    bool block_end;
379#endif
380};
381
382/* the playback structure */
383struct bplayback_ip {
384    /* this must be the 1st field in this structure */
385    struct bplayback            playback;
386#if 0
387    bplayback_iface             iface; /* bplayback_iface shall be the first member in the structure */
388    NEXUS_PlaybackHandle        playback;
389    bplayback_params            params;
390    bstream_t                   stream;
391    bstream_t                   bstream_alloc;
392    bplayback_file_t            socket;
393    NEXUS_FilePlayHandle        file;
394#endif
395    bplayback_ip_state          playback_state;
396    bplaypump_t                 pump;
397    bplaypump_params            pumpparams;
398    bplayback_ip_buffer_scheme  ip_buffer_scheme;
399    bsettop_ip_protocol         protocol;
400    B_PlaybackIpHandle          playback_ip_handle;
401    bplayback_socket_params     socket_params; /* cached socket params */
402    void*                       security_ctx;     /* security context - currently only used by SSL*/
403    bool                        transportTimeStampEnabled;
404    bool                        handlesSet;     /* set when nexus handles are passed to IP Applib */
405    void*                       dtcp_ctx;
406    void*                       akeHandle;
407    int                         scaleListEntries; /* number of entries in the scale list provided by the server, 0 if none */
408    float                       scaleList[MAX_SCALE_LIST_ENTRIES]; /* scale list provided by the server, 0 if none */
409    int                         firstPositiveScaleIndex;
410#if 0
411    /* TODO: old fields, cleanup once all features are added to IP Shim layer */
412    BKNI_EventHandle            playback_halt_event;
413    BKNI_EventHandle            read_callback_event;
414    b_timer_t                   pwm_slew_timer;
415    long                        current_pwm_value;
416    unsigned int                num_pwm_steps_pending;
417    bool                        forcing_pwm_slow;
418    bool                        buffer_fill_period_expired;
419    bool                        ip_recording;
420    unsigned int                payload_size;
421    bool                        recv_timeout_event;
422#ifdef LIVEMEDIA_SUPPORT
423    void                        *lm_context;
424    /* bplayback_lm_callbacks       lm_callbacks; */
425#endif
426#ifdef B_RECORD_IP
427    FILE *fp_save;
428#endif
429    b_task_t                    playback_task;
430    bdecode_status              decode_status;
431    char                        temp_buf[IP_MAX_PKT_SIZE];
432
433    void *                      buffer;
434    size_t                      buffer_size;
435    struct b_playback_ip_item   *item;
436#if !defined(B_HAS_PLAYPUMP_IP) && defined(B_HAS_NETACCEL)
437    uint8_t                     *item_mem;
438#endif
439    struct b_playback_ip_item_queue active_item; /* items pending in filter */
440    struct b_playback_ip_item_queue free_item; /* items ready for use */
441    unsigned long               byte_count;
442    batom_factory_t             factory;
443    batom_pipe_t                pipe_out;   /* pipe data out from playback to filter */
444    batom_pipe_t                pipe_in;    /* pipe data into playback from filter */
445    brtp_t                      rtp;        /* the RTP filter */
446    volatile bool               socket_flush;  /* Set by the controller to request socket evacuate */
447    int                         initial_data_len;
448    unsigned int                first_pts;  /* Cached First PTS value sent by the server */
449    unsigned int                cur_pts;    /* current pts value passed by the application */
450    unsigned int                speed;      /* new speed value passed by the application */
451    b_time_t                    start_time;
452#endif
453};
454
455static void bplayback_ip_params_init(bplayback_params *params, bplayback_t playback);
456static bresult bplayback_ip_get_status(bplayback_t playback, bplayback_status *status);
457static bresult bplayback_ip_get_trickmode_by_rate(bplayback_t playback, int rate, bplayback_trickmode_params *trickmode);
458void bplayback_ip_socket_close(bplayback_t playback);
459#define abs(x) (x>0 ? x : -x)
460#define MAX_BUFFER_SIZE (1316 * PKTS_PER_READ)
461
462/*
463Summary:
464    playback IP init.
465*/
466void bplayback_ip_p_init(void)
467{
468#if defined(B_DTCP_IP_HW_ENCRYPTION) || defined(B_DTCP_IP_HW_DECRYPTION)
469    if(DtcpInitHWSecurityParams((void *)g_dma.hDma) != BERR_SUCCESS)
470    {
471        BDBG_ERR(("%s: Failed to Initialize Dtcp/Ip HW Secruity\n", __FUNCTION__));
472    }
473#endif
474}
475
476/*
477Summary:
478    playback IP uninit.
479*/
480void bplayback_ip_p_uninit(void)
481{
482#if defined(B_DTCP_IP_HW_ENCRYPTION) || defined(B_DTCP_IP_HW_DECRYPTION)
483    DtcpCleanupHwSecurityParams();
484#endif
485}
486
487/*
488Summary:
489    Open an IP playback channel.
490*/
491bplayback_t bplayback_ip_p_open(void)
492{
493    bplayback_ip_t playback_ip;
494    B_PlaybackIpOpenSettings pSettings;
495
496    playback_ip = BKNI_Malloc(sizeof(struct bplayback_ip));
497    if (!playback_ip)
498        return NULL;
499    BKNI_Memset(playback_ip, 0, sizeof(struct bplayback_ip));
500    BDBG_MSG(("%s: Allocated %d bytes\n", __FUNCTION__, sizeof(struct bplayback_ip)));
501
502    /* initialize interface */
503    bplayback_iface_init(&playback_ip->playback.iface);
504
505    playback_ip->playback.iface.params_init = bplayback_ip_params_init;
506    playback_ip->playback.iface.start = bplayback_ip_start;
507
508    playback_ip->playback.iface.pause = bplayback_ip_pause;
509    playback_ip->playback.iface.play = bplayback_ip_play;
510    playback_ip->playback.iface.trickmode = bplayback_ip_trickmode;
511    playback_ip->playback.iface.get_trickmode_by_rate = bplayback_ip_get_trickmode_by_rate;
512
513    playback_ip->playback.iface.stop = bplayback_ip_stop;
514    playback_ip->playback.iface.get_status = bplayback_ip_get_status;
515    playback_ip->playback.iface.close = bplayback_ip_close;
516    playback_ip->playback.iface.goto_index = bplayback_ip_goto_index;
517
518    memset(&pSettings, 0, sizeof(pSettings));
519    playback_ip->playback_ip_handle = B_PlaybackIp_Open(NULL);
520    if (playback_ip->playback_ip_handle == NULL) {
521        BDBG_ERR(("Failed to Setup the IP Playback Channel\n"));
522    }
523    playback_ip->playback_state = bplayback_ip_state_stopped;
524    playback_ip->handlesSet = false;
525    return (bplayback_t)&playback_ip->playback.iface;
526
527}
528
529/*
530Summary:
531    Close a playback channel.
532*/
533void bplayback_ip_p_close(
534    bplayback_t playback /* Handle returned by bplayback_ip_open */
535    )
536{
537    bplayback_ip_t playback_ip = (bplayback_ip_t) playback;
538
539    BDBG_MSG(("%s: \n", __FUNCTION__));
540    if(playback_ip->playback_state != bplayback_ip_state_stopped)
541        bplayback_ip_stop(playback);
542
543    if (playback_ip->playback.source) {
544        bplayback_ip_socket_close(playback);
545        playback_ip->playback.source = NULL;
546    }
547
548    B_PlaybackIp_Close(playback_ip->playback_ip_handle);
549    playback_ip->playback_ip_handle = NULL;
550
551    BKNI_Free(playback_ip);
552}
553
554void bplayback_ip_params_init(bplayback_params *params, bplayback_t playback)
555{
556    BSTD_UNUSED(playback);
557    params->ip_params.buffer_scheme = bplayback_ip_buffer_scheme_precharge;
558    params->ip_params.use_live_playback_mode = true;
559    params->timestamp_enabled =  false;
560    params->tts_params.auto_detect =  true;
561    params->tts_params.pacing_max_error = 527;
562    params->tts_params.init_buf_depth = 600000;
563    params->tts_params.min_buf_depth = 0;
564    params->tts_params.max_buf_depth = 1000000;
565    params->tts_params.max_clock_mismatch = 100;
566}
567
568/*
569Summary:
570  Configures IP playback to be started.
571
572Description:
573    If bplayback_ip_start succeeds, it returns a digital stream handle which can
574    be decoded or recorded.
575*/
576bstream_t bplayback_ip_start(
577    bplayback_t             playback,
578    bplaypump_t             playpump,
579    const bstream_mpeg      *mpeg,
580    bplayback_file_t        source,
581    const bplayback_params  *params)
582{
583    bplayback_ip_t playback_ip = (bplayback_ip_t) playback;
584    NEXUS_Error rc;
585    B_PlaybackIpSettings playback_ip_settings;
586    B_PlaybackIpSessionStartSettings ipStartSettings;
587    B_PlaybackIpSessionStartStatus ipStartStatus;
588    bool is_tts;
589
590    BDBG_MSG(("%s: entering: playback %p\n", __FUNCTION__, (void *)playback));
591
592    playback_ip->pump = playpump;
593    playback_ip->playback.source = source;
594    playback_ip->ip_buffer_scheme = params->ip_params.buffer_scheme;
595
596
597    BDBG_OBJECT_ASSERT(playpump, bplaypump);
598    bplaypump_params_init(&playback_ip->pumpparams, playback_ip->pump);
599
600    if (playback_ip->protocol == bsettop_ip_protocol_http) {
601        NEXUS_PlaybackSettings playbackSettings;
602
603        BDBG_MSG(("%s: Starting Nexus Playback..., nexus playback %p, playpump %p \n",
604                    __FUNCTION__, (void *)playback_ip->playback.nPlayback, (void *)playpump->nPlaypump));
605        NEXUS_Playback_GetSettings(playback_ip->playback.nPlayback, &playbackSettings);
606        playbackSettings.playpump = playpump->nPlaypump;
607        playbackSettings.playpumpSettings.transportType = b_mpegtype2nexus(mpeg->mpeg_type);
608        playbackSettings.playpumpSettings.mode = NEXUS_PlaypumpMode_eFifo;
609        playbackSettings.endOfStreamAction = NEXUS_PlaybackLoopMode_eLoop; /* loop content */
610        if (playback_ip->transportTimeStampEnabled) {
611            playbackSettings.playpumpSettings.timestamp.type = NEXUS_TransportTimestampType_eMod300;
612            playbackSettings.playpumpSettings.timestamp.pacing = false;
613        }
614        rc = NEXUS_Playback_SetSettings(playback_ip->playback.nPlayback, &playbackSettings);
615        if (rc) {
616            BDBG_ERR(("%s: Failed to update the Nexus Playback Settings, rc = %d\n", __FUNCTION__, rc));
617            return NULL;
618        }
619
620        /* Now open the bstream */
621        playback_ip->playback.stream = bstream_p_open(NULL, NULL, playback, 0, mpeg);
622        if (!playback_ip->playback.stream) {
623            BDBG_ERR(("%s: Failed to create the stream\n", __FUNCTION__));
624            return NULL;
625        }
626        playback_ip->pump->stream = playback_ip->playback.stream;
627
628        /* Note: Nexus playback is started by the bdecode_start -> bplayback_p_start() */
629    }
630    else {
631        playback_ip->pumpparams.is_playback_ip = true;
632        playback_ip->pumpparams.use_live_playback_mode = params->ip_params.use_live_playback_mode;
633        if(params->timestamp_active && params->timestamp_enabled) {
634            /* a TTS */
635            playback_ip->pumpparams.timestamp_active = true;
636            playback_ip->pumpparams.timestamp_enabled = true;
637        }
638        else if(params->tts_params.auto_detect) {
639            if(B_PlaybackIp_DetectTts(playback_ip->playback_ip_handle, &is_tts)!=B_ERROR_SUCCESS) {
640                BDBG_ERR(("Failed to detect TTS/non-TTS"));
641                return NULL;
642            }
643            if(is_tts) {
644                /* a TTS */
645                playback_ip->pumpparams.timestamp_active = true;
646                playback_ip->pumpparams.timestamp_enabled = true;
647                BDBG_WRN(("B_PlaybackIp_DetectTts() returned is_tts=true"));
648            }
649            else {
650                /* not a TTS */
651                playback_ip->pumpparams.timestamp_active = params->timestamp_active;
652                playback_ip->pumpparams.timestamp_enabled = params->timestamp_enabled;
653                BDBG_WRN(("B_PlaybackIp_DetectTts() returned is_tts=false"));
654            }
655        }
656        else {
657            /* not a TTS */
658            playback_ip->pumpparams.timestamp_active = params->timestamp_active;
659        playback_ip->pumpparams.timestamp_enabled = params->timestamp_enabled;
660        }
661
662        B_PlaybackIp_GetSettings(playback_ip->playback_ip_handle, &playback_ip_settings);
663
664        if(playback_ip->pumpparams.timestamp_enabled) {
665            playback_ip_settings.ipMode = B_PlaybackIpClockRecoveryMode_ePushWithTtsNoSyncSlip;
666            playback_ip->pumpparams.pacing_max_error = params->tts_params.pacing_max_error;
667            BDBG_WRN(("Setup for TTS stream"));
668        }
669        else {
670            /* TODO: support PCR pacing */
671#if 0
672            playback_ip->init_buf_depth = params->tts_params.init_buf_depth;
673            playback_ip->pcr_pid = mpeg->pcr_pid;
674#endif
675            if(playback_ip->pumpparams.timestamp_active) {
676                playback_ip_settings.ipMode = B_PlaybackIpClockRecoveryMode_ePushWithTtsNoSyncSlip;
677                BDBG_WRN(("Setup for non-TTS stream (PCR-pacing version)"));
678            }
679            else {
680                playback_ip_settings.ipMode = B_PlaybackIpClockRecoveryMode_ePushWithPcrSyncSlip;
681                BDBG_WRN(("Setup for non-TTS stream (non-PCR-pacing version)"));
682            }
683        }
684
685        if(playback_ip_settings.ipMode == B_PlaybackIpClockRecoveryMode_ePushWithTtsNoSyncSlip) {
686            playback_ip_settings.ttsParams.autoDetect = params->tts_params.auto_detect;
687            playback_ip_settings.ttsParams.pacingMaxError = params->tts_params.pacing_max_error;
688            playback_ip_settings.ttsParams.throttleParams.initBufDepth = params->tts_params.init_buf_depth;
689            playback_ip_settings.ttsParams.throttleParams.maxBufDepth = params->tts_params.max_buf_depth;
690            playback_ip_settings.ttsParams.throttleParams.minBufDepth = params->tts_params.min_buf_depth;
691            playback_ip_settings.ttsParams.throttleParams.maxClockMismatch = params->tts_params.max_clock_mismatch;
692            BDBG_WRN(("auto_detect: %d, init_buf_depth: %d, max_buf_depth: %d, min_buf_depth: %d, pacing_max_error: 0x%x, max_clock_mismatch: %d",
693                      params->tts_params.auto_detect,
694                      params->tts_params.init_buf_depth,
695                      params->tts_params.max_buf_depth,
696                      params->tts_params.min_buf_depth,
697                      params->tts_params.pacing_max_error,
698                      params->tts_params.max_clock_mismatch));
699        }
700
701        B_PlaybackIp_SetSettings(playback_ip->playback_ip_handle, &playback_ip_settings);
702
703        /* Start Playpump, this in turn starts the Nexus Playpump */
704        playback_ip->playback.stream = bplaypump_start(playback_ip->pump, mpeg, &playback_ip->pumpparams);
705        if (!playback_ip->playback.stream) {
706            BDBG_ERR(("%s: Failed to create the stream\n", __FUNCTION__));
707            return NULL;
708        }
709    }
710
711    memset(&ipStartSettings, 0, sizeof(ipStartSettings));
712    ipStartSettings.nexusHandles.playpump = playpump->nPlaypump; /* we dont yet know the rest of the handles, they get set in the GetStatus call */
713    if (playback_ip->playback.nPlayback) {
714        ipStartSettings.nexusHandles.playback = playback_ip->playback.nPlayback;
715    }
716    ipStartSettings.nexusHandlesValid = true;
717    if (playback_ip->protocol == bsettop_ip_protocol_http)
718        ipStartSettings.u.http.preChargeBuffer = false;
719    else
720        ipStartSettings.u.rtsp.mediaTransportProtocol = B_PlaybackIpProtocol_eRtp;
721    rc = B_PlaybackIp_SessionStart(playback_ip->playback_ip_handle, &ipStartSettings, &ipStartStatus);
722    if (rc) {
723        BDBG_ERR(("%s: IP Session Start failed: %d\n", __FUNCTION__, rc));
724        B_PlaybackIp_SessionClose(playback_ip->playback_ip_handle);
725        goto error;
726    }
727
728    BDBG_WRN(("%s: IP Playback is Ready to Receive Data:", __FUNCTION__));
729
730    playback_ip->playback_state = bplayback_ip_state_playing;
731    return playback_ip->playback.stream;
732
733error:
734    bplayback_ip_stop((bplayback_t)playback_ip);
735    return NULL;
736}
737
738/*
739Summary:
740    Stop playback.
741Description:
742    If you are decoding the stream, the decode will be stopped as well.
743*/
744bresult bplayback_ip_stop(bplayback_t playback)
745{
746    B_PlaybackIpError err;
747    bplayback_ip_t playback_ip = (bplayback_ip_t) playback;
748
749    BDBG_WRN(("%s:", __FUNCTION__));
750
751    playback_ip->playback_state = bplayback_ip_state_stopping;
752
753    if ( (err = B_PlaybackIp_SessionStop(playback_ip->playback_ip_handle)) != B_ERROR_SUCCESS) {
754        BDBG_ERR(("%s:%d IP Applib Error: %d\n", __FUNCTION__, __LINE__, err));
755        return BSETTOP_ERROR(berr_external_error);
756    }
757
758    BKNI_Sleep(100);
759
760    if (playback_ip->protocol == bsettop_ip_protocol_http) {
761        BDBG_ASSERT(playback_ip->playback.nPlayback);
762        bstream_p_close(playback_ip->pump->stream);
763        NEXUS_Playback_Stop (playback_ip->playback.nPlayback);
764        playback_ip->pump->stream = NULL;
765    }
766    else {
767        bplaypump_stop(playback_ip->pump);
768    }
769
770    playback_ip->playback_state = bplayback_ip_state_stopped;
771
772    return b_ok;
773}
774
775/*
776Summary:
777    Open a IP playback socket to pass to bplayback_ip_start().
778Description:
779    The bplayback_ip_source_t can be used for only one IP playback at a time.
780*/
781bplayback_file_t bplayback_ip_socket_open(
782    bplayback_t playback, /* Handle returned by bplayback_ip_open */
783    bplayback_socket_params *params
784    )
785{
786    bplayback_ip_t playback_ip = (bplayback_ip_t) playback;
787    B_PlaybackIpError rc;
788    bplayback_file_t ip_source;
789    B_PlaybackIpPsiInfo psi;
790    B_PlaybackIpSocketState socketState;
791    B_PlaybackIpSessionOpenSettings sessionOpenSettings;
792    B_PlaybackIpSessionOpenStatus sessionOpenStatus;
793    B_PlaybackIpSessionSetupSettings sessionSetupSettings;
794    B_PlaybackIpSessionSetupStatus sessionSetupStatus;
795#ifdef B_HAS_SSL
796    B_PlaybackIpSslInitSettings sslInitSettings;
797#endif
798#ifdef B_HAS_DTCP_IP
799    struct timeval t_start, t_finish;
800    NEXUS_Error err;
801    int dtcp_server_port;
802#endif
803
804    ip_source = BKNI_Malloc(sizeof(*ip_source));
805    if (!ip_source) {
806        rc = BSETTOP_ERROR(berr_out_of_memory);
807        goto error;
808    }
809    BKNI_Memset(ip_source, 0, sizeof(*ip_source));
810    BKNI_Memset(&socketState, 0, sizeof(socketState));
811    BKNI_Memset(&sessionOpenSettings, 0, sizeof(sessionOpenSettings));
812    BKNI_Memset(&sessionOpenStatus, 0, sizeof(sessionOpenStatus));
813    BKNI_Memset(&psi, 0, sizeof(psi));
814    playback_ip->playback.source = ip_source;
815
816    /* Setup the socket setting structure using the input socket params */
817    memcpy(sessionOpenSettings.socketOpenSettings.ipAddr, params->open_params.ip_addr, sizeof(params->open_params.ip_addr));
818    memset(&sessionSetupSettings, 0, sizeof(sessionSetupSettings));
819    sessionOpenSettings.socketOpenSettings.port = params->open_params.port;
820    sessionOpenSettings.ipMode = B_PlaybackIpClockRecoveryMode_ePushWithPcrSyncSlip;
821    sessionOpenSettings.maxNetworkJitter = 300;
822    sessionOpenSettings.networkTimeout = 1;
823
824    switch (params->open_params.protocol) {
825    case bsettop_ip_protocol_udp:
826        sessionOpenSettings.socketOpenSettings.protocol = B_PlaybackIpProtocol_eUdp;
827        break;
828    case bsettop_ip_protocol_rtp:
829        sessionOpenSettings.socketOpenSettings.protocol = B_PlaybackIpProtocol_eRtp;
830        break;
831    case bsettop_ip_protocol_rtp_no_rtcp:
832        sessionOpenSettings.socketOpenSettings.protocol = B_PlaybackIpProtocol_eRtpNoRtcp;
833        break;
834    case bsettop_ip_protocol_rtsp:
835        {
836        char *tmp1, *tmp2;
837        sessionOpenSettings.socketOpenSettings.protocol = B_PlaybackIpProtocol_eRtsp;
838        /* For RTSP, brutus layer doesn't initialize ipAddr & port fields, rather they are included part of the url */
839        /* extract ipAddr & port information from URL and specify them as required by IP Applib */
840        if ( (tmp1 = strstr(params->open_params.url, "rtsp://")) != NULL ) {
841            tmp1 += strlen("rtsp://"); /* tmp1 points to ip address */
842            if ( (tmp2 = strstr(tmp1, ":")) != NULL ) {
843                strncpy(sessionOpenSettings.socketOpenSettings.ipAddr, tmp1, (tmp2 - tmp1));
844                sessionOpenSettings.socketOpenSettings.ipAddr[tmp2-tmp1] = 0;
845
846                /* now get the port info */
847                tmp1 = tmp2 + 1; /* get past the : and now it points to the port */
848                if ( (tmp2 = strstr(tmp1, "/")) != NULL ) {
849                    char tmp3[16];
850                    strncpy(tmp3, tmp1, (tmp2 - tmp1));
851                    tmp3[tmp2-tmp1] = 0;
852                    sessionOpenSettings.socketOpenSettings.port = strtol(tmp3, NULL, 10);
853
854                    /* now get the url, tmp2 already points to start of the URL */
855                    sessionOpenSettings.socketOpenSettings.url = tmp2;
856                }
857            }
858        }
859        else {
860            rc = BSETTOP_ERROR(berr_invalid_parameter);
861            goto error;
862        }
863        break;
864        }
865    case bsettop_ip_protocol_http:
866        sessionOpenSettings.socketOpenSettings.protocol = B_PlaybackIpProtocol_eHttp;
867        sessionOpenSettings.ipMode = B_PlaybackIpClockRecoveryMode_ePull;
868        sessionOpenSettings.u.http.networkBufferSize = (20*3*1024*1024)/8; /* data cache size: 20sec worth for a max bitrate of 3Mbps */
869        sessionOpenSettings.socketOpenSettings.url = params->open_params.url;
870        /* For HTTP, we use Nexus Playback to feeding IP data */
871        if ( (playback_ip->playback.nPlayback = NEXUS_Playback_Create()) == NULL ) {
872            BDBG_ERR(("%s: Failed to create Nexus Playback Handle\n", __FUNCTION__));
873            goto error;
874        }
875        sessionSetupSettings.u.http.enablePayloadScanning = true;
876        break;
877    default:
878        rc = BSETTOP_ERROR(berr_invalid_parameter);
879        goto error;
880    }
881
882    /* Initialize security */
883
884    switch (params->open_params.security.security_protocol) 
885    {
886    case bsettop_ip_security_ssl:
887#ifdef B_HAS_SSL
888        sessionOpenSettings.security.securityProtocol = B_PlaybackIpSecurityProtocol_Ssl;
889        sslInitSettings.rootCaCertPath=params->open_params.security.security_info.ssl.ca_file;
890        sslInitSettings.sslLibInitDone = false;
891        if (strlen(params->open_params.security.security_info.ssl.client_cert_file)) {
892            sslInitSettings.clientAuth=true;
893            sslInitSettings.ourCertPath=params->open_params.security.security_info.ssl.client_cert_file;
894            if (strlen(params->open_params.security.security_info.ssl.client_cert_key))
895                sslInitSettings.privKeyPath= params->open_params.security.security_info.ssl.client_cert_key;
896            if (strlen(params->open_params.security.security_info.ssl.password))
897                sslInitSettings.password= params->open_params.security.security_info.ssl.password;
898        } else
899            sslInitSettings.clientAuth=false;
900        playback_ip->security_ctx = B_PlaybackIp_SslInit(&sslInitSettings);
901        if (!playback_ip->security_ctx) {
902            BDBG_ERR(("%s: SSL Security initialization failed \n", __FUNCTION__ ));
903            goto error;
904        }
905        sessionOpenSettings.security.initialSecurityContext = playback_ip->security_ctx;
906#else
907        BDBG_ERR(("%s: Need to compile with B_HAS_SSL defined\n", __FUNCTION__ ));
908        goto error;
909#endif
910        break;
911    case bsettop_ip_security_dtcp_ip:
912#ifdef B_HAS_DTCP_IP
913        sessionOpenSettings.security.securityProtocol = B_PlaybackIpSecurityProtocol_DtcpIp;
914
915        playback_ip->dtcp_ctx = params->open_params.security.security_info.dtcp_ip.dtcp_ip_ctx;
916        if(playback_ip->dtcp_ctx == NULL) {
917            BDBG_ERR(("%s: Failed to Initialize Dtcp/Ip Library: DTCP/IP encryption/decryption won't work\n", __FUNCTION__));
918            goto error;
919        }
920        /* Perform AKE for DTCP/IP */
921        if (params->open_params.security.security_info.dtcp_ip.ake_server_port == 0)
922            dtcp_server_port = 8000;
923        else
924            dtcp_server_port = params->open_params.security.security_info.dtcp_ip.ake_server_port;
925        BDBG_WRN(("%s: setting up DTCP/IP AKE session with %s:%d\n", __FUNCTION__, sessionOpenSettings.socketOpenSettings.ipAddr, dtcp_server_port));
926        gettimeofday(&t_start, 0);
927        if((err = DtcpAppLib_DoAke(playback_ip->dtcp_ctx, sessionOpenSettings.socketOpenSettings.ipAddr,
928                        dtcp_server_port, &playback_ip->akeHandle)) != BERR_SUCCESS) {
929            BDBG_ERR(("DTCP AKE Failed!!!\n"));
930            goto error;
931        }
932        gettimeofday(&t_finish, 0);
933        BDBG_WRN(("%s: DTCP/IP AKE Successful (time consumed %d secs and %d msecs)\n", __FUNCTION__,
934            (t_finish.tv_usec < t_start.tv_usec? t_finish.tv_sec - t_start.tv_sec - 1: t_finish.tv_sec - t_start.tv_sec),
935            (t_finish.tv_usec < t_start.tv_usec? t_finish.tv_usec - t_start.tv_usec + 1000000: t_finish.tv_usec - t_start.tv_usec) ));
936        sessionOpenSettings.security.initialSecurityContext = playback_ip->akeHandle;
937#else
938        BDBG_ERR(("%s: Need to compile with B_HAS_DTCP_IP defined\n" ));
939        goto error;
940#endif
941        break;
942    case bsettop_ip_security_radea:
943#ifdef B_HAS_RAD_EA
944        sessionOpenSettings.security.securityProtocol = B_PlaybackIpSecurityProtocol_RadEa;
945        B_PlaybackIp_RadEaInit();
946#else
947        BDBG_ERR(("%s: Need to compile with B_HAS_RAD_EA defined\n" ));
948        goto error;
949#endif
950        break;
951    default:
952        sessionOpenSettings.security.securityProtocol = B_PlaybackIpSecurityProtocol_None;
953    }
954    BDBG_MSG(("%s: Security %d \n", __FUNCTION__, sessionOpenSettings.security.securityProtocol));
955
956    rc = B_PlaybackIp_SessionOpen(playback_ip->playback_ip_handle, &sessionOpenSettings, &sessionOpenStatus);
957    if (rc != B_ERROR_SUCCESS) {
958        BDBG_ERR(("B_PlaybackIp_SessionOpen failed"));
959        goto error;
960    }
961    params->open_params.fd = sessionOpenStatus.socketState.fd;
962    socketState = sessionOpenStatus.socketState;
963
964    rc = B_PlaybackIp_SessionSetup(playback_ip->playback_ip_handle, &sessionSetupSettings, &sessionSetupStatus);
965    if (rc != B_ERROR_SUCCESS) {
966        BDBG_ERR(("B_PlaybackIp_SessionSetup failed"));
967        B_PlaybackIp_SessionClose(playback_ip->playback_ip_handle);
968        goto error;
969    }
970
971    ip_source->nFile = sessionSetupStatus.u.http.file;
972    /* now copy the PSI information into the open_params */
973    /* For HTTP protocol, PSI info can be returned by the server in the response header */
974    psi = sessionSetupStatus.u.http.psi;
975    if (psi.psiValid == true) {
976        BDBG_MSG(("%s: PSI Info is Retrieved from HTTP Response Headers\n", __FUNCTION__));
977        bstream_mpeg_init(&(params->open_params.psi));
978        params->open_params.psi.video[0].pid = psi.videoPid;
979        /* TODO: define a mapping table instead of this switch below */
980        switch (psi.videoCodec) {
981        case NEXUS_VideoCodec_eMpeg1:
982            params->open_params.psi.video[0].format = bvideo_codec_mpeg1;
983            break;
984        case NEXUS_VideoCodec_eMpeg2:
985            params->open_params.psi.video[0].format = bvideo_codec_mpeg2;
986            break;
987        case NEXUS_VideoCodec_eH264:
988            params->open_params.psi.video[0].format = bvideo_codec_h264;
989            break;
990        case NEXUS_VideoCodec_eVc1SimpleMain:
991            params->open_params.psi.video[0].format = bvideo_codec_vc1_sm;
992            break;
993        case NEXUS_VideoCodec_eDivx311:
994            params->open_params.psi.video[0].format = bvideo_codec_divx_311;
995            break;
996        case NEXUS_VideoCodec_eVc1:
997            params->open_params.psi.video[0].format = bvideo_codec_vc1;
998            break;
999        default:
1000            BDBG_ERR(("%s: Video Codec %d is not yet mapped to Settop API\n", __FUNCTION__, psi.videoCodec));
1001        }
1002        params->open_params.psi.audio[0].pid = psi.audioPid;
1003
1004        switch (psi.audioCodec) {
1005        case NEXUS_AudioCodec_eAc3:
1006            params->open_params.psi.audio[0].format = baudio_format_ac3;
1007            break;
1008        case NEXUS_AudioCodec_eAc3Plus:
1009            params->open_params.psi.audio[0].format = baudio_format_ac3_plus;
1010            break;
1011        case NEXUS_AudioCodec_eWmaStd:
1012            params->open_params.psi.audio[0].format = baudio_format_wma_std;
1013            break;
1014        case NEXUS_AudioCodec_eWmaPro:
1015            params->open_params.psi.audio[0].format = baudio_format_wma_pro;
1016            break;
1017        case NEXUS_AudioCodec_eMpeg:
1018            params->open_params.psi.audio[0].format = baudio_format_mpeg;
1019            break;
1020        case NEXUS_AudioCodec_eAac:
1021            params->open_params.psi.audio[0].format = baudio_format_aac;
1022            break;
1023        default:
1024            BDBG_ERR(("%s: Audio Codec %d is not yet mapped to Settop API\n", __FUNCTION__, psi.audioCodec));
1025        }
1026        params->open_params.psi.pcr_pid = psi.pcrPid;
1027        params->open_params.psi.mpeg_type = psi.mpegType;
1028
1029        /* TODO: add more conversions as they are supported */
1030        if (psi.mpegType == NEXUS_TransportType_eTs) {
1031            params->open_params.psi.mpeg_type = bstream_mpeg_type_ts;
1032            playback_ip->transportTimeStampEnabled = psi.transportTimeStampEnabled;
1033        }
1034        else if (psi.mpegType == NEXUS_TransportType_eAsf)
1035            params->open_params.psi.mpeg_type = bstream_mpeg_type_asf;
1036        else if (psi.mpegType == NEXUS_TransportType_eMp4)
1037            params->open_params.psi.mpeg_type = bstream_mpeg_type_mp4;
1038        else if (psi.mpegType == NEXUS_TransportType_eVob)
1039            params->open_params.psi.mpeg_type = bstream_mpeg_type_vob;
1040        else
1041            BDBG_ERR(("%s: Transport type %d is not mapped to Settop API\n", __FUNCTION__, psi.mpegType));
1042
1043
1044        params->open_params.num_play_speed_entries = psi.numPlaySpeedEntries;
1045        params->open_params.first_pts = psi.firstPts;
1046        params->open_params.duration = psi.duration;
1047        params->open_params.http_min_iframe_speed = psi.httpMinIFrameSpeed;
1048        params->open_params.http_frame_repeat = psi.httpFrameRepeat;
1049        memcpy(params->open_params.play_speed, psi.playSpeed, IP_PVR_PLAYSPEED_MAX_COUNT);
1050    }
1051    else {
1052        if (params->open_params.protocol == bsettop_ip_protocol_rtsp) {
1053            int i;
1054            playback_ip->firstPositiveScaleIndex = 0;
1055            playback_ip->scaleListEntries = sessionSetupStatus.u.rtsp.scaleListEntries;
1056            for (i=0; i<playback_ip->scaleListEntries; i++) {
1057                playback_ip->scaleList[i] = sessionSetupStatus.u.rtsp.scaleList[i];
1058                if (playback_ip->scaleList[i] > 0 && !playback_ip->firstPositiveScaleIndex)
1059                    playback_ip->firstPositiveScaleIndex = i;
1060                BDBG_MSG(("scaleList[%d] %f, +ve Speed idx %d", playback_ip->scaleListEntries, playback_ip->scaleList[i], playback_ip->firstPositiveScaleIndex));
1061            }
1062/*#define TEST_CODE*/
1063#ifdef TEST_CODE
1064            playback_ip->firstPositiveScaleIndex = 5;
1065            playback_ip->scaleListEntries = 11;
1066            playback_ip->scaleList[0] = -24;
1067            playback_ip->scaleList[1] = -16;
1068            playback_ip->scaleList[2] = -8;
1069            playback_ip->scaleList[3] = -4;
1070            playback_ip->scaleList[4] = -2;
1071            playback_ip->scaleList[5] = 1;
1072            playback_ip->scaleList[6] = 2;
1073            playback_ip->scaleList[7] = 4;
1074            playback_ip->scaleList[8] = 8;
1075            playback_ip->scaleList[9] = 16;
1076            playback_ip->scaleList[10] = 24;
1077#endif
1078        }
1079        if (params->open_params.protocol == bsettop_ip_protocol_http)
1080            BDBG_MSG(("%s: PSI Info is *NOT* Retrieved from HTTP Response Headers\n", __FUNCTION__));
1081        params->open_params.psi.mpeg_type = bstream_mpeg_type_unknown;
1082    }
1083
1084    memcpy(&ip_source->socket, &socketState, sizeof(B_PlaybackIpSocketState));
1085    playback_ip->protocol = params->open_params.protocol;
1086    playback_ip->socket_params = *params;
1087    return (ip_source);
1088
1089error:
1090    if (ip_source) {
1091        playback_ip->playback.source = NULL;
1092        BKNI_Free(ip_source);
1093    }
1094
1095    if (playback_ip->playback.nPlayback) {
1096        NEXUS_Playback_Destroy(playback_ip->playback.nPlayback);
1097        playback_ip->playback.nPlayback = NULL;
1098    }
1099    return NULL;
1100}
1101
1102/*
1103Summary:
1104    Close a IP playback socket.
1105Description:
1106    Close a IP playback socket opened by bplayback_ip_socket_open(). Playback
1107    must be stopped BEFORE socket is closed
1108*/
1109void bplayback_ip_socket_close(
1110    bplayback_t playback /* Handle returned by bplayback_ip_open */
1111    )
1112{
1113    bplayback_ip_t playback_ip = (bplayback_ip_t) playback;
1114
1115    BDBG_MSG(("%s: \n", __FUNCTION__));
1116    /* closing the socket while running is not supported */
1117    if(playback_ip->playback_state != bplayback_ip_state_stopped)
1118        goto error;
1119
1120    B_PlaybackIp_SessionClose(playback_ip->playback_ip_handle);
1121#ifdef B_HAS_DTCP_IP
1122    if (playback_ip->akeHandle) {
1123        if (DtcpAppLib_CloseAke(playback_ip->dtcp_ctx, playback_ip->akeHandle) != BERR_SUCCESS) {
1124            BDBG_WRN(("%s: failed to close the DTCP AKE session\n", __FUNCTION__));
1125        }
1126        playback_ip->akeHandle = NULL;
1127    }
1128#if 0
1129    if (playback_ip->dtcp_ctx) {
1130        B_PlaybackIp_DtcpIpUnInit(playback_ip->dtcp_ctx);
1131        playback_ip->dtcp_ctx = NULL;
1132    }
1133#endif
1134#endif
1135    if (playback_ip->playback.source) {
1136        BKNI_Free(playback_ip->playback.source);
1137        playback_ip->playback.source = NULL;     /* PR27770 */
1138    }
1139    if (playback_ip->protocol == bsettop_ip_protocol_http && playback_ip->playback.nPlayback) {
1140        NEXUS_Playback_Destroy(playback_ip->playback.nPlayback);
1141        playback_ip->playback.nPlayback = NULL;
1142    }
1143    playback_ip->handlesSet = false;
1144
1145#ifdef B_HAS_SSL
1146    if (playback_ip->security_ctx) {
1147        B_PlaybackIp_SslUnInit(playback_ip->security_ctx);
1148        playback_ip->security_ctx = NULL;
1149    }
1150#endif
1151
1152
1153    BKNI_Sleep(500);
1154
1155    return;
1156
1157error:
1158    BDBG_ERR(("bplayback_ip_socket_close error"));
1159    BDBG_ASSERT(NULL);
1160    return;
1161}
1162
1163/*
1164Summary:
1165    Required to initialize the bplayback_ip_source_params structure.
1166*/
1167void
1168bplayback_ip_source_params_init(
1169    bplayback_socket_params *params,    /* [out] */
1170    bplayback_t             playback /* required for possible resource-dependent defaults */
1171    )
1172{
1173    BSTD_UNUSED(playback);
1174    strncpy(params->open_params.ip_addr, "127.0.0.1", sizeof("127.0.0.1"));         /* default to loopback address */
1175    params->open_params.port = 5001;                            /* default port number */
1176    params->open_params.protocol = bsettop_ip_protocol_udp;     /* default to non-RTP stream */
1177}
1178
1179static bresult
1180set_nexus_handles(bplayback_ip_t playback_ip)
1181{
1182    B_PlaybackIpError err;
1183
1184    if (!playback_ip->handlesSet) {
1185        B_PlaybackIpSettings pSettings;
1186        BDBG_WRN(("%s: updating nexus handles...", __FUNCTION__));
1187        playback_ip->handlesSet = true;
1188        memset((char *)&pSettings, 0, sizeof(pSettings));
1189        err = B_PlaybackIp_GetSettings(playback_ip->playback_ip_handle, &pSettings);
1190
1191        pSettings.nexusHandles.videoDecoder = playback_ip->playback.stream->consumers.decode->video_decode->nVideoDecoder;
1192        pSettings.nexusHandles.primaryAudioDecoder = playback_ip->playback.stream->consumers.decode->audio_decode->nAudioDecoder;
1193        if (playback_ip->playback.stream->consumers.decode->audio_decode->secondary_audio_decode)
1194            pSettings.nexusHandles.secondaryAudioDecoder =
1195                playback_ip->playback.stream->consumers.decode->audio_decode->secondary_audio_decode->nAudioDecoder;
1196        pSettings.nexusHandles.stcChannel = playback_ip->playback.stream->consumers.decode ? playback_ip->playback.stream->consumers.decode->stcChannel : NULL;
1197        pSettings.nexusHandlesValid = true;
1198        err = B_PlaybackIp_SetSettings(playback_ip->playback_ip_handle, &pSettings);
1199        if (err != B_ERROR_SUCCESS)
1200            return berr_external_error;
1201    }
1202    return b_ok;
1203}
1204
1205bresult
1206bplayback_ip_get_status(bplayback_t playback, bplayback_status *status)
1207{
1208    bresult rc = b_ok;
1209    B_PlaybackIpError err;
1210    NEXUS_PlaybackStatus playbackStatus;
1211    bplayback_ip_t playback_ip = (bplayback_ip_t) playback;
1212    B_PlaybackIpStatus playbackIpStatus;
1213
1214    BKNI_Memset(status, 0, sizeof(*status));
1215    BKNI_Memset(&playbackStatus, 0, sizeof(playbackStatus));
1216
1217    if (!playback_ip)
1218        return berr_external_error;
1219
1220    if (playback_ip->playback_state == bplayback_ip_state_stopped) {
1221        return berr_invalid_state;
1222    }
1223    if (!playback_ip->playback.stream || !playback_ip->playback.stream->consumers.decode ||
1224            !playback_ip->playback.stream->consumers.decode->video_decode ||
1225            !playback_ip->playback.stream->consumers.decode->video_decode->nVideoDecoder ||
1226            !playback_ip->playback.stream->consumers.decode->audio_decode ||
1227            !playback_ip->playback.stream->consumers.decode->audio_decode->nAudioDecoder
1228            ) {
1229        return berr_external_error;
1230    }
1231
1232    if (set_nexus_handles(playback_ip) != b_ok) {
1233        BDBG_ERR(("Failed to set the nexus handles w/ IP library \n"));
1234        return berr_external_error;
1235    }
1236
1237    err = B_PlaybackIp_GetStatus(playback_ip->playback_ip_handle, &playbackIpStatus);
1238    if (err != B_ERROR_SUCCESS)
1239        return berr_external_error;
1240    if (playback_ip->playback.nPlayback)
1241    {
1242        NEXUS_Error nerr = NEXUS_Playback_GetStatus(playback_ip->playback.nPlayback, &playbackStatus);
1243        if (nerr)
1244            return berr_external_error;
1245    }
1246
1247    /* TODO: trickmodes: needed this to get pause to work, otherwise reading state from IP Applib was causing issues */
1248    if (playback_ip->playback_state == bplayback_ip_state_playing) {
1249        status->state = bplayback_state_playing;
1250    }
1251    else if (playback_ip->playback_state == bplayback_ip_state_paused) {
1252        status->state = bplayback_state_paused;
1253    }
1254    else {
1255        BDBG_ERR(("%s: Warning: Not supported playback ip state %d, s/w bug\n", __FUNCTION__, playback_ip->playback_state));
1256    }
1257
1258    switch (playbackIpStatus.ipState)
1259    {
1260    case B_PlaybackIpState_eStopped:
1261        /* we igore the stopped state of the IP Applib. Otherwise, upon channel change */
1262        /* brutus wont call bsettop_playback_ip_stop to tear down */
1263    case B_PlaybackIpState_ePlaying:
1264        status->state = bplayback_state_playing;
1265        break;
1266    case B_PlaybackIpState_ePaused:
1267        status->state = bplayback_state_paused;
1268        break;
1269    case B_PlaybackIpState_eTrickMode:
1270        status->state = bplayback_state_trickmode;
1271        break;
1272    default:
1273        BDBG_WRN(("invalid state"));
1274        break;
1275    }
1276
1277    status->num_read_errors = playbackIpStatus.numRecvTimeouts;
1278
1279    status->fifo_depth = playbackStatus.fifoDepth;
1280    status->fifo_size = playbackStatus.fifoSize;
1281    status->bytes_played = playbackStatus.bytesPlayed;
1282
1283    status->has_index = false;
1284    status->position.has_index = status->has_index = false;
1285    status->position.timestamp = playbackStatus.position;
1286    status->first_timestamp = playbackStatus.first;
1287    status->last_timestamp = playbackStatus.last;
1288    status->position.index_offset = playbackStatus.position;
1289    status->trickmode_params = playback_ip->playback.trick_mode_params;
1290    BDBG_MSG_FLOW(("playback position: first %u, last %u, current %u\n", playbackStatus.first, playbackStatus.last, playbackStatus.position));
1291
1292#define SCALE_FACTOR 5000
1293    if (playback_ip->protocol == bsettop_ip_protocol_http) {
1294        if (playback_ip->socket_params.open_params.first_pts) {
1295            /* server has provided the PTS info, we use PTS to determine the current playback position */
1296            unsigned int first_pts, last_pts, current_pts;
1297            NEXUS_VideoDecoderStatus videoDecoderStatus;
1298            first_pts = playback_ip->socket_params.open_params.first_pts;
1299            last_pts = playback_ip->socket_params.open_params.first_pts + (playback_ip->socket_params.open_params.duration * 45);
1300            if (NEXUS_VideoDecoder_GetStatus(playback_ip->playback.stream->consumers.decode->video_decode->nVideoDecoder, &videoDecoderStatus) != NEXUS_SUCCESS) {
1301                BDBG_ERR(("%s: NEXUS_VideoDecoder_GetStatus() Failed\n", __FUNCTION__));
1302                return berr_external_error;
1303            }
1304            current_pts = videoDecoderStatus.pts;
1305            status->position.timestamp = ((current_pts - first_pts) / (last_pts - first_pts + 0.005)) * SCALE_FACTOR;
1306            BDBG_MSG_FLOW(("decoder pts position: first %x, last %x, current %x\n", first_pts, last_pts, current_pts));
1307        }
1308        else {
1309            /* we use the position provided by Nexus Playback */
1310            status->position.timestamp = (((playbackStatus.position - playbackStatus.first) /
1311                                        (float)(playbackStatus.last - playbackStatus.first + 0)) * SCALE_FACTOR);
1312        }
1313        status->last_timestamp = SCALE_FACTOR;
1314        status->first_timestamp = 0;
1315        status->position.has_index = status->has_index = true;
1316
1317    } else if((playback_ip->protocol == bsettop_ip_protocol_rtp ) || (playback_ip->protocol == bsettop_ip_protocol_rtsp )) {
1318        if (playbackStatus.last)
1319            status->position.has_index = status->has_index = true;
1320    }
1321
1322    return rc;
1323}
1324
1325/*
1326Summary:
1327    Pause playback.
1328*/
1329bresult bplayback_ip_pause(
1330    bplayback_t playback
1331    )
1332{
1333#if defined(B_HAS_IP)
1334    B_PlaybackIpTrickModesSettings ipTrickmodeSettings;
1335    bresult rc = b_ok;
1336    bplayback_ip_t playback_ip = (bplayback_ip_t) playback;
1337    BDBG_MSG(("Entered %s()", __FUNCTION__));
1338
1339    if (set_nexus_handles(playback_ip) != b_ok) {
1340        BDBG_ERR(("Failed to set the nexus handles w/ IP library \n"));
1341        return berr_external_error;
1342    }
1343
1344    memset(&ipTrickmodeSettings, 0, sizeof(ipTrickmodeSettings));
1345    if (playback_ip->playback_state == bplayback_ip_state_playing) {
1346        ipTrickmodeSettings.pauseMethod = B_PlaybackIpPauseMethod_UseDisconnectAndSeek;
1347        if (B_PlaybackIp_Pause(playback_ip->playback_ip_handle, &ipTrickmodeSettings) != B_ERROR_SUCCESS)
1348            return BSETTOP_ERROR(berr_external_error);
1349        playback_ip->playback_state = bplayback_ip_state_paused;
1350    }
1351    else {
1352        if (B_PlaybackIp_Play(playback_ip->playback_ip_handle) != B_ERROR_SUCCESS)
1353            return BSETTOP_ERROR(berr_external_error);
1354        playback_ip->playback_state = bplayback_ip_state_playing;
1355    }
1356    return rc;
1357#else
1358    BSTD_UNUSED(playback);
1359    return BSETTOP_ERROR(berr_not_supported);
1360#endif
1361}
1362
1363/*
1364Summary:
1365    Play/Resume playback.
1366*/
1367bresult bplayback_ip_play(
1368    bplayback_t playback
1369    )
1370{
1371#if defined(B_HAS_IP)
1372    bresult rc = b_ok;
1373    bplayback_ip_t playback_ip = (bplayback_ip_t) playback;
1374    BDBG_MSG(("Entered %s()", __FUNCTION__));
1375
1376    if (set_nexus_handles(playback_ip) != b_ok) {
1377        BDBG_ERR(("Failed to set the nexus handles w/ IP library \n"));
1378        return berr_external_error;
1379    }
1380
1381    if (B_PlaybackIp_Play(playback_ip->playback_ip_handle) != B_ERROR_SUCCESS)
1382        return BSETTOP_ERROR(berr_external_error);
1383    playback_ip->playback_state = bplayback_ip_state_playing;
1384    return rc;
1385#else
1386    BSTD_UNUSED(playback);
1387    return BSETTOP_ERROR(berr_not_supported);
1388#endif
1389}
1390
1391/*
1392Summary:
1393    Trickmode playback.
1394*/
1395bresult bplayback_ip_trickmode(
1396    bplayback_t playback,
1397    const bplayback_trickmode_params *trickmode
1398    )
1399{
1400#if defined(B_HAS_IP)
1401    bresult rc = b_ok;
1402    B_PlaybackIpError err;
1403    bplayback_ip_t playback_ip = (bplayback_ip_t) playback;
1404    B_PlaybackIpTrickModesSettings ipTrickModeSettings;
1405    BDBG_MSG(("Entered %s()", __FUNCTION__));
1406
1407
1408    if (set_nexus_handles(playback_ip) != b_ok) {
1409        BDBG_ERR(("Failed to set the nexus handles w/ IP library \n"));
1410        return berr_external_error;
1411    }
1412
1413    if (B_PlaybackIp_GetTrickModeSettings(playback_ip->playback_ip_handle, &ipTrickModeSettings) != B_ERROR_SUCCESS) {
1414        BDBG_ERR(("%s: Failed to get default IP TrickMode settings\n", __FUNCTION__));
1415        return BSETTOP_ERROR(berr_external_error);
1416    }
1417    playback_ip->playback.trick_mode_params = *trickmode;
1418    ipTrickModeSettings.method = B_PlaybackIpTrickModesMethod_UsePlaySpeed;
1419    if (playback_ip->protocol == bsettop_ip_protocol_rtsp) {
1420        /* convert Broadcom trickmode speed to RTSP scale value */
1421        int scale_idx;
1422        int scale;
1423        scale_idx = trickmode->mode_modifier/100;
1424        if (scale_idx == 0) {
1425            BDBG_ERR(("Dont support slow-motion rtsp yet, rate %d", trickmode->mode_modifier));
1426            return b_ok;
1427        }
1428       
1429        if (scale_idx > 0) {
1430            scale_idx = playback_ip->firstPositiveScaleIndex + scale_idx -1;
1431            if (scale_idx >= playback_ip->scaleListEntries)
1432                scale_idx = playback_ip->scaleListEntries-1;
1433        }
1434        else {
1435            /* -ve idx */
1436            scale_idx = playback_ip->firstPositiveScaleIndex + scale_idx;
1437            if (scale_idx < 0)
1438                scale_idx = 0;
1439        }
1440        scale = (int)playback_ip->scaleList[scale_idx];
1441        ipTrickModeSettings.rate = scale;
1442        BDBG_MSG(("scale passed to Playback IP: %d, idx %d, scale %0.1f", scale, scale_idx, playback_ip->scaleList[scale_idx]));
1443    }
1444    else {
1445        ipTrickModeSettings.rate = trickmode->mode_modifier;
1446    }
1447    ipTrickModeSettings.slowMotionRate = trickmode->slow_motion_rate;
1448    switch (trickmode->decode_mode) {
1449    case bplaypump_decode_mode_i:
1450        ipTrickModeSettings.decodeMode = NEXUS_VideoDecoderDecodeMode_eI;
1451        break;
1452    case bplaypump_decode_mode_ip:
1453        ipTrickModeSettings.decodeMode = NEXUS_VideoDecoderDecodeMode_eIP;
1454        break;
1455    case bplaypump_decode_mode_all:
1456    default:
1457        ipTrickModeSettings.decodeMode = NEXUS_VideoDecoderDecodeMode_eAll;
1458        break;
1459    }
1460    err = B_PlaybackIp_TrickMode(playback_ip->playback_ip_handle, &ipTrickModeSettings);
1461    if (err != B_ERROR_SUCCESS)
1462        return BSETTOP_ERROR(berr_external_error);
1463
1464    return rc;
1465#else
1466    BSTD_UNUSED(playback);
1467    BSTD_UNUSED(trickmode);
1468    return BSETTOP_ERROR(berr_not_supported);
1469#endif
1470}
1471
1472bresult bplayback_ip_get_trickmode_by_rate(
1473    bplayback_t playback,
1474    int rate,
1475    bplayback_trickmode_params *trickmode
1476    )
1477{
1478#if defined(B_HAS_IP)
1479    bresult rc = b_ok;
1480    bplayback_ip_t playback_ip = (bplayback_ip_t) playback;
1481    BDBG_MSG(("Entered %s: rate %d", __FUNCTION__, rate));
1482
1483#if 0
1484    B_PlaybackIpError err;
1485    /* For now, commenting the GetTrickModeByRate call to IP library's until it is implemented */
1486    err = B_PlaybackIp_GetTrickModeByRate(playback_ip->playback_ip_handle, rate, (B_PlaybackIpTrickModesSettings *)trickmode);
1487    if (err != B_ERROR_SUCCESS)
1488        return BSETTOP_ERROR(berr_external_error);
1489
1490    return rc;
1491#else
1492    /* legacy implementation */
1493    if ( playback_ip->protocol != bsettop_ip_protocol_http )
1494    {
1495        if (rate == BPLAYBACK_NORMALPLAY_SPEED || rate == 0) {
1496            /* normal play isn't a trick mode */
1497            return BSETTOP_ERROR(berr_invalid_parameter);
1498        }
1499        else {
1500            trickmode->mode = bplayback_player_mode_i; /* don't care */
1501            trickmode->mode_modifier = rate;
1502            trickmode->slow_motion_rate = 0; /* don't care */
1503            trickmode->decode_mode = bplaypump_decode_mode_all;
1504        }
1505        return rc;
1506    }
1507    bplayback_trickmode_params_init(trickmode);
1508    return rc;
1509#endif
1510#else
1511    BSTD_UNUSED(playback);
1512    BSTD_UNUSED(rate);
1513    BSTD_UNUSED(trickmode);
1514    return BSETTOP_ERROR(berr_not_supported);
1515#endif
1516}
1517
1518long bplayback_ip_goto_index (
1519    bplayback_t playback, /* Handle returned by bplayback_ip_open */
1520    long offset,
1521    int whence
1522    )
1523{
1524#if defined(B_HAS_IP)
1525    bresult rc = b_ok;
1526    bplayback_ip_t playback_ip = (bplayback_ip_t) playback;
1527    BDBG_MSG(("Entered %s()", __FUNCTION__));
1528    BSTD_UNUSED(offset);
1529    BSTD_UNUSED(whence);
1530    BSTD_UNUSED(playback_ip);
1531    return rc;
1532#else
1533    BSTD_UNUSED(playback);
1534    BSTD_UNUSED(offset);
1535    BSTD_UNUSED(whence);
1536    return BSETTOP_ERROR(berr_not_supported);
1537#endif
1538}
1539#endif /* LINUX  || vxworks */
1540
1541/*
1542Summary:
1543    Open an IP playback channel.
1544*/
1545bplayback_t bplayback_ip_open(void)
1546{
1547#if defined(B_HAS_IP)
1548    return bplayback_ip_p_open();
1549#else
1550    /* Fail silently. This function is used to query if IP support is present. */
1551    return NULL;
1552#endif
1553}
1554
1555/*
1556Summary:
1557    Close an IP playback channel.
1558*/
1559void bplayback_ip_close(bplayback_t playback)
1560{
1561#if defined(B_HAS_IP)
1562    BDBG_MSG(("%s: \n", __FUNCTION__));
1563    bplayback_ip_p_close(playback);
1564        return;
1565#else
1566    BSTD_UNUSED(playback);
1567    BSETTOP_ERROR(berr_not_supported);
1568    return;
1569#endif
1570}
1571
1572/*
1573Summary:
1574    Required to initialize the bplayback_socket_params structure.
1575*/
1576void
1577bplayback_socket_params_init(
1578    bplayback_socket_params *params,
1579    bplayback_t playback
1580    )
1581{
1582#if defined(B_HAS_IP)
1583    bplayback_ip_source_params_init(params, playback);
1584#else
1585    BSTD_UNUSED(params);
1586    BSTD_UNUSED(playback);
1587#endif
1588}
1589
1590/*
1591Summary:
1592    Open a IP playback socket to pass to bplayback_start().
1593Description:
1594    The bplayback_socket_t can be used for only one IP playback at a time.
1595*/
1596bplayback_file_t bplayback_socket_open(
1597    bplayback_t playback, /* Handle returned by bplayback_ip_open */
1598    const bplayback_socket_params *params
1599    )
1600{
1601#if defined(B_HAS_IP)
1602    return bplayback_ip_socket_open(playback, (bplayback_socket_params *) params);
1603#else
1604    BSTD_UNUSED(params);
1605    BSTD_UNUSED(playback);
1606    return NULL;
1607#endif
1608}
1609
1610/*
1611Summary:
1612    Close a IP playback socket.
1613Description:
1614    Close a IP playback socket opened by bplayback_socket_open().
1615*/
1616void bplayback_socket_close(
1617    bplayback_t playback /* Handle returned by bplayback_ip_open */
1618    )
1619{
1620#if defined(B_HAS_IP)
1621    BDBG_MSG(("%s: \n", __FUNCTION__));
1622    bplayback_ip_socket_close(playback);
1623#else
1624    BSTD_UNUSED(playback);
1625#endif
1626}
1627
Note: See TracBrowser for help on using the repository browser.