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

Open Mash Cross Reference
mash/codec/decoder.cc

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

  1 /*
  2  * decoder.cc --
  3  *
  4  *      Video Decoder class
  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.cc,v 1.29 2003/11/19 19:20:17 aswan Exp $";
 36 
 37 #include <stdio.h>
 38 #include <stdlib.h>
 39 #ifndef WIN32
 40 #include <sys/param.h>
 41 #endif
 42 #include "misc/sys-time.h"
 43 #include "rtp/inet.h"
 44 #include "rtp/rtp.h"
 45 #include "codec/decoder.h"
 46 #include "render/renderer.h"
 47 #include "render/color-hist.h"
 48 #include "codec/postdct.h"
 49 #include "misc/isblue_black.h"
 50 extern "C" {
 51 #ifdef USE_SHM
 52 #include <sys/ipc.h>
 53 #include <sys/shm.h>
 54 #if defined(sun) && !defined(__svr4__)
 55 int shmget(key_t, int, int);
 56 char *shmat(int, char*, int);
 57 int shmdt(char*);
 58 int shmctl(int, int, struct shmid_ds*);
 59 #endif
 60 #endif
 61 }
 62 
 63 Decoder::Decoder(int hdrlen) : PacketHandler(hdrlen),
 64         nstat_(0), color_(1), csss_(422), inw_(0), inh_(0),
 65         suppress_(0), engines_(0), rvts_(0), nblk_(0), ndblk_(0)
 66 {
 67         /*FIXME*/
 68         now_ = 1;
 69 
 70         for (int i = 0; i < MAXSTAT; ++i)
 71                 stat_[i].cnt = 0;
 72 }
 73 
 74 
 75 Decoder::~Decoder()
 76 {
 77         if (rvts_) delete[] rvts_;
 78 }
 79 
 80 int Decoder::command(int argc, const char*const* argv)
 81 {
 82         Tcl& tcl = Tcl::instance();
 83         if (argc == 2) {
 84                 if (strcmp(argv[1], "width") == 0) {
 85                         tcl.resultf("%d", width());
 86                         return (TCL_OK);
 87                 }
 88                 if (strcmp(argv[1], "height") == 0) {
 89                         tcl.resultf("%d", height());
 90                         return (TCL_OK);
 91                 }
 92                 if (strcmp(argv[1], "info") == 0) {
 93                         char* bp = tcl.buffer();
 94                         info(bp);
 95                         tcl.result(bp);
 96                         return (TCL_OK);
 97                 }
 98                 if (strcmp(argv[1], "stats") == 0) {
 99                         char* bp = tcl.buffer();
100                         tcl.result(bp);
101                         stats(bp);
102                         return (TCL_OK);
103                 }
104                 if (strcmp(argv[1], "csss") == 0) {
105                         tcl.resultf("%d", csss());
106                         return (TCL_OK);
107                 }
108                 if (strcmp(argv[1], "redraw") == 0) {
109                         redraw();
110                         return (TCL_OK);
111                 }
112                 if (strcmp(argv[1], "playout") == 0) {
113                         /*FIXME*/
114                         tcl.result("");
115                         return (TCL_OK);
116                 }
117         } else if (argc == 3) {
118                 if (strcmp(argv[1], "color") == 0) {
119                         setcolor(atoi(argv[2]));
120                         return (TCL_OK);
121                 }
122                 if (strcmp(argv[1], "suppress") == 0) {
123                         suppress_ = atoi(argv[2]);
124                         return (TCL_OK);
125                 }
126                 if (strcmp(argv[1], "attach") == 0) {
127                         Renderer* r = (Renderer*)TclObject::lookup(argv[2]);
128                         if (r == 0) {
129                                 tcl.resultf("%s attach: no such renderer: %s",
130                                             argv[0], argv[2]);
131                                 return (TCL_ERROR);
132                         }
133                         attach(r);
134                         return (TCL_OK);
135                 }
136                 if (strcmp(argv[1], "detach") == 0) {
137                         Renderer* r = (Renderer*)TclObject::lookup(argv[2]);
138                         if (r == 0) {
139                                 tcl.resultf("%s detach: no such target: %s",
140                                             argv[0], argv[2]);
141                                 return (TCL_ERROR);
142                         }
143                         return detach(r);
144                 }
145                 if (strcmp(argv[1], "histogram") == 0) {
146                         ColorHist* ch = ColorHist::lookup(argv[2]);
147                         if (ch == 0) {
148                                 tcl.resultf("%s histogram: no such histogram: %s",
149                                             argv[0], argv[2]);
150                                 return (TCL_ERROR);
151                         }
152                         colorhist(ch->histogram());
153                         return (TCL_OK);
154                 }
155         }
156         return (TclObject::command(argc, argv));
157 }
158 
159 void Decoder::info(char* wrk) const
160 {
161         *wrk = 0;
162 }
163 
164 void Decoder::stats(char* bp)
165 {
166         if (nstat_ == 0) {
167                 *bp = 0;
168                 return;
169         }
170         for (int i = 0; i < nstat_; ++i) {
171                 sprintf(bp, "%s %d ", stat_[i].name, stat_[i].cnt);
172                 bp += strlen(bp);
173         }
174         bp[-1] = 0;
175 }
176 
177 void Decoder::allocshm(dmabuf& d, int size, int flag)
178 {
179 #ifdef USE_SHM
180         d.shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0777);
181         if (d.shmid < 0) {
182                 perror("shmget");
183                 exit(1);
184         }
185         d.bp = (u_char *)shmat(d.shmid, 0, flag);
186         if (d.bp == (u_char*)-1) {
187                 perror("shmat");
188                 exit(1);
189         }
190 #endif
191 }
192 
193 /*FIXME not used*/
194 void Decoder::freeshm(dmabuf& d)
195 {
196 #ifdef USE_SHM
197         if (shmdt((char*)d.bp) < 0)
198                 perror("shmdt");
199 #endif
200 }
201 
202 /*
203  * Return time of day in microseconds.
204  */
205 double Decoder::gettimeofday()
206 {
207         timeval tv;
208         ::gettimeofday(&tv, 0);
209         return (1e6 * double(tv.tv_sec) + double(tv.tv_usec));
210 }
211 
212 void Decoder::attach(Renderer* r)
213 {
214         r->next_ = engines_;
215         engines_ = r;
216         r->setcolor(color_);
217         r->now(0);
218         redraw();
219 }
220 
221 void Decoder::redraw(const u_char* /* frm */)
222 {
223         /* make sure all the renderer's are synced */
224         now_ = 1;
225         memset(rvts_, 1, nblk_);
226         for (Renderer* p = engines_; p != 0; p = p->next_)
227                 p->now(0);
228 //      render_frame(frm);
229 }
230 
231 int Decoder::detach(Renderer* r)
232 {
233         Renderer** p;
234         for (p = &engines_; *p != r; p = &(*p)->next_)
235                 if (*p == 0)
236                         return TCL_ERROR;
237         *p = (*p)->next_;
238         return TCL_OK;
239 }
240 
241 void Decoder::colorhist_422_556(u_int* hist, const u_char* yp,
242                                         const u_char* up, const u_char* vp,
243                                         int width, int h) const
244 {
245         while (--h >= 0) {
246                 for (int w = width; w > 0; w -= 2) {
247                         /* 5V:5U:6Y */
248                         int uv = vp[0] >> 3 << 11 | up[0] >> 3 << 6;
249                         ++hist[uv | yp[0] >> 2];
250                         ++hist[uv | yp[1] >> 2];
251                         yp += 2;
252                         up += 1;
253                         vp += 1;
254                 }
255         }
256 }
257 
258 void Decoder::colorhist_411_556(u_int* hist, const u_char* yp,
259                                         const u_char* up, const u_char* vp,
260                                         int width, int h) const
261 {
262         while (--h >= 0) {
263                 for (int w = width; w > 0; w -= 4) {
264                         /* 5V:5U:6Y */
265                         int uv = vp[0] >> 3 << 11 | up[0] >> 3 << 6;
266                         ++hist[uv | yp[0] >> 2];
267                         ++hist[uv | yp[1] >> 2];
268                         ++hist[uv | yp[2] >> 2];
269                         ++hist[uv | yp[3] >> 2];
270                         yp += 4;
271                         up += 1;
272                         vp += 1;
273                 }
274         }
275 }
276 
277 void Decoder::colorhist_420_556(u_int* hist, const u_char* yp,
278                                         const u_char* up, const u_char* vp,
279                                         int width, int h) const
280 {
281         for (; h > 0; h -= 2) {
282                 for (int w = width; w > 0; w -= 2) {
283                         /* 5V:5U:6Y */
284                         int uv = vp[0] >> 3 << 11 | up[0] >> 3 << 6;
285                         ++hist[uv | yp[0] >> 2];
286                         ++hist[uv | yp[1] >> 2];
287                         ++hist[uv | yp[width] >> 2];
288                         ++hist[uv | yp[width + 1] >> 2];
289                         yp += 2;
290                         up += 1;
291                         vp += 1;
292                 }
293                 yp += width;
294         }
295 }
296 
297 void Decoder::render_frame(const u_char* frm)
298 {
299         render_frame(frm, CODEC_ANY, 0);
300 }
301 
302 void Decoder::render_frame(const u_char* frm, int codec, int quality)
303 {
304         //
305         // rvts_
306         //
307         // rvts_ is the Replenishment Vector of "TimeStamps" buffer, and it's 
308         //      composed of one byte per 8-pixel-wide, 8-pixel-high block. The 
309         //      purpose of carrying a replenishment vector in the decoder is to 
310         //      relieve the renderer of the task of refreshing the full video 
311         //      window if only a small number of blocks were updated by the source. 
312         //
313         // The structure is created by the main decoder object (Decoder::resize()), 
314         //      and is used by it, the particular decoder (e.g., H261Decoder and its 
315         //      implementation P64Decoder, where it's called marks_), and the 
316         //      Renderer. Every time the particular decoder decodes a block, it 
317         //      marks up the corresponding byte in the rvts_ with a commonly-agreed 
318         //      "timestamp" (check P64Decoder::decode_mb()). These timestamps have 
319         //      nothing in common with RTP timestamps (they are for sure 1-byte 
320         //      numbers).
321         //
322         // When the renderer receives the frame, it only renders those blocks 
323         //      whose timestamp is the current one. To avoid old blocks being 
324         //      rendered because they were updated 256 time ticks ago (and therefore 
325         //      whose timestamp coincides  with the current timestamp), 
326         //      Decoder::render_frame() takes care of adding one to those 
327         //      timestamps before permitting the particular decoder accessing to 
328         //      the structure. Therefore, the meaning of each table's value is the 
329         //      following: 
330         //
331         //      (now_ - rvts_[i]) mod 256 = how long ago was this block updated (255 
332         //                                  meaning 255 ticks or more)
333         //
334         // This decoder optimization only works for codecs where you can send 
335         //      only some blocks of a frame. I.e., it doesn't make sense for MJPEG.
336         //
337 
338         Renderer *p, *q;
339         long int engine_footprint, new_engine_footprint;
340 
341         // get the initial renderer list footprint
342         engine_footprint = 0;
343         for (p = engines_; p != 0; p = p->next_) {
344                 engine_footprint = engine_footprint ^ (long int)p;
345         }
346 
347         YuvFrame f(now_, (u_int8_t*)frm, rvts_, inw_, inh_, csss_);
348         //Fixme: A more elegant way to do figure out if an activeSource has
349         //been attached
350         if (suppress_) {
351             if (isBlue_Black(f.bp_, f.csss_, f.height_, f.width_, suppress_)) {
352                 mute_hide();
353                 return;
354             }
355             else {
356                 unhide();
357             }
358         }
359         for (p = engines_; p != 0; p = p->next_) {
360                 p->recv(&f, codec, quality);
361 
362                 // get the new renderer list footprint
363                 new_engine_footprint = 0;
364                 for (q = engines_; q != 0; q = q->next_) {
365                         new_engine_footprint = new_engine_footprint ^ (long int)q;
366                 }
367 
368                 // compare both footprints and exit if there were changes
369                 if (new_engine_footprint != engine_footprint) {
370                         // the renderer list has changed
371                         break;
372                 }
373         }
374 
375         // get the new timestamp
376         now_ = (now_ + 1) & 0xff;
377 
378         // actualize the replenishment vector (add one with saturation to 
379         //      the blocks whose timestamp coincides with the new timestamp)
380         u_char* ts = rvts_;
381         for (int k = nblk_; --k >= 0; ++ts) {
382                 if (*ts == now_) {
383                         *ts = (*ts + 1) & 0xff;
384                 }
385         }
386 }
387 
388 void Decoder::setcolor(int color)
389 {
390         if (color != color_) {
391                 color_ = color;
392                 for (Renderer* p = engines_; p != 0; p = p->next_)
393                         p->setcolor(color_);
394         }
395 }
396 
397 /*
398  * This method is called by a decoder (e.g., H261Decoder, etc.) when 
399  * the incoming packet stream changes sizes or when decoder is created.
400  * The tricky thing is that this points to an instance of the specific
401  * decoder, not to an instance of Decoder.  The method call on redraw()
402  * at the end of the method does not call Decoder::redraw(...) defined
403  * above - it actually calls the redraw routine for the specific decoder
404  * which in turn might call Decoder::redraw.
405  */
406 void Decoder::resize(int width, int height)
407 {
408         inw_ = width;
409         inh_ = height;
410         nblk_ = (width * height) / 64;
411         delete[] rvts_;
412         rvts_ = new u_char[nblk_];
413         memset(rvts_, 0, nblk_);
414         redraw();
415 }
416 
417 void Decoder::mute_hide() {
418         Tcl& tcl = Tcl::instance();
419         tcl.evalf("[%s set as_] mute-hide", name());
420 }
421        
422 void Decoder::unhide() {
423        Tcl& tcl = Tcl::instance();
424        tcl.evalf("[%s set as_] unhide", name());
425 }       
426 /*
427  * Dummy class for streams that we recognize but cannot decode (for lack
428  * of software support).  We still want to put all the stats etc. --
429  * especially the format -- but can't decode it.  FIXME We need to somehow
430  * mark the stream in the user-interface so that the user knows that
431  * vic cannot decode the stream (to avoid assuming something else is
432  * wrong with the tranmission)
433  */
434 class NullDecoder : public Decoder {
435 public:
436         NullDecoder() : Decoder(0) {}
437         int colorhist(u_int* /* histogram */) const { return (0); }
438         void redraw() {}
439         virtual void recv(pktbuf* pb) { pb->release();}
440 };
441 
442 static class VideoNullDecoderClass : public TclClass {
443 public:
444         VideoNullDecoderClass() : TclClass("Module/VideoDecoder/Null") {}
445         TclObject* create(int /* argc */, const char*const* /* argv */) {
446                 return (new NullDecoder);
447         }
448 } dm_null;
449 
450 PlaneDecoder::PlaneDecoder(int hdrlen) : Decoder(hdrlen), frm_(0)
451 {
452 }
453 
454 PlaneDecoder::~PlaneDecoder()
455 {
456         delete[] frm_;
457 }
458 
459 void PlaneDecoder::redraw()
460 {
461         Decoder::redraw(frm_);
462 }
463 
464 void PlaneDecoder::resize(int width, int height)
465 {
466         delete[] frm_;
467         int size = width * height;
468         frm_ = new u_char[2 * size];
469         /*
470          * Initialize image to gray.
471          */
472         memset(frm_, 0x80, 2 * size);
473         Decoder::resize(width, height);
474 }
475 
476 int PlaneDecoder::colorhist(u_int* histogram) const
477 {
478         int w = inw_;
479         int h = inh_;
480         int s = w * h;
481         u_char* up = frm_ + s;
482         colorhist_422_556(histogram, frm_, up, up + (s >> 1), w, h);
483         return (1);
484 }
485 

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