[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