r864: Merge 2.1:
[cinelerra_cv.git] / quicktime / qtdv.c
blobc104ae63d81af7d1aa7cba1be18b72184d9a2799
1 /* 2002: Refurbished by Arthur Peters amep@softhome.net */
2 /* 2000: Original codec by Heroine Virtual */
5 #include "colormodels.h"
6 #include "funcprotos.h"
7 #include "libdv/dv.h"
8 #include "quicktime.h"
10 #include <pthread.h>
11 #include <string.h>
13 // Buffer sizes
14 #define DV_NTSC_SIZE 120000
15 #define DV_PAL_SIZE 144000
17 typedef struct
19 dv_decoder_t *dv_decoder;
20 dv_encoder_t *dv_encoder;
21 unsigned char *data;
22 unsigned char *temp_frame, **temp_rows;
24 /* Parameters */
25 int decode_quality;
26 int anamorphic16x9;
27 int vlc_encode_passes;
28 int clamp_luma, clamp_chroma;
30 int add_ntsc_setup;
32 int rem_ntsc_setup;
34 int parameters_changed;
35 } quicktime_dv_codec_t;
37 static pthread_mutex_t libdv_init_mutex = PTHREAD_MUTEX_INITIALIZER;
39 static int delete_codec(quicktime_video_map_t *vtrack)
41 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
43 if(codec->dv_decoder)
45 dv_decoder_free( codec->dv_decoder );
46 codec->dv_decoder = NULL;
49 if(codec->dv_encoder)
51 dv_encoder_free( codec->dv_encoder );
52 codec->dv_encoder = NULL;
55 if(codec->temp_frame) free(codec->temp_frame);
56 if(codec->temp_rows) free(codec->temp_rows);
57 free(codec->data);
58 free(codec);
59 return 0;
62 static int check_sequentiality( unsigned char **row_pointers,
63 int bytes_per_row,
64 int height )
66 int i = 0;
68 for(; i < height-1; i++)
70 if( row_pointers[i+1] - row_pointers[i] != bytes_per_row )
72 return 0;
75 return 1;
78 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
80 long bytes;
81 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
82 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
83 int width = vtrack->track->tkhd.track_width;
84 int height = vtrack->track->tkhd.track_height;
85 int result = 0;
86 int i;
87 int decode_colormodel = 0;
88 int pitches[3] = { 720 * 2, 0, 0 };
91 quicktime_set_video_position(file, vtrack->current_position, track);
92 bytes = quicktime_frame_size(file, vtrack->current_position, track);
93 result = !quicktime_read_data(file, (char*)codec->data, bytes);
95 if( codec->dv_decoder && codec->parameters_changed )
97 dv_decoder_free( codec->dv_decoder );
98 codec->dv_decoder = NULL;
99 codec->parameters_changed = 0;
102 if( ! codec->dv_decoder )
104 pthread_mutex_lock( &libdv_init_mutex );
107 codec->dv_decoder = dv_decoder_new( codec->add_ntsc_setup,
108 codec->clamp_luma,
109 codec->clamp_chroma );
110 codec->dv_decoder->prev_frame_decoded = 0;
112 codec->parameters_changed = 0;
113 pthread_mutex_unlock( &libdv_init_mutex );
116 if(codec->dv_decoder)
118 int is_sequential =
119 check_sequentiality( row_pointers,
120 720 * cmodel_calculate_pixelsize(file->color_model),
121 file->out_h );
123 codec->dv_decoder->quality = codec->decode_quality;
125 dv_parse_header( codec->dv_decoder, codec->data );
127 // Libdv improperly decodes RGB colormodels.
128 if((file->color_model == BC_YUV422 ||
129 file->color_model == BC_RGB888) &&
130 file->in_x == 0 &&
131 file->in_y == 0 &&
132 file->in_w == width &&
133 file->in_h == height &&
134 file->out_w == width &&
135 file->out_h == height &&
136 is_sequential)
138 if( file->color_model == BC_YUV422 )
140 pitches[0] = 720 * 2;
141 dv_decode_full_frame( codec->dv_decoder, codec->data,
142 e_dv_color_yuv, row_pointers,
143 pitches );
145 else
146 if( file->color_model == BC_RGB888)
148 pitches[0] = 720 * 3;
149 dv_decode_full_frame( codec->dv_decoder, codec->data,
150 e_dv_color_rgb, row_pointers,
151 pitches );
154 else
156 if(!codec->temp_frame)
158 codec->temp_frame = malloc(720 * 576 * 2);
159 codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
160 for(i = 0; i < 576; i++)
161 codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
164 decode_colormodel = BC_YUV422;
165 pitches[0] = 720 * 2;
166 dv_decode_full_frame( codec->dv_decoder, codec->data,
167 e_dv_color_yuv, codec->temp_rows,
168 pitches );
173 cmodel_transfer(row_pointers,
174 codec->temp_rows,
175 row_pointers[0],
176 row_pointers[1],
177 row_pointers[2],
178 codec->temp_rows[0],
179 codec->temp_rows[1],
180 codec->temp_rows[2],
181 file->in_x,
182 file->in_y,
183 file->in_w,
184 file->in_h,
187 file->out_w,
188 file->out_h,
189 decode_colormodel,
190 file->color_model,
192 width,
193 file->out_w);
197 //printf(__FUNCTION__ " 2\n");
198 return result;
201 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
203 int64_t offset = quicktime_position(file);
204 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
205 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
206 quicktime_trak_t *trak = vtrack->track;
207 int width = trak->tkhd.track_width;
208 int height = trak->tkhd.track_height;
209 int width_i = 720;
210 int height_i = (height <= 480) ? 480 : 576;
211 int i;
212 unsigned char **input_rows;
213 int is_pal = (height_i == 480) ? 0 : 1;
214 int data_length = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
215 int result = 0;
216 int encode_colormodel = 0;
217 dv_color_space_t encode_dv_colormodel = 0;
218 quicktime_atom_t chunk_atom;
220 if( codec->dv_encoder != NULL && codec->parameters_changed )
222 dv_encoder_free( codec->dv_encoder );
223 codec->dv_encoder = NULL;
224 codec->parameters_changed = 0;
227 if( ! codec->dv_encoder )
229 pthread_mutex_lock( &libdv_init_mutex );
231 //printf( "dv.c encode: Alloc'ing encoder\n" );
233 codec->dv_encoder = dv_encoder_new( codec->rem_ntsc_setup,
234 codec->clamp_luma,
235 codec->clamp_chroma );
237 codec->parameters_changed = 0;
238 pthread_mutex_unlock( &libdv_init_mutex );
241 if(codec->dv_encoder)
243 int is_sequential =
244 check_sequentiality( row_pointers,
245 width_i * cmodel_calculate_pixelsize(file->color_model),
246 height );
248 if( ( file->color_model == BC_YUV422
249 || file->color_model == BC_RGB888 ) &&
250 width == width_i &&
251 height == height_i &&
252 is_sequential )
254 input_rows = row_pointers;
255 encode_colormodel = file->color_model;
256 switch( file->color_model )
258 case BC_YUV422:
259 encode_dv_colormodel = e_dv_color_yuv;
260 //printf( "dv.c encode: e_dv_color_yuv\n" );
261 break;
262 case BC_RGB888:
263 encode_dv_colormodel = e_dv_color_rgb;
264 //printf( "dv.c encode: e_dv_color_rgb\n" );
265 break;
266 default:
267 return 0;
268 break;
271 else
273 // The best colormodel for encoding is YUV 422
275 if(!codec->temp_frame)
277 codec->temp_frame = malloc(720 * 576 * 2);
278 codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
279 for(i = 0; i < 576; i++)
280 codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
283 cmodel_transfer(codec->temp_rows, /* Leave NULL if non existent */
284 row_pointers,
285 codec->temp_rows[0], /* Leave NULL if non existent */
286 codec->temp_rows[1],
287 codec->temp_rows[2],
288 row_pointers[0], /* Leave NULL if non existent */
289 row_pointers[1],
290 row_pointers[2],
291 0, /* Dimensions to capture from input frame */
293 MIN(width, width_i),
294 MIN(height, height_i),
295 0, /* Dimensions to project on output frame */
297 MIN(width, width_i),
298 MIN(height, height_i),
299 file->color_model,
300 BC_YUV422,
301 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
302 width, /* For planar use the luma rowspan */
303 width_i);
306 input_rows = codec->temp_rows;
307 encode_colormodel = BC_YUV422;
308 encode_dv_colormodel = e_dv_color_yuv;
311 // Setup the encoder
312 codec->dv_encoder->is16x9 = codec->anamorphic16x9;
313 codec->dv_encoder->vlc_encode_passes = codec->vlc_encode_passes;
314 codec->dv_encoder->static_qno = 0;
315 codec->dv_encoder->force_dct = DV_DCT_AUTO;
316 codec->dv_encoder->isPAL = is_pal;
319 //printf("dv.c encode: 1 %d %d %d\n", width_i, height_i, encode_dv_colormodel);
320 dv_encode_full_frame( codec->dv_encoder,
321 input_rows, encode_dv_colormodel, codec->data );
322 //printf("dv.c encode: 2 %d %d\n", width_i, height_i);
324 quicktime_write_chunk_header(file, trak, &chunk_atom);
325 result = !quicktime_write_data(file, codec->data, data_length);
326 quicktime_write_chunk_footer(file,
327 trak,
328 vtrack->current_chunk,
329 &chunk_atom,
331 vtrack->current_chunk++;
332 //printf("encode 3\n");
335 return result;
338 // Logic: DV contains a mixture of 420 and 411 so can only
339 // output/input 444 or 422 and libdv can output/input RGB as well so
340 // we include that.
342 // This function is used as both reads_colormodel and writes_colormodel
343 static int colormodel_dv(quicktime_t *file,
344 int colormodel,
345 int track)
347 return (colormodel == BC_RGB888 ||
348 colormodel == BC_YUV888 ||
349 colormodel == BC_YUV422);
352 static int set_parameter(quicktime_t *file,
353 int track,
354 char *key,
355 void *value)
357 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)file->vtracks[track].codec)->priv;
359 if(!strcasecmp(key, "dv_decode_quality"))
361 codec->decode_quality = *(int*)value;
363 else if(!strcasecmp(key, "dv_anamorphic16x9"))
365 codec->anamorphic16x9 = *(int*)value;
367 else if(!strcasecmp(key, "dv_vlc_encode_passes"))
369 codec->vlc_encode_passes = *(int*)value;
371 else if(!strcasecmp(key, "dv_clamp_luma"))
373 codec->clamp_luma = *(int*)value;
375 else if(!strcasecmp(key, "dv_clamp_chroma"))
377 codec->clamp_chroma = *(int*)value;
379 else if(!strcasecmp(key, "dv_add_ntsc_setup"))
381 codec->add_ntsc_setup = *(int*)value;
383 else if(!strcasecmp(key, "dv_rem_ntsc_setup"))
385 codec->rem_ntsc_setup = *(int*)value;
387 else
389 return 0;
392 codec->parameters_changed = 1;
393 return 0;
396 static void init_codec_common(quicktime_video_map_t *vtrack, char *fourcc)
398 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
399 quicktime_dv_codec_t *codec;
400 int i;
402 /* Init public items */
403 codec_base->priv = calloc(1, sizeof(quicktime_dv_codec_t));
404 codec_base->delete_vcodec = delete_codec;
405 codec_base->decode_video = decode;
406 codec_base->encode_video = encode;
407 codec_base->decode_audio = 0;
408 codec_base->encode_audio = 0;
409 codec_base->reads_colormodel = colormodel_dv;
410 codec_base->writes_colormodel = colormodel_dv;
411 codec_base->set_parameter = set_parameter;
412 codec_base->fourcc = fourcc;
413 codec_base->title = "DV";
414 codec_base->desc = "DV";
417 /* Init private items */
419 codec = codec_base->priv;
421 codec->dv_decoder = NULL;
422 codec->dv_encoder = NULL;
423 codec->decode_quality = DV_QUALITY_BEST;
424 codec->anamorphic16x9 = 0;
425 codec->vlc_encode_passes = 3;
426 codec->clamp_luma = codec->clamp_chroma = 0;
427 codec->add_ntsc_setup = 0;
428 codec->parameters_changed = 0;
430 // Allocate extra to work around some libdv overrun
431 codec->data = calloc(1, 144008);
434 void quicktime_init_codec_dv(quicktime_video_map_t *vtrack)
436 init_codec_common(vtrack, QUICKTIME_DV);
439 void quicktime_init_codec_dvcp(quicktime_video_map_t *vtrack)
441 init_codec_common(vtrack, QUICKTIME_DVCP);
445 void quicktime_init_codec_dv25(quicktime_video_map_t *vtrack)
447 init_codec_common(vtrack, QUICKTIME_DV25);
450 void quicktime_init_codec_dvsd(quicktime_video_map_t *vtrack)
452 init_codec_common(vtrack, QUICKTIME_DVSD);