~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Open Mash Cross Reference
mash/codec/encoder-h263.cc

Component: ~ [ mash ] ~ [ apps ] ~ [ gsm ] ~ [ lib ] ~ [ otcl ] ~ [ srm ] ~ [ tcl8.3 ] ~ [ tclcl ] ~ [ tk8.3 ] ~ [ tutorials ] ~

  1 /*
  2  * encoder-h263.cc --
  3  *
  4  *      H.263 video encoder.
  5  *
  6  * Copyright (c) 2001-2002 The Regents of the University of California.
  7  * All rights reserved.
  8  *
  9  * Redistribution and use in source and binary forms, with or without
 10  * modification, are permitted provided that the following conditions are met:
 11  *
 12  * A. Redistributions of source code must retain the above copyright notice,
 13  *    this list of conditions and the following disclaimer.
 14  * B. Redistributions in binary form must reproduce the above copyright notice,
 15  *    this list of conditions and the following disclaimer in the documentation
 16  *    and/or other materials provided with the distribution.
 17  * C. Neither the names of the copyright holders nor the names of its
 18  *    contributors may be used to endorse or promote products derived from this
 19  *    software without specific prior written permission.
 20  *
 21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
 22  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 23  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
 25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 31  * POSSIBILITY OF SUCH DAMAGE.
 32  */
 33 
 34 #include <assert.h>
 35 
 36 #include "codec/h263/defs.h"
 37 #include "rtp/inet.h"
 38 #include "rtp/rtp.h"
 39 #include "codec/dct.h"
 40 #include "misc/bsd-endian.h"
 41 
 42 #include "tclcl.h"
 43 #include "codec/crdef.h"
 44 #include "rtp/pktbuf-rtp.h"
 45 #include "codec/module.h"
 46 
 47 #define    DEFINE_GLOBALS    1
 48 
 49 extern "C" {
 50 #include "codec/h263/bitOut.h"
 51 #include "codec/h263/h263.h"
 52 #include "codec/h263/Util.h"
 53 #include "codec/h263/h263encoder.h"
 54 #include "codec/h263/h263encoder.p"
 55 
 56     int split_h263stream(
 57         int rtpFmt,              /* rtp format [in] */
 58         u_char *bs,              /* bitstream [in] */
 59         u_int bitcount,          /* bitstream length in bits [in] */
 60         u_int gobs_per_frame,    /* gobs per frame [in] */
 61         u_int mbs_per_gob,       /* mbs per gob [in] */
 62         int *mbind,              /* macroblock indices [in] */
 63         int *mbquant,            /* quantifiers [in] */
 64         MVField mvfield,         /* motion vectors [in] */
 65         u_int ts_,               /* timestamp [in] */
 66         int headersize,          /* headerlength [in] */
 67         h263_rtp_packet **packets /* rtp packets [out] */
 68     );
 69 
 70 /* define some external functions from h263/  */
 71 #include "codec/h263/Motion.h"
 72 extern void CopyMacroBlockPicture(
 73     int xPos, int yPos, Picture *pictIn,Picture *pictOut);
 74 extern int CopyMVector(MVector *mvIn, MVector *mvOut);
 75 extern void ResetMVector(MVector *mv);
 76 }
 77 #include "codec/encoder-h263.h"
 78 
 79 H263Encoder::H263Encoder() : EncoderModule()
 80 {    /* first frame must be coded INTRA */
 81     nexttype_ = PICTURE_CODING_TYPE_INTRA;
 82 
 83     ifn_ = 0;
 84     pfn_ = 0;
 85     lastw_ = 0;lasth_ = 0;
 86     oldpic_.w = 0;
 87     oldpic_.h = 0;
 88     oldpic_.y = new Byte[3];
 89     oldpic_.u = oldpic_.y+1;
 90     oldpic_.v = oldpic_.u+1;
 91     oldorigpic_.w = 0;
 92     oldorigpic_.h = 0;
 93     oldorigpic_.y = new Byte[3];
 94     oldorigpic_.u = oldorigpic_.y+1;
 95     oldorigpic_.v = oldorigpic_.u+1;
 96     mbind_=(int*)malloc(1);
 97     mbquant_=(int*)malloc(1);
 98     mvfield_.mx = (short*)malloc(1);
 99     mvfield_.my = (short*)malloc(1);
100     mvfield_.mode = (short*)malloc(1);
101     mvfield_.w = 1;
102     mvfield_.h = 1;
103     mbstruct_ = H263allocMbStruct(1, 6, 64);
104     decpict_.w = 0; decpict_.h = 0;
105     decpict_.y = new Byte[3];
106     decpict_.u = decpict_.y+1;
107     decpict_.v = decpict_.u+1;
108     
109     /* 
110          * Global maximum rate for the encoder. The encoder itself does not 
111          * have a fixed bitrate delimiter, so we just allocate a very big 
112          * buffer and hope that the encoder does not overflow it.
113          *
114          * THIS REALLY SHOULD BE FIXED - see how h.261 encoder fills rtp
115          * packet then takes bytes off the end of the packet and initializes
116          * a new packet.
117      */
118     maxrate_ = 500000;
119     bitstr_.b = new Byte[maxrate_*10/8];
120     bitstr_.size = maxrate_*10;
121     bitstr_.ind = 0;
122     bitstr_.actualSize = 0;
123     bitstr_.fp = NULL;
124     
125     codingtime_ = 5;      /* needed for h263/h263enc.c code - not used */
126     maycheck_ = 0;
127     q_ = 10;              /* default Quantizer is 10 */
128     modQuant_ = 0;        /* default off for Annex T modified quantization */
129     rtpFmt_ = RFC_2190;   /* default transport is RFC 2190 */
130     nb_ = 0;              /* initialize bit rate stat -- nb_ is in bytes */
131 }
132 
133 H263Encoder::~H263Encoder()
134 {
135     /* free storage used to encode images */
136     delete [] bitstr_.b;
137     delete[] oldpic_.y;
138     delete[] oldorigpic_.y;
139     delete[] decpict_.y;
140     free(mvfield_.mx);
141     free(mvfield_.my);
142     free(mvfield_.mode);
143     free(mbind_);
144     free(mbquant_);
145 }
146 
147 void
148 H263Encoder::size(int w, int h)
149 {
150     int mbsrow = w >> 4; /* number MBs per row */
151     int mbscol = h >> 4; /* number MBs per column */
152 
153     // fprintf(stderr,"send-h263: new frame size: %dx%d\n",w,h);
154     if (w == QCIF_WIDTH && h == QCIF_HEIGHT) {
155         src_fmt_ = QCIF;
156         mb_k_ = 1;
157     } else if (w == CIF_WIDTH && h == CIF_HEIGHT) {
158         src_fmt_ = CIF;
159         mb_k_ = 1;
160     } else if (w == CIF4_WIDTH && h == CIF4_HEIGHT) {
161         src_fmt_ = CIF4;
162         mb_k_ = 2;
163     } else if (w == CIF16_WIDTH && h == CIF16_HEIGHT) {
164         src_fmt_ = CIF16;
165         mb_k_ = 4;
166     } else if ( !(w % 16) && !(h %16)) {
167         mb_k_ = 1;
168         if ((h<4) || (h>1152)) {
169             fprintf(stderr, "Custom source format height <4 or >1152 is not supported.\n");
170             src_fmt_ = CIF;
171             w = CIF_WIDTH;
172             h = CIF_HEIGHT;
173         } else {
174             src_fmt_ = CUSTOM_SOURCE_FORMAT;
175             if ( h > 400 ) {
176                 mb_k_ = ( h<801 ? 2 : 4);
177             }
178         }
179     } else {
180         fprintf(stderr, 
181             "Custom format must be a multiple of 16 pixels (w=%d, h=%d).\n", 
182             w, h);
183         src_fmt_ = CIF;
184         mb_k_ = 1;
185         w = CIF_WIDTH;
186         h = CIF_HEIGHT;
187     }
188     nmbs_ = mbsrow * mbscol;
189     gobs_per_frame_ = h / (mb_k_ << 4);
190     mbs_per_gob_ = mb_k_ * mbsrow;
191     FrameModule::size(w, h);
192     return;
193 }
194 
195 void
196 H263Encoder::setq(int q)
197 {
198   q_ = q;
199 }
200 
201 int
202 H263Encoder::configure(const char *const s)
203 {
204     if (strcmp(s, "modQ") == 0) {
205         modQuant_ = 1;  /* enable Annex T modified quantization */
206         return (1);
207     }
208     /* check for transport format options */
209     if (strcmp(s, "rfc2190") == 0) {
210         rtpFmt_ = RFC_2190; 
211         return (1);
212     }
213     if (strcmp(s, "rfc2429") == 0) {
214         rtpFmt_ = RFC_2429; 
215         return (1);
216     }
217     if (strcmp(s, "rfc2190ucl") == 0) {
218         rtpFmt_ = RFC_2190ucl; 
219         return (1);
220     }
221     return (0);
222 }
223 
224 int
225 H263Encoder::command(int argc, const char*const* argv)
226 {
227     Tcl& tcl = Tcl::instance();
228 
229     if (argc == 2) {
230         if (strcmp(argv[1], "frame-format") == 0) {
231             tcl.result("420");
232             return (TCL_OK);
233         }
234     }
235 
236     if (argc == 3) {
237         if (strcmp(argv[1], "q") == 0) {
238             q_ = atoi(argv[2]);
239             return (TCL_OK);
240         }
241         if (strcmp(argv[1], "config") == 0) {
242             if (!configure(argv[2])) {
243                 tcl.resultf("H263 encoder: option %s unknown",
244                         argv[2]);
245                 return (TCL_ERROR);
246             }
247             return (TCL_OK);
248         }
249     }
250     return (EncoderModule::command(argc, argv));
251 }
252 
253 void
254 H263Encoder::recv(Buffer* bp)
255 {
256     const VideoFrame* vf = (VideoFrame*)bp;
257     if (!samesize(vf))
258       size(vf->width_, vf->height_);
259     YuvFrame* p = (YuvFrame*) vf; 
260     encode(vf, p->crvec_);
261 }
262 
263 int BitsToByteAlign(Bitstr *bs)
264 {
265     int n;
266     
267     n = 8-(bs->ind)%8;
268     if(n==8) n=0;
269    
270     return n;
271 }
272 
273 void PutNumber(int num, int n, Bitstr *b)
274 {
275     if (n > 0) {
276       int  i;
277       long numl = (long)num;
278       int  rem = b->ind & 0x7;
279       long mask = (0x1 << (8 - rem)) - 1;
280       int  ind = b->ind + n - 1;
281       int  byteInd = ind >> 3;
282       int  bitPEnd = 7 - (ind & 0x7);
283 
284 
285       numl <<= bitPEnd;
286 
287       for (i = rem + n - 8; i > 0; i -= 8) {
288         b->b[byteInd--] = (Byte)numl;
289         numl >>= 8;
290       }
291 
292       b->b[byteInd] &= ~mask;
293       b->b[byteInd] |= (numl & mask);
294       b->ind += n;
295     }
296 }
297 
298 
299 int ByteAlign(Bitstr *b)
300 {
301     int n;
302 
303     n = BitsToByteAlign(b);
304     PutNumber(0, n, b);
305 
306     return(n);
307 }
308 
309 int egob, emba;  /* global variables for debugging */
310 
311 /* This function encodes an INTRA frame and returns number of bits*/
312 int H263Encoder::encodeIframe(int codingTime, int t, int gfid,
313                  Picture *pict, Picture *decPict, Bitstr *bs,
314                  int *mbInd, int *mbQuant, MVField *mvField)
315 {
316     int    bits = 0;
317     int    gob = 0;
318     int mba = 0;
319     int mx = 0;
320     int my= 0;
321 
322     /* Init quant tables */
323     if (q_ != quantInit) {
324         H263initQuantTables(q_);
325         quantInit = q_;
326     }
327 
328     if (!mbInd || !mbQuant || !mvField) {
329         fprintf(stderr, "encodeIframe: missing mbInd, mbQuant, or mvField.\n");
330         return (0);
331     }
332 
333     //printf("ENCODE FRAME\n");
334 
335     while (mba < nmbs_) {
336 
337         /* init variables to do coding */
338         mbInd[mba] = bs->ind;
339         mbQuant[mba] = q_;
340         mvField->mode[mba] = MODE_INTRA;
341         mvField->mx[mba] = 0;
342         mvField->my[mba] = 0;
343 
344         /* Is it a Picture or GOB boundary? */
345         if ((mba % mbs_per_gob_) == 0) {
346             bits += ByteAlign(bs);
347             if (mba == 0) {
348                 bits += H263putPictureHeader(
349                     t, src_fmt_, PICTURE_CODING_TYPE_INTRA, q_, modQuant_,
350                     pict->w, pict->h, bs);
351             } else {
352                 bits += H263putGOBHeader(gob, gfid, q_, bs);
353             }
354         }
355 
356         egob=gob; emba=mba % mbs_per_gob_;
357         //printf("%2d %2d %2d", q_, gob, mba % mbs_per_gob_);
358         /* code the macroblock */
359         bits += H263dctMbEncodeIFrame(mx, my, q_, pict, decPict, bs, modQuant_);
360 
361         if (quantReset) {
362             H263initQuantTables(q_);
363             quantInit = q_;
364             quantReset = 0;
365         }
366 
367         mx += MACROBLOCK_SIZE;
368         if (mx >= pict->w) {
369             my += MACROBLOCK_SIZE;
370             mx = 0;
371         }
372 
373         mba++;
374         if ((mba % mbs_per_gob_) == 0) {
375             gob++;
376         }
377     }
378 
379 #if 0
380       printf("encode: I-Frame (%d bits)\n", bits);
381 #endif
382 
383   return(bits);
384 }
385 
386 /* This function encodes an INTER frame and returns number of bits*/
387 int
388 H263Encoder::encodePframe(int codingTime, int t, int gfid,
389     Picture *pict, Picture *prevPict, Picture *prevDecPict, Picture *decPict, 
390     Bitstr *bs, int *mbInd, int *mbQuant, MVField *mvField, 
391     const u_int8_t *crvec)
392 {
393     int bits = 0;
394     int gob = 0;
395     int mba = 0;
396     int mx = 0;
397     int my = 0;
398     int nibs = 0;
399     int nsbs = 0;
400     
401     /* Init quant tables */
402     if (q_ != quantInit) {
403         H263initQuantTables(q_);
404         quantInit = q_;
405     }
406 
407     if (!mbInd || !mbQuant || !mvField) {
408         fprintf(stderr, "encodePframe: missing mbInd, mbQuant, or mvField.\n");
409         return (0);
410     }
411     
412     while (mba < nmbs_) {
413 
414         /* init variables to do coding */
415         mbInd[mba] = bs->ind;
416         mbQuant[mba] = q_;
417 
418         if ((mba % mbs_per_gob_) == 0) {
419             bits += ByteAlign(bs);
420 
421             /* send picture/GOB header */
422             if (mba == 0) {
423                 bits += H263putPictureHeader(
424                     t, src_fmt_, PICTURE_CODING_TYPE_INTER, q_, modQuant_,
425                     pict->w, pict->h, bs);
426             } else {
427                 bits += H263putGOBHeader(gob, gfid, q_, bs);
428             }
429 
430             /* first MB in GOB => reset MV */
431             ResetMVector(mbstruct_->pv[0]);
432             ResetMVector(mbstruct_->mv[0]);
433             mbstruct_->quant = q_;
434         }
435 
436         u_int s = crvec[mba];
437         if ((s & CR_SEND) != 0) { /* send the block */
438             nibs++;
439             //printf(" C");
440             mbstruct_->type = MODE_INTRA;
441             bits += H263dctMbEncodePFrame(
442                     mx, my, mbstruct_, codingTime, pict, decPict, bs, modQuant_);
443         } else { /* don't send the block */
444             nsbs++;
445             //printf(" S");
446             mbstruct_->type = MODE_UNCODED;
447             CopyMacroBlockPicture(mx, my, prevPict, decPict);
448             PutBitX(1, bs);
449             bits += 1;
450         }
451         /* Store motion vector predictor for next macroblock */
452         CopyMVector(mbstruct_->mv[0], mbstruct_->pv[0]);
453 
454         mx += MACROBLOCK_SIZE;
455         if (mx >= pict->w) {
456             my += MACROBLOCK_SIZE;
457             mx = 0;
458         }
459 
460         mba++;
461         if ((mba % mbs_per_gob_) == 0) {
462             gob++;
463         }
464     }
465 
466 #if 0
467     printf("encode: P-Frame (%d bits, %d i-blocks, %d skip blocks)\n", 
468             bits, nibs, nsbs);
469 #endif
470         
471     return(bits);
472 }
473 
474 void dumprtp(pktbuf *pb) {
475     int i;
476 
477     for(i=0; i<pb->len; i++){
478         printf("%2x ", pb->data[i]);
479         if (i % 8 == 7)
480             printf("\n");
481     }
482     printf("\n");
483 }
484 
485 /*
486  * H263Encoder::encode()
487  *
488  * Main interface function to VIC is called for every grabbed frame.
489  * Encodes the frames into h.263, packetizes them according to RFC 2190 and
490  * sends the RTP packets using the RTP network layer of VIC.
491  *
492  * Returns number of sent bytes.
493  */
494 int H263Encoder::encode(const VideoFrame* vf, const u_int8_t *crvec)
495 {
496     YuvFrame*    yuv = (YuvFrame*)vf; /* real YUV Frame */
497     Picture      thispic;             /* current image */
498     Picture      tmppict;             /* temporary picture */
499     u_int        xfps,kbps;           /* parameter from Tcl */
500     int          i;
501     u_int        sentbytes=0;         /* sent bytes in this consume */
502     static int   gfid = -1;
503     static int   frame_num = 1;
504     u_int        w, h;
505     Tcl&         tcl = Tcl::instance();
506     pktbuf*      pb;
507     rtphdr*      rh;
508     
509     w = yuv->width_;
510     h = yuv->height_;
511     
512     /* did we the size of the grabbed frame change? */
513     if (w!=lastw_ || h!=lasth_) {
514         gfid++;
515         /* readjust structures, temp. arrays, et.al. */
516         delete[] oldpic_.y;
517         delete[] oldorigpic_.y;
518         delete[] decpict_.y;
519         
520         free(mvfield_.mx);
521         free(mvfield_.my);
522         free(mvfield_.mode);
523         
524         oldpic_.w = w;
525         oldpic_.h = h;
526         oldpic_.y = new Byte[w*h*3/2];
527         oldpic_.u = oldpic_.y+w*h;
528         oldpic_.v = oldpic_.u+w*h/4;
529         
530         oldorigpic_.w = w;oldpic_.h = h;
531         oldorigpic_.y = new Byte[w*h*3/2];
532         oldorigpic_.u = oldorigpic_.y+w*h;
533         oldorigpic_.v = oldorigpic_.u+w*h/4;
534         
535         decpict_.w = w;
536         decpict_.h = h;
537         decpict_.y = new Byte[w*h*3/2];
538         decpict_.u = decpict_.y+w*h;
539         decpict_.v = decpict_.u+w*h/4;
540         
541         mvfield_.mx = (short*)malloc(nmbs_*sizeof(short));
542         mvfield_.my = (short*)malloc(nmbs_*sizeof(short));
543         mvfield_.mode = (short*)malloc(nmbs_*sizeof(short));
544         mvfield_.w = mbs_per_gob_;
545         mvfield_.h = gobs_per_frame_;
546         nexttype_ = PICTURE_CODING_TYPE_INTRA;
547         lastw_ = w;
548         lasth_ = h;
549         free(mbind_);
550         free(mbquant_);
551         mbind_=(int*)malloc((nmbs_+1)*sizeof(int));
552         mbquant_=(int*)malloc(nmbs_*sizeof(int));
553     }
554 
555     /* HACK: We query the Tcl layers for the specified bps and fps values.
556     * Hack due to the fact, that no other encoder uses this values in this
557     * way and we could get feedback loops from the network code (who uses
558     * them). Bummer.
559     */
560     tcl.evalc("$fps_slider get");sscanf(tcl.result(),"%d",&xfps); 
561     tcl.evalc("$bps_slider get");sscanf(tcl.result(),"%d",&kbps);
562     dist_iframes_ = 15 * xfps;
563     
564     /* calculate target bits/frame */
565     target_bps_ = kbps/xfps;    
566     
567     /* temporary picture from passed YUV Frame */
568     thispic.w = w;
569     thispic.h = h;
570     thispic.y = (Byte*)yuv->bp_;
571     thispic.u = (Byte*)yuv->bp_+w*h;
572     thispic.v = (Byte*)yuv->bp_+w*h+(w*h)/4;
573     
574     /* Bitstream starts at 0 and mark end */
575     bitstr_.ind = 0;
576     bitstr_.b[bitstr_.size/8-1] = 0x42;
577     
578     switch (nexttype_) {
579     case PICTURE_CODING_TYPE_INTRA:
580         ifn_++; pfn_=0;
581         encodeIframe(codingtime_, (int)vf->ts_, gfid, &thispic, &decpict_,
582             &bitstr_, mbind_, mbquant_, &mvfield_);
583         /* change the next line to turn on/off inter frame coding */
584         nexttype_ = PICTURE_CODING_TYPE_INTER;
585         //nexttype_ = PICTURE_CODING_TYPE_INTRA;
586         frame_num = 1;
587         break;
588 
589     case PICTURE_CODING_TYPE_INTER:
590         pfn_++;
591         encodePframe(codingtime_, (int)vf->ts_, gfid, &thispic,
592             &oldpic_, &oldorigpic_, &decpict_, &bitstr_, 
593             mbind_, mbquant_, &mvfield_, crvec);
594         if (frame_num++ == dist_iframes_) {
595             nexttype_ = PICTURE_CODING_TYPE_INTRA;
596         }
597         break;
598 
599     default: 
600         fprintf(stderr, "Illegal picture coding type %d\n", nexttype_);
601         break;
602     }
603 
604     tmppict = oldpic_; oldpic_ = decpict_; decpict_ = tmppict;
605     memcpy(oldorigpic_.y,thispic.y,w*h*3/2);
606     
607     if (bitstr_.ind >= bitstr_.size) {
608         fprintf(stderr, "H263 encoder internal buffer overflow.");
609         fprintf(stderr, 
610             "Buffer size is %d bits and encoder generated %d bits.\n", 
611             bitstr_.size, bitstr_.ind);
612         abort();
613     }
614     assert(bitstr_.b[bitstr_.size/8-1] == 0x42);
615     
616     /* mark the end of the bitstream */
617     mbind_[nmbs_] = bitstr_.ind;
618     
619     /* The actual splitfunction */
620     h263_rtp_packet    *packets = NULL;
621     int nrofpackets = split_h263stream(
622         rtpFmt_,            /* [in] what payload format? */
623         bitstr_.b,          /* [in] bitstream */
624         bitstr_.ind,        /* [in] length in bits*/
625         gobs_per_frame_,
626         mbs_per_gob_,
627         mbind_,
628         mbquant_,
629         mvfield_,
630         yuv->ts_,           /* [in] timestamp */
631         mtu_,               /* [in] current MTU */
632         &packets            /* [out] packets... */
633         );
634 
635     /* 
636      * And now we send the packets...
637      * We use the 2 standard iov buffers, buffer 1 just for the RTP header,
638      * buffer 2 for the H263 payloadheader and the h.263 bits.
639      * Reason for this is that the VIC decoder structure does not 
640      * like differently sized headers and acts differently between loopback
641      * and network-in decoding.
642      */
643     for (i=0;i<nrofpackets;i++) {
644         pb = pool_->alloc(yuv->ts_,RTP_PT_H263);
645         rh = (rtphdr*)pb->data;
646         
647         memcpy(&pb->data[sizeof(rtphdr)],packets[i].header,
648                 packets[i].headersize);
649         memcpy(&pb->data[sizeof(rtphdr)]+packets[i].headersize,
650                 packets[i].data,packets[i].datasize);
651         pb->len = sizeof(rtphdr) + packets[i].datasize+packets[i].headersize;
652         
653         // mark the last packet 
654         if (i==nrofpackets-1)
655             rh->rh_flags |= htons(RTP_M);
656         // sending ...  
657         target_->recv(pb);
658         sentbytes+=packets[i].headersize+packets[i].datasize+sizeof(rtphdr);
659     }
660     free(packets);
661     nb_ += sentbytes;
662     return sentbytes;
663 }
664 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.