1 /* 2002: Refurbished by Arthur Peters amep@softhome.net */
2 /* 2000: Original codec by Heroine Virtual */
5 #include "colormodels.h"
6 #include "funcprotos.h"
14 #define DV_NTSC_SIZE 120000
15 #define DV_PAL_SIZE 144000
19 dv_decoder_t *dv_decoder;
20 dv_encoder_t *dv_encoder;
22 unsigned char *temp_frame, **temp_rows;
27 int vlc_encode_passes;
28 int clamp_luma, clamp_chroma;
34 int parameters_changed;
35 } quicktime_dv_codec_t;
37 static pthread_mutex_t libdv_init_mutex = PTHREAD_MUTEX_INITIALIZER;
39 static void delete_codec(quicktime_video_map_t *vtrack)
41 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
45 dv_decoder_free( codec->dv_decoder );
46 codec->dv_decoder = NULL;
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);
61 static int check_sequentiality( unsigned char **row_pointers,
67 for(; i < height-1; i++)
69 if( row_pointers[i+1] - row_pointers[i] != bytes_per_row )
77 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
80 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
81 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
82 int width = vtrack->track->tkhd.track_width;
83 int height = vtrack->track->tkhd.track_height;
86 int decode_colormodel = 0;
87 int pitches[3] = { 720 * 2, 0, 0 };
90 quicktime_set_video_position(file, vtrack->current_position, track);
91 bytes = quicktime_frame_size(file, vtrack->current_position, track);
92 result = !quicktime_read_data(file, (char*)codec->data, bytes);
94 if( codec->dv_decoder && codec->parameters_changed )
96 dv_decoder_free( codec->dv_decoder );
97 codec->dv_decoder = NULL;
98 codec->parameters_changed = 0;
101 if( ! codec->dv_decoder )
103 pthread_mutex_lock( &libdv_init_mutex );
106 codec->dv_decoder = dv_decoder_new( codec->add_ntsc_setup,
108 codec->clamp_chroma );
109 codec->dv_decoder->prev_frame_decoded = 0;
111 codec->parameters_changed = 0;
112 pthread_mutex_unlock( &libdv_init_mutex );
115 if(codec->dv_decoder)
118 check_sequentiality( row_pointers,
119 720 * cmodel_calculate_pixelsize(file->color_model),
122 codec->dv_decoder->quality = codec->decode_quality;
124 dv_parse_header( codec->dv_decoder, codec->data );
126 // Libdv improperly decodes RGB colormodels.
127 if((file->color_model == BC_YUV422 ||
128 file->color_model == BC_RGB888) &&
131 file->in_w == width &&
132 file->in_h == height &&
133 file->out_w == width &&
134 file->out_h == height &&
137 if( file->color_model == BC_YUV422 )
139 pitches[0] = 720 * 2;
140 dv_decode_full_frame( codec->dv_decoder, codec->data,
141 e_dv_color_yuv, row_pointers,
145 if( file->color_model == BC_RGB888)
147 pitches[0] = 720 * 3;
148 dv_decode_full_frame( codec->dv_decoder, codec->data,
149 e_dv_color_rgb, row_pointers,
155 if(!codec->temp_frame)
157 codec->temp_frame = malloc(720 * 576 * 2);
158 codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
159 for(i = 0; i < 576; i++)
160 codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
163 decode_colormodel = BC_YUV422;
164 pitches[0] = 720 * 2;
165 dv_decode_full_frame( codec->dv_decoder, codec->data,
166 e_dv_color_yuv, codec->temp_rows,
172 cmodel_transfer(row_pointers,
196 //printf(__FUNCTION__ " 2\n");
200 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
202 //int64_t offset = quicktime_position(file);
203 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
204 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
205 quicktime_trak_t *trak = vtrack->track;
206 int width = trak->tkhd.track_width;
207 int height = trak->tkhd.track_height;
209 int height_i = (height <= 480) ? 480 : 576;
211 unsigned char **input_rows;
212 int is_pal = (height_i == 480) ? 0 : 1;
213 int data_length = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
215 dv_color_space_t encode_dv_colormodel = 0;
216 quicktime_atom_t chunk_atom;
218 if( codec->dv_encoder != NULL && codec->parameters_changed )
220 dv_encoder_free( codec->dv_encoder );
221 codec->dv_encoder = NULL;
222 codec->parameters_changed = 0;
225 if( ! codec->dv_encoder )
227 pthread_mutex_lock( &libdv_init_mutex );
229 //printf( "dv.c encode: Alloc'ing encoder\n" );
231 codec->dv_encoder = dv_encoder_new( codec->rem_ntsc_setup,
233 codec->clamp_chroma );
235 codec->parameters_changed = 0;
236 pthread_mutex_unlock( &libdv_init_mutex );
239 if(codec->dv_encoder)
242 check_sequentiality( row_pointers,
243 width_i * cmodel_calculate_pixelsize(file->color_model),
246 if( ( file->color_model == BC_YUV422
247 || file->color_model == BC_RGB888 ) &&
249 height == height_i &&
252 input_rows = row_pointers;
253 switch( file->color_model )
256 encode_dv_colormodel = e_dv_color_yuv;
257 //printf( "dv.c encode: e_dv_color_yuv\n" );
260 encode_dv_colormodel = e_dv_color_rgb;
261 //printf( "dv.c encode: e_dv_color_rgb\n" );
270 // The best colormodel for encoding is YUV 422
272 if(!codec->temp_frame)
274 codec->temp_frame = malloc(720 * 576 * 2);
275 codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
276 for(i = 0; i < 576; i++)
277 codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
280 cmodel_transfer(codec->temp_rows, /* Leave NULL if non existent */
282 codec->temp_rows[0], /* Leave NULL if non existent */
285 row_pointers[0], /* Leave NULL if non existent */
288 0, /* Dimensions to capture from input frame */
291 MIN(height, height_i),
292 0, /* Dimensions to project on output frame */
295 MIN(height, height_i),
298 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
299 width, /* For planar use the luma rowspan */
303 input_rows = codec->temp_rows;
304 encode_dv_colormodel = e_dv_color_yuv;
308 codec->dv_encoder->is16x9 = codec->anamorphic16x9;
309 codec->dv_encoder->vlc_encode_passes = codec->vlc_encode_passes;
310 codec->dv_encoder->static_qno = 0;
311 codec->dv_encoder->force_dct = DV_DCT_AUTO;
312 codec->dv_encoder->isPAL = is_pal;
315 //printf("dv.c encode: 1 %d %d %d\n", width_i, height_i, encode_dv_colormodel);
316 dv_encode_full_frame( codec->dv_encoder,
317 input_rows, encode_dv_colormodel, codec->data );
318 //printf("dv.c encode: 2 %d %d\n", width_i, height_i);
320 quicktime_write_chunk_header(file, trak, &chunk_atom);
321 result = !quicktime_write_data(file, (char*)codec->data, data_length);
322 quicktime_write_chunk_footer(file,
324 vtrack->current_chunk,
327 vtrack->current_chunk++;
328 //printf("encode 3\n");
334 // Logic: DV contains a mixture of 420 and 411 so can only
335 // output/input 444 or 422 and libdv can output/input RGB as well so
338 // This function is used as both reads_colormodel and writes_colormodel
339 static int colormodel_dv(quicktime_t *file,
343 return (colormodel == BC_RGB888 ||
344 colormodel == BC_YUV888 ||
345 colormodel == BC_YUV422);
348 static int set_parameter(quicktime_t *file,
353 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)file->vtracks[track].codec)->priv;
355 if(!strcasecmp(key, "dv_decode_quality"))
357 codec->decode_quality = *(int*)value;
359 else if(!strcasecmp(key, "dv_anamorphic16x9"))
361 codec->anamorphic16x9 = *(int*)value;
363 else if(!strcasecmp(key, "dv_vlc_encode_passes"))
365 codec->vlc_encode_passes = *(int*)value;
367 else if(!strcasecmp(key, "dv_clamp_luma"))
369 codec->clamp_luma = *(int*)value;
371 else if(!strcasecmp(key, "dv_clamp_chroma"))
373 codec->clamp_chroma = *(int*)value;
375 else if(!strcasecmp(key, "dv_add_ntsc_setup"))
377 codec->add_ntsc_setup = *(int*)value;
379 else if(!strcasecmp(key, "dv_rem_ntsc_setup"))
381 codec->rem_ntsc_setup = *(int*)value;
388 codec->parameters_changed = 1;
392 static void init_codec_common(quicktime_video_map_t *vtrack, char *fourcc)
394 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
395 quicktime_dv_codec_t *codec;
397 /* Init public items */
398 codec_base->priv = calloc(1, sizeof(quicktime_dv_codec_t));
399 codec_base->delete_vcodec = delete_codec;
400 codec_base->decode_video = decode;
401 codec_base->encode_video = encode;
402 codec_base->decode_audio = 0;
403 codec_base->encode_audio = 0;
404 codec_base->reads_colormodel = colormodel_dv;
405 codec_base->writes_colormodel = colormodel_dv;
406 codec_base->set_parameter = set_parameter;
407 codec_base->fourcc = fourcc;
408 codec_base->title = "DV";
409 codec_base->desc = "DV";
412 /* Init private items */
414 codec = codec_base->priv;
416 codec->dv_decoder = NULL;
417 codec->dv_encoder = NULL;
418 codec->decode_quality = DV_QUALITY_BEST;
419 codec->anamorphic16x9 = 0;
420 codec->vlc_encode_passes = 3;
421 codec->clamp_luma = codec->clamp_chroma = 0;
422 codec->add_ntsc_setup = 0;
423 codec->parameters_changed = 0;
425 // Allocate extra to work around some libdv overrun
426 codec->data = calloc(1, 144008);
429 void quicktime_init_codec_dv(quicktime_video_map_t *vtrack)
431 init_codec_common(vtrack, QUICKTIME_DV);
434 void quicktime_init_codec_dvcp(quicktime_video_map_t *vtrack)
436 init_codec_common(vtrack, QUICKTIME_DVCP);
440 void quicktime_init_codec_dv25(quicktime_video_map_t *vtrack)
442 init_codec_common(vtrack, QUICKTIME_DV25);
445 void quicktime_init_codec_dvsd(quicktime_video_map_t *vtrack)
447 init_codec_common(vtrack, QUICKTIME_DVSD);