doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
roq.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 #include "../../../idlib/precompiled.h"
29 #pragma hdrstop
30 
31 #include "roq.h"
32 #include "codec.h"
33 
34 roq *theRoQ; // current roq file
35 
36 roq::roq( void )
37 {
38  image = 0;
39  quietMode = false;
40  encoder = 0;
41  previousSize = 0;
42  lastFrame = false;
43  dataStuff=false;
44 }
45 
46 roq::~roq( void )
47 {
48  if (image) delete image;
49  if (encoder) delete encoder;
50  return;
51 }
52 
53 void roq::EncodeQuietly( bool which )
54 {
55  quietMode = which;
56 }
57 
58 bool roq::IsQuiet( void )
59 {
60  return quietMode;
61 }
62 
63 bool roq::IsLastFrame( void )
64 {
65  return lastFrame;
66 }
67 
68 bool roq::Scaleable( void )
69 {
70  return paramFile->IsScaleable();
71 }
72 
73 bool roq::ParamNoAlpha( void )
74 {
75  return paramFile->NoAlpha();
76 }
77 
78 bool roq::MakingVideo( void )
79 {
80  return true; //paramFile->timecode];
81 }
82 
83 bool roq::SearchType( void )
84 {
85  return paramFile->SearchType();
86 }
87 
88 bool roq::HasSound( void )
89 {
90  return paramFile->HasSound();
91 }
92 
94 {
95  return previousSize;
96 }
97 
99 {
100  return paramFile->FirstFrameSize();
101 }
102 
104 {
105  return paramFile->NormalFrameSize();
106 }
107 
108 const char * roq::CurrentFilename( void )
109 {
110  return currentFile.c_str();
111 }
112 
113 void roq::EncodeStream( const char *paramInputFile )
114 {
115  int onFrame;
116  idStr f0, f1, f2;
117  int morestuff;
118 
119  onFrame = 1;
120 
121  encoder = new codec;
122  paramFile = new roqParam;
124 
125  paramFile->InitFromFile( paramInputFile );
126 
127  if (!paramFile->NumberOfFrames()) {
128  return;
129  }
130 
132 
134 
135  if (paramFile->NoAlpha()==true) common->Printf("encodeStream: eluding alpha\n");
136 
137  f0 = "";
139  if (( paramFile->MoreFrames() == true )) {
141  }
142  morestuff = numberOfFrames;
143 
144  while( morestuff ) {
145  LoadAndDisplayImage( f1 );
146 
147  if (onFrame==1) {
149 // WriteLossless();
150  } else {
151  if (!strcmp( f0, f1 ) && strcmp( f1, f2) ) {
152  WriteHangFrame();
153  } else {
155  }
156  }
157 
158  onFrame++;
159  f0 = f1;
160  f1 = f2;
161  if (paramFile->MoreFrames() == true) {
163  }
164  morestuff--;
166  }
167 
168 // if (numberOfFrames != 1) {
169 // if (image->hasAlpha() && paramFile->NoAlpha()==false) {
170 // lastFrame = true;
171 // encoder->SparseEncode();
172 // } else {
173 // WriteLossless();
174 // }
175 // }
176  CloseRoQFile();
177 }
178 
179 void roq::Write16Word( word *aWord, idFile *stream )
180 {
181  byte a, b;
182 
183  a = *aWord & 0xff;
184  b = *aWord >> 8;
185 
186  stream->Write( &a, 1 );
187  stream->Write( &b, 1 );
188 }
189 
190 void roq::Write32Word( unsigned int *aWord, idFile *stream )
191 {
192  byte a, b, c, d;
193 
194  a = *aWord & 0xff;
195  b = (*aWord >> 8) & 0xff;
196  c = (*aWord >> 16) & 0xff;
197  d = (*aWord >> 24) & 0xff;
198 
199  stream->Write( &a, 1 );
200  stream->Write( &b, 1 );
201  stream->Write( &c, 1 );
202  stream->Write( &d, 1 );
203 }
204 
205 int roq::SizeFile( idFile *ftosize )
206 {
207  return ftosize->Length();
208 }
209 
210 /* Expanded data destination object for stdio output */
211 
212 typedef struct {
213  struct jpeg_destination_mgr pub; /* public fields */
214 
215  byte* outfile; /* target stream */
216  int size;
218 
220 
221 
222 /*
223  * Initialize destination --- called by jpeg_start_compress
224  * before any data is actually written.
225  */
226 
228  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
229 
230  dest->pub.next_output_byte = dest->outfile;
231  dest->pub.free_in_buffer = dest->size;
232 }
233 
234 
235 /*
236  * Empty the output buffer --- called whenever buffer fills up.
237  *
238  * In typical applications, this should write the entire output buffer
239  * (ignoring the current state of next_output_byte & free_in_buffer),
240  * reset the pointer & count to the start of the buffer, and return true
241  * indicating that the buffer has been dumped.
242  *
243  * In applications that need to be able to suspend compression due to output
244  * overrun, a FALSE return indicates that the buffer cannot be emptied now.
245  * In this situation, the compressor will return to its caller (possibly with
246  * an indication that it has not accepted all the supplied scanlines). The
247  * application should resume compression after it has made more room in the
248  * output buffer. Note that there are substantial restrictions on the use of
249  * suspension --- see the documentation.
250  *
251  * When suspending, the compressor will back up to a convenient restart point
252  * (typically the start of the current MCU). next_output_byte & free_in_buffer
253  * indicate where the restart point will be if the current call returns FALSE.
254  * Data beyond this point will be regenerated after resumption, so do not
255  * write it out when emptying the buffer externally.
256  */
257 
259  return true;
260 }
261 
262 
263 /*
264  * Compression initialization.
265  * Before calling this, all parameters and a data destination must be set up.
266  *
267  * We require a write_all_tables parameter as a failsafe check when writing
268  * multiple datastreams from the same compression object. Since prior runs
269  * will have left all the tables marked sent_table=true, a subsequent run
270  * would emit an abbreviated stream (no tables) by default. This may be what
271  * is wanted, but for safety's sake it should not be the default behavior:
272  * programmers should have to make a deliberate choice to emit abbreviated
273  * images. Therefore the documentation and examples should encourage people
274  * to pass write_all_tables=true; then it will take active thought to do the
275  * wrong thing.
276  */
277 
278 void roq::JPEGStartCompress (j_compress_ptr cinfo, bool write_all_tables) {
279  if (cinfo->global_state != CSTATE_START)
280  ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
281 
282  if (write_all_tables)
283  jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */
284 
285  /* (Re)initialize error mgr and destination modules */
286  (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
287  (*cinfo->dest->init_destination) (cinfo);
288  /* Perform master selection of active modules */
289  jinit_compress_master(cinfo);
290  /* Set up for the first pass */
291  (*cinfo->master->prepare_for_pass) (cinfo);
292  /* Ready for application to drive first pass through jpeg_write_scanlines
293  * or jpeg_write_raw_data.
294  */
295  cinfo->next_scanline = 0;
296  cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING);
297 }
298 
299 
300 /*
301  * Write some scanlines of data to the JPEG compressor.
302  *
303  * The return value will be the number of lines actually written.
304  * This should be less than the supplied num_lines only in case that
305  * the data destination module has requested suspension of the compressor,
306  * or if more than image_height scanlines are passed in.
307  *
308  * Note: we warn about excess calls to jpeg_write_scanlines() since
309  * this likely signals an application programmer error. However,
310  * excess scanlines passed in the last valid call are *silently* ignored,
311  * so that the application need not adjust num_lines for end-of-image
312  * when using a multiple-scanline buffer.
313  */
314 
316  JDIMENSION row_ctr, rows_left;
317 
318  if (cinfo->global_state != CSTATE_SCANNING)
319  ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
320  if (cinfo->next_scanline >= cinfo->image_height)
321  WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
322 
323  /* Call progress monitor hook if present */
324  if (cinfo->progress != NULL) {
325  cinfo->progress->pass_counter = (long) cinfo->next_scanline;
326  cinfo->progress->pass_limit = (long) cinfo->image_height;
327  (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
328  }
329 
330  /* Give master control module another chance if this is first call to
331  * jpeg_write_scanlines. This lets output of the frame/scan headers be
332  * delayed so that application can write COM, etc, markers between
333  * jpeg_start_compress and jpeg_write_scanlines.
334  */
335  if (cinfo->master->call_pass_startup)
336  (*cinfo->master->pass_startup) (cinfo);
337 
338  /* Ignore any extra scanlines at bottom of image. */
339  rows_left = cinfo->image_height - cinfo->next_scanline;
340  if (num_lines > rows_left)
341  num_lines = rows_left;
342 
343  row_ctr = 0;
344  (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines);
345  cinfo->next_scanline += row_ctr;
346  return row_ctr;
347 }
348 
349 /*
350  * Terminate destination --- called by jpeg_finish_compress
351  * after all data has been written. Usually needs to flush buffer.
352  *
353  * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
354  * application must deal with any cleanup that should happen even
355  * for error exit.
356  */
357 
358 static int hackSize;
359 
361  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
362  size_t datacount = dest->size - dest->pub.free_in_buffer;
363  hackSize = datacount;
364 }
365 
366 
367 /*
368  * Prepare for output to a stdio stream.
369  * The caller must have already opened the stream, and is responsible
370  * for closing it after finishing compression.
371  */
372 
373 void roq::JPEGDest (j_compress_ptr cinfo, byte* outfile, int size) {
374  my_dest_ptr dest;
375 
376  /* The destination object is made permanent so that multiple JPEG images
377  * can be written to the same file without re-executing jpeg_stdio_dest.
378  * This makes it dangerous to use this manager and a different destination
379  * manager serially with the same JPEG object, because their private object
380  * sizes may be different. Caveat programmer.
381  */
382  if (cinfo->dest == NULL) { /* first time for this JPEG object? */
383  cinfo->dest = (struct jpeg_destination_mgr *)
384  (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
385  sizeof(my_destination_mgr));
386  }
387 
388  dest = (my_dest_ptr) cinfo->dest;
389  dest->pub.init_destination = JPEGInitDestination;
390  dest->pub.empty_output_buffer = JPEGEmptyOutputBuffer;
391  dest->pub.term_destination = JPEGTermDestination;
392  dest->outfile = outfile;
393  dest->size = size;
394 }
395 
396 void roq::WriteLossless( void ) {
397 
398  word direct;
399  uint directdw;
400 
401  if (!dataStuff) {
402  InitRoQPatterns();
403  dataStuff=true;
404  }
405  direct = RoQ_QUAD_JPEG;
406  Write16Word( &direct, RoQFile);
407 
408  /* This struct contains the JPEG compression parameters and pointers to
409  * working space (which is allocated as needed by the JPEG library).
410  * It is possible to have several such structures, representing multiple
411  * compression/decompression processes, in existence at once. We refer
412  * to any one struct (and its associated working data) as a "JPEG object".
413  */
414  struct jpeg_compress_struct cinfo;
415  /* This struct represents a JPEG error handler. It is declared separately
416  * because applications often want to supply a specialized error handler
417  * (see the second half of this file for an example). But here we just
418  * take the easy way out and use the standard error handler, which will
419  * print a message on stderr and call exit() if compression fails.
420  * Note that this struct must live as long as the main JPEG parameter
421  * struct, to avoid dangling-pointer problems.
422  */
423  struct jpeg_error_mgr jerr;
424  /* More stuff */
425  JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
426  int row_stride; /* physical row width in image buffer */
427  byte *out;
428 
429  /* Step 1: allocate and initialize JPEG compression object */
430 
431  /* We have to set up the error handler first, in case the initialization
432  * step fails. (Unlikely, but it could happen if you are out of memory.)
433  * This routine fills in the contents of struct jerr, and returns jerr's
434  * address which we place into the link field in cinfo.
435  */
436  cinfo.err = jpeg_std_error(&jerr);
437  /* Now we can initialize the JPEG compression object. */
438  jpeg_create_compress(&cinfo);
439 
440  /* Step 2: specify data destination (eg, a file) */
441  /* Note: steps 2 and 3 can be done in either order. */
442 
443  /* Here we use the library-supplied code to send compressed data to a
444  * stdio stream. You can also write your own code to do something else.
445  * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
446  * requires it in order to write binary files.
447  */
448  out = (byte *)Mem_Alloc(image->pixelsWide()*image->pixelsHigh()*4);
449  JPEGDest(&cinfo, out, image->pixelsWide()*image->pixelsHigh()*4);
450 
451  /* Step 3: set parameters for compression */
452 
453  /* First we supply a description of the input image.
454  * Four fields of the cinfo struct must be filled in:
455  */
456  cinfo.image_width = image->pixelsWide(); /* image width and height, in pixels */
457  cinfo.image_height = image->pixelsHigh();
458  cinfo.input_components = 4; /* # of color components per pixel */
459  cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
460  /* Now use the library's routine to set default compression parameters.
461  * (You must set at least cinfo.in_color_space before calling this,
462  * since the defaults depend on the source color space.)
463  */
464  jpeg_set_defaults(&cinfo);
465  /* Now you can set any non-default parameters you wish to.
466  * Here we just illustrate the use of quality (quantization table) scaling:
467  */
468  jpeg_set_quality(&cinfo, paramFile->JpegQuality(), true /* limit to baseline-JPEG values */);
469 
470  /* Step 4: Start compressor */
471 
472  /* true ensures that we will write a complete interchange-JPEG file.
473  * Pass true unless you are very sure of what you're doing.
474  */
475  JPEGStartCompress(&cinfo, true);
476 
477  /* Step 5: while (scan lines remain to be written) */
478  /* jpeg_write_scanlines(...); */
479 
480  /* Here we use the library's state variable cinfo.next_scanline as the
481  * loop counter, so that we don't have to keep track ourselves.
482  * To keep things simple, we pass one scanline per call; you can pass
483  * more if you wish, though.
484  */
485  row_stride = image->pixelsWide() * 4; /* JSAMPLEs per row in image_buffer */
486 
487  byte *pixbuf = image->bitmapData();
488  while (cinfo.next_scanline < cinfo.image_height) {
489  /* jpeg_write_scanlines expects an array of pointers to scanlines.
490  * Here the array is only one element long, but you could pass
491  * more than one scanline at a time if that's more convenient.
492  */
493  row_pointer[0] = &pixbuf[((cinfo.image_height-1)*row_stride)-cinfo.next_scanline * row_stride];
494  (void) JPEGWriteScanlines(&cinfo, row_pointer, 1);
495  }
496 
497  /* Step 6: Finish compression */
498 
499  jpeg_finish_compress(&cinfo);
500  /* After finish_compress, we can close the output file. */
501 
502  directdw = hackSize;
503  common->Printf("writeLossless: writing %d bytes to RoQ_QUAD_JPEG\n", hackSize);
504  Write32Word( &directdw, RoQFile );
505  direct = 0; // flags
506  Write16Word( &direct, RoQFile );
507 
508  RoQFile->Write( out, hackSize );
509  Mem_Free(out);
510 
511  /* Step 7: release JPEG compression object */
512 
513  /* This is an important step since it will release a good deal of memory. */
514  jpeg_destroy_compress(&cinfo);
515 
516  /* And we're done! */
517  encoder->SetPreviousImage( "first frame", image );
518 }
519 
520 void roq::InitRoQFile( const char *RoQFilename )
521 {
522  word i;
523  static int finit = 0;
524 
525  if (!finit) {
526  finit++;
527  common->Printf("initRoQFile: %s\n", RoQFilename);
528  RoQFile = fileSystem->OpenFileWrite( RoQFilename );
529 // chmod(RoQFilename, S_IREAD|S_IWRITE|S_ISUID|S_ISGID|0070|0007 );
530  if ( !RoQFile ) {
531  common->Error("Unable to open output file %s.\n", RoQFilename);
532  }
533 
534  i = RoQ_ID;
535  Write16Word( &i, RoQFile );
536 
537  i = 0xffff;
538  Write16Word( &i, RoQFile );
539  Write16Word( &i, RoQFile );
540 
541  // to retain exact file format write out 32 for new roq's
542  // on loading this will be noted and converted to 1000 / 30
543  // as with any new sound dump avi demos we need to playback
544  // at the speed the sound engine dumps the audio
545  i = 30; // framerate
546  Write16Word( &i, RoQFile );
547  }
548  roqOutfile = RoQFilename;
549 }
550 
552 {
553 uint j;
554 word direct;
555 
556  direct = RoQ_QUAD_INFO;
557  Write16Word( &direct, RoQFile );
558 
559  j = 8;
560 
561  Write32Word( &j, RoQFile );
562  common->Printf("initRoQPatterns: outputting %d bytes to RoQ_INFO\n", j);
563  direct = image->hasAlpha();
564  if (ParamNoAlpha() == true) direct = 0;
565 
566  Write16Word( &direct, RoQFile );
567 
568  direct = image->pixelsWide();
569  Write16Word( &direct, RoQFile );
570  direct = image->pixelsHigh();
571  Write16Word( &direct, RoQFile );
572  direct = 8;
573  Write16Word( &direct, RoQFile );
574  direct = 4;
575  Write16Word( &direct, RoQFile );
576 }
577 
578 void roq::CloseRoQFile( void )
579 {
580  common->Printf("closeRoQFile: closing RoQ file\n");
582 }
583 
585 {
586 uint j;
587 word direct;
588  common->Printf("*******************************************************************\n");
589  direct = RoQ_QUAD_HANG;
590  Write16Word( &direct, RoQFile);
591  j = 0;
592  Write32Word( &j, RoQFile);
593  direct = 0;
594  Write16Word( &direct, RoQFile);
595 }
596 
597 void roq::WriteCodeBookToStream( byte *codebook, int csize, word cflags )
598 {
599 uint j;
600 word direct;
601 
602  if (!csize) {
603  common->Printf("writeCodeBook: false VQ DATA!!!!\n");
604  return;
605  }
606 
607  direct = RoQ_QUAD_CODEBOOK;
608 
609  Write16Word( &direct, RoQFile);
610 
611  j = csize;
612 
613  Write32Word( &j, RoQFile);
614  common->Printf("writeCodeBook: outputting %d bytes to RoQ_QUAD_CODEBOOK\n", j);
615 
616  direct = cflags;
617  Write16Word( &direct, RoQFile);
618 
619  RoQFile->Write( codebook, j );
620 }
621 
623 {
624  memcpy( codes, codebook, 4096 );
625 }
626 
627 void roq::WriteFrame( quadcel *pquad )
628 {
629 word action, direct;
630 int onCCC, onAction, i, code;
631 uint j;
632 byte *cccList;
633 bool *use2, *use4;
634 int dx,dy,dxMean,dyMean,index2[256],index4[256], dimension;
635 
636  cccList = (byte *)Mem_Alloc( numQuadCels * 8); // maximum length
637  use2 = (bool *)Mem_Alloc(256*sizeof(bool));
638  use4 = (bool *)Mem_Alloc(256*sizeof(bool));
639 
640  for(i=0;i<256;i++) {
641  use2[i] = false;
642  use4[i] = false;
643  }
644 
645  action = 0;
646  j = onAction = 0;
647  onCCC = 2; // onAction going to go at zero
648 
649  dxMean = encoder->MotMeanX();
650  dyMean = encoder->MotMeanY();
651 
652  if (image->hasAlpha()) dimension = 10; else dimension = 6;
653 
654  for (i=0; i<numQuadCels; i++) {
655  if ( pquad[i].size && pquad[i].size < 16 ) {
656  switch( pquad[i].status ) {
657  case SLD:
658  use4[pquad[i].patten[0]] = true;
659  use2[codes[dimension*256+(pquad[i].patten[0]*4)+0]] = true;
660  use2[codes[dimension*256+(pquad[i].patten[0]*4)+1]] = true;
661  use2[codes[dimension*256+(pquad[i].patten[0]*4)+2]] = true;
662  use2[codes[dimension*256+(pquad[i].patten[0]*4)+3]] = true;
663  break;
664  case PAT:
665  use4[pquad[i].patten[0]] = true;
666  use2[codes[dimension*256+(pquad[i].patten[0]*4)+0]] = true;
667  use2[codes[dimension*256+(pquad[i].patten[0]*4)+1]] = true;
668  use2[codes[dimension*256+(pquad[i].patten[0]*4)+2]] = true;
669  use2[codes[dimension*256+(pquad[i].patten[0]*4)+3]] = true;
670  break;
671  case CCC:
672  use2[pquad[i].patten[1]] = true;
673  use2[pquad[i].patten[2]] = true;
674  use2[pquad[i].patten[3]] = true;
675  use2[pquad[i].patten[4]] = true;
676  }
677  }
678  }
679 
680  if (!dataStuff) {
681  dataStuff=true;
682  InitRoQPatterns();
683  if (image->hasAlpha()) i = 3584; else i = 2560;
684  WriteCodeBookToStream( codes, i, 0 );
685  for(i=0;i<256;i++) {
686  index2[i] = i;
687  index4[i] = i;
688  }
689  } else {
690  j = 0;
691  for(i=0;i<256;i++) {
692  if (use2[i]) {
693  index2[i] = j;
694  for(dx=0;dx<dimension;dx++) cccList[j*dimension+dx] = codes[i*dimension+dx];
695  j++;
696  }
697  }
698  code = j*dimension;
699  direct = j;
700  common->Printf("writeFrame: really used %d 2x2 cels\n", j);
701  j = 0;
702  for(i=0;i<256;i++) {
703  if (use4[i]) {
704  index4[i] = j;
705  for(dx=0;dx<4;dx++) cccList[j*4+code+dx] = index2[codes[i*4+(dimension*256)+dx]];
706  j++;
707  }
708  }
709  code += j*4;
710  direct = (direct<<8) + j;
711  common->Printf("writeFrame: really used %d 4x4 cels\n", j);
712  if (image->hasAlpha()) i = 3584; else i = 2560;
713  if ( code == i || j == 256) {
714  WriteCodeBookToStream( codes, i, 0 );
715  } else {
716  WriteCodeBookToStream( cccList, code, direct );
717  }
718  }
719 
720  action = 0;
721  j = onAction = 0;
722 
723  for (i=0; i<numQuadCels; i++) {
724  if ( pquad[i].size && pquad[i].size < 16 ) {
725  code = -1;
726  switch( pquad[i].status ) {
727  case DEP:
728  code = 3;
729  break;
730  case SLD:
731  code = 2;
732  cccList[onCCC++] = index4[pquad[i].patten[0]];
733  break;
734  case MOT:
735  code = 0;
736  break;
737  case FCC:
738  code = 1;
739  dx = ((pquad[i].domain >> 8 )) - 128 - dxMean + 8;
740  dy = ((pquad[i].domain & 0xff)) - 128 - dyMean + 8;
741  if (dx>15 || dx<0 || dy>15 || dy<0 ) {
742  common->Error("writeFrame: FCC error %d,%d mean %d,%d at %d,%d,%d rmse %f\n", dx,dy, dxMean, dyMean,pquad[i].xat,pquad[i].yat,pquad[i].size, pquad[i].snr[FCC] );
743  }
744  cccList[onCCC++] = (dx<<4)+dy;
745  break;
746  case PAT:
747  code = 2;
748  cccList[onCCC++] = index4[pquad[i].patten[0]];
749  break;
750  case CCC:
751  code = 3;
752  cccList[onCCC++] = index2[pquad[i].patten[1]];
753  cccList[onCCC++] = index2[pquad[i].patten[2]];
754  cccList[onCCC++] = index2[pquad[i].patten[3]];
755  cccList[onCCC++] = index2[pquad[i].patten[4]];
756  break;
757  case DEAD:
758  common->Error("dead cels in picture\n");
759  break;
760  }
761  if (code == -1) {
762  common->Error( "writeFrame: an error occurred writing the frame\n");
763  }
764 
765  action = (action<<2)|code;
766  j++;
767  if (j == 8) {
768  j = 0;
769  cccList[onAction+0] = (action & 0xff);
770  cccList[onAction+1] = ((action >> 8) & 0xff);
771  onAction = onCCC;
772  onCCC += 2;
773  }
774  }
775  }
776 
777  if (j) {
778  action <<= ((8-j)*2);
779  cccList[onAction+0] = (action & 0xff);
780  cccList[onAction+1] = ((action >> 8) & 0xff);
781  }
782 
783  direct = RoQ_QUAD_VQ;
784 
785  Write16Word( &direct, RoQFile);
786 
787  j = onCCC;
788  Write32Word( &j, RoQFile);
789 
790  direct = dyMean;
791  direct &= 0xff;
792  direct += (dxMean<<8); // flags
793 
794  Write16Word( &direct, RoQFile);
795 
796  common->Printf("writeFrame: outputting %d bytes to RoQ_QUAD_VQ\n", j);
797 
798  previousSize = j;
799 
800  RoQFile->Write( cccList, onCCC );
801 
802  Mem_Free( cccList );
803  Mem_Free( use2 );
804  Mem_Free( use4 );
805 }
806 
807 //
808 // load a frame, create a window (if neccesary) and display the frame
809 //
810 void roq::LoadAndDisplayImage( const char * filename )
811 {
812  if (image) delete image;
813 
814  common->Printf("loadAndDisplayImage: %s\n", filename);
815 
816  currentFile = filename;
817 
818  image = new NSBitmapImageRep( filename );
819 
820  numQuadCels = ((image->pixelsWide() & 0xfff0)*(image->pixelsHigh() & 0xfff0))/(MINSIZE*MINSIZE);
822 
823 // if (paramFile->deltaFrames] == true && cleared == false && [image isPlanar] == false) {
824 // cleared = true;
825 // imageData = [image data];
826 // memset( imageData, 0, image->pixelsWide()*image->pixelsHigh()*[image samplesPerPixel]);
827 // }
828 
829  if (!quietMode) common->Printf("loadAndDisplayImage: %dx%d\n", image->pixelsWide(), image->pixelsHigh());
830 }
831 
832 void roq::MarkQuadx( int xat, int yat, int size, float cerror, int choice ) {
833 }
834 
836 {
837  return image;
838 }
839 
840 int roq::NumberOfFrames( void ) {
841  return numberOfFrames;
842 }
843 
844 void RoQFileEncode_f( const idCmdArgs &args ) {
845  if ( args.Argc() != 2 ) {
846  common->Printf( "Usage: roq <paramfile>\n" );
847  return;
848  }
849  theRoQ = new roq;
850  int startMsec = Sys_Milliseconds();
851  theRoQ->EncodeStream( args.Argv( 1 ) );
852  int stopMsec = Sys_Milliseconds();
853  common->Printf( "total encoding time: %i second\n", ( stopMsec - startMsec ) / 1000 );
854 
855 }
roqParam * paramFile
Definition: roq.h:117
#define strcmp
Definition: Str.h:41
void SetPreviousImage(const char *filename, NSBitmapImageRep *timage)
Definition: codec.cpp:362
bool SearchType(void)
Definition: roqParam.cpp:506
unsigned int uint
Definition: Lib.h:78
#define CSTATE_START
Definition: jpegint.h:25
JSAMPLE FAR * JSAMPROW
Definition: jpeglib.h:79
bool IsLastFrame(void)
Definition: roq.cpp:63
byte * outfile
Definition: roq.cpp:215
#define RoQ_QUAD_JPEG
Definition: quaddefs.h:68
bool IsQuiet(void)
Definition: roq.cpp:58
void SparseEncode(void)
Definition: codec.cpp:1091
#define PAT
Definition: quaddefs.h:37
int previousSize
Definition: roq.h:127
roq * theRoQ
Definition: roq.cpp:34
void InitRoQFile(const char *roqFilename)
Definition: roq.cpp:520
struct jpeg_common_struct * j_common_ptr
Definition: jpeglib.h:260
void Write32Word(unsigned int *aWord, idFile *stream)
Definition: roq.cpp:190
bool NoAlpha(void)
Definition: roqParam.cpp:502
bool HasSound(void)
Definition: roqParam.cpp:494
#define MOT
Definition: quaddefs.h:38
size_t free_in_buffer
Definition: jpeglib.h:702
#define RoQ_QUAD_VQ
Definition: quaddefs.h:67
int Sys_Milliseconds(void)
JDIMENSION image_height
Definition: jpeglib.h:279
idFileSystem * fileSystem
Definition: FileSystem.cpp:500
void WriteCodeBookToStream(byte *codebook, int csize, word cflags)
Definition: roq.cpp:597
void JPEGDest(j_compress_ptr cinfo, byte *outfile, int size)
Definition: roq.cpp:373
bool SearchType(void)
Definition: roq.cpp:83
GLenum GLsizei GLenum GLenum const GLvoid * image
Definition: glext.h:2855
GLOBAL void jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress)
Definition: jcapimin.c:104
void WriteCodeBook(byte *codebook)
Definition: roq.cpp:622
static void JPEGInitDestination(j_compress_ptr cinfo)
Definition: roq.cpp:227
void InitRoQPatterns(void)
Definition: roq.cpp:551
void JPEGStartCompress(j_compress_ptr cinfo, bool write_all_tables)
Definition: roq.cpp:278
#define DEAD
Definition: quaddefs.h:39
int NumberOfFrames(void)
Definition: roq.cpp:840
#define CSTATE_RAW_OK
Definition: jpegint.h:27
int JpegQuality(void)
Definition: roqParam.cpp:538
void LoadAndDisplayImage(const char *filename)
Definition: roq.cpp:810
#define CSTATE_SCANNING
Definition: jpegint.h:26
boolean call_pass_startup
Definition: jpegint.h:51
#define DEP
Definition: quaddefs.h:33
int i
Definition: process.py:33
J_COLOR_SPACE in_color_space
Definition: jpeglib.h:281
JDIMENSION next_scanline
Definition: jpeglib.h:351
GLOBAL void jinit_compress_master(j_compress_ptr cinfo)
Definition: jcinit.c:30
void RoQFileEncode_f(const idCmdArgs &args)
Definition: roq.cpp:844
struct jpeg_destination_mgr pub
Definition: jdatadst.c:26
int numberOfFrames
Definition: roq.h:126
Definition: File.h:50
int MotMeanY(void)
Definition: codec.cpp:1086
#define FCC
Definition: quaddefs.h:34
JDIMENSION JPEGWriteScanlines(j_compress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION num_lines)
Definition: roq.cpp:315
static void JPEGTermDestination(j_compress_ptr cinfo)
Definition: roq.cpp:360
const GLubyte * c
Definition: glext.h:4677
#define SLD
Definition: quaddefs.h:36
static boolean JPEGEmptyOutputBuffer(j_compress_ptr cinfo)
Definition: roq.cpp:258
bool Scaleable(void)
Definition: roq.cpp:68
const char * CurrentFilename(void)
Definition: roq.cpp:108
idCommon * common
Definition: Common.cpp:206
#define NULL
Definition: Lib.h:88
GLOBAL void jpeg_finish_compress(j_compress_ptr cinfo)
Definition: jcapimin.c:132
void InitFromFile(const char *fileName)
Definition: roqParam.cpp:40
codec * encoder
Definition: roq.h:116
struct jpeg_destination_mgr * dest
Definition: jpeglib.h:271
virtual idFile * OpenFileWrite(const char *relativePath, const char *basePath="fs_savepath")=0
int FirstFrameSize(void)
Definition: roqParam.cpp:526
const char * GetNextImageFilename(void)
Definition: roqParam.cpp:439
Definition: codec.h:45
#define RoQ_ID
Definition: quaddefs.h:61
word patten[5]
Definition: quaddefs.h:100
#define CCC
Definition: quaddefs.h:35
struct jpeg_c_main_controller * main
Definition: jpeglib.h:393
int Argc(void) const
Definition: CmdArgs.h:48
#define WARNMS(cinfo, code)
Definition: jerror.h:226
void Mem_Free(void *ptr)
Definition: Heap.cpp:1087
int MotMeanX(void)
Definition: codec.cpp:1081
#define RoQ_QUAD_CODEBOOK
Definition: quaddefs.h:69
GLOBAL void jpeg_set_quality(j_compress_ptr cinfo, int quality, boolean force_baseline)
Definition: jcparam.c:128
GLubyte GLubyte GLubyte a
Definition: glext.h:4662
virtual void UpdateScreen(bool outOfSequence=true)=0
virtual void Printf(const char *fmt,...) id_attribute((format(printf
int FirstFrameSize(void)
Definition: roq.cpp:98
#define ERREXIT1(cinfo, code, p1)
Definition: jerror.h:196
int NormalFrameSize(void)
Definition: roqParam.cpp:530
NSBitmapImageRep * CurrentImage(void)
Definition: roq.cpp:835
int SizeFile(idFile *ftosize)
Definition: roq.cpp:205
~roq()
Definition: roq.cpp:46
void EncodeQuietly(bool which)
Definition: roq.cpp:53
void Write16Word(word *aWord, idFile *stream)
Definition: roq.cpp:179
word domain
Definition: quaddefs.h:99
#define RoQ_QUAD_INFO
Definition: quaddefs.h:66
bool HasSound(void)
Definition: roq.cpp:88
GLubyte GLubyte b
Definition: glext.h:4662
JSAMPROW * JSAMPARRAY
Definition: jpeglib.h:80
void MarkQuadx(int xat, int yat, int size, float cerror, int choice)
Definition: roq.cpp:832
bool dataStuff
Definition: roq.h:129
bool quietMode
Definition: roq.h:122
Definition: roq.h:69
unsigned short word
Definition: Lib.h:76
unsigned char byte
Definition: Lib.h:75
GLOBAL void jpeg_create_compress(j_compress_ptr cinfo)
Definition: jcapimin.c:30
void EncodeStream(const char *paramInputFile)
Definition: roq.cpp:113
GLsizeiptr size
Definition: glext.h:3112
virtual int Write(const void *buffer, int len)
Definition: File.cpp:189
Definition: Str.h:116
int PreviousFrameSize(void)
Definition: roq.cpp:93
int NormalFrameSize(void)
Definition: roq.cpp:103
const int MINSIZE
Definition: Cinematic.cpp:120
roq()
Definition: roq.cpp:36
GLOBAL struct jpeg_error_mgr * jpeg_std_error(struct jpeg_error_mgr *err)
Definition: jerror.c:213
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
const char * c_str(void) const
Definition: Str.h:487
#define FALSE
Definition: mprintf.c:70
idFile * RoQFile
Definition: roq.h:119
idStr currentFile
Definition: roq.h:125
int NumberOfFrames(void)
Definition: roqParam.cpp:522
int numInputFiles
Definition: roqParam.h:59
#define JPOOL_PERMANENT
Definition: jpeglib.h:735
const char * Argv(int arg) const
Definition: CmdArgs.h:50
GLOBAL void jpeg_destroy_compress(j_compress_ptr cinfo)
Definition: jcapimin.c:73
unsigned int JDIMENSION
Definition: jmorecfg.h:177
idStr roqOutfile
Definition: roq.h:124
void * Mem_Alloc(const int size)
Definition: Heap.cpp:1067
void CloseRoQFile(void)
Definition: roq.cpp:578
#define RoQ_QUAD_HANG
Definition: quaddefs.h:64
GLint j
Definition: qgl.h:264
void WriteHangFrame(void)
Definition: roq.cpp:584
void WriteFrame(quadcel *pquad)
Definition: roq.cpp:627
idStr outputFilename
Definition: roqParam.h:58
bool MoreFrames(void)
Definition: roqParam.cpp:510
boolean raw_data_in
Definition: jpeglib.h:319
GLOBAL void jpeg_set_defaults(j_compress_ptr cinfo)
Definition: jcparam.c:250
idSession * session
Definition: Session.cpp:48
virtual void CloseFile(idFile *f)=0
bool MakingVideo(void)
Definition: roq.cpp:78
my_destination_mgr * my_dest_ptr
Definition: roq.cpp:219
bool lastFrame
Definition: roq.h:123
virtual void Error(const char *fmt,...) id_attribute((format(printf
bool ParamNoAlpha(void)
Definition: roq.cpp:73
int numQuadCels
Definition: roq.h:121
byte codes[4096]
Definition: roq.h:128
JOCTET * next_output_byte
Definition: jpeglib.h:701
void WriteLossless(void)
Definition: roq.cpp:396
NSBitmapImageRep * image
Definition: roq.h:120
virtual int Length(void)
Definition: File.cpp:199
struct jpeg_comp_master * master
Definition: jpeglib.h:392
bool IsScaleable(void)
Definition: roqParam.cpp:534
JDIMENSION image_width
Definition: jpeglib.h:278