2 #include "h264encoder.h"
11 #include "gst/gstclock.h"
12 #include "gst/gstvalue.h"
14 #include "gst/vaapi/gstvaapidisplay_x11.h"
15 #include "gst/vaapi/gstvaapiobject.h"
16 #include "gst/vaapi/gstvaapiobject_priv.h"
17 #include "gst/vaapi/gstvaapicontext.h"
18 #include "gst/vaapi/gstvaapisurface.h"
19 #include "gst/vaapi/gstvaapivideobuffer.h"
20 #include "gst/vaapi/gstvaapidisplay_priv.h"
22 #define ENCPRV(encoder) GST_H264_ENCODER_GET_PRIVATE(encoder)
24 #define H264_CHECK_STATUS(exp, err_num, err_reason, ...) \
28 H264_LOG_ERROR(err_reason, ## __VA_ARGS__); \
32 #define SHARE_CODED_BUF 0
34 #define DEFAULT_SURFACE_NUMBER 3
35 #define DEFAULT_CODEDBUF_NUM 5
36 #define DEFAULT_SID_INPUT 0 // suface_ids[0]
38 #define REF_RECON_SURFACE_NUM 2
40 typedef struct _GstH264EncodeBuffer GstH264EncodeBuffer;
42 #define GST_TYPE_H264_ENCODE_BUFFER (gst_h264_encode_buffer_get_type())
47 NAL_IDR = 5, /* ref_idc != 0 */
48 NAL_SEI = 6, /* ref_idc == 0 */
55 struct _GstH264EncodeBuffer {
58 GstH264EncoderPrivate *encoder;
61 struct _GstH264EncoderPrivate {
62 GstH264Encoder *public;
63 uint32_t format; /*NV12, I420,*/
64 gboolean es_flag; /*elementary flag*/
67 GstVaapiDisplay *vaapi_display;
68 GstVaapiContext *vaapi_context;
69 GQueue *video_buffer_caches; /*not used for baseline*/
71 GstVaapiSurface *ref_surface; /* reference buffer*/
72 GstVaapiSurface *recon_surface; /* reconstruct buffer*/
74 H264_Encode_State encode_state;
76 VABufferID seq_parameter;
77 VABufferID pic_parameter;
78 VABufferID slice_parameter;
80 VABufferID *coded_bufs;
81 uint32_t coded_buf_num;
82 uint32_t cur_coded_index;
84 /*total encoded frames*/
90 GMutex *code_buffer_lock;
91 GCond *code_buffer_cond;
92 GQueue *available_code_buffers;
96 G_DEFINE_TYPE(GstH264Encoder, gst_h264_encoder, G_TYPE_OBJECT);
100 #define H264_BITSTREAM_ALLOC_ALIGN_MASK 0x0FFF
102 #define BIT_STREAM_BUFFER(stream) ((stream)->buffer)
103 #define BIT_STREAM_BIT_SIZE(stream) ((stream)->bit_size)
105 struct _H264Bitstream {
108 uint32_t max_bit_capability;
111 typedef struct _H264Bitstream H264Bitstream;
113 static const uint8_t h264_bit_mask[9] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
115 static GstBufferClass *h264_encode_buffer_parent_class = NULL;
117 static void gst_h264_encoder_finalize(GObject *object);
119 static VAProfile h264_get_va_profile(uint32_t profile);
120 static H264Status h264_encoder_alloc_buffers(GstH264EncoderPrivate *h264_prv);
121 static H264Status h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv);
122 static H264Status h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
124 GstVaapiSurface *surface);
126 static H264Status h264_prepare_encoding(GstH264EncoderPrivate *h264_prv,
127 GstBuffer *raw_pic, gboolean is_key,
128 VABufferID coded_buf);
129 static H264Status h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
130 VASurfaceID surface_id,
132 GstClockTime timestamp,
133 GstClockTime duration,
134 VABufferID *coded_buf,
137 h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const uint8_t *buf, uint32_t size);
138 static GstBuffer *h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
141 VABufferID *coded_buf);
144 /*encoded buffer, for SHARE_CODED_BUF */
145 static void gst_h264_encode_buffer_class_init (gpointer g_class, gpointer class_data);
146 static GType gst_h264_encode_buffer_get_type (void);
147 static void gst_h264_encode_buffer_finalize (GstH264EncodeBuffer *h264_buffer);
148 static GstH264EncodeBuffer *gst_h264_encode_buffer_new(GstH264EncoderPrivate *h264_prv,
149 VABufferID *coded_id);
151 /* h264 bitstream functions */
152 static void h264_bitstream_init(H264Bitstream *bitstream, uint32_t bit_capability);
153 static gboolean h264_bitstream_write_uint(H264Bitstream *bitstream, uint32_t value, uint32_t bit_size);
154 static gboolean h264_bitstream_align(H264Bitstream *bitstream, uint32_t value);
155 static gboolean h264_bitstream_write_ue(H264Bitstream *bitstream, uint32_t value);
156 static gboolean h264_bitstream_write_se(H264Bitstream *bitstream, int32_t value);
157 static gboolean h264_bitstream_write_trailing_bits(H264Bitstream *bitstream);
159 static gboolean h264_bitstream_write_byte_array(H264Bitstream *bitstream, const uint8_t *buf, uint32_t byte_size);
160 static void h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag);
161 static gboolean h264_bitstream_auto_grow(H264Bitstream *bitstream, uint32_t extra_bit_size);
162 static gboolean h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv);
163 static gboolean h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv);
164 static const uint8_t *h264_next_nal(const uint8_t *buffer, uint32_t len, uint32_t *nal_size);
165 static gboolean h264_read_sps_attributes(const uint8_t *sps_data, uint32_t sps_size,
166 uint32_t *profile_idc, uint32_t *profile_comp, uint32_t *level_idc);
169 gst_h264_encoder_class_init(GstH264EncoderClass *klass)
171 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
172 g_type_class_add_private(klass, sizeof(GstH264EncoderPrivate));
174 object_class->finalize = gst_h264_encoder_finalize;
176 object_class->set_property = gst_h264_encoder_set_property;
177 object_class->get_property = gst_h264_encoder_get_property;
183 gst_h264_encode_buffer_class_init (gpointer g_class, gpointer class_data)
185 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS(g_class);
187 h264_encode_buffer_parent_class = g_type_class_peek_parent(g_class);
188 H264_ASSERT(h264_encode_buffer_parent_class);
190 mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
191 gst_h264_encode_buffer_finalize;
196 gst_h264_encode_buffer_get_type (void)
198 static GType s_h264_encode_buffer_type = 0;
199 if (G_UNLIKELY (s_h264_encode_buffer_type == 0)) {
200 static const GTypeInfo s_h264_encode_buffer_info = {
201 sizeof(GstBufferClass),
204 gst_h264_encode_buffer_class_init,
207 sizeof(GstH264EncodeBuffer),
212 s_h264_encode_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
213 "GstH264EncodeBuffer", &s_h264_encode_buffer_info, 0);
215 return s_h264_encode_buffer_type;
219 gst_h264_encode_buffer_finalize (GstH264EncodeBuffer *h264_buffer)
221 GstH264EncoderPrivate *h264_prv = NULL;
222 VABufferID* coded_id = NULL;
224 h264_prv = h264_buffer->encoder;
225 coded_id = h264_buffer->coded_id;
227 H264_ASSERT(h264_prv->vaapi_display);
228 H264_ASSERT(h264_prv->vaapi_context);
229 VADisplay va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_display);
231 H264_ASSERT(h264_prv);
232 H264_ASSERT(coded_id && VA_INVALID_ID!= *coded_id);
233 H264_ASSERT(h264_prv->available_code_buffers);
235 g_mutex_lock(h264_prv->code_buffer_lock);
236 /*if (--(*h264_buffer->ref_coded_id) == 0) */
238 /*g_free(h264_buffer->ref_coded_id);*/
239 vaUnmapBuffer(va_dpy, *coded_id);
240 g_queue_push_head(h264_prv->available_code_buffers, coded_id);
241 g_cond_signal(h264_prv->code_buffer_cond);
244 g_mutex_unlock(h264_prv->code_buffer_lock);
246 if (GST_MINI_OBJECT_CLASS(h264_encode_buffer_parent_class)->finalize) {
247 GST_MINI_OBJECT_CLASS(h264_encode_buffer_parent_class)->finalize(GST_MINI_OBJECT(h264_buffer));
251 static GstH264EncodeBuffer *
252 gst_h264_encode_buffer_new(GstH264EncoderPrivate *h264_prv,
253 VABufferID *coded_id)
255 GstH264EncodeBuffer *buf = (GstH264EncodeBuffer*)gst_mini_object_new(GST_TYPE_H264_ENCODE_BUFFER);
256 buf->coded_id = coded_id;
257 buf->encoder = h264_prv;
262 static GstVaapiSurface *
263 h264_get_video_surface(GstH264EncoderPrivate *h264_prv, GstVaapiVideoBuffer *video_buffer)
266 GstVaapiSurface *ret = gst_vaapi_video_buffer_get_surface(video_buffer);
268 H264_CHECK_STATUS(ret, NULL, "video buffer doesn't have a surface");
270 g_queue_push_tail(h264_prv->video_buffer_caches,video_buffer);
271 gst_buffer_ref(GST_BUFFER(video_buffer));
280 h264_release_video_surface(GstH264EncoderPrivate *h264_prv, VASurfaceID surface)
283 H264_ASSERT(h264_prv->video_buffer_caches);
284 g_queue_find_custom(h264_prv->video_buffer_caches,xx, compare_func);
285 for (h264_prv->video_buffer_caches) {
290 static GstVaapiSurface *
291 h264_pop_free_surface(GstH264EncoderPrivate *h264_prv)
293 H264_ASSERT(h264_prv && h264_prv->vaapi_context);
296 GstVaapiSurface *surface = gst_vaapi_context_get_surface(h264_prv->vaapi_context);
301 h264_push_free_surface(GstH264EncoderPrivate *h264_prv, GstVaapiSurface *surface)
303 H264_ASSERT(surface);
307 gst_vaapi_context_put_surface(h264_prv->vaapi_context, surface);
311 H264_Encode_State gst_h264_encoder_get_state(GstH264Encoder* encoder)
313 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
314 return h264_prv->encode_state;
319 h264_get_va_profile(uint32_t profile)
322 case H264_PROFILE_BASELINE:
323 return VAProfileH264Baseline;
325 case H264_PROFILE_MAIN:
326 return VAProfileH264Main;
328 case H264_PROFILE_HIGH:
329 return VAProfileH264High;
338 gst_h264_encoder_new(void)
340 return GST_H264_ENCODER(g_object_new(GST_TYPE_H264_ENCODER, NULL));
345 gst_h264_encoder_init(GstH264Encoder *encoder)
347 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
348 H264_ASSERT(h264_prv);
350 /* init public attributes */
351 gst_h264_encoder_set_default_values(encoder);
353 /* init private values*/
354 h264_prv->public = encoder;
355 h264_prv->format = GST_MAKE_FOURCC('N','V','1','2');
356 h264_prv->es_flag = TRUE;
358 h264_prv->vaapi_display = NULL;
359 h264_prv->vaapi_context= NULL;
360 h264_prv->ref_surface = NULL;
361 h264_prv->recon_surface = NULL;
362 h264_prv->video_buffer_caches = g_queue_new();
364 h264_prv->encode_state = H264_ENC_NULL;
365 h264_prv->seq_parameter = VA_INVALID_ID;
366 h264_prv->pic_parameter = VA_INVALID_ID;
367 h264_prv->slice_parameter = VA_INVALID_ID;
369 h264_prv->coded_bufs = NULL;
370 h264_prv->coded_buf_num = DEFAULT_CODEDBUF_NUM;
371 h264_prv->frame_count = 0;
372 h264_prv->sps_data = NULL;
373 h264_prv->pps_data = NULL;
375 h264_prv->cur_coded_index = 0;
377 h264_prv->code_buffer_lock = g_mutex_new();
378 h264_prv->code_buffer_cond = g_cond_new();
379 h264_prv->available_code_buffers = g_queue_new();
384 gst_h264_encoder_finalize(GObject *object)
386 /*free private buffers*/
387 GstH264EncoderPrivate *h264_prv = ENCPRV(object);
389 g_mutex_free(h264_prv->code_buffer_lock);
390 g_cond_free(h264_prv->code_buffer_cond);
391 if (h264_prv->available_code_buffers) {
392 g_queue_free(h264_prv->available_code_buffers);
393 h264_prv->available_code_buffers = NULL;
396 if (h264_prv->ref_surface) {
397 if (h264_prv->vaapi_context) {
398 h264_push_free_surface(h264_prv, h264_prv->ref_surface);
400 g_object_unref(h264_prv->ref_surface);
402 h264_prv->ref_surface = NULL;
404 if (h264_prv->recon_surface) {
405 if (h264_prv->vaapi_context) {
406 h264_push_free_surface(h264_prv, h264_prv->recon_surface);
408 g_object_unref(h264_prv->recon_surface);
410 h264_prv->recon_surface = NULL;
412 if (h264_prv->vaapi_context) {
413 g_object_unref(h264_prv->vaapi_context);
414 h264_prv->vaapi_context= NULL;
416 if (h264_prv->vaapi_display) {
417 g_object_unref(h264_prv->vaapi_display);
418 h264_prv->vaapi_display = NULL;
420 if (h264_prv->video_buffer_caches) {
421 g_queue_free(h264_prv->video_buffer_caches);
422 h264_prv->video_buffer_caches = NULL;
424 if (h264_prv->sps_data) {
425 gst_buffer_unref(h264_prv->sps_data);
426 h264_prv->sps_data = NULL;
428 if (h264_prv->pps_data) {
429 gst_buffer_unref(h264_prv->pps_data);
430 h264_prv->pps_data = NULL;
436 gst_h264_encoder_set_default_values(GstH264Encoder* encoder)
438 encoder->profile = H264_DEFAULT_PROFILE;
439 encoder->level = H264_DEFAULT_LEVEL;
442 encoder->frame_rate = H264_DEFAULT_FPS;
443 encoder->bitrate = H264_DEFAULT_BITRATE;
444 encoder->intra_period = H264_DEFAULT_INTRA_PERIOD;
445 encoder->init_qp = H264_DEFAULT_INIT_QP;
449 gst_h264_encoder_set_input_format(GstH264Encoder* encoder, uint32_t format)
451 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
452 h264_prv->format = format;
456 gst_h264_encoder_set_es_flag(GstH264Encoder* encoder, gboolean es)
458 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
459 h264_prv->es_flag = es;
463 gst_h264_encoder_set_display(GstH264Encoder* encoder, GstVaapiDisplay *display)
465 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
466 if (display == h264_prv->vaapi_display) {
470 if (H264_ENC_INIT < h264_prv->encode_state) {
473 if (h264_prv->vaapi_display) {
474 g_object_unref(h264_prv->vaapi_display);
475 h264_prv->vaapi_display = NULL;
477 h264_prv->vaapi_display = g_object_ref(display);
482 gst_h264_encoder_get_display(GstH264Encoder* encoder)
484 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
485 return (h264_prv->vaapi_display ? g_object_ref(h264_prv->vaapi_display) : NULL);
490 gst_h264_encoder_initialize(GstH264Encoder* encoder)
492 H264Status ret = H264_NO_ERROR;
493 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
494 VAStatus va_status = VA_STATUS_SUCCESS;
495 int major_ver, minor_ver;
498 if (H264_ENC_INIT == h264_prv->encode_state) {
499 return H264_NO_ERROR;
501 H264_ASSERT(H264_ENC_NULL == h264_prv->encode_state);
502 if (H264_ENC_NULL != h264_prv->encode_state) {
503 return H264_STATE_ERR;
507 if (!h264_prv->vaapi_display) {
508 h264_prv->vaapi_display = gst_vaapi_display_x11_new(NULL);
509 H264_CHECK_STATUS(h264_prv->vaapi_display, H264_DISPLAY_ERR, "gst_vaapi_display_x11_new failed.\n");
512 h264_prv->encode_state = H264_ENC_INIT;
513 return H264_NO_ERROR;
516 gst_h264_encoder_uninitialize(encoder);
521 gst_h264_encoder_uninitialize(GstH264Encoder* encoder)
523 H264Status ret = H264_NO_ERROR;
524 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
526 /* release buffers first */
527 if (H264_ENC_NULL == h264_prv->encode_state) {
528 return H264_NO_ERROR;
531 if (H264_ENC_INIT < h264_prv->encode_state) {
532 gst_h264_encoder_close(encoder);
535 H264_ASSERT(H264_ENC_INIT == h264_prv->encode_state);
538 if (h264_prv->vaapi_display) {
539 g_object_unref(h264_prv->vaapi_display);
540 h264_prv->vaapi_display = NULL;
543 h264_prv->encode_state = H264_ENC_NULL;
544 return H264_NO_ERROR;
553 gst_h264_encoder_open(GstH264Encoder* encoder, GstVaapiSurfacePool *surfaces_pool)
555 gst_h264_encoder_open(GstH264Encoder* encoder)
558 H264Status ret = H264_NO_ERROR;
559 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
560 VAProfile va_profile = h264_get_va_profile(encoder->profile);
561 VAEntrypoint entrypoints[5];
562 int num_entrypoints,slice_entrypoint;
563 VAConfigAttrib attrib[5];
564 VAStatus va_status = VA_STATUS_SUCCESS;
567 if (H264_ENC_OPENED == h264_prv->encode_state) {
568 return H264_NO_ERROR;
570 H264_ASSERT(H264_ENC_INIT == h264_prv->encode_state);
571 if (H264_ENC_INIT != h264_prv->encode_state) {
572 return H264_STATE_ERR;
575 H264_ASSERT(h264_prv->vaapi_display);
576 H264_ASSERT(!h264_prv->vaapi_context);
577 H264_CHECK_STATUS(encoder->width && encoder->height, H264_PARAMETER_ERR, "width/height was not set.\n");
578 H264_CHECK_STATUS(-1 != va_profile, H264_PROFILE_ERR, "profile(%d) is NOT supported.\n", encoder->profile);
581 h264_prv->vaapi_context = g_object_new(
582 GST_VAAPI_TYPE_CONTEXT,
583 "display", h264_prv->vaapi_display,
584 "id", GST_VAAPI_ID(VA_INVALID_ID),
585 "entrypoint", gst_vaapi_entrypoint(VAEntrypointEncSlice),
586 "width", h264_prv->public->width,
587 "height", h264_prv->public->height,
591 gst_vaapi_context_set_surface_pool(h264_prv->vaapi_context, surfaces_pool);
593 g_object_set(h264_prv->vaapi_context, "profile", gst_vaapi_profile(va_profile), NULL);
596 h264_prv->vaapi_context = gst_vaapi_context_new(h264_prv->vaapi_display,
597 gst_vaapi_profile(va_profile),
598 gst_vaapi_entrypoint(VAEntrypointEncSlice),
599 h264_prv->public->width,
600 h264_prv->public->height);
602 H264_CHECK_STATUS(h264_prv->vaapi_context, H264_CONTEXT_ERR, "gst_vaapi_context_new failed.\n");
603 ret = h264_encoder_alloc_buffers(h264_prv);
604 if (H264_NO_ERROR != ret) {
608 h264_prv->encode_state = H264_ENC_OPENED;
609 return H264_NO_ERROR;
613 gst_h264_encoder_close(encoder);
619 gst_h264_encoder_close(GstH264Encoder* encoder)
621 H264Status ret = H264_NO_ERROR;
622 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
624 if (H264_ENC_INIT >= h264_prv->encode_state) {
625 return H264_NO_ERROR;
628 /* release buffers first */
629 if (H264_ENC_OPENED <= h264_prv->encode_state) {
630 h264_encoder_release_buffers(h264_prv);
633 /*remove ref_surface*/
634 if (h264_prv->ref_surface) {
635 if (h264_prv->vaapi_context) {
636 h264_push_free_surface(h264_prv, h264_prv->ref_surface);
638 g_object_unref(h264_prv->ref_surface);
640 h264_prv->ref_surface = NULL;
643 /*remove recon_surface*/
644 if (h264_prv->recon_surface) {
645 if (h264_prv->vaapi_context) {
646 h264_push_free_surface(h264_prv, h264_prv->recon_surface);
648 g_object_unref(h264_prv->recon_surface);
650 h264_prv->recon_surface = NULL;
653 /*remove vaapi_context*/
654 if (h264_prv->vaapi_context) {
655 g_object_unref(h264_prv->vaapi_context);
656 h264_prv->vaapi_context = NULL;
659 h264_prv->frame_count = 0;
660 h264_prv->encode_state = H264_ENC_INIT;
662 if (h264_prv->sps_data) {
663 gst_buffer_unref(h264_prv->sps_data);
664 h264_prv->sps_data = NULL;
666 if (h264_prv->pps_data) {
667 gst_buffer_unref(h264_prv->pps_data);
668 h264_prv->pps_data = NULL;
674 h264_encoder_alloc_buffers(GstH264EncoderPrivate *h264_prv)
676 H264Status ret = H264_NO_ERROR;
677 VAStatus va_status = VA_STATUS_SUCCESS;
680 H264_ASSERT(h264_prv->vaapi_display);
681 H264_ASSERT(h264_prv->vaapi_context);
682 VADisplay va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_display);
683 VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
684 gboolean is_locked = FALSE;
686 GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
689 /* 1. create sequence parameter set */
691 VAEncSequenceParameterBufferH264 seq_h264 = {0};
693 seq_h264.level_idc = h264_prv->public->level; /* 3.0 */
694 seq_h264.max_num_ref_frames = 1; /*Only I, P frames*/
695 seq_h264.picture_width_in_mbs = (h264_prv->public->width+15)/16;
696 seq_h264.picture_height_in_mbs = (h264_prv->public->height+15)/16;
698 seq_h264.bits_per_second = h264_prv->public->bitrate;
699 seq_h264.frame_rate = h264_prv->public->frame_rate;
700 seq_h264.initial_qp = h264_prv->public->init_qp; /*qp_value; 15, 24, 26?*/
701 seq_h264.min_qp = 1; /*0, 3, 10*/
702 seq_h264.basic_unit_size = 0;
703 seq_h264.intra_period = h264_prv->public->intra_period;
704 seq_h264.intra_idr_period = h264_prv->public->intra_period;
706 va_status = vaCreateBuffer(va_dpy, context_id,
707 VAEncSequenceParameterBufferType,
708 sizeof(seq_h264), 1, &seq_h264, &h264_prv->seq_parameter);
709 H264_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, H264_ENC_RES_ERR, "alloc seq-buffer failed.\n");
712 /* 2. create coded buffers */
713 h264_prv->coded_bufs = (VABufferID*)g_malloc0(h264_prv->coded_buf_num * sizeof(h264_prv->coded_bufs[0]));
714 { // check width, height ????
715 uint32_t codedbuf_size = (h264_prv->public->width * h264_prv->public->height * 400) / (16*16);
716 for (i = 0; i < h264_prv->coded_buf_num; i++) {
717 va_status = vaCreateBuffer(va_dpy, context_id,VAEncCodedBufferType,
718 codedbuf_size, 1, NULL, &h264_prv->coded_bufs[i]);
720 H264_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, H264_ENC_RES_ERR, "alloc coded buffer failed.\n");
725 GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
728 H264_ASSERT(h264_prv->available_code_buffers);
730 /* 3. init queue available_code_buffers */
731 g_mutex_lock(h264_prv->code_buffer_lock);
732 for (i = 0; i < h264_prv->coded_buf_num; i++) {
733 g_queue_push_tail (h264_prv->available_code_buffers, &h264_prv->coded_bufs[i]);
735 g_cond_signal(h264_prv->code_buffer_cond);
736 g_mutex_unlock(h264_prv->code_buffer_lock);
738 return H264_NO_ERROR;
742 GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
750 h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv)
752 VAStatus va_status = VA_STATUS_SUCCESS;
753 uint32_t available_buf_count = h264_prv->coded_buf_num;
756 H264_ASSERT(h264_prv->vaapi_display);
757 H264_ASSERT(h264_prv->vaapi_context);
758 VADisplay va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_display);
760 /* wait for all coded buffer freed*/
761 g_mutex_lock(h264_prv->code_buffer_lock);
762 while (available_buf_count) {
763 if (g_queue_is_empty(h264_prv->available_code_buffers)) {
764 g_cond_wait(h264_prv->code_buffer_cond, h264_prv->code_buffer_lock);
766 g_queue_pop_head(h264_prv->available_code_buffers);
767 available_buf_count--;
770 g_mutex_unlock(h264_prv->code_buffer_lock);
772 GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
773 for (i = 0; i < h264_prv->coded_buf_num; i++) {
774 va_status = vaDestroyBuffer(va_dpy, h264_prv->coded_bufs[i]);
776 va_status = vaDestroyBuffer(va_dpy, h264_prv->seq_parameter);
777 GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
779 if (h264_prv->coded_bufs) {
780 g_free(h264_prv->coded_bufs);
781 h264_prv->coded_bufs = NULL;
784 return H264_NO_ERROR;
788 gst_h264_encoder_encode(GstH264Encoder* encoder, GstBuffer *raw_pic, GList **coded_pics)
790 H264Status ret = H264_NO_ERROR;
791 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
792 gboolean is_key = FALSE;
793 VABufferID* coded_buf = NULL;
794 VAStatus va_status = VA_STATUS_SUCCESS;
795 VASurfaceID buffer_surface_id = VA_INVALID_SURFACE;
796 GstVaapiSurface *buffer_surface = NULL;
798 H264_ASSERT(h264_prv->vaapi_display);
799 H264_ASSERT(h264_prv->vaapi_context);
800 VADisplay va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_display);
801 VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
802 GstVaapiSurface *new_surface = NULL;
804 H264_CHECK_STATUS(h264_prv->encode_state >= H264_ENC_OPENED, H264_STATE_ERR, "H264 encoder was not opened.\n");
805 if (h264_prv->encode_state < H264_ENC_ENCODING) {
806 h264_prv->encode_state = H264_ENC_ENCODING;
809 if (GST_VAAPI_IS_VIDEO_BUFFER(raw_pic)) {
810 buffer_surface = h264_get_video_surface(h264_prv, GST_VAAPI_VIDEO_BUFFER(raw_pic));
812 new_surface = h264_pop_free_surface(h264_prv);
813 buffer_surface = new_surface;
814 H264_CHECK_STATUS(buffer_surface, H264_SURFACE_ERR, "h264_pop_free_surface failed.\n");
816 /*input picture to h264_prv->cur_surface_index*/
817 va_status = h264_put_raw_buffer_to_surface(h264_prv, raw_pic, buffer_surface);
818 H264_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, H264_PICTURE_ERR, "va put buffer to surface failed.\n");
820 buffer_surface_id = (VASurfaceID)GST_VAAPI_OBJECT_ID(buffer_surface);
821 H264_CHECK_STATUS(buffer_surface_id != VA_INVALID_SURFACE, H264_SURFACE_ERR, "surface id == VA_INVALID_SURFACE.\n");
823 /* begin picture, using default sid 0*/
824 GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
825 va_status = vaBeginPicture(va_dpy, context_id, buffer_surface_id);
826 GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
828 H264_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, H264_PICTURE_ERR, "vaBeginPicture error.\n");
830 /* set input buffers*/
831 is_key = ((h264_prv->frame_count % encoder->intra_period) == 0);
833 /*get valid coded buffer*/
834 g_mutex_lock(h264_prv->code_buffer_lock);
835 H264_ASSERT(h264_prv->available_code_buffers);
836 while (g_queue_is_empty(h264_prv->available_code_buffers)) {
837 g_cond_wait(h264_prv->code_buffer_cond, h264_prv->code_buffer_lock);
840 coded_buf = (VABufferID*)g_queue_pop_head (h264_prv->available_code_buffers);
841 ret = h264_prepare_encoding(h264_prv, raw_pic, is_key, *coded_buf);
842 if (H264_NO_ERROR != ret) {
843 g_queue_push_head(h264_prv->available_code_buffers, coded_buf);
845 g_mutex_unlock(h264_prv->code_buffer_lock);
847 H264_CHECK_STATUS(H264_NO_ERROR == ret, H264_PICTURE_ERR, "h264_prepare_encoding failed.\n");
850 GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
851 va_status = vaEndPicture(va_dpy, context_id);
852 GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
853 H264_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, H264_PICTURE_ERR, "vaEndPicture error.\n");
855 /*query surface result*/
856 ret = h264_query_encoding_status(h264_prv, buffer_surface_id,
857 is_key, GST_BUFFER_TIMESTAMP(raw_pic), GST_BUFFER_DURATION(raw_pic), coded_buf, coded_pics);
858 if (H264_NO_ERROR != ret) {
862 h264_prv->frame_count++;
867 h264_push_free_surface(h264_prv, new_surface);
873 h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
875 GstVaapiSurface *surface)
877 H264Status ret = H264_NO_ERROR;
878 VAStatus va_status = VA_STATUS_SUCCESS;
879 VAImage surface_image;
881 GstVaapiImage *image;
882 GstVaapiImageFormat image_format;
883 uint8_t *y_src = NULL, *u_src = NULL, *v_src = NULL;
884 uint8_t *y_dst = NULL, *u_dst = NULL, *v_dst = NULL;
885 int y_size = 0, u_size = 0;
886 int row = 0, col = 0;
887 uint32_t plane_count = 0;
888 uint32_t image_width = 0, image_height = 0;
889 uint32_t pitchy = 0, pitchu = 0, pitchv = 0;
891 H264_ASSERT(h264_prv->vaapi_display);
892 va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_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 H264_ASSERT(GST_BUFFER_SIZE(raw_pic) >= y_size + (y_size>>1));
904 y_size = h264_prv->public->width * h264_prv->public->height;
905 u_size = ((h264_prv->public->width+1) >> 1) * ((h264_prv->public->height+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 += h264_prv->public->width;
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 += (h264_prv->public->width>>1);
940 v_src += (h264_prv->public->width>>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 += h264_prv->public->width;
952 /* FIXME: fix this later */
957 g_object_unref(image);
964 h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gboolean is_key, VABufferID coded_buf)
966 H264Status ret = H264_NO_ERROR;
967 VAStatus va_status = VA_STATUS_SUCCESS;
969 VAEncPictureParameterBufferH264 pic_h264;
970 VAEncSliceParameterBuffer slice_h264;
972 H264_ASSERT(h264_prv->vaapi_display);
973 H264_ASSERT(h264_prv->vaapi_context);
974 VADisplay va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_display);
975 VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
978 GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
979 /*handle first surface_index*/
980 /*only need first frame*/
981 if (h264_prv->frame_count == 0) {
982 va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->seq_parameter, 1);
983 H264_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, H264_PICTURE_ERR, "vaRenderPicture seq-parameters failed.\n");
986 /* set pic_parameters*/
987 if (!h264_prv->ref_surface) {
988 h264_prv->ref_surface = h264_pop_free_surface(h264_prv);
989 H264_CHECK_STATUS(h264_prv->ref_surface, H264_SURFACE_ERR, "reference surface, h264_pop_free_surface failed.\n");
991 if (!h264_prv->recon_surface) {
992 h264_prv->recon_surface = h264_pop_free_surface(h264_prv);
993 H264_CHECK_STATUS(h264_prv->recon_surface, H264_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 = h264_prv->public->width;
999 pic_h264.picture_height = h264_prv->public->height;
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 H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_PICTURE_ERR, "creating pic-param buffer failed.\n");
1011 va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->pic_parameter, 1);
1012 H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_PICTURE_ERR, "rendering pic-param buffer failed.\n");
1014 /*set slice parameters*/
1015 /* one frame, one slice */
1016 memset(&slice_h264, 0, sizeof(slice_h264));
1017 slice_h264.start_row_number = 0;
1018 slice_h264.slice_height = (h264_prv->public->height+15)/16; /* Measured by MB */
1019 slice_h264.slice_flags.bits.is_intra = is_key;
1020 slice_h264.slice_flags.bits.disable_deblocking_filter_idc = 0;
1021 if (VA_INVALID_ID != h264_prv->slice_parameter) {
1022 vaDestroyBuffer(va_dpy, h264_prv->slice_parameter);
1023 h264_prv->slice_parameter = VA_INVALID_ID;
1025 va_status = vaCreateBuffer(va_dpy, context_id, VAEncSliceParameterBufferType,
1026 sizeof(slice_h264), 1, &slice_h264, &h264_prv->slice_parameter);
1027 H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_PICTURE_ERR, "creating slice-parameters buffer failed.\n");
1028 va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->slice_parameter, 1);
1029 H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_PICTURE_ERR, "rendering slice-parameters buffer failed.\n");
1032 /*after finished, set ref_surface_index, recon_surface_index */
1033 GstVaapiSurface *swap = h264_prv->ref_surface;
1034 h264_prv->ref_surface = h264_prv->recon_surface;
1035 h264_prv->recon_surface = swap;
1038 GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
1043 h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
1044 VASurfaceID surface_id,
1046 GstClockTime timestamp,
1047 GstClockTime duration,
1048 VABufferID *coded_buf,
1051 H264Status ret = H264_NO_ERROR;
1052 VAStatus va_status = VA_STATUS_SUCCESS;
1053 VASurfaceStatus surface_status = 0;
1054 VACodedBufferSegment *buf_list = NULL;
1055 GstBuffer* ret_buffer = NULL;
1056 gboolean has_coded_data = FALSE;
1057 gboolean is_locked = FALSE;
1059 H264_ASSERT(h264_prv->vaapi_display);
1060 H264_ASSERT(h264_prv->vaapi_context);
1061 VADisplay va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_display);
1062 //VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
1064 H264_ASSERT(coded_pics && *coded_pics == NULL);
1067 GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
1070 va_status = vaSyncSurface(va_dpy, surface_id);
1071 H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_QUERY_STATUS_ERR, "vaSyncSurface failed.\n");
1073 va_status = vaQuerySurfaceStatus(va_dpy, surface_id, &surface_status);
1074 H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_QUERY_STATUS_ERR, "vaQuerySurfaceStatus failed.\n");
1075 if (VASurfaceSkipped&surface_status) {
1076 H264_LOG_ERROR("frame skipped, dts:%" GST_TIME_FORMAT ".\n", GST_TIME_ARGS(timestamp));
1079 va_status = vaMapBuffer(va_dpy, *coded_buf, (void **)(&buf_list));
1080 H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_QUERY_STATUS_ERR, "vaMapBuffer failed.\n");
1084 GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
1088 while (buf_list != NULL) {
1089 if (!h264_prv->sps_data || !h264_prv->pps_data) {
1090 h264_encoder_read_sps_pps(h264_prv, buf_list->buf, buf_list->size);
1092 ret_buffer = h264_encoder_create_coded_buffer(h264_prv, buf_list->buf, buf_list->size, coded_buf);
1093 GST_BUFFER_TIMESTAMP(ret_buffer) = timestamp;
1094 GST_BUFFER_DURATION(ret_buffer) = duration;
1096 GST_BUFFER_FLAG_SET(ret_buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1098 *coded_pics = g_list_append(*coded_pics, ret_buffer);
1099 buf_list = (VACodedBufferSegment*)buf_list->next;
1100 H264_ASSERT(NULL == buf_list);
1101 has_coded_data = TRUE;
1105 if (!has_coded_data)
1107 { // if non-related, push back to available_code_buffers
1108 g_mutex_lock(h264_prv->code_buffer_lock);
1109 GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
1110 vaUnmapBuffer(va_dpy, *coded_buf);
1111 GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
1112 g_queue_push_head(h264_prv->available_code_buffers, coded_buf);
1113 g_cond_signal(h264_prv->code_buffer_cond);
1114 g_mutex_unlock(h264_prv->code_buffer_lock);
1117 return H264_NO_ERROR;
1122 GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
1129 h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
1131 uint32_t frame_size,
1132 VABufferID *coded_buf)
1134 GstBuffer *ret_buffer;
1136 const uint8_t *nal_start;
1140 ret_buffer = gst_h264_encode_buffer_new(h264_prv, coded_buf);
1141 H264_ASSERT(ret_buffer);
1142 GST_BUFFER_MALLOCDATA(ret_buffer) = NULL;
1143 GST_BUFFER_DATA(ret_buffer) = buf_list->buf;
1144 GST_BUFFER_SIZE(ret_buffer) = buf_list->size;
1146 ret_buffer = gst_buffer_new();
1147 H264_ASSERT(ret_buffer);
1148 H264Bitstream bitstream;
1149 h264_bitstream_init(&bitstream, (frame_size+32)*8);
1150 h264_bitstream_align(&bitstream, 0);
1151 H264_ASSERT(bitstream.bit_size == 0);
1153 if (!h264_prv->es_flag) { /*nal format*/
1154 h264_bitstream_write_byte_array(&bitstream, frame, frame_size);
1155 H264_ASSERT(bitstream.bit_size == frame_size*8);
1156 } else { /* elementary format */
1157 frame_end = frame + frame_size;
1160 while((nal_start = h264_next_nal(nal_start, frame_end-nal_start, &nal_size)) != NULL) {
1161 H264_ASSERT(nal_size);
1163 nal_start += nal_size;
1166 h264_bitstream_write_uint(&bitstream, nal_size, 32);
1167 h264_bitstream_write_byte_array(&bitstream, nal_start, nal_size);
1168 nal_start += nal_size;
1171 h264_bitstream_align(&bitstream, 0);
1173 GST_BUFFER_MALLOCDATA(ret_buffer) =
1174 GST_BUFFER_DATA(ret_buffer) = BIT_STREAM_BUFFER(&bitstream);
1175 GST_BUFFER_SIZE(ret_buffer) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
1176 h264_bitstream_destroy(&bitstream, FALSE);
1184 h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const uint8_t *buf, uint32_t size)
1186 const uint8_t *end = buf + size;
1187 const uint8_t *nal_start = buf;
1188 uint32_t nal_size = 0;
1190 GstBuffer *sps = NULL, *pps = NULL;
1192 while((!sps || !pps) && (nal_start = h264_next_nal(nal_start, end-nal_start, &nal_size)) != NULL) {
1194 nal_start += nal_size;
1198 nal_type = (*nal_start)&0x1F;
1201 sps = gst_buffer_new_and_alloc(nal_size);
1202 memcpy(GST_BUFFER_DATA(sps), nal_start, nal_size);
1203 gst_buffer_replace(&h264_prv->sps_data, sps);
1204 gst_buffer_unref(sps); /*don't set to NULL*/
1209 pps = gst_buffer_new_and_alloc(nal_size);
1210 memcpy(GST_BUFFER_DATA(pps), nal_start, nal_size);
1211 gst_buffer_replace(&h264_prv->pps_data, pps);
1212 gst_buffer_unref(pps);
1219 nal_start += nal_size;
1223 return H264_DATA_NOT_READY;
1225 return H264_NO_ERROR;
1229 h264_read_sps_attributes(const uint8_t *sps_data, uint32_t sps_size,
1230 uint32_t *profile_idc, uint32_t *profile_comp, uint32_t *level_idc)
1232 H264_ASSERT(profile_idc && profile_comp && level_idc);
1233 H264_ASSERT(sps_size >= 4);
1237 /*skip sps_data[0], nal_type*/
1238 *profile_idc = sps_data[1];
1239 *profile_comp = sps_data[2];
1240 *level_idc = sps_data[3];
1246 gst_h264_encoder_flush(GstH264Encoder* encoder, GList *coded_pics)
1248 H264Status ret = H264_NO_ERROR;
1249 //GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
1256 static int draw_picture(int width, int height,
1257 unsigned char *Y_start,
1258 unsigned char *U_start,
1259 unsigned char *V_start,
1260 int UV_interleave, int box_width, int row_shift);
1262 int main_test(int argc, const char* argv[])
1264 H264Status ret = H264_NO_ERROR;
1265 GstH264Encoder *encoder = NULL;
1267 GList *coded_pics = NULL;
1268 GstBuffer **raw_buffer = NULL;
1269 const uint32_t raw_buffer_num = 20;
1271 GstBuffer *tmp_buffer;
1273 uint32_t i = 0, k = 0;
1275 gst_init (&argc, &argv);
1278 if (!g_thread_supported ())
1279 g_thread_init (NULL);
1281 encoder = gst_h264_encoder_new();
1282 H264_ASSERT(encoder && ret == H264_NO_ERROR);
1284 encoder->profile = 64;
1285 encoder->level = 30;
1286 encoder->width = 1280;
1287 encoder->height = 720;
1288 encoder->frame_rate = 10;
1289 encoder->bitrate = 512*1000;
1290 encoder->intra_period = 30;
1291 ret = gst_h264_encoder_initialize(encoder);
1292 H264_ASSERT(ret == H264_NO_ERROR);
1294 ret = gst_h264_encoder_open(encoder, NULL);
1296 ret = gst_h264_encoder_open(encoder);
1298 H264_ASSERT(ret == H264_NO_ERROR);
1300 uint32_t buffer_size = encoder->width * encoder->height *3 /2;
1301 uint32_t y_width = encoder->width, y_size = encoder->width * encoder->height;
1302 uint32_t u_width = encoder->width/2, u_size = (encoder->width/2) * (encoder->height/2);
1303 uint32_t v_width = encoder->width/2;
1304 uint8_t *y_src, *u_src, *v_src;
1309 raw_buffer = (GstBuffer**)g_malloc0(raw_buffer_num*sizeof(GstBuffer*));
1310 for (i = 0; i < raw_buffer_num; i++) {
1311 raw_buffer[i] = gst_buffer_new_and_alloc(buffer_size);
1312 y_src = GST_BUFFER_DATA(raw_buffer[i]);
1313 u_src = y_src + y_size;
1314 v_src = u_src + u_size;
1316 draw_picture(encoder->width, encoder->height, y_src, u_src, v_src, 0, box_width, row_shift);
1318 if (row_shift==(2*box_width)) row_shift= 0;
1321 FILE *fp = fopen("tmp.h264", "wb");
1326 for (i = 0; i < 50; i++) {
1328 ret = gst_h264_encoder_encode(encoder, raw_buffer[k], &coded_pics);
1329 H264_ASSERT(H264_NO_ERROR == ret);
1331 if (k >= raw_buffer_num) k = 0;
1333 while (coded_pics) {
1334 tmp_buffer = coded_pics->data;
1335 coded_pics = g_list_remove(coded_pics, tmp_buffer);
1336 fwrite(GST_BUFFER_DATA(tmp_buffer), GST_BUFFER_SIZE(tmp_buffer), 1, fp);
1337 printf("F:%d, S:%d, %s\n", i, GST_BUFFER_SIZE(tmp_buffer), h264_dump_bytes(GST_BUFFER_DATA(tmp_buffer)+4, 8));
1338 gst_buffer_unref(tmp_buffer);
1343 ret = gst_h264_encoder_close(encoder);
1344 H264_ASSERT(H264_NO_ERROR == ret);
1346 for (i = 0; i < raw_buffer_num; i++) {
1347 gst_buffer_unref(raw_buffer[i]);
1350 gst_h264_encoder_unref(encoder);
1355 char *h264_dump_bytes(const uint8_t *buf, uint32_t num)
1357 static char tmp[1024];
1359 memset(tmp, 0, sizeof(tmp));
1362 for (i = 0; i < num; i++) {
1363 snprintf(p, 1024-(p-tmp), "%02x", (uint8_t)buf[i]);
1370 gst_h264_encoder_get_avcC_codec_data(GstH264Encoder *encoder, GstBuffer **buffer)
1372 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
1373 GstBuffer *avc_codec;
1374 const uint32_t configuration_version = 0x01;
1375 const uint32_t length_size_minus_one = 0x03;
1376 uint32_t profile, profile_comp, level_idc;
1378 H264_ASSERT(buffer);
1379 if (!h264_prv->sps_data || !h264_prv->pps_data) {
1380 return H264_DATA_NOT_READY;
1383 if (FALSE == h264_read_sps_attributes(GST_BUFFER_DATA(h264_prv->sps_data),
1384 GST_BUFFER_SIZE(h264_prv->sps_data),
1385 &profile, &profile_comp, &level_idc))
1388 return H264_DATA_ERR;
1391 H264Bitstream bitstream;
1392 h264_bitstream_init(&bitstream,
1393 (GST_BUFFER_SIZE(h264_prv->sps_data)+GST_BUFFER_SIZE(h264_prv->pps_data) + 32)*8);
1396 h264_bitstream_write_uint(&bitstream, configuration_version, 8);
1397 h264_bitstream_write_uint(&bitstream, profile, 8);
1398 h264_bitstream_write_uint(&bitstream, profile_comp, 8);
1399 h264_bitstream_write_uint(&bitstream, level_idc, 8);
1400 h264_bitstream_write_uint(&bitstream, h264_bit_mask[6], 6); /*111111*/
1401 h264_bitstream_write_uint(&bitstream, length_size_minus_one, 2);
1402 h264_bitstream_write_uint(&bitstream, h264_bit_mask[3], 3); /*111*/
1405 h264_bitstream_write_uint(&bitstream, 1, 5); /* sps count = 1*/
1406 H264_ASSERT( BIT_STREAM_BIT_SIZE(&bitstream)%8 == 0);
1407 h264_bitstream_write_uint(&bitstream, GST_BUFFER_SIZE(h264_prv->sps_data), 16);
1408 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->sps_data),
1409 GST_BUFFER_SIZE(h264_prv->sps_data));
1412 h264_bitstream_write_uint(&bitstream, 1, 8); /*pps count = 1*/
1413 h264_bitstream_write_uint(&bitstream, GST_BUFFER_SIZE(h264_prv->pps_data), 16);
1414 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->pps_data),
1415 GST_BUFFER_SIZE(h264_prv->pps_data));
1417 avc_codec = gst_buffer_new();
1418 GST_BUFFER_MALLOCDATA(avc_codec) =
1419 GST_BUFFER_DATA(avc_codec) =
1420 BIT_STREAM_BUFFER(&bitstream);
1421 GST_BUFFER_SIZE(avc_codec) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
1422 h264_bitstream_destroy(&bitstream, FALSE);
1423 *buffer = avc_codec;
1425 return H264_NO_ERROR;
1429 gst_h264_encoder_get_nal_codec_data(GstH264Encoder *encoder, GstBuffer **buffer)
1431 GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
1432 GstBuffer *nal_sps_pps;
1434 H264_ASSERT(buffer);
1435 if (!h264_prv->sps_data || !h264_prv->pps_data) {
1436 return H264_DATA_NOT_READY;
1439 H264Bitstream bitstream;
1440 h264_bitstream_init(&bitstream,
1441 (GST_BUFFER_SIZE(h264_prv->sps_data)+GST_BUFFER_SIZE(h264_prv->pps_data) + 8)*8);
1443 /*0x000001 start code*/
1444 h264_bitstream_write_uint(&bitstream, 0x000001, 24);
1445 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->sps_data),
1446 GST_BUFFER_SIZE(h264_prv->sps_data));
1447 h264_bitstream_write_uint(&bitstream, 0x000001, 24);
1448 h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->pps_data),
1449 GST_BUFFER_SIZE(h264_prv->pps_data));
1451 nal_sps_pps = gst_buffer_new();
1452 GST_BUFFER_MALLOCDATA(nal_sps_pps) =
1453 GST_BUFFER_DATA(nal_sps_pps) =
1454 BIT_STREAM_BUFFER(&bitstream);
1455 GST_BUFFER_SIZE(nal_sps_pps) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
1456 h264_bitstream_destroy(&bitstream, FALSE);
1457 *buffer = nal_sps_pps;
1458 return H264_NO_ERROR;
1462 h264_bitstream_init(H264Bitstream *bitstream, uint32_t bit_capability)
1464 bitstream->bit_size = 0;
1465 bitstream->buffer = NULL;
1466 bitstream->max_bit_capability = 0;
1467 if (bit_capability) {
1468 h264_bitstream_auto_grow(bitstream, bit_capability);
1473 h264_bitstream_write_uint(H264Bitstream *bitstream, uint32_t value, uint32_t bit_size)
1475 gboolean ret = TRUE;
1476 uint32_t byte_pos, bit_offset;
1484 H264_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, bit_size), FALSE, "h264_bitstream_auto_grow failed.\n");
1485 byte_pos = (bitstream->bit_size>>3);
1486 bit_offset = (bitstream->bit_size&0x07);
1487 cur_byte = bitstream->buffer + byte_pos;
1488 H264_ASSERT(bit_offset < 8 && bitstream->bit_size <= bitstream->max_bit_capability);
1491 fill_bits = ((8-bit_offset) < bit_size ? (8-bit_offset) : bit_size);
1492 bit_size -= fill_bits;
1493 bitstream->bit_size += fill_bits;
1495 *cur_byte |= ((value>>bit_size) & h264_bit_mask[fill_bits])<<(8-bit_offset-fill_bits);
1499 H264_ASSERT(cur_byte <= bitstream->buffer + bitstream->max_bit_capability/8);
1506 static gboolean h264_bitstream_align(H264Bitstream *bitstream, uint32_t value)
1508 uint32_t bit_offset, bit_left;
1510 bit_offset = (bitstream->bit_size&0x07);
1514 bit_left = 8 - bit_offset;
1515 if (value) value = h264_bit_mask[bit_left];
1516 return h264_bitstream_write_uint(bitstream, value, bit_left);
1521 h264_bitstream_write_byte_array(H264Bitstream *bitstream, const uint8_t *buf, uint32_t byte_size)
1523 gboolean ret = TRUE;
1527 H264_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, byte_size<<3), FALSE, "h264_bitstream_auto_grow failed.\n");
1528 if (0 == (bitstream->bit_size&0x07)) {
1529 memcpy(&bitstream->buffer[bitstream->bit_size>>3], buf, byte_size);
1530 bitstream->bit_size += (byte_size<<3);
1534 h264_bitstream_write_uint(bitstream, *buf, 8);
1546 h264_bitstream_write_ue(H264Bitstream *bitstream, uint32_t value)
1548 gboolean ret = TRUE;
1549 uint32_t size_in_bits = 0;
1550 uint32_t tmp_value = ++value;
1555 H264_CHECK_STATUS(h264_bitstream_write_uint(bitstream, 0, size_in_bits-1), FALSE, "h264_bitstream_write_ue failed.\n");
1556 H264_CHECK_STATUS(h264_bitstream_write_uint(bitstream, value, size_in_bits), FALSE, "h264_bitstream_write_ue failed.\n");
1564 h264_bitstream_write_se(H264Bitstream *bitstream, int32_t value)
1566 gboolean ret = TRUE;
1570 new_val = -(value<<1);
1572 new_val = (value<<1) - 1;
1575 H264_CHECK_STATUS(h264_bitstream_write_ue(bitstream, new_val), FALSE, "h264_bitstream_write_se failed.\n");
1583 h264_bitstream_write_trailing_bits(H264Bitstream *bitstream)
1585 h264_bitstream_write_uint(bitstream, 1, 1);
1586 h264_bitstream_align(bitstream, 0);
1591 h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag)
1593 if (bitstream->buffer && free_flag) {
1594 free (bitstream->buffer);
1596 bitstream->buffer = NULL;
1597 bitstream->bit_size = 0;
1598 bitstream->max_bit_capability = 0;
1602 h264_bitstream_auto_grow(H264Bitstream *bitstream, uint32_t extra_bit_size)
1604 uint32_t new_bit_size = extra_bit_size + bitstream->bit_size;
1607 H264_ASSERT(bitstream->bit_size <= bitstream->max_bit_capability);
1608 if (new_bit_size <= bitstream->max_bit_capability) {
1612 new_bit_size = ((new_bit_size + H264_BITSTREAM_ALLOC_ALIGN_MASK)
1613 &(~H264_BITSTREAM_ALLOC_ALIGN_MASK));
1614 H264_ASSERT(new_bit_size%(H264_BITSTREAM_ALLOC_ALIGN_MASK+1) == 0);
1615 clear_pos = ((bitstream->bit_size+7)>>3);
1616 bitstream->buffer = realloc(bitstream->buffer, new_bit_size>>3);
1617 memset(bitstream->buffer+clear_pos, 0, (new_bit_size>>3)-clear_pos);
1618 bitstream->max_bit_capability = new_bit_size;
1623 h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv)
1625 uint32_t constraint_set0_flag, constraint_set1_flag, constraint_set2_flag, constraint_set3_flag;
1626 uint32_t seq_parameter_set_id = 0;
1628 /*need to set the values*/
1629 uint32_t log2_max_frame_num_minus4 = 0; // 1? 3?
1630 uint32_t pic_order_cnt_type = 0; // Must be 0
1631 uint32_t log2_max_pic_order_cnt_lsb_minus4 = 0; // 2 ? 4?
1632 uint32_t num_ref_frames = 1; // only P frames
1633 uint32_t gaps_in_frame_num_value_allowed_flag = 0; // ??
1634 uint32_t mb_width = (h264_prv->public->width+15)/16; // mb_width
1635 uint32_t mb_height = (h264_prv->public->height+15)/16; // mb_height
1636 int32_t frame_mbs_only_flag = 1; // only mbs
1637 uint32_t frame_cropping_flag = 0;
1638 uint32_t frame_crop_bottom_offset = 0;
1639 uint32_t vui_present_flag = 0; // no vui flags
1642 constraint_set0_flag = h264_prv->public->profile == H264_PROFILE_BASELINE;
1643 constraint_set1_flag = h264_prv->public->profile <= H264_PROFILE_MAIN;
1644 constraint_set2_flag = 0;
1645 constraint_set3_flag = 0;
1647 if (mb_height * 16 - h264_prv->public->height) {
1648 frame_cropping_flag = 1;
1649 frame_crop_bottom_offset =
1650 (mb_height * 16 - h264_prv->public->height) / (2 * (!frame_mbs_only_flag + 1));
1653 h264_bitstream_write_uint(bitstream, h264_prv->public->profile, 8); /* profile_idc */
1654 h264_bitstream_write_uint(bitstream, constraint_set0_flag, 1); /* constraint_set0_flag */
1655 h264_bitstream_write_uint(bitstream, constraint_set1_flag, 1); /* constraint_set1_flag */
1656 h264_bitstream_write_uint(bitstream, constraint_set2_flag, 1); /* constraint_set2_flag */
1657 h264_bitstream_write_uint(bitstream, constraint_set3_flag, 1); /* constraint_set3_flag */
1658 h264_bitstream_write_uint(bitstream, 0, 4); /* reserved_zero_4bits */
1659 h264_bitstream_write_uint(bitstream, h264_prv->public->level, 8); /* level_idc */
1660 h264_bitstream_write_ue(bitstream, seq_parameter_set_id); /* seq_parameter_set_id */
1662 if (h264_prv->public->profile >= H264_PROFILE_HIGH) {
1663 /* FIXME: fix for high profile */
1667 h264_bitstream_write_ue(bitstream, log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
1668 h264_bitstream_write_ue(bitstream, pic_order_cnt_type); /* pic_order_cnt_type */
1670 if (pic_order_cnt_type == 0)
1671 h264_bitstream_write_ue(bitstream, log2_max_pic_order_cnt_lsb_minus4);/* log2_max_pic_order_cnt_lsb_minus4 */
1676 h264_bitstream_write_ue(bitstream, num_ref_frames); /* num_ref_frames */
1677 h264_bitstream_write_uint(bitstream, gaps_in_frame_num_value_allowed_flag, 1); /* gaps_in_frame_num_value_allowed_flag */
1679 h264_bitstream_write_ue(bitstream, mb_width - 1); /* pic_width_in_mbs_minus1 */
1680 h264_bitstream_write_ue(bitstream, mb_height - 1); /* pic_height_in_map_units_minus1 */
1681 h264_bitstream_write_uint(bitstream, frame_mbs_only_flag, 1); /* frame_mbs_only_flag */
1683 if (!frame_mbs_only_flag) { //ONLY mbs
1687 h264_bitstream_write_uint(bitstream, 0, 1); /* direct_8x8_inference_flag */
1688 h264_bitstream_write_uint(bitstream, frame_cropping_flag, 1); /* frame_cropping_flag */
1690 if (frame_cropping_flag) {
1691 h264_bitstream_write_ue(bitstream, 0); /* frame_crop_left_offset */
1692 h264_bitstream_write_ue(bitstream, 0); /* frame_crop_right_offset */
1693 h264_bitstream_write_ue(bitstream, 0); /* frame_crop_top_offset */
1694 h264_bitstream_write_ue(bitstream, frame_crop_bottom_offset); /* frame_crop_bottom_offset */
1697 h264_bitstream_write_uint(bitstream, vui_present_flag, 1); /* vui_parameters_present_flag */
1698 h264_bitstream_write_trailing_bits(bitstream); /* rbsp_trailing_bits */
1706 static const uint8_t *
1707 h264_next_nal(const uint8_t *buffer, uint32_t len, uint32_t *nal_size)
1709 const uint8_t *cur = buffer;
1710 const uint8_t *end = buffer + len;
1711 const uint8_t *nal_start = NULL;
1712 uint32_t flag = 0xFFFFFFFF;
1713 uint32_t nal_start_len = 0;
1715 H264_ASSERT(len >= 0 && buffer && nal_size);
1718 nal_start = (len ? buffer : NULL);
1722 /*locate head postion*/
1723 if (!buffer[0] && !buffer[1]) {
1724 if (buffer[2] == 1) { // 0x000001
1726 } else if (!buffer[2] && len >=4 && buffer[3] == 1) { //0x00000001
1730 nal_start = buffer + nal_start_len;
1733 /*find next nal start position*/
1735 flag = ((flag<<8) | ((*cur++)&0xFF));
1736 if (flag == 0x00000001) {
1737 *nal_size = cur - 4 - nal_start;
1739 } else if ((flag&0x00FFFFFF) == 0x00000001) {
1740 *nal_size = cur - 3 - nal_start;
1745 *nal_size = end - nal_start;
1746 if (nal_start >= end) {
1755 h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv)
1761 static int draw_picture(int width, int height,
1762 unsigned char *Y_start,
1763 unsigned char *U_start,
1764 unsigned char *V_start,
1765 int UV_interleave, int box_width, int row_shift)
1769 int Y_pitch = width;
1770 int U_pitch = width/2;
1771 int V_pitch = width/2;
1774 for (row=0;row<height;row++) {
1775 unsigned char *Y_row = Y_start + row * Y_pitch;
1778 ypos = (row / box_width) & 0x1;
1780 /* fill garbage data into the other field */
1781 if (((field == 1) && (row &1))
1782 || ((field == 2) && ((row &1)==0))) {
1783 memset(Y_row, 0xff, width);
1787 for (jj=0; jj<width; jj++) {
1788 xpos = ((row_shift + jj) / box_width) & 0x1;
1790 if ((xpos == 0) && (ypos == 0))
1792 if ((xpos == 1) && (ypos == 1))
1795 if ((xpos == 1) && (ypos == 0))
1797 if ((xpos == 0) && (ypos == 1))
1803 for( row =0; row < height/2; row++) {
1804 unsigned short value = 0x80;
1806 /* fill garbage data into the other field */
1807 if (((field == 1) && (row &1))
1808 || ((field == 2) && ((row &1)==0))) {
1812 if (UV_interleave) {
1813 unsigned short *UV_row = (unsigned short *)(U_start + row * U_pitch);
1815 memset(UV_row, value, width);
1817 unsigned char *U_row = U_start + row * U_pitch;
1818 unsigned char *V_row = V_start + row * V_pitch;
1820 memset (U_row,value,width/2);
1821 memset (V_row,value,width/2);