OSDN Git Service

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