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

Side by Side Diff: third_party/libva/test/v4l_h264/encode/avcenc.cpp

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 * 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,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /*
26 * Example based on Simple AVC encoder.
27 * http://cgit.freedesktop.org/libva/tree/test/encode/avcenc.c
28 *
29 */
30
31 #include <cstdio>
32 #include <cstring>
33 #include <cstdarg>
34 #include <cassert>
35 #include <va/va_x11.h>
36 #include <X11/Xlib.h>
37 #include <X11/Xutil.h>
38
39 #include <iostream>
40 #include <cstdlib>
41
42 #include "TCPSocketClient.h"
43
44 #define MY_Y 0x22
45 #define MY_U 0xff
46 #define MY_V 0x55
47
48
49 extern TCPSocketClient *sock_ptr;
50 extern int g_Debug;
51 extern char *device_settings;
52 Window win2;
53 int win2_width = 640;
54 int win2_height = 480;
55 int g_PX = -1;
56 int g_PY = -1;
57
58
59 bool g_LiveView = true;
60 bool g_Force_P_Only = false;
61 bool g_ShowNumber = true;
62
63
64
65
66 #define SLICE_TYPE_P 0
67 #define SLICE_TYPE_B 1
68 #define SLICE_TYPE_I 2
69
70 #define ENTROPY_MODE_CAVLC 0
71 #define ENTROPY_MODE_CABAC 1
72
73 #define PROFILE_IDC_BASELINE 66
74 #define PROFILE_IDC_MAIN 77
75 #define PROFILE_IDC_HIGH 100
76
77 #define CHECK_VASTATUS(va_status,func) \
78 if (va_status != VA_STATUS_SUCCESS) { \
79 std::cerr << __func__ << ':' << func << '(' << __LINE__ << ") failed, ex it\n"; \
80 exit(1); \
81 }
82
83 static Display *x11_display;
84 static VADisplay va_dpy;
85 static VAContextID context_id;
86 static VAConfigID config_id;
87
88 static int picture_width, picture_width_in_mbs;
89 static int picture_height, picture_height_in_mbs;
90 static int frame_size;
91 static int codedbuf_size;
92
93 static int qp_value = 26;
94
95 static int log2_max_frame_num_minus4 = 0;
96 static int pic_order_cnt_type = 0;
97 static int log2_max_pic_order_cnt_lsb_minus4 = 0;
98 static int entropy_coding_mode_flag = ENTROPY_MODE_CABAC;
99 static int deblocking_filter_control_present_flag = 1;
100 static int frame_mbs_only_flag = 1;
101
102 static void create_encode_pipe()
103 {
104 VAEntrypoint entrypoints[5];
105 int num_entrypoints,slice_entrypoint;
106 VAConfigAttrib attrib[2];
107 int major_ver, minor_ver;
108 VAStatus va_status;
109
110 x11_display = XOpenDisplay(":0.0");
111 assert(x11_display);
112
113 va_dpy = vaGetDisplay(x11_display);
114 va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
115 CHECK_VASTATUS(va_status, "vaInitialize");
116 vaQueryConfigEntrypoints(va_dpy, VAProfileH264Baseline, entrypoints, &num_en trypoints);
117
118 for (slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypo int++) {
119 if (entrypoints[slice_entrypoint] == VAEntrypointEncSlice)
120 break;
121 }
122
123 if (slice_entrypoint == num_entrypoints) {
124 /* not find Slice entry point */
125 assert(0);
126 }
127
128 /* find out the format for the render target, and rate control mode */
129 attrib[0].type = VAConfigAttribRTFormat;
130 attrib[1].type = VAConfigAttribRateControl;
131 vaGetConfigAttributes(va_dpy, VAProfileH264Baseline, VAEntrypointEncSlice, & attrib[0], 2);
132
133 if ((attrib[0].value & VA_RT_FORMAT_YUV420) == 0) {
134 /* not find desired YUV420 RT format */
135 assert(0);
136 }
137
138 if ((attrib[1].value & VA_RC_VBR) == 0) {
139 /* Can't find matched RC mode */
140 std::cerr << "VBR mode not found, exit\n";
141 assert(0);
142 }
143
144 attrib[0].value = VA_RT_FORMAT_YUV420; /* set to desired RT format */
145 attrib[1].value = VA_RC_VBR; /* set to desired RC mode */
146
147 va_status = vaCreateConfig(va_dpy, VAProfileH264Baseline, VAEntrypointEncSli ce, &attrib[0], 2,&config_id);
148 CHECK_VASTATUS(va_status, "vaCreateConfig");
149
150 /* Create a context for this decode pipe */
151 va_status = vaCreateContext(va_dpy, config_id, picture_width, picture_height , VA_PROGRESSIVE, 0, 0, &context_id);
152 CHECK_VASTATUS(va_status, "vaCreateContext");
153 }
154
155 static void destory_encode_pipe()
156 {
157 vaDestroyContext(va_dpy,context_id);
158 vaDestroyConfig(va_dpy,config_id);
159 vaTerminate(va_dpy);
160 XCloseDisplay(x11_display);
161 }
162
163 /***************************************************
164 *
165 * The encode pipe resource define
166 *
167 ***************************************************/
168 static VABufferID seq_parameter = VA_INVALID_ID; /*Sequence level parameter*/
169 static VABufferID pic_parameter = VA_INVALID_ID; /*Picture level parameter*/
170 static VABufferID slice_parameter = VA_INVALID_ID; /*Slice level pa rameter, multil slices*/
171 static VABufferID coded_buf = VA_INVALID_ID; /*Output buffer, compressed data*/
172
173 #define SID_NUMBER 3
174 #define SID_INPUT_PICTURE 0
175 #define SID_REFERENCE_PICTURE 1
176 #define SID_RECON_PICTURE 2
177 static VASurfaceID surface_ids[SID_NUMBER];
178
179 /***************************************************/
180
181 static void alloc_encode_resource()
182 {
183 VAStatus va_status;
184 seq_parameter = VA_INVALID_ID;
185 pic_parameter = VA_INVALID_ID;
186 slice_parameter = VA_INVALID_ID;
187
188 //1. Create sequence parameter set
189 {
190 VAEncSequenceParameterBufferH264 seq_h264 = {0};
191 seq_h264.level_idc = 30;
192 seq_h264.picture_width_in_mbs = picture_width_in_mbs;
193 seq_h264.picture_height_in_mbs = picture_height_in_mbs;
194 seq_h264.bits_per_second = 384*1000;
195 seq_h264.initial_qp = qp_value;
196 seq_h264.min_qp = 3;
197 va_status = vaCreateBuffer(va_dpy, context_id, VAEncSequenceParameterBuf ferType,
198 sizeof(seq_h264),1,&seq_h264,&seq_parameter);
199 CHECK_VASTATUS(va_status,"vaCreateBuffer");;
200 }
201 //2. Create surface
202 va_status = vaCreateSurfaces(va_dpy, picture_width, picture_height, VA_RT_FO RMAT_YUV420, SID_NUMBER, &surface_ids[0]);
203 CHECK_VASTATUS(va_status, "vaCreateSurfaces");
204 //3. Create coded buffer
205 {
206 va_status = vaCreateBuffer(va_dpy,context_id,VAEncCodedBufferType, coded buf_size, 1, NULL, &coded_buf);
207 CHECK_VASTATUS(va_status,"vaBeginPicture");
208 }
209 }
210
211 static void release_encode_resource()
212 {
213 //-3 Relese coded buffer
214 if (coded_buf != VA_INVALID_ID)
215 vaDestroyBuffer(va_dpy, coded_buf);
216 //-2 Release all the surfaces resource
217 vaDestroySurfaces(va_dpy, &surface_ids[0], SID_NUMBER);
218 //-1 Destory the sequence level parameter
219 if (seq_parameter != VA_INVALID_ID)
220 vaDestroyBuffer(va_dpy, seq_parameter);
221 }
222
223
224 static int get_coded_bitsteam_length(unsigned char *buffer, int buffer_length)
225 {
226 int i;
227 for (i = buffer_length - 1; i >= 0; i--) {
228 if (buffer[i])
229 break;
230 }
231 return i + 1;
232 }
233
234
235
236 void SetWindowTitle(const char* title, ...)
237 {
238 va_list args;
239 va_start(args, title);
240 char buf[256];
241 vsprintf(buf, title, args);
242 va_end(args);
243 XSetStandardProperties(x11_display,win2, buf, buf, None, NULL, 0, NULL);
244 }
245
246
247
248 int encoder_init(int width, int height)
249 {
250 picture_width = width;
251 picture_height = height;
252 picture_width_in_mbs = (picture_width + 15) / 16;
253 picture_height_in_mbs = (picture_height + 15) / 16;
254 qp_value = 26;
255 frame_size = picture_width * picture_height + ((picture_width * picture_hei ght) >> 1) ;
256 codedbuf_size = picture_width * picture_height * 1.5;
257 create_encode_pipe();
258 alloc_encode_resource();
259 sock_ptr->send(picture_width);
260 sock_ptr->send(picture_height);
261 sock_ptr->send(picture_width_in_mbs-1);
262 sock_ptr->send(picture_height_in_mbs-1);
263 if (g_LiveView) {
264 win2 = XCreateSimpleWindow(x11_display, RootWindow(x11_display, 0), 0, 0 , win2_width, win2_height, 0, 0, WhitePixel(x11_display, 0));
265 XMapWindow(x11_display, win2);
266 if ((g_PX !=-1) && (g_PY !=-1)) {
267 XMoveWindow(x11_display, win2, g_PX, g_PY);
268 }
269 SetWindowTitle("Input: %dx%d [TCP] %s",picture_width,picture_height, dev ice_settings);
270 XSync(x11_display, False);
271 }
272 return 0;
273 }
274
275 void encoder_close()
276 {
277 release_encode_resource();
278 destory_encode_pipe();
279 }
280
281
282 /* 8x8 font 0-9 only - asm type format */
283 unsigned char mydigits[80] {
284 // 0
285 0x0E,0x11,0x13,0x15,0x19,0x11,0x0E,0x00,
286 // 1
287 0x04,0x0C,0x04,0x04,0x04,0x04,0x0E,0x00,
288 // 2
289 0x0E,0x11,0x01,0x02,0x04,0x08,0x1F,0x00,
290 // 3
291 0x1F,0x02,0x04,0x02,0x01,0x11,0x0E,0x00,
292 // 4
293 0x02,0x06,0x0A,0x12,0x1F,0x02,0x02,0x00,
294 // 5
295 0x1F,0x10,0x1E,0x01,0x01,0x11,0x0E,0x00,
296 // 6
297 0x06,0x08,0x10,0x1E,0x11,0x11,0x0E,0x00,
298 // 7
299 0x1F,0x01,0x02,0x04,0x04,0x04,0x04,0x00,
300 // 8
301 0x1E,0x11,0x11,0x0E,0x11,0x11,0x0E,0x00,
302 //9
303 0x0E,0x11,0x11,0x0F,0x01,0x02,0x0C,0x00
304 };
305
306 #define INTERSIZE 16
307
308 static void ShowNumber(int num, unsigned char *buffer, VAImage *image)
309 {
310 int j;
311 char buf[20];
312 unsigned char *dst_y;
313 unsigned char *dst_uv_line;
314 unsigned char *digits_ptr;
315 assert(image);
316 int maxlen = sprintf(buf, "%d", num);
317 assert(maxlen<20);
318 for (int a=0; a<maxlen;a++) {
319 digits_ptr = &mydigits[(buf[a]-'0')*8];
320 for (int i=0; i<8; i++) {
321 unsigned char current = digits_ptr[i];
322 dst_y = (buffer+ image->offsets[0]) + ((i*2)*image->pitches[0])+(a*I NTERSIZE);
323 dst_uv_line = (buffer + image->offsets[1]) + (i*image->pitches[1])+( a*INTERSIZE);
324 for (j=7; j>=0;j--) {
325 if ((current >>j) & 1) {
326 *dst_y ++ = MY_Y;
327 *dst_y ++ = MY_Y;
328 *dst_uv_line++ = MY_U;
329 *dst_uv_line++ = MY_V;
330 } else {
331 dst_y += 2;
332 dst_uv_line +=2;
333 }
334 }
335 dst_y = (buffer+ image->offsets[0]) + (((i*2)+1)*image->pitches[0])+ (a*INTERSIZE);
336 for (j=7; j>=0;j--) {
337 if ((current >>j) & 1) {
338 *dst_y ++ = MY_Y;
339 *dst_y ++ = MY_Y;
340 } else {
341 dst_y += 2;
342 }
343 }
344 }
345 }
346 }
347
348
349
350 static void upload_yuv_to_surface(unsigned char *inbuf, VASurfaceID surface_id, unsigned int frame)
351 {
352 VAImage image;
353 VAStatus va_status;
354 void *pbuffer=NULL;
355 unsigned char *psrc = inbuf;
356 unsigned char *pdst = NULL;
357 unsigned char *dst_y, *dst_uv;
358 unsigned char *src_u, *src_v;
359 unsigned char *dst_uv_line = NULL;
360 int i,j;
361 va_status = vaDeriveImage(va_dpy, surface_id, &image);
362 va_status = vaMapBuffer(va_dpy, image.buf, &pbuffer);
363 pdst = (unsigned char *)pbuffer;
364 dst_uv_line = pdst + image.offsets[1];
365 dst_uv = dst_uv_line;
366 for (i=0; i<picture_height; i+=2) {
367 dst_y = (pdst + image.offsets[0]) + i*image.pitches[0];
368 for (j=0; j<(picture_width/2); ++j) {
369 *(dst_y++) = psrc[0];//y1;
370 *(dst_uv++) = psrc[1];//u;
371 *(dst_y++) = psrc[2];//y1;
372 *(dst_uv++) = psrc[3];//v;
373 psrc+=4;
374 }
375 dst_y = (pdst + image.offsets[0]) + (i+1)*image.pitches[0];
376 for (j=0; j<picture_width/2; ++j) {
377 *(dst_y++) = psrc[0];//y1;
378 *(dst_y++) = psrc[2];//y2;
379 psrc+=4;
380 }
381 dst_uv_line += image.pitches[1];
382 dst_uv = dst_uv_line;
383 }
384 if (g_ShowNumber) {
385 ShowNumber(frame, (unsigned char *)pbuffer, &image);
386 }
387 va_status = vaUnmapBuffer(va_dpy, image.buf);
388 CHECK_VASTATUS(va_status,"vaUnmapBuffer");
389 va_status = vaDestroyImage(va_dpy, image.image_id);
390 CHECK_VASTATUS(va_status,"vaDestroyImage");
391 if (g_LiveView) {
392 va_status = vaPutSurface(va_dpy, surface_id, win2, 0, 0, picture_width,p icture_height, 0, 0, win2_width, win2_height, NULL, 0, VA_FRAME_PICTURE);
393 CHECK_VASTATUS(va_status,"vaPutSurface");
394 }
395 }
396
397
398 static void prepare_input(unsigned char *buffer, int intra_slice, unsigned int f rame)
399 {
400 static VAEncPictureParameterBufferH264 pic_h264;
401 static VAEncSliceParameterBuffer slice_h264;
402 VAStatus va_status;
403 VABufferID tempID;
404 VACodedBufferSegment *coded_buffer_segment = NULL;
405 unsigned char *coded_mem;
406 // Sequence level
407 va_status = vaRenderPicture(va_dpy, context_id, &seq_parameter, 1);
408 CHECK_VASTATUS(va_status,"vaRenderPicture");;
409 // Copy Image to target surface according input YUV data.
410 upload_yuv_to_surface(buffer, surface_ids[SID_INPUT_PICTURE], frame);
411 // Picture level
412 pic_h264.reference_picture = surface_ids[SID_REFERENCE_PICTURE];
413 pic_h264.reconstructed_picture = surface_ids[SID_RECON_PICTURE];
414 pic_h264.coded_buf = coded_buf;
415 pic_h264.picture_width = picture_width;
416 pic_h264.picture_height = picture_height;
417 pic_h264.last_picture = 0;
418 if (pic_parameter != VA_INVALID_ID) {
419 vaDestroyBuffer(va_dpy, pic_parameter);
420 }
421 va_status = vaCreateBuffer(va_dpy, context_id,VAEncPictureParameterBufferTyp e,
422 sizeof(pic_h264),1,&pic_h264,&pic_parameter);
423 CHECK_VASTATUS(va_status,"vaCreateBuffer");
424 va_status = vaRenderPicture(va_dpy,context_id, &pic_parameter, 1);
425 CHECK_VASTATUS(va_status,"vaRenderPicture");
426 // clean old memory
427 va_status = vaMapBuffer(va_dpy,coded_buf,(void **)(&coded_buffer_segment));
428 CHECK_VASTATUS(va_status,"vaMapBuffer");
429 coded_mem = (unsigned char*)coded_buffer_segment->buf;
430 memset(coded_mem, 0, coded_buffer_segment->size);
431 vaUnmapBuffer(va_dpy, coded_buf);
432 // Slice level
433 slice_h264.start_row_number = 0;
434 slice_h264.slice_height = picture_height/16; /* Measured by MB */
435 slice_h264.slice_flags.bits.is_intra = intra_slice;
436 slice_h264.slice_flags.bits.disable_deblocking_filter_idc = 0;
437 if ( slice_parameter != VA_INVALID_ID) {
438 vaDestroyBuffer(va_dpy, slice_parameter);
439 }
440 va_status = vaCreateBuffer(va_dpy,context_id,VAEncSliceParameterBufferType,
441 sizeof(slice_h264),1,&slice_h264,&slice_parameter);
442 CHECK_VASTATUS(va_status,"vaCreateBuffer");;
443 va_status = vaRenderPicture(va_dpy,context_id, &slice_parameter, 1);
444 CHECK_VASTATUS(va_status,"vaRenderPicture");
445
446 // Prepare for next picture
447 tempID = surface_ids[SID_RECON_PICTURE];
448 surface_ids[SID_RECON_PICTURE] = surface_ids[SID_REFERENCE_PICTURE];
449 surface_ids[SID_REFERENCE_PICTURE] = tempID;
450 }
451
452 static void send_slice_data(unsigned int frcount, int slice_type)
453 {
454 VACodedBufferSegment *coded_buffer_segment;
455 unsigned char *coded_mem;
456 int i, slice_data_length;
457 int mm;
458 VAStatus va_status;
459 VASurfaceStatus surface_status;
460 int is_cabac = (entropy_coding_mode_flag == ENTROPY_MODE_CABAC);
461 va_status = vaSyncSurface(va_dpy, surface_ids[SID_INPUT_PICTURE]);
462 CHECK_VASTATUS(va_status,"vaSyncSurface");
463 surface_status = (VASurfaceStatus)0;
464 va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[SID_INPUT_PICTURE], &su rface_status);
465 CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
466 va_status = vaMapBuffer(va_dpy, coded_buf, (void **)(&coded_buffer_segment)) ;
467 CHECK_VASTATUS(va_status,"vaMapBuffer");
468 coded_mem = (unsigned char*)coded_buffer_segment->buf;
469 sock_ptr->send(frcount);
470 sock_ptr->send(slice_type);
471
472 if (is_cabac) {
473 if (!coded_buffer_segment->next) {
474 slice_data_length = get_coded_bitsteam_length(coded_mem, codedbuf_si ze);
475 } else {
476 /* Fixme me - to do: loop to each block and calculate the real data_ lenght */
477 assert(0);
478 }
479 if (g_Debug) {
480 printf("T=%d BS=%8d SZ=%8d C=%d\n", slice_type, codedbuf_size, slice _data_length, frcount);
481 }sock_ptr->send(slice_data_length);
482 sock_ptr->send((unsigned char*)coded_mem, slice_data_length);
483 } else {
484 /* FIXME */
485 assert(0);
486 }
487 vaUnmapBuffer(va_dpy, coded_buf);
488 }
489
490
491 int encode_frame(unsigned char *inbuf)
492 {
493 static unsigned int framecount = 0;
494 int is_intra = (framecount % 30 == 0);
495 if (g_Force_P_Only) {
496 is_intra = 1;
497 }
498 VAStatus va_status;
499 va_status = vaBeginPicture(va_dpy, context_id, surface_ids[SID_INPUT_PICTURE ]);
500 CHECK_VASTATUS(va_status,"vaBeginPicture");
501 prepare_input(inbuf, is_intra, framecount);
502 va_status = vaEndPicture(va_dpy,context_id);
503 CHECK_VASTATUS(va_status,"vaRenderPicture");
504 send_slice_data(framecount, is_intra ? SLICE_TYPE_I : SLICE_TYPE_P);
505 framecount++;
506 return 1;
507 }
508
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698