allow ffmpeg video to resample curr_pos, add bluray format
[goodguy/history.git] / cinelerra-5.0 / quicktime / qtdv.c
1 /* 2002: Refurbished by Arthur Peters amep@softhome.net */
2 /* 2000: Original codec by Heroine Virtual */
3
4
5 #include "colormodels.h"
6 #include "funcprotos.h"
7 #include "libdv/dv.h"
8 #include "quicktime.h"
9
10 #include <pthread.h>
11 #include <string.h>
12
13 // Buffer sizes
14 #define DV_NTSC_SIZE 120000
15 #define DV_PAL_SIZE 144000
16
17 typedef struct
18 {
19         dv_decoder_t *dv_decoder;
20         dv_encoder_t *dv_encoder;
21         unsigned char *data;
22         unsigned char *temp_frame, **temp_rows;
23
24         /* Parameters */
25         int decode_quality;
26         int anamorphic16x9;
27         int vlc_encode_passes;
28         int clamp_luma, clamp_chroma;
29
30         int add_ntsc_setup;
31
32         int rem_ntsc_setup;
33
34         int parameters_changed;
35 } quicktime_dv_codec_t;
36
37 static pthread_mutex_t libdv_init_mutex = PTHREAD_MUTEX_INITIALIZER;
38
39 static void delete_codec(quicktime_video_map_t *vtrack)
40 {
41         quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
42
43         if(codec->dv_decoder)
44         {
45                 dv_decoder_free( codec->dv_decoder );
46                 codec->dv_decoder = NULL;
47         }
48         
49         if(codec->dv_encoder)
50         {
51                 dv_encoder_free( codec->dv_encoder );
52                 codec->dv_encoder = NULL;
53         }
54         
55         if(codec->temp_frame) free(codec->temp_frame);
56         if(codec->temp_rows) free(codec->temp_rows);
57         free(codec->data);
58         free(codec);
59 }
60
61 static int check_sequentiality( unsigned char **row_pointers,
62                                                                 int bytes_per_row,
63                                                                 int height )
64 {
65         int i = 0;
66  
67         for(; i < height-1; i++)
68         {
69                 if( row_pointers[i+1] - row_pointers[i] != bytes_per_row )
70                 {
71                         return 0;
72                 }
73         }
74         return 1;
75 }
76
77 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
78 {
79         long bytes;
80         quicktime_video_map_t *vtrack = &(file->vtracks[track]);
81         quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
82         int width = vtrack->track->tkhd.track_width;
83         int height = vtrack->track->tkhd.track_height;
84         int result = 0;
85         int i;
86         int decode_colormodel = 0;
87         int pitches[3] = { 720 * 2, 0, 0 };
88
89
90         quicktime_set_video_position(file, vtrack->current_position, track);
91         bytes = quicktime_frame_size(file, vtrack->current_position, track);
92         result = !quicktime_read_data(file, (char*)codec->data, bytes);
93
94         if( codec->dv_decoder && codec->parameters_changed )
95         {
96                 dv_decoder_free( codec->dv_decoder );
97                 codec->dv_decoder = NULL;
98                 codec->parameters_changed = 0;
99         }
100         
101         if( ! codec->dv_decoder )
102         {
103                 pthread_mutex_lock( &libdv_init_mutex );
104
105                         
106                 codec->dv_decoder = dv_decoder_new( codec->add_ntsc_setup,
107                                                                                         codec->clamp_luma,
108                                                                                         codec->clamp_chroma );
109                 codec->dv_decoder->prev_frame_decoded = 0;
110                 
111                 codec->parameters_changed = 0;
112                 pthread_mutex_unlock( &libdv_init_mutex );
113         }
114
115         if(codec->dv_decoder)
116         {
117                 int is_sequential =
118                         check_sequentiality( row_pointers,
119                                                                  720 * cmodel_calculate_pixelsize(file->color_model),
120                                                                  file->out_h );
121
122                 codec->dv_decoder->quality = codec->decode_quality;
123
124                 dv_parse_header( codec->dv_decoder, codec->data );
125                 
126 // Libdv improperly decodes RGB colormodels.
127                 if((file->color_model == BC_YUV422 || 
128                         file->color_model == BC_RGB888) &&
129                         file->in_x == 0 && 
130                         file->in_y == 0 && 
131                         file->in_w == width &&
132                         file->in_h == height &&
133                         file->out_w == width &&
134                         file->out_h == height &&
135                         is_sequential)
136                 {
137                         if( file->color_model == BC_YUV422 )
138                         {
139                                 pitches[0] = 720 * 2;
140                                 dv_decode_full_frame( codec->dv_decoder, codec->data,
141                                                                           e_dv_color_yuv, row_pointers,
142                                                                           pitches );
143                         }
144                         else 
145                         if( file->color_model == BC_RGB888)
146                         {
147                                 pitches[0] = 720 * 3;
148                                 dv_decode_full_frame( codec->dv_decoder, codec->data,
149                                                                           e_dv_color_rgb, row_pointers,
150                                                                           pitches );
151                         }
152                 }
153                 else
154                 {
155                         if(!codec->temp_frame)
156                         {
157                                 codec->temp_frame = malloc(720 * 576 * 2);
158                                 codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
159                                 for(i = 0; i < 576; i++)
160                                         codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
161                         }
162
163                     decode_colormodel = BC_YUV422;
164                         pitches[0] = 720 * 2;
165                         dv_decode_full_frame( codec->dv_decoder, codec->data,
166                                                                   e_dv_color_yuv, codec->temp_rows,
167                                                                   pitches );
168                         
169
170
171
172                         cmodel_transfer(row_pointers, 
173                                 codec->temp_rows,
174                                 row_pointers[0],
175                                 row_pointers[1],
176                                 row_pointers[2],
177                                 codec->temp_rows[0],
178                                 codec->temp_rows[1],
179                                 codec->temp_rows[2],
180                                 file->in_x, 
181                                 file->in_y, 
182                                 file->in_w, 
183                                 file->in_h,
184                                 0, 
185                                 0, 
186                                 file->out_w, 
187                                 file->out_h,
188                                 decode_colormodel, 
189                                 file->color_model,
190                                 0,
191                                 width,
192                                 file->out_w);
193                 }
194         }
195
196 //printf(__FUNCTION__ " 2\n");
197         return result;
198 }
199
200 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
201 {
202         //int64_t offset = quicktime_position(file);
203         quicktime_video_map_t *vtrack = &(file->vtracks[track]);
204         quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
205         quicktime_trak_t *trak = vtrack->track;
206         int width = trak->tkhd.track_width;
207         int height = trak->tkhd.track_height;
208         int width_i = 720;
209         int height_i = (height <= 480) ? 480 : 576;
210         int i;
211         unsigned char **input_rows;
212         int is_pal = (height_i == 480) ? 0 : 1;
213         int data_length = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE;
214         int result = 0;
215         dv_color_space_t encode_dv_colormodel = 0;
216         quicktime_atom_t chunk_atom;
217
218         if( codec->dv_encoder != NULL && codec->parameters_changed )
219         {
220                 dv_encoder_free( codec->dv_encoder );
221                 codec->dv_encoder = NULL;
222                 codec->parameters_changed = 0;
223         }
224         
225         if( ! codec->dv_encoder )
226         {
227                 pthread_mutex_lock( &libdv_init_mutex );
228
229                 //printf( "dv.c encode: Alloc'ing encoder\n" );
230         
231                 codec->dv_encoder = dv_encoder_new( codec->rem_ntsc_setup,
232                                                                                         codec->clamp_luma,
233                                                                                         codec->clamp_chroma );
234
235                 codec->parameters_changed = 0;
236                 pthread_mutex_unlock( &libdv_init_mutex );
237         }
238
239         if(codec->dv_encoder)
240         {
241                 int is_sequential =
242                         check_sequentiality( row_pointers,
243                                                                  width_i * cmodel_calculate_pixelsize(file->color_model),
244                                                                  height );
245         
246                 if( ( file->color_model == BC_YUV422
247                           || file->color_model == BC_RGB888 ) &&
248                         width == width_i &&
249                         height == height_i &&
250                         is_sequential )
251                 {
252                         input_rows = row_pointers;
253                         switch( file->color_model )
254                         {
255                                 case BC_YUV422:
256                                         encode_dv_colormodel = e_dv_color_yuv;
257 //printf( "dv.c encode: e_dv_color_yuv\n" );
258                                         break;
259                                 case BC_RGB888:
260                                         encode_dv_colormodel = e_dv_color_rgb;
261 //printf( "dv.c encode: e_dv_color_rgb\n" );
262                                         break;
263                                 default:
264                                         return 0;
265                                         break;
266                         }
267                 }
268                 else
269                 {
270 // The best colormodel for encoding is YUV 422
271
272                         if(!codec->temp_frame)
273                         {
274                                 codec->temp_frame = malloc(720 * 576 * 2);
275                                 codec->temp_rows = malloc(sizeof(unsigned char*) * 576);
276                                 for(i = 0; i < 576; i++)
277                                         codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i;
278                         }
279                 
280                         cmodel_transfer(codec->temp_rows, /* Leave NULL if non existent */
281                                                         row_pointers,
282                                                         codec->temp_rows[0], /* Leave NULL if non existent */
283                                                         codec->temp_rows[1],
284                                                         codec->temp_rows[2],
285                                                         row_pointers[0], /* Leave NULL if non existent */
286                                                         row_pointers[1],
287                                                         row_pointers[2],
288                                                         0,   /* Dimensions to capture from input frame */
289                                                         0, 
290                                                         MIN(width, width_i), 
291                                                         MIN(height, height_i),
292                                                         0,   /* Dimensions to project on output frame */
293                                                         0, 
294                                                         MIN(width, width_i), 
295                                                         MIN(height, height_i),
296                                                         file->color_model, 
297                                                         BC_YUV422,
298                                                         0,    /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
299                                                         width,  /* For planar use the luma rowspan */
300                                                         width_i);
301
302
303                         input_rows = codec->temp_rows;
304                         encode_dv_colormodel = e_dv_color_yuv;
305                 }
306
307 // Setup the encoder
308                 codec->dv_encoder->is16x9 = codec->anamorphic16x9;
309                 codec->dv_encoder->vlc_encode_passes = codec->vlc_encode_passes;
310                 codec->dv_encoder->static_qno = 0;
311                 codec->dv_encoder->force_dct = DV_DCT_AUTO;
312                 codec->dv_encoder->isPAL = is_pal;
313
314
315 //printf("dv.c encode: 1 %d %d %d\n", width_i, height_i, encode_dv_colormodel);
316                 dv_encode_full_frame( codec->dv_encoder,
317                                                           input_rows, encode_dv_colormodel, codec->data );
318 //printf("dv.c encode: 2 %d %d\n", width_i, height_i);
319
320                 quicktime_write_chunk_header(file, trak, &chunk_atom);
321                 result = !quicktime_write_data(file, (char*)codec->data, data_length);
322                 quicktime_write_chunk_footer(file, 
323                         trak,
324                         vtrack->current_chunk,
325                         &chunk_atom, 
326                         1);
327                 vtrack->current_chunk++;
328 //printf("encode 3\n");
329         }
330
331         return result;
332 }
333
334 // Logic: DV contains a mixture of 420 and 411 so can only
335 // output/input 444 or 422 and libdv can output/input RGB as well so
336 // we include that.
337
338 // This function is used as both reads_colormodel and writes_colormodel
339 static int colormodel_dv(quicktime_t *file, 
340                 int colormodel, 
341                 int track)
342 {
343         return (colormodel == BC_RGB888 ||
344                         colormodel == BC_YUV888 ||
345                         colormodel == BC_YUV422);
346 }
347
348 static int set_parameter(quicktime_t *file, 
349                 int track, 
350                 char *key, 
351                 void *value)
352 {
353         quicktime_dv_codec_t *codec = ((quicktime_codec_t*)file->vtracks[track].codec)->priv;
354         
355         if(!strcasecmp(key, "dv_decode_quality"))
356         {
357                 codec->decode_quality = *(int*)value;
358         }
359         else if(!strcasecmp(key, "dv_anamorphic16x9"))
360         {
361                 codec->anamorphic16x9 = *(int*)value;
362         }
363         else if(!strcasecmp(key, "dv_vlc_encode_passes"))
364         {
365                 codec->vlc_encode_passes = *(int*)value;
366         }
367         else if(!strcasecmp(key, "dv_clamp_luma"))
368         {
369                 codec->clamp_luma = *(int*)value;
370         }
371         else if(!strcasecmp(key, "dv_clamp_chroma"))
372         {
373                 codec->clamp_chroma = *(int*)value;
374         }
375         else if(!strcasecmp(key, "dv_add_ntsc_setup"))
376         {
377                 codec->add_ntsc_setup = *(int*)value;
378         }
379         else if(!strcasecmp(key, "dv_rem_ntsc_setup"))
380         {
381                 codec->rem_ntsc_setup = *(int*)value;
382         }
383         else
384         {
385                 return 0;
386         }
387
388         codec->parameters_changed = 1;
389         return 0;
390 }
391
392 static void init_codec_common(quicktime_video_map_t *vtrack, char *fourcc)
393 {
394         quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
395         quicktime_dv_codec_t *codec;
396
397 /* Init public items */
398         codec_base->priv = calloc(1, sizeof(quicktime_dv_codec_t));
399         codec_base->delete_vcodec = delete_codec;
400         codec_base->decode_video = decode;
401         codec_base->encode_video = encode;
402         codec_base->decode_audio = 0;
403         codec_base->encode_audio = 0;
404         codec_base->reads_colormodel = colormodel_dv;
405         codec_base->writes_colormodel = colormodel_dv;
406         codec_base->set_parameter = set_parameter;
407         codec_base->fourcc = fourcc;
408         codec_base->title = "DV";
409         codec_base->desc = "DV";
410
411
412         /* Init private items */
413
414         codec = codec_base->priv;
415         
416         codec->dv_decoder = NULL;
417         codec->dv_encoder = NULL;
418         codec->decode_quality = DV_QUALITY_BEST;
419         codec->anamorphic16x9 = 0;
420         codec->vlc_encode_passes = 3;
421         codec->clamp_luma = codec->clamp_chroma = 0;
422         codec->add_ntsc_setup = 0;
423         codec->parameters_changed = 0;
424
425 // Allocate extra to work around some libdv overrun
426         codec->data = calloc(1, 144008);
427 }
428
429 void quicktime_init_codec_dv(quicktime_video_map_t *vtrack)
430 {
431         init_codec_common(vtrack, QUICKTIME_DV);
432 }
433
434 void quicktime_init_codec_dvcp(quicktime_video_map_t *vtrack)
435 {
436     init_codec_common(vtrack, QUICKTIME_DVCP);
437 }
438
439
440 void quicktime_init_codec_dv25(quicktime_video_map_t *vtrack)
441 {
442         init_codec_common(vtrack, QUICKTIME_DV25);
443 }
444
445 void quicktime_init_codec_dvsd(quicktime_video_map_t *vtrack)
446 {
447         init_codec_common(vtrack, QUICKTIME_DVSD);
448 }