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 
create_encode_pipe()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 
destory_encode_pipe()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 *
upload_thread_function(void * data)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 
alloc_encode_resource(FILE * yuv_fp)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 
release_encode_resource()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 
avcenc_update_sei_param(int frame_num)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 
avcenc_update_picture_parameter(int slice_type,int frame_num,int display_num,int is_idr)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 
upload_yuv_to_surface(FILE * yuv_fp,VASurfaceID surface_id)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 
avcenc_update_slice_parameter(int slice_type)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 
begin_picture(FILE * yuv_fp,int frame_num,int display_num,int slice_type,int is_idr)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 
avcenc_render_picture()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 
avcenc_destroy_buffers(VABufferID * va_buffers,unsigned int num_va_buffers)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 
end_picture(int slice_type,int next_is_bpic)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
va_swap32(unsigned int val)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
bitstream_start(bitstream * bs)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
bitstream_end(bitstream * bs)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
bitstream_put_ui(bitstream * bs,unsigned int val,int size_in_bits)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
bitstream_put_ue(bitstream * bs,unsigned int val)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
bitstream_put_se(bitstream * bs,int val)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
bitstream_byte_aligning(bitstream * bs,int bit)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
rbsp_trailing_bits(bitstream * bs)862 rbsp_trailing_bits(bitstream *bs)
863 {
864     bitstream_put_ui(bs, 1, 1);
865     bitstream_byte_aligning(bs, 0);
866 }
867 
nal_start_code_prefix(bitstream * bs)868 static void nal_start_code_prefix(bitstream *bs)
869 {
870     bitstream_put_ui(bs, 0x00000001, 32);
871 }
872 
nal_header(bitstream * bs,int nal_ref_idc,int nal_unit_type)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 
sps_rbsp(bitstream * bs)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 
pps_rbsp(bitstream * bs)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
build_packed_pic_buffer(unsigned char ** header_buffer)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
build_packed_seq_buffer(unsigned char ** header_buffer)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
build_packed_sei_buffer_timing(unsigned int init_cpb_removal_length,unsigned int init_cpb_removal_delay,unsigned int init_cpb_removal_delay_offset,unsigned int cpb_removal_length,unsigned int cpb_removal_delay,unsigned int dpb_output_length,unsigned int dpb_output_delay,unsigned char ** sei_buffer)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
store_coded_buffer(FILE * avc_fp,int slice_type)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
encode_picture(FILE * yuv_fp,FILE * avc_fp,int frame_num,int display_num,int is_idr,int slice_type,int next_is_bpic,int next_display_num)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 
encode_pb_pictures(FILE * yuv_fp,FILE * avc_fp,int f,int nbframes,int next_f)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 
show_help()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 
avcenc_context_seq_param_init(VAEncSequenceParameterBufferH264 * seq_param,int width,int height)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 
avcenc_context_pic_param_init(VAEncPictureParameterBufferH264 * pic_param)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 
avcenc_context_sei_init()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 
avcenc_context_init(int width,int height)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 
main(int argc,char * argv[])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