[xiph-commits] r10514 - in experimental/j/Elphel333: common http

j at svn.xiph.org j at svn.xiph.org
Thu Dec 1 15:40:39 PST 2005


Author: j
Date: 2005-12-01 15:40:34 -0800 (Thu, 01 Dec 2005)
New Revision: 10514

Added:
   experimental/j/Elphel333/common/cgi.c
   experimental/j/Elphel333/common/cgi.h
Modified:
   experimental/j/Elphel333/common/Makefile
   experimental/j/Elphel333/common/oggtheora.c
   experimental/j/Elphel333/common/oggtheora.h
   experimental/j/Elphel333/http/Makefile
   experimental/j/Elphel333/http/TheoraHTTP.c
Log:
somehow works as cgi, will not terminate right, data mostly garbage

Modified: experimental/j/Elphel333/common/Makefile
===================================================================
--- experimental/j/Elphel333/common/Makefile	2005-12-01 18:07:01 UTC (rev 10513)
+++ experimental/j/Elphel333/common/Makefile	2005-12-01 23:40:34 UTC (rev 10514)
@@ -13,7 +13,7 @@
 
 LD	= ld-cris
 
-OBJS=oggtheora.o utils.o
+OBJS=oggtheora.o utils.o cgi.o
 SRCS=$(OBJS:%.o=%.c)
 
 all: $(OBJS)

Added: experimental/j/Elphel333/common/cgi.c
===================================================================
--- experimental/j/Elphel333/common/cgi.c	2005-12-01 18:07:01 UTC (rev 10513)
+++ experimental/j/Elphel333/common/cgi.c	2005-12-01 23:40:34 UTC (rev 10514)
@@ -0,0 +1,70 @@
+#include <fcntl.h>  /*open*/
+#include <unistd.h> /* close, sleep */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+
+#include <sys/types.h> /* for fstat */
+#include <sys/stat.h> /* for fstat */
+
+#include <sys/mman.h>    /* mmap */
+
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+
+
+
+#include "cgi.h"
+
+int hexdigit (char c) {
+  int i;
+  i=c-'0';
+  if ((i>=0) && (i<10)) return i;
+  i=c-'a'+10;
+  if ((i>=10) && (i<16)) return i;
+  i=c-'A'+10;
+  if ((i>=10) && (i<16)) return i;
+  return 0;  // could be -1??
+}
+
+int unescape (char * s, int l) {
+  int i=0;
+  int j=0;
+  while ((i<l) && s[i]) {
+    if ((s[i]=='%') && (i<(l-2)) && s[i+1]){ // behavior from Mozilla
+      s[j++]=(hexdigit(s[i+1])<<4) | hexdigit(s[i+2]);
+      i+=3;
+    } else s[j++]=s[i++];
+  }
+  if (i<l) s[j]=0;
+  return j;
+}
+
+int parseQuery(struct key_value * params, char * qry)
+{
+  char * cp;
+  int l=0;
+  cp=strtok(qry,"=");
+  while ((cp) && (l<QRY_MAXPARAMS)) {
+    params[l].key=cp;
+    cp=strtok(NULL,"&");
+    params[l++].value=cp;
+    if (cp) cp=strtok(NULL,"=");
+  }
+ params[l].key=NULL;
+ return l;
+}
+
+char * paramValue(struct key_value * params, char * skey)
+{ // returns pointer to parameter value, NULL if not defined
+  int i=0;
+  if (skey)
+   while ((i<QRY_MAXPARAMS) && (params[i].key)) {
+    if (strcmp(skey,params[i].key)==0) return   params[i].value;
+
+    i++;
+   }
+  return NULL;
+}

Added: experimental/j/Elphel333/common/cgi.h
===================================================================
--- experimental/j/Elphel333/common/cgi.h	2005-12-01 18:07:01 UTC (rev 10513)
+++ experimental/j/Elphel333/common/cgi.h	2005-12-01 23:40:34 UTC (rev 10514)
@@ -0,0 +1,19 @@
+
+
+#ifndef _CGI_H
+#define _CGI_H
+#define QRY_MAXPARAMS 64
+struct key_value {
+  char *key;
+  char *value;
+};
+
+struct key_value gparams[QRY_MAXPARAMS+1];
+
+int parseQuery(struct key_value * params, char * qry);
+char * paramValue(struct key_value * params, char * skey); // returns pointer to parameter value, NULL if not defined
+int unescape (char * s, int l);
+int hexdigit (char c);
+
+
+#endif

Modified: experimental/j/Elphel333/common/oggtheora.c
===================================================================
--- experimental/j/Elphel333/common/oggtheora.c	2005-12-01 18:07:01 UTC (rev 10513)
+++ experimental/j/Elphel333/common/oggtheora.c	2005-12-01 23:40:34 UTC (rev 10514)
@@ -162,37 +162,7 @@
 int oc_huff_codes_pack(char *buf, int* bp,
  const theora_huff_code _codes[OC_NHUFFMAN_TABLES][OC_NDCT_TOKENS]);
 
-int ogg_page      (ogg_header_t *    ogg_header, // pointer to the header data (returns - header length in bytes)
-                            char     flags,
-                            u_int64_t granule,
-                            u_int32_t stream_serial,
-                            int      page,       // page
-                            int      num_packets, // number of packets in the page
-                   len_data_t *      packets);
-
-/*
-    similar to above, but dedicated to the frame data.
-    There could be 2 types
-    - first page of a frame (packet) then frame header will be attached 
-      and bit-combined with the frame
-    - continuation  page (flags bit 0 should be set) - 
-        then no frame header will be added to the data
-    currently there can not be two frames (packets) on one page
-*/
-int ogg_frame_page      (ogg_header_t *    ogg_header,      // pointer to the header data (returns - header length in bytes)
-                            char           flags,           // +1 - continuation, +4 - last (+2 - first)
-                            int            maxpage,         // maximal page size (w/o ogg header)
-                            u_int64_t      granule,         // 
-                            u_int32_t      stream_serial,   //
-                            int            page,            // page
-                            len_data_t     frame_header,    // not used if (flags & 1). frame_header.len is measured in bits, not bytes!
-                            int          * len,             // pointer frame data length (will modify - if non-zero - need continuation)
-                            u_int8_t    ** frame_data);     // pointer to pointer to an array with frame data
-                                                            // if it is not continuation data is bit-aligned to be combined with frame_header
-                                                            // first word of frame data will be modified - OR-ed with the last one from
-                                                            // the frame_header
                    
-                   
 int theora_identification (char *buf,  // returns length, buf should be big enough - 42 bytes
                               int   fmbw, // width in macroblocks
                               int   fmbh, // height in macroblocks
@@ -804,6 +774,7 @@
      int i,n,nn,r;
      u_int32_t crc_reg;
      char * c_header= (char *) ogg_header;
+
      memcpy (ogg_header->OggS,oggs_string,4);
      ogg_header->version=        0;
      ogg_header->serial[0]=      stream_serial & 0xff;
@@ -827,6 +798,7 @@
      ogg_header->crc[1]=         0;
      ogg_header->crc[2]=         0;
      ogg_header->crc[3]=         0;
+
 // first pass - just fill lacing values/number of segments
      n=0;
      for (i=0;i<num_packets; i++) {
@@ -839,6 +811,7 @@
             ogg_header->lacing_values[n]=255;
         ogg_header->lacing_values[n++]=r;
      }
+
      ogg_header->num_segm=       n;
      // second pass - calculate the crc     
      crc_reg=0;

Modified: experimental/j/Elphel333/common/oggtheora.h
===================================================================
--- experimental/j/Elphel333/common/oggtheora.h	2005-12-01 18:07:01 UTC (rev 10513)
+++ experimental/j/Elphel333/common/oggtheora.h	2005-12-01 23:40:34 UTC (rev 10514)
@@ -111,6 +111,40 @@
                        int         pre_ht30[6]);
 
 
+int ogg_page      (ogg_header_t *    ogg_header, // pointer to the header data (returns - header length in bytes)
+                            char     flags,
+                            u_int64_t granule,
+                            u_int32_t stream_serial,
+                            int      page,       // page
+                            int      num_packets, // number of packets in the page
+                   len_data_t *      packets);
+
+/*
+    similar to above, but dedicated to the frame data.
+    There could be 2 types
+    - first page of a frame (packet) then frame header will be attached 
+      and bit-combined with the frame
+    - continuation  page (flags bit 0 should be set) - 
+        then no frame header will be added to the data
+    currently there can not be two frames (packets) on one page
+*/
+int ogg_frame_page      (ogg_header_t *    ogg_header,      // pointer to the header data (returns - header length in bytes)
+                            char           flags,           // +1 - continuation, +4 - last (+2 - first)
+                            int            maxpage,         // maximal page size (w/o ogg header)
+                            u_int64_t      granule,         // 
+                            u_int32_t      stream_serial,   //
+                            int            page,            // page
+                            len_data_t     frame_header,    // not used if (flags & 1). frame_header.len is measured in bits, not bytes!
+                            int          * len,             // pointer frame data length (will modify - if non-zero - need continuation)
+                            u_int8_t    ** frame_data);     // pointer to pointer to an array with frame data
+                                                            // if it is not continuation data is bit-aligned to be combined with frame_header
+                                                            // first word of frame data will be modified - OR-ed with the last one from
+                                                            // the frame_header
+                   
+
+
+
+
 // load headers from file
 int load_headers(const char *headers_filename, len_data_t *packets, int *kfgshiftm);
 

Modified: experimental/j/Elphel333/http/Makefile
===================================================================
--- experimental/j/Elphel333/http/Makefile	2005-12-01 18:07:01 UTC (rev 10513)
+++ experimental/j/Elphel333/http/Makefile	2005-12-01 23:40:34 UTC (rev 10514)
@@ -6,7 +6,7 @@
 include $(AXIS_TOP_DIR)/tools/build/Rules.axis
 
 THEORACOMMON=../common
-THEORACOMMON_OBJS=$(THEORACOMMON)/oggtheora.o $(THEORACOMMON)/utils.o
+THEORACOMMON_OBJS=$(THEORACOMMON)/oggtheora.o $(THEORACOMMON)/utils.o $(THEORACOMMON)/cgi.o
 
 DEFS   = -DHAVE_CONFIG_H
 CFLAGS = -O2 -W  -Wwrite-strings -Wbad-function-cast -Wmissing-prototypes -Wcast-qual -Wmissing-declarations  $(DEFS) -I$(THEORACOMMON)

Modified: experimental/j/Elphel333/http/TheoraHTTP.c
===================================================================
--- experimental/j/Elphel333/http/TheoraHTTP.c	2005-12-01 18:07:01 UTC (rev 10513)
+++ experimental/j/Elphel333/http/TheoraHTTP.c	2005-12-01 23:40:34 UTC (rev 10514)
@@ -35,6 +35,7 @@
 
 #include "defines.h"
 #include "oggtheora.h"
+#include "cgi.h"
 
 #define D(x) 
 
@@ -126,6 +127,7 @@
     int         nframes_total, nframes_inter_full, nframes_inter_masked;
     int         time_slow;
     u_int8_t    *ccam_dma, *dp = NULL;
+    u_int8_t    *dp_prev = NULL;
     u_int32_t   *ccam_dma_index;
     int         circindex_fd;
     int         circbuf_fd;
@@ -142,11 +144,19 @@
     
     //FIXME where does this have to go?                    
     u_int64_t  granule=0;
+    u_int64_t    granule_mask=(1<<kfgshiftm)-1;
     int header_length;
     ogg_header_t header;
     int page_size=8192;
 
+      int          frame_header_length;   // frame header lengh truncated to 32-bit words (the rest is combined with frame data)
+      int          overlapped_header; // 0/4 - if "4" then bits from the first word of data are already copied to the header
+      int          first_frame=1;
 
+      int fw=0;
+      FILE *output_fd=stdout;
+
+
     a_ready = 0; 
     circindex_fd = open("/dev/circindex", O_RDWR);
     if (circindex_fd<0) { // check control OK
@@ -181,7 +191,6 @@
         return ;
     }
     
-    InitTimer();
     wp=wp0=0;
     
     nframe = HDR_INTERVAL;
@@ -201,12 +210,43 @@
     if(setup_tbl_FPGA( nframes_total, nframes_inter_full,
                                       nframes_inter_masked, time_slow)<0)
         return;
-    
-    if(make_OggTheoraHdrs(headers_filename)<0) {
-        fprintf(stderr,"Error prepare headers while parsing %s\n",headers_filename);
-        free(b_headers);
-        return;
+   
+    // Ogg Header this should go in its own function: ogg_send_header 
+    // first make and send first page
+    i= load_headers(headers_filename, packets, &kfgshiftm);
+    header_length = ogg_page (&header, (int)2, (int)0, stream_serial, page++, (int)1, &packets[0]);
+
+    if (header_length<0) 
+        return; // header_length-1000;
+    if ((fw= fwrite_all(output_fd, (char *) &header, header_length))<0) {
+        fprintf(stderr,"error writing output data1 - error = %d (%s)\n",
+                                                         errno,strerror(errno)); 
     }
+    if ((fw= fwrite_all(output_fd, packets[0].data, packets[0].len))<0) {
+        fprintf(stderr,"error writing output data2 - error = %d (%s)\n",
+                                                         errno,strerror(errno)); 
+    }
+
+
+    //make and send second page with 2 packets
+    header_length= ogg_page (&header, (int)0, (int)0, stream_serial, page++, (int)2, &packets[1]);
+
+    if (header_length<0) 
+        return; // header_length-2000;    
+    if ((fw= fwrite_all(output_fd, (char *) &header, header_length))<0) {
+        fprintf(stderr,"error writing output data3 - error = %d (%s)\n",
+                                                         errno,strerror(errno)); 
+    }
+    if ((fw= fwrite_all(output_fd, packets[1].data, packets[1].len))<0) {
+        fprintf(stderr,"error writing output data4 - error = %d (%s)\n",
+                        errno, strerror(errno)); 
+    }
+    if ((fw= fwrite_all(output_fd, packets[2].data, packets[2].len))<0) {
+        fprintf(stderr,"error writing output data5 - error = %d (%s)\n",
+                        errno,strerror(errno)); 
+    }
+    // Ogg Header End
+
     frame_no = 0;
 
     while (true) {
@@ -222,12 +262,8 @@
         ioctl(devfd, _IO(CMOSCAM_IOCTYPE, IO_CCAM_JPEG_GET_N ), acq_data);
 
         //wait for encoding to be done (or aborted?)
-        fprintf(stderr,"wait for encoding\n");
+        fprintf(stderr,"encoding...\n");
         while ((i=ioctl(devfd, _IO(CMOSCAM_IOCTYPE, IO_CCAM_MONITOR_SEQ ), 0)) > CAMSEQ_JPEG) {
-            if(strm_data->status == STOP_STREAM ) {
-                break;   // receive command STOP from web interface
-            }
-            // has to break here if http connection is closed
             
             // data ready ?    
             if(wp == 0) {
@@ -239,9 +275,7 @@
             }
 
             // dark_loop
-            fprintf(stderr,"dark loop\n");
             do {
-                // what does this do??? 
                 last_page_flags= (ccam_dma_index[frame_no+1]==0xffffffff)?4:0;
                 
                 if (last_page_flags == 4) {
@@ -249,7 +283,6 @@
                    sched_yield();
                 }
             } while(last_page_flags == 4);
-            fprintf(stderr,"dark loop done\n");
             //frame_no = ioctl(devfd, _CCCMD( CCAM_RPARS , P_JPEG_WP), 0)-1;
             // soft correction FPS    
 
@@ -270,14 +303,27 @@
                 continue;
             }
 
-            time_frame+= mTimeinterval; // time start for next frame INTER/INTRA
+            frame_header_length =  ((packets[3+frame_type].len+31)>>3)& (~3);
+            overlapped_header   =  (packets[3+frame_type].len & 31)?4:0;
+            last_page_flags     =  (ccam_dma_index[nframe+1]==0xffffffff)?4:0;
 
+            /* calculated granulepos */
+            if (first_frame) {
+                first_frame=0;
+            } else if (frame_type==INTRA){
+                granule=(granule+ (((granule&granule_mask)+1)<<kfgshiftm)) & (~granule_mask);
+            } else {
+                granule=(granule & (~granule_mask)) |  ((granule+1) &granule_mask);
+            }
+
             //pointer to next theora frame in camera dma
+
             dp=&ccam_dma[frame_start];
+            dp_prev = &ccam_dma[frame_start];
 
             //why this check for 1000000?
             if((unsigned)frame_length <1000000) {
-                fprintf(stderr,"ogg_frame_page\n");
+                fprintf(stderr,"ogg_frame_page: frame_length %d\n", frame_length);
                 header_length= ogg_frame_page (&header,       // [1]
                                        last_page_flags,       // [2]
                                        page_size,             // [3]
@@ -302,9 +348,44 @@
                 */
                 
                 //FIXME now actually print the ogg page here.
-                fprintf(stderr,"FIXME, now print ogg page, header_length %d = frame_length %d \n",
-                                                     header_length,frame_length);
+                if (header_length<0) 
+                    fprintf(stderr, "ups\n");
 
+                // write to output stream first (or only) page of a frame
+                if ((fw= fwrite_all(output_fd, (char *) &header, header_length))<0) {
+                    fprintf(stderr,"error writing output data6 - error = %d (%s)\n",
+                            errno,strerror(errno)); 
+                }
+                if ((fw= fwrite_all(output_fd, packets[3+frame_type].data, frame_header_length))<0) {
+                    fprintf(stderr,"error writing output data7 - error = %d (%s)\n",
+                            errno,strerror(errno)); 
+                }
+                if ((fw= fwrite_all(output_fd, dp_prev+overlapped_header, (int) (dp-dp_prev-overlapped_header)))<0) {
+                    fprintf(stderr,"error writing output data8 - error = %d (%s)\n",
+                            errno,strerror(errno)); 
+                }
+                while (frame_length>0) {
+                    dp_prev=dp;
+                    header_length= ogg_frame_page (&header,             // [1]
+                                        last_page_flags,        // [2]
+                                        page_size,              // [3]
+                                        granule,
+                                        stream_serial,
+                                        page++,
+                                        packets[3+frame_type],  // [4]
+                                        &frame_length,          // [5]
+                                        &dp);                   // [6]
+        
+            // write to output stream other pages of a frame
+            if ((fw= fwrite_all(output_fd, (char *) &header, header_length))<0) {
+                fprintf(stderr,"error writing output data9 - error = %d (%s)\n",
+                                errno,strerror(errno)); 
+            }
+            if ((fw= fwrite_all(output_fd, dp_prev, (int) (dp-dp_prev)))<0){
+                fprintf(stderr,"error writing output data10 - error = %d (%s)\n",
+                                errno,strerror(errno)); 
+            } 
+                }
                 
             }
             frame_start=next_frame_start;
@@ -348,75 +429,49 @@
     strcpy(strm_data_par.email,"camera at elphel.com");
     strm_data_par.encrypt_key[0]='\0';
 
-    while(true) {
-        c = getopt(argc, argv, "hwa:p:f:k:");
-        if (c == -1)
-            break;
-     
-        switch (c) {
-            case 'h':
-                flag++;    
-                break;
-            case 'w':
-                use_web = true;     
-                break;
-            case 'a':
-                memset(strm_data_par.address,0,21);
-                strncpy(strm_data_par.address,optarg,20);
-                break;
-            case 'k':
-                memset(strm_data_par.encrypt_key,0,41);
-                strncpy(strm_data_par.encrypt_key,optarg,40);
-                strm_data_par.encryption=1;
-                break;
-            case 'p':
-                strm_data_par.port = atol(optarg);    
-                break;
-            case 'f':
-                strm_data_par.fps = atof(optarg);
-                if(strm_data_par.fps < 0. )
-                    strm_data_par.fps=25.;    
-                break;
-            case '?':
-                flag++;
-                break;
-            default:
-                fprintf (stderr,"?? getopt returned character code 0%o ??\n", c);
-        }
-    }
-    if ((optind < argc)|| flag>0) {
-        usage();
-        exit(1);
-    }
-    if(use_web) {
-        unlink(mmapFileName);
-        // map shared memory for manage this with CGI 
-        // where shared memory opening whith query too
+
+  /* these are from cgitest.cgi */
+  int i;
+  const char *method;
+  const char *query;
+  const char *uri;
+  char  copyQuery [4096];
+
+  const char mmapFileName[]= "/var/tmp/mmap_strm";
+  strm_data_t    *strm_data;
+
+  method = getenv("REQUEST_METHOD");
+  query  = getenv("QUERY_STRING");
+  uri    = getenv("REQUEST_URI");
+  i= (query)? strlen (query):0;
+     fprintf(stderr,"querry length=%d\n", i);
+
+  if (i>(int)(sizeof(copyQuery)-1)) i= sizeof(copyQuery)-1;
+  if (i>0) strncpy(copyQuery,query, i);
+  copyQuery[i]=0;
+  unescape(copyQuery,sizeof(copyQuery));
+
+  if (method == NULL) {
+    /* Not a CGI! */
+    printf("This program should be run as a CGI from the web server!\n");
+   // exit(1);
+  }
+
+  parseQuery(gparams, copyQuery);
+
+
+    strm_data = &strm_data_par;  // use data from local buffer   
+    // not used web - start streamer immediate
+    strm_data_par.status = START_STREAM;    
     
-        devfd = open(mmapFileName,O_RDWR|O_CREAT); 
-        if(devfd == -1) {
-            printf("Error opening %s!\n",mmapFileName);
-        }
-        lseek(devfd,sizeof(strm_data_t),SEEK_SET);
-        write(devfd,"",1);
-        strm_data = (strm_data_t *) mmap(0, sizeof(strm_data_t), 
-                                     PROT_READ|PROT_WRITE, MAP_SHARED, devfd, 0);
-        if((int)strm_data == -1) {
-             fprintf(stderr,"Error in mmap %s\r\n",mmapFileName);
-             close(devfd);
-             unlink(mmapFileName);
-             exit(1);
-        }
-    } 
-    else {
-        strm_data = &strm_data_par;  // use data from local buffer   
-        // not used web - start streamer immediate
-        strm_data_par.status = START_STREAM;
-    }       
-    
     // OK - init data
 
     // General LOOP waiting command START
+    printf("HTTP/1.0 200 OK\n");
+    printf("Content-Type: applicatoin/ogg\n");
+    printf("Pragma: no-cache\n\n");
+
+
     while(true) {
          if(strm_data->status == -1)
             break;



More information about the commits mailing list