Пример #1
0
int VpuDec::get_DecInitialInfo(VencBlk * src)
{	
	int ret = -1;
	DecInitialInfo initinfo = {0};
	
	/* Parse bitstream and get width/height/framerate etc */
	vpu_DecSetEscSeqInit(handle, 1);
	ret = vpu_DecGetInitialInfo(handle, &initinfo);
	vpu_DecSetEscSeqInit(handle, 0);
	if (ret != RETCODE_SUCCESS) {
		printf("vpu_DecGetInitialInfo failed, ret:%d, errorcode:%ld\n",
		         ret, initinfo.errorcode);
		return -1;
	}

	/*if (cpu_is_mx6x())
		printf("Decoder: width = %d, height = %d, frameRateRes = %lu, frameRateDiv = %lu, count = %u\n",
			initinfo.picWidth, initinfo.picHeight,
			initinfo.frameRateRes, initinfo.frameRateDiv,
			initinfo.minFrameBufferCount);*/

	/*if(initinfo.picWidth != src->width || initinfo.picHeight != src->height){
		printf("initinfo.picWidth or initinfo.picHeight is not equal the src\tLINE:%d\n",__LINE__);
		return -1;
	}*/
	
	src->width = initinfo.picWidth;
	src->height = initinfo.picHeight;
	printf("Decoder: width = %d, height = %d\n",initinfo.picWidth,initinfo.picHeight);

	regfbcount = initinfo.minFrameBufferCount +2;
	slice_mem_desc.size = initinfo.worstSliceSize * 1024;
	
	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
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;
}
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 ;
}