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 int 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
);
62 static int check_sequentiality( unsigned char **row_pointers
,
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 );
80 static int decode(quicktime_t
*file
, unsigned char **row_pointers
, int track
)
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
;
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
,
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");
128 check_sequentiality( row_pointers
,
129 720 * cmodel_calculate_pixelsize(file
->color_model
),
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 */) &&
144 file
->in_w
== width
&&
145 file
->in_h
== height
&&
146 file
->out_w
== width
&&
147 file
->out_h
== height
&&
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
,
157 //printf(__FUNCTION__ " 7.2\n");
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
,
167 //printf(__FUNCTION__ " 7.4\n");
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
,
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
,
222 * printf( "decode 9 %02x%02x%02x%02x\n",
223 * row_pointers[0][0],
224 * row_pointers[0][1],
225 * row_pointers[0][2],
229 //printf("decode 9\n");
233 //printf(__FUNCTION__ " 2\n");
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
;
246 int height_i
= (height
<= 480) ? 480 : 576;
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
;
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
,
271 codec
->clamp_chroma
);
273 codec
->parameters_changed
= 0;
274 pthread_mutex_unlock( &libdv_init_mutex
);
277 if(codec
->dv_encoder
)
280 check_sequentiality( row_pointers
,
281 width_i
* cmodel_calculate_pixelsize(file
->color_model
),
284 if( ( file
->color_model
== BC_YUV422
285 || file
->color_model
== BC_RGB888
) &&
287 height
== height_i
&&
290 input_rows
= row_pointers
;
291 encode_colormodel
= file
->color_model
;
292 switch( file
->color_model
)
295 encode_dv_colormodel
= e_dv_color_yuv
;
296 //printf( "dv.c encode: e_dv_color_yuv\n" );
299 encode_dv_colormodel
= e_dv_color_rgb
;
300 //printf( "dv.c encode: e_dv_color_rgb\n" );
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 */
321 codec
->temp_rows
[0], /* Leave NULL if non existent */
324 row_pointers
[0], /* Leave NULL if non existent */
327 0, /* Dimensions to capture from input frame */
330 MIN(height
, height_i
),
331 0, /* Dimensions to project on output frame */
334 MIN(height
, height_i
),
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 */
342 input_rows
= codec
->temp_rows
;
343 encode_colormodel
= BC_YUV422
;
344 encode_dv_colormodel
= e_dv_color_yuv
;
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
,
364 vtrack
->current_chunk
,
367 vtrack
->current_chunk
++;
368 //printf("encode 3\n");
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
378 // This function is used as both reads_colormodel and writes_colormodel
379 static int colormodel_dv(quicktime_t
*file
,
383 return (colormodel
== BC_RGB888
||
384 colormodel
== BC_YUV888
||
385 colormodel
== BC_YUV422
);
388 static int set_parameter(quicktime_t
*file
,
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
;
428 codec
->parameters_changed
= 1;
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
;
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
);