你好,问一下,H264源码通过网口输入,然后解码,并转换位YUV422格式,通过调用VPIF OUT接口输出到SII9134,但是9134黑屏,不知道为什么,源码如下
int DecH264Thr(Args * args)
{
OSA_ThrHndl *disId;
disId = malloc(sizeof(OSA_ThrHndl));
printf("Starting DEC H264 Thr.\n");
hTime = Time_create(&tAttrs);
OSA_thrCreate(disId,(void*)DisThread,DIS_THREAD_PRIORITY,0,args);
Dec2dis = MBX_create(0);
while(1){
MBX_pend(Cap2dec,NULL);
if (args->cache) {
Memory_cacheWbInv(Buffer_getUserPtr(hInputBuf),Buffer_getSize(hInputBuf));
Memory_cacheInv(Buffer_getUserPtr(YUV420Buf), Buffer_getSize(YUV420Buf));
}
BufferGfx_resetDimensions(YUV420Buf);
if (Vdec2_process(hVe, hInputBuf, YUV420Buf) < 0) {
printf("Failed to encode video buffer\n");
}
if (Buffer_getNumBytesUsed(YUV420Buf) > 0) {
if (args->cache) {
Memory_cacheWb(Buffer_getUserPtr(YUV420Buf),Buffer_getNumBytesUsed(YUV420Buf));
}
MBX_post(Dec2dis,NULL);
}
else
printf("dec is fail…");
}
saveTsStream((Uint8 *)YUV420Buf,Buffer_getNumBytesUsed(YUV420Buf),100);
pthread_join(disId->hndl,NULL);
return 0;
}
static int sii9134_fd;
void DisThread(Args * args)
{
int vdcefd = 0,ret,display_fd;
Display_Attrs dAttrs;
int display_numbuffers = 3;
struct v4l2_format display_fmt;
ResizerSrc_Obj ResizerSrc;
ResizerDst_Obj ResizerDst;
void *hDisBuf;
char *value;
printf("Starting Display Thr.\n"); dAttrs = Display_Attrs_DM6467_VID_DEFAULT;
/* Create the video display */
dAttrs.videoStd = args->videoStd;/////1080P
dAttrs.videoOutput = args->videoOutput;
dAttrs.colorSpace = ColorSpace_YUV422PSEMI;
ret = initDisplay(&display_fd,&display_numbuffers,&display_fmt);
value = malloc(4);
startDisplay(&display_fd);
/******************************************
VDCE init
********************************************/
ResizerSrc.width = args->width + 64;
ResizerSrc.height = args->height;
ResizerSrc.pitch = args->width + 64;
ResizerSrc.img_type = VDCE_IMAGE_FMT_420;
ResizerSrc.buf_size = (args->width + 64)*args->height*3/2;
ResizerDst.width = args->width + 64;
ResizerDst.height = args->height;
ResizerDst.pitch = args->width + 64;
ResizerDst.img_type = VDCE_IMAGE_FMT_422;
ResizerDst.buf_size = (args->width + 64)*args->height*2;
vdcefd = init_vdce_engine(&ResizerSrc,&ResizerDst);
sii9134_fd = open("/dev/sii9134",O_RDWR);
if(sii9134_fd<0)
printf("Unable to open sii9134 Driver.\n");
ret = ioctl(sii9134_fd,1,0);
while(1)
{
MBX_pend(Dec2dis,NULL);
Time_reset(hTime);
hDisBuf = getDisplayBuffer(&display_fd);
Time_total(hTime,&args->time);
ResizerSrc.src_buf =(unsigned char*)Buffer_getUserPtr(YUV420Buf);
ResizerDst.dst_buf =(unsigned char*)hDisBuf;
ret = ioctl(sii9134_fd,3,0×42);
// ccv420_422(vdcefd,&ResizerSrc, &ResizerDst);////6ms
memset((unsigned char*)hDisBuf,0xFF,1920*1080*2);
// printf("%ld\n",args->time);
ret = putDisplayBuffer(&display_fd, display_numbuffers,hDisBuf);
if(ret<0)
printf("Failed to put display buffer\n");
}
stopDisplay(&display_fd);
}
int init_vdce_engine(ResizerSrc_Handle res_src,ResizerDst_Handle res_dst)
{
vdce_params_t vdce_params;
int vdcefd=0;
vdcefd = open(DEVICE_NAME,O_RDWR);
if( vdcefd <= 0){
printf("Unable to open VDCE Driver.\n");
close(vdcefd);
return -1;
}
/* We want to RESIZE.(as agianst other operations
like CCV,BLEND etc)
*/
vdce_params.vdce_mode = VDCE_OPERATION_CHROMINANCE_CONVERSION;
/* Get the default set of parameters to save ourselves from
enetring a whole host of parameters and using wrong parameters
*/
if (ioctl(vdcefd, VDCE_GET_DEFAULT, &vdce_params) < 0) {
printf("default params failed error.\n");
exit(-1);
}
vdce_params.vdce_mode_params.ccv_params.conversion_type =
VDCE_CCV_MODE_420_422;
/* change input and output size from the dafaults applicable for the current need
*/
vdce_params.common_params.src_hsz_luminance = res_src->width;
vdce_params.common_params.src_vsz_luminance = res_src->height;
/* set output size */
vdce_params.common_params.dst_hsz_luminance = res_dst->width;
vdce_params.common_params.dst_vsz_luminance= res_dst->height;
/* PROGRESSIVE indicates that we wish use a full framed buffer.
One could also use INTERLACED FRAME.INTERLACED
FIELD mode indicates separated fields.
*/
vdce_params.common_params.src_processing_mode = VDCE_PROGRESSIVE;
vdce_params.common_params.src_mode = VDCE_FRAME_MODE;
vdce_params.common_params.res_mode = VDCE_FRAME_MODE;
/* call ioctl to set parameters */
if (ioctl(vdcefd, VDCE_SET_PARAMS, &vdce_params) < 0) {
printf("set params failed \n");
exit(-1);
}
return vdcefd;
}
int ccv420_422(int vdcefd,ResizerSrc_Handle res_src, ResizerDst_Handle res_dst)
{
vdce_address_start_t runtime_params;
/* Here 0 is the index of the Driver allocated buffer.
For multiple driver allocated buffers, use 0,1,2 etc.
If one wishes to use user pointers, the index should be set to -1
*/ runtime_params.buffers[VDCE_BUF_IN].index =-1;/* Index number */
runtime_params.buffers[VDCE_BUF_OUT].index =-1;/* Index number */
runtime_params.src_horz_pitch = res_src->pitch;
runtime_params.res_horz_pitch = res_dst->pitch;
runtime_params.buffers[VDCE_BUF_IN].virt_ptr = (unsigned int)res_src->src_buf;
runtime_params.buffers[VDCE_BUF_OUT].virt_ptr =(unsigned int)res_dst->dst_buf;
runtime_params.buffers[VDCE_BUF_IN].size =res_src->buf_size;
runtime_params.buffers[VDCE_BUF_OUT].size = res_dst->buf_size;
if (ioctl(vdcefd, VDCE_START, &runtime_params) < 0) {
perror("ge start failed \n");
return -1;
}
return 0;
}
#define DISPLAY_DEVICE "/dev/video2"
v4l2_std_id input_std_id = V4L2_STD_1080P_60;
static struct buf_info display_buff_info[5];
static int initDisplay(int *display_fd,int *numbuffers,struct v4l2_format *fmt)
{
int mode = O_RDWR;
struct v4l2_buffer buf; int ret, i = 0; struct v4l2_requestbuffers reqbuf;
struct v4l2_output output;
int temp_output;
struct v4l2_standard standard;
int found = 0;
/* Open the channel-2 display device */
*display_fd = open((const char *)DISPLAY_DEVICE, mode);
if (*display_fd <= 0) { printf("Cannot open %s\n", DISPLAY_DEVICE);
return -1;
}
/* Enumerate outputs */
output.type = V4L2_OUTPUT_TYPE_ANALOG;
output.index = 0; while ((ret = ioctl(*display_fd, VIDIOC_ENUMOUTPUT, &output) == 0)) { if (!strcmp((char *)output.name, input_name)) {
found = 1;
break;
}
output.index++;
}
if (!found) {
printf("Unable to find output name matching input name %s\n", input_name);
return -1;
}
/* Set output */
ret = ioctl(*display_fd, VIDIOC_S_OUTPUT, &output.index);
if (ret < 0) {
perror("VIDIOC_S_OUTPUT failed\n");
return -1;
}
ret = ioctl(*display_fd, VIDIOC_G_OUTPUT, &temp_output);
if (ret < 0) {
perror("VIDIOC_S_OUTPUT failed\n");
return -1;
}
if (temp_output != output.index) {
printf("Couldn't set output index %d at display\n", output.index);
return -1;
}
/* Set standard */
found = 0;
/* Enumerate standard to get the name of the standard detected */
standard.index = 0;
do {
ret = ioctl(*display_fd, VIDIOC_ENUMSTD, &standard);
if (ret < 0) {
perror("VIDIOC_ENUM_STD failed\n");
return -1;
}
if (strcmp((char *)standard.name,"1080P-60") == 0) {
printf("Found standard support in the driver\n");
found = 1;
break;
}
standard.index++;
} while (1);
ret = ioctl(*display_fd, VIDIOC_S_STD, &input_std_id);
if (ret < 0) {
perror("VIDIOC_S_STD failed\n");
return -1;
}
printf("Set output standard to match with input capture standard\n");
printf("Setting display format\n");
/* Set format */
CLEAR(*fmt);
fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
fmt->fmt.pix.bytesperline = 1920;
fmt->fmt.pix.sizeimage = 1920*1080*2;
fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_NV16;
fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
ret = ioctl(*display_fd, VIDIOC_S_FMT, fmt);
if (ret < 0) {
perror("VIDIOC_S_FMT failed\n");
return -1;
}
CLEAR(*fmt);
fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
ret = ioctl(*display_fd, VIDIOC_G_FMT, fmt);
if (ret < 0) {
perror("VIDIOC_G_FMT\n");
return -1;
}
reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
reqbuf.count = *numbuffers;
reqbuf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(*display_fd, VIDIOC_REQBUFS, &reqbuf);
if (ret < 0) {
perror("cannot allocate memory\n");
return -1;
}
/* Store the numbfer of buffers allocated */
*numbuffers = reqbuf.count;
/* It is better to zero all the members of buffer structure */
memset(&buf, 0, sizeof(buf));
for (i = 0; i < reqbuf.count; i++) {
/* Query physical address of the buffers */
buf.index = i;
buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
buf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(*display_fd, VIDIOC_QUERYBUF, &buf);
if (ret < 0) {
perror("VIDIOC_QUERYCAP\n");
return -1;
}
/* Mmap the buffers in application space */
display_buff_info[i].length = buf.length;
display_buff_info[i].index = i;
display_buff_info[i].start =
mmap(NULL, buf.length, PROT_READ | PROT_WRITE,
MAP_SHARED, *display_fd, buf.m.offset);
if ((unsigned int)display_buff_info[i].start == MAP_SHARED) {
printf("Cannot mmap = %d buffer\n", i);
return -1;
}
memset(display_buff_info[i].start, 0x10,
display_buff_info[i].length/2);
memset(display_buff_info[i].start+display_buff_info[i].length/2, 0x80,
display_buff_info[i].length/2);
printf("display_buff_info[%d].length = %d\n", i, display_buff_info[i].length);
printf("display_buff_info[%d].index = %d\n", i, display_buff_info[i].index);
printf("display_buff_info[%d].start = %p\n", i, display_buff_info[i].start);
}
for (i = 0; i < reqbuf.count; i++) {
buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
ret = ioctl(*display_fd, VIDIOC_QBUF, &buf);
if (ret < 0) {
perror("VIDIOC_QBUF\n");
return -1;
}
}
return 0;
}
static int startDisplay(int *display_fd)
{
int a = V4L2_BUF_TYPE_VIDEO_OUTPUT, ret;
/* Here type of device to be streamed on is required to be passed */
ret = ioctl(*display_fd, VIDIOC_STREAMON, &a);
if (ret < 0) {
perror("VIDIOC_STREAMON\n");
return -1;
}
return 0;
}
static int stopDisplay(int *display_fd)
{
int ret, a = V4L2_BUF_TYPE_VIDEO_OUTPUT;
/* Here type of device to be streamed off is required to be passed */
ret = ioctl(*display_fd, VIDIOC_STREAMOFF, &a);
if (ret < 0) {
perror("VIDIOC_STREAMOFF\n");
return -1;
}
return 0;
}
static void *getDisplayBuffer(int *display_fd)
{
int ret;
struct v4l2_buffer buf;
/* It is better to zero members of v4l2_buffer structure */
memset(&buf, 0, sizeof(buf));
/* Dequeue buffer
* VIDIOC_DQBUF ioctl de-queues a displayed empty buffer from driver.
* This call can be blocking or non blocking. For blocking call, it
* blocks untill an empty buffer is available. For non-blocking call,
* it returns instantaneously with success or error depending on * empty buffer is available or not. */
buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
ret = ioctl(*display_fd, VIDIOC_DQBUF, &buf);
if (ret < 0) {
perror("VIDIOC_DQBUF\n");
return NULL;
}
return display_buff_info[buf.index].start;
}
static int putDisplayBuffer(int *display_fd, int numbuffers, void *addr)
{
struct v4l2_buffer buf;
int i, index = 0;
int ret;
if (addr == NULL)
return -1;
/* It is better to zero members of v4l2_buffer structure */
memset(&buf, 0, sizeof(buf));
/* Find index of the buffer whose address is passed as the argument */
for (i = 0; i < numbuffers; i++) {
if (addr == display_buff_info[i].start) {
index = display_buff_info[i].index;
break;
}
}
if (i == numbuffers)
return -1;
/* Enqueue the buffer */
buf.m.offset = (unsigned long)addr;
buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = index;
ret = ioctl(*display_fd, VIDIOC_QBUF, &buf);
if (ret < 0) {
perror("VIDIOC_QBUF\n");
}
return ret;
}
Chris Meng:
你好,
我认为你先要定位一下问题在哪里?是YUV输出显示的问题,还是YUV转换的问题,还是解码的问题。
你可以先尝试显示一个已知的YUV数据,看是否显示部分有问题?
如果显示没有问题,可以一级一级往上查。也可以从解码开始查。
yong tian3:
回复 Chris Meng:
你好,解码前的都没有问题,我验证过了,就是把解码的数据保存下来,然后可以正常播放,就是DVI无输出,我想问一下,我是不是只需要把源码YUV422直接放入getDisplayBuffer返回的空间,不需要打包成BT656格式吧,VPIFOUT接口会自动转换BT656格式发给SII9134吧