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