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

Open Mash Cross Reference
mash/tgw/pipe_rend.cc

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

  1 /*
  2  * pipe_rend.cc --
  3  *
  4  *      FIXME: This file needs a description here.
  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 "pipe_rend.h"
 35 #define ALPHA 90        // convergence for average diff size (out of 100)
 36 
 37 // Note: pntypes.h must be included before windows.h for MSVC6.0
 38 #include <stdio.h>
 39 #include <assert.h>
 40 
 41 // This class is a psuedo renderer that grabs the YUV frames and instead of
 42 // passing it to the screen, it gives it to a RealNetworks encoding engine. For use
 43 // in tgw.
 44 
 45 static class PipeRendererClass : public TclClass {
 46 public:
 47   PipeRendererClass() : TclClass ("Module/Renderer/PipeRenderer") {};
 48   TclObject* create(int /* argc */, const char*const* /* argv */) {
 49     return (new PipeRenderer);
 50   };
 51 } rm_Pipe;
 52 
 53 PipeRenderer::PipeRenderer() : ConditionalReplenisher(), encoder_(0),frame_data_(0), avg_diff_size_(0), bidder_house_(0), diff_threshold(24), diffs_want_to_send(0) {
 54   //  fd = fopen ("blah", "w");
 55   frame_ = new YuvFrame(0,0,0,0,420,0);
 56 }
 57 
 58 PipeRenderer::~PipeRenderer() {
 59   //  fclose (fd);
 60 }
 61 
 62 // This is to report the bandwidht usage for this source back to the UI (which is bandwidthObj)
 63 void PipeRenderer::bandwidthUsage(int x) {
 64   Tcl& tcl = Tcl::instance();
 65   tcl.evalf("%s %d", bandwidthObj, x);
 66 }
 67 
 68 // receive a YUV frame, setup structures if this is the first frame, else do the conditional
 69 // replenishment checks and report to the auction house how much data you want to send...
 70 void PipeRenderer::recv(Buffer* b) {
 71   YuvFrame* in_frame_ = (YuvFrame*)b;
 72   int y;
 73 
 74   if ((in_frame_->width_ != frame_->width_) || 
 75       (in_frame_->height_ != frame_->height_)) {
 76 
 77     /* First time called or frame size changed. Reallocate frame data space and reinit crvec */
 78 
 79     if (frame_data_ != 0) {
 80       delete [] frame_data_;
 81     }
 82     y = in_frame_->width_*in_frame_->height_*3/2;
 83     frame_data_ = new u_int8_t[y];
 84     
 85     memcpy(frame_data_, in_frame_->bp_, y);
 86 
 87     crinit(in_frame_->width_, in_frame_->height_);
 88     y = ((in_frame_->width_ >> 4) * (in_frame_->height_ >>4));
 89     crvec_to_send_ = new u_char[y];
 90     crvec_not_sent_ = new u_char[y];
 91     bzero(crvec_not_sent_, y);
 92           
 93     frame_->crvec_ = crvec_to_send_;
 94     frame_->bp_ = frame_data_;
 95     frame_->width_ = in_frame_->width_;
 96     frame_->height_ = in_frame_->height_;
 97     frame_->layer_ = 0;    
 98   } else {
 99     // Frame size is the same, so do conditional replenishment.
100     int mark = age_blocks() | CR_MOTION_BIT | CR_LQ;
101     
102     register int _stride = in_frame_->width_;
103     
104     const u_char* rb = &(frame_data_[scan_ * _stride]);
105     const u_char* lb = &(in_frame_->bp_[scan_ * _stride]);
106     
107     u_char* crv = crvec_;
108 
109     int bw = frame_->width_/16;
110     int bh = frame_->height_/16;
111     
112     for (y = 0; y < bh; y++) {
113       const u_char* nrb = rb;
114       const u_char* nlb = lb;
115       u_char* ncrv = crv;
116       
117       for (int x = 0; x < bw; x++) {
118         int tl = 0;
119         int tc1 = 0;
120         int tc2 = 0;
121         int tr = 0;
122         int bl = 0;
123         int bc1 = 0;
124         int bc2 = 0;
125         int br = 0;
126 
127         tl = lb[0] - rb[0] + lb[1] - rb[1] + lb[2] - rb[2] + lb[3] - rb[3];
128         if (tl < 0) tl = -tl;
129 
130         tc1 = lb[4] - rb[4] + lb[5] - rb[5] + lb[6] - rb[6] + lb[7] - rb[7];
131         if (tc1 < 0) tc1 = -tc1;
132 
133         tc2 = lb[8] - rb[8] + lb[9] - rb[9] + lb[10] - rb[10] + lb[11] -rb[11];
134         if (tc2 < 0) tc2 = -tc2;
135 
136         tr = lb[12] - rb[12] + lb[13] - rb[13] + lb[14] - rb[14] + 
137           lb[15] - rb[15];
138         if (tr < 0) tr = -tr;
139         
140         lb += _stride << 3;
141         rb += _stride << 3;
142 
143         bl = lb[0] - rb[0] + lb[1] - rb[1] + lb[2] - rb[2] + lb[3] - rb[3];
144         if (bl < 0) bl = -bl;
145         
146         bc1 = lb[4] - rb[4] + lb[5] - rb[5] + lb[6] - rb[6] + lb[7] - rb[7];
147         if (bc1 < 0) bc1 = -bc1;
148 
149         bc2 = lb[8] - rb[8] + lb[9] - rb[9] + lb[10] - rb[10] + lb[11] -rb[11];
150         if (bc2 < 0) bc2 = -bc2;
151 
152         br = lb[12] - rb[12] + lb[13] - rb[13] + lb[14] - rb[14] + 
153           lb[15] - rb[15];
154         if (br < 0) br = -br;
155         
156         lb -= _stride << 3;
157         rb -= _stride << 3;
158         
159         if (scan_ < 4) {
160           /*      // north-west 
161           if ((tl >= diff_threshold) && (x > 0) && (y > 0)) {
162             crv[-bw-1] = mark;
163           }
164           // north
165           if (((tl >= diff_threshold) || (tc1 >= diff_threshold) || (tc2 >= diff_threshold) || (tr >= diff_threshold)) &&
166               (y > 0)) {
167             crv[-bw] = mark;
168           }
169           // north-east 
170           if ((tr >= diff_threshold) && (x < bw - 1) && (y > 0)) {
171             crv[-bw+1] = mark;
172           }
173           // west
174           if (((tl >= diff_threshold) || (bl >= diff_threshold)) && (x > 0)) {
175             crv[-1] = mark;
176           } */
177           // middle 
178           if ((tl >= diff_threshold) || (tc1 >= diff_threshold) || (tc2 >= diff_threshold) || (tr >= diff_threshold) ||
179               (bl >= diff_threshold) || (bc1 >= diff_threshold) || (bc2 >= diff_threshold) || (br >= diff_threshold)) {
180             crv[0] = mark;
181           }/*
182           // east 
183           if (((tr >= diff_threshold) || (br >=diff_threshold)) && (x < bw - 1)) {
184             crv[1] = 0;
185           }*/
186         } else {
187           /*      // south-west 
188           if ((bl >= diff_threshold) && (x > 0) && (y < bh-1)) {
189             crv[bw-1] = mark;
190           }
191           // south 
192           if (((bl >= diff_threshold) || (bc1 >= diff_threshold) || (bc2 >= diff_threshold) || (br >= diff_threshold)) &&
193               (y < bh-1)) {
194             crv[bw] = mark;
195           }
196           // south-east
197           if ((br >= diff_threshold) && (x < bw - 1) && (y < bh - 1)) {
198             crv[bw+1] = mark;
199           }
200           // west 
201           if (((bl >= diff_threshold) || (tl >= diff_threshold)) && (x > 0)) {
202             crv[-1] = mark;
203           } */
204           // middle 
205           if ((bl >= diff_threshold) || (bc1 >= diff_threshold) || (bc2 >= diff_threshold) || (br >= diff_threshold) ||
206               (tl >= diff_threshold) || (tc1 >= diff_threshold) || (tc2 >= diff_threshold) || (tr >= diff_threshold)) {
207             crv[0] = mark;
208           }
209           /*      // east 
210           if (((br >= diff_threshold) || (tr >=diff_threshold)) && (x < bw - 1)) {
211             crv[1] = 0;
212             } */
213         }
214         lb += 16;
215         rb += 16;
216         crv++;
217       }
218       lb = nlb + (_stride << 4);
219       rb = nrb + (_stride << 4);
220       crv = ncrv + bw;
221     }
222 
223     // Copy blocks into frame based on conditional replenishment
224 
225     crv = crvec_;
226     int off = frame_->width_ * frame_->height_;
227     u_char* dest_lum = frame_data_;
228     u_char* dest_cr = frame_data_+off;
229     u_char* dest_cb = frame_data_+off+(off/4);
230     u_char* src_lum = in_frame_->bp_;
231     u_char* src_cr = in_frame_->bp_+off;
232     u_char* src_cb = in_frame_->bp_+off+(off/4);
233 
234     for (y = 0; y < bh; y++) {
235       int i;
236       for (int x = 0; x < bw; x++) {
237         int s = *crv++;
238         if ((s & CR_SEND) != 0) {
239           int idx = y*_stride*16+x*16;
240           u_int32_t* sl = (u_int32_t*) &(src_lum[idx]);
241           u_int32_t* dl = (u_int32_t*) &(dest_lum[idx]);
242           for(i=0; i<16; i++) {
243             dl[0] = sl[0];
244             dl[1] = sl[1];
245             dl[2] = sl[2];
246             dl[3] = sl[3];
247             dl += (_stride / 4);
248             sl += (_stride / 4);
249           }
250 
251           idx = y*(_stride/2)*8+x*8;
252           u_int32_t* scr = (u_int32_t*) &(src_cr[idx]);
253           u_int32_t* scb = (u_int32_t*) &(src_cb[idx]);
254           u_int32_t* dcr = (u_int32_t*) &(dest_cr[idx]);
255           u_int32_t* dcb = (u_int32_t*) &(dest_cb[idx]);
256           for(i=0; i<8; i++) {
257             dcr[0] = scr[0];
258             dcr[1] = scr[1];
259             dcb[0] = scb[0];
260             dcb[1] = scb[1];
261             dcr += _stride / 8;
262             dcb += _stride / 8;
263             scr += _stride / 8;
264             scb += _stride / 8;
265           }
266         }
267       }
268     }
269   }
270   frame_->ts_ = in_frame_->ts_;
271 
272   // calculate how many diffs you want to send.
273   diffs_want_to_send = 0;
274   for (y=((in_frame_->width_ >> 4) * (in_frame_->height_ >>4))-1;y>=0;y--) {
275     if ((crvec_[y] & CR_SEND) != 0) {
276       crvec_not_sent_[y] = crvec_[y];
277       diffs_want_to_send++;
278     } else if ((crvec_not_sent_[y] & CR_SEND) != 0) {
279       diffs_want_to_send++;
280     }
281   }
282   
283   // should only occur at startup...
284   if (avg_diff_size_ == 0)
285     avg_diff_size_ = 50;
286 
287   //  printf("diffs_want_to_send: %x, %d, avg_diff_size:%d\n", this, diffs_want_to_send, avg_diff_size_);
288   // tell the auction house how much data you want to send.
289   bidder_house_->setDiffCount(this, diffs_want_to_send, avg_diff_size_);
290 }
291 
292 // The auction house now tells the source that it can go ahead and send its data.
293 void PipeRenderer::giveToEncoder(int diffs_to_send) {
294   //  fprintf(fd, "diffs_going_to_send: %x, %d\n", this, diffs_to_send);
295   int x, marker, rand_num;
296   int bytes_sent = 0;
297   int size_of_crvec = ((frame_->width_ >> 4) * (frame_->height_ >>4));
298 
299   bzero(crvec_to_send_, size_of_crvec);
300 
301   if (diffs_to_send <= 0) {
302     return;
303   } else if (diffs_to_send >= diffs_want_to_send) {
304     // we can send all our updates.
305     memcpy(crvec_to_send_, crvec_not_sent_, size_of_crvec);
306     bzero(crvec_not_sent_, size_of_crvec);
307   } else {
308     // we can only send a subset (randomly chosen) of our data.
309     for (x = 0; x < diffs_to_send; x++) {
310       rand_num = random()%size_of_crvec;
311       marker = rand_num;
312       while (((crvec_not_sent_[rand_num]) & CR_SEND) == 0) {
313         rand_num = (rand_num+1)%size_of_crvec;
314         if (rand_num == marker) {
315           //    fprintf(fd, "we were told to send too much\n");
316           Tcl::instance().eval("puts \"we were told to send more diffs then we have to send\"");
317           break;
318         }
319       }
320       crvec_to_send_[rand_num] = crvec_not_sent_[rand_num];
321       crvec_not_sent_[rand_num] = 0;
322     }
323   }
324   
325   if (encoder_ != 0) {
326     // record how much data was actually sent.
327     bytes_sent = encoder_->nb();
328     encoder_->recv(frame_);
329     bytes_sent = encoder_->nb() - bytes_sent;
330     avg_diff_size_ = ((ALPHA*avg_diff_size_) + ((100-ALPHA)*(bytes_sent/diffs_to_send)))/100;
331   }
332 }
333 
334 int PipeRenderer::command(int argc, const char*const* argv) {
335   Tcl& tcl = Tcl::instance();
336   if (argc == 3) {
337     if (strcmp(argv[1], "attach_encoder") == 0) {
338       encoder_ = (EncoderModule*)TclObject::lookup(argv[2]);
339       if (encoder_ == 0) {
340         tcl.resultf("%s attach_encoder: no such encoder: %s", argv[0], argv[2]);
341         return (TCL_ERROR);
342       }
343       return (TCL_OK);
344     } else if (strcmp(argv[1], "use_auction_house") == 0) {
345       bidder_house_ = (BidderHouse*)TclObject::lookup(argv[2]);
346       if (bidder_house_ == 0) {
347         tcl.resultf("%s use_auction_house: no such bidder house: %s", argv[0], argv[2]);
348         return (TCL_ERROR);
349       }
350       bidder_house_->addSource(this);
351       return (TCL_OK);
352     } else if (strcmp(argv[1], "bandwidth_display") == 0) {
353       sprintf(bandwidthObj, "%s change_bwUsage", argv[2]);
354       return (TCL_OK);
355     }
356   }
357   return (Renderer::command(argc, argv));
358 }
359 
360 
361 
362 

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