2 #include "h264encoder.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 #define ENCPRV(encoder) GST_H264_ENCODER_GET_PRIVATE(encoder)
23 #define SHARE_CODED_BUF 0
25 #define DEFAULT_SURFACE_NUMBER 3
26 #define DEFAULT_CODEDBUF_NUM 5
27 #define DEFAULT_SID_INPUT 0 // suface_ids[0]
29 #define REF_RECON_SURFACE_NUM 2
31 typedef struct _GstH264EncodeBuffer GstH264EncodeBuffer;
33 #define GST_TYPE_H264_ENCODE_BUFFER (gst_h264_encode_buffer_get_type())
38 NAL_IDR = 5, /* ref_idc != 0 */
39 NAL_SEI = 6, /* ref_idc == 0 */
46 struct _GstH264EncodeBuffer {
49 GstH264EncoderPrivate *encoder;
52 struct _GstH264EncoderPrivate {
53 GstH264Encoder *public;
54 uint32_t format; /*NV12, I420,*/
55 gboolean es_flag; /*elementary flag*/
58 //GstVaapiDisplay *vaapi_display;
59 GstVaapiContext *vaapi_context;
60 GQueue *video_buffer_caches; /*not used for baseline*/
62 GstVaapiSurface *ref_surface; /* reference buffer*/
63 GstVaapiSurface *recon_surface; /* reconstruct buffer*/
65 //VAAPI_Encode_State encode_state;
67 VABufferID seq_parameter;
68 VABufferID pic_parameter;
69 VABufferID slice_parameter;
70 VAEncSliceParameterBuffer *slice_param_buffers;
71 uint32_t default_slice_height;
72 uint32_t slice_mod_mb_num;
74 VABufferID *coded_bufs;
75 uint32_t coded_buf_num;
76 uint32_t cur_coded_index;
78 /*total encoded frames*/
84 GMutex *code_buffer_lock;
85 GCond *code_buffer_cond;
86 GQueue *available_code_buffers;
90 G_DEFINE_TYPE(GstH264Encoder, gst_h264_encoder, GST_TYPE_VAAPI_ENCODER);
94 #define H264_BITSTREAM_ALLOC_ALIGN_MASK 0x0FFF
96 #define BIT_STREAM_BUFFER(stream) ((stream)->buffer)
97 #define BIT_STREAM_BIT_SIZE(stream) ((stream)->bit_size)
99 struct _H264Bitstream {
102 uint32_t max_bit_capability;
105 typedef struct _H264Bitstream H264Bitstream;
107 static const uint8_t h264_bit_mask[9] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
109 static GstBufferClass *h264_encode_buffer_parent_class = NULL;
112 static EncoderStatus gst_h264_encoder_initialize(GstVaapiEncoder* encoder);
113 static EncoderStatus gst_h264_encoder_uninitialize(GstVaapiEncoder* encoder);
114 static EncoderStatus gst_h264_encoder_open(GstVaapiEncoder* encoder, void* private_data);
115 static EncoderStatus gst_h264_encoder_close(GstVaapiEncoder* encoder);
116 static EncoderStatus gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstBuffer *raw_pic, GList **coded_pics);
117 static EncoderStatus gst_h264_encoder_flush(GstVaapiEncoder* encoder, GList **coded_pics);
119 static gboolean gst_h264_validate_parameters(GstH264Encoder *encoder);
120 static void gst_h264_encoder_finalize(GObject *object);
121 static void gst_h264_encoder_init_public_values(GstH264Encoder* encoder);
123 static VAProfile h264_get_va_profile(uint32_t profile);
124 static EncoderStatus h264_encoder_alloc_buffers(GstH264EncoderPrivate *h264_prv);
125 static EncoderStatus h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv);
126 static EncoderStatus h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
128 GstVaapiSurface *surface);
130 static EncoderStatus h264_prepare_encoding(GstH264EncoderPrivate *h264_prv,
131 GstBuffer *raw_pic, gboolean is_key,
132 VABufferID coded_buf);
133 static EncoderStatus h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
134 VASurfaceID surface_id,
136 GstClockTime timestamp,
137 GstClockTime duration,
138 VABufferID *coded_buf,
141 h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const uint8_t *buf, uint32_t size);
142 static GstBuffer *h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
145 VABufferID *coded_buf);
148 /*encoded buffer, for SHARE_CODED_BUF */
149 static void gst_h264_encode_buffer_class_init (gpointer g_class, gpointer class_data);
150 static GType gst_h264_encode_buffer_get_type (void);
151 static void gst_h264_encode_buffer_finalize (GstH264EncodeBuffer *h264_buffer);
152 static GstH264EncodeBuffer *gst_h264_encode_buffer_new(GstH264EncoderPrivate *h264_prv,
153 VABufferID *coded_id);
155 /* h264 bitstream functions */
156 static void h264_bitstream_init(H264Bitstream *bitstream, uint32_t bit_capability);
157 static gboolean h264_bitstream_write_uint(H264Bitstream *bitstream, uint32_t value, uint32_t bit_size);
158 static gboolean h264_bitstream_align(H264Bitstream *bitstream, uint32_t value);
159 static gboolean h264_bitstream_write_ue(H264Bitstream *bitstream, uint32_t value);
160 static gboolean h264_bitstream_write_se(H264Bitstream *bitstream, int32_t value);
161 static gboolean h264_bitstream_write_trailing_bits(H264Bitstream *bitstream);
163 static gboolean h264_bitstream_write_byte_array(H264Bitstream *bitstream, const uint8_t *buf, uint32_t byte_size);
164 static void h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag);
165 static gboolean h264_bitstream_auto_grow(H264Bitstream *bitstream, uint32_t extra_bit_size);
166 static gboolean h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv);
167 static gboolean h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv);
168 static const uint8_t *h264_next_nal(const uint8_t *buffer, uint32_t len, uint32_t *nal_size);
169 static gboolean h264_read_sps_attributes(const uint8_t *sps_data, uint32_t sps_size,
170 uint32_t *profile_idc, uint32_t *profile_comp, uint32_t *level_idc);
173 static EncoderStatus gst_h264_encoder_get_avcC_codec_data(GstVaapiEncoder* encoder, GstBuffer **buffer);
174 static EncoderStatus gst_h264_encoder_get_nal_codec_data(GstVaapiEncoder* encoder, GstBuffer **buffer);
178 gst_h264_encoder_class_init(GstH264EncoderClass *klass)
180 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
181 GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
182 g_type_class_add_private(klass, sizeof(GstH264EncoderPrivate));
184 object_class->finalize = gst_h264_encoder_finalize;
186 encoder_class->initialize = gst_h264_encoder_initialize;
187 encoder_class->uninitialize = gst_h264_encoder_uninitialize;
188 encoder_class->open = gst_h264_encoder_open;
189 encoder_class->close = gst_h264_encoder_close;
190 encoder_class->encode = gst_h264_encoder_encode;
191 encoder_class->flush = gst_h264_encoder_flush;
193 object_class->set_property = gst_h264_encoder_set_property;
194 object_class->get_property = gst_h264_encoder_get_property;
200 gst_h264_encode_buffer_class_init (gpointer g_class, gpointer class_data)
202 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS(g_class);
204 h264_encode_buffer_parent_class = g_type_class_peek_parent(g_class);
205 ENCODER_ASSERT(h264_encode_buffer_parent_class);
207 mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
208 gst_h264_encode_buffer_finalize;
213 gst_h264_encode_buffer_get_type (void)
215 static GType s_h264_encode_buffer_type = 0;
216 if (G_UNLIKELY (s_h264_encode_buffer_type == 0)) {
217 static const GTypeInfo s_h264_encode_buffer_info = {
218 sizeof(GstBufferClass),
221 gst_h264_encode_buffer_class_init,
224 sizeof(GstH264EncodeBuffer),
229 s_h264_encode_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
230 "GstH264EncodeBuffer", &s_h264_encode_buffer_info, 0);
232 return s_h264_encode_buffer_type;
236 gst_h264_encode_buffer_finalize (GstH264EncodeBuffer *h264_buffer)
238 GstH264EncoderPrivate *h264_prv = NULL;
239 VABufferID* coded_id = NULL;
240 GstVaapiDisplay *display = NULL;
242 h264_prv = h264_buffer->encoder;
243 coded_id = h264_buffer->coded_id;
244 display = ENCODER_DISPLAY(h264_prv->public);
246 ENCODER_ASSERT(display);
247 ENCODER_ASSERT(h264_prv->vaapi_context);
248 VADisplay va_dpy = gst_vaapi_display_get_display(display);
250 ENCODER_ASSERT(h264_prv);
251 ENCODER_ASSERT(coded_id && VA_INVALID_ID!= *coded_id);
252 ENCODER_ASSERT(h264_prv->available_code_buffers);
254 g_mutex_lock(h264_prv->code_buffer_lock);
255 /*if (--(*h264_buffer->ref_coded_id) == 0) */
257 /*g_free(h264_buffer->ref_coded_id);*/
258 vaUnmapBuffer(va_dpy, *coded_id);
259 g_queue_push_head(h264_prv->available_code_buffers, coded_id);
260 g_cond_signal(h264_prv->code_buffer_cond);
263 g_mutex_unlock(h264_prv->code_buffer_lock);
265 if (GST_MINI_OBJECT_CLASS(h264_encode_buffer_parent_class)->finalize) {
266 GST_MINI_OBJECT_CLASS(h264_encode_buffer_parent_class)->finalize(GST_MINI_OBJECT(h264_buffer));
270 static GstH264EncodeBuffer *
271 gst_h264_encode_buffer_new(GstH264EncoderPrivate *h264_prv,
272 VABufferID *coded_id)
274 GstH264EncodeBuffer *buf = (GstH264EncodeBuffer*)gst_mini_object_new(GST_TYPE_H264_ENCODE_BUFFER);
275 buf->coded_id = coded_id;
276 buf->encoder = h264_prv;
281 static GstVaapiSurface *
282 h264_get_video_surface(GstH264EncoderPrivate *h264_prv, GstVaapiVideoBuffer *video_buffer)
285 GstVaapiSurface *ret = gst_vaapi_video_buffer_get_surface(video_buffer);
287 ENCODER_CHECK_STATUS(ret, NULL, "video buffer doesn't have a surface");
289 g_queue_push_tail(h264_prv->video_buffer_caches,video_buffer);
290 gst_buffer_ref(GST_BUFFER(video_buffer));
299 h264_release_video_surface(GstH264EncoderPrivate *h264_prv, VASurfaceID surface)
302 ENCODER_ASSERT(h264_prv->video_buffer_caches);
303 g_queue_find_custom(h264_prv->video_buffer_caches,xx, compare_func);
304 for (h264_prv->video_buffer_caches) {
309 static GstVaapiSurface *
310 h264_pop_free_surface(GstH264EncoderPrivate *h264_prv)
312 ENCODER_ASSERT(h264_prv && h264_prv->vaapi_context);
315 GstVaapiSurface *surface = gst_vaapi_context_get_surface(h264_prv->vaapi_context);
320 h264_push_free_surface(GstH264EncoderPrivate *h264_prv, GstVaapiSurface *surface)
322 ENCODER_ASSERT(surface);
326 gst_vaapi_context_put_surface(h264_prv->vaapi_context, surface);
331 h264_get_va_profile(uint32_t profile)
334 case H264_PROFILE_BASELINE:
335 return VAProfileH264Baseline;
337 case H264_PROFILE_MAIN:
338 return VAProfileH264Main;
340 case H264_PROFILE_HIGH:
341 return VAProfileH264High;
350 gst_h264_encoder_new(void)
352 return GST_H264_ENCODER(g_object_new(GST_TYPE_H264_ENCODER, NULL));
357 gst_h264_encoder_init(GstH264Encoder *encoder)
359 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
360 GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
361 ENCODER_ASSERT(h264_prv);
362 h264_prv->public = encoder;
364 /* init public attributes */
365 gst_h264_encoder_init_public_values(encoder);
367 /* init private values*/
368 h264_prv->format = GST_MAKE_FOURCC('N','V','1','2');
369 h264_prv->es_flag = TRUE;
371 //h264_prv->vaapi_display = NULL;
372 h264_prv->vaapi_context= NULL;
373 h264_prv->ref_surface = NULL;
374 h264_prv->recon_surface = NULL;
375 h264_prv->video_buffer_caches = g_queue_new();
377 //h264_prv->encode_state = H264_ENC_NULL;
378 h264_prv->seq_parameter = VA_INVALID_ID;
379 h264_prv->pic_parameter = VA_INVALID_ID;
380 h264_prv->slice_parameter = VA_INVALID_ID;
381 h264_prv->slice_param_buffers = NULL;
382 h264_prv->default_slice_height = 0;
383 h264_prv->slice_mod_mb_num = 0;
385 h264_prv->coded_bufs = NULL;
386 h264_prv->coded_buf_num = DEFAULT_CODEDBUF_NUM;
387 h264_prv->frame_count = 0;
388 h264_prv->sps_data = NULL;
389 h264_prv->pps_data = NULL;
391 h264_prv->cur_coded_index = 0;
393 h264_prv->code_buffer_lock = g_mutex_new();
394 h264_prv->code_buffer_cond = g_cond_new();
395 h264_prv->available_code_buffers = g_queue_new();
397 encoder_prv->get_codec_data = gst_h264_encoder_get_avcC_codec_data;
398 /* encoder_prv->get_codec_data = gst_h264_encoder_get_nal_codec_data; */
403 gst_h264_encoder_finalize(GObject *object)
405 /*free private buffers*/
406 GstH264EncoderPrivate *h264_prv = ENCPRV(object);
408 g_mutex_free(h264_prv->code_buffer_lock);
409 g_cond_free(h264_prv->code_buffer_cond);
410 if (h264_prv->available_code_buffers) {
411 g_queue_free(h264_prv->available_code_buffers);
412 h264_prv->available_code_buffers = NULL;
415 if (h264_prv->ref_surface) {
416 if (h264_prv->vaapi_context) {
417 h264_push_free_surface(h264_prv, h264_prv->ref_surface);
419 g_object_unref(h264_prv->ref_surface);
421 h264_prv->ref_surface = NULL;
423 if (h264_prv->recon_surface) {
424 if (h264_prv->vaapi_context) {
425 h264_push_free_surface(h264_prv, h264_prv->recon_surface);
427 g_object_unref(h264_prv->recon_surface);
429 h264_prv->recon_surface = NULL;
431 if (h264_prv->vaapi_context) {
432 g_object_unref(h264_prv->vaapi_context);
433 h264_prv->vaapi_context= NULL;
436 if (h264_prv->video_buffer_caches) {
437 g_queue_free(h264_prv->video_buffer_caches);
438 h264_prv->video_buffer_caches = NULL;
440 if (h264_prv->sps_data) {
441 gst_buffer_unref(h264_prv->sps_data);
442 h264_prv->sps_data = NULL;
444 if (h264_prv->pps_data) {
445 gst_buffer_unref(h264_prv->pps_data);
446 h264_prv->pps_data = NULL;
448 if (h264_prv->slice_param_buffers) {
449 g_free(h264_prv->slice_param_buffers);
450 h264_prv->slice_param_buffers = NULL;
456 gst_h264_encoder_init_public_values(GstH264Encoder* encoder)
458 encoder->profile = 0;
460 //encoder->width = 0;
461 //encoder->height = 0;
462 //encoder->frame_rate = 0;
463 encoder->bitrate = 0;
464 encoder->intra_period = 0;
465 encoder->init_qp = -1;
466 encoder->min_qp = -1;
467 encoder->slice_num = 0;
471 gst_h264_encoder_set_input_format(GstH264Encoder* encoder, uint32_t format)
473 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
474 h264_prv->format = format;
478 gst_h264_encoder_set_es_flag(GstH264Encoder* encoder, gboolean es)
480 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
481 h264_prv->es_flag = es;
485 gst_h264_encoder_initialize(GstVaapiEncoder* encoder)
487 return ENCODER_NO_ERROR;
491 gst_h264_encoder_uninitialize(GstVaapiEncoder* encoder)
493 return ENCODER_NO_ERROR;
498 gst_h264_validate_parameters(GstH264Encoder *encoder)
500 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
501 if (!ENCODER_WIDTH(encoder) || !ENCODER_HEIGHT(encoder) || !ENCODER_FPS(encoder)) {
504 if (!encoder->profile) {
505 encoder->profile = H264_DEFAULT_PROFILE;
507 if (!encoder->level) {
508 encoder->level = H264_DEFAULT_LEVEL;
510 if (!encoder->intra_period) {
511 encoder->intra_period = H264_DEFAULT_INTRA_PERIOD;
513 if (-1 == encoder->init_qp) {
514 encoder->init_qp = H264_DEFAULT_INIT_QP;
516 if (-1 == encoder->min_qp) {
517 encoder->min_qp = H264_DEFAULT_MIN_QP;
520 if (encoder->min_qp > encoder->init_qp) {
521 encoder->min_qp = encoder->init_qp;
524 /* default compress ratio 1: (4*8*1.5) */
525 if (!encoder->bitrate) {
526 encoder->bitrate = ENCODER_WIDTH(encoder)*ENCODER_HEIGHT(encoder)*ENCODER_FPS(encoder)/4;
529 if (!encoder->slice_num) {
530 encoder->slice_num = H264_DEFAULT_SLICE_NUM;
533 /* need calculate slice-num and each slice-height
534 suppose: ((encoder->height+15)/16) = 13, slice_num = 8
535 then: slice_1_height = 2
544 h264_prv->default_slice_height = (ENCODER_HEIGHT(encoder)+15)/16/encoder->slice_num;
545 if (0 == h264_prv->default_slice_height) { /* special value */
546 h264_prv->default_slice_height = 1;
547 h264_prv->slice_mod_mb_num = 0;
548 encoder->slice_num = (ENCODER_HEIGHT(encoder)+15)/16;
550 h264_prv->slice_mod_mb_num = ((ENCODER_HEIGHT(encoder)+15)/16)%encoder->slice_num;
556 gst_h264_encoder_open(GstVaapiEncoder* encoder, void* private_data)
558 GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
559 GstVaapiSurfacePool *surfaces_pool = private_data;
560 GstVaapiDisplay *display = ENCODER_DISPLAY(encoder);
561 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
563 EncoderStatus ret = ENCODER_NO_ERROR;
564 VAProfile va_profile = -1;
565 VAEntrypoint entrypoints[5];
566 int num_entrypoints,slice_entrypoint;
567 VAConfigAttrib attrib[5];
568 VAStatus va_status = VA_STATUS_SUCCESS;
570 /*check and set default values*/
571 ENCODER_CHECK_STATUS(gst_h264_validate_parameters(h264_encoder), ENCODER_PARAMETER_ERR, "h264encoder paramerter error.\n");
573 va_profile = h264_get_va_profile(h264_encoder->profile);
574 ENCODER_ASSERT(ENCODER_DISPLAY(encoder));
575 ENCODER_ASSERT(!h264_prv->vaapi_context);
576 ENCODER_CHECK_STATUS(-1 != va_profile, ENCODER_PROFILE_ERR, "profile(%d) is NOT supported.\n", h264_encoder->profile);
579 h264_prv->vaapi_context = g_object_new(
580 GST_VAAPI_TYPE_CONTEXT,
582 "id", GST_VAAPI_ID(VA_INVALID_ID),
583 "entrypoint", gst_vaapi_entrypoint(VAEntrypointEncSlice),
584 "width", ENCODER_WIDTH(encoder),
585 "height", ENCODER_HEIGHT(encoder),
589 gst_vaapi_context_set_surface_pool(h264_prv->vaapi_context, surfaces_pool);
591 g_object_set(h264_prv->vaapi_context, "profile", gst_vaapi_profile(va_profile), NULL);
594 VAAPI_UNUSED_ARG(surfaces_pool);
595 h264_prv->vaapi_context = gst_vaapi_context_new(display,
596 gst_vaapi_profile(va_profile),
597 gst_vaapi_entrypoint(VAEntrypointEncSlice),
598 ENCODER_WIDTH(encoder),
599 ENCODER_HEIGHT(encoder));
601 ENCODER_CHECK_STATUS(h264_prv->vaapi_context, ENCODER_CONTEXT_ERR, "gst_vaapi_context_new failed.\n");
602 ret = h264_encoder_alloc_buffers(h264_prv);
603 if (ENCODER_NO_ERROR != ret) {
607 return ENCODER_NO_ERROR;
611 gst_h264_encoder_close(encoder);
617 gst_h264_encoder_close(GstVaapiEncoder* encoder)
619 GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
620 EncoderStatus ret = ENCODER_NO_ERROR;
621 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
623 /* release buffers first */
624 h264_encoder_release_buffers(h264_prv);
626 /*remove ref_surface*/
627 if (h264_prv->ref_surface) {
628 if (h264_prv->vaapi_context) {
629 h264_push_free_surface(h264_prv, h264_prv->ref_surface);
631 g_object_unref(h264_prv->ref_surface);
633 h264_prv->ref_surface = NULL;
636 /*remove recon_surface*/
637 if (h264_prv->recon_surface) {
638 if (h264_prv->vaapi_context) {
639 h264_push_free_surface(h264_prv, h264_prv->recon_surface);
641 g_object_unref(h264_prv->recon_surface);
643 h264_prv->recon_surface = NULL;
646 /*remove vaapi_context*/
647 if (h264_prv->vaapi_context) {
648 g_object_unref(h264_prv->vaapi_context);
649 h264_prv->vaapi_context = NULL;
652 h264_prv->frame_count = 0;
654 if (h264_prv->sps_data) {
655 gst_buffer_unref(h264_prv->sps_data);
656 h264_prv->sps_data = NULL;
658 if (h264_prv->pps_data) {
659 gst_buffer_unref(h264_prv->pps_data);
660 h264_prv->pps_data = NULL;
666 h264_encoder_alloc_buffers(GstH264EncoderPrivate *h264_prv)
668 EncoderStatus ret = ENCODER_NO_ERROR;
669 VAStatus va_status = VA_STATUS_SUCCESS;
670 GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
673 ENCODER_ASSERT(display);
674 ENCODER_ASSERT(h264_prv->vaapi_context);
675 VADisplay va_dpy = gst_vaapi_display_get_display(display);
676 VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
677 gboolean is_locked = FALSE;
679 GST_VAAPI_DISPLAY_LOCK(display);
682 /* create coded buffers */
683 h264_prv->coded_bufs = (VABufferID*)g_malloc0(h264_prv->coded_buf_num * sizeof(h264_prv->coded_bufs[0]));
684 { // check width, height ????
685 uint32_t codedbuf_size = (ENCODER_WIDTH(h264_prv->public) * ENCODER_HEIGHT(h264_prv->public) * 400) / (16*16);
686 for (i = 0; i < h264_prv->coded_buf_num; i++) {
687 va_status = vaCreateBuffer(va_dpy, context_id,VAEncCodedBufferType,
688 codedbuf_size, 1, NULL, &h264_prv->coded_bufs[i]);
690 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_ENC_RES_ERR, "alloc coded buffer failed.\n");
695 GST_VAAPI_DISPLAY_UNLOCK(display);
698 ENCODER_ASSERT(h264_prv->available_code_buffers);
700 /* create slice_param_buffers */
701 h264_prv->slice_param_buffers = (VAEncSliceParameterBuffer*)g_malloc0_n(h264_prv->public->slice_num,
702 sizeof(h264_prv->slice_param_buffers[0]));
704 /* init queue available_code_buffers */
705 g_mutex_lock(h264_prv->code_buffer_lock);
706 for (i = 0; i < h264_prv->coded_buf_num; i++) {
707 g_queue_push_tail (h264_prv->available_code_buffers, &h264_prv->coded_bufs[i]);
709 g_cond_signal(h264_prv->code_buffer_cond);
710 g_mutex_unlock(h264_prv->code_buffer_lock);
712 return ENCODER_NO_ERROR;
716 GST_VAAPI_DISPLAY_UNLOCK(display);
724 h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv)
726 VAStatus va_status = VA_STATUS_SUCCESS;
727 uint32_t available_buf_count = h264_prv->coded_buf_num;
728 GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
731 ENCODER_ASSERT(display);
732 ENCODER_ASSERT(h264_prv->vaapi_context);
733 VADisplay va_dpy = gst_vaapi_display_get_display(display);
735 /* wait for all coded buffer freed*/
736 g_mutex_lock(h264_prv->code_buffer_lock);
737 while (available_buf_count) {
738 if (g_queue_is_empty(h264_prv->available_code_buffers)) {
739 g_cond_wait(h264_prv->code_buffer_cond, h264_prv->code_buffer_lock);
741 g_queue_pop_head(h264_prv->available_code_buffers);
742 available_buf_count--;
745 g_mutex_unlock(h264_prv->code_buffer_lock);
747 GST_VAAPI_DISPLAY_LOCK(display);
748 for (i = 0; i < h264_prv->coded_buf_num; i++) {
749 va_status = vaDestroyBuffer(va_dpy, h264_prv->coded_bufs[i]);
751 va_status = vaDestroyBuffer(va_dpy, h264_prv->seq_parameter);
752 GST_VAAPI_DISPLAY_UNLOCK(display);
754 if (h264_prv->coded_bufs) {
755 g_free(h264_prv->coded_bufs);
756 h264_prv->coded_bufs = NULL;
759 if (h264_prv->slice_param_buffers) {
760 g_free(h264_prv->slice_param_buffers);
761 h264_prv->slice_param_buffers = NULL;
764 return ENCODER_NO_ERROR;
768 gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstBuffer *raw_pic, GList **coded_pics)
770 GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
771 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
772 GstVaapiDisplay *display = ENCODER_DISPLAY(encoder);
774 EncoderStatus ret = ENCODER_NO_ERROR;
775 gboolean is_key = FALSE;
776 VABufferID* coded_buf = NULL;
777 VAStatus va_status = VA_STATUS_SUCCESS;
778 VASurfaceID buffer_surface_id = VA_INVALID_SURFACE;
779 GstVaapiSurface *buffer_surface = NULL;
781 ENCODER_ASSERT(display);
782 ENCODER_ASSERT(h264_prv->vaapi_context);
783 VADisplay va_dpy = gst_vaapi_display_get_display(display);
784 VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
785 GstVaapiSurface *new_surface = NULL;
787 if (GST_VAAPI_IS_VIDEO_BUFFER(raw_pic)) {
788 buffer_surface = h264_get_video_surface(h264_prv, GST_VAAPI_VIDEO_BUFFER(raw_pic));
790 new_surface = h264_pop_free_surface(h264_prv);
791 buffer_surface = new_surface;
792 ENCODER_CHECK_STATUS(buffer_surface, ENCODER_SURFACE_ERR, "h264_pop_free_surface failed.\n");
794 /*input picture to h264_prv->cur_surface_index*/
795 va_status = h264_put_raw_buffer_to_surface(h264_prv, raw_pic, buffer_surface);
796 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "va put buffer to surface failed.\n");
798 buffer_surface_id = (VASurfaceID)GST_VAAPI_OBJECT_ID(buffer_surface);
799 ENCODER_CHECK_STATUS(buffer_surface_id != VA_INVALID_SURFACE, ENCODER_SURFACE_ERR, "surface id == VA_INVALID_SURFACE.\n");
801 /* begin picture, using default sid 0*/
802 GST_VAAPI_DISPLAY_LOCK(display);
803 va_status = vaBeginPicture(va_dpy, context_id, buffer_surface_id);
804 GST_VAAPI_DISPLAY_UNLOCK(display);
806 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaBeginPicture error.\n");
808 /* set input buffers*/
809 is_key = ((h264_prv->frame_count % h264_encoder->intra_period) == 0);
811 /*get valid coded buffer*/
812 g_mutex_lock(h264_prv->code_buffer_lock);
813 ENCODER_ASSERT(h264_prv->available_code_buffers);
814 while (g_queue_is_empty(h264_prv->available_code_buffers)) {
815 g_cond_wait(h264_prv->code_buffer_cond, h264_prv->code_buffer_lock);
818 coded_buf = (VABufferID*)g_queue_pop_head (h264_prv->available_code_buffers);
819 ret = h264_prepare_encoding(h264_prv, raw_pic, is_key, *coded_buf);
820 if (ENCODER_NO_ERROR != ret) {
821 g_queue_push_head(h264_prv->available_code_buffers, coded_buf);
823 g_mutex_unlock(h264_prv->code_buffer_lock);
825 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret, ENCODER_PICTURE_ERR, "h264_prepare_encoding failed.\n");
828 GST_VAAPI_DISPLAY_LOCK(display);
829 va_status = vaEndPicture(va_dpy, context_id);
830 GST_VAAPI_DISPLAY_UNLOCK(display);
831 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaEndPicture error.\n");
833 /*query surface result*/
834 ret = h264_query_encoding_status(h264_prv, buffer_surface_id,
835 is_key, GST_BUFFER_TIMESTAMP(raw_pic), GST_BUFFER_DURATION(raw_pic), coded_buf, coded_pics);
836 if (ENCODER_NO_ERROR != ret) {
840 h264_prv->frame_count++;
845 h264_push_free_surface(h264_prv, new_surface);
851 h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
853 GstVaapiSurface *surface)
855 EncoderStatus ret = ENCODER_NO_ERROR;
856 VAStatus va_status = VA_STATUS_SUCCESS;
857 VAImage surface_image;
859 GstVaapiImage *image;
860 GstVaapiImageFormat image_format;
861 uint8_t *y_src = NULL, *u_src = NULL, *v_src = NULL;
862 uint8_t *y_dst = NULL, *u_dst = NULL, *v_dst = NULL;
863 int y_size = 0, u_size = 0;
864 int row = 0, col = 0;
865 uint32_t plane_count = 0;
866 uint32_t image_width = 0, image_height = 0;
867 uint32_t pitchy = 0, pitchu = 0, pitchv = 0;
868 GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
870 ENCODER_ASSERT(display);
871 va_dpy = gst_vaapi_display_get_display(display);
873 image = gst_vaapi_surface_derive_image(surface);
874 gst_vaapi_image_map(image);
876 image_format = gst_vaapi_image_get_format(image);
877 image_width = gst_vaapi_image_get_width(image);
878 image_height = gst_vaapi_image_get_height(image);
880 /* copy buffer to surface */
881 ENCODER_ASSERT(GST_BUFFER_SIZE(raw_pic) >= y_size + (y_size>>1));
883 y_size = ENCODER_WIDTH(h264_prv->public) * ENCODER_HEIGHT(h264_prv->public);
884 u_size = ((ENCODER_WIDTH(h264_prv->public)+1) >> 1) * ((ENCODER_HEIGHT(h264_prv->public)+1) >> 1);
886 y_src = GST_BUFFER_DATA(raw_pic);
887 u_src = y_src + y_size;
888 v_src = u_src + u_size;
890 plane_count = gst_vaapi_image_get_plane_count(image);
891 y_dst = gst_vaapi_image_get_plane(image, 0);
892 u_dst = gst_vaapi_image_get_plane(image, 1);
893 pitchy = gst_vaapi_image_get_pitch(image, 0);
894 pitchu = gst_vaapi_image_get_pitch(image, 1);
896 if (plane_count > 2) {
897 v_dst = gst_vaapi_image_get_plane(image, 2);
898 pitchv = gst_vaapi_image_get_pitch(image, 2);
901 /* copy from avcenc.c*/
903 for (row = 0; row < image_height; row++) {
904 memcpy(y_dst, y_src, image_width);
906 y_src += ENCODER_WIDTH(h264_prv->public);
909 if (GST_VAAPI_IMAGE_NV12 == image_format) { /* UV plane */
910 if (GST_VAAPI_IMAGE_I420 == h264_prv->format) {
911 for (row = 0; row < image_height / 2; row++) {
912 for (col = 0; col < image_width / 2; col++) {
913 u_dst[col * 2] = u_src[col];
914 u_dst[col * 2 + 1] = v_src[col];
918 u_src += (ENCODER_WIDTH(h264_prv->public)>>1);
919 v_src += (ENCODER_WIDTH(h264_prv->public)>>1);
921 } else if (GST_VAAPI_IMAGE_NV12 == h264_prv->format){
922 for (row = 0; row < image_height / 2; row++) {
923 memcpy(u_dst, u_src, image_width);
924 u_src += ENCODER_WIDTH(h264_prv->public);
931 /* FIXME: fix this later */
936 g_object_unref(image);
943 h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gboolean is_key, VABufferID coded_buf)
945 EncoderStatus ret = ENCODER_NO_ERROR;
946 VAStatus va_status = VA_STATUS_SUCCESS;
947 GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
949 VAEncPictureParameterBufferH264 pic_h264;
950 VAEncSliceParameterBuffer *slice_h264 = NULL;
952 ENCODER_ASSERT(display);
953 ENCODER_ASSERT(h264_prv->vaapi_context);
954 VADisplay va_dpy = gst_vaapi_display_get_display(display);
955 VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
958 GST_VAAPI_DISPLAY_LOCK(display);
959 /*handle first surface_index*/
960 /*only need first frame*/
961 if (VA_INVALID_ID == h264_prv->seq_parameter) { /*first time*/
962 VAEncSequenceParameterBufferH264 seq_h264 = {0};
964 seq_h264.level_idc = h264_prv->public->level; /* 3.0 */
965 seq_h264.max_num_ref_frames = 1; /*Only I, P frames*/
966 seq_h264.picture_width_in_mbs = (ENCODER_WIDTH(h264_prv->public)+15)/16;
967 seq_h264.picture_height_in_mbs = (ENCODER_HEIGHT(h264_prv->public)+15)/16;
969 seq_h264.bits_per_second = h264_prv->public->bitrate;
970 seq_h264.frame_rate = ENCODER_FPS(h264_prv->public);
971 seq_h264.initial_qp = h264_prv->public->init_qp; /*qp_value; 15, 24, 26?*/
972 seq_h264.min_qp = h264_prv->public->min_qp; /*1, 6, 10*/
973 seq_h264.basic_unit_size = 0;
974 seq_h264.intra_period = h264_prv->public->intra_period;
975 seq_h264.intra_idr_period = h264_prv->public->intra_period;
977 va_status = vaCreateBuffer(va_dpy, context_id,
978 VAEncSequenceParameterBufferType,
979 sizeof(seq_h264), 1, &seq_h264, &h264_prv->seq_parameter);
980 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_ENC_RES_ERR, "alloc seq-buffer failed.\n");
981 va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->seq_parameter, 1);
982 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaRenderPicture seq-parameters failed.\n");
985 /* set pic_parameters*/
986 if (!h264_prv->ref_surface) {
987 h264_prv->ref_surface = h264_pop_free_surface(h264_prv);
988 ENCODER_CHECK_STATUS(h264_prv->ref_surface, ENCODER_SURFACE_ERR, "reference surface, h264_pop_free_surface failed.\n");
990 if (!h264_prv->recon_surface) {
991 h264_prv->recon_surface = h264_pop_free_surface(h264_prv);
992 ENCODER_CHECK_STATUS(h264_prv->recon_surface, ENCODER_SURFACE_ERR, "reconstructed surface, h264_pop_free_surface failed.\n");
995 pic_h264.reference_picture = GST_VAAPI_OBJECT_ID(h264_prv->ref_surface);
996 pic_h264.reconstructed_picture = GST_VAAPI_OBJECT_ID(h264_prv->recon_surface);
997 pic_h264.coded_buf = coded_buf;
998 pic_h264.picture_width = ENCODER_WIDTH(h264_prv->public);
999 pic_h264.picture_height = ENCODER_HEIGHT(h264_prv->public);
1000 pic_h264.last_picture = 0; // last pic or not
1002 if (VA_INVALID_ID != h264_prv->pic_parameter) { /* share the same pic_parameter*/
1003 vaDestroyBuffer(va_dpy, h264_prv->pic_parameter);
1004 h264_prv->pic_parameter = VA_INVALID_ID;
1006 va_status = vaCreateBuffer(va_dpy, context_id, VAEncPictureParameterBufferType,
1007 sizeof(pic_h264), 1, &pic_h264, &h264_prv->pic_parameter);
1009 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "creating pic-param buffer failed.\n");
1011 va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->pic_parameter, 1);
1012 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "rendering pic-param buffer failed.\n");
1014 /* set slice parameters, support multiple slices */
1016 uint32_t last_row_num = 0;
1017 uint32_t slice_mod_num = h264_prv->slice_mod_mb_num;
1019 memset(h264_prv->slice_param_buffers, 0, h264_prv->public->slice_num*sizeof(h264_prv->slice_param_buffers[0]));
1020 for (i = 0; i < h264_prv->public->slice_num; ++i) {
1021 slice_h264 = &h264_prv->slice_param_buffers[i];
1022 slice_h264->start_row_number = last_row_num; /* unit MB*/
1023 slice_h264->slice_height = h264_prv->default_slice_height; /* unit MB */
1024 if (slice_mod_num) {
1025 ++slice_h264->slice_height;
1028 last_row_num += slice_h264->slice_height;
1029 slice_h264->slice_flags.bits.is_intra = is_key;
1030 slice_h264->slice_flags.bits.disable_deblocking_filter_idc = 0;
1033 ENCODER_ASSERT(last_row_num == (ENCODER_HEIGHT(h264_prv->public)+15)/16);
1035 if (VA_INVALID_ID != h264_prv->slice_parameter) {
1036 vaDestroyBuffer(va_dpy, h264_prv->slice_parameter);
1037 h264_prv->slice_parameter = VA_INVALID_ID;
1039 va_status = vaCreateBuffer(va_dpy,
1041 VAEncSliceParameterBufferType,
1042 sizeof(h264_prv->slice_param_buffers[0]),
1043 h264_prv->public->slice_num,
1044 h264_prv->slice_param_buffers,
1045 &h264_prv->slice_parameter);
1046 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "creating slice-parameters buffer failed.\n");
1048 va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->slice_parameter, 1);
1049 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "rendering slice-parameters buffer failed.\n");
1052 /*after finished, set ref_surface_index, recon_surface_index */
1053 GstVaapiSurface *swap = h264_prv->ref_surface;
1054 h264_prv->ref_surface = h264_prv->recon_surface;
1055 h264_prv->recon_surface = swap;
1058 GST_VAAPI_DISPLAY_UNLOCK(display);
1062 static EncoderStatus
1063 h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
1064 VASurfaceID surface_id,
1066 GstClockTime timestamp,
1067 GstClockTime duration,
1068 VABufferID *coded_buf,
1071 EncoderStatus ret = ENCODER_NO_ERROR;
1072 VAStatus va_status = VA_STATUS_SUCCESS;
1073 VASurfaceStatus surface_status = 0;
1074 VACodedBufferSegment *buf_list = NULL;
1075 GstBuffer* ret_buffer = NULL;
1076 gboolean has_coded_data = FALSE;
1077 gboolean is_locked = FALSE;
1079 GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
1081 ENCODER_ASSERT(display);
1082 ENCODER_ASSERT(h264_prv->vaapi_context);
1083 VADisplay va_dpy = gst_vaapi_display_get_display(display);
1084 //VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
1086 ENCODER_ASSERT(coded_pics && *coded_pics == NULL);
1089 GST_VAAPI_DISPLAY_LOCK(display);
1092 va_status = vaSyncSurface(va_dpy, surface_id);
1093 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaSyncSurface failed.\n");
1095 va_status = vaQuerySurfaceStatus(va_dpy, surface_id, &surface_status);
1096 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaQuerySurfaceStatus failed.\n");
1097 if (VASurfaceSkipped&surface_status) {
1098 ENCODER_LOG_ERROR("frame skipped, dts:%" GST_TIME_FORMAT ".\n", GST_TIME_ARGS(timestamp));
1101 va_status = vaMapBuffer(va_dpy, *coded_buf, (void **)(&buf_list));
1102 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaMapBuffer failed.\n");
1106 GST_VAAPI_DISPLAY_UNLOCK(display);
1110 while (buf_list != NULL) {
1111 if (!h264_prv->sps_data || !h264_prv->pps_data) {
1112 h264_encoder_read_sps_pps(h264_prv, buf_list->buf, buf_list->size);
1114 ret_buffer = h264_encoder_create_coded_buffer(h264_prv, buf_list->buf, buf_list->size, coded_buf);
1115 GST_BUFFER_TIMESTAMP(ret_buffer) = timestamp;
1116 GST_BUFFER_DURATION(ret_buffer) = duration;
1118 GST_BUFFER_FLAG_SET(ret_buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1120 *coded_pics = g_list_append(*coded_pics, ret_buffer);
1121 buf_list = (VACodedBufferSegment*)buf_list->next;
1122 ENCODER_ASSERT(NULL == buf_list);
1123 has_coded_data = TRUE;
1127 if (!has_coded_data)
1129 { // if non-related, push back to available_code_buffers
1130 g_mutex_lock(h264_prv->code_buffer_lock);
1131 GST_VAAPI_DISPLAY_LOCK(display);
1132 vaUnmapBuffer(va_dpy, *coded_buf);
1133 GST_VAAPI_DISPLAY_UNLOCK(display);
1134 g_queue_push_head(h264_prv->available_code_buffers, coded_buf);
1135 g_cond_signal(h264_prv->code_buffer_cond);
1136 g_mutex_unlock(h264_prv->code_buffer_lock);
1139 return ENCODER_NO_ERROR;
1144 GST_VAAPI_DISPLAY_UNLOCK(display);
1151 h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
1153 uint32_t frame_size,
1154 VABufferID *coded_buf)
1156 GstBuffer *ret_buffer;
1158 const uint8_t *nal_start;
1162 ret_buffer = gst_h264_encode_buffer_new(h264_prv, coded_buf);
1163 ENCODER_ASSERT(ret_buffer);
1164 GST_BUFFER_MALLOCDATA(ret_buffer) = NULL;
1165 GST_BUFFER_DATA(ret_buffer) = buf_list->buf;
1166 GST_BUFFER_SIZE(ret_buffer) = buf_list->size;
1168 ret_buffer = gst_buffer_new();
1169 ENCODER_ASSERT(ret_buffer);
1170 H264Bitstream bitstream;
1171 h264_bitstream_init(&bitstream, (frame_size+32)*8);
1172 h264_bitstream_align(&bitstream, 0);
1173 ENCODER_ASSERT(bitstream.bit_size == 0);
1175 if (!h264_prv->es_flag) { /*nal format*/
1176 h264_bitstream_write_byte_array(&bitstream, frame, frame_size);
1177 ENCODER_ASSERT(bitstream.bit_size == frame_size*8);
1178 } else { /* elementary format */
1179 frame_end = frame + frame_size;
1182 while((nal_start = h264_next_nal(nal_start, frame_end-nal_start, &nal_size)) != NULL) {
1183 ENCODER_ASSERT(nal_size);
1185 nal_start += nal_size;
1188 h264_bitstream_write_uint(&bitstream, nal_size, 32);
1189 h264_bitstream_write_byte_array(&bitstream, nal_start, nal_size);
1190 nal_start += nal_size;
1193 h264_bitstream_align(&bitstream, 0);
1195 GST_BUFFER_MALLOCDATA(ret_buffer) =
1196 GST_BUFFER_DATA(ret_buffer) = BIT_STREAM_BUFFER(&bitstream);
1197 GST_BUFFER_SIZE(ret_buffer) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
1198 h264_bitstream_destroy(&bitstream, FALSE);
1205 static EncoderStatus
1206 h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const uint8_t *buf, uint32_t size)
1208 const uint8_t *end = buf + size;
1209 const uint8_t *nal_start = buf;
1210 uint32_t nal_size = 0;
1212 GstBuffer *sps = NULL, *pps = NULL;
1214 while((!sps || !pps) && (nal_start = h264_next_nal(nal_start, end-nal_start, &nal_size)) != NULL) {
1216 nal_start += nal_size;
1220 nal_type = (*nal_start)&0x1F;
1223 sps = gst_buffer_new_and_alloc(nal_size);
1224 memcpy(GST_BUFFER_DATA(sps), nal_start, nal_size);
1225 gst_buffer_replace(&h264_prv->sps_data, sps);
1226 gst_buffer_unref(sps); /*don't set to NULL*/
1231 pps = gst_buffer_new_and_alloc(nal_size);
1232 memcpy(GST_BUFFER_DATA(pps), nal_start, nal_size);
1233 gst_buffer_replace(&h264_prv->pps_data, pps);
1234 gst_buffer_unref(pps);
1241 nal_start += nal_size;
1245 return ENCODER_DATA_NOT_READY;
1247 return ENCODER_NO_ERROR;
1251 h264_read_sps_attributes(const uint8_t *sps_data, uint32_t sps_size,
1252 uint32_t *profile_idc, uint32_t *profile_comp, uint32_t *level_idc)
1254 ENCODER_ASSERT(profile_idc && profile_comp && level_idc);
1255 ENCODER_ASSERT(sps_size >= 4);
1259 /*skip sps_data[0], nal_type*/
1260 *profile_idc = sps_data[1];
1261 *profile_comp = sps_data[2];
1262 *level_idc = sps_data[3];
1268 gst_h264_encoder_flush(GstVaapiEncoder* encoder, GList **coded_pics)
1270 GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
1271 EncoderStatus ret = ENCODER_NO_ERROR;
1272 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
1273 GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
1275 h264_prv->frame_count = 0;
1276 /*do we need destroy h264_prv->seq_parameter? */
1283 static int draw_picture(int width, int height,
1284 unsigned char *Y_start,
1285 unsigned char *U_start,
1286 unsigned char *V_start,
1287 int UV_interleave, int box_width, int row_shift);
1289 int main_test(int argc, char* argv[])
1291 EncoderStatus ret = ENCODER_NO_ERROR;
1292 GstVaapiEncoder *encoder = NULL;
1294 GList *coded_pics = NULL;
1295 GstBuffer **raw_buffer = NULL;
1296 const uint32_t raw_buffer_num = 20;
1298 GstBuffer *tmp_buffer;
1300 uint32_t i = 0, k = 0;
1302 gst_init (&argc, &argv);
1305 if (!g_thread_supported ())
1306 g_thread_init (NULL);
1308 GstH264Encoder *h264_encoder = gst_h264_encoder_new();
1309 encoder = GST_VAAPI_ENCODER(h264_encoder);
1310 ENCODER_ASSERT(encoder);
1312 h264_encoder->profile = 64;
1313 h264_encoder->level = 30;
1314 h264_encoder->parent.width = 1280;
1315 h264_encoder->parent.height = 720;
1316 h264_encoder->parent.frame_rate = 10;
1317 h264_encoder->bitrate = 512*1000;
1318 h264_encoder->intra_period = 30;
1319 ret = gst_vaapi_encoder_initialize(encoder);
1320 ENCODER_ASSERT(ret == ENCODER_NO_ERROR);
1321 ret = gst_vaapi_encoder_open(encoder, NULL);
1322 ENCODER_ASSERT(ret == ENCODER_NO_ERROR);
1324 uint32_t buffer_size = encoder->width * encoder->width *3 /2;
1325 uint32_t y_width = encoder->width, y_size = encoder->width * encoder->height;
1326 uint32_t u_width = encoder->width/2, u_size = (encoder->width/2) * (encoder->height/2);
1327 uint32_t v_width = encoder->width/2;
1328 uint8_t *y_src, *u_src, *v_src;
1333 raw_buffer = (GstBuffer**)g_malloc0(raw_buffer_num*sizeof(GstBuffer*));
1334 for (i = 0; i < raw_buffer_num; i++) {
1335 raw_buffer[i] = gst_buffer_new_and_alloc(buffer_size);
1336 y_src = GST_BUFFER_DATA(raw_buffer[i]);
1337 u_src = y_src + y_size;
1338 v_src = u_src + u_size;
1340 draw_picture(encoder->width, encoder->height, y_src, u_src, v_src, 0, box_width, row_shift);
1342 if (row_shift==(2*box_width)) row_shift= 0;
1345 FILE *fp = fopen("tmp.h264", "wb");
1350 for (i = 0; i < 50; i++) {
1352 ret = gst_vaapi_encoder_encode(encoder, raw_buffer[k], &coded_pics);
1353 ENCODER_ASSERT(ENCODER_NO_ERROR == ret);
1355 if (k >= raw_buffer_num) k = 0;
1357 while (coded_pics) {
1358 tmp_buffer = coded_pics->data;
1359 coded_pics = g_list_remove(coded_pics, tmp_buffer);
1360 fwrite(GST_BUFFER_DATA(tmp_buffer), GST_BUFFER_SIZE(tmp_buffer), 1, fp);
1361 printf("F:%d, S:%d, %s\n", i, GST_BUFFER_SIZE(tmp_buffer), vaapi_encoder_dump_bytes(GST_BUFFER_DATA(tmp_buffer)+4, 8));
1362 gst_buffer_unref(tmp_buffer);
1367 ret = gst_vaapi_encoder_close(encoder);
1368 ENCODER_ASSERT(ENCODER_NO_ERROR == ret);
1370 for (i = 0; i < raw_buffer_num; i++) {
1371 gst_buffer_unref(raw_buffer[i]);
1374 gst_vaapi_encoder_unref(encoder);
1380 gst_h264_encoder_get_avcC_codec_data(GstVaapiEncoder *encoder, GstBuffer **buffer)
1382 GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
1383 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
1384 GstBuffer *avc_codec;
1385 const uint32_t configuration_version = 0x01;
1386 const uint32_t length_size_minus_one = 0x03;
1387 uint32_t profile, profile_comp, level_idc;
1389 ENCODER_ASSERT(buffer);
1390 if (!h264_prv->sps_data || !h264_prv->pps_data) {
1391 return ENCODER_DATA_NOT_READY;
1394 if (FALSE == h264_read_sps_attributes(GST_BUFFER_DATA(h264_prv->sps_data),
1395 GST_BUFFER_SIZE(h264_prv->sps_data),
1396 &profile, &profile_comp, &level_idc))
1399 return ENCODER_DATA_ERR;
1402 H264Bitstream bitstream;
1403 h264_bitstream_init(&bitstream,
1404 (GST_BUFFER_SIZE(h264_prv->sps_data)+GST_BUFFER_SIZE(h264_prv->pps_data) + 32)*8);
1407 h264_bitstream_write_uint(&bitstream, configuration_version, 8);
1408 h264_bitstream_write_uint(&bitstream, profile, 8);
1409 h264_bitstream_write_uint(&bitstream, profile_comp, 8);
1410 h264_bitstream_write_uint(&bitstream, level_idc, 8);
1411 h264_bitstream_write_uint(&bitstream, h264_bit_mask[6], 6); /*111111*/
1412 h264_bitstream_write_uint(&bitstream, length_size_minus_one, 2);
1413 h264_bitstream_write_uint(&bitstream, h264_bit_mask[3], 3); /*111*/
1416 h264_bitstream_write_uint(&bitstream, 1, 5); /* sps count = 1*/
1417 ENCODER_ASSERT( BIT_STREAM_BIT_SIZE(&bitstream)%8 == 0);
1418 h264_bitstream_write_uint(&bitstream, GST_BUFFER_SIZE(h264_prv->sps_data), 16);
1419 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->sps_data),
1420 GST_BUFFER_SIZE(h264_prv->sps_data));
1423 h264_bitstream_write_uint(&bitstream, 1, 8); /*pps count = 1*/
1424 h264_bitstream_write_uint(&bitstream, GST_BUFFER_SIZE(h264_prv->pps_data), 16);
1425 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->pps_data),
1426 GST_BUFFER_SIZE(h264_prv->pps_data));
1428 avc_codec = gst_buffer_new();
1429 GST_BUFFER_MALLOCDATA(avc_codec) =
1430 GST_BUFFER_DATA(avc_codec) =
1431 BIT_STREAM_BUFFER(&bitstream);
1432 GST_BUFFER_SIZE(avc_codec) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
1433 h264_bitstream_destroy(&bitstream, FALSE);
1434 *buffer = avc_codec;
1436 return ENCODER_NO_ERROR;
1440 gst_h264_encoder_get_nal_codec_data(GstVaapiEncoder *encoder, GstBuffer **buffer)
1442 GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
1443 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
1444 GstBuffer *nal_sps_pps;
1446 ENCODER_ASSERT(buffer);
1447 if (!h264_prv->sps_data || !h264_prv->pps_data) {
1448 return ENCODER_DATA_NOT_READY;
1451 H264Bitstream bitstream;
1452 h264_bitstream_init(&bitstream,
1453 (GST_BUFFER_SIZE(h264_prv->sps_data)+GST_BUFFER_SIZE(h264_prv->pps_data) + 8)*8);
1455 /*0x000001 start code*/
1456 h264_bitstream_write_uint(&bitstream, 0x000001, 24);
1457 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->sps_data),
1458 GST_BUFFER_SIZE(h264_prv->sps_data));
1459 h264_bitstream_write_uint(&bitstream, 0x000001, 24);
1460 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->pps_data),
1461 GST_BUFFER_SIZE(h264_prv->pps_data));
1463 nal_sps_pps = gst_buffer_new();
1464 GST_BUFFER_MALLOCDATA(nal_sps_pps) =
1465 GST_BUFFER_DATA(nal_sps_pps) =
1466 BIT_STREAM_BUFFER(&bitstream);
1467 GST_BUFFER_SIZE(nal_sps_pps) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
1468 h264_bitstream_destroy(&bitstream, FALSE);
1469 *buffer = nal_sps_pps;
1470 return ENCODER_NO_ERROR;
1474 h264_bitstream_init(H264Bitstream *bitstream, uint32_t bit_capability)
1476 bitstream->bit_size = 0;
1477 bitstream->buffer = NULL;
1478 bitstream->max_bit_capability = 0;
1479 if (bit_capability) {
1480 h264_bitstream_auto_grow(bitstream, bit_capability);
1485 h264_bitstream_write_uint(H264Bitstream *bitstream, uint32_t value, uint32_t bit_size)
1487 gboolean ret = TRUE;
1488 uint32_t byte_pos, bit_offset;
1496 ENCODER_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, bit_size), FALSE, "h264_bitstream_auto_grow failed.\n");
1497 byte_pos = (bitstream->bit_size>>3);
1498 bit_offset = (bitstream->bit_size&0x07);
1499 cur_byte = bitstream->buffer + byte_pos;
1500 ENCODER_ASSERT(bit_offset < 8 && bitstream->bit_size <= bitstream->max_bit_capability);
1503 fill_bits = ((8-bit_offset) < bit_size ? (8-bit_offset) : bit_size);
1504 bit_size -= fill_bits;
1505 bitstream->bit_size += fill_bits;
1507 *cur_byte |= ((value>>bit_size) & h264_bit_mask[fill_bits])<<(8-bit_offset-fill_bits);
1511 ENCODER_ASSERT(cur_byte <= bitstream->buffer + bitstream->max_bit_capability/8);
1518 static gboolean h264_bitstream_align(H264Bitstream *bitstream, uint32_t value)
1520 uint32_t bit_offset, bit_left;
1522 bit_offset = (bitstream->bit_size&0x07);
1526 bit_left = 8 - bit_offset;
1527 if (value) value = h264_bit_mask[bit_left];
1528 return h264_bitstream_write_uint(bitstream, value, bit_left);
1533 h264_bitstream_write_byte_array(H264Bitstream *bitstream, const uint8_t *buf, uint32_t byte_size)
1535 gboolean ret = TRUE;
1539 ENCODER_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, byte_size<<3), FALSE, "h264_bitstream_auto_grow failed.\n");
1540 if (0 == (bitstream->bit_size&0x07)) {
1541 memcpy(&bitstream->buffer[bitstream->bit_size>>3], buf, byte_size);
1542 bitstream->bit_size += (byte_size<<3);
1546 h264_bitstream_write_uint(bitstream, *buf, 8);
1558 h264_bitstream_write_ue(H264Bitstream *bitstream, uint32_t value)
1560 gboolean ret = TRUE;
1561 uint32_t size_in_bits = 0;
1562 uint32_t tmp_value = ++value;
1567 ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, 0, size_in_bits-1), FALSE, "h264_bitstream_write_ue failed.\n");
1568 ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, value, size_in_bits), FALSE, "h264_bitstream_write_ue failed.\n");
1576 h264_bitstream_write_se(H264Bitstream *bitstream, int32_t value)
1578 gboolean ret = TRUE;
1582 new_val = -(value<<1);
1584 new_val = (value<<1) - 1;
1587 ENCODER_CHECK_STATUS(h264_bitstream_write_ue(bitstream, new_val), FALSE, "h264_bitstream_write_se failed.\n");
1595 h264_bitstream_write_trailing_bits(H264Bitstream *bitstream)
1597 h264_bitstream_write_uint(bitstream, 1, 1);
1598 h264_bitstream_align(bitstream, 0);
1603 h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag)
1605 if (bitstream->buffer && free_flag) {
1606 free (bitstream->buffer);
1608 bitstream->buffer = NULL;
1609 bitstream->bit_size = 0;
1610 bitstream->max_bit_capability = 0;
1614 h264_bitstream_auto_grow(H264Bitstream *bitstream, uint32_t extra_bit_size)
1616 uint32_t new_bit_size = extra_bit_size + bitstream->bit_size;
1619 ENCODER_ASSERT(bitstream->bit_size <= bitstream->max_bit_capability);
1620 if (new_bit_size <= bitstream->max_bit_capability) {
1624 new_bit_size = ((new_bit_size + H264_BITSTREAM_ALLOC_ALIGN_MASK)
1625 &(~H264_BITSTREAM_ALLOC_ALIGN_MASK));
1626 ENCODER_ASSERT(new_bit_size%(H264_BITSTREAM_ALLOC_ALIGN_MASK+1) == 0);
1627 clear_pos = ((bitstream->bit_size+7)>>3);
1628 bitstream->buffer = realloc(bitstream->buffer, new_bit_size>>3);
1629 memset(bitstream->buffer+clear_pos, 0, (new_bit_size>>3)-clear_pos);
1630 bitstream->max_bit_capability = new_bit_size;
1635 h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv)
1637 uint32_t constraint_set0_flag, constraint_set1_flag, constraint_set2_flag, constraint_set3_flag;
1638 uint32_t seq_parameter_set_id = 0;
1640 /*need to set the values*/
1641 uint32_t log2_max_frame_num_minus4 = 0; // 1? 3?
1642 uint32_t pic_order_cnt_type = 0; // Must be 0
1643 uint32_t log2_max_pic_order_cnt_lsb_minus4 = 0; // 2 ? 4?
1644 uint32_t num_ref_frames = 1; // only P frames
1645 uint32_t gaps_in_frame_num_value_allowed_flag = 0; // ??
1646 uint32_t mb_width = (ENCODER_WIDTH(h264_prv->public)+15)/16; // mb_width
1647 uint32_t mb_height = (ENCODER_HEIGHT(h264_prv->public)+15)/16; // mb_height
1648 int32_t frame_mbs_only_flag = 1; // only mbs
1649 uint32_t frame_cropping_flag = 0;
1650 uint32_t frame_crop_bottom_offset = 0;
1651 uint32_t vui_present_flag = 0; // no vui flags
1654 constraint_set0_flag = h264_prv->public->profile == H264_PROFILE_BASELINE;
1655 constraint_set1_flag = h264_prv->public->profile <= H264_PROFILE_MAIN;
1656 constraint_set2_flag = 0;
1657 constraint_set3_flag = 0;
1659 if (mb_height * 16 - ENCODER_HEIGHT(h264_prv->public)) {
1660 frame_cropping_flag = 1;
1661 frame_crop_bottom_offset =
1662 (mb_height * 16 - ENCODER_HEIGHT(h264_prv->public)) / (2 * (!frame_mbs_only_flag + 1));
1665 h264_bitstream_write_uint(bitstream, h264_prv->public->profile, 8); /* profile_idc */
1666 h264_bitstream_write_uint(bitstream, constraint_set0_flag, 1); /* constraint_set0_flag */
1667 h264_bitstream_write_uint(bitstream, constraint_set1_flag, 1); /* constraint_set1_flag */
1668 h264_bitstream_write_uint(bitstream, constraint_set2_flag, 1); /* constraint_set2_flag */
1669 h264_bitstream_write_uint(bitstream, constraint_set3_flag, 1); /* constraint_set3_flag */
1670 h264_bitstream_write_uint(bitstream, 0, 4); /* reserved_zero_4bits */
1671 h264_bitstream_write_uint(bitstream, h264_prv->public->level, 8); /* level_idc */
1672 h264_bitstream_write_ue(bitstream, seq_parameter_set_id); /* seq_parameter_set_id */
1674 if (h264_prv->public->profile >= H264_PROFILE_HIGH) {
1675 /* FIXME: fix for high profile */
1679 h264_bitstream_write_ue(bitstream, log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
1680 h264_bitstream_write_ue(bitstream, pic_order_cnt_type); /* pic_order_cnt_type */
1682 if (pic_order_cnt_type == 0)
1683 h264_bitstream_write_ue(bitstream, log2_max_pic_order_cnt_lsb_minus4);/* log2_max_pic_order_cnt_lsb_minus4 */
1688 h264_bitstream_write_ue(bitstream, num_ref_frames); /* num_ref_frames */
1689 h264_bitstream_write_uint(bitstream, gaps_in_frame_num_value_allowed_flag, 1); /* gaps_in_frame_num_value_allowed_flag */
1691 h264_bitstream_write_ue(bitstream, mb_width - 1); /* pic_width_in_mbs_minus1 */
1692 h264_bitstream_write_ue(bitstream, mb_height - 1); /* pic_height_in_map_units_minus1 */
1693 h264_bitstream_write_uint(bitstream, frame_mbs_only_flag, 1); /* frame_mbs_only_flag */
1695 if (!frame_mbs_only_flag) { //ONLY mbs
1699 h264_bitstream_write_uint(bitstream, 0, 1); /* direct_8x8_inference_flag */
1700 h264_bitstream_write_uint(bitstream, frame_cropping_flag, 1); /* frame_cropping_flag */
1702 if (frame_cropping_flag) {
1703 h264_bitstream_write_ue(bitstream, 0); /* frame_crop_left_offset */
1704 h264_bitstream_write_ue(bitstream, 0); /* frame_crop_right_offset */
1705 h264_bitstream_write_ue(bitstream, 0); /* frame_crop_top_offset */
1706 h264_bitstream_write_ue(bitstream, frame_crop_bottom_offset); /* frame_crop_bottom_offset */
1709 h264_bitstream_write_uint(bitstream, vui_present_flag, 1); /* vui_parameters_present_flag */
1710 h264_bitstream_write_trailing_bits(bitstream); /* rbsp_trailing_bits */
1718 static const uint8_t *
1719 h264_next_nal(const uint8_t *buffer, uint32_t len, uint32_t *nal_size)
1721 const uint8_t *cur = buffer;
1722 const uint8_t *end = buffer + len;
1723 const uint8_t *nal_start = NULL;
1724 uint32_t flag = 0xFFFFFFFF;
1725 uint32_t nal_start_len = 0;
1727 ENCODER_ASSERT(len >= 0 && buffer && nal_size);
1730 nal_start = (len ? buffer : NULL);
1734 /*locate head postion*/
1735 if (!buffer[0] && !buffer[1]) {
1736 if (buffer[2] == 1) { // 0x000001
1738 } else if (!buffer[2] && len >=4 && buffer[3] == 1) { //0x00000001
1742 nal_start = buffer + nal_start_len;
1745 /*find next nal start position*/
1747 flag = ((flag<<8) | ((*cur++)&0xFF));
1748 if (flag == 0x00000001) {
1749 *nal_size = cur - 4 - nal_start;
1751 } else if ((flag&0x00FFFFFF) == 0x00000001) {
1752 *nal_size = cur - 3 - nal_start;
1757 *nal_size = end - nal_start;
1758 if (nal_start >= end) {
1767 h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv)
1773 static int draw_picture(int width, int height,
1774 unsigned char *Y_start,
1775 unsigned char *U_start,
1776 unsigned char *V_start,
1777 int UV_interleave, int box_width, int row_shift)
1781 int Y_pitch = width;
1782 int U_pitch = width/2;
1783 int V_pitch = width/2;
1786 for (row=0;row<height;row++) {
1787 unsigned char *Y_row = Y_start + row * Y_pitch;
1790 ypos = (row / box_width) & 0x1;
1792 /* fill garbage data into the other field */
1793 if (((field == 1) && (row &1))
1794 || ((field == 2) && ((row &1)==0))) {
1795 memset(Y_row, 0xff, width);
1799 for (jj=0; jj<width; jj++) {
1800 xpos = ((row_shift + jj) / box_width) & 0x1;
1802 if ((xpos == 0) && (ypos == 0))
1804 if ((xpos == 1) && (ypos == 1))
1807 if ((xpos == 1) && (ypos == 0))
1809 if ((xpos == 0) && (ypos == 1))
1815 for( row =0; row < height/2; row++) {
1816 unsigned short value = 0x80;
1818 /* fill garbage data into the other field */
1819 if (((field == 1) && (row &1))
1820 || ((field == 2) && ((row &1)==0))) {
1824 if (UV_interleave) {
1825 unsigned short *UV_row = (unsigned short *)(U_start + row * U_pitch);
1827 memset(UV_row, value, width);
1829 unsigned char *U_row = U_start + row * U_pitch;
1830 unsigned char *V_row = V_start + row * V_pitch;
1832 memset (U_row,value,width/2);
1833 memset (V_row,value,width/2);