00001
00002
00003
00004
00005 #include "colormodels.h"
00006 #include "funcprotos.h"
00007 #include "libdv/dv.h"
00008 #include "quicktime.h"
00009
00010 #include <pthread.h>
00011 #include <string.h>
00012
00013
00014 #define DV_NTSC_SIZE 120000
00015 #define DV_PAL_SIZE 144000
00016
00017 typedef struct
00018 {
00019 dv_decoder_t *dv_decoder;
00020 dv_encoder_t *dv_encoder;
00021 unsigned char *data;
00022 unsigned char *temp_frame, **temp_rows;
00023
00024
00025 int decode_quality;
00026 int anamorphic16x9;
00027 int vlc_encode_passes;
00028 int clamp_luma, clamp_chroma;
00029
00030 int add_ntsc_setup;
00031
00032 int rem_ntsc_setup;
00033
00034 int parameters_changed;
00035 } quicktime_dv_codec_t;
00036
00037 static pthread_mutex_t libdv_init_mutex = PTHREAD_MUTEX_INITIALIZER;
00038
00039 static int delete_codec(quicktime_video_map_t *vtrack)
00040 {
00041 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00042
00043 if(codec->dv_decoder)
00044 {
00045 dv_decoder_free( codec->dv_decoder );
00046 codec->dv_decoder = NULL;
00047 }
00048
00049 if(codec->dv_encoder)
00050 {
00051 dv_encoder_free( codec->dv_encoder );
00052 codec->dv_encoder = NULL;
00053 }
00054
00055 if(codec->temp_frame) free(codec->temp_frame);
00056 if(codec->temp_rows) free(codec->temp_rows);
00057 free(codec->data);
00058 free(codec);
00059 return 0;
00060 }
00061
00062 static int check_sequentiality( unsigned char **row_pointers,
00063 int bytes_per_row,
00064 int height )
00065 {
00066 int i = 0;
00067
00068 for(; i < height-1; i++)
00069 {
00070 if( row_pointers[i+1] - row_pointers[i] != bytes_per_row )
00071 {
00072 return 0;
00073 }
00074 }
00075 return 1;
00076 }
00077
00078 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
00079 {
00080 long bytes;
00081 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00082 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00083 int width = vtrack->track->tkhd.track_width;
00084 int height = vtrack->track->tkhd.track_height;
00085 int result = 0;
00086 int i;
00087 int decode_colormodel = 0;
00088 int pitches[3] = { 720 * 2, 0, 0 };
00089
00090
00091 quicktime_set_video_position(file, vtrack->current_position, track);
00092 bytes = quicktime_frame_size(file, vtrack->current_position, track);
00093 result = !quicktime_read_data(file, (char*)codec->data, bytes);
00094
00095 if( codec->dv_decoder && codec->parameters_changed )
00096 {
00097 dv_decoder_free( codec->dv_decoder );
00098 codec->dv_decoder = NULL;
00099 codec->parameters_changed = 0;
00100 }
00101
00102 if( ! codec->dv_decoder )
00103 {
00104 pthread_mutex_lock( &libdv_init_mutex );
00105
00106
00107 codec->dv_decoder = dv_decoder_new( codec->add_ntsc_setup,
00108 codec->clamp_luma,
00109 codec->clamp_chroma );
00110 codec->dv_decoder->prev_frame_decoded = 0;
00111
00112 codec->parameters_changed = 0;
00113 pthread_mutex_unlock( &libdv_init_mutex );
00114 }
00115
00116 if(codec->dv_decoder)
00117 {
00118 int is_sequential =
00119 check_sequentiality( row_pointers,
00120 720 * cmodel_calculate_pixelsize(file->color_model),
00121 file->out_h );
00122
00123 codec->dv_decoder->quality = codec->decode_quality;
00124
00125 dv_parse_header( codec->dv_decoder, codec->data );
00126
00127
00128 if((file->color_model == BC_YUV422 ||
00129 file->color_model == BC_RGB888) &&
00130 file->in_x == 0 &&
00131 file->in_y == 0 &&
00132 file->in_w == width &&
00133 file->in_h == height &&
00134 file->out_w == width &&
00135 file->out_h == height &&
00136 is_sequential)
00137 {
00138 if( file->color_model == BC_YUV422 )
00139 {
00140 pitches[0] = 720 * 2;
00141 dv_decode_full_frame( codec->dv_decoder, codec->data,
00142 e_dv_color_yuv, row_pointers,
00143 pitches );
00144 }
00145 else
00146 if( file->color_model == BC_RGB888)
00147 {
00148 pitches[0] = 720 * 3;
00149 dv_decode_full_frame( codec->dv_decoder, codec->data,
00150 e_dv_color_rgb, row_pointers,
00151 pitches );
00152 }
00153 }
00154 else
00155 {
00156 if(!codec->temp_frame)
00157 {
00158 codec->temp_frame = malloc(720 * 576 * 2);
00159 codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
00160 for(i = 0; i < 576; i++)
00161 codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
00162 }
00163
00164 decode_colormodel = BC_YUV422;
00165 pitches[0] = 720 * 2;
00166 dv_decode_full_frame( codec->dv_decoder, codec->data,
00167 e_dv_color_yuv, codec->temp_rows,
00168 pitches );
00169
00170
00171
00172
00173 cmodel_transfer(row_pointers,
00174 codec->temp_rows,
00175 row_pointers[0],
00176 row_pointers[1],
00177 row_pointers[2],
00178 codec->temp_rows[0],
00179 codec->temp_rows[1],
00180 codec->temp_rows[2],
00181 file->in_x,
00182 file->in_y,
00183 file->in_w,
00184 file->in_h,
00185 0,
00186 0,
00187 file->out_w,
00188 file->out_h,
00189 decode_colormodel,
00190 file->color_model,
00191 0,
00192 width,
00193 file->out_w);
00194 }
00195 }
00196
00197
00198 return result;
00199 }
00200
00201 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
00202 {
00203 int64_t offset = quicktime_position(file);
00204 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00205 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00206 quicktime_trak_t *trak = vtrack->track;
00207 int width = trak->tkhd.track_width;
00208 int height = trak->tkhd.track_height;
00209 int width_i = 720;
00210 int height_i = (height <= 480) ? 480 : 576;
00211 int i;
00212 unsigned char **input_rows;
00213 int is_pal = (height_i == 480) ? 0 : 1;
00214 int data_length = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
00215 int result = 0;
00216 int encode_colormodel = 0;
00217 dv_color_space_t encode_dv_colormodel = 0;
00218 quicktime_atom_t chunk_atom;
00219
00220 if( codec->dv_encoder != NULL && codec->parameters_changed )
00221 {
00222 dv_encoder_free( codec->dv_encoder );
00223 codec->dv_encoder = NULL;
00224 codec->parameters_changed = 0;
00225 }
00226
00227 if( ! codec->dv_encoder )
00228 {
00229 pthread_mutex_lock( &libdv_init_mutex );
00230
00231
00232
00233 codec->dv_encoder = dv_encoder_new( codec->rem_ntsc_setup,
00234 codec->clamp_luma,
00235 codec->clamp_chroma );
00236
00237 codec->parameters_changed = 0;
00238 pthread_mutex_unlock( &libdv_init_mutex );
00239 }
00240
00241 if(codec->dv_encoder)
00242 {
00243 int is_sequential =
00244 check_sequentiality( row_pointers,
00245 width_i * cmodel_calculate_pixelsize(file->color_model),
00246 height );
00247
00248 if( ( file->color_model == BC_YUV422
00249 || file->color_model == BC_RGB888 ) &&
00250 width == width_i &&
00251 height == height_i &&
00252 is_sequential )
00253 {
00254 input_rows = row_pointers;
00255 encode_colormodel = file->color_model;
00256 switch( file->color_model )
00257 {
00258 case BC_YUV422:
00259 encode_dv_colormodel = e_dv_color_yuv;
00260
00261 break;
00262 case BC_RGB888:
00263 encode_dv_colormodel = e_dv_color_rgb;
00264
00265 break;
00266 default:
00267 return 0;
00268 break;
00269 }
00270 }
00271 else
00272 {
00273
00274
00275 if(!codec->temp_frame)
00276 {
00277 codec->temp_frame = malloc(720 * 576 * 2);
00278 codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
00279 for(i = 0; i < 576; i++)
00280 codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
00281 }
00282
00283 cmodel_transfer(codec->temp_rows,
00284 row_pointers,
00285 codec->temp_rows[0],
00286 codec->temp_rows[1],
00287 codec->temp_rows[2],
00288 row_pointers[0],
00289 row_pointers[1],
00290 row_pointers[2],
00291 0,
00292 0,
00293 MIN(width, width_i),
00294 MIN(height, height_i),
00295 0,
00296 0,
00297 MIN(width, width_i),
00298 MIN(height, height_i),
00299 file->color_model,
00300 BC_YUV422,
00301 0,
00302 width,
00303 width_i);
00304
00305
00306 input_rows = codec->temp_rows;
00307 encode_colormodel = BC_YUV422;
00308 encode_dv_colormodel = e_dv_color_yuv;
00309 }
00310
00311
00312 codec->dv_encoder->is16x9 = codec->anamorphic16x9;
00313 codec->dv_encoder->vlc_encode_passes = codec->vlc_encode_passes;
00314 codec->dv_encoder->static_qno = 0;
00315 codec->dv_encoder->force_dct = DV_DCT_AUTO;
00316 codec->dv_encoder->isPAL = is_pal;
00317
00318
00319
00320 dv_encode_full_frame( codec->dv_encoder,
00321 input_rows, encode_dv_colormodel, codec->data );
00322
00323
00324 quicktime_write_chunk_header(file, trak, &chunk_atom);
00325 result = !quicktime_write_data(file, codec->data, data_length);
00326 quicktime_write_chunk_footer(file,
00327 trak,
00328 vtrack->current_chunk,
00329 &chunk_atom,
00330 1);
00331 vtrack->current_chunk++;
00332
00333 }
00334
00335 return result;
00336 }
00337
00338
00339
00340
00341
00342
00343 static int colormodel_dv(quicktime_t *file,
00344 int colormodel,
00345 int track)
00346 {
00347 return (colormodel == BC_RGB888 ||
00348 colormodel == BC_YUV888 ||
00349 colormodel == BC_YUV422);
00350 }
00351
00352 static int set_parameter(quicktime_t *file,
00353 int track,
00354 char *key,
00355 void *value)
00356 {
00357 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)file->vtracks[track].codec)->priv;
00358
00359 if(!strcasecmp(key, "dv_decode_quality"))
00360 {
00361 codec->decode_quality = *(int*)value;
00362 }
00363 else if(!strcasecmp(key, "dv_anamorphic16x9"))
00364 {
00365 codec->anamorphic16x9 = *(int*)value;
00366 }
00367 else if(!strcasecmp(key, "dv_vlc_encode_passes"))
00368 {
00369 codec->vlc_encode_passes = *(int*)value;
00370 }
00371 else if(!strcasecmp(key, "dv_clamp_luma"))
00372 {
00373 codec->clamp_luma = *(int*)value;
00374 }
00375 else if(!strcasecmp(key, "dv_clamp_chroma"))
00376 {
00377 codec->clamp_chroma = *(int*)value;
00378 }
00379 else if(!strcasecmp(key, "dv_add_ntsc_setup"))
00380 {
00381 codec->add_ntsc_setup = *(int*)value;
00382 }
00383 else if(!strcasecmp(key, "dv_rem_ntsc_setup"))
00384 {
00385 codec->rem_ntsc_setup = *(int*)value;
00386 }
00387 else
00388 {
00389 return 0;
00390 }
00391
00392 codec->parameters_changed = 1;
00393 return 0;
00394 }
00395
00396 static void init_codec_common(quicktime_video_map_t *vtrack, char *fourcc)
00397 {
00398 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
00399 quicktime_dv_codec_t *codec;
00400 int i;
00401
00402
00403 codec_base->priv = calloc(1, sizeof(quicktime_dv_codec_t));
00404 codec_base->delete_vcodec = delete_codec;
00405 codec_base->decode_video = decode;
00406 codec_base->encode_video = encode;
00407 codec_base->decode_audio = 0;
00408 codec_base->encode_audio = 0;
00409 codec_base->reads_colormodel = colormodel_dv;
00410 codec_base->writes_colormodel = colormodel_dv;
00411 codec_base->set_parameter = set_parameter;
00412 codec_base->fourcc = fourcc;
00413 codec_base->title = "DV";
00414 codec_base->desc = "DV";
00415
00416
00417
00418
00419 codec = codec_base->priv;
00420
00421 codec->dv_decoder = NULL;
00422 codec->dv_encoder = NULL;
00423 codec->decode_quality = DV_QUALITY_BEST;
00424 codec->anamorphic16x9 = 0;
00425 codec->vlc_encode_passes = 3;
00426 codec->clamp_luma = codec->clamp_chroma = 0;
00427 codec->add_ntsc_setup = 0;
00428 codec->parameters_changed = 0;
00429
00430
00431 codec->data = calloc(1, 144008);
00432 }
00433
00434 void quicktime_init_codec_dv(quicktime_video_map_t *vtrack)
00435 {
00436 init_codec_common(vtrack, QUICKTIME_DV);
00437 }
00438
00439 void quicktime_init_codec_dvcp(quicktime_video_map_t *vtrack)
00440 {
00441 init_codec_common(vtrack, QUICKTIME_DVCP);
00442 }
00443
00444
00445 void quicktime_init_codec_dv25(quicktime_video_map_t *vtrack)
00446 {
00447 init_codec_common(vtrack, QUICKTIME_DV25);
00448 }
00449
00450 void quicktime_init_codec_dvsd(quicktime_video_map_t *vtrack)
00451 {
00452 init_codec_common(vtrack, QUICKTIME_DVSD);
00453 }