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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: third_party/libva/test/v4l_h264/encode/avcenc.cpp
diff --git a/third_party/libva/test/v4l_h264/encode/avcenc.cpp b/third_party/libva/test/v4l_h264/encode/avcenc.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b3afd569bf41eb50526b65321f5994a2ba2cc7f3
--- /dev/null
+++ b/third_party/libva/test/v4l_h264/encode/avcenc.cpp
@@ -0,0 +1,508 @@
+/*
+ * Copyright (c) 2012 Intel Corporation. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+* Example based on Simple AVC encoder.
+* http://cgit.freedesktop.org/libva/tree/test/encode/avcenc.c
+*
+*/
+
+#include <cstdio>
+#include <cstring>
+#include <cstdarg>
+#include <cassert>
+#include <va/va_x11.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <iostream>
+#include <cstdlib>
+
+#include "TCPSocketClient.h"
+
+#define MY_Y 0x22
+#define MY_U 0xff
+#define MY_V 0x55
+
+
+extern TCPSocketClient *sock_ptr;
+extern int g_Debug;
+extern char *device_settings;
+Window win2;
+int win2_width = 640;
+int win2_height = 480;
+int g_PX = -1;
+int g_PY = -1;
+
+
+bool g_LiveView = true;
+bool g_Force_P_Only = false;
+bool g_ShowNumber = true;
+
+
+
+
+#define SLICE_TYPE_P 0
+#define SLICE_TYPE_B 1
+#define SLICE_TYPE_I 2
+
+#define ENTROPY_MODE_CAVLC 0
+#define ENTROPY_MODE_CABAC 1
+
+#define PROFILE_IDC_BASELINE 66
+#define PROFILE_IDC_MAIN 77
+#define PROFILE_IDC_HIGH 100
+
+#define CHECK_VASTATUS(va_status,func) \
+ if (va_status != VA_STATUS_SUCCESS) { \
+ std::cerr << __func__ << ':' << func << '(' << __LINE__ << ") failed, exit\n"; \
+ exit(1); \
+ }
+
+static Display *x11_display;
+static VADisplay va_dpy;
+static VAContextID context_id;
+static VAConfigID config_id;
+
+static int picture_width, picture_width_in_mbs;
+static int picture_height, picture_height_in_mbs;
+static int frame_size;
+static int codedbuf_size;
+
+static int qp_value = 26;
+
+static int log2_max_frame_num_minus4 = 0;
+static int pic_order_cnt_type = 0;
+static int log2_max_pic_order_cnt_lsb_minus4 = 0;
+static int entropy_coding_mode_flag = ENTROPY_MODE_CABAC;
+static int deblocking_filter_control_present_flag = 1;
+static int frame_mbs_only_flag = 1;
+
+static void create_encode_pipe()
+{
+ VAEntrypoint entrypoints[5];
+ int num_entrypoints,slice_entrypoint;
+ VAConfigAttrib attrib[2];
+ int major_ver, minor_ver;
+ VAStatus va_status;
+
+ x11_display = XOpenDisplay(":0.0");
+ assert(x11_display);
+
+ va_dpy = vaGetDisplay(x11_display);
+ va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
+ CHECK_VASTATUS(va_status, "vaInitialize");
+ vaQueryConfigEntrypoints(va_dpy, VAProfileH264Baseline, entrypoints, &num_entrypoints);
+
+ for (slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypoint++) {
+ if (entrypoints[slice_entrypoint] == VAEntrypointEncSlice)
+ break;
+ }
+
+ if (slice_entrypoint == num_entrypoints) {
+ /* not find Slice entry point */
+ assert(0);
+ }
+
+ /* find out the format for the render target, and rate control mode */
+ attrib[0].type = VAConfigAttribRTFormat;
+ attrib[1].type = VAConfigAttribRateControl;
+ vaGetConfigAttributes(va_dpy, VAProfileH264Baseline, VAEntrypointEncSlice, &attrib[0], 2);
+
+ if ((attrib[0].value & VA_RT_FORMAT_YUV420) == 0) {
+ /* not find desired YUV420 RT format */
+ assert(0);
+ }
+
+ if ((attrib[1].value & VA_RC_VBR) == 0) {
+ /* Can't find matched RC mode */
+ std::cerr << "VBR mode not found, exit\n";
+ assert(0);
+ }
+
+ attrib[0].value = VA_RT_FORMAT_YUV420; /* set to desired RT format */
+ attrib[1].value = VA_RC_VBR; /* set to desired RC mode */
+
+ va_status = vaCreateConfig(va_dpy, VAProfileH264Baseline, VAEntrypointEncSlice, &attrib[0], 2,&config_id);
+ CHECK_VASTATUS(va_status, "vaCreateConfig");
+
+ /* Create a context for this decode pipe */
+ va_status = vaCreateContext(va_dpy, config_id, picture_width, picture_height, VA_PROGRESSIVE, 0, 0, &context_id);
+ CHECK_VASTATUS(va_status, "vaCreateContext");
+}
+
+static void destory_encode_pipe()
+{
+ vaDestroyContext(va_dpy,context_id);
+ vaDestroyConfig(va_dpy,config_id);
+ vaTerminate(va_dpy);
+ XCloseDisplay(x11_display);
+}
+
+/***************************************************
+*
+* The encode pipe resource define
+*
+***************************************************/
+static VABufferID seq_parameter = VA_INVALID_ID; /*Sequence level parameter*/
+static VABufferID pic_parameter = VA_INVALID_ID; /*Picture level parameter*/
+static VABufferID slice_parameter = VA_INVALID_ID; /*Slice level parameter, multil slices*/
+static VABufferID coded_buf = VA_INVALID_ID; /*Output buffer, compressed data*/
+
+#define SID_NUMBER 3
+#define SID_INPUT_PICTURE 0
+#define SID_REFERENCE_PICTURE 1
+#define SID_RECON_PICTURE 2
+static VASurfaceID surface_ids[SID_NUMBER];
+
+/***************************************************/
+
+static void alloc_encode_resource()
+{
+ VAStatus va_status;
+ seq_parameter = VA_INVALID_ID;
+ pic_parameter = VA_INVALID_ID;
+ slice_parameter = VA_INVALID_ID;
+
+ //1. Create sequence parameter set
+ {
+ VAEncSequenceParameterBufferH264 seq_h264 = {0};
+ seq_h264.level_idc = 30;
+ seq_h264.picture_width_in_mbs = picture_width_in_mbs;
+ seq_h264.picture_height_in_mbs = picture_height_in_mbs;
+ seq_h264.bits_per_second = 384*1000;
+ seq_h264.initial_qp = qp_value;
+ seq_h264.min_qp = 3;
+ va_status = vaCreateBuffer(va_dpy, context_id, VAEncSequenceParameterBufferType,
+ sizeof(seq_h264),1,&seq_h264,&seq_parameter);
+ CHECK_VASTATUS(va_status,"vaCreateBuffer");;
+ }
+ //2. Create surface
+ va_status = vaCreateSurfaces(va_dpy, picture_width, picture_height, VA_RT_FORMAT_YUV420, SID_NUMBER, &surface_ids[0]);
+ CHECK_VASTATUS(va_status, "vaCreateSurfaces");
+ //3. Create coded buffer
+ {
+ va_status = vaCreateBuffer(va_dpy,context_id,VAEncCodedBufferType, codedbuf_size, 1, NULL, &coded_buf);
+ CHECK_VASTATUS(va_status,"vaBeginPicture");
+ }
+}
+
+static void release_encode_resource()
+{
+ //-3 Relese coded buffer
+ if (coded_buf != VA_INVALID_ID)
+ vaDestroyBuffer(va_dpy, coded_buf);
+ //-2 Release all the surfaces resource
+ vaDestroySurfaces(va_dpy, &surface_ids[0], SID_NUMBER);
+ //-1 Destory the sequence level parameter
+ if (seq_parameter != VA_INVALID_ID)
+ vaDestroyBuffer(va_dpy, seq_parameter);
+}
+
+
+static int get_coded_bitsteam_length(unsigned char *buffer, int buffer_length)
+{
+ int i;
+ for (i = buffer_length - 1; i >= 0; i--) {
+ if (buffer[i])
+ break;
+ }
+ return i + 1;
+}
+
+
+
+void SetWindowTitle(const char* title, ...)
+{
+ va_list args;
+ va_start(args, title);
+ char buf[256];
+ vsprintf(buf, title, args);
+ va_end(args);
+ XSetStandardProperties(x11_display,win2, buf, buf, None, NULL, 0, NULL);
+}
+
+
+
+int encoder_init(int width, int height)
+{
+ picture_width = width;
+ picture_height = height;
+ picture_width_in_mbs = (picture_width + 15) / 16;
+ picture_height_in_mbs = (picture_height + 15) / 16;
+ qp_value = 26;
+ frame_size = picture_width * picture_height + ((picture_width * picture_height) >> 1) ;
+ codedbuf_size = picture_width * picture_height * 1.5;
+ create_encode_pipe();
+ alloc_encode_resource();
+ sock_ptr->send(picture_width);
+ sock_ptr->send(picture_height);
+ sock_ptr->send(picture_width_in_mbs-1);
+ sock_ptr->send(picture_height_in_mbs-1);
+ if (g_LiveView) {
+ win2 = XCreateSimpleWindow(x11_display, RootWindow(x11_display, 0), 0, 0, win2_width, win2_height, 0, 0, WhitePixel(x11_display, 0));
+ XMapWindow(x11_display, win2);
+ if ((g_PX !=-1) && (g_PY !=-1)) {
+ XMoveWindow(x11_display, win2, g_PX, g_PY);
+ }
+ SetWindowTitle("Input: %dx%d [TCP] %s",picture_width,picture_height, device_settings);
+ XSync(x11_display, False);
+ }
+ return 0;
+}
+
+void encoder_close()
+{
+ release_encode_resource();
+ destory_encode_pipe();
+}
+
+
+/* 8x8 font 0-9 only - asm type format */
+unsigned char mydigits[80] {
+ // 0
+ 0x0E,0x11,0x13,0x15,0x19,0x11,0x0E,0x00,
+ // 1
+ 0x04,0x0C,0x04,0x04,0x04,0x04,0x0E,0x00,
+ // 2
+ 0x0E,0x11,0x01,0x02,0x04,0x08,0x1F,0x00,
+ // 3
+ 0x1F,0x02,0x04,0x02,0x01,0x11,0x0E,0x00,
+ // 4
+ 0x02,0x06,0x0A,0x12,0x1F,0x02,0x02,0x00,
+ // 5
+ 0x1F,0x10,0x1E,0x01,0x01,0x11,0x0E,0x00,
+ // 6
+ 0x06,0x08,0x10,0x1E,0x11,0x11,0x0E,0x00,
+ // 7
+ 0x1F,0x01,0x02,0x04,0x04,0x04,0x04,0x00,
+ // 8
+ 0x1E,0x11,0x11,0x0E,0x11,0x11,0x0E,0x00,
+ //9
+ 0x0E,0x11,0x11,0x0F,0x01,0x02,0x0C,0x00
+};
+
+#define INTERSIZE 16
+
+static void ShowNumber(int num, unsigned char *buffer, VAImage *image)
+{
+ int j;
+ char buf[20];
+ unsigned char *dst_y;
+ unsigned char *dst_uv_line;
+ unsigned char *digits_ptr;
+ assert(image);
+ int maxlen = sprintf(buf, "%d", num);
+ assert(maxlen<20);
+ for (int a=0; a<maxlen;a++) {
+ digits_ptr = &mydigits[(buf[a]-'0')*8];
+ for (int i=0; i<8; i++) {
+ unsigned char current = digits_ptr[i];
+ dst_y = (buffer+ image->offsets[0]) + ((i*2)*image->pitches[0])+(a*INTERSIZE);
+ dst_uv_line = (buffer + image->offsets[1]) + (i*image->pitches[1])+(a*INTERSIZE);
+ for (j=7; j>=0;j--) {
+ if ((current >>j) & 1) {
+ *dst_y ++ = MY_Y;
+ *dst_y ++ = MY_Y;
+ *dst_uv_line++ = MY_U;
+ *dst_uv_line++ = MY_V;
+ } else {
+ dst_y += 2;
+ dst_uv_line +=2;
+ }
+ }
+ dst_y = (buffer+ image->offsets[0]) + (((i*2)+1)*image->pitches[0])+(a*INTERSIZE);
+ for (j=7; j>=0;j--) {
+ if ((current >>j) & 1) {
+ *dst_y ++ = MY_Y;
+ *dst_y ++ = MY_Y;
+ } else {
+ dst_y += 2;
+ }
+ }
+ }
+ }
+}
+
+
+
+static void upload_yuv_to_surface(unsigned char *inbuf, VASurfaceID surface_id, unsigned int frame)
+{
+ VAImage image;
+ VAStatus va_status;
+ void *pbuffer=NULL;
+ unsigned char *psrc = inbuf;
+ unsigned char *pdst = NULL;
+ unsigned char *dst_y, *dst_uv;
+ unsigned char *src_u, *src_v;
+ unsigned char *dst_uv_line = NULL;
+ int i,j;
+ va_status = vaDeriveImage(va_dpy, surface_id, &image);
+ va_status = vaMapBuffer(va_dpy, image.buf, &pbuffer);
+ pdst = (unsigned char *)pbuffer;
+ dst_uv_line = pdst + image.offsets[1];
+ dst_uv = dst_uv_line;
+ for (i=0; i<picture_height; i+=2) {
+ dst_y = (pdst + image.offsets[0]) + i*image.pitches[0];
+ for (j=0; j<(picture_width/2); ++j) {
+ *(dst_y++) = psrc[0];//y1;
+ *(dst_uv++) = psrc[1];//u;
+ *(dst_y++) = psrc[2];//y1;
+ *(dst_uv++) = psrc[3];//v;
+ psrc+=4;
+ }
+ dst_y = (pdst + image.offsets[0]) + (i+1)*image.pitches[0];
+ for (j=0; j<picture_width/2; ++j) {
+ *(dst_y++) = psrc[0];//y1;
+ *(dst_y++) = psrc[2];//y2;
+ psrc+=4;
+ }
+ dst_uv_line += image.pitches[1];
+ dst_uv = dst_uv_line;
+ }
+ if (g_ShowNumber) {
+ ShowNumber(frame, (unsigned char *)pbuffer, &image);
+ }
+ va_status = vaUnmapBuffer(va_dpy, image.buf);
+ CHECK_VASTATUS(va_status,"vaUnmapBuffer");
+ va_status = vaDestroyImage(va_dpy, image.image_id);
+ CHECK_VASTATUS(va_status,"vaDestroyImage");
+ if (g_LiveView) {
+ va_status = vaPutSurface(va_dpy, surface_id, win2, 0, 0, picture_width,picture_height, 0, 0, win2_width, win2_height, NULL, 0, VA_FRAME_PICTURE);
+ CHECK_VASTATUS(va_status,"vaPutSurface");
+ }
+}
+
+
+static void prepare_input(unsigned char *buffer, int intra_slice, unsigned int frame)
+{
+ static VAEncPictureParameterBufferH264 pic_h264;
+ static VAEncSliceParameterBuffer slice_h264;
+ VAStatus va_status;
+ VABufferID tempID;
+ VACodedBufferSegment *coded_buffer_segment = NULL;
+ unsigned char *coded_mem;
+ // Sequence level
+ va_status = vaRenderPicture(va_dpy, context_id, &seq_parameter, 1);
+ CHECK_VASTATUS(va_status,"vaRenderPicture");;
+ // Copy Image to target surface according input YUV data.
+ upload_yuv_to_surface(buffer, surface_ids[SID_INPUT_PICTURE], frame);
+ // Picture level
+ pic_h264.reference_picture = surface_ids[SID_REFERENCE_PICTURE];
+ pic_h264.reconstructed_picture = surface_ids[SID_RECON_PICTURE];
+ pic_h264.coded_buf = coded_buf;
+ pic_h264.picture_width = picture_width;
+ pic_h264.picture_height = picture_height;
+ pic_h264.last_picture = 0;
+ if (pic_parameter != VA_INVALID_ID) {
+ vaDestroyBuffer(va_dpy, pic_parameter);
+ }
+ va_status = vaCreateBuffer(va_dpy, context_id,VAEncPictureParameterBufferType,
+ sizeof(pic_h264),1,&pic_h264,&pic_parameter);
+ CHECK_VASTATUS(va_status,"vaCreateBuffer");
+ va_status = vaRenderPicture(va_dpy,context_id, &pic_parameter, 1);
+ CHECK_VASTATUS(va_status,"vaRenderPicture");
+ // clean old memory
+ va_status = vaMapBuffer(va_dpy,coded_buf,(void **)(&coded_buffer_segment));
+ CHECK_VASTATUS(va_status,"vaMapBuffer");
+ coded_mem = (unsigned char*)coded_buffer_segment->buf;
+ memset(coded_mem, 0, coded_buffer_segment->size);
+ vaUnmapBuffer(va_dpy, coded_buf);
+ // Slice level
+ slice_h264.start_row_number = 0;
+ slice_h264.slice_height = picture_height/16; /* Measured by MB */
+ slice_h264.slice_flags.bits.is_intra = intra_slice;
+ slice_h264.slice_flags.bits.disable_deblocking_filter_idc = 0;
+ if ( slice_parameter != VA_INVALID_ID) {
+ vaDestroyBuffer(va_dpy, slice_parameter);
+ }
+ va_status = vaCreateBuffer(va_dpy,context_id,VAEncSliceParameterBufferType,
+ sizeof(slice_h264),1,&slice_h264,&slice_parameter);
+ CHECK_VASTATUS(va_status,"vaCreateBuffer");;
+ va_status = vaRenderPicture(va_dpy,context_id, &slice_parameter, 1);
+ CHECK_VASTATUS(va_status,"vaRenderPicture");
+
+ // Prepare for next picture
+ tempID = surface_ids[SID_RECON_PICTURE];
+ surface_ids[SID_RECON_PICTURE] = surface_ids[SID_REFERENCE_PICTURE];
+ surface_ids[SID_REFERENCE_PICTURE] = tempID;
+}
+
+static void send_slice_data(unsigned int frcount, int slice_type)
+{
+ VACodedBufferSegment *coded_buffer_segment;
+ unsigned char *coded_mem;
+ int i, slice_data_length;
+ int mm;
+ VAStatus va_status;
+ VASurfaceStatus surface_status;
+ int is_cabac = (entropy_coding_mode_flag == ENTROPY_MODE_CABAC);
+ va_status = vaSyncSurface(va_dpy, surface_ids[SID_INPUT_PICTURE]);
+ CHECK_VASTATUS(va_status,"vaSyncSurface");
+ surface_status = (VASurfaceStatus)0;
+ va_status = vaQuerySurfaceStatus(va_dpy, surface_ids[SID_INPUT_PICTURE], &surface_status);
+ CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus");
+ va_status = vaMapBuffer(va_dpy, coded_buf, (void **)(&coded_buffer_segment));
+ CHECK_VASTATUS(va_status,"vaMapBuffer");
+ coded_mem = (unsigned char*)coded_buffer_segment->buf;
+ sock_ptr->send(frcount);
+ sock_ptr->send(slice_type);
+
+ if (is_cabac) {
+ if (!coded_buffer_segment->next) {
+ slice_data_length = get_coded_bitsteam_length(coded_mem, codedbuf_size);
+ } else {
+ /* Fixme me - to do: loop to each block and calculate the real data_lenght */
+ assert(0);
+ }
+ if (g_Debug) {
+ printf("T=%d BS=%8d SZ=%8d C=%d\n", slice_type, codedbuf_size, slice_data_length, frcount);
+ }sock_ptr->send(slice_data_length);
+ sock_ptr->send((unsigned char*)coded_mem, slice_data_length);
+ } else {
+ /* FIXME */
+ assert(0);
+ }
+ vaUnmapBuffer(va_dpy, coded_buf);
+}
+
+
+int encode_frame(unsigned char *inbuf)
+{
+ static unsigned int framecount = 0;
+ int is_intra = (framecount % 30 == 0);
+ if (g_Force_P_Only) {
+ is_intra = 1;
+ }
+ VAStatus va_status;
+ va_status = vaBeginPicture(va_dpy, context_id, surface_ids[SID_INPUT_PICTURE]);
+ CHECK_VASTATUS(va_status,"vaBeginPicture");
+ prepare_input(inbuf, is_intra, framecount);
+ va_status = vaEndPicture(va_dpy,context_id);
+ CHECK_VASTATUS(va_status,"vaRenderPicture");
+ send_slice_data(framecount, is_intra ? SLICE_TYPE_I : SLICE_TYPE_P);
+ framecount++;
+ return 1;
+}
+

Powered by Google App Engine
This is Rietveld 408576698