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 "rtp/inet.h"
39 #include "rtp/rtp.h"
40 #include "codec/decoder.h"
41 #include "render/renderer.h"
42 #include "net/pktbuf.h"
43 #include "codec/postdct.h"
44 #include "codec/h263/h263-decoder.h"
45
46 #include "codec/decoder-h263.h"
47
48
49 static class H263DecoderClass : public TclClass {
50 public:
51 H263DecoderClass() : TclClass("Module/VideoDecoder/H263") {}
52 TclObject* create(int /* argc */, const char*const* /* argv */) {
53 return (new H263Decoder);
54 };
55 } dm_h263;
56
57
58
59 #define DUMP_INFO 0
60
61
62 #define STAT_BAD_PSC 0
63 #define STAT_BAD_GOB 1
64 #define STAT_BAD_SYNTAX 2
65 #define STAT_BAD_FMT 3
66 #define STAT_FMT_CHANGE 4 /* # times fmt changed */
67 #define STAT_BAD_HEADER 5
68
69 // this variable contains a file where debugging output can be written.
70 FILE *debugFile;
71
72 H263Decoder::H263Decoder() : Decoder(4), codec_(0), last_seqno_(0)
73 {
74 //debugFile = fopen("dbg", "w");
75 debugFile = 0; // shut the compiler up!
76
77 stat_[STAT_BAD_PSC].name = "H263-Bad-PSC";
78 stat_[STAT_BAD_GOB].name = "H263-Bad-GOB";
79 stat_[STAT_BAD_SYNTAX].name = "H263-Bad-Syntax";
80 stat_[STAT_BAD_FMT].name = "H263-Bad-fmt";
81 stat_[STAT_FMT_CHANGE].name = "H263-Fmt-change";
82 stat_[STAT_BAD_HEADER].name = "H263-Bad-Header";
83 nstat_ = 6;
84 csss_ = 420;
85
86 /*
87 * Assume CIF. Picture header will trigger a resize if
88 * we encounter a different size.
89 */
90 inw_ = 352;
91 inh_ = 288;
92 resize(inw_, inh_);
93 }
94
95 H263Decoder::~H263Decoder()
96 {
97 delete codec_;
98 }
99
100 void H263Decoder::info(char* wrk) const
101 {
102 if (codec_ == 0)
103 *wrk = 0;
104 else
105 sprintf(wrk, "[q=%d]", codec_->qtidx());
106 }
107
108 void H263Decoder::stats(char* wrk)
109 {
110 /* pull stats out of vic independent of decoder */
111 setstat(STAT_BAD_PSC, codec_->bad_psc());
112 setstat(STAT_BAD_GOB, codec_->bad_GOBno());
113 setstat(STAT_BAD_SYNTAX, codec_->bad_bits());
114 setstat(STAT_BAD_FMT, codec_->bad_fmt());
115 Decoder::stats(wrk);
116 }
117
118 int H263Decoder::colorhist(u_int* hist) const
119 {
120 const u_char* frm = codec_->frame();
121 int w = inw_;
122 int h = inh_;
123 int s = w * h;
124 colorhist_420_556(hist, frm, frm + s, frm + s + (s >> 2), w, h);
125 return (1);
126 }
127
128
129 #ifdef CR_STATS
130 u_char shadow[640*480/64];
131
132 void dumpShadow(u_int32_t ts, u_char* p, int nblk)
133 {
134 ts &= 0x7fffffff;
135 static u_int32_t lastTS = 0;
136 if (ts != lastTS) {
137 printf("ts %u\n", ts);
138 lastTS = ts;
139 }
140 int left = -1;
141 for (int i = 0; i < nblk; ++i) {
142 if (shadow[i] != p[i]) {
143 if (left < 0) {
144 left = i;
145 }
146 } else {
147 if (left > 0)
148 printf("b %d %d\n", left, i - 1);
149 left = -1;
150 }
151 }
152 if (left > 0)
153 printf("b %d %d\n", left, i - 1);
154 }
155 #endif
156
157 extern void dumprtp(pktbuf* pb);
158 int npkts = 0;
159
160 void H263Decoder::recv(pktbuf* pb)
161 {
162 rtphdr* rh = (rtphdr*)pb->dp; /* RTP header */
163 u_int16_t seqno = ntohs(rh->rh_seqno); /* RTP sequence number */
164 u_int8_t* vh = (u_int8_t*)(rh + 1); /* video header */
165 int vhsize; /* video header size */
166 int fflag, pflag, sbit, ebit, src;
167 int iflag, uflag, sflag, aflag;
168 int dbq, trb, tr, quant, gob, mba, mvdh1, mvdv1, mvdh2, mvdv2;
169
170 npkts++;
171
172 if (codec_ == 0) {
173 codec_ = new H263BitstreamDecoder();
174 codec_->marks(rvts_);
175 #if 0
176 // open the debug file and write a timestamp
177 unsigned long tval;
178 tval = time(NULL);
179 fprintf(debugFile, "# Debug dump - %s\n",
180 ctime(((const long *)&tval)));
181 #endif
182 }
183 //printf(".%s", (((npkts % 25) == 0) ? "\n" : ""));
184
185 #ifdef CR_STATS
186 memcpy(shadow, rvts_, nblk_);
187 #endif
188
189 fflag = vh[0] >> 7;
190 pflag = (vh[0] >> 6) & 0x01;
191 sbit = (vh[0] >> 3) & 0x07;
192 ebit = vh[0] & 0x07;
193 src = vh[1] >> 5;
194
195 if (!fflag) {
196 /* Mode A packet */
197
198 vhsize = 4;
199 iflag = (vh[1] >> 4) & 0x01;
200 uflag = (vh[1] >> 3) & 0x01;
201 sflag = (vh[1] >> 2) & 0x01;
202 aflag = (vh[1] >> 1) & 0x01;
203 dbq = (vh[2] >> 3) & 0x03;
204 trb = vh[2] & 0x07;
205 tr = vh[3];
206
207 #if 0
208 if (true) {
209 fprintf(debugFile,"\n 'A' Pckt %d received (I%d:P%d, F#=%d) %s\n",
210 npkts, codec_->ifn_, codec_->pfn_, codec_->fn_,
211 (ntohs(rh->rh_flags) & RTP_M ? "last pkt in frame" : ""));
212 fprintf(debugFile,
213 " seqno=%d fflag=0x%x pflag=0x%x sbit=0x%x ebit=0x%x src=0x%x\n",
214 seqno, fflag, pflag, sbit, ebit, src);
215 fprintf(debugFile," iflag=0x%x uflag=0x%x sflag=0x%x aflag=0x%x\n",
216 iflag, uflag, sflag, aflag);
217 fprintf(debugFile," dbq=0x%x trb=0x%x tr=0x%x\n",
218 dbq, trb, tr);
219 fprintf(debugFile," pkt begins:");
220 for (int k=0; k<10; k++) {
221 fprintf(debugFile, " 0x%x%x", (vh[4+k] >> 4), (vh[4+k] & 0x0f));
222 }
223 fprintf(debugFile, "\n");
224 }
225 #endif
226
227 quant = 0;
228 mba = 0;
229 mvdh1 = 0;
230 mvdv1 = 0;
231 mvdh2 = 0;
232 mvdv2 = 0;
233
234 /* PB-frame? */
235 if (pflag) {
236 printf("PB Frame - not supported\n");
237 pb->release();
238 return;
239 }
240
241 /*
242 * Mode A packets don't contain a GOB number so we tell the codec
243 * whether or not the previous packet was received.
244 */
245 if (seqno == last_seqno_ + 1) {
246
247 /* The previous packet was received */
248
249 gob = SEQUENTIAL_PACKET;
250 } else {
251
252 /* The previous packet was not received */
253
254 gob = NONSEQUENTIAL_PACKET;
255 }
256
257 } else if (!pflag) {
258 /* Mode B packet */
259 u_int32_t v = ntohl(*(u_int32_t*)vh);
260
261 vhsize = 8;
262 quant = (v >> 16) & 0x1F;
263 gob = (v >> 11) & 0x1F;
264 mba = (v >> 2) & 0x1FF;
265 iflag = (vh[4] >> 7) & 0x01;
266 uflag = (vh[4] >> 6) & 0x01;
267 sflag = (vh[4] >> 5) & 0x01;
268 aflag = (vh[4] >> 4) & 0x01;
269 v = ntohl(*(u_int32_t*)&vh[4]);
270 mvdh1 = (v >> 21) & 0x7F;
271 mvdv1 = (v >> 14) & 0x7F;
272 mvdh2 = (v >> 7) & 0x7F;
273 mvdv2 = v & 0x7F;
274
275 #if 0
276 if ((codec_->fn_ <= 53)) {
277 fprintf(debugFile,"'B' Pckt %d received (I%d:P%d, F#=%d) %s...\n",
278 npkts, codec_->ifn_, codec_->pfn_, codec_->fn_,
279 (ntohs(rh->rh_flags) & RTP_M ? "last pkt in frame" : ""));
280 fprintf(debugFile,
281 " seqno=%d gob=%d mba=%d mvdh1=%d mvdv1=%d mvdh2=%d mvdv2=%d\n",
282 seqno, gob, mba, mvdh1, mvdv1, mvdh2, mvdv2);
283 }
284 #endif
285 /*
286 * Mode B packets from UCL vic always contain the same GOB number. We
287 * work around this bug by treating these packets like mode A packets.
288 */
289 if (gob == codec_->ngob() - 1) {
290 if (seqno == last_seqno_ + 1) {
291 gob = SEQUENTIAL_PACKET; // Previous packet received
292 } else {
293 gob = NONSEQUENTIAL_PACKET; // Previous packet not received
294 }
295 }
296 } else {
297 /* Mode C packet */
298 u_int32_t v = ntohl(*(u_int32_t*)vh);
299
300 vhsize = 12;
301 quant = (v >> 16) & 0x1F;
302 gob = (v >> 11) & 0x1F;
303 mba = (v >> 2) & 0x1FF;
304 iflag = (vh[4] >> 7) & 0x01;
305 uflag = (vh[4] >> 6) & 0x01;
306 sflag = (vh[4] >> 5) & 0x01;
307 aflag = (vh[4] >> 4) & 0x01;
308 v = ntohl(*(u_int32_t*)&vh[4]);
309 mvdh1 = (v >> 21) & 0x7F;
310 mvdv1 = (v >> 14) & 0x7F;
311 mvdh2 = (v >> 7) & 0x7F;
312 mvdv2 = v & 0x7F;
313 dbq = (vh[10] >> 3) & 0x03;
314 trb = vh[10] & 0x07;
315 tr = vh[11];
316
317 #if 0
318 if ((codec_->fn_ <= 53)) {
319 fprintf(debugFile,"'C' Pckt %d received (I%d:P%d, F#=%d) %s...\n",
320 npkts, codec_->ifn_, codec_->pfn_, codec_->fn_,
321 (ntohs(rh->rh_flags) & RTP_M ? "last pkt in frame" : ""));
322 fprintf(debugFile,
323 " seqno=%d gob=%d mba=%d mvdh1=%d mvdv1=%d mvdh2=%d mvdv2=%d\n",
324 seqno, gob, mba, mvdh1, mvdv1, mvdh2, mvdv2);
325 }
326 #endif
327 }
328
329 last_seqno_ = seqno;
330
331 if (gob > MAX_NUM_GOBS) {
332 printf("bad gob value received\n");
333 count(STAT_BAD_HEADER);
334 pb->release();
335 return;
336 }
337
338 int cc = pb->len - (sizeof(*rh) + vhsize);
339 codec_->mark(now_);
340
341 (void)codec_->decode(vh + vhsize, cc, sbit, ebit,
342 mba, gob, quant, mvdh1, mvdv1, mvdh2, mvdv2, fflag, pflag);
343
344 #ifdef CR_STATS
345 dumpShadow(ntohl(rh->rh_ts), rvts_, nblk_);
346 #endif
347
348 /* If the stream changes format, issue a resize */
349 if (codec_->width() != inw_) {
350 //printf("H263 decoder: stream format change %d X %d => %d X %d\n",
351 //inw_, inh_, codec_->width(), codec_->height());
352 resize(codec_->width(), codec_->height());
353 codec_->marks(rvts_);
354 count(STAT_FMT_CHANGE);
355 }
356
357 // variables for frame dump code below
358 //int myfn, myifn, mypfn, mysize, mybw, mybytes;
359 //char myfile[128];
360 //FILE *myfp;
361
362 /* If end of frame, then render it */
363 if (ntohs(rh->rh_flags) & RTP_M) {
364 //printf("#recv'd=%d #dec'd=%d\n", npkts, codec_->npkts_);
365 codec_->sync();
366 ndblk_ = codec_->ndblk();
367 #if 0
368 /*
369 * This code will allow you to dump decoded images.
370 * Move this code to a method on Decoder.
371 */
372 // move declarations out of if block
373 myifn = codec_->ifn_;
374 mypfn = codec_->pfn_;
375 myfn = codec_->fn_;
376 if (((myifn==1) && (mypfn==0)) ||
377 ((myifn==1) && (mypfn>=50) && (mypfn<=80))) {
378 // dump yuv frame
379 sprintf(myfile, "vid.yuv/f%d.yuv", mypfn);
380 if ((myfp=fopen(myfile, "wb")) == NULL) {
381 printf("Error openning file %d\n", errno);
382 }
383 //mysize = codec_->width_ * codec_->height_
384 //+ codec->width_ * codec->height_ / 2;
385 mysize = 152064;
386 mybw = 0;
387 while (mybw < mysize) {
388 mybytes = fwrite(codec_->frame() + mybw, sizeof(char),
389 mysize - mybw, myfp);
390 if (mybytes < 0) {
391 printf("bytes not written - abort\n");
392 abort();
393 }
394 mybw += mybytes;
395 }
396 fclose(myfp);
397 }
398 #endif
399 render_frame(codec_->frame(), CODEC_H261, quant);
400 #if 0
401 // print frame numbers to console window
402 if ((codec_->fn_ % 25) == 0) {
403 printf("%d (i=%d p=%d)\n", codec_->fn_, codec_->ifn_, codec_->pfn_);
404 }
405 #endif
406 codec_->dump_stats();
407 codec_->reset_stats();
408 codec_->resetndblk();
409 //npkts = 0;
410 }
411 pb->release();
412 }
413
414 void H263Decoder::redraw()
415 {
416 if (codec_ != 0)
417 Decoder::redraw(codec_->frame());
418 }
419
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.