OSDN Git Service

add assert check for potential NULL issue in test/encode/
[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     assert(bs->buffer);
957     bs->bit_offset = 0;
958 }
959
960 static void
961 bitstream_end(bitstream *bs)
962 {
963     int pos = (bs->bit_offset >> 5);
964     int bit_offset = (bs->bit_offset & 0x1f);
965     int bit_left = 32 - bit_offset;
966
967     if (bit_offset) {
968         bs->buffer[pos] = va_swap32((bs->buffer[pos] << bit_left));
969     }
970 }
971  
972 static void
973 bitstream_put_ui(bitstream *bs, unsigned int val, int size_in_bits)
974 {
975     int pos = (bs->bit_offset >> 5);
976     int bit_offset = (bs->bit_offset & 0x1f);
977     int bit_left = 32 - bit_offset;
978
979     if (!size_in_bits)
980         return;
981
982     bs->bit_offset += size_in_bits;
983
984     if (bit_left > size_in_bits) {
985         bs->buffer[pos] = (bs->buffer[pos] << size_in_bits | val);
986     } else {
987         size_in_bits -= bit_left;
988         bs->buffer[pos] = (bs->buffer[pos] << bit_left) | (val >> size_in_bits);
989         bs->buffer[pos] = va_swap32(bs->buffer[pos]);
990
991         if (pos + 1 == bs->max_size_in_dword) {
992             bs->max_size_in_dword += BITSTREAM_ALLOCATE_STEPPING;
993             bs->buffer = realloc(bs->buffer, bs->max_size_in_dword * sizeof(unsigned int));
994             assert(bs->buffer);
995         }
996
997         bs->buffer[pos + 1] = val;
998     }
999 }
1000
1001 static void
1002 bitstream_put_ue(bitstream *bs, unsigned int val)
1003 {
1004     int size_in_bits = 0;
1005     int tmp_val = ++val;
1006
1007     while (tmp_val) {
1008         tmp_val >>= 1;
1009         size_in_bits++;
1010     }
1011
1012     bitstream_put_ui(bs, 0, size_in_bits - 1); // leading zero
1013     bitstream_put_ui(bs, val, size_in_bits);
1014 }
1015
1016 static void
1017 bitstream_put_se(bitstream *bs, int val)
1018 {
1019     unsigned int new_val;
1020
1021     if (val <= 0)
1022         new_val = -2 * val;
1023     else
1024         new_val = 2 * val - 1;
1025
1026     bitstream_put_ue(bs, new_val);
1027 }
1028
1029 static void
1030 bitstream_byte_aligning(bitstream *bs, int bit)
1031 {
1032     int bit_offset = (bs->bit_offset & 0x7);
1033     int bit_left = 8 - bit_offset;
1034     int new_val;
1035
1036     if (!bit_offset)
1037         return;
1038
1039     assert(bit == 0 || bit == 1);
1040
1041     if (bit)
1042         new_val = (1 << bit_left) - 1;
1043     else
1044         new_val = 0;
1045
1046     bitstream_put_ui(bs, new_val, bit_left);
1047 }
1048
1049 static void 
1050 rbsp_trailing_bits(bitstream *bs)
1051 {
1052     bitstream_put_ui(bs, 1, 1);
1053     bitstream_byte_aligning(bs, 0);
1054 }
1055
1056 static void nal_start_code_prefix(bitstream *bs)
1057 {
1058     bitstream_put_ui(bs, 0x00000001, 32);
1059 }
1060
1061 static void nal_header(bitstream *bs, int nal_ref_idc, int nal_unit_type)
1062 {
1063     bitstream_put_ui(bs, 0, 1);                /* forbidden_zero_bit: 0 */
1064     bitstream_put_ui(bs, nal_ref_idc, 2);
1065     bitstream_put_ui(bs, nal_unit_type, 5);
1066 }
1067
1068 static void sps_rbsp(bitstream *bs)
1069 {
1070     VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
1071     int profile_idc = PROFILE_IDC_BASELINE;
1072
1073     if (avcenc_context.profile == VAProfileH264High)
1074         profile_idc = PROFILE_IDC_HIGH;
1075     else if (avcenc_context.profile == VAProfileH264Main)
1076         profile_idc = PROFILE_IDC_MAIN;
1077
1078     bitstream_put_ui(bs, profile_idc, 8);               /* profile_idc */
1079     bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 1), 1);                         /* constraint_set0_flag */
1080     bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 2), 1);                         /* constraint_set1_flag */
1081     bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 4), 1);                         /* constraint_set2_flag */
1082     bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 8), 1);                         /* constraint_set3_flag */
1083     bitstream_put_ui(bs, 0, 4);                         /* reserved_zero_4bits */
1084     bitstream_put_ui(bs, seq_param->level_idc, 8);      /* level_idc */
1085     bitstream_put_ue(bs, seq_param->seq_parameter_set_id);      /* seq_parameter_set_id */
1086
1087     if ( profile_idc == PROFILE_IDC_HIGH) {
1088         bitstream_put_ue(bs, 1);        /* chroma_format_idc = 1, 4:2:0 */ 
1089         bitstream_put_ue(bs, 0);        /* bit_depth_luma_minus8 */
1090         bitstream_put_ue(bs, 0);        /* bit_depth_chroma_minus8 */
1091         bitstream_put_ui(bs, 0, 1);     /* qpprime_y_zero_transform_bypass_flag */
1092         bitstream_put_ui(bs, 0, 1);     /* seq_scaling_matrix_present_flag */
1093     }
1094
1095     bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
1096     bitstream_put_ue(bs, seq_param->seq_fields.bits.pic_order_cnt_type);        /* pic_order_cnt_type */
1097
1098     if (seq_param->seq_fields.bits.pic_order_cnt_type == 0)
1099         bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4);     /* log2_max_pic_order_cnt_lsb_minus4 */
1100     else {
1101         assert(0);
1102     }
1103
1104     bitstream_put_ue(bs, seq_param->max_num_ref_frames);        /* num_ref_frames */
1105     bitstream_put_ui(bs, 0, 1);                                 /* gaps_in_frame_num_value_allowed_flag */
1106
1107     bitstream_put_ue(bs, seq_param->picture_width_in_mbs - 1);  /* pic_width_in_mbs_minus1 */
1108     bitstream_put_ue(bs, seq_param->picture_height_in_mbs - 1); /* pic_height_in_map_units_minus1 */
1109     bitstream_put_ui(bs, seq_param->seq_fields.bits.frame_mbs_only_flag, 1);    /* frame_mbs_only_flag */
1110
1111     if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {
1112         assert(0);
1113     }
1114
1115     bitstream_put_ui(bs, seq_param->seq_fields.bits.direct_8x8_inference_flag, 1);      /* direct_8x8_inference_flag */
1116     bitstream_put_ui(bs, seq_param->frame_cropping_flag, 1);            /* frame_cropping_flag */
1117
1118     if (seq_param->frame_cropping_flag) {
1119         bitstream_put_ue(bs, seq_param->frame_crop_left_offset);        /* frame_crop_left_offset */
1120         bitstream_put_ue(bs, seq_param->frame_crop_right_offset);       /* frame_crop_right_offset */
1121         bitstream_put_ue(bs, seq_param->frame_crop_top_offset);         /* frame_crop_top_offset */
1122         bitstream_put_ue(bs, seq_param->frame_crop_bottom_offset);      /* frame_crop_bottom_offset */
1123     }
1124     
1125     if ( frame_bit_rate < 0 ) {
1126         bitstream_put_ui(bs, 0, 1); /* vui_parameters_present_flag */
1127     } else {
1128         bitstream_put_ui(bs, 1, 1); /* vui_parameters_present_flag */
1129         bitstream_put_ui(bs, 0, 1); /* aspect_ratio_info_present_flag */
1130         bitstream_put_ui(bs, 0, 1); /* overscan_info_present_flag */
1131         bitstream_put_ui(bs, 0, 1); /* video_signal_type_present_flag */
1132         bitstream_put_ui(bs, 0, 1); /* chroma_loc_info_present_flag */
1133         bitstream_put_ui(bs, 1, 1); /* timing_info_present_flag */
1134         {
1135             bitstream_put_ui(bs, 1, 32);
1136             bitstream_put_ui(bs, frame_rate * 2, 32);
1137             bitstream_put_ui(bs, 1, 1);
1138         }
1139         bitstream_put_ui(bs, 1, 1); /* nal_hrd_parameters_present_flag */
1140         {
1141             // hrd_parameters 
1142             bitstream_put_ue(bs, 0);    /* cpb_cnt_minus1 */
1143             bitstream_put_ui(bs, 0, 4); /* bit_rate_scale */
1144             bitstream_put_ui(bs, 2, 4); /* cpb_size_scale */
1145            
1146             /* the frame_bit_rate is in kbps */
1147             bitstream_put_ue(bs, (((frame_bit_rate * 1000)>> 6) - 1)); /* bit_rate_value_minus1[0] */
1148             bitstream_put_ue(bs, ((frame_bit_rate * 8000) >> 6) - 1); /* cpb_size_value_minus1[0] */
1149             bitstream_put_ui(bs, 1, 1);  /* cbr_flag[0] */
1150
1151             /* initial_cpb_removal_delay_length_minus1 */
1152             bitstream_put_ui(bs,
1153                 (avcenc_context.i_initial_cpb_removal_delay_length - 1), 5);
1154             /* cpb_removal_delay_length_minus1 */
1155             bitstream_put_ui(bs,
1156                 (avcenc_context.i_cpb_removal_delay_length - 1), 5);
1157             /* dpb_output_delay_length_minus1 */
1158             bitstream_put_ui(bs,
1159                 (avcenc_context.i_dpb_output_delay_length - 1), 5);
1160             /* time_offset_length  */
1161             bitstream_put_ui(bs,
1162                 (avcenc_context.time_offset_length - 1), 5);
1163         }
1164         bitstream_put_ui(bs, 0, 1);   /* vcl_hrd_parameters_present_flag */
1165         bitstream_put_ui(bs, 0, 1);   /* low_delay_hrd_flag */ 
1166
1167         bitstream_put_ui(bs, 0, 1); /* pic_struct_present_flag */
1168         bitstream_put_ui(bs, 0, 1); /* bitstream_restriction_flag */
1169     }
1170
1171     rbsp_trailing_bits(bs);     /* rbsp_trailing_bits */
1172 }
1173
1174 #if 0
1175 static void build_nal_sps(FILE *avc_fp)
1176 {
1177     bitstream bs;
1178
1179     bitstream_start(&bs);
1180     nal_start_code_prefix(&bs);
1181     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
1182     sps_rbsp(&bs);
1183     bitstream_end(&bs, avc_fp);
1184 }
1185 #endif
1186
1187 static void pps_rbsp(bitstream *bs)
1188 {
1189     VAEncPictureParameterBufferH264 *pic_param = &avcenc_context.pic_param;
1190
1191     bitstream_put_ue(bs, pic_param->pic_parameter_set_id);      /* pic_parameter_set_id */
1192     bitstream_put_ue(bs, pic_param->seq_parameter_set_id);      /* seq_parameter_set_id */
1193
1194     bitstream_put_ui(bs, pic_param->pic_fields.bits.entropy_coding_mode_flag, 1);  /* entropy_coding_mode_flag */
1195
1196     bitstream_put_ui(bs, 0, 1);                         /* pic_order_present_flag: 0 */
1197
1198     bitstream_put_ue(bs, 0);                            /* num_slice_groups_minus1 */
1199
1200     bitstream_put_ue(bs, pic_param->num_ref_idx_l0_active_minus1);      /* num_ref_idx_l0_active_minus1 */
1201     bitstream_put_ue(bs, pic_param->num_ref_idx_l1_active_minus1);      /* num_ref_idx_l1_active_minus1 1 */
1202
1203     bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_pred_flag, 1);     /* weighted_pred_flag: 0 */
1204     bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_bipred_idc, 2);    /* weighted_bipred_idc: 0 */
1205
1206     bitstream_put_se(bs, pic_param->pic_init_qp - 26);  /* pic_init_qp_minus26 */
1207     bitstream_put_se(bs, 0);                            /* pic_init_qs_minus26 */
1208     bitstream_put_se(bs, 0);                            /* chroma_qp_index_offset */
1209
1210     bitstream_put_ui(bs, pic_param->pic_fields.bits.deblocking_filter_control_present_flag, 1); /* deblocking_filter_control_present_flag */
1211     bitstream_put_ui(bs, 0, 1);                         /* constrained_intra_pred_flag */
1212     bitstream_put_ui(bs, 0, 1);                         /* redundant_pic_cnt_present_flag */
1213     
1214     /* more_rbsp_data */
1215     bitstream_put_ui(bs, pic_param->pic_fields.bits.transform_8x8_mode_flag, 1);    /*transform_8x8_mode_flag */
1216     bitstream_put_ui(bs, 0, 1);                         /* pic_scaling_matrix_present_flag */
1217     bitstream_put_se(bs, pic_param->second_chroma_qp_index_offset );    /*second_chroma_qp_index_offset */
1218
1219     rbsp_trailing_bits(bs);
1220 }
1221
1222 #if 0
1223 static void build_nal_pps(FILE *avc_fp)
1224 {
1225     bitstream bs;
1226
1227     bitstream_start(&bs);
1228     nal_start_code_prefix(&bs);
1229     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
1230     pps_rbsp(&bs);
1231     bitstream_end(&bs, avc_fp);
1232 }
1233
1234 static void 
1235 build_header(FILE *avc_fp)
1236 {
1237     build_nal_sps(avc_fp);
1238     build_nal_pps(avc_fp);
1239 }
1240 #endif
1241
1242 static int
1243 build_packed_pic_buffer(unsigned char **header_buffer)
1244 {
1245     bitstream bs;
1246
1247     bitstream_start(&bs);
1248     nal_start_code_prefix(&bs);
1249     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
1250     pps_rbsp(&bs);
1251     bitstream_end(&bs);
1252
1253     *header_buffer = (unsigned char *)bs.buffer;
1254     return bs.bit_offset;
1255 }
1256
1257 static int
1258 build_packed_seq_buffer(unsigned char **header_buffer)
1259 {
1260     bitstream bs;
1261
1262     bitstream_start(&bs);
1263     nal_start_code_prefix(&bs);
1264     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
1265     sps_rbsp(&bs);
1266     bitstream_end(&bs);
1267
1268     *header_buffer = (unsigned char *)bs.buffer;
1269     return bs.bit_offset;
1270 }
1271
1272 static int 
1273 build_packed_idr_sei_buffer_timing(unsigned int init_cpb_removal_delay_length,
1274                                 unsigned int cpb_removal_length,
1275                                 unsigned int dpb_output_length,
1276                                 unsigned char **sei_buffer)
1277 {
1278     unsigned char *byte_buf;
1279     int bp_byte_size, i, pic_byte_size;
1280     unsigned int cpb_removal_delay;
1281
1282     bitstream nal_bs;
1283     bitstream sei_bp_bs, sei_pic_bs;
1284
1285     bitstream_start(&sei_bp_bs);
1286     bitstream_put_ue(&sei_bp_bs, 0);       /*seq_parameter_set_id*/
1287     /* SEI buffer period info */
1288     /* NALHrdBpPresentFlag == 1 */
1289     bitstream_put_ui(&sei_bp_bs, avcenc_context.i_initial_cpb_removal_delay,
1290                      init_cpb_removal_delay_length);
1291     bitstream_put_ui(&sei_bp_bs, avcenc_context.i_initial_cpb_removal_delay_offset,
1292                      init_cpb_removal_delay_length);
1293     if ( sei_bp_bs.bit_offset & 0x7) {
1294         bitstream_put_ui(&sei_bp_bs, 1, 1);
1295     }
1296     bitstream_end(&sei_bp_bs);
1297     bp_byte_size = (sei_bp_bs.bit_offset + 7) / 8;
1298     
1299     /* SEI pic timing info */
1300     bitstream_start(&sei_pic_bs);
1301     /* The info of CPB and DPB delay is controlled by CpbDpbDelaysPresentFlag,
1302      * which is derived as 1 if one of the following conditions is true:
1303      * nal_hrd_parameters_present_flag is present in the bitstream and is equal to 1,
1304      * vcl_hrd_parameters_present_flag is present in the bitstream and is equal to 1,
1305      */
1306     cpb_removal_delay = (avcenc_context.current_cpb_removal - avcenc_context.prev_idr_cpb_removal);
1307     bitstream_put_ui(&sei_pic_bs, cpb_removal_delay, cpb_removal_length); 
1308     bitstream_put_ui(&sei_pic_bs, avcenc_context.current_dpb_removal_delta,
1309                      dpb_output_length);
1310     if ( sei_pic_bs.bit_offset & 0x7) {
1311         bitstream_put_ui(&sei_pic_bs, 1, 1);
1312     }
1313     /* The pic_structure_present_flag determines whether the pic_structure
1314      * info is written into the SEI pic timing info.
1315      * Currently it is set to zero.
1316      */
1317     bitstream_end(&sei_pic_bs);
1318     pic_byte_size = (sei_pic_bs.bit_offset + 7) / 8;
1319     
1320     bitstream_start(&nal_bs);
1321     nal_start_code_prefix(&nal_bs);
1322     nal_header(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI);
1323
1324         /* Write the SEI buffer period data */    
1325     bitstream_put_ui(&nal_bs, 0, 8);
1326     bitstream_put_ui(&nal_bs, bp_byte_size, 8);
1327     
1328     byte_buf = (unsigned char *)sei_bp_bs.buffer;
1329     for(i = 0; i < bp_byte_size; i++) {
1330         bitstream_put_ui(&nal_bs, byte_buf[i], 8);
1331     }
1332     free(byte_buf);
1333         /* write the SEI pic timing data */
1334     bitstream_put_ui(&nal_bs, 0x01, 8);
1335     bitstream_put_ui(&nal_bs, pic_byte_size, 8);
1336     
1337     byte_buf = (unsigned char *)sei_pic_bs.buffer;
1338     for(i = 0; i < pic_byte_size; i++) {
1339         bitstream_put_ui(&nal_bs, byte_buf[i], 8);
1340     }
1341     free(byte_buf);
1342
1343     rbsp_trailing_bits(&nal_bs);
1344     bitstream_end(&nal_bs);
1345
1346     *sei_buffer = (unsigned char *)nal_bs.buffer; 
1347    
1348     return nal_bs.bit_offset;
1349 }
1350
1351 static int
1352 build_packed_sei_pic_timing(unsigned int cpb_removal_length,
1353                                 unsigned int dpb_output_length,
1354                                 unsigned char **sei_buffer)
1355 {
1356     unsigned char *byte_buf;
1357     int i, pic_byte_size;
1358     unsigned int cpb_removal_delay;
1359
1360     bitstream nal_bs;
1361     bitstream sei_pic_bs;
1362
1363     bitstream_start(&sei_pic_bs);
1364     /* The info of CPB and DPB delay is controlled by CpbDpbDelaysPresentFlag,
1365      * which is derived as 1 if one of the following conditions is true:
1366      * nal_hrd_parameters_present_flag is present in the bitstream and is equal to 1,
1367      * vcl_hrd_parameters_present_flag is present in the bitstream and is equal to 1,
1368      */
1369     cpb_removal_delay = (avcenc_context.current_cpb_removal - avcenc_context.current_idr_cpb_removal);
1370     bitstream_put_ui(&sei_pic_bs, cpb_removal_delay, cpb_removal_length);
1371     bitstream_put_ui(&sei_pic_bs, avcenc_context.current_dpb_removal_delta,
1372                      dpb_output_length);
1373     if ( sei_pic_bs.bit_offset & 0x7) {
1374         bitstream_put_ui(&sei_pic_bs, 1, 1);
1375     }
1376
1377     /* The pic_structure_present_flag determines whether the pic_structure
1378      * info is written into the SEI pic timing info.
1379      * Currently it is set to zero.
1380      */
1381     bitstream_end(&sei_pic_bs);
1382     pic_byte_size = (sei_pic_bs.bit_offset + 7) / 8;
1383
1384     bitstream_start(&nal_bs);
1385     nal_start_code_prefix(&nal_bs);
1386     nal_header(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI);
1387
1388         /* write the SEI Pic timing data */
1389     bitstream_put_ui(&nal_bs, 0x01, 8);
1390     bitstream_put_ui(&nal_bs, pic_byte_size, 8);
1391
1392     byte_buf = (unsigned char *)sei_pic_bs.buffer;
1393     for(i = 0; i < pic_byte_size; i++) {
1394         bitstream_put_ui(&nal_bs, byte_buf[i], 8);
1395     }
1396     free(byte_buf);
1397
1398     rbsp_trailing_bits(&nal_bs);
1399     bitstream_end(&nal_bs);
1400
1401     *sei_buffer = (unsigned char *)nal_bs.buffer;
1402
1403     return nal_bs.bit_offset;
1404 }
1405
1406 #if 0
1407 static void 
1408 slice_header(bitstream *bs, int frame_num, int display_frame, int slice_type, int nal_ref_idc, int is_idr)
1409 {
1410     VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
1411     VAEncPictureParameterBufferH264 *pic_param = &avcenc_context.pic_param;
1412     int is_cabac = (pic_param->pic_fields.bits.entropy_coding_mode_flag == ENTROPY_MODE_CABAC);
1413
1414     bitstream_put_ue(bs, 0);                   /* first_mb_in_slice: 0 */
1415     bitstream_put_ue(bs, slice_type);          /* slice_type */
1416     bitstream_put_ue(bs, 0);                   /* pic_parameter_set_id: 0 */
1417     bitstream_put_ui(bs, frame_num & 0x0F, seq_param->seq_fields.bits.log2_max_frame_num_minus4 + 4);    /* frame_num */
1418
1419     /* frame_mbs_only_flag == 1 */
1420     if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {
1421         /* FIXME: */
1422         assert(0);
1423     }
1424
1425     if (is_idr)
1426         bitstream_put_ue(bs, 0);                /* idr_pic_id: 0 */
1427
1428     if (seq_param->seq_fields.bits.pic_order_cnt_type == 0) {
1429         bitstream_put_ui(bs, (display_frame*2) & 0x3F, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 + 4);
1430         /* only support frame */
1431     } else {
1432         /* FIXME: */
1433         assert(0);
1434     }
1435
1436     /* redundant_pic_cnt_present_flag == 0 */
1437     
1438     /* slice type */
1439     if (slice_type == SLICE_TYPE_P) {
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     } else if (slice_type == SLICE_TYPE_B) {
1444         bitstream_put_ui(bs, 1, 1);            /* direct_spatial_mv_pred: 1 */
1445         bitstream_put_ui(bs, 0, 1);            /* num_ref_idx_active_override_flag: 0 */
1446         /* ref_pic_list_reordering */
1447         bitstream_put_ui(bs, 0, 1);            /* ref_pic_list_reordering_flag_l0: 0 */
1448         bitstream_put_ui(bs, 0, 1);            /* ref_pic_list_reordering_flag_l1: 0 */
1449     } 
1450
1451     /* weighted_pred_flag == 0 */
1452
1453     /* dec_ref_pic_marking */
1454     if (nal_ref_idc != 0) {
1455         if ( is_idr) {
1456             bitstream_put_ui(bs, 0, 1);            /* no_output_of_prior_pics_flag: 0 */
1457             bitstream_put_ui(bs, 0, 1);            /* long_term_reference_flag: 0 */
1458         } else {
1459             bitstream_put_ui(bs, 0, 1);            /* adaptive_ref_pic_marking_mode_flag: 0 */
1460         }
1461     }
1462
1463     if (is_cabac && (slice_type != SLICE_TYPE_I))
1464         bitstream_put_ue(bs, 0);               /* cabac_init_idc: 0 */
1465
1466     bitstream_put_se(bs, 0);                   /* slice_qp_delta: 0 */
1467
1468     if (pic_param->pic_fields.bits.deblocking_filter_control_present_flag == 1) {
1469         bitstream_put_ue(bs, 0);               /* disable_deblocking_filter_idc: 0 */
1470         bitstream_put_se(bs, 2);               /* slice_alpha_c0_offset_div2: 2 */
1471         bitstream_put_se(bs, 2);               /* slice_beta_offset_div2: 2 */
1472     }
1473 }
1474
1475 static void 
1476 slice_data(bitstream *bs)
1477 {
1478     VACodedBufferSegment *coded_buffer_segment;
1479     unsigned char *coded_mem;
1480     int i, slice_data_length;
1481     VAStatus va_status;
1482     VASurfaceStatus surface_status;
1483
1484     va_status = vaSyncSurface(va_dpy, surface_ids[avcenc_context.current_input_surface]);
1485     CHECK_VASTATUS(va_status,"vaSyncSurface");
1486
1487     surface_status = 0;
1488     va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[avcenc_context.current_input_surface], &surface_status);
1489     CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
1490
1491     va_status = vaMapBuffer(va_dpy, avcenc_context.codedbuf_buf_id, (void **)(&coded_buffer_segment));
1492     CHECK_VASTATUS(va_status,"vaMapBuffer");
1493     coded_mem = coded_buffer_segment->buf;
1494
1495     slice_data_length = get_coded_bitsteam_length(coded_mem, codedbuf_size);
1496
1497     for (i = 0; i < slice_data_length; i++) {
1498         bitstream_put_ui(bs, *coded_mem, 8);
1499         coded_mem++;
1500     }
1501
1502     vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
1503 }
1504
1505 static void 
1506 build_nal_slice(FILE *avc_fp, int frame_num, int display_frame, int slice_type, int is_idr)
1507 {
1508     bitstream bs;
1509
1510     bitstream_start(&bs);
1511     slice_data(&bs);
1512     bitstream_end(&bs, avc_fp);
1513 }
1514
1515 #endif
1516
1517 static int
1518 store_coded_buffer(FILE *avc_fp, int slice_type)
1519 {
1520     VACodedBufferSegment *coded_buffer_segment;
1521     unsigned char *coded_mem;
1522     int slice_data_length;
1523     VAStatus va_status;
1524     VASurfaceStatus surface_status;
1525     size_t w_items;
1526
1527     va_status = vaSyncSurface(va_dpy, surface_ids[avcenc_context.current_input_surface]);
1528     CHECK_VASTATUS(va_status,"vaSyncSurface");
1529
1530     surface_status = 0;
1531     va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[avcenc_context.current_input_surface], &surface_status);
1532     CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
1533
1534     va_status = vaMapBuffer(va_dpy, avcenc_context.codedbuf_buf_id, (void **)(&coded_buffer_segment));
1535     CHECK_VASTATUS(va_status,"vaMapBuffer");
1536     coded_mem = coded_buffer_segment->buf;
1537
1538     if (coded_buffer_segment->status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK) {
1539         if (slice_type == SLICE_TYPE_I)
1540             avcenc_context.codedbuf_i_size *= 2;
1541         else
1542             avcenc_context.codedbuf_pb_size *= 2;
1543
1544         vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
1545         return -1;
1546     }
1547
1548     slice_data_length = coded_buffer_segment->size;
1549
1550     do {
1551         w_items = fwrite(coded_mem, slice_data_length, 1, avc_fp);
1552     } while (w_items != 1);
1553
1554     vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
1555
1556     return 0;
1557 }
1558
1559 /*
1560  * It is from the h264encode.c but it simplifies something.
1561  * For example: When one frame is encoded as I-frame under the scenario with
1562  * P-B frames, it will be regarded as IDR frame(key-frame) and then new GOP is
1563  * started. If the video clip is encoded as all I-frames, the first frame
1564  * is regarded as IDR and the remaining is regarded as I-frame.
1565  *
1566  */
1567
1568 static void encoding2display_order(
1569     unsigned long long encoding_order,int gop_size,
1570     int ip_period,
1571     unsigned long long *displaying_order,
1572     int *frame_type)
1573 {
1574     int encoding_order_gop = 0;
1575
1576     /* When ip_period is 0, all are I/IDR frames */
1577     if (ip_period == 0) { /* all are I/IDR frames */
1578         if (encoding_order == 0)
1579             *frame_type = FRAME_IDR;
1580         else
1581             *frame_type = SLICE_TYPE_I;
1582
1583         *displaying_order = encoding_order;
1584         return;
1585     }
1586
1587     /* new sequence like
1588      * IDR PPPPP IDRPPPPP
1589      * IDR (PBB)(PBB)(PBB)(PBB) IDR (PBB)(PBB)(PBB)(PBB)
1590      */
1591     encoding_order_gop = encoding_order % gop_size;
1592
1593     if (encoding_order_gop == 0) { /* the first frame */
1594         *frame_type = FRAME_IDR;
1595         *displaying_order = encoding_order;
1596     } else {
1597         int gop_delta;
1598
1599         gop_delta = 1;
1600
1601         if ((ip_period != 1) && ((gop_size - 1) % ip_period)) {
1602             int ipb_size;
1603             ipb_size = (gop_size - 1) / ip_period * ip_period + 1;
1604             if (encoding_order_gop >= ipb_size) {
1605                 gop_delta = ipb_size;
1606                 ip_period = gop_size - ipb_size;
1607             }
1608         }
1609
1610         if (((encoding_order_gop - gop_delta) % ip_period) == 0) { /* P frames */
1611             *frame_type = SLICE_TYPE_P;
1612             *displaying_order = encoding_order + ip_period - 1;
1613         } else {
1614             *frame_type = SLICE_TYPE_B;
1615             *displaying_order = encoding_order - 1;
1616         }
1617     }
1618 }
1619
1620
1621 static void
1622 encode_picture(FILE *yuv_fp, FILE *avc_fp,
1623                int frame_num, int display_num,
1624                int is_idr,
1625                int slice_type, int next_is_bpic,
1626                int next_display_num)
1627 {
1628     VAStatus va_status;
1629     int ret = 0, codedbuf_size;
1630     
1631     begin_picture(yuv_fp, frame_num, display_num, slice_type, is_idr);
1632
1633     //if (next_display_num < frame_number) {
1634     if (1) {
1635         int index;
1636
1637         /* prepare for next frame */
1638         if (avcenc_context.current_input_surface == SID_INPUT_PICTURE_0)
1639             index = SID_INPUT_PICTURE_1;
1640         else
1641             index = SID_INPUT_PICTURE_0;
1642         if ( next_display_num >= frame_number )
1643             next_display_num = frame_number - 1;
1644         fseeko(yuv_fp, (off_t)frame_size * next_display_num, SEEK_SET);
1645
1646         avcenc_context.upload_thread_param.yuv_fp = yuv_fp;
1647         avcenc_context.upload_thread_param.surface_id = surface_ids[index];
1648
1649         avcenc_context.upload_thread_value = pthread_create(&avcenc_context.upload_thread_id,
1650                                                             NULL,
1651                                                             upload_thread_function, 
1652                                                             (void*)&avcenc_context.upload_thread_param);
1653     }
1654
1655     do {
1656         avcenc_destroy_buffers(&avcenc_context.codedbuf_buf_id, 1);
1657         avcenc_destroy_buffers(&avcenc_context.pic_param_buf_id, 1);
1658
1659
1660         if (SLICE_TYPE_I == slice_type) {
1661             codedbuf_size = avcenc_context.codedbuf_i_size;
1662         } else {
1663             codedbuf_size = avcenc_context.codedbuf_pb_size;
1664         }
1665
1666         /* coded buffer */
1667         va_status = vaCreateBuffer(va_dpy,
1668                                    avcenc_context.context_id,
1669                                    VAEncCodedBufferType,
1670                                    codedbuf_size, 1, NULL,
1671                                    &avcenc_context.codedbuf_buf_id);
1672         CHECK_VASTATUS(va_status,"vaCreateBuffer");
1673
1674         /* Update the RefPicList */
1675         update_RefPicList();
1676
1677         /* picture parameter set */
1678         avcenc_update_picture_parameter(slice_type, is_idr);
1679
1680         /* slice parameter */
1681         avcenc_update_slice_parameter(slice_type);
1682
1683         if (avcenc_context.rate_control_method == VA_RC_CBR)
1684                 avcenc_update_sei_param(is_idr);
1685
1686         avcenc_render_picture();
1687
1688         ret = store_coded_buffer(avc_fp, slice_type);
1689     } while (ret);
1690
1691     end_picture(slice_type, next_is_bpic);
1692 }
1693
1694 static void show_help()
1695 {
1696     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");
1697 }
1698
1699 static void avcenc_context_seq_param_init(VAEncSequenceParameterBufferH264 *seq_param,
1700                                           int width, int height)
1701
1702 {
1703     int width_in_mbs = (width + 15) / 16;
1704     int height_in_mbs = (height + 15) / 16;
1705     int frame_cropping_flag = 0;
1706     int frame_crop_bottom_offset = 0;
1707
1708     seq_param->seq_parameter_set_id = 0;
1709     seq_param->level_idc = 41;
1710     seq_param->intra_period = intra_period;
1711     seq_param->intra_idr_period = seq_param->intra_period;
1712     seq_param->ip_period = ip_period;
1713     seq_param->max_num_ref_frames = 4;
1714     seq_param->picture_width_in_mbs = width_in_mbs;
1715     seq_param->picture_height_in_mbs = height_in_mbs;
1716     seq_param->seq_fields.bits.frame_mbs_only_flag = 1;
1717     seq_param->seq_fields.bits.chroma_format_idc = 1;
1718
1719     
1720     if (frame_bit_rate > 0)
1721         seq_param->bits_per_second = 1000 * frame_bit_rate; /* use kbps as input */
1722     else
1723         seq_param->bits_per_second = 0;
1724     
1725     seq_param->time_scale = frame_rate * 2;
1726     seq_param->num_units_in_tick = 1;                   /* Tc = num_units_in_tick / time_sacle */
1727
1728     if (height_in_mbs * 16 - height) {
1729         frame_cropping_flag = 1;
1730         frame_crop_bottom_offset = 
1731             (height_in_mbs * 16 - height) / (2 * (!seq_param->seq_fields.bits.frame_mbs_only_flag + 1));
1732     }
1733
1734     seq_param->frame_cropping_flag = frame_cropping_flag;
1735     seq_param->frame_crop_left_offset = 0;
1736     seq_param->frame_crop_right_offset = 0;
1737     seq_param->frame_crop_top_offset = 0;
1738     seq_param->frame_crop_bottom_offset = frame_crop_bottom_offset;
1739
1740     seq_param->seq_fields.bits.pic_order_cnt_type = 0;
1741     seq_param->seq_fields.bits.direct_8x8_inference_flag = 0;
1742     
1743     seq_param->seq_fields.bits.log2_max_frame_num_minus4 = Log2MaxFrameNum - 4;
1744     seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = Log2MaxPicOrderCntLsb - 4;
1745         
1746     if (frame_bit_rate > 0)
1747         seq_param->vui_parameters_present_flag = 1;     //HRD info located in vui
1748     else
1749         seq_param->vui_parameters_present_flag = 0;
1750 }
1751
1752 static void avcenc_context_pic_param_init(VAEncPictureParameterBufferH264 *pic_param)
1753 {
1754     pic_param->seq_parameter_set_id = 0;
1755     pic_param->pic_parameter_set_id = 0;
1756
1757     pic_param->last_picture = 0;
1758     pic_param->frame_num = 0;
1759     
1760     pic_param->pic_init_qp = (qp_value >= 0 ?  qp_value : 26);
1761     pic_param->num_ref_idx_l0_active_minus1 = 0;
1762     pic_param->num_ref_idx_l1_active_minus1 = 0;
1763
1764     pic_param->pic_fields.bits.idr_pic_flag = 0;
1765     pic_param->pic_fields.bits.reference_pic_flag = 0;
1766     pic_param->pic_fields.bits.entropy_coding_mode_flag = ENTROPY_MODE_CABAC;
1767     pic_param->pic_fields.bits.weighted_pred_flag = 0;
1768     pic_param->pic_fields.bits.weighted_bipred_idc = 0;
1769     
1770     if (avcenc_context.constraint_set_flag & 0x7)
1771         pic_param->pic_fields.bits.transform_8x8_mode_flag = 0;
1772     else
1773         pic_param->pic_fields.bits.transform_8x8_mode_flag = 1;
1774
1775     pic_param->pic_fields.bits.deblocking_filter_control_present_flag = 1;
1776
1777     memset(pic_param->ReferenceFrames, 0xff, 16 * sizeof(VAPictureH264)); /* invalid all */
1778 }
1779
1780 static void avcenc_context_sei_init()
1781 {
1782         /* it comes for the bps defined in SPS */
1783         avcenc_context.i_initial_cpb_removal_delay = 2 * 90000;
1784         avcenc_context.i_initial_cpb_removal_delay_offset = 2 * 90000;
1785
1786         avcenc_context.i_cpb_removal_delay = 2;
1787         avcenc_context.i_initial_cpb_removal_delay_length = 24;
1788         avcenc_context.i_cpb_removal_delay_length = 24;
1789         avcenc_context.i_dpb_output_delay_length = 24;
1790         avcenc_context.time_offset_length = 24;
1791
1792         avcenc_context.prev_idr_cpb_removal = avcenc_context.i_initial_cpb_removal_delay / 90000;
1793         avcenc_context.current_idr_cpb_removal = avcenc_context.prev_idr_cpb_removal;
1794         avcenc_context.current_cpb_removal = 0;
1795         avcenc_context.idr_frame_num = 0;
1796 }
1797
1798 static void avcenc_context_init(int width, int height)
1799 {
1800     int i;
1801     memset(&avcenc_context, 0, sizeof(avcenc_context));
1802     avcenc_context.profile = VAProfileH264Main;
1803
1804     memset(&use_slot, 0, sizeof(use_slot));
1805     switch (avcenc_context.profile) {
1806     case VAProfileH264Baseline:
1807         avcenc_context.constraint_set_flag |= (1 << 0); /* Annex A.2.1 */
1808         break;
1809
1810     case VAProfileH264Main:
1811         avcenc_context.constraint_set_flag |= (1 << 1); /* Annex A.2.2 */
1812         break;
1813
1814     case VAProfileH264High:
1815         avcenc_context.constraint_set_flag |= (1 << 3); /* Annex A.2.4 */
1816         break;
1817         
1818     default:
1819         break;
1820     }
1821         
1822     avcenc_context.seq_param_buf_id = VA_INVALID_ID;
1823     avcenc_context.pic_param_buf_id = VA_INVALID_ID;
1824     avcenc_context.packed_seq_header_param_buf_id = VA_INVALID_ID;
1825     avcenc_context.packed_seq_buf_id = VA_INVALID_ID;
1826     avcenc_context.packed_pic_header_param_buf_id = VA_INVALID_ID;
1827     avcenc_context.packed_pic_buf_id = VA_INVALID_ID;
1828     avcenc_context.codedbuf_buf_id = VA_INVALID_ID;
1829     avcenc_context.misc_parameter_hrd_buf_id = VA_INVALID_ID;
1830     avcenc_context.codedbuf_i_size = width * height;
1831     avcenc_context.codedbuf_pb_size = width * height;
1832     avcenc_context.current_input_surface = SID_INPUT_PICTURE_0;
1833     avcenc_context.upload_thread_value = -1;
1834     avcenc_context.packed_sei_header_param_buf_id = VA_INVALID_ID;
1835     avcenc_context.packed_sei_buf_id = VA_INVALID_ID;
1836
1837     if (qp_value == -1)
1838         avcenc_context.rate_control_method = VA_RC_CBR;
1839     else if (qp_value == -2)
1840         avcenc_context.rate_control_method = VA_RC_VBR;
1841     else {
1842         assert(qp_value >= 0 && qp_value <= 51);
1843         avcenc_context.rate_control_method = VA_RC_CQP;
1844     }
1845
1846     for (i = 0; i < MAX_SLICES; i++) {
1847         avcenc_context.slice_param_buf_id[i] = VA_INVALID_ID;
1848     }
1849
1850     avcenc_context_seq_param_init(&avcenc_context.seq_param, width, height);
1851     avcenc_context_pic_param_init(&avcenc_context.pic_param);
1852     if (avcenc_context.rate_control_method == VA_RC_CBR)
1853         avcenc_context_sei_init();
1854 }
1855
1856 int main(int argc, char *argv[])
1857 {
1858     int f;
1859     FILE *yuv_fp;
1860     FILE *avc_fp;
1861     off_t file_size;
1862     int mode_value;
1863     struct timeval tpstart,tpend; 
1864     float  timeuse;
1865
1866     va_init_display_args(&argc, argv);
1867
1868     if(argc < 5) {
1869         show_help();
1870         return -1;
1871     }
1872
1873     picture_width = atoi(argv[1]);
1874     picture_height = atoi(argv[2]);
1875     picture_width_in_mbs = (picture_width + 15) / 16;
1876     picture_height_in_mbs = (picture_height + 15) / 16;
1877
1878     if (argc > 5) {
1879         char o;
1880
1881         optind = 5;
1882
1883         while ((o = getopt_long_only(argc, argv, "", longopts, NULL)) != -1) {
1884             switch (o) {
1885             case 1:     // qp
1886                 frame_bit_rate = -1;
1887                 qp_value = atoi(optarg);
1888
1889                 if (qp_value > 51)
1890                     qp_value = 51;
1891
1892                 if (qp_value < 0)
1893                     qp_value = 0;
1894
1895                 break;
1896
1897             case 2:     // fb
1898                 qp_value = -1;
1899                 frame_bit_rate = atoi(optarg);
1900
1901                 if (frame_bit_rate <= 0) {
1902                     show_help();
1903
1904                     return -1;
1905                 }
1906
1907                 break;
1908
1909             case 3:     // mode
1910                 mode_value = atoi(optarg);
1911
1912                 if (mode_value == 0)
1913                     ip_period = 0;
1914                 else if (mode_value == 1)
1915                     ip_period = 1;
1916                 else if (mode_value == 2)
1917                     /* Hack mechanism before adding the parameter of B-frame number */
1918                     ip_period = 2;
1919                 else {
1920                     printf("mode_value = %d\n", mode_value);
1921                     show_help();
1922                     return -1;
1923                 }
1924
1925                 break;
1926
1927             case 4:     // low-power mode
1928                 select_entrypoint = VAEntrypointEncSliceLP;
1929                 break;
1930
1931             default:
1932                 show_help();
1933                 return -1;
1934             }
1935         }
1936     } else
1937         qp_value = 28;                          //default const QP mode
1938
1939     yuv_fp = fopen(argv[3],"rb");
1940     if ( yuv_fp == NULL){
1941         printf("Can't open input YUV file\n");
1942         return -1;
1943     }
1944     fseeko(yuv_fp, (off_t)0, SEEK_END);
1945     file_size = ftello(yuv_fp);
1946     frame_size = picture_width * picture_height +  ((picture_width * picture_height) >> 1) ;
1947
1948     if ( (file_size < frame_size) || (file_size % frame_size) ) {
1949         fclose(yuv_fp);
1950         printf("The YUV file's size is not correct\n");
1951         return -1;
1952     }
1953     frame_number = file_size / frame_size;
1954     fseeko(yuv_fp, (off_t)0, SEEK_SET);
1955
1956     avc_fp = fopen(argv[4], "wb");      
1957     if ( avc_fp == NULL) {
1958         fclose(yuv_fp);
1959         printf("Can't open output avc file\n");
1960         return -1;
1961     }   
1962     gettimeofday(&tpstart,NULL);        
1963     avcenc_context_init(picture_width, picture_height);
1964     create_encode_pipe();
1965     alloc_encode_resource(yuv_fp);
1966
1967     enc_frame_number = 0;
1968     for ( f = 0; f < frame_number; f++) {               //picture level loop
1969         unsigned long long next_frame_display;
1970         int next_frame_type;
1971
1972         enc_frame_number = f;
1973
1974         encoding2display_order(enc_frame_number, intra_period, ip_period,
1975                                &current_frame_display, &current_frame_type);
1976
1977         encoding2display_order(enc_frame_number + 1, intra_period, ip_period,
1978                                &next_frame_display, &next_frame_type);
1979
1980         if (current_frame_type == FRAME_IDR) {
1981             numShortTerm = 0;
1982             current_frame_num = 0;
1983             memset(&use_slot, 0, sizeof(use_slot));
1984             current_IDR_display = current_frame_display;
1985             if (avcenc_context.rate_control_method == VA_RC_CBR) {
1986                 unsigned long long frame_interval;
1987
1988                 frame_interval = enc_frame_number - avcenc_context.idr_frame_num;
1989
1990                 /* Based on the H264 spec the removal time of the IDR access
1991                  * unit is derived as the following:
1992                  * the removal time of previous IDR unit + Tc * cpb_removal_delay(n)
1993                  */
1994                 avcenc_context.current_cpb_removal = avcenc_context.prev_idr_cpb_removal +
1995                                 frame_interval * 2;
1996                 avcenc_context.idr_frame_num = enc_frame_number;
1997                 avcenc_context.current_idr_cpb_removal = avcenc_context.current_cpb_removal;
1998                 if (ip_period)
1999                     avcenc_context.current_dpb_removal_delta = (ip_period + 1) * 2;
2000                 else
2001                     avcenc_context.current_dpb_removal_delta = 2;
2002             }
2003         } else {
2004             if (avcenc_context.rate_control_method == VA_RC_CBR) {
2005                 unsigned long long frame_interval;
2006
2007                 frame_interval = enc_frame_number - avcenc_context.idr_frame_num;
2008
2009                 /* Based on the H264 spec the removal time of the non-IDR access
2010                  * unit is derived as the following:
2011                  * the removal time of current IDR unit + Tc * cpb_removal_delay(n)
2012                  */
2013                 avcenc_context.current_cpb_removal = avcenc_context.current_idr_cpb_removal +
2014                                 frame_interval * 2;
2015                 if (current_frame_type == SLICE_TYPE_I ||
2016                     current_frame_type == SLICE_TYPE_P) {
2017                     if (ip_period)
2018                         avcenc_context.current_dpb_removal_delta = (ip_period + 1) * 2;
2019                     else
2020                         avcenc_context.current_dpb_removal_delta = 2;
2021                 } else
2022                    avcenc_context.current_dpb_removal_delta = 2;
2023             }
2024         }
2025
2026         /* use the simple mechanism to calc the POC */
2027         current_poc = (current_frame_display - current_IDR_display) * 2;
2028
2029         encode_picture(yuv_fp, avc_fp, frame_number, current_frame_display,
2030                       (current_frame_type == FRAME_IDR) ? 1 : 0,
2031                       (current_frame_type == FRAME_IDR) ? SLICE_TYPE_I : current_frame_type,
2032                       (next_frame_type == SLICE_TYPE_B) ? 1 : 0,
2033                 next_frame_display);
2034         if ((current_frame_type == FRAME_IDR) &&
2035             (avcenc_context.rate_control_method == VA_RC_CBR)) {
2036            /* after one IDR frame is written, it needs to update the
2037             * prev_idr_cpb_removal for next IDR
2038             */
2039            avcenc_context.prev_idr_cpb_removal = avcenc_context.current_idr_cpb_removal;
2040         }
2041         printf("\r %d/%d ...", f, frame_number);
2042         fflush(stdout);
2043     }
2044
2045     gettimeofday(&tpend,NULL);
2046     timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+ tpend.tv_usec-tpstart.tv_usec;
2047     timeuse/=1000000;
2048     printf("\ndone!\n");
2049     printf("encode %d frames in %f secondes, FPS is %.1f\n",frame_number, timeuse, frame_number/timeuse);
2050     release_encode_resource();
2051     destory_encode_pipe();
2052
2053     fclose(yuv_fp);
2054     fclose(avc_fp);
2055
2056     return 0;
2057 }