extract vaapiencoder structure to make other encoders possible
[profile/ivi/gstreamer-vaapi.git] / gst / vaapiencode / h264encoder.c
1
2 #include "h264encoder.h"
3
4 #include <string.h>
5 #include <stdlib.h>
6 #include <va/va.h>
7 #include "va/va_x11.h"
8 #include <X11/Xlib.h>
9 #include <glib.h>
10
11 #include "gst/gstclock.h"
12 #include "gst/gstvalue.h"
13
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"
20
21 #define ENCPRV(encoder) GST_H264_ENCODER_GET_PRIVATE(encoder)
22
23 #define SHARE_CODED_BUF         0
24
25 #define DEFAULT_SURFACE_NUMBER  3
26 #define DEFAULT_CODEDBUF_NUM    5
27 #define DEFAULT_SID_INPUT       0 // suface_ids[0]
28
29 #define REF_RECON_SURFACE_NUM   2
30
31 typedef struct _GstH264EncodeBuffer  GstH264EncodeBuffer;
32
33 #define GST_TYPE_H264_ENCODE_BUFFER (gst_h264_encode_buffer_get_type())
34
35 typedef enum {
36   NAL_UNKNOWN     = 0,
37   NAL_NON_IDR     = 1,
38   NAL_IDR         = 5,    /* ref_idc != 0 */
39   NAL_SEI         = 6,    /* ref_idc == 0 */
40   NAL_SPS         = 7,
41   NAL_PPS         = 8,
42   NAL_AUD         = 9,
43   NAL_FILLER      = 12,
44 }H264_NAL_TYPE;
45
46 struct _GstH264EncodeBuffer {
47   GstBuffer           buffer;
48   VABufferID         *coded_id;
49   GstH264EncoderPrivate *encoder;
50 };
51
52 struct _GstH264EncoderPrivate {
53   GstH264Encoder   *public;
54   uint32_t          format;   /*NV12, I420,*/
55   gboolean          es_flag;  /*elementary flag*/
56
57   /* private data*/
58   //GstVaapiDisplay  *vaapi_display;
59   GstVaapiContext  *vaapi_context;
60   GQueue           *video_buffer_caches; /*not used for baseline*/
61
62   GstVaapiSurface  *ref_surface;  /* reference buffer*/
63   GstVaapiSurface  *recon_surface; /* reconstruct buffer*/
64
65   //VAAPI_Encode_State encode_state;
66
67   VABufferID        seq_parameter;
68   VABufferID        pic_parameter;
69   VABufferID        slice_parameter;
70   VAEncSliceParameterBuffer *slice_param_buffers;
71   uint32_t          default_slice_height;
72   uint32_t          slice_mod_mb_num;
73
74   VABufferID       *coded_bufs;
75   uint32_t          coded_buf_num;
76   uint32_t          cur_coded_index;
77
78   /*total encoded frames*/
79   uint32_t          frame_count;
80
81   GstBuffer        *sps_data;
82   GstBuffer        *pps_data;
83
84   GMutex           *code_buffer_lock;
85   GCond            *code_buffer_cond;
86   GQueue           *available_code_buffers;
87
88 };
89
90 G_DEFINE_TYPE(GstH264Encoder, gst_h264_encoder, GST_TYPE_VAAPI_ENCODER);
91
92
93 // 4096-1
94 #define H264_BITSTREAM_ALLOC_ALIGN_MASK 0x0FFF
95
96 #define BIT_STREAM_BUFFER(stream)    ((stream)->buffer)
97 #define BIT_STREAM_BIT_SIZE(stream)  ((stream)->bit_size)
98
99 struct _H264Bitstream {
100   uint8_t  *buffer;
101   uint32_t  bit_size;
102   uint32_t  max_bit_capability;
103 };
104
105 typedef struct _H264Bitstream H264Bitstream;
106
107 static const uint8_t h264_bit_mask[9] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
108
109 static GstBufferClass *h264_encode_buffer_parent_class = NULL;
110
111
112 static EncoderStatus gst_h264_encoder_initialize(GstVaapiEncoder* encoder);
113 static EncoderStatus gst_h264_encoder_uninitialize(GstVaapiEncoder* encoder);
114 static EncoderStatus gst_h264_encoder_open(GstVaapiEncoder* encoder, void* private_data);
115 static EncoderStatus gst_h264_encoder_close(GstVaapiEncoder* encoder);
116 static EncoderStatus gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstBuffer *raw_pic, GList **coded_pics);
117 static EncoderStatus gst_h264_encoder_flush(GstVaapiEncoder* encoder, GList **coded_pics);
118
119 static gboolean   gst_h264_validate_parameters(GstH264Encoder *encoder);
120 static void     gst_h264_encoder_finalize(GObject *object);
121 static void     gst_h264_encoder_init_public_values(GstH264Encoder* encoder);
122
123 static VAProfile  h264_get_va_profile(uint32_t profile);
124 static EncoderStatus h264_encoder_alloc_buffers(GstH264EncoderPrivate *h264_prv);
125 static EncoderStatus h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv);
126 static EncoderStatus h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
127                                              GstBuffer *raw_pic,
128                                              GstVaapiSurface *surface);
129
130 static EncoderStatus h264_prepare_encoding(GstH264EncoderPrivate *h264_prv,
131                                              GstBuffer *raw_pic, gboolean is_key,
132                                              VABufferID coded_buf);
133 static EncoderStatus h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
134                                          VASurfaceID surface_id,
135                                          gboolean is_key,
136                                          GstClockTime timestamp,
137                                          GstClockTime duration,
138                                          VABufferID *coded_buf,
139                                          GList **coded_pics);
140 static EncoderStatus
141 h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const uint8_t *buf, uint32_t size);
142 static GstBuffer *h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
143                                                    uint8_t *frame,
144                                                    uint32_t frame_size,
145                                                    VABufferID *coded_buf);
146
147
148 /*encoded buffer, for SHARE_CODED_BUF */
149 static void gst_h264_encode_buffer_class_init (gpointer g_class, gpointer class_data);
150 static GType gst_h264_encode_buffer_get_type (void);
151 static void gst_h264_encode_buffer_finalize (GstH264EncodeBuffer *h264_buffer);
152 static GstH264EncodeBuffer *gst_h264_encode_buffer_new(GstH264EncoderPrivate *h264_prv,
153                                                        VABufferID *coded_id);
154
155 /* h264 bitstream functions */
156 static void     h264_bitstream_init(H264Bitstream *bitstream, uint32_t bit_capability);
157 static gboolean h264_bitstream_write_uint(H264Bitstream *bitstream, uint32_t value, uint32_t bit_size);
158 static gboolean h264_bitstream_align(H264Bitstream *bitstream, uint32_t value);
159 static gboolean h264_bitstream_write_ue(H264Bitstream *bitstream, uint32_t value);
160 static gboolean h264_bitstream_write_se(H264Bitstream *bitstream, int32_t value);
161 static gboolean h264_bitstream_write_trailing_bits(H264Bitstream *bitstream);
162
163 static gboolean h264_bitstream_write_byte_array(H264Bitstream *bitstream, const uint8_t *buf, uint32_t byte_size);
164 static void     h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag);
165 static gboolean h264_bitstream_auto_grow(H264Bitstream *bitstream, uint32_t extra_bit_size);
166 static gboolean h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv);
167 static gboolean h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv);
168 static const uint8_t *h264_next_nal(const uint8_t *buffer, uint32_t len, uint32_t *nal_size);
169 static gboolean h264_read_sps_attributes(const uint8_t *sps_data, uint32_t sps_size,
170                                 uint32_t *profile_idc, uint32_t *profile_comp, uint32_t *level_idc);
171
172 /*other functions*/
173 static EncoderStatus gst_h264_encoder_get_avcC_codec_data(GstVaapiEncoder* encoder, GstBuffer **buffer);
174 static EncoderStatus gst_h264_encoder_get_nal_codec_data(GstVaapiEncoder* encoder, GstBuffer **buffer);
175
176
177 static void
178 gst_h264_encoder_class_init(GstH264EncoderClass *klass)
179 {
180   GObjectClass * const object_class = G_OBJECT_CLASS(klass);
181   GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
182   g_type_class_add_private(klass, sizeof(GstH264EncoderPrivate));
183
184   object_class->finalize = gst_h264_encoder_finalize;
185
186   encoder_class->initialize = gst_h264_encoder_initialize;
187   encoder_class->uninitialize = gst_h264_encoder_uninitialize;
188   encoder_class->open = gst_h264_encoder_open;
189   encoder_class->close = gst_h264_encoder_close;
190   encoder_class->encode = gst_h264_encoder_encode;
191   encoder_class->flush = gst_h264_encoder_flush;
192   /*
193   object_class->set_property = gst_h264_encoder_set_property;
194   object_class->get_property = gst_h264_encoder_get_property;
195   */
196 }
197
198
199 static void
200 gst_h264_encode_buffer_class_init (gpointer g_class, gpointer class_data)
201 {
202   GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS(g_class);
203
204   h264_encode_buffer_parent_class = g_type_class_peek_parent(g_class);
205   ENCODER_ASSERT(h264_encode_buffer_parent_class);
206
207   mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
208       gst_h264_encode_buffer_finalize;
209 }
210
211
212 static GType
213 gst_h264_encode_buffer_get_type (void)
214 {
215   static GType s_h264_encode_buffer_type = 0;
216   if (G_UNLIKELY (s_h264_encode_buffer_type == 0)) {
217     static const GTypeInfo s_h264_encode_buffer_info = {
218       sizeof(GstBufferClass),
219       NULL,
220       NULL,
221       gst_h264_encode_buffer_class_init,
222       NULL,
223       NULL,
224       sizeof(GstH264EncodeBuffer),
225       0,
226       NULL,
227       NULL
228     };
229     s_h264_encode_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
230         "GstH264EncodeBuffer", &s_h264_encode_buffer_info, 0);
231   }
232   return s_h264_encode_buffer_type;
233 }
234
235 static void
236 gst_h264_encode_buffer_finalize (GstH264EncodeBuffer *h264_buffer)
237 {
238   GstH264EncoderPrivate *h264_prv = NULL;
239   VABufferID* coded_id = NULL;
240   GstVaapiDisplay *display = NULL;
241
242   h264_prv = h264_buffer->encoder;
243   coded_id = h264_buffer->coded_id;
244   display = ENCODER_DISPLAY(h264_prv->public);
245
246   ENCODER_ASSERT(display);
247   ENCODER_ASSERT(h264_prv->vaapi_context);
248   VADisplay va_dpy = gst_vaapi_display_get_display(display);
249
250   ENCODER_ASSERT(h264_prv);
251   ENCODER_ASSERT(coded_id && VA_INVALID_ID!= *coded_id);
252   ENCODER_ASSERT(h264_prv->available_code_buffers);
253
254   g_mutex_lock(h264_prv->code_buffer_lock);
255   /*if (--(*h264_buffer->ref_coded_id) == 0) */
256   {
257     /*g_free(h264_buffer->ref_coded_id);*/
258     vaUnmapBuffer(va_dpy, *coded_id);
259     g_queue_push_head(h264_prv->available_code_buffers, coded_id);
260     g_cond_signal(h264_prv->code_buffer_cond);
261   }
262
263   g_mutex_unlock(h264_prv->code_buffer_lock);
264
265   if (GST_MINI_OBJECT_CLASS(h264_encode_buffer_parent_class)->finalize) {
266     GST_MINI_OBJECT_CLASS(h264_encode_buffer_parent_class)->finalize(GST_MINI_OBJECT(h264_buffer));
267   }
268 }
269
270 static GstH264EncodeBuffer *
271 gst_h264_encode_buffer_new(GstH264EncoderPrivate *h264_prv,
272                            VABufferID *coded_id)
273 {
274   GstH264EncodeBuffer *buf = (GstH264EncodeBuffer*)gst_mini_object_new(GST_TYPE_H264_ENCODE_BUFFER);
275   buf->coded_id = coded_id;
276   buf->encoder = h264_prv;
277   return buf;
278 }
279
280
281 static GstVaapiSurface *
282 h264_get_video_surface(GstH264EncoderPrivate *h264_prv, GstVaapiVideoBuffer *video_buffer)
283 {
284   //ref_surface
285   GstVaapiSurface *ret = gst_vaapi_video_buffer_get_surface(video_buffer);
286
287   ENCODER_CHECK_STATUS(ret, NULL, "video buffer doesn't have a surface");
288 #if 0
289   g_queue_push_tail(h264_prv->video_buffer_caches,video_buffer);
290   gst_buffer_ref(GST_BUFFER(video_buffer));
291 #endif
292   return ret;
293
294   end:
295   return NULL;
296 }
297
298 static void
299 h264_release_video_surface(GstH264EncoderPrivate *h264_prv, VASurfaceID surface)
300 {
301 #if 0
302   ENCODER_ASSERT(h264_prv->video_buffer_caches);
303   g_queue_find_custom(h264_prv->video_buffer_caches,xx, compare_func);
304   for (h264_prv->video_buffer_caches) {
305   }
306 #endif
307 }
308
309 static GstVaapiSurface *
310 h264_pop_free_surface(GstH264EncoderPrivate *h264_prv)
311 {
312   ENCODER_ASSERT(h264_prv && h264_prv->vaapi_context);
313
314   /*may need lock*/
315   GstVaapiSurface *surface = gst_vaapi_context_get_surface(h264_prv->vaapi_context);
316   return surface;
317 }
318
319 static void
320 h264_push_free_surface(GstH264EncoderPrivate *h264_prv, GstVaapiSurface *surface)
321 {
322   ENCODER_ASSERT(surface);
323   if (!surface) {
324     return;
325   }
326   gst_vaapi_context_put_surface(h264_prv->vaapi_context, surface);
327 }
328
329
330 static VAProfile
331 h264_get_va_profile(uint32_t profile)
332 {
333   switch (profile) {
334     case H264_PROFILE_BASELINE:
335       return VAProfileH264Baseline;
336
337     case H264_PROFILE_MAIN:
338       return VAProfileH264Main;
339
340     case H264_PROFILE_HIGH:
341       return VAProfileH264High;
342
343     default:
344       break;
345   }
346   return (-1);
347 }
348
349 GstH264Encoder *
350 gst_h264_encoder_new(void)
351 {
352   return GST_H264_ENCODER(g_object_new(GST_TYPE_H264_ENCODER, NULL));
353 }
354
355
356 static void
357 gst_h264_encoder_init(GstH264Encoder *encoder)
358 {
359   GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
360   GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
361   ENCODER_ASSERT(h264_prv);
362   h264_prv->public = encoder;
363
364   /* init public attributes */
365   gst_h264_encoder_init_public_values(encoder);
366
367   /* init private values*/
368   h264_prv->format = GST_MAKE_FOURCC('N','V','1','2');
369   h264_prv->es_flag = TRUE;
370
371   //h264_prv->vaapi_display = NULL;
372   h264_prv->vaapi_context= NULL;
373   h264_prv->ref_surface = NULL;
374   h264_prv->recon_surface = NULL;
375   h264_prv->video_buffer_caches = g_queue_new();
376
377   //h264_prv->encode_state = H264_ENC_NULL;
378   h264_prv->seq_parameter = VA_INVALID_ID;
379   h264_prv->pic_parameter = VA_INVALID_ID;
380   h264_prv->slice_parameter = VA_INVALID_ID;
381   h264_prv->slice_param_buffers = NULL;
382   h264_prv->default_slice_height = 0;
383   h264_prv->slice_mod_mb_num = 0;
384
385   h264_prv->coded_bufs = NULL;
386   h264_prv->coded_buf_num = DEFAULT_CODEDBUF_NUM;
387   h264_prv->frame_count = 0;
388   h264_prv->sps_data = NULL;
389   h264_prv->pps_data = NULL;
390   /*index init*/
391   h264_prv->cur_coded_index = 0;
392   /*init others*/
393   h264_prv->code_buffer_lock = g_mutex_new();
394   h264_prv->code_buffer_cond = g_cond_new();
395   h264_prv->available_code_buffers = g_queue_new();
396
397   encoder_prv->get_codec_data = gst_h264_encoder_get_avcC_codec_data;
398   /* encoder_prv->get_codec_data = gst_h264_encoder_get_nal_codec_data; */
399
400 }
401
402 static void
403 gst_h264_encoder_finalize(GObject *object)
404 {
405   /*free private buffers*/
406   GstH264EncoderPrivate *h264_prv = ENCPRV(object);
407
408   g_mutex_free(h264_prv->code_buffer_lock);
409   g_cond_free(h264_prv->code_buffer_cond);
410   if (h264_prv->available_code_buffers) {
411     g_queue_free(h264_prv->available_code_buffers);
412     h264_prv->available_code_buffers = NULL;
413   }
414
415   if (h264_prv->ref_surface) {
416     if (h264_prv->vaapi_context) {
417       h264_push_free_surface(h264_prv, h264_prv->ref_surface);
418     } else {
419       g_object_unref(h264_prv->ref_surface);
420     }
421     h264_prv->ref_surface = NULL;
422   }
423   if (h264_prv->recon_surface) {
424     if (h264_prv->vaapi_context) {
425       h264_push_free_surface(h264_prv, h264_prv->recon_surface);
426     } else {
427       g_object_unref(h264_prv->recon_surface);
428     }
429     h264_prv->recon_surface = NULL;
430   }
431   if (h264_prv->vaapi_context) {
432     g_object_unref(h264_prv->vaapi_context);
433     h264_prv->vaapi_context= NULL;
434   }
435
436   if (h264_prv->video_buffer_caches) {
437     g_queue_free(h264_prv->video_buffer_caches);
438     h264_prv->video_buffer_caches = NULL;
439   };
440   if (h264_prv->sps_data) {
441     gst_buffer_unref(h264_prv->sps_data);
442     h264_prv->sps_data = NULL;
443   }
444   if (h264_prv->pps_data) {
445     gst_buffer_unref(h264_prv->pps_data);
446     h264_prv->pps_data = NULL;
447   }
448   if (h264_prv->slice_param_buffers) {
449     g_free(h264_prv->slice_param_buffers);
450     h264_prv->slice_param_buffers = NULL;
451   }
452 }
453
454
455 static void
456 gst_h264_encoder_init_public_values(GstH264Encoder* encoder)
457 {
458   encoder->profile = 0;
459   encoder->level = 0;
460   //encoder->width = 0;
461   //encoder->height = 0;
462   //encoder->frame_rate = 0;
463   encoder->bitrate = 0;
464   encoder->intra_period = 0;
465   encoder->init_qp = -1;
466   encoder->min_qp = -1;
467   encoder->slice_num = 0;
468 }
469
470 void
471 gst_h264_encoder_set_input_format(GstH264Encoder* encoder, uint32_t format)
472 {
473   GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
474   h264_prv->format = format;
475 }
476
477 void
478 gst_h264_encoder_set_es_flag(GstH264Encoder* encoder, gboolean es)
479 {
480   GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
481   h264_prv->es_flag = es;
482 }
483
484 EncoderStatus
485 gst_h264_encoder_initialize(GstVaapiEncoder* encoder)
486 {
487   return ENCODER_NO_ERROR;
488 }
489
490 EncoderStatus
491 gst_h264_encoder_uninitialize(GstVaapiEncoder* encoder)
492 {
493   return ENCODER_NO_ERROR;
494
495 }
496
497 gboolean
498 gst_h264_validate_parameters(GstH264Encoder *encoder)
499 {
500   GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
501   if (!ENCODER_WIDTH(encoder) || !ENCODER_HEIGHT(encoder) || !ENCODER_FPS(encoder)) {
502     return FALSE;
503   }
504   if (!encoder->profile) {
505     encoder->profile = H264_DEFAULT_PROFILE;
506   }
507   if (!encoder->level) {
508     encoder->level = H264_DEFAULT_LEVEL;
509   }
510   if (!encoder->intra_period) {
511     encoder->intra_period = H264_DEFAULT_INTRA_PERIOD;
512   }
513   if (-1 == encoder->init_qp) {
514     encoder->init_qp = H264_DEFAULT_INIT_QP;
515   }
516   if (-1 == encoder->min_qp) {
517     encoder->min_qp = H264_DEFAULT_MIN_QP;
518   }
519
520   if (encoder->min_qp > encoder->init_qp) {
521     encoder->min_qp = encoder->init_qp;
522   }
523
524   /* default compress ratio 1: (4*8*1.5) */
525   if (!encoder->bitrate) {
526     encoder->bitrate = ENCODER_WIDTH(encoder)*ENCODER_HEIGHT(encoder)*ENCODER_FPS(encoder)/4;
527   }
528
529   if (!encoder->slice_num) {
530     encoder->slice_num = H264_DEFAULT_SLICE_NUM;
531   }
532
533   /* need  calculate slice-num and each slice-height
534         suppose:  ((encoder->height+15)/16) = 13, slice_num = 8
535         then: slice_1_height = 2
536                  slice_2_height = 2
537                  slice_3_height = 2
538                  slice_4_height = 2
539                  slice_5_height = 2
540                  slice_6_height = 1
541                  slice_7_height = 1
542                  slice_8_height = 1
543    */
544   h264_prv->default_slice_height = (ENCODER_HEIGHT(encoder)+15)/16/encoder->slice_num;
545   if (0 == h264_prv->default_slice_height) { /* special value */
546     h264_prv->default_slice_height = 1;
547     h264_prv->slice_mod_mb_num = 0;
548     encoder->slice_num = (ENCODER_HEIGHT(encoder)+15)/16;
549   } else {
550     h264_prv->slice_mod_mb_num = ((ENCODER_HEIGHT(encoder)+15)/16)%encoder->slice_num;
551   }
552   return TRUE;
553 }
554
555 EncoderStatus
556 gst_h264_encoder_open(GstVaapiEncoder* encoder, void* private_data)
557 {
558   GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
559   GstVaapiSurfacePool *surfaces_pool = private_data;
560   GstVaapiDisplay *display = ENCODER_DISPLAY(encoder);
561   GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
562
563   EncoderStatus ret = ENCODER_NO_ERROR;
564   VAProfile va_profile = -1;
565   VAEntrypoint entrypoints[5];
566   int num_entrypoints,slice_entrypoint;
567   VAConfigAttrib attrib[5];
568   VAStatus va_status = VA_STATUS_SUCCESS;
569
570   /*check and set default values*/
571   ENCODER_CHECK_STATUS(gst_h264_validate_parameters(h264_encoder), ENCODER_PARAMETER_ERR, "h264encoder paramerter error.\n");
572
573   va_profile = h264_get_va_profile(h264_encoder->profile);
574   ENCODER_ASSERT(ENCODER_DISPLAY(encoder));
575   ENCODER_ASSERT(!h264_prv->vaapi_context);
576   ENCODER_CHECK_STATUS(-1 != va_profile, ENCODER_PROFILE_ERR, "profile(%d) is NOT supported.\n", h264_encoder->profile);
577
578 #ifdef _MRST_
579   h264_prv->vaapi_context = g_object_new(
580         GST_VAAPI_TYPE_CONTEXT,
581         "display",      display,
582         "id",           GST_VAAPI_ID(VA_INVALID_ID),
583         "entrypoint",   gst_vaapi_entrypoint(VAEntrypointEncSlice),
584         "width",        ENCODER_WIDTH(encoder),
585         "height",       ENCODER_HEIGHT(encoder),
586         NULL
587     );
588   if (surfaces_pool) {
589     gst_vaapi_context_set_surface_pool(h264_prv->vaapi_context, surfaces_pool);
590   }
591   g_object_set(h264_prv->vaapi_context, "profile",  gst_vaapi_profile(va_profile), NULL);
592
593 #else
594   VAAPI_UNUSED_ARG(surfaces_pool);
595   h264_prv->vaapi_context = gst_vaapi_context_new(display,
596                         gst_vaapi_profile(va_profile),
597                         gst_vaapi_entrypoint(VAEntrypointEncSlice),
598                         ENCODER_WIDTH(encoder),
599                         ENCODER_HEIGHT(encoder));
600 #endif
601   ENCODER_CHECK_STATUS(h264_prv->vaapi_context, ENCODER_CONTEXT_ERR, "gst_vaapi_context_new failed.\n");
602   ret = h264_encoder_alloc_buffers(h264_prv);
603   if (ENCODER_NO_ERROR != ret) {
604     goto end;
605   }
606
607   return ENCODER_NO_ERROR;
608
609   end:
610   // clear resources
611   gst_h264_encoder_close(encoder);
612   return ret;
613
614 }
615
616 EncoderStatus
617 gst_h264_encoder_close(GstVaapiEncoder* encoder)
618 {
619   GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
620   EncoderStatus ret = ENCODER_NO_ERROR;
621   GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
622
623   /* release buffers first */
624   h264_encoder_release_buffers(h264_prv);
625
626   /*remove ref_surface*/
627   if (h264_prv->ref_surface) {
628     if (h264_prv->vaapi_context) {
629       h264_push_free_surface(h264_prv, h264_prv->ref_surface);
630     } else {
631       g_object_unref(h264_prv->ref_surface);
632     }
633     h264_prv->ref_surface = NULL;
634   }
635
636   /*remove recon_surface*/
637   if (h264_prv->recon_surface) {
638     if (h264_prv->vaapi_context) {
639       h264_push_free_surface(h264_prv, h264_prv->recon_surface);
640     } else {
641       g_object_unref(h264_prv->recon_surface);
642     }
643     h264_prv->recon_surface = NULL;
644   }
645
646   /*remove vaapi_context*/
647   if (h264_prv->vaapi_context) {
648     g_object_unref(h264_prv->vaapi_context);
649     h264_prv->vaapi_context = NULL;
650   }
651
652   h264_prv->frame_count = 0;
653
654   if (h264_prv->sps_data) {
655     gst_buffer_unref(h264_prv->sps_data);
656     h264_prv->sps_data = NULL;
657   }
658   if (h264_prv->pps_data) {
659     gst_buffer_unref(h264_prv->pps_data);
660     h264_prv->pps_data = NULL;
661   }
662   return ret;
663 }
664
665 static EncoderStatus
666 h264_encoder_alloc_buffers(GstH264EncoderPrivate *h264_prv)
667 {
668   EncoderStatus ret = ENCODER_NO_ERROR;
669   VAStatus va_status = VA_STATUS_SUCCESS;
670   GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
671   uint32_t i;
672
673   ENCODER_ASSERT(display);
674   ENCODER_ASSERT(h264_prv->vaapi_context);
675   VADisplay va_dpy = gst_vaapi_display_get_display(display);
676   VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
677   gboolean is_locked = FALSE;
678
679   GST_VAAPI_DISPLAY_LOCK(display);
680   is_locked = TRUE;
681
682   /* create coded buffers */
683   h264_prv->coded_bufs = (VABufferID*)g_malloc0(h264_prv->coded_buf_num * sizeof(h264_prv->coded_bufs[0]));
684   { // check width, height  ????
685       uint32_t codedbuf_size = (ENCODER_WIDTH(h264_prv->public) * ENCODER_HEIGHT(h264_prv->public) * 400) / (16*16);
686       for (i = 0; i < h264_prv->coded_buf_num; i++) {
687         va_status = vaCreateBuffer(va_dpy, context_id,VAEncCodedBufferType,
688                                    codedbuf_size, 1, NULL, &h264_prv->coded_bufs[i]);
689
690         ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_ENC_RES_ERR, "alloc coded buffer failed.\n");
691       }
692   }
693
694   /* unlock here */
695   GST_VAAPI_DISPLAY_UNLOCK(display);
696   is_locked = FALSE;
697
698   ENCODER_ASSERT(h264_prv->available_code_buffers);
699
700   /* create slice_param_buffers */
701   h264_prv->slice_param_buffers = (VAEncSliceParameterBuffer*)g_malloc0_n(h264_prv->public->slice_num,
702                                                      sizeof(h264_prv->slice_param_buffers[0]));
703
704   /* init queue available_code_buffers */
705   g_mutex_lock(h264_prv->code_buffer_lock);
706   for (i = 0; i < h264_prv->coded_buf_num; i++) {
707     g_queue_push_tail (h264_prv->available_code_buffers, &h264_prv->coded_bufs[i]);
708   }
709   g_cond_signal(h264_prv->code_buffer_cond);
710   g_mutex_unlock(h264_prv->code_buffer_lock);
711
712   return ENCODER_NO_ERROR;
713
714   end:
715   if (is_locked) {
716     GST_VAAPI_DISPLAY_UNLOCK(display);
717     is_locked = FALSE;
718   }
719   return ret;
720
721 }
722
723 static EncoderStatus
724 h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv)
725 {
726   VAStatus va_status = VA_STATUS_SUCCESS;
727   uint32_t available_buf_count = h264_prv->coded_buf_num;
728   GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
729   uint32_t i;
730
731   ENCODER_ASSERT(display);
732   ENCODER_ASSERT(h264_prv->vaapi_context);
733   VADisplay va_dpy = gst_vaapi_display_get_display(display);
734
735   /* wait for all coded buffer freed*/
736   g_mutex_lock(h264_prv->code_buffer_lock);
737   while (available_buf_count) {
738     if (g_queue_is_empty(h264_prv->available_code_buffers)) {
739       g_cond_wait(h264_prv->code_buffer_cond, h264_prv->code_buffer_lock);
740     } else {
741       g_queue_pop_head(h264_prv->available_code_buffers);
742       available_buf_count--;
743     }
744   }
745   g_mutex_unlock(h264_prv->code_buffer_lock);
746
747   GST_VAAPI_DISPLAY_LOCK(display);
748   for (i = 0; i < h264_prv->coded_buf_num; i++) {
749     va_status = vaDestroyBuffer(va_dpy, h264_prv->coded_bufs[i]);
750   }
751   va_status = vaDestroyBuffer(va_dpy, h264_prv->seq_parameter);
752   GST_VAAPI_DISPLAY_UNLOCK(display);
753
754   if (h264_prv->coded_bufs) {
755     g_free(h264_prv->coded_bufs);
756     h264_prv->coded_bufs = NULL;
757   }
758
759   if (h264_prv->slice_param_buffers) {
760     g_free(h264_prv->slice_param_buffers);
761     h264_prv->slice_param_buffers = NULL;
762   }
763
764   return ENCODER_NO_ERROR;
765 }
766
767 EncoderStatus
768 gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstBuffer *raw_pic, GList **coded_pics)
769 {
770   GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
771   GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
772   GstVaapiDisplay *display = ENCODER_DISPLAY(encoder);
773
774   EncoderStatus ret = ENCODER_NO_ERROR;
775   gboolean is_key = FALSE;
776   VABufferID* coded_buf = NULL;
777   VAStatus va_status = VA_STATUS_SUCCESS;
778   VASurfaceID  buffer_surface_id = VA_INVALID_SURFACE;
779   GstVaapiSurface *buffer_surface = NULL;
780
781   ENCODER_ASSERT(display);
782   ENCODER_ASSERT(h264_prv->vaapi_context);
783   VADisplay va_dpy = gst_vaapi_display_get_display(display);
784   VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
785   GstVaapiSurface *new_surface = NULL;
786
787   if (GST_VAAPI_IS_VIDEO_BUFFER(raw_pic)) {
788     buffer_surface = h264_get_video_surface(h264_prv, GST_VAAPI_VIDEO_BUFFER(raw_pic));
789   } else {
790     new_surface = h264_pop_free_surface(h264_prv);
791     buffer_surface = new_surface;
792     ENCODER_CHECK_STATUS(buffer_surface, ENCODER_SURFACE_ERR, "h264_pop_free_surface failed.\n");
793
794     /*input picture to h264_prv->cur_surface_index*/
795     va_status = h264_put_raw_buffer_to_surface(h264_prv, raw_pic, buffer_surface);
796     ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "va put buffer to surface failed.\n");
797   }
798   buffer_surface_id = (VASurfaceID)GST_VAAPI_OBJECT_ID(buffer_surface);
799   ENCODER_CHECK_STATUS(buffer_surface_id != VA_INVALID_SURFACE, ENCODER_SURFACE_ERR, "surface id == VA_INVALID_SURFACE.\n");
800
801   /* begin picture, using default sid 0*/
802   GST_VAAPI_DISPLAY_LOCK(display);
803   va_status = vaBeginPicture(va_dpy, context_id, buffer_surface_id);
804   GST_VAAPI_DISPLAY_UNLOCK(display);
805
806   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaBeginPicture error.\n");
807
808   /* set input buffers*/
809   is_key = ((h264_prv->frame_count % h264_encoder->intra_period) == 0);
810
811   /*get valid coded buffer*/
812   g_mutex_lock(h264_prv->code_buffer_lock);
813   ENCODER_ASSERT(h264_prv->available_code_buffers);
814   while (g_queue_is_empty(h264_prv->available_code_buffers)) {
815     g_cond_wait(h264_prv->code_buffer_cond, h264_prv->code_buffer_lock);
816   }
817
818   coded_buf = (VABufferID*)g_queue_pop_head (h264_prv->available_code_buffers);
819   ret = h264_prepare_encoding(h264_prv, raw_pic, is_key, *coded_buf);
820   if (ENCODER_NO_ERROR != ret) {
821     g_queue_push_head(h264_prv->available_code_buffers, coded_buf);
822   }
823   g_mutex_unlock(h264_prv->code_buffer_lock);
824
825   ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret, ENCODER_PICTURE_ERR, "h264_prepare_encoding failed.\n");
826
827   /* end picture */
828   GST_VAAPI_DISPLAY_LOCK(display);
829   va_status = vaEndPicture(va_dpy, context_id);
830   GST_VAAPI_DISPLAY_UNLOCK(display);
831   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaEndPicture error.\n");
832
833   /*query surface result*/
834   ret = h264_query_encoding_status(h264_prv, buffer_surface_id,
835                                    is_key, GST_BUFFER_TIMESTAMP(raw_pic), GST_BUFFER_DURATION(raw_pic), coded_buf, coded_pics);
836   if (ENCODER_NO_ERROR != ret) {
837     goto end;
838   }
839
840   h264_prv->frame_count++;
841
842
843   end:
844   if (new_surface) {
845     h264_push_free_surface(h264_prv, new_surface);
846   }
847   return ret;
848 }
849
850 static EncoderStatus
851 h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
852                                GstBuffer *raw_pic,
853                                GstVaapiSurface *surface)
854 {
855   EncoderStatus ret = ENCODER_NO_ERROR;
856   VAStatus va_status = VA_STATUS_SUCCESS;
857   VAImage surface_image;
858   VADisplay va_dpy;
859   GstVaapiImage *image;
860   GstVaapiImageFormat image_format;
861   uint8_t *y_src = NULL, *u_src = NULL, *v_src = NULL;
862   uint8_t *y_dst = NULL, *u_dst = NULL, *v_dst = NULL;
863   int y_size = 0, u_size = 0;
864   int row = 0, col = 0;
865   uint32_t plane_count = 0;
866   uint32_t image_width = 0, image_height = 0;
867   uint32_t pitchy = 0, pitchu = 0, pitchv = 0;
868   GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
869
870   ENCODER_ASSERT(display);
871   va_dpy = gst_vaapi_display_get_display(display);
872   /*map image*/
873   image = gst_vaapi_surface_derive_image(surface);
874   gst_vaapi_image_map(image);
875
876   image_format = gst_vaapi_image_get_format(image);
877   image_width = gst_vaapi_image_get_width(image);
878   image_height = gst_vaapi_image_get_height(image);
879
880   /* copy buffer to surface */
881   ENCODER_ASSERT(GST_BUFFER_SIZE(raw_pic) >= y_size + (y_size>>1));
882
883   y_size = ENCODER_WIDTH(h264_prv->public) * ENCODER_HEIGHT(h264_prv->public);
884   u_size = ((ENCODER_WIDTH(h264_prv->public)+1) >> 1) * ((ENCODER_HEIGHT(h264_prv->public)+1) >> 1);
885
886   y_src = GST_BUFFER_DATA(raw_pic);
887   u_src = y_src + y_size;
888   v_src = u_src + u_size;
889
890   plane_count = gst_vaapi_image_get_plane_count(image);
891   y_dst = gst_vaapi_image_get_plane(image, 0);
892   u_dst = gst_vaapi_image_get_plane(image, 1);
893   pitchy = gst_vaapi_image_get_pitch(image, 0);
894   pitchu = gst_vaapi_image_get_pitch(image, 1);
895
896   if (plane_count > 2) {
897     v_dst = gst_vaapi_image_get_plane(image, 2);
898     pitchv = gst_vaapi_image_get_pitch(image, 2);
899   }
900
901   /* copy from avcenc.c*/
902   /* Y plane */
903   for (row = 0; row < image_height; row++) {
904       memcpy(y_dst, y_src, image_width);
905       y_dst += pitchy;
906       y_src += ENCODER_WIDTH(h264_prv->public);
907   }
908
909   if (GST_VAAPI_IMAGE_NV12 == image_format) { /* UV plane */
910     if (GST_VAAPI_IMAGE_I420 == h264_prv->format) {
911       for (row = 0; row < image_height / 2; row++) {
912           for (col = 0; col < image_width / 2; col++) {
913               u_dst[col * 2] = u_src[col];
914               u_dst[col * 2 + 1] = v_src[col];
915           }
916
917           u_dst += pitchu;
918           u_src += (ENCODER_WIDTH(h264_prv->public)>>1);
919           v_src += (ENCODER_WIDTH(h264_prv->public)>>1);
920       }
921     } else if (GST_VAAPI_IMAGE_NV12 == h264_prv->format){
922       for (row = 0; row < image_height / 2; row++) {
923         memcpy(u_dst, u_src, image_width);
924         u_src += ENCODER_WIDTH(h264_prv->public);
925         u_dst += pitchu;
926       }
927     } else {
928       ENCODER_ASSERT(0);
929     }
930   } else {
931       /* FIXME: fix this later */
932       ENCODER_ASSERT(0);
933   }
934
935   /*unmap image*/
936   g_object_unref(image);
937   end:
938   return ret;
939 }
940
941
942 static EncoderStatus
943 h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gboolean is_key, VABufferID coded_buf)
944 {
945   EncoderStatus ret = ENCODER_NO_ERROR;
946   VAStatus va_status = VA_STATUS_SUCCESS;
947   GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
948
949   VAEncPictureParameterBufferH264 pic_h264;
950   VAEncSliceParameterBuffer *slice_h264 = NULL;
951
952   ENCODER_ASSERT(display);
953   ENCODER_ASSERT(h264_prv->vaapi_context);
954   VADisplay va_dpy = gst_vaapi_display_get_display(display);
955   VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
956
957   /* lock display */
958   GST_VAAPI_DISPLAY_LOCK(display);
959   /*handle first surface_index*/
960   /*only need first frame*/
961   if (VA_INVALID_ID == h264_prv->seq_parameter) { /*first time*/
962     VAEncSequenceParameterBufferH264 seq_h264 = {0};
963
964     seq_h264.level_idc = h264_prv->public->level; /* 3.0 */
965     seq_h264.max_num_ref_frames = 1; /*Only I, P frames*/
966     seq_h264.picture_width_in_mbs = (ENCODER_WIDTH(h264_prv->public)+15)/16;
967     seq_h264.picture_height_in_mbs = (ENCODER_HEIGHT(h264_prv->public)+15)/16;
968
969     seq_h264.bits_per_second = h264_prv->public->bitrate;
970     seq_h264.frame_rate = ENCODER_FPS(h264_prv->public);
971     seq_h264.initial_qp = h264_prv->public->init_qp; /*qp_value; 15, 24, 26?*/
972     seq_h264.min_qp = h264_prv->public->min_qp;     /*1, 6, 10*/
973     seq_h264.basic_unit_size = 0;
974     seq_h264.intra_period = h264_prv->public->intra_period;
975     seq_h264.intra_idr_period = h264_prv->public->intra_period;
976
977     va_status = vaCreateBuffer(va_dpy, context_id,
978                                VAEncSequenceParameterBufferType,
979                                sizeof(seq_h264), 1, &seq_h264, &h264_prv->seq_parameter);
980     ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_ENC_RES_ERR, "alloc seq-buffer failed.\n");
981     va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->seq_parameter, 1);
982     ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaRenderPicture seq-parameters failed.\n");
983   }
984
985   /* set pic_parameters*/
986   if (!h264_prv->ref_surface) {
987     h264_prv->ref_surface = h264_pop_free_surface(h264_prv);
988     ENCODER_CHECK_STATUS(h264_prv->ref_surface, ENCODER_SURFACE_ERR, "reference surface, h264_pop_free_surface failed.\n");
989   }
990   if (!h264_prv->recon_surface) {
991     h264_prv->recon_surface = h264_pop_free_surface(h264_prv);
992     ENCODER_CHECK_STATUS(h264_prv->recon_surface, ENCODER_SURFACE_ERR, "reconstructed surface, h264_pop_free_surface failed.\n");
993   }
994
995   pic_h264.reference_picture = GST_VAAPI_OBJECT_ID(h264_prv->ref_surface);
996   pic_h264.reconstructed_picture = GST_VAAPI_OBJECT_ID(h264_prv->recon_surface);
997   pic_h264.coded_buf = coded_buf;
998   pic_h264.picture_width = ENCODER_WIDTH(h264_prv->public);
999   pic_h264.picture_height = ENCODER_HEIGHT(h264_prv->public);
1000   pic_h264.last_picture = 0; // last pic or not
1001
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;
1005   }
1006   va_status = vaCreateBuffer(va_dpy, context_id, VAEncPictureParameterBufferType,
1007                                sizeof(pic_h264), 1, &pic_h264, &h264_prv->pic_parameter);
1008
1009   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "creating pic-param buffer failed.\n");
1010
1011   va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->pic_parameter, 1);
1012   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "rendering pic-param buffer failed.\n");
1013
1014   /* set slice parameters, support multiple slices */
1015   int i = 0;
1016   uint32_t last_row_num = 0;
1017   uint32_t slice_mod_num = h264_prv->slice_mod_mb_num;
1018
1019   memset(h264_prv->slice_param_buffers, 0, h264_prv->public->slice_num*sizeof(h264_prv->slice_param_buffers[0]));
1020   for (i = 0; i < h264_prv->public->slice_num; ++i) {
1021     slice_h264 = &h264_prv->slice_param_buffers[i];
1022     slice_h264->start_row_number = last_row_num;               /* unit MB*/
1023     slice_h264->slice_height = h264_prv->default_slice_height; /* unit MB */
1024     if (slice_mod_num) {
1025       ++slice_h264->slice_height;
1026       --slice_mod_num;
1027     }
1028     last_row_num += slice_h264->slice_height;
1029     slice_h264->slice_flags.bits.is_intra = is_key;
1030     slice_h264->slice_flags.bits.disable_deblocking_filter_idc = 0;
1031
1032   }
1033   ENCODER_ASSERT(last_row_num == (ENCODER_HEIGHT(h264_prv->public)+15)/16);
1034
1035   if (VA_INVALID_ID != h264_prv->slice_parameter) {
1036     vaDestroyBuffer(va_dpy, h264_prv->slice_parameter);
1037     h264_prv->slice_parameter = VA_INVALID_ID;
1038   }
1039   va_status = vaCreateBuffer(va_dpy,
1040                              context_id,
1041                              VAEncSliceParameterBufferType,
1042                              sizeof(h264_prv->slice_param_buffers[0]),
1043                              h264_prv->public->slice_num,
1044                              h264_prv->slice_param_buffers,
1045                              &h264_prv->slice_parameter);
1046   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "creating slice-parameters buffer failed.\n");
1047
1048   va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->slice_parameter, 1);
1049   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "rendering slice-parameters buffer failed.\n");
1050
1051
1052   /*after finished, set ref_surface_index, recon_surface_index */
1053   GstVaapiSurface *swap = h264_prv->ref_surface;
1054   h264_prv->ref_surface = h264_prv->recon_surface;
1055   h264_prv->recon_surface = swap;
1056
1057   end:
1058   GST_VAAPI_DISPLAY_UNLOCK(display);
1059   return ret;
1060 }
1061
1062 static EncoderStatus
1063 h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
1064                            VASurfaceID surface_id,
1065                            gboolean is_key,
1066                            GstClockTime timestamp,
1067                            GstClockTime duration,
1068                            VABufferID *coded_buf,
1069                            GList **coded_pics)
1070 {
1071   EncoderStatus ret = ENCODER_NO_ERROR;
1072   VAStatus va_status = VA_STATUS_SUCCESS;
1073   VASurfaceStatus surface_status = 0;
1074   VACodedBufferSegment *buf_list = NULL;
1075   GstBuffer* ret_buffer = NULL;
1076   gboolean has_coded_data = FALSE;
1077   gboolean is_locked = FALSE;
1078
1079   GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
1080
1081   ENCODER_ASSERT(display);
1082   ENCODER_ASSERT(h264_prv->vaapi_context);
1083   VADisplay va_dpy = gst_vaapi_display_get_display(display);
1084   //VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
1085
1086   ENCODER_ASSERT(coded_pics && *coded_pics == NULL);
1087
1088   /* lock display */
1089   GST_VAAPI_DISPLAY_LOCK(display);
1090   is_locked = TRUE;
1091
1092   va_status = vaSyncSurface(va_dpy, surface_id);
1093   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaSyncSurface failed.\n");
1094
1095   va_status = vaQuerySurfaceStatus(va_dpy, surface_id, &surface_status);
1096   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaQuerySurfaceStatus failed.\n");
1097   if (VASurfaceSkipped&surface_status) {
1098     ENCODER_LOG_ERROR("frame skipped, dts:%" GST_TIME_FORMAT ".\n", GST_TIME_ARGS(timestamp));
1099   }
1100
1101   va_status = vaMapBuffer(va_dpy, *coded_buf, (void **)(&buf_list));
1102   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaMapBuffer failed.\n");
1103
1104   /*unlock display*/
1105   if (is_locked) {
1106     GST_VAAPI_DISPLAY_UNLOCK(display);
1107     is_locked = FALSE;
1108   }
1109
1110   while (buf_list != NULL) {
1111       if (!h264_prv->sps_data || !h264_prv->pps_data) {
1112         h264_encoder_read_sps_pps(h264_prv, buf_list->buf, buf_list->size);
1113       }
1114       ret_buffer = h264_encoder_create_coded_buffer(h264_prv, buf_list->buf, buf_list->size, coded_buf);
1115       GST_BUFFER_TIMESTAMP(ret_buffer) = timestamp;
1116       GST_BUFFER_DURATION(ret_buffer) = duration;
1117       if (!is_key) {
1118         GST_BUFFER_FLAG_SET(ret_buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1119       }
1120       *coded_pics = g_list_append(*coded_pics, ret_buffer);
1121       buf_list = (VACodedBufferSegment*)buf_list->next;
1122       ENCODER_ASSERT(NULL == buf_list);
1123       has_coded_data = TRUE;
1124   }
1125
1126 #if SHARE_CODED_BUF
1127   if (!has_coded_data)
1128 #endif
1129   { // if non-related, push back to available_code_buffers
1130     g_mutex_lock(h264_prv->code_buffer_lock);
1131     GST_VAAPI_DISPLAY_LOCK(display);
1132     vaUnmapBuffer(va_dpy, *coded_buf);
1133     GST_VAAPI_DISPLAY_UNLOCK(display);
1134     g_queue_push_head(h264_prv->available_code_buffers, coded_buf);
1135     g_cond_signal(h264_prv->code_buffer_cond);
1136     g_mutex_unlock(h264_prv->code_buffer_lock);
1137   }
1138
1139   return ENCODER_NO_ERROR;
1140
1141   end:
1142   /*unlock display*/
1143   if (is_locked) {
1144     GST_VAAPI_DISPLAY_UNLOCK(display);
1145     is_locked = FALSE;
1146   }
1147   return ret;
1148 }
1149
1150 static GstBuffer *
1151 h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
1152                                         uint8_t *frame,
1153                                         uint32_t frame_size,
1154                                         VABufferID *coded_buf)
1155 {
1156   GstBuffer *ret_buffer;
1157   uint32_t   nal_size;
1158   const uint8_t   *nal_start;
1159   uint8_t  *frame_end;
1160
1161 #if SHARE_CODED_BUF
1162   ret_buffer = gst_h264_encode_buffer_new(h264_prv, coded_buf);
1163   ENCODER_ASSERT(ret_buffer);
1164   GST_BUFFER_MALLOCDATA(ret_buffer) = NULL;
1165   GST_BUFFER_DATA(ret_buffer) = buf_list->buf;
1166   GST_BUFFER_SIZE(ret_buffer) = buf_list->size;
1167 #else
1168   ret_buffer = gst_buffer_new();
1169   ENCODER_ASSERT(ret_buffer);
1170   H264Bitstream bitstream;
1171   h264_bitstream_init(&bitstream, (frame_size+32)*8);
1172   h264_bitstream_align(&bitstream, 0);
1173   ENCODER_ASSERT(bitstream.bit_size == 0);
1174
1175   if (!h264_prv->es_flag) { /*nal format*/
1176     h264_bitstream_write_byte_array(&bitstream, frame, frame_size);
1177     ENCODER_ASSERT(bitstream.bit_size == frame_size*8);
1178   } else { /* elementary format */
1179     frame_end = frame + frame_size;
1180     nal_start = frame;
1181     nal_size = 0;
1182     while((nal_start = h264_next_nal(nal_start, frame_end-nal_start, &nal_size)) != NULL) {
1183       ENCODER_ASSERT(nal_size);
1184       if (!nal_size) {
1185         nal_start += nal_size;
1186         continue;
1187       }
1188       h264_bitstream_write_uint(&bitstream, nal_size, 32);
1189       h264_bitstream_write_byte_array(&bitstream, nal_start, nal_size);
1190       nal_start += nal_size;
1191     }
1192   }
1193   h264_bitstream_align(&bitstream, 0);
1194
1195   GST_BUFFER_MALLOCDATA(ret_buffer) =
1196         GST_BUFFER_DATA(ret_buffer) = BIT_STREAM_BUFFER(&bitstream);
1197   GST_BUFFER_SIZE(ret_buffer) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
1198   h264_bitstream_destroy(&bitstream, FALSE);
1199 #endif
1200
1201   return ret_buffer;
1202
1203 }
1204
1205 static EncoderStatus
1206 h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const uint8_t *buf, uint32_t size)
1207 {
1208   const uint8_t *end = buf + size;
1209   const uint8_t *nal_start = buf;
1210   uint32_t nal_size = 0;
1211   uint8_t nal_type;
1212   GstBuffer *sps = NULL, *pps = NULL;
1213
1214   while((!sps || !pps) && (nal_start = h264_next_nal(nal_start, end-nal_start, &nal_size)) != NULL) {
1215     if (!nal_size) {
1216       nal_start += nal_size;
1217       continue;
1218     }
1219
1220     nal_type = (*nal_start)&0x1F;
1221     switch (nal_type) {
1222       case NAL_SPS: {
1223         sps = gst_buffer_new_and_alloc(nal_size);
1224         memcpy(GST_BUFFER_DATA(sps), nal_start, nal_size);
1225         gst_buffer_replace(&h264_prv->sps_data, sps);
1226         gst_buffer_unref(sps); /*don't set to NULL*/
1227         break;
1228       }
1229
1230       case NAL_PPS: {
1231         pps = gst_buffer_new_and_alloc(nal_size);
1232         memcpy(GST_BUFFER_DATA(pps), nal_start, nal_size);
1233         gst_buffer_replace(&h264_prv->pps_data, pps);
1234         gst_buffer_unref(pps);
1235         break;
1236       }
1237
1238       default:
1239         break;
1240     }
1241     nal_start += nal_size;
1242
1243   }
1244   if (!sps || !pps) {
1245     return ENCODER_DATA_NOT_READY;
1246   }
1247   return ENCODER_NO_ERROR;
1248 }
1249
1250 static gboolean
1251 h264_read_sps_attributes(const uint8_t *sps_data, uint32_t sps_size,
1252                                 uint32_t *profile_idc, uint32_t *profile_comp, uint32_t *level_idc)
1253 {
1254   ENCODER_ASSERT(profile_idc && profile_comp && level_idc);
1255   ENCODER_ASSERT(sps_size >= 4);
1256   if (sps_size < 4) {
1257     return FALSE;
1258   }
1259   /*skip sps_data[0], nal_type*/
1260   *profile_idc = sps_data[1];
1261   *profile_comp = sps_data[2];
1262   *level_idc = sps_data[3];
1263   return TRUE;
1264 }
1265
1266
1267 EncoderStatus
1268 gst_h264_encoder_flush(GstVaapiEncoder* encoder, GList **coded_pics)
1269 {
1270   GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
1271   EncoderStatus ret = ENCODER_NO_ERROR;
1272   GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
1273   GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
1274
1275   h264_prv->frame_count = 0;
1276   /*do we need destroy h264_prv->seq_parameter? */
1277
1278   //end:
1279   return ret;
1280 }
1281
1282 /*test*/
1283 static int draw_picture(int width, int height,
1284                          unsigned char *Y_start,
1285                          unsigned char *U_start,
1286                          unsigned char *V_start,
1287                          int UV_interleave, int box_width, int row_shift);
1288
1289 int main_test(int argc, char* argv[])
1290 {
1291   EncoderStatus ret = ENCODER_NO_ERROR;
1292   GstVaapiEncoder *encoder = NULL;
1293
1294   GList *coded_pics = NULL;
1295   GstBuffer **raw_buffer = NULL;
1296   const uint32_t raw_buffer_num = 20;
1297
1298   GstBuffer *tmp_buffer;
1299
1300   uint32_t i = 0, k = 0;
1301
1302   gst_init (&argc, &argv);
1303
1304   g_type_init();
1305   if (!g_thread_supported ())
1306     g_thread_init (NULL);
1307
1308   GstH264Encoder *h264_encoder = gst_h264_encoder_new();
1309   encoder = GST_VAAPI_ENCODER(h264_encoder);
1310   ENCODER_ASSERT(encoder);
1311
1312   h264_encoder->profile = 64;
1313   h264_encoder->level = 30;
1314   h264_encoder->parent.width = 1280;
1315   h264_encoder->parent.height = 720;
1316   h264_encoder->parent.frame_rate = 10;
1317   h264_encoder->bitrate = 512*1000;
1318   h264_encoder->intra_period = 30;
1319   ret = gst_vaapi_encoder_initialize(encoder);
1320   ENCODER_ASSERT(ret == ENCODER_NO_ERROR);
1321   ret = gst_vaapi_encoder_open(encoder, NULL);
1322   ENCODER_ASSERT(ret == ENCODER_NO_ERROR);
1323
1324   uint32_t buffer_size = encoder->width * encoder->width *3 /2;
1325   uint32_t y_width = encoder->width, y_size = encoder->width * encoder->height;
1326   uint32_t u_width = encoder->width/2, u_size = (encoder->width/2) * (encoder->height/2);
1327   uint32_t v_width = encoder->width/2;
1328   uint8_t *y_src, *u_src, *v_src;
1329
1330   /*set buffers*/
1331   int box_width=8;
1332   int row_shift=0;
1333   raw_buffer = (GstBuffer**)g_malloc0(raw_buffer_num*sizeof(GstBuffer*));
1334   for (i = 0; i < raw_buffer_num; i++) {
1335     raw_buffer[i] = gst_buffer_new_and_alloc(buffer_size);
1336     y_src = GST_BUFFER_DATA(raw_buffer[i]);
1337     u_src = y_src + y_size;
1338     v_src = u_src + u_size;
1339
1340     draw_picture(encoder->width, encoder->height, y_src, u_src, v_src, 0, box_width, row_shift);
1341     row_shift++;
1342     if (row_shift==(2*box_width)) row_shift= 0;
1343   }
1344
1345   FILE *fp = fopen("tmp.h264", "wb");
1346   ENCODER_ASSERT(fp);
1347
1348   k = 0;
1349
1350   for (i = 0; i < 50; i++) {
1351     coded_pics = NULL;
1352     ret = gst_vaapi_encoder_encode(encoder, raw_buffer[k], &coded_pics);
1353     ENCODER_ASSERT(ENCODER_NO_ERROR == ret);
1354     ++k;
1355     if (k >= raw_buffer_num) k = 0;
1356
1357     while (coded_pics) {
1358       tmp_buffer = coded_pics->data;
1359       coded_pics = g_list_remove(coded_pics, tmp_buffer);
1360       fwrite(GST_BUFFER_DATA(tmp_buffer), GST_BUFFER_SIZE(tmp_buffer), 1, fp);
1361       printf("F:%d, S:%d, %s\n", i, GST_BUFFER_SIZE(tmp_buffer), vaapi_encoder_dump_bytes(GST_BUFFER_DATA(tmp_buffer)+4, 8));
1362       gst_buffer_unref(tmp_buffer);
1363     }
1364   }
1365   fclose(fp);
1366
1367   ret = gst_vaapi_encoder_close(encoder);
1368   ENCODER_ASSERT(ENCODER_NO_ERROR == ret);
1369
1370   for (i = 0; i < raw_buffer_num; i++) {
1371     gst_buffer_unref(raw_buffer[i]);
1372   }
1373   g_free(raw_buffer);
1374   gst_vaapi_encoder_unref(encoder);
1375
1376   return 0;
1377 }
1378
1379 EncoderStatus
1380 gst_h264_encoder_get_avcC_codec_data(GstVaapiEncoder *encoder, GstBuffer **buffer)
1381 {
1382   GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
1383   GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
1384   GstBuffer *avc_codec;
1385   const uint32_t configuration_version = 0x01;
1386   const uint32_t length_size_minus_one = 0x03;
1387   uint32_t profile, profile_comp, level_idc;
1388
1389   ENCODER_ASSERT(buffer);
1390   if (!h264_prv->sps_data || !h264_prv->pps_data) {
1391     return ENCODER_DATA_NOT_READY;
1392   }
1393
1394   if (FALSE == h264_read_sps_attributes(GST_BUFFER_DATA(h264_prv->sps_data),
1395                                    GST_BUFFER_SIZE(h264_prv->sps_data),
1396                                    &profile, &profile_comp, &level_idc))
1397   {
1398     ENCODER_ASSERT(0);
1399     return ENCODER_DATA_ERR;
1400   }
1401
1402   H264Bitstream bitstream;
1403   h264_bitstream_init(&bitstream,
1404                      (GST_BUFFER_SIZE(h264_prv->sps_data)+GST_BUFFER_SIZE(h264_prv->pps_data) + 32)*8);
1405
1406   /*codec_data*/
1407   h264_bitstream_write_uint(&bitstream, configuration_version, 8);
1408   h264_bitstream_write_uint(&bitstream, profile, 8);
1409   h264_bitstream_write_uint(&bitstream, profile_comp, 8);
1410   h264_bitstream_write_uint(&bitstream, level_idc, 8);
1411   h264_bitstream_write_uint(&bitstream, h264_bit_mask[6], 6); /*111111*/
1412   h264_bitstream_write_uint(&bitstream, length_size_minus_one, 2);
1413   h264_bitstream_write_uint(&bitstream, h264_bit_mask[3], 3); /*111*/
1414
1415   /*write sps*/
1416   h264_bitstream_write_uint(&bitstream, 1, 5);   /* sps count = 1*/
1417   ENCODER_ASSERT( BIT_STREAM_BIT_SIZE(&bitstream)%8 == 0);
1418   h264_bitstream_write_uint(&bitstream, GST_BUFFER_SIZE(h264_prv->sps_data), 16);
1419   h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->sps_data),
1420                                               GST_BUFFER_SIZE(h264_prv->sps_data));
1421
1422   /*write pps*/
1423   h264_bitstream_write_uint(&bitstream, 1, 8); /*pps count = 1*/
1424   h264_bitstream_write_uint(&bitstream, GST_BUFFER_SIZE(h264_prv->pps_data), 16);
1425   h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->pps_data),
1426                                               GST_BUFFER_SIZE(h264_prv->pps_data));
1427
1428   avc_codec = gst_buffer_new();
1429   GST_BUFFER_MALLOCDATA(avc_codec) =
1430          GST_BUFFER_DATA(avc_codec) =
1431          BIT_STREAM_BUFFER(&bitstream);
1432   GST_BUFFER_SIZE(avc_codec) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
1433   h264_bitstream_destroy(&bitstream, FALSE);
1434   *buffer = avc_codec;
1435
1436   return ENCODER_NO_ERROR;
1437 }
1438
1439 EncoderStatus
1440 gst_h264_encoder_get_nal_codec_data(GstVaapiEncoder *encoder, GstBuffer **buffer)
1441 {
1442   GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
1443   GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
1444   GstBuffer *nal_sps_pps;
1445
1446   ENCODER_ASSERT(buffer);
1447   if (!h264_prv->sps_data || !h264_prv->pps_data) {
1448     return ENCODER_DATA_NOT_READY;
1449   }
1450
1451   H264Bitstream bitstream;
1452   h264_bitstream_init(&bitstream,
1453                      (GST_BUFFER_SIZE(h264_prv->sps_data)+GST_BUFFER_SIZE(h264_prv->pps_data) + 8)*8);
1454
1455   /*0x000001 start code*/
1456   h264_bitstream_write_uint(&bitstream, 0x000001, 24);
1457   h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->sps_data),
1458                                               GST_BUFFER_SIZE(h264_prv->sps_data));
1459   h264_bitstream_write_uint(&bitstream, 0x000001, 24);
1460   h264_bitstream_write_byte_array(&bitstream, GST_BUFFER_DATA(h264_prv->pps_data),
1461                                               GST_BUFFER_SIZE(h264_prv->pps_data));
1462
1463   nal_sps_pps = gst_buffer_new();
1464   GST_BUFFER_MALLOCDATA(nal_sps_pps) =
1465          GST_BUFFER_DATA(nal_sps_pps) =
1466          BIT_STREAM_BUFFER(&bitstream);
1467   GST_BUFFER_SIZE(nal_sps_pps) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
1468   h264_bitstream_destroy(&bitstream, FALSE);
1469   *buffer = nal_sps_pps;
1470   return ENCODER_NO_ERROR;
1471 }
1472
1473 static void
1474 h264_bitstream_init(H264Bitstream *bitstream, uint32_t bit_capability)
1475 {
1476   bitstream->bit_size = 0;
1477   bitstream->buffer = NULL;
1478   bitstream->max_bit_capability = 0;
1479   if (bit_capability) {
1480     h264_bitstream_auto_grow(bitstream, bit_capability);
1481   }
1482 }
1483
1484 static gboolean
1485 h264_bitstream_write_uint(H264Bitstream *bitstream, uint32_t value, uint32_t bit_size)
1486 {
1487   gboolean ret = TRUE;
1488   uint32_t byte_pos, bit_offset;
1489   uint8_t  *cur_byte;
1490   uint32_t fill_bits;
1491
1492   if(!bit_size) {
1493     return TRUE;
1494   }
1495
1496   ENCODER_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, bit_size), FALSE, "h264_bitstream_auto_grow failed.\n");
1497   byte_pos = (bitstream->bit_size>>3);
1498   bit_offset = (bitstream->bit_size&0x07);
1499   cur_byte = bitstream->buffer + byte_pos;
1500   ENCODER_ASSERT(bit_offset < 8 && bitstream->bit_size <= bitstream->max_bit_capability);
1501
1502   while (bit_size) {
1503     fill_bits = ((8-bit_offset) < bit_size ? (8-bit_offset) : bit_size);
1504     bit_size -= fill_bits;
1505     bitstream->bit_size += fill_bits;
1506
1507     *cur_byte |= ((value>>bit_size) & h264_bit_mask[fill_bits])<<(8-bit_offset-fill_bits);
1508     ++cur_byte;
1509     bit_offset = 0;
1510   }
1511   ENCODER_ASSERT(cur_byte <= bitstream->buffer + bitstream->max_bit_capability/8);
1512   return TRUE;
1513
1514   end:
1515   return FALSE;
1516 }
1517
1518 static gboolean h264_bitstream_align(H264Bitstream *bitstream, uint32_t value)
1519 {
1520   uint32_t bit_offset, bit_left;
1521
1522   bit_offset = (bitstream->bit_size&0x07);
1523   if (!bit_offset) {
1524     return TRUE;
1525   }
1526   bit_left = 8 - bit_offset;
1527   if (value) value = h264_bit_mask[bit_left];
1528   return h264_bitstream_write_uint(bitstream, value, bit_left);
1529 }
1530
1531
1532 static gboolean
1533 h264_bitstream_write_byte_array(H264Bitstream *bitstream, const uint8_t *buf, uint32_t byte_size)
1534 {
1535   gboolean ret = TRUE;
1536   if (!byte_size) {
1537     return 0;
1538   }
1539   ENCODER_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, byte_size<<3), FALSE, "h264_bitstream_auto_grow failed.\n");
1540   if (0 == (bitstream->bit_size&0x07)) {
1541     memcpy(&bitstream->buffer[bitstream->bit_size>>3], buf, byte_size);
1542     bitstream->bit_size += (byte_size<<3);
1543   } else {
1544     ENCODER_ASSERT(0);
1545     while(byte_size) {
1546       h264_bitstream_write_uint(bitstream, *buf, 8);
1547       --byte_size;
1548       ++buf;
1549     }
1550   }
1551   return TRUE;
1552
1553   end:
1554   return FALSE;
1555 }
1556
1557 static gboolean
1558 h264_bitstream_write_ue(H264Bitstream *bitstream, uint32_t value)
1559 {
1560   gboolean ret = TRUE;
1561   uint32_t size_in_bits = 0;
1562   uint32_t tmp_value = ++value;
1563   while (tmp_value) {
1564     ++size_in_bits;
1565     tmp_value >>= 1;
1566   }
1567   ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, 0, size_in_bits-1), FALSE, "h264_bitstream_write_ue failed.\n");
1568   ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, value, size_in_bits), FALSE, "h264_bitstream_write_ue failed.\n");
1569   return TRUE;
1570
1571   end:
1572   return FALSE;
1573 }
1574
1575 static gboolean
1576 h264_bitstream_write_se(H264Bitstream *bitstream, int32_t value)
1577 {
1578   gboolean ret = TRUE;
1579   uint32_t new_val;
1580
1581   if (value <= 0) {
1582     new_val = -(value<<1);
1583   } else {
1584     new_val = (value<<1) - 1;
1585   }
1586
1587   ENCODER_CHECK_STATUS(h264_bitstream_write_ue(bitstream, new_val), FALSE, "h264_bitstream_write_se failed.\n");
1588   return TRUE;
1589
1590   end:
1591   return FALSE;
1592 }
1593
1594 static gboolean
1595 h264_bitstream_write_trailing_bits(H264Bitstream *bitstream)
1596 {
1597     h264_bitstream_write_uint(bitstream, 1, 1);
1598     h264_bitstream_align(bitstream, 0);
1599     return TRUE;
1600 }
1601
1602 static void
1603 h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag)
1604 {
1605   if (bitstream->buffer && free_flag) {
1606     free (bitstream->buffer);
1607   }
1608   bitstream->buffer = NULL;
1609   bitstream->bit_size = 0;
1610   bitstream->max_bit_capability = 0;
1611 }
1612
1613 static gboolean
1614 h264_bitstream_auto_grow(H264Bitstream *bitstream, uint32_t extra_bit_size)
1615 {
1616   uint32_t new_bit_size = extra_bit_size + bitstream->bit_size;
1617   uint32_t clear_pos;
1618
1619   ENCODER_ASSERT(bitstream->bit_size <= bitstream->max_bit_capability);
1620   if (new_bit_size <= bitstream->max_bit_capability) {
1621     return TRUE;
1622   }
1623
1624   new_bit_size = ((new_bit_size + H264_BITSTREAM_ALLOC_ALIGN_MASK)
1625                 &(~H264_BITSTREAM_ALLOC_ALIGN_MASK));
1626   ENCODER_ASSERT(new_bit_size%(H264_BITSTREAM_ALLOC_ALIGN_MASK+1) == 0);
1627   clear_pos = ((bitstream->bit_size+7)>>3);
1628   bitstream->buffer = realloc(bitstream->buffer, new_bit_size>>3);
1629   memset(bitstream->buffer+clear_pos, 0, (new_bit_size>>3)-clear_pos);
1630   bitstream->max_bit_capability = new_bit_size;
1631   return TRUE;
1632 }
1633
1634 static gboolean
1635 h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv)
1636 {
1637   uint32_t constraint_set0_flag, constraint_set1_flag, constraint_set2_flag, constraint_set3_flag;
1638   uint32_t seq_parameter_set_id = 0;
1639
1640   /*need to set the values*/
1641   uint32_t log2_max_frame_num_minus4 = 0;  // 1? 3?
1642   uint32_t pic_order_cnt_type = 0; // Must be 0
1643   uint32_t log2_max_pic_order_cnt_lsb_minus4 = 0;  // 2 ? 4?
1644   uint32_t num_ref_frames = 1;  // only P frames
1645   uint32_t gaps_in_frame_num_value_allowed_flag = 0; // ??
1646   uint32_t mb_width = (ENCODER_WIDTH(h264_prv->public)+15)/16; // mb_width
1647   uint32_t mb_height = (ENCODER_HEIGHT(h264_prv->public)+15)/16; // mb_height
1648   int32_t frame_mbs_only_flag = 1; // only mbs
1649   uint32_t frame_cropping_flag = 0;
1650   uint32_t frame_crop_bottom_offset = 0;
1651   uint32_t vui_present_flag = 0; // no vui flags
1652
1653
1654   constraint_set0_flag = h264_prv->public->profile == H264_PROFILE_BASELINE;
1655   constraint_set1_flag = h264_prv->public->profile <= H264_PROFILE_MAIN;
1656   constraint_set2_flag = 0;
1657   constraint_set3_flag = 0;
1658
1659   if (mb_height * 16 - ENCODER_HEIGHT(h264_prv->public)) {
1660     frame_cropping_flag = 1;
1661     frame_crop_bottom_offset =
1662         (mb_height * 16 - ENCODER_HEIGHT(h264_prv->public)) / (2 * (!frame_mbs_only_flag + 1));
1663   }
1664
1665   h264_bitstream_write_uint(bitstream, h264_prv->public->profile, 8); /* profile_idc */
1666   h264_bitstream_write_uint(bitstream, constraint_set0_flag, 1);     /* constraint_set0_flag */
1667   h264_bitstream_write_uint(bitstream, constraint_set1_flag, 1);     /* constraint_set1_flag */
1668   h264_bitstream_write_uint(bitstream, constraint_set2_flag, 1);     /* constraint_set2_flag */
1669   h264_bitstream_write_uint(bitstream, constraint_set3_flag, 1);     /* constraint_set3_flag */
1670   h264_bitstream_write_uint(bitstream, 0, 4);                        /* reserved_zero_4bits */
1671   h264_bitstream_write_uint(bitstream, h264_prv->public->level, 8);   /* level_idc */
1672   h264_bitstream_write_ue(bitstream, seq_parameter_set_id);          /* seq_parameter_set_id */
1673
1674   if (h264_prv->public->profile >= H264_PROFILE_HIGH) {
1675       /* FIXME: fix for high profile */
1676       ENCODER_ASSERT(0);
1677   }
1678
1679   h264_bitstream_write_ue(bitstream, log2_max_frame_num_minus4);    /* log2_max_frame_num_minus4 */
1680   h264_bitstream_write_ue(bitstream, pic_order_cnt_type);           /* pic_order_cnt_type */
1681
1682   if (pic_order_cnt_type == 0)
1683       h264_bitstream_write_ue(bitstream, log2_max_pic_order_cnt_lsb_minus4);/* log2_max_pic_order_cnt_lsb_minus4 */
1684   else {
1685       ENCODER_ASSERT(0);
1686   }
1687
1688   h264_bitstream_write_ue(bitstream, num_ref_frames);                            /* num_ref_frames */
1689   h264_bitstream_write_uint(bitstream, gaps_in_frame_num_value_allowed_flag, 1); /* gaps_in_frame_num_value_allowed_flag */
1690
1691   h264_bitstream_write_ue(bitstream, mb_width - 1);              /* pic_width_in_mbs_minus1 */
1692   h264_bitstream_write_ue(bitstream, mb_height - 1);             /* pic_height_in_map_units_minus1 */
1693   h264_bitstream_write_uint(bitstream, frame_mbs_only_flag, 1);  /* frame_mbs_only_flag */
1694
1695   if (!frame_mbs_only_flag) { //ONLY mbs
1696       ENCODER_ASSERT(0);
1697   }
1698
1699   h264_bitstream_write_uint(bitstream, 0, 1);                         /* direct_8x8_inference_flag */
1700   h264_bitstream_write_uint(bitstream, frame_cropping_flag, 1);       /* frame_cropping_flag */
1701
1702   if (frame_cropping_flag) {
1703       h264_bitstream_write_ue(bitstream, 0);                        /* frame_crop_left_offset */
1704       h264_bitstream_write_ue(bitstream, 0);                        /* frame_crop_right_offset */
1705       h264_bitstream_write_ue(bitstream, 0);                        /* frame_crop_top_offset */
1706       h264_bitstream_write_ue(bitstream, frame_crop_bottom_offset); /* frame_crop_bottom_offset */
1707   }
1708
1709   h264_bitstream_write_uint(bitstream, vui_present_flag, 1);                         /* vui_parameters_present_flag */
1710   h264_bitstream_write_trailing_bits(bitstream);                             /* rbsp_trailing_bits */
1711   return TRUE;
1712
1713   //end:
1714   //return FALSE;
1715
1716 }
1717
1718 static const uint8_t *
1719 h264_next_nal(const uint8_t *buffer, uint32_t len, uint32_t *nal_size)
1720 {
1721     const uint8_t *cur = buffer;
1722     const uint8_t *end = buffer + len;
1723     const uint8_t *nal_start = NULL;
1724     uint32_t flag = 0xFFFFFFFF;
1725     uint32_t nal_start_len = 0;
1726
1727     ENCODER_ASSERT(len >= 0 && buffer && nal_size);
1728     if (len < 3) {
1729         *nal_size = len;
1730         nal_start = (len ? buffer : NULL);
1731         return nal_start;
1732     }
1733
1734     /*locate head postion*/
1735     if (!buffer[0] && !buffer[1]) {
1736         if (buffer[2] == 1) { // 0x000001
1737             nal_start_len = 3;
1738         } else if (!buffer[2] && len >=4 && buffer[3] == 1) { //0x00000001
1739             nal_start_len = 4;
1740         }
1741     }
1742     nal_start = buffer + nal_start_len;
1743     cur = nal_start;
1744
1745     /*find next nal start position*/
1746     while (cur < end) {
1747         flag = ((flag<<8) | ((*cur++)&0xFF));
1748         if (flag == 0x00000001) {
1749             *nal_size = cur - 4 - nal_start;
1750             break;
1751         } else if ((flag&0x00FFFFFF) == 0x00000001) {
1752             *nal_size = cur - 3 - nal_start;
1753             break;
1754         }
1755     }
1756     if (cur >= end) {
1757       *nal_size = end - nal_start;
1758       if (nal_start >= end) {
1759         nal_start = NULL;
1760       }
1761     }
1762     return nal_start;
1763 }
1764
1765
1766 static gboolean
1767 h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv)
1768 {
1769   ENCODER_ASSERT(0);
1770   return TRUE;
1771 }
1772
1773 static int draw_picture(int width, int height,
1774                          unsigned char *Y_start,
1775                          unsigned char *U_start,
1776                          unsigned char *V_start,
1777                          int UV_interleave, int box_width, int row_shift)
1778 {
1779     int row;
1780     int field = 0;
1781     int Y_pitch = width;
1782     int U_pitch = width/2;
1783     int V_pitch = width/2;
1784
1785     /* copy Y plane */
1786     for (row=0;row<height;row++) {
1787         unsigned char *Y_row = Y_start + row * Y_pitch;
1788         int jj, xpos, ypos;
1789
1790         ypos = (row / box_width) & 0x1;
1791
1792         /* fill garbage data into the other field */
1793         if (((field == 1) && (row &1))
1794             || ((field == 2) && ((row &1)==0))) {
1795             memset(Y_row, 0xff, width);
1796             continue;
1797         }
1798
1799         for (jj=0; jj<width; jj++) {
1800             xpos = ((row_shift + jj) / box_width) & 0x1;
1801
1802             if ((xpos == 0) && (ypos == 0))
1803                 Y_row[jj] = 0xeb;
1804             if ((xpos == 1) && (ypos == 1))
1805                 Y_row[jj] = 0xeb;
1806
1807             if ((xpos == 1) && (ypos == 0))
1808                 Y_row[jj] = 0x10;
1809             if ((xpos == 0) && (ypos == 1))
1810                 Y_row[jj] = 0x10;
1811         }
1812     }
1813
1814     /* copy UV data */
1815     for( row =0; row < height/2; row++) {
1816         unsigned short value = 0x80;
1817
1818         /* fill garbage data into the other field */
1819         if (((field == 1) && (row &1))
1820             || ((field == 2) && ((row &1)==0))) {
1821             value = 0xff;
1822         }
1823
1824         if (UV_interleave) {
1825             unsigned short *UV_row = (unsigned short *)(U_start + row * U_pitch);
1826
1827             memset(UV_row, value, width);
1828         } else {
1829             unsigned char *U_row = U_start + row * U_pitch;
1830             unsigned char *V_row = V_start + row * V_pitch;
1831
1832             memset (U_row,value,width/2);
1833             memset (V_row,value,width/2);
1834         }
1835     }
1836     return 0;
1837 }
1838
1839
1840