2 * Copyright (c) 2012 Intel Corporation. All Rights Reserved.
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:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
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.
25 * Simple AVC encoder based on libVA.
28 * ./avcenc <width> <height> <input file> <output file> [qp]
39 #include <sys/types.h>
48 #include <va/va_enc_h264.h>
49 #include "va_display.h"
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
61 #define SLICE_TYPE_P 0
62 #define SLICE_TYPE_B 1
63 #define SLICE_TYPE_I 2
65 #define ENTROPY_MODE_CAVLC 0
66 #define ENTROPY_MODE_CABAC 1
68 #define PROFILE_IDC_BASELINE 66
69 #define PROFILE_IDC_MAIN 77
70 #define PROFILE_IDC_HIGH 100
72 #define CHECK_VASTATUS(va_status,func) \
73 if (va_status != VA_STATUS_SUCCESS) { \
74 fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
78 static VADisplay va_dpy;
80 static int picture_width, picture_width_in_mbs;
81 static int picture_height, picture_height_in_mbs;
82 static int frame_size;
83 static unsigned char *newImageBuffer = 0;
85 static int qp_value = 26;
87 static int intra_period = 30;
88 static int pb_period = 5;
89 static int frame_bit_rate = -1;
94 build_packed_pic_buffer(unsigned char **header_buffer);
97 build_packed_seq_buffer(unsigned char **header_buffer);
99 struct upload_thread_param
102 VASurfaceID surface_id;
106 upload_yuv_to_surface(FILE *yuv_fp, VASurfaceID surface_id);
110 int constraint_set_flag;
111 VAEncSequenceParameterBufferH264 seq_param;
112 VAEncPictureParameterBufferH264 pic_param;
113 VAEncSliceParameterBufferH264 slice_param[MAX_SLICES];
114 VAContextID context_id;
115 VAConfigID config_id;
116 VABufferID seq_param_buf_id; /* Sequence level parameter */
117 VABufferID pic_param_buf_id; /* Picture level parameter */
118 VABufferID slice_param_buf_id[MAX_SLICES]; /* Slice level parameter, multil slices */
119 VABufferID codedbuf_buf_id; /* Output buffer, compressed data */
120 VABufferID packed_seq_header_param_buf_id;
121 VABufferID packed_seq_buf_id;
122 VABufferID packed_pic_header_param_buf_id;
123 VABufferID packed_pic_buf_id;
124 VABufferID misc_parameter_hrd_buf_id;
128 int codedbuf_pb_size;
129 int current_input_surface;
130 int rate_control_method;
131 struct upload_thread_param upload_thread_param;
132 pthread_t upload_thread_id;
133 int upload_thread_value;
136 static void create_encode_pipe()
138 VAEntrypoint entrypoints[5];
139 int num_entrypoints,slice_entrypoint;
140 VAConfigAttrib attrib[2];
141 int major_ver, minor_ver;
144 va_dpy = va_open_display();
145 va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
146 CHECK_VASTATUS(va_status, "vaInitialize");
148 vaQueryConfigEntrypoints(va_dpy, avcenc_context.profile, entrypoints,
151 for (slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypoint++) {
152 if (entrypoints[slice_entrypoint] == VAEntrypointEncSlice)
156 if (slice_entrypoint == num_entrypoints) {
157 /* not find Slice entry point */
161 /* find out the format for the render target, and rate control mode */
162 attrib[0].type = VAConfigAttribRTFormat;
163 attrib[1].type = VAConfigAttribRateControl;
164 vaGetConfigAttributes(va_dpy, avcenc_context.profile, VAEntrypointEncSlice,
167 if ((attrib[0].value & VA_RT_FORMAT_YUV420) == 0) {
168 /* not find desired YUV420 RT format */
172 if ((attrib[1].value & avcenc_context.rate_control_method) == 0) {
173 /* Can't find matched RC mode */
174 printf("Can't find the desired RC mode, exit\n");
178 attrib[0].value = VA_RT_FORMAT_YUV420; /* set to desired RT format */
179 attrib[1].value = avcenc_context.rate_control_method; /* set to desired RC mode */
181 va_status = vaCreateConfig(va_dpy, avcenc_context.profile, VAEntrypointEncSlice,
182 &attrib[0], 2,&avcenc_context.config_id);
183 CHECK_VASTATUS(va_status, "vaCreateConfig");
185 /* Create a context for this decode pipe */
186 va_status = vaCreateContext(va_dpy, avcenc_context.config_id,
187 picture_width, picture_height,
190 &avcenc_context.context_id);
191 CHECK_VASTATUS(va_status, "vaCreateContext");
194 static void destory_encode_pipe()
196 vaDestroyContext(va_dpy,avcenc_context.context_id);
197 vaDestroyConfig(va_dpy,avcenc_context.config_id);
199 va_close_display(va_dpy);
202 /***************************************************
204 * The encode pipe resource define
206 ***************************************************/
207 #define SID_INPUT_PICTURE_0 0
208 #define SID_INPUT_PICTURE_1 1
209 #define SID_REFERENCE_PICTURE_L0 2
210 #define SID_REFERENCE_PICTURE_L1 3
211 #define SID_RECON_PICTURE 4
212 #define SID_NUMBER SID_RECON_PICTURE + 1
213 static VASurfaceID surface_ids[SID_NUMBER];
215 static int frame_number;
216 static int enc_frame_number;
218 /***************************************************/
221 upload_thread_function(void *data)
223 struct upload_thread_param *param = data;
225 upload_yuv_to_surface(param->yuv_fp, param->surface_id);
230 static void alloc_encode_resource(FILE *yuv_fp)
235 va_status = vaCreateSurfaces(va_dpy, picture_width, picture_height,
236 VA_RT_FORMAT_YUV420, SID_NUMBER, &surface_ids[0]);
237 CHECK_VASTATUS(va_status, "vaCreateSurfaces");
239 newImageBuffer = (unsigned char *)malloc(frame_size);
241 /* firstly upload YUV data to SID_INPUT_PICTURE_1 */
242 avcenc_context.upload_thread_param.yuv_fp = yuv_fp;
243 avcenc_context.upload_thread_param.surface_id = surface_ids[SID_INPUT_PICTURE_1];
245 avcenc_context.upload_thread_value = pthread_create(&avcenc_context.upload_thread_id,
247 upload_thread_function,
248 (void*)&avcenc_context.upload_thread_param);
251 static void release_encode_resource()
253 pthread_join(avcenc_context.upload_thread_id, NULL);
254 free(newImageBuffer);
256 // Release all the surfaces resource
257 vaDestroySurfaces(va_dpy, &surface_ids[0], SID_NUMBER);
260 static void avcenc_update_picture_parameter(int slice_type, int frame_num, int display_num, int is_idr)
262 VAEncPictureParameterBufferH264 *pic_param;
266 pic_param = &avcenc_context.pic_param;
267 pic_param->CurrPic.picture_id = surface_ids[SID_RECON_PICTURE];
268 pic_param->CurrPic.TopFieldOrderCnt = display_num * 2;
269 pic_param->ReferenceFrames[0].picture_id = surface_ids[SID_REFERENCE_PICTURE_L0];
270 pic_param->ReferenceFrames[1].picture_id = surface_ids[SID_REFERENCE_PICTURE_L1];
271 pic_param->ReferenceFrames[2].picture_id = VA_INVALID_ID;
272 assert(avcenc_context.codedbuf_buf_id != VA_INVALID_ID);
273 pic_param->coded_buf = avcenc_context.codedbuf_buf_id;
274 pic_param->frame_num = frame_num;
275 pic_param->pic_fields.bits.idr_pic_flag = !!is_idr;
276 pic_param->pic_fields.bits.reference_pic_flag = (slice_type != SLICE_TYPE_B);
278 va_status = vaCreateBuffer(va_dpy,
279 avcenc_context.context_id,
280 VAEncPictureParameterBufferType,
281 sizeof(*pic_param), 1, pic_param,
282 &avcenc_context.pic_param_buf_id);
283 CHECK_VASTATUS(va_status,"vaCreateBuffer");
286 #ifndef VA_FOURCC_I420
287 #define VA_FOURCC_I420 0x30323449
290 static void upload_yuv_to_surface(FILE *yuv_fp, VASurfaceID surface_id)
292 VAImage surface_image;
294 void *surface_p = NULL;
295 unsigned char *y_src, *u_src, *v_src;
296 unsigned char *y_dst, *u_dst, *v_dst;
297 int y_size = picture_width * picture_height;
298 int u_size = (picture_width >> 1) * (picture_height >> 1);
303 n_items = fread(newImageBuffer, frame_size, 1, yuv_fp);
304 } while (n_items != 1);
306 va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
307 CHECK_VASTATUS(va_status,"vaDeriveImage");
309 vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
310 assert(VA_STATUS_SUCCESS == va_status);
312 y_src = newImageBuffer;
313 u_src = newImageBuffer + y_size; /* UV offset for NV12 */
314 v_src = newImageBuffer + y_size + u_size;
316 y_dst = surface_p + surface_image.offsets[0];
317 u_dst = surface_p + surface_image.offsets[1]; /* UV offset for NV12 */
318 v_dst = surface_p + surface_image.offsets[2];
321 for (row = 0; row < surface_image.height; row++) {
322 memcpy(y_dst, y_src, surface_image.width);
323 y_dst += surface_image.pitches[0];
324 y_src += picture_width;
327 if (surface_image.format.fourcc == VA_FOURCC_NV12) { /* UV plane */
328 for (row = 0; row < surface_image.height / 2; row++) {
329 for (col = 0; col < surface_image.width / 2; col++) {
330 u_dst[col * 2] = u_src[col];
331 u_dst[col * 2 + 1] = v_src[col];
334 u_dst += surface_image.pitches[1];
335 u_src += (picture_width / 2);
336 v_src += (picture_width / 2);
338 } else if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
339 surface_image.format.fourcc == VA_FOURCC_I420) {
340 const int U = surface_image.format.fourcc == VA_FOURCC_I420 ? 1 : 2;
341 const int V = surface_image.format.fourcc == VA_FOURCC_I420 ? 2 : 1;
343 u_dst = surface_p + surface_image.offsets[U];
344 v_dst = surface_p + surface_image.offsets[V];
346 for (row = 0; row < surface_image.height / 2; row++) {
347 memcpy(u_dst, u_src, surface_image.width / 2);
348 memcpy(v_dst, v_src, surface_image.width / 2);
349 u_dst += surface_image.pitches[U];
350 v_dst += surface_image.pitches[V];
351 u_src += (picture_width / 2);
352 v_src += (picture_width / 2);
356 vaUnmapBuffer(va_dpy, surface_image.buf);
357 vaDestroyImage(va_dpy, surface_image.image_id);
360 static void avcenc_update_slice_parameter(int slice_type)
362 VAEncSliceParameterBufferH264 *slice_param;
368 slice_param = &avcenc_context.slice_param[i];
369 slice_param->macroblock_address = 0;
370 slice_param->num_macroblocks = picture_height_in_mbs * picture_width_in_mbs;
371 slice_param->pic_parameter_set_id = 0;
372 slice_param->slice_type = slice_type;
373 slice_param->direct_spatial_mv_pred_flag = 0;
374 slice_param->num_ref_idx_l0_active_minus1 = 0; /* FIXME: ??? */
375 slice_param->num_ref_idx_l1_active_minus1 = 0;
376 slice_param->cabac_init_idc = 0;
377 slice_param->slice_qp_delta = 0;
378 slice_param->disable_deblocking_filter_idc = 0;
379 slice_param->slice_alpha_c0_offset_div2 = 2;
380 slice_param->slice_beta_offset_div2 = 2;
381 slice_param->idr_pic_id = 0;
383 /* FIXME: fill other fields */
385 va_status = vaCreateBuffer(va_dpy,
386 avcenc_context.context_id,
387 VAEncSliceParameterBufferType,
388 sizeof(*slice_param), 1, slice_param,
389 &avcenc_context.slice_param_buf_id[i]);
390 CHECK_VASTATUS(va_status,"vaCreateBuffer");;
394 slice_param = &avcenc_context.slice_param[i];
395 slice_param->macroblock_address = picture_height_in_mbs * picture_width_in_mbs / 2;
396 slice_param->num_macroblocks = picture_height_in_mbs * picture_width_in_mbs / 2;
397 slice_param->pic_parameter_set_id = 0;
398 slice_param->slice_type = slice_type;
399 slice_param->direct_spatial_mv_pred_flag = 0;
400 slice_param->num_ref_idx_l0_active_minus1 = 0; /* FIXME: ??? */
401 slice_param->num_ref_idx_l1_active_minus1 = 0;
402 slice_param->cabac_init_idc = 0;
403 slice_param->slice_qp_delta = 0;
404 slice_param->disable_deblocking_filter_idc = 0;
405 slice_param->slice_alpha_c0_offset_div2 = 2;
406 slice_param->slice_beta_offset_div2 = 2;
407 slice_param->idr_pic_id = 0;
409 /* FIXME: fill other fields */
411 va_status = vaCreateBuffer(va_dpy,
412 avcenc_context.context_id,
413 VAEncSliceParameterBufferType,
414 sizeof(*slice_param), 1, slice_param,
415 &avcenc_context.slice_param_buf_id[i]);
416 CHECK_VASTATUS(va_status,"vaCreateBuffer");;
420 avcenc_context.num_slices = i;
423 static int begin_picture(FILE *yuv_fp, int frame_num, int display_num, int slice_type, int is_idr)
427 if (avcenc_context.upload_thread_value != 0) {
428 fprintf(stderr, "FATAL error!!!\n");
432 pthread_join(avcenc_context.upload_thread_id, NULL);
434 avcenc_context.upload_thread_value = -1;
436 if (avcenc_context.current_input_surface == SID_INPUT_PICTURE_0)
437 avcenc_context.current_input_surface = SID_INPUT_PICTURE_1;
439 avcenc_context.current_input_surface = SID_INPUT_PICTURE_0;
441 if (frame_num == 0) {
442 VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
443 unsigned int length_in_bits, offset_in_bytes;
444 unsigned char *packed_seq_buffer = NULL, *packed_pic_buffer = NULL;
446 assert(slice_type == SLICE_TYPE_I);
447 length_in_bits = build_packed_seq_buffer(&packed_seq_buffer);
449 packed_header_param_buffer.type = VAEncPackedHeaderSequence;
450 packed_header_param_buffer.bit_length = length_in_bits;
451 packed_header_param_buffer.has_emulation_bytes = 0;
452 va_status = vaCreateBuffer(va_dpy,
453 avcenc_context.context_id,
454 VAEncPackedHeaderParameterBufferType,
455 sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
456 &avcenc_context.packed_seq_header_param_buf_id);
457 CHECK_VASTATUS(va_status,"vaCreateBuffer");
459 va_status = vaCreateBuffer(va_dpy,
460 avcenc_context.context_id,
461 VAEncPackedHeaderDataBufferType,
462 (length_in_bits + 7) / 8, 1, packed_seq_buffer,
463 &avcenc_context.packed_seq_buf_id);
464 CHECK_VASTATUS(va_status,"vaCreateBuffer");
466 length_in_bits = build_packed_pic_buffer(&packed_pic_buffer);
468 packed_header_param_buffer.type = VAEncPackedHeaderPicture;
469 packed_header_param_buffer.bit_length = length_in_bits;
470 packed_header_param_buffer.has_emulation_bytes = 0;
472 va_status = vaCreateBuffer(va_dpy,
473 avcenc_context.context_id,
474 VAEncPackedHeaderParameterBufferType,
475 sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
476 &avcenc_context.packed_pic_header_param_buf_id);
477 CHECK_VASTATUS(va_status,"vaCreateBuffer");
479 va_status = vaCreateBuffer(va_dpy,
480 avcenc_context.context_id,
481 VAEncPackedHeaderDataBufferType,
482 (length_in_bits + 7) / 8, 1, packed_pic_buffer,
483 &avcenc_context.packed_pic_buf_id);
484 CHECK_VASTATUS(va_status,"vaCreateBuffer");
486 free(packed_seq_buffer);
487 free(packed_pic_buffer);
490 /* sequence parameter set */
491 VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
492 va_status = vaCreateBuffer(va_dpy,
493 avcenc_context.context_id,
494 VAEncSequenceParameterBufferType,
495 sizeof(*seq_param), 1, seq_param,
496 &avcenc_context.seq_param_buf_id);
497 CHECK_VASTATUS(va_status,"vaCreateBuffer");
501 VAEncMiscParameterBuffer *misc_param;
502 VAEncMiscParameterHRD *misc_hrd_param;
503 vaCreateBuffer(va_dpy,
504 avcenc_context.context_id,
505 VAEncMiscParameterBufferType,
506 sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterRateControl),
509 &avcenc_context.misc_parameter_hrd_buf_id);
510 CHECK_VASTATUS(va_status, "vaCreateBuffer");
513 avcenc_context.misc_parameter_hrd_buf_id,
514 (void **)&misc_param);
515 misc_param->type = VAEncMiscParameterTypeHRD;
516 misc_hrd_param = (VAEncMiscParameterHRD *)misc_param->data;
518 if (frame_bit_rate > 0) {
519 misc_hrd_param->initial_buffer_fullness = frame_bit_rate * 1024 * 4;
520 misc_hrd_param->buffer_size = frame_bit_rate * 1024 * 8;
522 misc_hrd_param->initial_buffer_fullness = 0;
523 misc_hrd_param->buffer_size = 0;
526 vaUnmapBuffer(va_dpy, avcenc_context.misc_parameter_hrd_buf_id);
528 /* slice parameter */
529 avcenc_update_slice_parameter(slice_type);
534 int avcenc_render_picture()
537 VABufferID va_buffers[8];
538 unsigned int num_va_buffers = 0;
541 va_buffers[num_va_buffers++] = avcenc_context.seq_param_buf_id;
542 va_buffers[num_va_buffers++] = avcenc_context.pic_param_buf_id;
544 if (avcenc_context.packed_seq_header_param_buf_id != VA_INVALID_ID)
545 va_buffers[num_va_buffers++] = avcenc_context.packed_seq_header_param_buf_id;
547 if (avcenc_context.packed_seq_buf_id != VA_INVALID_ID)
548 va_buffers[num_va_buffers++] = avcenc_context.packed_seq_buf_id;
550 if (avcenc_context.packed_pic_header_param_buf_id != VA_INVALID_ID)
551 va_buffers[num_va_buffers++] = avcenc_context.packed_pic_header_param_buf_id;
553 if (avcenc_context.packed_pic_buf_id != VA_INVALID_ID)
554 va_buffers[num_va_buffers++] = avcenc_context.packed_pic_buf_id;
556 if (avcenc_context.misc_parameter_hrd_buf_id != VA_INVALID_ID)
557 va_buffers[num_va_buffers++] = avcenc_context.misc_parameter_hrd_buf_id;
559 va_status = vaBeginPicture(va_dpy,
560 avcenc_context.context_id,
561 surface_ids[avcenc_context.current_input_surface]);
562 CHECK_VASTATUS(va_status,"vaBeginPicture");
564 va_status = vaRenderPicture(va_dpy,
565 avcenc_context.context_id,
568 CHECK_VASTATUS(va_status,"vaRenderPicture");
570 for(i = 0; i < avcenc_context.num_slices; i++) {
571 va_status = vaRenderPicture(va_dpy,
572 avcenc_context.context_id,
573 &avcenc_context.slice_param_buf_id[i],
575 CHECK_VASTATUS(va_status,"vaRenderPicture");
578 va_status = vaEndPicture(va_dpy, avcenc_context.context_id);
579 CHECK_VASTATUS(va_status,"vaEndPicture");
584 static int avcenc_destroy_buffers(VABufferID *va_buffers, unsigned int num_va_buffers)
589 for (i = 0; i < num_va_buffers; i++) {
590 if (va_buffers[i] != VA_INVALID_ID) {
591 va_status = vaDestroyBuffer(va_dpy, va_buffers[i]);
592 CHECK_VASTATUS(va_status,"vaDestroyBuffer");
593 va_buffers[i] = VA_INVALID_ID;
600 static void end_picture(int slice_type, int next_is_bpic)
604 /* Prepare for next picture */
605 tempID = surface_ids[SID_RECON_PICTURE];
607 if (slice_type != SLICE_TYPE_B) {
609 surface_ids[SID_RECON_PICTURE] = surface_ids[SID_REFERENCE_PICTURE_L1];
610 surface_ids[SID_REFERENCE_PICTURE_L1] = tempID;
612 surface_ids[SID_RECON_PICTURE] = surface_ids[SID_REFERENCE_PICTURE_L0];
613 surface_ids[SID_REFERENCE_PICTURE_L0] = tempID;
617 surface_ids[SID_RECON_PICTURE] = surface_ids[SID_REFERENCE_PICTURE_L0];
618 surface_ids[SID_REFERENCE_PICTURE_L0] = surface_ids[SID_REFERENCE_PICTURE_L1];
619 surface_ids[SID_REFERENCE_PICTURE_L1] = tempID;
623 avcenc_destroy_buffers(&avcenc_context.seq_param_buf_id, 1);
624 avcenc_destroy_buffers(&avcenc_context.pic_param_buf_id, 1);
625 avcenc_destroy_buffers(&avcenc_context.packed_seq_header_param_buf_id, 1);
626 avcenc_destroy_buffers(&avcenc_context.packed_seq_buf_id, 1);
627 avcenc_destroy_buffers(&avcenc_context.packed_pic_header_param_buf_id, 1);
628 avcenc_destroy_buffers(&avcenc_context.packed_pic_buf_id, 1);
629 avcenc_destroy_buffers(&avcenc_context.slice_param_buf_id[0], avcenc_context.num_slices);
630 avcenc_destroy_buffers(&avcenc_context.codedbuf_buf_id, 1);
631 avcenc_destroy_buffers(&avcenc_context.misc_parameter_hrd_buf_id, 1);
633 memset(avcenc_context.slice_param, 0, sizeof(avcenc_context.slice_param));
634 avcenc_context.num_slices = 0;
637 #define BITSTREAM_ALLOCATE_STEPPING 4096
640 unsigned int *buffer;
642 int max_size_in_dword;
645 typedef struct __bitstream bitstream;
649 get_coded_bitsteam_length(unsigned char *buffer, int buffer_length)
653 for (i = 0; i < buffer_length - 3; i++) {
666 va_swap32(unsigned int val)
668 unsigned char *pval = (unsigned char *)&val;
670 return ((pval[0] << 24) |
677 bitstream_start(bitstream *bs)
679 bs->max_size_in_dword = BITSTREAM_ALLOCATE_STEPPING;
680 bs->buffer = calloc(bs->max_size_in_dword * sizeof(int), 1);
685 bitstream_end(bitstream *bs)
687 int pos = (bs->bit_offset >> 5);
688 int bit_offset = (bs->bit_offset & 0x1f);
689 int bit_left = 32 - bit_offset;
692 bs->buffer[pos] = va_swap32((bs->buffer[pos] << bit_left));
697 bitstream_put_ui(bitstream *bs, unsigned int val, int size_in_bits)
699 int pos = (bs->bit_offset >> 5);
700 int bit_offset = (bs->bit_offset & 0x1f);
701 int bit_left = 32 - bit_offset;
706 bs->bit_offset += size_in_bits;
708 if (bit_left > size_in_bits) {
709 bs->buffer[pos] = (bs->buffer[pos] << size_in_bits | val);
711 size_in_bits -= bit_left;
712 bs->buffer[pos] = (bs->buffer[pos] << bit_left) | (val >> size_in_bits);
713 bs->buffer[pos] = va_swap32(bs->buffer[pos]);
715 if (pos + 1 == bs->max_size_in_dword) {
716 bs->max_size_in_dword += BITSTREAM_ALLOCATE_STEPPING;
717 bs->buffer = realloc(bs->buffer, bs->max_size_in_dword * sizeof(unsigned int));
720 bs->buffer[pos + 1] = val;
725 bitstream_put_ue(bitstream *bs, unsigned int val)
727 int size_in_bits = 0;
735 bitstream_put_ui(bs, 0, size_in_bits - 1); // leading zero
736 bitstream_put_ui(bs, val, size_in_bits);
740 bitstream_put_se(bitstream *bs, int val)
742 unsigned int new_val;
747 new_val = 2 * val - 1;
749 bitstream_put_ue(bs, new_val);
753 bitstream_byte_aligning(bitstream *bs, int bit)
755 int bit_offset = (bs->bit_offset & 0x7);
756 int bit_left = 8 - bit_offset;
762 assert(bit == 0 || bit == 1);
765 new_val = (1 << bit_left) - 1;
769 bitstream_put_ui(bs, new_val, bit_left);
773 rbsp_trailing_bits(bitstream *bs)
775 bitstream_put_ui(bs, 1, 1);
776 bitstream_byte_aligning(bs, 0);
779 static void nal_start_code_prefix(bitstream *bs)
781 bitstream_put_ui(bs, 0x00000001, 32);
784 static void nal_header(bitstream *bs, int nal_ref_idc, int nal_unit_type)
786 bitstream_put_ui(bs, 0, 1); /* forbidden_zero_bit: 0 */
787 bitstream_put_ui(bs, nal_ref_idc, 2);
788 bitstream_put_ui(bs, nal_unit_type, 5);
791 static void sps_rbsp(bitstream *bs)
793 VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
794 int profile_idc = PROFILE_IDC_BASELINE;
796 if (avcenc_context.profile == VAProfileH264High)
797 profile_idc = PROFILE_IDC_HIGH;
798 else if (avcenc_context.profile == VAProfileH264Main)
799 profile_idc = PROFILE_IDC_MAIN;
801 bitstream_put_ui(bs, profile_idc, 8); /* profile_idc */
802 bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 1), 1); /* constraint_set0_flag */
803 bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 2), 1); /* constraint_set1_flag */
804 bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 4), 1); /* constraint_set2_flag */
805 bitstream_put_ui(bs, !!(avcenc_context.constraint_set_flag & 8), 1); /* constraint_set3_flag */
806 bitstream_put_ui(bs, 0, 4); /* reserved_zero_4bits */
807 bitstream_put_ui(bs, seq_param->level_idc, 8); /* level_idc */
808 bitstream_put_ue(bs, seq_param->seq_parameter_set_id); /* seq_parameter_set_id */
810 if ( profile_idc == PROFILE_IDC_HIGH) {
811 bitstream_put_ue(bs, 1); /* chroma_format_idc = 1, 4:2:0 */
812 bitstream_put_ue(bs, 0); /* bit_depth_luma_minus8 */
813 bitstream_put_ue(bs, 0); /* bit_depth_chroma_minus8 */
814 bitstream_put_ui(bs, 0, 1); /* qpprime_y_zero_transform_bypass_flag */
815 bitstream_put_ui(bs, 0, 1); /* seq_scaling_matrix_present_flag */
818 bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
819 bitstream_put_ue(bs, seq_param->seq_fields.bits.pic_order_cnt_type); /* pic_order_cnt_type */
821 if (seq_param->seq_fields.bits.pic_order_cnt_type == 0)
822 bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4); /* log2_max_pic_order_cnt_lsb_minus4 */
827 bitstream_put_ue(bs, seq_param->max_num_ref_frames); /* num_ref_frames */
828 bitstream_put_ui(bs, 0, 1); /* gaps_in_frame_num_value_allowed_flag */
830 bitstream_put_ue(bs, seq_param->picture_width_in_mbs - 1); /* pic_width_in_mbs_minus1 */
831 bitstream_put_ue(bs, seq_param->picture_height_in_mbs - 1); /* pic_height_in_map_units_minus1 */
832 bitstream_put_ui(bs, seq_param->seq_fields.bits.frame_mbs_only_flag, 1); /* frame_mbs_only_flag */
834 if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {
838 bitstream_put_ui(bs, seq_param->seq_fields.bits.direct_8x8_inference_flag, 1); /* direct_8x8_inference_flag */
839 bitstream_put_ui(bs, seq_param->frame_cropping_flag, 1); /* frame_cropping_flag */
841 if (seq_param->frame_cropping_flag) {
842 bitstream_put_ue(bs, seq_param->frame_crop_left_offset); /* frame_crop_left_offset */
843 bitstream_put_ue(bs, seq_param->frame_crop_right_offset); /* frame_crop_right_offset */
844 bitstream_put_ue(bs, seq_param->frame_crop_top_offset); /* frame_crop_top_offset */
845 bitstream_put_ue(bs, seq_param->frame_crop_bottom_offset); /* frame_crop_bottom_offset */
848 if ( frame_bit_rate < 0 ) {
849 bitstream_put_ui(bs, 0, 1); /* vui_parameters_present_flag */
851 bitstream_put_ui(bs, 1, 1); /* vui_parameters_present_flag */
852 bitstream_put_ui(bs, 0, 1); /* aspect_ratio_info_present_flag */
853 bitstream_put_ui(bs, 0, 1); /* overscan_info_present_flag */
854 bitstream_put_ui(bs, 0, 1); /* video_signal_type_present_flag */
855 bitstream_put_ui(bs, 0, 1); /* chroma_loc_info_present_flag */
856 bitstream_put_ui(bs, 1, 1); /* timing_info_present_flag */
858 bitstream_put_ui(bs, 15, 32);
859 bitstream_put_ui(bs, 900, 32);
860 bitstream_put_ui(bs, 1, 1);
862 bitstream_put_ui(bs, 1, 1); /* nal_hrd_parameters_present_flag */
865 bitstream_put_ue(bs, 0); /* cpb_cnt_minus1 */
866 bitstream_put_ui(bs, 4, 4); /* bit_rate_scale */
867 bitstream_put_ui(bs, 6, 4); /* cpb_size_scale */
869 bitstream_put_ue(bs, frame_bit_rate - 1); /* bit_rate_value_minus1[0] */
870 bitstream_put_ue(bs, frame_bit_rate*8 - 1); /* cpb_size_value_minus1[0] */
871 bitstream_put_ui(bs, 1, 1); /* cbr_flag[0] */
873 bitstream_put_ui(bs, 23, 5); /* initial_cpb_removal_delay_length_minus1 */
874 bitstream_put_ui(bs, 23, 5); /* cpb_removal_delay_length_minus1 */
875 bitstream_put_ui(bs, 23, 5); /* dpb_output_delay_length_minus1 */
876 bitstream_put_ui(bs, 23, 5); /* time_offset_length */
878 bitstream_put_ui(bs, 0, 1); /* vcl_hrd_parameters_present_flag */
879 bitstream_put_ui(bs, 0, 1); /* low_delay_hrd_flag */
881 bitstream_put_ui(bs, 0, 1); /* pic_struct_present_flag */
882 bitstream_put_ui(bs, 0, 1); /* bitstream_restriction_flag */
885 rbsp_trailing_bits(bs); /* rbsp_trailing_bits */
889 static void build_nal_sps(FILE *avc_fp)
893 bitstream_start(&bs);
894 nal_start_code_prefix(&bs);
895 nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
897 bitstream_end(&bs, avc_fp);
901 static void pps_rbsp(bitstream *bs)
903 VAEncPictureParameterBufferH264 *pic_param = &avcenc_context.pic_param;
905 bitstream_put_ue(bs, pic_param->pic_parameter_set_id); /* pic_parameter_set_id */
906 bitstream_put_ue(bs, pic_param->seq_parameter_set_id); /* seq_parameter_set_id */
908 bitstream_put_ui(bs, pic_param->pic_fields.bits.entropy_coding_mode_flag, 1); /* entropy_coding_mode_flag */
910 bitstream_put_ui(bs, 0, 1); /* pic_order_present_flag: 0 */
912 bitstream_put_ue(bs, 0); /* num_slice_groups_minus1 */
914 bitstream_put_ue(bs, pic_param->num_ref_idx_l0_active_minus1); /* num_ref_idx_l0_active_minus1 */
915 bitstream_put_ue(bs, pic_param->num_ref_idx_l1_active_minus1); /* num_ref_idx_l1_active_minus1 1 */
917 bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_pred_flag, 1); /* weighted_pred_flag: 0 */
918 bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_bipred_idc, 2); /* weighted_bipred_idc: 0 */
920 bitstream_put_se(bs, pic_param->pic_init_qp - 26); /* pic_init_qp_minus26 */
921 bitstream_put_se(bs, 0); /* pic_init_qs_minus26 */
922 bitstream_put_se(bs, 0); /* chroma_qp_index_offset */
924 bitstream_put_ui(bs, pic_param->pic_fields.bits.deblocking_filter_control_present_flag, 1); /* deblocking_filter_control_present_flag */
925 bitstream_put_ui(bs, 0, 1); /* constrained_intra_pred_flag */
926 bitstream_put_ui(bs, 0, 1); /* redundant_pic_cnt_present_flag */
929 bitstream_put_ui(bs, pic_param->pic_fields.bits.transform_8x8_mode_flag, 1); /*transform_8x8_mode_flag */
930 bitstream_put_ui(bs, 0, 1); /* pic_scaling_matrix_present_flag */
931 bitstream_put_se(bs, pic_param->second_chroma_qp_index_offset ); /*second_chroma_qp_index_offset */
933 rbsp_trailing_bits(bs);
937 static void build_nal_pps(FILE *avc_fp)
941 bitstream_start(&bs);
942 nal_start_code_prefix(&bs);
943 nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
945 bitstream_end(&bs, avc_fp);
949 build_header(FILE *avc_fp)
951 build_nal_sps(avc_fp);
952 build_nal_pps(avc_fp);
957 build_packed_pic_buffer(unsigned char **header_buffer)
961 bitstream_start(&bs);
962 nal_start_code_prefix(&bs);
963 nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
967 *header_buffer = (unsigned char *)bs.buffer;
968 return bs.bit_offset;
972 build_packed_seq_buffer(unsigned char **header_buffer)
976 bitstream_start(&bs);
977 nal_start_code_prefix(&bs);
978 nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
982 *header_buffer = (unsigned char *)bs.buffer;
983 return bs.bit_offset;
989 slice_header(bitstream *bs, int frame_num, int display_frame, int slice_type, int nal_ref_idc, int is_idr)
991 VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
992 VAEncPictureParameterBufferH264 *pic_param = &avcenc_context.pic_param;
993 int is_cabac = (pic_param->pic_fields.bits.entropy_coding_mode_flag == ENTROPY_MODE_CABAC);
995 bitstream_put_ue(bs, 0); /* first_mb_in_slice: 0 */
996 bitstream_put_ue(bs, slice_type); /* slice_type */
997 bitstream_put_ue(bs, 0); /* pic_parameter_set_id: 0 */
998 bitstream_put_ui(bs, frame_num & 0x0F, seq_param->seq_fields.bits.log2_max_frame_num_minus4 + 4); /* frame_num */
1000 /* frame_mbs_only_flag == 1 */
1001 if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {
1007 bitstream_put_ue(bs, 0); /* idr_pic_id: 0 */
1009 if (seq_param->seq_fields.bits.pic_order_cnt_type == 0) {
1010 bitstream_put_ui(bs, (display_frame*2) & 0x3F, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 + 4);
1011 /* only support frame */
1017 /* redundant_pic_cnt_present_flag == 0 */
1020 if (slice_type == SLICE_TYPE_P) {
1021 bitstream_put_ui(bs, 0, 1); /* num_ref_idx_active_override_flag: 0 */
1022 /* ref_pic_list_reordering */
1023 bitstream_put_ui(bs, 0, 1); /* ref_pic_list_reordering_flag_l0: 0 */
1024 } else if (slice_type == SLICE_TYPE_B) {
1025 bitstream_put_ui(bs, 1, 1); /* direct_spatial_mv_pred: 1 */
1026 bitstream_put_ui(bs, 0, 1); /* num_ref_idx_active_override_flag: 0 */
1027 /* ref_pic_list_reordering */
1028 bitstream_put_ui(bs, 0, 1); /* ref_pic_list_reordering_flag_l0: 0 */
1029 bitstream_put_ui(bs, 0, 1); /* ref_pic_list_reordering_flag_l1: 0 */
1032 /* weighted_pred_flag == 0 */
1034 /* dec_ref_pic_marking */
1035 if (nal_ref_idc != 0) {
1037 bitstream_put_ui(bs, 0, 1); /* no_output_of_prior_pics_flag: 0 */
1038 bitstream_put_ui(bs, 0, 1); /* long_term_reference_flag: 0 */
1040 bitstream_put_ui(bs, 0, 1); /* adaptive_ref_pic_marking_mode_flag: 0 */
1044 if (is_cabac && (slice_type != SLICE_TYPE_I))
1045 bitstream_put_ue(bs, 0); /* cabac_init_idc: 0 */
1047 bitstream_put_se(bs, 0); /* slice_qp_delta: 0 */
1049 if (pic_param->pic_fields.bits.deblocking_filter_control_present_flag == 1) {
1050 bitstream_put_ue(bs, 0); /* disable_deblocking_filter_idc: 0 */
1051 bitstream_put_se(bs, 2); /* slice_alpha_c0_offset_div2: 2 */
1052 bitstream_put_se(bs, 2); /* slice_beta_offset_div2: 2 */
1057 slice_data(bitstream *bs)
1059 VACodedBufferSegment *coded_buffer_segment;
1060 unsigned char *coded_mem;
1061 int i, slice_data_length;
1063 VASurfaceStatus surface_status;
1065 va_status = vaSyncSurface(va_dpy, surface_ids[avcenc_context.current_input_surface]);
1066 CHECK_VASTATUS(va_status,"vaSyncSurface");
1069 va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[avcenc_context.current_input_surface], &surface_status);
1070 CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
1072 va_status = vaMapBuffer(va_dpy, avcenc_context.codedbuf_buf_id, (void **)(&coded_buffer_segment));
1073 CHECK_VASTATUS(va_status,"vaMapBuffer");
1074 coded_mem = coded_buffer_segment->buf;
1076 slice_data_length = get_coded_bitsteam_length(coded_mem, codedbuf_size);
1078 for (i = 0; i < slice_data_length; i++) {
1079 bitstream_put_ui(bs, *coded_mem, 8);
1083 vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
1087 build_nal_slice(FILE *avc_fp, int frame_num, int display_frame, int slice_type, int is_idr)
1091 bitstream_start(&bs);
1093 bitstream_end(&bs, avc_fp);
1099 store_coded_buffer(FILE *avc_fp, int slice_type)
1101 VACodedBufferSegment *coded_buffer_segment;
1102 unsigned char *coded_mem;
1103 int slice_data_length;
1105 VASurfaceStatus surface_status;
1108 va_status = vaSyncSurface(va_dpy, surface_ids[avcenc_context.current_input_surface]);
1109 CHECK_VASTATUS(va_status,"vaSyncSurface");
1112 va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[avcenc_context.current_input_surface], &surface_status);
1113 CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
1115 va_status = vaMapBuffer(va_dpy, avcenc_context.codedbuf_buf_id, (void **)(&coded_buffer_segment));
1116 CHECK_VASTATUS(va_status,"vaMapBuffer");
1117 coded_mem = coded_buffer_segment->buf;
1119 if (coded_buffer_segment->status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK) {
1120 if (slice_type == SLICE_TYPE_I)
1121 avcenc_context.codedbuf_i_size *= 2;
1123 avcenc_context.codedbuf_pb_size *= 2;
1125 vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
1129 slice_data_length = coded_buffer_segment->size;
1132 w_items = fwrite(coded_mem, slice_data_length, 1, avc_fp);
1133 } while (w_items != 1);
1135 if (slice_type == SLICE_TYPE_I) {
1136 if (avcenc_context.codedbuf_i_size > slice_data_length * 3 / 2) {
1137 avcenc_context.codedbuf_i_size = slice_data_length * 3 / 2;
1140 if (avcenc_context.codedbuf_pb_size < slice_data_length) {
1141 avcenc_context.codedbuf_pb_size = slice_data_length;
1144 if (avcenc_context.codedbuf_pb_size > slice_data_length * 3 / 2) {
1145 avcenc_context.codedbuf_pb_size = slice_data_length * 3 / 2;
1149 vaUnmapBuffer(va_dpy, avcenc_context.codedbuf_buf_id);
1155 encode_picture(FILE *yuv_fp, FILE *avc_fp,
1156 int frame_num, int display_num,
1158 int slice_type, int next_is_bpic,
1159 int next_display_num)
1162 int ret = 0, codedbuf_size;
1164 begin_picture(yuv_fp, frame_num, display_num, slice_type, is_idr);
1166 //if (next_display_num < frame_number) {
1170 /* prepare for next frame */
1171 if (avcenc_context.current_input_surface == SID_INPUT_PICTURE_0)
1172 index = SID_INPUT_PICTURE_1;
1174 index = SID_INPUT_PICTURE_0;
1175 if ( next_display_num >= frame_number )
1176 next_display_num = frame_number - 1;
1177 fseek(yuv_fp, frame_size * next_display_num, SEEK_SET);
1179 avcenc_context.upload_thread_param.yuv_fp = yuv_fp;
1180 avcenc_context.upload_thread_param.surface_id = surface_ids[index];
1182 avcenc_context.upload_thread_value = pthread_create(&avcenc_context.upload_thread_id,
1184 upload_thread_function,
1185 (void*)&avcenc_context.upload_thread_param);
1189 avcenc_destroy_buffers(&avcenc_context.codedbuf_buf_id, 1);
1190 avcenc_destroy_buffers(&avcenc_context.pic_param_buf_id, 1);
1193 if (SLICE_TYPE_I == slice_type) {
1194 codedbuf_size = avcenc_context.codedbuf_i_size;
1196 codedbuf_size = avcenc_context.codedbuf_pb_size;
1200 va_status = vaCreateBuffer(va_dpy,
1201 avcenc_context.context_id,
1202 VAEncCodedBufferType,
1203 codedbuf_size, 1, NULL,
1204 &avcenc_context.codedbuf_buf_id);
1205 CHECK_VASTATUS(va_status,"vaCreateBuffer");
1207 /* picture parameter set */
1208 avcenc_update_picture_parameter(slice_type, frame_num, display_num, is_idr);
1210 avcenc_render_picture();
1212 ret = store_coded_buffer(avc_fp, slice_type);
1215 end_picture(slice_type, next_is_bpic);
1218 static void encode_pb_pictures(FILE *yuv_fp, FILE *avc_fp, int f, int nbframes, int next_f)
1221 encode_picture(yuv_fp, avc_fp,
1222 enc_frame_number, f + nbframes,
1224 SLICE_TYPE_P, 1, f);
1226 for( i = 0; i < nbframes - 1; i++) {
1227 encode_picture(yuv_fp, avc_fp,
1228 enc_frame_number + 1, f + i,
1230 SLICE_TYPE_B, 1, f + i + 1);
1233 encode_picture(yuv_fp, avc_fp,
1234 enc_frame_number + 1, f + nbframes - 1,
1236 SLICE_TYPE_B, 0, next_f);
1239 static void show_help()
1241 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");
1244 static void avcenc_context_seq_param_init(VAEncSequenceParameterBufferH264 *seq_param,
1245 int width, int height)
1248 int width_in_mbs = (width + 15) / 16;
1249 int height_in_mbs = (height + 15) / 16;
1250 int frame_cropping_flag = 0;
1251 int frame_crop_bottom_offset = 0;
1253 seq_param->seq_parameter_set_id = 0;
1254 seq_param->level_idc = 41;
1255 seq_param->intra_period = intra_period;
1256 seq_param->ip_period = 0; /* FIXME: ??? */
1257 seq_param->max_num_ref_frames = 4;
1258 seq_param->picture_width_in_mbs = width_in_mbs;
1259 seq_param->picture_height_in_mbs = height_in_mbs;
1260 seq_param->seq_fields.bits.frame_mbs_only_flag = 1;
1262 if (frame_bit_rate > 0)
1263 seq_param->bits_per_second = 1024 * frame_bit_rate; /* use kbps as input */
1265 seq_param->bits_per_second = 0;
1267 seq_param->time_scale = 900;
1268 seq_param->num_units_in_tick = 15; /* Tc = num_units_in_tick / time_sacle */
1270 if (height_in_mbs * 16 - height) {
1271 frame_cropping_flag = 1;
1272 frame_crop_bottom_offset =
1273 (height_in_mbs * 16 - height) / (2 * (!seq_param->seq_fields.bits.frame_mbs_only_flag + 1));
1276 seq_param->frame_cropping_flag = frame_cropping_flag;
1277 seq_param->frame_crop_left_offset = 0;
1278 seq_param->frame_crop_right_offset = 0;
1279 seq_param->frame_crop_top_offset = 0;
1280 seq_param->frame_crop_bottom_offset = frame_crop_bottom_offset;
1282 seq_param->seq_fields.bits.pic_order_cnt_type = 0;
1283 seq_param->seq_fields.bits.direct_8x8_inference_flag = 0;
1285 seq_param->seq_fields.bits.log2_max_frame_num_minus4 = 0;
1286 seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = 2;
1288 if (frame_bit_rate > 0)
1289 seq_param->vui_parameters_present_flag = 1; //HRD info located in vui
1291 seq_param->vui_parameters_present_flag = 0;
1294 static void avcenc_context_pic_param_init(VAEncPictureParameterBufferH264 *pic_param)
1296 pic_param->seq_parameter_set_id = 0;
1297 pic_param->pic_parameter_set_id = 0;
1299 pic_param->last_picture = 0;
1300 pic_param->frame_num = 0;
1302 pic_param->pic_init_qp = (qp_value >= 0 ? qp_value : 26);
1303 pic_param->num_ref_idx_l0_active_minus1 = 0;
1304 pic_param->num_ref_idx_l1_active_minus1 = 0;
1306 pic_param->pic_fields.bits.idr_pic_flag = 0;
1307 pic_param->pic_fields.bits.reference_pic_flag = 0;
1308 pic_param->pic_fields.bits.entropy_coding_mode_flag = ENTROPY_MODE_CABAC;
1309 pic_param->pic_fields.bits.weighted_pred_flag = 0;
1310 pic_param->pic_fields.bits.weighted_bipred_idc = 0;
1312 if (avcenc_context.constraint_set_flag & 0x7)
1313 pic_param->pic_fields.bits.transform_8x8_mode_flag = 0;
1315 pic_param->pic_fields.bits.transform_8x8_mode_flag = 1;
1317 pic_param->pic_fields.bits.deblocking_filter_control_present_flag = 1;
1320 static void avcenc_context_init(int width, int height)
1323 memset(&avcenc_context, 0, sizeof(avcenc_context));
1324 avcenc_context.profile = VAProfileH264Main;
1326 switch (avcenc_context.profile) {
1327 case VAProfileH264Baseline:
1328 avcenc_context.constraint_set_flag |= (1 << 0); /* Annex A.2.1 */
1331 case VAProfileH264Main:
1332 avcenc_context.constraint_set_flag |= (1 << 1); /* Annex A.2.2 */
1335 case VAProfileH264High:
1336 avcenc_context.constraint_set_flag |= (1 << 3); /* Annex A.2.4 */
1343 avcenc_context.seq_param_buf_id = VA_INVALID_ID;
1344 avcenc_context.pic_param_buf_id = VA_INVALID_ID;
1345 avcenc_context.packed_seq_header_param_buf_id = VA_INVALID_ID;
1346 avcenc_context.packed_seq_buf_id = VA_INVALID_ID;
1347 avcenc_context.packed_pic_header_param_buf_id = VA_INVALID_ID;
1348 avcenc_context.packed_pic_buf_id = VA_INVALID_ID;
1349 avcenc_context.codedbuf_buf_id = VA_INVALID_ID;
1350 avcenc_context.misc_parameter_hrd_buf_id = VA_INVALID_ID;
1351 avcenc_context.codedbuf_i_size = width * height;
1352 avcenc_context.codedbuf_pb_size = 0;
1353 avcenc_context.current_input_surface = SID_INPUT_PICTURE_0;
1354 avcenc_context.upload_thread_value = -1;
1357 avcenc_context.rate_control_method = VA_RC_CBR;
1358 else if (qp_value == -2)
1359 avcenc_context.rate_control_method = VA_RC_VBR;
1361 assert(qp_value >= 0 && qp_value <= 51);
1362 avcenc_context.rate_control_method = VA_RC_CQP;
1365 for (i = 0; i < MAX_SLICES; i++) {
1366 avcenc_context.slice_param_buf_id[i] = VA_INVALID_ID;
1369 avcenc_context_seq_param_init(&avcenc_context.seq_param, width, height);
1370 avcenc_context_pic_param_init(&avcenc_context.pic_param);
1373 int main(int argc, char *argv[])
1379 int i_frame_only=0,i_p_frame_only=1;
1381 struct timeval tpstart,tpend;
1384 va_init_display_args(&argc, argv);
1386 //TODO may be we should using option analytics library
1387 if(argc != 5 && argc != 6 && argc != 7) {
1392 picture_width = atoi(argv[1]);
1393 picture_height = atoi(argv[2]);
1394 picture_width_in_mbs = (picture_width + 15) / 16;
1395 picture_height_in_mbs = (picture_height + 15) / 16;
1397 if (argc == 6 || argc == 7) {
1399 sscanf(argv[5], "qp=%d", &qp_value);
1400 if ( qp_value == -1 ) {
1401 frame_bit_rate = -1;
1402 sscanf(argv[5], "fb=%d", &frame_bit_rate);
1403 if ( frame_bit_rate == -1 ) {
1407 } else if (qp_value > 51) {
1409 } else if (qp_value < 0) {
1413 qp_value = 28; //default const QP mode
1416 sscanf(argv[6], "mode=%d", &mode_value);
1417 if ( mode_value == 0 ) {
1421 else if ( mode_value == 1) {
1425 else if ( mode_value == 2 ) {
1430 printf("mode_value=%d\n",mode_value);
1436 yuv_fp = fopen(argv[3],"rb");
1437 if ( yuv_fp == NULL){
1438 printf("Can't open input YUV file\n");
1441 fseek(yuv_fp,0l, SEEK_END);
1442 file_size = ftell(yuv_fp);
1443 frame_size = picture_width * picture_height + ((picture_width * picture_height) >> 1) ;
1445 if ( (file_size < frame_size) || (file_size % frame_size) ) {
1447 printf("The YUV file's size is not correct\n");
1450 frame_number = file_size / frame_size;
1451 fseek(yuv_fp, 0l, SEEK_SET);
1453 avc_fp = fopen(argv[4], "wb");
1454 if ( avc_fp == NULL) {
1456 printf("Can't open output avc file\n");
1459 gettimeofday(&tpstart,NULL);
1460 avcenc_context_init(picture_width, picture_height);
1461 create_encode_pipe();
1462 alloc_encode_resource(yuv_fp);
1464 enc_frame_number = 0;
1465 for ( f = 0; f < frame_number; ) { //picture level loop
1466 static int const frame_type_pattern[][2] = { {SLICE_TYPE_I,1},
1467 {SLICE_TYPE_P,3}, {SLICE_TYPE_P,3},{SLICE_TYPE_P,3},
1468 {SLICE_TYPE_P,3}, {SLICE_TYPE_P,3},{SLICE_TYPE_P,3},
1469 {SLICE_TYPE_P,3}, {SLICE_TYPE_P,3},{SLICE_TYPE_P,3},
1472 if ( i_frame_only ) {
1473 encode_picture(yuv_fp, avc_fp,enc_frame_number, f, f==0, SLICE_TYPE_I, 0, f+1);
1476 } else if ( i_p_frame_only ) {
1477 if ( (f % intra_period) == 0 ) {
1478 encode_picture(yuv_fp, avc_fp,enc_frame_number, f, f==0, SLICE_TYPE_I, 0, f+1);
1482 encode_picture(yuv_fp, avc_fp,enc_frame_number, f, f==0, SLICE_TYPE_P, 0, f+1);
1486 } else { // follow the i,p,b pattern
1487 static int fcurrent = 0;
1490 fcurrent = fcurrent % (sizeof(frame_type_pattern)/sizeof(int[2]));
1491 fnext = (fcurrent+1) % (sizeof(frame_type_pattern)/sizeof(int[2]));
1493 if ( frame_type_pattern[fcurrent][0] == SLICE_TYPE_I ) {
1494 encode_picture(yuv_fp, avc_fp,enc_frame_number, f, f==0, SLICE_TYPE_I, 0,
1495 f+frame_type_pattern[fnext][1]);
1499 encode_pb_pictures(yuv_fp, avc_fp, f, frame_type_pattern[fcurrent][1]-1,
1500 f + frame_type_pattern[fcurrent][1] + frame_type_pattern[fnext][1] -1 );
1501 f += frame_type_pattern[fcurrent][1];
1507 printf("\r %d/%d ...", f+1, frame_number);
1511 gettimeofday(&tpend,NULL);
1512 timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+ tpend.tv_usec-tpstart.tv_usec;
1514 printf("\ndone!\n");
1515 printf("encode %d frames in %f secondes, FPS is %.1f\n",frame_number, timeuse, frame_number/timeuse);
1516 release_encode_resource();
1517 destory_encode_pipe();