int vpu_encode_one_frame(EncodingInstance instance, const unsigned char* data) { EncHandle handle = instance->handle; int src_fbid = instance->src_fbid; EncOutputInfo outinfo = {}; int ret; u32 vbuf; u32 yuv_addr; yuv_addr = instance->pfbpool[src_fbid]->addrY + instance->pfbpool[src_fbid]->desc.virt_uaddr - instance->pfbpool[src_fbid]->desc.phy_addr; MEMCPY((unsigned char*)yuv_addr, data, instance->input_size); pthread_mutex_lock(&vpu_mutex); ret = vpu_EncStartOneFrame(handle, &(instance->enc_param)); if(vpu_IsBusy()) { usleep(0); vpu_WaitForInt(200); } ret = vpu_EncGetOutputInfo(handle, &outinfo); pthread_mutex_unlock(&vpu_mutex); vbuf = (instance->virt_bsbuf_addr + outinfo.bitstreamBuffer - instance->phy_bsbuf_addr); ret = vpu_write(instance->fd, (void*)vbuf, outinfo.bitstreamSize); return 0; }
static int decoder_renderer_submit_decode_unit(PDECODE_UNIT decodeUnit) { Uint32 space; PhysicalAddress pa_read_ptr, pa_write_ptr; if (vpu_DecGetBitstreamBuffer(handle, &pa_read_ptr, &pa_write_ptr, &space) != RETCODE_SUCCESS) { fprintf(stderr, "Can't get video decoder buffer\n"); exit(EXIT_FAILURE); } Uint32 target_addr = mem_desc.virt_uaddr + (pa_write_ptr - mem_desc.phy_addr); if (space < decodeUnit->fullLength) { fprintf(stderr, "Not enough space in buffer %d/%d\n", decodeUnit->fullLength, space); } PLENTRY entry = decodeUnit->bufferList; int written = 0; while (entry != NULL) { if ( (target_addr + entry->length) > mem_desc.virt_uaddr + STREAM_BUF_SIZE) { int room = mem_desc.virt_uaddr + STREAM_BUF_SIZE - target_addr; memcpy((void *)target_addr, entry->data, room); memcpy((void *)mem_desc.virt_uaddr, entry->data + room, entry->length - room); target_addr = mem_desc.virt_uaddr + entry->length - room; } else { memcpy((void *)target_addr, entry->data, entry->length); target_addr += entry->length; } entry = entry->next; } vpu_DecUpdateBitstreamBuffer(handle, decodeUnit->fullLength); if (!initialized) { initialized = true; DecInitialInfo info = {0}; vpu_DecSetEscSeqInit(handle, 1); vpu_DecGetInitialInfo(handle, &info); vpu_DecSetEscSeqInit(handle, 0); if (vpu_DecRegisterFrameBuffer(handle, fb, regfbcount, stride, &bufinfo) != RETCODE_SUCCESS) { fprintf(stderr, "Can't register decoder to framebuffer\n"); exit(EXIT_FAILURE); } } if (!decoding) { if (vpu_DecStartOneFrame(handle, &decparam) != RETCODE_SUCCESS) { fprintf(stderr, "Can't start decoding\n"); exit(EXIT_FAILURE); } decoding = true; } int loop_id = 0; while (vpu_IsBusy()) { if (loop_id > 50) { vpu_SWReset(handle, 0); fprintf(stderr, "VPU is too long busy\n"); exit(EXIT_FAILURE); } vpu_WaitForInt(100); loop_id++; } if (decoding) { decoding = 0; DecOutputInfo outinfo = {0}; if (vpu_DecGetOutputInfo(handle, &outinfo) != RETCODE_SUCCESS) { fprintf(stderr, "Can't get output info\n"); exit(EXIT_FAILURE); } if (outinfo.decodingSuccess & 0x10) { return DR_OK; } else if (outinfo.notSufficientPsBuffer) { fprintf(stderr, "Not enough space in stream buffer\n"); exit(EXIT_FAILURE); } else if (outinfo.notSufficientSliceBuffer) { fprintf(stderr, "Not enough space in slice buffer\n"); exit(EXIT_FAILURE); } if (outinfo.indexFrameDisplay >= 0) { struct timeval tv; gettimeofday(&tv, 0); dbuf.timestamp.tv_sec = tv.tv_sec; dbuf.timestamp.tv_usec = tv.tv_usec; dbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; dbuf.memory = V4L2_MEMORY_MMAP; dbuf.index = outinfo.indexFrameDisplay; if (ioctl(fd, VIDIOC_QUERYBUF, &dbuf) < 0) { fprintf(stderr, "Can't get output buffer\n"); exit(EXIT_FAILURE); } dbuf.index = outinfo.indexFrameDisplay; dbuf.field = V4L2_FIELD_NONE; if (ioctl(fd, VIDIOC_QBUF, &dbuf) < 0) { fprintf(stderr, "Can't get output buffer\n"); exit(EXIT_FAILURE); } if (!displaying) { int type = V4L2_BUF_TYPE_VIDEO_OUTPUT; if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) { fprintf(stderr, "Failed to output video\n"); exit(EXIT_FAILURE); } displaying = true; } queued_count++; if (queued_count > THRESHOLD) { dbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; dbuf.memory = V4L2_MEMORY_MMAP; if (ioctl(fd, VIDIOC_DQBUF, &dbuf) < 0) { fprintf(stderr, "Failed to dequeue buffer\n"); exit(EXIT_FAILURE); } else queued_count--; } if (disp_clr_index >= 0) vpu_DecClrDispFlag(handle, disp_clr_index); disp_clr_index = outinfo.indexFrameDisplay; } else if (outinfo.indexFrameDisplay == -1) { fprintf(stderr, "Failed to decode frame\n"); exit(EXIT_FAILURE); } } return DR_OK; }
int VpuDec::decode(VencBlk * src, ImgBlk * dest)//blocking { int ret = 1; int loop_id = 0; int imageSize; DecOutputInfo outinfo = {0}; DecParam decparam = {0}; if(dec_fb == NULL || dec_pfbpool == NULL){ if (write_Src_Ringbuf(src) == -1 || get_DecInitialInfo(src) == -1 || calloc_FrameBuff(src) == -1){ printf("Config VPU error:VencBlk codec 0x%x, %dx%d, frameSize %d, frameType %d\n",src->codec,src->width,src->height,src->frameSize,src->frameType); return -1; } decparam.dispReorderBuf = 0; decparam.skipframeMode = 0; decparam.skipframeNum = 0; decparam.iframeSearchEnable = 0; if(dec_format == STD_MJPG) vpu_DecGiveCommand(handle, SET_ROTATOR_STRIDE, &src->width); }else{ ret = write_Src_Ringbuf(src); if (ret < 0) { printf("read data failed\n"); return -1; } } if(dec_format == STD_MJPG){ decparam.chunkSize = src->frameSize; decparam.phyJpgChunkBase = Dec_bufZone.pStartAddr; decparam.virtJpgChunkBase = (unsigned char*)Dec_bufZone.vStartaddr; vpu_DecGiveCommand(handle, SET_ROTATOR_OUTPUT,(void *)&dec_fb[0]); } imageSize = src->width * src->height * 3 / 2; ret = vpu_DecStartOneFrame(handle, &decparam); if (ret != RETCODE_SUCCESS) { printf("DecStartOneFrame failed, ret=%d,LINE:%d\n", ret,__LINE__); return -1; } loop_id = 0; while (vpu_IsBusy()) { if (loop_id == 50) { ret = vpu_SWReset(handle, 0); return -1; } vpu_WaitForInt(100); loop_id ++; } ret = vpu_DecGetOutputInfo(handle, &outinfo); if (ret != RETCODE_SUCCESS) { printf("vpu_DecGetOutputInfo failed Err code is %d\n" "\tframe_id = %d\n", ret, (int)frame_id); return -1; } if (cpu_is_mx6x() && (outinfo.decodingSuccess & 0x10)) { printf("vpu needs more bitstream in rollback mode\n" "\tframe_id = %d\n", (int)frame_id); return -1; } if (outinfo.notSufficientPsBuffer) { printf("PS Buffer overflow,LINE:%d\n",__LINE__); return -1; } if (outinfo.notSufficientSliceBuffer) { printf("Slice Buffer overflow,LINE:%d\n",__LINE__); return -1; } if (outinfo.indexFrameDisplay == -1){ printf("VPU has no more display data,LINE:%d\n",__LINE__); return -1; } if ((outinfo.indexFrameDisplay == -3) ||(outinfo.indexFrameDisplay == -2)) { printf("VPU doesn't have picture to be displayed.\n" "\toutinfo.indexFrameDisplay = %d\n", outinfo.indexFrameDisplay); if (disp_clr_index >= 0) { ret = vpu_DecClrDispFlag(handle, disp_clr_index); if (ret) printf("vpu_DecClrDispFlag failed Error code" " %d\n", ret); } disp_clr_index = outinfo.indexFrameDisplay; } dis_index = outinfo.indexFrameDisplay; dest->vaddr = (void *)(dec_pfbpool[dis_index]->addrY + (dec_pfbpool[dis_index]->desc.virt_uaddr- dec_pfbpool[dis_index]->desc.phy_addr)); dest->paddr = dec_pfbpool[dis_index]->desc.phy_addr; //physical address dest->size = imageSize; dest->height = src->height; dest->width = src->width; dest->fourcc = PIX_FMT_YUV420P;//src->codec; dest->pts = src->pts; //printf("dis_index:%d,frame_id:%d,disp_clr_index:%d\n",dis_index,frame_id,disp_clr_index); if(dec_format == STD_AVC){ if (disp_clr_index >= 0) { ret = vpu_DecClrDispFlag(handle,disp_clr_index); if (ret) printf("vpu_DecClrDispFlag failed Error code%d,LINE:%d\n", ret,__LINE__); } } disp_clr_index = outinfo.indexFrameDisplay; frame_id++; return 1; }
static int decoder_renderer_submit_decode_unit(PDECODE_UNIT decodeUnit) { PLENTRY entry = decodeUnit->bufferList; while (entry != NULL) { Uint32 space; PhysicalAddress pa_read_ptr, pa_write_ptr; if (vpu_DecGetBitstreamBuffer(handle, &pa_read_ptr, &pa_write_ptr, &space) != RETCODE_SUCCESS) { fprintf(stderr, "Can't get video decoder buffer\n"); exit(EXIT_FAILURE); } Uint32 target_addr = mem_desc.virt_uaddr + (pa_write_ptr - mem_desc.phy_addr); if ( (target_addr + entry->length) > mem_desc.virt_uaddr + STREAM_BUF_SIZE) { int room = mem_desc.virt_uaddr + STREAM_BUF_SIZE - target_addr; memcpy((void *)target_addr, entry->data, room); memcpy((void *)mem_desc.virt_uaddr, entry->data + room, entry->length - room); } else { memcpy((void *)target_addr, entry->data, entry->length); } vpu_DecUpdateBitstreamBuffer(handle, entry->length); } if (!initialized) { initialized = true; vpu_DecSetEscSeqInit(handle, 1); DecInitialInfo initinfo = {0}; if (vpu_DecGetInitialInfo(handle, &initinfo) != RETCODE_SUCCESS) { fprintf(stderr, "Can't get initial info\n"); exit(EXIT_FAILURE); } vpu_DecSetEscSeqInit(handle, 0); int regfbcount = initinfo.minFrameBufferCount + 2; threshold = regfbcount - initinfo.minFrameBufferCount; int picWidth = ((initinfo.picWidth + 15) & ~15); int picHeight = ((initinfo.picHeight + 15) & ~15); int stride = picWidth; int phy_slicebuf_size = initinfo.worstSliceSize * 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); 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) { return -9; } 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; } DecBufInfo bufinfo; 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); if (vpu_DecRegisterFrameBuffer(handle, fb, regfbcount, stride, &bufinfo) != RETCODE_SUCCESS) { fprintf(stderr, "Can't register decoder to framebuffer\n"); exit(EXIT_FAILURE); } if (!decoding) { if (vpu_DecStartOneFrame(handle, &decparam) != RETCODE_SUCCESS) { fprintf(stderr, "Can't start decoding\n"); exit(EXIT_FAILURE); } decoding = true; } } int loop_id = 0; while (vpu_IsBusy()) { if (loop_id > 50) { vpu_SWReset(handle, 0); fprintf(stderr, "VPU is too long busy\n"); exit(EXIT_FAILURE); } vpu_WaitForInt(100); loop_id++; } loop_id = 0; if (decoding) { decoding = 0; DecOutputInfo outinfo = {0}; if (vpu_DecGetOutputInfo(handle, &outinfo) != RETCODE_SUCCESS) { fprintf(stderr, "Can't get output info\n"); exit(EXIT_FAILURE); } if (outinfo.decodingSuccess & 0x10) { return 0; } else if (outinfo.notSufficientPsBuffer) { fprintf(stderr, "Not enough space in stream buffer\n"); exit(EXIT_FAILURE); } else if (outinfo.notSufficientSliceBuffer) { fprintf(stderr, "Not enough space in slice buffer\n"); exit(EXIT_FAILURE); } if (outinfo.indexFrameDisplay >= 0) { struct timeval tv; gettimeofday(&tv, 0); dbuf.timestamp.tv_sec = tv.tv_sec; dbuf.timestamp.tv_usec = tv.tv_usec; dbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; dbuf.memory = V4L2_MEMORY_MMAP; dbuf.index = outinfo.indexFrameDisplay; if (ioctl(fd, VIDIOC_QUERYBUF, &dbuf) < 0) { fprintf(stderr, "Can't get output buffer\n"); exit(EXIT_FAILURE); } dbuf.index = outinfo.indexFrameDisplay; dbuf.field = V4L2_FIELD_NONE; if (ioctl(fd, VIDIOC_QBUF, &dbuf) < 0) { fprintf(stderr, "Can't get output buffer\n"); exit(EXIT_FAILURE); } if (!displaying) { int type = V4L2_BUF_TYPE_VIDEO_OUTPUT; if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) { fprintf(stderr, "Failed to output video\n"); exit(EXIT_FAILURE); } displaying = true; } queued_count++; if (queued_count > threshold) { dbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; dbuf.memory = V4L2_MEMORY_MMAP; if (ioctl(fd, VIDIOC_DQBUF, &dbuf) < 0) { fprintf(stderr, "Failed to dequeue buffer\n"); exit(EXIT_FAILURE); } else queued_count--; } else dbuf.index = -1; if (disp_clr_index >= 0) vpu_DecClrDispFlag(handle, disp_clr_index); disp_clr_index = outinfo.indexFrameDisplay; } else if (outinfo.indexFrameDisplay == -1) { fprintf(stderr, "Failed to decode frame\n"); exit(EXIT_FAILURE); } } return DR_OK; }
static int x264_encoder_start(EncData *d,MSPicture *pic,MSQueue *nalus,int* sizeAll,SPSInfo *sps,PPSInfo *pps,int* key) { struct x264_encode *enc=d->enc; EncHandle handle = enc->handle; EncParam enc_param = {0}; EncOpenParam encop = {0}; EncOutputInfo outinfo = {0}; RetCode ret = 0; int src_fbid = enc->src_fbid, img_size; FrameBuffer *fb = enc->fb; struct frame_buf **pfbpool = enc->pfbpool; struct frame_buf *pfb; unsigned int yuv_addr; unsigned int vbuf; mblk_t *m; int i; if(d->framenum==0) { ret = x264_encoder_fill_headers(enc,nalus,d,sizeAll,sps,pps); if (ret) { ms_error("MSH264Enc: Encode fill headers failed\n"); return -1; } } enc_param.sourceFrame = &enc->fb[src_fbid]; enc_param.quantParam = 23; if(d->framenum%100==0) { enc_param.forceIPicture = 1; } else { enc_param.forceIPicture = 0; } enc_param.skipPicture = 0; enc_param.enableAutoSkip = 1; enc_param.encLeftOffset = 0; enc_param.encTopOffset = 0; if ((enc_param.encLeftOffset + enc->enc_picwidth) > enc->src_picwidth) { ms_error("MSH264Enc: Configure is failure for width and left offset\n"); return -1; } if ((enc_param.encTopOffset + enc->enc_picheight) > enc->src_picheight) { ms_error("MSH264Enc: Configure is failure for height and top offset\n"); return -1; } img_size = enc->src_picwidth * enc->src_picheight * 3 / 2; /* The main encoding loop */ pfb = pfbpool[src_fbid]; yuv_addr = pfb->addrY + pfb->desc.virt_uaddr - pfb->desc.phy_addr; memcpy((void *)yuv_addr, pic->planes[0],img_size); ret = vpu_EncStartOneFrame(handle, &enc_param); if (ret != RETCODE_SUCCESS) { ms_error("MSH264Enc: vpu_EncStartOneFrame failed Err code:%d\n", ret); goto err2; } //struct timeval tv1,tv2; //gettimeofday(&tv2,NULL); while (vpu_IsBusy()) { vpu_WaitForInt(200); } //gettimeofday(&tv1,NULL); //ms_message("[INFO] TIME=%d ",tv1.tv_sec*1000 + tv1.tv_usec/1000 - tv2.tv_sec*1000 - tv2.tv_usec/1000); ret = vpu_EncGetOutputInfo(handle, &outinfo); if (ret != RETCODE_SUCCESS) { ms_error("MSH264Enc: vpu_EncGetOutputInfo failed Err code: %d\n", ret); goto err2; } if (outinfo.skipEncoded) ms_message("[INFO] Skip encoding one Frame!\n"); vbuf = (enc->virt_bsbuf_addr + outinfo.bitstreamBuffer - enc->phy_bsbuf_addr); //ms_message("[INFO] LEN=%d NUM=%d",outinfo.bitstreamSize,outinfo.numOfSlices); if( (*((char*)vbuf+4) & 0x1F) ==5 ) { *key=1; //ms_message("[KEY]=%x num=%llu",*((char*)vbuf+4),d->framenum); } for(i=1;i<=outinfo.numOfSlices;i++) { void *ptr; int size; if(i==outinfo.numOfSlices) { m=allocb(outinfo.bitstreamSize+10,0); memcpy(m->b_wptr,(void*)vbuf+4,outinfo.bitstreamSize-4); m->b_wptr+=outinfo.bitstreamSize-4; ms_queue_put(nalus,m); *sizeAll+=outinfo.bitstreamSize; //ms_message("[INFO] LEN[%d]=%d",i,outinfo.bitstreamSize); break; } ptr=x264_find_header((void*)vbuf+1000,outinfo.bitstreamSize-1000); if(ptr==NULL) { ms_error("MSH264Enc: x264_find_header failed error"); goto err2; } size=ptr-(void*)vbuf; m=allocb(size+10,0); memcpy(m->b_wptr,(void*)vbuf+4,size-4); m->b_wptr+=size-4; ms_queue_put(nalus,m); *sizeAll+=size; vbuf=(unsigned int)ptr; outinfo.bitstreamSize-=size; //ms_message("[INFO] LEN[%d]=%d",i,size); } err2: /* For automation of test case */ if (ret > 0) ret = 0; return ret; }
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; }
bool mjpeg_decoder_t::decode_complete(void const *&y, void const *&u, void const *&v, void *&opaque, unsigned &displayIdx, int &picType, bool &errors ) { displayIdx = 0 ; errors = false ; if( startedDecode_ && !vpu_IsBusy() ){ DecOutputInfo outinfo = {0}; RetCode ret = vpu_DecGetOutputInfo(handle_, &outinfo); debugPrint("vpu_DecGetOutputInfo(%d): %d display, %d decode\n", ret, outinfo.indexFrameDisplay, outinfo.indexFrameDecoded); if (ret == RETCODE_SUCCESS) { startedDecode_ = false ; debugPrint("success %d\n", outinfo.decodingSuccess); debugPrint("indexFrame decoded %d (0x%x)\n", outinfo.indexFrameDecoded, outinfo.indexFrameDecoded); debugPrint("indexFrame display %d (0x%x)\n", outinfo.indexFrameDisplay, outinfo.indexFrameDisplay); debugPrint("picType %d\n", outinfo.picType); picType = outinfo.picType ; if( 0 != outinfo.numOfErrMBs) { debugPrint("%d errMBs\n", outinfo.numOfErrMBs); errors = true ; } debugPrint("qpInfo %p\n", outinfo.qpInfo); debugPrint("hscale %d\n", outinfo.hScaleFlag); debugPrint("vscale %d\n", outinfo.vScaleFlag); debugPrint("index rangemap %d\n", outinfo.indexFrameRangemap); debugPrint("prescan result %d\n", outinfo.prescanresult); debugPrint("picstruct %d\n", outinfo.pictureStructure); debugPrint("topfield first %d\n", outinfo.topFieldFirst); debugPrint("repeat first %d\n", outinfo.repeatFirstField); debugPrint("field seq %d\n", outinfo.fieldSequence); debugPrint("size %dx%d\n", outinfo.decPicWidth, outinfo.decPicHeight); debugPrint("nsps %d\n", outinfo.notSufficientPsBuffer); debugPrint("nsslice %d\n", outinfo.notSufficientSliceBuffer); debugPrint("success %d\n", outinfo.decodingSuccess); debugPrint("interlaced %d\n", outinfo.interlacedFrame); debugPrint("mp4packed %d\n", outinfo.mp4PackedPBframe); debugPrint("h264Npf %d\n", outinfo.h264Npf); debugPrint("prog/repeat %d\n", outinfo.progressiveFrame); debugPrint("crop %d:%d->%d:%d\n", outinfo.decPicCrop.left,outinfo.decPicCrop.top, outinfo.decPicCrop.right, outinfo.decPicCrop.bottom); if( (0 <= outinfo.indexFrameDisplay) && (fbcount > outinfo.indexFrameDisplay) ){ unsigned mask = 1<<outinfo.indexFrameDisplay ; assert(0 != (decoder_fbs&mask)); decoder_fbs &= ~mask ; assert(0 == (app_fbs & mask)); app_fbs |= mask ; frame_buf *pfb = pfbpool+outinfo.indexFrameDisplay ; y = (void *)(pfb->addrY + pfb->desc.virt_uaddr - pfb->desc.phy_addr); u = (char *)y + ySize(); v = (char *)u + uvSize(); displayIdx = outinfo.indexFrameDisplay ; debugPrint("returning display index %u:%p\n", displayIdx,y); return true ; } else { fprintf(stderr, "Invalid display fb index: %d\n", outinfo.indexFrameDisplay); startDecode(); } } else { fprintf( stderr, "Error %d from vpu_DecGetOutputInfo\n", ret ); } } else { debugPrint( "VPU is busy\n" ); vpu_WaitForInt(0); } return false ; }