1 /************************************************************************
2 *
3 * tmndec.c, main(), initialization, options for tmndecode (H.263 decoder)
4 * Copyright (C) 1995, 1996 Telenor R&D, Norway
5 *
6 * Contacts:
7 * Robert Danielsen <Robert.Danielsen@nta.no>
8 *
9 * Telenor Research and Development http://www.nta.no/brukere/DVC/
10 * P.O.Box 83 tel.: +47 63 84 84 00
11 * N-2007 Kjeller, Norway fax.: +47 63 81 00 76
12 *
13 * Copyright (C) 1997 University of BC, Canada
14 * Modified by: Michael Gallant <mikeg@ee.ubc.ca>
15 * Guy Cote <guyc@ee.ubc.ca>
16 * Berna Erol <bernae@ee.ubc.ca>
17 *
18 * Contacts:
19 * Michael Gallant <mikeg@ee.ubc.ca>
20 *
21 * UBC Image Processing Laboratory http://www.ee.ubc.ca/image
22 * 2356 Main Mall tel.: +1 604 822 4051
23 * Vancouver BC Canada V6T1Z4 fax.: +1 604 822 5949
24 *
25 ************************************************************************/
26
27 /* Disclaimer of Warranty
28 *
29 * These software programs are available to the user without any license fee
30 * or royalty on an "as is" basis. The University of British Columbia
31 * disclaims any and all warranties, whether express, implied, or
32 * statuary, including any implied warranties or merchantability or of
33 * fitness for a particular purpose. In no event shall the
34 * copyright-holder be liable for any incidental, punitive, or
35 * consequential damages of any kind whatsoever arising from the use of
36 * these programs.
37 *
38 * This disclaimer of warranty extends to the user of these programs and
39 * user's customers, employees, agents, transferees, successors, and
40 * assigns.
41 *
42 * The University of British Columbia does not represent or warrant that the
43 * programs furnished hereunder are free of infringement of any
44 * third-party patents.
45 *
46 * Commercial implementations of H.263, including shareware, are subject to
47 * royalty fees to patent holders. Many of these patents are general
48 * enough such that they are unavoidable regardless of implementation
49 * design.
50 *
51 */
52
53
54
55 /* modified to support annex O true B frames, mikeg@ee.ubc.ca
56 *
57 * based on mpeg2decode, (C) 1994, MPEG Software Simulation Group and
58 * mpeg2play, (C) 1994 Stefan Eckart <stefan@lis.e-technik.tu-muenchen.de>
59 *
60 */
61
62
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <ctype.h>
66 #include <fcntl.h>
67 #include <string.h>
68 #define GLOBAL
69 #include "config.h"
70 #include "tmndec.h"
71 #include "global.h"
72
73 #ifdef USE_TIME
74 #ifndef WIN32
75 #include <sys/time.h>
76 #else
77 #include <windows.h>
78 #endif
79 #endif
80 #ifdef WIN32
81 #include <io.h>
82 #endif
83
84
85
86 #ifdef WINDOWS
87 int initDisplay (int pels, int lines);
88 int closeDisplay ();
89 #endif
90
91 /* private prototypes */
92 static void initdecoder _ANSI_ARGS_ ((void));
93 static void options _ANSI_ARGS_ ((int *argcp, char **argvp[]));
94 static int getval _ANSI_ARGS_ ((char *argv[]));
95 static void flushdisplaybuffer _ANSI_ARGS_ ((int framenum));
96 /* private data */
97 static int loopflag;
98
99 #ifdef VIC
100
101 #include "libh263.h"
102
103 extern char *vic_packetbuf;
104
105 /* the decoder is'nt reentrant -- therefore I copy around the important
106 state information */
107
108 static struct CONF {
109 char *ptr;
110 int size;
111 } config[] = {
112 { (char*)(&next_I_P_frame), sizeof(char*)*3 },
113 { (char*)(&prev_I_P_frame), sizeof(char*)*3 },
114 { (char*)(¤t_frame), sizeof(char*)*3 },
115 { (char*)(&prev_frame), sizeof(char*)*3 },
116 { (char*)(&bframe), sizeof(char*)*3 },
117 { (char*)(&tmp_f), sizeof(char*)*3 },
118 { (char*)(&tmp_b), sizeof(char*)*3 },
119 { (char*)(&buffered_frame), sizeof(char*)*3 },
120 { (char*)(&edgeframeorig), sizeof(char*)*3 },
121 { (char*)(&nextedgeframeorig), sizeof(char*)*3 },
122 { (char*)(&ring_lum), sizeof(char*)*RING_SIZE },
123 { (char*)(&ring_c1), sizeof(char*)*RING_SIZE },
124 { (char*)(&ring_c2), sizeof(char*)*RING_SIZE },
125 { (char*)(&ring_tr), sizeof(int)*RING_SIZE },
126 { (char*)(&ring_qu), sizeof(int)*RING_SIZE },
127
128 { (char*)(&ring_ptr), sizeof(int) },
129 { (char*)(&coded_picture_width), sizeof(int) },
130 { (char*)(&coded_picture_height), sizeof(int) },
131 { (char*)(&reference_picture_selection_mode), sizeof(int) },
132 { (char*)(&stop_decoder), sizeof(int) },
133 { NULL }
134 };
135
136 static int current_conf;
137
138 static void save_conf(char *dest, struct CONF *conf)
139 {
140 int i,n;
141 for (i = 0, n = 0; conf[i].ptr != NULL; n += conf[i].size, i++)
142 memcpy(&dest[n],conf[i].ptr,conf[i].size);
143 }
144
145 static void restore_conf(char *src, struct CONF *conf)
146 {
147 int i,n;
148 for (i = 0, n = 0; conf[i].ptr != NULL; n += conf[i].size, i++)
149 memcpy(conf[i].ptr,&src[n],conf[i].size);
150 }
151
152 struct H263_STATE*
153 h263_start()
154 {
155 static int count = 0;
156 struct H263_STATE *state;
157
158 state = malloc(sizeof(struct H263_STATE));
159 memset(state,0,sizeof(struct H263_STATE));
160 state->conf = ++count;
161 return state;
162 }
163
164 void
165 h263_stop(struct H263_STATE *state)
166 {
167 int cc;
168
169 if (state->conf != current_conf)
170 restore_conf(state->conf_data,config);
171 current_conf = state->conf;
172
173 for (cc = 0; cc < 3; cc++) {
174 free(next_I_P_frame[cc]);
175 free(prev_I_P_frame[cc]);
176 free(bframe[cc]);
177 free(tmp_f[cc]);
178 free(tmp_b[cc]);
179 free(buffered_frame[cc]);
180 free(edgeframeorig[cc]);
181 free(nextedgeframeorig[cc]);
182 }
183 free(state);
184 }
185
186 int
187 h263_decode_frame(struct H263_STATE *state, char *packet)
188 {
189 if (0 == state->framenum) {
190 initoptions();
191 temp_ref = 0;
192 prev_non_disposable_temp_ref = next_non_disposable_temp_ref = 0;
193 ld = &base;
194 quiet = 0;
195 outtype = T_X11; /* no file output! */
196 outputname = "test263.txt";
197 stop_decoder = 1;
198 memset(ring_lum,0,sizeof(ring_lum));
199 } else if (state->conf != current_conf)
200 restore_conf(state->conf_data,config);
201 current_conf = state->conf;
202
203 vic_packetbuf = packet;
204 initbits ();
205
206 getheader();
207 if (pict_type == PCT_INTRA)
208 stop_decoder = 0;
209 if (0 == state->framenum) {
210 base_source_format = source_format;
211 initdecoder ();
212 if (stop_decoder) {
213 getpicture (&state->framenum);
214 state->framenum++;
215 save_conf(state->conf_data, config);
216 fprintf(stderr,"decoder start -- waiting for I-frame\n");
217 return -1;
218 }
219 }
220 if (stop_decoder)
221 return -1;
222 getpicture (&state->framenum);
223 state->framenum++;
224 save_conf(state->conf_data, config);
225
226 state->frame = buffered_frame;
227 state->width = coded_picture_width;
228 state->height = coded_picture_height;
229 return 0;
230 }
231
232 #else /* VIC */
233
234 int main (int argc, char *argv[])
235 {
236 int first, framenum;
237 #ifdef USE_TIME
238 int runtime;
239 #ifndef WIN32
240 struct timeval tstart, tstop;
241 #else
242 unsigned int startTime, stopTime;
243 #endif
244 #endif
245
246 #ifdef USE_TIME
247 /* default is read frame rate from bitstream */
248 framerate = 99;
249 #endif
250
251 options (&argc, &argv);
252
253 if (trace)
254 {
255 if ((trace_file = fopen (trace_file_name, "wt")) == NULL)
256 {
257 printf ("Unable to open trace file");
258 exit (-1);
259 }
260 }
261 if (save_frames)
262 {
263 if ((recon_file_ptr = fopen (recon_file_name, "wb")) == NULL)
264 {
265 printf ("Unable to open reconstruction file");
266 exit (-1);
267 }
268 }
269 /* pointer to name of output files */
270 #if (defined DISPLAY || defined WINDOWS)
271 if (outtype == T_X11 || outtype == T_WIN)
272 outputname = "";
273 else
274 #endif
275 outputname = argv[argc - 1];
276
277 ld = &base;
278
279 /* open MPEG input file(s) */
280 if (0 == strcmp(argv[1],"stdin"))
281 base.infile = 0;
282 else if ((base.infile = open (argv[1], O_RDONLY | O_BINARY)) < 0)
283 {
284 sprintf (errortext, "Input file %s not found\n", argv[1]);
285 error (errortext);
286 }
287 first = 1;
288
289 do
290 {
291 if (base.infile != 0)
292 lseek (base.infile, 0l, 0);
293 initbits ();
294 initoptions ();
295 framenum = 0;
296 temp_ref = 0;
297 prev_non_disposable_temp_ref = next_non_disposable_temp_ref = 0;
298
299 while (getheader ())
300 {
301 if (first)
302 {
303 base_source_format = source_format;
304 initdecoder ();
305 #ifdef USE_TIME
306 #ifndef WIN32
307 gettimeofday (&tstart, (struct timezone *) NULL);
308 if (framerate > 0)
309 gettimeofday (&tftarget, (struct timezone *) NULL);
310 #else
311 startTime = timeGetTime ();
312 if (framerate > 0)
313 targetTime = timeGetTime ();
314 #endif
315 #endif
316 first = 0;
317 }
318 getpicture (&framenum);
319
320 #if 0 /* for debugging */
321 if (trace)
322 fflush(trace_file);
323 getchar();
324 #endif
325
326 framenum++;
327 }
328
329 flushdisplaybuffer (framenum);
330
331 } while (loopflag);
332
333 close (base.infile);
334
335 #ifdef USE_TIME
336 #ifndef WIN32
337 gettimeofday (&tstop, (struct timezone *) NULL);
338 runtime = 100 * (tstop.tv_sec - tstart.tv_sec)
339 + (tstop.tv_usec - tstart.tv_usec) / 10000;
340 #else
341 stopTime = timeGetTime ();
342 runtime = (stopTime - startTime) / 10;
343 #endif
344 if (!quiet && runtime != 0)
345 printf ("%d.%02d seconds, %d frames, %d.%02d fps\n",
346 runtime / 100, runtime % 100,
347 framenum, ((10000 * framenum + runtime / 2) / runtime) / 100,
348 ((10000 * framenum + runtime / 2) / runtime) % 100);
349 #endif
350
351 #ifdef DISPLAY
352 if (outtype == T_X11)
353 exit_display ();
354 #endif
355 #ifdef WINDOWS
356 if (outtype == T_WIN)
357 closeDisplay ();
358 #endif
359
360 return 0;
361 }
362 #endif /* VIC */
363
364 static void initdecoder ()
365 {
366 int i, cc, size;
367 FILE *cleared;
368
369 /* clip table */
370 if (!(clp = (unsigned char *) malloc (1024)))
371 error ("malloc failed\n");
372
373 clp += 384;
374
375 for (i = -384; i < 640; i++)
376 clp[i] = (i < 0) ? 0 : ((i > 255) ? 255 : i);
377
378 /* MPEG-1 = TMN parameters */
379 matrix_coefficients = 5;
380
381 blk_cnt = 6;
382
383 for (i=0; i<MAX_LAYERS; i++)
384 enhancement_layer_init[i] = OFF;
385
386 for (cc = 0; cc < 3; cc++)
387 {
388 if (cc == 0)
389 size = coded_picture_width * coded_picture_height;
390 else
391 size = chrom_width * chrom_height;
392
393 /* Used for bidirectional and direct prediction mode for true B
394 * pictures, one for forward and one for backward. */
395 if (!(next_I_P_frame[cc] = (unsigned char *) malloc (size)))
396 error ("malloc failed\n");
397
398 if (!(prev_I_P_frame[cc] = (unsigned char *) malloc (size)))
399 error ("malloc failed\n");
400
401 #if 1
402 if (!(current_frame[cc] = (unsigned char *) malloc (size)))
403 error ("malloc failed\n");
404 #endif
405
406 if (!(bframe[cc] = (unsigned char *) malloc (size)))
407 error ("malloc failed\n");
408
409 prev_frame[cc] = current_frame[cc];
410
411 if (!(tmp_f[cc] = (unsigned char *) malloc (size)))
412 error ("malloc failed\n");
413
414 if (!(tmp_b[cc] = (unsigned char *) malloc (size)))
415 error ("malloc failed\n");
416
417 /* Stores frame in display buffer */
418 if (!(buffered_frame[cc] = (unsigned char *) malloc (size)))
419 error ("malloc failed\n");
420 }
421
422 for (cc = 0; cc < 3; cc++)
423 {
424 if (cc == 0)
425 {
426 size = (coded_picture_width + 64) * (coded_picture_height + 64);
427
428 /* Stores framed version of previous inter-picture, luminance. */
429 if (!(edgeframeorig[cc] = (unsigned char *) malloc (size)))
430 error ("malloc failed\n");
431 edgeframe[cc] = edgeframeorig[cc] + (coded_picture_width + 64) * 32 + 32;
432
433 /* Required for true B frames backward, bidir, and direct
434 * prediction. Stores future inter-picture, luminance */
435 if (!(nextedgeframeorig[cc] = (unsigned char *) malloc (size)))
436 error ("malloc failed\n");
437 nextedgeframe[cc] = nextedgeframeorig[cc] + (coded_picture_width + 64) * 32 + 32;
438 }
439 else
440 {
441 size = (chrom_width + 32) * (chrom_height + 32);
442
443 /* Stores framed version of previous inter-picture, chrominance. */
444 if (!(edgeframeorig[cc] = (unsigned char *) malloc (size)))
445 error ("malloc failed\n");
446 edgeframe[cc] = edgeframeorig[cc] + (chrom_width + 32) * 16 + 16;
447
448 /* Required for true B frames backward, bidir, and direct
449 * prediction. Stores future inter-picture, chrominance. */
450 if (!(nextedgeframeorig[cc] = (unsigned char *) malloc (size)))
451 error ("malloc failed\n");
452 nextedgeframe[cc] = nextedgeframeorig[cc] + (chrom_width + 32) * 16 + 16;
453 }
454 }
455
456 if (expand)
457 {
458 for (cc = 0; cc < 3; cc++)
459 {
460 if (cc == 0)
461 size = coded_picture_width * coded_picture_height * 4;
462 else
463 size = chrom_width * chrom_height * 4;
464
465 if (!(exnewframe[cc] = (unsigned char *) malloc (size)))
466 error ("malloc failed\n");
467 }
468 }
469 /* Clear output file for concatenated storing */
470 if (outtype == T_YUV_CONC)
471 {
472 if ((cleared = fopen (outputname, "wb")) == NULL)
473 error ("couldn't clear outputfile\n");
474 else
475 fclose (cleared);
476 }
477 /* IDCT */
478 if (refidct)
479 init_idctref ();
480 else
481 init_idct ();
482
483 #ifdef DISPLAY
484 if (outtype == T_X11)
485 {
486 init_display ("");
487 }
488 #endif
489 #ifdef WINDOWS
490 if (outtype == T_WIN)
491 {
492 initDisplay (coded_picture_width, coded_picture_height);
493 }
494 #endif
495
496
497 }
498
499 void error (char *text)
500 {
501 fprintf (stderr, text);
502 exit (1);
503 }
504
505 /* trace output */
506 void printbits (int code, int bits, int len)
507 {
508 int i;
509 for (i = 0; i < len; i++)
510 fprintf (trace_file, "%d", (code >> (bits - 1 - i)) & 1);
511 }
512
513 #ifndef VIC
514
515 /* option processing */
516 static void options (int *argcp, char **argvp[])
517 {
518 trace = 0;
519 save_frames = 0;
520
521 while (*argcp > 1 && (*argvp)[1][0] == '-')
522 {
523 while ((*argvp)[1][1])
524 {
525 switch (toupper ((*argvp)[1][1]))
526 {
527 #ifdef USE_TIME
528 case 'F':
529 framerate = getval (*argvp);
530 break;
531 #endif
532 case 'V':
533 verbose = getval (*argvp);
534 break;
535 case 'O':
536 outtype = getval (*argvp);
537 break;
538 case 'R':
539 refidct = 1;
540 break;
541 case 'L':
542 loopflag = 1;
543 break;
544 case 'X':
545 expand = 1;
546 break;
547 case 'T':
548 trace = 1;
549 strcpy (trace_file_name, "trace.dec");
550 break;
551 case 'S':
552 save_frames = 1;
553 (*argvp)++;
554 (*argcp)--;
555 strcpy (recon_file_name, (*argvp)[1]);
556 (*argvp)[1] += strlen (recon_file_name);
557 if (recon_file_name[0] == '-')
558 {
559 printf ("Reconstruction file name is expected after -S option");
560 exit (-1);
561 }
562 break;
563
564 case 'Q':
565 quiet = 1;
566 break;
567 case 'P':
568 post_filter = 1;
569 break;
570
571 default:
572 fprintf (stderr, "undefined option -%c ignored\n", (*argvp)[1][1]);
573 }
574
575 (*argvp)[1]++;
576 }
577
578 (*argvp)++;
579 (*argcp)--;
580 }
581
582
583 if (outtype != T_X11 && outtype != T_WIN)
584 {
585 loopflag = 0; /* No looping for output to file */
586 #ifdef USE_TIME
587 framerate = 0; /* No delay necessary when output to file */
588 #endif
589 }
590 #ifdef DISPLAY
591 if (outtype == T_X11)
592 {
593 (*argcp)++; /* fake outfile parameter */
594 }
595 #endif
596 #ifdef WINDOWS
597 if (outtype == T_WIN)
598 {
599 (*argcp)++; /* fake outfile parameter */
600 }
601 #endif
602
603 if (*argcp != 3 && *argcp != 4)
604 {
605 printf ("\n%s\n", version);
606 printf ("Usage: tmndecode {options} bitstream {outputfilename%%d}\n\
607 Options: -vn verbose output (n: level)\n\
608 -on output format \n\
609 n=0 : YUV\n\
610 n=1 : SIF\n\
611 n=2 : TGA\n\
612 n=3 : PPM\n");
613 #ifdef DISPLAY
614 printf ("\
615 n=4 : X11 Display\n");
616 #endif
617 printf ("\
618 n=5 : YUV concatenated\n");
619 #ifdef WINDOWS
620 printf ("\
621 n=6 : Windows 95/NT Display\n");
622 #endif
623 printf ("\
624 You have to choose one output format!\n\
625 -q disable warnings to stderr\n\
626 -r use double precision reference IDCT\n\
627 -t enable low level tracing\n\
628 -s <filename> output reconstructed frame to filename (YUV concatenated)\n\
629 -p enable tmn-8 post filter\n");
630 #ifdef DISPLAY
631 printf ("\
632 -x interpolate pictures to double size before display\n");
633 #endif
634 #ifdef USE_TIME
635 printf ("\
636 -fn frame rate\n\
637 n=0 : as fast as possible\n\
638 n=99 : read frame rate from bitstream (default)\n");
639 #endif
640 #ifdef DISPLAY
641 printf ("\
642 -l loop sequence\n");
643 #endif
644 exit (0);
645 }
646 }
647
648 #endif /* VIC */
649
650 static int getval (char *argv[])
651 {
652 int val;
653
654 if (sscanf (argv[1] + 2, "%d", &val) != 1)
655 return 0;
656
657 while (isdigit (argv[1][2]))
658 argv[1]++;
659
660 return val;
661 }
662
663
664
665 #ifdef USE_TIME
666 #ifndef WINDOWS
667
668 /* Unix version */
669 void doframerate (int pb)
670 {
671 struct timeval tfdiff;
672 const float REF_FRAME_RATE = 29.97;
673
674 /* Compute desired frame rate */
675 if (framerate <= 0)
676 return;
677
678 if (framerate != 99)
679 {
680 tftarget.tv_usec += 1000000 / framerate;
681 } else
682 {
683 if (pb)
684 {
685 tftarget.tv_usec += 1000000 / (REF_FRAME_RATE / trb);
686 } else
687 {
688 tftarget.tv_usec += 1000000 / (REF_FRAME_RATE / (trd - trb));
689 }
690 }
691
692 /* this is where we should be */
693 if (tftarget.tv_usec >= 1000000)
694 {
695 tftarget.tv_usec -= 1000000;
696 tftarget.tv_sec++;
697 }
698 /* this is where we are */
699 gettimeofday (&tfdiff, (struct timezone *) NULL);
700
701 tfdiff.tv_usec = tftarget.tv_usec - tfdiff.tv_usec;
702 tfdiff.tv_sec = tftarget.tv_sec - tfdiff.tv_sec;
703 if (tfdiff.tv_usec < 0)
704 {
705 tfdiff.tv_usec += 1000000;
706 tfdiff.tv_sec--;
707 }
708 /* See if we are already lagging behind */
709 if (tfdiff.tv_sec < 0 || (tfdiff.tv_sec == 0 && tfdiff.tv_usec <= 0))
710 return;
711
712 /* Spin for awhile */
713 select (0, NULL, NULL, NULL, &tfdiff);
714 }
715
716 #else
717
718 /* Win32 version */
719 void doframerate (int pb)
720 {
721 DWORD currentTime;
722 int diffTime;
723 const float REF_FRAME_RATE = (float) 29.97;
724
725 /* Compute desired frame rate */
726 if (framerate <= 0)
727 return;
728
729 if (framerate != 99)
730 {
731 targetTime += 1000 / framerate;
732 } else
733 {
734 if (pb)
735 {
736 targetTime += (int) (1000 / (REF_FRAME_RATE / trb));
737 } else
738 {
739 targetTime += (int) (1000 / (REF_FRAME_RATE / (trd - trb)));
740 }
741 }
742
743 /* this is where we are */
744 currentTime = timeGetTime ();
745
746
747 diffTime = targetTime - currentTime;
748
749 /* See if we are already lagging behind */
750 if (diffTime <= 0)
751 return;
752
753 /* Spin for awhile */
754 Sleep (diffTime);
755 /* this is not a very accurate timer */
756 }
757
758 #endif
759
760 #endif
761
762 /**********************************************************************
763 *
764 * Name: flushdisplaybuffer
765 * Description: empties last frame from display buffer when sequence
766 * fully decoded
767 * Input: frame number
768 * Returns:
769 * Side effects:
770 *
771 * Date: 971102 Author: mikeg@ee.ubc.ca
772 *
773 ***********************************************************************/
774
775 void flushdisplaybuffer (int framenum)
776 {
777
778 /* Ensure the dimensions are set properly for displaying the last picture in
779 * the display buffer */
780 coded_picture_width = horizontal_size = lines[base_source_format];
781 coded_picture_height = vertical_size = pels[base_source_format];
782
783 mb_width = horizontal_size / 16;
784 mb_height = vertical_size / 16;
785 chrom_width = coded_picture_width >> 1;
786 chrom_height = coded_picture_height >> 1;
787
788 if (expand && outtype == T_X11)
789 {
790 /* display this image and keep frame already in storage where it is. */
791 interpolate_image (buffered_frame[0], exnewframe[0],
792 coded_picture_width, coded_picture_height);
793 interpolate_image (buffered_frame[1], exnewframe[1], chrom_width, chrom_height);
794 interpolate_image (buffered_frame[2], exnewframe[2], chrom_width, chrom_height);
795
796 storeframe (exnewframe, framenum);
797 if (save_frames)
798 {
799 save_frame (exnewframe, framenum, recon_file_ptr);
800 }
801 } else
802 {
803 storeframe (buffered_frame, framenum);
804 if (save_frames)
805 {
806 save_frame (buffered_frame, framenum, recon_file_ptr);
807 }
808 }
809 }
810
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.