r663: This commit was generated by cvs2svn to compensate for changes in r662,
[cinelerra_cv.git] / quicktime / dv.c
blob8c8819c13bae3c032604f2a2cc1780db01b4baf9
1 /* 2004: FFMPEG DV Decode by Richard Bavestock baver@thebeever.com */
2 /* 2002: Refurbished by Arthur Peters amep@softhome.net */
3 /* 2000: Original codec by Heroine Virtual */
5 #include "../config.h"
7 #ifdef DV_USE_FFMPEG
8 #include <ffmpeg/avcodec.h>
9 #endif
11 #include "colormodels.h"
12 #include "funcprotos.h"
13 #include "libdv/dv.h"
14 #include "quicktime.h"
16 #include <pthread.h>
17 #include <string.h>
19 // Buffer sizes
20 #define DV_NTSC_SIZE 120000
21 #define DV_PAL_SIZE 144000
23 typedef struct
26 #ifdef DV_USE_FFMPEG
27 AVCodec *codec;
28 AVCodecContext *context;
29 AVFrame *frame;
30 #endif
32 dv_decoder_t *dv_decoder;
33 dv_encoder_t *dv_encoder;
34 unsigned char *data;
35 unsigned char *temp_frame, **temp_rows;
37 /* Parameters */
38 int decode_quality;
39 int anamorphic16x9;
40 int vlc_encode_passes;
41 int clamp_luma, clamp_chroma;
43 int add_ntsc_setup;
45 int rem_ntsc_setup;
47 int parameters_changed;
48 } quicktime_dv_codec_t;
50 static pthread_mutex_t libdv_init_mutex = PTHREAD_MUTEX_INITIALIZER;
52 static int delete_codec(quicktime_video_map_t *vtrack)
54 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
56 #ifdef DV_USE_FFMPEG
57 if(codec->context)
59 avcodec_close(codec->context);
60 free(codec->context);
62 if(codec->frame) free(codec->frame);
63 #endif
65 if(codec->dv_decoder)
67 dv_decoder_free( codec->dv_decoder );
68 codec->dv_decoder = NULL;
71 if(codec->dv_encoder)
73 dv_encoder_free( codec->dv_encoder );
74 codec->dv_encoder = NULL;
77 if(codec->temp_frame) free(codec->temp_frame);
78 if(codec->temp_rows) free(codec->temp_rows);
79 free(codec->data);
80 free(codec);
81 return 0;
84 static int check_sequentiality( unsigned char **row_pointers,
85 int bytes_per_row,
86 int height )
88 int i = 0;
89 //printf( "dv.c check_sequentiality: %p, %d, %d\n", row_pointers, bytes_per_row, height );
91 for(; i < height-1; i++)
93 if( row_pointers[i+1] - row_pointers[i] != bytes_per_row )
95 //printf( "dv.c check_sequentiality: %p - %p != %p\n", row_pointers[i+1], row_pointers[i], bytes_per_row );
96 return 0;
99 return 1;
102 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
104 long bytes;
105 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
106 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
107 int width = vtrack->track->tkhd.track_width;
108 int height = vtrack->track->tkhd.track_height;
109 int result = 0;
110 int i;
111 int decode_colormodel = 0;
112 int pitches[3] = { 720 * 2, 0, 0 };
114 //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] );
116 //printf(__FUNCTION__ " 1\n");
117 quicktime_set_video_position(file, vtrack->current_position, track);
118 bytes = quicktime_frame_size(file, vtrack->current_position, track);
119 result = !quicktime_read_data(file, (char*)codec->data, bytes);
121 //printf(__FUNCTION__ " 1\n");
122 #ifdef DV_USE_FFMPEG
123 if( codec->codec && codec->parameters_changed )
125 avcodec_close(codec->context);
126 free(codec->context);
127 codec->context = NULL;
128 codec->codec = NULL;
129 codec->parameters_changed = 0;
131 #else
132 if( codec->dv_decoder && codec->parameters_changed )
134 dv_decoder_free( codec->dv_decoder );
135 codec->dv_decoder = NULL;
136 codec->parameters_changed = 0;
138 #endif // DV_USE_FFMEPG
140 //printf(__FUNCTION__ " 2\n");
141 #ifdef DV_USE_FFMPEG
142 if( ! codec->codec )
144 pthread_mutex_lock( &libdv_init_mutex );
146 codec->codec = avcodec_find_decoder(CODEC_ID_DVVIDEO);
147 codec->context = avcodec_alloc_context();
148 avcodec_open(codec->context, codec->codec);
150 codec->parameters_changed = 0;
151 pthread_mutex_unlock( &libdv_init_mutex );
153 #else
154 if( ! codec->dv_decoder )
156 pthread_mutex_lock( &libdv_init_mutex );
158 //printf( "dv.c decode: Alloc'ing decoder\n" );
160 codec->dv_decoder = dv_decoder_new( codec->add_ntsc_setup,
161 codec->clamp_luma,
162 codec->clamp_chroma );
163 codec->dv_decoder->prev_frame_decoded = 0;
165 codec->parameters_changed = 0;
166 pthread_mutex_unlock( &libdv_init_mutex );
168 #endif // DV_USE_FFMPEG
169 //printf(__FUNCTION__ " 3\n");
171 #ifdef DV_USE_FFMPEG
172 if(codec->codec)
174 int got_picture = 0;
175 int i = 0;
176 AVPicture temp_frame;
178 if(!codec->frame) codec->frame = avcodec_alloc_frame();
180 if(avcodec_decode_video(codec->context,
181 codec->frame,
182 &got_picture,
183 codec->data,
184 bytes) < 0)
186 printf("Error while decoding frame\n");
189 if(!codec->temp_frame)
191 codec->temp_frame = malloc(720 * 576 * 2);
192 codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
193 for(i = 0; i < 576; i++)
194 codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
197 temp_frame.linesize[0] = 720 * 2;
198 for(i = 0; i < 4; i++)
199 temp_frame.data[i] = codec->temp_rows[i];
201 decode_colormodel = BC_YUV422;
203 img_convert(&temp_frame,
204 PIX_FMT_YUV422,
205 (AVPicture *)codec->frame,
206 (file->in_h == 576 ? PIX_FMT_YUV420P : PIX_FMT_YUV411P),
207 file->in_w,
208 file->in_h);
210 #else
212 if(codec->dv_decoder)
214 //printf(__FUNCTION__ " 4\n");
215 int is_sequential =
216 check_sequentiality( row_pointers,
217 720 * cmodel_calculate_pixelsize(file->color_model),
218 file->out_h );
219 //printf(__FUNCTION__ " 5\n");
221 codec->dv_decoder->quality = codec->decode_quality;
222 //printf(__FUNCTION__ " 6\n");
224 dv_parse_header( codec->dv_decoder, codec->data );
225 //printf(__FUNCTION__ " 7\n");
227 // Libdv improperly decodes RGB colormodels.
228 if((file->color_model == BC_YUV422 ||
229 file->color_model == BC_RGB888) &&
230 file->in_x == 0 &&
231 file->in_y == 0 &&
232 file->in_w == width &&
233 file->in_h == height &&
234 file->out_w == width &&
235 file->out_h == height &&
236 is_sequential)
238 if( file->color_model == BC_YUV422 )
240 pitches[0] = 720 * 2;
241 //printf(__FUNCTION__ " 7.1\n");
242 dv_decode_full_frame( codec->dv_decoder, codec->data,
243 e_dv_color_yuv, row_pointers,
244 pitches );
245 //printf(__FUNCTION__ " 7.2\n");
247 else
248 if( file->color_model == BC_RGB888)
250 pitches[0] = 720 * 3;
251 //printf(__FUNCTION__ " 7.3\n");
252 dv_decode_full_frame( codec->dv_decoder, codec->data,
253 e_dv_color_rgb, row_pointers,
254 pitches );
255 //printf(__FUNCTION__ " 7.4\n");
258 else
260 //printf(__FUNCTION__ " 8\n");
261 if(!codec->temp_frame)
263 codec->temp_frame = malloc(720 * 576 * 2);
264 codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
265 for(i = 0; i < 576; i++)
266 codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
268 //printf(__FUNCTION__ " 8\n");
270 decode_colormodel = BC_YUV422;
271 pitches[0] = 720 * 2;
272 dv_decode_full_frame( codec->dv_decoder, codec->data,
273 e_dv_color_yuv, codec->temp_rows,
274 pitches );
275 #endif // DV_USE_FFMPEG
277 //printf(__FUNCTION__ " 8\n");
281 * printf( "decode 8 %02x%02x%02x%02x\n",
282 * codec->temp_rows[0][0],
283 * codec->temp_rows[0][1],
284 * codec->temp_rows[0][2],
285 * codec->temp_rows[0][3]
289 cmodel_transfer(row_pointers,
290 codec->temp_rows,
291 row_pointers[0],
292 row_pointers[1],
293 row_pointers[2],
294 codec->temp_rows[0],
295 codec->temp_rows[1],
296 codec->temp_rows[2],
297 file->in_x,
298 file->in_y,
299 file->in_w,
300 file->in_h,
303 file->out_w,
304 file->out_h,
305 decode_colormodel,
306 file->color_model,
308 width,
309 file->out_w);
311 * printf( "decode 9 %02x%02x%02x%02x\n",
312 * row_pointers[0][0],
313 * row_pointers[0][1],
314 * row_pointers[0][2],
315 * row_pointers[0][3]
316 * );
318 //printf("decode 9\n");
319 #ifndef DV_USE_FFMPEG
321 #endif // DV_USE_FFMPEG
324 //printf(__FUNCTION__ " 2\n");
325 return result;
328 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
330 int64_t offset = quicktime_position(file);
331 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
332 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
333 quicktime_trak_t *trak = vtrack->track;
334 int width = trak->tkhd.track_width;
335 int height = trak->tkhd.track_height;
336 int width_i = 720;
337 int height_i = (height <= 480) ? 480 : 576;
338 int i;
339 unsigned char **input_rows;
340 int is_pal = (height_i == 480) ? 0 : 1;
341 int data_length = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
342 int result = 0;
343 int encode_colormodel = 0;
344 dv_color_space_t encode_dv_colormodel = 0;
345 quicktime_atom_t chunk_atom;
347 if( codec->dv_encoder != NULL && codec->parameters_changed )
349 dv_encoder_free( codec->dv_encoder );
350 codec->dv_encoder = NULL;
351 codec->parameters_changed = 0;
354 if( ! codec->dv_encoder )
356 pthread_mutex_lock( &libdv_init_mutex );
358 //printf( "dv.c encode: Alloc'ing encoder\n" );
360 codec->dv_encoder = dv_encoder_new( codec->rem_ntsc_setup,
361 codec->clamp_luma,
362 codec->clamp_chroma );
364 codec->parameters_changed = 0;
365 pthread_mutex_unlock( &libdv_init_mutex );
368 if(codec->dv_encoder)
370 int is_sequential =
371 check_sequentiality( row_pointers,
372 width_i * cmodel_calculate_pixelsize(file->color_model),
373 height );
375 if( ( file->color_model == BC_YUV422
376 || file->color_model == BC_RGB888 ) &&
377 width == width_i &&
378 height == height_i &&
379 is_sequential )
381 input_rows = row_pointers;
382 encode_colormodel = file->color_model;
383 switch( file->color_model )
385 case BC_YUV422:
386 encode_dv_colormodel = e_dv_color_yuv;
387 //printf( "dv.c encode: e_dv_color_yuv\n" );
388 break;
389 case BC_RGB888:
390 encode_dv_colormodel = e_dv_color_rgb;
391 //printf( "dv.c encode: e_dv_color_rgb\n" );
392 break;
393 default:
394 return 0;
395 break;
398 else
400 // The best colormodel for encoding is YUV 422
402 if(!codec->temp_frame)
404 codec->temp_frame = malloc(720 * 576 * 2);
405 codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
406 for(i = 0; i < 576; i++)
407 codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
410 cmodel_transfer(codec->temp_rows, /* Leave NULL if non existent */
411 row_pointers,
412 codec->temp_rows[0], /* Leave NULL if non existent */
413 codec->temp_rows[1],
414 codec->temp_rows[2],
415 row_pointers[0], /* Leave NULL if non existent */
416 row_pointers[1],
417 row_pointers[2],
418 0, /* Dimensions to capture from input frame */
420 MIN(width, width_i),
421 MIN(height, height_i),
422 0, /* Dimensions to project on output frame */
424 MIN(width, width_i),
425 MIN(height, height_i),
426 file->color_model,
427 BC_YUV422,
428 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
429 width, /* For planar use the luma rowspan */
430 width_i);
433 input_rows = codec->temp_rows;
434 encode_colormodel = BC_YUV422;
435 encode_dv_colormodel = e_dv_color_yuv;
438 // Setup the encoder
439 codec->dv_encoder->is16x9 = codec->anamorphic16x9;
440 codec->dv_encoder->vlc_encode_passes = codec->vlc_encode_passes;
441 codec->dv_encoder->static_qno = 0;
442 codec->dv_encoder->force_dct = DV_DCT_AUTO;
443 codec->dv_encoder->isPAL = is_pal;
446 //printf("dv.c encode: 1 %d %d %d\n", width_i, height_i, encode_dv_colormodel);
447 dv_encode_full_frame( codec->dv_encoder,
448 input_rows, encode_dv_colormodel, codec->data );
449 dv_encode_timecode(codec->data, codec->dv_encoder->isPAL,
450 file->current_frame);
451 file->current_frame++;
452 //printf("dv.c encode: 2 %d %d\n", width_i, height_i);
454 quicktime_write_chunk_header(file, trak, &chunk_atom);
455 result = !quicktime_write_data(file, codec->data, data_length);
456 quicktime_write_chunk_footer(file,
457 trak,
458 vtrack->current_chunk,
459 &chunk_atom,
461 vtrack->current_chunk++;
462 //printf("encode 3\n");
465 return result;
468 // Logic: DV contains a mixture of 420 and 411 so can only
469 // output/input 444 or 422 and libdv can output/input RGB as well so
470 // we include that.
472 // This function is used as both reads_colormodel and writes_colormodel
473 static int colormodel_dv(quicktime_t *file,
474 int colormodel,
475 int track)
477 return (colormodel == BC_RGB888 ||
478 colormodel == BC_YUV888 ||
479 colormodel == BC_YUV422);
482 static int set_parameter(quicktime_t *file,
483 int track,
484 char *key,
485 void *value)
487 quicktime_dv_codec_t *codec = ((quicktime_codec_t*)file->vtracks[track].codec)->priv;
489 if(!strcasecmp(key, "dv_decode_quality"))
491 codec->decode_quality = *(int*)value;
493 else if(!strcasecmp(key, "dv_anamorphic16x9"))
495 codec->anamorphic16x9 = *(int*)value;
497 else if(!strcasecmp(key, "dv_vlc_encode_passes"))
499 codec->vlc_encode_passes = *(int*)value;
501 else if(!strcasecmp(key, "dv_clamp_luma"))
503 codec->clamp_luma = *(int*)value;
505 else if(!strcasecmp(key, "dv_clamp_chroma"))
507 codec->clamp_chroma = *(int*)value;
509 else if(!strcasecmp(key, "dv_add_ntsc_setup"))
511 codec->add_ntsc_setup = *(int*)value;
513 else if(!strcasecmp(key, "dv_rem_ntsc_setup"))
515 codec->rem_ntsc_setup = *(int*)value;
517 else
519 return 0;
522 codec->parameters_changed = 1;
523 return 0;
526 static void init_codec_common(quicktime_video_map_t *vtrack, char *fourcc)
528 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
529 quicktime_dv_codec_t *codec;
530 int i;
532 #ifdef DV_USE_FFMPEG
533 avcodec_init();
534 avcodec_register_all();
535 #endif // DV_USE_FFMPEG
537 /* Init public items */
538 codec_base->priv = calloc(1, sizeof(quicktime_dv_codec_t));
539 codec_base->delete_vcodec = delete_codec;
540 codec_base->decode_video = decode;
541 codec_base->encode_video = encode;
542 codec_base->decode_audio = 0;
543 codec_base->encode_audio = 0;
544 codec_base->reads_colormodel = colormodel_dv;
545 codec_base->writes_colormodel = colormodel_dv;
546 codec_base->set_parameter = set_parameter;
547 codec_base->fourcc = fourcc;
548 codec_base->title = "DV";
549 codec_base->desc = "DV";
552 /* Init private items */
554 codec = codec_base->priv;
556 #ifdef DV_USE_FFMPEG
557 codec->codec = NULL;
558 codec->context = NULL;
559 codec->frame = NULL;
560 #endif // DV_USE_FFMPEG
561 codec->dv_decoder = NULL;
562 codec->dv_encoder = NULL;
563 codec->decode_quality = DV_QUALITY_BEST;
564 codec->anamorphic16x9 = 0;
565 codec->vlc_encode_passes = 3;
566 codec->clamp_luma = codec->clamp_chroma = 0;
567 codec->add_ntsc_setup = 0;
568 codec->parameters_changed = 0;
570 // Allocate extra to work around some libdv overrun
571 codec->data = calloc(1, 144008);
574 void quicktime_init_codec_dv(quicktime_video_map_t *vtrack)
576 init_codec_common(vtrack, QUICKTIME_DV);
579 void quicktime_init_codec_dv25(quicktime_video_map_t *vtrack)
581 init_codec_common(vtrack, QUICKTIME_DV25);
584 void quicktime_init_codec_dvsd(quicktime_video_map_t *vtrack)
586 init_codec_common(vtrack, QUICKTIME_DVSD);