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 */
8 #include <ffmpeg/avcodec.h>
11 #include "colormodels.h"
12 #include "funcprotos.h"
14 #include "quicktime.h"
20 #define DV_NTSC_SIZE 120000
21 #define DV_PAL_SIZE 144000
28 AVCodecContext
*context
;
32 dv_decoder_t
*dv_decoder
;
33 dv_encoder_t
*dv_encoder
;
35 unsigned char *temp_frame
, **temp_rows
;
40 int vlc_encode_passes
;
41 int clamp_luma
, clamp_chroma
;
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
;
59 avcodec_close(codec
->context
);
62 if(codec
->frame
) free(codec
->frame
);
67 dv_decoder_free( codec
->dv_decoder
);
68 codec
->dv_decoder
= NULL
;
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
);
84 static int check_sequentiality( unsigned char **row_pointers
,
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 );
102 static int decode(quicktime_t
*file
, unsigned char **row_pointers
, int track
)
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
;
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");
123 if( codec
->codec
&& codec
->parameters_changed
)
125 avcodec_close(codec
->context
);
126 free(codec
->context
);
127 codec
->context
= NULL
;
129 codec
->parameters_changed
= 0;
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");
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
);
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
,
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");
176 AVPicture temp_frame
;
178 if(!codec
->frame
) codec
->frame
= avcodec_alloc_frame();
180 if(avcodec_decode_video(codec
->context
,
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
,
205 (AVPicture
*)codec
->frame
,
206 (file
->in_h
== 576 ? PIX_FMT_YUV420P
: PIX_FMT_YUV411P
),
212 if(codec
->dv_decoder
)
214 //printf(__FUNCTION__ " 4\n");
216 check_sequentiality( row_pointers
,
217 720 * cmodel_calculate_pixelsize(file
->color_model
),
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
) &&
232 file
->in_w
== width
&&
233 file
->in_h
== height
&&
234 file
->out_w
== width
&&
235 file
->out_h
== height
&&
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
,
245 //printf(__FUNCTION__ " 7.2\n");
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
,
255 //printf(__FUNCTION__ " 7.4\n");
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
,
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
,
311 * printf( "decode 9 %02x%02x%02x%02x\n",
312 * row_pointers[0][0],
313 * row_pointers[0][1],
314 * row_pointers[0][2],
318 //printf("decode 9\n");
319 #ifndef DV_USE_FFMPEG
321 #endif // DV_USE_FFMPEG
324 //printf(__FUNCTION__ " 2\n");
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
;
337 int height_i
= (height
<= 480) ? 480 : 576;
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
;
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
,
362 codec
->clamp_chroma
);
364 codec
->parameters_changed
= 0;
365 pthread_mutex_unlock( &libdv_init_mutex
);
368 if(codec
->dv_encoder
)
371 check_sequentiality( row_pointers
,
372 width_i
* cmodel_calculate_pixelsize(file
->color_model
),
375 if( ( file
->color_model
== BC_YUV422
376 || file
->color_model
== BC_RGB888
) &&
378 height
== height_i
&&
381 input_rows
= row_pointers
;
382 encode_colormodel
= file
->color_model
;
383 switch( file
->color_model
)
386 encode_dv_colormodel
= e_dv_color_yuv
;
387 //printf( "dv.c encode: e_dv_color_yuv\n" );
390 encode_dv_colormodel
= e_dv_color_rgb
;
391 //printf( "dv.c encode: e_dv_color_rgb\n" );
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 */
412 codec
->temp_rows
[0], /* Leave NULL if non existent */
415 row_pointers
[0], /* Leave NULL if non existent */
418 0, /* Dimensions to capture from input frame */
421 MIN(height
, height_i
),
422 0, /* Dimensions to project on output frame */
425 MIN(height
, height_i
),
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 */
433 input_rows
= codec
->temp_rows
;
434 encode_colormodel
= BC_YUV422
;
435 encode_dv_colormodel
= e_dv_color_yuv
;
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
,
458 vtrack
->current_chunk
,
461 vtrack
->current_chunk
++;
462 //printf("encode 3\n");
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
472 // This function is used as both reads_colormodel and writes_colormodel
473 static int colormodel_dv(quicktime_t
*file
,
477 return (colormodel
== BC_RGB888
||
478 colormodel
== BC_YUV888
||
479 colormodel
== BC_YUV422
);
482 static int set_parameter(quicktime_t
*file
,
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
;
522 codec
->parameters_changed
= 1;
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
;
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
;
558 codec
->context
= 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
);