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

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

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

  1 /*
  2  * decoder-h263.cc --
  3  *
  4  *      Source code for H.263 video decoder object.
  5  *
  6  * Copyright (c) 2002-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 
 35 #include <stdio.h>
 36 #include <stdlib.h>
 37 #include <string.h>
 38 #include "rtp/inet.h"
 39 #include "rtp/rtp.h"
 40 #include "codec/decoder.h"
 41 #include "render/renderer.h"
 42 #include "net/pktbuf.h"
 43 #include "codec/postdct.h"
 44 #include "codec/h263/h263-decoder.h"
 45 
 46 #include "codec/decoder-h263.h"
 47 
 48 
 49 static class H263DecoderClass : public TclClass {
 50 public:
 51     H263DecoderClass() : TclClass("Module/VideoDecoder/H263") {}
 52     TclObject* create(int /* argc */, const char*const* /* argv */) {
 53         return (new H263Decoder);
 54     };
 55 } dm_h263;
 56 
 57 
 58 
 59 #define DUMP_INFO 0
 60 
 61 
 62 #define STAT_BAD_PSC    0
 63 #define STAT_BAD_GOB    1
 64 #define STAT_BAD_SYNTAX 2
 65 #define STAT_BAD_FMT    3
 66 #define STAT_FMT_CHANGE 4    /* # times fmt changed */
 67 #define STAT_BAD_HEADER 5
 68 
 69 // this variable contains a file where debugging output can be written.
 70 FILE *debugFile;
 71 
 72 H263Decoder::H263Decoder() : Decoder(4), codec_(0), last_seqno_(0)
 73 {
 74         //debugFile = fopen("dbg", "w");
 75         debugFile = 0; // shut the compiler up!
 76 
 77     stat_[STAT_BAD_PSC].name = "H263-Bad-PSC";
 78     stat_[STAT_BAD_GOB].name = "H263-Bad-GOB";
 79     stat_[STAT_BAD_SYNTAX].name = "H263-Bad-Syntax";
 80     stat_[STAT_BAD_FMT].name = "H263-Bad-fmt";
 81     stat_[STAT_FMT_CHANGE].name = "H263-Fmt-change";
 82     stat_[STAT_BAD_HEADER].name = "H263-Bad-Header";
 83     nstat_ = 6;
 84     csss_ = 420;
 85 
 86     /*
 87      * Assume CIF.  Picture header will trigger a resize if
 88      * we encounter a different size.
 89      */
 90     inw_ = 352;
 91     inh_ = 288;
 92     resize(inw_, inh_);
 93 }
 94 
 95 H263Decoder::~H263Decoder()
 96 {
 97     delete codec_;
 98 }
 99 
100 void H263Decoder::info(char* wrk) const
101 {
102     if (codec_ == 0)
103         *wrk = 0;
104     else
105         sprintf(wrk, "[q=%d]", codec_->qtidx());
106 }
107 
108 void H263Decoder::stats(char* wrk)
109 {
110     /* pull stats out of vic independent of decoder */
111     setstat(STAT_BAD_PSC, codec_->bad_psc());
112     setstat(STAT_BAD_GOB, codec_->bad_GOBno());
113     setstat(STAT_BAD_SYNTAX, codec_->bad_bits());
114     setstat(STAT_BAD_FMT, codec_->bad_fmt());
115     Decoder::stats(wrk);
116 }
117 
118 int H263Decoder::colorhist(u_int* hist) const
119 {
120     const u_char* frm = codec_->frame();
121     int w = inw_;
122     int h = inh_;
123     int s = w * h;
124     colorhist_420_556(hist, frm, frm + s, frm + s + (s >> 2), w, h);
125     return (1);
126 }
127 
128 
129 #ifdef CR_STATS
130 u_char shadow[640*480/64];
131 
132 void dumpShadow(u_int32_t ts, u_char* p, int nblk)
133 {
134     ts &= 0x7fffffff;
135     static u_int32_t lastTS = 0;
136     if (ts != lastTS) {
137         printf("ts %u\n", ts);
138         lastTS = ts;
139     }
140     int left = -1;
141     for (int i = 0; i < nblk; ++i) {
142         if (shadow[i] != p[i]) {
143             if (left < 0) {
144                 left = i;
145             }
146         } else {
147             if (left > 0)
148                 printf("b %d %d\n", left, i - 1);
149             left = -1;
150         }
151     }
152     if (left > 0)
153         printf("b %d %d\n", left, i - 1);
154 }
155 #endif
156 
157 extern void dumprtp(pktbuf* pb);
158 int npkts = 0;
159 
160 void H263Decoder::recv(pktbuf* pb)
161 {
162     rtphdr* rh = (rtphdr*)pb->dp;           /* RTP header */
163     u_int16_t seqno = ntohs(rh->rh_seqno);  /* RTP sequence number */
164     u_int8_t* vh = (u_int8_t*)(rh + 1);     /* video header */
165     int vhsize;                             /* video header size */
166     int fflag, pflag, sbit, ebit, src;
167     int iflag, uflag, sflag, aflag;
168     int dbq, trb, tr, quant, gob, mba, mvdh1, mvdv1, mvdh2, mvdv2;
169 
170         npkts++;
171 
172     if (codec_ == 0) {
173         codec_ = new H263BitstreamDecoder();
174         codec_->marks(rvts_);
175 #if 0
176                 // open the debug file and write a timestamp
177                 unsigned long tval;
178                 tval = time(NULL);
179                 fprintf(debugFile, "# Debug dump - %s\n",
180                                 ctime(((const long *)&tval)));
181 #endif
182     }
183         //printf(".%s", (((npkts % 25) == 0) ? "\n" : ""));
184 
185 #ifdef CR_STATS
186     memcpy(shadow, rvts_, nblk_);
187 #endif
188 
189     fflag = vh[0] >> 7;
190     pflag = (vh[0] >> 6) & 0x01;
191     sbit = (vh[0] >> 3) & 0x07;
192     ebit = vh[0] & 0x07;
193     src = vh[1] >> 5;
194 
195     if (!fflag) {
196         /* Mode A packet */
197 
198         vhsize = 4;
199         iflag = (vh[1] >> 4) & 0x01;
200         uflag = (vh[1] >> 3) & 0x01;
201         sflag = (vh[1] >> 2) & 0x01;
202         aflag = (vh[1] >> 1) & 0x01;
203         dbq = (vh[2] >> 3) & 0x03;
204         trb = vh[2] & 0x07;
205         tr = vh[3];
206 
207 #if 0
208                 if (true) {
209                         fprintf(debugFile,"\n  'A' Pckt %d received (I%d:P%d, F#=%d) %s\n",
210                                         npkts, codec_->ifn_, codec_->pfn_, codec_->fn_,
211                                         (ntohs(rh->rh_flags) & RTP_M ? "last pkt in frame" : ""));
212                         fprintf(debugFile,
213                                         "  seqno=%d fflag=0x%x pflag=0x%x sbit=0x%x ebit=0x%x src=0x%x\n",
214                                         seqno, fflag, pflag, sbit, ebit, src);
215                         fprintf(debugFile,"  iflag=0x%x uflag=0x%x sflag=0x%x aflag=0x%x\n",
216                                         iflag, uflag, sflag, aflag);
217                         fprintf(debugFile,"  dbq=0x%x trb=0x%x tr=0x%x\n",
218                                         dbq, trb, tr);
219                         fprintf(debugFile,"  pkt begins:");
220                         for (int k=0; k<10; k++) {
221                                 fprintf(debugFile, " 0x%x%x", (vh[4+k] >> 4), (vh[4+k] & 0x0f));
222                         }
223                         fprintf(debugFile, "\n");
224                 }
225 #endif
226 
227         quant = 0;
228         mba = 0;
229                 mvdh1 = 0;
230                 mvdv1 = 0;
231                 mvdh2 = 0;
232                 mvdv2 = 0;
233 
234         /* PB-frame? */
235         if (pflag) {
236                         printf("PB Frame - not supported\n");
237                 pb->release();
238                 return;
239         }
240 
241         /*
242          * Mode A packets don't contain a GOB number so we tell the codec
243          * whether or not the previous packet was received.
244          */
245         if (seqno == last_seqno_ + 1) {
246 
247             /* The previous packet was received */
248 
249             gob = SEQUENTIAL_PACKET;
250         } else {
251 
252             /* The previous packet was not received */
253 
254             gob = NONSEQUENTIAL_PACKET;
255         }
256 
257     } else if (!pflag) {
258         /* Mode B packet */
259         u_int32_t v = ntohl(*(u_int32_t*)vh);
260 
261         vhsize = 8;
262         quant = (v >> 16) & 0x1F;
263         gob = (v >> 11) & 0x1F;
264         mba = (v >> 2) & 0x1FF;
265         iflag = (vh[4] >> 7) & 0x01;
266         uflag = (vh[4] >> 6) & 0x01;
267         sflag = (vh[4] >> 5) & 0x01;
268         aflag = (vh[4] >> 4) & 0x01;
269         v = ntohl(*(u_int32_t*)&vh[4]);
270         mvdh1 = (v >> 21) & 0x7F;
271         mvdv1 = (v >> 14) & 0x7F;
272         mvdh2 = (v >> 7) & 0x7F;
273         mvdv2 = v & 0x7F;
274 
275 #if 0
276                 if ((codec_->fn_ <= 53)) {
277                         fprintf(debugFile,"'B' Pckt %d received (I%d:P%d, F#=%d) %s...\n",
278                                         npkts, codec_->ifn_, codec_->pfn_, codec_->fn_,
279                                         (ntohs(rh->rh_flags) & RTP_M ? "last pkt in frame" : ""));
280                         fprintf(debugFile,
281                                         "  seqno=%d gob=%d mba=%d mvdh1=%d mvdv1=%d mvdh2=%d mvdv2=%d\n",
282                                         seqno, gob, mba, mvdh1, mvdv1, mvdh2, mvdv2);
283                 }
284 #endif
285         /*
286          * Mode B packets from UCL vic always contain the same GOB number.  We
287          * work around this bug by treating these packets like mode A packets.
288          */
289         if (gob == codec_->ngob() - 1) {
290             if (seqno == last_seqno_ + 1) {
291                 gob = SEQUENTIAL_PACKET; // Previous packet received
292             } else {
293                 gob = NONSEQUENTIAL_PACKET; // Previous packet not received
294             }
295         }
296     } else {
297         /* Mode C packet */
298         u_int32_t v = ntohl(*(u_int32_t*)vh);
299 
300         vhsize = 12;
301         quant = (v >> 16) & 0x1F;
302         gob = (v >> 11) & 0x1F;
303         mba = (v >> 2) & 0x1FF;
304         iflag = (vh[4] >> 7) & 0x01;
305         uflag = (vh[4] >> 6) & 0x01;
306         sflag = (vh[4] >> 5) & 0x01;
307         aflag = (vh[4] >> 4) & 0x01;
308         v = ntohl(*(u_int32_t*)&vh[4]);
309         mvdh1 = (v >> 21) & 0x7F;
310         mvdv1 = (v >> 14) & 0x7F;
311         mvdh2 = (v >> 7) & 0x7F;
312         mvdv2 = v & 0x7F;
313         dbq = (vh[10] >> 3) & 0x03;
314         trb = vh[10] & 0x07;
315         tr = vh[11];
316 
317 #if 0
318                 if ((codec_->fn_ <= 53)) {
319                         fprintf(debugFile,"'C' Pckt %d received (I%d:P%d, F#=%d) %s...\n",
320                                         npkts, codec_->ifn_, codec_->pfn_, codec_->fn_,
321                                         (ntohs(rh->rh_flags) & RTP_M ? "last pkt in frame" : ""));
322                         fprintf(debugFile,
323                                         "  seqno=%d gob=%d mba=%d mvdh1=%d mvdv1=%d mvdh2=%d mvdv2=%d\n",
324                                         seqno, gob, mba, mvdh1, mvdv1, mvdh2, mvdv2);
325                 }
326 #endif
327         }
328 
329     last_seqno_ = seqno;
330 
331     if (gob > MAX_NUM_GOBS) {
332         printf("bad gob value received\n"); 
333         count(STAT_BAD_HEADER);
334         pb->release();
335         return;
336     }
337 
338     int cc = pb->len - (sizeof(*rh) + vhsize);
339     codec_->mark(now_);
340 
341     (void)codec_->decode(vh + vhsize, cc, sbit, ebit,
342         mba, gob, quant, mvdh1, mvdv1, mvdh2, mvdv2, fflag, pflag);
343 
344 #ifdef CR_STATS
345     dumpShadow(ntohl(rh->rh_ts), rvts_, nblk_);
346 #endif
347 
348     /* If the stream changes format, issue a resize */
349     if (codec_->width() != inw_) {
350                 //printf("H263 decoder: stream format change %d X %d => %d X %d\n",
351                 //inw_, inh_, codec_->width(), codec_->height());
352         resize(codec_->width(), codec_->height());
353         codec_->marks(rvts_);
354         count(STAT_FMT_CHANGE);
355     }
356 
357         // variables for frame dump code below
358         //int myfn, myifn, mypfn, mysize, mybw, mybytes;
359         //char myfile[128];
360         //FILE *myfp;
361 
362         /* If end of frame, then render it */
363     if (ntohs(rh->rh_flags) & RTP_M) {
364                 //printf("#recv'd=%d #dec'd=%d\n", npkts, codec_->npkts_);
365         codec_->sync();
366         ndblk_ = codec_->ndblk();
367 #if 0
368                 /*
369                  * This code will allow you to dump decoded images. 
370                  * Move this code to a method on Decoder.
371                  */
372         // move declarations out of if block
373                 myifn = codec_->ifn_;
374                 mypfn = codec_->pfn_;
375                 myfn = codec_->fn_;
376                 if (((myifn==1) && (mypfn==0)) ||
377                         ((myifn==1) && (mypfn>=50) && (mypfn<=80))) {
378                         // dump yuv frame
379                         sprintf(myfile, "vid.yuv/f%d.yuv", mypfn);
380                         if ((myfp=fopen(myfile, "wb")) == NULL) {
381                                 printf("Error openning file %d\n", errno);
382                         }
383                         //mysize = codec_->width_ * codec_->height_ 
384                         //+ codec->width_ * codec->height_ / 2;
385                         mysize = 152064;
386                         mybw = 0;
387                         while (mybw < mysize) {
388                                 mybytes = fwrite(codec_->frame() + mybw, sizeof(char), 
389                                                 mysize - mybw, myfp);
390                                 if (mybytes < 0) {
391                                         printf("bytes not written - abort\n");
392                                         abort();
393                                 }
394                                 mybw += mybytes;
395                         }
396                         fclose(myfp);
397                 }
398 #endif
399         render_frame(codec_->frame(), CODEC_H261, quant);
400 #if 0
401                 // print frame numbers to console window
402                 if ((codec_->fn_ % 25) == 0) {
403                         printf("%d (i=%d p=%d)\n", codec_->fn_, codec_->ifn_, codec_->pfn_);
404                 }
405 #endif
406                 codec_->dump_stats();
407                 codec_->reset_stats();
408         codec_->resetndblk();
409                 //npkts = 0;
410     }
411     pb->release();
412 }
413 
414 void H263Decoder::redraw()
415 {
416     if (codec_ != 0)
417         Decoder::redraw(codec_->frame());
418 }
419 

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