2 #include "colormodels.h"
3 #include "funcprotos.h"
7 #include "workarounds.h"
15 x264_t
*encoder
[FIELDS
];
16 x264_picture_t
*pic
[FIELDS
];
19 int encode_initialized
[FIELDS
];
21 // Temporary storage for color conversions
23 // Storage of compressed data
24 unsigned char *work_buffer
;
25 // Amount of data in work_buffer
28 // Set by flush to get the header
32 quicktime_ffmpeg_t
*decoder
;
34 } quicktime_h264_codec_t
;
36 static pthread_mutex_t h264_lock
= PTHREAD_MUTEX_INITIALIZER
;
49 // Direct copy routines
50 int quicktime_h264_is_key(unsigned char *data
, long size
, char *codec_id
)
58 static int delete_codec(quicktime_video_map_t
*vtrack
)
60 quicktime_h264_codec_t
*codec
;
64 codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
65 for(i
= 0; i
< codec
->total_fields
; i
++)
67 if(codec
->encode_initialized
[i
])
69 pthread_mutex_lock(&h264_lock
);
74 x264_picture_clean(codec
->pic
[i
]);
80 x264_encoder_close(codec
->encoder
[i
]);
83 pthread_mutex_unlock(&h264_lock
);
89 if(codec
->temp_frame
) free(codec
->temp_frame
);
90 if(codec
->work_buffer
) free(codec
->work_buffer
);
99 static int encode(quicktime_t
*file
, unsigned char **row_pointers
, int track
)
101 int64_t offset
= quicktime_position(file
);
102 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
103 quicktime_h264_codec_t
*codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
104 quicktime_trak_t
*trak
= vtrack
->track
;
105 int width
= quicktime_video_width(file
, track
);
106 int height
= quicktime_video_height(file
, track
);
107 int w_16
= quicktime_quantize16(width
);
108 int h_16
= quicktime_quantize16(height
);
113 int current_field
= vtrack
->current_position
% codec
->total_fields
;
114 quicktime_atom_t chunk_atom
;
115 unsigned char header
[1024];
119 quicktime_avcc_t
*avcc
= &trak
->mdia
.minf
.stbl
.stsd
.table
[0].avcc
;
126 pthread_mutex_lock(&h264_lock
);
128 if(!codec
->encode_initialized
[current_field
])
130 codec
->encode_initialized
[current_field
] = 1;
131 codec
->param
.i_width
= w_16
;
132 codec
->param
.i_height
= w_16
;
133 codec
->param
.i_fps_num
= quicktime_frame_rate_n(file
, track
);
134 codec
->param
.i_fps_den
= quicktime_frame_rate_d(file
, track
);
136 x264_param_t default_params
;
137 x264_param_default(&default_params
);
138 // Reset quantizer if fixed bitrate
139 if(codec
->param
.rc
.b_cbr
)
141 codec
->param
.rc
.i_qp_constant
= default_params
.rc
.i_qp_constant
;
142 codec
->param
.rc
.i_qp_min
= default_params
.rc
.i_qp_min
;
143 codec
->param
.rc
.i_qp_max
= default_params
.rc
.i_qp_max
;
149 codec
->param
.i_threads
= file
->cpus
;
152 codec
->encoder
[current_field
] = x264_encoder_open(&codec
->param
);
153 codec
->pic
[current_field
] = calloc(1, sizeof(x264_picture_t
));
154 x264_picture_alloc(codec
->pic
[current_field
],
156 codec
->param
.i_width
,
157 codec
->param
.i_height
);
165 codec
->pic
[current_field
]->i_type
= X264_TYPE_AUTO
;
166 codec
->pic
[current_field
]->i_qpplus1
= 0;
169 if(codec
->header_only
)
171 bzero(codec
->pic
[current_field
]->img
.plane
[0], w_16
* h_16
);
172 bzero(codec
->pic
[current_field
]->img
.plane
[1], w_16
* h_16
/ 4);
173 bzero(codec
->pic
[current_field
]->img
.plane
[2], w_16
* h_16
/ 4);
176 if(file
->color_model
== BC_YUV420P
)
178 memcpy(codec
->pic
[current_field
]->img
.plane
[0], row_pointers
[0], w_16
* h_16
);
179 memcpy(codec
->pic
[current_field
]->img
.plane
[1], row_pointers
[1], w_16
* h_16
/ 4);
180 memcpy(codec
->pic
[current_field
]->img
.plane
[2], row_pointers
[2], w_16
* h_16
/ 4);
184 cmodel_transfer(0, /* Leave NULL if non existent */
186 codec
->pic
[current_field
]->img
.plane
[0], /* Leave NULL if non existent */
187 codec
->pic
[current_field
]->img
.plane
[1],
188 codec
->pic
[current_field
]->img
.plane
[2],
189 row_pointers
[0], /* Leave NULL if non existent */
192 0, /* Dimensions to capture from input frame */
196 0, /* Dimensions to project on output frame */
202 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
203 width
, /* For planar use the luma rowspan */
204 codec
->pic
[current_field
]->img
.i_stride
[0]);
219 x264_picture_t pic_out
;
222 x264_encoder_encode(codec
->encoder
[current_field
],
225 codec
->pic
[current_field
],
227 int allocation
= w_16
* h_16
* 3;
228 if(!codec
->work_buffer
)
230 codec
->work_buffer
= calloc(1, allocation
);
233 codec
->buffer_size
= 0;
234 for(i
= 0; i
< nnal
; i
++)
236 int size
= x264_nal_encode(codec
->work_buffer
+ codec
->buffer_size
,
240 unsigned char *ptr
= codec
->work_buffer
+ codec
->buffer_size
;
244 // Size of NAL for avc
245 uint64_t avc_size
= size
- 4;
247 // Synthesize header.
248 // Hopefully all the parameter set NAL's are present in the first frame.
253 header
[header_size
++] = 0x01;
254 header
[header_size
++] = 0x4d;
255 header
[header_size
++] = 0x40;
256 header
[header_size
++] = 0x1f;
257 header
[header_size
++] = 0xff;
258 header
[header_size
++] = 0xe1;
261 int nal_type
= (ptr
[4] & 0x1f);
262 // Picture parameter or sequence parameter set
263 if(nal_type
== 0x7 && !got_sps
)
266 header
[header_size
++] = (avc_size
& 0xff00) >> 8;
267 header
[header_size
++] = (avc_size
& 0xff);
268 memcpy(&header
[header_size
],
271 header_size
+= avc_size
;
274 if(nal_type
== 0x8 && !got_pps
)
277 // Number of sps nal's.
278 header
[header_size
++] = 0x1;
279 header
[header_size
++] = (avc_size
& 0xff00) >> 8;
280 header
[header_size
++] = (avc_size
& 0xff);
281 memcpy(&header
[header_size
],
284 header_size
+= avc_size
;
288 if(got_sps
&& got_pps
)
290 quicktime_set_avcc_header(avcc
,
297 // Convert to avc nal
298 *ptr
++ = (avc_size
& 0xff000000) >> 24;
299 *ptr
++ = (avc_size
& 0xff0000) >> 16;
300 *ptr
++ = (avc_size
& 0xff00) >> 8;
301 *ptr
++ = (avc_size
& 0xff);
302 codec
->buffer_size
+= size
;
308 pthread_mutex_unlock(&h264_lock
);
312 if(!codec
->header_only
)
314 if(pic_out
.i_type
== X264_TYPE_IDR
||
315 pic_out
.i_type
== X264_TYPE_I
)
320 if(codec
->buffer_size
)
322 quicktime_write_chunk_header(file
, trak
, &chunk_atom
);
323 result
= !quicktime_write_data(file
,
326 quicktime_write_chunk_footer(file
,
328 vtrack
->current_chunk
,
335 quicktime_insert_keyframe(file
,
336 vtrack
->current_position
,
339 vtrack
->current_chunk
++;
347 static int decode(quicktime_t
*file
, unsigned char **row_pointers
, int track
)
349 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
350 quicktime_trak_t
*trak
= vtrack
->track
;
351 quicktime_h264_codec_t
*codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
352 quicktime_stsd_table_t
*stsd_table
= &trak
->mdia
.minf
.stbl
.stsd
.table
[0];
353 int width
= trak
->tkhd
.track_width
;
354 int height
= trak
->tkhd
.track_height
;
355 int w_16
= quicktime_quantize16(width
);
356 int h_16
= quicktime_quantize16(height
);
359 if(!codec
->decoder
) codec
->decoder
= quicktime_new_ffmpeg(
368 if(codec
->decoder
) return quicktime_ffmpeg_decode(codec
->decoder
,
376 // Straight out of another h264 file
378 * static int write_avcc_header(unsigned char *data)
381 * unsigned char *ptr = data;
384 * static unsigned char test[] =
386 * 0x01, 0x4d, 0x40, 0x1f, 0xff, 0xe1, 0x00, 0x14,
387 * 0x27, 0x4d, 0x40, 0x1f, 0xa9, 0x18, 0x0a, 0x00,
388 * 0xb7, 0x60, 0x0d, 0x40, 0x40, 0x40, 0x4c, 0x2b,
389 * 0x5e, 0xf7, 0xc0, 0x40, 0x01, 0x00, 0x04, 0x28,
393 * memcpy(data, test, sizeof(test));
394 * result = sizeof(test);
400 static void flush(quicktime_t
*file
, int track
)
402 quicktime_video_map_t
*track_map
= &(file
->vtracks
[track
]);
403 quicktime_trak_t
*trak
= track_map
->track
;
404 quicktime_h264_codec_t
*codec
= ((quicktime_codec_t
*)track_map
->codec
)->priv
;
405 quicktime_avcc_t
*avcc
= &trak
->mdia
.minf
.stbl
.stsd
.table
[0].avcc
;
409 codec
->header_only
= 1;
410 encode(file
, 0, track
);
412 * unsigned char temp[1024];
413 * int size = write_avcc_header(temp);
415 * quicktime_set_avcc_header(avcc,
421 * trak->mdia.minf.stbl.stsd.table[0].version = 1;
422 * trak->mdia.minf.stbl.stsd.table[0].revision = 1;
428 static int reads_colormodel(quicktime_t
*file
,
432 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
433 quicktime_codec_t
*codec
= (quicktime_codec_t
*)vtrack
->codec
;
434 return (colormodel
== BC_YUV420P
);
437 static int writes_colormodel(quicktime_t
*file
,
441 return (colormodel
== BC_YUV420P
);
444 static int set_parameter(quicktime_t
*file
,
449 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
450 char *compressor
= quicktime_compressor(vtrack
->track
);
452 if(quicktime_match_32(compressor
, QUICKTIME_H264
) ||
453 quicktime_match_32(compressor
, QUICKTIME_HV64
))
455 quicktime_h264_codec_t
*codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
456 if(!strcasecmp(key
, "h264_bitrate"))
458 if(quicktime_match_32(compressor
, QUICKTIME_H264
))
459 codec
->param
.rc
.i_bitrate
= *(int*)value
;
461 codec
->param
.rc
.i_bitrate
= *(int*)value
/ 2;
464 if(!strcasecmp(key
, "h264_quantizer"))
466 codec
->param
.rc
.i_qp_constant
=
467 codec
->param
.rc
.i_qp_min
=
468 codec
->param
.rc
.i_qp_max
= *(int*)value
;
471 if(!strcasecmp(key
, "h264_fix_bitrate"))
472 codec
->param
.rc
.b_cbr
= (*(int*)value
) / 1000;
476 static quicktime_h264_codec_t
* init_common(quicktime_video_map_t
*vtrack
,
481 quicktime_codec_t
*codec_base
= (quicktime_codec_t
*)vtrack
->codec
;
482 quicktime_h264_codec_t
*codec
;
484 codec_base
->priv
= calloc(1, sizeof(quicktime_h264_codec_t
));
485 codec_base
->delete_vcodec
= delete_codec
;
486 codec_base
->decode_video
= decode
;
487 codec_base
->encode_video
= encode
;
488 codec_base
->flush
= flush
;
489 codec_base
->reads_colormodel
= reads_colormodel
;
490 codec_base
->writes_colormodel
= writes_colormodel
;
491 codec_base
->set_parameter
= set_parameter
;
492 codec_base
->fourcc
= compressor
;
493 codec_base
->title
= title
;
494 codec_base
->desc
= description
;
497 codec
= (quicktime_h264_codec_t
*)codec_base
->priv
;
498 x264_param_default(&codec
->param
);
505 void quicktime_init_codec_h264(quicktime_video_map_t
*vtrack
)
507 quicktime_h264_codec_t
*result
= init_common(vtrack
,
511 result
->total_fields
= 1;
516 void quicktime_init_codec_hv64(quicktime_video_map_t
*vtrack
)
518 quicktime_h264_codec_t
*result
= init_common(vtrack
,
521 "H.264 with two streams alternating every other frame. (Not standardized)");
522 result
->total_fields
= 2;