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