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

Open Mash Cross Reference
mash/codec/video/transcoder-h261.cc

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

  1 /*
  2  * transcoder-h261.cc --
  3  *
  4  *      H.261 Transcoder
  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 #ifndef lint
 35 static const char rcsid[] =
 36     "@(#) $Header: /usr/mash/src/repository/mash/mash-1/codec/video/transcoder-h261.cc,v 1.13 2003/11/19 19:20:24 aswan Exp $";
 37 #endif
 38 
 39 #include <stdio.h>
 40 #include <stdlib.h>
 41 #include <string.h>
 42 #ifndef WIN32
 43 #include <sys/param.h>
 44 #include <netinet/in.h>
 45 #endif
 46 #include "rtp/inet.h"
 47 #include "rtp/rtp.h"
 48 #include "codec/transcoder.h"
 49 #include "net/transmitter.h"
 50 #include "codec/p64/p64.h"
 51 #include "codec/crdef.h"
 52 
 53 class H261Transcoder : public VideoTranscoder {
 54 public:
 55         H261Transcoder();
 56         ~H261Transcoder();
 57 protected:
 58         virtual void configure() = 0;
 59         P64Decoder* decoder_;
 60         int ibit_;
 61         int h261_rtp_bug_;
 62 };
 63 
 64 #ifdef notyet
 65 class H261DCTTranscoder : public H261Transcoder {
 66 public:
 67         virtual void configure();
 68         virtual void recv_data(pktbuf* pb);
 69 };
 70 #endif
 71 
 72 class H261PixelTranscoder : public H261Transcoder {
 73 public:
 74         virtual void configure();
 75         virtual void recv_data(pktbuf* pb);
 76 };
 77 
 78 #ifdef notyet
 79 static class H261DCTTranscoderClass : public TclClass {
 80 public:
 81         H261DCTTranscoderClass() : TclClass("Transcoder/H261/DCT") {}
 82         TclObject* create(int, const char*const*) {
 83                     return (new H261DCTTranscoder);
 84         }
 85 } h261_dct_transcoder_class;
 86 #endif
 87 
 88 static class H261PixelTranscoderClass : public TclClass {
 89 public:
 90         H261PixelTranscoderClass() : TclClass("Transcoder/H261/Pixel") {}
 91         TclObject* create(int, const char*const*) {
 92                     return (new H261PixelTranscoder);
 93         }
 94 } h261_pixel_transcoder_class;
 95 
 96 H261Transcoder::H261Transcoder()
 97                :VideoTranscoder(4), decoder_(0),
 98                  ibit_(-1), h261_rtp_bug_(0)
 99 {}
100 
101 H261Transcoder::~H261Transcoder()
102 {
103         delete decoder_;
104 }
105 
106 #ifdef notyet
107 void H261DCTTranscoder::configure()
108 {
109         delete decoder_;
110         if (ibit_ != 0)
111                 decoder_ = new IntraP64DCTDecoder();
112         else
113                 decoder_ = new FullP64Decoder();
114 
115         decoder_->mark(CR_SEND|CR_MOTION);
116 }
117 #endif
118 
119 void H261PixelTranscoder::configure()
120 {
121         delete decoder_;
122         if (ibit_ != 0)
123                 decoder_ = new IntraP64Decoder();
124         else
125                 decoder_ = new FullP64Decoder();
126 
127         decoder_->mark(CR_MOTION_BIT | CR_LQ);
128 }
129 
130 void H261PixelTranscoder::recv_data(pktbuf* pb)
131 {
132         rtphdr* rh = (rtphdr*)(pb->dp);
133         int cc = pb->len - sizeof(rtphdr);
134         const u_char* bp = (const u_char*)(rh + 1);
135 
136         u_int v = ntohl(*(u_int*)(rh + 1));
137         int sbit = v >> 29;
138         int ebit = (v >> 26) & 7;
139         int quant = (v >> 10) & 0x1f;
140         int mvdh = (v >> 5) & 0x1f;
141         int mvdv = v & 0x1f;
142         int mba, gob;
143         /*
144          * vic-2.7 swapped the GOB and MBA fields in the RTP packet header
145          * with respect to the spec.  To maintain backward compat, whenever
146          * we see an out of range gob, we change our assumption about the
147          * stream and continue.
148          */
149         if (!h261_rtp_bug_) {
150                 mba = (v >> 15) & 0x1f;
151                 gob = (v >> 20) & 0xf;
152                 if (gob > 12) {
153                         h261_rtp_bug_ = 1;
154                         mba = (v >> 19) & 0x1f;
155                         gob = (v >> 15) & 0xf;
156                 }
157         } else {
158                 mba = (v >> 19) & 0x1f;
159                 gob = (v >> 15) & 0xf;
160                 if (gob > 12) {
161                         h261_rtp_bug_ = 0;
162                         mba = (v >> 15) & 0x1f;
163                         gob = (v >> 20) & 0xf;
164                 }
165         }
166 
167         if (gob > 12) {
168                 pb->release();
169                 return;
170         }
171 
172         int ibit = (v >> 25) & 1;
173         if (ibit != ibit_) {
174                 ibit_ = ibit;
175                 configure();
176         }
177 
178         bp += 4;;
179         cc -= 4;
180 
181         decoder_->marks(crvec_);
182         (void)decoder_->decode(bp, cc, sbit, ebit, mba, gob, quant, mvdh,
183                                mvdv);
184         pb->release();
185         /*
186          * If the stream changes format, issue a resize.
187          */
188         if (decoder_->width() != inw_ || decoder_->height() != inh_) {
189                 inw_ = decoder_->width();
190                 inh_ = decoder_->height();
191                 Tcl& tcl = Tcl::instance();
192                 tcl.evalf("%s frame_width %d", encoder_->name(), inw_);
193                 outw_ = atoi(tcl.result());
194                 tcl.evalf("%s frame_height %d", encoder_->name(), inh_);
195                 outh_ = atoi(tcl.result());
196                 pixel_crinit(outw_, outh_);
197                 decoder_->marks(crvec_);
198         }
199 
200         if (!(ntohs(rh->rh_flags) & RTP_M))
201                 return;
202 
203         /*
204          * Have a frame.
205          */
206         decoder_->sync();
207 
208         double now;
209         if (!txonly_) {
210                 if (bps_ == 0)
211                         return;
212                 now = gettimeofday();
213         }
214 
215         if (fc_ <= now || txonly_) {
216                 /* If we have fallen behind (>200ms), re-sync. */
217                 if (now - fc_ > 200000.)
218                         fc_ = now;
219                 blk_to_mb_cr();
220                 YuvFrame vf(ntohl(rh->rh_ts),
221                             ((P64Decoder*)decoder_)->frame(),
222                             mb_crvec_, outw_, outh_, 420);
223                 int nb = encoder_->nb();
224                 encoder_->recv(&vf);
225                 obytes_ = encoder_->nb();
226                 nb = obytes_ - nb;
227                 double bits = 8 * nb;
228                 lastfc_ = fc_;
229                 fc_ += 1e6 * bits / bps_;
230                 ofrms_++;
231 
232                 decoder_->mark(age_blocks() | CR_MOTION_BIT | CR_LQ);
233         }
234 }
235 
236 #ifdef notyet
237 void H261DCTTranscoder::recv_data(pktbuf* pb)
238 {
239         rtphdr* rh = (rtphdr*)(pb->dp);
240         int cc = pb->len - sizeof(rtphdr);
241         const u_char* bp = (const u_char*)(rh + 1);
242 
243         u_int v = ntohl(*(u_int*)(rh + 1));
244         int sbit = v >> 29;
245         int ebit = (v >> 26) & 7;
246         int quant = (v >> 10) & 0x1f;
247         int mvdh = (v >> 5) & 0x1f;
248         int mvdv = v & 0x1f;
249         int mba, gob;
250         /*
251          * vic-2.7 swapped the GOB and MBA fields in the RTP packet header
252          * with respect to the spec.  To maintain backward compat, whenever
253          * we see an out of range gob, we change our assumption about the
254          * stream and continue.
255          */
256         if (!h261_rtp_bug_) {
257                 mba = (v >> 15) & 0x1f;
258                 gob = (v >> 20) & 0xf;
259                 if (gob > 12) {
260                         h261_rtp_bug_ = 1;
261                         mba = (v >> 19) & 0x1f;
262                         gob = (v >> 15) & 0xf;
263                 }
264         } else {
265                 mba = (v >> 19) & 0x1f;
266                 gob = (v >> 15) & 0xf;
267                 if (gob > 12) {
268                         h261_rtp_bug_ = 0;
269                         mba = (v >> 15) & 0x1f;
270                         gob = (v >> 20) & 0xf;
271                 }
272         }
273 
274         int ibit = (v >> 25) & 1;
275         if (ibit != ibit_) {
276                 ibit_ = ibit;
277                 configure();
278         }
279 
280         bp += sizeof(h261hdr);
281         cc -= sizeof(h261hdr);
282 
283         (void)decoder_->decode(bp, cc, sbit, ebit, mba, gob, quant, mvdh,
284                                mvdv);
285         pb->release();
286         /*
287          * If the stream changes format, issue a resize.
288          */
289         if (decoder_->width() != inw_ || decoder_->height() != inh_) {
290                 inw_ = decoder_->width();
291                 inh_ = decoder_->height();
292                 Tcl& tcl = Tcl::instance();
293                 tcl.evalf("%s frame_width %d", encoder_->name(), inw);
294                 outw_ = atoi(tcl.result());
295                 tcl.evalf("%s frame_height %d", encoder_->name(), inh);
296                 outh_ = atoi(tcl.result());
297                 crinit(outw_, outh_);
298                 decoder_->marks(crvec_);
299         }
300 
301         if (!(ntohs(rh->rh_flags) & RTP_M))
302                 return;
303 
304         /*
305          * Have a frame.
306          */
307         decoder_->sync();
308 
309         if (bps_ == 0)
310                 return;
311 
312         double now = gettimeofday();
313         if (fc_ <= now) {
314                 /* If we have fallen behind (>200ms), re-sync. */
315                 if (now - fc_ > 200000.)
316                         fc_ = now;
317                 DCTFrame df(ntohl(rh->rh_ts),
318                             (IntraP64DCTDecoder*)decoder_->frame(), crvec_,
319                             outw_, outh_, 420);
320                 int nb = encoder_->nb();
321                 encoder_->recv(&df);
322                 obytes_ = encoder_->nb();
323                 nb = obytes_ - nb;
324                 double bits = 8 * nb;
325                 lastfc_ = fc_;
326                 fc_ += 1e6 * bits / bps_;
327                 ofrms_++;
328 
329                 mark_ = age_blocks() | CR_MOTION_BIT | CR_LQ;
330         }
331 }
332 #endif
333 

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