2 * This library is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU Lesser General Public License as published
4 * by the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This library is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 #include "colormodels.h"
78 #define QUICKTIME_MARKER_SIZE 0x2c
79 #define AVI_MARKER_SIZE 0x12
80 #define QUICKTIME_JPEG_TAG 0x6d6a7067
81 #define QUICKTIME_AVI_TAG 0x41564931
84 METHODDEF(void) mjpeg_error_exit (j_common_ptr cinfo
)
86 /* cinfo->err really points to a mjpeg_error_mgr struct, so coerce pointer */
87 mjpeg_error_ptr mjpegerr
= (mjpeg_error_ptr
) cinfo
->err
;
89 /* Always display the message. */
90 /* We could postpone this until after returning, if we chose. */
91 (*cinfo
->err
->output_message
) (cinfo
);
93 /* Return control to the setjmp point */
94 longjmp(mjpegerr
->setjmp_buffer
, 1);
99 struct jpeg_destination_mgr pub
; /* public fields */
101 JOCTET
*buffer
; /* Pointer to buffer */
102 mjpeg_compressor
*engine
;
103 } mjpeg_destination_mgr
;
105 typedef mjpeg_destination_mgr
*mjpeg_dest_ptr
;
109 * Initialize destination --- called by jpeg_start_compress
110 * before any data is actually written.
113 METHODDEF(void) init_destination(j_compress_ptr cinfo
)
115 mjpeg_dest_ptr dest
= (mjpeg_dest_ptr
)cinfo
->dest
;
117 /* Set the pointer to the preallocated buffer */
118 if(!dest
->engine
->output_buffer
)
120 dest
->engine
->output_buffer
= calloc(1, 65536);
121 dest
->engine
->output_allocated
= 65536;
123 dest
->buffer
= dest
->engine
->output_buffer
;
124 dest
->pub
.next_output_byte
= dest
->engine
->output_buffer
;
125 dest
->pub
.free_in_buffer
= dest
->engine
->output_allocated
;
129 * Empty the output buffer --- called whenever buffer fills up.
131 * In typical applications, this should write the entire output buffer
132 * (ignoring the current state of next_output_byte & free_in_buffer),
133 * reset the pointer & count to the start of the buffer, and return TRUE
134 * indicating that the buffer has been dumped.
136 * In applications that need to be able to suspend compression due to output
137 * overrun, a FALSE return indicates that the buffer cannot be emptied now.
138 * In this situation, the compressor will return to its caller (possibly with
139 * an indication that it has not accepted all the supplied scanlines). The
140 * application should resume compression after it has made more room in the
141 * output buffer. Note that there are substantial restrictions on the use of
142 * suspension --- see the documentation.
144 * When suspending, the compressor will back up to a convenient restart point
145 * (typically the start of the current MCU). next_output_byte & free_in_buffer
146 * indicate where the restart point will be if the current call returns FALSE.
147 * Data beyond this point will be regenerated after resumption, so do not
148 * write it out when emptying the buffer externally.
151 METHODDEF(boolean
) empty_output_buffer(j_compress_ptr cinfo
)
153 /* Allocate a bigger buffer. */
154 mjpeg_dest_ptr dest
= (mjpeg_dest_ptr
)cinfo
->dest
;
156 dest
->engine
->output_size
= dest
->engine
->output_allocated
;
157 dest
->engine
->output_allocated
*= 2;
158 dest
->engine
->output_buffer
= realloc(dest
->engine
->output_buffer
,
159 dest
->engine
->output_allocated
);
160 dest
->buffer
= dest
->engine
->output_buffer
;
161 dest
->pub
.next_output_byte
= dest
->buffer
+ dest
->engine
->output_size
;
162 dest
->pub
.free_in_buffer
= dest
->engine
->output_allocated
- dest
->engine
->output_size
;
168 * Terminate destination --- called by jpeg_finish_compress
169 * after all data has been written. Usually needs to flush buffer.
171 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
172 * application must deal with any cleanup that should happen even
175 METHODDEF(void) term_destination(j_compress_ptr cinfo
)
177 /* Just get the length */
178 mjpeg_dest_ptr dest
= (mjpeg_dest_ptr
)cinfo
->dest
;
179 dest
->engine
->output_size
= dest
->engine
->output_allocated
- dest
->pub
.free_in_buffer
;
182 GLOBAL(void) jpeg_buffer_dest(j_compress_ptr cinfo
, mjpeg_compressor
*engine
)
186 /* The destination object is made permanent so that multiple JPEG images
187 * can be written to the same file without re-executing jpeg_stdio_dest.
188 * This makes it dangerous to use this manager and a different destination
189 * manager serially with the same JPEG object, because their private object
190 * sizes may be different. Caveat programmer.
192 if(cinfo
->dest
== NULL
)
194 /* first time for this JPEG object? */
195 cinfo
->dest
= (struct jpeg_destination_mgr
*)
196 (*cinfo
->mem
->alloc_small
)((j_common_ptr
)cinfo
,
198 sizeof(mjpeg_destination_mgr
));
201 dest
= (mjpeg_dest_ptr
)cinfo
->dest
;
202 dest
->pub
.init_destination
= init_destination
;
203 dest
->pub
.empty_output_buffer
= empty_output_buffer
;
204 dest
->pub
.term_destination
= term_destination
;
205 dest
->engine
= engine
;
222 struct jpeg_source_mgr pub
; /* public fields */
224 JOCTET
* buffer
; /* start of buffer */
225 int bytes
; /* total size of buffer */
228 typedef mjpeg_source_mgr
* mjpeg_src_ptr
;
230 METHODDEF(void) init_source(j_decompress_ptr cinfo
)
232 mjpeg_src_ptr src
= (mjpeg_src_ptr
) cinfo
->src
;
235 METHODDEF(boolean
) fill_input_buffer(j_decompress_ptr cinfo
)
237 mjpeg_src_ptr src
= (mjpeg_src_ptr
) cinfo
->src
;
239 src
->buffer
[0] = (JOCTET
)0xFF;
240 src
->buffer
[1] = (JOCTET
)M_EOI
;
241 src
->pub
.next_input_byte
= src
->buffer
;
242 src
->pub
.bytes_in_buffer
= 2;
248 METHODDEF(void) skip_input_data(j_decompress_ptr cinfo
, long num_bytes
)
250 mjpeg_src_ptr src
= (mjpeg_src_ptr
)cinfo
->src
;
252 src
->pub
.next_input_byte
+= (size_t)num_bytes
;
253 src
->pub
.bytes_in_buffer
-= (size_t)num_bytes
;
257 METHODDEF(void) term_source(j_decompress_ptr cinfo
)
261 GLOBAL(void) jpeg_buffer_src(j_decompress_ptr cinfo
, unsigned char *buffer
, long bytes
)
265 /* first time for this JPEG object? */
266 if(cinfo
->src
== NULL
)
268 cinfo
->src
= (struct jpeg_source_mgr
*)
269 (*cinfo
->mem
->alloc_small
)((j_common_ptr
)cinfo
,
271 sizeof(mjpeg_source_mgr
));
272 src
= (mjpeg_src_ptr
)cinfo
->src
;
275 src
= (mjpeg_src_ptr
)cinfo
->src
;
276 src
->pub
.init_source
= init_source
;
277 src
->pub
.fill_input_buffer
= fill_input_buffer
;
278 src
->pub
.skip_input_data
= skip_input_data
;
279 src
->pub
.resync_to_restart
= jpeg_resync_to_restart
; /* use default method */
280 src
->pub
.term_source
= term_source
;
281 src
->pub
.bytes_in_buffer
= bytes
;
282 src
->pub
.next_input_byte
= buffer
;
283 src
->buffer
= buffer
;
302 static void reset_buffer(unsigned char **buffer
, long *size
, long *allocated
)
307 static void delete_buffer(unsigned char **buffer
, long *size
, long *allocated
)
317 static void append_buffer(unsigned char **buffer
,
325 *buffer
= calloc(1, 65536);
330 if(*size
+ data_size
> *allocated
)
332 *allocated
= *size
+ data_size
;
333 *buffer
= realloc(*buffer
, *allocated
);
336 memcpy(*buffer
+ *size
, data
, data_size
);
340 static void allocate_temps(mjpeg_t
*mjpeg
)
344 if(!mjpeg
->temp_data
)
346 switch(mjpeg
->jpeg_color_model
)
349 mjpeg
->temp_data
= calloc(1, mjpeg
->coded_w
* mjpeg
->coded_h
* 2);
350 mjpeg
->temp_rows
[0] = calloc(1, sizeof(unsigned char*) * mjpeg
->coded_h
);
351 mjpeg
->temp_rows
[1] = calloc(1, sizeof(unsigned char*) * mjpeg
->coded_h
);
352 mjpeg
->temp_rows
[2] = calloc(1, sizeof(unsigned char*) * mjpeg
->coded_h
);
353 for(i
= 0; i
< mjpeg
->coded_h
; i
++)
355 mjpeg
->temp_rows
[0][i
] = mjpeg
->temp_data
+ i
* mjpeg
->coded_w
;
356 mjpeg
->temp_rows
[1][i
] = mjpeg
->temp_data
+ mjpeg
->coded_w
* mjpeg
->coded_h
+ i
* mjpeg
->coded_w
/ 2;
357 mjpeg
->temp_rows
[2][i
] = mjpeg
->temp_data
+ mjpeg
->coded_w
* mjpeg
->coded_h
+ mjpeg
->coded_w
/ 2 * mjpeg
->coded_h
+ i
* mjpeg
->coded_w
/ 2;
362 mjpeg
->temp_data
= calloc(1, mjpeg
->coded_w
* mjpeg
->coded_h
* 3);
363 mjpeg
->temp_rows
[0] = calloc(1, sizeof(unsigned char*) * mjpeg
->coded_h
);
364 mjpeg
->temp_rows
[1] = calloc(1, sizeof(unsigned char*) * mjpeg
->coded_h
);
365 mjpeg
->temp_rows
[2] = calloc(1, sizeof(unsigned char*) * mjpeg
->coded_h
);
366 for(i
= 0; i
< mjpeg
->coded_h
; i
++)
368 mjpeg
->temp_rows
[0][i
] = mjpeg
->temp_data
+ i
* mjpeg
->coded_w
;
369 mjpeg
->temp_rows
[1][i
] = mjpeg
->temp_data
+ mjpeg
->coded_w
* mjpeg
->coded_h
+ i
* mjpeg
->coded_w
;
370 mjpeg
->temp_rows
[2][i
] = mjpeg
->temp_data
+ mjpeg
->coded_w
* mjpeg
->coded_h
+ mjpeg
->coded_w
* mjpeg
->coded_h
+ i
* mjpeg
->coded_w
;
375 mjpeg
->temp_data
= calloc(1, mjpeg
->coded_w
* mjpeg
->coded_h
+ mjpeg
->coded_w
* mjpeg
->coded_h
/ 2);
376 mjpeg
->temp_rows
[0] = calloc(1, sizeof(unsigned char*) * mjpeg
->coded_h
);
377 mjpeg
->temp_rows
[1] = calloc(1, sizeof(unsigned char*) * mjpeg
->coded_h
/ 2);
378 mjpeg
->temp_rows
[2] = calloc(1, sizeof(unsigned char*) * mjpeg
->coded_h
/ 2);
379 for(i
= 0; i
< mjpeg
->coded_h
; i
++)
381 mjpeg
->temp_rows
[0][i
] = mjpeg
->temp_data
+ i
* mjpeg
->coded_w
;
382 if(i
< mjpeg
->coded_h
/ 2)
384 mjpeg
->temp_rows
[1][i
] = mjpeg
->temp_data
+ mjpeg
->coded_w
* mjpeg
->coded_h
+ i
* (mjpeg
->coded_w
/ 2);
385 mjpeg
->temp_rows
[2][i
] = mjpeg
->temp_data
+ mjpeg
->coded_w
* mjpeg
->coded_h
+ (mjpeg
->coded_h
/ 2) * (mjpeg
->coded_w
/ 2) + i
* (mjpeg
->coded_w
/ 2);
393 static int get_input_row(mjpeg_t
*mjpeg
, mjpeg_compressor
*compressor
, int i
)
396 if(mjpeg
->fields
> 1)
397 input_row
= i
* 2 + compressor
->instance
;
400 if(input_row
>= mjpeg
->coded_h
) input_row
= mjpeg
->coded_h
- 1;
404 // Get pointers to rows for the JPEG compressor
405 static void get_rows(mjpeg_t
*mjpeg
, mjpeg_compressor
*compressor
)
408 switch(mjpeg
->jpeg_color_model
)
412 if(!compressor
->rows
[0])
414 compressor
->rows
[0] = calloc(1, sizeof(unsigned char*) * compressor
->coded_field_h
);
415 compressor
->rows
[1] = calloc(1, sizeof(unsigned char*) * compressor
->coded_field_h
);
416 compressor
->rows
[2] = calloc(1, sizeof(unsigned char*) * compressor
->coded_field_h
);
419 // User colormodel matches jpeg colormodel
420 if(mjpeg
->color_model
== BC_YUV444P
&&
421 mjpeg
->output_w
== mjpeg
->coded_w
&&
422 mjpeg
->output_h
== mjpeg
->coded_h
)
424 for(i
= 0; i
< compressor
->coded_field_h
; i
++)
426 int input_row
= get_input_row(mjpeg
, compressor
, i
);
427 compressor
->rows
[0][i
] = mjpeg
->y_argument
+
428 mjpeg
->coded_w
* input_row
;
429 compressor
->rows
[1][i
] = mjpeg
->u_argument
+
430 mjpeg
->coded_w
* input_row
;
431 compressor
->rows
[2][i
] = mjpeg
->v_argument
+
432 mjpeg
->coded_w
* input_row
;
437 for(i
= 0; i
< compressor
->coded_field_h
; i
++)
439 int input_row
= get_input_row(mjpeg
, compressor
, i
);
440 compressor
->rows
[0][i
] = mjpeg
->temp_rows
[0][input_row
];
441 compressor
->rows
[1][i
] = mjpeg
->temp_rows
[1][input_row
];
442 compressor
->rows
[2][i
] = mjpeg
->temp_rows
[2][input_row
];
450 if(!compressor
->rows
[0])
452 compressor
->rows
[0] = calloc(1, sizeof(unsigned char*) * compressor
->coded_field_h
);
453 compressor
->rows
[1] = calloc(1, sizeof(unsigned char*) * compressor
->coded_field_h
);
454 compressor
->rows
[2] = calloc(1, sizeof(unsigned char*) * compressor
->coded_field_h
);
457 // User colormodel matches jpeg colormodel
458 if(mjpeg
->color_model
== BC_YUV422P
&&
459 mjpeg
->output_w
== mjpeg
->coded_w
&&
460 mjpeg
->output_h
== mjpeg
->coded_h
)
462 for(i
= 0; i
< compressor
->coded_field_h
; i
++)
464 int input_row
= get_input_row(mjpeg
, compressor
, i
);
465 compressor
->rows
[0][i
] = mjpeg
->y_argument
+
466 mjpeg
->coded_w
* input_row
;
467 compressor
->rows
[1][i
] = mjpeg
->u_argument
+
468 (mjpeg
->coded_w
/ 2) * input_row
;
469 compressor
->rows
[2][i
] = mjpeg
->v_argument
+
470 (mjpeg
->coded_w
/ 2) * input_row
;
475 for(i
= 0; i
< compressor
->coded_field_h
; i
++)
477 int input_row
= get_input_row(mjpeg
, compressor
, i
);
478 compressor
->rows
[0][i
] = mjpeg
->temp_rows
[0][input_row
];
479 compressor
->rows
[1][i
] = mjpeg
->temp_rows
[1][input_row
];
480 compressor
->rows
[2][i
] = mjpeg
->temp_rows
[2][input_row
];
488 if(!compressor
->rows
[0])
490 compressor
->rows
[0] = calloc(1, sizeof(unsigned char*) * mjpeg
->coded_h
);
491 compressor
->rows
[1] = calloc(1, sizeof(unsigned char*) * mjpeg
->coded_h
/ 2);
492 compressor
->rows
[2] = calloc(1, sizeof(unsigned char*) * mjpeg
->coded_h
/ 2);
495 // User colormodel matches jpeg colormodel
496 if(mjpeg
->color_model
== BC_YUV420P
&&
497 mjpeg
->output_w
== mjpeg
->coded_w
&&
498 mjpeg
->output_h
== mjpeg
->coded_h
)
500 for(i
= 0; i
< compressor
->coded_field_h
; i
++)
502 int input_row
= get_input_row(mjpeg
, compressor
, i
);
503 compressor
->rows
[0][i
] = mjpeg
->y_argument
+
504 mjpeg
->coded_w
* input_row
;
505 if(i
< compressor
->coded_field_h
/ 2)
507 compressor
->rows
[1][i
] = mjpeg
->u_argument
+
508 (mjpeg
->coded_w
/ 2) * input_row
;
509 compressor
->rows
[2][i
] = mjpeg
->v_argument
+
510 (mjpeg
->coded_w
/ 2) * input_row
;
516 for(i
= 0; i
< compressor
->coded_field_h
; i
++)
518 int input_row
= get_input_row(mjpeg
, compressor
, i
);
519 compressor
->rows
[0][i
] = mjpeg
->temp_rows
[0][input_row
];
520 if(i
< compressor
->coded_field_h
/ 2)
522 compressor
->rows
[1][i
] = mjpeg
->temp_rows
[1][input_row
];
523 compressor
->rows
[2][i
] = mjpeg
->temp_rows
[2][input_row
];
532 static void delete_rows(mjpeg_compressor
*compressor
)
534 if(compressor
->rows
[0])
536 free(compressor
->rows
[0]);
537 free(compressor
->rows
[1]);
538 free(compressor
->rows
[2]);
543 static void new_jpeg_objects(mjpeg_compressor
*engine
)
545 engine
->jpeg_decompress
.err
= jpeg_std_error(&(engine
->jpeg_error
.pub
));
546 engine
->jpeg_error
.pub
.error_exit
= mjpeg_error_exit
;
547 /* Ideally the error handler would be set here but it must be called in a thread */
548 jpeg_create_decompress(&(engine
->jpeg_decompress
));
549 engine
->jpeg_decompress
.raw_data_out
= TRUE
;
550 engine
->jpeg_decompress
.dct_method
= JDCT_IFAST
;
553 static void delete_jpeg_objects(mjpeg_compressor
*engine
)
555 jpeg_destroy_decompress(&(engine
->jpeg_decompress
));
560 static void unlock_compress_loop(mjpeg_compressor
*engine
)
562 pthread_mutex_unlock(&(engine
->input_lock
));
565 static void lock_compress_loop(mjpeg_compressor
*engine
)
567 pthread_mutex_lock(&(engine
->output_lock
));
570 // Make temp rows for compressor
571 static void get_mcu_rows(mjpeg_t
*mjpeg
,
572 mjpeg_compressor
*engine
,
576 for(i
= 0; i
< 3; i
++)
578 for(j
= 0; j
< 16; j
++)
580 if(i
> 0 && j
>= 8 && mjpeg
->jpeg_color_model
== BC_YUV420P
) break;
582 scanline
= start_row
;
583 if(i
> 0 && mjpeg
->jpeg_color_model
== BC_YUV420P
) scanline
/= 2;
585 if(scanline
>= engine
->coded_field_h
) scanline
= engine
->coded_field_h
- 1;
586 engine
->mcu_rows
[i
][j
] = engine
->rows
[i
][scanline
];
592 static void decompress_field(mjpeg_compressor
*engine
)
594 mjpeg_t
*mjpeg
= engine
->mjpeg
;
595 long buffer_offset
= engine
->instance
* mjpeg
->input_field2
;
596 unsigned char *buffer
= mjpeg
->input_data
+ buffer_offset
;
600 //printf("decompress_field %02x%02x %d\n", buffer[0], buffer[1], engine->instance * mjpeg->input_field2);
601 if(engine
->instance
== 0 && mjpeg
->fields
> 1)
602 buffer_size
= mjpeg
->input_field2
- buffer_offset
;
604 buffer_size
= mjpeg
->input_size
- buffer_offset
;
608 if(setjmp(engine
->jpeg_error
.setjmp_buffer
))
610 /* If we get here, the JPEG code has signaled an error. */
611 delete_jpeg_objects(engine
);
612 new_jpeg_objects(engine
);
614 //printf("decompress_field 1\n");
618 //printf("decompress_field 2\n");
619 jpeg_buffer_src(&engine
->jpeg_decompress
,
622 jpeg_read_header(&engine
->jpeg_decompress
, TRUE
);
624 // Reset by jpeg_read_header
625 engine
->jpeg_decompress
.raw_data_out
= TRUE
;
626 jpeg_start_decompress(&engine
->jpeg_decompress
);
628 // Generate colormodel from jpeg sampling
629 if(engine
->jpeg_decompress
.comp_info
[0].v_samp_factor
== 2 &&
630 engine
->jpeg_decompress
.comp_info
[0].h_samp_factor
== 2)
631 mjpeg
->jpeg_color_model
= BC_YUV420P
;
633 if(engine
->jpeg_decompress
.comp_info
[0].v_samp_factor
== 1 &&
634 engine
->jpeg_decompress
.comp_info
[0].h_samp_factor
== 2)
635 mjpeg
->jpeg_color_model
= BC_YUV422P
;
637 mjpeg
->jpeg_color_model
= BC_YUV444P
;
639 // Must be here because the color model isn't known until now
640 pthread_mutex_lock(&(mjpeg
->decompress_init
));
641 allocate_temps(mjpeg
);
642 pthread_mutex_unlock(&(mjpeg
->decompress_init
));
643 get_rows(mjpeg
, engine
);
645 //printf("decompress_field 3 %d\n", engine->jpeg_decompress.output_scanline);
647 while(engine
->jpeg_decompress
.output_scanline
< engine
->jpeg_decompress
.output_height
)
649 get_mcu_rows(mjpeg
, engine
, engine
->jpeg_decompress
.output_scanline
);
650 jpeg_read_raw_data(&engine
->jpeg_decompress
,
652 engine
->coded_field_h
);
654 jpeg_finish_decompress(&engine
->jpeg_decompress
);
661 void mjpeg_decompress_loop(mjpeg_compressor
*engine
)
665 pthread_mutex_lock(&engine
->input_lock
);
668 decompress_field(engine
);
670 pthread_mutex_unlock(&(engine
->output_lock
));
675 static void compress_field(mjpeg_compressor
*engine
)
678 mjpeg_t
*mjpeg
= engine
->mjpeg
;
680 //printf("compress_field 1\n");
681 get_rows(engine
->mjpeg
, engine
);
682 reset_buffer(&engine
->output_buffer
, &engine
->output_size
, &engine
->output_allocated
);
683 jpeg_buffer_dest(&engine
->jpeg_compress
, engine
);
686 engine
->jpeg_compress
.raw_data_in
= TRUE
;
687 jpeg_start_compress(&engine
->jpeg_compress
, TRUE
);
689 while(engine
->jpeg_compress
.next_scanline
< engine
->jpeg_compress
.image_height
)
691 get_mcu_rows(mjpeg
, engine
, engine
->jpeg_compress
.next_scanline
);
693 jpeg_write_raw_data(&engine
->jpeg_compress
,
695 engine
->coded_field_h
);
697 jpeg_finish_compress(&engine
->jpeg_compress
);
698 //printf("compress_field 2\n");
702 void mjpeg_compress_loop(mjpeg_compressor
*engine
)
706 pthread_mutex_lock(&engine
->input_lock
);
709 compress_field(engine
);
711 pthread_mutex_unlock(&engine
->output_lock
);
715 static void delete_temps(mjpeg_t
*mjpeg
)
719 free(mjpeg
->temp_data
);
720 free(mjpeg
->temp_rows
[0]);
721 free(mjpeg
->temp_rows
[1]);
722 free(mjpeg
->temp_rows
[2]);
726 mjpeg_compressor
* mjpeg_new_decompressor(mjpeg_t
*mjpeg
, int instance
)
728 mjpeg_compressor
*result
= calloc(1, sizeof(mjpeg_compressor
));
730 struct sched_param param
;
731 pthread_mutexattr_t mutex_attr
;
734 result
->mjpeg
= mjpeg
;
735 result
->instance
= instance
;
736 new_jpeg_objects(result
);
737 result
->field_h
= mjpeg
->output_h
/ mjpeg
->fields
;
738 result
->coded_field_h
= (result
->field_h
% 16) ?
739 result
->field_h
+ (16 - (result
->field_h
% 16)) : result
->field_h
;
741 result
->mcu_rows
[0] = malloc(16 * sizeof(unsigned char*));
742 result
->mcu_rows
[1] = malloc(16 * sizeof(unsigned char*));
743 result
->mcu_rows
[2] = malloc(16 * sizeof(unsigned char*));
745 pthread_mutexattr_init(&mutex_attr
);
746 pthread_mutex_init(&(result
->input_lock
), &mutex_attr
);
747 pthread_mutex_lock(&(result
->input_lock
));
748 pthread_mutex_init(&(result
->output_lock
), &mutex_attr
);
749 pthread_mutex_lock(&(result
->output_lock
));
751 pthread_attr_init(&attr
);
752 pthread_create(&(result
->tid
), &attr
, (void*)mjpeg_decompress_loop
, result
);
757 void mjpeg_delete_decompressor(mjpeg_compressor
*engine
)
760 pthread_mutex_unlock(&(engine
->input_lock
));
761 pthread_join(engine
->tid
, 0);
762 pthread_mutex_destroy(&(engine
->input_lock
));
763 pthread_mutex_destroy(&(engine
->output_lock
));
764 jpeg_destroy_decompress(&(engine
->jpeg_decompress
));
766 free(engine
->mcu_rows
[0]);
767 free(engine
->mcu_rows
[1]);
768 free(engine
->mcu_rows
[2]);
772 mjpeg_compressor
* mjpeg_new_compressor(mjpeg_t
*mjpeg
, int instance
)
775 struct sched_param param
;
776 pthread_mutexattr_t mutex_attr
;
777 mjpeg_compressor
*result
= calloc(1, sizeof(mjpeg_compressor
));
779 result
->field_h
= mjpeg
->output_h
/ mjpeg
->fields
;
780 result
->coded_field_h
= (result
->field_h
% 16) ?
781 result
->field_h
+ (16 - (result
->field_h
% 16)) : result
->field_h
;
782 result
->mjpeg
= mjpeg
;
783 result
->instance
= instance
;
784 result
->jpeg_compress
.err
= jpeg_std_error(&(result
->jpeg_error
.pub
));
785 jpeg_create_compress(&(result
->jpeg_compress
));
786 result
->jpeg_compress
.image_width
= mjpeg
->output_w
;
787 result
->jpeg_compress
.image_height
= result
->field_h
;
788 result
->jpeg_compress
.input_components
= 3;
789 result
->jpeg_compress
.in_color_space
= JCS_RGB
;
790 jpeg_set_defaults(&(result
->jpeg_compress
));
791 result
->jpeg_compress
.input_components
= 3;
792 result
->jpeg_compress
.in_color_space
= JCS_RGB
;
793 jpeg_set_quality(&(result
->jpeg_compress
), mjpeg
->quality
, 0);
796 result
->jpeg_compress
.dct_method
= JDCT_FLOAT
;
798 result
->jpeg_compress
.dct_method
= JDCT_IFAST
;
799 // result->jpeg_compress.dct_method = JDCT_ISLOW;
802 switch(mjpeg
->fields
)
805 mjpeg
->jpeg_color_model
= BC_YUV420P
;
806 result
->jpeg_compress
.comp_info
[0].h_samp_factor
= 2;
807 result
->jpeg_compress
.comp_info
[0].v_samp_factor
= 2;
808 result
->jpeg_compress
.comp_info
[1].h_samp_factor
= 1;
809 result
->jpeg_compress
.comp_info
[1].v_samp_factor
= 1;
810 result
->jpeg_compress
.comp_info
[2].h_samp_factor
= 1;
811 result
->jpeg_compress
.comp_info
[2].v_samp_factor
= 1;
814 mjpeg
->jpeg_color_model
= BC_YUV422P
;
815 result
->jpeg_compress
.comp_info
[0].h_samp_factor
= 2;
816 result
->jpeg_compress
.comp_info
[0].v_samp_factor
= 1;
817 result
->jpeg_compress
.comp_info
[1].h_samp_factor
= 1;
818 result
->jpeg_compress
.comp_info
[1].v_samp_factor
= 1;
819 result
->jpeg_compress
.comp_info
[2].h_samp_factor
= 1;
820 result
->jpeg_compress
.comp_info
[2].v_samp_factor
= 1;
823 allocate_temps(mjpeg
);
825 result
->mcu_rows
[0] = malloc(16 * sizeof(unsigned char*));
826 result
->mcu_rows
[1] = malloc(16 * sizeof(unsigned char*));
827 result
->mcu_rows
[2] = malloc(16 * sizeof(unsigned char*));
829 pthread_mutexattr_init(&mutex_attr
);
830 pthread_mutex_init(&(result
->input_lock
), &mutex_attr
);
831 pthread_mutex_lock(&(result
->input_lock
));
832 pthread_mutex_init(&(result
->output_lock
), &mutex_attr
);
833 pthread_mutex_lock(&(result
->output_lock
));
835 pthread_attr_init(&attr
);
836 pthread_create(&(result
->tid
), &attr
, (void*)mjpeg_compress_loop
, result
);
841 void mjpeg_delete_compressor(mjpeg_compressor
*engine
)
844 pthread_mutex_unlock(&(engine
->input_lock
));
845 pthread_join(engine
->tid
, 0);
846 pthread_mutex_destroy(&(engine
->input_lock
));
847 pthread_mutex_destroy(&(engine
->output_lock
));
848 jpeg_destroy((j_common_ptr
)&(engine
->jpeg_compress
));
849 if(engine
->output_buffer
) free(engine
->output_buffer
);
851 free(engine
->mcu_rows
[0]);
852 free(engine
->mcu_rows
[1]);
853 free(engine
->mcu_rows
[2]);
857 unsigned char* mjpeg_output_buffer(mjpeg_t
*mjpeg
)
859 return mjpeg
->output_data
;
862 long mjpeg_output_field2(mjpeg_t
*mjpeg
)
864 return mjpeg
->output_field2
;
867 long mjpeg_output_size(mjpeg_t
*mjpeg
)
869 return mjpeg
->output_size
;
872 int mjpeg_compress(mjpeg_t
*mjpeg
,
873 unsigned char **row_pointers
,
874 unsigned char *y_plane
,
875 unsigned char *u_plane
,
876 unsigned char *v_plane
,
881 int corrected_fields
= mjpeg
->fields
;
882 mjpeg
->color_model
= color_model
;
885 //printf("mjpeg_compress 1 %d\n", color_model);
886 /* Reset output buffer */
887 reset_buffer(&mjpeg
->output_data
,
889 &mjpeg
->output_allocated
);
891 /* Create compression engines as needed */
892 for(i
= 0; i
< mjpeg
->fields
; i
++)
894 if(!mjpeg
->compressors
[i
])
896 mjpeg
->compressors
[i
] = mjpeg_new_compressor(mjpeg
, i
);
900 /* Arm YUV buffers */
901 mjpeg
->row_argument
= row_pointers
;
902 mjpeg
->y_argument
= y_plane
;
903 mjpeg
->u_argument
= u_plane
;
904 mjpeg
->v_argument
= v_plane
;
905 // User colormodel doesn't match encoder colormodel
906 // Copy to interlacing buffer first
907 if(mjpeg
->color_model
!= mjpeg
->jpeg_color_model
||
908 mjpeg
->output_w
!= mjpeg
->coded_w
||
909 mjpeg
->output_h
!= mjpeg
->coded_h
)
912 * printf("mjpeg_compress %d %d %d %d\n",
913 * mjpeg->output_w, mjpeg->output_h, mjpeg->coded_w, mjpeg->coded_h);
917 mjpeg
->temp_rows
[0][0],
918 mjpeg
->temp_rows
[1][0],
919 mjpeg
->temp_rows
[2][0],
932 mjpeg
->jpeg_color_model
,
938 /* Start the compressors on the image fields */
939 if(mjpeg
->deinterlace
) corrected_fields
= 1;
940 for(i
= 0; i
< corrected_fields
&& !result
; i
++)
942 unlock_compress_loop(mjpeg
->compressors
[i
]);
944 if(mjpeg
->cpus
< 2 && i
< corrected_fields
- 1)
946 lock_compress_loop(mjpeg
->compressors
[i
]);
950 /* Wait for the compressors and store in master output */
951 for(i
= 0; i
< corrected_fields
&& !result
; i
++)
953 if(mjpeg
->cpus
> 1 || i
== corrected_fields
- 1)
955 lock_compress_loop(mjpeg
->compressors
[i
]);
958 append_buffer(&mjpeg
->output_data
,
960 &mjpeg
->output_allocated
,
961 mjpeg
->compressors
[i
]->output_buffer
,
962 mjpeg
->compressors
[i
]->output_size
);
963 if(i
== 0) mjpeg
->output_field2
= mjpeg
->output_size
;
966 if(corrected_fields
< mjpeg
->fields
)
968 append_buffer(&mjpeg
->output_data
,
970 &mjpeg
->output_allocated
,
971 mjpeg
->compressors
[0]->output_buffer
,
972 mjpeg
->compressors
[0]->output_size
);
974 //printf("mjpeg_compress 2\n");
980 int mjpeg_decompress(mjpeg_t
*mjpeg
,
981 unsigned char *buffer
,
984 unsigned char **row_pointers
,
985 unsigned char *y_plane
,
986 unsigned char *u_plane
,
987 unsigned char *v_plane
,
992 int got_first_thread
= 0;
994 //printf("mjpeg_decompress 1 %ld %ld\n", buffer_len, input_field2);
995 if(buffer_len
== 0) return 1;
996 if(input_field2
== 0 && mjpeg
->fields
> 1) return 1;
998 //printf("mjpeg_decompress 2\n");
999 /* Create decompression engines as needed */
1000 for(i
= 0; i
< mjpeg
->fields
; i
++)
1002 if(!mjpeg
->decompressors
[i
])
1004 mjpeg
->decompressors
[i
] = mjpeg_new_decompressor(mjpeg
, i
);
1008 //printf("mjpeg_decompress 3\n");
1009 /* Arm YUV buffers */
1010 mjpeg
->row_argument
= row_pointers
;
1011 mjpeg
->y_argument
= y_plane
;
1012 mjpeg
->u_argument
= u_plane
;
1013 mjpeg
->v_argument
= v_plane
;
1014 mjpeg
->input_data
= buffer
;
1015 mjpeg
->input_size
= buffer_len
;
1016 mjpeg
->input_field2
= input_field2
;
1017 mjpeg
->color_model
= color_model
;
1020 //printf("mjpeg_decompress 4 %02x %02x %d %02x %02x\n", buffer[0], buffer[1], input_field2, buffer[input_field2], buffer[input_field2 + 1]);
1021 /* Start decompressors */
1022 for(i
= 0; i
< mjpeg
->fields
&& !result
; i
++)
1024 unlock_compress_loop(mjpeg
->decompressors
[i
]);
1026 // For dual CPUs, don't want second thread to start until temp data is allocated by the first.
1027 // For single CPUs, don't want two threads running simultaneously
1028 if(mjpeg
->cpus
< 2 || !mjpeg
->temp_data
1029 /* && i < mjpeg->fields - 1 && !mjpeg->temp_data */)
1031 lock_compress_loop(mjpeg
->decompressors
[i
]);
1032 if(i
== 0) got_first_thread
= 1;
1036 //printf("mjpeg_decompress 5\n");
1037 /* Wait for decompressors */
1038 for(i
= 0; i
< mjpeg
->fields
&& !result
; i
++)
1042 if(i
> 0 || !got_first_thread
)
1043 lock_compress_loop(mjpeg
->decompressors
[i
]);
1046 //printf("mjpeg_decompress 6\n");
1048 /* Convert colormodel */
1049 // User colormodel didn't match decompressor
1051 * if(!mjpeg->error &&
1052 * (mjpeg->jpeg_color_model != mjpeg->color_model ||
1053 * mjpeg->coded_w != mjpeg->output_w ||
1054 * mjpeg->coded_h != mjpeg->output_h))
1057 if((mjpeg
->jpeg_color_model
!= mjpeg
->color_model
||
1058 mjpeg
->coded_w
!= mjpeg
->output_w
||
1059 mjpeg
->coded_h
!= mjpeg
->output_h
)
1061 (mjpeg
->temp_data
||
1065 * printf("mjpeg_decompress %d %d %d %d %d\n",
1066 * mjpeg->jpeg_color_model,
1067 * mjpeg->color_model,
1072 cmodel_transfer(row_pointers
,
1077 mjpeg
->temp_rows
[0][0],
1078 mjpeg
->temp_rows
[1][0],
1079 mjpeg
->temp_rows
[2][0],
1088 mjpeg
->jpeg_color_model
,
1092 mjpeg
->rowspan
? mjpeg
->rowspan
: mjpeg
->output_w
);
1094 //printf("mjpeg_decompress 7\n");
1099 void mjpeg_set_deinterlace(mjpeg_t
*mjpeg
, int value
)
1101 mjpeg
->deinterlace
= value
;
1104 void mjpeg_set_quality(mjpeg_t
*mjpeg
, int quality
)
1106 mjpeg
->quality
= quality
;
1109 void mjpeg_set_float(mjpeg_t
*mjpeg
, int use_float
)
1111 mjpeg
->use_float
= use_float
;
1114 void mjpeg_set_cpus(mjpeg_t
*mjpeg
, int cpus
)
1119 void mjpeg_set_rowspan(mjpeg_t
*mjpeg
, int rowspan
)
1121 mjpeg
->rowspan
= rowspan
;
1124 int mjpeg_get_fields(mjpeg_t
*mjpeg
)
1126 return mjpeg
->fields
;
1130 mjpeg_t
* mjpeg_new(int w
,
1134 mjpeg_t
*result
= calloc(1, sizeof(mjpeg_t
));
1135 pthread_mutexattr_t mutex_attr
;
1138 result
->output_w
= w
;
1139 result
->output_h
= h
;
1140 result
->fields
= fields
;
1141 result
->color_model
= BC_RGB888
;
1143 result
->quality
= 80;
1144 result
->use_float
= 0;
1146 pthread_mutexattr_init(&mutex_attr
);
1147 pthread_mutex_init(&(result
->decompress_init
), &mutex_attr
);
1150 // Calculate coded dimensions
1151 // An interlaced frame with 4:2:0 sampling must be a multiple of 32
1153 result
->coded_w
= (w
% 16) ? w
+ (16 - (w
% 16)) : w
;
1156 result
->coded_h
= (h
% 16) ? h
+ (16 - (h
% 16)) : h
;
1158 result
->coded_h
= (h
% 32) ? h
+ (32 - (h
% 32)) : h
;
1162 //printf("mjpeg_new %d %d %d %d\n", result->output_w, result->output_h, result->coded_w, result->coded_h);
1169 void mjpeg_delete(mjpeg_t
*mjpeg
)
1172 //printf("mjpeg_delete 1\n");
1173 for(i
= 0; i
< mjpeg
->fields
; i
++)
1175 //printf("mjpeg_delete 2\n");
1176 if(mjpeg
->compressors
[i
]) mjpeg_delete_compressor(mjpeg
->compressors
[i
]);
1177 //printf("mjpeg_delete 3\n");
1178 if(mjpeg
->decompressors
[i
]) mjpeg_delete_decompressor(mjpeg
->decompressors
[i
]);
1179 //printf("mjpeg_delete 4\n");
1181 //printf("mjpeg_delete 5\n");
1182 delete_temps(mjpeg
);
1183 //printf("mjpeg_delete 6\n");
1184 delete_buffer(&mjpeg
->output_data
, &mjpeg
->output_size
, &mjpeg
->output_allocated
);
1185 //printf("mjpeg_delete 7\n");
1187 //printf("mjpeg_delete 2\n");
1191 /* Open up a space to insert a marker */
1192 static void insert_space(unsigned char **buffer
,
1194 long *buffer_allocated
,
1199 // Make sure enough space is available
1200 if(*buffer_allocated
- *buffer_size
< space_len
)
1202 *buffer_allocated
+= space_len
;
1203 *buffer
= realloc(*buffer
, *buffer_allocated
);
1207 for(in
= *buffer_size
- 1, out
= *buffer_size
- 1 + space_len
;
1211 (*buffer
)[out
] = (*buffer
)[in
];
1213 *buffer_size
+= space_len
;
1217 static inline int nextbyte(unsigned char *data
, long *offset
, long length
)
1219 if(length
- *offset
< 1) return 0;
1221 return (unsigned char)data
[*offset
- 1];
1224 static inline int read_int32(unsigned char *data
, long *offset
, long length
)
1226 if(length
- *offset
< 4)
1232 return ((((unsigned int)data
[*offset
- 4]) << 24) |
1233 (((unsigned int)data
[*offset
- 3]) << 16) |
1234 (((unsigned int)data
[*offset
- 2]) << 8) |
1235 (((unsigned int)data
[*offset
- 1])));
1238 static inline int read_int16(unsigned char *data
, long *offset
, long length
)
1240 if(length
- *offset
< 2)
1247 return ((((unsigned int)data
[*offset
- 2]) << 8) |
1248 (((unsigned int)data
[*offset
- 1])));
1251 static inline unsigned char read_char(unsigned char *data
, long *offset
, long length
)
1253 if(length
- *offset
< 1)
1260 return (unsigned char)data
[*offset
- 1];
1263 static inline int next_int16(unsigned char *data
, long *offset
, long length
)
1265 if(length
- *offset
< 2)
1270 return ((((unsigned int)data
[*offset
]) << 8) |
1271 (((unsigned int)data
[*offset
+ 1])));
1274 static inline void write_int32(unsigned char *data
, long *offset
, long length
, unsigned int value
)
1276 if(length
- *offset
< 4)
1283 data
[(*offset
)++] = (unsigned int)(value
& 0xff000000) >> 24;
1284 data
[(*offset
)++] = (unsigned int)(value
& 0xff0000) >> 16;
1285 data
[(*offset
)++] = (unsigned int)(value
& 0xff00) >> 8;
1286 data
[(*offset
)++] = (unsigned char)(value
& 0xff);
1290 static inline void write_char(unsigned char *data
, long *offset
, long length
, unsigned char value
)
1292 if(length
- *offset
< 1)
1298 data
[(*offset
)++] = value
;
1302 static int next_marker(unsigned char *buffer
, long *offset
, long buffer_size
)
1304 int c
, done
= 0; /* 1 - completion 2 - error */
1306 while(*offset
< buffer_size
- 1)
1308 if(buffer
[*offset
] == 0xff && buffer
[*offset
+ 1] != 0xff)
1311 return buffer
[*offset
- 1];
1321 /* Find the next marker after offset and return 0 on success */
1322 static int find_marker(unsigned char *buffer
,
1325 unsigned long marker_type
)
1330 while(!result
&& *offset
< buffer_size
- 1)
1332 int marker
= next_marker(buffer
, offset
, buffer_size
);
1333 if(marker
== (marker_type
& 0xff)) result
= 1;
1343 int padded_field_size
;
1356 int unpadded_field_size
;
1359 #define LML_MARKER_SIZE 0x2c
1360 #define LML_MARKER_TAG 0xffe3
1361 void insert_lml33_markers(unsigned char **buffer
,
1362 long *field2_offset
,
1364 long *buffer_allocated
)
1366 long marker_offset
= -1;
1369 /* Search for existing marker to replace */
1370 // marker_offset = find_marker(*buffer, *buffer_size, LML_MARKER_TAG);
1372 /* Insert new marker */
1373 if(marker_offset
< 0)
1376 insert_space(buffer
,
1384 static int qt_table_offsets(unsigned char *buffer
,
1395 bzero(header
, sizeof(qt_hdr_t
) * 2);
1397 // Read every marker to get the offsets for the headers
1398 for(field
= 0; field
< 2; field
++)
1403 marker
= next_marker(buffer
,
1411 // The first field may be padded
1414 header
[0].next_offset
=
1415 header
[0].padded_field_size
=
1422 // Quicktime marker already exists. Abort.
1423 if(buffer
[offset
+ 6] == 'm' &&
1424 buffer
[offset
+ 7] == 'j' &&
1425 buffer
[offset
+ 8] == 'p' &&
1426 buffer
[offset
+ 9] == 'a')
1434 if(!header
[field
].quant_offset
)
1436 header
[field
].quant_offset
= offset
- 2;
1438 header
[field
].quant_offset
-= header
[0].next_offset
;
1440 len
= read_int16(buffer
, &offset
, buffer_size
);
1445 if(!header
[field
].huffman_offset
)
1447 header
[field
].huffman_offset
= offset
- 2;
1449 header
[field
].huffman_offset
-= header
[0].next_offset
;
1451 len
= read_int16(buffer
, &offset
, buffer_size
);
1456 if(!header
[field
].image_offset
)
1458 header
[field
].image_offset
= offset
- 2;
1460 header
[field
].image_offset
-= header
[0].next_offset
;
1462 len
= read_int16(buffer
, &offset
, buffer_size
);
1467 header
[field
].scan_offset
= offset
- 2;
1469 header
[field
].scan_offset
-= header
[0].next_offset
;
1470 len
= read_int16(buffer
, &offset
, buffer_size
);
1472 header
[field
].data_offset
= offset
+ len
;
1474 header
[field
].data_offset
-= header
[0].next_offset
;
1481 header
[field
].field_size
=
1482 header
[field
].padded_field_size
=
1483 offset
- header
[0].next_offset
;
1484 header
[field
].next_offset
= 0;
1488 // Often misses second SOI but gets first EOI
1489 // header[0].next_offset =
1490 // header[0].padded_field_size =
1493 //printf("table_offsets M_EOI %d %x\n", field, offset);
1499 // Junk appears between fields
1501 // len = read_int16(buffer, &offset, buffer_size);
1506 if(!done
) offset
+= len
;
1513 static void insert_quicktime_marker(unsigned char *buffer
,
1518 write_int32(buffer
, &offset
, buffer_size
, 0xff000000 |
1519 ((unsigned long)M_APP1
<< 16) |
1520 (QUICKTIME_MARKER_SIZE
- 2));
1521 write_int32(buffer
, &offset
, buffer_size
, 0);
1522 write_int32(buffer
, &offset
, buffer_size
, QUICKTIME_JPEG_TAG
);
1523 write_int32(buffer
, &offset
, buffer_size
, header
->field_size
);
1524 write_int32(buffer
, &offset
, buffer_size
, header
->padded_field_size
);
1525 write_int32(buffer
, &offset
, buffer_size
, header
->next_offset
);
1526 write_int32(buffer
, &offset
, buffer_size
, header
->quant_offset
);
1527 write_int32(buffer
, &offset
, buffer_size
, header
->huffman_offset
);
1528 write_int32(buffer
, &offset
, buffer_size
, header
->image_offset
);
1529 write_int32(buffer
, &offset
, buffer_size
, header
->scan_offset
);
1530 write_int32(buffer
, &offset
, buffer_size
, header
->data_offset
);
1534 void mjpeg_insert_quicktime_markers(unsigned char **buffer
,
1536 long *buffer_allocated
,
1538 long *field2_offset
)
1543 *field2_offset
= -1;
1545 if(fields
< 2) return;
1548 // Get offsets for tables in both fields
1549 exists
= qt_table_offsets(*buffer
, *buffer_size
, header
);
1551 // APP1 for quicktime already exists
1554 //printf("mjpeg_insert_quicktime_markers %x %02x %02x\n",
1555 // header[0].next_offset, (*buffer)[*field2_offset], (*buffer)[*field2_offset + 1]);
1556 //if(*field2_offset == 0)
1557 // fwrite(*buffer, *buffer_size, 1, stdout);
1561 header
[0].field_size
+= QUICKTIME_MARKER_SIZE
;
1562 header
[0].padded_field_size
+= QUICKTIME_MARKER_SIZE
;
1563 header
[0].next_offset
+= QUICKTIME_MARKER_SIZE
;
1564 header
[0].quant_offset
+= QUICKTIME_MARKER_SIZE
;
1565 header
[0].huffman_offset
+= QUICKTIME_MARKER_SIZE
;
1566 header
[0].image_offset
+= QUICKTIME_MARKER_SIZE
;
1567 header
[0].scan_offset
+= QUICKTIME_MARKER_SIZE
;
1568 header
[0].data_offset
+= QUICKTIME_MARKER_SIZE
;
1569 header
[1].field_size
+= QUICKTIME_MARKER_SIZE
;
1570 header
[1].padded_field_size
+= QUICKTIME_MARKER_SIZE
;
1571 header
[1].quant_offset
+= QUICKTIME_MARKER_SIZE
;
1572 header
[1].huffman_offset
+= QUICKTIME_MARKER_SIZE
;
1573 header
[1].image_offset
+= QUICKTIME_MARKER_SIZE
;
1574 header
[1].scan_offset
+= QUICKTIME_MARKER_SIZE
;
1575 header
[1].data_offset
+= QUICKTIME_MARKER_SIZE
;
1576 *field2_offset
= header
[0].next_offset
;
1580 // Insert APP1 marker
1581 insert_space(buffer
,
1585 QUICKTIME_MARKER_SIZE
);
1586 insert_quicktime_marker(*buffer
,
1591 insert_space(buffer
,
1594 header
[0].next_offset
+ 2,
1595 QUICKTIME_MARKER_SIZE
);
1596 header
[1].next_offset
= 0;
1597 insert_quicktime_marker(*buffer
,
1599 header
[0].next_offset
+ 2,
1604 static int avi_table_offsets(unsigned char *buffer
,
1608 int field2
= mjpeg_get_field2(buffer
, buffer_size
);
1610 header
[0].field_number
= 1;
1611 header
[0].field_size
= field2
;
1612 header
[0].unpadded_field_size
= field2
;
1614 header
[1].field_number
= 2;
1615 header
[1].field_size
= buffer_size
- field2
;
1616 header
[1].unpadded_field_size
= buffer_size
- field2
;
1620 static void insert_avi_marker(unsigned char *buffer
,
1625 write_int32(buffer
, &offset
, buffer_size
, 0xff000000 |
1626 ((unsigned long)M_APP0
<< 16) |
1627 (AVI_MARKER_SIZE
- 2));
1628 write_int32(buffer
, &offset
, buffer_size
, QUICKTIME_AVI_TAG
);
1630 // One version of McRoweSoft only allows field polarity while
1631 // another version allows field size.
1632 write_char(buffer
, &offset
, buffer_size
, header
->field_number
);
1633 write_char(buffer
, &offset
, buffer_size
, 0);
1634 write_int32(buffer
, &offset
, buffer_size
, header
->field_size
);
1635 write_int32(buffer
, &offset
, buffer_size
, header
->unpadded_field_size
);
1638 void mjpeg_insert_avi_markers(unsigned char **buffer
,
1640 long *buffer_allocated
,
1642 long *field2_offset
)
1644 avi_hdr_t header
[2];
1646 *field2_offset
= -1;
1649 // Test for existing marker
1650 if(!find_marker(*buffer
, &offset
, *buffer_size
, M_APP0
))
1652 if((*buffer
)[offset
+ 2] == 'A' &&
1653 (*buffer
)[offset
+ 3] == 'V' &&
1654 (*buffer
)[offset
+ 4] == 'I' &&
1655 (*buffer
)[offset
+ 5] == '1')
1660 avi_table_offsets(*buffer
, *buffer_size
, header
);
1662 header
[0].field_size
+= AVI_MARKER_SIZE
;
1663 header
[0].unpadded_field_size
+= AVI_MARKER_SIZE
;
1664 header
[1].field_size
+= AVI_MARKER_SIZE
;
1665 header
[1].unpadded_field_size
+= AVI_MARKER_SIZE
;
1666 *field2_offset
= header
[0].field_size
;
1668 // Insert APP0 marker into field 1
1669 insert_space(buffer
,
1674 insert_avi_marker(*buffer
,
1679 insert_space(buffer
,
1684 insert_avi_marker(*buffer
,
1694 static void read_avi_markers(unsigned char *buffer
,
1699 int marker_count
= 0;
1701 while(marker_count
< 2 && offset
< buffer_size
&& !result
)
1703 result
= find_marker(buffer
,
1710 // Marker size, AVI1
1713 header
[marker_count
].field_number
= read_char(buffer
, &offset
, buffer_size
);
1714 read_char(buffer
, &offset
, buffer_size
);
1715 header
[marker_count
].field_size
= read_int32(buffer
, &offset
, buffer_size
);
1716 header
[marker_count
].unpadded_field_size
= read_int32(buffer
, &offset
, buffer_size
);
1723 static void read_quicktime_markers(unsigned char *buffer
,
1728 int marker_count
= 0;
1731 while(marker_count
< 2 && offset
< buffer_size
&& !result
)
1733 result
= find_marker(buffer
,
1741 read_int16(buffer
, &offset
, buffer_size
);
1743 read_int32(buffer
, &offset
, buffer_size
);
1745 read_int32(buffer
, &offset
, buffer_size
);
1747 header
[marker_count
].field_size
= read_int32(buffer
, &offset
, buffer_size
);
1748 header
[marker_count
].padded_field_size
= read_int32(buffer
, &offset
, buffer_size
);
1749 header
[marker_count
].next_offset
= read_int32(buffer
, &offset
, buffer_size
);
1750 header
[marker_count
].quant_offset
= read_int32(buffer
, &offset
, buffer_size
);
1751 header
[marker_count
].huffman_offset
= read_int32(buffer
, &offset
, buffer_size
);
1752 header
[marker_count
].image_offset
= read_int32(buffer
, &offset
, buffer_size
);
1753 header
[marker_count
].scan_offset
= read_int32(buffer
, &offset
, buffer_size
);
1754 header
[marker_count
].data_offset
= read_int32(buffer
, &offset
, buffer_size
);
1758 //printf("read_quicktime_markers 1 %d\n", marker_count);
1761 long mjpeg_get_quicktime_field2(unsigned char *buffer
, long buffer_size
)
1764 bzero(&header
, sizeof(qt_hdr_t
) * 2);
1766 read_quicktime_markers(buffer
, buffer_size
, header
);
1767 return header
[0].next_offset
;
1770 long mjpeg_get_avi_field2(unsigned char *buffer
,
1772 int *field_dominance
)
1774 avi_hdr_t header
[2];
1775 bzero(&header
, sizeof(avi_hdr_t
) * 2);
1776 read_avi_markers(buffer
, buffer_size
, header
);
1778 *field_dominance
= (header
[0].field_number
== 1) ? 1 : 2;
1780 // One version of McRoweSoft only allows field polarity while
1781 // another version allows field size.
1782 if(header
[0].field_size
)
1784 return header
[0].field_size
;
1788 return mjpeg_get_field2(buffer
, buffer_size
);
1792 long mjpeg_get_field2(unsigned char *buffer
, long buffer_size
)
1795 int total_fields
= 0;
1797 long field2_offset
= 0;
1800 for(i
= 0; i
< buffer_size
; i
++)
1802 if(buffer
[i
] == 0xff && buffer
[i
+ 1] == M_SOI
)
1806 if(total_fields
== 2) break;
1811 return field2_offset
;
1814 void mjpeg_video_size(unsigned char *data
, long data_size
, int *w
, int *h
)
1821 *h
= (data
[offset
+ 3] << 8) | (data
[offset
+ 4]);
1822 *w
= (data
[offset
+ 5] << 8) | (data
[offset
+ 6]);