USB摄像头同步传输H264遇到的花屏问题
2021-11-09
1158
0
以往拿到的摄像头数据传输都是批量传输,本人也只在音频驱动的开发中使用了同步传输。
这次突然拿到一个摄像头,数据采用的是同步传输,本以为很简单的代码移植,却没有想到还是遇到了一个坑,自己花费了大力气来排查,在这期间自己也看了大量的资料,今天在这里做一个简单的总结。
以前的摄像头拿到的USB摄像头如批量传输,数据每隔8192字节加一个UVC的负载数据头,而且是MJPG格式,固件厂商也比较讲究,数据包中没有大量没用的00数据,只要搞定一个,后面它们弄的像H264等其它格式的摄像头,自己也只做一个适配就行了,所以驱动开发起来那就一个快并轻松。
如一包MJPG的数据,它的数据格式布局大概如下:
但这次拿到的摄像头比较事多,是一个H264格式的同步传输的摄像头,它是有数据时发数据,没有数据时发00,数据和00全部混在一起,同步对于每个小包USBD_ISO_PACKET_DESCRIPTOR的1024长度数据,也加了UVC负载数据头。
对于同步的数据传输,本人在每URB中每读取0x80个同步包。这样在我的理解中,每个URB应返回一个完整数据帧或者半完整帧,这样自己通过代码再将这个URB中的数据进行整合,应该就没有问题了。
数据整合的代码如下:
PURB urb = frame->Urb;
ULONG OkOffset = 0;
for (ULONG i = 0; i < urb->UrbIsochronousTransfer.NumberOfPackets; i++)
{
if (urb->UrbIsochronousTransfer.IsoPacket[i].Status == STATUS_SUCCESS
&& urb->UrbIsochronousTransfer.IsoPacket[i].Length >0)
{
PUCHAR pSrc = frame->data + urb->UrbIsochronousTransfer.IsoPacket[i].Offset;
ULONG PackeLen = urb->UrbIsochronousTransfer.IsoPacket[i].Length;
// if (OkOffset != urb->UrbIsochronousTransfer.IsoPacket[i].Offset)
{
RtlCopyMemory(frame->data + OkOffset,pSrc,PackeLen);
}
OkOffset += PackeLen;
}
}
frame->size = urb->UrbIsochronousTransfer.TransferBufferLength ;
`
但这个数据在交层解析时,会出现花屏问题。
这个奇怪的问题竟然一弄就查了2天。
最后经过本人不懈的努务,终于发现了问题所在。
原因在于每URB中的同步传会出现粘包问题,所以这个URB中可能会有两包的数据,这样在中间的IsoPacket中会出现某一包的长度不等于1024字节,这样经过上层的代码进行拷贝后,会出现负载数据头错乱的问题,导致解码失败。
最后调整增加如下代码代码:
ULONG PackeLen = urb->UrbIsochronousTransfer.IsoPacket[i].Length;
if (i < (urb->UrbIsochronousTransfer.NumberOfPackets-1)
&& PackeLen != (urb->UrbIsochronousTransfer.IsoPacket[i+1].Offset - urb->UrbIsochronousTransfer.IsoPacket[i].Offset))
{
PackeLen = urb->UrbIsochronousTransfer.IsoPacket[i+1].Offset - urb->UrbIsochronousTransfer.IsoPacket[i].Offset;
}
...
frame->size = OkOffset;//
这样即可解决花屏问题
HID人机交互QQ群:564808376
UAC音频QQ群:218581009
UVC相机QQ群:331552032
BOT&UASP大容量存储QQ群:258159197
STC-USB单片机QQ群:315457461
USB技术交流QQ群2:580684376
USB技术交流QQ群:952873936