allow ffmpeg video to resample curr_pos, add bluray format
[goodguy/history.git] / cinelerra-5.0 / quicktime / jpeg.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <strings.h>
4 #include <unistd.h>
5 #include "colormodels.h"
6 #include "funcprotos.h"
7 #include "jpeg.h"
8 #include "libmjpeg.h"
9 #include "quicktime.h"
10
11 // Jpeg types
12 #define JPEG_PROGRESSIVE 0
13 #define JPEG_MJPA 1
14 #define JPEG_MJPB 2
15
16 typedef struct
17 {
18         unsigned char *buffer;
19         long buffer_allocated;
20         long buffer_size;
21         mjpeg_t *mjpeg;
22         int jpeg_type;
23         unsigned char *temp_video;
24         int initialized;
25         int quality;
26         int use_float;
27 } quicktime_jpeg_codec_t;
28
29 static void delete_codec(quicktime_video_map_t *vtrack)
30 {
31         quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
32
33         if(codec->mjpeg) mjpeg_delete(codec->mjpeg);
34         if(codec->buffer)
35                 free(codec->buffer);
36         if(codec->temp_video)
37                 free(codec->temp_video);
38         free(codec);
39 }
40
41 void quicktime_set_jpeg(quicktime_t *file, int quality, int use_float)
42 {
43         int i;
44
45 printf("1\n");
46         for(i = 0; i < file->total_vtracks; i++)
47         {
48                 if(quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_JPEG) ||
49                         quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_MJPA) ||
50                         quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_RTJ0))
51                 {
52                         quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)file->vtracks[i].codec)->priv;
53                         codec->quality = quality;
54                         codec->use_float = use_float;
55                 }
56         }
57 printf("10\n");
58 }
59
60
61 static void initialize(quicktime_video_map_t *vtrack)
62 {
63         quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
64         if(!codec->initialized)
65         {
66 /* Init private items */
67                 codec->mjpeg = mjpeg_new(vtrack->track->tkhd.track_width, 
68                         vtrack->track->tkhd.track_height, 
69                         1 + (codec->jpeg_type == JPEG_MJPA || codec->jpeg_type == JPEG_MJPB));
70
71 /* This information must be stored in the initialization routine because of */
72 /* direct copy rendering.  Quicktime for Windows must have this information. */
73                 if(codec->jpeg_type == JPEG_MJPA && 
74                         !vtrack->track->mdia.minf.stbl.stsd.table[0].fields)
75                 {
76                         vtrack->track->mdia.minf.stbl.stsd.table[0].fields = 2;
77                         vtrack->track->mdia.minf.stbl.stsd.table[0].field_dominance = 1;
78                 }
79                 codec->initialized = 1;
80         }
81 }
82
83 static int decode(quicktime_t *file, 
84         unsigned char **row_pointers, 
85         int track)
86 {
87         quicktime_video_map_t *vtrack = &(file->vtracks[track]);
88         initialize(vtrack);
89         quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
90         quicktime_trak_t *trak = vtrack->track;
91         mjpeg_t *mjpeg = codec->mjpeg;
92         long size, field2_offset = 0;
93         int track_height = trak->tkhd.track_height;
94         int track_width = trak->tkhd.track_width;
95         int result = 0;
96         int field_dominance = trak->mdia.minf.stbl.stsd.table[0].field_dominance;
97
98         mjpeg_set_cpus(codec->mjpeg, file->cpus);
99         if(file->row_span) 
100                 mjpeg_set_rowspan(codec->mjpeg, file->row_span);
101         else
102                 mjpeg_set_rowspan(codec->mjpeg, 0);
103
104         quicktime_set_video_position(file, vtrack->current_position, track);
105         size = quicktime_frame_size(file, vtrack->current_position, track);
106         codec->buffer_size = size;
107
108         if(size > codec->buffer_allocated)
109         {
110                 codec->buffer_allocated = size;
111                 codec->buffer = realloc(codec->buffer, codec->buffer_allocated);
112         }
113
114         result = !quicktime_read_data(file, (char*)codec->buffer, size);
115 /*
116  * printf("decode 1 %02x %02x %02x %02x %02x %02x %02x %02x\n", 
117  * codec->buffer[0],
118  * codec->buffer[1],
119  * codec->buffer[2],
120  * codec->buffer[3],
121  * codec->buffer[4],
122  * codec->buffer[5],
123  * codec->buffer[6],
124  * codec->buffer[7]
125  * );
126  */
127
128         if(!result)
129         {
130                 if(mjpeg_get_fields(mjpeg) == 2)
131                 {
132                         if(file->use_avi)
133                         {
134                                 field2_offset = mjpeg_get_avi_field2(codec->buffer, 
135                                         size, 
136                                         &field_dominance);
137                         }
138                         else
139                         {
140                                 field2_offset = mjpeg_get_quicktime_field2(codec->buffer, 
141                                         size);
142 // Sanity check
143                                 if(!field2_offset)
144                                 {
145                                         printf("decode: FYI field2_offset=0\n");
146                                         field2_offset = mjpeg_get_field2(codec->buffer, size);
147                                 }
148                         }
149                 }
150                 else
151                         field2_offset = 0;
152
153
154 //printf("decode 2 %d\n", field2_offset);
155 /*
156  * printf("decode result=%d field1=%llx field2=%llx size=%d %02x %02x %02x %02x\n", 
157  * result, 
158  * quicktime_position(file) - size,
159  * quicktime_position(file) - size + field2_offset,
160  * size,
161  * codec->buffer[0], 
162  * codec->buffer[1], 
163  * codec->buffer[field2_offset + 0], 
164  * codec->buffer[field2_offset + 1]);
165  */
166
167                 if(file->in_x == 0 && 
168                         file->in_y == 0 && 
169                         file->in_w == track_width &&
170                         file->in_h == track_height &&
171                         file->out_w == track_width &&
172                         file->out_h == track_height)
173                 {
174                         mjpeg_decompress(codec->mjpeg, 
175                                 codec->buffer, 
176                                 size,
177                                 field2_offset,  
178                                 row_pointers, 
179                                 row_pointers[0], 
180                                 row_pointers[1], 
181                                 row_pointers[2],
182                                 file->color_model,
183                                 file->cpus);
184                 }
185                 else
186                 {
187                         int i;
188                         unsigned char **temp_rows;
189                         int temp_cmodel = BC_YUV888;
190                         int temp_rowsize = cmodel_calculate_pixelsize(temp_cmodel) * track_width;
191
192                         if(!codec->temp_video)
193                                 codec->temp_video = malloc(temp_rowsize * track_height);
194                         temp_rows = malloc(sizeof(unsigned char*) * track_height);
195                         for(i = 0; i < track_height; i++)
196                                 temp_rows[i] = codec->temp_video + i * temp_rowsize;
197
198 //printf("decode 10\n");
199                         mjpeg_decompress(codec->mjpeg, 
200                                 codec->buffer, 
201                                 size,
202                                 field2_offset,  
203                                 temp_rows, 
204                                 temp_rows[0], 
205                                 temp_rows[1], 
206                                 temp_rows[2],
207                                 temp_cmodel,
208                                 file->cpus);
209
210                         cmodel_transfer(row_pointers, 
211                                 temp_rows,
212                                 row_pointers[0],
213                                 row_pointers[1],
214                                 row_pointers[2],
215                                 temp_rows[0],
216                                 temp_rows[1],
217                                 temp_rows[2],
218                                 file->in_x, 
219                                 file->in_y, 
220                                 file->in_w, 
221                                 file->in_h,
222                                 0, 
223                                 0, 
224                                 file->out_w, 
225                                 file->out_h,
226                                 temp_cmodel, 
227                                 file->color_model,
228                                 0,
229                                 track_width,
230                                 file->out_w);
231
232 //printf("decode 30\n");
233                         free(temp_rows);
234
235 //printf("decode 40\n");
236                 }
237         }
238 //printf("decode 2 %d\n", result);
239
240         return result;
241 }
242
243 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
244 {
245         quicktime_video_map_t *vtrack = &(file->vtracks[track]);
246         initialize(vtrack);
247         quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
248         quicktime_trak_t *trak = vtrack->track;
249         mjpeg_set_quality(codec->mjpeg, codec->quality);
250         mjpeg_set_float(codec->mjpeg, codec->use_float);
251         //int64_t offset = quicktime_position(file);
252         int result = 0;
253         long field2_offset;
254         quicktime_atom_t chunk_atom;
255
256 //printf("encode 1\n");
257         mjpeg_set_cpus(codec->mjpeg, file->cpus);
258         mjpeg_compress(codec->mjpeg, row_pointers, 
259                 row_pointers[0], row_pointers[1], row_pointers[2],
260                 file->color_model, file->cpus);
261
262         if(codec->jpeg_type == JPEG_MJPA)
263         {
264                 if(file->use_avi)
265                 {
266                         mjpeg_insert_avi_markers(&codec->mjpeg->output_data,
267                                 &codec->mjpeg->output_size,
268                                 &codec->mjpeg->output_allocated,
269                                 2,
270                                 &field2_offset);
271                 }
272                 else
273                 {
274                         mjpeg_insert_quicktime_markers(&codec->mjpeg->output_data,
275                                 &codec->mjpeg->output_size,
276                                 &codec->mjpeg->output_allocated,
277                                 2,
278                                 &field2_offset);
279                 }
280         }
281
282         quicktime_write_chunk_header(file, trak, &chunk_atom);
283         result = !quicktime_write_data(file, 
284                                 (char*)mjpeg_output_buffer(codec->mjpeg), 
285                                 mjpeg_output_size(codec->mjpeg));
286         quicktime_write_chunk_footer(file, 
287                                         trak,
288                                         vtrack->current_chunk,
289                                         &chunk_atom, 
290                                         1);
291
292         vtrack->current_chunk++;
293 //printf("encode 100\n");
294         return result;
295 }
296
297 static int reads_colormodel(quicktime_t *file, 
298                 int colormodel, 
299                 int track)
300 {
301         quicktime_video_map_t *vtrack = &(file->vtracks[track]);
302         quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
303
304 // Some JPEG_PROGRESSIVE is BC_YUV422P
305         if(codec->jpeg_type == JPEG_PROGRESSIVE)
306         {
307                 return (colormodel == BC_RGB888 ||
308                         colormodel == BC_YUV888 ||
309                         colormodel == BC_YUV420P ||
310                         colormodel == BC_YUV422P ||
311                         colormodel == BC_YUV422);
312         }
313         else
314         {
315                 return (colormodel == BC_RGB888 ||
316                         colormodel == BC_YUV888 ||
317 //                      colormodel == BC_YUV420P ||
318                         colormodel == BC_YUV422P ||
319                         colormodel == BC_YUV422);
320 // The BC_YUV420P option was provided only for mpeg2movie use.because some 
321 // interlaced movies were accidentally in YUV4:2:0
322         }
323 }
324
325 static int writes_colormodel(quicktime_t *file, 
326                 int colormodel, 
327                 int track)
328 {
329         quicktime_video_map_t *vtrack = &(file->vtracks[track]);
330         quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
331
332         if(codec->jpeg_type == JPEG_PROGRESSIVE)
333         {
334                 return (colormodel == BC_RGB888 ||
335                         colormodel == BC_YUV888 ||
336                         colormodel == BC_YUV420P);
337         }
338         else
339         {
340                 return (colormodel == BC_RGB888 ||
341                         colormodel == BC_YUV888 ||
342                         colormodel == BC_YUV422P);
343         }
344 }
345
346 static int set_parameter(quicktime_t *file, 
347                 int track, 
348                 char *key, 
349                 void *value)
350 {
351         quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)file->vtracks[track].codec)->priv;
352         
353         if(!strcasecmp(key, "jpeg_quality"))
354         {
355                 codec->quality = *(int*)value;
356         }
357         else
358         if(!strcasecmp(key, "jpeg_usefloat"))
359         {
360                 codec->use_float = *(int*)value;
361         }
362         return 0;
363 }
364
365 static void init_codec_common(quicktime_video_map_t *vtrack, char *compressor)
366 {
367         quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
368         quicktime_jpeg_codec_t *codec;
369
370         codec = codec_base->priv = calloc(1, sizeof(quicktime_jpeg_codec_t));
371         if(quicktime_match_32(compressor, QUICKTIME_JPEG))
372                 codec->jpeg_type = JPEG_PROGRESSIVE;
373         if(quicktime_match_32(compressor, QUICKTIME_MJPA))
374                 codec->jpeg_type = JPEG_MJPA;
375         codec->quality = 80;
376         codec->use_float = 0;
377
378 /* Init public items */
379         codec_base->delete_vcodec = delete_codec;
380         codec_base->decode_video = decode;
381         codec_base->encode_video = encode;
382         codec_base->decode_audio = 0;
383         codec_base->encode_audio = 0;
384         codec_base->reads_colormodel = reads_colormodel;
385         codec_base->writes_colormodel = writes_colormodel;
386         codec_base->set_parameter = set_parameter;
387         codec_base->fourcc = compressor;
388         codec_base->title = (codec->jpeg_type == JPEG_PROGRESSIVE ? "JPEG Photo" : "Motion JPEG A");
389         codec_base->desc = codec_base->title;
390
391 }
392
393 void quicktime_init_codec_jpeg(quicktime_video_map_t *vtrack)
394 {
395         init_codec_common(vtrack, QUICKTIME_JPEG);
396 }
397
398 void quicktime_init_codec_mjpa(quicktime_video_map_t *vtrack)
399 {
400         init_codec_common(vtrack, QUICKTIME_MJPA);
401 }
402
403 void quicktime_init_codec_mjpg(quicktime_video_map_t *vtrack)
404 {
405         init_codec_common(vtrack, QUICKTIME_MJPG);
406 }
407
408
409
410
411