Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
int VpuDec::set_DecOpenParam()
{
	int ret = -1;
	memset(&handle,0,sizeof(DecHandle));
	DecOpenParam oparam;// = {0};
	memset(&oparam, 0, sizeof(DecOpenParam)); //must to clean to 0
	
	allocHwBuffer(Dec_RingBuf_Size);
	
	oparam.bitstreamFormat = (CodStd)dec_format;
	oparam.bitstreamBuffer = Dec_bufZone.pStartAddr;
	oparam.bitstreamBufferSize = Dec_bufZone.bufSize;
	oparam.pBitStream = (Uint8 *)Dec_bufZone.vStartaddr;
	oparam.reorderEnable = 1;
	oparam.mp4DeblkEnable = 0;
	oparam.chromaInterleave = 0;
	oparam.mp4Class = 0;
	if (cpu_is_mx6x())
		oparam.avcExtension = 0;
	oparam.mjpg_thumbNailDecEnable = 0;
	oparam.mapType = 0;
	oparam.tiled2LinearEnable = 0;
	oparam.bitstreamMode = 1;
	oparam.jpgLineBufferMode = 1;
	
	if (dec_format == STD_AVC) {
		ps_mem_desc.size = PS_SAVE_SIZE;
		ret = IOGetPhyMem(&ps_mem_desc);
		if (ret){
			printf("Unable to obtain physical ps save mem,LINE%d\n",__LINE__);
			return -1;
		}
		
		oparam.psSaveBuffer = ps_mem_desc.phy_addr;
		oparam.psSaveBufferSize = PS_SAVE_SIZE;
	}
		//printf("bitstreamFormat %x, bitstreamBuffer %x,bitstreamBufferSize %d, pBitStream %x\n",oparam.bitstreamFormat,
			//oparam.bitstreamBuffer,oparam.bitstreamBufferSize,oparam.pBitStream);

	ret = vpu_DecOpen(&handle, &oparam);
	if (ret != RETCODE_SUCCESS) {
		printf("vpu_DecOpen failed, ret:%d\n", ret);
		return -1;
	}
	
	return 0;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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);
}
Esempio n. 10
0
int VpuDec::calloc_FrameBuff(VencBlk * src)
{	
	int mvCol = 1;
	int ret = -1;
	int i;
	DecBufInfo bufinfo;
	FrameBuffer *fb;
	struct frame_buf **pfbpool;

	if (dec_format == STD_MJPG)
		mvCol = 0;
	
	fb = dec_fb = (FrameBuffer *)calloc(regfbcount, sizeof(FrameBuffer));
	if (fb == NULL) {
		printf("Failed to allocate fb,LINE:%d\n",__LINE__);
		return -1;
	}

	pfbpool = dec_pfbpool = (frame_buf **)calloc(regfbcount, sizeof(struct frame_buf *));
	if (pfbpool == NULL) {
		printf("Failed to allocate pfbpool,LINE:%d\n",__LINE__);
		free(dec_fb);
		dec_fb = NULL;
		return -1;
	}

	for (i = 0; i < regfbcount; i++) {
		pfbpool[i] = framebuf_alloc(&fbpool[i], STD_AVC, 0, src->width, src->height, mvCol);
		if (pfbpool[i] == NULL)
			return -1;
	}

	for (i = 0; i < regfbcount; i++) {
			fb[i].myIndex = i;
			fb[i].bufY = pfbpool[i]->addrY;
			fb[i].bufCb = pfbpool[i]->addrCb;
			fb[i].bufCr = pfbpool[i]->addrCr;
			fb[i].bufMvCol = pfbpool[i]->mvColBuf;
	}

	if (dec_format == STD_AVC) {
		ret = IOGetPhyMem(&slice_mem_desc);
			if (ret) {
				printf("Unable to obtain physical slice save mem,LINE:%d\n",__LINE__);
				return -1;
			}

		bufinfo.avcSliceBufInfo.bufferBase = slice_mem_desc.phy_addr;
		bufinfo.avcSliceBufInfo.bufferSize = slice_mem_desc.size;
	}

	bufinfo.maxDecFrmInfo.maxMbX = src->width / 16;
	bufinfo.maxDecFrmInfo.maxMbY = src->height / 16;
	bufinfo.maxDecFrmInfo.maxMbNum = src->width * src->height / 256;

	ret = vpu_DecRegisterFrameBuffer(handle, fb, regfbcount, src->width, &bufinfo);
	if (ret != RETCODE_SUCCESS) {
		printf("Register frame buffer failed, ret=%d,LINE:%d\n", ret,__LINE__);
		return -1;
	}
	
	return 0;

}
Esempio n. 11
0
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;
}
Esempio n. 12
0
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;
}
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 ;
}