2 #include "gstvaapih264encoder.h"
11 #include "gst/gstclock.h"
12 #include "gst/gstvalue.h"
14 #include "gst/vaapi/gstvaapiobject.h"
15 #include "gst/vaapi/gstvaapiobject_priv.h"
16 #include "gst/vaapi/gstvaapicontext.h"
17 #include "gst/vaapi/gstvaapisurface.h"
18 #include "gst/vaapi/gstvaapivideobuffer.h"
19 #include "gst/vaapi/gstvaapidisplay_priv.h"
21 GST_DEBUG_CATEGORY_STATIC (gst_vaapi_h264_encoder_debug);
22 #define GST_CAT_DEFAULT gst_vaapi_h264_encoder_debug
24 #define SHARE_CODED_BUF 0
26 #define DEFAULT_SURFACE_NUMBER 3
27 #define DEFAULT_CODEDBUF_NUM 5
28 #define DEFAULT_SID_INPUT 0 // suface_ids[0]
30 #define REF_RECON_SURFACE_NUM 2
35 NAL_IDR = 5, /* ref_idc != 0 */
36 NAL_SEI = 6, /* ref_idc == 0 */
43 struct _GstH264EncodeBuffer {
46 GstH264EncoderPrivate *encoder;
49 struct _GstH264EncoderPrivate {
50 GstH264Encoder *public;
51 guint32 format; /*NV12, I420,*/
52 gboolean es_flag; /*elementary flag*/
55 GQueue *video_buffer_caches; /*not used for baseline*/
57 GstVaapiSurface *ref_surface; /* reference buffer*/
58 GstVaapiSurface *recon_surface; /* reconstruct buffer*/
60 VABufferID seq_parameter;
61 VABufferID pic_parameter;
62 VABufferID slice_parameter;
63 VAEncSliceParameterBuffer *slice_param_buffers;
64 guint32 default_slice_height;
65 guint32 slice_mod_mb_num;
72 G_DEFINE_TYPE(GstH264Encoder, gst_h264_encoder, GST_TYPE_VAAPI_BASE_ENCODER);
76 #define H264_BITSTREAM_ALLOC_ALIGN_MASK 0x0FFF
78 #define BIT_STREAM_BUFFER(stream) ((stream)->buffer)
79 #define BIT_STREAM_BIT_SIZE(stream) ((stream)->bit_size)
81 struct _H264Bitstream {
84 guint32 max_bit_capability;
87 typedef struct _H264Bitstream H264Bitstream;
89 static const guint8 h264_bit_mask[9] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
91 static EncoderStatus gst_h264_encoder_flush(GstVaapiEncoder* encoder, GstVaapiDisplay *display,
92 GstVaapiContext *context, GList **coded_pics);
95 static EncoderStatus gst_h264_encoder_get_avcC_codec_data(
96 GstVaapiEncoder* encoder, GstBuffer **buffer);
97 static EncoderStatus gst_h264_encoder_get_nal_codec_data(GstVaapiEncoder* encoder, GstBuffer **buffer);
99 static gboolean gst_h264_validate_parameters(GstVaapiBaseEncoder *encoder);
100 static void gst_h264_encoder_finalize(GObject *object);
101 static void gst_h264_encoder_init_public_values(GstH264Encoder* encoder);
103 static gboolean gst_h264_encoder_alloc_slices(GstVaapiBaseEncoder *encoder,
104 GstVaapiDisplay *display, GstVaapiContext *context);
105 static gboolean gst_h264_encoder_release_resource(GstVaapiBaseEncoder* encoder,
106 GstVaapiDisplay *display, GstVaapiContext *context);
108 static EncoderStatus gst_h264_prepare_encoding(GstVaapiBaseEncoder *encoder, GstVaapiDisplay *display,
109 GstVaapiContext *context, GstVaapiSurface *surface,
110 guint frame_index, VABufferID coded_buf, gboolean *is_key);
111 static void gst_h264_notify_frame(GstVaapiBaseEncoder *encoder, guint8 *buf, guint32 size);
112 //static EncoderStatus h264_encoder_read_sps_pps(
113 // GstH264EncoderPrivate *h264_prv, const guint8 *buf, guint32 size);
114 static GstBuffer *gst_h264_encoder_copy_coded_buffer(GstVaapiBaseEncoder *encoder,
115 guint8 *frame, guint32 frame_size, VABufferID *coded_buf);
117 /* h264 bitstream functions */
118 static void h264_bitstream_init(H264Bitstream *bitstream, guint32 bit_capability);
119 static gboolean h264_bitstream_write_uint(H264Bitstream *bitstream, guint32 value, guint32 bit_size);
120 static gboolean h264_bitstream_align(H264Bitstream *bitstream, guint32 value);
121 static gboolean h264_bitstream_write_ue(H264Bitstream *bitstream, guint32 value);
122 static gboolean h264_bitstream_write_se(H264Bitstream *bitstream, guint32 value);
123 static gboolean h264_bitstream_write_trailing_bits(H264Bitstream *bitstream);
125 static gboolean h264_bitstream_write_byte_array(H264Bitstream *bitstream, const guint8 *buf, guint32 byte_size);
126 static void h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag);
127 static gboolean h264_bitstream_auto_grow(H264Bitstream *bitstream, guint32 extra_bit_size);
128 static gboolean h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv);
129 static gboolean h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv);
130 static const guint8 *h264_next_nal(const guint8 *buffer, guint32 len, guint32 *nal_size);
131 static gboolean h264_read_sps_attributes(const guint8 *sps_data, guint32 sps_size,
132 guint32 *profile_idc, guint32 *profile_comp, guint32 *level_idc);
135 gst_h264_encoder_class_init(GstH264EncoderClass *klass)
137 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
138 GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
139 GstVaapiBaseEncoderClass * const base_class = GST_VAAPI_BASE_ENCODER_CLASS(klass);
141 g_type_class_add_private(klass, sizeof(GstH264EncoderPrivate));
143 GST_DEBUG_CATEGORY_INIT (gst_vaapi_h264_encoder_debug, "gst_va_h264_encoder", 0,
144 "gst_va_h264_encoder element");
146 object_class->finalize = gst_h264_encoder_finalize;
148 base_class->validate_attributes = gst_h264_validate_parameters;
149 base_class->pre_alloc_resource = gst_h264_encoder_alloc_slices;
150 base_class->release_resource = gst_h264_encoder_release_resource;
151 base_class->prepare_frame = gst_h264_prepare_encoding;
152 base_class->notify_frame = gst_h264_notify_frame;
153 base_class->copy_coded_frame = gst_h264_encoder_copy_coded_buffer;
155 encoder_class->flush = gst_h264_encoder_flush;
157 encoder_class->get_codec_data = gst_h264_encoder_get_avcC_codec_data;
158 /* encoder_class->get_codec_data = gst_h264_encoder_get_nal_codec_data; */
161 object_class->set_property = gst_h264_encoder_set_property;
162 object_class->get_property = gst_h264_encoder_get_property;
168 gst_h264_encode_buffer_class_init (gpointer g_class, gpointer class_data)
170 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS(g_class);
172 h264_encode_buffer_parent_class = g_type_class_peek_parent(g_class);
173 ENCODER_ASSERT(h264_encode_buffer_parent_class);
175 mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
176 gst_h264_encode_buffer_finalize;
181 gst_h264_encode_buffer_get_type (void)
183 static GType s_h264_encode_buffer_type = 0;
184 if (G_UNLIKELY (s_h264_encode_buffer_type == 0)) {
185 static const GTypeInfo s_h264_encode_buffer_info = {
186 sizeof(GstBufferClass),
189 gst_h264_encode_buffer_class_init,
192 sizeof(GstH264EncodeBuffer),
197 s_h264_encode_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
198 "GstH264EncodeBuffer", &s_h264_encode_buffer_info, 0);
200 return s_h264_encode_buffer_type;
204 gst_h264_encode_buffer_finalize (GstH264EncodeBuffer *h264_buffer)
206 GstH264EncoderPrivate *h264_prv = NULL;
207 VABufferID* coded_id = NULL;
208 GstVaapiDisplay *display = NULL;
210 gboolean is_locked = FALSE;
212 h264_prv = h264_buffer->encoder;
213 coded_id = h264_buffer->coded_id;
214 display = ENCODER_DISPLAY(h264_prv->public);
216 ENCODER_ASSERT(display);
217 VADisplay va_dpy = gst_vaapi_display_get_display(display);
219 ENCODER_ASSERT(h264_prv);
220 ENCODER_ASSERT(coded_id && VA_INVALID_ID!= *coded_id);
222 /*if (--(*h264_buffer->ref_coded_id) == 0) */
224 /*g_free(h264_buffer->ref_coded_id);*/
225 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
226 vaUnmapBuffer(va_dpy, *coded_id);
227 ENCODER_RELEASE_DISPLAY_LOCK(display);
228 push_available_coded_buffer(h264_prv, coded_id);
231 if (GST_MINI_OBJECT_CLASS(h264_encode_buffer_parent_class)->finalize) {
232 GST_MINI_OBJECT_CLASS(h264_encode_buffer_parent_class)->finalize(GST_MINI_OBJECT(h264_buffer));
236 static GstH264EncodeBuffer *
237 gst_h264_encode_buffer_new(GstH264EncoderPrivate *h264_prv,
238 VABufferID *coded_id)
240 GstH264EncodeBuffer *buf = (GstH264EncodeBuffer*)gst_mini_object_new(GST_TYPE_H264_ENCODE_BUFFER);
241 buf->coded_id = coded_id;
242 buf->encoder = h264_prv;
247 static GstVaapiSurface *
248 h264_get_video_surface(GstH264EncoderPrivate *h264_prv, GstVaapiVideoBuffer *video_buffer)
251 GstVaapiSurface *ret = gst_vaapi_video_buffer_get_surface(video_buffer);
253 ENCODER_CHECK_STATUS(ret, NULL, "video buffer doesn't have a surface");
255 g_queue_push_tail(h264_prv->video_buffer_caches,video_buffer);
256 gst_buffer_ref(GST_BUFFER(video_buffer));
265 h264_release_video_surface(GstH264EncoderPrivate *h264_prv, VASurfaceID surface)
268 ENCODER_ASSERT(h264_prv->video_buffer_caches);
269 g_queue_find_custom(h264_prv->video_buffer_caches,xx, compare_func);
270 for (h264_prv->video_buffer_caches) {
276 h264_get_va_profile(guint32 profile)
279 case H264_PROFILE_BASELINE:
280 return VAProfileH264Baseline;
282 case H264_PROFILE_MAIN:
283 return VAProfileH264Main;
285 case H264_PROFILE_HIGH:
286 return VAProfileH264High;
295 gst_h264_encoder_new(void)
297 return GST_H264_ENCODER(g_object_new(GST_TYPE_H264_ENCODER, NULL));
302 gst_h264_encoder_init(GstH264Encoder *encoder)
304 GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(encoder);
305 GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
306 ENCODER_ASSERT(h264_prv);
307 h264_prv->public = encoder;
309 /* init public attributes */
310 gst_h264_encoder_init_public_values(encoder);
311 gst_vaapi_base_encoder_set_frame_notify(GST_VAAPI_BASE_ENCODER(encoder), TRUE);
313 /* init private values*/
314 h264_prv->format = GST_MAKE_FOURCC('N','V','1','2');
315 h264_prv->es_flag = TRUE;
317 h264_prv->ref_surface = NULL;
318 h264_prv->recon_surface = NULL;
320 h264_prv->seq_parameter = VA_INVALID_ID;
321 h264_prv->pic_parameter = VA_INVALID_ID;
322 h264_prv->slice_parameter = VA_INVALID_ID;
323 h264_prv->slice_param_buffers = NULL;
324 h264_prv->default_slice_height = 0;
325 h264_prv->slice_mod_mb_num = 0;
327 h264_prv->sps_data = NULL;
328 h264_prv->pps_data = NULL;
332 gst_h264_encoder_finalize(GObject *object)
334 /*free private buffers*/
335 GstVaapiEncoder *encoder = GST_VAAPI_ENCODER(object);
336 GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(object);
338 if (gst_vaapi_encoder_get_state(encoder) != VAAPI_ENC_NULL) {
339 gst_vaapi_encoder_uninitialize(encoder);
342 if (h264_prv->sps_data) {
343 gst_buffer_unref(h264_prv->sps_data);
344 h264_prv->sps_data = NULL;
346 if (h264_prv->pps_data) {
347 gst_buffer_unref(h264_prv->pps_data);
348 h264_prv->pps_data = NULL;
350 if (h264_prv->slice_param_buffers) {
351 g_free(h264_prv->slice_param_buffers);
352 h264_prv->slice_param_buffers = NULL;
355 G_OBJECT_CLASS(gst_h264_encoder_parent_class)->finalize(object);
360 gst_h264_encoder_init_public_values(GstH264Encoder* encoder)
362 encoder->profile = 0;
364 encoder->bitrate = 0;
365 encoder->intra_period = 0;
366 encoder->init_qp = -1;
367 encoder->min_qp = -1;
368 encoder->slice_num = 0;
372 gst_h264_encoder_set_es_flag(GstH264Encoder* encoder, gboolean es)
374 GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(encoder);
375 h264_prv->es_flag = es;
380 gst_h264_validate_parameters(GstVaapiBaseEncoder *base_encoder)
382 GstH264Encoder *encoder = GST_H264_ENCODER(base_encoder);
383 GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(encoder);
384 if (!ENCODER_WIDTH(encoder) || !ENCODER_HEIGHT(encoder) || !ENCODER_FPS(encoder)) {
387 if (!encoder->profile) {
388 encoder->profile = H264_DEFAULT_PROFILE;
390 gst_vaapi_base_encoder_set_va_profile(base_encoder, h264_get_va_profile(encoder->profile));
391 if (!encoder->level) {
392 encoder->level = H264_DEFAULT_LEVEL;
394 if (!encoder->intra_period) {
395 encoder->intra_period = H264_DEFAULT_INTRA_PERIOD;
397 if (-1 == encoder->init_qp) {
398 encoder->init_qp = H264_DEFAULT_INIT_QP;
400 if (-1 == encoder->min_qp) {
401 encoder->min_qp = H264_DEFAULT_MIN_QP;
404 if (encoder->min_qp > encoder->init_qp) {
405 encoder->min_qp = encoder->init_qp;
408 /* default compress ratio 1: (4*8*1.5) */
409 if (!encoder->bitrate) {
410 encoder->bitrate = ENCODER_WIDTH(encoder)*ENCODER_HEIGHT(encoder)*ENCODER_FPS(encoder)/4;
413 if (!encoder->slice_num) {
414 encoder->slice_num = H264_DEFAULT_SLICE_NUM;
417 /* need calculate slice-num and each slice-height
418 suppose: ((encoder->height+15)/16) = 13, slice_num = 8
419 then: slice_1_height = 2
428 h264_prv->default_slice_height = (ENCODER_HEIGHT(encoder)+15)/16/encoder->slice_num;
429 if (0 == h264_prv->default_slice_height) { /* special value */
430 h264_prv->default_slice_height = 1;
431 h264_prv->slice_mod_mb_num = 0;
432 encoder->slice_num = (ENCODER_HEIGHT(encoder)+15)/16;
434 h264_prv->slice_mod_mb_num = ((ENCODER_HEIGHT(encoder)+15)/16)%encoder->slice_num;
441 h264_encoder_release_parameters(GstH264Encoder *h264_encoder, GstVaapiDisplay *display, GstVaapiContext *context)
443 VAStatus va_status = VA_STATUS_SUCCESS;
444 GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(h264_encoder);
447 gboolean is_locked = FALSE;
449 ENCODER_ASSERT(display);
450 ENCODER_ASSERT(context);
451 VADisplay va_dpy = gst_vaapi_display_get_display(display);
453 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
454 if (VA_INVALID_ID != h264_prv->seq_parameter) {
455 va_status = vaDestroyBuffer(va_dpy, h264_prv->seq_parameter);
456 h264_prv->seq_parameter = VA_INVALID_ID;
458 if (VA_INVALID_ID != h264_prv->pic_parameter) {
459 va_status = vaDestroyBuffer(va_dpy, h264_prv->pic_parameter);
460 h264_prv->pic_parameter = VA_INVALID_ID;
462 if (VA_INVALID_ID != h264_prv->slice_parameter) {
463 va_status = vaDestroyBuffer(va_dpy, h264_prv->slice_parameter);
464 h264_prv->slice_parameter = VA_INVALID_ID;
467 ENCODER_RELEASE_DISPLAY_LOCK(display);
469 if (h264_prv->slice_param_buffers) {
470 g_free(h264_prv->slice_param_buffers);
471 h264_prv->slice_param_buffers = NULL;
479 gst_h264_encoder_release_resource(GstVaapiBaseEncoder* encoder, GstVaapiDisplay *display, GstVaapiContext *context)
481 GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
483 GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(h264_encoder);
485 /* release buffers first */
486 h264_encoder_release_parameters(h264_encoder, display, context);
488 /*remove ref_surface*/
489 if (h264_prv->ref_surface) {
491 gst_vaapi_context_put_surface(context, h264_prv->ref_surface);
493 g_object_unref(h264_prv->ref_surface);
495 h264_prv->ref_surface = NULL;
498 /*remove recon_surface*/
499 if (h264_prv->recon_surface) {
501 gst_vaapi_context_put_surface(context, h264_prv->recon_surface);
503 g_object_unref(h264_prv->recon_surface);
505 h264_prv->recon_surface = NULL;
508 if (h264_prv->sps_data) {
509 gst_buffer_unref(h264_prv->sps_data);
510 h264_prv->sps_data = NULL;
512 if (h264_prv->pps_data) {
513 gst_buffer_unref(h264_prv->pps_data);
514 h264_prv->pps_data = NULL;
520 gst_h264_encoder_alloc_slices(GstVaapiBaseEncoder *encoder, GstVaapiDisplay *display, GstVaapiContext *context)
523 VAStatus va_status = VA_STATUS_SUCCESS;
524 GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
525 GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(encoder);
527 h264_prv->slice_param_buffers = (VAEncSliceParameterBuffer*)g_malloc0_n(h264_encoder->slice_num,
528 sizeof(h264_prv->slice_param_buffers[0]));
535 gst_h264_prepare_encoding(GstVaapiBaseEncoder *encoder, GstVaapiDisplay *display,
536 GstVaapiContext *context, GstVaapiSurface *surface,
537 guint frame_index, VABufferID coded_buf, gboolean *is_key)
539 EncoderStatus ret = ENCODER_NO_ERROR;
540 VAStatus va_status = VA_STATUS_SUCCESS;
541 GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
542 GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(h264_encoder);
544 VAEncPictureParameterBufferH264 pic_h264;
546 VAEncPictureParameterBufferH264Baseline pic_h264;
548 VAEncSliceParameterBuffer *slice_h264 = NULL;
550 gboolean is_locked = FALSE;
552 ENCODER_ASSERT(display && context);
553 VADisplay va_dpy = gst_vaapi_display_get_display(display);
554 VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
556 *is_key = ((frame_index % h264_encoder->intra_period) == 0);
559 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
560 /*handle first surface_index*/
561 /*only need first frame*/
562 if (VA_INVALID_ID == h264_prv->seq_parameter) { /*first time*/
564 VAEncSequenceParameterBufferH264 seq_h264 = {0};
566 VAEncSequenceParameterBufferH264Baseline seq_h264 = {0};
569 seq_h264.level_idc = h264_encoder->level; /* 3.0 */
570 seq_h264.max_num_ref_frames = 1; /*Only I, P frames*/
571 seq_h264.picture_width_in_mbs = (ENCODER_WIDTH(h264_encoder)+15)/16;
572 seq_h264.picture_height_in_mbs = (ENCODER_HEIGHT(h264_encoder)+15)/16;
574 seq_h264.bits_per_second = h264_encoder->bitrate;
575 seq_h264.frame_rate = ENCODER_FPS(h264_encoder);
576 seq_h264.initial_qp = h264_encoder->init_qp; /*qp_value; 15, 24, 26?*/
577 seq_h264.min_qp = h264_encoder->min_qp; /*1, 6, 10*/
578 seq_h264.basic_unit_size = 0;
579 seq_h264.intra_period = h264_encoder->intra_period;
580 seq_h264.intra_idr_period = h264_encoder->intra_period;
582 va_status = vaCreateBuffer(va_dpy, context_id,
583 VAEncSequenceParameterBufferType,
584 sizeof(seq_h264), 1, &seq_h264, &h264_prv->seq_parameter);
585 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_ENC_RES_ERR, "alloc seq-buffer failed.\n");
586 va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->seq_parameter, 1);
587 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaRenderPicture seq-parameters failed.\n");
590 /* set pic_parameters*/
591 if (!h264_prv->ref_surface) {
592 h264_prv->ref_surface = gst_vaapi_context_get_surface(context);
593 ENCODER_CHECK_STATUS(h264_prv->ref_surface, ENCODER_SURFACE_ERR, "reference surface, h264_pop_free_surface failed.\n");
595 if (!h264_prv->recon_surface) {
596 h264_prv->recon_surface = gst_vaapi_context_get_surface(context);
597 ENCODER_CHECK_STATUS(h264_prv->recon_surface, ENCODER_SURFACE_ERR, "reconstructed surface, h264_pop_free_surface failed.\n");
600 pic_h264.reference_picture = GST_VAAPI_OBJECT_ID(h264_prv->ref_surface);
601 pic_h264.reconstructed_picture = GST_VAAPI_OBJECT_ID(h264_prv->recon_surface);
602 pic_h264.coded_buf = coded_buf;
603 pic_h264.picture_width = ENCODER_WIDTH(h264_encoder);
604 pic_h264.picture_height = ENCODER_HEIGHT(h264_encoder);
605 pic_h264.last_picture = 0; // last pic or not
607 if (VA_INVALID_ID != h264_prv->pic_parameter) { /* share the same pic_parameter*/
608 vaDestroyBuffer(va_dpy, h264_prv->pic_parameter);
609 h264_prv->pic_parameter = VA_INVALID_ID;
611 va_status = vaCreateBuffer(va_dpy, context_id, VAEncPictureParameterBufferType,
612 sizeof(pic_h264), 1, &pic_h264, &h264_prv->pic_parameter);
614 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "creating pic-param buffer failed.\n");
616 va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->pic_parameter, 1);
617 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "rendering pic-param buffer failed.\n");
619 /* set slice parameters, support multiple slices */
621 guint32 last_row_num = 0;
622 guint32 slice_mod_num = h264_prv->slice_mod_mb_num;
624 memset(h264_prv->slice_param_buffers, 0, h264_encoder->slice_num*sizeof(h264_prv->slice_param_buffers[0]));
625 for (i = 0; i < h264_encoder->slice_num; ++i) {
626 slice_h264 = &h264_prv->slice_param_buffers[i];
627 slice_h264->start_row_number = last_row_num; /* unit MB*/
628 slice_h264->slice_height = h264_prv->default_slice_height; /* unit MB */
630 ++slice_h264->slice_height;
633 last_row_num += slice_h264->slice_height;
634 slice_h264->slice_flags.bits.is_intra = *is_key;
635 slice_h264->slice_flags.bits.disable_deblocking_filter_idc = 0;
638 ENCODER_ASSERT(last_row_num == (ENCODER_HEIGHT(h264_encoder)+15)/16);
640 if (VA_INVALID_ID != h264_prv->slice_parameter) {
641 vaDestroyBuffer(va_dpy, h264_prv->slice_parameter);
642 h264_prv->slice_parameter = VA_INVALID_ID;
644 va_status = vaCreateBuffer(va_dpy,
646 VAEncSliceParameterBufferType,
647 sizeof(h264_prv->slice_param_buffers[0]),
648 h264_encoder->slice_num,
649 h264_prv->slice_param_buffers,
650 &h264_prv->slice_parameter);
651 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "creating slice-parameters buffer failed.\n");
653 va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->slice_parameter, 1);
654 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "rendering slice-parameters buffer failed.\n");
656 /*after finished, set ref_surface_index, recon_surface_index */
657 GstVaapiSurface *swap = h264_prv->ref_surface;
658 h264_prv->ref_surface = h264_prv->recon_surface;
659 h264_prv->recon_surface = swap;
662 ENCODER_RELEASE_DISPLAY_LOCK(display);
668 gst_h264_encoder_copy_coded_buffer(GstVaapiBaseEncoder *encoder,
671 VABufferID *coded_buf)
673 GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(encoder);
674 GstBuffer *ret_buffer;
676 const guint8 *nal_start;
679 ret_buffer = gst_buffer_new();
680 ENCODER_ASSERT(ret_buffer);
681 H264Bitstream bitstream;
682 h264_bitstream_init(&bitstream, (frame_size+32)*8);
683 h264_bitstream_align(&bitstream, 0);
684 ENCODER_ASSERT(bitstream.bit_size == 0);
686 if (!h264_prv->es_flag) { /*nal format*/
687 h264_bitstream_write_byte_array(&bitstream, frame, frame_size);
688 ENCODER_ASSERT(bitstream.bit_size == frame_size*8);
689 } else { /* elementary format */
690 frame_end = frame + frame_size;
693 while((nal_start = h264_next_nal(nal_start, frame_end-nal_start, &nal_size)) != NULL) {
694 ENCODER_ASSERT(nal_size);
696 nal_start += nal_size;
699 h264_bitstream_write_uint(&bitstream, nal_size, 32);
700 h264_bitstream_write_byte_array(&bitstream, nal_start, nal_size);
701 nal_start += nal_size;
704 h264_bitstream_align(&bitstream, 0);
706 GST_BUFFER_MALLOCDATA(ret_buffer) =
707 GST_BUFFER_DATA(ret_buffer) = BIT_STREAM_BUFFER(&bitstream);
708 GST_BUFFER_SIZE(ret_buffer) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
709 h264_bitstream_destroy(&bitstream, FALSE);
715 h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const guint8 *buf, guint32 size)
717 const guint8 *end = buf + size;
718 const guint8 *nal_start = buf;
719 guint32 nal_size = 0;
721 GstBuffer *sps = NULL, *pps = NULL;
723 while((!sps || !pps) && (nal_start = h264_next_nal(nal_start, end-nal_start, &nal_size)) != NULL) {
725 nal_start += nal_size;
729 nal_type = (*nal_start)&0x1F;
732 sps = gst_buffer_new_and_alloc(nal_size);
733 memcpy(GST_BUFFER_DATA(sps), nal_start, nal_size);
734 gst_buffer_replace(&h264_prv->sps_data, sps);
735 gst_buffer_unref(sps); /*don't set to NULL*/
740 pps = gst_buffer_new_and_alloc(nal_size);
741 memcpy(GST_BUFFER_DATA(pps), nal_start, nal_size);
742 gst_buffer_replace(&h264_prv->pps_data, pps);
743 gst_buffer_unref(pps);
750 nal_start += nal_size;
754 return ENCODER_DATA_NOT_READY;
756 return ENCODER_NO_ERROR;
760 gst_h264_notify_frame(GstVaapiBaseEncoder *encoder, guint8 *buf, guint32 size)
762 GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(encoder);
763 if (!h264_prv->sps_data || !h264_prv->pps_data) {
764 h264_encoder_read_sps_pps(h264_prv, buf, size);
766 if (h264_prv->sps_data && h264_prv->pps_data) {
767 gst_vaapi_base_encoder_set_frame_notify(GST_VAAPI_BASE_ENCODER(encoder), FALSE);
773 h264_read_sps_attributes(const guint8 *sps_data, guint32 sps_size,
774 guint32 *profile_idc, guint32 *profile_comp, guint32 *level_idc)
776 ENCODER_ASSERT(profile_idc && profile_comp && level_idc);
777 ENCODER_ASSERT(sps_size >= 4);
781 /*skip sps_data[0], nal_type*/
782 *profile_idc = sps_data[1];
783 *profile_comp = sps_data[2];
784 *level_idc = sps_data[3];
790 gst_h264_encoder_flush(GstVaapiEncoder* encoder, GstVaapiDisplay *display,
791 GstVaapiContext *context, GList **coded_pics)
793 GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
794 EncoderStatus ret = ENCODER_NO_ERROR;
795 GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(h264_encoder);
797 //h264_prv->frame_count = 0;
798 //gst_vaapi_base_encoder_set_frame_notify((GST_VAAPI_BASE_ENCODER)encoder, TRUE);
805 static int draw_picture(int width, int height,
806 unsigned char *Y_start,
807 unsigned char *U_start,
808 unsigned char *V_start,
809 int UV_interleave, int box_width, int row_shift);
811 int main_test(int argc, char* argv[])
813 EncoderStatus ret = ENCODER_NO_ERROR;
814 GstVaapiEncoder *encoder = NULL;
816 GList *coded_pics = NULL;
817 GstBuffer **raw_buffer = NULL;
818 const guint32 raw_buffer_num = 20;
820 GstBuffer *tmp_buffer;
822 guint32 i = 0, k = 0;
824 gst_init (&argc, &argv);
827 if (!g_thread_supported ())
828 g_thread_init (NULL);
830 GstH264Encoder *h264_encoder = gst_h264_encoder_new();
831 encoder = GST_VAAPI_ENCODER(h264_encoder);
832 ENCODER_ASSERT(encoder);
834 h264_encoder->profile = 64;
835 h264_encoder->level = 30;
836 encoder->width = 1280;
837 encoder->height = 720;
838 encoder->frame_rate = 10;
839 h264_encoder->bitrate = 512*1000;
840 h264_encoder->intra_period = 30;
841 ret = gst_vaapi_encoder_initialize(encoder);
842 ENCODER_ASSERT(ret == ENCODER_NO_ERROR);
843 ret = gst_vaapi_encoder_open(encoder, NULL);
844 ENCODER_ASSERT(ret == ENCODER_NO_ERROR);
846 guint32 buffer_size = encoder->width * encoder->width *3 /2;
847 guint32 y_width = encoder->width, y_size = encoder->width * encoder->height;
848 guint32 u_width = encoder->width/2, u_size = (encoder->width/2) * (encoder->height/2);
849 guint32 v_width = encoder->width/2;
850 guint8 *y_src, *u_src, *v_src;
855 raw_buffer = (GstBuffer**)g_malloc0(raw_buffer_num*sizeof(GstBuffer*));
856 for (i = 0; i < raw_buffer_num; i++) {
857 raw_buffer[i] = gst_buffer_new_and_alloc(buffer_size);
858 y_src = GST_BUFFER_DATA(raw_buffer[i]);
859 u_src = y_src + y_size;
860 v_src = u_src + u_size;
862 draw_picture(encoder->width, encoder->height, y_src, u_src, v_src, 0, box_width, row_shift);
864 if (row_shift==(2*box_width)) row_shift= 0;
867 FILE *fp = fopen("tmp.h264", "wb");
872 for (i = 0; i < 50; i++) {
874 ret = gst_vaapi_encoder_encode(encoder, raw_buffer[k], &coded_pics);
875 ENCODER_ASSERT(ENCODER_NO_ERROR == ret);
877 if (k >= raw_buffer_num) k = 0;
880 tmp_buffer = coded_pics->data;
881 coded_pics = g_list_remove(coded_pics, tmp_buffer);
882 fwrite(GST_BUFFER_DATA(tmp_buffer), GST_BUFFER_SIZE(tmp_buffer), 1, fp);
883 printf("F:%d, S:%d, %s\n", i, GST_BUFFER_SIZE(tmp_buffer), vaapi_encoder_dump_bytes(GST_BUFFER_DATA(tmp_buffer)+4, 8));
884 gst_buffer_unref(tmp_buffer);
889 ret = gst_vaapi_encoder_close(encoder);
890 ENCODER_ASSERT(ENCODER_NO_ERROR == ret);
892 for (i = 0; i < raw_buffer_num; i++) {
893 gst_buffer_unref(raw_buffer[i]);
896 gst_vaapi_encoder_unref(encoder);
902 gst_h264_encoder_get_avcC_codec_data(GstVaapiEncoder *encoder, GstBuffer **buffer)
904 GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
905 GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(h264_encoder);
906 GstBuffer *avc_codec;
907 const guint32 configuration_version = 0x01;
908 const guint32 length_size_minus_one = 0x03;
909 guint32 profile, profile_comp, level_idc;
911 ENCODER_ASSERT(buffer);
912 if (!h264_prv->sps_data || !h264_prv->pps_data) {
913 return ENCODER_DATA_NOT_READY;
916 if (FALSE == h264_read_sps_attributes(GST_BUFFER_DATA(h264_prv->sps_data),
917 GST_BUFFER_SIZE(h264_prv->sps_data),
918 &profile, &profile_comp, &level_idc))
921 return ENCODER_DATA_ERR;
924 H264Bitstream bitstream;
925 h264_bitstream_init(&bitstream,
926 (GST_BUFFER_SIZE(h264_prv->sps_data)+GST_BUFFER_SIZE(h264_prv->pps_data) + 32)*8);
929 h264_bitstream_write_uint(&bitstream, configuration_version, 8);
930 h264_bitstream_write_uint(&bitstream, profile, 8);
931 h264_bitstream_write_uint(&bitstream, profile_comp, 8);
932 h264_bitstream_write_uint(&bitstream, level_idc, 8);
933 h264_bitstream_write_uint(&bitstream, h264_bit_mask[6], 6); /*111111*/
934 h264_bitstream_write_uint(&bitstream, length_size_minus_one, 2);
935 h264_bitstream_write_uint(&bitstream, h264_bit_mask[3], 3); /*111*/
938 h264_bitstream_write_uint(&bitstream, 1, 5); /* sps count = 1*/
939 ENCODER_ASSERT( BIT_STREAM_BIT_SIZE(&bitstream)%8 == 0);
940 h264_bitstream_write_uint(&bitstream, GST_BUFFER_SIZE(h264_prv->sps_data), 16);
941 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->sps_data),
942 GST_BUFFER_SIZE(h264_prv->sps_data));
945 h264_bitstream_write_uint(&bitstream, 1, 8); /*pps count = 1*/
946 h264_bitstream_write_uint(&bitstream, GST_BUFFER_SIZE(h264_prv->pps_data), 16);
947 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->pps_data),
948 GST_BUFFER_SIZE(h264_prv->pps_data));
950 avc_codec = gst_buffer_new();
951 GST_BUFFER_MALLOCDATA(avc_codec) =
952 GST_BUFFER_DATA(avc_codec) =
953 BIT_STREAM_BUFFER(&bitstream);
954 GST_BUFFER_SIZE(avc_codec) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
955 h264_bitstream_destroy(&bitstream, FALSE);
958 return ENCODER_NO_ERROR;
962 gst_h264_encoder_get_nal_codec_data(GstVaapiEncoder *encoder, GstBuffer **buffer)
964 GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
965 GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(h264_encoder);
966 GstBuffer *nal_sps_pps;
968 ENCODER_ASSERT(buffer);
969 if (!h264_prv->sps_data || !h264_prv->pps_data) {
970 return ENCODER_DATA_NOT_READY;
973 H264Bitstream bitstream;
974 h264_bitstream_init(&bitstream,
975 (GST_BUFFER_SIZE(h264_prv->sps_data)+GST_BUFFER_SIZE(h264_prv->pps_data) + 8)*8);
977 /*0x000001 start code*/
978 h264_bitstream_write_uint(&bitstream, 0x000001, 24);
979 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->sps_data),
980 GST_BUFFER_SIZE(h264_prv->sps_data));
981 h264_bitstream_write_uint(&bitstream, 0x000001, 24);
982 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->pps_data),
983 GST_BUFFER_SIZE(h264_prv->pps_data));
985 nal_sps_pps = gst_buffer_new();
986 GST_BUFFER_MALLOCDATA(nal_sps_pps) =
987 GST_BUFFER_DATA(nal_sps_pps) =
988 BIT_STREAM_BUFFER(&bitstream);
989 GST_BUFFER_SIZE(nal_sps_pps) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
990 h264_bitstream_destroy(&bitstream, FALSE);
991 *buffer = nal_sps_pps;
992 return ENCODER_NO_ERROR;
996 h264_bitstream_init(H264Bitstream *bitstream, guint32 bit_capability)
998 bitstream->bit_size = 0;
999 bitstream->buffer = NULL;
1000 bitstream->max_bit_capability = 0;
1001 if (bit_capability) {
1002 h264_bitstream_auto_grow(bitstream, bit_capability);
1007 h264_bitstream_write_uint(H264Bitstream *bitstream, guint32 value, guint32 bit_size)
1009 gboolean ret = TRUE;
1010 guint32 byte_pos, bit_offset;
1018 ENCODER_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, bit_size), FALSE, "h264_bitstream_auto_grow failed.\n");
1019 byte_pos = (bitstream->bit_size>>3);
1020 bit_offset = (bitstream->bit_size&0x07);
1021 cur_byte = bitstream->buffer + byte_pos;
1022 ENCODER_ASSERT(bit_offset < 8 && bitstream->bit_size <= bitstream->max_bit_capability);
1025 fill_bits = ((8-bit_offset) < bit_size ? (8-bit_offset) : bit_size);
1026 bit_size -= fill_bits;
1027 bitstream->bit_size += fill_bits;
1029 *cur_byte |= ((value>>bit_size) & h264_bit_mask[fill_bits])<<(8-bit_offset-fill_bits);
1033 ENCODER_ASSERT(cur_byte <= bitstream->buffer + bitstream->max_bit_capability/8);
1040 static gboolean h264_bitstream_align(H264Bitstream *bitstream, guint32 value)
1042 guint32 bit_offset, bit_left;
1044 bit_offset = (bitstream->bit_size&0x07);
1048 bit_left = 8 - bit_offset;
1049 if (value) value = h264_bit_mask[bit_left];
1050 return h264_bitstream_write_uint(bitstream, value, bit_left);
1055 h264_bitstream_write_byte_array(H264Bitstream *bitstream, const guint8 *buf, guint32 byte_size)
1057 gboolean ret = TRUE;
1061 ENCODER_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, byte_size<<3), FALSE, "h264_bitstream_auto_grow failed.\n");
1062 if (0 == (bitstream->bit_size&0x07)) {
1063 memcpy(&bitstream->buffer[bitstream->bit_size>>3], buf, byte_size);
1064 bitstream->bit_size += (byte_size<<3);
1068 h264_bitstream_write_uint(bitstream, *buf, 8);
1080 h264_bitstream_write_ue(H264Bitstream *bitstream, guint32 value)
1082 gboolean ret = TRUE;
1083 guint32 size_in_bits = 0;
1084 guint32 tmp_value = ++value;
1089 ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, 0, size_in_bits-1), FALSE, "h264_bitstream_write_ue failed.\n");
1090 ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, value, size_in_bits), FALSE, "h264_bitstream_write_ue failed.\n");
1098 h264_bitstream_write_se(H264Bitstream *bitstream, guint32 value)
1100 gboolean ret = TRUE;
1104 new_val = -(value<<1);
1106 new_val = (value<<1) - 1;
1109 ENCODER_CHECK_STATUS(h264_bitstream_write_ue(bitstream, new_val), FALSE, "h264_bitstream_write_se failed.\n");
1117 h264_bitstream_write_trailing_bits(H264Bitstream *bitstream)
1119 h264_bitstream_write_uint(bitstream, 1, 1);
1120 h264_bitstream_align(bitstream, 0);
1125 h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag)
1127 if (bitstream->buffer && free_flag) {
1128 free (bitstream->buffer);
1130 bitstream->buffer = NULL;
1131 bitstream->bit_size = 0;
1132 bitstream->max_bit_capability = 0;
1136 h264_bitstream_auto_grow(H264Bitstream *bitstream, guint32 extra_bit_size)
1138 guint32 new_bit_size = extra_bit_size + bitstream->bit_size;
1141 ENCODER_ASSERT(bitstream->bit_size <= bitstream->max_bit_capability);
1142 if (new_bit_size <= bitstream->max_bit_capability) {
1146 new_bit_size = ((new_bit_size + H264_BITSTREAM_ALLOC_ALIGN_MASK)
1147 &(~H264_BITSTREAM_ALLOC_ALIGN_MASK));
1148 ENCODER_ASSERT(new_bit_size%(H264_BITSTREAM_ALLOC_ALIGN_MASK+1) == 0);
1149 clear_pos = ((bitstream->bit_size+7)>>3);
1150 bitstream->buffer = realloc(bitstream->buffer, new_bit_size>>3);
1151 memset(bitstream->buffer+clear_pos, 0, (new_bit_size>>3)-clear_pos);
1152 bitstream->max_bit_capability = new_bit_size;
1157 h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv)
1159 guint32 constraint_set0_flag, constraint_set1_flag, constraint_set2_flag, constraint_set3_flag;
1160 guint32 seq_parameter_set_id = 0;
1162 /*need to set the values*/
1163 guint32 log2_max_frame_num_minus4 = 0; // 1? 3?
1164 guint32 pic_order_cnt_type = 0; // Must be 0
1165 guint32 log2_max_pic_order_cnt_lsb_minus4 = 0; // 2 ? 4?
1166 guint32 num_ref_frames = 1; // only P frames
1167 guint32 gaps_in_frame_num_value_allowed_flag = 0; // ??
1168 guint32 mb_width = (ENCODER_WIDTH(h264_prv->public)+15)/16; // mb_width
1169 guint32 mb_height = (ENCODER_HEIGHT(h264_prv->public)+15)/16; // mb_height
1170 guint32 frame_mbs_only_flag = 1; // only mbs
1171 guint32 frame_cropping_flag = 0;
1172 guint32 frame_crop_bottom_offset = 0;
1173 guint32 vui_present_flag = 0; // no vui flags
1176 constraint_set0_flag = h264_prv->public->profile == H264_PROFILE_BASELINE;
1177 constraint_set1_flag = h264_prv->public->profile <= H264_PROFILE_MAIN;
1178 constraint_set2_flag = 0;
1179 constraint_set3_flag = 0;
1181 if (mb_height * 16 - ENCODER_HEIGHT(h264_prv->public)) {
1182 frame_cropping_flag = 1;
1183 frame_crop_bottom_offset =
1184 (mb_height * 16 - ENCODER_HEIGHT(h264_prv->public)) / (2 * (!frame_mbs_only_flag + 1));
1187 h264_bitstream_write_uint(bitstream, h264_prv->public->profile, 8); /* profile_idc */
1188 h264_bitstream_write_uint(bitstream, constraint_set0_flag, 1); /* constraint_set0_flag */
1189 h264_bitstream_write_uint(bitstream, constraint_set1_flag, 1); /* constraint_set1_flag */
1190 h264_bitstream_write_uint(bitstream, constraint_set2_flag, 1); /* constraint_set2_flag */
1191 h264_bitstream_write_uint(bitstream, constraint_set3_flag, 1); /* constraint_set3_flag */
1192 h264_bitstream_write_uint(bitstream, 0, 4); /* reserved_zero_4bits */
1193 h264_bitstream_write_uint(bitstream, h264_prv->public->level, 8); /* level_idc */
1194 h264_bitstream_write_ue(bitstream, seq_parameter_set_id); /* seq_parameter_set_id */
1196 if (h264_prv->public->profile >= H264_PROFILE_HIGH) {
1197 /* FIXME: fix for high profile */
1201 h264_bitstream_write_ue(bitstream, log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
1202 h264_bitstream_write_ue(bitstream, pic_order_cnt_type); /* pic_order_cnt_type */
1204 if (pic_order_cnt_type == 0)
1205 h264_bitstream_write_ue(bitstream, log2_max_pic_order_cnt_lsb_minus4);/* log2_max_pic_order_cnt_lsb_minus4 */
1210 h264_bitstream_write_ue(bitstream, num_ref_frames); /* num_ref_frames */
1211 h264_bitstream_write_uint(bitstream, gaps_in_frame_num_value_allowed_flag, 1); /* gaps_in_frame_num_value_allowed_flag */
1213 h264_bitstream_write_ue(bitstream, mb_width - 1); /* pic_width_in_mbs_minus1 */
1214 h264_bitstream_write_ue(bitstream, mb_height - 1); /* pic_height_in_map_units_minus1 */
1215 h264_bitstream_write_uint(bitstream, frame_mbs_only_flag, 1); /* frame_mbs_only_flag */
1217 if (!frame_mbs_only_flag) { //ONLY mbs
1221 h264_bitstream_write_uint(bitstream, 0, 1); /* direct_8x8_inference_flag */
1222 h264_bitstream_write_uint(bitstream, frame_cropping_flag, 1); /* frame_cropping_flag */
1224 if (frame_cropping_flag) {
1225 h264_bitstream_write_ue(bitstream, 0); /* frame_crop_left_offset */
1226 h264_bitstream_write_ue(bitstream, 0); /* frame_crop_right_offset */
1227 h264_bitstream_write_ue(bitstream, 0); /* frame_crop_top_offset */
1228 h264_bitstream_write_ue(bitstream, frame_crop_bottom_offset); /* frame_crop_bottom_offset */
1231 h264_bitstream_write_uint(bitstream, vui_present_flag, 1); /* vui_parameters_present_flag */
1232 h264_bitstream_write_trailing_bits(bitstream); /* rbsp_trailing_bits */
1240 static const guint8 *
1241 h264_next_nal(const guint8 *buffer, guint32 len, guint32 *nal_size)
1243 const guint8 *cur = buffer;
1244 const guint8 *end = buffer + len;
1245 const guint8 *nal_start = NULL;
1246 guint32 flag = 0xFFFFFFFF;
1247 guint32 nal_start_len = 0;
1249 ENCODER_ASSERT(len >= 0 && buffer && nal_size);
1252 nal_start = (len ? buffer : NULL);
1256 /*locate head postion*/
1257 if (!buffer[0] && !buffer[1]) {
1258 if (buffer[2] == 1) { // 0x000001
1260 } else if (!buffer[2] && len >=4 && buffer[3] == 1) { //0x00000001
1264 nal_start = buffer + nal_start_len;
1267 /*find next nal start position*/
1269 flag = ((flag<<8) | ((*cur++)&0xFF));
1270 if (flag == 0x00000001) {
1271 *nal_size = cur - 4 - nal_start;
1273 } else if ((flag&0x00FFFFFF) == 0x00000001) {
1274 *nal_size = cur - 3 - nal_start;
1279 *nal_size = end - nal_start;
1280 if (nal_start >= end) {
1289 h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv)
1295 static int draw_picture(int width, int height,
1296 unsigned char *Y_start,
1297 unsigned char *U_start,
1298 unsigned char *V_start,
1299 int UV_interleave, int box_width, int row_shift)
1303 int Y_pitch = width;
1304 int U_pitch = width/2;
1305 int V_pitch = width/2;
1308 for (row=0;row<height;row++) {
1309 unsigned char *Y_row = Y_start + row * Y_pitch;
1312 ypos = (row / box_width) & 0x1;
1314 /* fill garbage data into the other field */
1315 if (((field == 1) && (row &1))
1316 || ((field == 2) && ((row &1)==0))) {
1317 memset(Y_row, 0xff, width);
1321 for (jj=0; jj<width; jj++) {
1322 xpos = ((row_shift + jj) / box_width) & 0x1;
1324 if ((xpos == 0) && (ypos == 0))
1326 if ((xpos == 1) && (ypos == 1))
1329 if ((xpos == 1) && (ypos == 0))
1331 if ((xpos == 0) && (ypos == 1))
1337 for( row =0; row < height/2; row++) {
1338 unsigned short value = 0x80;
1340 /* fill garbage data into the other field */
1341 if (((field == 1) && (row &1))
1342 || ((field == 2) && ((row &1)==0))) {
1346 if (UV_interleave) {
1347 unsigned short *UV_row = (unsigned short *)(U_start + row * U_pitch);
1349 memset(UV_row, value, width);
1351 unsigned char *U_row = U_start + row * U_pitch;
1352 unsigned char *V_row = V_start + row * V_pitch;
1354 memset (U_row,value,width/2);
1355 memset (V_row,value,width/2);