source: svn/newcon3bcm2_21bu/nexus/lib/playback_ip/apps/ip_http.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: 60.9 KB
Line 
1/***************************************************************************
2 *     (c)2007-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: ip_http.c $
39 * $brcm_Revision: 82 $
40 * $brcm_Date: 12/19/11 12:56a $
41 *
42 * Module Description: http server module
43 *                                         
44 * 
45 * Revision History:
46 *   
47 * $brcm_Log: /nexus/lib/playback_ip/apps/ip_http.c $
48 *
49 * 82   12/19/11 12:56a ssood
50 * SW7231-516: raaga encoding support: added changes to support running
51 *  raaga based xcode alongside the local decode on BMC
52 *
53 * 81   12/13/11 7:33p ssood
54 * SW7231-516: enabled support for local display while encoding & live
55 *  channels encoding & streaming out using raaga dsp
56 *
57 * 80   12/8/11 7:40p ssood
58 * SW7231-516: enhance ip_streamer to stream out raaga encoded TS streams
59 *  from live or file sources
60 *
61 * 79   11/4/11 11:31a kagrawal
62 * SW7425-1661: Fixed build failure for Android
63 *
64 * 78   10/18/11 7:25a ssood
65 * SW7425-889: enabled audio in the live xcoded streams for streaming to
66 *  iOS devices
67 *
68 * 77   10/14/11 10:18a ssood
69 * SW7425-889: initial check-in for enabling audio in the live xcoded
70 *  streams
71 *
72 * 76   10/7/11 6:10p ssood
73 * SW7346-341: allow apps to pass-in the key slot pointer
74 *
75 * 75   9/30/11 10:32p ssood
76 * SW7346-341: assigned more friendly name for the PVR decryption related
77 *  variables
78 *
79 * 74   9/29/11 7:03p ssood
80 * SW7346-312: Expose QAM Annex & Symbol Rate settings to DMS app
81 *
82 * 73   9/26/11 10:22a ssood
83 * SW7346-341: Add PVR Decryption support for file streaming
84 *
85 * 72   8/28/11 5:30a ssood
86 * SW7346-309: add support for parsing additional satellite modes
87 *
88 * 71   8/22/11 12:20p ssood
89 * SW7425-1040: add logic to Skip PSI probing for FCC & provide end of
90 *  streaming callback
91 *
92 * 70   8/15/11 12:24p jrubio
93 * SW7346-451: fix coverity issue uninit
94 *
95 * 69   8/15/11 10:21a mward
96 * SW7125-1066: Set contentTypeString = NULL for NEXUS_TransportType_eEs,
97 *  NEXUS_AudioCodec_eUnknown.
98 *
99 * 68   8/5/11 3:13p ssood
100 * SW7425-1040: add fast channel change support to IP Sessions
101 *
102 * 67   7/14/11 12:01p ssood
103 * SW7346-309: Add support for Streaming from Satellite Source
104 *
105 * 66   6/20/11 11:13p ssood
106 * SW7425-751: add configurable option for nav & nav files
107 *
108 * 65   6/18/11 11:52a ssood
109 * SW7425-718: 3128 related changes: use different frontend resources for
110 *  each streaming session even though it is same channel
111 *
112 * 64   6/6/11 1:35a ssood
113 * SW7231-166: refine trickplay rates, account for timeSeekEnd from
114 *  ip_client
115 *
116 * 63   5/24/11 2:34p ssood
117 * SW7231-166: add support to handle Range.dtcp.com header
118 *
119 * 62   5/24/11 11:35a ssood
120 * SW7405-4392: Coverity fixes
121 *
122 * 61   5/19/11 4:35p ssood
123 * SW7420-1774: Add support to stream SVC/MVC videos
124 *
125 * 60   5/3/11 3:49p ssood
126 * SW7425-492: dont include netaccel header file for non-netaccel builds
127 *
128 * 59   4/29/11 1:50p ssood
129 * SW7425-175: fixed compilation warning
130 *
131 * 58   4/29/11 1:20p ssood
132 * SW7425-175: disable DTCP/IP encryption for transcode & local sessions
133 *
134 * 57   4/14/11 4:49p kagrawal
135 * SW7420-1812: Initial support for DMS on Android
136 *
137 * 56   3/16/11 4:56p ssood
138 * SW7420-1616: initial check-in for pvr encryption support
139 *
140 * 55   2/8/11 6:13a ssood
141 * SW7425-59: added MPEG2 encode support
142 *
143 * 54   1/20/11 3:28p ssood
144 * SW7425-59: switch decode to live mode in xcode path + all ces related
145 *  changes + support for 2nd xcode client
146 *
147 * 53   1/2/11 5:26p ssood
148 * SW7420-1257: added support to stream encoded frame using unicast for
149 *  local client
150 *
151 * 52   12/31/10 3:25p ssood
152 * SW7425-59: add change to support clean stop/stop sequence w/ 7425
153 *  xcoder + insert PAT/PMT into outgoing stream
154 *
155 * 51   12/30/10 1:06p ssood
156 * SW7425-59: surround all 7425 transcoder changes w/
157 *  NEXUS_HAS_VIDEO_ENCODER compile flag
158 *
159 * 50   12/30/10 12:55p ssood
160 * SW7425-59: initial 7425 transcoder support on h/w platform (no PSI, no
161 *  PCRs, no Audio in xcoded stream)
162 *
163 * 49   12/28/10 12:32p ssood
164 * SW7425-59: fix compile error for non-xcode builds
165 *
166 * 48   12/28/10 12:28p ssood
167 * SW7425-59: Add support for using HDMI-in as the source for
168 *  transcoding+streaming out
169 *
170 * 47   12/26/10 10:45p ssood
171 * SW7425-59: Add support for 7425 transcoder
172 *
173 * 46   12/6/10 4:25p ssood
174 * SW7420-1257: video conferencing parsing had broken file parsing
175 *
176 * 45   11/23/10 11:55a ssood
177 * SW7420-1257: initial check-in for rtp/udp streaming support in
178 *  ip_streamer for Video Conferencing Demo
179 *
180 * 44   9/27/10 3:16p junyel
181 * SW7420-1115: cross-platform code for DMS
182 *
183 * 43   8/26/10 5:18p ssood
184 * SW7420-883: added code to parse end offset
185 *
186 * 42   8/12/10 11:24a ssood
187 * SW7420-883: added support for streaming same transcoding session to
188 *  multiple clients
189 *
190 * 41   8/9/10 11:59a ssood
191 * SW7420-883: fixed 1 more compilation errors for non-transcoded cases
192 *
193 * 40   8/8/10 11:07p ssood
194 * SW7420-883: fixed compilation errors for non-transcoded cases
195 *
196 * 39   8/6/10 6:33p ssood
197 * SW7420-883: allow only one transcoding session at a time
198 *
199 * 38   8/5/10 7:32a ssood
200 * SW7420-883: added support for allowing external apps to configure
201 *  transcoding parameters into ip streamer library
202 *
203 * 37   7/30/10 3:34p garetht
204 * SW7420-919: Add CableCARD support to Ip_streamer
205 *
206 * 36   7/30/10 3:19p ssood
207 * SW7420-883: add support to transcode/pass-thru audio to IP Streamer
208 *
209 * 35   7/27/10 2:55p ssood
210 * SW7420-883: add transcoding support to IP Streamer (no audio
211 *  transcoding yet)
212 *
213 * 34   7/23/10 9:27a ssood
214 * SW7125-353: Coverity fixes
215 *
216 * 33   4/29/10 10:06a ssood
217 * SW7420-561: fixed bug in handling of long urls
218 *
219 * 32   4/15/10 7:33p sgundime
220 * SW7420-689: Time seek range support is added.
221 *
222 * 31   4/2/10 5:57p ssood
223 * SW7420-561: add support to handle large URLs (HTML5 URLs can be over
224 *  256bytes) + Coverity fixes
225 *
226 * 30   3/15/10 4:40p ssood
227 * SW7125-233: Coverity fixes
228 *
229 * 29   3/1/10 12:51p ssood
230 * SW7420-604: Enable optional support for streaming both file & live
231 *  content using HTTP Xfer Chunk Encoding (build flag
232 *  USE_HTTP_CHUNK_ENCODING)
233 *
234 * 28   1/27/10 10:18a ssood
235 * SW7420-454: conditionally compile Live Streaming Code using
236 *  LIVE_STREAMING_SUPPORT
237 *
238 * 27   1/23/10 11:16a ssood
239 * SW7420-454: added support to extract 1st PTS from TS files, store in
240 *  info file & send to clients in HTTP resp
241 *
242 * 26   1/19/10 4:55p ssood
243 * SW7420-454: convert verbose output to be available via msg modules
244 *  flags
245 *
246 * 25   1/14/10 6:41p ssood
247 * SW7408-47: Add support to compile IP Streamer App on platforms w/ no
248 *  frontend support
249 *
250 * 24   1/3/10 12:19a ssood
251 * SW7420-454: modify duration to follow x-intel-mediaDuration syntax
252 *
253 * 23   12/30/09 1:22a ssood
254 * SW7420-454: fail recording if it is not a live channel
255 *
256 * 22   12/17/09 2:07p ssood
257 * SW7420-454: Add option to just open IP Streamer & IP library contexts
258 *  for Media Probe purposes
259 *
260 * 21   12/15/09 3:56p ssood
261 * SW7420-454: accept PlaySpeed & TimeOffset fields from DMS URL
262 *
263 * 20   12/10/09 7:33p ssood
264 * SW7420-502: Add HTTP header to indicate usage of HTTP chunked encoding
265 *
266 * 19   12/7/09 6:35p ssood
267 * SW7420-454: Added support to parse PlaySpeed & TimeSeekRange Headers
268 *
269 * 18   12/3/09 2:35p ssood
270 * SW7420-454: Add support to stream any generic media formats
271 *
272 * 17   11/24/09 10:48a ssood
273 * SW7420-454: add option to allow apps to specify a specific interface
274 *  name to receive live IP content
275 *
276 * 16   11/18/09 3:21p ssood
277 * SW7420-454: qam streaming wasn't working due to IP dst being disabled
278 *  for qam
279 *
280 * 16   11/18/09 3:18p ssood
281 * SW7420-454: qam streaming wasn't working due to IP dst being disabled
282 *  for qam
283 *
284 * 15   11/18/09 12:43p ssood
285 * SW7420-454: added HTTP parameter on client so that it can indicate
286 *  DTCP/IP encryption to ip_streamer
287 *
288 * 14   11/17/09 2:57p ssood
289 * SW7420-454: Enhance IP Streamer to stream files from local disk
290 *
291 * 11   11/2/09 3:56p ssood
292 * SW7420-340: add support for recording a live stream
293 *
294 * 10   10/20/09 6:33p ssood
295 * SW7420-340: remove nexus playback, audio, video decoder dependencies
296 *  for SMS compilation
297 *
298 * 9   10/11/09 8:52p ssood
299 * SW7420-340: added support to bind ip_streamer to a particular network
300 *  interface
301 *
302 * 8   10/11/09 12:22a ssood
303 * SW7420-340: increase the write queue size
304 *
305 * 7   10/10/09 10:49p ssood
306 * SW7420-340: Changes to allow non-Broadcom DLNA clients play live
307 *  content
308 *
309 * 6   10/9/09 12:29p ssood
310 * SW7420-340: add support to play live streams on non-Broadcom clients
311 *
312 * 5   10/6/09 12:18p ssood
313 * SW7420-340: Add DTCP/IP support to ip_streamer & IP Applib
314 *
315 * 4   10/2/09 11:28a ssood
316 * SW7420-340: increased the TCP Send q size for streaming sessions
317 *
318 * 3   9/25/09 6:27p ismailk
319 * SW7405-3080: Get the URI from the CDS in the DMS case.
320 *
321 * 2   9/17/09 2:58p ssood
322 * SW7420-340: compiling for SMS
323 *
324 * 1   9/16/09 10:50a ssood
325 * SW7420-340: Adding example apps for demonstrating IP Streaming & Client
326 *  features of IP Applib
327 *
328 *
329 *************************************************************/ 
330#include <stdio.h>
331#include <stdlib.h>
332#include <errno.h>
333#include <string.h>
334#include <signal.h>
335#include <sched.h>
336#include <unistd.h>
337#include <fcntl.h>
338#include <sys/stat.h>
339#include <sys/types.h>
340#include <sys/select.h>
341#include <sys/socket.h>
342#include <sys/uio.h>
343#include <arpa/inet.h>
344#include <netinet/in.h>
345#include <arpa/inet.h>
346#include <net/if.h>
347#include <sys/syscall.h>
348#ifdef __mips__
349#include <asm/cachectl.h>
350#endif
351#ifndef DMS_CROSS_PLATFORMS
352#include "nexus_platform.h"
353#endif /* DMS_CROSS_PLATFORMS */
354#if B_HAS_LIVE_STREAMING
355#include "nexus_frontend.h"
356#include "nexus_parser_band.h"
357#include "nexus_pid_channel.h"
358#include "nexus_playpump.h"
359#include "nexus_message.h"
360#include "nexus_recpump.h"
361#include "nexus_record.h"
362#endif
363#include "b_playback_ip_lib.h"
364#if !defined(DMS_CROSS_PLATFORMS) && defined(B_HAS_NETACCEL_SUPPORT)
365#include "bnetaccel_info.h"
366#endif /* DMS_CROSS_PLATFORMS */
367#include "ip_streamer_lib.h"
368#include "ip_streamer.h"
369BDBG_MODULE(ip_http);
370
371#define ALIGN_4096   (4096 - 1)
372#define BUF_SIZE        (188*7*128)
373#define NUM_BUF_DESC    24
374#ifndef O_DIRECT  /* DMS_CROSS_PLATFORMS */
375#define O_DIRECT        0x8000
376#endif  /* DMS_CROSS_PLATFORMS */
377#define FILENAME_MAX_LEN 256
378
379extern int gExitThread;
380
381extern char *getXferURIfromCDS(char *url);
382extern char *B_PlaybackIp_UtilsStristr ( char *str, char *subStr);
383
384static char *gRootDir = NULL;
385
386#if !defined(DMS_CROSS_PLATFORMS) && defined(B_HAS_NETACCEL_SUPPORT)
387int 
388sockWait(int sd, int socket_type, unsigned int size)
389{
390    STRM_Status_t status;
391    unsigned int len = sizeof(status);
392
393    if(getsockopt(sd, socket_type, STRM_STATUS, &status, &len) != 0)
394        return -1;
395
396    while( (status.free_desc_count <= 2) || 
397                        ((status.buffer_locked_depth + size ) > (size * NUM_BUF_DESC))) {
398        usleep(10000);
399        if (getsockopt(sd,  SOCK_BRCM_DGRAM, STRM_STATUS, &status, &len) != 0)
400            return -1;
401    }
402
403    return 0;
404}
405
406#if 0
407static void
408setThreadAffinity(int cpu_affinity_mask)
409{
410#ifdef __mips__
411        unsigned long new_mask;
412
413    syscall(SYS_sched_setaffinity, getpid(), 4, &cpu_affinity_mask);
414    syscall(SYS_sched_getaffinity, getpid(), 4, &new_mask);
415
416        printf("Updated CPU Affinity mask %lu", new_mask);
417        /* uncomment this line to verify the cpu affinity */
418        /* while (1); */
419#endif
420}
421#endif
422
423/* set the number of buffer descriptors in the driver */
424int 
425sockSetDesc(int sd, int socket_type, int num_desc)
426{
427    STRM_SetBuffer_t bi;
428    unsigned int len = sizeof(bi);
429    bi.num_desc = num_desc;
430
431    if (setsockopt(sd, socket_type, STRM_SETDESC, &bi, len) != 0)
432        return -1;
433    return 0;
434}
435
436int 
437sockSetMode(int sd, int socket_type, int disable_checksum)
438{
439    STRM_Ctrl_t ctrl;
440    memset(&ctrl,0,sizeof(ctrl));
441
442        BDBG_MSG(("TCP Checksum computation %s", (disable_checksum == 1) ? "OFF" : "ON"));
443    ctrl.disable_checksum = disable_checksum;
444    if(setsockopt(sd, socket_type, STRM_CTRL, &ctrl, sizeof(ctrl)) != 0)
445            BDBG_WRN(("setsockopt: %s Failed to disable checksum", "STRM_CTRL"));
446    return 0;
447}
448#endif /* DMS_CROSS_PLATFORMS */
449
450/* Open the listener service on port 5000 */
451int 
452initTcpServer(IpStreamerGlobalCfg *ipStreamerGlobalCfg)
453{
454    struct sockaddr_in localAddr;
455    int port, socket_type;
456    char *interfaceName;
457    int sd;
458    int reuse_flag = 1;
459
460    port = ipStreamerGlobalCfg->listeningPort;
461#if !defined(DMS_CROSS_PLATFORMS) && defined(B_HAS_NETACCEL_SUPPORT)
462    socket_type = (ipStreamerGlobalCfg->accelSocket == 1) ? SOCK_BRCM_STREAM : SOCK_STREAM; 
463#else
464    socket_type = SOCK_STREAM;
465#endif   
466    interfaceName = ipStreamerGlobalCfg->interfaceName;
467    gRootDir = ipStreamerGlobalCfg->rootDir;
468    if ( (sd = socket(AF_INET, socket_type, 0)) < 0) {
469        /* Socket Create Error */
470        perror("Socket Open Err");
471        return -EINVAL;
472    }
473
474    if (setsockopt( sd, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_flag, sizeof(reuse_flag) ) < 0 ) {
475        BDBG_ERR(("REUSE Socket Error"));
476        return -EINVAL;
477    }
478
479#if 0
480    struct ifreq ifr;
481    /* TODO: see if this code is needed anymore */
482    memset(&ifr, 0, sizeof(ifr));
483    strncpy(ifr.ifr_name, interfaceName, sizeof(ifr.ifr_name));
484    if (setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr) ) < 0 ) {
485        BDBG_ERR(("SO_BINDTODEVICE Failed"));
486        return -EINVAL;
487    }
488    BDBG_WRN(("Binding to i/f %s", interfaceName));
489#endif
490
491    localAddr.sin_family = AF_INET;
492    localAddr.sin_port = htons(port);
493    localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
494    if (bind(sd, (struct sockaddr *) &localAddr, sizeof(localAddr))) {
495        perror("Socket Bind Err to bind to actual i/f");
496        return -EINVAL;
497    }
498    BDBG_MSG(("Socket Bind to actual i/f successful"));
499   
500    if (listen(sd, 4)) {
501        perror("Socket listen Err");
502        return -EINVAL;
503    }
504    BDBG_MSG(("Started listening on %d port ", port));
505
506    /* Set stdin to non-blocking */
507    if (fcntl(sd, F_SETFL, fcntl(sd, F_GETFL)|O_NONBLOCK) < 0)
508        BDBG_WRN(("ERROR setting non-blocking mode on listening socket"));
509
510    return sd;
511}
512
513/* Close the listener service */
514void 
515unInitTcpServer(int sd)
516{
517    close(sd);
518}
519
520/* Parses the input for pattern begin; followed by pattern end */
521int 
522parseToken(char *input, char *output, int output_len, char *begin, char *end)
523{
524        char *p_begin = strstr(input, begin);
525        char *p_end;
526        char temp;
527
528        if (p_begin)
529        {
530                p_begin += strlen(begin);
531                p_end = strstr(p_begin,end);
532                if(!p_end)
533                        return -1;
534                temp = *p_end;
535                *p_end = 0;
536                BDBG_MSG(("TokenFound = [%s]",p_begin));
537#ifndef DMS_CROSS_PLATFORMS
538                strlcpy(output,p_begin, output_len-1);
539#else
540                if ( output_len > 1 )
541                        strncpy(output,p_begin, output_len-1);
542#endif /* DMS_CROSS_PLATFORMS */
543                *p_end = temp;
544                return 0;
545        }
546        return -1; /* Not found */
547}
548
549void 
550waitForNetworkEvent(int sd)
551{
552        fd_set rfds;
553        struct timeval tv;
554
555        while (!gExitThread) {
556                FD_ZERO(&rfds);
557                FD_SET(sd, &rfds);
558                tv.tv_sec = 2;
559                tv.tv_usec = 0;
560
561                if ( select(sd +1, &rfds, NULL, NULL, &tv) < 0 ) {
562                        perror("ERROR: select(): exiting...");
563                        break;
564                }
565
566                if (!FD_ISSET(sd, &rfds))
567                        /* No request from Client yet, go back to select loop */
568                        continue;
569                break;
570        }
571
572    return;
573}
574
575void 
576getContentType(B_PlaybackIpPsiInfo *psi, char *contentType, int contentTypeLength)
577{
578    char *contentTypeString= NULL; 
579    memset(contentType, 0, contentTypeLength);
580    switch (psi->mpegType) {
581        case NEXUS_TransportType_eTs:
582        case NEXUS_TransportType_eMpeg2Pes:
583        case NEXUS_TransportType_eVob:
584        case NEXUS_TransportType_eMpeg1Ps:
585            contentTypeString = "video/mpeg"; /* MPEG2, AVC TS files */
586            break;
587            /* FOR TTS files, use "video/vnd.dlna.mpeg-tts" */
588        case NEXUS_TransportType_eMp4:
589            contentTypeString = "video/mp4"; /* MP4 */
590            break;
591        case NEXUS_TransportType_eAsf:
592            contentTypeString = "video/x-ms-wmv"; /* ASF: WMV/WMA */
593            break;
594        case NEXUS_TransportType_eAvi:
595            contentTypeString = "video/x-msvideo"; /* AVI */
596            break;
597        case NEXUS_TransportType_eWav:
598            contentTypeString = "video/x-wav"; /* WAV */
599            break;
600        case NEXUS_TransportType_eEs:
601            if (psi->audioCodec == NEXUS_AudioCodec_eUnknown) {
602                                BDBG_WRN(("Couldn't determine MIME type for container NEXUS_TransportType_eEs, video codec %d, audio codec NEXUS_AudioCodec_eUnknown", psi->videoCodec));
603                                contentTypeString = NULL;
604                        }
605                        else {
606                                contentTypeString = "audio/mpeg"; /* MP3 */
607                        }
608            break;
609        default:
610            contentTypeString = NULL;
611    }
612
613    if(contentTypeString == NULL ){
614        BDBG_WRN(("Couldn't determine MIME type for container %d, video codec %d, audio codec %d", psi->mpegType, psi->videoCodec, psi->audioCodec));
615        return;
616    }
617
618    if (strlen(contentTypeString) < (unsigned)contentTypeLength)
619        snprintf(contentType, contentTypeLength-1, "%s", contentTypeString);
620    return;
621}
622
623/* waits for incoming HTTP requests, sends out HTTP response and returns new socket descriptor */
624int 
625sendHttpResponse(IpStreamerConfig *ipStreamerCfg, int sd, B_PlaybackIpPsiInfo *psi)
626{
627        int nbytes;
628    unsigned i;
629    char responseBuf[1024], *response;
630    off_t contentLength = 0;
631    char contentType[32];
632    int bytesCopied, bytesLeft;
633
634    /* Build HTTP response */
635    memset(responseBuf, 0, sizeof(responseBuf));
636    memset(contentType, 0, sizeof(contentType));
637    response = responseBuf;
638    bytesLeft = sizeof(responseBuf) - 1;
639    bytesCopied = snprintf(response, bytesLeft,
640        "HTTP/1.1 200 OK\r\n"
641        "Accept-Ranges: bytes\r\n"
642        "Connection: close\r\n"
643#ifdef B_USE_HTTP_CHUNK_ENCODING
644        "TRANSFER-ENCODING: chunked\r\n"
645#endif
646        "transferMode.dlna.org: Streaming\r\n"
647        "Server: Linux/2.6.xx, Broadcom IP Streamer 2.0\r\n"
648        );
649    bytesLeft -= bytesCopied;
650    response += bytesCopied;
651
652    if (psi) {
653        getContentType(psi, contentType, sizeof(contentType));
654        bytesCopied = snprintf(response, bytesLeft, "Content-Type: %s\r\n", contentType);
655        bytesLeft -= bytesCopied;
656        response += bytesCopied;
657        if (psi->liveChannel) {
658#if 0
659#define USE_TRANSPORT_TIMESTAMPS
660#endif
661#ifdef USE_TRANSPORT_TIMESTAMPS
662            bytesCopied = snprintf(response, bytesLeft, "BCM-LiveChannel: 1\r\nTTS: 1\r\n");
663#else
664            bytesCopied = snprintf(response, bytesLeft, "BCM-LiveChannel: 1\r\n");
665#endif
666            bytesLeft -= bytesCopied;
667            response += bytesCopied;
668        }
669        else {
670            /* File playback */
671            if (ipStreamerCfg->beginFileOffset) {
672                bytesCopied = snprintf(response, bytesLeft, "Range: bytes=%lld-", ipStreamerCfg->beginFileOffset);
673                bytesLeft -= bytesCopied;
674                response += bytesCopied;
675                if (!ipStreamerCfg->endFileOffset) {
676                    ipStreamerCfg->endFileOffset = psi->contentLength - 1;
677                }
678                contentLength = ipStreamerCfg->endFileOffset - ipStreamerCfg->beginFileOffset + 1;
679                bytesCopied = snprintf(response, bytesLeft, "%lld/%lld\r\n", ipStreamerCfg->endFileOffset, psi->contentLength);
680                bytesLeft -= bytesCopied;
681                response += bytesCopied;
682            }
683            else {
684                /* No begin offset requested, so send content length is available */
685                contentLength = psi->contentLength;
686                ipStreamerCfg->endFileOffset = psi->contentLength - 1;
687                ipStreamerCfg->beginFileOffset = 0;
688            }
689            bytesCopied = snprintf(response, bytesLeft, "Content-Length: %lld\r\n", contentLength);
690            bytesLeft -= bytesCopied;
691            response += bytesCopied;
692        }
693        if (psi->psiValid) {
694            BDBG_MSG(("Content length %lld, PSI info vpid %d, vcodec %d, pcr pid %d, apid %d, acodec %d, transport type %d",
695                contentLength, psi->videoPid, psi->videoCodec, psi->pcrPid,
696                psi->audioPid, psi->audioCodec, psi->mpegType));
697            bytesCopied = snprintf(response, bytesLeft,
698                "BCM-Video-Pid: %d\r\n"
699                "BCM-Video-Type: %d\r\n"
700                "BCM-Pcr-Pid: %d\r\n"
701                "BCM-Audio-Pid: %d\r\n"
702                "BCM-Audio-Type: %d\r\n"
703                "BCM-Transport-Type: %d\r\n"
704                ,
705#if defined(NEXUS_HAS_7043_TRANSCODER) || defined(NEXUS_HAS_VIDEO_ENCODER)
706                (ipStreamerCfg->transcodeEnabled ? ipStreamerCfg->transcode.outVideoPid:psi->videoPid), 
707                (ipStreamerCfg->transcodeEnabled ? ipStreamerCfg->transcode.outVideoCodec:psi->videoCodec), 
708                (ipStreamerCfg->transcodeEnabled ? ipStreamerCfg->transcode.outPcrPid:psi->pcrPid), 
709                (ipStreamerCfg->transcodeEnabled ? ipStreamerCfg->transcode.outAudioPid:psi->audioPid),
710                (ipStreamerCfg->transcodeEnabled ? ipStreamerCfg->transcode.outAudioCodec:psi->audioCodec),
711                (ipStreamerCfg->transcodeEnabled ? ipStreamerCfg->transcode.transportType: psi->mpegType)
712#else
713                psi->videoPid, 
714                psi->videoCodec,
715                psi->pcrPid,
716                psi->audioPid, 
717                psi->audioCodec,
718                psi->mpegType
719#endif
720                );
721            bytesLeft -= bytesCopied;
722            response += bytesCopied;
723            if (psi->extraVideoCodec != NEXUS_VideoCodec_eNone && psi->extraVideoPid != 0) {
724                bytesCopied = snprintf(response, bytesLeft,
725                                        "BCM-Extra-Video-Pid: %d\r\n"
726                                        "BCM-Extra-Video-Type: %d\r\n",
727                                        psi->extraVideoPid, psi->extraVideoCodec);
728                bytesLeft -= bytesCopied;
729                response += bytesCopied;
730            }
731            if (psi->numPlaySpeedEntries) {
732                bytesCopied = snprintf(response, bytesLeft,
733                    "x-intel-MediaDuration: %u\r\n"  /* this is in seconds */ 
734                    "TTS: %d\r\n"
735                    "BCM-Frame-Repeat: %u\r\n"
736                    "BCM-Min-Iframe-Speed: %u\r\n"
737                    "BCM-First-PTS: %u\r\n",
738                     psi->duration/1000 /* convert to seconds */, 
739                     psi->transportTimeStampEnabled, 
740                     psi->httpFrameRepeat, 
741                     psi->httpMinIFrameSpeed,
742                     psi->firstPts
743                     );
744                bytesLeft -= bytesCopied;
745                response += bytesCopied;
746
747                bytesCopied = snprintf(response, bytesLeft, 
748                    "ContentFeatures.dlna.org: DLNA.ORG_PN=MPEG_TS_NTSC;DLNA.ORG_OP=10;DLNA.ORG_PS=%d", 
749                    psi->playSpeed[0]);
750                bytesLeft -= bytesCopied;
751                response += bytesCopied;
752                for (i=1; i<psi->numPlaySpeedEntries; i++) {
753                    bytesCopied = snprintf(response, bytesLeft, ",%d", psi->playSpeed[i]);
754                    bytesLeft -= bytesCopied;
755                    response += bytesCopied;
756                }
757                bytesCopied = snprintf(response, bytesLeft, "\r\n");
758                bytesLeft -= bytesCopied;
759                response += bytesCopied;
760            }
761        }
762        bytesCopied = snprintf(response, bytesLeft, "\r\n");
763        bytesLeft -= bytesCopied;
764        response += bytesCopied;
765    }
766    else {
767        bytesCopied = snprintf(response, bytesLeft, "\r\n");
768        bytesLeft -= bytesCopied;
769        response += bytesCopied;
770    }
771    nbytes = response - responseBuf;
772#ifdef __mips__
773#if ANDROID
774    syscall(cacheflush, response, nbytes, DCACHE); 
775#else
776    syscall(SYS_cacheflush, response, nbytes, DCACHE); 
777#endif
778#endif
779    BDBG_MSG(("HTTP Response (size %d) [%s]", nbytes, responseBuf));
780
781    /* send out HTTP response */
782    if (write(sd, responseBuf, nbytes) != nbytes) {
783        printf("Failed to write HTTP Response of %d bytes", nbytes);
784        perror("write(): ");
785        return -1;
786    }
787    return 0;
788}
789
790void 
791setDefaultIpStreamerSessionConfig(
792    IpStreamerConfig *ipStreamerCfg,
793    IpStreamerGlobalCfg *ipStreamerGlobalCfg
794    )
795{
796        memset(ipStreamerCfg, 0, sizeof(IpStreamerConfig));
797
798    /* IP tuner defaults */
799        ipStreamerCfg->iphVersion = 4;
800        ipStreamerCfg->srcProtocol = B_PlaybackIpProtocol_eHttp;
801        memcpy(ipStreamerCfg->srcIpAddress, "127.0.0.1", sizeof(ipStreamerCfg->srcIpAddress));
802        ipStreamerCfg->srcPort = 1234;
803    ipStreamerCfg->accelSocket = false;
804    ipStreamerCfg->useLiveIpMode = true;
805    ipStreamerCfg->encryptionEnabled = false;
806    ipStreamerCfg->emiValue = 12;
807   
808    strncpy(ipStreamerCfg->interfaceName, ipStreamerGlobalCfg->interfaceName, sizeof(ipStreamerCfg->interfaceName)-1);
809#if B_HAS_LIVE_STREAMING
810    /* Qam tuner defaults */
811    ipStreamerCfg->frequency = 111;
812    ipStreamerCfg->subChannel = 1;
813    ipStreamerCfg->qamMode = NEXUS_FrontendQamMode_e256;
814    ipStreamerCfg->recDstEnabled = false;
815    strncpy(ipStreamerCfg->fileName, "recfile.mpg", strlen("recfile.mpg"));
816    strncpy(ipStreamerCfg->indexFileName, "recfile.nav", strlen("recfile.nav"));
817#endif
818}
819
820#if defined(NEXUS_HAS_VIDEO_ENCODER)
821static void 
822mapFrameRateToNexusValue(NEXUS_VideoFrameRate* nexusFrameRate, int frameRate)
823{
824    switch (frameRate)
825    {
826        case 23976:
827            *nexusFrameRate = NEXUS_VideoFrameRate_e23_976;
828            break;
829        case 24:
830            *nexusFrameRate = NEXUS_VideoFrameRate_e24;
831            break;
832        case 25:
833            *nexusFrameRate = NEXUS_VideoFrameRate_e25;
834            break;
835        case 2997:
836            *nexusFrameRate = NEXUS_VideoFrameRate_e29_97;
837            break;
838        case 30:
839            *nexusFrameRate = NEXUS_VideoFrameRate_e30;
840            break;
841        case 50:
842            *nexusFrameRate = NEXUS_VideoFrameRate_e50;
843            break;
844        case 5994:
845            *nexusFrameRate = NEXUS_VideoFrameRate_e59_94;
846            break;
847        case 60:
848            *nexusFrameRate = NEXUS_VideoFrameRate_e60;
849            break;
850        case 14985:
851        case 15:
852            *nexusFrameRate = NEXUS_VideoFrameRate_e14_985;
853            break;
854        case 7493:
855            *nexusFrameRate = NEXUS_VideoFrameRate_e7_493;
856            break;
857        default:
858            /* not specified, we default framt rate to 30 and rely on vice firmware to do cadence detection */
859            *nexusFrameRate = NEXUS_VideoFrameRate_e30;
860    }
861    BDBG_MSG(("frame rate %d, nexus frame rate value %d", frameRate, *nexusFrameRate));
862}
863#endif
864
865int 
866parseTranscodeOptions(
867        IpStreamerOpenSettings *openSettings,
868        IpStreamerConfig *cfg
869        )
870{
871#if defined(NEXUS_HAS_7043_TRANSCODER) || defined(NEXUS_HAS_VIDEO_ENCODER)
872    char *url = openSettings->requestUri;
873    char tmpBuf[256];
874    /* TranscodeEnabled="Yes|No";TransportBitrate=xxx;OutTransport="TS|PS";*/
875    /* OutVideo="Yes|No";OutVideoCodec="MPEG2|H264|MPEG4Part2";OutAspectRatio="16x9|4x3"; */
876    /* OutFrameRate="2995|30";OutWidth=xxx;OutHeight=xxx;OutProfile="BaseLine|Main";OutLevel="L3|L31|L4|Main"; */
877    /* OutAudio="Yes|No";OutAudioCodec="AC3|MPEG|AAC"; */
878#define TRANSCODER_VIDEO_PID 0x0011
879#if 0
880#define TRANSCODER_AUDIO_PID 0x0000
881#else
882#define TRANSCODER_AUDIO_PID 0x0015
883#endif
884#define TRANSCODER_PCR_PID 0x0012
885#define TRANSCODER_PMT_PID 0x0050
886    if (parseToken(url, tmpBuf, sizeof(tmpBuf), "TranscodeEnabled=Yes", ";") == 0) {
887        cfg->transcodeEnabled = true;
888        cfg->ipDstEnabled = true;
889        /* DTCP/IP encryption is disabled for xcode channel */
890        cfg->encryptionEnabled = false;
891        BDBG_WRN(("DTCP/IP encryption has been disabled for xcode channel"));
892        /* default settings */
893        cfg->transcode.outVideoPid = TRANSCODER_VIDEO_PID;
894        cfg->transcode.outAudioPid = TRANSCODER_AUDIO_PID;
895        cfg->transcode.outPcrPid = TRANSCODER_PCR_PID;
896        cfg->transcode.outPatPid = 0;
897        cfg->transcode.outPmtPid = TRANSCODER_PMT_PID;
898
899
900        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "TransportBitrate=", ";") == 0)
901            cfg->transcode.transportBitrate = strtol(tmpBuf, (char **)NULL, 10);
902        else
903            cfg->transcode.transportBitrate = 2000000;
904        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutTransport=PS", ";") == 0)
905            cfg->transcode.transportType = NEXUS_TransportType_eMpeg2Pes;
906        else if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutTransport=TS", ";") == 0)
907            cfg->transcode.transportType = NEXUS_TransportType_eTs;
908        else
909            cfg->transcode.transportType = NEXUS_TransportType_eTs;
910
911        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutVideo=No", ";") == 0) 
912            cfg->transcode.outVideo = false;
913        else
914            cfg->transcode.outVideo = true;
915        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutVideoCodec=MPEG2", ";") == 0)
916            cfg->transcode.outVideoCodec = NEXUS_VideoCodec_eMpeg2;
917        else if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutVideoCodec=H264", ";") == 0)
918            cfg->transcode.outVideoCodec = NEXUS_VideoCodec_eH264;
919        else if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutVideoCodec=MPEG4Part2", ";") == 0)
920            cfg->transcode.outVideoCodec = NEXUS_VideoCodec_eMpeg4Part2;
921        else
922            cfg->transcode.outVideoCodec = NEXUS_VideoCodec_eH264;
923
924        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutAspectRatio=16x9", ";") == 0)
925            cfg->transcode.outAspectRatio = NEXUS_DisplayAspectRatio_e16x9;
926        else if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutAspectRatio=4x3", ";") == 0)
927            cfg->transcode.outAspectRatio = NEXUS_DisplayAspectRatio_e4x3;
928        else
929            cfg->transcode.outAspectRatio = NEXUS_AspectRatio_e16x9;
930
931        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutFrameRate=", ";") == 0) {
932            int frameRate;
933            frameRate = strtol(tmpBuf, (char **)NULL, 10);
934            mapFrameRateToNexusValue(&cfg->transcode.outFrameRate, frameRate);
935        }
936        else {
937            /* not specified, we default framt rate to 30 and rely on vice firmware to do cadence detection */
938            cfg->transcode.outFrameRate = NEXUS_VideoFrameRate_e30;
939        }
940        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutHeight=", ";") == 0)
941            cfg->transcode.outHeight = strtol(tmpBuf, (char **)NULL, 10);
942        else
943            cfg->transcode.outHeight = 480;
944
945        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutWidth=", ";") == 0)
946            cfg->transcode.outWidth = strtol(tmpBuf, (char **)NULL, 10);
947        else {
948            if (cfg->transcode.outHeight == 480)
949                cfg->transcode.outWidth = 640;
950            else
951                cfg->transcode.outWidth = 1280;
952        }
953
954        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutAudio=No", ";") == 0)
955            cfg->transcode.outAudio = false;
956        else
957            cfg->transcode.outAudio = true;
958
959        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutAudioCodec=MPEG", ";") == 0)
960            cfg->transcode.outAudioCodec = NEXUS_AudioCodec_eMp3;
961        else if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutAudioCodec=AC3", ";") == 0)
962            cfg->transcode.outAudioCodec = NEXUS_AudioCodec_eAc3;
963        else if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutAudioCodec=AAC", ";") == 0)
964            cfg->transcode.outAudioCodec = NEXUS_AudioCodec_eAacAdts;
965        else
966            cfg->transcode.outAudioCodec = NEXUS_AudioCodec_eAacAdts;
967        if (cfg->transcode.outAudioPid == 0)
968            cfg->transcode.outAudio = false;
969
970        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "OutInterlaced=Yes", ";") == 0) 
971            cfg->transcode.outInterlaced = true;
972        else
973            /* default is progressive output */
974            cfg->transcode.outInterlaced = false;
975        BDBG_WRN(("xcode: bitrate %d, transport %d, ar %d, interlaced %d, fr %d, res %dx%d, video %d, audio %d, vcodec %d, acodec %d",
976                cfg->transcode.transportBitrate, cfg->transcode.transportType, cfg->transcode.outAspectRatio, cfg->transcode.outInterlaced, cfg->transcode.outFrameRate, 
977                cfg->transcode.outWidth, cfg->transcode.outHeight, cfg->transcode.outVideo, cfg->transcode.outAudio,  cfg->transcode.outVideoCodec,  cfg->transcode.outAudioCodec));
978    }
979    else {
980        BDBG_MSG(("Transcode Param is not set"));
981        if (cfg->srcType == IpStreamerSrc_eHdmi) {
982            BDBG_ERR(("ERROR: Encoding Parameters need to be set for streaming out HDMI input"));
983            return -1;
984        }
985        cfg->transcodeEnabled = false;
986    }
987    return 0;
988#else
989    BSTD_UNUSED(openSettings);
990    BSTD_UNUSED(cfg);
991#endif
992    return 0;
993}
994
995int 
996getRequestInfoFromUrl(
997        IpStreamerOpenSettings *openSettings,
998        IpStreamerConfig *cfg,
999        IpStreamerGlobalCfg *ipStreamerGlobalCfg
1000    )
1001{
1002    char tmpBuf[256];
1003    char *tmpPtr;
1004    char *url; 
1005    int newFd;
1006
1007    /* default configuration */
1008    setDefaultIpStreamerSessionConfig(cfg, ipStreamerGlobalCfg);
1009
1010    url = openSettings->requestUri;
1011    newFd = openSettings->streamingFd;
1012    cfg->streamingFd = newFd;
1013    cfg->streamingFdLocal = openSettings->streamingFdLocal;
1014    cfg->mediaProbeOnly = openSettings->mediaProbeOnly;
1015    cfg->skipPsiAcquisition = openSettings->skipPsiAcquisition;
1016    cfg->eventCallback = openSettings->eventCallback;
1017    cfg->appCtx = openSettings->appCtx;
1018    cfg->pvrDecKeyHandle = openSettings->pvrDecKeyHandle;
1019
1020    BDBG_WRN(("URL is:%s", url));
1021    tmpPtr = strstr(url, "LiveChannel;");
1022    if (!tmpPtr) {
1023        /* it is not a live channel, return error if RecEnabled is set */
1024        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "RecEnabled=", ";") == 0) {
1025            BDBG_WRN(("Recording is being requested for non-Live channels, return error"));
1026            return -1;
1027        }
1028        goto fileParsing;
1029    }
1030#if B_HAS_LIVE_STREAMING
1031    memset(tmpBuf, 0, sizeof(tmpBuf));
1032    if (parseToken(url, tmpBuf, sizeof(tmpBuf), "Type=", ";")) {
1033        BDBG_MSG(("No Type Parameter found"));
1034        return -1;
1035    }
1036    BDBG_MSG(("Type is %s", tmpBuf));
1037    cfg->ipDstEnabled = true;
1038    if (strcmp(tmpBuf, "IP") == 0) {
1039    /* Syntax is --> */
1040    /* /LiveChannel;Type=IP;Address=192.168.1.1.;Port=1234;InterfaceName=eth0;Protocol=UDP;EncEnabled=Yes;RecEnabled=Yes;FileName=/data/videos/rec0.mpg; */
1041        cfg->srcType = IpStreamerSrc_eIp;
1042        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "Address=", ";")) {
1043            BDBG_WRN(("ERROR: No Address Parameter found"));
1044            return -1;
1045        }
1046        memcpy(cfg->srcIpAddress, tmpBuf, sizeof(cfg->srcIpAddress));
1047        BDBG_MSG(("Host is %s", cfg->srcIpAddress));
1048        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "Port=", ";")) {
1049            BDBG_MSG(("ERROR: No Port Parameter found"));
1050            return -1;
1051        }
1052        cfg->srcPort = strtol(tmpBuf, (char **)NULL, 10);
1053        BDBG_MSG(("port is %d", cfg->srcPort));
1054        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "Protocol=", ";") == 0) {
1055            BDBG_MSG(("Protocol is %s", tmpBuf));
1056            if (strcmp(tmpBuf, "UDP") == 0)
1057                cfg->srcProtocol = B_PlaybackIpProtocol_eUdp;
1058            else
1059                cfg->srcProtocol = B_PlaybackIpProtocol_eRtp;
1060        }
1061        else {
1062            BDBG_MSG(("No Protocol Parameter found, assuming UDP"));
1063            cfg->srcProtocol = B_PlaybackIpProtocol_eUdp;
1064        }
1065        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "InterfaceName=", ";") == 0) {
1066            BDBG_MSG(("Interface is %s", tmpBuf));
1067            strncpy(cfg->interfaceName, tmpBuf, sizeof(cfg->interfaceName)-1);
1068        }
1069        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "IpVersion=", ";") == 0) {
1070            BDBG_MSG(("IP version is %s", tmpBuf));
1071            if (strcmp(tmpBuf, "4") == 0)
1072                cfg->iphVersion = 4;
1073            else
1074                cfg->iphVersion = 6;
1075        }
1076        else {
1077            BDBG_MSG(("No IP Version Parameter, assuming IPv4"));
1078            cfg->iphVersion = 4;
1079        }
1080    }
1081    /* Syntax is --> */
1082    /* /LiveChannel;Type=QAM;QamMode=QAM256;Freq=357.00;SubChannel=2;EncEnabled=Yes;TranscodeEnabled=Yes;AspectRatio=;Width=;Height=;BitRate= */
1083    else if (strcmp(tmpBuf, "QAM") == 0) {
1084        cfg->srcType = IpStreamerSrc_eQam;
1085        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "Freq=", ";")) {
1086            BDBG_MSG(("No Frequency Parameter found"));
1087            return -1;
1088        }
1089        cfg->frequency = strtol(tmpBuf, (char **)NULL, 10);
1090        BDBG_MSG(("frequency is %d", cfg->frequency));
1091        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "QamMode=", ";") == 0) {
1092            if (strcmp(tmpBuf, "QAM256") == 0)
1093                cfg->qamMode = NEXUS_FrontendQamMode_e256;
1094            else
1095                cfg->qamMode = NEXUS_FrontendQamMode_e64;
1096            BDBG_MSG(("QAM Modulation type set to %d", cfg->qamMode));
1097        }
1098        else {
1099            BDBG_MSG(("No QAM Modulation type set, assuming QAM256 "));
1100            cfg->qamMode = NEXUS_FrontendQamMode_e256;
1101        }
1102
1103#ifdef STREAMER_CABLECARD_SUPPORT
1104        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "SourceID=", ";")) {
1105            BDBG_MSG(("No Source ID Parameter found"));
1106            return -1;
1107        }
1108        cfg->sourceId = strtol(tmpBuf, (char **)NULL, 10);
1109#endif
1110
1111        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "QamAnnex=", ";") == 0) {
1112            if (strcmp(tmpBuf, "A") == 0)
1113                cfg->qamAnnex = NEXUS_FrontendQamAnnex_eA;
1114            else if (strcmp(tmpBuf, "B") == 0)
1115                cfg->qamAnnex = NEXUS_FrontendQamAnnex_eB;
1116            else if (strcmp(tmpBuf, "C") == 0)
1117                cfg->qamAnnex = NEXUS_FrontendQamAnnex_eC;
1118            else
1119                cfg->qamAnnex = NEXUS_FrontendQamAnnex_eB;
1120            BDBG_MSG(("QAM Annex set to %d", cfg->qamAnnex));
1121        }
1122        else {
1123            BDBG_MSG(("No QAM Annex set, assuming AnnexB "));
1124                cfg->qamAnnex = NEXUS_FrontendQamAnnex_eB;
1125        }
1126
1127        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "SymbolRate=", ";") == 0) {
1128            cfg->symbolRate = strtol(tmpBuf, (char **)NULL, 10);
1129            BDBG_MSG(("%s: symbolRate is %d", __FUNCTION__, cfg->symbolRate));
1130        }
1131        else {
1132            switch(cfg->qamMode) {
1133            case NEXUS_FrontendQamMode_e64: cfg->symbolRate = 5056900; break;
1134            case NEXUS_FrontendQamMode_e256: cfg->symbolRate = 5360537; break;
1135            default:
1136            case NEXUS_FrontendQamMode_e1024: cfg->symbolRate = 0; /* TODO */ break; 
1137            }
1138            BDBG_MSG(("No Symbol Rate set, setting based on the qamMode to %d", cfg->symbolRate));
1139        }
1140
1141    }
1142    else if (strcmp(tmpBuf, "SAT") == 0) {
1143        /* Complete string is */
1144        /* /LiveChannel\;Type=SAT\;SatMode=DVB\;DiseqcVoltage=13\;ToneEnabled=Yes\;SymbolRate=20000000\;Freq=1207\;SubChannel=1\; */
1145        /* Fields are: */
1146        /* SatMode = DVB/DSS/etc.. */
1147        /* ToneEnabled=Yes|No */
1148        /* SymbolRate=20000000 */
1149        /* ToneEnabled=Yes|No */
1150        /* DiseqcVoltage=13|18 */
1151        int voltage;
1152        cfg->srcType = IpStreamerSrc_eSat;
1153        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "Freq=", ";")) {
1154            BDBG_ERR(("%s: No Frequency Parameter found", __FUNCTION__));
1155            return -1;
1156        }
1157        cfg->frequency = strtol(tmpBuf, (char **)NULL, 10);
1158        BDBG_MSG(("frequency is %d", cfg->frequency));
1159
1160        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "SymbolRate=", ";")) {
1161            BDBG_ERR(("%s: No SymbolRate Parameter found", __FUNCTION__));
1162            return -1;
1163        }
1164        cfg->symbolRate = strtol(tmpBuf, (char **)NULL, 10);
1165        BDBG_MSG(("%s: symbolRate is %d", __FUNCTION__, cfg->symbolRate));
1166
1167        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "SatMode=", ";")) {
1168            BDBG_ERR(("%s: No Sat Modulation type set", __FUNCTION__));
1169            return -1;
1170        }
1171        if (strcmp(tmpBuf, "DVB") == 0)
1172            cfg->satMode = NEXUS_FrontendSatelliteMode_eDvb;
1173        else if (strcmp(tmpBuf, "DSS") == 0)
1174            cfg->satMode = NEXUS_FrontendSatelliteMode_eDss;
1175        else if (strcmp(tmpBuf, "LDPC") == 0)
1176            cfg->satMode = NEXUS_FrontendSatelliteMode_eLdpc;
1177        else if (strcmp(tmpBuf, "QPSKLDPC") == 0)
1178            cfg->satMode = NEXUS_FrontendSatelliteMode_eQpskLdpc;
1179        else if (strcmp(tmpBuf, "TURBO") == 0)
1180            cfg->satMode = NEXUS_FrontendSatelliteMode_eTurbo;
1181        else {
1182            BDBG_MSG(("%s: TODO: Sat Modulation type %s is not yet supported", __FUNCTION__, cfg->satMode));
1183            return -1;
1184        }
1185        BDBG_MSG(("Sat Modulation type set to %d", cfg->satMode));
1186
1187        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "DiseqcVoltage=", ";")) {
1188            BDBG_ERR(("%s: ERROR: No DiseqcVoltage Parameter found", __FUNCTION__));
1189            return -1;
1190        }
1191        voltage = strtol(tmpBuf, (char **)NULL, 10);
1192        switch(voltage) {
1193            case 13:
1194                cfg->diseqcVoltage = NEXUS_FrontendDiseqcVoltage_e13v;
1195                break;
1196            case 14:
1197            default:
1198                cfg->diseqcVoltage = NEXUS_FrontendDiseqcVoltage_e18v;
1199                break;
1200        }
1201        BDBG_MSG(("DiseqcVoltage is set to %d", cfg->diseqcVoltage));
1202
1203        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "ToneEnabled=", ";") == 0) {
1204            if (strcmp(tmpBuf, "Yes") == 0) {
1205                cfg->toneEnabled = true;
1206                BDBG_MSG(("ToneEnabled Param is set"));
1207            }
1208            else {
1209                cfg->toneEnabled = false;
1210            }
1211        } else {
1212            BDBG_MSG(("ToneEnabled Param is not set"));
1213            cfg->toneEnabled = false;
1214        }
1215    }
1216    else if (strcmp(tmpBuf, "HDMI") == 0) {
1217        /* Syntax is --> */
1218        /* /LiveChannel;Type=HDMI;InputId=0;TranscodeEnabled=Yes;AspectRatio=;Width=;Height=;BitRate= */
1219#if !NEXUS_HAS_HDMI_INPUT
1220        BDBG_ERR(("ERROR: HDMI Input is not enabled/available for this platform"));
1221        return -1;
1222#endif
1223#if !NEXUS_HAS_VIDEO_ENCODER
1224        BDBG_ERR(("ERROR: HDMI Encoder is not enabled/available for this platform"));
1225        return -1;
1226#endif
1227#ifdef NEXUS_HAS_HDMI_INPUT
1228        cfg->srcType = IpStreamerSrc_eHdmi;
1229        /* TODO transcode: add any HDMI specific params */
1230        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "InputId=", ";")) {
1231            BDBG_MSG(("HDMI InputId not set, defaulting to 0"));
1232            cfg->hdmiInputId = 0;
1233        }
1234        else {
1235            cfg->hdmiInputId = strtol(tmpBuf, (char **)NULL, 10);
1236            if (cfg->hdmiInputId >= NEXUS_NUM_HDMI_INPUTS) {
1237                BDBG_ERR(("ERROR: HDMI Input Id %d is not valid, Max for this platform %d", cfg->hdmiInputId, NEXUS_NUM_HDMI_INPUTS-1));
1238                return -1;
1239            }
1240        }
1241#endif /* NEXUS_HAS_HDMI_INPUT */
1242    }
1243    /* Parameters common */
1244    /* EncEnabled=Yes;SubChannel=number;RecEnabled=Yes;FileName=/data/videos/rec0.mpg; */
1245    if (parseToken(url, tmpBuf, sizeof(tmpBuf), "SubChannel=", ";") == 0) {
1246        cfg->subChannel = strtol(tmpBuf, (char **)NULL, 10);
1247        BDBG_MSG(("Sub-Channel # is %d", cfg->subChannel));
1248    }
1249    else {
1250        BDBG_MSG(("No SubChannel Parameter found, assuming 1st channel"));
1251        cfg->subChannel = 1;
1252    }
1253    if (parseToken(url, tmpBuf, sizeof(tmpBuf), "StreamingEnabled=", ";") == 0) {
1254        /* by default, IP Streaming is always enabled unless specifically disabled */
1255        if (strcasecmp(tmpBuf, "No") == 0) {
1256            cfg->ipDstEnabled = false;
1257            BDBG_MSG(("IP Streaming is disabled "));
1258        }
1259    }
1260
1261    if (parseToken(url, tmpBuf, sizeof(tmpBuf), "EncEnabled=", ";") == 0) {
1262        if (cfg->ipDstEnabled && strcmp(tmpBuf, "Yes") == 0) {
1263            struct sockaddr_in remoteAddr, selfAddr;
1264            int addrLen;
1265
1266            addrLen = sizeof(remoteAddr);
1267            if (getpeername(cfg->streamingFd, (struct sockaddr *)&remoteAddr, (socklen_t *)&addrLen) != 0) {
1268                BDBG_ERR(("ERROR: Failed to obtain remote IP address, errno: %d \n", errno));
1269                perror("getpeername");
1270                return -1;
1271            }
1272            if (getsockname(cfg->streamingFd, (struct sockaddr *)&selfAddr, (socklen_t *)&addrLen) != 0) {
1273                BDBG_ERR(("ERROR: Failed to obtain self IP address, errno: %d \n", errno));
1274                perror("getsockname");
1275                return -1;
1276            }
1277            if (remoteAddr.sin_addr.s_addr == selfAddr.sin_addr.s_addr) {
1278                BDBG_WRN(("Disable DTCP/IP encryption for local client"));
1279                cfg->encryptionEnabled = false;
1280            } else {
1281                cfg->encryptionEnabled = true;
1282            }
1283            BDBG_MSG(("EncEnabled Param is set, will encrypt live stream"));
1284        }
1285    }
1286    else {
1287        BDBG_MSG(("EncEnabled Param set is not, assuming clear session "));
1288        cfg->encryptionEnabled = false;
1289    }
1290
1291    if (parseToken(url, tmpBuf, sizeof(tmpBuf), "PvrEncDecEnabled=", ";") == 0) {
1292        if (strcmp(tmpBuf, "Yes") == 0) {
1293            cfg->pvrEncryptionEnabled = true;
1294            BDBG_MSG(("PvrEncDecEnabled Param is set, will encrypt live stream"));
1295        }
1296    }
1297    else {
1298        BDBG_MSG(("PvrEncDecEnabled Param set is not, assuming clear session "));
1299        cfg->pvrEncryptionEnabled = false;
1300    }
1301
1302    if (parseToken(url, tmpBuf, sizeof(tmpBuf), "RecEnabled=", ";") == 0) {
1303        if (strcmp(tmpBuf, "Yes") == 0) {
1304            cfg->recDstEnabled = true;
1305            BDBG_MSG(("RecEnabled Param is set"));
1306            if (parseToken(url, tmpBuf, sizeof(tmpBuf), "FileName=", ";") == 0) {
1307                if (strlen(tmpBuf) < sizeof(cfg->fileName) && strlen(tmpBuf) != 0) {
1308                    strncpy(cfg->fileName, tmpBuf, sizeof(cfg->fileName)-1);
1309                    BDBG_MSG(("record live stream to %s", cfg->fileName));
1310                }
1311                else {
1312                    BDBG_MSG(("Invalid or too long of a file name %s", cfg->fileName));
1313                    strncpy(cfg->fileName, "recFile.mpg", strlen("recFile.mpg"));
1314                    BDBG_MSG(("defaulting record file name to %s ", cfg->fileName));
1315                }
1316            }
1317            else {
1318                strncpy(cfg->fileName, "recFile.mpg", strlen("recFile.mpg"));
1319                BDBG_MSG(("recording file name is not specified, defaulting to %s", cfg->fileName));
1320            }
1321            strncpy(cfg->indexFileName, cfg->fileName, sizeof(cfg->indexFileName)-1);
1322            tmpPtr = strstr(cfg->indexFileName, ".");
1323            if (tmpPtr) {
1324                /* Note: assumption that we will always have space for the extension byte in the name string */
1325                strncpy(tmpPtr+1, "nav", 3);
1326            }
1327            else {
1328                strncpy(tmpPtr+1, ".nav", 4);
1329            }
1330            BDBG_MSG(("index file %s", cfg->indexFileName));
1331        }
1332    }
1333    else {
1334        BDBG_MSG(("RecEnabled Param is not set, so not recording live session "));
1335        cfg->recDstEnabled = false;
1336    }
1337    /* Transcoding String */
1338    if (parseTranscodeOptions(openSettings, cfg)) {
1339        BDBG_ERR(("%s: Failed to parse transcode related parameters"));
1340        return -1;
1341    }
1342    return 0;
1343#else
1344    /* LIVE STREAMING is not compiled in, returned error */
1345    return -1;
1346#endif /* B_HAS_LIVE_STREAMING */
1347
1348fileParsing:
1349    memset(tmpBuf, 0, sizeof(tmpBuf));
1350    /* /File=<name>;ByteRangeBegin=<start>;ByteRangeEnd=<end>; */
1351    if (parseToken(url, tmpBuf, sizeof(tmpBuf), "/File=", ";") == 0) {
1352        /* we got this URL via the local DMS as regular test client doesn't send such URL param to us */
1353        strncpy(cfg->fileName, tmpBuf, sizeof(cfg->fileName)-1);
1354        BDBG_MSG(("File %s playback requested by DMS", cfg->fileName));
1355        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "MediaInfoDir=", ";") == 0) {
1356            /* we got this URL via the local DMS as regular test client doesn't send such URL param to us */
1357            strncpy(cfg->mediaInfoFilesDir, tmpBuf, sizeof(cfg->mediaInfoFilesDir)-1);
1358        }
1359        else {
1360            /* since app didn't specify mediaInfoDir, we use the media file directory for storing info & nav files */
1361            char *endPtr = NULL;
1362            char *tmp;
1363            int rootDirLen;
1364
1365            /* extract the media file directory name by seaching the file name in the string */
1366            tmp = cfg->fileName;
1367            while ((tmp = strstr(tmp, "/")) != NULL) {
1368                endPtr = tmp;
1369                tmp += 1; /* move past "/" char */
1370            }
1371            /* now mediaRelativeFileNamePtr points to the relative media file name */
1372            if (endPtr && ((unsigned)(rootDirLen = endPtr - cfg->fileName)) < sizeof(cfg->mediaInfoFilesDir)) {
1373                strncpy(cfg->mediaInfoFilesDir, cfg->fileName, rootDirLen);
1374                cfg->mediaInfoFilesDir[rootDirLen] = '\0';
1375            }
1376            else {
1377                BDBG_ERR(("%s: media file name (%s) needs to contain absolute path", __FUNCTION__, cfg->fileName));
1378                return -1;
1379            }
1380        }
1381        BDBG_MSG(("Media Info files dir is %s", cfg->mediaInfoFilesDir));
1382        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "ByteRangeBegin=", ";") == 0) {
1383            cfg->beginFileOffset = strtoll(tmpBuf, (char **)NULL, 10);
1384            BDBG_MSG(("Byte Range: Begin %lld", cfg->beginFileOffset));
1385        }
1386        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "ByteRangeEnd=", ";") == 0) {
1387            cfg->endFileOffset = strtoll(tmpBuf, (char **)NULL, 10);
1388            BDBG_MSG(("Byte Range: End %lld", cfg->endFileOffset));
1389        }
1390        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "EncEnabled=", ";") == 0) {
1391            if (strcmp(tmpBuf, "Yes") == 0) {
1392                cfg->encryptionEnabled = true;
1393                BDBG_MSG(("EncEnabled Param is set, will encrypt live stream"));
1394            }
1395        }
1396        else {
1397            BDBG_MSG(("EncEnabled Param set is not, assuming clear session"));
1398            cfg->encryptionEnabled = false;
1399        }
1400        /* Parse for ByteRangeStart/End, || TimeRangeStart/End, PlaySpeed, */
1401        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "PlaySpeed=", ";") == 0) {
1402            cfg->playSpeed = strtol(tmpBuf, (char **)NULL, 10);
1403            BDBG_MSG(("PlaySpeed %d", cfg->playSpeed));
1404        }
1405        else
1406            cfg->playSpeed = 1;
1407        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "TimeOffset=", ";") == 0) {
1408            #if ANDROID
1409            cfg->beginTimeOffset = strtod(tmpBuf, (char **)NULL);
1410            #else
1411            cfg->beginTimeOffset = strtold(tmpBuf, (char **)NULL);
1412            #endif /* ANDROID */
1413            BDBG_MSG(("TimeOffset %.3f", cfg->beginTimeOffset));                       
1414        }
1415        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "endTimeOffset=", ";") == 0) {
1416            #if ANDROID
1417            cfg->endTimeOffset = strtod(tmpBuf, (char **)NULL);
1418            #else
1419            cfg->endTimeOffset = strtold(tmpBuf, (char **)NULL);
1420            #endif /* ANDROID */
1421            BDBG_MSG(("TimeOffset %.3f", cfg->endTimeOffset));                 
1422        }               
1423        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "Address=", ";") == 0) {
1424            cfg->streamingCfg.streamingIpAddress = strdup(tmpBuf);
1425            BDBG_MSG(("Streaming to Host %s", cfg->streamingCfg.streamingIpAddress));
1426        }
1427        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "Port=", ";") == 0) {
1428            cfg->streamingCfg.streamingPort = strtol(tmpBuf, (char **)NULL, 10);
1429            BDBG_MSG(("port is %d", cfg->streamingCfg.streamingPort));
1430        }
1431
1432        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "Protocol=", ";") == 0) {
1433            BDBG_MSG(("Protocol is %s", tmpBuf));
1434            if (strcmp(tmpBuf, "UDP") == 0)
1435                cfg->streamingCfg.streamingProtocol = B_PlaybackIpProtocol_eUdp;
1436            else if (strcmp(tmpBuf, "RTP") == 0)
1437                cfg->streamingCfg.streamingProtocol = B_PlaybackIpProtocol_eRtp;
1438            else
1439                cfg->streamingCfg.streamingProtocol = B_PlaybackIpProtocol_eHttp;
1440        }
1441        else {
1442            BDBG_MSG(("No Protocol Parameter found, assuming HTTP"));
1443            cfg->streamingCfg.streamingProtocol = B_PlaybackIpProtocol_eHttp;
1444        }
1445        if (cfg->streamingCfg.streamingProtocol == B_PlaybackIpProtocol_eUdp || cfg->streamingCfg.streamingProtocol == B_PlaybackIpProtocol_eRtp)
1446            cfg->streamingCfg.url = strdup(cfg->fileName);
1447        cfg->srcType = IpStreamerSrc_eFile;
1448
1449        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "PvrDecEnabled=", ";") == 0) {
1450            if (strcmp(tmpBuf, "Yes") == 0) {
1451                cfg->pvrDecryptionEnabled = true;
1452                BDBG_MSG(("PvrEncEnabled Param is set, will decrypt the encrypted stream"));
1453            }
1454        }
1455        else {
1456            BDBG_MSG(("PvrDecEnabled Param set is not, assuming clear session "));
1457            cfg->pvrDecryptionEnabled = false;
1458        }
1459
1460        if (parseTranscodeOptions(openSettings, cfg)) {
1461            BDBG_ERR(("%s: Failed to parse transcode related parameters"));
1462            return -1;
1463        }
1464        if (cfg->transcodeEnabled) {
1465#ifdef B_HAS_LIVE_STREAMING
1466            cfg->usePlaybackForStreamingFiles = true; /* for xcoding files, we use playback channel to feed the files to xpt */
1467#else
1468            BDBG_ERR(("ERROR: Client is asking to enable transcoding, IP Streamer needs to be compiled with LIVE_STREAMING_SUPPORT=y option"));
1469            return -1;
1470#endif
1471        }
1472        return 0;
1473    }
1474
1475    /* we got this URL from a test client (not DLNA client), so need to add root dir to file name */
1476    if (parseToken(url, tmpBuf, sizeof(tmpBuf), "/", " ") == 0) {
1477        /* we got this URL directly from the regular test client */
1478        /* look for any additional arguments appended to the URL */
1479        tmpPtr = strstr(tmpBuf, ";");
1480        if (tmpPtr)
1481            /* ; is present in the URL, so it contains additional arguments, replace it w/ null char so that we get get the exact file name */
1482            *tmpPtr = '\0';
1483        cfg->fileName[sizeof(cfg->fileName)-1] = '\0';
1484        strncpy(cfg->fileName, gRootDir, sizeof(cfg->fileName)-1);
1485        strncat(cfg->fileName, "/", 1);
1486        strncat(cfg->fileName, tmpBuf, sizeof(cfg->fileName)-1);
1487
1488        BDBG_MSG(("File %s playback requested by ip test client", cfg->fileName));
1489        strncpy(cfg->mediaInfoFilesDir, gRootDir, sizeof(cfg->mediaInfoFilesDir)-1);
1490        cfg->mediaInfoFilesDir[sizeof(cfg->mediaInfoFilesDir)-1] = '\0';
1491        BDBG_MSG(("Media Info files dir is %s", cfg->mediaInfoFilesDir));
1492        if (tmpPtr) 
1493            /* replace back the ; */
1494            *tmpPtr = ';';
1495
1496        if (parseTranscodeOptions(openSettings, cfg)) {
1497            BDBG_ERR(("%s: Failed to parse transcode related parameters"));
1498            return -1;
1499        }
1500        if (cfg->transcodeEnabled) {
1501#ifdef B_HAS_LIVE_STREAMING
1502            cfg->usePlaybackForStreamingFiles = true; /* for xcoding files, we use playback channel to feed the files to xpt */
1503#else
1504            BDBG_ERR(("ERROR: Client is asking to enable transcoding, IP Streamer needs to be compiled with LIVE_STREAMING_SUPPORT=y option"));
1505            return -1;
1506#endif
1507        }
1508        /* Parse for ByteRangeStart/End, || TimeRangeStart/End, PlaySpeed, */
1509        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "Range.dtcp.com:", "\r\n") == 0) {
1510            char tmpBuf1[64];
1511            tmpPtr = tmpBuf;    /* points to "bytes=" string */
1512            if (parseToken(tmpBuf, tmpBuf1, sizeof(tmpBuf1), "bytes=", "-") == 0) {
1513                cfg->beginFileOffset = strtoll(tmpBuf1, (char **)NULL, 10);
1514                BDBG_MSG(("Byte Range: Start %lld", cfg->beginFileOffset));
1515            }
1516            tmpPtr[strlen(tmpPtr)] = '\n';
1517            if (parseToken(tmpPtr, tmpBuf1, sizeof(tmpBuf1), "-", "\n") == 0) {
1518                cfg->endFileOffset = strtoll(tmpBuf1, (char **)NULL, 10);
1519                BDBG_MSG(("Byte Range: End %lld", cfg->endFileOffset));
1520            }
1521        }
1522        else if (parseToken(url, tmpBuf, sizeof(tmpBuf), "Range:", "\r\n") == 0) {
1523            char tmpBuf1[64];
1524            tmpPtr = tmpBuf;    /* points to "bytes=" string */
1525            if (parseToken(tmpBuf, tmpBuf1, sizeof(tmpBuf1), "bytes=", "-") == 0) {
1526                cfg->beginFileOffset = strtoll(tmpBuf1, (char **)NULL, 10);
1527                BDBG_MSG(("Byte Range: Start %lld", cfg->beginFileOffset));
1528            }
1529            tmpPtr[strlen(tmpPtr)] = '\n';
1530            if (parseToken(tmpPtr, tmpBuf1, sizeof(tmpBuf1), "-", "\n") == 0) {
1531                cfg->endFileOffset = strtoll(tmpBuf1, (char **)NULL, 10);
1532                BDBG_MSG(("Byte Range: End %lld", cfg->endFileOffset));
1533            }
1534        }
1535        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "EncEnabled: ", "\r\n") == 0) {
1536            if (strcmp(tmpBuf, "Yes") == 0) {
1537                cfg->encryptionEnabled = true;
1538                BDBG_MSG(("EncEnabled Param is set, will encrypt file being streamed"));
1539            }
1540        }
1541        else {
1542            BDBG_MSG(("EncEnabled Param set is not, assuming clear session "));
1543            cfg->encryptionEnabled = false;
1544        }
1545        cfg->srcType = IpStreamerSrc_eFile;
1546
1547        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "PlaySpeed.dlna.org: speed=", "\r\n") == 0) {
1548            cfg->playSpeed = strtol(tmpBuf, (char **)NULL, 10);
1549            BDBG_MSG(("Play Speed %d", cfg->playSpeed));
1550        }
1551        if (parseToken(url, tmpBuf, sizeof(tmpBuf), "TimeSeekRange.dlna.org: npt=", "\r\n") == 0) {
1552            cfg->beginTimeOffset = strtod(tmpBuf, (char **)NULL);
1553            BDBG_MSG(("start time offset %.3f", cfg->beginTimeOffset));
1554            /* find end time offset */
1555            tmpPtr = strstr(tmpBuf, "-"); 
1556            cfg->endTimeOffset = strtod(tmpPtr+1, (char **)NULL);
1557            BDBG_MSG(("end time offset %.3f", cfg->endTimeOffset));
1558        }
1559        cfg->streamingCfg.streamingProtocol = B_PlaybackIpProtocol_eHttp;
1560        return 0;
1561    }
1562    return -1;
1563}
1564
1565char * 
1566acceptNewHttpRequest(
1567        int listeningFd, 
1568        char *requestUrl, 
1569        int requestUrlLen, 
1570        int *newFd
1571        )
1572{
1573    struct sockaddr_in remoteAddr;
1574    int addrLen = sizeof(remoteAddr);
1575    int nbytes;
1576    int sockFd;
1577
1578#if 0
1579    /* TODO: enable cpu affinity later */
1580#ifdef __mips__
1581    unsigned long cpu_affinity_mask = 1;        /* CPU0 = 1, CPU1 = 2; CPU0 || CPU1 = 3 */
1582    /* optionally set CPU affinity */
1583    setThreadAffinity(cpu_affinity_mask);
1584    /* uncomment this line to verify the cpu affinity */
1585    /* while (1); */
1586#endif
1587#endif
1588
1589    /* wait for HTTP request & send HTTP reply */
1590    while (!gExitThread) {
1591        waitForNetworkEvent(listeningFd);
1592
1593        /* accept connection */
1594        if ((sockFd = accept(listeningFd, (struct sockaddr *)&remoteAddr, (socklen_t *)&addrLen)) < 0) {
1595            if (errno == EAGAIN || errno == EINTR)
1596                continue;
1597            perror("ERROR: accept(): exiting...");
1598            break;
1599        }
1600        waitForNetworkEvent(sockFd);
1601
1602        /* Read HTTP request */
1603        if ((nbytes = read(sockFd, requestUrl, requestUrlLen)) <= 0) {
1604            perror("read failed to read the HTTP Get request");
1605            break;
1606        }
1607        requestUrl[nbytes] = 0;
1608        BDBG_MSG(("Read HTTP Req (%d bytes)", nbytes));
1609
1610        *newFd = sockFd;
1611        /* we dont do any parsing part here */
1612                return requestUrl;
1613        }
1614        BDBG_MSG(("Failed handling HttpRequest..."));
1615        return NULL;
1616}
1617
1618void 
1619closeHttpSession(int sd)
1620{
1621    BDBG_MSG(("%s: Closing socket %d", __FUNCTION__, sd));
1622    close(sd);
1623}
1624
Note: See TracBrowser for help on using the repository browser.