2 #include "colormodels.h"
3 #include "funcprotos.h"
8 #include "workarounds.h"
16 x264_t
*encoder
[FIELDS
];
17 x264_picture_t
*pic
[FIELDS
];
20 int encode_initialized
[FIELDS
];
22 // Temporary storage for color conversions
24 // Storage of compressed data
25 unsigned char *work_buffer
;
26 // Amount of data in work_buffer
29 // Set by flush to get the header
33 quicktime_ffmpeg_t
*decoder
;
35 } quicktime_h264_codec_t
;
37 static pthread_mutex_t h264_lock
= PTHREAD_MUTEX_INITIALIZER
;
50 // Direct copy routines
51 int quicktime_h264_is_key(unsigned char *data
, long size
, char *codec_id
)
59 static int delete_codec(quicktime_video_map_t
*vtrack
)
61 quicktime_h264_codec_t
*codec
;
65 codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
66 for(i
= 0; i
< codec
->total_fields
; i
++)
68 if(codec
->encode_initialized
[i
])
70 pthread_mutex_lock(&h264_lock
);
75 x264_picture_clean(codec
->pic
[i
]);
81 x264_encoder_close(codec
->encoder
[i
]);
84 pthread_mutex_unlock(&h264_lock
);
90 if(codec
->temp_frame
) free(codec
->temp_frame
);
91 if(codec
->work_buffer
) free(codec
->work_buffer
);
92 if(codec
->decoder
) quicktime_delete_ffmpeg(codec
->decoder
);
101 static int encode(quicktime_t
*file
, unsigned char **row_pointers
, int track
)
103 int64_t offset
= quicktime_position(file
);
104 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
105 quicktime_h264_codec_t
*codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
106 quicktime_trak_t
*trak
= vtrack
->track
;
107 int width
= quicktime_video_width(file
, track
);
108 int height
= quicktime_video_height(file
, track
);
109 int w_16
= quicktime_quantize16(width
);
110 int h_16
= quicktime_quantize16(height
);
115 int current_field
= vtrack
->current_position
% codec
->total_fields
;
116 quicktime_atom_t chunk_atom
;
117 unsigned char header
[1024];
121 quicktime_avcc_t
*avcc
= &trak
->mdia
.minf
.stbl
.stsd
.table
[0].avcc
;
128 pthread_mutex_lock(&h264_lock
);
130 if(!codec
->encode_initialized
[current_field
])
132 codec
->encode_initialized
[current_field
] = 1;
133 codec
->param
.i_width
= w_16
;
134 codec
->param
.i_height
= w_16
;
135 codec
->param
.i_fps_num
= quicktime_frame_rate_n(file
, track
);
136 codec
->param
.i_fps_den
= quicktime_frame_rate_d(file
, track
);
138 x264_param_t default_params
;
139 x264_param_default(&default_params
);
140 // Reset quantizer if fixed bitrate
142 if(codec
->param
.rc
.b_cbr
)
144 if(codec
->param
.rc
.i_rc_method
== X264_RC_ABR
)
147 codec
->param
.rc
.i_qp_constant
= default_params
.rc
.i_qp_constant
;
148 codec
->param
.rc
.i_qp_min
= default_params
.rc
.i_qp_min
;
149 codec
->param
.rc
.i_qp_max
= default_params
.rc
.i_qp_max
;
155 codec
->param
.i_threads
= file
->cpus
;
158 codec
->encoder
[current_field
] = x264_encoder_open(&codec
->param
);
159 codec
->pic
[current_field
] = calloc(1, sizeof(x264_picture_t
));
160 x264_picture_alloc(codec
->pic
[current_field
],
162 codec
->param
.i_width
,
163 codec
->param
.i_height
);
171 codec
->pic
[current_field
]->i_type
= X264_TYPE_AUTO
;
172 codec
->pic
[current_field
]->i_qpplus1
= 0;
175 if(codec
->header_only
)
177 bzero(codec
->pic
[current_field
]->img
.plane
[0], w_16
* h_16
);
178 bzero(codec
->pic
[current_field
]->img
.plane
[1], w_16
* h_16
/ 4);
179 bzero(codec
->pic
[current_field
]->img
.plane
[2], w_16
* h_16
/ 4);
182 if(file
->color_model
== BC_YUV420P
)
184 memcpy(codec
->pic
[current_field
]->img
.plane
[0], row_pointers
[0], w_16
* h_16
);
185 memcpy(codec
->pic
[current_field
]->img
.plane
[1], row_pointers
[1], w_16
* h_16
/ 4);
186 memcpy(codec
->pic
[current_field
]->img
.plane
[2], row_pointers
[2], w_16
* h_16
/ 4);
190 cmodel_transfer(0, /* Leave NULL if non existent */
192 codec
->pic
[current_field
]->img
.plane
[0], /* Leave NULL if non existent */
193 codec
->pic
[current_field
]->img
.plane
[1],
194 codec
->pic
[current_field
]->img
.plane
[2],
195 row_pointers
[0], /* Leave NULL if non existent */
198 0, /* Dimensions to capture from input frame */
202 0, /* Dimensions to project on output frame */
208 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
209 width
, /* For planar use the luma rowspan */
210 codec
->pic
[current_field
]->img
.i_stride
[0]);
225 x264_picture_t pic_out
;
228 x264_encoder_encode(codec
->encoder
[current_field
],
231 codec
->pic
[current_field
],
233 int allocation
= w_16
* h_16
* 3;
234 if(!codec
->work_buffer
)
236 codec
->work_buffer
= calloc(1, allocation
);
239 codec
->buffer_size
= 0;
240 for(i
= 0; i
< nnal
; i
++)
242 int size
= x264_nal_encode(codec
->work_buffer
+ codec
->buffer_size
,
246 unsigned char *ptr
= codec
->work_buffer
+ codec
->buffer_size
;
250 // Size of NAL for avc
251 uint64_t avc_size
= size
- 4;
253 // Synthesize header.
254 // Hopefully all the parameter set NAL's are present in the first frame.
259 header
[header_size
++] = 0x01;
260 header
[header_size
++] = 0x4d;
261 header
[header_size
++] = 0x40;
262 header
[header_size
++] = 0x1f;
263 header
[header_size
++] = 0xff;
264 header
[header_size
++] = 0xe1;
267 int nal_type
= (ptr
[4] & 0x1f);
268 // Picture parameter or sequence parameter set
269 if(nal_type
== 0x7 && !got_sps
)
272 header
[header_size
++] = (avc_size
& 0xff00) >> 8;
273 header
[header_size
++] = (avc_size
& 0xff);
274 memcpy(&header
[header_size
],
277 header_size
+= avc_size
;
280 if(nal_type
== 0x8 && !got_pps
)
283 // Number of sps nal's.
284 header
[header_size
++] = 0x1;
285 header
[header_size
++] = (avc_size
& 0xff00) >> 8;
286 header
[header_size
++] = (avc_size
& 0xff);
287 memcpy(&header
[header_size
],
290 header_size
+= avc_size
;
294 if(got_sps
&& got_pps
)
296 quicktime_set_avcc_header(avcc
,
303 // Convert to avc nal
304 *ptr
++ = (avc_size
& 0xff000000) >> 24;
305 *ptr
++ = (avc_size
& 0xff0000) >> 16;
306 *ptr
++ = (avc_size
& 0xff00) >> 8;
307 *ptr
++ = (avc_size
& 0xff);
308 codec
->buffer_size
+= size
;
314 pthread_mutex_unlock(&h264_lock
);
318 if(!codec
->header_only
)
320 if(pic_out
.i_type
== X264_TYPE_IDR
||
321 pic_out
.i_type
== X264_TYPE_I
)
326 if(codec
->buffer_size
)
328 quicktime_write_chunk_header(file
, trak
, &chunk_atom
);
329 result
= !quicktime_write_data(file
,
332 quicktime_write_chunk_footer(file
,
334 vtrack
->current_chunk
,
341 quicktime_insert_keyframe(file
,
342 vtrack
->current_position
,
345 vtrack
->current_chunk
++;
353 static int decode(quicktime_t
*file
, unsigned char **row_pointers
, int track
)
355 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
356 quicktime_trak_t
*trak
= vtrack
->track
;
357 quicktime_h264_codec_t
*codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
358 quicktime_stsd_table_t
*stsd_table
= &trak
->mdia
.minf
.stbl
.stsd
.table
[0];
359 int width
= trak
->tkhd
.track_width
;
360 int height
= trak
->tkhd
.track_height
;
361 int w_16
= quicktime_quantize16(width
);
362 int h_16
= quicktime_quantize16(height
);
365 if(!codec
->decoder
) codec
->decoder
= quicktime_new_ffmpeg(
374 if(codec
->decoder
) return quicktime_ffmpeg_decode(codec
->decoder
,
382 // Straight out of another h264 file
384 * static int write_avcc_header(unsigned char *data)
387 * unsigned char *ptr = data;
390 * static unsigned char test[] =
392 * 0x01, 0x4d, 0x40, 0x1f, 0xff, 0xe1, 0x00, 0x14,
393 * 0x27, 0x4d, 0x40, 0x1f, 0xa9, 0x18, 0x0a, 0x00,
394 * 0xb7, 0x60, 0x0d, 0x40, 0x40, 0x40, 0x4c, 0x2b,
395 * 0x5e, 0xf7, 0xc0, 0x40, 0x01, 0x00, 0x04, 0x28,
399 * memcpy(data, test, sizeof(test));
400 * result = sizeof(test);
406 static void flush(quicktime_t
*file
, int track
)
408 quicktime_video_map_t
*track_map
= &(file
->vtracks
[track
]);
409 quicktime_trak_t
*trak
= track_map
->track
;
410 quicktime_h264_codec_t
*codec
= ((quicktime_codec_t
*)track_map
->codec
)->priv
;
411 quicktime_avcc_t
*avcc
= &trak
->mdia
.minf
.stbl
.stsd
.table
[0].avcc
;
415 codec
->header_only
= 1;
416 encode(file
, 0, track
);
418 * unsigned char temp[1024];
419 * int size = write_avcc_header(temp);
421 * quicktime_set_avcc_header(avcc,
427 * trak->mdia.minf.stbl.stsd.table[0].version = 1;
428 * trak->mdia.minf.stbl.stsd.table[0].revision = 1;
434 static int reads_colormodel(quicktime_t
*file
,
438 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
439 quicktime_codec_t
*codec
= (quicktime_codec_t
*)vtrack
->codec
;
440 return (colormodel
== BC_YUV420P
);
443 static int writes_colormodel(quicktime_t
*file
,
447 return (colormodel
== BC_YUV420P
);
450 static int set_parameter(quicktime_t
*file
,
455 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
456 char *compressor
= quicktime_compressor(vtrack
->track
);
458 if(quicktime_match_32(compressor
, QUICKTIME_H264
) ||
459 quicktime_match_32(compressor
, QUICKTIME_HV64
))
461 quicktime_h264_codec_t
*codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
462 if(!strcasecmp(key
, "h264_bitrate"))
464 if(quicktime_match_32(compressor
, QUICKTIME_H264
))
465 codec
->param
.rc
.i_bitrate
= *(int*)value
;
467 codec
->param
.rc
.i_bitrate
= *(int*)value
/ 2;
470 if(!strcasecmp(key
, "h264_quantizer"))
472 codec
->param
.rc
.i_qp_constant
=
473 codec
->param
.rc
.i_qp_min
=
474 codec
->param
.rc
.i_qp_max
= *(int*)value
;
477 if(!strcasecmp(key
, "h264_fix_bitrate"))
479 codec
->param
.rc
.b_cbr
= (*(int*)value
) / 1000;
481 codec
->param
.rc
.i_bitrate
= (*(int*)value
) / 1000;
486 static quicktime_h264_codec_t
* init_common(quicktime_video_map_t
*vtrack
,
491 quicktime_codec_t
*codec_base
= (quicktime_codec_t
*)vtrack
->codec
;
492 quicktime_h264_codec_t
*codec
;
494 codec_base
->priv
= calloc(1, sizeof(quicktime_h264_codec_t
));
495 codec_base
->delete_vcodec
= delete_codec
;
496 codec_base
->decode_video
= decode
;
497 codec_base
->encode_video
= encode
;
498 codec_base
->flush
= flush
;
499 codec_base
->reads_colormodel
= reads_colormodel
;
500 codec_base
->writes_colormodel
= writes_colormodel
;
501 codec_base
->set_parameter
= set_parameter
;
502 codec_base
->fourcc
= compressor
;
503 codec_base
->title
= title
;
504 codec_base
->desc
= description
;
507 codec
= (quicktime_h264_codec_t
*)codec_base
->priv
;
508 x264_param_default(&codec
->param
);
515 void quicktime_init_codec_h264(quicktime_video_map_t
*vtrack
)
517 quicktime_h264_codec_t
*result
= init_common(vtrack
,
521 result
->total_fields
= 1;
526 void quicktime_init_codec_hv64(quicktime_video_map_t
*vtrack
)
528 quicktime_h264_codec_t
*result
= init_common(vtrack
,
531 "H.264 with two streams alternating every other frame. (Not standardized)");
532 result
->total_fields
= 2;