Blender  V2.59
mjpeg.c
Go to the documentation of this file.
00001 /*
00002  * $Id: mjpeg.c 35249 2011-02-27 20:43:42Z jesterking $
00003  *
00004  * This is external code. Converts between avi and mpeg/jpeg.
00005  *
00006  * ***** BEGIN GPL LICENSE BLOCK *****
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License
00010  * as published by the Free Software Foundation; either version 2
00011  * of the License, or (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software Foundation,
00020  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00021  *
00022  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00023  * All rights reserved.
00024  *
00025  * The Original Code is: all of this file.
00026  *
00027  * Contributor(s): none yet.
00028  *
00029  * ***** END GPL LICENSE BLOCK *****
00030  *
00031  */
00032 
00038 #include "AVI_avi.h"
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include "jpeglib.h"
00042 #include "jerror.h"
00043 #include "MEM_guardedalloc.h"
00044 
00045 #include "mjpeg.h"
00046 
00047 #define PADUP(num, amt) ((num+(amt-1))&~(amt-1))
00048 
00049 static void jpegmemdestmgr_build (j_compress_ptr cinfo, unsigned char *buffer, int bufsize);
00050 static void jpegmemsrcmgr_build (j_decompress_ptr dinfo, unsigned char *buffer, int bufsize);
00051 
00052 static int numbytes;
00053 
00054 static void add_huff_table (j_decompress_ptr dinfo, JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) {
00055         if (*htblptr == NULL)
00056                 *htblptr = jpeg_alloc_huff_table((j_common_ptr) dinfo);
00057 
00058         memcpy((*htblptr)->bits, bits, sizeof((*htblptr)->bits));
00059         memcpy((*htblptr)->huffval, val, sizeof((*htblptr)->huffval));
00060 
00061         /* Initialize sent_table FALSE so table will be written to JPEG file. */
00062         (*htblptr)->sent_table = FALSE;
00063 }
00064 
00065 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
00066 /* IMPORTANT: these are only valid for 8-bit data precision! */
00067 
00068 static void std_huff_tables (j_decompress_ptr dinfo) {
00069         static const UINT8 bits_dc_luminance[17] =
00070         { /* 0-base */
00071                 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0       };
00072         static const UINT8 val_dc_luminance[] =
00073         { 
00074                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11    };
00075 
00076         static const UINT8 bits_dc_chrominance[17] =
00077         { /* 0-base */
00078                 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0       };
00079         static const UINT8 val_dc_chrominance[] =
00080         { 
00081                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11    };
00082 
00083         static const UINT8 bits_ac_luminance[17] =
00084         { /* 0-base */
00085                 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d    };
00086         static const UINT8 val_ac_luminance[] =
00087         { 
00088                 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
00089                 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
00090                 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
00091                 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
00092                 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
00093                 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
00094                 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
00095                 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
00096                 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
00097                 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
00098                 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
00099                 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
00100                 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
00101                 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
00102                 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
00103                 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
00104                 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
00105                 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
00106                 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
00107                 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
00108                 0xf9, 0xfa      };
00109         static const UINT8 bits_ac_chrominance[17] =
00110         { /* 0-base */
00111                 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77    };
00112         static const UINT8 val_ac_chrominance[] =
00113         { 
00114                 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
00115                 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
00116                 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
00117                 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
00118                 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
00119                 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
00120                 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
00121                 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
00122                 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
00123                 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
00124                 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
00125                 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
00126                 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
00127                 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
00128                 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
00129                 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
00130                 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
00131                 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
00132                 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
00133                 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
00134                 0xf9, 0xfa      };
00135 
00136         add_huff_table(dinfo, &dinfo->dc_huff_tbl_ptrs[0],
00137                 bits_dc_luminance, val_dc_luminance);
00138         add_huff_table(dinfo, &dinfo->ac_huff_tbl_ptrs[0],
00139                 bits_ac_luminance, val_ac_luminance);
00140         add_huff_table(dinfo, &dinfo->dc_huff_tbl_ptrs[1],
00141                 bits_dc_chrominance, val_dc_chrominance);
00142         add_huff_table(dinfo, &dinfo->ac_huff_tbl_ptrs[1],
00143                 bits_ac_chrominance, val_ac_chrominance);
00144 }
00145 
00146 static int Decode_JPEG(unsigned char *inBuffer, unsigned char *outBuffer, unsigned int width, unsigned int height, int bufsize) {
00147         int rowstride;
00148         unsigned int y;
00149         struct jpeg_decompress_struct dinfo;
00150         struct jpeg_error_mgr jerr;
00151         
00152         (void)width; /* unused */
00153 
00154         numbytes= 0;
00155 
00156         dinfo.err = jpeg_std_error(&jerr);
00157         jpeg_create_decompress(&dinfo);
00158         jpegmemsrcmgr_build(&dinfo, inBuffer, bufsize);
00159         jpeg_read_header(&dinfo, TRUE);
00160         if (dinfo.dc_huff_tbl_ptrs[0] == NULL){
00161                 std_huff_tables(&dinfo);
00162         }
00163         dinfo.out_color_space = JCS_RGB;
00164         dinfo.dct_method = JDCT_IFAST;
00165 
00166         jpeg_start_decompress(&dinfo);
00167 
00168         rowstride= dinfo.output_width*dinfo.output_components;
00169         for (y= 0; y<dinfo.output_height; y++) {
00170                 jpeg_read_scanlines(&dinfo, (JSAMPARRAY) &outBuffer, 1);
00171                 outBuffer += rowstride;
00172         }
00173         jpeg_finish_decompress(&dinfo);
00174 
00175         if (dinfo.output_height >= height) return 0;
00176         
00177         inBuffer+= numbytes;
00178         jpegmemsrcmgr_build(&dinfo, inBuffer, bufsize-numbytes);
00179 
00180         numbytes= 0;
00181         jpeg_read_header(&dinfo, TRUE);
00182         if (dinfo.dc_huff_tbl_ptrs[0] == NULL){
00183                 std_huff_tables(&dinfo);
00184         }
00185 
00186         jpeg_start_decompress(&dinfo);
00187         rowstride= dinfo.output_width*dinfo.output_components;
00188         for (y= 0; y<dinfo.output_height; y++){
00189                 jpeg_read_scanlines(&dinfo, (JSAMPARRAY) &outBuffer, 1);
00190                 outBuffer += rowstride;
00191         }
00192         jpeg_finish_decompress(&dinfo);
00193         jpeg_destroy_decompress(&dinfo);
00194         
00195         return 1;
00196 }
00197 
00198 static void Compress_JPEG(int quality, unsigned char *outbuffer, unsigned char *inBuffer, int width, int height, int bufsize) {
00199         int i, rowstride;
00200         unsigned int y;
00201         struct jpeg_compress_struct cinfo;
00202         struct jpeg_error_mgr jerr;
00203         unsigned char marker[60];
00204 
00205         cinfo.err = jpeg_std_error(&jerr);
00206         jpeg_create_compress(&cinfo);
00207         jpegmemdestmgr_build(&cinfo, outbuffer, bufsize);
00208 
00209         cinfo.image_width = width;
00210         cinfo.image_height = height;
00211         cinfo.input_components = 3;
00212         cinfo.in_color_space = JCS_RGB;
00213 
00214         jpeg_set_defaults(&cinfo);
00215         jpeg_set_colorspace (&cinfo, JCS_YCbCr);
00216                 
00217         jpeg_set_quality (&cinfo, quality, TRUE);
00218 
00219         cinfo.dc_huff_tbl_ptrs[0]->sent_table = TRUE;
00220         cinfo.dc_huff_tbl_ptrs[1]->sent_table = TRUE;
00221         cinfo.ac_huff_tbl_ptrs[0]->sent_table = TRUE;
00222         cinfo.ac_huff_tbl_ptrs[1]->sent_table = TRUE;
00223 
00224         cinfo.comp_info[0].component_id = 0;
00225         cinfo.comp_info[0].v_samp_factor = 1;
00226         cinfo.comp_info[1].component_id = 1;
00227         cinfo.comp_info[2].component_id = 2;
00228 
00229         cinfo.write_JFIF_header = FALSE;
00230 
00231         jpeg_start_compress(&cinfo, FALSE);
00232 
00233         i=0;
00234         marker[i++] = 'A';
00235         marker[i++] = 'V';
00236         marker[i++] = 'I';
00237         marker[i++] = '1';
00238         marker[i++] = 0;
00239         while (i<60)
00240                 marker[i++] = 32;
00241 
00242         jpeg_write_marker (&cinfo, JPEG_APP0, marker, 60);
00243 
00244         i=0;
00245         while (i<60)
00246                 marker[i++] = 0;
00247 
00248         jpeg_write_marker (&cinfo, JPEG_COM, marker, 60);
00249 
00250         rowstride= cinfo.image_width*cinfo.input_components;
00251         for (y = 0; y < cinfo.image_height; y++){
00252                 jpeg_write_scanlines(&cinfo, (JSAMPARRAY) &inBuffer, 1);
00253                 inBuffer += rowstride;
00254         }
00255         jpeg_finish_compress(&cinfo);
00256         jpeg_destroy_compress(&cinfo);
00257 }
00258 
00259 static void interlace(unsigned char *to, unsigned char *from, int width, int height) {
00260         int i, rowstride= width*3;
00261         
00262         for (i=0; i<height; i++) {
00263                 if (i&1)
00264                         memcpy (&to[i*rowstride], &from[(i/2 + height/2)*rowstride], rowstride);
00265                 else 
00266                         memcpy (&to[i*rowstride], &from[(i/2)*rowstride], rowstride);
00267         }
00268 }
00269 
00270 static void deinterlace(int odd, unsigned char *to, unsigned char *from, int width, int height) {
00271         int i, rowstride= width*3;
00272         
00273         for (i=0; i<height; i++) {
00274                 if ((i&1)==odd)
00275                         memcpy (&to[(i/2 + height/2)*rowstride], &from[i*rowstride], rowstride);
00276                 else 
00277                         memcpy (&to[(i/2)*rowstride], &from[i*rowstride], rowstride);
00278         }
00279 }
00280 
00281 static int check_and_decode_jpeg(unsigned char *inbuf, unsigned char *outbuf, int width, int height, int bufsize) {
00282                 /* JPEG's are always multiples of 16, extra is cropped out AVI's */     
00283         if ((width&0xF) || (height&0xF)) {
00284                 int i, rrowstride, jrowstride;
00285                 int jwidth= PADUP(width, 16);
00286                 int jheight= PADUP(height, 16);
00287                 unsigned char *tmpbuf= MEM_mallocN(jwidth*jheight*3, "avi.check_and_decode_jpeg");
00288                 int ret= Decode_JPEG(inbuf, tmpbuf, jwidth, jheight, bufsize);
00289                 
00290                         /* crop the tmpbuf into the real buffer */
00291                 rrowstride= width*3;
00292                 jrowstride= jwidth*3;
00293                 for (i=0; i<height; i++)
00294                         memcpy(&outbuf[i*rrowstride], &tmpbuf[i*jrowstride], rrowstride);
00295                 MEM_freeN(tmpbuf);
00296                 
00297                 return ret;
00298         } else {
00299                 return Decode_JPEG(inbuf, outbuf, width, height, bufsize);
00300         }
00301 }
00302 
00303 static void check_and_compress_jpeg(int quality, unsigned char *outbuf, unsigned char *inbuf, int width, int height, int bufsize) {
00304                 /* JPEG's are always multiples of 16, extra is ignored in AVI's */      
00305         if ((width&0xF) || (height&0xF)) {
00306                 int i, rrowstride, jrowstride;
00307                 int jwidth= PADUP(width, 16);
00308                 int jheight= PADUP(height, 16);
00309                 unsigned char *tmpbuf= MEM_mallocN(jwidth*jheight*3, "avi.check_and_compress_jpeg");
00310                 
00311                         /* resize the realbuf into the tmpbuf */
00312                 rrowstride= width*3;
00313                 jrowstride= jwidth*3;
00314                 for (i=0; i<jheight; i++) {
00315                         if (i<height)
00316                                 memcpy(&tmpbuf[i*jrowstride], &inbuf[i*rrowstride], rrowstride);
00317                         else
00318                                 memset(&tmpbuf[i*jrowstride], 0, rrowstride);
00319                         memset(&tmpbuf[i*jrowstride+rrowstride], 0, jrowstride-rrowstride);
00320                 }
00321 
00322                 Compress_JPEG(quality, outbuf, tmpbuf, jwidth, jheight, bufsize);
00323 
00324                 MEM_freeN(tmpbuf);
00325         } else {
00326                 Compress_JPEG(quality, outbuf, inbuf, width, height, bufsize);
00327         }
00328 }
00329 
00330 void *avi_converter_from_mjpeg (AviMovie *movie, int stream, unsigned char *buffer, int *size) {
00331         int deint;
00332         unsigned char *buf;
00333 
00334         (void)stream; /* unused */
00335 
00336         buf= MEM_mallocN (movie->header->Height * movie->header->Width * 3, "avi.avi_converter_from_mjpeg 1");
00337 
00338         deint= check_and_decode_jpeg(buffer, buf, movie->header->Width, movie->header->Height, *size);
00339         
00340         MEM_freeN(buffer);
00341         
00342         if (deint) {
00343                 buffer = MEM_mallocN (movie->header->Height * movie->header->Width * 3, "avi.avi_converter_from_mjpeg 2");
00344                 interlace (buffer, buf, movie->header->Width, movie->header->Height);
00345                 MEM_freeN (buf);
00346         
00347                 buf= buffer;
00348         }
00349                 
00350         return buf;
00351 }
00352 
00353 void *avi_converter_to_mjpeg (AviMovie *movie, int stream, unsigned char *buffer, int *size) {
00354         unsigned char *buf;
00355         int bufsize= *size;
00356         
00357         numbytes = 0;
00358         *size= 0;
00359 
00360         buf = MEM_mallocN (movie->header->Height * movie->header->Width * 3, "avi.avi_converter_to_mjpeg 1");   
00361         if (!movie->interlace) {
00362                 check_and_compress_jpeg(movie->streams[stream].sh.Quality/100, buf, buffer,  movie->header->Width, movie->header->Height, bufsize);
00363         } else {
00364                 deinterlace (movie->odd_fields, buf, buffer, movie->header->Width, movie->header->Height);
00365                 MEM_freeN (buffer);
00366         
00367                 buffer= buf;
00368                 buf= MEM_mallocN (movie->header->Height * movie->header->Width * 3, "avi.avi_converter_to_mjpeg 2");
00369         
00370                 check_and_compress_jpeg(movie->streams[stream].sh.Quality/100, buf, buffer,  movie->header->Width, movie->header->Height/2, bufsize/2);
00371                 *size+= numbytes;
00372                 numbytes=0;
00373                 check_and_compress_jpeg(movie->streams[stream].sh.Quality/100, buf+*size, buffer+(movie->header->Height/2)*movie->header->Width*3,  movie->header->Width, movie->header->Height/2, bufsize/2);
00374         }
00375         *size += numbytes;      
00376 
00377         MEM_freeN (buffer);
00378         return buf;
00379 }
00380 
00381 
00382 /* Compression from memory */
00383 
00384 static void jpegmemdestmgr_init_destination(j_compress_ptr cinfo) {
00385         (void)cinfo; /* unused */
00386 }
00387 
00388 static boolean jpegmemdestmgr_empty_output_buffer(j_compress_ptr cinfo) {
00389         (void)cinfo; /* unused */
00390         return TRUE;
00391 }
00392 
00393 static void jpegmemdestmgr_term_destination(j_compress_ptr cinfo) {
00394         numbytes-= cinfo->dest->free_in_buffer;
00395 
00396         MEM_freeN(cinfo->dest);
00397 }
00398 
00399 static void jpegmemdestmgr_build(j_compress_ptr cinfo, unsigned char *buffer, int bufsize) {
00400         cinfo->dest= MEM_mallocN(sizeof(*(cinfo->dest)), "avi.jpegmemdestmgr_build");
00401         
00402         cinfo->dest->init_destination= jpegmemdestmgr_init_destination;
00403         cinfo->dest->empty_output_buffer= jpegmemdestmgr_empty_output_buffer;
00404         cinfo->dest->term_destination= jpegmemdestmgr_term_destination;
00405 
00406         cinfo->dest->next_output_byte= buffer;
00407         cinfo->dest->free_in_buffer= bufsize;
00408         
00409         numbytes= bufsize;
00410 }
00411 
00412 /* Decompression from memory */
00413 
00414 static void jpegmemsrcmgr_init_source(j_decompress_ptr dinfo) {
00415         (void)dinfo;
00416 }
00417 
00418 static boolean jpegmemsrcmgr_fill_input_buffer(j_decompress_ptr dinfo) {
00419         unsigned char *buf= (unsigned char*) dinfo->src->next_input_byte-2;
00420         
00421                 /* if we get called, must have run out of data */
00422         WARNMS(dinfo, JWRN_JPEG_EOF);
00423         
00424         buf[0]= (JOCTET) 0xFF;
00425         buf[1]= (JOCTET) JPEG_EOI;
00426         
00427         dinfo->src->next_input_byte= buf;
00428         dinfo->src->bytes_in_buffer= 2;
00429         
00430         return TRUE;
00431 }
00432 
00433 static void jpegmemsrcmgr_skip_input_data(j_decompress_ptr dinfo, long skipcnt) {
00434         if (dinfo->src->bytes_in_buffer<skipcnt)
00435                 skipcnt= dinfo->src->bytes_in_buffer;
00436 
00437         dinfo->src->next_input_byte+= skipcnt;
00438         dinfo->src->bytes_in_buffer-= skipcnt;
00439 }
00440 
00441 static void jpegmemsrcmgr_term_source(j_decompress_ptr dinfo) {
00442         numbytes-= dinfo->src->bytes_in_buffer;
00443         
00444         MEM_freeN(dinfo->src);
00445 }
00446 
00447 static void jpegmemsrcmgr_build(j_decompress_ptr dinfo, unsigned char *buffer, int bufsize) {
00448         dinfo->src= MEM_mallocN(sizeof(*(dinfo->src)), "avi.jpegmemsrcmgr_build");
00449         
00450         dinfo->src->init_source= jpegmemsrcmgr_init_source;
00451         dinfo->src->fill_input_buffer= jpegmemsrcmgr_fill_input_buffer;
00452         dinfo->src->skip_input_data= jpegmemsrcmgr_skip_input_data;
00453         dinfo->src->resync_to_restart= jpeg_resync_to_restart;
00454         dinfo->src->term_source= jpegmemsrcmgr_term_source;
00455         
00456         dinfo->src->bytes_in_buffer= bufsize;
00457         dinfo->src->next_input_byte= buffer;
00458 
00459         numbytes= bufsize;
00460 }