OSDN Git Service

test/encode/avcenc: Wait upload thread exiting before release driver resource.
[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_display.h"
49
50 #define NAL_REF_IDC_NONE        0
51 #define NAL_REF_IDC_LOW         1
52 #define NAL_REF_IDC_MEDIUM      2
53 #define NAL_REF_IDC_HIGH        3
54
55 #define NAL_NON_IDR             1
56 #define NAL_IDR                 5
57 #define NAL_SPS                 7
58 #define NAL_PPS                 8
59
60 #define SLICE_TYPE_P            0
61 #define SLICE_TYPE_B            1
62 #define SLICE_TYPE_I            2
63
64 #define ENTROPY_MODE_CAVLC      0
65 #define ENTROPY_MODE_CABAC      1
66
67 #define PROFILE_IDC_BASELINE    66
68 #define PROFILE_IDC_MAIN        77
69 #define PROFILE_IDC_HIGH        100
70
71 #define CHECK_VASTATUS(va_status,func)                                  \
72     if (va_status != VA_STATUS_SUCCESS) {                               \
73         fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
74         exit(1);                                                        \
75     }
76
77 static VADisplay va_dpy;
78
79 static int picture_width, picture_width_in_mbs;
80 static int picture_height, picture_height_in_mbs;
81 static int frame_size;
82 static unsigned char *newImageBuffer = 0;
83
84 static int qp_value = 26;
85
86 static int intra_period = 30;
87 static int pb_period = 5;
88 static int frame_bit_rate = -1;
89
90 #define BR_CBR          0
91 #define BR_VBR          1
92 #define BR_CQP          2
93
94 #define MAX_SLICES      32
95
96 static int
97 build_packed_pic_buffer(unsigned char **header_buffer);
98
99 static int
100 build_packed_seq_buffer(unsigned char **header_buffer);
101
102 struct upload_thread_param
103 {
104     FILE *yuv_fp;
105     VASurfaceID surface_id;
106 };
107
108 static void 
109 upload_yuv_to_surface(FILE *yuv_fp, VASurfaceID surface_id);
110
111 struct packed_data_format
112 {
113     unsigned int length_in_bits;
114     unsigned char flag;
115     unsigned char num_skip_bytes;
116     unsigned char pad[2];
117 };
118
119 struct {
120     VAEncSequenceParameterBufferH264Ext seq_param;
121     VAEncPictureParameterBufferH264Ext pic_param;
122     VAEncSliceParameterBufferH264Ext slice_param[MAX_SLICES];
123     VAEncH264DecRefPicMarkingBuffer dec_ref_pic_marking;
124     VAContextID context_id;
125     VAConfigID config_id;
126     VABufferID seq_param_buf_id;                /* Sequence level parameter */
127     VABufferID pic_param_buf_id;                /* Picture level parameter */
128     VABufferID slice_param_buf_id[MAX_SLICES];  /* Slice level parameter, multil slices */
129     VABufferID dec_ref_pic_marking_buf_id;
130     VABufferID codedbuf_buf_id;                 /* Output buffer, compressed data */
131     VABufferID packed_seq_buf_id;
132     VABufferID packed_pic_buf_id;
133     int num_slices;
134     int codedbuf_i_size;
135     int codedbuf_pb_size;
136     int current_input_surface;
137     struct upload_thread_param upload_thread_param;
138     pthread_t upload_thread_id;
139     int upload_thread_value;
140 } avcenc_context;
141
142 static void create_encode_pipe()
143 {
144     VAEntrypoint entrypoints[5];
145     int num_entrypoints,slice_entrypoint;
146     VAConfigAttrib attrib[2];
147     int major_ver, minor_ver;
148     VAStatus va_status;
149
150     va_dpy = va_open_display();
151     va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
152     CHECK_VASTATUS(va_status, "vaInitialize");
153
154     vaQueryConfigEntrypoints(va_dpy, VAProfileH264Baseline, entrypoints, 
155                              &num_entrypoints);
156
157     for (slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypoint++) {
158         if (entrypoints[slice_entrypoint] == VAEntrypointEncSlice)
159             break;
160     }
161
162     if (slice_entrypoint == num_entrypoints) {
163         /* not find Slice entry point */
164         assert(0);
165     }
166
167     /* find out the format for the render target, and rate control mode */
168     attrib[0].type = VAConfigAttribRTFormat;
169     attrib[1].type = VAConfigAttribRateControl;
170     vaGetConfigAttributes(va_dpy, VAProfileH264Baseline, VAEntrypointEncSlice,
171                           &attrib[0], 2);
172
173     if ((attrib[0].value & VA_RT_FORMAT_YUV420) == 0) {
174         /* not find desired YUV420 RT format */
175         assert(0);
176     }
177
178     if ((attrib[1].value & VA_RC_VBR) == 0) {
179         /* Can't find matched RC mode */
180         printf("VBR mode doesn't found, exit\n");
181         assert(0);
182     }
183
184     attrib[0].value = VA_RT_FORMAT_YUV420; /* set to desired RT format */
185     attrib[1].value = VA_RC_VBR; /* set to desired RC mode */
186
187     va_status = vaCreateConfig(va_dpy, VAProfileH264Baseline, VAEntrypointEncSlice,
188                                &attrib[0], 2,&avcenc_context.config_id);
189     CHECK_VASTATUS(va_status, "vaCreateConfig");
190
191     /* Create a context for this decode pipe */
192     va_status = vaCreateContext(va_dpy, avcenc_context.config_id,
193                                 picture_width, picture_height,
194                                 VA_PROGRESSIVE, 
195                                 0, 0,
196                                 &avcenc_context.context_id);
197     CHECK_VASTATUS(va_status, "vaCreateContext");
198 }
199
200 static void destory_encode_pipe()
201 {
202     vaDestroyContext(va_dpy,avcenc_context.context_id);
203     vaDestroyConfig(va_dpy,avcenc_context.config_id);
204     vaTerminate(va_dpy);
205     va_close_display(va_dpy);
206 }
207
208 /***************************************************
209  *
210  *  The encode pipe resource define 
211  *
212  ***************************************************/
213 #define SID_INPUT_PICTURE_0                     0
214 #define SID_INPUT_PICTURE_1                     1
215 #define SID_REFERENCE_PICTURE_L0                2
216 #define SID_REFERENCE_PICTURE_L1                3
217 #define SID_RECON_PICTURE                       4
218 #define SID_NUMBER                              SID_RECON_PICTURE + 1
219 static  VASurfaceID surface_ids[SID_NUMBER];
220
221 static int frame_number;
222 static int enc_frame_number;
223
224 /***************************************************/
225
226 static void *
227 upload_thread_function(void *data)
228 {
229     struct upload_thread_param *param = data;
230
231     upload_yuv_to_surface(param->yuv_fp, param->surface_id);
232
233     return NULL;
234 }
235
236 static void alloc_encode_resource(FILE *yuv_fp)
237 {
238     VAStatus va_status;
239
240     // Create surface
241     va_status = vaCreateSurfaces(va_dpy, picture_width, picture_height,
242                                  VA_RT_FORMAT_YUV420, SID_NUMBER, &surface_ids[0]);
243     CHECK_VASTATUS(va_status, "vaCreateSurfaces");
244
245     newImageBuffer = (unsigned char *)malloc(frame_size);
246
247     /* firstly upload YUV data to SID_INPUT_PICTURE_1 */
248     avcenc_context.upload_thread_param.yuv_fp = yuv_fp;
249     avcenc_context.upload_thread_param.surface_id = surface_ids[SID_INPUT_PICTURE_1];
250
251     avcenc_context.upload_thread_value = pthread_create(&avcenc_context.upload_thread_id,
252                                                         NULL,
253                                                         upload_thread_function, 
254                                                         (void*)&avcenc_context.upload_thread_param);
255 }
256
257 static void release_encode_resource()
258 {
259     pthread_join(avcenc_context.upload_thread_id, NULL);
260     free(newImageBuffer);
261
262     // Release all the surfaces resource
263     vaDestroySurfaces(va_dpy, &surface_ids[0], SID_NUMBER);     
264 }
265
266 static void avcenc_update_picture_parameter(int slice_type, int frame_num, int display_num, int is_idr)
267 {
268     VAEncPictureParameterBufferH264Ext *pic_param;
269     VAStatus va_status;
270
271     // Picture level
272     pic_param = &avcenc_context.pic_param;
273     pic_param->CurrPic.picture_id = surface_ids[SID_RECON_PICTURE];
274     pic_param->CurrPic.TopFieldOrderCnt = display_num * 2;
275     pic_param->ReferenceFrames[0].picture_id = surface_ids[SID_REFERENCE_PICTURE_L0];
276     pic_param->ReferenceFrames[1].picture_id = surface_ids[SID_REFERENCE_PICTURE_L1];
277     pic_param->ReferenceFrames[2].picture_id = VA_INVALID_ID;
278     assert(avcenc_context.codedbuf_buf_id != VA_INVALID_ID);
279     pic_param->CodedBuf = avcenc_context.codedbuf_buf_id;
280     pic_param->frame_num = frame_num;
281     pic_param->pic_fields.bits.idr_pic_flag = !!is_idr;
282     pic_param->pic_fields.bits.reference_pic_flag = (slice_type != SLICE_TYPE_B);
283
284     va_status = vaCreateBuffer(va_dpy,
285                                avcenc_context.context_id,
286                                VAEncPictureParameterBufferExtType,
287                                sizeof(*pic_param), 1, pic_param,
288                                &avcenc_context.pic_param_buf_id);
289     CHECK_VASTATUS(va_status,"vaCreateBuffer");
290 }
291
292 static void upload_yuv_to_surface(FILE *yuv_fp, VASurfaceID surface_id)
293 {
294     VAImage surface_image;
295     VAStatus va_status;
296     void *surface_p = NULL;
297     unsigned char *y_src, *u_src, *v_src;
298     unsigned char *y_dst, *u_dst, *v_dst;
299     int y_size = picture_width * picture_height;
300     int u_size = (picture_width >> 1) * (picture_height >> 1);
301     int row, col;
302     size_t n_items;
303
304     do {
305         n_items = fread(newImageBuffer, frame_size, 1, yuv_fp);
306     } while (n_items != 1);
307
308     va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
309     CHECK_VASTATUS(va_status,"vaDeriveImage");
310
311     vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
312     assert(VA_STATUS_SUCCESS == va_status);
313         
314     y_src = newImageBuffer;
315     u_src = newImageBuffer + y_size; /* UV offset for NV12 */
316     v_src = newImageBuffer + y_size + u_size;
317
318     y_dst = surface_p + surface_image.offsets[0];
319     u_dst = surface_p + surface_image.offsets[1]; /* UV offset for NV12 */
320     v_dst = surface_p + surface_image.offsets[2];
321
322     /* Y plane */
323     for (row = 0; row < surface_image.height; row++) {
324         memcpy(y_dst, y_src, surface_image.width);
325         y_dst += surface_image.pitches[0];
326         y_src += picture_width;
327     }
328
329     if (surface_image.format.fourcc == VA_FOURCC_NV12) { /* UV plane */
330         for (row = 0; row < surface_image.height / 2; row++) {
331             for (col = 0; col < surface_image.width / 2; col++) {
332                 u_dst[col * 2] = u_src[col];
333                 u_dst[col * 2 + 1] = v_src[col];
334             }
335
336             u_dst += surface_image.pitches[1];
337             u_src += (picture_width / 2);
338             v_src += (picture_width / 2);
339         }
340     } else {
341         /* FIXME: fix this later */
342         assert(0);
343     }
344
345     vaUnmapBuffer(va_dpy, surface_image.buf);
346     vaDestroyImage(va_dpy, surface_image.image_id);
347 }
348
349 static void avcenc_update_slice_parameter(int slice_type)
350 {
351     VAEncSliceParameterBufferH264Ext *slice_param;
352     VAStatus va_status;
353     int i;
354
355     // Slice level
356     i = 0;
357     slice_param = &avcenc_context.slice_param[i];
358     slice_param->start_row_number = 0;
359     slice_param->slice_height = picture_height_in_mbs/16; /* Measured by MB */
360     slice_param->pic_parameter_set_id = 0;
361     slice_param->slice_type = slice_type;
362     slice_param->direct_spatial_mv_pred_flag = 0;
363     slice_param->num_ref_idx_l0_active_minus1 = 0;      /* FIXME: ??? */
364     slice_param->num_ref_idx_l1_active_minus1 = 0;
365     slice_param->cabac_init_idc = 0;
366     slice_param->slice_qp_delta = 0;
367     slice_param->disable_deblocking_filter_idc = 0;
368     slice_param->slice_alpha_c0_offset_div2 = 2;
369     slice_param->slice_beta_offset_div2 = 2;
370     slice_param->idr_pic_id = 0;
371
372     /* ref_pic_list_modification() */
373     slice_param->ref_pic_list_modification_flag_l0 = 0;
374     slice_param->ref_pic_list_modification_flag_l1 = 0;
375     /* FIXME: fill other fields */
376
377     va_status = vaCreateBuffer(va_dpy,
378                                avcenc_context.context_id,
379                                VAEncSliceParameterBufferExtType,
380                                sizeof(*slice_param), 1, slice_param,
381                                &avcenc_context.slice_param_buf_id[i]);
382     CHECK_VASTATUS(va_status,"vaCreateBuffer");;
383
384     i++;
385
386     avcenc_context.num_slices = i;
387 }
388
389 static int begin_picture(FILE *yuv_fp, int frame_num, int display_num, int slice_type, int is_idr)
390 {
391     VAStatus va_status;
392
393     if (avcenc_context.upload_thread_value != 0) {
394         fprintf(stderr, "FATAL error!!!\n");
395         exit(1);
396     }
397     
398     pthread_join(avcenc_context.upload_thread_id, NULL);
399
400     avcenc_context.upload_thread_value = -1;
401
402     if (avcenc_context.current_input_surface == SID_INPUT_PICTURE_0)
403         avcenc_context.current_input_surface = SID_INPUT_PICTURE_1;
404     else
405         avcenc_context.current_input_surface = SID_INPUT_PICTURE_0;
406
407     if (frame_num == 0) {
408         unsigned char *packed_seq_buffer = NULL, *packed_pic_buffer = NULL;
409         int seq_length, pic_length;
410
411         assert(slice_type == SLICE_TYPE_I);
412         seq_length = build_packed_seq_buffer(&packed_seq_buffer);
413         va_status = vaCreateBuffer(va_dpy,
414                                    avcenc_context.context_id,
415                                    VAEncPackedSequenceParameterBufferType,
416                                    (seq_length + 7) / 8, 1, packed_seq_buffer,
417                                    &avcenc_context.packed_seq_buf_id);
418         CHECK_VASTATUS(va_status,"vaCreateBuffer");;
419
420         pic_length = build_packed_pic_buffer(&packed_pic_buffer);
421         va_status = vaCreateBuffer(va_dpy,
422                                    avcenc_context.context_id,
423                                    VAEncPackedPictureParameterBufferType,
424                                    (pic_length + 7) / 8 , 1, packed_pic_buffer,
425                                    &avcenc_context.packed_pic_buf_id);
426         CHECK_VASTATUS(va_status,"vaCreateBuffer");;
427
428         free(packed_seq_buffer);
429         free(packed_pic_buffer);
430     }
431
432     /* sequence parameter set */
433     VAEncSequenceParameterBufferH264Ext *seq_param = &avcenc_context.seq_param;
434     va_status = vaCreateBuffer(va_dpy,
435                                avcenc_context.context_id,
436                                VAEncSequenceParameterBufferExtType,
437                                sizeof(*seq_param), 1, seq_param,
438                                &avcenc_context.seq_param_buf_id);
439     CHECK_VASTATUS(va_status,"vaCreateBuffer");;
440
441     /* slice parameter */
442     avcenc_update_slice_parameter(slice_type);
443
444     return 0;
445 }
446
447 int avcenc_render_picture()
448 {
449     VAStatus va_status;
450     VABufferID va_buffers[8];
451     unsigned int num_va_buffers = 0;
452
453     va_buffers[num_va_buffers++] = avcenc_context.seq_param_buf_id;
454     va_buffers[num_va_buffers++] = avcenc_context.pic_param_buf_id;
455
456     if (avcenc_context.dec_ref_pic_marking_buf_id != VA_INVALID_ID)
457         va_buffers[num_va_buffers++] = avcenc_context.dec_ref_pic_marking_buf_id;
458
459     if (avcenc_context.packed_seq_buf_id != VA_INVALID_ID)
460         va_buffers[num_va_buffers++] = avcenc_context.packed_seq_buf_id;
461
462     if (avcenc_context.packed_pic_buf_id != VA_INVALID_ID)
463         va_buffers[num_va_buffers++] = avcenc_context.packed_pic_buf_id;
464
465     va_status = vaBeginPicture(va_dpy,
466                                avcenc_context.context_id,
467                                surface_ids[avcenc_context.current_input_surface]);
468     CHECK_VASTATUS(va_status,"vaBeginPicture");
469
470     va_status = vaRenderPicture(va_dpy,
471                                 avcenc_context.context_id,
472                                 va_buffers,
473                                 num_va_buffers);
474     CHECK_VASTATUS(va_status,"vaRenderPicture");
475
476     va_status = vaRenderPicture(va_dpy,
477                                 avcenc_context.context_id,
478                                 &avcenc_context.slice_param_buf_id[0],
479                                 avcenc_context.num_slices);
480     CHECK_VASTATUS(va_status,"vaRenderPicture");
481
482     va_status = vaEndPicture(va_dpy, avcenc_context.context_id);
483     CHECK_VASTATUS(va_status,"vaEndPicture");
484
485     return 0;
486 }
487
488 static int avcenc_destroy_buffers(VABufferID *va_buffers, unsigned int num_va_buffers)
489 {
490     VAStatus va_status;
491     unsigned int i;
492
493     for (i = 0; i < num_va_buffers; i++) {
494         if (va_buffers[i] != VA_INVALID_ID) {
495             va_status = vaDestroyBuffer(va_dpy, va_buffers[i]);
496             CHECK_VASTATUS(va_status,"vaDestroyBuffer");
497             va_buffers[i] = VA_INVALID_ID;
498         }
499     }
500
501     return 0;
502 }
503
504 static void end_picture(int slice_type, int next_is_bpic)
505 {
506     VABufferID tempID;
507
508     /* Prepare for next picture */
509     tempID = surface_ids[SID_RECON_PICTURE];  
510
511     if (slice_type != SLICE_TYPE_B) {
512         if (next_is_bpic) {
513             surface_ids[SID_RECON_PICTURE] = surface_ids[SID_REFERENCE_PICTURE_L1]; 
514             surface_ids[SID_REFERENCE_PICTURE_L1] = tempID;     
515         } else {
516             surface_ids[SID_RECON_PICTURE] = surface_ids[SID_REFERENCE_PICTURE_L0]; 
517             surface_ids[SID_REFERENCE_PICTURE_L0] = tempID;
518         }
519     } else {
520         if (!next_is_bpic) {
521             surface_ids[SID_RECON_PICTURE] = surface_ids[SID_REFERENCE_PICTURE_L0]; 
522             surface_ids[SID_REFERENCE_PICTURE_L0] = surface_ids[SID_REFERENCE_PICTURE_L1];
523             surface_ids[SID_REFERENCE_PICTURE_L1] = tempID;
524         }
525     }
526
527     avcenc_destroy_buffers(&avcenc_context.seq_param_buf_id, 1);
528     avcenc_destroy_buffers(&avcenc_context.pic_param_buf_id, 1);
529     avcenc_destroy_buffers(&avcenc_context.dec_ref_pic_marking_buf_id, 1);
530     avcenc_destroy_buffers(&avcenc_context.packed_seq_buf_id, 1);
531     avcenc_destroy_buffers(&avcenc_context.packed_pic_buf_id, 1);
532     avcenc_destroy_buffers(&avcenc_context.slice_param_buf_id[0], avcenc_context.num_slices);
533     avcenc_destroy_buffers(&avcenc_context.codedbuf_buf_id, 1);
534     memset(avcenc_context.slice_param, 0, sizeof(avcenc_context.slice_param));
535     avcenc_context.num_slices = 0;
536 }
537
538 #define BITSTREAM_ALLOCATE_STEPPING     4096
539
540 struct __bitstream {
541     unsigned int *buffer;
542     int bit_offset;
543     int max_size_in_dword;
544 };
545
546 typedef struct __bitstream bitstream;
547
548 #if 0
549 static int 
550 get_coded_bitsteam_length(unsigned char *buffer, int buffer_length)
551 {
552     int i;
553
554     for (i = 0; i < buffer_length - 3; i++) {
555         if (!buffer[i] &&
556             !buffer[i + 1] &&
557             !buffer[i + 2] &&
558             !buffer[i + 3])
559             break;
560     }
561
562     return i;
563 }
564 #endif
565
566 static unsigned int 
567 va_swap32(unsigned int val)
568 {
569     unsigned char *pval = (unsigned char *)&val;
570
571     return ((pval[0] << 24)     |
572             (pval[1] << 16)     |
573             (pval[2] << 8)      |
574             (pval[3] << 0));
575 }
576
577 static void
578 bitstream_start(bitstream *bs)
579 {
580     bs->max_size_in_dword = BITSTREAM_ALLOCATE_STEPPING;
581     bs->buffer = calloc(bs->max_size_in_dword * sizeof(int), 1);
582     bs->bit_offset = sizeof(struct packed_data_format) * 8; /* the first 64 bits used for format */
583 }
584
585 static void
586 bitstream_end(bitstream *bs)
587 {
588     int pos = (bs->bit_offset >> 5);
589     int bit_offset = (bs->bit_offset & 0x1f);
590     int bit_left = 32 - bit_offset;
591     struct packed_data_format *format;
592
593     if (bit_offset) {
594         bs->buffer[pos] = va_swap32((bs->buffer[pos] << bit_left));
595     }
596
597     format = (struct packed_data_format *)bs->buffer;
598     format->length_in_bits = bs->bit_offset - sizeof(struct packed_data_format) * 8;
599     format->flag |= 1;
600     format->num_skip_bytes = 5; /* ignore start code & nal type for emulation prevetion check */
601 }
602  
603 static void
604 bitstream_put_ui(bitstream *bs, unsigned int val, int size_in_bits)
605 {
606     int pos = (bs->bit_offset >> 5);
607     int bit_offset = (bs->bit_offset & 0x1f);
608     int bit_left = 32 - bit_offset;
609
610     if (!size_in_bits)
611         return;
612
613     bs->bit_offset += size_in_bits;
614
615     if (bit_left > size_in_bits) {
616         bs->buffer[pos] = (bs->buffer[pos] << size_in_bits | val);
617     } else {
618         size_in_bits -= bit_left;
619         bs->buffer[pos] = (bs->buffer[pos] << bit_left) | (val >> size_in_bits);
620         bs->buffer[pos] = va_swap32(bs->buffer[pos]);
621
622         if (pos + 1 == bs->max_size_in_dword) {
623             bs->max_size_in_dword += BITSTREAM_ALLOCATE_STEPPING;
624             bs->buffer = realloc(bs->buffer, bs->max_size_in_dword * sizeof(unsigned int));
625         }
626
627         bs->buffer[pos + 1] = val;
628     }
629 }
630
631 static void
632 bitstream_put_ue(bitstream *bs, unsigned int val)
633 {
634     int size_in_bits = 0;
635     int tmp_val = ++val;
636
637     while (tmp_val) {
638         tmp_val >>= 1;
639         size_in_bits++;
640     }
641
642     bitstream_put_ui(bs, 0, size_in_bits - 1); // leading zero
643     bitstream_put_ui(bs, val, size_in_bits);
644 }
645
646 static void
647 bitstream_put_se(bitstream *bs, int val)
648 {
649     unsigned int new_val;
650
651     if (val <= 0)
652         new_val = -2 * val;
653     else
654         new_val = 2 * val - 1;
655
656     bitstream_put_ue(bs, new_val);
657 }
658
659 static void
660 bitstream_byte_aligning(bitstream *bs, int bit)
661 {
662     int bit_offset = (bs->bit_offset & 0x7);
663     int bit_left = 8 - bit_offset;
664     int new_val;
665
666     if (!bit_offset)
667         return;
668
669     assert(bit == 0 || bit == 1);
670
671     if (bit)
672         new_val = (1 << bit_left) - 1;
673     else
674         new_val = 0;
675
676     bitstream_put_ui(bs, new_val, bit_left);
677 }
678
679 static void 
680 rbsp_trailing_bits(bitstream *bs)
681 {
682     bitstream_put_ui(bs, 1, 1);
683     bitstream_byte_aligning(bs, 0);
684 }
685
686 static void nal_start_code_prefix(bitstream *bs)
687 {
688     bitstream_put_ui(bs, 0x00000001, 32);
689 }
690
691 static void nal_header(bitstream *bs, int nal_ref_idc, int nal_unit_type)
692 {
693     bitstream_put_ui(bs, 0, 1);                /* forbidden_zero_bit: 0 */
694     bitstream_put_ui(bs, nal_ref_idc, 2);
695     bitstream_put_ui(bs, nal_unit_type, 5);
696 }
697
698 static void sps_rbsp(bitstream *bs)
699 {
700     VAEncSequenceParameterBufferH264Ext *seq_param = &avcenc_context.seq_param;
701
702     bitstream_put_ui(bs, seq_param->profile_idc, 8);    /* profile_idc */
703     bitstream_put_ui(bs, 0, 1);                         /* constraint_set0_flag */
704     bitstream_put_ui(bs, 1, 1);                         /* constraint_set1_flag */
705     bitstream_put_ui(bs, 0, 1);                         /* constraint_set2_flag */
706     bitstream_put_ui(bs, 0, 1);                         /* constraint_set3_flag */
707     bitstream_put_ui(bs, 0, 4);                         /* reserved_zero_4bits */
708     bitstream_put_ui(bs, seq_param->level_idc, 8);      /* level_idc */
709     bitstream_put_ue(bs, seq_param->seq_parameter_set_id);      /* seq_parameter_set_id */
710
711     if (seq_param->profile_idc >= PROFILE_IDC_HIGH) {
712         /* FIXME: fix for high profile */
713         assert(0);
714     }
715
716     bitstream_put_ue(bs, seq_param->log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
717     bitstream_put_ue(bs, seq_param->pic_order_cnt_type);        /* pic_order_cnt_type */
718
719     if (seq_param->pic_order_cnt_type == 0)
720         bitstream_put_ue(bs, seq_param->log2_max_pic_order_cnt_lsb_minus4);     /* log2_max_pic_order_cnt_lsb_minus4 */
721     else {
722         assert(0);
723     }
724
725     bitstream_put_ue(bs, seq_param->max_num_ref_frames);        /* num_ref_frames */
726     bitstream_put_ui(bs, 0, 1);                                 /* gaps_in_frame_num_value_allowed_flag */
727
728     bitstream_put_ue(bs, seq_param->picture_width_in_mbs - 1);  /* pic_width_in_mbs_minus1 */
729     bitstream_put_ue(bs, seq_param->picture_height_in_mbs - 1); /* pic_height_in_map_units_minus1 */
730     bitstream_put_ui(bs, seq_param->frame_mbs_only_flag, 1);    /* frame_mbs_only_flag */
731
732     if (!seq_param->frame_mbs_only_flag) {
733         assert(0);
734     }
735
736     bitstream_put_ui(bs, seq_param->direct_8x8_inference_flag, 1);      /* direct_8x8_inference_flag */
737     bitstream_put_ui(bs, seq_param->frame_cropping_flag, 1);            /* frame_cropping_flag */
738
739     if (seq_param->frame_cropping_flag) {
740         bitstream_put_ue(bs, seq_param->frame_crop_left_offset);        /* frame_crop_left_offset */
741         bitstream_put_ue(bs, seq_param->frame_crop_right_offset);       /* frame_crop_right_offset */
742         bitstream_put_ue(bs, seq_param->frame_crop_top_offset);         /* frame_crop_top_offset */
743         bitstream_put_ue(bs, seq_param->frame_crop_bottom_offset);      /* frame_crop_bottom_offset */
744     }
745
746     bitstream_put_ui(bs, 0, 1); /* vui_parameters_present_flag */
747     rbsp_trailing_bits(bs);     /* rbsp_trailing_bits */
748 }
749
750 #if 0
751 static void build_nal_sps(FILE *avc_fp)
752 {
753     bitstream bs;
754
755     bitstream_start(&bs);
756     nal_start_code_prefix(&bs);
757     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
758     sps_rbsp(&bs);
759     bitstream_end(&bs, avc_fp);
760 }
761 #endif
762
763 static void pps_rbsp(bitstream *bs)
764 {
765     VAEncPictureParameterBufferH264Ext *pic_param = &avcenc_context.pic_param;
766
767     bitstream_put_ue(bs, pic_param->pic_parameter_set_id);      /* pic_parameter_set_id */
768     bitstream_put_ue(bs, pic_param->seq_parameter_set_id);      /* seq_parameter_set_id */
769
770     bitstream_put_ui(bs, pic_param->pic_fields.bits.entropy_coding_mode_flag, 1);  /* entropy_coding_mode_flag */
771
772     bitstream_put_ui(bs, 0, 1);                         /* pic_order_present_flag: 0 */
773
774     bitstream_put_ue(bs, 0);                            /* num_slice_groups_minus1 */
775
776     bitstream_put_ue(bs, pic_param->num_ref_idx_l0_active_minus1);      /* num_ref_idx_l0_active_minus1 */
777     bitstream_put_ue(bs, pic_param->num_ref_idx_l1_active_minus1);      /* num_ref_idx_l1_active_minus1 1 */
778
779     bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_pred_flag, 1);     /* weighted_pred_flag: 0 */
780     bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_bipred_idc, 2);    /* weighted_bipred_idc: 0 */
781
782     bitstream_put_se(bs, pic_param->pic_init_qp - 26);  /* pic_init_qp_minus26 */
783     bitstream_put_se(bs, 0);                            /* pic_init_qs_minus26 */
784     bitstream_put_se(bs, 0);                            /* chroma_qp_index_offset */
785
786     bitstream_put_ui(bs, pic_param->pic_fields.bits.deblocking_filter_control_present_flag, 1); /* deblocking_filter_control_present_flag */
787     bitstream_put_ui(bs, 0, 1);                         /* constrained_intra_pred_flag */
788     bitstream_put_ui(bs, 0, 1);                         /* redundant_pic_cnt_present_flag */
789
790     rbsp_trailing_bits(bs);
791 }
792
793 #if 0
794 static void build_nal_pps(FILE *avc_fp)
795 {
796     bitstream bs;
797
798     bitstream_start(&bs);
799     nal_start_code_prefix(&bs);
800     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
801     pps_rbsp(&bs);
802     bitstream_end(&bs, avc_fp);
803 }
804
805 static void 
806 build_header(FILE *avc_fp)
807 {
808     build_nal_sps(avc_fp);
809     build_nal_pps(avc_fp);
810 }
811 #endif
812
813 static int
814 build_packed_pic_buffer(unsigned char **header_buffer)
815 {
816     bitstream bs;
817
818     bitstream_start(&bs);
819     nal_start_code_prefix(&bs);
820     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
821     pps_rbsp(&bs);
822     bitstream_end(&bs);
823
824     *header_buffer = (unsigned char *)bs.buffer;
825     return bs.bit_offset;
826 }
827
828 static int
829 build_packed_seq_buffer(unsigned char **header_buffer)
830 {
831     bitstream bs;
832
833     bitstream_start(&bs);
834     nal_start_code_prefix(&bs);
835     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
836     sps_rbsp(&bs);
837     bitstream_end(&bs);
838
839     *header_buffer = (unsigned char *)bs.buffer;
840     return bs.bit_offset;
841 }
842
843
844 #if 0
845 static void 
846 slice_header(bitstream *bs, int frame_num, int display_frame, int slice_type, int nal_ref_idc, int is_idr)
847 {
848     VAEncSequenceParameterBufferH264Ext *seq_param = &avcenc_context.seq_param;
849     VAEncPictureParameterBufferH264Ext *pic_param = &avcenc_context.pic_param;
850     int is_cabac = (pic_param->pic_fields.bits.entropy_coding_mode_flag == ENTROPY_MODE_CABAC);
851
852     bitstream_put_ue(bs, 0);                   /* first_mb_in_slice: 0 */
853     bitstream_put_ue(bs, slice_type);          /* slice_type */
854     bitstream_put_ue(bs, 0);                   /* pic_parameter_set_id: 0 */
855     bitstream_put_ui(bs, frame_num & 0x0F, seq_param->log2_max_frame_num_minus4 + 4);    /* frame_num */
856
857     /* frame_mbs_only_flag == 1 */
858     if (!seq_param->frame_mbs_only_flag) {
859         /* FIXME: */
860         assert(0);
861     }
862
863     if (is_idr)
864         bitstream_put_ue(bs, 0);                /* idr_pic_id: 0 */
865
866     if (seq_param->pic_order_cnt_type == 0) {
867         bitstream_put_ui(bs, (display_frame*2) & 0x3F, seq_param->log2_max_pic_order_cnt_lsb_minus4 + 4);
868         /* only support frame */
869     } else {
870         /* FIXME: */
871         assert(0);
872     }
873
874     /* redundant_pic_cnt_present_flag == 0 */
875     
876     /* slice type */
877     if (slice_type == SLICE_TYPE_P) {
878         bitstream_put_ui(bs, 0, 1);            /* num_ref_idx_active_override_flag: 0 */
879         /* ref_pic_list_reordering */
880         bitstream_put_ui(bs, 0, 1);            /* ref_pic_list_reordering_flag_l0: 0 */
881     } else if (slice_type == SLICE_TYPE_B) {
882         bitstream_put_ui(bs, 1, 1);            /* direct_spatial_mv_pred: 1 */
883         bitstream_put_ui(bs, 0, 1);            /* num_ref_idx_active_override_flag: 0 */
884         /* ref_pic_list_reordering */
885         bitstream_put_ui(bs, 0, 1);            /* ref_pic_list_reordering_flag_l0: 0 */
886         bitstream_put_ui(bs, 0, 1);            /* ref_pic_list_reordering_flag_l1: 0 */
887     } 
888
889     /* weighted_pred_flag == 0 */
890
891     /* dec_ref_pic_marking */
892     if (nal_ref_idc != 0) {
893         if ( is_idr) {
894             bitstream_put_ui(bs, 0, 1);            /* no_output_of_prior_pics_flag: 0 */
895             bitstream_put_ui(bs, 0, 1);            /* long_term_reference_flag: 0 */
896         } else {
897             bitstream_put_ui(bs, 0, 1);            /* adaptive_ref_pic_marking_mode_flag: 0 */
898         }
899     }
900
901     if (is_cabac && (slice_type != SLICE_TYPE_I))
902         bitstream_put_ue(bs, 0);               /* cabac_init_idc: 0 */
903
904     bitstream_put_se(bs, 0);                   /* slice_qp_delta: 0 */
905
906     if (pic_param->pic_fields.bits.deblocking_filter_control_present_flag == 1) {
907         bitstream_put_ue(bs, 0);               /* disable_deblocking_filter_idc: 0 */
908         bitstream_put_se(bs, 2);               /* slice_alpha_c0_offset_div2: 2 */
909         bitstream_put_se(bs, 2);               /* slice_beta_offset_div2: 2 */
910     }
911 }
912
913 static void 
914 slice_data(bitstream *bs)
915 {
916     VACodedBufferSegment *coded_buffer_segment;
917     unsigned char *coded_mem;
918     int i, slice_data_length;
919     VAStatus va_status;
920     VASurfaceStatus surface_status;
921
922     va_status = vaSyncSurface(va_dpy, surface_ids[avcenc_context.current_input_surface]);
923     CHECK_VASTATUS(va_status,"vaSyncSurface");
924
925     surface_status = 0;
926     va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[avcenc_context.current_input_surface], &surface_status);
927     CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
928
929     va_status = vaMapBuffer(va_dpy, avcenc_context.codedbuf_buf_id, (void **)(&coded_buffer_segment));
930     CHECK_VASTATUS(va_status,"vaMapBuffer");
931     coded_mem = coded_buffer_segment->buf;
932
933     slice_data_length = get_coded_bitsteam_length(coded_mem, codedbuf_size);
934
935     for (i = 0; i < slice_data_length; i++) {
936         bitstream_put_ui(bs, *coded_mem, 8);
937         coded_mem++;
938     }
939
940     vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
941 }
942
943 static void 
944 build_nal_slice(FILE *avc_fp, int frame_num, int display_frame, int slice_type, int is_idr)
945 {
946     bitstream bs;
947
948     bitstream_start(&bs);
949     slice_data(&bs);
950     bitstream_end(&bs, avc_fp);
951 }
952
953 #endif
954
955 static int
956 store_coded_buffer(FILE *avc_fp, int slice_type)
957 {
958     VACodedBufferSegment *coded_buffer_segment;
959     unsigned char *coded_mem;
960     int slice_data_length;
961     VAStatus va_status;
962     VASurfaceStatus surface_status;
963     size_t w_items;
964
965     va_status = vaSyncSurface(va_dpy, surface_ids[avcenc_context.current_input_surface]);
966     CHECK_VASTATUS(va_status,"vaSyncSurface");
967
968     surface_status = 0;
969     va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[avcenc_context.current_input_surface], &surface_status);
970     CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
971
972     va_status = vaMapBuffer(va_dpy, avcenc_context.codedbuf_buf_id, (void **)(&coded_buffer_segment));
973     CHECK_VASTATUS(va_status,"vaMapBuffer");
974     coded_mem = coded_buffer_segment->buf;
975
976     if (coded_buffer_segment->status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK) {
977         if (slice_type == SLICE_TYPE_I)
978             avcenc_context.codedbuf_i_size *= 2;
979         else
980             avcenc_context.codedbuf_pb_size *= 2;
981
982         vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
983         return -1;
984     }
985
986     slice_data_length = coded_buffer_segment->size;
987
988     do {
989         w_items = fwrite(coded_mem, slice_data_length, 1, avc_fp);
990     } while (w_items != 1);
991
992     if (slice_type == SLICE_TYPE_I) {
993         if (avcenc_context.codedbuf_i_size > slice_data_length * 3 / 2) {
994             avcenc_context.codedbuf_i_size = slice_data_length * 3 / 2;
995         }
996         
997         if (avcenc_context.codedbuf_pb_size < slice_data_length) {
998             avcenc_context.codedbuf_pb_size = slice_data_length;
999         }
1000     } else {
1001         if (avcenc_context.codedbuf_pb_size > slice_data_length * 3 / 2) {
1002             avcenc_context.codedbuf_pb_size = slice_data_length * 3 / 2;
1003         }
1004     }
1005
1006     vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
1007
1008     return 0;
1009 }
1010
1011 static void
1012 encode_picture(FILE *yuv_fp, FILE *avc_fp,
1013                int frame_num, int display_num,
1014                int is_idr,
1015                int slice_type, int next_is_bpic,
1016                int next_display_num)
1017 {
1018     VAStatus va_status;
1019     int ret = 0, codedbuf_size;
1020     
1021     begin_picture(yuv_fp, frame_num, display_num, slice_type, is_idr);
1022
1023     //if (next_display_num < frame_number) {
1024     if (1) {
1025         int index;
1026
1027         /* prepare for next frame */
1028         if (avcenc_context.current_input_surface == SID_INPUT_PICTURE_0)
1029             index = SID_INPUT_PICTURE_1;
1030         else
1031             index = SID_INPUT_PICTURE_0;
1032         if ( next_display_num >= frame_number )
1033             next_display_num = frame_number - 1;
1034         fseek(yuv_fp, frame_size * next_display_num, SEEK_SET);
1035
1036         avcenc_context.upload_thread_param.yuv_fp = yuv_fp;
1037         avcenc_context.upload_thread_param.surface_id = surface_ids[index];
1038
1039         avcenc_context.upload_thread_value = pthread_create(&avcenc_context.upload_thread_id,
1040                                                             NULL,
1041                                                             upload_thread_function, 
1042                                                             (void*)&avcenc_context.upload_thread_param);
1043     }
1044
1045     do {
1046         avcenc_destroy_buffers(&avcenc_context.codedbuf_buf_id, 1);
1047         avcenc_destroy_buffers(&avcenc_context.pic_param_buf_id, 1);
1048
1049
1050         if (SLICE_TYPE_I == slice_type) {
1051             codedbuf_size = avcenc_context.codedbuf_i_size;
1052         } else {
1053             codedbuf_size = avcenc_context.codedbuf_pb_size;
1054         }
1055
1056         /* coded buffer */
1057         va_status = vaCreateBuffer(va_dpy,
1058                                    avcenc_context.context_id,
1059                                    VAEncCodedBufferType,
1060                                    codedbuf_size, 1, NULL,
1061                                    &avcenc_context.codedbuf_buf_id);
1062         CHECK_VASTATUS(va_status,"vaCreateBuffer");
1063
1064         /* picture parameter set */
1065         avcenc_update_picture_parameter(slice_type, frame_num, display_num, is_idr);
1066
1067         avcenc_render_picture();
1068
1069         ret = store_coded_buffer(avc_fp, slice_type);
1070     } while (ret);
1071
1072     end_picture(slice_type, next_is_bpic);
1073 }
1074
1075 static void encode_pb_pictures(FILE *yuv_fp, FILE *avc_fp, int f, int nbframes, int next_f)
1076 {
1077     int i;
1078     encode_picture(yuv_fp, avc_fp,
1079                    enc_frame_number, f + nbframes,
1080                    0,
1081                    SLICE_TYPE_P, 1, f);
1082
1083     for( i = 0; i < nbframes - 1; i++) {
1084         encode_picture(yuv_fp, avc_fp,
1085                        enc_frame_number + 1, f + i,
1086                        0,
1087                        SLICE_TYPE_B, 1, f + i + 1);
1088     }
1089     
1090     encode_picture(yuv_fp, avc_fp,
1091                    enc_frame_number + 1, f + nbframes - 1,
1092                    0,
1093                    SLICE_TYPE_B, 0, next_f);
1094 }
1095
1096 static void show_help()
1097 {
1098     printf("Usage: avnenc <width> <height> <input_yuvfile> <output_avcfile> [qp=qpvalue|fb=framebitrate] [mode=0(I frames only)/1(I and P frames)/2(I, P and B frames)\n");
1099 }
1100
1101 static void avcenc_context_seq_param_init(VAEncSequenceParameterBufferH264Ext *seq_param,
1102                                           int width, int height)
1103
1104 {
1105     int width_in_mbs = (width + 15) / 16;
1106     int height_in_mbs = (height + 15) / 16;
1107     int frame_cropping_flag = 0;
1108     int frame_crop_bottom_offset = 0;
1109
1110     seq_param->seq_parameter_set_id = 0;
1111     seq_param->profile_idc = PROFILE_IDC_MAIN;
1112     seq_param->level_idc = 41;
1113     seq_param->intra_period = intra_period;
1114     seq_param->ip_period = 0;   /* FIXME: ??? */
1115     seq_param->max_num_ref_frames = 4;
1116     seq_param->picture_width_in_mbs = width_in_mbs;
1117     seq_param->picture_height_in_mbs = height_in_mbs;
1118     seq_param->frame_mbs_only_flag = 1;
1119     seq_param->target_usage = 1;
1120     
1121     /* 0:CBR, 1:VBR, 2:Constant QP */
1122     if (qp_value == -1)
1123         seq_param->rate_control_method = BR_CBR;
1124     else if (qp_value == -2)
1125         seq_param->rate_control_method = BR_VBR;
1126     else {
1127         assert(qp_value >= 0 && qp_value <= 51);
1128         seq_param->rate_control_method = BR_CQP;
1129     }
1130
1131     if (frame_bit_rate > 0)
1132         seq_param->bits_per_second = 30 * frame_bit_rate;
1133     else
1134         seq_param->bits_per_second = 0;
1135
1136     if (seq_param->rate_control_method == BR_VBR) {
1137         seq_param->max_bits_per_second = 0;     /* FIXME: set it later */
1138         seq_param->min_bits_per_second = 0;
1139     }
1140
1141     seq_param->initial_hrd_buffer_fullness = 0; /* FIXME: ??? */
1142     seq_param->hrd_buffer_size = 0;             /* FIXME: ??? */
1143     seq_param->time_scale = 900;
1144     seq_param->num_units_in_tick = 15;
1145
1146     if (height_in_mbs * 16 - height) {
1147         frame_cropping_flag = 1;
1148         frame_crop_bottom_offset = 
1149             (height_in_mbs * 16 - height) / (2 * (!seq_param->frame_mbs_only_flag + 1));
1150     }
1151
1152     seq_param->frame_cropping_flag = frame_cropping_flag;
1153     seq_param->frame_crop_left_offset = 0;
1154     seq_param->frame_crop_right_offset = 0;
1155     seq_param->frame_crop_top_offset = 0;
1156     seq_param->frame_crop_bottom_offset = frame_crop_bottom_offset;
1157
1158     seq_param->pic_order_cnt_type = 0;
1159     seq_param->direct_8x8_inference_flag = 0;
1160     
1161     seq_param->log2_max_frame_num_minus4 = 0;
1162     seq_param->log2_max_pic_order_cnt_lsb_minus4 = 2;
1163
1164     seq_param->vui_flag = 0;
1165 }
1166
1167 static void avcenc_context_pic_param_init(VAEncPictureParameterBufferH264Ext *pic_param)
1168 {
1169     pic_param->seq_parameter_set_id = 0;
1170     pic_param->pic_parameter_set_id = 0;
1171
1172     pic_param->last_picture = 0;
1173     pic_param->frame_num = 0;
1174     pic_param->coding_type = 0;
1175     
1176     pic_param->pic_init_qp = (qp_value >= 0 ?  qp_value : 26);
1177     pic_param->num_ref_idx_l0_active_minus1 = 0;
1178     pic_param->num_ref_idx_l1_active_minus1 = 0;
1179
1180     pic_param->pic_fields.bits.idr_pic_flag = 0;
1181     pic_param->pic_fields.bits.reference_pic_flag = 0;
1182     pic_param->pic_fields.bits.entropy_coding_mode_flag = ENTROPY_MODE_CABAC;
1183     pic_param->pic_fields.bits.weighted_pred_flag = 0;
1184     pic_param->pic_fields.bits.weighted_bipred_idc = 0;
1185     pic_param->pic_fields.bits.transform_8x8_mode_flag = 0;
1186     pic_param->pic_fields.bits.deblocking_filter_control_present_flag = 1;
1187 }
1188
1189 static void avcenc_context_init(int width, int height)
1190 {
1191     int i;
1192     memset(&avcenc_context, 0, sizeof(avcenc_context));
1193     avcenc_context.seq_param_buf_id = VA_INVALID_ID;
1194     avcenc_context.pic_param_buf_id = VA_INVALID_ID;
1195     avcenc_context.dec_ref_pic_marking_buf_id = VA_INVALID_ID;
1196     avcenc_context.packed_seq_buf_id = VA_INVALID_ID;
1197     avcenc_context.packed_pic_buf_id = VA_INVALID_ID;
1198     avcenc_context.codedbuf_buf_id = VA_INVALID_ID;
1199     avcenc_context.codedbuf_i_size = width * height;
1200     avcenc_context.codedbuf_pb_size = 0;
1201     avcenc_context.current_input_surface = SID_INPUT_PICTURE_0;
1202     avcenc_context.upload_thread_value = -1;
1203
1204     for (i = 0; i < MAX_SLICES; i++) {
1205         avcenc_context.slice_param_buf_id[i] = VA_INVALID_ID;
1206     }
1207
1208     avcenc_context_seq_param_init(&avcenc_context.seq_param, width, height);
1209     avcenc_context_pic_param_init(&avcenc_context.pic_param);
1210 }
1211
1212 int main(int argc, char *argv[])
1213 {
1214     int f;
1215     FILE *yuv_fp;
1216     FILE *avc_fp;
1217     long file_size;
1218     int i_frame_only=0,i_p_frame_only=1;
1219     int mode_value;
1220     struct timeval tpstart,tpend; 
1221     float  timeuse;
1222
1223     va_init_display_args(&argc, argv);
1224
1225     //TODO may be we should using option analytics library
1226     if(argc != 5 && argc != 6 && argc != 7) {
1227         show_help();
1228         return -1;
1229     }
1230
1231     picture_width = atoi(argv[1]);
1232     picture_height = atoi(argv[2]);
1233     picture_width_in_mbs = (picture_width + 15) / 16;
1234     picture_height_in_mbs = (picture_height + 15) / 16;
1235
1236     if (argc == 6 || argc == 7) {
1237         qp_value = -1;
1238         sscanf(argv[5], "qp=%d", &qp_value);
1239         if ( qp_value == -1 ) {
1240             frame_bit_rate = -1;
1241             sscanf(argv[5], "fb=%d", &frame_bit_rate);
1242             if (  frame_bit_rate == -1 ) {
1243                 show_help();
1244                 return -1;
1245             }
1246         } else if (qp_value > 51) {
1247             qp_value = 51;
1248         } else if (qp_value < 0) {
1249             qp_value = 0;
1250         }
1251     } else
1252         qp_value = 28;                          //default const QP mode
1253
1254     if (argc == 7) {
1255         sscanf(argv[6], "mode=%d", &mode_value);
1256         if ( mode_value == 0 ) {
1257                 i_frame_only = 1;
1258                 i_p_frame_only = 0;
1259         }
1260         else if ( mode_value == 1) {
1261                 i_frame_only = 0;
1262                 i_p_frame_only = 1;
1263         }
1264         else if ( mode_value == 2 ) {
1265                 i_frame_only = 0;
1266                 i_p_frame_only = 0;
1267         }
1268         else {
1269                 printf("mode_value=%d\n",mode_value);
1270                 show_help();
1271                 return -1;
1272         }
1273     }
1274
1275     yuv_fp = fopen(argv[3],"rb");
1276     if ( yuv_fp == NULL){
1277         printf("Can't open input YUV file\n");
1278         return -1;
1279     }
1280     fseek(yuv_fp,0l, SEEK_END);
1281     file_size = ftell(yuv_fp);
1282     frame_size = picture_width * picture_height +  ((picture_width * picture_height) >> 1) ;
1283
1284     if ( (file_size < frame_size) || (file_size % frame_size) ) {
1285         fclose(yuv_fp);
1286         printf("The YUV file's size is not correct\n");
1287         return -1;
1288     }
1289     frame_number = file_size / frame_size;
1290     fseek(yuv_fp, 0l, SEEK_SET);
1291
1292     avc_fp = fopen(argv[4], "wb");      
1293     if ( avc_fp == NULL) {
1294         fclose(yuv_fp);
1295         printf("Can't open output avc file\n");
1296         return -1;
1297     }   
1298     gettimeofday(&tpstart,NULL);        
1299     avcenc_context_init(picture_width, picture_height);
1300     create_encode_pipe();
1301     alloc_encode_resource(yuv_fp);
1302
1303     enc_frame_number = 0;
1304     for ( f = 0; f < frame_number; ) {          //picture level loop
1305         static int const frame_type_pattern[][2] = { {SLICE_TYPE_I,1}, 
1306                                                      {SLICE_TYPE_P,3}, {SLICE_TYPE_P,3},{SLICE_TYPE_P,3},
1307                                                      {SLICE_TYPE_P,3}, {SLICE_TYPE_P,3},{SLICE_TYPE_P,3},
1308                                                      {SLICE_TYPE_P,3}, {SLICE_TYPE_P,3},{SLICE_TYPE_P,3},
1309                                                      {SLICE_TYPE_P,2} };
1310
1311         if ( i_frame_only ) {
1312             encode_picture(yuv_fp, avc_fp,enc_frame_number, f, f==0, SLICE_TYPE_I, 0, f+1);
1313             f++;
1314             enc_frame_number++;
1315         } else if ( i_p_frame_only ) {
1316             if ( (f % intra_period) == 0 ) {
1317                 encode_picture(yuv_fp, avc_fp,enc_frame_number, f, f==0, SLICE_TYPE_I, 0, f+1);
1318                 f++;
1319                 enc_frame_number++;
1320             } else {
1321                 encode_picture(yuv_fp, avc_fp,enc_frame_number, f, f==0, SLICE_TYPE_P, 0, f+1);
1322                 f++;
1323                 enc_frame_number++;
1324             }
1325         } else { // follow the i,p,b pattern
1326             static int fcurrent = 0;
1327             int fnext;
1328             
1329             fcurrent = fcurrent % (sizeof(frame_type_pattern)/sizeof(int[2]));
1330             fnext = (fcurrent+1) % (sizeof(frame_type_pattern)/sizeof(int[2]));
1331             
1332             if ( frame_type_pattern[fcurrent][0] == SLICE_TYPE_I ) {
1333                 encode_picture(yuv_fp, avc_fp,enc_frame_number, f, f==0, SLICE_TYPE_I, 0, 
1334                         f+frame_type_pattern[fnext][1]);
1335                 f++;
1336                 enc_frame_number++;
1337             } else {
1338                 encode_pb_pictures(yuv_fp, avc_fp, f, frame_type_pattern[fcurrent][1]-1, 
1339                         f + frame_type_pattern[fcurrent][1] + frame_type_pattern[fnext][1] -1 );
1340                 f += frame_type_pattern[fcurrent][1];
1341                 enc_frame_number++;
1342             }
1343  
1344             fcurrent++;
1345         }
1346         printf("\r %d/%d ...", f+1, frame_number);
1347         fflush(stdout);
1348     }
1349
1350     gettimeofday(&tpend,NULL);
1351     timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+ tpend.tv_usec-tpstart.tv_usec;
1352     timeuse/=1000000;
1353     printf("\ndone!\n");
1354     printf("encode %d frames in %f secondes, FPS is %.1f\n",frame_number, timeuse, frame_number/timeuse);
1355     release_encode_resource();
1356     destory_encode_pipe();
1357
1358     fclose(yuv_fp);
1359     fclose(avc_fp);
1360
1361     return 0;
1362 }