add properties in gsth264encode; profile, level,bitrate, intra-period, init-qp
[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/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"
21
22 #define ENCPRV(encoder) GST_H264_ENCODER_GET_PRIVATE(encoder)
23
24 #define H264_CHECK_STATUS(exp, err_num, err_reason, ...)  \
25   H264_ASSERT(exp);                             \
26   if (!(exp)) {                                 \
27     ret = err_num;                              \
28     H264_LOG_ERROR(err_reason, ## __VA_ARGS__);                 \
29     goto error;                                 \
30   }
31
32 #define SHARE_CODED_BUF         0
33
34 #define DEFAULT_SURFACE_NUMBER  3
35 #define DEFAULT_CODEDBUF_NUM    5
36 #define DEFAULT_SID_INPUT       0 // suface_ids[0]
37
38 #define REF_RECON_SURFACE_NUM   2
39
40 typedef struct _GstH264EncodeBuffer  GstH264EncodeBuffer;
41
42 #define GST_TYPE_H264_ENCODE_BUFFER (gst_h264_encode_buffer_get_type())
43
44 typedef enum {
45   NAL_UNKNOWN     = 0,
46   NAL_NON_IDR     = 1,
47   NAL_IDR         = 5,    /* ref_idc != 0 */
48   NAL_SEI         = 6,    /* ref_idc == 0 */
49   NAL_SPS         = 7,
50   NAL_PPS         = 8,
51   NAL_AUD         = 9,
52   NAL_FILLER      = 12,
53 }H264_NAL_TYPE;
54
55 struct _GstH264EncodeBuffer {
56   GstBuffer           buffer;
57   VABufferID         *coded_id;
58   GstH264EncoderPrivate *encoder;
59 };
60
61 struct _GstH264EncoderPrivate {
62   GstH264Encoder   *public;
63   uint32_t          format;   /*NV12, I420,*/
64   gboolean          es_flag;  /*elementary flag*/
65
66   /* private data*/
67   GstVaapiDisplay  *vaapi_display;
68   GstVaapiContext  *vaapi_context;
69   GQueue           *video_buffer_caches; /*not used for baseline*/
70
71   GstVaapiSurface  *ref_surface;  /* reference buffer*/
72   GstVaapiSurface  *recon_surface; /* reconstruct buffer*/
73
74   H264_Encode_State encode_state;
75
76   VABufferID        seq_parameter;
77   VABufferID        pic_parameter;
78   VABufferID        slice_parameter;
79
80   VABufferID       *coded_bufs;
81   uint32_t          coded_buf_num;
82   uint32_t          cur_coded_index;
83
84   /*total encoded frames*/
85   uint32_t          frame_count;
86
87   GstBuffer        *sps_data;
88   GstBuffer        *pps_data;
89
90   GMutex           *code_buffer_lock;
91   GCond            *code_buffer_cond;
92   GQueue           *available_code_buffers;
93
94 };
95
96 G_DEFINE_TYPE(GstH264Encoder, gst_h264_encoder, G_TYPE_OBJECT);
97
98
99 // 4096-1
100 #define H264_BITSTREAM_ALLOC_ALIGN_MASK 0x0FFF
101
102 #define BIT_STREAM_BUFFER(stream)    ((stream)->buffer)
103 #define BIT_STREAM_BIT_SIZE(stream)  ((stream)->bit_size)
104
105 struct _H264Bitstream {
106   uint8_t  *buffer;
107   uint32_t  bit_size;
108   uint32_t  max_bit_capability;
109 };
110
111 typedef struct _H264Bitstream H264Bitstream;
112
113 static const uint8_t h264_bit_mask[9] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
114
115 static GstBufferClass *h264_encode_buffer_parent_class = NULL;
116
117 static void gst_h264_encoder_finalize(GObject *object);
118
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,
123                                              GstBuffer *raw_pic,
124                                              GstVaapiSurface *surface);
125
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,
131                                          gboolean is_key,
132                                          GstClockTime timestamp,
133                                          GstClockTime duration,
134                                          VABufferID *coded_buf,
135                                          GList **coded_pics);
136 static H264Status
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,
139                                                    uint8_t *frame,
140                                                    uint32_t frame_size,
141                                                    VABufferID *coded_buf);
142
143
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);
150
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);
158
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);
167
168 static void
169 gst_h264_encoder_class_init(GstH264EncoderClass *klass)
170 {
171   GObjectClass * const object_class = G_OBJECT_CLASS(klass);
172   g_type_class_add_private(klass, sizeof(GstH264EncoderPrivate));
173
174   object_class->finalize = gst_h264_encoder_finalize;
175   /*
176   object_class->set_property = gst_h264_encoder_set_property;
177   object_class->get_property = gst_h264_encoder_get_property;
178   */
179 }
180
181
182 static void
183 gst_h264_encode_buffer_class_init (gpointer g_class, gpointer class_data)
184 {
185   GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS(g_class);
186
187   h264_encode_buffer_parent_class = g_type_class_peek_parent(g_class);
188   H264_ASSERT(h264_encode_buffer_parent_class);
189
190   mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
191       gst_h264_encode_buffer_finalize;
192 }
193
194
195 static GType
196 gst_h264_encode_buffer_get_type (void)
197 {
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),
202       NULL,
203       NULL,
204       gst_h264_encode_buffer_class_init,
205       NULL,
206       NULL,
207       sizeof(GstH264EncodeBuffer),
208       0,
209       NULL,
210       NULL
211     };
212     s_h264_encode_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
213         "GstH264EncodeBuffer", &s_h264_encode_buffer_info, 0);
214   }
215   return s_h264_encode_buffer_type;
216 }
217
218 static void
219 gst_h264_encode_buffer_finalize (GstH264EncodeBuffer *h264_buffer)
220 {
221   GstH264EncoderPrivate *h264_prv = NULL;
222   VABufferID* coded_id = NULL;
223
224   h264_prv = h264_buffer->encoder;
225   coded_id = h264_buffer->coded_id;
226
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);
230
231   H264_ASSERT(h264_prv);
232   H264_ASSERT(coded_id && VA_INVALID_ID!= *coded_id);
233   H264_ASSERT(h264_prv->available_code_buffers);
234
235   g_mutex_lock(h264_prv->code_buffer_lock);
236   /*if (--(*h264_buffer->ref_coded_id) == 0) */
237   {
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);
242   }
243
244   g_mutex_unlock(h264_prv->code_buffer_lock);
245
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));
248   }
249 }
250
251 static GstH264EncodeBuffer *
252 gst_h264_encode_buffer_new(GstH264EncoderPrivate *h264_prv,
253                            VABufferID *coded_id)
254 {
255   GstH264EncodeBuffer *buf = (GstH264EncodeBuffer*)gst_mini_object_new(GST_TYPE_H264_ENCODE_BUFFER);
256   buf->coded_id = coded_id;
257   buf->encoder = h264_prv;
258   return buf;
259 }
260
261
262 static GstVaapiSurface *
263 h264_get_video_surface(GstH264EncoderPrivate *h264_prv, GstVaapiVideoBuffer *video_buffer)
264 {
265   //ref_surface
266   GstVaapiSurface *ret = gst_vaapi_video_buffer_get_surface(video_buffer);
267
268   H264_CHECK_STATUS(ret, NULL, "video buffer doesn't have a surface");
269 #if 0
270   g_queue_push_tail(h264_prv->video_buffer_caches,video_buffer);
271   gst_buffer_ref(GST_BUFFER(video_buffer));
272 #endif
273   return ret;
274
275   error:
276   return NULL;
277 }
278
279 static void
280 h264_release_video_surface(GstH264EncoderPrivate *h264_prv, VASurfaceID surface)
281 {
282 #if 0
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) {
286   }
287 #endif
288 }
289
290 static GstVaapiSurface *
291 h264_pop_free_surface(GstH264EncoderPrivate *h264_prv)
292 {
293   H264_ASSERT(h264_prv && h264_prv->vaapi_context);
294
295   /*may need lock*/
296   GstVaapiSurface *surface = gst_vaapi_context_get_surface(h264_prv->vaapi_context);
297   return surface;
298 }
299
300 static void
301 h264_push_free_surface(GstH264EncoderPrivate *h264_prv, GstVaapiSurface *surface)
302 {
303   H264_ASSERT(surface);
304   if (!surface) {
305     return;
306   }
307   gst_vaapi_context_put_surface(h264_prv->vaapi_context, surface);
308 }
309
310
311 H264_Encode_State gst_h264_encoder_get_state(GstH264Encoder* encoder)
312 {
313   GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
314   return h264_prv->encode_state;
315 }
316
317
318 static VAProfile
319 h264_get_va_profile(uint32_t profile)
320 {
321   switch (profile) {
322     case H264_PROFILE_BASELINE:
323       return VAProfileH264Baseline;
324
325     case H264_PROFILE_MAIN:
326       return VAProfileH264Main;
327
328     case H264_PROFILE_HIGH:
329       return VAProfileH264High;
330
331     default:
332       break;
333   }
334   return (-1);
335 }
336
337 GstH264Encoder *
338 gst_h264_encoder_new(void)
339 {
340   return GST_H264_ENCODER(g_object_new(GST_TYPE_H264_ENCODER, NULL));
341 }
342
343
344 static void
345 gst_h264_encoder_init(GstH264Encoder *encoder)
346 {
347   GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
348   H264_ASSERT(h264_prv);
349
350   /* init public attributes */
351   gst_h264_encoder_set_default_values(encoder);
352
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;
357
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();
363
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;
368
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;
374   /*index init*/
375   h264_prv->cur_coded_index = 0;
376   /*init others*/
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();
380
381 }
382
383 static void
384 gst_h264_encoder_finalize(GObject *object)
385 {
386   /*free private buffers*/
387   GstH264EncoderPrivate *h264_prv = ENCPRV(object);
388
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;
394   }
395
396   if (h264_prv->ref_surface) {
397     if (h264_prv->vaapi_context) {
398       h264_push_free_surface(h264_prv, h264_prv->ref_surface);
399     } else {
400       g_object_unref(h264_prv->ref_surface);
401     }
402     h264_prv->ref_surface = NULL;
403   }
404   if (h264_prv->recon_surface) {
405     if (h264_prv->vaapi_context) {
406       h264_push_free_surface(h264_prv, h264_prv->recon_surface);
407     } else {
408       g_object_unref(h264_prv->recon_surface);
409     }
410     h264_prv->recon_surface = NULL;
411   }
412   if (h264_prv->vaapi_context) {
413     g_object_unref(h264_prv->vaapi_context);
414     h264_prv->vaapi_context= NULL;
415   }
416   if (h264_prv->vaapi_display) {
417     g_object_unref(h264_prv->vaapi_display);
418     h264_prv->vaapi_display = NULL;
419   }
420   if (h264_prv->video_buffer_caches) {
421     g_queue_free(h264_prv->video_buffer_caches);
422     h264_prv->video_buffer_caches = NULL;
423   };
424   if (h264_prv->sps_data) {
425     gst_buffer_unref(h264_prv->sps_data);
426     h264_prv->sps_data = NULL;
427   }
428   if (h264_prv->pps_data) {
429     gst_buffer_unref(h264_prv->pps_data);
430     h264_prv->pps_data = NULL;
431   }
432 }
433
434
435 void
436 gst_h264_encoder_set_default_values(GstH264Encoder* encoder)
437 {
438   encoder->profile = H264_DEFAULT_PROFILE;
439   encoder->level = H264_DEFAULT_LEVEL;
440   encoder->width = 0;
441   encoder->height = 0;
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;
446 }
447
448 void
449 gst_h264_encoder_set_input_format(GstH264Encoder* encoder, uint32_t format)
450 {
451   GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
452   h264_prv->format = format;
453 }
454
455 void
456 gst_h264_encoder_set_es_flag(GstH264Encoder* encoder, gboolean es)
457 {
458   GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
459   h264_prv->es_flag = es;
460 }
461
462 gboolean
463 gst_h264_encoder_set_display(GstH264Encoder* encoder, GstVaapiDisplay *display)
464 {
465   GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
466   if (display == h264_prv->vaapi_display) {
467     return TRUE;
468   }
469
470   if (H264_ENC_INIT < h264_prv->encode_state) {
471     return FALSE;
472   }
473   if (h264_prv->vaapi_display) {
474     g_object_unref(h264_prv->vaapi_display);
475     h264_prv->vaapi_display = NULL;
476   }
477   h264_prv->vaapi_display = g_object_ref(display);
478   return TRUE;
479 }
480
481 GstVaapiDisplay *
482 gst_h264_encoder_get_display(GstH264Encoder* encoder)
483 {
484   GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
485   return (h264_prv->vaapi_display ? g_object_ref(h264_prv->vaapi_display) : NULL);
486 }
487
488
489 H264Status
490 gst_h264_encoder_initialize(GstH264Encoder* encoder)
491 {
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;
496
497   /* check state */
498   if (H264_ENC_INIT == h264_prv->encode_state) {
499     return H264_NO_ERROR;
500   }
501   H264_ASSERT(H264_ENC_NULL == h264_prv->encode_state);
502   if (H264_ENC_NULL != h264_prv->encode_state) {
503     return H264_STATE_ERR;
504   }
505
506 /* create va_dpy*/
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");
510   }
511
512   h264_prv->encode_state = H264_ENC_INIT;
513   return H264_NO_ERROR;
514
515   error:
516   gst_h264_encoder_uninitialize(encoder);
517   return ret;
518 }
519
520 H264Status
521 gst_h264_encoder_uninitialize(GstH264Encoder* encoder)
522 {
523   H264Status ret = H264_NO_ERROR;
524   GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
525
526   /* release buffers first */
527   if (H264_ENC_NULL == h264_prv->encode_state) {
528     return H264_NO_ERROR;
529   }
530
531   if (H264_ENC_INIT < h264_prv->encode_state) {
532     gst_h264_encoder_close(encoder);
533   }
534
535   H264_ASSERT(H264_ENC_INIT == h264_prv->encode_state);
536
537   /* close va_dpy */
538   if (h264_prv->vaapi_display) {
539     g_object_unref(h264_prv->vaapi_display);
540     h264_prv->vaapi_display = NULL;
541   }
542
543   h264_prv->encode_state = H264_ENC_NULL;
544   return H264_NO_ERROR;
545
546   //error:
547   return ret;
548 }
549
550
551 H264Status
552 #ifdef _MRST_
553 gst_h264_encoder_open(GstH264Encoder* encoder, GstVaapiSurfacePool *surfaces_pool)
554 #else
555 gst_h264_encoder_open(GstH264Encoder* encoder)
556 #endif
557 {
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;
565
566   /* check state */
567   if (H264_ENC_OPENED == h264_prv->encode_state) {
568     return H264_NO_ERROR;
569   }
570   H264_ASSERT(H264_ENC_INIT == h264_prv->encode_state);
571   if (H264_ENC_INIT != h264_prv->encode_state) {
572     return H264_STATE_ERR;
573   }
574
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);
579
580 #ifdef _MRST_
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,
588         NULL
589     );
590   if (surfaces_pool) {
591     gst_vaapi_context_set_surface_pool(h264_prv->vaapi_context, surfaces_pool);
592   }
593   g_object_set(h264_prv->vaapi_context, "profile",  gst_vaapi_profile(va_profile), NULL);
594
595 #else
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);
601 #endif
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) {
605     goto error;
606   }
607
608   h264_prv->encode_state = H264_ENC_OPENED;
609   return H264_NO_ERROR;
610
611   error:
612   // clear resources
613   gst_h264_encoder_close(encoder);
614   return ret;
615
616 }
617
618 H264Status
619 gst_h264_encoder_close(GstH264Encoder* encoder)
620 {
621   H264Status ret = H264_NO_ERROR;
622   GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
623
624   if (H264_ENC_INIT >= h264_prv->encode_state) {
625     return H264_NO_ERROR;
626   }
627
628   /* release buffers first */
629   if (H264_ENC_OPENED <= h264_prv->encode_state) {
630     h264_encoder_release_buffers(h264_prv);
631   }
632
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);
637     } else {
638       g_object_unref(h264_prv->ref_surface);
639     }
640     h264_prv->ref_surface = NULL;
641   }
642
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);
647     } else {
648       g_object_unref(h264_prv->recon_surface);
649     }
650     h264_prv->recon_surface = NULL;
651   }
652
653   /*remove vaapi_context*/
654   if (h264_prv->vaapi_context) {
655     g_object_unref(h264_prv->vaapi_context);
656     h264_prv->vaapi_context = NULL;
657   }
658
659   h264_prv->frame_count = 0;
660   h264_prv->encode_state = H264_ENC_INIT;
661
662   if (h264_prv->sps_data) {
663     gst_buffer_unref(h264_prv->sps_data);
664     h264_prv->sps_data = NULL;
665   }
666   if (h264_prv->pps_data) {
667     gst_buffer_unref(h264_prv->pps_data);
668     h264_prv->pps_data = NULL;
669   }
670   return ret;
671 }
672
673 static H264Status
674 h264_encoder_alloc_buffers(GstH264EncoderPrivate *h264_prv)
675 {
676   H264Status ret = H264_NO_ERROR;
677   VAStatus va_status = VA_STATUS_SUCCESS;
678   uint32_t i;
679
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;
685
686   GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
687   is_locked = TRUE;
688
689   /* 1. create sequence parameter set */
690   {
691       VAEncSequenceParameterBufferH264 seq_h264 = {0};
692
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;
697
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;
705
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");
710   }
711
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]);
719
720         H264_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, H264_ENC_RES_ERR, "alloc coded buffer failed.\n");
721       }
722   }
723
724   /* unlock here */
725   GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
726   is_locked = FALSE;
727
728   H264_ASSERT(h264_prv->available_code_buffers);
729
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]);
734   }
735   g_cond_signal(h264_prv->code_buffer_cond);
736   g_mutex_unlock(h264_prv->code_buffer_lock);
737
738   return H264_NO_ERROR;
739
740   error:
741   if (is_locked) {
742     GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
743     is_locked = FALSE;
744   }
745   return ret;
746
747 }
748
749 static H264Status
750 h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv)
751 {
752   VAStatus va_status = VA_STATUS_SUCCESS;
753   uint32_t available_buf_count = h264_prv->coded_buf_num;
754   uint32_t i;
755
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);
759
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);
765     } else {
766       g_queue_pop_head(h264_prv->available_code_buffers);
767       available_buf_count--;
768     }
769   }
770   g_mutex_unlock(h264_prv->code_buffer_lock);
771
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]);
775   }
776   va_status = vaDestroyBuffer(va_dpy, h264_prv->seq_parameter);
777   GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
778
779   if (h264_prv->coded_bufs) {
780     g_free(h264_prv->coded_bufs);
781     h264_prv->coded_bufs = NULL;
782   }
783
784   return H264_NO_ERROR;
785 }
786
787 H264Status
788 gst_h264_encoder_encode(GstH264Encoder* encoder, GstBuffer *raw_pic, GList **coded_pics)
789 {
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;
797
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;
803
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;
807   }
808
809   if (GST_VAAPI_IS_VIDEO_BUFFER(raw_pic)) {
810     buffer_surface = h264_get_video_surface(h264_prv, GST_VAAPI_VIDEO_BUFFER(raw_pic));
811   } else {
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");
815
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");
819   }
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");
822
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);
827
828   H264_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, H264_PICTURE_ERR, "vaBeginPicture error.\n");
829
830   /* set input buffers*/
831   is_key = ((h264_prv->frame_count % encoder->intra_period) == 0);
832
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);
838   }
839
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);
844   }
845   g_mutex_unlock(h264_prv->code_buffer_lock);
846
847   H264_CHECK_STATUS(H264_NO_ERROR == ret, H264_PICTURE_ERR, "h264_prepare_encoding failed.\n");
848
849   /* end picture */
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");
854
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) {
859     goto error;
860   }
861
862   h264_prv->frame_count++;
863
864
865   error:
866   if (new_surface) {
867     h264_push_free_surface(h264_prv, new_surface);
868   }
869   return ret;
870 }
871
872 static H264Status
873 h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
874                                GstBuffer *raw_pic,
875                                GstVaapiSurface *surface)
876 {
877   H264Status ret = H264_NO_ERROR;
878   VAStatus va_status = VA_STATUS_SUCCESS;
879   VAImage surface_image;
880   VADisplay va_dpy;
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;
890
891   H264_ASSERT(h264_prv->vaapi_display);
892   va_dpy = gst_vaapi_display_get_display(h264_prv->vaapi_display);
893   /*map image*/
894   image = gst_vaapi_surface_derive_image(surface);
895   gst_vaapi_image_map(image);
896
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);
900
901   /* copy buffer to surface */
902   H264_ASSERT(GST_BUFFER_SIZE(raw_pic) >= y_size + (y_size>>1));
903
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);
906
907   y_src = GST_BUFFER_DATA(raw_pic);
908   u_src = y_src + y_size;
909   v_src = u_src + u_size;
910
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);
916
917   if (plane_count > 2) {
918     v_dst = gst_vaapi_image_get_plane(image, 2);
919     pitchv = gst_vaapi_image_get_pitch(image, 2);
920   }
921
922   /* copy from avcenc.c*/
923   /* Y plane */
924   for (row = 0; row < image_height; row++) {
925       memcpy(y_dst, y_src, image_width);
926       y_dst += pitchy;
927       y_src += h264_prv->public->width;
928   }
929
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];
936           }
937
938           u_dst += pitchu;
939           u_src += (h264_prv->public->width>>1);
940           v_src += (h264_prv->public->width>>1);
941       }
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;
946         u_dst += pitchu;
947       }
948     } else {
949       H264_ASSERT(0);
950     }
951   } else {
952       /* FIXME: fix this later */
953       H264_ASSERT(0);
954   }
955
956   /*unmap image*/
957   g_object_unref(image);
958   error:
959   return ret;
960 }
961
962
963 static H264Status
964 h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gboolean is_key, VABufferID coded_buf)
965 {
966   H264Status ret = H264_NO_ERROR;
967   VAStatus va_status = VA_STATUS_SUCCESS;
968
969   VAEncPictureParameterBufferH264 pic_h264;
970   VAEncSliceParameterBuffer slice_h264;
971
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);
976
977   /* lock display */
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");
984   }
985
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");
990   }
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");
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 = h264_prv->public->width;
999   pic_h264.picture_height = h264_prv->public->height;
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   H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_PICTURE_ERR, "creating pic-param buffer failed.\n");
1010
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");
1013
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;
1024   }
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");
1030
1031
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;
1036
1037   error:
1038   GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
1039   return ret;
1040 }
1041
1042 static H264Status
1043 h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
1044                            VASurfaceID surface_id,
1045                            gboolean is_key,
1046                            GstClockTime timestamp,
1047                            GstClockTime duration,
1048                            VABufferID *coded_buf,
1049                            GList **coded_pics)
1050 {
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;
1058
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);
1063
1064   H264_ASSERT(coded_pics && *coded_pics == NULL);
1065
1066   /* lock display */
1067   GST_VAAPI_DISPLAY_LOCK(h264_prv->vaapi_display);
1068   is_locked = TRUE;
1069
1070   va_status = vaSyncSurface(va_dpy, surface_id);
1071   H264_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, H264_QUERY_STATUS_ERR, "vaSyncSurface failed.\n");
1072
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));
1077   }
1078
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");
1081
1082   /*unlock display*/
1083   if (is_locked) {
1084     GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
1085     is_locked = FALSE;
1086   }
1087
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);
1091       }
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;
1095       if (!is_key) {
1096         GST_BUFFER_FLAG_SET(ret_buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1097       }
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;
1102   }
1103
1104 #if SHARE_CODED_BUF
1105   if (!has_coded_data)
1106 #endif
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);
1115   }
1116
1117   return H264_NO_ERROR;
1118
1119   error:
1120   /*unlock display*/
1121   if (is_locked) {
1122     GST_VAAPI_DISPLAY_UNLOCK(h264_prv->vaapi_display);
1123     is_locked = FALSE;
1124   }
1125   return ret;
1126 }
1127
1128 static GstBuffer *
1129 h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
1130                                         uint8_t *frame,
1131                                         uint32_t frame_size,
1132                                         VABufferID *coded_buf)
1133 {
1134   GstBuffer *ret_buffer;
1135   uint32_t   nal_size;
1136   const uint8_t   *nal_start;
1137   uint8_t  *frame_end;
1138
1139 #if SHARE_CODED_BUF
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;
1145 #else
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);
1152
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;
1158     nal_start = frame;
1159     nal_size = 0;
1160     while((nal_start = h264_next_nal(nal_start, frame_end-nal_start, &nal_size)) != NULL) {
1161       H264_ASSERT(nal_size);
1162       if (!nal_size) {
1163         nal_start += nal_size;
1164         continue;
1165       }
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;
1169     }
1170   }
1171   h264_bitstream_align(&bitstream, 0);
1172
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);
1177 #endif
1178
1179   return ret_buffer;
1180
1181 }
1182
1183 static H264Status
1184 h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const uint8_t *buf, uint32_t size)
1185 {
1186   const uint8_t *end = buf + size;
1187   const uint8_t *nal_start = buf;
1188   uint32_t nal_size = 0;
1189   uint8_t nal_type;
1190   GstBuffer *sps = NULL, *pps = NULL;
1191
1192   while((!sps || !pps) && (nal_start = h264_next_nal(nal_start, end-nal_start, &nal_size)) != NULL) {
1193     if (!nal_size) {
1194       nal_start += nal_size;
1195       continue;
1196     }
1197
1198     nal_type = (*nal_start)&0x1F;
1199     switch (nal_type) {
1200       case NAL_SPS: {
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*/
1205         break;
1206       }
1207
1208       case NAL_PPS: {
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);
1213         break;
1214       }
1215
1216       default:
1217         break;
1218     }
1219     nal_start += nal_size;
1220
1221   }
1222   if (!sps || !pps) {
1223     return H264_DATA_NOT_READY;
1224   }
1225   return H264_NO_ERROR;
1226 }
1227
1228 static gboolean
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)
1231 {
1232   H264_ASSERT(profile_idc && profile_comp && level_idc);
1233   H264_ASSERT(sps_size >= 4);
1234   if (sps_size < 4) {
1235     return FALSE;
1236   }
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];
1241   return TRUE;
1242 }
1243
1244
1245 H264Status
1246 gst_h264_encoder_flush(GstH264Encoder* encoder, GList *coded_pics)
1247 {
1248   H264Status ret = H264_NO_ERROR;
1249   //GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
1250
1251   //error:
1252   return ret;
1253 }
1254
1255 /*test*/
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);
1261
1262 int main_test(int argc, const char* argv[])
1263 {
1264   H264Status ret = H264_NO_ERROR;
1265   GstH264Encoder *encoder = NULL;
1266
1267   GList *coded_pics = NULL;
1268   GstBuffer **raw_buffer = NULL;
1269   const uint32_t raw_buffer_num = 20;
1270
1271   GstBuffer *tmp_buffer;
1272
1273   uint32_t i = 0, k = 0;
1274
1275   gst_init (&argc, &argv);
1276
1277   g_type_init();
1278   if (!g_thread_supported ())
1279     g_thread_init (NULL);
1280
1281   encoder = gst_h264_encoder_new();
1282   H264_ASSERT(encoder && ret == H264_NO_ERROR);
1283
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);
1293   #ifdef _MRST_
1294   ret = gst_h264_encoder_open(encoder, NULL);
1295   #else
1296   ret = gst_h264_encoder_open(encoder);
1297   #endif
1298   H264_ASSERT(ret == H264_NO_ERROR);
1299
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;
1305
1306   /*set buffers*/
1307   int box_width=8;
1308   int row_shift=0;
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;
1315
1316     draw_picture(encoder->width, encoder->height, y_src, u_src, v_src, 0, box_width, row_shift);
1317     row_shift++;
1318     if (row_shift==(2*box_width)) row_shift= 0;
1319   }
1320
1321   FILE *fp = fopen("tmp.h264", "wb");
1322   H264_ASSERT(fp);
1323
1324   k = 0;
1325
1326   for (i = 0; i < 50; i++) {
1327     coded_pics = NULL;
1328     ret = gst_h264_encoder_encode(encoder, raw_buffer[k], &coded_pics);
1329     H264_ASSERT(H264_NO_ERROR == ret);
1330     ++k;
1331     if (k >= raw_buffer_num) k = 0;
1332
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);
1339     }
1340   }
1341   fclose(fp);
1342
1343   ret = gst_h264_encoder_close(encoder);
1344   H264_ASSERT(H264_NO_ERROR == ret);
1345
1346   for (i = 0; i < raw_buffer_num; i++) {
1347     gst_buffer_unref(raw_buffer[i]);
1348   }
1349   g_free(raw_buffer);
1350   gst_h264_encoder_unref(encoder);
1351
1352   return 0;
1353 }
1354
1355 char *h264_dump_bytes(const uint8_t *buf, uint32_t num)
1356 {
1357   static char tmp[1024];
1358   uint32_t i = 0;
1359   memset(tmp, 0, sizeof(tmp));
1360
1361   char *p = tmp;
1362   for (i = 0; i < num; i++) {
1363     snprintf(p, 1024-(p-tmp), "%02x", (uint8_t)buf[i]);
1364     p += strlen(p);
1365   }
1366   return tmp;
1367 }
1368
1369 H264Status
1370 gst_h264_encoder_get_avcC_codec_data(GstH264Encoder *encoder, GstBuffer **buffer)
1371 {
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;
1377
1378   H264_ASSERT(buffer);
1379   if (!h264_prv->sps_data || !h264_prv->pps_data) {
1380     return H264_DATA_NOT_READY;
1381   }
1382
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))
1386   {
1387     H264_ASSERT(0);
1388     return H264_DATA_ERR;
1389   }
1390
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);
1394
1395   /*codec_data*/
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*/
1403
1404   /*write sps*/
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));
1410
1411   /*write pps*/
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));
1416
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;
1424
1425   return H264_NO_ERROR;
1426 }
1427
1428 H264Status
1429 gst_h264_encoder_get_nal_codec_data(GstH264Encoder *encoder, GstBuffer **buffer)
1430 {
1431   GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
1432   GstBuffer *nal_sps_pps;
1433
1434   H264_ASSERT(buffer);
1435   if (!h264_prv->sps_data || !h264_prv->pps_data) {
1436     return H264_DATA_NOT_READY;
1437   }
1438
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);
1442
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));
1450
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;
1459 }
1460
1461 static void
1462 h264_bitstream_init(H264Bitstream *bitstream, uint32_t bit_capability)
1463 {
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);
1469   }
1470 }
1471
1472 static gboolean
1473 h264_bitstream_write_uint(H264Bitstream *bitstream, uint32_t value, uint32_t bit_size)
1474 {
1475   gboolean ret = TRUE;
1476   uint32_t byte_pos, bit_offset;
1477   uint8_t  *cur_byte;
1478   uint32_t fill_bits;
1479
1480   if(!bit_size) {
1481     return TRUE;
1482   }
1483
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);
1489
1490   while (bit_size) {
1491     fill_bits = ((8-bit_offset) < bit_size ? (8-bit_offset) : bit_size);
1492     bit_size -= fill_bits;
1493     bitstream->bit_size += fill_bits;
1494
1495     *cur_byte |= ((value>>bit_size) & h264_bit_mask[fill_bits])<<(8-bit_offset-fill_bits);
1496     ++cur_byte;
1497     bit_offset = 0;
1498   }
1499   H264_ASSERT(cur_byte <= bitstream->buffer + bitstream->max_bit_capability/8);
1500   return TRUE;
1501
1502   error:
1503   return FALSE;
1504 }
1505
1506 static gboolean h264_bitstream_align(H264Bitstream *bitstream, uint32_t value)
1507 {
1508   uint32_t bit_offset, bit_left;
1509
1510   bit_offset = (bitstream->bit_size&0x07);
1511   if (!bit_offset) {
1512     return TRUE;
1513   }
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);
1517 }
1518
1519
1520 static gboolean
1521 h264_bitstream_write_byte_array(H264Bitstream *bitstream, const uint8_t *buf, uint32_t byte_size)
1522 {
1523   gboolean ret = TRUE;
1524   if (!byte_size) {
1525     return 0;
1526   }
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);
1531   } else {
1532     H264_ASSERT(0);
1533     while(byte_size) {
1534       h264_bitstream_write_uint(bitstream, *buf, 8);
1535       --byte_size;
1536       ++buf;
1537     }
1538   }
1539   return TRUE;
1540
1541   error:
1542   return FALSE;
1543 }
1544
1545 static gboolean
1546 h264_bitstream_write_ue(H264Bitstream *bitstream, uint32_t value)
1547 {
1548   gboolean ret = TRUE;
1549   uint32_t size_in_bits = 0;
1550   uint32_t tmp_value = ++value;
1551   while (tmp_value) {
1552     ++size_in_bits;
1553     tmp_value >>= 1;
1554   }
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");
1557   return TRUE;
1558
1559   error:
1560   return FALSE;
1561 }
1562
1563 static gboolean
1564 h264_bitstream_write_se(H264Bitstream *bitstream, int32_t value)
1565 {
1566   gboolean ret = TRUE;
1567   uint32_t new_val;
1568
1569   if (value <= 0) {
1570     new_val = -(value<<1);
1571   } else {
1572     new_val = (value<<1) - 1;
1573   }
1574
1575   H264_CHECK_STATUS(h264_bitstream_write_ue(bitstream, new_val), FALSE, "h264_bitstream_write_se failed.\n");
1576   return TRUE;
1577
1578   error:
1579   return FALSE;
1580 }
1581
1582 static gboolean
1583 h264_bitstream_write_trailing_bits(H264Bitstream *bitstream)
1584 {
1585     h264_bitstream_write_uint(bitstream, 1, 1);
1586     h264_bitstream_align(bitstream, 0);
1587     return TRUE;
1588 }
1589
1590 static void
1591 h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag)
1592 {
1593   if (bitstream->buffer && free_flag) {
1594     free (bitstream->buffer);
1595   }
1596   bitstream->buffer = NULL;
1597   bitstream->bit_size = 0;
1598   bitstream->max_bit_capability = 0;
1599 }
1600
1601 static gboolean
1602 h264_bitstream_auto_grow(H264Bitstream *bitstream, uint32_t extra_bit_size)
1603 {
1604   uint32_t new_bit_size = extra_bit_size + bitstream->bit_size;
1605   uint32_t clear_pos;
1606
1607   H264_ASSERT(bitstream->bit_size <= bitstream->max_bit_capability);
1608   if (new_bit_size <= bitstream->max_bit_capability) {
1609     return TRUE;
1610   }
1611
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;
1619   return TRUE;
1620 }
1621
1622 static gboolean
1623 h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv)
1624 {
1625   uint32_t constraint_set0_flag, constraint_set1_flag, constraint_set2_flag, constraint_set3_flag;
1626   uint32_t seq_parameter_set_id = 0;
1627
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
1640
1641
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;
1646
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));
1651   }
1652
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 */
1661
1662   if (h264_prv->public->profile >= H264_PROFILE_HIGH) {
1663       /* FIXME: fix for high profile */
1664       H264_ASSERT(0);
1665   }
1666
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 */
1669
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 */
1672   else {
1673       H264_ASSERT(0);
1674   }
1675
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 */
1678
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 */
1682
1683   if (!frame_mbs_only_flag) { //ONLY mbs
1684       H264_ASSERT(0);
1685   }
1686
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 */
1689
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 */
1695   }
1696
1697   h264_bitstream_write_uint(bitstream, vui_present_flag, 1);                         /* vui_parameters_present_flag */
1698   h264_bitstream_write_trailing_bits(bitstream);                             /* rbsp_trailing_bits */
1699   return TRUE;
1700
1701   //error:
1702   //return FALSE;
1703
1704 }
1705
1706 static const uint8_t *
1707 h264_next_nal(const uint8_t *buffer, uint32_t len, uint32_t *nal_size)
1708 {
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;
1714
1715     H264_ASSERT(len >= 0 && buffer && nal_size);
1716     if (len < 3) {
1717         *nal_size = len;
1718         nal_start = (len ? buffer : NULL);
1719         return nal_start;
1720     }
1721
1722     /*locate head postion*/
1723     if (!buffer[0] && !buffer[1]) {
1724         if (buffer[2] == 1) { // 0x000001
1725             nal_start_len = 3;
1726         } else if (!buffer[2] && len >=4 && buffer[3] == 1) { //0x00000001
1727             nal_start_len = 4;
1728         }
1729     }
1730     nal_start = buffer + nal_start_len;
1731     cur = nal_start;
1732
1733     /*find next nal start position*/
1734     while (cur < end) {
1735         flag = ((flag<<8) | ((*cur++)&0xFF));
1736         if (flag == 0x00000001) {
1737             *nal_size = cur - 4 - nal_start;
1738             break;
1739         } else if ((flag&0x00FFFFFF) == 0x00000001) {
1740             *nal_size = cur - 3 - nal_start;
1741             break;
1742         }
1743     }
1744     if (cur >= end) {
1745       *nal_size = end - nal_start;
1746       if (nal_start >= end) {
1747         nal_start = NULL;
1748       }
1749     }
1750     return nal_start;
1751 }
1752
1753
1754 static gboolean
1755 h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv)
1756 {
1757   H264_ASSERT(0);
1758   return TRUE;
1759 }
1760
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)
1766 {
1767     int row;
1768     int field = 0;
1769     int Y_pitch = width;
1770     int U_pitch = width/2;
1771     int V_pitch = width/2;
1772
1773     /* copy Y plane */
1774     for (row=0;row<height;row++) {
1775         unsigned char *Y_row = Y_start + row * Y_pitch;
1776         int jj, xpos, ypos;
1777
1778         ypos = (row / box_width) & 0x1;
1779
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);
1784             continue;
1785         }
1786
1787         for (jj=0; jj<width; jj++) {
1788             xpos = ((row_shift + jj) / box_width) & 0x1;
1789
1790             if ((xpos == 0) && (ypos == 0))
1791                 Y_row[jj] = 0xeb;
1792             if ((xpos == 1) && (ypos == 1))
1793                 Y_row[jj] = 0xeb;
1794
1795             if ((xpos == 1) && (ypos == 0))
1796                 Y_row[jj] = 0x10;
1797             if ((xpos == 0) && (ypos == 1))
1798                 Y_row[jj] = 0x10;
1799         }
1800     }
1801
1802     /* copy UV data */
1803     for( row =0; row < height/2; row++) {
1804         unsigned short value = 0x80;
1805
1806         /* fill garbage data into the other field */
1807         if (((field == 1) && (row &1))
1808             || ((field == 2) && ((row &1)==0))) {
1809             value = 0xff;
1810         }
1811
1812         if (UV_interleave) {
1813             unsigned short *UV_row = (unsigned short *)(U_start + row * U_pitch);
1814
1815             memset(UV_row, value, width);
1816         } else {
1817             unsigned char *U_row = U_start + row * U_pitch;
1818             unsigned char *V_row = V_start + row * V_pitch;
1819
1820             memset (U_row,value,width/2);
1821             memset (V_row,value,width/2);
1822         }
1823     }
1824     return 0;
1825 }
1826
1827
1828