apps/streamer/str.c

Go to the documentation of this file.
00001 /*
00002  * The main function of the streamer for Elphel 313 cameras
00003  * (C) Elphel, Inc
00004  * 2004 Alexander Melichenko <alexlp@freemail.ru>
00005  * 2007 Mykhailo Malyshko aka Spectr
00006  *
00007  *  This program is free software: you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation, either version 3 of the License, or
00010  *  (at your option) any later version.
00011  *
00012  *  This program is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *  GNU General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU General Public License
00018  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <stdint.h>
00025 #include <string.h>
00026 #include <getopt.h>
00027 #include <time.h>
00028 #include <sys/time.h>
00029 #include <sys/types.h>
00030 #include <sys/ioctl.h>
00031 #include <sys/mman.h>
00032 #include <fcntl.h>
00033 #include <unistd.h>
00034 #include <limits.h>
00035 #include <math.h>
00036 #include <netinet/in.h>
00037 #include <pthread.h>
00038 #include <sched.h>
00039 #include <errno.h>
00040 
00041 #include <sys/socket.h>
00042 #include <netinet/in.h>
00043 #include <arpa/inet.h>
00044 #include <netpacket/packet.h>
00045 #include <net/ethernet.h>
00046 
00047 #include "str.h"
00048 #include "net_udp.h"
00049 #include "rtp.h"
00050 #include <asm/elphel/c313a.h>
00051 #include <asm/elphel/hist.h>
00052 #include "event.h"
00053 #include "rtsp.h"
00054 
00055 #define RTP_PAYLOAD_SIZE        1460    /* MTU - IP - UDP - RTP  ---> 1500 - 20 - 8 - 12 */
00056 #define JPEG_RTP_HDR_SIZE       8
00057 
00058 #define MMAP_METHOD             1
00059 #define READ_METHOD             2
00060 
00061 #define SDP_FILE                "/var/html/session.sdp"
00062 #define SESSION_DESCR           "Elphel camera 353"
00063 
00064 #define PROGR_PARAM             1
00065 #define DEFAULT_DEST_IP         "232.1.1.1"
00066 #define DEFAULT_DEST_PORT       20020
00067 #define DEFAULT_RTSP_PORT       554
00068 #define DEFAULT_TTL             2
00069 #define DEFAULT_REFRESH_INTERVAL 5
00070 
00071 #define RTSP_ON_TAG             10
00072 #define RTSP_OFF_TAG            11
00073 #define RTSP_LISTEN_PORT_TAG    12
00074 #define RTSP_USE_OPT_ADDR_TAG   13
00075 #define RTSP_USE_OPT_PORT_TAG   14
00076 #define RTSP_QT_COMPAT_TAG      15
00077 
00078 #define FRESH_FILE              "/var/html/fresh.jpeg"
00079 #define HDR_SIZE                623
00080 #define TMP_BUF_OFFS            0xfe000
00081 #define YUV420                  1
00082 #define MAX_JPEG_BUF            2000000
00083 #define HZ                      10000
00084 
00085 #define NO_IOCTLS_IN_CIRCBUF y
00086 int8_t version[] = "1.7";
00087 
00088 static int8_t *header =
00089     "RTP/JPEG streamer for Elphel 333/353 camera\n"
00090     "Version %s\n"
00091         " (C) Elphel, Inc\n"
00092         " 2004 Alexander Melichenko <alexlp@freemail.ru>\n"
00093         " 2007 Mykhailo Malyshko aka Spectr\n"
00094         "\n";
00095 
00096 
00097 const uint64_t TimestampTicks = 1000000;
00098 int32_t fd;
00100 int32_t ioctl_fd;
00101 
00102 
00103 inline uint64_t GetTimestamp(uint32_t tv_sec, uint32_t tv_usec) {
00104         return ((uint64_t) tv_sec * TimestampTicks) + tv_usec;
00105 }
00106 
00107 inline uint32_t ts2rtp(struct param * p, uint64_t t) {
00108         if(p->start_timestamp) {
00109                 return (uint32_t) (((t - p->start_timestamp) * p->vbitrt) / TimestampTicks);
00110         }
00111         p->start_timestamp = t;
00112         return 0;
00113 }
00114 
00115 /* write_sdp()
00116  * Form a SDP content and save it to an array and/or a file
00117  *      sdp  - array
00118  *      save - if 1 then create sdp file
00119  */
00120 int8_t write_sdp(struct param * p, int save, int8_t *sdp) {
00121     FILE *f = NULL;
00122     struct timeval tv;
00123     uint64_t session_id, version;
00124     int8_t var[256];
00125     int32_t count;
00126     int32_t port;
00127     int8_t  *dst, dst_d[]="0.0.0.0";
00128     double fps = 0;
00129         int w, h;
00130     
00131         /* get and skip first frame... */
00132     fps = 0.01 * ioctl(ioctl_fd, _CCCMD(CCAM_RPARS, P_FP100S), 0);
00133         w = ioctl(ioctl_fd, _CCCMD(CCAM_RPARS, P_ACTUAL_WIDTH), 0);
00134         h = ioctl(ioctl_fd, _CCCMD(CCAM_RPARS, P_ACTUAL_HEIGHT), 0);
00135     
00136     if(save){
00137         f = fopen(SDP_FILE, "w");
00138         if (!f) {
00139             fprintf(stderr, "SDP file creating error!");
00140             return -1;
00141         }
00142     }
00143     
00144     count = 0;
00145     memset(var, 0, 256);
00146     sprintf(var, "v=0\n");
00147     strcpy(sdp+count, var);
00148     count += strlen(var);
00149     
00150     gettimeofday(&tv, NULL);
00151     session_id = (uint64_t) tv.tv_sec * 1000000 + tv.tv_usec;
00152     gettimeofday(&tv, NULL);
00153     version = (uint64_t) tv.tv_sec * 1000000 + tv.tv_usec;
00154 
00155     memset(var, 0, 256);
00156     sprintf(var, "o=- %lld %lld IN IP4 %s\n", session_id, version, p->src);
00157     strcpy(sdp+count, var);
00158     count += strlen(var);
00159     
00160     if(p->rtsp && !p->rtsp_use_cmd_port && str_count < 1){
00161         port = 0;
00162     } else {
00163         port = p->dport;
00164     }
00165     
00166     if(p->rtsp && !p->rtsp_use_cmd_addr && str_count < 1){
00167         dst = dst_d;
00168     } else {
00169                 dst = p->dst;
00170     }
00171     
00172     memset(var, 0, 256);
00173     sprintf(var, "s=%s\n"
00174                  "m=video %d RTP/AVP %d\n"
00175                  "c=IN IP4 %s", SESSION_DESCR, port, 
00176                                 JPEG_PAYLOAD_NUM, dst);
00177     strcpy(sdp+count, var);
00178     count += strlen(var);
00179 
00180     if (ismulticast(p) && (p->rtsp && p->rtsp_use_cmd_addr)){
00181         memset(var, 0, 256);
00182         sprintf(var, "/%d", p->ttl);
00183         strcpy(sdp+count, var);
00184         count += strlen(var);
00185     }
00186 
00187     memset(var, 0, 256);
00188     sprintf(var, "\n");
00189     strcpy(sdp+count, var);
00190     count += strlen(var);
00191 
00192     if(p->rtsp){
00193         memset(var, 0, 256);
00194         sprintf(var, "a=control:rtsp://%s:%d\na=control:track1\n", 
00195             p->src, p->rtsp_port);
00196         strcpy(sdp+count, var);
00197         count += strlen(var);
00198     }
00199     
00200     if((p->fps_soft > 0) && (p->fps_soft <= p->fps)){
00201         fps = (double) p->fps_soft;
00202     }
00203 
00204     memset(var, 0, 256);
00205     sprintf(var, "a=x-framerate:%.2f\n", fps);
00206     strcpy(sdp+count, var);
00207     count += strlen(var);
00208     
00209     memset(var, 0, 256);
00210     sprintf(var, "a=framerate:%.2f\n", fps);
00211     strcpy(sdp+count, var);
00212     count += strlen(var);
00213 
00214         /* add width... */
00215 //      if(w > 2040) {
00216                 memset(var, 0, 256);
00217                 sprintf(var, "a=x-width:%d\n", w);
00218                 strcpy(sdp+count, var);
00219                 count += strlen(var);
00220                 memset(var, 0, 256);
00221                 sprintf(var, "a=width:%d\n", w);
00222                 strcpy(sdp+count, var);
00223                 count += strlen(var);
00224 //      }
00225         /* add height... */
00226 //      if(h > 2040) {
00227                 memset(var, 0, 256);
00228                 sprintf(var, "a=x-height:%d\n", h);
00229                 strcpy(sdp+count, var);
00230                 count += strlen(var);
00231                 memset(var, 0, 256);
00232                 sprintf(var, "a=height:%d\n", h);
00233                 strcpy(sdp+count, var);
00234                 count += strlen(var);
00235 
00236                 memset(var, 0, 256);
00237                 sprintf(var, "a=x-dimensions:%d,%d\n", w, h);
00238                 strcpy(sdp+count, var);
00239                 count += strlen(var);
00240 //      }
00241 
00242     sdp[count] = 0;
00243     
00244     if(save){
00245         fprintf(f, "%s", sdp);
00246         fclose(f);
00247         fflush(NULL);
00248     }
00249 
00250     return 0;
00251 }
00252 
00253 void session_finish(struct param *p) {
00254         rtp_done(p);
00255         fprintf(stderr, "\nSession %#x finished...\n", p->my_ssrc);
00256 }
00257 
00258 int32_t jpeg_session_start(struct param *p) {
00259     int32_t q = ioctl(ioctl_fd, _CCCMD(CCAM_RPARS, P_QUALITY), 0);
00260     int32_t ism = 0;
00261     int32_t res;
00262 
00263         p->payload_num = JPEG_PAYLOAD_NUM;
00264         p->start_timestamp = 0;
00265 
00266         res = rtp_init(p);
00267         if(res != 0) {
00268                 fprintf(stderr, "Couldn't start rtp session\n");
00269                 return -1;
00270         }
00271 
00272         ism = ismulticast(p);
00273         fprintf(stderr, header, version);
00274         if(p->rtsp) {
00275                 fprintf(stderr, "\tRTSP server is listening on the port %d.\n", p->rtsp_port);
00276                 if(!p->rtsp_use_cmd_addr) {
00277                         fprintf(stderr, "\tDestination address will got from rtsp request.\n");
00278                 }
00279                 if(!p->rtsp_use_cmd_port) {
00280                         fprintf(stderr, "\tDestination port will got from rtsp request.\n");
00281                 } 
00282                 fprintf(stderr, "\n\tStream is accessible by uri rtsp://%s:%d\n", p->src, p->rtsp_port);
00283         }
00284 
00285         fprintf(stderr, "\nSession %#x started...\n", p->my_ssrc);
00286 
00287         if(p->web > 0) {
00288                 fprintf(stderr, "\tWeb camera mode enabled. Refresh time - %d second\n", p->web);
00289         }
00290         if(p->meth == READ_METHOD) {
00291                 fprintf(stderr, "\tAccess method READ\n");
00292         } else {
00293                 fprintf(stderr, "\tAccess method MMAP\n");
00294         }
00295         if(p->zero) {
00296                 fprintf(stderr, "\tVideo streaming disabled\n");
00297                 fprintf(stderr,
00298                         "\twidth     = %d\n"
00299                         "\theight    = %d\n"
00300                         "\tquality   = %d\n"
00301                         "\tFPS       = %.2f\n", p->width, p->height, q, p->fps);
00302                 return 0;
00303         }
00304         fprintf(stderr, "\tmode       = ");
00305         if(ism)
00306                 fprintf(stderr, "multicast  ");
00307         else
00308                 fprintf(stderr, "unicast    ");
00309         if(p->raw)
00310                 fprintf(stderr, "by-passing UDP/IP stack\n");
00311         else
00312                 fprintf(stderr, "using UDP/IP stack\n");
00313         fprintf(stderr, "\tdest_addr  = %s\n", p->dst);
00314         if(ism)
00315                 fprintf(stderr, "\tttl        = %d\n", p->ttl);
00316                 fprintf(stderr,
00317                         "\tdest_port  = %d\n"
00318                         "\twidth      = %d\n"
00319                         "\theight     = %d\n"
00320                         "\tquality    = %d\n"
00321                         "\tSystem FPS = %.2f\n"
00322                         "\tSoft FPS   = %d\n",
00323                         p->dport, p->width, p->height, q, p->fps, p->fps_soft);
00324 
00325 
00326         if(p->raw) {
00327                 if(p->fd_raw == 0)
00328                         p->fd_raw = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
00329 
00330                 struct sockaddr_in s_in;
00331 
00332                 memset(&p->s_ll, 0, sizeof(p->s_ll));
00333         
00334                 p->s_ll.sll_family   = AF_PACKET;
00335                 p->s_ll.sll_protocol = htons(ETH_P_IP);
00336                 p->s_ll.sll_ifindex  = p->eth_index;
00337                 p->s_ll.sll_halen    = ETH_ALEN;   // MAC
00338 
00339                 if(ismulticast(p)){
00340                         // Generate multicast ethernet address
00341                         memcpy(p->s_ll.sll_addr, "\x01\x00\x5e", 3);
00342                         unsigned char a[3];
00343                         unsigned int _a;
00344                         _a = inet_addr(p->dst);
00345                         a[0] = (_a >> 8) & 0x7F;
00346                         a[1] = (_a >> 16) & 0xFF;
00347                         a[2] = (_a >> 24) & 0xFF;
00348                         memcpy(p->s_ll.sll_addr + 3, a, 3);
00349                         // set multicast option for socket
00350                         struct ip_mreqn multiaddr;
00351                         multiaddr.imr_multiaddr.s_addr = inet_addr(p->dst);
00352                         multiaddr.imr_address.s_addr = htonl(INADDR_ANY);
00353                         multiaddr.imr_ifindex = 0;
00354                         setsockopt(p->fd_raw, IPPROTO_IP, IP_ADD_MEMBERSHIP, &multiaddr, sizeof(struct sockaddr_in));
00355                 } else {
00356                         memcpy(p->s_ll.sll_addr, p->dst_mac, 6);
00357                 }
00358 
00359                 p->msg.msg_control = 0;
00360                 p->msg.msg_flags = 0;
00361                 p->msg.msg_name = (void *)&p->s_ll;
00362                 p->msg.msg_namelen = sizeof(p->s_ll);
00363 //unsigned char *ptr = (unsigned char *)(&p->s_ll.sll_addr);
00364 //fprintf(stderr, "MAC: %02X%02X%02X%02X%02X%02X \n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
00365 
00366         } else {
00367                 if(p->fd_udp == 0)
00368                         p->fd_udp = socket(PF_INET, SOCK_DGRAM, 0);
00369                 struct sockaddr_in addr;
00370                 addr.sin_addr.s_addr = inet_addr(p->dst);
00371                 addr.sin_port = htons(p->dport);;
00372                 addr.sin_family = AF_INET;
00373 
00374                 connect(p->fd_udp, (struct sockaddr *)&addr, sizeof(struct sockaddr));
00375         }
00376 
00377     return 0;
00378 }
00379 
00380 int32_t send_jpeg(struct param *p, uint8_t * _data, uint32_t sz,
00381               uint32_t max_size, uint8_t type, uint8_t q, uint32_t t_sec, uint32_t t_usec)
00382 {
00383     uint32_t size = sz + 2;
00384     uint32_t offset = 0;
00385 //    uint32_t rtpTimestamp = ts2rtp(p, GetTimestamp());
00386     uint8_t *dt = _data;
00387     int32_t ret;
00388         uint32_t rtpTimestamp = ts2rtp(p, GetTimestamp(t_sec, t_usec));
00389 /*
00390         static uint32_t prev_sec = 0;
00391         static uint32_t prev_usec = 0;
00392         unsigned long d = t_usec;
00393         if(prev_sec != t_sec)
00394                 d += 1000000;
00395         fprintf(stderr, "; delta == %d\n", d - prev_usec);
00396         prev_sec = t_sec;
00397         prev_usec = t_usec;
00398 */
00399     if(max_size > RTP_PAYLOAD_SIZE) {
00400                 fprintf(stderr, "Max rtp size couldn't be more then %d\n", RTP_PAYLOAD_SIZE);
00401                 return -1;
00402     }
00403 
00404         uint8_t h[128];
00405         int h_offset = 96;
00406 
00407         dt += 8 + 12;
00408         if(p->raw)
00409                 dt += 28;
00410 
00411         h[h_offset + 0] = 0;
00412         h[h_offset + 1] = 0;
00413         h[h_offset + 2] = 0;
00414         h[h_offset + 3] = 0;
00415         h[h_offset + 4] = type;
00416         h[h_offset + 5] = q;
00417         if(p->width <= 2040)
00418                 h[h_offset + 6] = p->width / 8;
00419         else
00420                 h[h_offset + 6] = 0;
00421         if(p->height <= 2040)
00422                 h[h_offset + 7] = p->height / 8;
00423         else
00424                 h[h_offset + 7] = 0;
00425         max_size -= JPEG_RTP_HDR_SIZE;
00426         max_size -= 32;
00427 
00428         uint32_t payloadLength = max_size;
00429         int32_t lastPacket = 0;
00430     while(size) {
00431                 if(size <= max_size) {
00432                     payloadLength = size;
00433                     lastPacket = 1;
00434                 }
00435 /*
00436 
00437                 if(size <= max_size) {
00438                     payloadLength = size;
00439                     lastPacket = 1;
00440                 } else {
00441                     payloadLength = max_size;
00442                 lastPacket = 0;
00443                 }
00444 */
00445                 ret = rtp_send_data(p, rtpTimestamp, p->payload_num, lastPacket, dt, payloadLength, (unsigned char *)h, h_offset, 8);
00446 
00447                 dt += payloadLength;
00448 
00449                 offset += payloadLength;
00450                 size -= payloadLength;
00451                 h[h_offset + 0] = 0;
00452                 h[h_offset + 1] = offset >> 16;
00453                 h[h_offset + 2] = offset >> 8;
00454                 h[h_offset + 3] = offset;
00455                 h[h_offset + 4] = type;
00456                 h[h_offset + 5] = q;
00457                 if(p->width <= 2040)
00458                         h[h_offset + 6] = p->width / 8;
00459                 else
00460                         h[h_offset + 6] = 0;
00461                 if(p->height <= 2040)
00462                         h[h_offset + 7] = p->height / 8;
00463                 else
00464                         h[h_offset + 7] = 0;
00465 //              h[h_offset + 6] = p->width / 8;
00466 //              h[h_offset + 7] = p->height / 8;
00467     }
00468 
00469     return 0;
00470 }
00471 
00472 
00473 void usage(struct param *p, int32_t ret)
00474 {
00475     static int8_t *usage =
00476         "Usage: %s [options]\n"
00477         "Options:\n"
00478         "\t-a --addr xx.xx.xx.xx - multicast destination address\n"
00479         "\t               by default == %s\n"
00480         "\t               (must be from 224.0.0.0 to 239.255.255.255)\n"
00481         "\t-p --port xx - port, destination for multicast, and source for unicast/multicast\n"
00482         "\t               by default == %d\n"
00483         "\t-t --ttl  xx - TTL (Time-To-Live for multicast, default %d)\n"
00484         "\t-s --silent  - \"silent\" mode for multicast - wait client over RTSP for streaming\n"
00485         "\t               (w/o this option - send multicast stream all time - by default)\n"
00486         "\t-m --mcast   - send stream over multicast\n"
00487         "\t-u --ucast   - send stream over unicast (used by default)\n"
00488         "\t               in unicast mode supported only one active RTSP client\n"
00489         "\t-f --fps  xx.xx - use fixed FPS for stream\n"
00490         "\n";
00491 /*
00492         "Usage: %s [options]\n"
00493         "Options:\n"
00494         "\t-v --verbose\tPrint statistical information \n"
00495         "\t-q --quiet\tNo print additional information (default)\n"
00496         "\t-a --addr IP\tDestination UNICAST or MULTICAST IP address\n"
00497         "\t\t\t(default MULTICAST %s) (if --rtsp-off \n"
00498         "\t\t\tis not present and --rtsp-use-opt-addr is not present,\n"
00499         "\t\t\tthen destination address will got from rtsp request)\n"
00500         "\t-p --port PORT\tDestination port (default %d) (if --rtsp-off\n"
00501         "\t\t\tis not present and --rtsp-use-opt-port is not present,\n"
00502         "\t\t\tthen destination port will got from rtsp request)\n"
00503         "\t-t --ttl TTL\tTime-To-Live (default %d)\n"
00504         "\t-n --nostack\tFast networking (no use tcp/ip stack)(default)\n"
00505         "\t-s --stack\tUse UDP/IP stack\n"
00506         "\t-r --read\tUse access method READ\n"
00507         "\t-m --mmap\tUse access method MMAP (default)\n"
00508         "\t-f --fps\tIf system FPS is too much you can decrease it by\n"
00509         "\t\t\tseting this value. In this case some portion of video\n"
00510         "\t\t\tframes will passed. For example, if system FPS=600 but\n"
00511         "\t\t\tyou need only 20 you can set --fps=20\n"
00512         "\t-w --web SEC\tWeb camera mode. Every SEC second will be generate\n"
00513         "\t\t\tfresh image file which accessible by url\n"
00514         "\t\t\thttp://camera_address/var/fresh.jpg\n"
00515         "\t\t\tThis is useful for organize web camera but it can \n"
00516         "\t\t\tslow down video streaming (if streaming enabled)\n"
00517         "\t\t\tCurrently it work only with --read options\n"
00518         "\t-z --zero\tVideo streaming disabled. Only webcam mode enabled.\n"
00519         "\t\t\tIf no -w option present then -w=%d\n"
00520         "\t\t\tIn this mode a data access method will be READ\n"
00521         "\t-h --help\tShow this help\n"
00522         "\n"
00523         "\t--rtsp-on\t\tSimple RTSP server enabled (default)\n"
00524         "\t\t\t\tSupport OPTIONS, DESCRIBE, SETUP, PLAY, PAUSE,\n"
00525         "\t\t\t\tTEARDOWN rtsp requests.\n"
00526         "\t\t\t\tIf -z is present rtsp server will be disabled\n"
00527         "\t\t\t\t(because it has no video streaming)\n"
00528         "\t--rtsp-off\t\tDisable RTSP server\n"
00529         "\t--rtsp-port PORT\tRTSP server listen for incomming connections\n"
00530         "\t\t\t\ton this port. (default %d)\n"
00531         "\t\t\t\tYou can connect to the server by URI:\n"
00532         "\t\t\t\trtsp://camera_address:PORT\n"
00533         "\t--rtsp-use-opt-addr\tIf this option enabled the destination IP\n"
00534         "\t\t\t\taddress will got from the command option -a\n"
00535         "\t\t\t\t(or --addr). Otherwise it will got from the\n"
00536         "\t\t\t\trtsp request.\n"
00537         "\t--rtsp-use-opt-port\tIf this option enabled the destination port\n"
00538         "\t\t\t\twill got from the command option -a (or --addr).\n"
00539         "\t\t\t\tOtherwise it will got from the rtsp request.\n"
00540         "\t\t\t\tTwo last options can be useful if you want send\n"
00541         "\t\t\t\ta stream to multicast.\n"
00542         "\t--rtsp-qt-compat\tQuickTime compatible mode enable.\n"
00543         "\t\t\t\tQuickTime has some features in rtsp realisation.\n"
00544         "\t\t\t\tIf you want use the QuickTime player you MUST\n"
00545         "\t\t\t\tenter in the command line this option. In this\n"
00546         "\t\t\t\tcase you MUST use also --rtsp-use-opt-addr\n"
00547         "\t\t\t\toption. Saddanly it has no way use\n"
00548         "\t\t\t\tIP-From-RTSP-Request method with QT (I don't\n"
00549         "\t\t\t\tknow how do it)\n";
00550 */      
00551     fprintf(stderr, header, version);
00552     fprintf(stderr, usage, p->program_name, DEFAULT_DEST_IP,
00553             DEFAULT_DEST_PORT, DEFAULT_TTL);
00554 //    fprintf(stderr, usage, p->program_name, DEFAULT_DEST_IP,
00555 //          DEFAULT_DEST_PORT, DEFAULT_TTL, DEFAULT_REFRESH_INTERVAL, DEFAULT_RTSP_PORT);
00556     exit(ret);
00557 }
00558 
00559 void opt_parse(int32_t argc, char *const argv[], struct param *p)
00560 {
00561     uint32_t var;
00562     int32_t next;
00563     const struct option long_opt[] = {
00564                 {"addr",    1, NULL, 'a'},
00565                 {"port",    1, NULL, 'p'},
00566                 {"ttl",     1, NULL, 't'},
00567                 {"silent",  0, NULL, 's'},
00568                 {"mcast",   0, NULL, 'm'},
00569                 {"ucast",   0, NULL, 'u'},
00570                 {"fps",     1, NULL, 'f'},
00571                 {NULL,      0, NULL,  0 }
00572     };
00573     const int8_t *const short_opt = "a:p:t:smuf:";
00574 /*
00575     const struct option long_opt[] = {
00576         {"addr",    1, NULL, 'a'},
00577         {"port",    1, NULL, 'p'},
00578         {"ttl",     1, NULL, 't'},
00579         {"raw",     0, NULL, 'r'},
00580         {"stack",   0, NULL, 's'},
00581         {"nostack", 0, NULL, 'n'},
00582         {"mmap",    0, NULL, 'm'},
00583         {"fps",     1, NULL, 'f'},
00584         {"help",    0, NULL, 'h'},
00585         {"verbose", 0, NULL, 'v'},
00586         {"quiet",   0, NULL, 'q'},
00587         {"web",     1, NULL, 'w'},
00588         {"zero",    0, NULL, 'z'},
00589         {"rtsp-on",           0, NULL, RTSP_ON_TAG          },
00590         {"rtsp-off",          0, NULL, RTSP_OFF_TAG         },
00591         {"rtsp-port",         1, NULL, RTSP_LISTEN_PORT_TAG },
00592         {"rtsp-use-opt-addr", 0, NULL, RTSP_USE_OPT_ADDR_TAG},
00593         {"rtsp-use-opt-port", 0, NULL, RTSP_USE_OPT_PORT_TAG},
00594         {"rtsp-qt-compat",    0, NULL, RTSP_QT_COMPAT_TAG   },
00595         {NULL,                0, NULL, 0                    }
00596     };
00597     const int8_t *const short_opt = "a:f:hmnp:qrst:vw:z";
00598 */
00599         int mcast = 0;
00600         int silent = 0;
00601         float fps = 0;
00602 
00603         p->program_name = strdup(argv[0]);
00604 
00605         if(argc < PROGR_PARAM)
00606                 usage(p, 0);
00607 
00608         do {
00609                 next = getopt_long(argc, argv, short_opt, long_opt, NULL);
00610                 switch(next) {
00611                 case '?':
00612                 case 'h':
00613                         usage(p, 0);
00614                         break;
00615                 case 'a':
00616                         p->dst = optarg;
00617                         mcast = 1;
00618                         break;
00619                 case 'p':
00620                         var = strtoul(optarg, (char **)NULL, 10);
00621                         if((var > 65535) || (var <= 0)) {
00622                                 fprintf(stderr, "ERROR: destination RTP port is not correct\n\n");
00623                                 goto error;
00624                         }
00625                         p->dport = (uint16_t)var;
00626                         if(p->dport % 2) {
00627                                 fprintf(stderr, "\nERROR: destination RTP port cann't be odd\n\n");
00628                                 goto error;
00629                         }
00630                         break;
00631                 case 't':
00632                         var = strtoul(optarg, (char **) NULL, 10);
00633                         if((var > 255) || (var <= 0)) {
00634                                 fprintf(stderr, "ERROR: TTL is not correct\n\n");
00635                                 goto error;
00636                         }
00637                         p->ttl = (uint16_t) var;
00638                         break;
00639                 case 'f':
00640                         fps = atof(optarg);
00641                         if(fps < 0)
00642                                 fps = 0;
00643                         if(fps > 250)
00644                                 fps = 250;
00645                         p->hw_fps = 100 * fps;
00646                         break;
00647                 case 's':
00648                         silent = 1;
00649                         break;
00650                 case 'u':
00651                         mcast = 0;
00652                         break;
00653                 case 'm':
00654                         mcast = 1;
00655                         break;
00656                 case -1:
00657                         break;
00658                 default:
00659                         usage(p, 1);
00660                         break;
00661                 }
00662         } while(next != -1);
00663 
00664         if(mcast) {
00665                 p->rtsp_use_cmd_addr = 1;
00666                 p->rtsp_use_cmd_port = 1;
00667                 p->rtsp_qt_compat = 1;
00668         }
00669 //      if(silent) {
00670 //      }
00671         next = optind;
00672 
00673         return;
00674 error:
00675         exit(-1);
00676 /*
00677         do {
00678                 next = getopt_long(argc, argv, short_opt, long_opt, NULL);
00679                 switch(next) {
00680                 case '?':
00681                 case 'h':
00682                         usage(p, 0);
00683                         break;
00684                 case 'p':
00685                         var = strtoul(optarg, (char **)NULL, 10);
00686                         if((var > 65535) || (var <= 0)) {
00687                                 fprintf(stderr, "ERROR: destination video port is not correct\n\n");
00688                                 usage(p, 0);
00689                         }
00690                         p->dport = (uint16_t)var;
00691                         if(p->dport % 2) {
00692                                 fprintf(stderr, "\nERROR: destination video port cann't be odd\n\n");
00693                                 usage(p, 0);
00694                         }
00695                         mcast = 1;
00696                         break;
00697                 case 'a':
00698                         p->dst = optarg;
00699                         mcast = 1;
00700                         break;
00701                 case 'v':
00702                         p->verbose = 1;
00703                         break;
00704                 case 'q':
00705                         p->verbose = 0;
00706                         break;
00707                 case 's':
00708                         p->raw = 0;
00709                         break;
00710                 case 'z':
00711                         p->zero = 1;
00712                         break;
00713                 case 'n':
00714                         p->raw = 1;
00715                         break;
00716                 case 'w':
00717                         var = strtoul(optarg, (char **) NULL, 10);
00718                         if(var < 0) {
00719                                 fprintf(stderr, "ERROR: WEB time is not correct\n\n");
00720                                 usage(p, 0);
00721                         }
00722                         p->web = (uint32_t)var;
00723                         break;
00724                 case 'r':
00725                         p->meth = READ_METHOD;
00726                         break;
00727                 case 'm':
00728                         p->meth = MMAP_METHOD;
00729                         break;
00730                 case 't':
00731                         var = strtoul(optarg, (char **) NULL, 10);
00732                         if((var > 255) || (var <= 0)) {
00733                                 fprintf(stderr, "ERROR: TTL is not correct\n\n");
00734                                 usage(p, 0);
00735                         }
00736                         p->ttl = (uint16_t) var;
00737                         break;
00738                 case 'f':
00739                         var = strtoul(optarg, NULL, 10);
00740                         if((var > 1000) || (var < 0)) {
00741                                 fprintf(stderr, "ERROR: Software FPS is not correct\n\n");
00742                                 usage(p, 0);
00743                         }
00744                         p->fps_soft = var;
00745                         break;
00746                 case RTSP_ON_TAG:
00747                         p->rtsp = 1;
00748                         break;
00749                 case RTSP_OFF_TAG:
00750                         p->rtsp = 0;
00751                         break;
00752                 case RTSP_LISTEN_PORT_TAG:
00753                         var = strtoul(optarg, (char **) NULL, 10);
00754                         if((var > 65535) || (var <= 0)) {
00755                                 fprintf(stderr, "ERROR: RTSP server port is not correct\n\n");
00756                                 usage(p, 0);
00757                         }
00758                         p->rtsp_port = (uint16_t) var;
00759                         break;      
00760                 case RTSP_USE_OPT_ADDR_TAG:
00761                         p->rtsp_use_cmd_addr = 1;
00762                         break;
00763                 case RTSP_USE_OPT_PORT_TAG:
00764                         p->rtsp_use_cmd_port = 1;
00765                         break;
00766                 case RTSP_QT_COMPAT_TAG:
00767                         p->rtsp_qt_compat = 1;
00768                         break;
00769                 case -1:
00770                         break;
00771                 default:
00772                         usage(p, 1);
00773                         break;
00774                 }
00775         } while(next != -1);
00776 */
00777 
00778         if(mcast) {
00779                 p->rtsp_use_cmd_addr = 1;
00780                 p->rtsp_use_cmd_port = 1;
00781                 p->rtsp_qt_compat = 1;
00782         }
00783         next = optind;
00784 }
00785 
00786 int32_t buf_size;
00787 int32_t str_setup;
00788 int32_t str_play;
00789 int32_t str_teardown;
00790 int32_t str_stop;
00791 int32_t str_count;
00792 int8_t  *wbuf;
00793 unsigned long *start, *ccam_dma_buf;
00794 
00795 int32_t grab_and_send(struct param *p)
00796 {
00797     int32_t status = 0, res, res_buf;
00798     int32_t offs;
00799     int32_t alen, jpeg_wp, old_jpeg_wp = 0, frame;
00800     int32_t ret, count, fr_fd = -1;
00801     int32_t all_buf_sz;
00802     int32_t stack_offs = 0, cnt = 0, buf_len = 0;
00803     uint8_t q = 0;
00804     uint8_t jpeg_type = YUV420;
00805     uint32_t frame_avg = 0;
00806     uint32_t fps_dlt = 0, dlt;
00807     double _fps, bw, tm;
00808     struct timeval st, ft, fps_st, fps_fn;
00809     time_t cur_time;
00810     static time_t old_time = 0;
00811     int8_t *buf, sdp[8192];
00812     static int32_t run_flag = 0;
00813 
00814         struct timeval tv;
00815 
00816         if(run_flag && p->rtsp && p->rtsp_qt_compat) {
00817                 goto run_flag1;
00818         }
00819         run_flag = 1;
00820 
00821         if(p->fps_soft > 0) {
00822                 fps_dlt = 1000000 / p->fps_soft;
00823         }
00824 
00825         status = ioctl(ioctl_fd, _IO(CMOSCAM_IOCTYPE, IO_CCAM_MONITOR_SEQ), 0);
00826         if((status == CAMSEQ_RUN || status == CAMSEQ_SINGLE) && p->meth == READ_METHOD) {
00827                 ioctl(ioctl_fd, _IO(CMOSCAM_IOCTYPE, IO_CCAM_JPEG), JPEG_CMD_STOP);
00828         }
00829 
00830         if(status != CAMSEQ_RUN && p->meth == MMAP_METHOD) {
00831                 ioctl(ioctl_fd, _IO(CMOSCAM_IOCTYPE, IO_CCAM_JPEG), JPEG_CMD_START);
00832                 fprintf(stderr, "+++++++++++++++ Compressor start\n");
00833         }
00834 
00835         if(p->meth == READ_METHOD) {
00836                 ioctl(ioctl_fd, _IO(CMOSCAM_IOCTYPE, IO_CCAM_JPEG), JPEG_CMD_CATCHUP);
00837                 ioctl(ioctl_fd, _IO(CMOSCAM_IOCTYPE, IO_CCAM_JPEG), JPEG_CMD_FORGET);
00838                 ioctl(ioctl_fd, _IO(CMOSCAM_IOCTYPE, IO_CCAM_JPEG), JPEG_CMD_ACQUIRE);
00839         }
00840 
00841 run_flag1:
00842 
00843         p->width = ioctl(ioctl_fd, _CCCMD(CCAM_RPARS, P_ACTUAL_WIDTH), 0);
00844         p->height = ioctl(ioctl_fd, _CCCMD(CCAM_RPARS, P_ACTUAL_HEIGHT), 0);
00845         p->fps = 0.01 * ioctl(ioctl_fd, _CCCMD(CCAM_RPARS, P_FP100S), 0);
00846         p->vbitrt = 90000;
00847 
00848         res = jpeg_session_start(p);
00849         if(res != 0) {
00850                 fprintf(stderr, "Start session error!\n");
00851                 return -1;
00852         }
00853     
00854         memset(sdp, 0, 8192);
00855         res = write_sdp(p, 1, sdp);
00856 
00857         if(p->raw)
00858                 stack_offs += IP_UDP_SIZE;
00859 
00860         while(!str_play && !str_stop && !str_teardown)
00861                 sched_yield();
00862 //              usleep(10);
00863     
00864         gettimeofday(&st, NULL);
00865         gettimeofday(&fps_st, NULL);
00866         while (!str_stop && !str_teardown) {
00867                 while(!str_play && !str_stop && !str_teardown)
00868                         sched_yield();
00869 //                      usleep(10);
00870                 if(str_stop || str_teardown)
00871                         break;
00872                 if(p->fps_soft > 0){
00873                         while(1) {
00874                                 gettimeofday(&fps_fn, NULL);
00875                                 dlt = (fps_fn.tv_sec*1000000+fps_fn.tv_usec) - (fps_st.tv_sec*1000000+fps_st.tv_usec);
00876                                 if(dlt < fps_dlt){
00877                                         if(fps_dlt-dlt > HZ*2) {
00878                                                 usleep(HZ);
00879                                         }
00880                                         continue;
00881                                 }
00882                                 gettimeofday(&fps_st, NULL);
00883                                 break;
00884                         }
00885                 }
00886         
00887                 offs = sizeof(rtp_packet) + JPEG_RTP_HDR_SIZE + stack_offs;
00888                 if(p->meth == READ_METHOD) {
00889                 while((lseek(fd, 0, SEEK_END) == 0));
00890                     ioctl(ioctl_fd, _IO(CMOSCAM_IOCTYPE, IO_CCAM_JPEG), JPEG_CMD_ACQUIRE);
00891                     lseek(fd, 0, SEEK_SET);
00892                 buf_len = 0;
00893                     res_buf = 0;
00894                     while((res_buf = read(fd, wbuf + offs, MAX_JPEG_BUF - 100 - res_buf)) > 0) {
00895                                 offs += res_buf;
00896                                 buf_len += res_buf;
00897                     }
00898                 buf = wbuf + HDR_SIZE;
00899                 } else {
00900                     jpeg_wp = ioctl(ioctl_fd, _CCCMD(CCAM_RPARS, G_CIRCBUFWP), 0)>>2;
00901                 if(jpeg_wp == old_jpeg_wp)
00902                                 continue;
00903                     old_jpeg_wp = jpeg_wp;
00904                 /* MUST be multiple by 32 */
00905                     if(jpeg_wp & 0x7)
00906                                 continue;
00907                 alen = jpeg_wp - 9;
00908                     if(alen < 0)
00909                                 alen += (buf_size >> 2);
00910                 /* MUST be 0xff in old length's byte */
00911                         if((ccam_dma_buf[alen] & 0xff000000) != 0xff000000) {
00912                                 fprintf(stderr, "skip frame with signature: 0x%08X\n", (unsigned int)ccam_dma_buf[alen]);
00913                                 continue;
00914                         }
00915                     buf_len = ccam_dma_buf[alen] & 0x00ffffff;
00916                         tv.tv_sec = ccam_dma_buf[alen - 2];
00917                         tv.tv_usec = ccam_dma_buf[alen - 1];
00918                     /* Size is not correct */
00919                     if(buf_len > buf_size)
00920                                 continue;
00921 
00922 //              all_buf_sz = ((((buf_len + 3) >> 2) + 9) >> 3) << 3;
00923                     all_buf_sz = ((((buf_len + 3) >> 2) + 11) >> 3) << 3;
00924                     frame = alen + 1 - all_buf_sz;
00925                 if(frame < 0) {
00926                                 frame += buf_size >> 2;
00927                                 {
00928                                 int8_t *ptr;
00929                                 int32_t end_part, start_part = 0;
00930                                     end_part = (frame << 2) + buf_len - buf_size;
00931                                     if(end_part >= 0)
00932                                                 start_part = buf_len - end_part;
00933                                 ptr = ((int8_t *) (start + (TMP_BUF_OFFS >> 2))) - start_part;
00934                                     memcpy(ptr, &ccam_dma_buf[frame], start_part);
00935                                     buf = (int8_t *) (start + (TMP_BUF_OFFS >> 2) - (offs >> 2)) - start_part;
00936                                 }
00937                     } else {
00938                                 buf = (int8_t *) (start + (TMP_BUF_OFFS >> 2) + frame - (offs >> 2));
00939                     }
00940                 }
00941 
00942                 if(p->web > 0) {
00943                     cur_time = time(NULL);
00944                 if(cur_time - old_time >= p->web) {
00945                                 old_time = cur_time;
00946                                 fr_fd = open(FRESH_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644);
00947                                 if(fr_fd < 0) {
00948                                     fprintf(stderr, "Fresh JPEG file is not created!\n");
00949                                     fprintf(stderr, "You can't use WEB CAMERA mode.\n");
00950                                     p->web = 0;
00951                                     goto noweb;
00952                                 }
00953 
00954                                 count = 0;
00955                                 while(count != buf_len) {
00956                                         offs = sizeof(rtp_packet) + JPEG_RTP_HDR_SIZE + stack_offs;
00957                                         ret  = write(fr_fd, wbuf + offs + count, buf_len - count);
00958                                         if(ret < 0) {
00959                                                 fprintf(stderr, "Fresh JPEG file is not created!\n");
00960                                                 fprintf(stderr, "You can't use WEB CAMERA mode.\n");
00961                                                 close(fr_fd);
00962                                                 p->web = 0;
00963                                                 goto noweb;
00964                                         }
00965                                         count += ret;
00966                                 }
00967                         }
00968                         close(fr_fd);
00969                 }
00970 noweb:
00971                 frame_avg += buf_len;
00972         
00973                 cnt++;
00974                 if(!p->zero) {
00975                         if(tv.tv_sec == 0 && tv.tv_usec == 0)
00976                                 gettimeofday(&tv, NULL);
00977                         q = ioctl(ioctl_fd, _CCCMD(CCAM_RPARS, P_QUALITY), 0);
00978                         send_jpeg(p, buf, buf_len, RTP_PAYLOAD_SIZE, jpeg_type, q, tv.tv_sec, tv.tv_usec);
00979                 }
00980 
00981                 if(cnt == 100 && p->verbose && !p->zero) {
00982                         gettimeofday(&ft, NULL);
00983                         tm = (((double)((ft.tv_sec * 1000000 + ft.tv_usec) - (st.tv_sec * 1000000 + st.tv_usec))) / 1000000);
00984                         _fps = 100 / tm;
00985                         bw = frame_avg * 8 / tm / 1000000;
00986                         frame_avg = frame_avg / 100;
00987                         gettimeofday(&st, NULL);
00988                         fprintf(stderr, "fps=%.2f  avg_size=%d   BW=%.1f Mb/s\n", _fps, frame_avg, bw);
00989                         fflush(NULL);
00990                         cnt = 0;
00991                         frame_avg = 0;
00992                 }
00993 
00994                 if(p->meth == READ_METHOD) {
00995                         ioctl(ioctl_fd, _IO(CMOSCAM_IOCTYPE, IO_CCAM_JPEG), JPEG_CMD_FORGET);
00996                 }
00997         }
00998 
00999         if(run_flag && p->rtsp && p->rtsp_qt_compat) {
01000                 goto run_flag2;
01001         }
01002 
01003         if(status == CAMSEQ_RUN || status == CAMSEQ_SINGLE) {
01004                 status = ioctl(ioctl_fd, _IO(CMOSCAM_IOCTYPE, IO_CCAM_MONITOR_SEQ), 0);
01005                 if(status != CAMSEQ_RUN && status != CAMSEQ_SINGLE) {
01006                         ioctl(ioctl_fd, _IO(CMOSCAM_IOCTYPE, IO_CCAM_JPEG), JPEG_CMD_START);
01007                 }
01008         } else {
01009                 ioctl(ioctl_fd, _IO(CMOSCAM_IOCTYPE, IO_CCAM_JPEG), JPEG_CMD_STOP);
01010         }
01011 
01012 run_flag2:
01013 
01014         session_finish(p);
01015         return 0;
01016 }
01017 
01018 
01019 void *rtsp_loop(void* var){
01020     struct param *p = (struct param *)var;
01021 
01022     rtsp_listen(p);
01023     event_loop(0);    
01024     str_stop = 1;
01025     sleep(2);
01026     pthread_exit(0);
01027     return 0;
01028 }
01029 
01030 int main(int argc, char **argv) {
01031         int32_t res;
01032         int8_t *ccam_file = "/dev/ccam_dma.raw";
01033         int8_t *circ_file = "/dev/circbuf";
01034 
01035         int8_t *res_file;
01036         struct param p;
01037         pthread_t pid;
01038 
01039         int _fd, c;
01040         for(c = 0; c < 20; c++)
01041                 if(_fd = open("/dev/stream", O_RDONLY) < 0)
01042                         usleep(50000);
01043                 else
01044                         break;
01045 //      int _fd = open("/dev/stream", O_RDONLY);
01046         if(_fd < 0) {
01047                 fprintf(stderr, "streamer already running, exit\n");
01048                 return -1;
01049         }
01050 
01051         p.dport                 = DEFAULT_DEST_PORT;
01052         p.ttl           = DEFAULT_TTL;
01053         p.meth          = MMAP_METHOD;
01054         p.dst           = DEFAULT_DEST_IP;
01055         p.raw           = 1;
01056         p.verbose       = 0;
01057         p.web           = 0;
01058         p.zero          = 0;
01059         p.rtsp          = 1;
01060         p.rtsp_port             = DEFAULT_RTSP_PORT;
01061         p.rtsp_use_cmd_port = 0;
01062         p.rtsp_use_cmd_addr = 0;
01063         p.fps_soft          = 0;
01064         p.rtsp_qt_compat        = 0;
01065         p.fd_udp = 0;
01066         p.fd_raw = 0;
01067         p.hw_fps = 0;
01068         memset(&p.msg, 0, sizeof(struct msghdr));
01069 
01070         opt_parse(argc, argv, &p);
01071 
01072         if(p.hw_fps != 0)
01073                 ioctl(_fd, _IO(IOC_STREAM_SET_FPS, 0x00), p.hw_fps);
01074         if(p.zero) {
01075                 p.meth = READ_METHOD;
01076                 if(p.web <= 0)
01077                         p.web = DEFAULT_REFRESH_INTERVAL;
01078                 p.rtsp = 0;
01079         }
01080         if(p.meth == MMAP_METHOD && p.web) {
01081                 fprintf(stderr, "\nWARNING!!! Webcam mode can be activated only with READ method (option -r)\n\n");
01082                 p.web = 0;
01083         }
01084         if(p.rtsp && p.rtsp_qt_compat && !p.rtsp_use_cmd_addr) {
01085                 fprintf(stderr, "\nERROR!!! You MUST use --rtsp-use-opt-addr with --rtsp-qt-compat\n\n");
01086                 usage(&p, 1);
01087         }
01088 
01089         if(get_src_addr(&p) != 0) {
01090                 return -1;
01091         }
01092 #ifdef NO_IOCTLS_IN_CIRCBUF
01094         if((ioctl_fd = open(ccam_file, O_RDWR)) < 0) {
01095                 fprintf(stderr, "Can't open device %s\n",ccam_file);
01096                 return -1;
01097         }
01098 
01099         if(p.meth == READ_METHOD)
01100                 fd=ioctl_fd ; 
01101         else { // separate file for ioctls
01102                 if((fd = open(circ_file, O_RDWR)) < 0) {
01103                         fprintf(stderr, "Can't open device %s\n",circ_file);
01104                         return -1;
01105                 }
01106         }
01107 #else
01108         if(p.meth == READ_METHOD)
01109                 res_file = ccam_file;
01110         else
01111                 res_file = circ_file;
01112         if((fd = open(res_file, O_RDWR)) < 0) {
01113                 fprintf(stderr, "Cann't open device!\n");
01114                 return -1;
01115         }
01116         ioctl_fd=fd; 
01117 #endif
01118         if(p.meth == READ_METHOD) {
01119                 wbuf = (int8_t *) malloc(MAX_JPEG_BUF);
01120         } else {
01121                 start = (unsigned long *) valloc(0x100000);
01122                 buf_size = lseek(fd, 0, 2);
01123                 ccam_dma_buf = (unsigned long *) mmap(start + (TMP_BUF_OFFS >> 2), buf_size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, 0);
01124                 if((int) ccam_dma_buf == -1) {
01125                         fprintf(stderr, "mmap error!\n");
01126                         return -1;
01127                 }
01128         }
01129     
01130         if(p.rtsp) {
01131                 fprintf(stderr, "\n\tRTSP server is listening on the port %d.\n", p.rtsp_port);
01132                 if(!p.rtsp_use_cmd_addr) {
01133                         fprintf(stderr, "\tDestination address will got from rtsp request.\n");
01134                 } 
01135                 if(!p.rtsp_use_cmd_port) {
01136                         fprintf(stderr, "\tDestination port will got from rtsp request.\n");
01137                 }
01138                 fprintf(stderr, "\n\tStream is accessible by uri rtsp://%s:%d\n\n",     p.src, p.rtsp_port);
01139         }
01140 
01141         str_stop     = 0;
01142         str_teardown = 0;
01143         str_count    = 0;
01144 
01145         if(p.rtsp){
01146                 str_setup = 0;
01147                 str_play  = 0; 
01148                 if(pthread_create(&pid, NULL, rtsp_loop, &p) != 0) {
01149                         fprintf(stderr, "thread create error!\n");
01150                         return -1;
01151                 }
01152         } else {
01153                 str_setup = 1;
01154                 str_play  = 1; 
01155         }
01156 
01157         if(p.rtsp_qt_compat) {
01158                 str_setup = 1;
01159                 str_play  = 1; 
01160         }
01161     
01162         while(1) {
01163                 if(!str_setup && !str_stop && !str_teardown) {
01164                         sched_yield();
01165 //                      usleep(10);
01166                         continue;
01167                 }
01168         
01169                 if(str_setup) {
01170                         str_setup = 0;
01171                 }
01172         
01173                 if(str_teardown) {
01174                         str_teardown = 0;
01175 //                      usleep(10);
01176                         sched_yield();
01177                         continue;
01178                 }
01179                 if(str_stop)
01180                         break;
01181                 res = grab_and_send(&p);
01182                 str_play  = 0;
01183                 str_setup = 0;
01184                 if(p.rtsp_qt_compat) {
01185                         str_setup = 1;
01186                         str_play  = 1; 
01187                 }
01188                 if(res != 0)
01189                         return -1;
01190                 if(str_stop)
01191                         break;
01192         }
01193 
01194         if(p.meth == MMAP_METHOD) {
01195                 munmap(start + TMP_BUF_OFFS, buf_size);
01196         }
01197 
01198         if(p.meth == READ_METHOD) {
01199                 free(wbuf);
01200         }
01201 
01202         return 0;
01203 }
01204 
01205 

Generated on Fri Nov 28 00:06:23 2008 for elphel by  doxygen 1.5.1