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