int mediaBufferInit(struct mediaBuffer *medBuf, int size) { int err; if (medBuf == NULL) { err_msg("Media Buffer: cannot init\n"); return -1; } medBuf->desc.size = size; err = IOGetPhyMem(&medBuf->desc); if (err) { err_msg("Media buffer: phys allocation failure\n"); return -1; } medBuf->desc.virt_uaddr = IOGetVirtMem(&(medBuf->desc)); if (medBuf->desc.virt_uaddr <= 0) { IOFreePhyMem(&medBuf->desc); err_msg("Media buffer: IOGetVirtMem failed\n"); return -1; } info_msg("Media buffer: allocated new buffer with size of %d\n", size); medBuf->vBufOut = (unsigned char *)medBuf->desc.virt_uaddr; medBuf->pBufOut = (unsigned char *)medBuf->desc.phy_addr; return 0; }
bufZone* VpuDec::allocHwBuffer(u32 size) { int ret = 0; mem_desc.size = size; Dec_bufZone.bufSize = mem_desc.size; ret = IOGetPhyMem(&mem_desc); if (ret) { printf("Unable to obtain physical memory,LINE:%d\n",__LINE__); return 0; } Dec_bufZone.pStartAddr = mem_desc.phy_addr; Dec_bufZone.vStartaddr = (void *)IOGetVirtMem(&mem_desc); if (Dec_bufZone.vStartaddr <= 0) { printf("Unable to map physical memory,LINE:%d\n",__LINE__); return 0; } if(dec_format == STD_AVC) Dec_bufZone.isRingBuf = 1; else Dec_bufZone.isRingBuf = 0; return &Dec_bufZone; }
struct frame_buf * vpu_framebuf_alloc(int strideY, int height) { struct frame_buf *fb; int size; fb = get_framebuf(); if (fb == NULL) return NULL; size = strideY * height; memset(&(fb->desc), 0, sizeof(vpu_mem_desc)); fb->desc.size = (size * 3 / 2); if (IOGetPhyMem(&fb->desc)) { DBG("--- Frame buffer allocation failed ---\n"); memset(&(fb->desc), 0, sizeof(vpu_mem_desc)); return NULL; } fb->addrY = fb->desc.phy_addr; fb->addrCb = fb->addrY + size; fb->addrCr = fb->addrCb + (size>>2); fb->desc.virt_uaddr = IOGetVirtMem(&(fb->desc)); if (fb->desc.virt_uaddr <= 0) { IOFreePhyMem(&fb->desc); memset(&(fb->desc), 0, sizeof(vpu_mem_desc)); return NULL; } return fb; }
EncodingInstance vpu_create_encoding_instance(const int src_width, const int src_height, const char* filename) { EncodingInstance instance = NULL; instance = calloc(1, sizeof(struct EncodingInstance)); instance->mem_desc.size = STREAM_BUF_SIZE; IOGetPhyMem(&(instance->mem_desc)); instance->virt_bsbuf_addr = IOGetVirtMem(&(instance->mem_desc)); instance->phy_bsbuf_addr = instance->mem_desc.phy_addr; instance->src_picwidth = src_width; instance->src_picheight = src_height; // instance->enc_picwidth = 640; // instance->enc_picheight = 480; instance->fd = open(filename, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); encoder_open(instance); encoder_configure(instance); encoder_allocate_framebuffer(instance); encoder_fill_headers(instance); instance->enc_param.sourceFrame = &instance->fb[instance->src_fbid]; instance->enc_param.quantParam = 23; instance->enc_param.forceIPicture = 0; instance->enc_param.skipPicture = 0; instance->enc_param.enableAutoSkip = 1; instance->enc_param.encLeftOffset = 0; instance->enc_param.encTopOffset = 0; return instance; }
struct frame_buf *framebuf_alloc(int stdMode, int format, int strideY, int height) { struct frame_buf *fb; int err; int divX, divY; fb = get_framebuf(); if(fb == NULL) return NULL; divX = (format == MODE420 || format == MODE422) ? 2 : 1; divY = (format == MODE420 || format == MODE224) ? 2 : 1; memset(&(fb->desc), 0, sizeof(vpu_mem_desc)); fb->desc.size = (strideY * height + strideY / divX * height / divY * 2); if(cpu_is_mx37() || cpu_is_mx5x()) fb->desc.size += strideY / divX * height / divY; err = IOGetPhyMem(&fb->desc); if(err) { printf("Frame buffer allocation failure\n"); memset(&(fb->desc), 0, sizeof(vpu_mem_desc)); return NULL; } fb->addrY = fb->desc.phy_addr; fb->addrCb = fb->addrY + strideY * height; fb->addrCr = fb->addrCb + strideY / divX * height / divY; fb->strideY = strideY; fb->strideC = strideY / divX; if(cpu_is_mx37() || cpu_is_mx5x()) { if(stdMode == STD_MJPG) fb->mvColBuf = fb->addrCr; else fb->mvColBuf = fb->addrCr + strideY / divX * height / divY; } fb->desc.virt_uaddr = IOGetVirtMem(&(fb->desc)); if(fb->desc.virt_uaddr <= 0) { IOFreePhyMem(&fb->desc); memset(&(fb->desc), 0, sizeof(vpu_mem_desc)); return NULL; } return fb; }
static struct frame_buf *x264_framebuf_alloc(int stdMode, int format, int strideY, int height) { struct frame_buf *fb; int err; int divX, divY; fb = x264_get_framebuf(); if (fb == NULL) return NULL; divX = (format == MODE420 || format == MODE422) ? 2 : 1; divY = (format == MODE420 || format == MODE224) ? 2 : 1; memset(&(fb->desc), 0, sizeof(vpu_mem_desc)); fb->desc.size = (strideY * height + strideY / divX * height / divY * 2); fb->desc.size += strideY / divX * height / divY; err = IOGetPhyMem(&fb->desc); if (err) { ms_error("MSH264Enc: Frame buffer allocation failure\n"); memset(&(fb->desc), 0, sizeof(vpu_mem_desc)); return NULL; } fb->addrY = fb->desc.phy_addr; fb->addrCb = fb->addrY + strideY * height; fb->addrCr = fb->addrCb + strideY / divX * height / divY; fb->strideY = strideY; fb->strideC = strideY / divX; fb->mvColBuf = fb->addrCr + strideY / divX * height / divY; fb->desc.virt_uaddr = IOGetVirtMem(&(fb->desc)); if (fb->desc.virt_uaddr <= 0) { IOFreePhyMem(&fb->desc); memset(&(fb->desc), 0, sizeof(vpu_mem_desc)); return NULL; } return fb; }
static void enc_init(MSFilter *f){ EncData *d=ms_new(EncData,1); d->enc=NULL; d->keyframe_int=10; /*10 seconds */ d->mode=0; d->framenum=0; d->generate_keyframe=FALSE; d->packer=NULL; d->vconf_list = &x264_conf_list[0]; d->vconf = ms_video_find_best_configuration_for_bitrate(d->vconf_list, 384000); d->flv = newFLVStream(2*1024*1024); d->enc = ms_new0(struct x264_encode,1); f->data=d; if(vpu_Init(NULL)!=0) { ms_error("MSH264Enc: VPU Init error\n"); return ; } d->mem_desc.size = STREAM_BUF_SIZE; if(IOGetPhyMem(&d->mem_desc)!=0) { ms_error("MSH264Enc: Unable to obtain physical memory\n"); return ; } /* mmap that physical buffer */ d->enc->virt_bsbuf_addr = IOGetVirtMem(&d->mem_desc); if (d->enc->virt_bsbuf_addr <= 0) { IOFreePhyMem(&d->mem_desc); ms_error("MSH264Enc: Unable to map physical memory\n"); return ; } d->enc->phy_bsbuf_addr = d->mem_desc.phy_addr; }
static void decoder_renderer_setup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) { if (videoFormat != VIDEO_FORMAT_H264) { fprintf(stderr, "Video format not supported\n"); exit(1); } struct mxcfb_gbl_alpha alpha; dbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; dbuf.memory = V4L2_MEMORY_MMAP; int fd_fb = open("/dev/fb0", O_RDWR, 0); if (fd_fb < 0){ fprintf(stderr, "Can't access framebuffer\n"); exit(EXIT_FAILURE); } alpha.alpha = 0; alpha.enable = 1; if (ioctl(fd_fb, MXCFB_SET_GBL_ALPHA, &alpha) < 0){ fprintf(stderr, "Can't set framebuffer output\n"); exit(EXIT_FAILURE); } close(fd_fb); mem_desc.size = STREAM_BUF_SIZE; if (IOGetPhyMem(&mem_desc)){ fprintf(stderr, "Can't get physical memory address\n"); exit(EXIT_FAILURE); } if (IOGetVirtMem(&mem_desc) <= 0) { fprintf(stderr, "Can't get virtual memory address\n"); exit(EXIT_FAILURE); } ps_mem_desc.size = PS_SAVE_SIZE; if (IOGetPhyMem(&ps_mem_desc)) { fprintf(stderr, "Can't get physical memory address\n"); exit(EXIT_FAILURE); } DecOpenParam oparam = {0}; oparam.bitstreamFormat = STD_AVC; oparam.bitstreamBuffer = mem_desc.phy_addr; oparam.bitstreamBufferSize = STREAM_BUF_SIZE; oparam.pBitStream = (Uint8 *) mem_desc.virt_uaddr; oparam.reorderEnable = 1; oparam.mp4DeblkEnable = 0; oparam.chromaInterleave = 0; oparam.avcExtension = oparam.mp4Class = 0; oparam.mjpg_thumbNailDecEnable = 0; oparam.mapType = LINEAR_FRAME_MAP; oparam.tiled2LinearEnable = 0; oparam.bitstreamMode = 1; oparam.psSaveBuffer = ps_mem_desc.phy_addr; oparam.psSaveBufferSize = PS_SAVE_SIZE; if (vpu_DecOpen(&handle, &oparam) != RETCODE_SUCCESS) { fprintf(stderr, "Can't open video decoder\n"); exit(EXIT_FAILURE); } decparam.dispReorderBuf = 0; decparam.skipframeMode = 0; decparam.skipframeNum = 0; decparam.iframeSearchEnable = 0; regfbcount = MIN_FRAME_BUFFER_COUNT + 2; int picWidth = ((width + 15) & ~15); int picHeight = ((height + 15) & ~15); stride = picWidth; int phy_slicebuf_size = WORST_SLICE_SIZE * 1024; slice_mem_desc.size = phy_slicebuf_size; if (IOGetPhyMem(&slice_mem_desc)){ fprintf(stderr, "Can't get slice physical address\n"); exit(EXIT_FAILURE); } fb = calloc(regfbcount, sizeof(FrameBuffer)); if (fb == NULL) { fprintf(stderr, "Can't allocate framebuffers\n"); exit(EXIT_FAILURE); } char v4l_device[16], node[8]; sprintf(node, "%d", 17); strcpy(v4l_device, "/dev/video"); strcat(v4l_device, node); fd = open(v4l_device, O_RDWR, 0); if (fd < 0){ fprintf(stderr, "Can't access video output\n"); exit(EXIT_FAILURE); } struct v4l2_format fmt = {0}; fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; fmt.fmt.pix.width = picWidth; fmt.fmt.pix.height = picHeight; fmt.fmt.pix.bytesperline = picWidth; fmt.fmt.pix.field = V4L2_FIELD_ANY; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) { fprintf(stderr, "Can't set source video format\n"); exit(EXIT_FAILURE); } if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) { fprintf(stderr, "Can't set output video format\n"); exit(EXIT_FAILURE); } struct v4l2_requestbuffers reqbuf = {0}; reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; reqbuf.memory = V4L2_MEMORY_MMAP; reqbuf.count = regfbcount; struct v4l_buf* buffers[regfbcount]; if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) { fprintf(stderr, "Can't get video buffers\n"); exit(EXIT_FAILURE); } if (reqbuf.count < regfbcount) { fprintf(stderr, "Not enough video buffers\n"); exit(EXIT_FAILURE); } for (int i = 0; i < regfbcount; i++) { struct v4l2_buffer buffer = {0}; struct v4l_buf *buf; buf = calloc(1, sizeof(struct v4l_buf)); if (buf == NULL) { fprintf(stderr, "Not enough memory\n"); exit(EXIT_FAILURE); } buffers[i] = buf; buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; buffer.memory = V4L2_MEMORY_MMAP; buffer.index = i; if (ioctl(fd, VIDIOC_QUERYBUF, &buffer) < 0) { fprintf(stderr, "Can't get video buffer\n"); exit(EXIT_FAILURE); } buf->start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buffer.m.offset); /* * Workaround for new V4L interface change, this change * will be removed after V4L driver is updated for this. * Need to call QUERYBUF ioctl again after mmap. */ if (ioctl(fd, VIDIOC_QUERYBUF, &buffer) < 0) { fprintf(stderr, "Can't set source video format\n"); exit(EXIT_FAILURE); } buf->offset = buffer.m.offset; buf->length = buffer.length; if (buf->start == MAP_FAILED) { fprintf(stderr, "Failed to map video buffer\n"); exit(EXIT_FAILURE); } } int img_size = stride * picHeight; vpu_mem_desc *mvcol_md = NULL; int mjpg_fmt = MODE420; int divX = (mjpg_fmt == MODE420 || mjpg_fmt == MODE422) ? 2 : 1; int divY = (mjpg_fmt == MODE420 || mjpg_fmt == MODE224) ? 2 : 1; mvcol_md = calloc(regfbcount, sizeof(vpu_mem_desc)); for (int i = 0; i < regfbcount; i++) { fb[i].myIndex = i; fb[i].bufY = buffers[i]->offset; fb[i].bufCb = fb[i].bufY + img_size; fb[i].bufCr = fb[i].bufCb + (img_size / divX / divY); /* allocate MvCol buffer here */ memset(&mvcol_md[i], 0, sizeof(vpu_mem_desc)); mvcol_md[i].size = img_size / divX / divY; if (IOGetPhyMem(&mvcol_md[i])) { fprintf(stderr, "Can't get physical address of colomn buffer\n"); exit(EXIT_FAILURE); } fb[i].bufMvCol = mvcol_md[i].phy_addr; } bufinfo.avcSliceBufInfo.bufferBase = slice_mem_desc.phy_addr; bufinfo.avcSliceBufInfo.bufferSize = phy_slicebuf_size; bufinfo.maxDecFrmInfo.maxMbX = stride / 16; bufinfo.maxDecFrmInfo.maxMbY = picHeight / 16; bufinfo.maxDecFrmInfo.maxMbNum = stride * picHeight / 256; int delay = -1; vpu_DecGiveCommand(handle, DEC_SET_FRAME_DELAY, &delay); }
/*! * @brief IO system initialization. * When user wants to start up the codec system, * this function call is needed, to open the codec device, * map the register into user space, * get the working buffer/code buffer/parameter buffer, * download the firmware, and then set up the interrupt signal path. * * @param callback vpu interrupt callback. * * @return * @li 0 System initialization success. * @li -1 System initialization failure. */ int IOSystemInit(void *callback) { int ret; /* Exit directly if already initialized */ if (vpu_fd > 0) { vpu_active_num++; return 0; } ret = get_system_rev(); if (ret == -1) { err_msg("Error: Unable to obtain system rev information\n"); return -1; } vpu_fd = open("/dev/mxc_vpu", O_RDWR); if (vpu_fd < 0) { err_msg("Can't open /dev/mxc_vpu: %s\n", strerror(errno)); return -1; } vpu_shared_mem = vpu_semaphore_open(); if (vpu_shared_mem == NULL) { err_msg("Error: Unable to open vpu shared memory file\n"); close(vpu_fd); vpu_fd = -1; return -1; } if (!semaphore_wait(vpu_semap, API_MUTEX)) { err_msg("Error: Unable to get mutex\n"); close (vpu_fd); vpu_fd = -1; return -1; } vpu_reg_base = (unsigned long)mmap(NULL, BIT_REG_MARGIN, PROT_READ | PROT_WRITE, MAP_SHARED, vpu_fd, 0); if ((void *)vpu_reg_base == MAP_FAILED) { err_msg("Can't map register\n"); close(vpu_fd); vpu_fd = -1; semaphore_post(vpu_semap, API_MUTEX); return -1; } vpu_active_num++; IOClkGateSet(true); #ifdef BUILD_FOR_ANDROID unsigned long va_addr; /* Special handle the bit work buffer, which reserved in vpu driver probe */ bit_work_addr.size = TEMP_BUF_SIZE + PARA_BUF_SIZE + CODE_BUF_SIZE + PARA_BUF2_SIZE; if (_IOGetPhyMem(VPU_IOC_GET_WORK_ADDR, &bit_work_addr) < 0) { err_msg("Get bitwork address failed!\n"); goto err; } va_addr = (unsigned long)mmap(NULL, bit_work_addr.size, PROT_READ | PROT_WRITE, MAP_SHARED, vpu_fd, bit_work_addr.phy_addr); if ((void *)va_addr == MAP_FAILED) { bit_work_addr.virt_uaddr = 0; goto err; } bit_work_addr.virt_uaddr = va_addr; #else bit_work_addr.size = TEMP_BUF_SIZE + PARA_BUF_SIZE + CODE_BUF_SIZE + PARA_BUF2_SIZE; if (_IOGetPhyMem(VPU_IOC_GET_WORK_ADDR, &bit_work_addr) < 0) { err_msg("Get bitwork address failed!\n"); goto err; } if (IOGetVirtMem(&bit_work_addr) == -1) goto err; #endif UnlockVpu(vpu_semap); return 0; err: err_msg("Error in IOSystemInit()"); UnlockVpu(vpu_semap); IOSystemShutdown(); return -1; }
/*! * @brief IO system initialization. * When user wants to start up the codec system, * this function call is needed, to open the codec device, * map the register into user space, * get the working buffer/code buffer/parameter buffer, * download the firmware, and then set up the interrupt signal path. * * @param callback vpu interrupt callback. * * @return * @li 0 System initialization success. * @li -1 System initialization failure. */ int IOSystemInit(void *callback) { int ret; /* Exit directly if already initialized */ if (vpu_fd > 0) { vpu_active_num++; return 0; } ret = get_system_rev(); if (ret == -1) { err_msg("Error: Unable to obtain system rev information\n"); return -1; } vpu_fd = open("/dev/mxc_vpu", O_RDWR); if (vpu_fd < 0) { err_msg("Can't open /dev/mxc_vpu\n"); return -1; } vpu_semap = vpu_semaphore_open(); if (vpu_semap == NULL) { err_msg("Error: Unable to open vpu shared memory file\n"); close(vpu_fd); vpu_fd = -1; return -1; } if (!semaphore_wait(vpu_semap, API_MUTEX)) { err_msg("Error: Unable to get mutex\n"); close (vpu_fd); vpu_fd = -1; return -1; } vpu_reg_base = (unsigned long)mmap(NULL, BIT_REG_MARGIN, PROT_READ | PROT_WRITE, MAP_SHARED, vpu_fd, 0); if ((void *)vpu_reg_base == MAP_FAILED) { err_msg("Can't map register\n"); close(vpu_fd); vpu_fd = -1; semaphore_post(vpu_semap, API_MUTEX); return -1; } vpu_active_num++; IOClkGateSet(true); bit_work_addr.size = TEMP_BUF_SIZE + PARA_BUF_SIZE + CODE_BUF_SIZE + PARA_BUF2_SIZE; if (_IOGetPhyMem(VPU_IOC_GET_WORK_ADDR, &bit_work_addr) < 0) { err_msg("Get bitwork address failed!\n"); goto err; } if (IOGetVirtMem(&bit_work_addr) <= 0) goto err; UnlockVpu(vpu_semap); return 0; err: err_msg("Error in IOSystemInit()"); UnlockVpu(vpu_semap); IOSystemShutdown(); return -1; }
static void decoder_renderer_setup(int width, int height, int redrawRate, void* context, int drFlags) { struct mxcfb_gbl_alpha alpha; dbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; dbuf.memory = V4L2_MEMORY_MMAP; int fd_fb = open("/dev/fb0", O_RDWR, 0); if (fd_fb < 0){ fprintf(stderr, "Can't access framebuffer\n"); exit(EXIT_FAILURE); } alpha.alpha = 0; alpha.enable = 1; if (ioctl(fd_fb, MXCFB_SET_GBL_ALPHA, &alpha) < 0){ fprintf(stderr, "Can't set framebuffer output\n"); exit(EXIT_FAILURE); } close(fd_fb); mem_desc.size = STREAM_BUF_SIZE; if (IOGetPhyMem(&mem_desc)){ fprintf(stderr, "Can't get physical memory address\n"); exit(EXIT_FAILURE); } if (IOGetVirtMem(&mem_desc) <= 0) { fprintf(stderr, "Can't get virtual memory address\n"); exit(EXIT_FAILURE); } ps_mem_desc.size = PS_SAVE_SIZE; if (IOGetPhyMem(&ps_mem_desc)) { fprintf(stderr, "Can't get physical memory address\n"); exit(EXIT_FAILURE); } DecOpenParam oparam = {0}; oparam.bitstreamFormat = STD_AVC; oparam.bitstreamBuffer = mem_desc.phy_addr; oparam.bitstreamBufferSize = STREAM_BUF_SIZE; oparam.pBitStream = (Uint8 *) mem_desc.virt_uaddr; oparam.reorderEnable = 1; oparam.mp4DeblkEnable = 0; oparam.chromaInterleave = 0; oparam.avcExtension = oparam.mp4Class = 0; oparam.mjpg_thumbNailDecEnable = 0; oparam.mapType = LINEAR_FRAME_MAP; oparam.tiled2LinearEnable = 0; oparam.bitstreamMode = 1; oparam.psSaveBuffer = ps_mem_desc.phy_addr; oparam.psSaveBufferSize = PS_SAVE_SIZE; if (vpu_DecOpen(&handle, &oparam) != RETCODE_SUCCESS) { fprintf(stderr, "Can't open video decoder\n"); exit(EXIT_FAILURE); } decparam.dispReorderBuf = 0; decparam.skipframeMode = 0; decparam.skipframeNum = 0; decparam.iframeSearchEnable = 0; }
int main(void){ int ret = 0, i; vpu_versioninfo ver; // vpu version information vpu_mem_desc bit_stream_buf; // input bit stream allocated memory vpu_mem_desc source_buf; // source buffer allocated memory FrameBuffer source_frame; // source framebuffer // VPU specific members defined in vpu_lib.h EncHandle *handle = malloc(sizeof(EncHandle)); EncOpenParam *encOP = malloc(sizeof(EncOpenParam)); EncInitialInfo *initialInfo = malloc(sizeof(EncInitialInfo)); EncOutputInfo *outputInfo = malloc(sizeof(EncOutputInfo)); EncParam *encParam = malloc(sizeof(EncParam)); // Set allocated memory to zero memset (initialInfo, 0, sizeof (EncInitialInfo)); memset (encParam, 0, sizeof (EncParam)); memset (encOP, 0, sizeof (EncOpenParam)); memset (outputInfo, 0, sizeof (EncOutputInfo)); memset (&bit_stream_buf, 0, sizeof (vpu_mem_desc)); // Init VPU if(vpu_Init (NULL) < 0) { printf(">> failed to call vpu_Init()\n"); ret = -1; goto free; } vpu_GetVersionInfo(&ver); printf("VPU Version: firmware %d.%d.%d; libvpu: %d.%d.%d \n", ver.fw_major, ver.fw_minor, ver.fw_release, ver.lib_major, ver.lib_minor, ver.lib_release); // Allocate input buffer bit_stream_buf.size = BUFF_FILL_SIZE; IOGetPhyMem (&bit_stream_buf); if(bit_stream_buf.phy_addr == 0) { printf(">> error allocating encoder bitstream buffer\n"); ret = -1; goto free; } IOGetVirtMem (&bit_stream_buf); // Set up encoder operation parameters encOP->bitstreamBuffer = bit_stream_buf.phy_addr; encOP->bitstreamBufferSize = BUFF_FILL_SIZE; encOP->bitstreamFormat = STD_AVC; encOP->gopSize = DEFAULT_GOP_SIZE; encOP->rcIntraQp = VPU_DEFAULT_H264_QP; encOP->userQpMaxEnable = 1; encOP->userQpMax = H264_QP_MAX; encOP->userQpMinEnable = 1; encOP->userQpMin = H264_QP_MIN; encOP->frameRateInfo = DEFAULT_FRAME_RATE; encOP->picWidth = DEFAULT_WIDTH; encOP->picHeight = DEFAULT_HEIGHT; encOP->ringBufferEnable = 0; // Open encoder vpu_EncOpen (handle, encOP); // Configure IRAM memory SearchRamParam search_pa = { 0 }; iram_t iram; int ram_size; memset (&iram, 0, sizeof (iram_t)); ram_size = ((DEFAULT_WIDTH + 15) & ~15) * 36 + 2048; IOGetIramBase (&iram); if ((iram.end - iram.start) < ram_size) ram_size = iram.end - iram.start; search_pa.searchRamAddr = iram.start; search_pa.SearchRamSize = ram_size; vpu_EncGiveCommand (*handle, ENC_SET_SEARCHRAM_PARAM, &search_pa); vpu_EncGetInitialInfo (*handle, initialInfo); // Disable rotation/mirroring vpu_EncGiveCommand (*handle, DISABLE_ROTATION, 0); vpu_EncGiveCommand (*handle, DISABLE_MIRRORING, 0); // Allocate memory for source frame buffer source_buf.size = DEFAULT_WIDTH * DEFAULT_HEIGHT * 3/2; IOGetPhyMem (&source_buf); if(source_buf.phy_addr == 0) { printf(">> error allocating source frame buffer\n"); ret = -1; goto close; } IOGetVirtMem(&source_buf); source_frame.strideY = DEFAULT_WIDTH; source_frame.strideC = DEFAULT_WIDTH >> 1; source_frame.bufY = source_buf.phy_addr; source_frame.bufCb = source_frame.bufY + DEFAULT_WIDTH * DEFAULT_HEIGHT; source_frame.bufCr = source_frame.bufCb + (DEFAULT_WIDTH * DEFAULT_HEIGHT >> 2); printf("source frame buffer %i phys(%p) virt(%p)\n", 0, source_buf.phy_addr, source_buf.virt_uaddr); // Get number of destination frame buffers and allocate int num = initialInfo->minFrameBufferCount; printf("number of needed frame buffers: %d\n", num); vpu_mem_desc *framedesc = malloc(sizeof(vpu_mem_desc) * num); FrameBuffer *frame = malloc(sizeof(FrameBuffer) * num); memset (framedesc, 0, (sizeof (vpu_mem_desc) * num)); memset (frame, 0, (sizeof (FrameBuffer) * num)); // Allocate each destination frame buffer for (i = 0; i < num; i++) { framedesc[i].size = DEFAULT_WIDTH * DEFAULT_HEIGHT * 3/2; IOGetPhyMem (&(framedesc[i])); if (framedesc[i].phy_addr == 0) { printf(">> error allocating destination frame buffers\n"); ret = -1; goto frame; } IOGetVirtMem (&(framedesc[i])); frame[i].strideY = DEFAULT_WIDTH; frame[i].strideC = DEFAULT_WIDTH >> 1; frame[i].bufY = framedesc[i].phy_addr; frame[i].bufCb = frame[i].bufY + (DEFAULT_WIDTH * DEFAULT_HEIGHT); frame[i].bufCr = frame[i].bufCb + ((DEFAULT_WIDTH * DEFAULT_HEIGHT) >> 2); printf("destination frame buffer %i phys(%p) virt(%p)\n", i, framedesc[i].phy_addr, framedesc[i].virt_uaddr); } // Register allocated frame buffers vpu_EncRegisterFrameBuffer (*handle, frame, num, DEFAULT_WIDTH, DEFAULT_WIDTH, 0, 0, NULL); encParam->forceIPicture = 0; encParam->skipPicture = 0; encParam->enableAutoSkip = 0; encParam->quantParam = VPU_DEFAULT_H264_QP; // Get encoding Headers EncHeaderParam enchdr_param = { 0 }; uint8_t *ptr; uint8_t *header[NUM_INPUT_BUF]; uint32_t headersize[NUM_INPUT_BUF]; // size for each header element enchdr_param.headerType = SPS_RBSP; vpu_EncGiveCommand (*handle, ENC_PUT_AVC_HEADER, &enchdr_param); headersize[SPS_HDR] = enchdr_param.size; header[SPS_HDR] = malloc (enchdr_param.size); if (header[SPS_HDR] == NULL) { printf (">> error in allocating memory for SPS_RBSP Header" ); ret = -1; goto frame; } ptr = (uint8_t*) (bit_stream_buf.virt_uaddr + enchdr_param.buf - bit_stream_buf.phy_addr); memcpy (header[SPS_HDR], ptr, enchdr_param.size); printf("header[SPS_HDR]: %d bytes\n", headersize[SPS_HDR]); enchdr_param.headerType = PPS_RBSP; vpu_EncGiveCommand (*handle, ENC_PUT_AVC_HEADER, &enchdr_param); headersize[PPS_HDR] = enchdr_param.size; header[PPS_HDR] = malloc (enchdr_param.size); if (header[PPS_HDR] == NULL) { printf (">> error in allocating memory for PPS_HDR Header" ); ret = -1; goto frame; } ptr = (uint8_t*) (bit_stream_buf.virt_uaddr + enchdr_param.buf - bit_stream_buf.phy_addr); memcpy (header[PPS_HDR], ptr, enchdr_param.size); printf("header[PPS_HDR]: %d bytes\n", headersize[PPS_HDR]); // Open output file and write headers FILE *out = fopen ("BigBuckBunny_640x360_small.h264", "w"); //stdout fwrite(header[SPS_HDR], 1, headersize[SPS_HDR], out); fwrite(header[PPS_HDR], 1, headersize[PPS_HDR], out); // Copy and Encode FILE *in = fopen ("BigBuckBunny_640x360_small.yuv", "r"); while(fread((void*) source_buf.virt_uaddr, 1, DEFAULT_WIDTH * DEFAULT_HEIGHT * 3/2, in)) { encParam->sourceFrame = &source_frame; // Encode a single frame vpu_EncStartOneFrame (*handle, encParam); while(vpu_IsBusy()) { vpu_WaitForInt (100); } vpu_EncGetOutputInfo (*handle, outputInfo); // Write bitstream to file fwrite((void*) bit_stream_buf.virt_uaddr, 1, outputInfo->bitstreamSize, out); } printf("\n"); fclose(in); fclose(out); frame: for (i = 0; i < num; i++) { IOFreeVirtMem(&(framedesc[i])); IOFreePhyMem(&(framedesc[i])); } free(frame); free(framedesc); close: // Close encoder vpu_EncClose (*handle); // Free alocated input buffer IOFreeVirtMem (&bit_stream_buf); IOFreePhyMem (&bit_stream_buf); free: free(encOP); free(initialInfo); free(outputInfo); free(encParam); free(handle); return ret; }
mjpeg_decoder_t::mjpeg_decoder_t(vpu_t &vpu) : w_(0) , h_(0) , ystride_(0) , uvstride_(0) , imgSize_(0) , handle_(0) , phy_bsbuf_addr(0) , phy_ps_buf(0) , phy_slice_buf(0) , phy_slicebuf_size(0) , virt_bsbuf_addr(0) , bsbuf_end(0) , numRead(0) , fbcount(0) , fb(0) , pfbpool(0) , mvcol_memdesc(0) , startedDecode_(false) , app_fbs(0) , decoder_fbs(0) , state_(ERR) { vpu_mem_desc mem_desc = {0}; mem_desc.size = STREAM_BUF_SIZE; int ret = IOGetPhyMem(&mem_desc); if (ret) { fprintf(stderr,"Unable to obtain physical mem\n"); return; } if (IOGetVirtMem(&mem_desc) <= 0) { fprintf(stderr,"Unable to obtain virtual mem\n"); IOFreePhyMem(&mem_desc); return; } vpu_mem_desc slice_mem_desc = {0}; phy_bsbuf_addr = mem_desc.phy_addr; virt_bsbuf_addr = mem_desc.virt_uaddr; bsbuf_end = virt_bsbuf_addr + mem_desc.size ; DecOpenParam oparam ; memset(&oparam,0,sizeof(oparam)); oparam.bitstreamFormat = STD_MJPG ; oparam.bitstreamBuffer = phy_bsbuf_addr; oparam.bitstreamBufferSize = STREAM_BUF_SIZE; oparam.reorderEnable = 1 ; oparam.mp4DeblkEnable = 0 ; oparam.dynamicAllocEnable = 1 ; oparam.psSaveBuffer = 0 ; oparam.psSaveBufferSize = 0 ; ret = vpu_DecOpen(&handle_, &oparam); if (ret != RETCODE_SUCCESS) { fprintf(stderr,"vpu_DecOpen failed: %d\n", ret); return ; } debugPrint("vpu_DecOpen success\n" ); ret = vpu_DecGiveCommand(handle_,DEC_SET_REPORT_USERDATA, &userData); debugPrint("vpu_DecGiveCommand: %d(DEC_SET_REPORT_USERDATA)/%d\n", DEC_SET_REPORT_USERDATA,ret); if (ret != RETCODE_SUCCESS) { fprintf(stderr, "Failed to set user data report, ret %d\n", ret ); return ; } else printf( "disabled userdata\n" ); /* Parse bitstream and get width/height/framerate etc */ ret = vpu_DecSetEscSeqInit(handle_, 1); if (ret != RETCODE_SUCCESS) { fprintf(stderr, "Failed to set Esc Seq, ret %d\n", ret ); return ; } else debugPrint("vpu_DecSetEscSeqInit(1): %d\n", ret); state_ = INIT ; }
bool mjpeg_decoder_t::fill_buf( void const *data, unsigned length, void *opaque ) { if( length < STREAM_BUF_SIZE ){ memcpy((void *)virt_bsbuf_addr,data,length); numRead = length ; vpu_DecUpdateBitstreamBuffer(handle_,length); debugPrint( "copied %u bytes, state == %d\n", length, state_ ); if( INIT == state_ ) { RetCode ret; DecInitialInfo initinfo = {0}; ret = vpu_DecGetInitialInfo(handle_, &initinfo); debugPrint("vpu_DecGetInitialInfo: %d\n", ret); if (ret != RETCODE_SUCCESS) { fprintf(stderr, "vpu_DecGetInitialInfo failed %d\n", ret); return false ; } else { vpu_DecSetEscSeqInit(handle_, 0); debugPrint("vpu_DecSetEscSeqInit(0): %d\n", ret); if (initinfo.streamInfoObtained) { printf( "have stream info\n" ); printf("Decoder: width = %d, height = %d, fps = %lu, minfbcount = %u\n", initinfo.picWidth, initinfo.picHeight, initinfo.frameRateInfo, initinfo.minFrameBufferCount); assert(0 == fbcount); assert(0 == fb); assert(0 == pfbpool); fbcount = initinfo.minFrameBufferCount + 2 ; fb = (FrameBuffer *)calloc(fbcount, sizeof(fb[0])); if (fb == NULL) { fprintf(stderr,"Failed to allocate fb\n"); return false ; } pfbpool = (frame_buf *)calloc(fbcount, sizeof(pfbpool[0])); if (pfbpool == NULL) { fprintf(stderr, "Failed to allocate pfbpool\n"); return false ; } printf("fb == %p, pfbpool == %p, malloc == %p\n", fb, pfbpool, malloc(0x10000) ); w_ = initinfo.picWidth ; h_ = initinfo.picHeight ; ystride_ = (initinfo.picWidth + 15)&~15; uvstride_ = ((initinfo.picWidth/2)+15)&~15; printf( "strides: %u/%u\n", ystride_, uvstride_ ); unsigned paddedHeight = (h_+15)&~15 ; // Why??? unsigned ySize = ystride_ * paddedHeight ; unsigned uvSize = uvstride_ * (paddedHeight/2); imgSize_ = paddedHeight*(ystride_+uvstride_); printf( "imgSize == %u, ySize %u, uvSize %u\n", imgSize_, ySize, uvSize ); imgSize_ += (ystride_*paddedHeight) / 4 ; // Why? printf( "padded == %u\n", imgSize_ ); for (unsigned i = 0; i < fbcount ; i++) { decoder_fbs |= (1 <<i); struct frame_buf *f = pfbpool + i ; debugPrint( "pfbpool[%u] == %p\n", i, f); f->desc.size = imgSize_ ; int err = IOGetPhyMem(&f->desc); if (err) { printf("Frame buffer allocation failure: %d\n", err); return false ; } debugPrint( "allocated frame buffer %u == 0x%x\n", i, f->desc.phy_addr ); f->addrY = f->desc.phy_addr; f->addrCb = f->addrY + ySize ; f->addrCr = f->addrCb + uvSize ; f->mvColBuf = f->addrCr + uvSize ; f->desc.virt_uaddr = IOGetVirtMem(&(f->desc)); debugPrint( "virt == %p\n", f->desc.virt_uaddr ); if (f->desc.virt_uaddr <= 0) { fprintf(stderr, "Error mapping frame buffer memory\n" ); return false ; } fb[i].bufY = f->addrY; fb[i].bufCb = f->addrCb; fb[i].bufCr = f->addrCr; fb[i].bufMvCol = f->mvColBuf ; } debugPrint( "allocated frame buffers\n" ); for( unsigned i = 0 ; i < fbcount ; i++ ) { debugPrint("fb[%d].bufY = 0x%lx\n", i, fb[i].bufY ); debugPrint("fb[%d].bufCb = 0x%lx\n", i, fb[i].bufCb ); debugPrint("fb[%d].bufCr = 0x%lx\n", i, fb[i].bufCr ); debugPrint("fb[%d].bufMvCol = 0x%lx\n", i, fb[i].bufMvCol ); } DecBufInfo bufinfo = {0}; ret = vpu_DecRegisterFrameBuffer(handle_, fb, fbcount, ystride_, &bufinfo); debugPrint("vpu_DecRegisterFrameBuffer: %d, %u fbs, stride %u\n", ret, fbcount,ystride_); if (ret != RETCODE_SUCCESS) { fprintf(stderr,"Register frame buffer failed\n"); return false ; } debugPrint( "registered frame buffers\n"); int rot_angle = 0 ; ret = vpu_DecGiveCommand(handle_, SET_ROTATION_ANGLE, &rot_angle); debugPrint("vpu_DecGiveCommand: %d(SET_ROTATION_ANGLE)/%d, angle %d\n", SET_ROTATION_ANGLE,ret, rot_angle); if (ret != RETCODE_SUCCESS) fprintf(stderr,"rot_angle %d\n", ret); int mirror = 0 ; ret = vpu_DecGiveCommand(handle_, SET_MIRROR_DIRECTION,&mirror); debugPrint("vpu_DecGiveCommand: %d(SET_MIRROR_DIRECTION)/%d, mirror %d\n", SET_MIRROR_DIRECTION,ret, mirror); if (ret != RETCODE_SUCCESS) fprintf(stderr,"mirror %d\n", ret); int rot_stride = ystride_ ; ret = vpu_DecGiveCommand(handle_, SET_ROTATOR_STRIDE, &rot_stride); debugPrint("vpu_DecGiveCommand: %d(SET_ROTATOR_STRIDE)/%d, stride %d\n", SET_ROTATOR_STRIDE,ret, rot_stride); if (ret != RETCODE_SUCCESS) fprintf(stderr,"rotstride %d\n", ret); state_ = DECODING ; debugPrint("before decode: image size %u, ySize %u, uvSize %u\n", yuvSize(), this->ySize(), this->uvSize() ); startDecode(); } } } return true ; } else return false ; }