00001 #include "video.h"
00002
00003 #include <sys/types.h>
00004 #include <sys/stat.h>
00005 #include <sys/ioctl.h>
00006 #include <sys/mman.h>
00007 #include <arpa/inet.h>
00008 #include <fcntl.h>
00009 #include <unistd.h>
00010
00011 #include <asm/elphel/c313a.h>
00012 #include <asm/elphel/hist.h>
00013 #include <asm/elphel/ext353.h>
00014
00015 #include <iostream>
00016 #include "streamer.h"
00017 using namespace std;
00018
00019
00020
00021 #define QTABLES_INCLUDE
00022
00023 int fd_stream = 0;
00024 int fd_circbuf = 0;
00025
00026 Video::Video(void) {
00027 stream_name = "video";
00028 for(int c = 0; c < 20; c++)
00029 if((fd_stream = open("/dev/stream", O_RDWR)) < 0)
00030 usleep(50000);
00031 else
00032 break;
00033 if(fd_stream < 0)
00034 throw("can't open /dev/stream");
00035 fd_circbuf = open("/dev/circbuf", O_RDONLY);
00036 if(fd_circbuf < 0)
00037 throw("can't open /dev/circbuf");
00038
00039 fd_ctl = fd_circbuf;
00040
00041
00042
00044 fd_ioctl = open("/dev/sensorpars", O_RDWR);
00045 if(fd_ioctl < 0)
00046 throw("can't open /dev/sensorpars");
00047
00048 _fd = fd_stream;
00049
00050 qtables_include = true;
00051
00052 SSRC = 12;
00053 _ptype = 26;
00054 rtp_socket = NULL;
00055 rtcp_socket = NULL;
00056 _play = false;
00057 prev_jpeg_wp = 0;
00058 buffer_length = 0;
00059 f_quality = -1;
00060
00061
00062 init_pthread((void *)this);
00063 }
00064
00065 Video::~Video(void) {
00066 if(fd_ioctl > 0)
00067 close(fd_ioctl);
00068 if(fd_circbuf > 0)
00069 close(fd_circbuf);
00070 if(fd_stream > 0)
00071 close(fd_stream);
00072 }
00073
00074 void Video::Start(string ip, long port) {
00075 if(_play)
00076 return;
00077
00078 v_t_sec = 0;
00079 v_t_usec = 0;
00080 v_frames = 0;
00081
00082 if(buffer_length == 0)
00083 buffer_length = lseek(fd_ctl, 0, 2);
00084 buffer_ptr = (unsigned long *)mmap(0, buffer_length, PROT_READ, MAP_SHARED, fd_circbuf, 0);
00085 buffer_ptr_s = (unsigned long *)mmap(buffer_ptr + (buffer_length / 4), buffer_length, PROT_READ, MAP_FIXED | MAP_SHARED, fd_circbuf, 0);
00086
00087
00088
00089
00090 f_width = width();
00091 f_height = height();
00092
00093 int status = ioctl(fd_ioctl, _IO(CMOSCAM_IOCTYPE, IO_CCAM_MONITOR_SEQ), 0);
00094
00095
00096 if(status != CAMSEQ_RUN)
00097 ioctl(fd_ioctl, _IO(CMOSCAM_IOCTYPE, IO_CCAM_JPEG), JPEG_CMD_START);
00098 RTP_Stream::Start(ip, port);
00099 }
00100
00101 void Video::Stop(void) {
00102 if(!_play)
00103 return;
00104 RTP_Stream::Stop();
00105
00106 prev_jpeg_wp = 0;
00107 munmap(buffer_ptr_s, buffer_length);
00108 munmap(buffer_ptr, buffer_length);
00109 }
00110
00111 int Video::width(void) {
00112 return ioctl(fd_ioctl, _CCCMD(CCAM_RPARS, P_ACTUAL_WIDTH), 0);
00113 }
00114
00115 int Video::height(void) {
00116 return ioctl(fd_ioctl, _CCCMD(CCAM_RPARS, P_ACTUAL_HEIGHT), 0);
00117 }
00118
00119 int Video::quality(void) {
00120 return ioctl(fd_ioctl, _CCCMD(CCAM_RPARS, P_QUALITY), 0);
00121 }
00122
00123 float Video::fps(void) {
00124 float fps = ioctl(fd_ioctl, _CCCMD(CCAM_RPARS, P_FP100S), 0);
00125 fps *= 0.01;
00126 return fps;
00127 }
00128
00129 void Video::fps(float fps) {
00130 if(fps > 0.01)
00131 ioctl(fd_stream, _IO(IOC_STREAM_SET_FPS, 0x00), int(fps * 100.0));
00132 }
00133
00134 long Video::capture(void) {
00135 long frame_len;
00136 long len;
00137
00138 int quality;
00139 unsigned long last_ptr;
00140 last_ptr = lseek(fd_circbuf, CIRCLSEEK_TOWP, SEEK_END);
00141 lseek(fd_circbuf, CIRCLSEEK_WAIT, SEEK_END);
00142 frame_ptr = (char *)((unsigned long)buffer_ptr + last_ptr);
00143 if(last_ptr < 32)
00144 last_ptr += buffer_length;
00145 last_ptr >>= 2;
00146 frame_len = buffer_ptr[last_ptr - 1];
00147
00148 char *ts_ptr = (char *)((unsigned long)frame_ptr + (long)(((frame_len + CCAM_MMAP_META + 3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC));
00149 unsigned long t[2];
00150 memcpy(&t, (void *)ts_ptr, 8);
00151 f_tv.tv_sec = t[0];
00152 f_tv.tv_usec = t[1];
00153
00154 char *meta = (char *)frame_ptr;
00155 meta -= 32;
00156 if(meta < (char *)buffer_ptr)
00157 meta += buffer_length;
00158 struct frame_params_t *fp = (struct frame_params_t *)meta;
00159 quality = fp->quality;
00160 if(qtables_include && quality != f_quality) {
00161 ioctl(fd_stream, _IO(IOC_STREAM_GET_QTABLES, (unsigned char)quality), (void *)&qtable[0]);
00162
00163 }
00164 f_quality = quality;
00165
00166 if(Streamer::instance()->opt_present("d")) {
00167 if(v_t_sec == 0) {
00168 v_frames = 0;
00169 v_t_sec = f_tv.tv_sec;
00170 v_t_usec = f_tv.tv_usec;
00171 }
00172 long t = f_tv.tv_sec - v_t_sec;
00173 t *= 1000000;
00174 t += f_tv.tv_usec;
00175 t -= v_t_usec;
00176 if(t >= 1000000) {
00177 float fps = v_frames * 1000000;
00178 fps /= t;
00179 char buf[128];
00180 float Tframe = 1.0 / fps;
00181 Tframe *= 96000000.0;
00182
00183 sprintf(buf, "fps == %3.6f, frames == %d, time == %d; Tframe == %.1f clk, ts: %d:%d", fps, v_frames, (int) t, Tframe, f_tv.tv_sec, f_tv.tv_usec);
00184 cerr << buf;
00185 v_t_sec = 0;
00186 unsigned long t[4];
00187 ioctl(fd_stream, _IO(IOC_STREAM_GET_TIME, 0x00), (void *)&t[0]);
00188 sprintf(buf, "; sys time == %d:%06d; FPGA time == %d:%06d", t[0], t[1], t[2], t[3]);
00189 cerr << buf << endl;
00190 long long ts, tf, d;
00191 ts = t[0];
00192 ts <<= 32;
00193 ts += t[1];
00194 tf = t[2];
00195 tf <<= 32;
00196 tf += t[3];
00197 if(ts > tf)
00198 d = ts - tf;
00199 else
00200 d = tf - ts;
00201 unsigned long t_usec = d & 0xFFFFFFFF;
00202 d >>= 32;
00203 unsigned long t_sec = d & 0xFFFFFFFF;
00204 cerr << "delta time: " << t_sec << ":" << t_usec << endl;
00205 }
00206 v_frames++;
00207 }
00208 return frame_len;
00209 }
00210
00211 bool Video::process(void) {
00212 int _plen = 1400;
00213 int to_send = _plen;
00214 int _qtables_len = 128 + 4;
00215 long frame_len = capture();
00216 if(frame_len <= 0)
00217 return false;
00218
00219 int to_send_len = frame_len;
00220 unsigned char h[20 + 4];
00221 int packet_len = 0;
00222 unsigned char *data = (unsigned char *)frame_ptr;
00223
00224 float f = f_tv.tv_usec;
00225 f /= 1000000;
00226 f += (f_tv.tv_sec & 0x7FFF);
00227 f *= 90000;
00228 timestamp = (unsigned long)f;
00229 unsigned long ts = htonl(timestamp);
00230
00231 long offset = 0;
00232 void *v_ptr[4];
00233 int v_len[4] = {0, 0, 0, 0};
00234 bool first = true;
00235 while(to_send_len && _play) {
00236 unsigned long pnum = htons(packet_num);
00237 bool last = false;
00238 to_send = _plen;
00239 if(qtables_include && first)
00240 to_send = _plen - _qtables_len;
00241 if(to_send_len <= to_send) {
00242 packet_len = to_send_len;
00243 to_send_len = 0;
00244 last = true;
00245 } else {
00246 packet_len = to_send;
00247 to_send_len -= to_send;
00248 }
00249
00250 h[0] = 0x80;
00251 if(!last)
00252 h[1] = _ptype;
00253 else
00254 h[1] = 0x80 + _ptype;
00255 memcpy((void *)&h[2], (void *)&pnum, 2);
00256 memcpy((void *)&h[4], (void *)&ts, 4);
00257 memcpy((void *)&h[8], (void *)&SSRC, 4);
00258
00259 unsigned long off = htonl(offset);
00260 memcpy((void *)&h[12], (void *)&off, 4);
00261 h[12] = 0x00;
00262 h[16] = 0x01;
00263 unsigned int q = f_quality;
00264 if(qtables_include)
00265 q += 128;
00266 h[17] = (unsigned char)(q & 0xFF);
00267 if(f_width <= 2040)
00268 h[18] = (f_width / 8) & 0xFF;
00269 else
00270 h[18] = 0;
00271 if(f_height <= 2040)
00272 h[19] = (f_height / 8) & 0xFF;
00273 else
00274 h[19] = 0;
00275 h[20] = 0;
00276 h[21] = 0;
00277 unsigned short l = htons(128);
00278 memcpy((void *)&h[22], (void *)&l, 2);
00279
00280 rtp_packets++;
00281 rtp_octets += packet_len + 8;
00282
00283 if(first) {
00284 v_ptr[0] = h;
00285 if(qtables_include) {
00286 v_len[0] = 24;
00287 v_ptr[1] = qtable;
00288 v_len[1] = 128;
00289 v_ptr[2] = data;
00290 v_len[2] = packet_len;
00291 rtp_socket->send3v(&v_ptr[0], &v_len[0]);
00292 } else {
00293 v_len[0] = 20;
00294 v_ptr[1] = data;
00295 v_len[1] = packet_len;
00296 rtp_socket->send2v(&v_ptr[0], &v_len[0]);
00297 }
00298 first = false;
00299 } else {
00300 v_ptr[0] = h;
00301 v_len[0] = 20;
00302 v_ptr[1] = data;
00303 v_len[1] = packet_len;
00304 rtp_socket->send2v(&v_ptr[0], &v_len[0]);
00305 }
00306
00307 packet_num++;
00308 data += packet_len;
00309 offset += packet_len;
00310 }
00311 return true;
00312 }