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
,
68 for(; i
< height
-1; i
++)
70 if( row_pointers
[i
+1] - row_pointers
[i
] != bytes_per_row
)
78 static int decode(quicktime_t
*file
, unsigned char **row_pointers
, int track
)
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
;
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
,
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
)
119 check_sequentiality( row_pointers
,
120 720 * cmodel_calculate_pixelsize(file
->color_model
),
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
) &&
132 file
->in_w
== width
&&
133 file
->in_h
== height
&&
134 file
->out_w
== width
&&
135 file
->out_h
== height
&&
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
,
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
,
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
,
173 cmodel_transfer(row_pointers
,
197 //printf(__FUNCTION__ " 2\n");
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
;
210 int height_i
= (height
<= 480) ? 480 : 576;
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
;
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
,
235 codec
->clamp_chroma
);
237 codec
->parameters_changed
= 0;
238 pthread_mutex_unlock( &libdv_init_mutex
);
241 if(codec
->dv_encoder
)
244 check_sequentiality( row_pointers
,
245 width_i
* cmodel_calculate_pixelsize(file
->color_model
),
248 if( ( file
->color_model
== BC_YUV422
249 || file
->color_model
== BC_RGB888
) &&
251 height
== height_i
&&
254 input_rows
= row_pointers
;
255 encode_colormodel
= file
->color_model
;
256 switch( file
->color_model
)
259 encode_dv_colormodel
= e_dv_color_yuv
;
260 //printf( "dv.c encode: e_dv_color_yuv\n" );
263 encode_dv_colormodel
= e_dv_color_rgb
;
264 //printf( "dv.c encode: e_dv_color_rgb\n" );
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 */
285 codec
->temp_rows
[0], /* Leave NULL if non existent */
288 row_pointers
[0], /* Leave NULL if non existent */
291 0, /* Dimensions to capture from input frame */
294 MIN(height
, height_i
),
295 0, /* Dimensions to project on output frame */
298 MIN(height
, height_i
),
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 */
306 input_rows
= codec
->temp_rows
;
307 encode_colormodel
= BC_YUV422
;
308 encode_dv_colormodel
= e_dv_color_yuv
;
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
,
328 vtrack
->current_chunk
,
331 vtrack
->current_chunk
++;
332 //printf("encode 3\n");
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
342 // This function is used as both reads_colormodel and writes_colormodel
343 static int colormodel_dv(quicktime_t
*file
,
347 return (colormodel
== BC_RGB888
||
348 colormodel
== BC_YUV888
||
349 colormodel
== BC_YUV422
);
352 static int set_parameter(quicktime_t
*file
,
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
;
392 codec
->parameters_changed
= 1;
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
;
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
);