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

Open Mash Cross Reference
mash/codec/decoder-h261v1.cc

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

  1 /*
  2  * decoder-h261v1.cc --
  3  *
  4  *      H.261 v1 decoder object source code
  5  *
  6  * Copyright (c) 1993-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 static const char rcsid[] =
 35     "@(#) $Header: /usr/mash/src/repository/mash/mash-1/codec/decoder-h261v1.cc,v 1.15 2003/11/19 19:20:17 aswan Exp $";
 36 
 37 #include <stdio.h>
 38 #include <stdlib.h>
 39 #include <string.h>
 40 #include "rtp/inet.h"
 41 #include "rtp/rtp.h"
 42 #include "codec/decoder.h"
 43 #include "codec/p64/p64.h"
 44 #include "net/pktbuf.h"
 45 
 46 class RTPv1H261Decoder : public Decoder {
 47 public:
 48         RTPv1H261Decoder();
 49         ~RTPv1H261Decoder();
 50         int colorhist(u_int* hist) const;
 51         virtual void recv(pktbuf*);
 52         void stats(char* wrk);
 53 protected:
 54         const u_char* reassemble(const u_char* bp, int& cc, u_int& seqno,
 55                                  u_int& flags);
 56         virtual void redraw();
 57 
 58         u_short seqno_;         /* last rtp seqno */
 59         /*
 60          * Reassembly buffer 'slots' for resequencing & reassembling
 61          * gobs split across packet boundaries.
 62          */
 63 #define H261_SLOTS 64
 64 #define H261_SLOTMASK (H261_SLOTS - 1)
 65         static u_char* wrkbuf_;
 66         static u_int wrkbuflen_;
 67         int packetsize_;        /* max size of gob fragments */
 68         struct slot {
 69                 int len;
 70                 u_short flags;
 71                 u_short seqno;
 72                 u_char* bp;
 73                 int pad;
 74         } slot_[H261_SLOTS];
 75         u_char* slotbuf_;
 76 
 77         P64Decoder* codec_;
 78 };
 79 
 80 static class RTPv1H261DecoderClass : public TclClass {
 81 public:
 82         RTPv1H261DecoderClass() : TclClass("Module/VideoDecoder/H261v1") {}
 83         TclObject* create(int /* argc */, const char*const* /* argv */) {
 84                 return (new RTPv1H261Decoder);
 85         };
 86 } dm_h261v1;
 87 
 88 #define STAT_BAD_PSC    0
 89 #define STAT_BAD_GOB    1
 90 #define STAT_BAD_SYNTAX 2
 91 #define STAT_BAD_FMT    3
 92 #define STAT_BAD_SIZE   4       /* packet dropped for unsupported fmt */
 93 #define STAT_BAD_BITOFF 5       /* unexpected non-zero sbits or ebits */
 94 #define STAT_SIZE_CHANGE 6      /* packet dropped because frag size changed */
 95 #define STAT_FMT_CHANGE 7       /* # times fmt changed */
 96 
 97 u_char* RTPv1H261Decoder::wrkbuf_;
 98 u_int RTPv1H261Decoder::wrkbuflen_;
 99 
100 RTPv1H261Decoder::RTPv1H261Decoder() : Decoder(2)
101 {
102         stat_[STAT_BAD_PSC].name = "Bad-PSC";
103         stat_[STAT_BAD_GOB].name = "Bad-GOB";
104         stat_[STAT_BAD_SYNTAX].name = "Bad-Syntax";
105         stat_[STAT_BAD_FMT].name = "Bad-fmt";
106         stat_[STAT_BAD_SIZE].name = "Bad-size";
107         stat_[STAT_BAD_BITOFF].name = "Bad-bitoff";
108         stat_[STAT_SIZE_CHANGE].name = "Size-change";
109         stat_[STAT_FMT_CHANGE].name = "Fmt-change";
110         nstat_ = 8;
111 
112         /* cause a resize trigger later */
113         inw_ = 0;
114         inh_ = 0;
115         csss_ = 420;
116         seqno_ = 0;
117         packetsize_ = 0;
118         for (int i = 0; i < H261_SLOTS; ++i) {
119                 slot_[i].len = 0;
120                 slot_[i].flags = 0;
121                 slot_[i].seqno = 0;
122                 slot_[i].bp = 0;
123         }
124         slotbuf_ = 0;
125         codec_ = new FullP64Decoder();
126         resize(codec_->width(), codec_->height());
127         codec_->marks(rvts_);
128 }
129 
130 RTPv1H261Decoder::~RTPv1H261Decoder()
131 {
132         delete slotbuf_;
133         delete codec_;
134 }
135 
136 void RTPv1H261Decoder::stats(char* wrk)
137 {
138         /* pull stats out of vic indepdendent P64Decoder */
139         setstat(STAT_BAD_PSC, codec_->bad_psc());
140         setstat(STAT_BAD_GOB, codec_->bad_GOBno());
141         setstat(STAT_BAD_SYNTAX, codec_->bad_bits());
142         setstat(STAT_BAD_FMT, codec_->bad_fmt());
143         Decoder::stats(wrk);
144 }
145 
146 /*
147  * Packets waiting for reassembly are kept in 'slots'
148  * indexed by the low bits of the sequence number.
149  * To try to avoid copying packets twice, we assume
150  * that the packet source is breaking packets at some
151  * fixed, max size (which we can determine from the size
152  * of a packet with the SOG marker) and we allocate the buffer
153  * for slots to be this size.  As long as a packet doesn't
154  * wrap, this should make the final packets contiguous.
155  */
156 inline const u_char*
157 RTPv1H261Decoder::reassemble(const u_char* bp, int& cc,
158                          u_int& rseqno, u_int& rflags)
159 {
160         register int flags = rflags;
161         /* FIXME if the packet is complete just render it */
162         if ((flags & 0x88) == 0x88)
163                 return (bp);
164 
165         register u_int seqno = rseqno;
166         if (packetsize_ != cc) {
167                 if (packetsize_ == 0) {
168                         if ((flags & 0x80) == 0)
169                                 return (0);
170                         packetsize_ = cc;
171                         u_int len = cc * H261_SLOTS;
172                         slotbuf_ = new u_char[len+4];
173                         u_char* bp = slotbuf_ + 4;
174                         for (int i = 0; i < H261_SLOTS; ++i) {
175                                 slot_[i].bp = bp;
176                                 bp += cc;
177                         }
178                         if (len > wrkbuflen_) {
179                                 delete wrkbuf_;
180                                 wrkbuf_ = new u_char[len+4];
181                                 wrkbuflen_ = len;
182                         }
183                 } else if ((flags & 0x08) == 0 || cc > packetsize_) {
184                         count(STAT_SIZE_CHANGE);
185                         delete slotbuf_;
186                         slotbuf_ = 0;
187                         packetsize_ = 0;
188                         for (int i = 0; i < H261_SLOTS; ++i) {
189                                 slot_[i].len = 0;
190                                 slot_[i].flags = 0;
191                                 slot_[i].seqno = 0;
192                                 slot_[i].bp = 0;
193                         }
194                         return (0);
195                 }
196         }
197         register u_int l = seqno & H261_SLOTMASK;
198 
199         slot_[l].len = cc;
200         slot_[l].seqno = seqno;
201         slot_[l].flags = flags;
202         memcpy((char*)slot_[l].bp, (char*)bp, cc);
203 
204         /*
205          * Don't bother trying to reassemble packet unless it
206          * has an EOG marker or we have the next packet.
207          */
208         if ((flags & 0x08) == 0 &&
209             ((seqno + 1) & 0xffff) !=
210             slot_[(l + 1) & H261_SLOTMASK].seqno)
211                 return (0);
212 
213         /* scan backward for BOG */
214         register u_int pseq = seqno;
215         register u_int f = l;
216         while ((slot_[f].flags & 0x80) == 0) {
217                 pseq = (pseq - 1) & 0xffff;
218                 f = pseq & H261_SLOTMASK;
219                 if (slot_[f].seqno != pseq)
220                         /* packet missing */
221                         return (0);
222         }
223 
224         /* scan forward for EOG */
225         while ((slot_[l].flags & 0x08) == 0) {
226                 seqno = (seqno + 1) & 0xffff;
227                 l = seqno & H261_SLOTMASK;
228                 if (slot_[l].seqno != seqno)
229                         /* packet missing */
230                         return (0);
231         }
232 
233         if (l < f) {
234                 /* packet wraps around buffer, have to copy it */
235                 u_char* wp = wrkbuf_ + 4;
236                 register u_int i = f - 1;
237                 do {
238                         i = (i + 1) & H261_SLOTMASK;
239                         register int slen = slot_[i].len;
240                         memcpy((char*)wp, (char*)slot_[i].bp, slen);
241                         wp += slen;
242                 } while (i != l);
243                 bp = wrkbuf_ + 4;
244                 cc = wp - bp;
245         } else {
246                 bp = slot_[f].bp;
247                 cc = slot_[l].bp - bp + slot_[l].len;
248         }
249 
250         /*
251          * At this point, all we care about is ebit and sbit.
252          */
253         flags = slot_[f].flags & 0x70;
254         flags |= slot_[l].flags & 0x07;
255         rflags = flags;
256         rseqno = seqno;
257 
258         return (bp);
259 }
260 
261 void RTPv1H261Decoder::recv(pktbuf* pb)
262 {
263         rtphdr* rh = (rtphdr*)pb->dp;
264         u_int8_t* vh = (u_int8_t*)(rh + 1);
265         /*
266          * if the packet has a non-zero sbit but no SOG or
267          * a non-zero ebit but no EOG, toss it.
268          * if the packet contains both start & end gobs we can
269          * just render it.  Otherwise we wait until we get the
270          * start and end markers and all the packets in between.
271          */
272         u_int v = ntohs(*(u_int16_t*)vh);
273         u_int flags = v >> 8;
274         if (((flags & 0x70) != 0 && (flags & 0x80) == 0) ||
275             ((flags & 0x07) != 0 && (flags & 0x08) == 0)) {
276                 count(STAT_BAD_BITOFF);
277                 return;
278         }
279 
280         int cc = pb->len - (sizeof(*rh) + 2);
281         const u_int8_t* bp = vh + 2;
282         u_int seqno = ntohs(rh->rh_seqno);
283         bp = reassemble(bp, cc, seqno, flags);
284         if (bp == 0)
285                 return;
286 
287         int sbit = (flags >> 4) & 7;
288         int ebit = flags & 7;
289 
290         /* FIXME tack on the start code */
291         /*FIXME*/
292         cc += 2;
293         bp -= 2;
294         ((u_char*)bp)[0] = 0;
295         if (sbit == 0)
296                 ((u_char*)bp)[1] = 1;
297         else {
298                 ((u_char*)bp)[1] = 0;
299                 ((u_char*)bp)[2] |= 0x100 >> sbit;
300         }
301 
302         codec_->mark(now_);
303         (void)codec_->decode(bp, cc, sbit, ebit, 0, 0, 0, 0, 0);
304         /*
305          * If the stream changes format, issue a resize.
306          */
307         if (codec_->width() != inw_) {
308                 count(STAT_FMT_CHANGE);
309                 resize(codec_->width(), codec_->height());
310                 codec_->marks(rvts_);
311         }
312 
313         /*FIXME*/
314         if (ntohs(rh->rh_flags) & RTP_M) {
315                 codec_->sync();
316                 ndblk_ = codec_->ndblk();
317                 render_frame(codec_->frame());
318                 codec_->resetndblk();
319         }
320         pb->release();
321 }
322 
323 int RTPv1H261Decoder::colorhist(u_int* hist) const
324 {
325         const u_char* frm = codec_->frame();
326         int w = inw_;
327         int h = inh_;
328         int s = w * h;
329         colorhist_420_556(hist, frm, frm + s, frm + s + (s >> 2), w, h);
330         return (1);
331 }
332 
333 void RTPv1H261Decoder::redraw()
334 {
335         if (codec_ != 0)
336                 Decoder::redraw(codec_->frame());
337 }
338 

~ [ 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.