Пример #1
0
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;
}
Пример #2
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;
}
Пример #3
0
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;

}
Пример #4
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;
}
Пример #5
0
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 ;
}