2 #include "colormodels.h"
3 #include "funcprotos.h"
13 int decode_initialized
;
14 int encode_initialized
;
16 AVCodecContext
*decoder_context
;
17 AVCodecContext
*encoder_context
;
24 // ID out of avcodec.h for the codec used
29 int bitrate_tolerance
;
37 } quicktime_div3_codec_t
;
39 static pthread_mutex_t encode_mutex
;
40 static pthread_mutex_t decode_mutex
;
41 static int mutex_initialized
= 0;
42 static int global_initialized
= 0;
45 static int reads_colormodel(quicktime_t
*file
,
49 return (colormodel
== BC_YUV420P
);
52 static int writes_colormodel(quicktime_t
*file
,
56 return (colormodel
== BC_RGB888
||
57 colormodel
== BC_RGBA8888
||
58 colormodel
== BC_RGB161616
||
59 colormodel
== BC_RGBA16161616
||
60 colormodel
== BC_YUV888
||
61 colormodel
== BC_YUVA8888
||
62 colormodel
== BC_YUV161616
||
63 colormodel
== BC_YUVA16161616
||
64 colormodel
== BC_YUV420P
||
65 colormodel
== BC_YUV422
||
66 colormodel
== BC_COMPRESSED
);
71 static void init_mutex()
73 if(!mutex_initialized
)
75 pthread_mutexattr_t attr
;
76 mutex_initialized
= 1;
77 pthread_mutexattr_init(&attr
);
78 pthread_mutex_init(&decode_mutex
, &attr
);
79 pthread_mutex_init(&encode_mutex
, &attr
);
83 static int delete_codec(quicktime_video_map_t
*vtrack
)
85 quicktime_div3_codec_t
*codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
86 if(codec
->decode_initialized
)
88 pthread_mutex_lock(&decode_mutex
);
89 avcodec_close(codec
->decoder_context
);
90 free(codec
->decoder_context
);
91 pthread_mutex_unlock(&decode_mutex
);
93 if(codec
->encode_initialized
)
95 pthread_mutex_lock(&encode_mutex
);
96 avcodec_close(codec
->encoder_context
);
97 free(codec
->encoder_context
);
98 pthread_mutex_unlock(&encode_mutex
);
100 if(codec
->temp_frame
) free(codec
->temp_frame
);
101 if(codec
->work_buffer
) free(codec
->work_buffer
);
105 static int init_codec(quicktime_div3_codec_t
*codec
, int width_i
, int height_i
)
107 if(!global_initialized
)
109 global_initialized
= 1;
111 avcodec_register_all();
115 codec
->decoder
= avcodec_find_decoder(codec
->derivative
);
118 printf("init_codec: avcodec_find_decoder returned NULL.\n");
122 codec
->decoder_context
= avcodec_alloc_context();
123 codec
->decoder_context
->width
= width_i
;
124 codec
->decoder_context
->height
= height_i
;
125 if(avcodec_open(codec
->decoder_context
, codec
->decoder
) < 0)
127 printf("init_codec: avcodec_open failed.\n");
136 int quicktime_div3_is_key(unsigned char *data
, long size
)
140 // First 2 bits are pict type.
141 result
= (data
[0] & 0xc0) == 0;
148 static int decode_wrapper(quicktime_div3_codec_t
*codec
,
155 if(!codec
->got_key
&& !quicktime_div3_is_key(data
, size
)) return 0;
157 if(quicktime_div3_is_key(data
, size
)) codec
->got_key
= 1;
159 result
= avcodec_decode_video(codec
->decoder_context
,
172 static int decode(quicktime_t
*file
, unsigned char **row_pointers
, int track
)
174 //printf(__FUNCTION__ " div3 1\n");
175 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
176 quicktime_div3_codec_t
*codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
177 quicktime_trak_t
*trak
= vtrack
->track
;
179 int width
= trak
->tkhd
.track_width
;
180 int height
= trak
->tkhd
.track_height
;
181 int width_i
= (int)((float)width
/ 16 + 0.5) * 16;
182 int height_i
= (int)((float)height
/ 16 + 0.5) * 16;
186 unsigned char **input_rows
;
189 pthread_mutex_lock(&decode_mutex
);
192 if(!codec
->decode_initialized
)
194 init_codec(codec
, width_i
, height_i
);
196 codec
->decode_initialized
= 1;
200 if(quicktime_has_keyframes(file
, track
) &&
201 vtrack
->current_position
!= codec
->last_frame
+ 1)
203 int frame1
, frame2
= vtrack
->current_position
;
205 frame1
= quicktime_get_keyframe_before(file
,
206 vtrack
->current_position
,
209 if(frame1
< codec
->last_frame
&&
210 frame2
> codec
->last_frame
) frame1
= codec
->last_frame
+ 1;
212 while(frame1
< frame2
)
215 quicktime_set_video_position(file
, frame1
, track
);
217 bytes
= quicktime_frame_size(file
, frame1
, track
);
219 if(!codec
->work_buffer
|| codec
->buffer_size
< bytes
)
221 if(codec
->work_buffer
) free(codec
->work_buffer
);
222 codec
->buffer_size
= bytes
;
223 codec
->work_buffer
= calloc(1, codec
->buffer_size
+ 100);
227 result
= !quicktime_read_data(file
,
233 result
= decode_wrapper(codec
,
240 vtrack
->current_position
= frame2
;
243 codec
->last_frame
= vtrack
->current_position
;
244 bytes
= quicktime_frame_size(file
, vtrack
->current_position
, track
);
245 quicktime_set_video_position(file
, vtrack
->current_position
, track
);
247 if(!codec
->work_buffer
|| codec
->buffer_size
< bytes
)
249 if(codec
->work_buffer
) free(codec
->work_buffer
);
250 codec
->buffer_size
= bytes
;
251 codec
->work_buffer
= calloc(1, codec
->buffer_size
+ 100);
253 result
= !quicktime_read_data(file
, codec
->work_buffer
, bytes
);
256 result
= decode_wrapper(codec
,
260 pthread_mutex_unlock(&decode_mutex
);
272 result
= (result
<= 0);
273 switch(codec
->decoder_context
->pix_fmt
)
275 case PIX_FMT_YUV420P
:
276 input_cmodel
= BC_YUV420P
;
279 input_cmodel
= BC_YUV422
;
281 case PIX_FMT_YUV422P
:
282 input_cmodel
= BC_YUV422P
;
289 int y_out_size
= codec
->decoder_context
->width
*
290 codec
->decoder_context
->height
;
291 int u_out_size
= codec
->decoder_context
->width
*
292 codec
->decoder_context
->height
/
294 int v_out_size
= codec
->decoder_context
->width
*
295 codec
->decoder_context
->height
/
297 int y_in_size
= codec
->picture
.linesize
[0] *
298 codec
->decoder_context
->height
;
299 int u_in_size
= codec
->picture
.linesize
[1] *
300 codec
->decoder_context
->height
/
302 int v_in_size
= codec
->picture
.linesize
[2] *
303 codec
->decoder_context
->height
/
306 malloc(sizeof(unsigned char*) *
307 codec
->decoder_context
->height
);
309 for(i
= 0; i
< codec
->decoder_context
->height
; i
++)
310 input_rows
[i
] = codec
->picture
.data
[0] +
312 codec
->decoder_context
->width
*
313 cmodel_calculate_pixelsize(input_cmodel
);
315 if(!codec
->temp_frame
)
317 codec
->temp_frame
= malloc(y_out_size
+
322 if(codec
->picture
.data
[0])
324 for(i
= 0; i
< codec
->decoder_context
->height
; i
++)
326 memcpy(codec
->temp_frame
+ i
* codec
->decoder_context
->width
,
327 codec
->picture
.data
[0] + i
* codec
->picture
.linesize
[0],
328 codec
->decoder_context
->width
);
331 for(i
= 0; i
< codec
->decoder_context
->height
; i
+= 2)
333 memcpy(codec
->temp_frame
+
336 codec
->decoder_context
->width
/ 2,
337 codec
->picture
.data
[1] +
339 codec
->picture
.linesize
[1],
340 codec
->decoder_context
->width
/ 2);
342 memcpy(codec
->temp_frame
+
346 codec
->decoder_context
->width
/ 2,
347 codec
->picture
.data
[2] +
349 codec
->picture
.linesize
[2],
350 codec
->decoder_context
->width
/ 2);
354 cmodel_transfer(row_pointers
, /* Leave NULL if non existent */
356 row_pointers
[0], /* Leave NULL if non existent */
359 codec
->temp_frame
, /* Leave NULL if non existent */
360 codec
->temp_frame
+ y_out_size
,
361 codec
->temp_frame
+ y_out_size
+ u_out_size
,
362 file
->in_x
, /* Dimensions to capture from input frame */
366 0, /* Dimensions to project on output frame */
372 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
373 codec
->decoder_context
->width
, /* For planar use the luma rowspan */
383 static int encode(quicktime_t
*file
, unsigned char **row_pointers
, int track
)
385 //printf(__FUNCTION__ " 1\n");
386 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
387 quicktime_div3_codec_t
*codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
388 quicktime_trak_t
*trak
= vtrack
->track
;
389 int width
= trak
->tkhd
.track_width
;
390 int height
= trak
->tkhd
.track_height
;
392 int width_i
= (int)((float)width
/ 16 + 0.5) * 16;
393 int height_i
= (int)((float)height
/ 16 + 0.5) * 16;
396 quicktime_atom_t chunk_atom
;
397 //printf(__FUNCTION__ " 1\n");
400 //printf(__FUNCTION__ " 1\n");
402 pthread_mutex_lock(&encode_mutex
);
403 if(!codec
->encode_initialized
)
405 static char *video_rc_eq
="tex^qComp";
406 codec
->encode_initialized
= 1;
407 if(!global_initialized
)
409 global_initialized
= 1;
411 avcodec_register_all();
414 codec
->encoder
= avcodec_find_encoder(codec
->derivative
);
417 printf("encode: avcodec_find_encoder returned NULL.\n");
418 pthread_mutex_unlock(&encode_mutex
);
422 codec
->encoder_context
= avcodec_alloc_context();
423 codec
->encoder_context
->frame_rate
= FRAME_RATE_BASE
*
424 quicktime_frame_rate(file
, track
);
425 codec
->encoder_context
->width
= width_i
;
426 codec
->encoder_context
->height
= height_i
;
427 codec
->encoder_context
->gop_size
= codec
->gop_size
;
428 codec
->encoder_context
->pix_fmt
= PIX_FMT_YUV420P
;
429 codec
->encoder_context
->bit_rate
= codec
->bitrate
;
430 codec
->encoder_context
->bit_rate_tolerance
= codec
->bitrate_tolerance
;
431 codec
->encoder_context
->rc_eq
= video_rc_eq
;
432 codec
->encoder_context
->qmin
= 2;
433 codec
->encoder_context
->qmax
= 31;
434 codec
->encoder_context
->max_qdiff
= 3;
435 codec
->encoder_context
->qblur
= 0.5;
436 codec
->encoder_context
->qcompress
= 0.5;
437 codec
->encoder_context
->me_method
= ME_FULL
;
439 if(!codec
->fix_bitrate
)
441 codec
->encoder_context
->flags
|= CODEC_FLAG_QSCALE
;
444 if(codec
->interlaced
)
446 codec
->encoder_context
->flags
|= CODEC_FLAG_INTERLACED_DCT
;
450 avcodec_open(codec
->encoder_context
, codec
->encoder
);
452 codec
->work_buffer
= calloc(1, width_i
* height_i
* 3);
453 codec
->buffer_size
= width_i
* height_i
* 3;
455 //printf(__FUNCTION__ " 1\n");
459 if(width_i
== width
&&
460 height_i
== height
&&
461 file
->color_model
== BC_YUV420P
)
463 pict_tmp
.data
[0] = row_pointers
[0];
464 pict_tmp
.data
[1] = row_pointers
[1];
465 pict_tmp
.data
[2] = row_pointers
[2];
466 pict_tmp
.linesize
[0] = width_i
;
467 pict_tmp
.linesize
[1] = width_i
/ 2;
468 pict_tmp
.linesize
[2] = width_i
/ 2;
472 //printf(__FUNCTION__ " 1\n");
473 if(!codec
->temp_frame
)
475 codec
->temp_frame
= malloc(width_i
* height_i
* 3 / 2);
477 //printf(__FUNCTION__ " 1\n");
479 cmodel_transfer(0, /* Leave NULL if non existent */
481 codec
->temp_frame
, /* Leave NULL if non existent */
482 codec
->temp_frame
+ width_i
* height_i
,
483 codec
->temp_frame
+ width_i
* height_i
+ width_i
* height_i
/ 4,
484 row_pointers
[0], /* Leave NULL if non existent */
487 0, /* Dimensions to capture from input frame */
491 0, /* Dimensions to project on output frame */
497 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
498 width
, /* For planar use the luma rowspan */
500 //printf(__FUNCTION__ " 1\n");
502 pict_tmp
.data
[0] = codec
->temp_frame
;
503 pict_tmp
.data
[1] = codec
->temp_frame
+ width_i
* height_i
;
504 pict_tmp
.data
[2] = codec
->temp_frame
+ width_i
* height_i
+ width_i
* height_i
/ 4;
505 pict_tmp
.linesize
[0] = width_i
;
506 pict_tmp
.linesize
[1] = width_i
/ 2;
507 pict_tmp
.linesize
[2] = width_i
/ 2;
511 //printf("encode 1\n");
512 if(codec
->quantizer
>= 0)
513 pict_tmp
.quality
= codec
->quantizer
;
514 bytes
= avcodec_encode_video(codec
->encoder_context
,
518 pthread_mutex_unlock(&encode_mutex
);
519 //printf("encode 100\n");
521 quicktime_write_chunk_header(file
, trak
, &chunk_atom
);
522 //printf(__FUNCTION__ " 1\n");
523 result
= !quicktime_write_data(file
,
526 //printf(__FUNCTION__ " 1\n");
528 quicktime_write_chunk_footer(file
,
530 vtrack
->current_chunk
,
533 //printf(__FUNCTION__ " 1\n");
534 if(pict_tmp
.key_frame
)
535 quicktime_insert_keyframe(file
,
536 vtrack
->current_position
,
538 vtrack
->current_chunk
++;
540 //printf(__FUNCTION__ " 100\n");
550 static int set_parameter(quicktime_t
*file
,
555 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
556 quicktime_div3_codec_t
*codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
557 if(!strcasecmp(key
, "div3_bitrate"))
558 codec
->bitrate
= *(int*)value
;
560 if(!strcasecmp(key
, "div3_bitrate_tolerance"))
561 codec
->bitrate_tolerance
= *(int*)value
;
563 if(!strcasecmp(key
, "div3_interlaced"))
564 codec
->quantizer
= *(int*)value
;
566 if(!strcasecmp(key
, "div3_gop_size"))
567 codec
->gop_size
= *(int*)value
;
569 if(!strcasecmp(key
, "div3_quantizer"))
570 codec
->quantizer
= *(int*)value
;
572 if(!strcasecmp(key
, "div3_fix_bitrate"))
573 codec
->fix_bitrate
= *(int*)value
;
579 void quicktime_init_codec_div3(quicktime_video_map_t
*vtrack
)
581 quicktime_div3_codec_t
*codec
;
582 ((quicktime_codec_t
*)vtrack
->codec
)->priv
= calloc(1, sizeof(quicktime_div3_codec_t
));
583 ((quicktime_codec_t
*)vtrack
->codec
)->delete_vcodec
= delete_codec
;
584 ((quicktime_codec_t
*)vtrack
->codec
)->decode_video
= decode
;
585 ((quicktime_codec_t
*)vtrack
->codec
)->encode_video
= encode
;
586 ((quicktime_codec_t
*)vtrack
->codec
)->reads_colormodel
= reads_colormodel
;
587 ((quicktime_codec_t
*)vtrack
->codec
)->writes_colormodel
= writes_colormodel
;
588 ((quicktime_codec_t
*)vtrack
->codec
)->set_parameter
= set_parameter
;
590 codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
591 codec
->derivative
= CODEC_ID_MSMPEG4V3
;
592 // codec->derivative = CODEC_ID_MPEG4;
593 codec
->quantizer
= -1;
601 void quicktime_init_codec_div4(quicktime_video_map_t
*vtrack
)
603 quicktime_div3_codec_t
*codec
;
604 ((quicktime_codec_t
*)vtrack
->codec
)->priv
= calloc(1, sizeof(quicktime_div3_codec_t
));
605 ((quicktime_codec_t
*)vtrack
->codec
)->delete_vcodec
= delete_codec
;
606 ((quicktime_codec_t
*)vtrack
->codec
)->decode_video
= decode
;
607 ((quicktime_codec_t
*)vtrack
->codec
)->encode_video
= encode
;
608 ((quicktime_codec_t
*)vtrack
->codec
)->reads_colormodel
= reads_colormodel
;
609 ((quicktime_codec_t
*)vtrack
->codec
)->writes_colormodel
= writes_colormodel
;
610 ((quicktime_codec_t
*)vtrack
->codec
)->set_parameter
= set_parameter
;
612 codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
613 codec
->derivative
= CODEC_ID_MPEG4
;
614 codec
->quantizer
= -1;