r105: This commit was manufactured by cvs2svn to create tag
[cinelerra_cv/mob.git] / hvirtual / quicktime / dv.c
blobfe09aa2f8683dfcfd4dd87bc91c800bdc1f6ce3b
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;
67 //printf( "dv.c check_sequentiality: %p, %d, %d\n", row_pointers, bytes_per_row, height );
69 for(; i < height-1; i++)
71 if( row_pointers[i+1] - row_pointers[i] != bytes_per_row )
73 //printf( "dv.c check_sequentiality: %p - %p != %p\n", row_pointers[i+1], row_pointers[i], bytes_per_row );
74 return 0;
77 return 1;
80 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
82 long bytes;
83 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
84 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
85 int width = vtrack->track->tkhd.track_width;
86 int height = vtrack->track->tkhd.track_height;
87 int result = 0;
88 int i;
89 int decode_colormodel = 0;
90 int pitches[3] = { 720 * 2, 0, 0 };
92 //printf( "dv.c decode: row_pointers=%p {%p, %p, %p, %p, ...}\n", row_pointers, row_pointers[0], row_pointers[1], row_pointers[2], row_pointers[3] );
94 //printf(__FUNCTION__ " 1\n");
95 quicktime_set_video_position(file, vtrack->current_position, track);
96 bytes = quicktime_frame_size(file, vtrack->current_position, track);
97 result = !quicktime_read_data(file, (char*)codec->data, bytes);
99 //printf(__FUNCTION__ " 1\n");
100 if( codec->dv_decoder && codec->parameters_changed )
102 dv_decoder_free( codec->dv_decoder );
103 codec->dv_decoder = NULL;
104 codec->parameters_changed = 0;
107 //printf(__FUNCTION__ " 2\n");
108 if( ! codec->dv_decoder )
110 pthread_mutex_lock( &libdv_init_mutex );
112 //printf( "dv.c decode: Alloc'ing decoder\n" );
114 codec->dv_decoder = dv_decoder_new( codec->add_ntsc_setup,
115 codec->clamp_luma,
116 codec->clamp_chroma );
117 codec->dv_decoder->prev_frame_decoded = 0;
119 codec->parameters_changed = 0;
120 pthread_mutex_unlock( &libdv_init_mutex );
123 //printf(__FUNCTION__ " 3\n");
124 if(codec->dv_decoder)
126 //printf(__FUNCTION__ " 4\n");
127 int is_sequential =
128 check_sequentiality( row_pointers,
129 720 * cmodel_calculate_pixelsize(file->color_model),
130 file->out_h );
131 //printf(__FUNCTION__ " 5\n");
133 codec->dv_decoder->quality = codec->decode_quality;
134 //printf(__FUNCTION__ " 6\n");
136 dv_parse_header( codec->dv_decoder, codec->data );
137 //printf(__FUNCTION__ " 7\n");
139 // Libdv improperly decodes RGB colormodels.
140 if( (file->color_model == BC_YUV422
141 /* || file->color_model == BC_RGB888 */) &&
142 file->in_x == 0 &&
143 file->in_y == 0 &&
144 file->in_w == width &&
145 file->in_h == height &&
146 file->out_w == width &&
147 file->out_h == height &&
148 is_sequential )
150 if( file->color_model == BC_YUV422 )
152 pitches[0] = 720 * 2;
153 //printf(__FUNCTION__ " 7.1\n");
154 dv_decode_full_frame( codec->dv_decoder, codec->data,
155 e_dv_color_yuv, row_pointers,
156 pitches );
157 //printf(__FUNCTION__ " 7.2\n");
159 else
160 if( file->color_model == BC_RGB888)
162 pitches[0] = 720 * 3;
163 //printf(__FUNCTION__ " 7.3\n");
164 dv_decode_full_frame( codec->dv_decoder, codec->data,
165 e_dv_color_rgb, row_pointers,
166 pitches );
167 //printf(__FUNCTION__ " 7.4\n");
170 else
172 //printf(__FUNCTION__ " 8\n");
173 if(!codec->temp_frame)
175 codec->temp_frame = malloc(720 * 576 * 2);
176 codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
177 for(i = 0; i < 576; i++)
178 codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
180 //printf(__FUNCTION__ " 8\n");
182 decode_colormodel = BC_YUV422;
183 pitches[0] = 720 * 2;
184 dv_decode_full_frame( codec->dv_decoder, codec->data,
185 e_dv_color_yuv, codec->temp_rows,
186 pitches );
187 //printf(__FUNCTION__ " 8\n");
191 * printf( "decode 8 %02x%02x%02x%02x\n",
192 * codec->temp_rows[0][0],
193 * codec->temp_rows[0][1],
194 * codec->temp_rows[0][2],
195 * codec->temp_rows[0][3]
200 cmodel_transfer(row_pointers,
201 codec->temp_rows,
202 row_pointers[0],
203 row_pointers[1],
204 row_pointers[2],
205 codec->temp_rows[0],
206 codec->temp_rows[1],
207 codec->temp_rows[2],
208 file->in_x,
209 file->in_y,
210 file->in_w,
211 file->in_h,
214 file->out_w,
215 file->out_h,
216 decode_colormodel,
217 file->color_model,
219 width,
220 file->out_w);
222 * printf( "decode 9 %02x%02x%02x%02x\n",
223 * row_pointers[0][0],
224 * row_pointers[0][1],
225 * row_pointers[0][2],
226 * row_pointers[0][3]
227 * );
229 //printf("decode 9\n");
233 //printf(__FUNCTION__ " 2\n");
234 return result;
237 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
239 int64_t offset = quicktime_position(file);
240 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
241 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
242 quicktime_trak_t *trak = vtrack->track;
243 int width = trak->tkhd.track_width;
244 int height = trak->tkhd.track_height;
245 int width_i = 720;
246 int height_i = (height <= 480) ? 480 : 576;
247 int i;
248 unsigned char **input_rows;
249 int is_pal = (height_i == 480) ? 0 : 1;
250 int data_length = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
251 int result = 0;
252 int encode_colormodel = 0;
253 dv_color_space_t encode_dv_colormodel = 0;
254 quicktime_atom_t chunk_atom;
256 if( codec->dv_encoder != NULL && codec->parameters_changed )
258 dv_encoder_free( codec->dv_encoder );
259 codec->dv_encoder = NULL;
260 codec->parameters_changed = 0;
263 if( ! codec->dv_encoder )
265 pthread_mutex_lock( &libdv_init_mutex );
267 //printf( "dv.c encode: Alloc'ing encoder\n" );
269 codec->dv_encoder = dv_encoder_new( codec->rem_ntsc_setup,
270 codec->clamp_luma,
271 codec->clamp_chroma );
273 codec->parameters_changed = 0;
274 pthread_mutex_unlock( &libdv_init_mutex );
277 if(codec->dv_encoder)
279 int is_sequential =
280 check_sequentiality( row_pointers,
281 width_i * cmodel_calculate_pixelsize(file->color_model),
282 height );
284 if( ( file->color_model == BC_YUV422
285 || file->color_model == BC_RGB888 ) &&
286 width == width_i &&
287 height == height_i &&
288 is_sequential )
290 input_rows = row_pointers;
291 encode_colormodel = file->color_model;
292 switch( file->color_model )
294 case BC_YUV422:
295 encode_dv_colormodel = e_dv_color_yuv;
296 //printf( "dv.c encode: e_dv_color_yuv\n" );
297 break;
298 case BC_RGB888:
299 encode_dv_colormodel = e_dv_color_rgb;
300 //printf( "dv.c encode: e_dv_color_rgb\n" );
301 break;
302 default:
303 return 0;
304 break;
307 else
309 // The best colormodel for encoding is YUV 422
311 if(!codec->temp_frame)
313 codec->temp_frame = malloc(720 * 576 * 2);
314 codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
315 for(i = 0; i < 576; i++)
316 codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
319 cmodel_transfer(codec->temp_rows, /* Leave NULL if non existent */
320 row_pointers,
321 codec->temp_rows[0], /* Leave NULL if non existent */
322 codec->temp_rows[1],
323 codec->temp_rows[2],
324 row_pointers[0], /* Leave NULL if non existent */
325 row_pointers[1],
326 row_pointers[2],
327 0, /* Dimensions to capture from input frame */
329 MIN(width, width_i),
330 MIN(height, height_i),
331 0, /* Dimensions to project on output frame */
333 MIN(width, width_i),
334 MIN(height, height_i),
335 file->color_model,
336 BC_YUV422,
337 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
338 width, /* For planar use the luma rowspan */
339 width_i);
342 input_rows = codec->temp_rows;
343 encode_colormodel = BC_YUV422;
344 encode_dv_colormodel = e_dv_color_yuv;
347 // Setup the encoder
348 codec->dv_encoder->is16x9 = codec->anamorphic16x9;
349 codec->dv_encoder->vlc_encode_passes = codec->vlc_encode_passes;
350 codec->dv_encoder->static_qno = 0;
351 codec->dv_encoder->force_dct = DV_DCT_AUTO;
352 codec->dv_encoder->isPAL = is_pal;
355 //printf("dv.c encode: 1 %d %d %d\n", width_i, height_i, encode_dv_colormodel);
356 dv_encode_full_frame( codec->dv_encoder,
357 input_rows, encode_dv_colormodel, codec->data );
358 //printf("dv.c encode: 2 %d %d\n", width_i, height_i);
360 quicktime_write_chunk_header(file, trak, &chunk_atom);
361 result = !quicktime_write_data(file, codec->data, data_length);
362 quicktime_write_chunk_footer(file,
363 trak,
364 vtrack->current_chunk,
365 &chunk_atom,
367 vtrack->current_chunk++;
368 //printf("encode 3\n");
371 return result;
374 // Logic: DV contains a mixture of 420 and 411 so can only
375 // output/input 444 or 422 and libdv can output/input RGB as well so
376 // we include that.
378 // This function is used as both reads_colormodel and writes_colormodel
379 static int colormodel_dv(quicktime_t *file,
380 int colormodel,
381 int track)
383 return (colormodel == BC_RGB888 ||
384 colormodel == BC_YUV888 ||
385 colormodel == BC_YUV422);
388 static int set_parameter(quicktime_t *file,
389 int track,
390 char *key,
391 void *value)
393 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)file->vtracks[track].codec)->priv;
395 if(!strcasecmp(key, "dv_decode_quality"))
397 codec->decode_quality = *(int*)value;
399 else if(!strcasecmp(key, "dv_anamorphic16x9"))
401 codec->anamorphic16x9 = *(int*)value;
403 else if(!strcasecmp(key, "dv_vlc_encode_passes"))
405 codec->vlc_encode_passes = *(int*)value;
407 else if(!strcasecmp(key, "dv_clamp_luma"))
409 codec->clamp_luma = *(int*)value;
411 else if(!strcasecmp(key, "dv_clamp_chroma"))
413 codec->clamp_chroma = *(int*)value;
415 else if(!strcasecmp(key, "dv_add_ntsc_setup"))
417 codec->add_ntsc_setup = *(int*)value;
419 else if(!strcasecmp(key, "dv_rem_ntsc_setup"))
421 codec->rem_ntsc_setup = *(int*)value;
423 else
425 return 0;
428 codec->parameters_changed = 1;
429 return 0;
432 static void init_codec_common(quicktime_video_map_t *vtrack, char *fourcc)
434 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
435 quicktime_dv_codec_t *codec;
436 int i;
438 /* Init public items */
439 codec_base->priv = calloc(1, sizeof(quicktime_dv_codec_t));
440 codec_base->delete_vcodec = delete_codec;
441 codec_base->decode_video = decode;
442 codec_base->encode_video = encode;
443 codec_base->decode_audio = 0;
444 codec_base->encode_audio = 0;
445 codec_base->reads_colormodel = colormodel_dv;
446 codec_base->writes_colormodel = colormodel_dv;
447 codec_base->set_parameter = set_parameter;
448 codec_base->fourcc = fourcc;
449 codec_base->title = "DV";
450 codec_base->desc = "DV";
453 /* Init private items */
455 codec = codec_base->priv;
457 codec->dv_decoder = NULL;
458 codec->dv_encoder = NULL;
459 codec->decode_quality = DV_QUALITY_BEST;
460 codec->anamorphic16x9 = 0;
461 codec->vlc_encode_passes = 3;
462 codec->clamp_luma = codec->clamp_chroma = 0;
463 codec->add_ntsc_setup = 0;
464 codec->parameters_changed = 0;
466 // Allocate extra to work around some libdv overrun
467 codec->data = calloc(1, 144008);
470 void quicktime_init_codec_dv(quicktime_video_map_t *vtrack)
472 init_codec_common(vtrack, QUICKTIME_DV);
475 void quicktime_init_codec_dvsd(quicktime_video_map_t *vtrack)
477 init_codec_common(vtrack, QUICKTIME_DVSD);