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 guint32 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 guint32 default_slice_height;
72 guint32 slice_mod_mb_num;
74 VABufferID *coded_bufs;
75 guint32 coded_buf_num;
76 guint32 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 guint32 max_bit_capability;
105 typedef struct _H264Bitstream H264Bitstream;
107 static const guint8 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, GstVaapiDisplay *display);
113 static EncoderStatus gst_h264_encoder_uninitialize(GstVaapiEncoder* encoder, GstVaapiDisplay *display);
114 static EncoderStatus gst_h264_encoder_open(GstVaapiEncoder* encoder, GstVaapiDisplay *display, void* private_data, GstVaapiContext **context);
115 static EncoderStatus gst_h264_encoder_close(GstVaapiEncoder* encoder, GstVaapiDisplay *display, GstVaapiContext *context);
116 static EncoderStatus gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstVaapiDisplay *display,
117 GstVaapiContext *context, GstBuffer *raw_pic, GList **coded_pics);
118 static EncoderStatus gst_h264_encoder_flush(GstVaapiEncoder* encoder, GstVaapiDisplay *display,
119 GstVaapiContext *context, GList **coded_pics);
121 static EncoderStatus gst_h264_encoder_get_avcC_codec_data(GstVaapiEncoder* encoder, GstBuffer **buffer);
122 static EncoderStatus gst_h264_encoder_get_nal_codec_data(GstVaapiEncoder* encoder, GstBuffer **buffer);
124 static gboolean gst_h264_validate_parameters(GstH264Encoder *encoder);
125 static void gst_h264_encoder_finalize(GObject *object);
126 static void gst_h264_encoder_init_public_values(GstH264Encoder* encoder);
128 static VAProfile h264_get_va_profile(guint32 profile);
129 static EncoderStatus h264_encoder_alloc_buffers(GstH264Encoder *h264_encoder,
130 GstVaapiDisplay *display, GstVaapiContext *context);
131 static EncoderStatus h264_encoder_release_buffers(GstH264Encoder *h264_encoder,
132 GstVaapiDisplay *display, GstVaapiContext *context);
133 static EncoderStatus h264_put_raw_buffer_to_surface(GstH264Encoder *h264_encoder,
134 GstVaapiDisplay *display,
136 GstVaapiSurface *surface);
138 static EncoderStatus h264_prepare_encoding(GstH264Encoder *h264_encoder, GstVaapiDisplay *display,
139 GstVaapiContext *context, gboolean is_key, VABufferID coded_buf);
140 static EncoderStatus h264_query_encoding_status(GstH264Encoder *h264_encoder,
141 GstVaapiDisplay *display,
142 GstVaapiSurface *buffer_surface,
144 GstClockTime timestamp,
145 GstClockTime duration,
146 VABufferID *coded_buf,
149 h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const guint8 *buf, guint32 size);
150 static GstBuffer *h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
153 VABufferID *coded_buf);
156 /*encoded buffer, for SHARE_CODED_BUF */
157 static void gst_h264_encode_buffer_class_init (gpointer g_class, gpointer class_data);
158 static GType gst_h264_encode_buffer_get_type (void);
159 static void gst_h264_encode_buffer_finalize (GstH264EncodeBuffer *h264_buffer);
160 static GstH264EncodeBuffer *gst_h264_encode_buffer_new(GstH264EncoderPrivate *h264_prv,
161 VABufferID *coded_id);
163 /* h264 bitstream functions */
164 static void h264_bitstream_init(H264Bitstream *bitstream, guint32 bit_capability);
165 static gboolean h264_bitstream_write_uint(H264Bitstream *bitstream, guint32 value, guint32 bit_size);
166 static gboolean h264_bitstream_align(H264Bitstream *bitstream, guint32 value);
167 static gboolean h264_bitstream_write_ue(H264Bitstream *bitstream, guint32 value);
168 static gboolean h264_bitstream_write_se(H264Bitstream *bitstream, guint32 value);
169 static gboolean h264_bitstream_write_trailing_bits(H264Bitstream *bitstream);
171 static gboolean h264_bitstream_write_byte_array(H264Bitstream *bitstream, const guint8 *buf, guint32 byte_size);
172 static void h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag);
173 static gboolean h264_bitstream_auto_grow(H264Bitstream *bitstream, guint32 extra_bit_size);
174 static gboolean h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv);
175 static gboolean h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv);
176 static const guint8 *h264_next_nal(const guint8 *buffer, guint32 len, guint32 *nal_size);
177 static gboolean h264_read_sps_attributes(const guint8 *sps_data, guint32 sps_size,
178 guint32 *profile_idc, guint32 *profile_comp, guint32 *level_idc);
180 /* available_coded_buffer actions */
181 static VABufferID *pop_available_coded_buffer(GstH264EncoderPrivate *h264_prv);
182 static gboolean push_available_coded_buffer(GstH264EncoderPrivate *h264_prv, VABufferID *buf);
183 static gboolean alloc_all_available_coded_buffers(GstH264EncoderPrivate *h264_prv,
184 GstVaapiDisplay *display, GstVaapiContext *context,
185 guint32 buffer_size, gboolean need_display_lock);
186 static void wait_and_clear_available_coded_buffers(GstH264EncoderPrivate *h264_prv,
187 GstVaapiDisplay *display, gboolean need_display_lock);
190 gst_h264_encoder_class_init(GstH264EncoderClass *klass)
192 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
193 GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
194 g_type_class_add_private(klass, sizeof(GstH264EncoderPrivate));
196 object_class->finalize = gst_h264_encoder_finalize;
198 encoder_class->initialize = gst_h264_encoder_initialize;
199 encoder_class->uninitialize = gst_h264_encoder_uninitialize;
200 encoder_class->open = gst_h264_encoder_open;
201 encoder_class->close = gst_h264_encoder_close;
202 encoder_class->encode = gst_h264_encoder_encode;
203 encoder_class->flush = gst_h264_encoder_flush;
204 encoder_class->get_codec_data = gst_h264_encoder_get_avcC_codec_data;
205 /* encoder_class->get_codec_data = gst_h264_encoder_get_nal_codec_data; */
208 object_class->set_property = gst_h264_encoder_set_property;
209 object_class->get_property = gst_h264_encoder_get_property;
215 gst_h264_encode_buffer_class_init (gpointer g_class, gpointer class_data)
217 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS(g_class);
219 h264_encode_buffer_parent_class = g_type_class_peek_parent(g_class);
220 ENCODER_ASSERT(h264_encode_buffer_parent_class);
222 mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
223 gst_h264_encode_buffer_finalize;
228 gst_h264_encode_buffer_get_type (void)
230 static GType s_h264_encode_buffer_type = 0;
231 if (G_UNLIKELY (s_h264_encode_buffer_type == 0)) {
232 static const GTypeInfo s_h264_encode_buffer_info = {
233 sizeof(GstBufferClass),
236 gst_h264_encode_buffer_class_init,
239 sizeof(GstH264EncodeBuffer),
244 s_h264_encode_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
245 "GstH264EncodeBuffer", &s_h264_encode_buffer_info, 0);
247 return s_h264_encode_buffer_type;
251 gst_h264_encode_buffer_finalize (GstH264EncodeBuffer *h264_buffer)
253 GstH264EncoderPrivate *h264_prv = NULL;
254 VABufferID* coded_id = NULL;
255 GstVaapiDisplay *display = NULL;
257 gboolean is_locked = FALSE;
259 h264_prv = h264_buffer->encoder;
260 coded_id = h264_buffer->coded_id;
261 display = ENCODER_DISPLAY(h264_prv->public);
263 ENCODER_ASSERT(display);
264 VADisplay va_dpy = gst_vaapi_display_get_display(display);
266 ENCODER_ASSERT(h264_prv);
267 ENCODER_ASSERT(coded_id && VA_INVALID_ID!= *coded_id);
269 /*if (--(*h264_buffer->ref_coded_id) == 0) */
271 /*g_free(h264_buffer->ref_coded_id);*/
272 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
273 vaUnmapBuffer(va_dpy, *coded_id);
274 ENCODER_RELEASE_DISPLAY_LOCK(display);
275 push_available_coded_buffer(h264_prv, coded_id);
278 if (GST_MINI_OBJECT_CLASS(h264_encode_buffer_parent_class)->finalize) {
279 GST_MINI_OBJECT_CLASS(h264_encode_buffer_parent_class)->finalize(GST_MINI_OBJECT(h264_buffer));
283 static GstH264EncodeBuffer *
284 gst_h264_encode_buffer_new(GstH264EncoderPrivate *h264_prv,
285 VABufferID *coded_id)
287 GstH264EncodeBuffer *buf = (GstH264EncodeBuffer*)gst_mini_object_new(GST_TYPE_H264_ENCODE_BUFFER);
288 buf->coded_id = coded_id;
289 buf->encoder = h264_prv;
294 static GstVaapiSurface *
295 h264_get_video_surface(GstH264EncoderPrivate *h264_prv, GstVaapiVideoBuffer *video_buffer)
298 GstVaapiSurface *ret = gst_vaapi_video_buffer_get_surface(video_buffer);
300 ENCODER_CHECK_STATUS(ret, NULL, "video buffer doesn't have a surface");
302 g_queue_push_tail(h264_prv->video_buffer_caches,video_buffer);
303 gst_buffer_ref(GST_BUFFER(video_buffer));
312 h264_release_video_surface(GstH264EncoderPrivate *h264_prv, VASurfaceID surface)
315 ENCODER_ASSERT(h264_prv->video_buffer_caches);
316 g_queue_find_custom(h264_prv->video_buffer_caches,xx, compare_func);
317 for (h264_prv->video_buffer_caches) {
323 h264_get_va_profile(guint32 profile)
326 case H264_PROFILE_BASELINE:
327 return VAProfileH264Baseline;
329 case H264_PROFILE_MAIN:
330 return VAProfileH264Main;
332 case H264_PROFILE_HIGH:
333 return VAProfileH264High;
342 gst_h264_encoder_new(void)
344 return GST_H264_ENCODER(g_object_new(GST_TYPE_H264_ENCODER, NULL));
349 gst_h264_encoder_init(GstH264Encoder *encoder)
351 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
352 GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
353 ENCODER_ASSERT(h264_prv);
354 h264_prv->public = encoder;
356 /* init public attributes */
357 gst_h264_encoder_init_public_values(encoder);
359 /* init private values*/
360 h264_prv->format = GST_MAKE_FOURCC('N','V','1','2');
361 h264_prv->es_flag = TRUE;
363 //h264_prv->vaapi_display = NULL;
364 h264_prv->ref_surface = NULL;
365 h264_prv->recon_surface = NULL;
366 h264_prv->video_buffer_caches = g_queue_new();
368 //h264_prv->encode_state = H264_ENC_NULL;
369 h264_prv->seq_parameter = VA_INVALID_ID;
370 h264_prv->pic_parameter = VA_INVALID_ID;
371 h264_prv->slice_parameter = VA_INVALID_ID;
372 h264_prv->slice_param_buffers = NULL;
373 h264_prv->default_slice_height = 0;
374 h264_prv->slice_mod_mb_num = 0;
376 h264_prv->coded_bufs = NULL;
377 h264_prv->coded_buf_num = DEFAULT_CODEDBUF_NUM;
378 h264_prv->frame_count = 0;
379 h264_prv->sps_data = NULL;
380 h264_prv->pps_data = NULL;
382 h264_prv->cur_coded_index = 0;
384 h264_prv->code_buffer_lock = g_mutex_new();
385 h264_prv->code_buffer_cond = g_cond_new();
386 h264_prv->available_code_buffers = g_queue_new();
391 gst_h264_encoder_finalize(GObject *object)
393 /*free private buffers*/
394 GstVaapiEncoder *encoder = GST_VAAPI_ENCODER(object);
395 GstH264EncoderPrivate *h264_prv = ENCPRV(object);
397 if (gst_vaapi_encoder_get_state(encoder) != VAAPI_ENC_NULL) {
398 gst_vaapi_encoder_uninitialize(encoder);
401 g_mutex_free(h264_prv->code_buffer_lock);
402 g_cond_free(h264_prv->code_buffer_cond);
403 if (h264_prv->available_code_buffers) {
404 g_queue_free(h264_prv->available_code_buffers);
405 h264_prv->available_code_buffers = NULL;
408 if (h264_prv->video_buffer_caches) {
409 g_queue_free(h264_prv->video_buffer_caches);
410 h264_prv->video_buffer_caches = NULL;
412 if (h264_prv->sps_data) {
413 gst_buffer_unref(h264_prv->sps_data);
414 h264_prv->sps_data = NULL;
416 if (h264_prv->pps_data) {
417 gst_buffer_unref(h264_prv->pps_data);
418 h264_prv->pps_data = NULL;
420 if (h264_prv->slice_param_buffers) {
421 g_free(h264_prv->slice_param_buffers);
422 h264_prv->slice_param_buffers = NULL;
428 gst_h264_encoder_init_public_values(GstH264Encoder* encoder)
430 encoder->profile = 0;
432 //encoder->width = 0;
433 //encoder->height = 0;
434 //encoder->frame_rate = 0;
435 encoder->bitrate = 0;
436 encoder->intra_period = 0;
437 encoder->init_qp = -1;
438 encoder->min_qp = -1;
439 encoder->slice_num = 0;
443 gst_h264_encoder_set_input_format(GstH264Encoder* encoder, guint32 format)
445 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
446 h264_prv->format = format;
450 gst_h264_encoder_set_es_flag(GstH264Encoder* encoder, gboolean es)
452 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
453 h264_prv->es_flag = es;
457 gst_h264_encoder_initialize(GstVaapiEncoder* encoder, GstVaapiDisplay *display)
459 return ENCODER_NO_ERROR;
463 gst_h264_encoder_uninitialize(GstVaapiEncoder* encoder, GstVaapiDisplay *display)
465 return ENCODER_NO_ERROR;
470 gst_h264_validate_parameters(GstH264Encoder *encoder)
472 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
473 if (!ENCODER_WIDTH(encoder) || !ENCODER_HEIGHT(encoder) || !ENCODER_FPS(encoder)) {
476 if (!encoder->profile) {
477 encoder->profile = H264_DEFAULT_PROFILE;
479 if (!encoder->level) {
480 encoder->level = H264_DEFAULT_LEVEL;
482 if (!encoder->intra_period) {
483 encoder->intra_period = H264_DEFAULT_INTRA_PERIOD;
485 if (-1 == encoder->init_qp) {
486 encoder->init_qp = H264_DEFAULT_INIT_QP;
488 if (-1 == encoder->min_qp) {
489 encoder->min_qp = H264_DEFAULT_MIN_QP;
492 if (encoder->min_qp > encoder->init_qp) {
493 encoder->min_qp = encoder->init_qp;
496 /* default compress ratio 1: (4*8*1.5) */
497 if (!encoder->bitrate) {
498 encoder->bitrate = ENCODER_WIDTH(encoder)*ENCODER_HEIGHT(encoder)*ENCODER_FPS(encoder)/4;
501 if (!encoder->slice_num) {
502 encoder->slice_num = H264_DEFAULT_SLICE_NUM;
505 /* need calculate slice-num and each slice-height
506 suppose: ((encoder->height+15)/16) = 13, slice_num = 8
507 then: slice_1_height = 2
516 h264_prv->default_slice_height = (ENCODER_HEIGHT(encoder)+15)/16/encoder->slice_num;
517 if (0 == h264_prv->default_slice_height) { /* special value */
518 h264_prv->default_slice_height = 1;
519 h264_prv->slice_mod_mb_num = 0;
520 encoder->slice_num = (ENCODER_HEIGHT(encoder)+15)/16;
522 h264_prv->slice_mod_mb_num = ((ENCODER_HEIGHT(encoder)+15)/16)%encoder->slice_num;
528 gst_h264_encoder_open(GstVaapiEncoder* encoder, GstVaapiDisplay *display, void* private_data, GstVaapiContext **context)
530 GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
531 GstVaapiSurfacePool *surfaces_pool = private_data;
532 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
533 GstVaapiContext *out_context = NULL;
534 VAProfile va_profile = -1;
536 EncoderStatus ret = ENCODER_NO_ERROR;
537 VAStatus va_status = VA_STATUS_SUCCESS;
539 /*check and set default values*/
540 ENCODER_CHECK_STATUS(gst_h264_validate_parameters(h264_encoder), ENCODER_PARAMETER_ERR, "h264encoder paramerter error.\n");
542 va_profile = h264_get_va_profile(h264_encoder->profile);
543 ENCODER_ASSERT(ENCODER_DISPLAY(encoder));
544 ENCODER_CHECK_STATUS(-1 != va_profile, ENCODER_PROFILE_ERR, "profile(%d) is NOT supported.\n", h264_encoder->profile);
547 out_context = g_object_new(
548 GST_VAAPI_TYPE_CONTEXT,
550 "id", GST_VAAPI_ID(VA_INVALID_ID),
551 "entrypoint", gst_vaapi_entrypoint(VAEntrypointEncSlice),
552 "width", ENCODER_WIDTH(encoder),
553 "height", ENCODER_HEIGHT(encoder),
557 gst_vaapi_context_set_surface_pool(out_context, surfaces_pool);
559 g_object_set(out_context, "profile", gst_vaapi_profile(va_profile), NULL);
562 VAAPI_UNUSED_ARG(surfaces_pool);
563 out_context = gst_vaapi_context_new(display,
564 gst_vaapi_profile(va_profile),
565 gst_vaapi_entrypoint(VAEntrypointEncSlice),
566 ENCODER_WIDTH(encoder),
567 ENCODER_HEIGHT(encoder));
569 ENCODER_CHECK_STATUS(out_context, ENCODER_CONTEXT_ERR, "gst_vaapi_context_new failed.\n");
570 ret = h264_encoder_alloc_buffers(h264_encoder, display, out_context);
571 if (ENCODER_NO_ERROR != ret) {
574 *context = out_context;
575 return ENCODER_NO_ERROR;
579 if (ENCODER_NO_ERROR != ret) {
580 gst_h264_encoder_close(encoder, display, out_context);
582 g_object_unref(out_context);
590 gst_h264_encoder_close(GstVaapiEncoder* encoder, GstVaapiDisplay *display, GstVaapiContext *context)
592 GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
593 EncoderStatus ret = ENCODER_NO_ERROR;
594 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
596 /* release buffers first */
597 h264_encoder_release_buffers(h264_encoder, display, context);
599 /*remove ref_surface*/
600 if (h264_prv->ref_surface) {
602 gst_vaapi_context_put_surface(context, h264_prv->ref_surface);
604 g_object_unref(h264_prv->ref_surface);
606 h264_prv->ref_surface = NULL;
609 /*remove recon_surface*/
610 if (h264_prv->recon_surface) {
612 gst_vaapi_context_put_surface(context, h264_prv->recon_surface);
614 g_object_unref(h264_prv->recon_surface);
616 h264_prv->recon_surface = NULL;
619 h264_prv->frame_count = 0;
621 if (h264_prv->sps_data) {
622 gst_buffer_unref(h264_prv->sps_data);
623 h264_prv->sps_data = NULL;
625 if (h264_prv->pps_data) {
626 gst_buffer_unref(h264_prv->pps_data);
627 h264_prv->pps_data = NULL;
633 h264_encoder_alloc_buffers(GstH264Encoder *h264_encoder, GstVaapiDisplay *display, GstVaapiContext *context)
635 EncoderStatus ret = ENCODER_NO_ERROR;
636 VAStatus va_status = VA_STATUS_SUCCESS;
637 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
640 ENCODER_ASSERT(display && context);
641 VADisplay va_dpy = gst_vaapi_display_get_display(display);
642 VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
643 gboolean is_locked = FALSE;
645 guint32 codedbuf_size = (ENCODER_WIDTH(h264_encoder) * ENCODER_HEIGHT(h264_encoder) * 400) / (16*16);
646 ENCODER_CHECK_STATUS(alloc_all_available_coded_buffers(h264_prv, display, context, codedbuf_size, TRUE),
648 "alloc_all_available_coded_buffers failed.\n");
650 /* create slice_param_buffers */
651 h264_prv->slice_param_buffers = (VAEncSliceParameterBuffer*)g_malloc0_n(h264_encoder->slice_num,
652 sizeof(h264_prv->slice_param_buffers[0]));
658 h264_encoder_release_buffers(GstH264Encoder *h264_encoder, GstVaapiDisplay *display, GstVaapiContext *context)
660 VAStatus va_status = VA_STATUS_SUCCESS;
661 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
662 guint32 available_buf_count = h264_prv->coded_buf_num;
665 gboolean is_locked = FALSE;
667 ENCODER_ASSERT(display);
668 ENCODER_ASSERT(context);
669 VADisplay va_dpy = gst_vaapi_display_get_display(display);
671 /* wait clear all coded buffer freed*/
672 wait_and_clear_available_coded_buffers(h264_prv, display, TRUE);
674 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
675 va_status = vaDestroyBuffer(va_dpy, h264_prv->seq_parameter);
676 ENCODER_RELEASE_DISPLAY_LOCK(display);
678 if (h264_prv->slice_param_buffers) {
679 g_free(h264_prv->slice_param_buffers);
680 h264_prv->slice_param_buffers = NULL;
683 return ENCODER_NO_ERROR;
687 gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstVaapiDisplay *display,
688 GstVaapiContext *context, GstBuffer *raw_pic, GList **coded_pics)
690 GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
691 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
693 EncoderStatus ret = ENCODER_NO_ERROR;
694 gboolean is_key = FALSE;
695 VABufferID* coded_buf = NULL;
696 VAStatus va_status = VA_STATUS_SUCCESS;
697 VASurfaceID buffer_surface_id = VA_INVALID_SURFACE;
698 GstVaapiSurface *buffer_surface = NULL;
700 gboolean is_locked = FALSE;
702 ENCODER_ASSERT(display && context);
703 VADisplay va_dpy = gst_vaapi_display_get_display(display);
704 VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
705 GstVaapiSurface *new_surface = NULL;
707 if (GST_VAAPI_IS_VIDEO_BUFFER(raw_pic)) {
708 buffer_surface = h264_get_video_surface(h264_prv, GST_VAAPI_VIDEO_BUFFER(raw_pic));
710 new_surface = gst_vaapi_context_get_surface(context);
711 buffer_surface = new_surface;
712 ENCODER_CHECK_STATUS(buffer_surface, ENCODER_SURFACE_ERR, "h264_pop_free_surface failed.\n");
714 /*input picture to h264_prv->cur_surface_index*/
715 va_status = h264_put_raw_buffer_to_surface(h264_encoder, display, raw_pic, buffer_surface);
716 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "va put buffer to surface failed.\n");
718 buffer_surface_id = (VASurfaceID)GST_VAAPI_OBJECT_ID(buffer_surface);
719 ENCODER_CHECK_STATUS(buffer_surface_id != VA_INVALID_SURFACE, ENCODER_SURFACE_ERR, "surface id == VA_INVALID_SURFACE.\n");
721 /* begin picture, using default sid 0*/
722 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
723 va_status = vaBeginPicture(va_dpy, context_id, buffer_surface_id);
724 ENCODER_RELEASE_DISPLAY_LOCK(display);
726 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaBeginPicture error.\n");
728 /* set input buffers*/
729 is_key = ((h264_prv->frame_count % h264_encoder->intra_period) == 0);
731 /*get valid coded buffer*/
732 coded_buf = pop_available_coded_buffer(h264_prv);
733 ENCODER_CHECK_STATUS(coded_buf, ENCODER_ENC_RES_ERR, "dequeue_available_coded_buffer error.\n");
735 ret = h264_prepare_encoding(h264_encoder, display, context, is_key, *coded_buf);
736 if (ENCODER_NO_ERROR != ret) {
737 push_available_coded_buffer(h264_prv, coded_buf);
739 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret, ENCODER_PICTURE_ERR, "h264_prepare_encoding failed.\n");
742 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
743 va_status = vaEndPicture(va_dpy, context_id);
744 ENCODER_RELEASE_DISPLAY_LOCK(display);
745 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaEndPicture error.\n");
747 /*query surface result*/
748 ret = h264_query_encoding_status(h264_encoder, display, buffer_surface,
749 is_key, GST_BUFFER_TIMESTAMP(raw_pic), GST_BUFFER_DURATION(raw_pic), coded_buf, coded_pics);
750 if (ENCODER_NO_ERROR != ret) {
754 h264_prv->frame_count++;
757 ENCODER_RELEASE_DISPLAY_LOCK(display);
759 gst_vaapi_context_put_surface(context, new_surface);
765 pop_available_coded_buffer(GstH264EncoderPrivate *h264_prv)
767 VABufferID *coded_buf = NULL;
770 g_mutex_lock(h264_prv->code_buffer_lock);
772 ENCODER_CHECK_STATUS(h264_prv->available_code_buffers, FALSE, "coded buffer not found");
773 while (g_queue_is_empty(h264_prv->available_code_buffers)) {
774 g_cond_wait(h264_prv->code_buffer_cond, h264_prv->code_buffer_lock);
776 coded_buf = (VABufferID*)g_queue_pop_head (h264_prv->available_code_buffers);
779 g_mutex_unlock(h264_prv->code_buffer_lock);
784 push_available_coded_buffer(GstH264EncoderPrivate *h264_prv, VABufferID *buf)
786 g_mutex_lock(h264_prv->code_buffer_lock);
787 g_queue_push_head(h264_prv->available_code_buffers, buf);
788 g_cond_signal(h264_prv->code_buffer_cond);
789 g_mutex_unlock(h264_prv->code_buffer_lock);
794 alloc_all_available_coded_buffers(GstH264EncoderPrivate *h264_prv, GstVaapiDisplay *display,
795 GstVaapiContext *context, guint32 buffer_size, gboolean need_display_lock)
799 VADisplay va_dpy = gst_vaapi_display_get_display(display);
800 VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
801 VAStatus va_status = VA_STATUS_SUCCESS;
803 ENCODER_ASSERT(h264_prv->available_code_buffers);
804 ENCODER_ASSERT(!h264_prv->coded_bufs);
806 h264_prv->coded_bufs = (VABufferID*)g_malloc0(h264_prv->coded_buf_num * sizeof(h264_prv->coded_bufs[0]));
808 if (need_display_lock) { /* lock */
809 GST_VAAPI_DISPLAY_LOCK(display);
811 for (i = 0; i < h264_prv->coded_buf_num; i++) {
812 va_status = vaCreateBuffer(va_dpy, context_id,VAEncCodedBufferType,
813 buffer_size, 1, NULL, &h264_prv->coded_bufs[i]);
814 if (VA_STATUS_SUCCESS != va_status)
817 if (need_display_lock) { /* unlock */
818 GST_VAAPI_DISPLAY_UNLOCK(display);
820 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, FALSE, "alloc coded buffer failed.\n");
822 /* init queue available_code_buffers */
823 g_mutex_lock(h264_prv->code_buffer_lock);
824 for (i = 0; i < h264_prv->coded_buf_num; i++) {
825 g_queue_push_head(h264_prv->available_code_buffers, &h264_prv->coded_bufs[i]);
827 g_cond_signal(h264_prv->code_buffer_cond);
828 g_mutex_unlock(h264_prv->code_buffer_lock);
835 wait_and_clear_available_coded_buffers(GstH264EncoderPrivate *h264_prv,
836 GstVaapiDisplay *display, gboolean need_display_lock)
838 guint32 available_buf_count = h264_prv->coded_buf_num;
839 VADisplay va_dpy = gst_vaapi_display_get_display(display);
840 VAStatus va_status = VA_STATUS_SUCCESS;
843 g_mutex_lock(h264_prv->code_buffer_lock);
844 while (available_buf_count) {
845 if (g_queue_is_empty(h264_prv->available_code_buffers)) {
846 g_cond_wait(h264_prv->code_buffer_cond, h264_prv->code_buffer_lock);
848 g_queue_pop_head(h264_prv->available_code_buffers);
849 available_buf_count--;
852 g_mutex_unlock(h264_prv->code_buffer_lock);
854 if (need_display_lock) {
855 GST_VAAPI_DISPLAY_LOCK(display);
857 for (i = 0; i < h264_prv->coded_buf_num; i++) {
858 va_status = vaDestroyBuffer(va_dpy, h264_prv->coded_bufs[i]);
860 if (need_display_lock) {
861 GST_VAAPI_DISPLAY_UNLOCK(display);
864 if (h264_prv->coded_bufs) {
865 g_free(h264_prv->coded_bufs);
866 h264_prv->coded_bufs = NULL;
871 h264_put_raw_buffer_to_surface(GstH264Encoder *h264_encoder,
872 GstVaapiDisplay *display,
874 GstVaapiSurface *surface)
876 EncoderStatus ret = ENCODER_NO_ERROR;
877 VAStatus va_status = VA_STATUS_SUCCESS;
878 VAImage surface_image;
880 GstVaapiImage *image;
881 GstVaapiImageFormat image_format;
882 guint8 *y_src = NULL, *u_src = NULL, *v_src = NULL;
883 guint8 *y_dst = NULL, *u_dst = NULL, *v_dst = NULL;
884 int y_size = 0, u_size = 0;
885 int row = 0, col = 0;
886 guint32 plane_count = 0;
887 guint32 image_width = 0, image_height = 0;
888 guint32 pitchy = 0, pitchu = 0, pitchv = 0;
889 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
891 ENCODER_ASSERT(display);
892 va_dpy = gst_vaapi_display_get_display(display);
894 image = gst_vaapi_surface_derive_image(surface);
895 gst_vaapi_image_map(image);
897 image_format = gst_vaapi_image_get_format(image);
898 image_width = gst_vaapi_image_get_width(image);
899 image_height = gst_vaapi_image_get_height(image);
901 /* copy buffer to surface */
902 ENCODER_ASSERT(GST_BUFFER_SIZE(raw_pic) >= y_size + (y_size>>1));
904 y_size = ENCODER_WIDTH(h264_encoder) * ENCODER_HEIGHT(h264_encoder);
905 u_size = ((ENCODER_WIDTH(h264_encoder)+1) >> 1) * ((ENCODER_HEIGHT(h264_encoder)+1) >> 1);
907 y_src = GST_BUFFER_DATA(raw_pic);
908 u_src = y_src + y_size;
909 v_src = u_src + u_size;
911 plane_count = gst_vaapi_image_get_plane_count(image);
912 y_dst = gst_vaapi_image_get_plane(image, 0);
913 u_dst = gst_vaapi_image_get_plane(image, 1);
914 pitchy = gst_vaapi_image_get_pitch(image, 0);
915 pitchu = gst_vaapi_image_get_pitch(image, 1);
917 if (plane_count > 2) {
918 v_dst = gst_vaapi_image_get_plane(image, 2);
919 pitchv = gst_vaapi_image_get_pitch(image, 2);
922 /* copy from avcenc.c*/
924 for (row = 0; row < image_height; row++) {
925 memcpy(y_dst, y_src, image_width);
927 y_src += ENCODER_WIDTH(h264_encoder);
930 if (GST_VAAPI_IMAGE_NV12 == image_format) { /* UV plane */
931 if (GST_VAAPI_IMAGE_I420 == h264_prv->format) {
932 for (row = 0; row < image_height / 2; row++) {
933 for (col = 0; col < image_width / 2; col++) {
934 u_dst[col * 2] = u_src[col];
935 u_dst[col * 2 + 1] = v_src[col];
939 u_src += (ENCODER_WIDTH(h264_encoder)>>1);
940 v_src += (ENCODER_WIDTH(h264_encoder)>>1);
942 } else if (GST_VAAPI_IMAGE_NV12 == h264_prv->format){
943 for (row = 0; row < image_height / 2; row++) {
944 memcpy(u_dst, u_src, image_width);
945 u_src += ENCODER_WIDTH(h264_encoder);
952 /* FIXME: fix this later */
957 g_object_unref(image);
964 h264_prepare_encoding(GstH264Encoder *h264_encoder, GstVaapiDisplay *display,
965 GstVaapiContext *context, gboolean is_key, VABufferID coded_buf)
967 EncoderStatus ret = ENCODER_NO_ERROR;
968 VAStatus va_status = VA_STATUS_SUCCESS;
969 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
971 VAEncPictureParameterBufferH264 pic_h264;
972 VAEncSliceParameterBuffer *slice_h264 = NULL;
974 gboolean is_locked = FALSE;
976 ENCODER_ASSERT(display && context);
977 VADisplay va_dpy = gst_vaapi_display_get_display(display);
978 VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
981 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
982 /*handle first surface_index*/
983 /*only need first frame*/
984 if (VA_INVALID_ID == h264_prv->seq_parameter) { /*first time*/
985 VAEncSequenceParameterBufferH264 seq_h264 = {0};
987 seq_h264.level_idc = h264_encoder->level; /* 3.0 */
988 seq_h264.max_num_ref_frames = 1; /*Only I, P frames*/
989 seq_h264.picture_width_in_mbs = (ENCODER_WIDTH(h264_encoder)+15)/16;
990 seq_h264.picture_height_in_mbs = (ENCODER_HEIGHT(h264_encoder)+15)/16;
992 seq_h264.bits_per_second = h264_encoder->bitrate;
993 seq_h264.frame_rate = ENCODER_FPS(h264_encoder);
994 seq_h264.initial_qp = h264_encoder->init_qp; /*qp_value; 15, 24, 26?*/
995 seq_h264.min_qp = h264_encoder->min_qp; /*1, 6, 10*/
996 seq_h264.basic_unit_size = 0;
997 seq_h264.intra_period = h264_encoder->intra_period;
998 seq_h264.intra_idr_period = h264_encoder->intra_period;
1000 va_status = vaCreateBuffer(va_dpy, context_id,
1001 VAEncSequenceParameterBufferType,
1002 sizeof(seq_h264), 1, &seq_h264, &h264_prv->seq_parameter);
1003 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_ENC_RES_ERR, "alloc seq-buffer failed.\n");
1004 va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->seq_parameter, 1);
1005 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaRenderPicture seq-parameters failed.\n");
1008 /* set pic_parameters*/
1009 if (!h264_prv->ref_surface) {
1010 h264_prv->ref_surface = gst_vaapi_context_get_surface(context);
1011 ENCODER_CHECK_STATUS(h264_prv->ref_surface, ENCODER_SURFACE_ERR, "reference surface, h264_pop_free_surface failed.\n");
1013 if (!h264_prv->recon_surface) {
1014 h264_prv->recon_surface = gst_vaapi_context_get_surface(context);
1015 ENCODER_CHECK_STATUS(h264_prv->recon_surface, ENCODER_SURFACE_ERR, "reconstructed surface, h264_pop_free_surface failed.\n");
1018 pic_h264.reference_picture = GST_VAAPI_OBJECT_ID(h264_prv->ref_surface);
1019 pic_h264.reconstructed_picture = GST_VAAPI_OBJECT_ID(h264_prv->recon_surface);
1020 pic_h264.coded_buf = coded_buf;
1021 pic_h264.picture_width = ENCODER_WIDTH(h264_encoder);
1022 pic_h264.picture_height = ENCODER_HEIGHT(h264_encoder);
1023 pic_h264.last_picture = 0; // last pic or not
1025 if (VA_INVALID_ID != h264_prv->pic_parameter) { /* share the same pic_parameter*/
1026 vaDestroyBuffer(va_dpy, h264_prv->pic_parameter);
1027 h264_prv->pic_parameter = VA_INVALID_ID;
1029 va_status = vaCreateBuffer(va_dpy, context_id, VAEncPictureParameterBufferType,
1030 sizeof(pic_h264), 1, &pic_h264, &h264_prv->pic_parameter);
1032 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "creating pic-param buffer failed.\n");
1034 va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->pic_parameter, 1);
1035 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "rendering pic-param buffer failed.\n");
1037 /* set slice parameters, support multiple slices */
1039 guint32 last_row_num = 0;
1040 guint32 slice_mod_num = h264_prv->slice_mod_mb_num;
1042 memset(h264_prv->slice_param_buffers, 0, h264_encoder->slice_num*sizeof(h264_prv->slice_param_buffers[0]));
1043 for (i = 0; i < h264_encoder->slice_num; ++i) {
1044 slice_h264 = &h264_prv->slice_param_buffers[i];
1045 slice_h264->start_row_number = last_row_num; /* unit MB*/
1046 slice_h264->slice_height = h264_prv->default_slice_height; /* unit MB */
1047 if (slice_mod_num) {
1048 ++slice_h264->slice_height;
1051 last_row_num += slice_h264->slice_height;
1052 slice_h264->slice_flags.bits.is_intra = is_key;
1053 slice_h264->slice_flags.bits.disable_deblocking_filter_idc = 0;
1056 ENCODER_ASSERT(last_row_num == (ENCODER_HEIGHT(h264_encoder)+15)/16);
1058 if (VA_INVALID_ID != h264_prv->slice_parameter) {
1059 vaDestroyBuffer(va_dpy, h264_prv->slice_parameter);
1060 h264_prv->slice_parameter = VA_INVALID_ID;
1062 va_status = vaCreateBuffer(va_dpy,
1064 VAEncSliceParameterBufferType,
1065 sizeof(h264_prv->slice_param_buffers[0]),
1066 h264_encoder->slice_num,
1067 h264_prv->slice_param_buffers,
1068 &h264_prv->slice_parameter);
1069 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "creating slice-parameters buffer failed.\n");
1071 va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->slice_parameter, 1);
1072 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "rendering slice-parameters buffer failed.\n");
1074 /*after finished, set ref_surface_index, recon_surface_index */
1075 GstVaapiSurface *swap = h264_prv->ref_surface;
1076 h264_prv->ref_surface = h264_prv->recon_surface;
1077 h264_prv->recon_surface = swap;
1080 ENCODER_RELEASE_DISPLAY_LOCK(display);
1084 static EncoderStatus
1085 h264_query_encoding_status(GstH264Encoder *h264_encoder,
1086 GstVaapiDisplay *display,
1087 GstVaapiSurface *buffer_surface,
1089 GstClockTime timestamp,
1090 GstClockTime duration,
1091 VABufferID *coded_buf,
1094 EncoderStatus ret = ENCODER_NO_ERROR;
1095 VAStatus va_status = VA_STATUS_SUCCESS;
1096 VASurfaceStatus surface_status = 0;
1097 VACodedBufferSegment *buf_list = NULL;
1098 GstBuffer* ret_buffer = NULL;
1099 gboolean has_coded_data = FALSE;
1100 gboolean is_locked = FALSE;
1101 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
1103 ENCODER_ASSERT(display && context);
1104 VASurfaceID surface_id = (VASurfaceID)GST_VAAPI_OBJECT_ID(buffer_surface);
1105 VADisplay va_dpy = gst_vaapi_display_get_display(display);
1107 ENCODER_ASSERT(coded_pics && *coded_pics == NULL);
1110 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
1112 va_status = vaSyncSurface(va_dpy, surface_id);
1113 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaSyncSurface failed.\n");
1115 va_status = vaQuerySurfaceStatus(va_dpy, surface_id, &surface_status);
1116 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaQuerySurfaceStatus failed.\n");
1117 if (VASurfaceSkipped&surface_status) {
1118 ENCODER_LOG_ERROR("frame skipped, dts:%" GST_TIME_FORMAT ".\n", GST_TIME_ARGS(timestamp));
1121 va_status = vaMapBuffer(va_dpy, *coded_buf, (void **)(&buf_list));
1122 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaMapBuffer failed.\n");
1125 ENCODER_RELEASE_DISPLAY_LOCK(display);
1127 while (buf_list != NULL) {
1128 if (!h264_prv->sps_data || !h264_prv->pps_data) {
1129 h264_encoder_read_sps_pps(h264_prv, buf_list->buf, buf_list->size);
1131 ret_buffer = h264_encoder_create_coded_buffer(h264_prv, buf_list->buf, buf_list->size, coded_buf);
1132 GST_BUFFER_TIMESTAMP(ret_buffer) = timestamp;
1133 GST_BUFFER_DURATION(ret_buffer) = duration;
1135 GST_BUFFER_FLAG_SET(ret_buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1137 *coded_pics = g_list_append(*coded_pics, ret_buffer);
1138 buf_list = (VACodedBufferSegment*)buf_list->next;
1139 ENCODER_ASSERT(NULL == buf_list);
1140 has_coded_data = TRUE;
1144 if (!has_coded_data)
1146 { // if non-related, push back to available_code_buffers
1147 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
1148 vaUnmapBuffer(va_dpy, *coded_buf);
1149 ENCODER_RELEASE_DISPLAY_LOCK(display);
1150 push_available_coded_buffer(h264_prv, coded_buf);
1153 return ENCODER_NO_ERROR;
1157 ENCODER_RELEASE_DISPLAY_LOCK(display);
1162 h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
1165 VABufferID *coded_buf)
1167 GstBuffer *ret_buffer;
1169 const guint8 *nal_start;
1173 ret_buffer = gst_h264_encode_buffer_new(h264_prv, coded_buf);
1174 ENCODER_ASSERT(ret_buffer);
1175 GST_BUFFER_MALLOCDATA(ret_buffer) = NULL;
1176 GST_BUFFER_DATA(ret_buffer) = buf_list->buf;
1177 GST_BUFFER_SIZE(ret_buffer) = buf_list->size;
1179 ret_buffer = gst_buffer_new();
1180 ENCODER_ASSERT(ret_buffer);
1181 H264Bitstream bitstream;
1182 h264_bitstream_init(&bitstream, (frame_size+32)*8);
1183 h264_bitstream_align(&bitstream, 0);
1184 ENCODER_ASSERT(bitstream.bit_size == 0);
1186 if (!h264_prv->es_flag) { /*nal format*/
1187 h264_bitstream_write_byte_array(&bitstream, frame, frame_size);
1188 ENCODER_ASSERT(bitstream.bit_size == frame_size*8);
1189 } else { /* elementary format */
1190 frame_end = frame + frame_size;
1193 while((nal_start = h264_next_nal(nal_start, frame_end-nal_start, &nal_size)) != NULL) {
1194 ENCODER_ASSERT(nal_size);
1196 nal_start += nal_size;
1199 h264_bitstream_write_uint(&bitstream, nal_size, 32);
1200 h264_bitstream_write_byte_array(&bitstream, nal_start, nal_size);
1201 nal_start += nal_size;
1204 h264_bitstream_align(&bitstream, 0);
1206 GST_BUFFER_MALLOCDATA(ret_buffer) =
1207 GST_BUFFER_DATA(ret_buffer) = BIT_STREAM_BUFFER(&bitstream);
1208 GST_BUFFER_SIZE(ret_buffer) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
1209 h264_bitstream_destroy(&bitstream, FALSE);
1216 static EncoderStatus
1217 h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const guint8 *buf, guint32 size)
1219 const guint8 *end = buf + size;
1220 const guint8 *nal_start = buf;
1221 guint32 nal_size = 0;
1223 GstBuffer *sps = NULL, *pps = NULL;
1225 while((!sps || !pps) && (nal_start = h264_next_nal(nal_start, end-nal_start, &nal_size)) != NULL) {
1227 nal_start += nal_size;
1231 nal_type = (*nal_start)&0x1F;
1234 sps = gst_buffer_new_and_alloc(nal_size);
1235 memcpy(GST_BUFFER_DATA(sps), nal_start, nal_size);
1236 gst_buffer_replace(&h264_prv->sps_data, sps);
1237 gst_buffer_unref(sps); /*don't set to NULL*/
1242 pps = gst_buffer_new_and_alloc(nal_size);
1243 memcpy(GST_BUFFER_DATA(pps), nal_start, nal_size);
1244 gst_buffer_replace(&h264_prv->pps_data, pps);
1245 gst_buffer_unref(pps);
1252 nal_start += nal_size;
1256 return ENCODER_DATA_NOT_READY;
1258 return ENCODER_NO_ERROR;
1262 h264_read_sps_attributes(const guint8 *sps_data, guint32 sps_size,
1263 guint32 *profile_idc, guint32 *profile_comp, guint32 *level_idc)
1265 ENCODER_ASSERT(profile_idc && profile_comp && level_idc);
1266 ENCODER_ASSERT(sps_size >= 4);
1270 /*skip sps_data[0], nal_type*/
1271 *profile_idc = sps_data[1];
1272 *profile_comp = sps_data[2];
1273 *level_idc = sps_data[3];
1279 gst_h264_encoder_flush(GstVaapiEncoder* encoder, GstVaapiDisplay *display,
1280 GstVaapiContext *context, GList **coded_pics)
1282 GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
1283 EncoderStatus ret = ENCODER_NO_ERROR;
1284 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
1286 h264_prv->frame_count = 0;
1287 /*do we need destroy h264_prv->seq_parameter? */
1294 static int draw_picture(int width, int height,
1295 unsigned char *Y_start,
1296 unsigned char *U_start,
1297 unsigned char *V_start,
1298 int UV_interleave, int box_width, int row_shift);
1300 int main_test(int argc, char* argv[])
1302 EncoderStatus ret = ENCODER_NO_ERROR;
1303 GstVaapiEncoder *encoder = NULL;
1305 GList *coded_pics = NULL;
1306 GstBuffer **raw_buffer = NULL;
1307 const guint32 raw_buffer_num = 20;
1309 GstBuffer *tmp_buffer;
1311 guint32 i = 0, k = 0;
1313 gst_init (&argc, &argv);
1316 if (!g_thread_supported ())
1317 g_thread_init (NULL);
1319 GstH264Encoder *h264_encoder = gst_h264_encoder_new();
1320 encoder = GST_VAAPI_ENCODER(h264_encoder);
1321 ENCODER_ASSERT(encoder);
1323 h264_encoder->profile = 64;
1324 h264_encoder->level = 30;
1325 h264_encoder->parent.width = 1280;
1326 h264_encoder->parent.height = 720;
1327 h264_encoder->parent.frame_rate = 10;
1328 h264_encoder->bitrate = 512*1000;
1329 h264_encoder->intra_period = 30;
1330 ret = gst_vaapi_encoder_initialize(encoder);
1331 ENCODER_ASSERT(ret == ENCODER_NO_ERROR);
1332 ret = gst_vaapi_encoder_open(encoder, NULL);
1333 ENCODER_ASSERT(ret == ENCODER_NO_ERROR);
1335 guint32 buffer_size = encoder->width * encoder->width *3 /2;
1336 guint32 y_width = encoder->width, y_size = encoder->width * encoder->height;
1337 guint32 u_width = encoder->width/2, u_size = (encoder->width/2) * (encoder->height/2);
1338 guint32 v_width = encoder->width/2;
1339 guint8 *y_src, *u_src, *v_src;
1344 raw_buffer = (GstBuffer**)g_malloc0(raw_buffer_num*sizeof(GstBuffer*));
1345 for (i = 0; i < raw_buffer_num; i++) {
1346 raw_buffer[i] = gst_buffer_new_and_alloc(buffer_size);
1347 y_src = GST_BUFFER_DATA(raw_buffer[i]);
1348 u_src = y_src + y_size;
1349 v_src = u_src + u_size;
1351 draw_picture(encoder->width, encoder->height, y_src, u_src, v_src, 0, box_width, row_shift);
1353 if (row_shift==(2*box_width)) row_shift= 0;
1356 FILE *fp = fopen("tmp.h264", "wb");
1361 for (i = 0; i < 50; i++) {
1363 ret = gst_vaapi_encoder_encode(encoder, raw_buffer[k], &coded_pics);
1364 ENCODER_ASSERT(ENCODER_NO_ERROR == ret);
1366 if (k >= raw_buffer_num) k = 0;
1368 while (coded_pics) {
1369 tmp_buffer = coded_pics->data;
1370 coded_pics = g_list_remove(coded_pics, tmp_buffer);
1371 fwrite(GST_BUFFER_DATA(tmp_buffer), GST_BUFFER_SIZE(tmp_buffer), 1, fp);
1372 printf("F:%d, S:%d, %s\n", i, GST_BUFFER_SIZE(tmp_buffer), vaapi_encoder_dump_bytes(GST_BUFFER_DATA(tmp_buffer)+4, 8));
1373 gst_buffer_unref(tmp_buffer);
1378 ret = gst_vaapi_encoder_close(encoder);
1379 ENCODER_ASSERT(ENCODER_NO_ERROR == ret);
1381 for (i = 0; i < raw_buffer_num; i++) {
1382 gst_buffer_unref(raw_buffer[i]);
1385 gst_vaapi_encoder_unref(encoder);
1391 gst_h264_encoder_get_avcC_codec_data(GstVaapiEncoder *encoder, GstBuffer **buffer)
1393 GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
1394 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
1395 GstBuffer *avc_codec;
1396 const guint32 configuration_version = 0x01;
1397 const guint32 length_size_minus_one = 0x03;
1398 guint32 profile, profile_comp, level_idc;
1400 ENCODER_ASSERT(buffer);
1401 if (!h264_prv->sps_data || !h264_prv->pps_data) {
1402 return ENCODER_DATA_NOT_READY;
1405 if (FALSE == h264_read_sps_attributes(GST_BUFFER_DATA(h264_prv->sps_data),
1406 GST_BUFFER_SIZE(h264_prv->sps_data),
1407 &profile, &profile_comp, &level_idc))
1410 return ENCODER_DATA_ERR;
1413 H264Bitstream bitstream;
1414 h264_bitstream_init(&bitstream,
1415 (GST_BUFFER_SIZE(h264_prv->sps_data)+GST_BUFFER_SIZE(h264_prv->pps_data) + 32)*8);
1418 h264_bitstream_write_uint(&bitstream, configuration_version, 8);
1419 h264_bitstream_write_uint(&bitstream, profile, 8);
1420 h264_bitstream_write_uint(&bitstream, profile_comp, 8);
1421 h264_bitstream_write_uint(&bitstream, level_idc, 8);
1422 h264_bitstream_write_uint(&bitstream, h264_bit_mask[6], 6); /*111111*/
1423 h264_bitstream_write_uint(&bitstream, length_size_minus_one, 2);
1424 h264_bitstream_write_uint(&bitstream, h264_bit_mask[3], 3); /*111*/
1427 h264_bitstream_write_uint(&bitstream, 1, 5); /* sps count = 1*/
1428 ENCODER_ASSERT( BIT_STREAM_BIT_SIZE(&bitstream)%8 == 0);
1429 h264_bitstream_write_uint(&bitstream, GST_BUFFER_SIZE(h264_prv->sps_data), 16);
1430 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->sps_data),
1431 GST_BUFFER_SIZE(h264_prv->sps_data));
1434 h264_bitstream_write_uint(&bitstream, 1, 8); /*pps count = 1*/
1435 h264_bitstream_write_uint(&bitstream, GST_BUFFER_SIZE(h264_prv->pps_data), 16);
1436 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->pps_data),
1437 GST_BUFFER_SIZE(h264_prv->pps_data));
1439 avc_codec = gst_buffer_new();
1440 GST_BUFFER_MALLOCDATA(avc_codec) =
1441 GST_BUFFER_DATA(avc_codec) =
1442 BIT_STREAM_BUFFER(&bitstream);
1443 GST_BUFFER_SIZE(avc_codec) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
1444 h264_bitstream_destroy(&bitstream, FALSE);
1445 *buffer = avc_codec;
1447 return ENCODER_NO_ERROR;
1451 gst_h264_encoder_get_nal_codec_data(GstVaapiEncoder *encoder, GstBuffer **buffer)
1453 GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
1454 GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
1455 GstBuffer *nal_sps_pps;
1457 ENCODER_ASSERT(buffer);
1458 if (!h264_prv->sps_data || !h264_prv->pps_data) {
1459 return ENCODER_DATA_NOT_READY;
1462 H264Bitstream bitstream;
1463 h264_bitstream_init(&bitstream,
1464 (GST_BUFFER_SIZE(h264_prv->sps_data)+GST_BUFFER_SIZE(h264_prv->pps_data) + 8)*8);
1466 /*0x000001 start code*/
1467 h264_bitstream_write_uint(&bitstream, 0x000001, 24);
1468 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->sps_data),
1469 GST_BUFFER_SIZE(h264_prv->sps_data));
1470 h264_bitstream_write_uint(&bitstream, 0x000001, 24);
1471 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->pps_data),
1472 GST_BUFFER_SIZE(h264_prv->pps_data));
1474 nal_sps_pps = gst_buffer_new();
1475 GST_BUFFER_MALLOCDATA(nal_sps_pps) =
1476 GST_BUFFER_DATA(nal_sps_pps) =
1477 BIT_STREAM_BUFFER(&bitstream);
1478 GST_BUFFER_SIZE(nal_sps_pps) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
1479 h264_bitstream_destroy(&bitstream, FALSE);
1480 *buffer = nal_sps_pps;
1481 return ENCODER_NO_ERROR;
1485 h264_bitstream_init(H264Bitstream *bitstream, guint32 bit_capability)
1487 bitstream->bit_size = 0;
1488 bitstream->buffer = NULL;
1489 bitstream->max_bit_capability = 0;
1490 if (bit_capability) {
1491 h264_bitstream_auto_grow(bitstream, bit_capability);
1496 h264_bitstream_write_uint(H264Bitstream *bitstream, guint32 value, guint32 bit_size)
1498 gboolean ret = TRUE;
1499 guint32 byte_pos, bit_offset;
1507 ENCODER_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, bit_size), FALSE, "h264_bitstream_auto_grow failed.\n");
1508 byte_pos = (bitstream->bit_size>>3);
1509 bit_offset = (bitstream->bit_size&0x07);
1510 cur_byte = bitstream->buffer + byte_pos;
1511 ENCODER_ASSERT(bit_offset < 8 && bitstream->bit_size <= bitstream->max_bit_capability);
1514 fill_bits = ((8-bit_offset) < bit_size ? (8-bit_offset) : bit_size);
1515 bit_size -= fill_bits;
1516 bitstream->bit_size += fill_bits;
1518 *cur_byte |= ((value>>bit_size) & h264_bit_mask[fill_bits])<<(8-bit_offset-fill_bits);
1522 ENCODER_ASSERT(cur_byte <= bitstream->buffer + bitstream->max_bit_capability/8);
1529 static gboolean h264_bitstream_align(H264Bitstream *bitstream, guint32 value)
1531 guint32 bit_offset, bit_left;
1533 bit_offset = (bitstream->bit_size&0x07);
1537 bit_left = 8 - bit_offset;
1538 if (value) value = h264_bit_mask[bit_left];
1539 return h264_bitstream_write_uint(bitstream, value, bit_left);
1544 h264_bitstream_write_byte_array(H264Bitstream *bitstream, const guint8 *buf, guint32 byte_size)
1546 gboolean ret = TRUE;
1550 ENCODER_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, byte_size<<3), FALSE, "h264_bitstream_auto_grow failed.\n");
1551 if (0 == (bitstream->bit_size&0x07)) {
1552 memcpy(&bitstream->buffer[bitstream->bit_size>>3], buf, byte_size);
1553 bitstream->bit_size += (byte_size<<3);
1557 h264_bitstream_write_uint(bitstream, *buf, 8);
1569 h264_bitstream_write_ue(H264Bitstream *bitstream, guint32 value)
1571 gboolean ret = TRUE;
1572 guint32 size_in_bits = 0;
1573 guint32 tmp_value = ++value;
1578 ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, 0, size_in_bits-1), FALSE, "h264_bitstream_write_ue failed.\n");
1579 ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, value, size_in_bits), FALSE, "h264_bitstream_write_ue failed.\n");
1587 h264_bitstream_write_se(H264Bitstream *bitstream, guint32 value)
1589 gboolean ret = TRUE;
1593 new_val = -(value<<1);
1595 new_val = (value<<1) - 1;
1598 ENCODER_CHECK_STATUS(h264_bitstream_write_ue(bitstream, new_val), FALSE, "h264_bitstream_write_se failed.\n");
1606 h264_bitstream_write_trailing_bits(H264Bitstream *bitstream)
1608 h264_bitstream_write_uint(bitstream, 1, 1);
1609 h264_bitstream_align(bitstream, 0);
1614 h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag)
1616 if (bitstream->buffer && free_flag) {
1617 free (bitstream->buffer);
1619 bitstream->buffer = NULL;
1620 bitstream->bit_size = 0;
1621 bitstream->max_bit_capability = 0;
1625 h264_bitstream_auto_grow(H264Bitstream *bitstream, guint32 extra_bit_size)
1627 guint32 new_bit_size = extra_bit_size + bitstream->bit_size;
1630 ENCODER_ASSERT(bitstream->bit_size <= bitstream->max_bit_capability);
1631 if (new_bit_size <= bitstream->max_bit_capability) {
1635 new_bit_size = ((new_bit_size + H264_BITSTREAM_ALLOC_ALIGN_MASK)
1636 &(~H264_BITSTREAM_ALLOC_ALIGN_MASK));
1637 ENCODER_ASSERT(new_bit_size%(H264_BITSTREAM_ALLOC_ALIGN_MASK+1) == 0);
1638 clear_pos = ((bitstream->bit_size+7)>>3);
1639 bitstream->buffer = realloc(bitstream->buffer, new_bit_size>>3);
1640 memset(bitstream->buffer+clear_pos, 0, (new_bit_size>>3)-clear_pos);
1641 bitstream->max_bit_capability = new_bit_size;
1646 h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv)
1648 guint32 constraint_set0_flag, constraint_set1_flag, constraint_set2_flag, constraint_set3_flag;
1649 guint32 seq_parameter_set_id = 0;
1651 /*need to set the values*/
1652 guint32 log2_max_frame_num_minus4 = 0; // 1? 3?
1653 guint32 pic_order_cnt_type = 0; // Must be 0
1654 guint32 log2_max_pic_order_cnt_lsb_minus4 = 0; // 2 ? 4?
1655 guint32 num_ref_frames = 1; // only P frames
1656 guint32 gaps_in_frame_num_value_allowed_flag = 0; // ??
1657 guint32 mb_width = (ENCODER_WIDTH(h264_prv->public)+15)/16; // mb_width
1658 guint32 mb_height = (ENCODER_HEIGHT(h264_prv->public)+15)/16; // mb_height
1659 guint32 frame_mbs_only_flag = 1; // only mbs
1660 guint32 frame_cropping_flag = 0;
1661 guint32 frame_crop_bottom_offset = 0;
1662 guint32 vui_present_flag = 0; // no vui flags
1665 constraint_set0_flag = h264_prv->public->profile == H264_PROFILE_BASELINE;
1666 constraint_set1_flag = h264_prv->public->profile <= H264_PROFILE_MAIN;
1667 constraint_set2_flag = 0;
1668 constraint_set3_flag = 0;
1670 if (mb_height * 16 - ENCODER_HEIGHT(h264_prv->public)) {
1671 frame_cropping_flag = 1;
1672 frame_crop_bottom_offset =
1673 (mb_height * 16 - ENCODER_HEIGHT(h264_prv->public)) / (2 * (!frame_mbs_only_flag + 1));
1676 h264_bitstream_write_uint(bitstream, h264_prv->public->profile, 8); /* profile_idc */
1677 h264_bitstream_write_uint(bitstream, constraint_set0_flag, 1); /* constraint_set0_flag */
1678 h264_bitstream_write_uint(bitstream, constraint_set1_flag, 1); /* constraint_set1_flag */
1679 h264_bitstream_write_uint(bitstream, constraint_set2_flag, 1); /* constraint_set2_flag */
1680 h264_bitstream_write_uint(bitstream, constraint_set3_flag, 1); /* constraint_set3_flag */
1681 h264_bitstream_write_uint(bitstream, 0, 4); /* reserved_zero_4bits */
1682 h264_bitstream_write_uint(bitstream, h264_prv->public->level, 8); /* level_idc */
1683 h264_bitstream_write_ue(bitstream, seq_parameter_set_id); /* seq_parameter_set_id */
1685 if (h264_prv->public->profile >= H264_PROFILE_HIGH) {
1686 /* FIXME: fix for high profile */
1690 h264_bitstream_write_ue(bitstream, log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
1691 h264_bitstream_write_ue(bitstream, pic_order_cnt_type); /* pic_order_cnt_type */
1693 if (pic_order_cnt_type == 0)
1694 h264_bitstream_write_ue(bitstream, log2_max_pic_order_cnt_lsb_minus4);/* log2_max_pic_order_cnt_lsb_minus4 */
1699 h264_bitstream_write_ue(bitstream, num_ref_frames); /* num_ref_frames */
1700 h264_bitstream_write_uint(bitstream, gaps_in_frame_num_value_allowed_flag, 1); /* gaps_in_frame_num_value_allowed_flag */
1702 h264_bitstream_write_ue(bitstream, mb_width - 1); /* pic_width_in_mbs_minus1 */
1703 h264_bitstream_write_ue(bitstream, mb_height - 1); /* pic_height_in_map_units_minus1 */
1704 h264_bitstream_write_uint(bitstream, frame_mbs_only_flag, 1); /* frame_mbs_only_flag */
1706 if (!frame_mbs_only_flag) { //ONLY mbs
1710 h264_bitstream_write_uint(bitstream, 0, 1); /* direct_8x8_inference_flag */
1711 h264_bitstream_write_uint(bitstream, frame_cropping_flag, 1); /* frame_cropping_flag */
1713 if (frame_cropping_flag) {
1714 h264_bitstream_write_ue(bitstream, 0); /* frame_crop_left_offset */
1715 h264_bitstream_write_ue(bitstream, 0); /* frame_crop_right_offset */
1716 h264_bitstream_write_ue(bitstream, 0); /* frame_crop_top_offset */
1717 h264_bitstream_write_ue(bitstream, frame_crop_bottom_offset); /* frame_crop_bottom_offset */
1720 h264_bitstream_write_uint(bitstream, vui_present_flag, 1); /* vui_parameters_present_flag */
1721 h264_bitstream_write_trailing_bits(bitstream); /* rbsp_trailing_bits */
1729 static const guint8 *
1730 h264_next_nal(const guint8 *buffer, guint32 len, guint32 *nal_size)
1732 const guint8 *cur = buffer;
1733 const guint8 *end = buffer + len;
1734 const guint8 *nal_start = NULL;
1735 guint32 flag = 0xFFFFFFFF;
1736 guint32 nal_start_len = 0;
1738 ENCODER_ASSERT(len >= 0 && buffer && nal_size);
1741 nal_start = (len ? buffer : NULL);
1745 /*locate head postion*/
1746 if (!buffer[0] && !buffer[1]) {
1747 if (buffer[2] == 1) { // 0x000001
1749 } else if (!buffer[2] && len >=4 && buffer[3] == 1) { //0x00000001
1753 nal_start = buffer + nal_start_len;
1756 /*find next nal start position*/
1758 flag = ((flag<<8) | ((*cur++)&0xFF));
1759 if (flag == 0x00000001) {
1760 *nal_size = cur - 4 - nal_start;
1762 } else if ((flag&0x00FFFFFF) == 0x00000001) {
1763 *nal_size = cur - 3 - nal_start;
1768 *nal_size = end - nal_start;
1769 if (nal_start >= end) {
1778 h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv)
1784 static int draw_picture(int width, int height,
1785 unsigned char *Y_start,
1786 unsigned char *U_start,
1787 unsigned char *V_start,
1788 int UV_interleave, int box_width, int row_shift)
1792 int Y_pitch = width;
1793 int U_pitch = width/2;
1794 int V_pitch = width/2;
1797 for (row=0;row<height;row++) {
1798 unsigned char *Y_row = Y_start + row * Y_pitch;
1801 ypos = (row / box_width) & 0x1;
1803 /* fill garbage data into the other field */
1804 if (((field == 1) && (row &1))
1805 || ((field == 2) && ((row &1)==0))) {
1806 memset(Y_row, 0xff, width);
1810 for (jj=0; jj<width; jj++) {
1811 xpos = ((row_shift + jj) / box_width) & 0x1;
1813 if ((xpos == 0) && (ypos == 0))
1815 if ((xpos == 1) && (ypos == 1))
1818 if ((xpos == 1) && (ypos == 0))
1820 if ((xpos == 0) && (ypos == 1))
1826 for( row =0; row < height/2; row++) {
1827 unsigned short value = 0x80;
1829 /* fill garbage data into the other field */
1830 if (((field == 1) && (row &1))
1831 || ((field == 2) && ((row &1)==0))) {
1835 if (UV_interleave) {
1836 unsigned short *UV_row = (unsigned short *)(U_start + row * U_pitch);
1838 memset(UV_row, value, width);
1840 unsigned char *U_row = U_start + row * U_pitch;
1841 unsigned char *V_row = V_start + row * V_pitch;
1843 memset (U_row,value,width/2);
1844 memset (V_row,value,width/2);