1 /*
2 * decoder-h261.cc --
3 *
4 * Source code for H.261 Video Decoder object
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
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 "codec/p64/p64.h"
43 #include "net/pktbuf.h"
44 #include "codec/postdct.h"
45
46 #include "codec/decoder-h261.h"
47
48
49 static class H261DecoderClass : public TclClass {
50 public:
51 H261DecoderClass() : TclClass("Module/VideoDecoder/H261") {}
52 TclObject* create(int /* argc */, const char*const* /* argv */) {
53 return (new H261Decoder);
54 };
55 } dm_h261;
56
57
58
59 #define STAT_BAD_PSC 0
60 #define STAT_BAD_GOB 1
61 #define STAT_BAD_SYNTAX 2
62 #define STAT_BAD_FMT 3
63 #define STAT_FMT_CHANGE 4 /* # times fmt changed */
64 #define STAT_BAD_HEADER 5
65
66
67 H261Decoder::H261Decoder() : Decoder(4), codec_(0), h261_rtp_bug_(0)
68 {
69 stat_[STAT_BAD_PSC].name = "H261-Bad-PSC";
70 stat_[STAT_BAD_GOB].name = "H261-Bad-GOB";
71 stat_[STAT_BAD_SYNTAX].name = "H261-Bad-Syntax";
72 stat_[STAT_BAD_FMT].name = "H261-Bad-fmt";
73 stat_[STAT_FMT_CHANGE].name = "H261-Fmt-change";
74 stat_[STAT_BAD_HEADER].name = "H261-Bad-Header";
75 nstat_ = 6;
76
77 csss_ = 420;
78 /*
79 * Assume CIF. Picture header will trigger a resize if
80 * we encounter QCIF instead.
81 */
82 inw_ = 352;
83 inh_ = 288;
84
85 /*FIXME*/
86 resize(inw_, inh_);
87 }
88
89 H261Decoder::~H261Decoder()
90 {
91 delete codec_;
92 }
93
94 void H261Decoder::info(char* wrk) const
95 {
96 if (codec_ == 0)
97 *wrk = 0;
98 else
99 sprintf(wrk, "[q=%d]", codec_->gobquant());
100 }
101
102 void H261Decoder::stats(char* wrk)
103 {
104 /* pull stats out of vic indepdendent P64Decoder */
105 setstat(STAT_BAD_PSC, codec_->bad_psc());
106 setstat(STAT_BAD_GOB, codec_->bad_GOBno());
107 setstat(STAT_BAD_SYNTAX, codec_->bad_bits());
108 setstat(STAT_BAD_FMT, codec_->bad_fmt());
109 Decoder::stats(wrk);
110 }
111
112 int H261Decoder::colorhist(u_int* hist) const
113 {
114 const u_char* frm = codec_->frame();
115 int w = inw_;
116 int h = inh_;
117 int s = w * h;
118 colorhist_420_556(hist, frm, frm + s, frm + s + (s >> 2), w, h);
119 return (1);
120 }
121
122
123 #ifdef CR_STATS
124 u_char shadow[640*480/64];
125
126 void dumpShadow(u_int32_t ts, u_char* p, int nblk)
127 {
128 ts &= 0x7fffffff;
129 static u_int32_t lastTS = 0;
130 if (ts != lastTS) {
131 printf("ts %u\n", ts);
132 lastTS = ts;
133 }
134 int left = -1;
135 for (int i = 0; i < nblk; ++i) {
136 if (shadow[i] != p[i]) {
137 if (left < 0) {
138 left = i;
139 }
140 } else {
141 if (left > 0)
142 printf("b %d %d\n", left, i - 1);
143 left = -1;
144 }
145 }
146 if (left > 0)
147 printf("b %d %d\n", left, i - 1);
148 }
149 #endif
150
151 void H261Decoder::recv(pktbuf* pb)
152 {
153 rtphdr* rh = (rtphdr*)pb->dp;
154 u_int8_t* vh = (u_int8_t*)(rh + 1);
155 if (codec_ == 0) {
156 if ((vh[0] & 2) != 0)
157 codec_ = new IntraP64Decoder();
158 else
159 codec_ = new FullP64Decoder();
160 codec_->marks(rvts_);
161 }
162 #ifdef CR_STATS
163 memcpy(shadow, rvts_, nblk_);
164 #endif
165 u_int v = ntohl(*(u_int32_t*)vh);
166 int sbit = v >> 29;
167 int ebit = (v >> 26) & 7;
168 int quant = (v >> 10) & 0x1f;
169 int mvdh = (v >> 5) & 0x1f;
170 int mvdv = v & 0x1f;
171 int mba, gob;
172 /*
173 * vic-2.7 swapped the GOB and MBA fields in the RTP packet header
174 * with respect to the spec. To maintain backward compat, whenever
175 * we see an out of range gob, we change our assumption about the
176 * stream and continue.
177 */
178 if (!h261_rtp_bug_) {
179 mba = (v >> 15) & 0x1f;
180 gob = (v >> 20) & 0xf;
181 if (gob > 12) {
182 h261_rtp_bug_ = 1;
183 mba = (v >> 19) & 0x1f;
184 gob = (v >> 15) & 0xf;
185 }
186 } else {
187 mba = (v >> 19) & 0x1f;
188 gob = (v >> 15) & 0xf;
189 if (gob > 12) {
190 h261_rtp_bug_ = 0;
191 mba = (v >> 15) & 0x1f;
192 gob = (v >> 20) & 0xf;
193 }
194 }
195
196 if (gob > 12) {
197 count(STAT_BAD_HEADER);
198 pb->release();
199 return;
200 }
201 int cc = pb->len - (sizeof(*rh) + 4);
202 codec_->mark(now_);
203 (void)codec_->decode(vh + 4, cc, sbit, ebit,
204 mba, gob, quant, mvdh, mvdv);
205 #ifdef CR_STATS
206 dumpShadow(ntohl(rh->rh_ts), rvts_, nblk_);
207 #endif
208 /*
209 * If the stream changes format, issue a resize.
210 */
211 if (codec_->width() != inw_) {
212 resize(codec_->width(), codec_->height());
213 codec_->marks(rvts_);
214 count(STAT_FMT_CHANGE);
215 }
216
217 /*FIXME*/
218 if (ntohs(rh->rh_flags) & RTP_M) {
219 //printf ("now_ = %2x, timestamp = %d\n", now_, ntohl(rh->rh_ts)); // XXX
220 codec_->sync();
221 ndblk_ = codec_->ndblk();
222 render_frame(codec_->frame(), CODEC_H261, quant);
223 codec_->resetndblk();
224 }
225 pb->release();
226 }
227
228 void H261Decoder::redraw()
229 {
230 if (codec_ != 0)
231 Decoder::redraw(codec_->frame());
232 }
233
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.