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 "inet.h"
39 #include "rtp.h"
40 #include "decoder.h"
41 #include "renderer.h"
42 #include "pktbuf.h"
43 #include "postdct.h"
44
45 #include "decoder-h263.h"
46
47
48 static class H263DecoderClass : public TclClass {
49 public:
50 H263DecoderClass() : TclClass("Module/VideoDecoder/H263") {}
51 TclObject* create(int /* argc */, const char*const* /* argv */) {
52 return (new H263Decoder);
53 };
54 } dm_h263;
55
56
57
58 #define DUMP_INFO 1
59
60
61 #define STAT_BAD_PSC 0
62 #define STAT_BAD_GOB 1
63 #define STAT_BAD_SYNTAX 2
64 #define STAT_BAD_FMT 3
65 #define STAT_FMT_CHANGE 4 /* # times fmt changed */
66 #define STAT_BAD_HEADER 5
67
68
69 H263Decoder::H263Decoder() : Decoder(4), codec_(0), last_seqno_(0)
70 {
71 stat_[STAT_BAD_PSC].name = "H263-Bad-PSC";
72 stat_[STAT_BAD_GOB].name = "H263-Bad-GOB";
73 stat_[STAT_BAD_SYNTAX].name = "H263-Bad-Syntax";
74 stat_[STAT_BAD_FMT].name = "H263-Bad-fmt";
75 stat_[STAT_FMT_CHANGE].name = "H263-Fmt-change";
76 stat_[STAT_BAD_HEADER].name = "H263-Bad-Header";
77 nstat_ = 6;
78
79 csss_ = 420;
80 /*
81 * Assume CIF. Picture header will trigger a resize if
82 * we encounter QCIF instead.
83 */
84 inw_ = 352;
85 inh_ = 288;
86
87 /*FIXME*/
88 resize(inw_, inh_);
89 }
90
91 H263Decoder::~H263Decoder()
92 {
93 delete codec_;
94 }
95
96 void H263Decoder::info(char* wrk) const
97 {
98 if (codec_ == 0)
99 *wrk = 0;
100 else
101 sprintf(wrk, "[q=%d]", codec_->gobquant());
102 }
103
104 void H263Decoder::stats(char* wrk)
105 {
106 /* pull stats out of vic indepdendent P64Decoder */
107 setstat(STAT_BAD_PSC, codec_->bad_psc());
108 setstat(STAT_BAD_GOB, codec_->bad_GOBno());
109 setstat(STAT_BAD_SYNTAX, codec_->bad_bits());
110 setstat(STAT_BAD_FMT, codec_->bad_fmt());
111 Decoder::stats(wrk);
112 }
113
114 int H263Decoder::colorhist(u_int* hist) const
115 {
116 const u_char* frm = codec_->frame();
117 int w = inw_;
118 int h = inh_;
119 int s = w * h;
120 colorhist_420_556(hist, frm, frm + s, frm + s + (s >> 2), w, h);
121 return (1);
122 }
123
124
125 #ifdef CR_STATS
126 u_char shadow[640*480/64];
127
128 void dumpShadow(u_int32_t ts, u_char* p, int nblk)
129 {
130 ts &= 0x7fffffff;
131 static u_int32_t lastTS = 0;
132 if (ts != lastTS) {
133 printf("ts %u\n", ts);
134 lastTS = ts;
135 }
136 int left = -1;
137 for (int i = 0; i < nblk; ++i) {
138 if (shadow[i] != p[i]) {
139 if (left < 0) {
140 left = i;
141 }
142 } else {
143 if (left > 0)
144 printf("b %d %d\n", left, i - 1);
145 left = -1;
146 }
147 }
148 if (left > 0)
149 printf("b %d %d\n", left, i - 1);
150 }
151 #endif
152
153 void H263Decoder::recv(pktbuf* pb)
154 {
155 rtphdr* rh = (rtphdr*)pb->dp; /* RTP header */
156 u_int16_t seqno = ntohs(rh->rh_seqno); /* RTP sequence number */
157 u_int8_t* vh = (u_int8_t*)(rh + 1); /* video header */
158 int vhsize; /* video header size */
159
160 if (codec_ == 0) {
161 codec_ = new H263BitstreamDecoder();
162 codec_->marks(rvts_);
163 }
164 #ifdef CR_STATS
165 memcpy(shadow, rvts_, nblk_);
166 #endif
167
168 int fflag = vh[0] >> 7;
169 int pflag = (vh[0] >> 6) & 0x01;
170 int sbit = (vh[0] >> 3) & 0x07;
171 int ebit = vh[0] & 0x07;
172 int src = vh[1] >> 5;
173 int iflag, uflag, sflag, aflag;
174 int dbq, trb, tr;
175 int quant, gob, mba, mvdh1, mvdv1, mvdh2, mvdv2;
176
177 /*
178 * Mode A packet.
179 */
180 if (!fflag) {
181 vhsize = 4;
182
183 iflag = (vh[1] >> 4) & 0x01;
184 uflag = (vh[1] >> 3) & 0x01;
185 sflag = (vh[1] >> 2) & 0x01;
186 aflag = (vh[1] >> 1) & 0x01;
187 dbq = (vh[2] >> 3) & 0x03;
188 trb = vh[2] & 0x07;
189 tr = vh[3];
190
191 quant = 0;
192 mba = 0;
193
194 /*
195 * I-picture or P-picture.
196 */
197 if (!pflag) {
198 #if DUMP_INFO
199 printf("mode A packet received with I-picture or P-picture\n");
200 #endif
201
202 /*
203 * PB-frame.
204 */
205 } else {
206 /*
207 * The optional PB-frame mode is not supported.
208 */
209 #if DUMP_INFO
210 printf("mode A packet received with PB-frame\n");
211 #endif
212 }
213
214 /*
215 * Mode A packets don't contain a GOB number so we tell the codec
216 * whether or not the previous packet was received.
217 */
218 if (seqno == last_seqno_ + 1) {
219 /*
220 * The previous packet was received.
221 */
222 gob = SEQUENTIAL_PACKET;
223 } else {
224 /*
225 * The previous packet was not received.
226 */
227 gob = NONSEQUENTIAL_PACKET;
228 #if DUMP_INFO
229 printf("previous packet was not received\n");
230 printf("last sequence number = %d, current sequence number = %d\n",
231 last_seqno_, seqno);
232 #endif
233 }
234
235 /*
236 * Mode B packet.
237 */
238 } else if (!pflag) {
239 vhsize = 8;
240
241 u_int32_t v = ntohl(*(u_int32_t*)vh);
242 quant = (v >> 16) & 0x1F;
243 gob = (v >> 11) & 0x1F;
244 mba = (v >> 2) & 0x1FF;
245 iflag = (vh[4] >> 7) & 0x01;
246 uflag = (vh[4] >> 6) & 0x01;
247 sflag = (vh[4] >> 5) & 0x01;
248 aflag = (vh[4] >> 4) & 0x01;
249 v = ntohl(*(u_int32_t*)&vh[4]);
250 mvdh1 = (v >> 21) & 0x7F;
251 mvdv1 = (v >> 14) & 0x7F;
252 mvdh2 = (v >> 7) & 0x7F;
253 mvdv2 = v & 0x7F;
254
255 #if DUMP_INFO
256 printf("mode B packet received\n");
257 #endif
258
259 /*
260 * Mode B packets from UCL vic always contain the same GOB number. We
261 * work around this bug by treating these packets like mode A packets.
262 */
263 if (gob == codec_->ngob() - 1) {
264 if (seqno == last_seqno_ + 1) {
265 /*
266 * The previous packet was received.
267 */
268 gob = SEQUENTIAL_PACKET;
269 } else {
270 /*
271 * The previous packet was not received.
272 */
273 gob = NONSEQUENTIAL_PACKET;
274 #if DUMP_INFO
275 printf("previous packet was not received\n");
276 printf("last sequence number = %d,"
277 " current sequence number = %d\n", last_seqno_, seqno);
278 #endif
279 }
280 }
281
282 /*
283 * Mode C packet.
284 */
285 } else {
286 vhsize = 12;
287
288 u_int32_t v = ntohl(*(u_int32_t*)vh);
289 quant = (v >> 16) & 0x1F;
290 gob = (v >> 11) & 0x1F;
291 mba = (v >> 2) & 0x1FF;
292 iflag = (vh[4] >> 7) & 0x01;
293 uflag = (vh[4] >> 6) & 0x01;
294 sflag = (vh[4] >> 5) & 0x01;
295 aflag = (vh[4] >> 4) & 0x01;
296 v = ntohl(*(u_int32_t*)&vh[4]);
297 mvdh1 = (v >> 21) & 0x7F;
298 mvdv1 = (v >> 14) & 0x7F;
299 mvdh2 = (v >> 7) & 0x7F;
300 mvdv2 = v & 0x7F;
301 dbq = (vh[10] >> 3) & 0x03;
302 trb = vh[10] & 0x07;
303 tr = vh[11];
304
305 /*
306 * The optional PB-frame mode is not supported.
307 */
308 #if DUMP_INFO
309 printf("mode C packet received\n");
310 #endif
311 }
312
313 last_seqno_ = seqno;
314
315 if (gob > MAX_NUM_GOBS) {
316 printf("bad gob value received\n"); // FIXME
317 count(STAT_BAD_HEADER);
318 pb->release();
319 return;
320 }
321
322 int cc = pb->len - (sizeof(*rh) + vhsize);
323 codec_->mark(now_);
324 (void)codec_->decode(vh + vhsize, cc, sbit, ebit,
325 mba, gob, quant, mvdh1, mvdv1, mvdh2, mvdv2);
326 #ifdef CR_STATS
327 dumpShadow(ntohl(rh->rh_ts), rvts_, nblk_);
328 #endif
329 #if 0
330 /*
331 * If the stream changes format, issue a resize.
332 */
333 if (codec_->width() != inw_) {
334 resize(codec_->width(), codec_->height());
335 codec_->marks(rvts_);
336 count(STAT_FMT_CHANGE);
337 }
338
339 /*FIXME*/
340 if (ntohs(rh->rh_flags) & RTP_M) {
341 #if DUMP_INFO
342 printf("packet is marked as the end of frame\n");
343 #endif
344 //printf ("now_ = %2x, timestamp = %d\n", now_, ntohl(rh->rh_ts)); // XXX
345 #endif
346 codec_->sync();
347 ndblk_ = codec_->ndblk();
348 render_frame(codec_->frame(), CODEC_H261, quant);
349 codec_->resetndblk();
350 #if 0
351 }
352 #endif
353 pb->release();
354 }
355
356 void H263Decoder::redraw()
357 {
358 if (codec_ != 0)
359 Decoder::redraw(codec_->frame());
360 }
361
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.