Home | History | Annotate | Download | only in encode
      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 ENTROPY_MODE_CAVLC      0
     67 #define ENTROPY_MODE_CABAC      1
     68 
     69 #define PROFILE_IDC_BASELINE    66
     70 #define PROFILE_IDC_MAIN        77
     71 #define PROFILE_IDC_HIGH        100
     72 
     73 #define CHECK_VASTATUS(va_status,func)                                  \
     74     if (va_status != VA_STATUS_SUCCESS) {                               \
     75         fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
     76         exit(1);                                                        \
     77     }
     78 
     79 static VADisplay va_dpy;
     80 
     81 static int picture_width, picture_width_in_mbs;
     82 static int picture_height, picture_height_in_mbs;
     83 static int frame_size;
     84 static unsigned char *newImageBuffer = 0;
     85 
     86 static int qp_value = 26;
     87 
     88 static int intra_period = 30;
     89 static int pb_period = 5;
     90 static int frame_bit_rate = -1;
     91 
     92 #define MAX_SLICES      32
     93 
     94 static int
     95 build_packed_pic_buffer(unsigned char **header_buffer);
     96 
     97 static int
     98 build_packed_seq_buffer(unsigned char **header_buffer);
     99 
    100 static int
    101 build_packed_sei_buffer_timing(unsigned int init_cpb_removal_length,
    102 				unsigned int init_cpb_removal_delay,
    103 				unsigned int init_cpb_removal_delay_offset,
    104 				unsigned int cpb_removal_length,
    105 				unsigned int cpb_removal_delay,
    106 				unsigned int dpb_output_length,
    107 				unsigned int dpb_output_delay,
    108 				unsigned char **sei_buffer);
    109 
    110 struct upload_thread_param
    111 {
    112     FILE *yuv_fp;
    113     VASurfaceID surface_id;
    114 };
    115 
    116 static void
    117 upload_yuv_to_surface(FILE *yuv_fp, VASurfaceID surface_id);
    118 
    119 static struct {
    120     VAProfile profile;
    121     int constraint_set_flag;
    122     VAEncSequenceParameterBufferH264 seq_param;
    123     VAEncPictureParameterBufferH264 pic_param;
    124     VAEncSliceParameterBufferH264 slice_param[MAX_SLICES];
    125     VAContextID context_id;
    126     VAConfigID config_id;
    127     VABufferID seq_param_buf_id;                /* Sequence level parameter */
    128     VABufferID pic_param_buf_id;                /* Picture level parameter */
    129     VABufferID slice_param_buf_id[MAX_SLICES];  /* Slice level parameter, multil slices */
    130     VABufferID codedbuf_buf_id;                 /* Output buffer, compressed data */
    131     VABufferID packed_seq_header_param_buf_id;
    132     VABufferID packed_seq_buf_id;
    133     VABufferID packed_pic_header_param_buf_id;
    134     VABufferID packed_pic_buf_id;
    135     VABufferID packed_sei_header_param_buf_id;   /* the SEI buffer */
    136     VABufferID packed_sei_buf_id;
    137     VABufferID misc_parameter_hrd_buf_id;
    138 
    139     int num_slices;
    140     int codedbuf_i_size;
    141     int codedbuf_pb_size;
    142     int current_input_surface;
    143     int rate_control_method;
    144     struct upload_thread_param upload_thread_param;
    145     pthread_t upload_thread_id;
    146     int upload_thread_value;
    147     int i_initial_cpb_removal_delay;
    148     int i_initial_cpb_removal_delay_length;
    149     int i_cpb_removal_delay;
    150     int i_cpb_removal_delay_length;
    151     int i_dpb_output_delay_length;
    152 } avcenc_context;
    153 
    154 static  VAPictureH264 ReferenceFrames[16], RefPicList0[32], RefPicList1[32];
    155 
    156 static void create_encode_pipe()
    157 {
    158     VAEntrypoint entrypoints[5];
    159     int num_entrypoints,slice_entrypoint;
    160     VAConfigAttrib attrib[2];
    161     int major_ver, minor_ver;
    162     VAStatus va_status;
    163 
    164     va_dpy = va_open_display();
    165     va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
    166     CHECK_VASTATUS(va_status, "vaInitialize");
    167 
    168     vaQueryConfigEntrypoints(va_dpy, avcenc_context.profile, entrypoints,
    169                              &num_entrypoints);
    170 
    171     for	(slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypoint++) {
    172         if (entrypoints[slice_entrypoint] == VAEntrypointEncSlice)
    173             break;
    174     }
    175 
    176     if (slice_entrypoint == num_entrypoints) {
    177         /* not find Slice entry point */
    178         assert(0);
    179     }
    180 
    181     /* find out the format for the render target, and rate control mode */
    182     attrib[0].type = VAConfigAttribRTFormat;
    183     attrib[1].type = VAConfigAttribRateControl;
    184     vaGetConfigAttributes(va_dpy, avcenc_context.profile, VAEntrypointEncSlice,
    185                           &attrib[0], 2);
    186 
    187     if ((attrib[0].value & VA_RT_FORMAT_YUV420) == 0) {
    188         /* not find desired YUV420 RT format */
    189         assert(0);
    190     }
    191 
    192     if ((attrib[1].value & avcenc_context.rate_control_method) == 0) {
    193         /* Can't find matched RC mode */
    194         printf("Can't find the desired RC mode, exit\n");
    195         assert(0);
    196     }
    197 
    198     attrib[0].value = VA_RT_FORMAT_YUV420; /* set to desired RT format */
    199     attrib[1].value = avcenc_context.rate_control_method; /* set to desired RC mode */
    200 
    201     va_status = vaCreateConfig(va_dpy, avcenc_context.profile, VAEntrypointEncSlice,
    202                                &attrib[0], 2,&avcenc_context.config_id);
    203     CHECK_VASTATUS(va_status, "vaCreateConfig");
    204 
    205     /* Create a context for this decode pipe */
    206     va_status = vaCreateContext(va_dpy, avcenc_context.config_id,
    207                                 picture_width, picture_height,
    208                                 VA_PROGRESSIVE,
    209                                 0, 0,
    210                                 &avcenc_context.context_id);
    211     CHECK_VASTATUS(va_status, "vaCreateContext");
    212 }
    213 
    214 static void destory_encode_pipe()
    215 {
    216     vaDestroyContext(va_dpy,avcenc_context.context_id);
    217     vaDestroyConfig(va_dpy,avcenc_context.config_id);
    218     vaTerminate(va_dpy);
    219     va_close_display(va_dpy);
    220 }
    221 
    222 /***************************************************
    223  *
    224  *  The encode pipe resource define
    225  *
    226  ***************************************************/
    227 #define SID_INPUT_PICTURE_0                     0
    228 #define SID_INPUT_PICTURE_1                     1
    229 #define SID_REFERENCE_PICTURE_L0                2
    230 #define SID_REFERENCE_PICTURE_L1                3
    231 #define SID_RECON_PICTURE                       4
    232 #define SID_NUMBER                              SID_RECON_PICTURE + 1
    233 static  VASurfaceID surface_ids[SID_NUMBER];
    234 
    235 static int frame_number;
    236 static int enc_frame_number;
    237 
    238 /***************************************************/
    239 
    240 static void *
    241 upload_thread_function(void *data)
    242 {
    243     struct upload_thread_param *param = data;
    244 
    245     upload_yuv_to_surface(param->yuv_fp, param->surface_id);
    246 
    247     return NULL;
    248 }
    249 
    250 static void alloc_encode_resource(FILE *yuv_fp)
    251 {
    252     VAStatus va_status;
    253 
    254     // Create surface
    255     va_status = vaCreateSurfaces(
    256         va_dpy,
    257         VA_RT_FORMAT_YUV420, picture_width, picture_height,
    258         &surface_ids[0], SID_NUMBER,
    259         NULL, 0
    260     );
    261 
    262     CHECK_VASTATUS(va_status, "vaCreateSurfaces");
    263 
    264     newImageBuffer = (unsigned char *)malloc(frame_size);
    265 
    266     /* firstly upload YUV data to SID_INPUT_PICTURE_1 */
    267     avcenc_context.upload_thread_param.yuv_fp = yuv_fp;
    268     avcenc_context.upload_thread_param.surface_id = surface_ids[SID_INPUT_PICTURE_1];
    269 
    270     avcenc_context.upload_thread_value = pthread_create(&avcenc_context.upload_thread_id,
    271                                                         NULL,
    272                                                         upload_thread_function,
    273                                                         (void*)&avcenc_context.upload_thread_param);
    274 }
    275 
    276 static void release_encode_resource()
    277 {
    278     pthread_join(avcenc_context.upload_thread_id, NULL);
    279     free(newImageBuffer);
    280 
    281     // Release all the surfaces resource
    282     vaDestroySurfaces(va_dpy, &surface_ids[0], SID_NUMBER);
    283 }
    284 
    285 static void avcenc_update_sei_param(int frame_num)
    286 {
    287 	VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
    288 	unsigned int length_in_bits, offset_in_bytes;
    289 	unsigned char *packed_sei_buffer = NULL;
    290 	VAStatus va_status;
    291 
    292 	length_in_bits = build_packed_sei_buffer_timing(
    293 				avcenc_context.i_initial_cpb_removal_delay_length,
    294 				avcenc_context.i_initial_cpb_removal_delay,
    295 				0,
    296 				avcenc_context.i_cpb_removal_delay_length,
    297 				avcenc_context.i_cpb_removal_delay * frame_num,
    298 				avcenc_context.i_dpb_output_delay_length,
    299 				0,
    300 				&packed_sei_buffer);
    301 
    302 	offset_in_bytes = 0;
    303 	packed_header_param_buffer.type = VAEncPackedHeaderH264_SEI;
    304 	packed_header_param_buffer.bit_length = length_in_bits;
    305 	packed_header_param_buffer.has_emulation_bytes = 0;
    306 
    307 	va_status = vaCreateBuffer(va_dpy,
    308 				avcenc_context.context_id,
    309 				VAEncPackedHeaderParameterBufferType,
    310 				sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
    311 				&avcenc_context.packed_sei_header_param_buf_id);
    312 	CHECK_VASTATUS(va_status,"vaCreateBuffer");
    313 
    314 	va_status = vaCreateBuffer(va_dpy,
    315 				avcenc_context.context_id,
    316 				VAEncPackedHeaderDataBufferType,
    317 				(length_in_bits + 7) / 8, 1, packed_sei_buffer,
    318 				&avcenc_context.packed_sei_buf_id);
    319 	CHECK_VASTATUS(va_status,"vaCreateBuffer");
    320 	free(packed_sei_buffer);
    321 	return;
    322 }
    323 
    324 static void avcenc_update_picture_parameter(int slice_type, int frame_num, int display_num, int is_idr)
    325 {
    326     VAEncPictureParameterBufferH264 *pic_param;
    327     VAStatus va_status;
    328 
    329     // Picture level
    330     pic_param = &avcenc_context.pic_param;
    331     pic_param->CurrPic.picture_id = surface_ids[SID_RECON_PICTURE];
    332     pic_param->CurrPic.TopFieldOrderCnt = display_num * 2;
    333     pic_param->ReferenceFrames[0].picture_id = surface_ids[SID_REFERENCE_PICTURE_L0];
    334     pic_param->ReferenceFrames[1].picture_id = surface_ids[SID_REFERENCE_PICTURE_L1];
    335     pic_param->ReferenceFrames[2].picture_id = VA_INVALID_ID;
    336     assert(avcenc_context.codedbuf_buf_id != VA_INVALID_ID);
    337     pic_param->coded_buf = avcenc_context.codedbuf_buf_id;
    338     pic_param->frame_num = frame_num;
    339     pic_param->pic_fields.bits.idr_pic_flag = !!is_idr;
    340     pic_param->pic_fields.bits.reference_pic_flag = (slice_type != SLICE_TYPE_B);
    341 
    342     va_status = vaCreateBuffer(va_dpy,
    343                                avcenc_context.context_id,
    344                                VAEncPictureParameterBufferType,
    345                                sizeof(*pic_param), 1, pic_param,
    346                                &avcenc_context.pic_param_buf_id);
    347     CHECK_VASTATUS(va_status,"vaCreateBuffer");
    348 }
    349 
    350 #ifndef VA_FOURCC_I420
    351 #define VA_FOURCC_I420          0x30323449
    352 #endif
    353 
    354 static void upload_yuv_to_surface(FILE *yuv_fp, VASurfaceID surface_id)
    355 {
    356     VAImage surface_image;
    357     VAStatus va_status;
    358     void *surface_p = NULL;
    359     unsigned char *y_src, *u_src, *v_src;
    360     unsigned char *y_dst, *u_dst, *v_dst;
    361     int y_size = picture_width * picture_height;
    362     int u_size = (picture_width >> 1) * (picture_height >> 1);
    363     int row, col;
    364     size_t n_items;
    365 
    366     do {
    367         n_items = fread(newImageBuffer, frame_size, 1, yuv_fp);
    368     } while (n_items != 1);
    369 
    370     va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
    371     CHECK_VASTATUS(va_status,"vaDeriveImage");
    372 
    373     vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
    374     assert(VA_STATUS_SUCCESS == va_status);
    375 
    376     y_src = newImageBuffer;
    377     u_src = newImageBuffer + y_size; /* UV offset for NV12 */
    378     v_src = newImageBuffer + y_size + u_size;
    379 
    380     y_dst = surface_p + surface_image.offsets[0];
    381     u_dst = surface_p + surface_image.offsets[1]; /* UV offset for NV12 */
    382     v_dst = surface_p + surface_image.offsets[2];
    383 
    384     /* Y plane */
    385     for (row = 0; row < surface_image.height; row++) {
    386         memcpy(y_dst, y_src, surface_image.width);
    387         y_dst += surface_image.pitches[0];
    388         y_src += picture_width;
    389     }
    390 
    391     if (surface_image.format.fourcc == VA_FOURCC_NV12) { /* UV plane */
    392         for (row = 0; row < surface_image.height / 2; row++) {
    393             for (col = 0; col < surface_image.width / 2; col++) {
    394                 u_dst[col * 2] = u_src[col];
    395                 u_dst[col * 2 + 1] = v_src[col];
    396             }
    397 
    398             u_dst += surface_image.pitches[1];
    399             u_src += (picture_width / 2);
    400             v_src += (picture_width / 2);
    401         }
    402     } else if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
    403                surface_image.format.fourcc == VA_FOURCC_I420) {
    404         const int U = surface_image.format.fourcc == VA_FOURCC_I420 ? 1 : 2;
    405         const int V = surface_image.format.fourcc == VA_FOURCC_I420 ? 2 : 1;
    406 
    407         u_dst = surface_p + surface_image.offsets[U];
    408         v_dst = surface_p + surface_image.offsets[V];
    409 
    410         for (row = 0; row < surface_image.height / 2; row++) {
    411             memcpy(u_dst, u_src, surface_image.width / 2);
    412             memcpy(v_dst, v_src, surface_image.width / 2);
    413             u_dst += surface_image.pitches[U];
    414             v_dst += surface_image.pitches[V];
    415             u_src += (picture_width / 2);
    416             v_src += (picture_width / 2);
    417         }
    418     }
    419 
    420     vaUnmapBuffer(va_dpy, surface_image.buf);
    421     vaDestroyImage(va_dpy, surface_image.image_id);
    422 }
    423 
    424 static void avcenc_update_slice_parameter(int slice_type)
    425 {
    426     VAEncSliceParameterBufferH264 *slice_param;
    427     VAStatus va_status;
    428     int i;
    429 
    430     // Slice level
    431     i = 0;
    432     slice_param = &avcenc_context.slice_param[i];
    433     slice_param->macroblock_address = 0;
    434     slice_param->num_macroblocks = picture_height_in_mbs * picture_width_in_mbs;
    435     slice_param->pic_parameter_set_id = 0;
    436     slice_param->slice_type = slice_type;
    437     slice_param->direct_spatial_mv_pred_flag = 0;
    438     slice_param->num_ref_idx_l0_active_minus1 = 0;      /* FIXME: ??? */
    439     slice_param->num_ref_idx_l1_active_minus1 = 0;
    440     slice_param->cabac_init_idc = 0;
    441     slice_param->slice_qp_delta = 0;
    442     slice_param->disable_deblocking_filter_idc = 0;
    443     slice_param->slice_alpha_c0_offset_div2 = 2;
    444     slice_param->slice_beta_offset_div2 = 2;
    445     slice_param->idr_pic_id = 0;
    446 
    447     /* FIXME: fill other fields */
    448     if ((slice_type == SLICE_TYPE_P) || (slice_type == SLICE_TYPE_B)) {
    449 	int j;
    450 	slice_param->RefPicList0[0].picture_id = surface_ids[SID_REFERENCE_PICTURE_L0];
    451 	for (j = 1; j < 32; j++) {
    452 	    slice_param->RefPicList0[j].picture_id = VA_INVALID_SURFACE;
    453 	    slice_param->RefPicList0[j].flags = VA_PICTURE_H264_INVALID;
    454 	}
    455     }
    456 
    457     if ((slice_type == SLICE_TYPE_B)) {
    458 	int j;
    459 	slice_param->RefPicList1[0].picture_id = surface_ids[SID_REFERENCE_PICTURE_L1];
    460 	for (j = 1; j < 32; j++) {
    461 	    slice_param->RefPicList1[j].picture_id = VA_INVALID_SURFACE;
    462 	    slice_param->RefPicList1[j].flags = VA_PICTURE_H264_INVALID;
    463 	}
    464     }
    465 
    466     va_status = vaCreateBuffer(va_dpy,
    467                                avcenc_context.context_id,
    468                                VAEncSliceParameterBufferType,
    469                                sizeof(*slice_param), 1, slice_param,
    470                                &avcenc_context.slice_param_buf_id[i]);
    471     CHECK_VASTATUS(va_status,"vaCreateBuffer");;
    472     i++;
    473 
    474 #if 0
    475     slice_param = &avcenc_context.slice_param[i];
    476     slice_param->macroblock_address = picture_height_in_mbs * picture_width_in_mbs / 2;
    477     slice_param->num_macroblocks = picture_height_in_mbs * picture_width_in_mbs / 2;
    478     slice_param->pic_parameter_set_id = 0;
    479     slice_param->slice_type = slice_type;
    480     slice_param->direct_spatial_mv_pred_flag = 0;
    481     slice_param->num_ref_idx_l0_active_minus1 = 0;      /* FIXME: ??? */
    482     slice_param->num_ref_idx_l1_active_minus1 = 0;
    483     slice_param->cabac_init_idc = 0;
    484     slice_param->slice_qp_delta = 0;
    485     slice_param->disable_deblocking_filter_idc = 0;
    486     slice_param->slice_alpha_c0_offset_div2 = 2;
    487     slice_param->slice_beta_offset_div2 = 2;
    488     slice_param->idr_pic_id = 0;
    489 
    490     /* FIXME: fill other fields */
    491 
    492     va_status = vaCreateBuffer(va_dpy,
    493                                avcenc_context.context_id,
    494                                VAEncSliceParameterBufferType,
    495                                sizeof(*slice_param), 1, slice_param,
    496                                &avcenc_context.slice_param_buf_id[i]);
    497     CHECK_VASTATUS(va_status,"vaCreateBuffer");;
    498     i++;
    499 #endif
    500 
    501     avcenc_context.num_slices = i;
    502 }
    503 
    504 static int begin_picture(FILE *yuv_fp, int frame_num, int display_num, int slice_type, int is_idr)
    505 {
    506     VAStatus va_status;
    507 
    508     if (avcenc_context.upload_thread_value != 0) {
    509         fprintf(stderr, "FATAL error!!!\n");
    510         exit(1);
    511     }
    512 
    513     pthread_join(avcenc_context.upload_thread_id, NULL);
    514 
    515     avcenc_context.upload_thread_value = -1;
    516 
    517     if (avcenc_context.current_input_surface == SID_INPUT_PICTURE_0)
    518         avcenc_context.current_input_surface = SID_INPUT_PICTURE_1;
    519     else
    520         avcenc_context.current_input_surface = SID_INPUT_PICTURE_0;
    521 
    522     if (frame_num == 0) {
    523         VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
    524         unsigned int length_in_bits, offset_in_bytes;
    525         unsigned char *packed_seq_buffer = NULL, *packed_pic_buffer = NULL;
    526 
    527         assert(slice_type == SLICE_TYPE_I);
    528         length_in_bits = build_packed_seq_buffer(&packed_seq_buffer);
    529         offset_in_bytes = 0;
    530         packed_header_param_buffer.type = VAEncPackedHeaderSequence;
    531         packed_header_param_buffer.bit_length = length_in_bits;
    532         packed_header_param_buffer.has_emulation_bytes = 0;
    533         va_status = vaCreateBuffer(va_dpy,
    534                                    avcenc_context.context_id,
    535                                    VAEncPackedHeaderParameterBufferType,
    536                                    sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
    537                                    &avcenc_context.packed_seq_header_param_buf_id);
    538         CHECK_VASTATUS(va_status,"vaCreateBuffer");
    539 
    540         va_status = vaCreateBuffer(va_dpy,
    541                                    avcenc_context.context_id,
    542                                    VAEncPackedHeaderDataBufferType,
    543                                    (length_in_bits + 7) / 8, 1, packed_seq_buffer,
    544                                    &avcenc_context.packed_seq_buf_id);
    545         CHECK_VASTATUS(va_status,"vaCreateBuffer");
    546 
    547         length_in_bits = build_packed_pic_buffer(&packed_pic_buffer);
    548         offset_in_bytes = 0;
    549         packed_header_param_buffer.type = VAEncPackedHeaderPicture;
    550         packed_header_param_buffer.bit_length = length_in_bits;
    551         packed_header_param_buffer.has_emulation_bytes = 0;
    552 
    553         va_status = vaCreateBuffer(va_dpy,
    554                                    avcenc_context.context_id,
    555                                    VAEncPackedHeaderParameterBufferType,
    556                                    sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
    557                                    &avcenc_context.packed_pic_header_param_buf_id);
    558         CHECK_VASTATUS(va_status,"vaCreateBuffer");
    559 
    560         va_status = vaCreateBuffer(va_dpy,
    561                                    avcenc_context.context_id,
    562                                    VAEncPackedHeaderDataBufferType,
    563                                    (length_in_bits + 7) / 8, 1, packed_pic_buffer,
    564                                    &avcenc_context.packed_pic_buf_id);
    565         CHECK_VASTATUS(va_status,"vaCreateBuffer");
    566 
    567         free(packed_seq_buffer);
    568         free(packed_pic_buffer);
    569     }
    570 
    571     /* sequence parameter set */
    572     VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
    573     va_status = vaCreateBuffer(va_dpy,
    574                                avcenc_context.context_id,
    575                                VAEncSequenceParameterBufferType,
    576                                sizeof(*seq_param), 1, seq_param,
    577                                &avcenc_context.seq_param_buf_id);
    578     CHECK_VASTATUS(va_status,"vaCreateBuffer");
    579 
    580 
    581     /* hrd parameter */
    582     VAEncMiscParameterBuffer *misc_param;
    583     VAEncMiscParameterHRD *misc_hrd_param;
    584     vaCreateBuffer(va_dpy,
    585                    avcenc_context.context_id,
    586                    VAEncMiscParameterBufferType,
    587                    sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterRateControl),
    588                    1,
    589                    NULL,
    590                    &avcenc_context.misc_parameter_hrd_buf_id);
    591     CHECK_VASTATUS(va_status, "vaCreateBuffer");
    592 
    593     vaMapBuffer(va_dpy,
    594                 avcenc_context.misc_parameter_hrd_buf_id,
    595                 (void **)&misc_param);
    596     misc_param->type = VAEncMiscParameterTypeHRD;
    597     misc_hrd_param = (VAEncMiscParameterHRD *)misc_param->data;
    598 
    599     if (frame_bit_rate > 0) {
    600         misc_hrd_param->initial_buffer_fullness = frame_bit_rate * 1024 * 4;
    601         misc_hrd_param->buffer_size = frame_bit_rate * 1024 * 8;
    602     } else {
    603         misc_hrd_param->initial_buffer_fullness = 0;
    604         misc_hrd_param->buffer_size = 0;
    605     }
    606 
    607     vaUnmapBuffer(va_dpy, avcenc_context.misc_parameter_hrd_buf_id);
    608 
    609     /* slice parameter */
    610     avcenc_update_slice_parameter(slice_type);
    611 
    612     return 0;
    613 }
    614 
    615 int avcenc_render_picture()
    616 {
    617     VAStatus va_status;
    618     VABufferID va_buffers[10];
    619     unsigned int num_va_buffers = 0;
    620     int i;
    621 
    622     va_buffers[num_va_buffers++] = avcenc_context.seq_param_buf_id;
    623     va_buffers[num_va_buffers++] = avcenc_context.pic_param_buf_id;
    624 
    625     if (avcenc_context.packed_seq_header_param_buf_id != VA_INVALID_ID)
    626         va_buffers[num_va_buffers++] = avcenc_context.packed_seq_header_param_buf_id;
    627 
    628     if (avcenc_context.packed_seq_buf_id != VA_INVALID_ID)
    629         va_buffers[num_va_buffers++] = avcenc_context.packed_seq_buf_id;
    630 
    631     if (avcenc_context.packed_pic_header_param_buf_id != VA_INVALID_ID)
    632         va_buffers[num_va_buffers++] = avcenc_context.packed_pic_header_param_buf_id;
    633 
    634     if (avcenc_context.packed_pic_buf_id != VA_INVALID_ID)
    635         va_buffers[num_va_buffers++] = avcenc_context.packed_pic_buf_id;
    636 
    637     if (avcenc_context.packed_sei_header_param_buf_id != VA_INVALID_ID)
    638         va_buffers[num_va_buffers++] = avcenc_context.packed_sei_header_param_buf_id;
    639 
    640     if (avcenc_context.packed_sei_buf_id != VA_INVALID_ID)
    641         va_buffers[num_va_buffers++] = avcenc_context.packed_sei_buf_id;
    642 
    643     if (avcenc_context.misc_parameter_hrd_buf_id != VA_INVALID_ID)
    644         va_buffers[num_va_buffers++] =  avcenc_context.misc_parameter_hrd_buf_id;
    645 
    646     va_status = vaBeginPicture(va_dpy,
    647                                avcenc_context.context_id,
    648                                surface_ids[avcenc_context.current_input_surface]);
    649     CHECK_VASTATUS(va_status,"vaBeginPicture");
    650 
    651     va_status = vaRenderPicture(va_dpy,
    652                                 avcenc_context.context_id,
    653                                 va_buffers,
    654                                 num_va_buffers);
    655     CHECK_VASTATUS(va_status,"vaRenderPicture");
    656 
    657     for(i = 0; i < avcenc_context.num_slices; i++) {
    658         va_status = vaRenderPicture(va_dpy,
    659                                 avcenc_context.context_id,
    660                                 &avcenc_context.slice_param_buf_id[i],
    661                                 1);
    662         CHECK_VASTATUS(va_status,"vaRenderPicture");
    663     }
    664 
    665     va_status = vaEndPicture(va_dpy, avcenc_context.context_id);
    666     CHECK_VASTATUS(va_status,"vaEndPicture");
    667 
    668     return 0;
    669 }
    670 
    671 static int avcenc_destroy_buffers(VABufferID *va_buffers, unsigned int num_va_buffers)
    672 {
    673     VAStatus va_status;
    674     unsigned int i;
    675 
    676     for (i = 0; i < num_va_buffers; i++) {
    677         if (va_buffers[i] != VA_INVALID_ID) {
    678             va_status = vaDestroyBuffer(va_dpy, va_buffers[i]);
    679             CHECK_VASTATUS(va_status,"vaDestroyBuffer");
    680             va_buffers[i] = VA_INVALID_ID;
    681         }
    682     }
    683 
    684     return 0;
    685 }
    686 
    687 static void end_picture(int slice_type, int next_is_bpic)
    688 {
    689     VABufferID tempID;
    690 
    691     /* Prepare for next picture */
    692     tempID = surface_ids[SID_RECON_PICTURE];
    693 
    694     if (slice_type != SLICE_TYPE_B) {
    695         if (next_is_bpic) {
    696             surface_ids[SID_RECON_PICTURE] = surface_ids[SID_REFERENCE_PICTURE_L1];
    697             surface_ids[SID_REFERENCE_PICTURE_L1] = tempID;
    698         } else {
    699             surface_ids[SID_RECON_PICTURE] = surface_ids[SID_REFERENCE_PICTURE_L0];
    700             surface_ids[SID_REFERENCE_PICTURE_L0] = tempID;
    701         }
    702     } else {
    703         if (!next_is_bpic) {
    704             surface_ids[SID_RECON_PICTURE] = surface_ids[SID_REFERENCE_PICTURE_L0];
    705             surface_ids[SID_REFERENCE_PICTURE_L0] = surface_ids[SID_REFERENCE_PICTURE_L1];
    706             surface_ids[SID_REFERENCE_PICTURE_L1] = tempID;
    707         }
    708     }
    709 
    710     avcenc_destroy_buffers(&avcenc_context.seq_param_buf_id, 1);
    711     avcenc_destroy_buffers(&avcenc_context.pic_param_buf_id, 1);
    712     avcenc_destroy_buffers(&avcenc_context.packed_seq_header_param_buf_id, 1);
    713     avcenc_destroy_buffers(&avcenc_context.packed_seq_buf_id, 1);
    714     avcenc_destroy_buffers(&avcenc_context.packed_pic_header_param_buf_id, 1);
    715     avcenc_destroy_buffers(&avcenc_context.packed_pic_buf_id, 1);
    716     avcenc_destroy_buffers(&avcenc_context.packed_sei_header_param_buf_id, 1);
    717     avcenc_destroy_buffers(&avcenc_context.packed_sei_buf_id, 1);
    718     avcenc_destroy_buffers(&avcenc_context.slice_param_buf_id[0], avcenc_context.num_slices);
    719     avcenc_destroy_buffers(&avcenc_context.codedbuf_buf_id, 1);
    720     avcenc_destroy_buffers(&avcenc_context.misc_parameter_hrd_buf_id, 1);
    721 
    722     memset(avcenc_context.slice_param, 0, sizeof(avcenc_context.slice_param));
    723     avcenc_context.num_slices = 0;
    724 }
    725 
    726 #define BITSTREAM_ALLOCATE_STEPPING     4096
    727 
    728 struct __bitstream {
    729     unsigned int *buffer;
    730     int bit_offset;
    731     int max_size_in_dword;
    732 };
    733 
    734 typedef struct __bitstream bitstream;
    735 
    736 #if 0
    737 static int
    738 get_coded_bitsteam_length(unsigned char *buffer, int buffer_length)
    739 {
    740     int i;
    741 
    742     for (i = 0; i < buffer_length - 3; i++) {
    743         if (!buffer[i] &&
    744             !buffer[i + 1] &&
    745             !buffer[i + 2] &&
    746             !buffer[i + 3])
    747             break;
    748     }
    749 
    750     return i;
    751 }
    752 #endif
    753 
    754 static unsigned int
    755 va_swap32(unsigned int val)
    756 {
    757     unsigned char *pval = (unsigned char *)&val;
    758 
    759     return ((pval[0] << 24)     |
    760             (pval[1] << 16)     |
    761             (pval[2] << 8)      |
    762             (pval[3] << 0));
    763 }
    764 
    765 static void
    766 bitstream_start(bitstream *bs)
    767 {
    768     bs->max_size_in_dword = BITSTREAM_ALLOCATE_STEPPING;
    769     bs->buffer = calloc(bs->max_size_in_dword * sizeof(int), 1);
    770     bs->bit_offset = 0;
    771 }
    772 
    773 static void
    774 bitstream_end(bitstream *bs)
    775 {
    776     int pos = (bs->bit_offset >> 5);
    777     int bit_offset = (bs->bit_offset & 0x1f);
    778     int bit_left = 32 - bit_offset;
    779 
    780     if (bit_offset) {
    781         bs->buffer[pos] = va_swap32((bs->buffer[pos] << bit_left));
    782     }
    783 }
    784 
    785 static void
    786 bitstream_put_ui(bitstream *bs, unsigned int val, int size_in_bits)
    787 {
    788     int pos = (bs->bit_offset >> 5);
    789     int bit_offset = (bs->bit_offset & 0x1f);
    790     int bit_left = 32 - bit_offset;
    791 
    792     if (!size_in_bits)
    793         return;
    794 
    795     bs->bit_offset += size_in_bits;
    796 
    797     if (bit_left > size_in_bits) {
    798         bs->buffer[pos] = (bs->buffer[pos] << size_in_bits | val);
    799     } else {
    800         size_in_bits -= bit_left;
    801         bs->buffer[pos] = (bs->buffer[pos] << bit_left) | (val >> size_in_bits);
    802         bs->buffer[pos] = va_swap32(bs->buffer[pos]);
    803 
    804         if (pos + 1 == bs->max_size_in_dword) {
    805             bs->max_size_in_dword += BITSTREAM_ALLOCATE_STEPPING;
    806             bs->buffer = realloc(bs->buffer, bs->max_size_in_dword * sizeof(unsigned int));
    807         }
    808 
    809         bs->buffer[pos + 1] = val;
    810     }
    811 }
    812 
    813 static void
    814 bitstream_put_ue(bitstream *bs, unsigned int val)
    815 {
    816     int size_in_bits = 0;
    817     int tmp_val = ++val;
    818 
    819     while (tmp_val) {
    820         tmp_val >>= 1;
    821         size_in_bits++;
    822     }
    823 
    824     bitstream_put_ui(bs, 0, size_in_bits - 1); // leading zero
    825     bitstream_put_ui(bs, val, size_in_bits);
    826 }
    827 
    828 static void
    829 bitstream_put_se(bitstream *bs, int val)
    830 {
    831     unsigned int new_val;
    832 
    833     if (val <= 0)
    834         new_val = -2 * val;
    835     else
    836         new_val = 2 * val - 1;
    837 
    838     bitstream_put_ue(bs, new_val);
    839 }
    840 
    841 static void
    842 bitstream_byte_aligning(bitstream *bs, int bit)
    843 {
    844     int bit_offset = (bs->bit_offset & 0x7);
    845     int bit_left = 8 - bit_offset;
    846     int new_val;
    847 
    848     if (!bit_offset)
    849         return;
    850 
    851     assert(bit == 0 || bit == 1);
    852 
    853     if (bit)
    854         new_val = (1 << bit_left) - 1;
    855     else
    856         new_val = 0;
    857 
    858     bitstream_put_ui(bs, new_val, bit_left);
    859 }
    860 
    861 static void
    862 rbsp_trailing_bits(bitstream *bs)
    863 {
    864     bitstream_put_ui(bs, 1, 1);
    865     bitstream_byte_aligning(bs, 0);
    866 }
    867 
    868 static void nal_start_code_prefix(bitstream *bs)
    869 {
    870     bitstream_put_ui(bs, 0x00000001, 32);
    871 }
    872 
    873 static void nal_header(bitstream *bs, int nal_ref_idc, int nal_unit_type)
    874 {
    875     bitstream_put_ui(bs, 0, 1);                /* forbidden_zero_bit: 0 */
    876     bitstream_put_ui(bs, nal_ref_idc, 2);
    877     bitstream_put_ui(bs, nal_unit_type, 5);
    878 }
    879 
    880 static void sps_rbsp(bitstream *bs)
    881 {
    882     VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
    883     int profile_idc = PROFILE_IDC_BASELINE;
    884 
    885     if (avcenc_context.profile == VAProfileH264High)
    886         profile_idc = PROFILE_IDC_HIGH;
    887     else if (avcenc_context.profile == VAProfileH264Main)
    888         profile_idc = PROFILE_IDC_MAIN;
    889 
    890     bitstream_put_ui(bs, profile_idc, 8);               /* profile_idc */
    891     bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 1), 1);                         /* constraint_set0_flag */
    892     bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 2), 1);                         /* constraint_set1_flag */
    893     bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 4), 1);                         /* constraint_set2_flag */
    894     bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 8), 1);                         /* constraint_set3_flag */
    895     bitstream_put_ui(bs, 0, 4);                         /* reserved_zero_4bits */
    896     bitstream_put_ui(bs, seq_param->level_idc, 8);      /* level_idc */
    897     bitstream_put_ue(bs, seq_param->seq_parameter_set_id);      /* seq_parameter_set_id */
    898 
    899     if ( profile_idc == PROFILE_IDC_HIGH) {
    900         bitstream_put_ue(bs, 1);        /* chroma_format_idc = 1, 4:2:0 */
    901         bitstream_put_ue(bs, 0);        /* bit_depth_luma_minus8 */
    902         bitstream_put_ue(bs, 0);        /* bit_depth_chroma_minus8 */
    903         bitstream_put_ui(bs, 0, 1);     /* qpprime_y_zero_transform_bypass_flag */
    904         bitstream_put_ui(bs, 0, 1);     /* seq_scaling_matrix_present_flag */
    905     }
    906 
    907     bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
    908     bitstream_put_ue(bs, seq_param->seq_fields.bits.pic_order_cnt_type);        /* pic_order_cnt_type */
    909 
    910     if (seq_param->seq_fields.bits.pic_order_cnt_type == 0)
    911         bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4);     /* log2_max_pic_order_cnt_lsb_minus4 */
    912     else {
    913         assert(0);
    914     }
    915 
    916     bitstream_put_ue(bs, seq_param->max_num_ref_frames);        /* num_ref_frames */
    917     bitstream_put_ui(bs, 0, 1);                                 /* gaps_in_frame_num_value_allowed_flag */
    918 
    919     bitstream_put_ue(bs, seq_param->picture_width_in_mbs - 1);  /* pic_width_in_mbs_minus1 */
    920     bitstream_put_ue(bs, seq_param->picture_height_in_mbs - 1); /* pic_height_in_map_units_minus1 */
    921     bitstream_put_ui(bs, seq_param->seq_fields.bits.frame_mbs_only_flag, 1);    /* frame_mbs_only_flag */
    922 
    923     if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {
    924         assert(0);
    925     }
    926 
    927     bitstream_put_ui(bs, seq_param->seq_fields.bits.direct_8x8_inference_flag, 1);      /* direct_8x8_inference_flag */
    928     bitstream_put_ui(bs, seq_param->frame_cropping_flag, 1);            /* frame_cropping_flag */
    929 
    930     if (seq_param->frame_cropping_flag) {
    931         bitstream_put_ue(bs, seq_param->frame_crop_left_offset);        /* frame_crop_left_offset */
    932         bitstream_put_ue(bs, seq_param->frame_crop_right_offset);       /* frame_crop_right_offset */
    933         bitstream_put_ue(bs, seq_param->frame_crop_top_offset);         /* frame_crop_top_offset */
    934         bitstream_put_ue(bs, seq_param->frame_crop_bottom_offset);      /* frame_crop_bottom_offset */
    935     }
    936 
    937     if ( frame_bit_rate < 0 ) {
    938         bitstream_put_ui(bs, 0, 1); /* vui_parameters_present_flag */
    939     } else {
    940         bitstream_put_ui(bs, 1, 1); /* vui_parameters_present_flag */
    941         bitstream_put_ui(bs, 0, 1); /* aspect_ratio_info_present_flag */
    942         bitstream_put_ui(bs, 0, 1); /* overscan_info_present_flag */
    943         bitstream_put_ui(bs, 0, 1); /* video_signal_type_present_flag */
    944         bitstream_put_ui(bs, 0, 1); /* chroma_loc_info_present_flag */
    945         bitstream_put_ui(bs, 1, 1); /* timing_info_present_flag */
    946         {
    947             bitstream_put_ui(bs, 15, 32);
    948             bitstream_put_ui(bs, 900, 32);
    949             bitstream_put_ui(bs, 1, 1);
    950         }
    951         bitstream_put_ui(bs, 1, 1); /* nal_hrd_parameters_present_flag */
    952         {
    953             // hrd_parameters
    954             bitstream_put_ue(bs, 0);    /* cpb_cnt_minus1 */
    955             bitstream_put_ui(bs, 4, 4); /* bit_rate_scale */
    956             bitstream_put_ui(bs, 6, 4); /* cpb_size_scale */
    957 
    958             bitstream_put_ue(bs, frame_bit_rate - 1); /* bit_rate_value_minus1[0] */
    959             bitstream_put_ue(bs, frame_bit_rate*8 - 1); /* cpb_size_value_minus1[0] */
    960             bitstream_put_ui(bs, 1, 1);  /* cbr_flag[0] */
    961 
    962             bitstream_put_ui(bs, 23, 5);   /* initial_cpb_removal_delay_length_minus1 */
    963             bitstream_put_ui(bs, 23, 5);   /* cpb_removal_delay_length_minus1 */
    964             bitstream_put_ui(bs, 23, 5);   /* dpb_output_delay_length_minus1 */
    965             bitstream_put_ui(bs, 23, 5);   /* time_offset_length  */
    966         }
    967         bitstream_put_ui(bs, 0, 1);   /* vcl_hrd_parameters_present_flag */
    968         bitstream_put_ui(bs, 0, 1);   /* low_delay_hrd_flag */
    969 
    970         bitstream_put_ui(bs, 0, 1); /* pic_struct_present_flag */
    971         bitstream_put_ui(bs, 0, 1); /* bitstream_restriction_flag */
    972     }
    973 
    974     rbsp_trailing_bits(bs);     /* rbsp_trailing_bits */
    975 }
    976 
    977 #if 0
    978 static void build_nal_sps(FILE *avc_fp)
    979 {
    980     bitstream bs;
    981 
    982     bitstream_start(&bs);
    983     nal_start_code_prefix(&bs);
    984     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
    985     sps_rbsp(&bs);
    986     bitstream_end(&bs, avc_fp);
    987 }
    988 #endif
    989 
    990 static void pps_rbsp(bitstream *bs)
    991 {
    992     VAEncPictureParameterBufferH264 *pic_param = &avcenc_context.pic_param;
    993 
    994     bitstream_put_ue(bs, pic_param->pic_parameter_set_id);      /* pic_parameter_set_id */
    995     bitstream_put_ue(bs, pic_param->seq_parameter_set_id);      /* seq_parameter_set_id */
    996 
    997     bitstream_put_ui(bs, pic_param->pic_fields.bits.entropy_coding_mode_flag, 1);  /* entropy_coding_mode_flag */
    998 
    999     bitstream_put_ui(bs, 0, 1);                         /* pic_order_present_flag: 0 */
   1000 
   1001     bitstream_put_ue(bs, 0);                            /* num_slice_groups_minus1 */
   1002 
   1003     bitstream_put_ue(bs, pic_param->num_ref_idx_l0_active_minus1);      /* num_ref_idx_l0_active_minus1 */
   1004     bitstream_put_ue(bs, pic_param->num_ref_idx_l1_active_minus1);      /* num_ref_idx_l1_active_minus1 1 */
   1005 
   1006     bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_pred_flag, 1);     /* weighted_pred_flag: 0 */
   1007     bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_bipred_idc, 2);	/* weighted_bipred_idc: 0 */
   1008 
   1009     bitstream_put_se(bs, pic_param->pic_init_qp - 26);  /* pic_init_qp_minus26 */
   1010     bitstream_put_se(bs, 0);                            /* pic_init_qs_minus26 */
   1011     bitstream_put_se(bs, 0);                            /* chroma_qp_index_offset */
   1012 
   1013     bitstream_put_ui(bs, pic_param->pic_fields.bits.deblocking_filter_control_present_flag, 1); /* deblocking_filter_control_present_flag */
   1014     bitstream_put_ui(bs, 0, 1);                         /* constrained_intra_pred_flag */
   1015     bitstream_put_ui(bs, 0, 1);                         /* redundant_pic_cnt_present_flag */
   1016 
   1017     /* more_rbsp_data */
   1018     bitstream_put_ui(bs, pic_param->pic_fields.bits.transform_8x8_mode_flag, 1);    /*transform_8x8_mode_flag */
   1019     bitstream_put_ui(bs, 0, 1);                         /* pic_scaling_matrix_present_flag */
   1020     bitstream_put_se(bs, pic_param->second_chroma_qp_index_offset );    /*second_chroma_qp_index_offset */
   1021 
   1022     rbsp_trailing_bits(bs);
   1023 }
   1024 
   1025 #if 0
   1026 static void build_nal_pps(FILE *avc_fp)
   1027 {
   1028     bitstream bs;
   1029 
   1030     bitstream_start(&bs);
   1031     nal_start_code_prefix(&bs);
   1032     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
   1033     pps_rbsp(&bs);
   1034     bitstream_end(&bs, avc_fp);
   1035 }
   1036 
   1037 static void
   1038 build_header(FILE *avc_fp)
   1039 {
   1040     build_nal_sps(avc_fp);
   1041     build_nal_pps(avc_fp);
   1042 }
   1043 #endif
   1044 
   1045 static int
   1046 build_packed_pic_buffer(unsigned char **header_buffer)
   1047 {
   1048     bitstream bs;
   1049 
   1050     bitstream_start(&bs);
   1051     nal_start_code_prefix(&bs);
   1052     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
   1053     pps_rbsp(&bs);
   1054     bitstream_end(&bs);
   1055 
   1056     *header_buffer = (unsigned char *)bs.buffer;
   1057     return bs.bit_offset;
   1058 }
   1059 
   1060 static int
   1061 build_packed_seq_buffer(unsigned char **header_buffer)
   1062 {
   1063     bitstream bs;
   1064 
   1065     bitstream_start(&bs);
   1066     nal_start_code_prefix(&bs);
   1067     nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
   1068     sps_rbsp(&bs);
   1069     bitstream_end(&bs);
   1070 
   1071     *header_buffer = (unsigned char *)bs.buffer;
   1072     return bs.bit_offset;
   1073 }
   1074 
   1075 static int
   1076 build_packed_sei_buffer_timing(unsigned int init_cpb_removal_length,
   1077 				unsigned int init_cpb_removal_delay,
   1078 				unsigned int init_cpb_removal_delay_offset,
   1079 				unsigned int cpb_removal_length,
   1080 				unsigned int cpb_removal_delay,
   1081 				unsigned int dpb_output_length,
   1082 				unsigned int dpb_output_delay,
   1083 				unsigned char **sei_buffer)
   1084 {
   1085     unsigned char *byte_buf;
   1086     int bp_byte_size, i, pic_byte_size;
   1087 
   1088     bitstream nal_bs;
   1089     bitstream sei_bp_bs, sei_pic_bs;
   1090 
   1091     bitstream_start(&sei_bp_bs);
   1092     bitstream_put_ue(&sei_bp_bs, 0);       /*seq_parameter_set_id*/
   1093     bitstream_put_ui(&sei_bp_bs, init_cpb_removal_delay, cpb_removal_length);
   1094     bitstream_put_ui(&sei_bp_bs, init_cpb_removal_delay_offset, cpb_removal_length);
   1095     if ( sei_bp_bs.bit_offset & 0x7) {
   1096         bitstream_put_ui(&sei_bp_bs, 1, 1);
   1097     }
   1098     bitstream_end(&sei_bp_bs);
   1099     bp_byte_size = (sei_bp_bs.bit_offset + 7) / 8;
   1100 
   1101     bitstream_start(&sei_pic_bs);
   1102     bitstream_put_ui(&sei_pic_bs, cpb_removal_delay, cpb_removal_length);
   1103     bitstream_put_ui(&sei_pic_bs, dpb_output_delay, dpb_output_length);
   1104     if ( sei_pic_bs.bit_offset & 0x7) {
   1105         bitstream_put_ui(&sei_pic_bs, 1, 1);
   1106     }
   1107     bitstream_end(&sei_pic_bs);
   1108     pic_byte_size = (sei_pic_bs.bit_offset + 7) / 8;
   1109 
   1110     bitstream_start(&nal_bs);
   1111     nal_start_code_prefix(&nal_bs);
   1112     nal_header(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI);
   1113 
   1114 	/* Write the SEI buffer period data */
   1115     bitstream_put_ui(&nal_bs, 0, 8);
   1116     bitstream_put_ui(&nal_bs, bp_byte_size, 8);
   1117 
   1118     byte_buf = (unsigned char *)sei_bp_bs.buffer;
   1119     for(i = 0; i < bp_byte_size; i++) {
   1120         bitstream_put_ui(&nal_bs, byte_buf[i], 8);
   1121     }
   1122     free(byte_buf);
   1123 	/* write the SEI timing data */
   1124     bitstream_put_ui(&nal_bs, 0x01, 8);
   1125     bitstream_put_ui(&nal_bs, pic_byte_size, 8);
   1126 
   1127     byte_buf = (unsigned char *)sei_pic_bs.buffer;
   1128     for(i = 0; i < pic_byte_size; i++) {
   1129         bitstream_put_ui(&nal_bs, byte_buf[i], 8);
   1130     }
   1131     free(byte_buf);
   1132 
   1133     rbsp_trailing_bits(&nal_bs);
   1134     bitstream_end(&nal_bs);
   1135 
   1136     *sei_buffer = (unsigned char *)nal_bs.buffer;
   1137 
   1138     return nal_bs.bit_offset;
   1139 }
   1140 
   1141 #if 0
   1142 static void
   1143 slice_header(bitstream *bs, int frame_num, int display_frame, int slice_type, int nal_ref_idc, int is_idr)
   1144 {
   1145     VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
   1146     VAEncPictureParameterBufferH264 *pic_param = &avcenc_context.pic_param;
   1147     int is_cabac = (pic_param->pic_fields.bits.entropy_coding_mode_flag == ENTROPY_MODE_CABAC);
   1148 
   1149     bitstream_put_ue(bs, 0);                   /* first_mb_in_slice: 0 */
   1150     bitstream_put_ue(bs, slice_type);          /* slice_type */
   1151     bitstream_put_ue(bs, 0);                   /* pic_parameter_set_id: 0 */
   1152     bitstream_put_ui(bs, frame_num & 0x0F, seq_param->seq_fields.bits.log2_max_frame_num_minus4 + 4);    /* frame_num */
   1153 
   1154     /* frame_mbs_only_flag == 1 */
   1155     if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {
   1156         /* FIXME: */
   1157         assert(0);
   1158     }
   1159 
   1160     if (is_idr)
   1161         bitstream_put_ue(bs, 0);		/* idr_pic_id: 0 */
   1162 
   1163     if (seq_param->seq_fields.bits.pic_order_cnt_type == 0) {
   1164         bitstream_put_ui(bs, (display_frame*2) & 0x3F, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 + 4);
   1165         /* only support frame */
   1166     } else {
   1167         /* FIXME: */
   1168         assert(0);
   1169     }
   1170 
   1171     /* redundant_pic_cnt_present_flag == 0 */
   1172 
   1173     /* slice type */
   1174     if (slice_type == SLICE_TYPE_P) {
   1175         bitstream_put_ui(bs, 0, 1);            /* num_ref_idx_active_override_flag: 0 */
   1176         /* ref_pic_list_reordering */
   1177         bitstream_put_ui(bs, 0, 1);            /* ref_pic_list_reordering_flag_l0: 0 */
   1178     } else if (slice_type == SLICE_TYPE_B) {
   1179         bitstream_put_ui(bs, 1, 1);            /* direct_spatial_mv_pred: 1 */
   1180         bitstream_put_ui(bs, 0, 1);            /* num_ref_idx_active_override_flag: 0 */
   1181         /* ref_pic_list_reordering */
   1182         bitstream_put_ui(bs, 0, 1);            /* ref_pic_list_reordering_flag_l0: 0 */
   1183         bitstream_put_ui(bs, 0, 1);            /* ref_pic_list_reordering_flag_l1: 0 */
   1184     }
   1185 
   1186     /* weighted_pred_flag == 0 */
   1187 
   1188     /* dec_ref_pic_marking */
   1189     if (nal_ref_idc != 0) {
   1190         if ( is_idr) {
   1191             bitstream_put_ui(bs, 0, 1);            /* no_output_of_prior_pics_flag: 0 */
   1192             bitstream_put_ui(bs, 0, 1);            /* long_term_reference_flag: 0 */
   1193         } else {
   1194             bitstream_put_ui(bs, 0, 1);            /* adaptive_ref_pic_marking_mode_flag: 0 */
   1195         }
   1196     }
   1197 
   1198     if (is_cabac && (slice_type != SLICE_TYPE_I))
   1199         bitstream_put_ue(bs, 0);               /* cabac_init_idc: 0 */
   1200 
   1201     bitstream_put_se(bs, 0);                   /* slice_qp_delta: 0 */
   1202 
   1203     if (pic_param->pic_fields.bits.deblocking_filter_control_present_flag == 1) {
   1204         bitstream_put_ue(bs, 0);               /* disable_deblocking_filter_idc: 0 */
   1205         bitstream_put_se(bs, 2);               /* slice_alpha_c0_offset_div2: 2 */
   1206         bitstream_put_se(bs, 2);               /* slice_beta_offset_div2: 2 */
   1207     }
   1208 }
   1209 
   1210 static void
   1211 slice_data(bitstream *bs)
   1212 {
   1213     VACodedBufferSegment *coded_buffer_segment;
   1214     unsigned char *coded_mem;
   1215     int i, slice_data_length;
   1216     VAStatus va_status;
   1217     VASurfaceStatus surface_status;
   1218 
   1219     va_status = vaSyncSurface(va_dpy, surface_ids[avcenc_context.current_input_surface]);
   1220     CHECK_VASTATUS(va_status,"vaSyncSurface");
   1221 
   1222     surface_status = 0;
   1223     va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[avcenc_context.current_input_surface], &surface_status);
   1224     CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
   1225 
   1226     va_status = vaMapBuffer(va_dpy, avcenc_context.codedbuf_buf_id, (void **)(&coded_buffer_segment));
   1227     CHECK_VASTATUS(va_status,"vaMapBuffer");
   1228     coded_mem = coded_buffer_segment->buf;
   1229 
   1230     slice_data_length = get_coded_bitsteam_length(coded_mem, codedbuf_size);
   1231 
   1232     for (i = 0; i < slice_data_length; i++) {
   1233         bitstream_put_ui(bs, *coded_mem, 8);
   1234         coded_mem++;
   1235     }
   1236 
   1237     vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
   1238 }
   1239 
   1240 static void
   1241 build_nal_slice(FILE *avc_fp, int frame_num, int display_frame, int slice_type, int is_idr)
   1242 {
   1243     bitstream bs;
   1244 
   1245     bitstream_start(&bs);
   1246     slice_data(&bs);
   1247     bitstream_end(&bs, avc_fp);
   1248 }
   1249 
   1250 #endif
   1251 
   1252 static int
   1253 store_coded_buffer(FILE *avc_fp, int slice_type)
   1254 {
   1255     VACodedBufferSegment *coded_buffer_segment;
   1256     unsigned char *coded_mem;
   1257     int slice_data_length;
   1258     VAStatus va_status;
   1259     VASurfaceStatus surface_status;
   1260     size_t w_items;
   1261 
   1262     va_status = vaSyncSurface(va_dpy, surface_ids[avcenc_context.current_input_surface]);
   1263     CHECK_VASTATUS(va_status,"vaSyncSurface");
   1264 
   1265     surface_status = 0;
   1266     va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[avcenc_context.current_input_surface], &surface_status);
   1267     CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
   1268 
   1269     va_status = vaMapBuffer(va_dpy, avcenc_context.codedbuf_buf_id, (void **)(&coded_buffer_segment));
   1270     CHECK_VASTATUS(va_status,"vaMapBuffer");
   1271     coded_mem = coded_buffer_segment->buf;
   1272 
   1273     if (coded_buffer_segment->status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK) {
   1274         if (slice_type == SLICE_TYPE_I)
   1275             avcenc_context.codedbuf_i_size *= 2;
   1276         else
   1277             avcenc_context.codedbuf_pb_size *= 2;
   1278 
   1279         vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
   1280         return -1;
   1281     }
   1282 
   1283     slice_data_length = coded_buffer_segment->size;
   1284 
   1285     do {
   1286         w_items = fwrite(coded_mem, slice_data_length, 1, avc_fp);
   1287     } while (w_items != 1);
   1288 
   1289     if (slice_type == SLICE_TYPE_I) {
   1290         if (avcenc_context.codedbuf_i_size > slice_data_length * 3 / 2) {
   1291             avcenc_context.codedbuf_i_size = slice_data_length * 3 / 2;
   1292         }
   1293 
   1294         if (avcenc_context.codedbuf_pb_size < slice_data_length) {
   1295             avcenc_context.codedbuf_pb_size = slice_data_length;
   1296         }
   1297     } else {
   1298         if (avcenc_context.codedbuf_pb_size > slice_data_length * 3 / 2) {
   1299             avcenc_context.codedbuf_pb_size = slice_data_length * 3 / 2;
   1300         }
   1301     }
   1302 
   1303     vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
   1304 
   1305     return 0;
   1306 }
   1307 
   1308 static void
   1309 encode_picture(FILE *yuv_fp, FILE *avc_fp,
   1310                int frame_num, int display_num,
   1311                int is_idr,
   1312                int slice_type, int next_is_bpic,
   1313                int next_display_num)
   1314 {
   1315     VAStatus va_status;
   1316     int ret = 0, codedbuf_size;
   1317 
   1318     begin_picture(yuv_fp, frame_num, display_num, slice_type, is_idr);
   1319 
   1320     //if (next_display_num < frame_number) {
   1321     if (1) {
   1322         int index;
   1323 
   1324         /* prepare for next frame */
   1325         if (avcenc_context.current_input_surface == SID_INPUT_PICTURE_0)
   1326             index = SID_INPUT_PICTURE_1;
   1327         else
   1328             index = SID_INPUT_PICTURE_0;
   1329         if ( next_display_num >= frame_number )
   1330             next_display_num = frame_number - 1;
   1331         fseeko(yuv_fp, (off_t)frame_size * next_display_num, SEEK_SET);
   1332 
   1333         avcenc_context.upload_thread_param.yuv_fp = yuv_fp;
   1334         avcenc_context.upload_thread_param.surface_id = surface_ids[index];
   1335 
   1336         avcenc_context.upload_thread_value = pthread_create(&avcenc_context.upload_thread_id,
   1337                                                             NULL,
   1338                                                             upload_thread_function,
   1339                                                             (void*)&avcenc_context.upload_thread_param);
   1340     }
   1341 
   1342     do {
   1343         avcenc_destroy_buffers(&avcenc_context.codedbuf_buf_id, 1);
   1344         avcenc_destroy_buffers(&avcenc_context.pic_param_buf_id, 1);
   1345 
   1346 
   1347         if (SLICE_TYPE_I == slice_type) {
   1348             codedbuf_size = avcenc_context.codedbuf_i_size;
   1349         } else {
   1350             codedbuf_size = avcenc_context.codedbuf_pb_size;
   1351         }
   1352 
   1353         /* coded buffer */
   1354         va_status = vaCreateBuffer(va_dpy,
   1355                                    avcenc_context.context_id,
   1356                                    VAEncCodedBufferType,
   1357                                    codedbuf_size, 1, NULL,
   1358                                    &avcenc_context.codedbuf_buf_id);
   1359         CHECK_VASTATUS(va_status,"vaCreateBuffer");
   1360 
   1361         /* picture parameter set */
   1362         avcenc_update_picture_parameter(slice_type, frame_num, display_num, is_idr);
   1363 
   1364 	if (avcenc_context.rate_control_method == VA_RC_CBR)
   1365 		avcenc_update_sei_param(frame_num);
   1366 
   1367         avcenc_render_picture();
   1368 
   1369         ret = store_coded_buffer(avc_fp, slice_type);
   1370     } while (ret);
   1371 
   1372     end_picture(slice_type, next_is_bpic);
   1373 }
   1374 
   1375 static void encode_pb_pictures(FILE *yuv_fp, FILE *avc_fp, int f, int nbframes, int next_f)
   1376 {
   1377     int i;
   1378     encode_picture(yuv_fp, avc_fp,
   1379                    enc_frame_number, f + nbframes,
   1380                    0,
   1381                    SLICE_TYPE_P, 1, f);
   1382 
   1383     for( i = 0; i < nbframes - 1; i++) {
   1384         encode_picture(yuv_fp, avc_fp,
   1385                        enc_frame_number + 1, f + i,
   1386                        0,
   1387                        SLICE_TYPE_B, 1, f + i + 1);
   1388     }
   1389 
   1390     encode_picture(yuv_fp, avc_fp,
   1391                    enc_frame_number + 1, f + nbframes - 1,
   1392                    0,
   1393                    SLICE_TYPE_B, 0, next_f);
   1394 }
   1395 
   1396 static void show_help()
   1397 {
   1398     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");
   1399 }
   1400 
   1401 static void avcenc_context_seq_param_init(VAEncSequenceParameterBufferH264 *seq_param,
   1402                                           int width, int height)
   1403 
   1404 {
   1405     int width_in_mbs = (width + 15) / 16;
   1406     int height_in_mbs = (height + 15) / 16;
   1407     int frame_cropping_flag = 0;
   1408     int frame_crop_bottom_offset = 0;
   1409 
   1410     seq_param->seq_parameter_set_id = 0;
   1411     seq_param->level_idc = 41;
   1412     seq_param->intra_period = intra_period;
   1413     seq_param->ip_period = 0;   /* FIXME: ??? */
   1414     seq_param->max_num_ref_frames = 4;
   1415     seq_param->picture_width_in_mbs = width_in_mbs;
   1416     seq_param->picture_height_in_mbs = height_in_mbs;
   1417     seq_param->seq_fields.bits.frame_mbs_only_flag = 1;
   1418 
   1419     if (frame_bit_rate > 0)
   1420         seq_param->bits_per_second = 1024 * frame_bit_rate; /* use kbps as input */
   1421     else
   1422         seq_param->bits_per_second = 0;
   1423 
   1424     seq_param->time_scale = 900;
   1425     seq_param->num_units_in_tick = 15;			/* Tc = num_units_in_tick / time_sacle */
   1426 
   1427     if (height_in_mbs * 16 - height) {
   1428         frame_cropping_flag = 1;
   1429         frame_crop_bottom_offset =
   1430             (height_in_mbs * 16 - height) / (2 * (!seq_param->seq_fields.bits.frame_mbs_only_flag + 1));
   1431     }
   1432 
   1433     seq_param->frame_cropping_flag = frame_cropping_flag;
   1434     seq_param->frame_crop_left_offset = 0;
   1435     seq_param->frame_crop_right_offset = 0;
   1436     seq_param->frame_crop_top_offset = 0;
   1437     seq_param->frame_crop_bottom_offset = frame_crop_bottom_offset;
   1438 
   1439     seq_param->seq_fields.bits.pic_order_cnt_type = 0;
   1440     seq_param->seq_fields.bits.direct_8x8_inference_flag = 0;
   1441 
   1442     seq_param->seq_fields.bits.log2_max_frame_num_minus4 = 0;
   1443     seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = 2;
   1444 
   1445     if (frame_bit_rate > 0)
   1446         seq_param->vui_parameters_present_flag = 1;	//HRD info located in vui
   1447     else
   1448         seq_param->vui_parameters_present_flag = 0;
   1449 }
   1450 
   1451 static void avcenc_context_pic_param_init(VAEncPictureParameterBufferH264 *pic_param)
   1452 {
   1453     pic_param->seq_parameter_set_id = 0;
   1454     pic_param->pic_parameter_set_id = 0;
   1455 
   1456     pic_param->last_picture = 0;
   1457     pic_param->frame_num = 0;
   1458 
   1459     pic_param->pic_init_qp = (qp_value >= 0 ?  qp_value : 26);
   1460     pic_param->num_ref_idx_l0_active_minus1 = 0;
   1461     pic_param->num_ref_idx_l1_active_minus1 = 0;
   1462 
   1463     pic_param->pic_fields.bits.idr_pic_flag = 0;
   1464     pic_param->pic_fields.bits.reference_pic_flag = 0;
   1465     pic_param->pic_fields.bits.entropy_coding_mode_flag = ENTROPY_MODE_CABAC;
   1466     pic_param->pic_fields.bits.weighted_pred_flag = 0;
   1467     pic_param->pic_fields.bits.weighted_bipred_idc = 0;
   1468 
   1469     if (avcenc_context.constraint_set_flag & 0x7)
   1470         pic_param->pic_fields.bits.transform_8x8_mode_flag = 0;
   1471     else
   1472         pic_param->pic_fields.bits.transform_8x8_mode_flag = 1;
   1473 
   1474     pic_param->pic_fields.bits.deblocking_filter_control_present_flag = 1;
   1475 }
   1476 
   1477 static void avcenc_context_sei_init()
   1478 {
   1479 	int init_cpb_size;
   1480 	int target_bit_rate;
   1481 
   1482 	/* it comes for the bps defined in SPS */
   1483 	target_bit_rate = avcenc_context.seq_param.bits_per_second;
   1484 	init_cpb_size = (target_bit_rate * 8) >> 10;
   1485 	avcenc_context.i_initial_cpb_removal_delay = init_cpb_size * 0.5 * 1024 / target_bit_rate * 90000;
   1486 
   1487 	avcenc_context.i_cpb_removal_delay = 2;
   1488 	avcenc_context.i_initial_cpb_removal_delay_length = 24;
   1489 	avcenc_context.i_cpb_removal_delay_length = 24;
   1490 	avcenc_context.i_dpb_output_delay_length = 24;
   1491 }
   1492 
   1493 static void avcenc_context_init(int width, int height)
   1494 {
   1495     int i;
   1496     memset(&avcenc_context, 0, sizeof(avcenc_context));
   1497     avcenc_context.profile = VAProfileH264Main;
   1498 
   1499     switch (avcenc_context.profile) {
   1500     case VAProfileH264Baseline:
   1501         avcenc_context.constraint_set_flag |= (1 << 0); /* Annex A.2.1 */
   1502         break;
   1503 
   1504     case VAProfileH264Main:
   1505         avcenc_context.constraint_set_flag |= (1 << 1); /* Annex A.2.2 */
   1506         break;
   1507 
   1508     case VAProfileH264High:
   1509         avcenc_context.constraint_set_flag |= (1 << 3); /* Annex A.2.4 */
   1510         break;
   1511 
   1512     default:
   1513         break;
   1514     }
   1515 
   1516     avcenc_context.seq_param_buf_id = VA_INVALID_ID;
   1517     avcenc_context.pic_param_buf_id = VA_INVALID_ID;
   1518     avcenc_context.packed_seq_header_param_buf_id = VA_INVALID_ID;
   1519     avcenc_context.packed_seq_buf_id = VA_INVALID_ID;
   1520     avcenc_context.packed_pic_header_param_buf_id = VA_INVALID_ID;
   1521     avcenc_context.packed_pic_buf_id = VA_INVALID_ID;
   1522     avcenc_context.codedbuf_buf_id = VA_INVALID_ID;
   1523     avcenc_context.misc_parameter_hrd_buf_id = VA_INVALID_ID;
   1524     avcenc_context.codedbuf_i_size = width * height;
   1525     avcenc_context.codedbuf_pb_size = 0;
   1526     avcenc_context.current_input_surface = SID_INPUT_PICTURE_0;
   1527     avcenc_context.upload_thread_value = -1;
   1528     avcenc_context.packed_sei_header_param_buf_id = VA_INVALID_ID;
   1529     avcenc_context.packed_sei_buf_id = VA_INVALID_ID;
   1530 
   1531     if (qp_value == -1)
   1532         avcenc_context.rate_control_method = VA_RC_CBR;
   1533     else if (qp_value == -2)
   1534         avcenc_context.rate_control_method = VA_RC_VBR;
   1535     else {
   1536         assert(qp_value >= 0 && qp_value <= 51);
   1537         avcenc_context.rate_control_method = VA_RC_CQP;
   1538     }
   1539 
   1540     for (i = 0; i < MAX_SLICES; i++) {
   1541         avcenc_context.slice_param_buf_id[i] = VA_INVALID_ID;
   1542     }
   1543 
   1544     avcenc_context_seq_param_init(&avcenc_context.seq_param, width, height);
   1545     avcenc_context_pic_param_init(&avcenc_context.pic_param);
   1546     if (avcenc_context.rate_control_method == VA_RC_CBR)
   1547 	avcenc_context_sei_init();
   1548 }
   1549 
   1550 int main(int argc, char *argv[])
   1551 {
   1552     int f;
   1553     FILE *yuv_fp;
   1554     FILE *avc_fp;
   1555     off_t file_size;
   1556     int i_frame_only=0,i_p_frame_only=1;
   1557     int mode_value;
   1558     struct timeval tpstart,tpend;
   1559     float  timeuse;
   1560 
   1561     va_init_display_args(&argc, argv);
   1562 
   1563     //TODO may be we should using option analytics library
   1564     if(argc != 5 && argc != 6 && argc != 7) {
   1565         show_help();
   1566         return -1;
   1567     }
   1568 
   1569     picture_width = atoi(argv[1]);
   1570     picture_height = atoi(argv[2]);
   1571     picture_width_in_mbs = (picture_width + 15) / 16;
   1572     picture_height_in_mbs = (picture_height + 15) / 16;
   1573 
   1574     if (argc == 6 || argc == 7) {
   1575         qp_value = -1;
   1576         sscanf(argv[5], "qp=%d", &qp_value);
   1577         if ( qp_value == -1 ) {
   1578             frame_bit_rate = -1;
   1579             sscanf(argv[5], "fb=%d", &frame_bit_rate);
   1580             if (  frame_bit_rate == -1 ) {
   1581                 show_help();
   1582                 return -1;
   1583             }
   1584         } else if (qp_value > 51) {
   1585             qp_value = 51;
   1586         } else if (qp_value < 0) {
   1587             qp_value = 0;
   1588         }
   1589     } else
   1590         qp_value = 28;                          //default const QP mode
   1591 
   1592     if (argc == 7) {
   1593         sscanf(argv[6], "mode=%d", &mode_value);
   1594         if ( mode_value == 0 ) {
   1595                 i_frame_only = 1;
   1596 		i_p_frame_only = 0;
   1597         }
   1598         else if ( mode_value == 1) {
   1599 		i_frame_only = 0;
   1600                 i_p_frame_only = 1;
   1601         }
   1602         else if ( mode_value == 2 ) {
   1603 		i_frame_only = 0;
   1604                 i_p_frame_only = 0;
   1605         }
   1606         else {
   1607                 printf("mode_value=%d\n",mode_value);
   1608                 show_help();
   1609                 return -1;
   1610         }
   1611     }
   1612 
   1613     yuv_fp = fopen(argv[3],"rb");
   1614     if ( yuv_fp == NULL){
   1615         printf("Can't open input YUV file\n");
   1616         return -1;
   1617     }
   1618     fseeko(yuv_fp, (off_t)0, SEEK_END);
   1619     file_size = ftello(yuv_fp);
   1620     frame_size = picture_width * picture_height +  ((picture_width * picture_height) >> 1) ;
   1621 
   1622     if ( (file_size < frame_size) || (file_size % frame_size) ) {
   1623         fclose(yuv_fp);
   1624         printf("The YUV file's size is not correct\n");
   1625         return -1;
   1626     }
   1627     frame_number = file_size / frame_size;
   1628     fseeko(yuv_fp, (off_t)0, SEEK_SET);
   1629 
   1630     avc_fp = fopen(argv[4], "wb");
   1631     if ( avc_fp == NULL) {
   1632         fclose(yuv_fp);
   1633         printf("Can't open output avc file\n");
   1634         return -1;
   1635     }
   1636     gettimeofday(&tpstart,NULL);
   1637     avcenc_context_init(picture_width, picture_height);
   1638     create_encode_pipe();
   1639     alloc_encode_resource(yuv_fp);
   1640 
   1641     enc_frame_number = 0;
   1642     for ( f = 0; f < frame_number; ) {		//picture level loop
   1643         static int const frame_type_pattern[][2] = { {SLICE_TYPE_I,1},
   1644                                                      {SLICE_TYPE_P,3}, {SLICE_TYPE_P,3},{SLICE_TYPE_P,3},
   1645                                                      {SLICE_TYPE_P,3}, {SLICE_TYPE_P,3},{SLICE_TYPE_P,3},
   1646                                                      {SLICE_TYPE_P,3}, {SLICE_TYPE_P,3},{SLICE_TYPE_P,3},
   1647                                                      {SLICE_TYPE_P,2} };
   1648 
   1649         if ( i_frame_only ) {
   1650             encode_picture(yuv_fp, avc_fp,enc_frame_number, f, f==0, SLICE_TYPE_I, 0, f+1);
   1651             f++;
   1652             enc_frame_number++;
   1653         } else if ( i_p_frame_only ) {
   1654             if ( (f % intra_period) == 0 ) {
   1655                 encode_picture(yuv_fp, avc_fp,enc_frame_number, f, f==0, SLICE_TYPE_I, 0, f+1);
   1656                 f++;
   1657                 enc_frame_number++;
   1658             } else {
   1659                 encode_picture(yuv_fp, avc_fp,enc_frame_number, f, f==0, SLICE_TYPE_P, 0, f+1);
   1660                 f++;
   1661                 enc_frame_number++;
   1662             }
   1663         } else { // follow the i,p,b pattern
   1664             static int fcurrent = 0;
   1665             int fnext;
   1666 
   1667             fcurrent = fcurrent % (sizeof(frame_type_pattern)/sizeof(int[2]));
   1668             fnext = (fcurrent+1) % (sizeof(frame_type_pattern)/sizeof(int[2]));
   1669 
   1670             if ( frame_type_pattern[fcurrent][0] == SLICE_TYPE_I ) {
   1671                 encode_picture(yuv_fp, avc_fp,enc_frame_number, f, f==0, SLICE_TYPE_I, 0,
   1672                         f+frame_type_pattern[fnext][1]);
   1673                 f++;
   1674                 enc_frame_number++;
   1675             } else {
   1676                 encode_pb_pictures(yuv_fp, avc_fp, f, frame_type_pattern[fcurrent][1]-1,
   1677                         f + frame_type_pattern[fcurrent][1] + frame_type_pattern[fnext][1] -1 );
   1678                 f += frame_type_pattern[fcurrent][1];
   1679                 enc_frame_number++;
   1680             }
   1681 
   1682             fcurrent++;
   1683         }
   1684         printf("\r %d/%d ...", f+1, frame_number);
   1685         fflush(stdout);
   1686     }
   1687 
   1688     gettimeofday(&tpend,NULL);
   1689     timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+ tpend.tv_usec-tpstart.tv_usec;
   1690     timeuse/=1000000;
   1691     printf("\ndone!\n");
   1692     printf("encode %d frames in %f secondes, FPS is %.1f\n",frame_number, timeuse, frame_number/timeuse);
   1693     release_encode_resource();
   1694     destory_encode_pipe();
   1695 
   1696     fclose(yuv_fp);
   1697     fclose(avc_fp);
   1698 
   1699     return 0;
   1700 }
   1701