#include #include #include #include #include #include #include "frame.c" #include "picinfo.h" #include "encoder.h" #include "video_common.h" #include "rtp.h" /* f better be a pre-allocated frame */ int get_frame(Frame *f, int fd, frformat_t *picformat) { int rc = 0; read(fd, f->Getydata(), picformat->ysize); read(fd, f->Getudata(), picformat->usize); rc = read(fd, f->Getvdata(), picformat->vsize); if(rc != picformat->vsize) exit(0); return rc; } void dispatch_pkt(int filefd, u_char *buf, PicInfo *p, int hdrlen, rtp_hdr_t &rtphdr, h261_hdr_t &h261hdr) { int rc = 0; struct timeval tv; rtphdr.seq++; h261hdr.ebit = p->output.wflush_bits(); put_rtphdr(buf, &rtphdr); put_h261hdr(buf + H261HDR_OFFSET, &h261hdr); rc = send(filefd, buf, hdrlen + p->output.GetBufWbytes(), 0); if(rc < 0) perror("send "); tv.tv_sec = 0; tv.tv_usec = 50000; // select(0,0,0,0, &tv); } Encoder::Encoder():Thread() { n_xn = n_xmcn1 = n_xpn1 = 0; p = 0; picformat = NULL_FORMAT; } Encoder::~Encoder() { fprintf(stderr, "n_xn %x xmcn1 %x npn1 %x\n", n_xn, n_xmcn1, n_xpn1); // delete n_xn; delete n_xmcn1; delete n_xpn1;// delete p; // Base class destructor is automatically called } void Encoder::init_encoder(frformat_t &format, int sockfd, int filefd ) { if( memcmp(&picformat, &format,sizeof(picformat))) { fprintf(stderr, "initing encoder\n"); delete n_xn; delete n_xmcn1; delete n_xpn1; delete p; picformat = format; n_xn = new Frame(picformat.rows, picformat.cols); n_xmcn1 = new Frame(picformat.rows, picformat.cols); n_xpn1 = new Frame(picformat.rows, picformat.cols); p = new PicInfo( picformat ); } tx_fd = sockfd; img_fd = filefd; } float time_diff(struct timeval *t1, struct timeval *t2) { float rc = 0.0; if( t1 && t2) rc = float(t2->tv_sec - t1->tv_sec) + 1.0E-6 * float(t2->tv_usec - t1->tv_usec); return rc; } #define SBUF_SZ 8192 static u_char send_buf[SBUF_SZ]; void Encoder::Run(void) { int fr_num=0; int hdrlen = sizeof(rtp_hdr_t) + sizeof(h261_hdr_t); rtp_hdr_t rtphdr; h261_hdr_t h261hdr; struct timeval tv; struct timeval lasttime; sleep(5); memset(send_buf, 0, hdrlen); memset(&rtphdr, 0, sizeof(rtphdr)); memset(&h261hdr, 0, sizeof(h261hdr)); rtphdr.version = 2; rtphdr.pt = 31; for(int i=0; i < p->frameformat.numgbs; i++) { if(p->frameformat.type == CIF_TYPE) p->gquant[i] = 8; else if(p->frameformat.type == QCIF_TYPE) p->gquant[i*2] = 8; #ifdef BOUNDS_CHECK else bounds_error(__LINE__, __FILE__, __PRETTY_FUNCTION__); #endif } gettimeofday(&lasttime, NULL); /* Frame is already received */ while(get_frame(n_xn, img_fd, &picformat) > 0) { int startgb =0, startmb = 0; float delay; rtphdr.ts += 3003; #define TIMECHK #ifdef TIMECHK gettimeofday(&tv, NULL); delay = time_diff(&lasttime, &tv); lasttime = tv; if(delay < 0.1) { tv.tv_sec = 0; tv.tv_usec = long((0.1-delay)*1.0E6); select(0,0,0,0, &tv); } #endif /* Setup policy for iframe blocks */ p->framenum = fr_num % 32; for(int i=0; i < p->frameformat.nummbs; i++) { if(!(p->framenum)) p->mbinfo[i] = INTRA_FRAME; else p->mbinfo[i] = 0; } tryagain: p->output.attach_wbuf(send_buf + hdrlen, SBUF_SZ - hdrlen ); /* Form RTP and H261 header */ if(!startmb) { h261hdr.quant = 0; h261hdr.mbap = 0; h261hdr.i = 1; } else { h261hdr.quant = p->gquant[startgb]; h261hdr.mbap = startmb - 1; h261hdr.i = 0; } h261hdr.gobn = startgb; try { write_picture(p, n_xn, n_xpn1, n_xmcn1, startgb, startmb); } catch (PicException_t X) { if(X.type == END_OF_PKT) { startmb = X.mbnum + 1; startgb = X.gbnum; if(p->frameformat.type == QCIF_TYPE) startgb = startgb / 2; if(startmb >= MBS_IN_GOB) { startmb %= MBS_IN_GOB; startgb++; } if(startgb < p->frameformat.numgbs) { dispatch_pkt(tx_fd, send_buf, p, hdrlen, rtphdr, h261hdr); goto tryagain; } } else { fprintf(stderr, "%s ***** rcvd exception %d\n", __PRETTY_FUNCTION__, X.type); } } dispatch_pkt(tx_fd, send_buf, p, hdrlen, rtphdr, h261hdr); fr_num++; } }