Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: third_party/libva/test/encode/avcenc.c

Issue 10375035: Add libva to chromium third_party. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Simple AVC encoder based on libVA.
3 *
4 * Usage:
5 * ./avcenc <width> <height> <input file> <output file> [qp]
6 */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <getopt.h>
12 #include <X11/Xlib.h>
13
14 #include <unistd.h>
15
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <assert.h>
20 #include <time.h>
21
22 #include <va/va.h>
23 #include <va/va_x11.h>
24
25 #define NAL_REF_IDC_NONE 0
26 #define NAL_REF_IDC_LOW 1
27 #define NAL_REF_IDC_MEDIUM 2
28 #define NAL_REF_IDC_HIGH 3
29
30 #define NAL_NON_IDR 1
31 #define NAL_IDR 5
32 #define NAL_SPS 7
33 #define NAL_PPS 8
34
35 #define SLICE_TYPE_P 0
36 #define SLICE_TYPE_B 1
37 #define SLICE_TYPE_I 2
38
39 #define ENTROPY_MODE_CAVLC 0
40 #define ENTROPY_MODE_CABAC 1
41
42 #define PROFILE_IDC_BASELINE 66
43 #define PROFILE_IDC_MAIN 77
44 #define PROFILE_IDC_HIGH 100
45
46 #define CHECK_VASTATUS(va_status,func) \
47 if (va_status != VA_STATUS_SUCCESS) { \
48 fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
49 exit(1); \
50 }
51
52 static Display *x11_display;
53 static VADisplay va_dpy;
54 static VAContextID context_id;
55 static VAConfigID config_id;
56
57 static int picture_width, picture_width_in_mbs;
58 static int picture_height, picture_height_in_mbs;
59 static int frame_size;
60 static unsigned char *newImageBuffer = 0;
61 static int codedbuf_size;
62
63 static int qp_value = 26;
64
65 static int log2_max_frame_num_minus4 = 0;
66 static int pic_order_cnt_type = 0;
67 static int log2_max_pic_order_cnt_lsb_minus4 = 0;
68 static int entropy_coding_mode_flag = ENTROPY_MODE_CABAC;
69 static int deblocking_filter_control_present_flag = 1;
70 static int frame_mbs_only_flag = 1;
71
72 static void create_encode_pipe()
73 {
74 VAEntrypoint entrypoints[5];
75 int num_entrypoints,slice_entrypoint;
76 VAConfigAttrib attrib[2];
77 int major_ver, minor_ver;
78 VAStatus va_status;
79
80 x11_display = XOpenDisplay(":0.0");
81 assert(x11_display);
82
83 va_dpy = vaGetDisplay(x11_display);
84 va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
85 CHECK_VASTATUS(va_status, "vaInitialize");
86
87 vaQueryConfigEntrypoints(va_dpy, VAProfileH264Baseline, entrypoints,
88 &num_entrypoints);
89
90 for (slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypo int++) {
91 if (entrypoints[slice_entrypoint] == VAEntrypointEncSlice)
92 break;
93 }
94
95 if (slice_entrypoint == num_entrypoints) {
96 /* not find Slice entry point */
97 assert(0);
98 }
99
100 /* find out the format for the render target, and rate control mode */
101 attrib[0].type = VAConfigAttribRTFormat;
102 attrib[1].type = VAConfigAttribRateControl;
103 vaGetConfigAttributes(va_dpy, VAProfileH264Baseline, VAEntrypointEncSlice,
104 &attrib[0], 2);
105
106 if ((attrib[0].value & VA_RT_FORMAT_YUV420) == 0) {
107 /* not find desired YUV420 RT format */
108 assert(0);
109 }
110
111 if ((attrib[1].value & VA_RC_VBR) == 0) {
112 /* Can't find matched RC mode */
113 printf("VBR mode doesn't found, exit\n");
114 assert(0);
115 }
116
117 attrib[0].value = VA_RT_FORMAT_YUV420; /* set to desired RT format */
118 attrib[1].value = VA_RC_VBR; /* set to desired RC mode */
119
120 va_status = vaCreateConfig(va_dpy, VAProfileH264Baseline, VAEntrypointEncSli ce,
121 &attrib[0], 2,&config_id);
122 CHECK_VASTATUS(va_status, "vaCreateConfig");
123
124 /* Create a context for this decode pipe */
125 va_status = vaCreateContext(va_dpy, config_id,
126 picture_width, picture_height,
127 VA_PROGRESSIVE,
128 0, 0,
129 &context_id);
130 CHECK_VASTATUS(va_status, "vaCreateContext");
131 }
132
133 static void destory_encode_pipe()
134 {
135 vaDestroyContext(va_dpy,context_id);
136 vaDestroyConfig(va_dpy,config_id);
137 vaTerminate(va_dpy);
138 XCloseDisplay(x11_display);
139 }
140
141 /***************************************************
142 *
143 * The encode pipe resource define
144 *
145 ***************************************************/
146 static VABufferID seq_parameter = VA_INVALID_ID; /*Sequence level parameter*/
147 static VABufferID pic_parameter = VA_INVALID_ID; /*Picture level parameter*/
148 static VABufferID slice_parameter = VA_INVALID_ID; /*Slice level pa rameter, multil slices*/
149
150 static VABufferID coded_buf; /*Output buffer, compressed data*/
151
152 #define SID_NUMBER 3
153 #define SID_INPUT_PICTURE 0
154 #define SID_REFERENCE_PICTURE 1
155 #define SID_RECON_PICTURE 2
156 static VASurfaceID surface_ids[SID_NUMBER];
157
158 /***************************************************/
159
160 static void alloc_encode_resource()
161 {
162 VAStatus va_status;
163
164 seq_parameter = VA_INVALID_ID;
165 pic_parameter = VA_INVALID_ID;
166 slice_parameter = VA_INVALID_ID;
167
168 //1. Create sequence parameter set
169 {
170 VAEncSequenceParameterBufferH264 seq_h264 = {0};
171
172 seq_h264.level_idc = 30;
173 seq_h264.picture_width_in_mbs = picture_width_in_mbs;
174 seq_h264.picture_height_in_mbs = picture_height_in_mbs;
175
176 seq_h264.bits_per_second = 384*1000;
177 seq_h264.initial_qp = qp_value;
178 seq_h264.min_qp = 3;
179
180 va_status = vaCreateBuffer(va_dpy, context_id,
181 VAEncSequenceParameterBufferType,
182 sizeof(seq_h264),1,&seq_h264,&seq_parameter);
183 CHECK_VASTATUS(va_status,"vaCreateBuffer");;
184 }
185
186 //2. Create surface
187 va_status = vaCreateSurfaces(va_dpy, picture_width, picture_height,
188 VA_RT_FORMAT_YUV420, SID_NUMBER, &surface_ids[0 ]);
189 CHECK_VASTATUS(va_status, "vaCreateSurfaces");
190
191 //3. Create coded buffer
192 {
193 va_status = vaCreateBuffer(va_dpy,context_id,VAEncCodedBufferType,
194 codedbuf_size, 1, NULL, &coded_buf);
195
196 CHECK_VASTATUS(va_status,"vaBeginPicture");
197 }
198
199 newImageBuffer = (unsigned char *)malloc(frame_size);
200 }
201
202 static void release_encode_resource()
203 {
204 free(newImageBuffer);
205
206 //-3 Relese coded buffer
207 vaDestroyBuffer(va_dpy, coded_buf);
208
209 //-2 Release all the surfaces resource
210 vaDestroySurfaces(va_dpy, &surface_ids[0], SID_NUMBER);
211
212 //-1 Destory the sequence level parameter
213 vaDestroyBuffer(va_dpy, seq_parameter);
214 }
215
216 static void begin_picture()
217 {
218 VAStatus va_status;
219 va_status = vaBeginPicture(va_dpy, context_id, surface_ids[SID_INPUT_PICTURE ]);
220 CHECK_VASTATUS(va_status,"vaBeginPicture");
221 }
222
223 static void upload_yuv_to_surface(FILE *yuv_fp, VASurfaceID surface_id)
224 {
225 VAImage surface_image;
226 VAStatus va_status;
227 void *surface_p = NULL;
228 unsigned char *y_src, *u_src, *v_src;
229 unsigned char *y_dst, *u_dst, *v_dst;
230 int y_size = picture_width * picture_height;
231 int u_size = (picture_width >> 1) * (picture_height >> 1);
232 int row, col;
233 size_t n_items;
234
235 do {
236 n_items = fread(newImageBuffer, frame_size, 1, yuv_fp);
237 } while (n_items != 1);
238
239 va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
240 CHECK_VASTATUS(va_status,"vaDeriveImage");
241
242 vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
243 assert(VA_STATUS_SUCCESS == va_status);
244
245 y_src = newImageBuffer;
246 u_src = newImageBuffer + y_size; /* UV offset for NV12 */
247 v_src = newImageBuffer + y_size + u_size;
248
249 y_dst = surface_p + surface_image.offsets[0];
250 u_dst = surface_p + surface_image.offsets[1]; /* UV offset for NV12 */
251 v_dst = surface_p + surface_image.offsets[2];
252
253 /* Y plane */
254 for (row = 0; row < surface_image.height; row++) {
255 memcpy(y_dst, y_src, surface_image.width);
256 y_dst += surface_image.pitches[0];
257 y_src += picture_width;
258 }
259
260 if (surface_image.format.fourcc == VA_FOURCC_NV12) { /* UV plane */
261 for (row = 0; row < surface_image.height / 2; row++) {
262 for (col = 0; col < surface_image.width / 2; col++) {
263 u_dst[col * 2] = u_src[col];
264 u_dst[col * 2 + 1] = v_src[col];
265 }
266
267 u_dst += surface_image.pitches[1];
268 u_src += (picture_width / 2);
269 v_src += (picture_width / 2);
270 }
271 } else {
272 /* FIXME: fix this later */
273 assert(0);
274 }
275
276 vaUnmapBuffer(va_dpy, surface_image.buf);
277 vaDestroyImage(va_dpy, surface_image.image_id);
278 }
279
280 static void prepare_input(FILE * yuv_fp, int intra_slice)
281 {
282 static VAEncPictureParameterBufferH264 pic_h264;
283 static VAEncSliceParameterBuffer slice_h264;
284 VAStatus va_status;
285 VABufferID tempID;
286 VACodedBufferSegment *coded_buffer_segment = NULL;
287 unsigned char *coded_mem;
288
289 // Sequence level
290 va_status = vaRenderPicture(va_dpy, context_id, &seq_parameter, 1);
291 CHECK_VASTATUS(va_status,"vaRenderPicture");;
292
293 // Copy Image to target surface according input YUV data.
294 upload_yuv_to_surface(yuv_fp, surface_ids[SID_INPUT_PICTURE]);
295
296 // Picture level
297 pic_h264.reference_picture = surface_ids[SID_REFERENCE_PICTURE];
298 pic_h264.reconstructed_picture = surface_ids[SID_RECON_PICTURE];
299 pic_h264.coded_buf = coded_buf;
300 pic_h264.picture_width = picture_width;
301 pic_h264.picture_height = picture_height;
302 pic_h264.last_picture = 0;
303 if (pic_parameter != VA_INVALID_ID) {
304 vaDestroyBuffer(va_dpy, pic_parameter);
305 }
306 va_status = vaCreateBuffer(va_dpy, context_id,VAEncPictureParameterBufferTyp e,
307 sizeof(pic_h264),1,&pic_h264,&pic_parameter);
308 CHECK_VASTATUS(va_status,"vaCreateBuffer");
309 va_status = vaRenderPicture(va_dpy,context_id, &pic_parameter, 1);
310 CHECK_VASTATUS(va_status,"vaRenderPicture");
311
312 // clean old memory
313 va_status = vaMapBuffer(va_dpy,coded_buf,(void **)(&coded_buffer_segment));
314 CHECK_VASTATUS(va_status,"vaMapBuffer");
315 coded_mem = coded_buffer_segment->buf;
316 memset(coded_mem, 0, coded_buffer_segment->size);
317 vaUnmapBuffer(va_dpy, coded_buf);
318
319 // Slice level
320 slice_h264.start_row_number = 0;
321 slice_h264.slice_height = picture_height/16; /* Measured by MB */
322 slice_h264.slice_flags.bits.is_intra = intra_slice;
323 slice_h264.slice_flags.bits.disable_deblocking_filter_idc = 0;
324 if ( slice_parameter != VA_INVALID_ID){
325 vaDestroyBuffer(va_dpy, slice_parameter);
326 }
327 va_status = vaCreateBuffer(va_dpy,context_id,VAEncSliceParameterBufferType,
328 sizeof(slice_h264),1,&slice_h264,&slice_parameter );
329 CHECK_VASTATUS(va_status,"vaCreateBuffer");;
330 va_status = vaRenderPicture(va_dpy,context_id, &slice_parameter, 1);
331 CHECK_VASTATUS(va_status,"vaRenderPicture");
332
333 // Prepare for next picture
334 tempID = surface_ids[SID_RECON_PICTURE];
335 surface_ids[SID_RECON_PICTURE] = surface_ids[SID_REFERENCE_PICTURE];
336 surface_ids[SID_REFERENCE_PICTURE] = tempID;
337 }
338
339 static void end_picture()
340 {
341 VAStatus va_status;
342
343 va_status = vaEndPicture(va_dpy,context_id);
344 CHECK_VASTATUS(va_status,"vaRenderPicture");
345 }
346
347 #define BITSTREAM_ALLOCATE_STEPPING 4096
348
349 struct __bitstream {
350 unsigned int *buffer;
351 int bit_offset;
352 int max_size_in_dword;
353 };
354
355 typedef struct __bitstream bitstream;
356
357 static int
358 get_coded_bitsteam_length(unsigned char *buffer, int buffer_length)
359 {
360 int i;
361
362 for (i = buffer_length - 1; i >= 0; i--) {
363 if (buffer[i])
364 break;
365 }
366
367 return i + 1;
368 }
369
370 static unsigned int
371 swap32(unsigned int val)
372 {
373 unsigned char *pval = (unsigned char *)&val;
374
375 return ((pval[0] << 24) |
376 (pval[1] << 16) |
377 (pval[2] << 8) |
378 (pval[3] << 0));
379 }
380
381 static void
382 bitstream_start(bitstream *bs)
383 {
384 bs->max_size_in_dword = BITSTREAM_ALLOCATE_STEPPING;
385 bs->buffer = calloc(bs->max_size_in_dword * sizeof(int), 1);
386 bs->bit_offset = 0;
387 }
388
389 static void
390 bitstream_end(bitstream *bs, FILE *avc_fp)
391 {
392 int pos = (bs->bit_offset >> 5);
393 int bit_offset = (bs->bit_offset & 0x1f);
394 int bit_left = 32 - bit_offset;
395 int length = (bs->bit_offset + 7) >> 3;
396 size_t w_items;
397
398 if (bit_offset) {
399 bs->buffer[pos] = swap32((bs->buffer[pos] << bit_left));
400 }
401
402 do {
403 w_items = fwrite(bs->buffer, length, 1, avc_fp);
404 } while (w_items != 1);
405
406 free(bs->buffer);
407 }
408
409 static void
410 bitstream_put_ui(bitstream *bs, unsigned int val, int size_in_bits)
411 {
412 int pos = (bs->bit_offset >> 5);
413 int bit_offset = (bs->bit_offset & 0x1f);
414 int bit_left = 32 - bit_offset;
415
416 if (!size_in_bits)
417 return;
418
419 bs->bit_offset += size_in_bits;
420
421 if (bit_left > size_in_bits) {
422 bs->buffer[pos] = (bs->buffer[pos] << size_in_bits | val);
423 } else {
424 size_in_bits -= bit_left;
425 bs->buffer[pos] = (bs->buffer[pos] << bit_left) | (val >> size_in_bits);
426 bs->buffer[pos] = swap32(bs->buffer[pos]);
427
428 if (pos + 1 == bs->max_size_in_dword) {
429 bs->max_size_in_dword += BITSTREAM_ALLOCATE_STEPPING;
430 bs->buffer = realloc(bs->buffer, bs->max_size_in_dword * sizeof(unsi gned int));
431 }
432
433 bs->buffer[pos + 1] = val;
434 }
435 }
436
437 static void
438 bitstream_put_ue(bitstream *bs, unsigned int val)
439 {
440 int size_in_bits = 0;
441 int tmp_val = ++val;
442
443 while (tmp_val) {
444 tmp_val >>= 1;
445 size_in_bits++;
446 }
447
448 bitstream_put_ui(bs, 0, size_in_bits - 1); // leading zero
449 bitstream_put_ui(bs, val, size_in_bits);
450 }
451
452 static void
453 bitstream_put_se(bitstream *bs, int val)
454 {
455 unsigned int new_val;
456
457 if (val <= 0)
458 new_val = -2 * val;
459 else
460 new_val = 2 * val - 1;
461
462 bitstream_put_ue(bs, new_val);
463 }
464
465 static void
466 bitstream_byte_aligning(bitstream *bs, int bit)
467 {
468 int bit_offset = (bs->bit_offset & 0x7);
469 int bit_left = 8 - bit_offset;
470 int new_val;
471
472 if (!bit_offset)
473 return;
474
475 assert(bit == 0 || bit == 1);
476
477 if (bit)
478 new_val = (1 << bit_left) - 1;
479 else
480 new_val = 0;
481
482 bitstream_put_ui(bs, new_val, bit_left);
483 }
484
485 static void
486 rbsp_trailing_bits(bitstream *bs)
487 {
488 bitstream_put_ui(bs, 1, 1);
489 bitstream_byte_aligning(bs, 0);
490 }
491
492 static void nal_start_code_prefix(bitstream *bs)
493 {
494 bitstream_put_ui(bs, 0x00000001, 32);
495 }
496
497 static void nal_header(bitstream *bs, int nal_ref_idc, int nal_unit_type)
498 {
499 bitstream_put_ui(bs, 0, 1); /* forbidden_zero_bit: 0 */
500 bitstream_put_ui(bs, nal_ref_idc, 2);
501 bitstream_put_ui(bs, nal_unit_type, 5);
502 }
503
504 static void sps_rbsp(bitstream *bs)
505 {
506 int mb_width, mb_height;
507 int frame_cropping_flag = 0;
508 int frame_crop_bottom_offset = 0;
509 int profile_idc = PROFILE_IDC_MAIN;
510
511 mb_width = picture_width_in_mbs;
512 mb_height = picture_height_in_mbs;
513
514 if (mb_height * 16 - picture_height) {
515 frame_cropping_flag = 1;
516 frame_crop_bottom_offset =
517 (mb_height * 16 - picture_height) / (2 * (!frame_mbs_only_flag + 1)) ;
518 }
519
520 bitstream_put_ui(bs, profile_idc, 8); /* profile_idc */
521 bitstream_put_ui(bs, 0, 1); /* constraint_set0_flag */
522 bitstream_put_ui(bs, 1, 1); /* constraint_set1_flag */
523 bitstream_put_ui(bs, 0, 1); /* constraint_set2_flag */
524 bitstream_put_ui(bs, 0, 1); /* constraint_set3_flag */
525 bitstream_put_ui(bs, 0, 4); /* reserved_zero_4bits * /
526 bitstream_put_ui(bs, 41, 8); /* level_idc */
527 bitstream_put_ue(bs, 0); /* seq_parameter_set_id */
528
529 if (profile_idc >= 100) {
530 /* FIXME: fix for high profile */
531 assert(0);
532 }
533
534 bitstream_put_ue(bs, log2_max_frame_num_minus4); /* log2_max_frame_num_mi nus4 */
535 bitstream_put_ue(bs, pic_order_cnt_type); /* pic_order_cnt_type */
536
537 if (pic_order_cnt_type == 0)
538 bitstream_put_ue(bs, log2_max_pic_order_cnt_lsb_minus4); /* log2_ max_pic_order_cnt_lsb_minus4 */
539 else {
540 assert(0);
541 }
542
543 bitstream_put_ue(bs, 1); /* num_ref_frames */
544 bitstream_put_ui(bs, 0, 1); /* gaps_in_frame_num_val ue_allowed_flag */
545
546 bitstream_put_ue(bs, mb_width - 1); /* pic_width_in_mbs_minu s1 */
547 bitstream_put_ue(bs, mb_height - 1); /* pic_height_in_map_uni ts_minus1 */
548 bitstream_put_ui(bs, frame_mbs_only_flag, 1); /* frame_mbs_only_flag * /
549
550 if (!frame_mbs_only_flag) {
551 assert(0);
552 }
553
554 bitstream_put_ui(bs, 0, 1); /* direct_8x8_inference_ flag */
555 bitstream_put_ui(bs, frame_cropping_flag, 1); /* frame_cropping_flag * /
556
557 if (frame_cropping_flag) {
558 bitstream_put_ue(bs, 0); /* frame_crop_left_offse t */
559 bitstream_put_ue(bs, 0); /* frame_crop_right_offs et */
560 bitstream_put_ue(bs, 0); /* frame_crop_top_offset */
561 bitstream_put_ue(bs, frame_crop_bottom_offset); /* frame_crop_bottom_off set */
562 }
563
564 bitstream_put_ui(bs, 0, 1); /* vui_parameters_presen t_flag */
565 rbsp_trailing_bits(bs); /* rbsp_trailing_bits */
566 }
567
568 static void build_nal_sps(FILE *avc_fp)
569 {
570 bitstream bs;
571
572 bitstream_start(&bs);
573 nal_start_code_prefix(&bs);
574 nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
575 sps_rbsp(&bs);
576 bitstream_end(&bs, avc_fp);
577 }
578
579 static void pps_rbsp(bitstream *bs)
580 {
581 bitstream_put_ue(bs, 0); /* pic_parameter_set_id */
582 bitstream_put_ue(bs, 0); /* seq_parameter_set_id */
583
584 bitstream_put_ui(bs, entropy_coding_mode_flag, 1); /* entropy_coding_mode_f lag */
585
586 bitstream_put_ui(bs, 0, 1); /* pic_order_present_fla g: 0 */
587
588 bitstream_put_ue(bs, 0); /* num_slice_groups_minu s1 */
589
590 bitstream_put_ue(bs, 0); /* num_ref_idx_l0_active _minus1 */
591 bitstream_put_ue(bs, 0); /* num_ref_idx_l1_active _minus1 1 */
592
593 bitstream_put_ui(bs, 0, 1); /* weighted_pred_flag: 0 */
594 bitstream_put_ui(bs, 0, 2); /* weighted_bipred_idc: 0 */
595
596 bitstream_put_se(bs, 0); /* pic_init_qp_minus26 * /
597 bitstream_put_se(bs, 0); /* pic_init_qs_minus26 * /
598 bitstream_put_se(bs, 0); /* chroma_qp_index_offse t */
599
600 bitstream_put_ui(bs, 1, 1); /* deblocking_filter_con trol_present_flag */
601 bitstream_put_ui(bs, 0, 1); /* constrained_intra_pre d_flag */
602 bitstream_put_ui(bs, 0, 1); /* redundant_pic_cnt_pre sent_flag */
603
604 rbsp_trailing_bits(bs);
605 }
606
607 static void build_nal_pps(FILE *avc_fp)
608 {
609 bitstream bs;
610
611 bitstream_start(&bs);
612 nal_start_code_prefix(&bs);
613 nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
614 pps_rbsp(&bs);
615 bitstream_end(&bs, avc_fp);
616 }
617
618 static void
619 build_header(FILE *avc_fp)
620 {
621 build_nal_sps(avc_fp);
622 build_nal_pps(avc_fp);
623 }
624
625
626 static void
627 slice_header(bitstream *bs, int frame_num, int slice_type, int is_idr)
628 {
629 int is_cabac = (entropy_coding_mode_flag == ENTROPY_MODE_CABAC);
630
631 bitstream_put_ue(bs, 0); /* first_mb_in_slice: 0 */
632 bitstream_put_ue(bs, slice_type); /* slice_type */
633 bitstream_put_ue(bs, 0); /* pic_parameter_set_id: 0 */
634 bitstream_put_ui(bs, frame_num & 0x0F, log2_max_frame_num_minus4 + 4); /* frame_num */
635
636 /* frame_mbs_only_flag == 1 */
637 if (!frame_mbs_only_flag) {
638 /* FIXME: */
639 assert(0);
640 }
641
642 if (is_idr)
643 bitstream_put_ue(bs, 0); /* idr_pic_id: 0 */
644
645 if (pic_order_cnt_type == 0) {
646 bitstream_put_ui(bs, (frame_num * 2) & 0x0F, log2_max_pic_order_cnt_lsb_ minus4 + 4);
647 /* only support frame */
648 } else {
649 /* FIXME: */
650 assert(0);
651 }
652
653 /* redundant_pic_cnt_present_flag == 0 */
654
655 /* slice type */
656 if (slice_type == SLICE_TYPE_P) {
657 bitstream_put_ui(bs, 0, 1); /* num_ref_idx_active_override_fl ag: 0 */
658 /* ref_pic_list_reordering */
659 bitstream_put_ui(bs, 0, 1); /* ref_pic_list_reordering_flag_l 0: 0 */
660 } else if (slice_type == SLICE_TYPE_B) {
661 /* FIXME */
662 assert(0);
663 }
664
665 /* weighted_pred_flag == 0 */
666
667 /* dec_ref_pic_marking */
668 if (is_idr) {
669 bitstream_put_ui(bs, 0, 1); /* no_output_of_prior_pics_flag: 0 */
670 bitstream_put_ui(bs, 0, 1); /* long_term_reference_flag: 0 */
671 } else {
672 bitstream_put_ui(bs, 0, 1); /* adaptive_ref_pic_marking_mode_ flag: 0 */
673 }
674
675 if (is_cabac && (slice_type != SLICE_TYPE_I))
676 bitstream_put_ue(bs, 0); /* cabac_init_idc: 0 */
677
678 bitstream_put_se(bs, 0); /* slice_qp_delta: 0 */
679
680 if (deblocking_filter_control_present_flag == 1) {
681 bitstream_put_ue(bs, 0); /* disable_deblocking_filter_idc: 0 */
682 bitstream_put_se(bs, 2); /* slice_alpha_c0_offset_div2: 2 */
683 bitstream_put_se(bs, 2); /* slice_beta_offset_div2: 2 */
684 }
685 }
686
687 static void
688 slice_data(bitstream *bs)
689 {
690 VACodedBufferSegment *coded_buffer_segment;
691 unsigned char *coded_mem;
692 int i, slice_data_length;
693 VAStatus va_status;
694 VASurfaceStatus surface_status;
695 int is_cabac = (entropy_coding_mode_flag == ENTROPY_MODE_CABAC);
696
697 va_status = vaSyncSurface(va_dpy, surface_ids[SID_INPUT_PICTURE]);
698 CHECK_VASTATUS(va_status,"vaSyncSurface");
699
700 surface_status = 0;
701 va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[SID_INPUT_PICTURE], &su rface_status);
702 CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
703
704 va_status = vaMapBuffer(va_dpy, coded_buf, (void **)(&coded_buffer_segment)) ;
705 CHECK_VASTATUS(va_status,"vaMapBuffer");
706 coded_mem = coded_buffer_segment->buf;
707
708 if (is_cabac) {
709 bitstream_byte_aligning(bs, 1);
710 slice_data_length = get_coded_bitsteam_length(coded_mem, codedbuf_size);
711
712 for (i = 0; i < slice_data_length; i++) {
713 bitstream_put_ui(bs, *coded_mem, 8);
714 coded_mem++;
715 }
716 } else {
717 /* FIXME */
718 assert(0);
719 }
720
721 vaUnmapBuffer(va_dpy, coded_buf);
722 }
723
724 static void
725 build_nal_slice(FILE *avc_fp, int frame_num, int slice_type, int is_idr)
726 {
727 bitstream bs;
728
729 bitstream_start(&bs);
730 nal_start_code_prefix(&bs);
731 nal_header(&bs, NAL_REF_IDC_HIGH, is_idr ? NAL_IDR : NAL_NON_IDR);
732 slice_header(&bs, frame_num, slice_type, is_idr);
733 slice_data(&bs);
734 bitstream_end(&bs, avc_fp);
735 }
736
737 static void
738 store_coded_buffer(FILE *avc_fp, int frame_num, int is_intra, int is_idr)
739 {
740 build_nal_slice(avc_fp, frame_num, is_intra ? SLICE_TYPE_I : SLICE_TYPE_P, i s_idr);
741 }
742
743 int main(int argc, char *argv[])
744 {
745 int f;
746 FILE *yuv_fp;
747 FILE *avc_fp;
748 int frame_number;
749 long file_size;
750 clock_t start_clock, end_clock;
751 float encoding_time;
752
753 if(argc != 5 && argc != 6) {
754 printf("Usage: %s <width> <height> <input_yuvfile> <output_avcfile> [qp] \n", argv[0]);
755 return -1;
756 }
757
758 picture_width = atoi(argv[1]);
759 picture_height = atoi(argv[2]);
760 picture_width_in_mbs = (picture_width + 15) / 16;
761 picture_height_in_mbs = (picture_height + 15) / 16;
762
763 if (argc == 6)
764 qp_value = atoi(argv[5]);
765 else
766 qp_value = 26;
767
768 yuv_fp = fopen(argv[3],"rb");
769 if ( yuv_fp == NULL){
770 printf("Can't open input YUV file\n");
771 return -1;
772 }
773 fseek(yuv_fp,0l, SEEK_END);
774 file_size = ftell(yuv_fp);
775 frame_size = picture_width * picture_height + ((picture_width * picture_hei ght) >> 1) ;
776 codedbuf_size = picture_width * picture_height * 1.5;
777
778 if ( (file_size < frame_size) || (file_size % frame_size) ) {
779 printf("The YUV file's size is not correct\n");
780 return -1;
781 }
782 frame_number = file_size / frame_size;
783 fseek(yuv_fp, 0l, SEEK_SET);
784
785 avc_fp = fopen(argv[4], "wb");
786 if ( avc_fp == NULL) {
787 printf("Can't open output avc file\n");
788 return -1;
789 }
790 start_clock = clock();
791 build_header(avc_fp);
792
793 create_encode_pipe();
794 alloc_encode_resource();
795
796 for ( f = 0; f < frame_number; f++ ) { //picture level loop
797 int is_intra = (f % 30 == 0);
798 int is_idr = (f == 0);
799
800 begin_picture();
801 prepare_input(yuv_fp, is_intra);
802 end_picture();
803 store_coded_buffer(avc_fp, f, is_intra, is_idr);
804
805 printf("\r %d/%d ...", f+1, frame_number);
806 fflush(stdout);
807 }
808
809 end_clock = clock();
810 printf("\ndone!\n");
811 encoding_time = (float)(end_clock-start_clock)/CLOCKS_PER_SEC;
812 printf("encode %d frames in %f secondes, FPS is %.1f\n",frame_number, encodi ng_time, frame_number/encoding_time);
813
814 release_encode_resource();
815 destory_encode_pipe();
816
817 return 0;
818 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698