OSDN Git Service

test/encode/avcenc: use getopt_long_only() to parse optional command-line options
[android-x86/hardware-intel-common-libva.git] / test / encode / avcenc.c
1 /*
2  * Copyright (c) 2012 Intel Corporation. All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 /*
25  * Simple AVC encoder based on libVA.
26  *
27  * Usage:
28  * ./avcenc <width> <height> <input file> <output file> [qp]
29  */  
30
31 #include "sysdeps.h"
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <getopt.h>
36 #include <unistd.h>
37
38 #include <sys/time.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <fcntl.h>
42 #include <assert.h>
43 #include <time.h>
44
45 #include <pthread.h>
46
47 #include <va/va.h>
48 #include <va/va_enc_h264.h>
49 #include "va_display.h"
50
51 #define NAL_REF_IDC_NONE        0
52 #define NAL_REF_IDC_LOW         1
53 #define NAL_REF_IDC_MEDIUM      2
54 #define NAL_REF_IDC_HIGH        3
55
56 #define NAL_NON_IDR             1
57 #define NAL_IDR                 5
58 #define NAL_SPS                 7
59 #define NAL_PPS                 8
60 #define NAL_SEI                 6
61
62 #define SLICE_TYPE_P            0
63 #define SLICE_TYPE_B            1
64 #define SLICE_TYPE_I            2
65
66 #define FRAME_IDR 7
67
68 #define ENTROPY_MODE_CAVLC      0
69 #define ENTROPY_MODE_CABAC      1
70
71 #define PROFILE_IDC_BASELINE    66
72 #define PROFILE_IDC_MAIN        77
73 #define PROFILE_IDC_HIGH        100
74
75 #define CHECK_VASTATUS(va_status,func)                                  \
76     if (va_status != VA_STATUS_SUCCESS) {                               \
77         fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
78         exit(1);                                                        \
79     }
80
81 static VADisplay va_dpy;
82
83 static int picture_width, picture_width_in_mbs;
84 static int picture_height, picture_height_in_mbs;
85 static int frame_size;
86 static unsigned char *newImageBuffer = 0;
87
88 static int qp_value = 26;
89
90 static int intra_period = 30;
91 static int frame_bit_rate = -1;
92 static int frame_rate = 30;
93 static int ip_period = 1;
94
95 #define MAX_SLICES      32
96
97
98 static  unsigned int MaxFrameNum = (1<<12);
99 static  unsigned int Log2MaxFrameNum = 12;
100 static  unsigned int Log2MaxPicOrderCntLsb = 8;
101
102 static const struct option longopts[] = {
103     {"qp", required_argument, 0, 1},
104     {"fb", required_argument, 0, 2},
105     {"mode", required_argument, 0, 3},
106     { NULL, 0, NULL, 0}
107 };
108
109 static int
110 build_packed_pic_buffer(unsigned char **header_buffer);
111
112 static int
113 build_packed_seq_buffer(unsigned char **header_buffer);
114
115 static int 
116 build_packed_sei_pic_timing(unsigned int cpb_removal_length,
117                                 unsigned int dpb_output_length,
118                                 unsigned char **sei_buffer);
119
120 static int
121 build_packed_idr_sei_buffer_timing(unsigned int init_cpb_removal_delay_length,
122                                 unsigned int cpb_removal_length,
123                                 unsigned int dpb_output_length,
124                                 unsigned char **sei_buffer);
125
126 struct upload_thread_param
127 {
128     FILE *yuv_fp;
129     VASurfaceID surface_id;
130 };
131
132 static void 
133 upload_yuv_to_surface(FILE *yuv_fp, VASurfaceID surface_id);
134
135 static struct {
136     VAProfile profile;
137     int constraint_set_flag;
138     VAEncSequenceParameterBufferH264 seq_param;
139     VAEncPictureParameterBufferH264 pic_param;
140     VAEncSliceParameterBufferH264 slice_param[MAX_SLICES];
141     VAContextID context_id;
142     VAConfigID config_id;
143     VABufferID seq_param_buf_id;                /* Sequence level parameter */
144     VABufferID pic_param_buf_id;                /* Picture level parameter */
145     VABufferID slice_param_buf_id[MAX_SLICES];  /* Slice level parameter, multil slices */
146     VABufferID codedbuf_buf_id;                 /* Output buffer, compressed data */
147     VABufferID packed_seq_header_param_buf_id;
148     VABufferID packed_seq_buf_id;
149     VABufferID packed_pic_header_param_buf_id;
150     VABufferID packed_pic_buf_id;
151     VABufferID packed_sei_header_param_buf_id;   /* the SEI buffer */
152     VABufferID packed_sei_buf_id;
153     VABufferID misc_parameter_hrd_buf_id;
154
155     int num_slices;
156     int codedbuf_i_size;
157     int codedbuf_pb_size;
158     int current_input_surface;
159     int rate_control_method;
160     struct upload_thread_param upload_thread_param;
161     pthread_t upload_thread_id;
162     int upload_thread_value;
163     int i_initial_cpb_removal_delay;
164     int i_initial_cpb_removal_delay_offset;
165     int i_initial_cpb_removal_delay_length;
166     int i_cpb_removal_delay;
167     int i_cpb_removal_delay_length;
168     int i_dpb_output_delay_length;
169     int time_offset_length;
170
171     unsigned long long idr_frame_num;
172     unsigned long long prev_idr_cpb_removal;
173     unsigned long long current_idr_cpb_removal;
174     unsigned long long current_cpb_removal;
175     /* This is relative to the current_cpb_removal */
176     unsigned int current_dpb_removal_delta;
177 } avcenc_context;
178
179 static  VAPictureH264 ReferenceFrames[16], RefPicList0[32], RefPicList1[32];
180
181 static void create_encode_pipe()
182 {
183     VAEntrypoint entrypoints[5];
184     int num_entrypoints,slice_entrypoint;
185     VAConfigAttrib attrib[2];
186     int major_ver, minor_ver;
187     VAStatus va_status;
188
189     va_dpy = va_open_display();
190     va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
191     CHECK_VASTATUS(va_status, "vaInitialize");
192
193     vaQueryConfigEntrypoints(va_dpy, avcenc_context.profile, entrypoints, 
194                              &num_entrypoints);
195
196     for (slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypoint++) {
197         if (entrypoints[slice_entrypoint] == VAEntrypointEncSlice)
198             break;
199     }
200
201     if (slice_entrypoint == num_entrypoints) {
202         /* not find Slice entry point */
203         assert(0);
204     }
205
206     /* find out the format for the render target, and rate control mode */
207     attrib[0].type = VAConfigAttribRTFormat;
208     attrib[1].type = VAConfigAttribRateControl;
209     vaGetConfigAttributes(va_dpy, avcenc_context.profile, VAEntrypointEncSlice,
210                           &attrib[0], 2);
211
212     if ((attrib[0].value & VA_RT_FORMAT_YUV420) == 0) {
213         /* not find desired YUV420 RT format */
214         assert(0);
215     }
216
217     if ((attrib[1].value & avcenc_context.rate_control_method) == 0) {
218         /* Can't find matched RC mode */
219         printf("Can't find the desired RC mode, exit\n");
220         assert(0);
221     }
222
223     attrib[0].value = VA_RT_FORMAT_YUV420; /* set to desired RT format */
224     attrib[1].value = avcenc_context.rate_control_method; /* set to desired RC mode */
225
226     va_status = vaCreateConfig(va_dpy, avcenc_context.profile, VAEntrypointEncSlice,
227                                &attrib[0], 2,&avcenc_context.config_id);
228     CHECK_VASTATUS(va_status, "vaCreateConfig");
229
230     /* Create a context for this decode pipe */
231     va_status = vaCreateContext(va_dpy, avcenc_context.config_id,
232                                 picture_width, picture_height,
233                                 VA_PROGRESSIVE, 
234                                 0, 0,
235                                 &avcenc_context.context_id);
236     CHECK_VASTATUS(va_status, "vaCreateContext");
237 }
238
239 static void destory_encode_pipe()
240 {
241     vaDestroyContext(va_dpy,avcenc_context.context_id);
242     vaDestroyConfig(va_dpy,avcenc_context.config_id);
243     vaTerminate(va_dpy);
244     va_close_display(va_dpy);
245 }
246
247 /***************************************************
248  *
249  *  The encode pipe resource define 
250  *
251  ***************************************************/
252 #define SID_INPUT_PICTURE_0                     0
253 #define SID_INPUT_PICTURE_1                     1
254 #define SID_REFERENCE_PICTURE_L0                2
255 #define SID_REFERENCE_PICTURE_L1                3
256 #define SID_RECON_PICTURE                       4
257 #define SID_NUMBER                              SID_RECON_PICTURE + 1
258
259 #define SURFACE_NUM 16 /* 16 surfaces for reference */
260
261 static  VASurfaceID surface_ids[SID_NUMBER];
262 static  VASurfaceID ref_surface[SURFACE_NUM];
263 static  int use_slot[SURFACE_NUM];
264
265 static  unsigned long long current_frame_display = 0;
266 static  unsigned long long current_IDR_display = 0;
267
268 static  VAPictureH264 CurrentCurrPic;
269
270 #define current_slot (current_frame_display % SURFACE_NUM)
271
272 static int frame_number;
273 static unsigned long long enc_frame_number;
274 static int current_frame_type;
275 static int current_frame_num;
276 static unsigned int current_poc;
277
278 static  unsigned int num_ref_frames = 2;
279 static  unsigned int numShortTerm = 0;
280 /***************************************************/
281
282 static int get_free_slot()
283 {
284     int i, index = -1;
285
286     for (i = 0; i < SURFACE_NUM; i++) {
287         if (use_slot[i] == 0) {
288             index = i;
289             break;
290         }
291     }
292     if (index < 0) {
293         printf("WARNING: No free slot to store the reconstructed frame \n");
294         index = SURFACE_NUM - 1;
295     }
296     return index;
297 }
298
299 static void *
300 upload_thread_function(void *data)
301 {
302     struct upload_thread_param *param = data;
303
304     upload_yuv_to_surface(param->yuv_fp, param->surface_id);
305
306     return NULL;
307 }
308
309 static void alloc_encode_resource(FILE *yuv_fp)
310 {
311     VAStatus va_status;
312
313     // Create surface
314     va_status = vaCreateSurfaces(
315         va_dpy,
316         VA_RT_FORMAT_YUV420, picture_width, picture_height,
317         surface_ids, SID_NUMBER,
318         NULL, 0
319     );
320
321     CHECK_VASTATUS(va_status, "vaCreateSurfaces");
322
323     // Create surface
324     va_status = vaCreateSurfaces(
325         va_dpy,
326         VA_RT_FORMAT_YUV420, picture_width, picture_height,
327         ref_surface, SURFACE_NUM,
328         NULL, 0
329     );
330
331     CHECK_VASTATUS(va_status, "vaCreateSurfaces");
332
333
334     newImageBuffer = (unsigned char *)malloc(frame_size);
335
336     /* firstly upload YUV data to SID_INPUT_PICTURE_1 */
337     avcenc_context.upload_thread_param.yuv_fp = yuv_fp;
338     avcenc_context.upload_thread_param.surface_id = surface_ids[SID_INPUT_PICTURE_1];
339
340     avcenc_context.upload_thread_value = pthread_create(&avcenc_context.upload_thread_id,
341                                                         NULL,
342                                                         upload_thread_function, 
343                                                         (void*)&avcenc_context.upload_thread_param);
344 }
345
346 static void release_encode_resource()
347 {
348     pthread_join(avcenc_context.upload_thread_id, NULL);
349     free(newImageBuffer);
350
351     // Release all the surfaces resource
352     vaDestroySurfaces(va_dpy, surface_ids, SID_NUMBER);
353     // Release all the reference surfaces
354     vaDestroySurfaces(va_dpy, ref_surface, SURFACE_NUM);
355 }
356
357 static void avcenc_update_sei_param(int is_idr)
358 {
359         VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
360         unsigned int length_in_bits;
361         unsigned char *packed_sei_buffer = NULL;
362         VAStatus va_status;
363
364         if (is_idr)
365             length_in_bits = build_packed_idr_sei_buffer_timing(
366                                 avcenc_context.i_initial_cpb_removal_delay_length,
367                                 avcenc_context.i_cpb_removal_delay_length,
368                                 avcenc_context.i_dpb_output_delay_length,
369                                 &packed_sei_buffer);
370        else
371             length_in_bits = build_packed_sei_pic_timing(
372                                 avcenc_context.i_cpb_removal_delay_length,
373                                 avcenc_context.i_dpb_output_delay_length,
374                                 &packed_sei_buffer);
375
376         packed_header_param_buffer.type = VAEncPackedHeaderH264_SEI;
377         packed_header_param_buffer.bit_length = length_in_bits;
378         packed_header_param_buffer.has_emulation_bytes = 0;
379
380         va_status = vaCreateBuffer(va_dpy,
381                                 avcenc_context.context_id,
382                                 VAEncPackedHeaderParameterBufferType,
383                                 sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
384                                 &avcenc_context.packed_sei_header_param_buf_id);
385         CHECK_VASTATUS(va_status,"vaCreateBuffer");
386
387         va_status = vaCreateBuffer(va_dpy,
388                                 avcenc_context.context_id,
389                                 VAEncPackedHeaderDataBufferType,
390                                 (length_in_bits + 7) / 8, 1, packed_sei_buffer,
391                                 &avcenc_context.packed_sei_buf_id);
392         CHECK_VASTATUS(va_status,"vaCreateBuffer");
393         free(packed_sei_buffer);
394         return;
395 }
396
397 #define partition(ref, field, key, ascending)   \
398     while (i <= j) {                            \
399         if (ascending) {                        \
400             while (ref[i].field < key)          \
401                 i++;                            \
402             while (ref[j].field > key)          \
403                 j--;                            \
404         } else {                                \
405             while (ref[i].field > key)          \
406                 i++;                            \
407             while (ref[j].field < key)          \
408                 j--;                            \
409         }                                       \
410         if (i <= j) {                           \
411             tmp = ref[i];                       \
412             ref[i] = ref[j];                    \
413             ref[j] = tmp;                       \
414             i++;                                \
415             j--;                                \
416         }                                       \
417     }                                           \
418
419 static void sort_one(VAPictureH264 ref[], int left, int right,
420                      int ascending, int frame_idx)
421 {
422     int i = left, j = right;
423     unsigned int key;
424     VAPictureH264 tmp;
425
426     if (frame_idx) {
427         key = ref[(left + right) / 2].frame_idx;
428         partition(ref, frame_idx, key, ascending);
429     } else {
430         key = ref[(left + right) / 2].TopFieldOrderCnt;
431         partition(ref, TopFieldOrderCnt, (signed int)key, ascending);
432     }
433
434     /* recursion */
435     if (left < j)
436         sort_one(ref, left, j, ascending, frame_idx);
437
438     if (i < right)
439         sort_one(ref, i, right, ascending, frame_idx);
440 }
441
442 static void sort_two(VAPictureH264 ref[], int left, int right, unsigned int key, unsigned int frame_idx,
443                      int partition_ascending, int list0_ascending, int list1_ascending)
444 {
445     int i = left, j = right;
446     VAPictureH264 tmp;
447
448     if (frame_idx) {
449         partition(ref, frame_idx, key, partition_ascending);
450     } else {
451         partition(ref, TopFieldOrderCnt, (signed int)key, partition_ascending);
452     }
453
454     sort_one(ref, left, i-1, list0_ascending, frame_idx);
455     sort_one(ref, j+1, right, list1_ascending, frame_idx);
456 }
457
458 static int update_RefPicList()
459 {
460
461     if (current_frame_type == SLICE_TYPE_P) {
462         memcpy(RefPicList0, ReferenceFrames, numShortTerm * sizeof(VAPictureH264));
463         sort_one(RefPicList0, 0, numShortTerm-1, 0, 1);
464     }
465
466     if (current_frame_type == SLICE_TYPE_B) {
467         memcpy(RefPicList0, ReferenceFrames, numShortTerm * sizeof(VAPictureH264));
468         sort_two(RefPicList0, 0, numShortTerm-1, current_poc, 0,
469                  1, 0, 1);
470
471         memcpy(RefPicList1, ReferenceFrames, numShortTerm * sizeof(VAPictureH264));
472         sort_two(RefPicList1, 0, numShortTerm-1, current_poc, 0,
473                  0, 1, 0);
474     }
475
476     return 0;
477 }
478
479 static void avcenc_update_picture_parameter(int slice_type, int is_idr)
480 {
481     VAEncPictureParameterBufferH264 *pic_param;
482     VAStatus va_status;
483     int recon_index;
484
485     recon_index = get_free_slot();
486     // Picture level
487     pic_param = &avcenc_context.pic_param;
488
489     pic_param->CurrPic.picture_id = ref_surface[recon_index];
490     pic_param->CurrPic.frame_idx = current_frame_num;
491     pic_param->CurrPic.flags = 0;
492
493     pic_param->CurrPic.TopFieldOrderCnt = current_poc;
494     pic_param->CurrPic.BottomFieldOrderCnt = pic_param->CurrPic.TopFieldOrderCnt;
495
496     assert(avcenc_context.codedbuf_buf_id != VA_INVALID_ID);
497     pic_param->coded_buf = avcenc_context.codedbuf_buf_id;
498     pic_param->frame_num = current_frame_num;
499     pic_param->pic_fields.bits.idr_pic_flag = !!is_idr;
500     pic_param->pic_fields.bits.reference_pic_flag = (slice_type != SLICE_TYPE_B);
501     CurrentCurrPic = pic_param->CurrPic;
502
503     if (slice_type == SLICE_TYPE_P || slice_type == SLICE_TYPE_B)
504         memset(pic_param->ReferenceFrames, 0xff, 16 * sizeof(VAPictureH264)); /* invalid all */
505
506     if ((slice_type == SLICE_TYPE_P) || (slice_type == SLICE_TYPE_B)) {
507         pic_param->ReferenceFrames[0] = RefPicList0[0];
508     }
509     if (slice_type == SLICE_TYPE_B) {
510         pic_param->ReferenceFrames[1] = RefPicList1[0];
511     }
512
513     va_status = vaCreateBuffer(va_dpy,
514                                avcenc_context.context_id,
515                                VAEncPictureParameterBufferType,
516                                sizeof(*pic_param), 1, pic_param,
517                                &avcenc_context.pic_param_buf_id);
518     CHECK_VASTATUS(va_status,"vaCreateBuffer");
519
520 }
521
522 #ifndef VA_FOURCC_I420
523 #define VA_FOURCC_I420          0x30323449
524 #endif
525
526 static void upload_yuv_to_surface(FILE *yuv_fp, VASurfaceID surface_id)
527 {
528     VAImage surface_image;
529     VAStatus va_status;
530     void *surface_p = NULL;
531     unsigned char *y_src, *u_src, *v_src;
532     unsigned char *y_dst, *u_dst, *v_dst;
533     int y_size = picture_width * picture_height;
534     int u_size = (picture_width >> 1) * (picture_height >> 1);
535     int row, col;
536     size_t n_items;
537
538     do {
539         n_items = fread(newImageBuffer, frame_size, 1, yuv_fp);
540     } while (n_items != 1);
541
542     va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
543     CHECK_VASTATUS(va_status,"vaDeriveImage");
544
545     vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
546     assert(VA_STATUS_SUCCESS == va_status);
547         
548     y_src = newImageBuffer;
549     u_src = newImageBuffer + y_size; /* UV offset for NV12 */
550     v_src = newImageBuffer + y_size + u_size;
551
552     y_dst = surface_p + surface_image.offsets[0];
553     u_dst = surface_p + surface_image.offsets[1]; /* UV offset for NV12 */
554     v_dst = surface_p + surface_image.offsets[2];
555
556     /* Y plane */
557     for (row = 0; row < surface_image.height; row++) {
558         memcpy(y_dst, y_src, surface_image.width);
559         y_dst += surface_image.pitches[0];
560         y_src += picture_width;
561     }
562
563     if (surface_image.format.fourcc == VA_FOURCC_NV12) { /* UV plane */
564         for (row = 0; row < surface_image.height / 2; row++) {
565             for (col = 0; col < surface_image.width / 2; col++) {
566                 u_dst[col * 2] = u_src[col];
567                 u_dst[col * 2 + 1] = v_src[col];
568             }
569
570             u_dst += surface_image.pitches[1];
571             u_src += (picture_width / 2);
572             v_src += (picture_width / 2);
573         }
574     } else if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
575                surface_image.format.fourcc == VA_FOURCC_I420) {
576         const int U = surface_image.format.fourcc == VA_FOURCC_I420 ? 1 : 2;
577         const int V = surface_image.format.fourcc == VA_FOURCC_I420 ? 2 : 1;
578
579         u_dst = surface_p + surface_image.offsets[U];
580         v_dst = surface_p + surface_image.offsets[V];
581
582         for (row = 0; row < surface_image.height / 2; row++) {
583             memcpy(u_dst, u_src, surface_image.width / 2);
584             memcpy(v_dst, v_src, surface_image.width / 2);
585             u_dst += surface_image.pitches[U];
586             v_dst += surface_image.pitches[V];
587             u_src += (picture_width / 2);
588             v_src += (picture_width / 2);
589         }
590     }
591
592     vaUnmapBuffer(va_dpy, surface_image.buf);
593     vaDestroyImage(va_dpy, surface_image.image_id);
594 }
595
596 static void avcenc_update_slice_parameter(int slice_type)
597 {
598     VAEncSliceParameterBufferH264 *slice_param;
599     VAStatus va_status;
600     int i;
601
602     // Slice level
603     i = 0;
604     slice_param = &avcenc_context.slice_param[i];
605     slice_param->macroblock_address = 0;
606     slice_param->num_macroblocks = picture_height_in_mbs * picture_width_in_mbs; 
607     slice_param->pic_parameter_set_id = 0;
608     slice_param->slice_type = slice_type;
609     slice_param->direct_spatial_mv_pred_flag = 0;
610     slice_param->num_ref_idx_l0_active_minus1 = 0;      /* FIXME: ??? */
611     slice_param->num_ref_idx_l1_active_minus1 = 0;
612     slice_param->cabac_init_idc = 0;
613     slice_param->slice_qp_delta = 0;
614     slice_param->disable_deblocking_filter_idc = 0;
615     slice_param->slice_alpha_c0_offset_div2 = 2;
616     slice_param->slice_beta_offset_div2 = 2;
617     slice_param->idr_pic_id = 0;
618
619     /* FIXME: fill other fields */
620     if ((slice_type == SLICE_TYPE_P) || (slice_type == SLICE_TYPE_B)) {
621         memset(slice_param->RefPicList0, 0xFF, 32 * sizeof(VAPictureH264));
622         slice_param->RefPicList0[0] = RefPicList0[0];
623     }
624
625     if ((slice_type == SLICE_TYPE_B)) {
626         memset(slice_param->RefPicList1, 0xFF, 32 * sizeof(VAPictureH264));
627         slice_param->RefPicList1[0] = RefPicList1[0];
628     }
629
630     va_status = vaCreateBuffer(va_dpy,
631                                avcenc_context.context_id,
632                                VAEncSliceParameterBufferType,
633                                sizeof(*slice_param), 1, slice_param,
634                                &avcenc_context.slice_param_buf_id[i]);
635     CHECK_VASTATUS(va_status,"vaCreateBuffer");;
636     i++;
637
638 #if 0
639     slice_param = &avcenc_context.slice_param[i];
640     slice_param->macroblock_address = picture_height_in_mbs * picture_width_in_mbs / 2;
641     slice_param->num_macroblocks = picture_height_in_mbs * picture_width_in_mbs / 2;
642     slice_param->pic_parameter_set_id = 0;
643     slice_param->slice_type = slice_type;
644     slice_param->direct_spatial_mv_pred_flag = 0;
645     slice_param->num_ref_idx_l0_active_minus1 = 0;      /* FIXME: ??? */
646     slice_param->num_ref_idx_l1_active_minus1 = 0;
647     slice_param->cabac_init_idc = 0;
648     slice_param->slice_qp_delta = 0;
649     slice_param->disable_deblocking_filter_idc = 0;
650     slice_param->slice_alpha_c0_offset_div2 = 2;
651     slice_param->slice_beta_offset_div2 = 2;
652     slice_param->idr_pic_id = 0;
653
654     /* FIXME: fill other fields */
655
656     va_status = vaCreateBuffer(va_dpy,
657                                avcenc_context.context_id,
658                                VAEncSliceParameterBufferType,
659                                sizeof(*slice_param), 1, slice_param,
660                                &avcenc_context.slice_param_buf_id[i]);
661     CHECK_VASTATUS(va_status,"vaCreateBuffer");;
662     i++;
663 #endif
664
665     avcenc_context.num_slices = i;
666 }
667
668 static int update_ReferenceFrames(void)
669 {
670     int i;
671     /* B-frame is not used for reference */
672     if (current_frame_type == SLICE_TYPE_B)
673         return 0;
674
675     CurrentCurrPic.flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
676     numShortTerm++;
677     if (numShortTerm > num_ref_frames)
678         numShortTerm = num_ref_frames;
679     for (i=numShortTerm-1; i>0; i--)
680         ReferenceFrames[i] = ReferenceFrames[i-1];
681     ReferenceFrames[0] = CurrentCurrPic;
682
683     if (current_frame_type != SLICE_TYPE_B)
684         current_frame_num++;
685     if (current_frame_num > MaxFrameNum)
686         current_frame_num = 0;
687
688     /* Update the use_slot. Only when the surface is used in reference
689      * frame list, the use_slot[index] is set
690      */
691     for (i = 0; i < SURFACE_NUM; i++) {
692         int j;
693         bool found;
694
695         found = false;
696         for (j = 0; j < numShortTerm; j++) {
697             if (ref_surface[i] == ReferenceFrames[j].picture_id) {
698                 found = true;
699                 break;
700             }
701         }
702         if (found)
703             use_slot[i] = 1;
704         else
705             use_slot[i] = 0;
706     }
707
708     return 0;
709 }
710
711 static int begin_picture(FILE *yuv_fp, int frame_num, int display_num, int slice_type, int is_idr)
712 {
713     VAStatus va_status;
714
715     if (avcenc_context.upload_thread_value != 0) {
716         fprintf(stderr, "FATAL error!!!\n");
717         exit(1);
718     }
719
720     pthread_join(avcenc_context.upload_thread_id, NULL);
721
722     avcenc_context.upload_thread_value = -1;
723
724     if (avcenc_context.current_input_surface == SID_INPUT_PICTURE_0)
725         avcenc_context.current_input_surface = SID_INPUT_PICTURE_1;
726     else
727         avcenc_context.current_input_surface = SID_INPUT_PICTURE_0;
728
729     if (is_idr) {
730         VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
731         unsigned int length_in_bits;
732         unsigned char *packed_seq_buffer = NULL, *packed_pic_buffer = NULL;
733
734         assert(slice_type == SLICE_TYPE_I);
735         length_in_bits = build_packed_seq_buffer(&packed_seq_buffer);
736         packed_header_param_buffer.type = VAEncPackedHeaderSequence;
737         packed_header_param_buffer.bit_length = length_in_bits;
738         packed_header_param_buffer.has_emulation_bytes = 0;
739         va_status = vaCreateBuffer(va_dpy,
740                                    avcenc_context.context_id,
741                                    VAEncPackedHeaderParameterBufferType,
742                                    sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
743                                    &avcenc_context.packed_seq_header_param_buf_id);
744         CHECK_VASTATUS(va_status,"vaCreateBuffer");
745
746         va_status = vaCreateBuffer(va_dpy,
747                                    avcenc_context.context_id,
748                                    VAEncPackedHeaderDataBufferType,
749                                    (length_in_bits + 7) / 8, 1, packed_seq_buffer,
750                                    &avcenc_context.packed_seq_buf_id);
751         CHECK_VASTATUS(va_status,"vaCreateBuffer");
752
753         length_in_bits = build_packed_pic_buffer(&packed_pic_buffer);
754         packed_header_param_buffer.type = VAEncPackedHeaderPicture;
755         packed_header_param_buffer.bit_length = length_in_bits;
756         packed_header_param_buffer.has_emulation_bytes = 0;
757
758         va_status = vaCreateBuffer(va_dpy,
759                                    avcenc_context.context_id,
760                                    VAEncPackedHeaderParameterBufferType,
761                                    sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
762                                    &avcenc_context.packed_pic_header_param_buf_id);
763         CHECK_VASTATUS(va_status,"vaCreateBuffer");
764
765         va_status = vaCreateBuffer(va_dpy,
766                                    avcenc_context.context_id,
767                                    VAEncPackedHeaderDataBufferType,
768                                    (length_in_bits + 7) / 8, 1, packed_pic_buffer,
769                                    &avcenc_context.packed_pic_buf_id);
770         CHECK_VASTATUS(va_status,"vaCreateBuffer");
771
772         free(packed_seq_buffer);
773         free(packed_pic_buffer);
774     }
775
776     /* sequence parameter set */
777     VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
778     va_status = vaCreateBuffer(va_dpy,
779                                avcenc_context.context_id,
780                                VAEncSequenceParameterBufferType,
781                                sizeof(*seq_param), 1, seq_param,
782                                &avcenc_context.seq_param_buf_id);
783     CHECK_VASTATUS(va_status,"vaCreateBuffer");
784
785
786     /* hrd parameter */
787     VAEncMiscParameterBuffer *misc_param;
788     VAEncMiscParameterHRD *misc_hrd_param;
789     vaCreateBuffer(va_dpy,
790                    avcenc_context.context_id,
791                    VAEncMiscParameterBufferType,
792                    sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterRateControl),
793                    1,
794                    NULL, 
795                    &avcenc_context.misc_parameter_hrd_buf_id);
796     CHECK_VASTATUS(va_status, "vaCreateBuffer");
797
798     vaMapBuffer(va_dpy,
799                 avcenc_context.misc_parameter_hrd_buf_id,
800                 (void **)&misc_param);
801     misc_param->type = VAEncMiscParameterTypeHRD;
802     misc_hrd_param = (VAEncMiscParameterHRD *)misc_param->data;
803
804     if (frame_bit_rate > 0) {
805         misc_hrd_param->initial_buffer_fullness = frame_bit_rate * 1000 * 4;
806         misc_hrd_param->buffer_size = frame_bit_rate * 1000 * 8;
807     } else {
808         misc_hrd_param->initial_buffer_fullness = 0;
809         misc_hrd_param->buffer_size = 0;
810     }
811
812     vaUnmapBuffer(va_dpy, avcenc_context.misc_parameter_hrd_buf_id);
813
814     return 0;
815 }
816
817 int avcenc_render_picture()
818 {
819     VAStatus va_status;
820     VABufferID va_buffers[10];
821     unsigned int num_va_buffers = 0;
822     int i;
823
824     va_buffers[num_va_buffers++] = avcenc_context.seq_param_buf_id;
825     va_buffers[num_va_buffers++] = avcenc_context.pic_param_buf_id;
826
827     if (avcenc_context.packed_seq_header_param_buf_id != VA_INVALID_ID)
828         va_buffers[num_va_buffers++] = avcenc_context.packed_seq_header_param_buf_id;
829
830     if (avcenc_context.packed_seq_buf_id != VA_INVALID_ID)
831         va_buffers[num_va_buffers++] = avcenc_context.packed_seq_buf_id;
832
833     if (avcenc_context.packed_pic_header_param_buf_id != VA_INVALID_ID)
834         va_buffers[num_va_buffers++] = avcenc_context.packed_pic_header_param_buf_id;
835
836     if (avcenc_context.packed_pic_buf_id != VA_INVALID_ID)
837         va_buffers[num_va_buffers++] = avcenc_context.packed_pic_buf_id;
838
839     if (avcenc_context.packed_sei_header_param_buf_id != VA_INVALID_ID)
840         va_buffers[num_va_buffers++] = avcenc_context.packed_sei_header_param_buf_id;
841
842     if (avcenc_context.packed_sei_buf_id != VA_INVALID_ID)
843         va_buffers[num_va_buffers++] = avcenc_context.packed_sei_buf_id;
844
845     if (avcenc_context.misc_parameter_hrd_buf_id != VA_INVALID_ID)
846         va_buffers[num_va_buffers++] =  avcenc_context.misc_parameter_hrd_buf_id;
847
848     va_status = vaBeginPicture(va_dpy,
849                                avcenc_context.context_id,
850                                surface_ids[avcenc_context.current_input_surface]);
851     CHECK_VASTATUS(va_status,"vaBeginPicture");
852     
853     va_status = vaRenderPicture(va_dpy,
854                                 avcenc_context.context_id,
855                                 va_buffers,
856                                 num_va_buffers);
857     CHECK_VASTATUS(va_status,"vaRenderPicture");
858     
859     for(i = 0; i < avcenc_context.num_slices; i++) {
860         va_status = vaRenderPicture(va_dpy,
861                                 avcenc_context.context_id,
862                                 &avcenc_context.slice_param_buf_id[i],
863                                 1);
864         CHECK_VASTATUS(va_status,"vaRenderPicture");
865     }
866
867     va_status = vaEndPicture(va_dpy, avcenc_context.context_id);
868     CHECK_VASTATUS(va_status,"vaEndPicture");
869
870     return 0;
871 }
872
873 static int avcenc_destroy_buffers(VABufferID *va_buffers, unsigned int num_va_buffers)
874 {
875     VAStatus va_status;
876     unsigned int i;
877
878     for (i = 0; i < num_va_buffers; i++) {
879         if (va_buffers[i] != VA_INVALID_ID) {
880             va_status = vaDestroyBuffer(va_dpy, va_buffers[i]);
881             CHECK_VASTATUS(va_status,"vaDestroyBuffer");
882             va_buffers[i] = VA_INVALID_ID;
883         }
884     }
885
886     return 0;
887 }
888
889 static void end_picture()
890 {
891
892     update_ReferenceFrames();
893     avcenc_destroy_buffers(&avcenc_context.seq_param_buf_id, 1);
894     avcenc_destroy_buffers(&avcenc_context.pic_param_buf_id, 1);
895     avcenc_destroy_buffers(&avcenc_context.packed_seq_header_param_buf_id, 1);
896     avcenc_destroy_buffers(&avcenc_context.packed_seq_buf_id, 1);
897     avcenc_destroy_buffers(&avcenc_context.packed_pic_header_param_buf_id, 1);
898     avcenc_destroy_buffers(&avcenc_context.packed_pic_buf_id, 1);
899     avcenc_destroy_buffers(&avcenc_context.packed_sei_header_param_buf_id, 1);
900     avcenc_destroy_buffers(&avcenc_context.packed_sei_buf_id, 1);
901     avcenc_destroy_buffers(&avcenc_context.slice_param_buf_id[0], avcenc_context.num_slices);
902     avcenc_destroy_buffers(&avcenc_context.codedbuf_buf_id, 1);
903     avcenc_destroy_buffers(&avcenc_context.misc_parameter_hrd_buf_id, 1);
904
905     memset(avcenc_context.slice_param, 0, sizeof(avcenc_context.slice_param));
906     avcenc_context.num_slices = 0;
907 }
908
909 #define BITSTREAM_ALLOCATE_STEPPING     4096
910
911 struct __bitstream {
912     unsigned int *buffer;
913     int bit_offset;
914     int max_size_in_dword;
915 };
916
917 typedef struct __bitstream bitstream;
918
919 #if 0
920 static int 
921 get_coded_bitsteam_length(unsigned char *buffer, int buffer_length)
922 {
923     int i;
924
925     for (i = 0; i < buffer_length - 3; i++) {
926         if (!buffer[i] &&
927             !buffer[i + 1] &&
928             !buffer[i + 2] &&
929             !buffer[i + 3])
930             break;
931     }
932
933     return i;
934 }
935 #endif
936
937 static unsigned int 
938 va_swap32(unsigned int val)
939 {
940     unsigned char *pval = (unsigned char *)&val;
941
942     return ((pval[0] << 24)     |
943             (pval[1] << 16)     |
944             (pval[2] << 8)      |
945             (pval[3] << 0));
946 }
947
948 static void
949 bitstream_start(bitstream *bs)
950 {
951     bs->max_size_in_dword = BITSTREAM_ALLOCATE_STEPPING;
952     bs->buffer = calloc(bs->max_size_in_dword * sizeof(int), 1);
953     bs->bit_offset = 0;
954 }
955
956 static void
957 bitstream_end(bitstream *bs)
958 {
959     int pos = (bs->bit_offset >> 5);
960     int bit_offset = (bs->bit_offset & 0x1f);
961     int bit_left = 32 - bit_offset;
962
963     if (bit_offset) {
964         bs->buffer[pos] = va_swap32((bs->buffer[pos] << bit_left));
965     }
966 }
967  
968 static void
969 bitstream_put_ui(bitstream *bs, unsigned int val, int size_in_bits)
970 {
971     int pos = (bs->bit_offset >> 5);
972     int bit_offset = (bs->bit_offset & 0x1f);
973     int bit_left = 32 - bit_offset;
974
975     if (!size_in_bits)
976         return;
977
978     bs->bit_offset += size_in_bits;
979
980     if (bit_left > size_in_bits) {
981         bs->buffer[pos] = (bs->buffer[pos] << size_in_bits | val);
982     } else {
983         size_in_bits -= bit_left;
984         bs->buffer[pos] = (bs->buffer[pos] << bit_left) | (val >> size_in_bits);
985         bs->buffer[pos] = va_swap32(bs->buffer[pos]);
986
987         if (pos + 1 == bs->max_size_in_dword) {
988             bs->max_size_in_dword += BITSTREAM_ALLOCATE_STEPPING;
989             bs->buffer = realloc(bs->buffer, bs->max_size_in_dword * sizeof(unsigned int));
990         }
991
992         bs->buffer[pos + 1] = val;
993     }
994 }
995
996 static void
997 bitstream_put_ue(bitstream *bs, unsigned int val)
998 {
999     int size_in_bits = 0;
1000     int tmp_val = ++val;
1001
1002     while (tmp_val) {
1003         tmp_val >>= 1;
1004         size_in_bits++;
1005     }
1006
1007     bitstream_put_ui(bs, 0, size_in_bits - 1); // leading zero
1008     bitstream_put_ui(bs, val, size_in_bits);
1009 }
1010
1011 static void
1012 bitstream_put_se(bitstream *bs, int val)
1013 {
1014     unsigned int new_val;
1015
1016     if (val <= 0)
1017         new_val = -2 * val;
1018     else
1019         new_val = 2 * val - 1;
1020
1021     bitstream_put_ue(bs, new_val);
1022 }
1023
1024 static void
1025 bitstream_byte_aligning(bitstream *bs, int bit)
1026 {
1027     int bit_offset = (bs->bit_offset & 0x7);
1028     int bit_left = 8 - bit_offset;
1029     int new_val;
1030
1031     if (!bit_offset)
1032         return;
1033
1034     assert(bit == 0 || bit == 1);
1035
1036     if (bit)
1037         new_val = (1 << bit_left) - 1;
1038     else
1039         new_val = 0;
1040
1041     bitstream_put_ui(bs, new_val, bit_left);
1042 }
1043
1044 static void 
1045 rbsp_trailing_bits(bitstream *bs)
1046 {
1047     bitstream_put_ui(bs, 1, 1);
1048     bitstream_byte_aligning(bs, 0);
1049 }
1050
1051 static void nal_start_code_prefix(bitstream *bs)
1052 {
1053     bitstream_put_ui(bs, 0x00000001, 32);
1054 }
1055
1056 static void nal_header(bitstream *bs, int nal_ref_idc, int nal_unit_type)
1057 {
1058     bitstream_put_ui(bs, 0, 1);                /* forbidden_zero_bit: 0 */
1059     bitstream_put_ui(bs, nal_ref_idc, 2);
1060     bitstream_put_ui(bs, nal_unit_type, 5);
1061 }
1062
1063 static void sps_rbsp(bitstream *bs)
1064 {
1065     VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
1066     int profile_idc = PROFILE_IDC_BASELINE;
1067
1068     if (avcenc_context.profile == VAProfileH264High)
1069         profile_idc = PROFILE_IDC_HIGH;
1070     else if (avcenc_context.profile == VAProfileH264Main)
1071         profile_idc = PROFILE_IDC_MAIN;
1072
1073     bitstream_put_ui(bs, profile_idc, 8);               /* profile_idc */
1074     bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 1), 1);                         /* constraint_set0_flag */
1075     bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 2), 1);                         /* constraint_set1_flag */
1076     bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 4), 1);                         /* constraint_set2_flag */
1077     bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 8), 1);                         /* constraint_set3_flag */
1078     bitstream_put_ui(bs, 0, 4);                         /* reserved_zero_4bits */
1079     bitstream_put_ui(bs, seq_param->level_idc, 8);      /* level_idc */
1080     bitstream_put_ue(bs, seq_param->seq_parameter_set_id);      /* seq_parameter_set_id */
1081
1082     if ( profile_idc == PROFILE_IDC_HIGH) {
1083         bitstream_put_ue(bs, 1);        /* chroma_format_idc = 1, 4:2:0 */ 
1084         bitstream_put_ue(bs, 0);        /* bit_depth_luma_minus8 */
1085         bitstream_put_ue(bs, 0);        /* bit_depth_chroma_minus8 */
1086         bitstream_put_ui(bs, 0, 1);     /* qpprime_y_zero_transform_bypass_flag */
1087         bitstream_put_ui(bs, 0, 1);     /* seq_scaling_matrix_present_flag */
1088     }
1089
1090     bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
1091     bitstream_put_ue(bs, seq_param->seq_fields.bits.pic_order_cnt_type);        /* pic_order_cnt_type */
1092
1093     if (seq_param->seq_fields.bits.pic_order_cnt_type == 0)
1094         bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4);     /* log2_max_pic_order_cnt_lsb_minus4 */
1095     else {
1096         assert(0);
1097     }
1098
1099     bitstream_put_ue(bs, seq_param->max_num_ref_frames);        /* num_ref_frames */
1100     bitstream_put_ui(bs, 0, 1);                                 /* gaps_in_frame_num_value_allowed_flag */
1101
1102     bitstream_put_ue(bs, seq_param->picture_width_in_mbs - 1);  /* pic_width_in_mbs_minus1 */
1103     bitstream_put_ue(bs, seq_param->picture_height_in_mbs - 1); /* pic_height_in_map_units_minus1 */
1104     bitstream_put_ui(bs, seq_param->seq_fields.bits.frame_mbs_only_flag, 1);    /* frame_mbs_only_flag */
1105
1106     if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {
1107         assert(0);
1108     }
1109
1110     bitstream_put_ui(bs, seq_param->seq_fields.bits.direct_8x8_inference_flag, 1);      /* direct_8x8_inference_flag */
1111     bitstream_put_ui(bs, seq_param->frame_cropping_flag, 1);            /* frame_cropping_flag */
1112
1113     if (seq_param->frame_cropping_flag) {
1114         bitstream_put_ue(bs, seq_param->frame_crop_left_offset);        /* frame_crop_left_offset */
1115         bitstream_put_ue(bs, seq_param->frame_crop_right_offset);       /* frame_crop_right_offset */
1116         bitstream_put_ue(bs, seq_param->frame_crop_top_offset);         /* frame_crop_top_offset */
1117         bitstream_put_ue(bs, seq_param->frame_crop_bottom_offset);      /* frame_crop_bottom_offset */
1118     }
1119     
1120     if ( frame_bit_rate < 0 ) {
1121         bitstream_put_ui(bs, 0, 1); /* vui_parameters_present_flag */
1122     } else {
1123         bitstream_put_ui(bs, 1, 1); /* vui_parameters_present_flag */
1124         bitstream_put_ui(bs, 0, 1); /* aspect_ratio_info_present_flag */
1125         bitstream_put_ui(bs, 0, 1); /* overscan_info_present_flag */
1126         bitstream_put_ui(bs, 0, 1); /* video_signal_type_present_flag */
1127         bitstream_put_ui(bs, 0, 1); /* chroma_loc_info_present_flag */
1128         bitstream_put_ui(bs, 1, 1); /* timing_info_present_flag */
1129         {
1130             bitstream_put_ui(bs, 1, 32);
1131             bitstream_put_ui(bs, frame_rate * 2, 32);
1132             bitstream_put_ui(bs, 1, 1);
1133         }
1134         bitstream_put_ui(bs, 1, 1); /* nal_hrd_parameters_present_flag */
1135         {
1136             // hrd_parameters 
1137             bitstream_put_ue(bs, 0);    /* cpb_cnt_minus1 */
1138             bitstream_put_ui(bs, 0, 4); /* bit_rate_scale */
1139             bitstream_put_ui(bs, 2, 4); /* cpb_size_scale */
1140            
1141             /* the frame_bit_rate is in kbps */
1142             bitstream_put_ue(bs, (((frame_bit_rate * 1000)>> 6) - 1)); /* bit_rate_value_minus1[0] */
1143             bitstream_put_ue(bs, ((frame_bit_rate * 8000) >> 6) - 1); /* cpb_size_value_minus1[0] */
1144             bitstream_put_ui(bs, 1, 1);  /* cbr_flag[0] */
1145
1146             /* initial_cpb_removal_delay_length_minus1 */
1147             bitstream_put_ui(bs,
1148                 (avcenc_context.i_initial_cpb_removal_delay_length - 1), 5);
1149             /* cpb_removal_delay_length_minus1 */
1150             bitstream_put_ui(bs,
1151                 (avcenc_context.i_cpb_removal_delay_length - 1), 5);
1152             /* dpb_output_delay_length_minus1 */
1153             bitstream_put_ui(bs,
1154                 (avcenc_context.i_dpb_output_delay_length - 1), 5);
1155             /* time_offset_length  */
1156             bitstream_put_ui(bs,
1157                 (avcenc_context.time_offset_length - 1), 5);
1158         }
1159         bitstream_put_ui(bs, 0, 1);   /* vcl_hrd_parameters_present_flag */
1160         bitstream_put_ui(bs, 0, 1);   /* low_delay_hrd_flag */ 
1161
1162         bitstream_put_ui(bs, 0, 1); /* pic_struct_present_flag */
1163         bitstream_put_ui(bs, 0, 1); /* bitstream_restriction_flag */
1164     }
1165
1166     rbsp_trailing_bits(bs);     /* rbsp_trailing_bits */
1167 }
1168
1169 #if 0
1170 static void build_nal_sps(FILE *avc_fp)
1171 {
1172     bitstream bs;
1173
1174     bitstream_start(&bs);
1175     nal_start_code_prefix(&bs);
1176     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
1177     sps_rbsp(&bs);
1178     bitstream_end(&bs, avc_fp);
1179 }
1180 #endif
1181
1182 static void pps_rbsp(bitstream *bs)
1183 {
1184     VAEncPictureParameterBufferH264 *pic_param = &avcenc_context.pic_param;
1185
1186     bitstream_put_ue(bs, pic_param->pic_parameter_set_id);      /* pic_parameter_set_id */
1187     bitstream_put_ue(bs, pic_param->seq_parameter_set_id);      /* seq_parameter_set_id */
1188
1189     bitstream_put_ui(bs, pic_param->pic_fields.bits.entropy_coding_mode_flag, 1);  /* entropy_coding_mode_flag */
1190
1191     bitstream_put_ui(bs, 0, 1);                         /* pic_order_present_flag: 0 */
1192
1193     bitstream_put_ue(bs, 0);                            /* num_slice_groups_minus1 */
1194
1195     bitstream_put_ue(bs, pic_param->num_ref_idx_l0_active_minus1);      /* num_ref_idx_l0_active_minus1 */
1196     bitstream_put_ue(bs, pic_param->num_ref_idx_l1_active_minus1);      /* num_ref_idx_l1_active_minus1 1 */
1197
1198     bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_pred_flag, 1);     /* weighted_pred_flag: 0 */
1199     bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_bipred_idc, 2);    /* weighted_bipred_idc: 0 */
1200
1201     bitstream_put_se(bs, pic_param->pic_init_qp - 26);  /* pic_init_qp_minus26 */
1202     bitstream_put_se(bs, 0);                            /* pic_init_qs_minus26 */
1203     bitstream_put_se(bs, 0);                            /* chroma_qp_index_offset */
1204
1205     bitstream_put_ui(bs, pic_param->pic_fields.bits.deblocking_filter_control_present_flag, 1); /* deblocking_filter_control_present_flag */
1206     bitstream_put_ui(bs, 0, 1);                         /* constrained_intra_pred_flag */
1207     bitstream_put_ui(bs, 0, 1);                         /* redundant_pic_cnt_present_flag */
1208     
1209     /* more_rbsp_data */
1210     bitstream_put_ui(bs, pic_param->pic_fields.bits.transform_8x8_mode_flag, 1);    /*transform_8x8_mode_flag */
1211     bitstream_put_ui(bs, 0, 1);                         /* pic_scaling_matrix_present_flag */
1212     bitstream_put_se(bs, pic_param->second_chroma_qp_index_offset );    /*second_chroma_qp_index_offset */
1213
1214     rbsp_trailing_bits(bs);
1215 }
1216
1217 #if 0
1218 static void build_nal_pps(FILE *avc_fp)
1219 {
1220     bitstream bs;
1221
1222     bitstream_start(&bs);
1223     nal_start_code_prefix(&bs);
1224     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
1225     pps_rbsp(&bs);
1226     bitstream_end(&bs, avc_fp);
1227 }
1228
1229 static void 
1230 build_header(FILE *avc_fp)
1231 {
1232     build_nal_sps(avc_fp);
1233     build_nal_pps(avc_fp);
1234 }
1235 #endif
1236
1237 static int
1238 build_packed_pic_buffer(unsigned char **header_buffer)
1239 {
1240     bitstream bs;
1241
1242     bitstream_start(&bs);
1243     nal_start_code_prefix(&bs);
1244     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
1245     pps_rbsp(&bs);
1246     bitstream_end(&bs);
1247
1248     *header_buffer = (unsigned char *)bs.buffer;
1249     return bs.bit_offset;
1250 }
1251
1252 static int
1253 build_packed_seq_buffer(unsigned char **header_buffer)
1254 {
1255     bitstream bs;
1256
1257     bitstream_start(&bs);
1258     nal_start_code_prefix(&bs);
1259     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
1260     sps_rbsp(&bs);
1261     bitstream_end(&bs);
1262
1263     *header_buffer = (unsigned char *)bs.buffer;
1264     return bs.bit_offset;
1265 }
1266
1267 static int 
1268 build_packed_idr_sei_buffer_timing(unsigned int init_cpb_removal_delay_length,
1269                                 unsigned int cpb_removal_length,
1270                                 unsigned int dpb_output_length,
1271                                 unsigned char **sei_buffer)
1272 {
1273     unsigned char *byte_buf;
1274     int bp_byte_size, i, pic_byte_size;
1275     unsigned int cpb_removal_delay;
1276
1277     bitstream nal_bs;
1278     bitstream sei_bp_bs, sei_pic_bs;
1279
1280     bitstream_start(&sei_bp_bs);
1281     bitstream_put_ue(&sei_bp_bs, 0);       /*seq_parameter_set_id*/
1282     /* SEI buffer period info */
1283     /* NALHrdBpPresentFlag == 1 */
1284     bitstream_put_ui(&sei_bp_bs, avcenc_context.i_initial_cpb_removal_delay,
1285                      init_cpb_removal_delay_length);
1286     bitstream_put_ui(&sei_bp_bs, avcenc_context.i_initial_cpb_removal_delay_offset,
1287                      init_cpb_removal_delay_length);
1288     if ( sei_bp_bs.bit_offset & 0x7) {
1289         bitstream_put_ui(&sei_bp_bs, 1, 1);
1290     }
1291     bitstream_end(&sei_bp_bs);
1292     bp_byte_size = (sei_bp_bs.bit_offset + 7) / 8;
1293     
1294     /* SEI pic timing info */
1295     bitstream_start(&sei_pic_bs);
1296     /* The info of CPB and DPB delay is controlled by CpbDpbDelaysPresentFlag,
1297      * which is derived as 1 if one of the following conditions is true:
1298      * nal_hrd_parameters_present_flag is present in the bitstream and is equal to 1,
1299      * vcl_hrd_parameters_present_flag is present in the bitstream and is equal to 1,
1300      */
1301     cpb_removal_delay = (avcenc_context.current_cpb_removal - avcenc_context.prev_idr_cpb_removal);
1302     bitstream_put_ui(&sei_pic_bs, cpb_removal_delay, cpb_removal_length); 
1303     bitstream_put_ui(&sei_pic_bs, avcenc_context.current_dpb_removal_delta,
1304                      dpb_output_length);
1305     if ( sei_pic_bs.bit_offset & 0x7) {
1306         bitstream_put_ui(&sei_pic_bs, 1, 1);
1307     }
1308     /* The pic_structure_present_flag determines whether the pic_structure
1309      * info is written into the SEI pic timing info.
1310      * Currently it is set to zero.
1311      */
1312     bitstream_end(&sei_pic_bs);
1313     pic_byte_size = (sei_pic_bs.bit_offset + 7) / 8;
1314     
1315     bitstream_start(&nal_bs);
1316     nal_start_code_prefix(&nal_bs);
1317     nal_header(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI);
1318
1319         /* Write the SEI buffer period data */    
1320     bitstream_put_ui(&nal_bs, 0, 8);
1321     bitstream_put_ui(&nal_bs, bp_byte_size, 8);
1322     
1323     byte_buf = (unsigned char *)sei_bp_bs.buffer;
1324     for(i = 0; i < bp_byte_size; i++) {
1325         bitstream_put_ui(&nal_bs, byte_buf[i], 8);
1326     }
1327     free(byte_buf);
1328         /* write the SEI pic timing data */
1329     bitstream_put_ui(&nal_bs, 0x01, 8);
1330     bitstream_put_ui(&nal_bs, pic_byte_size, 8);
1331     
1332     byte_buf = (unsigned char *)sei_pic_bs.buffer;
1333     for(i = 0; i < pic_byte_size; i++) {
1334         bitstream_put_ui(&nal_bs, byte_buf[i], 8);
1335     }
1336     free(byte_buf);
1337
1338     rbsp_trailing_bits(&nal_bs);
1339     bitstream_end(&nal_bs);
1340
1341     *sei_buffer = (unsigned char *)nal_bs.buffer; 
1342    
1343     return nal_bs.bit_offset;
1344 }
1345
1346 static int
1347 build_packed_sei_pic_timing(unsigned int cpb_removal_length,
1348                                 unsigned int dpb_output_length,
1349                                 unsigned char **sei_buffer)
1350 {
1351     unsigned char *byte_buf;
1352     int i, pic_byte_size;
1353     unsigned int cpb_removal_delay;
1354
1355     bitstream nal_bs;
1356     bitstream sei_pic_bs;
1357
1358     bitstream_start(&sei_pic_bs);
1359     /* The info of CPB and DPB delay is controlled by CpbDpbDelaysPresentFlag,
1360      * which is derived as 1 if one of the following conditions is true:
1361      * nal_hrd_parameters_present_flag is present in the bitstream and is equal to 1,
1362      * vcl_hrd_parameters_present_flag is present in the bitstream and is equal to 1,
1363      */
1364     cpb_removal_delay = (avcenc_context.current_cpb_removal - avcenc_context.current_idr_cpb_removal);
1365     bitstream_put_ui(&sei_pic_bs, cpb_removal_delay, cpb_removal_length);
1366     bitstream_put_ui(&sei_pic_bs, avcenc_context.current_dpb_removal_delta,
1367                      dpb_output_length);
1368     if ( sei_pic_bs.bit_offset & 0x7) {
1369         bitstream_put_ui(&sei_pic_bs, 1, 1);
1370     }
1371
1372     /* The pic_structure_present_flag determines whether the pic_structure
1373      * info is written into the SEI pic timing info.
1374      * Currently it is set to zero.
1375      */
1376     bitstream_end(&sei_pic_bs);
1377     pic_byte_size = (sei_pic_bs.bit_offset + 7) / 8;
1378
1379     bitstream_start(&nal_bs);
1380     nal_start_code_prefix(&nal_bs);
1381     nal_header(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI);
1382
1383         /* write the SEI Pic timing data */
1384     bitstream_put_ui(&nal_bs, 0x01, 8);
1385     bitstream_put_ui(&nal_bs, pic_byte_size, 8);
1386
1387     byte_buf = (unsigned char *)sei_pic_bs.buffer;
1388     for(i = 0; i < pic_byte_size; i++) {
1389         bitstream_put_ui(&nal_bs, byte_buf[i], 8);
1390     }
1391     free(byte_buf);
1392
1393     rbsp_trailing_bits(&nal_bs);
1394     bitstream_end(&nal_bs);
1395
1396     *sei_buffer = (unsigned char *)nal_bs.buffer;
1397
1398     return nal_bs.bit_offset;
1399 }
1400
1401 #if 0
1402 static void 
1403 slice_header(bitstream *bs, int frame_num, int display_frame, int slice_type, int nal_ref_idc, int is_idr)
1404 {
1405     VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
1406     VAEncPictureParameterBufferH264 *pic_param = &avcenc_context.pic_param;
1407     int is_cabac = (pic_param->pic_fields.bits.entropy_coding_mode_flag == ENTROPY_MODE_CABAC);
1408
1409     bitstream_put_ue(bs, 0);                   /* first_mb_in_slice: 0 */
1410     bitstream_put_ue(bs, slice_type);          /* slice_type */
1411     bitstream_put_ue(bs, 0);                   /* pic_parameter_set_id: 0 */
1412     bitstream_put_ui(bs, frame_num & 0x0F, seq_param->seq_fields.bits.log2_max_frame_num_minus4 + 4);    /* frame_num */
1413
1414     /* frame_mbs_only_flag == 1 */
1415     if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {
1416         /* FIXME: */
1417         assert(0);
1418     }
1419
1420     if (is_idr)
1421         bitstream_put_ue(bs, 0);                /* idr_pic_id: 0 */
1422
1423     if (seq_param->seq_fields.bits.pic_order_cnt_type == 0) {
1424         bitstream_put_ui(bs, (display_frame*2) & 0x3F, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 + 4);
1425         /* only support frame */
1426     } else {
1427         /* FIXME: */
1428         assert(0);
1429     }
1430
1431     /* redundant_pic_cnt_present_flag == 0 */
1432     
1433     /* slice type */
1434     if (slice_type == SLICE_TYPE_P) {
1435         bitstream_put_ui(bs, 0, 1);            /* num_ref_idx_active_override_flag: 0 */
1436         /* ref_pic_list_reordering */
1437         bitstream_put_ui(bs, 0, 1);            /* ref_pic_list_reordering_flag_l0: 0 */
1438     } else if (slice_type == SLICE_TYPE_B) {
1439         bitstream_put_ui(bs, 1, 1);            /* direct_spatial_mv_pred: 1 */
1440         bitstream_put_ui(bs, 0, 1);            /* num_ref_idx_active_override_flag: 0 */
1441         /* ref_pic_list_reordering */
1442         bitstream_put_ui(bs, 0, 1);            /* ref_pic_list_reordering_flag_l0: 0 */
1443         bitstream_put_ui(bs, 0, 1);            /* ref_pic_list_reordering_flag_l1: 0 */
1444     } 
1445
1446     /* weighted_pred_flag == 0 */
1447
1448     /* dec_ref_pic_marking */
1449     if (nal_ref_idc != 0) {
1450         if ( is_idr) {
1451             bitstream_put_ui(bs, 0, 1);            /* no_output_of_prior_pics_flag: 0 */
1452             bitstream_put_ui(bs, 0, 1);            /* long_term_reference_flag: 0 */
1453         } else {
1454             bitstream_put_ui(bs, 0, 1);            /* adaptive_ref_pic_marking_mode_flag: 0 */
1455         }
1456     }
1457
1458     if (is_cabac && (slice_type != SLICE_TYPE_I))
1459         bitstream_put_ue(bs, 0);               /* cabac_init_idc: 0 */
1460
1461     bitstream_put_se(bs, 0);                   /* slice_qp_delta: 0 */
1462
1463     if (pic_param->pic_fields.bits.deblocking_filter_control_present_flag == 1) {
1464         bitstream_put_ue(bs, 0);               /* disable_deblocking_filter_idc: 0 */
1465         bitstream_put_se(bs, 2);               /* slice_alpha_c0_offset_div2: 2 */
1466         bitstream_put_se(bs, 2);               /* slice_beta_offset_div2: 2 */
1467     }
1468 }
1469
1470 static void 
1471 slice_data(bitstream *bs)
1472 {
1473     VACodedBufferSegment *coded_buffer_segment;
1474     unsigned char *coded_mem;
1475     int i, slice_data_length;
1476     VAStatus va_status;
1477     VASurfaceStatus surface_status;
1478
1479     va_status = vaSyncSurface(va_dpy, surface_ids[avcenc_context.current_input_surface]);
1480     CHECK_VASTATUS(va_status,"vaSyncSurface");
1481
1482     surface_status = 0;
1483     va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[avcenc_context.current_input_surface], &surface_status);
1484     CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
1485
1486     va_status = vaMapBuffer(va_dpy, avcenc_context.codedbuf_buf_id, (void **)(&coded_buffer_segment));
1487     CHECK_VASTATUS(va_status,"vaMapBuffer");
1488     coded_mem = coded_buffer_segment->buf;
1489
1490     slice_data_length = get_coded_bitsteam_length(coded_mem, codedbuf_size);
1491
1492     for (i = 0; i < slice_data_length; i++) {
1493         bitstream_put_ui(bs, *coded_mem, 8);
1494         coded_mem++;
1495     }
1496
1497     vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
1498 }
1499
1500 static void 
1501 build_nal_slice(FILE *avc_fp, int frame_num, int display_frame, int slice_type, int is_idr)
1502 {
1503     bitstream bs;
1504
1505     bitstream_start(&bs);
1506     slice_data(&bs);
1507     bitstream_end(&bs, avc_fp);
1508 }
1509
1510 #endif
1511
1512 static int
1513 store_coded_buffer(FILE *avc_fp, int slice_type)
1514 {
1515     VACodedBufferSegment *coded_buffer_segment;
1516     unsigned char *coded_mem;
1517     int slice_data_length;
1518     VAStatus va_status;
1519     VASurfaceStatus surface_status;
1520     size_t w_items;
1521
1522     va_status = vaSyncSurface(va_dpy, surface_ids[avcenc_context.current_input_surface]);
1523     CHECK_VASTATUS(va_status,"vaSyncSurface");
1524
1525     surface_status = 0;
1526     va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[avcenc_context.current_input_surface], &surface_status);
1527     CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
1528
1529     va_status = vaMapBuffer(va_dpy, avcenc_context.codedbuf_buf_id, (void **)(&coded_buffer_segment));
1530     CHECK_VASTATUS(va_status,"vaMapBuffer");
1531     coded_mem = coded_buffer_segment->buf;
1532
1533     if (coded_buffer_segment->status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK) {
1534         if (slice_type == SLICE_TYPE_I)
1535             avcenc_context.codedbuf_i_size *= 2;
1536         else
1537             avcenc_context.codedbuf_pb_size *= 2;
1538
1539         vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
1540         return -1;
1541     }
1542
1543     slice_data_length = coded_buffer_segment->size;
1544
1545     do {
1546         w_items = fwrite(coded_mem, slice_data_length, 1, avc_fp);
1547     } while (w_items != 1);
1548
1549     vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
1550
1551     return 0;
1552 }
1553
1554 /*
1555  * It is from the h264encode.c but it simplifies something.
1556  * For example: When one frame is encoded as I-frame under the scenario with
1557  * P-B frames, it will be regarded as IDR frame(key-frame) and then new GOP is
1558  * started. If the video clip is encoded as all I-frames, the first frame
1559  * is regarded as IDR and the remaining is regarded as I-frame.
1560  *
1561  */
1562
1563 static void encoding2display_order(
1564     unsigned long long encoding_order,int gop_size,
1565     int ip_period,
1566     unsigned long long *displaying_order,
1567     int *frame_type)
1568 {
1569     int encoding_order_gop = 0;
1570
1571     /* When ip_period is 0, all are I/IDR frames */
1572     if (ip_period == 0) { /* all are I/IDR frames */
1573         if (encoding_order == 0)
1574             *frame_type = FRAME_IDR;
1575         else
1576             *frame_type = SLICE_TYPE_I;
1577
1578         *displaying_order = encoding_order;
1579         return;
1580     }
1581
1582     /* new sequence like
1583      * IDR PPPPP IDRPPPPP
1584      * IDR (PBB)(PBB)(PBB)(PBB) IDR (PBB)(PBB)(PBB)(PBB)
1585      */
1586     encoding_order_gop = encoding_order % gop_size;
1587
1588     if (encoding_order_gop == 0) { /* the first frame */
1589         *frame_type = FRAME_IDR;
1590         *displaying_order = encoding_order;
1591     } else {
1592         int gop_delta;
1593
1594         gop_delta = 1;
1595
1596         if ((ip_period != 1) && ((gop_size - 1) % ip_period)) {
1597             int ipb_size;
1598             ipb_size = (gop_size - 1) / ip_period * ip_period + 1;
1599             if (encoding_order_gop >= ipb_size) {
1600                 gop_delta = ipb_size;
1601                 ip_period = gop_size - ipb_size;
1602             }
1603         }
1604
1605         if (((encoding_order_gop - gop_delta) % ip_period) == 0) { /* P frames */
1606             *frame_type = SLICE_TYPE_P;
1607             *displaying_order = encoding_order + ip_period - 1;
1608         } else {
1609             *frame_type = SLICE_TYPE_B;
1610             *displaying_order = encoding_order - 1;
1611         }
1612     }
1613 }
1614
1615
1616 static void
1617 encode_picture(FILE *yuv_fp, FILE *avc_fp,
1618                int frame_num, int display_num,
1619                int is_idr,
1620                int slice_type, int next_is_bpic,
1621                int next_display_num)
1622 {
1623     VAStatus va_status;
1624     int ret = 0, codedbuf_size;
1625     
1626     begin_picture(yuv_fp, frame_num, display_num, slice_type, is_idr);
1627
1628     //if (next_display_num < frame_number) {
1629     if (1) {
1630         int index;
1631
1632         /* prepare for next frame */
1633         if (avcenc_context.current_input_surface == SID_INPUT_PICTURE_0)
1634             index = SID_INPUT_PICTURE_1;
1635         else
1636             index = SID_INPUT_PICTURE_0;
1637         if ( next_display_num >= frame_number )
1638             next_display_num = frame_number - 1;
1639         fseeko(yuv_fp, (off_t)frame_size * next_display_num, SEEK_SET);
1640
1641         avcenc_context.upload_thread_param.yuv_fp = yuv_fp;
1642         avcenc_context.upload_thread_param.surface_id = surface_ids[index];
1643
1644         avcenc_context.upload_thread_value = pthread_create(&avcenc_context.upload_thread_id,
1645                                                             NULL,
1646                                                             upload_thread_function, 
1647                                                             (void*)&avcenc_context.upload_thread_param);
1648     }
1649
1650     do {
1651         avcenc_destroy_buffers(&avcenc_context.codedbuf_buf_id, 1);
1652         avcenc_destroy_buffers(&avcenc_context.pic_param_buf_id, 1);
1653
1654
1655         if (SLICE_TYPE_I == slice_type) {
1656             codedbuf_size = avcenc_context.codedbuf_i_size;
1657         } else {
1658             codedbuf_size = avcenc_context.codedbuf_pb_size;
1659         }
1660
1661         /* coded buffer */
1662         va_status = vaCreateBuffer(va_dpy,
1663                                    avcenc_context.context_id,
1664                                    VAEncCodedBufferType,
1665                                    codedbuf_size, 1, NULL,
1666                                    &avcenc_context.codedbuf_buf_id);
1667         CHECK_VASTATUS(va_status,"vaCreateBuffer");
1668
1669         /* Update the RefPicList */
1670         update_RefPicList();
1671
1672         /* picture parameter set */
1673         avcenc_update_picture_parameter(slice_type, is_idr);
1674
1675         /* slice parameter */
1676         avcenc_update_slice_parameter(slice_type);
1677
1678         if (avcenc_context.rate_control_method == VA_RC_CBR)
1679                 avcenc_update_sei_param(is_idr);
1680
1681         avcenc_render_picture();
1682
1683         ret = store_coded_buffer(avc_fp, slice_type);
1684     } while (ret);
1685
1686     end_picture(slice_type, next_is_bpic);
1687 }
1688
1689 static void show_help()
1690 {
1691     printf("Usage: avnenc <width> <height> <input_yuvfile> <output_avcfile> [--qp=qpvalue|--fb=framebitrate] [--mode=0(I frames only)/1(I and P frames)/2(I, P and B frames)\n");
1692 }
1693
1694 static void avcenc_context_seq_param_init(VAEncSequenceParameterBufferH264 *seq_param,
1695                                           int width, int height)
1696
1697 {
1698     int width_in_mbs = (width + 15) / 16;
1699     int height_in_mbs = (height + 15) / 16;
1700     int frame_cropping_flag = 0;
1701     int frame_crop_bottom_offset = 0;
1702
1703     seq_param->seq_parameter_set_id = 0;
1704     seq_param->level_idc = 41;
1705     seq_param->intra_period = intra_period;
1706     seq_param->intra_idr_period = seq_param->intra_period;
1707     seq_param->ip_period = ip_period;
1708     seq_param->max_num_ref_frames = 4;
1709     seq_param->picture_width_in_mbs = width_in_mbs;
1710     seq_param->picture_height_in_mbs = height_in_mbs;
1711     seq_param->seq_fields.bits.frame_mbs_only_flag = 1;
1712     seq_param->seq_fields.bits.chroma_format_idc = 1;
1713
1714     
1715     if (frame_bit_rate > 0)
1716         seq_param->bits_per_second = 1000 * frame_bit_rate; /* use kbps as input */
1717     else
1718         seq_param->bits_per_second = 0;
1719     
1720     seq_param->time_scale = frame_rate * 2;
1721     seq_param->num_units_in_tick = 1;                   /* Tc = num_units_in_tick / time_sacle */
1722
1723     if (height_in_mbs * 16 - height) {
1724         frame_cropping_flag = 1;
1725         frame_crop_bottom_offset = 
1726             (height_in_mbs * 16 - height) / (2 * (!seq_param->seq_fields.bits.frame_mbs_only_flag + 1));
1727     }
1728
1729     seq_param->frame_cropping_flag = frame_cropping_flag;
1730     seq_param->frame_crop_left_offset = 0;
1731     seq_param->frame_crop_right_offset = 0;
1732     seq_param->frame_crop_top_offset = 0;
1733     seq_param->frame_crop_bottom_offset = frame_crop_bottom_offset;
1734
1735     seq_param->seq_fields.bits.pic_order_cnt_type = 0;
1736     seq_param->seq_fields.bits.direct_8x8_inference_flag = 0;
1737     
1738     seq_param->seq_fields.bits.log2_max_frame_num_minus4 = Log2MaxFrameNum - 4;
1739     seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = Log2MaxPicOrderCntLsb - 4;
1740         
1741     if (frame_bit_rate > 0)
1742         seq_param->vui_parameters_present_flag = 1;     //HRD info located in vui
1743     else
1744         seq_param->vui_parameters_present_flag = 0;
1745 }
1746
1747 static void avcenc_context_pic_param_init(VAEncPictureParameterBufferH264 *pic_param)
1748 {
1749     pic_param->seq_parameter_set_id = 0;
1750     pic_param->pic_parameter_set_id = 0;
1751
1752     pic_param->last_picture = 0;
1753     pic_param->frame_num = 0;
1754     
1755     pic_param->pic_init_qp = (qp_value >= 0 ?  qp_value : 26);
1756     pic_param->num_ref_idx_l0_active_minus1 = 0;
1757     pic_param->num_ref_idx_l1_active_minus1 = 0;
1758
1759     pic_param->pic_fields.bits.idr_pic_flag = 0;
1760     pic_param->pic_fields.bits.reference_pic_flag = 0;
1761     pic_param->pic_fields.bits.entropy_coding_mode_flag = ENTROPY_MODE_CABAC;
1762     pic_param->pic_fields.bits.weighted_pred_flag = 0;
1763     pic_param->pic_fields.bits.weighted_bipred_idc = 0;
1764     
1765     if (avcenc_context.constraint_set_flag & 0x7)
1766         pic_param->pic_fields.bits.transform_8x8_mode_flag = 0;
1767     else
1768         pic_param->pic_fields.bits.transform_8x8_mode_flag = 1;
1769
1770     pic_param->pic_fields.bits.deblocking_filter_control_present_flag = 1;
1771
1772     memset(pic_param->ReferenceFrames, 0xff, 16 * sizeof(VAPictureH264)); /* invalid all */
1773 }
1774
1775 static void avcenc_context_sei_init()
1776 {
1777         /* it comes for the bps defined in SPS */
1778         avcenc_context.i_initial_cpb_removal_delay = 2 * 90000;
1779         avcenc_context.i_initial_cpb_removal_delay_offset = 2 * 90000;
1780
1781         avcenc_context.i_cpb_removal_delay = 2;
1782         avcenc_context.i_initial_cpb_removal_delay_length = 24;
1783         avcenc_context.i_cpb_removal_delay_length = 24;
1784         avcenc_context.i_dpb_output_delay_length = 24;
1785         avcenc_context.time_offset_length = 24;
1786
1787         avcenc_context.prev_idr_cpb_removal = avcenc_context.i_initial_cpb_removal_delay / 90000;
1788         avcenc_context.current_idr_cpb_removal = avcenc_context.prev_idr_cpb_removal;
1789         avcenc_context.current_cpb_removal = 0;
1790         avcenc_context.idr_frame_num = 0;
1791 }
1792
1793 static void avcenc_context_init(int width, int height)
1794 {
1795     int i;
1796     memset(&avcenc_context, 0, sizeof(avcenc_context));
1797     avcenc_context.profile = VAProfileH264Main;
1798
1799     memset(&use_slot, 0, sizeof(use_slot));
1800     switch (avcenc_context.profile) {
1801     case VAProfileH264Baseline:
1802         avcenc_context.constraint_set_flag |= (1 << 0); /* Annex A.2.1 */
1803         break;
1804
1805     case VAProfileH264Main:
1806         avcenc_context.constraint_set_flag |= (1 << 1); /* Annex A.2.2 */
1807         break;
1808
1809     case VAProfileH264High:
1810         avcenc_context.constraint_set_flag |= (1 << 3); /* Annex A.2.4 */
1811         break;
1812         
1813     default:
1814         break;
1815     }
1816         
1817     avcenc_context.seq_param_buf_id = VA_INVALID_ID;
1818     avcenc_context.pic_param_buf_id = VA_INVALID_ID;
1819     avcenc_context.packed_seq_header_param_buf_id = VA_INVALID_ID;
1820     avcenc_context.packed_seq_buf_id = VA_INVALID_ID;
1821     avcenc_context.packed_pic_header_param_buf_id = VA_INVALID_ID;
1822     avcenc_context.packed_pic_buf_id = VA_INVALID_ID;
1823     avcenc_context.codedbuf_buf_id = VA_INVALID_ID;
1824     avcenc_context.misc_parameter_hrd_buf_id = VA_INVALID_ID;
1825     avcenc_context.codedbuf_i_size = width * height;
1826     avcenc_context.codedbuf_pb_size = width * height;
1827     avcenc_context.current_input_surface = SID_INPUT_PICTURE_0;
1828     avcenc_context.upload_thread_value = -1;
1829     avcenc_context.packed_sei_header_param_buf_id = VA_INVALID_ID;
1830     avcenc_context.packed_sei_buf_id = VA_INVALID_ID;
1831
1832     if (qp_value == -1)
1833         avcenc_context.rate_control_method = VA_RC_CBR;
1834     else if (qp_value == -2)
1835         avcenc_context.rate_control_method = VA_RC_VBR;
1836     else {
1837         assert(qp_value >= 0 && qp_value <= 51);
1838         avcenc_context.rate_control_method = VA_RC_CQP;
1839     }
1840
1841     for (i = 0; i < MAX_SLICES; i++) {
1842         avcenc_context.slice_param_buf_id[i] = VA_INVALID_ID;
1843     }
1844
1845     avcenc_context_seq_param_init(&avcenc_context.seq_param, width, height);
1846     avcenc_context_pic_param_init(&avcenc_context.pic_param);
1847     if (avcenc_context.rate_control_method == VA_RC_CBR)
1848         avcenc_context_sei_init();
1849 }
1850
1851 int main(int argc, char *argv[])
1852 {
1853     int f;
1854     FILE *yuv_fp;
1855     FILE *avc_fp;
1856     off_t file_size;
1857     int mode_value;
1858     struct timeval tpstart,tpend; 
1859     float  timeuse;
1860
1861     va_init_display_args(&argc, argv);
1862
1863     if(argc < 5) {
1864         show_help();
1865         return -1;
1866     }
1867
1868     picture_width = atoi(argv[1]);
1869     picture_height = atoi(argv[2]);
1870     picture_width_in_mbs = (picture_width + 15) / 16;
1871     picture_height_in_mbs = (picture_height + 15) / 16;
1872
1873     if (argc > 5) {
1874         char o;
1875
1876         optind = 5;
1877
1878         while ((o = getopt_long_only(argc, argv, "", longopts, NULL)) != -1) {
1879             switch (o) {
1880             case 1:     // qp
1881                 frame_bit_rate = -1;
1882                 qp_value = atoi(optarg);
1883
1884                 if (qp_value > 51)
1885                     qp_value = 51;
1886
1887                 if (qp_value < 0)
1888                     qp_value = 0;
1889
1890                 break;
1891
1892             case 2:     // fb
1893                 qp_value = -1;
1894                 frame_bit_rate = atoi(optarg);
1895
1896                 if (frame_bit_rate <= 0) {
1897                     show_help();
1898
1899                     return -1;
1900                 }
1901
1902                 break;
1903
1904             case 3:     // mode
1905                 mode_value = atoi(optarg);
1906
1907                 if (mode_value == 0)
1908                     ip_period = 0;
1909                 else if (mode_value == 1)
1910                     ip_period = 1;
1911                 else if (mode_value == 2)
1912                     /* Hack mechanism before adding the parameter of B-frame number */
1913                     ip_period = 2;
1914                 else {
1915                     printf("mode_value = %d\n", mode_value);
1916                     show_help();
1917                     return -1;
1918                 }
1919
1920                 break;
1921
1922             default:
1923                 show_help();
1924                 return -1;
1925             }
1926         }
1927     } else
1928         qp_value = 28;                          //default const QP mode
1929
1930     yuv_fp = fopen(argv[3],"rb");
1931     if ( yuv_fp == NULL){
1932         printf("Can't open input YUV file\n");
1933         return -1;
1934     }
1935     fseeko(yuv_fp, (off_t)0, SEEK_END);
1936     file_size = ftello(yuv_fp);
1937     frame_size = picture_width * picture_height +  ((picture_width * picture_height) >> 1) ;
1938
1939     if ( (file_size < frame_size) || (file_size % frame_size) ) {
1940         fclose(yuv_fp);
1941         printf("The YUV file's size is not correct\n");
1942         return -1;
1943     }
1944     frame_number = file_size / frame_size;
1945     fseeko(yuv_fp, (off_t)0, SEEK_SET);
1946
1947     avc_fp = fopen(argv[4], "wb");      
1948     if ( avc_fp == NULL) {
1949         fclose(yuv_fp);
1950         printf("Can't open output avc file\n");
1951         return -1;
1952     }   
1953     gettimeofday(&tpstart,NULL);        
1954     avcenc_context_init(picture_width, picture_height);
1955     create_encode_pipe();
1956     alloc_encode_resource(yuv_fp);
1957
1958     enc_frame_number = 0;
1959     for ( f = 0; f < frame_number; f++) {               //picture level loop
1960         unsigned long long next_frame_display;
1961         int next_frame_type;
1962
1963         enc_frame_number = f;
1964
1965         encoding2display_order(enc_frame_number, intra_period, ip_period,
1966                                &current_frame_display, &current_frame_type);
1967
1968         encoding2display_order(enc_frame_number + 1, intra_period, ip_period,
1969                                &next_frame_display, &next_frame_type);
1970
1971         if (current_frame_type == FRAME_IDR) {
1972             numShortTerm = 0;
1973             current_frame_num = 0;
1974             memset(&use_slot, 0, sizeof(use_slot));
1975             current_IDR_display = current_frame_display;
1976             if (avcenc_context.rate_control_method == VA_RC_CBR) {
1977                 unsigned long long frame_interval;
1978
1979                 frame_interval = enc_frame_number - avcenc_context.idr_frame_num;
1980
1981                 /* Based on the H264 spec the removal time of the IDR access
1982                  * unit is derived as the following:
1983                  * the removal time of previous IDR unit + Tc * cpb_removal_delay(n)
1984                  */
1985                 avcenc_context.current_cpb_removal = avcenc_context.prev_idr_cpb_removal +
1986                                 frame_interval * 2;
1987                 avcenc_context.idr_frame_num = enc_frame_number;
1988                 avcenc_context.current_idr_cpb_removal = avcenc_context.current_cpb_removal;
1989                 if (ip_period)
1990                     avcenc_context.current_dpb_removal_delta = (ip_period + 1) * 2;
1991                 else
1992                     avcenc_context.current_dpb_removal_delta = 2;
1993             }
1994         } else {
1995             if (avcenc_context.rate_control_method == VA_RC_CBR) {
1996                 unsigned long long frame_interval;
1997
1998                 frame_interval = enc_frame_number - avcenc_context.idr_frame_num;
1999
2000                 /* Based on the H264 spec the removal time of the non-IDR access
2001                  * unit is derived as the following:
2002                  * the removal time of current IDR unit + Tc * cpb_removal_delay(n)
2003                  */
2004                 avcenc_context.current_cpb_removal = avcenc_context.current_idr_cpb_removal +
2005                                 frame_interval * 2;
2006                 if (current_frame_type == SLICE_TYPE_I ||
2007                     current_frame_type == SLICE_TYPE_P) {
2008                     if (ip_period)
2009                         avcenc_context.current_dpb_removal_delta = (ip_period + 1) * 2;
2010                     else
2011                         avcenc_context.current_dpb_removal_delta = 2;
2012                 } else
2013                    avcenc_context.current_dpb_removal_delta = 2;
2014             }
2015         }
2016
2017         /* use the simple mechanism to calc the POC */
2018         current_poc = (current_frame_display - current_IDR_display) * 2;
2019
2020         encode_picture(yuv_fp, avc_fp, frame_number, current_frame_display,
2021                       (current_frame_type == FRAME_IDR) ? 1 : 0,
2022                       (current_frame_type == FRAME_IDR) ? SLICE_TYPE_I : current_frame_type,
2023                       (next_frame_type == SLICE_TYPE_B) ? 1 : 0,
2024                 next_frame_display);
2025         if ((current_frame_type == FRAME_IDR) &&
2026             (avcenc_context.rate_control_method == VA_RC_CBR)) {
2027            /* after one IDR frame is written, it needs to update the
2028             * prev_idr_cpb_removal for next IDR
2029             */
2030            avcenc_context.prev_idr_cpb_removal = avcenc_context.current_idr_cpb_removal;
2031         }
2032         printf("\r %d/%d ...", f, frame_number);
2033         fflush(stdout);
2034     }
2035
2036     gettimeofday(&tpend,NULL);
2037     timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+ tpend.tv_usec-tpstart.tv_usec;
2038     timeuse/=1000000;
2039     printf("\ndone!\n");
2040     printf("encode %d frames in %f secondes, FPS is %.1f\n",frame_number, timeuse, frame_number/timeuse);
2041     release_encode_resource();
2042     destory_encode_pipe();
2043
2044     fclose(yuv_fp);
2045     fclose(avc_fp);
2046
2047     return 0;
2048 }