uvc摄像头代码解析7

来源:互联网 发布:iapp 免杀源码 编辑:程序博客网 时间:2024/06/06 07:38

转http://blog.csdn.net/orz415678659/article/details/10083585


13.uvc视频初始化
13.1 uvc数据流控制
[cpp] view plain copy
  1. struct uvc_streaming_control {  
  2.     __u16 bmHint;  
  3.     __u8  bFormatIndex; //视频格式索引  
  4.     __u8  bFrameIndex;  //视频帧索引  
  5.     __u32 dwFrameInterval;  //视频帧间隔  
  6.     __u16 wKeyFrameRate;    //  
  7.     __u16 wPFrameRate;  
  8.     __u16 wCompQuality;  
  9.     __u16 wCompWindowSize;  
  10.     __u16 wDelay;   //延时  
  11.     __u32 dwMaxVideoFrameSize;  //最大视频帧大小  
  12.     __u32 dwMaxPayloadTransferSize;  
  13.     __u32 dwClockFrequency; //时钟频率  
  14.     __u8  bmFramingInfo;  
  15.     __u8  bPreferedVersion;  
  16.     __u8  bMinVersion;  //版本  
  17.     __u8  bMaxVersion;  //版本  
  18. } __attribute__((__packed__));  
13.2 uvc_video_init
[cpp] view plain copy
  1. int uvc_video_init(struct uvc_streaming *stream)  
  2. {  
  3.     struct uvc_streaming_control *probe = &stream->ctrl; //获取uvc数据流的uvs数据流控制对象  
  4.     struct uvc_format *format = NULL;  
  5.     struct uvc_frame *frame = NULL;  
  6.     unsigned int i;  
  7.     int ret;  
  8.     if (stream->nformats == 0) {  
  9.         uvc_printk(KERN_INFO, "No supported video formats found.\n");  
  10.         return -EINVAL;  
  11.     }  
  12.     atomic_set(&stream->active, 0);  
  13.     uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param); //初始化视频缓冲区队列  
  14.     usb_set_interface(stream->dev->udev, stream->intfnum, 0);  //选择Alt.Setting 0  
  15.     if (uvc_get_video_ctrl(stream, probe, 1, UVC_GET_DEF) == 0) //VS_PROBE_CONTROL(GET_DEF)  
  16.         uvc_set_video_ctrl(stream, probe, 1);                   //VS_PROBE_CONTROL(SET_DEF)  
  17.     ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR);    //VS_PROBE_CONTROL(GET_CUR)  
  18.     if (ret < 0)  
  19.         return ret;  
  20.     for (i = stream->nformats; i > 0; --i) {  //获取对应的uvc格式  
  21.         format = &stream->format[i-1];     
  22.         if (format->index == probe->bFormatIndex) //匹配uvc格式索引值  
  23.             break;  
  24.     }  
  25.     if (format->nframes == 0) {  
  26.         uvc_printk(KERN_INFO, "No frame descriptor found for the default format.\n");  
  27.         return -EINVAL;  
  28.     }  
  29.     for (i = format->nframes; i > 0; --i) {  
  30.         frame = &format->frame[i-1]; //获取对应的uvc帧  
  31.         if (frame->bFrameIndex == probe->bFrameIndex) //匹配uvc帧索引值  
  32.             break;  
  33.     }  
  34.     probe->bFormatIndex = format->index;      //设置uvc视频流控制的格式索引为uvc格式的索引  
  35.     probe->bFrameIndex = frame->bFrameIndex;  //设置uvc视频流控制的帧索引为uvc帧的索引  
  36.     stream->cur_format = format;             //设置uvc格式为uvc数据流的cur_format成员  
  37.     stream->cur_frame = frame;                   //设置uvc帧未uvc数据流的cur_frame成员  
  38.     /* Select the video decoding function 选择视频解码函数*/  
  39.     if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {   //视频采集  
  40.         if (stream->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)  
  41.             stream->decode = uvc_video_decode_isight;  
  42.         else if (stream->intf->num_altsetting > 1)  
  43.             stream->decode = uvc_video_decode_isoc;  //同步方式  
  44.         else  
  45.             stream->decode = uvc_video_decode_bulk;  //bluk方式  
  46.     }   
  47.     else {  //视频播放  
  48.         if (stream->intf->num_altsetting == 1)  
  49.             stream->decode = uvc_video_encode_bulk;  
  50.         else {  
  51.             uvc_printk(KERN_INFO, "Isochronous endpoints are not supported for video output devices.\n");  
  52.             return -EINVAL;  
  53.         }  
  54.     }  
  55.     return 0;  
  56. }  
13.2.1 初始化uvc队列
[cpp] view plain copy
  1. void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,int drop_corrupted)  
  2. {  
  3.     mutex_init(&queue->mutex);  
  4.     spin_lock_init(&queue->irqlock);  
  5.     INIT_LIST_HEAD(&queue->mainqueue);   //初始化uvc视频队列mainqueue链表  
  6.     INIT_LIST_HEAD(&queue->irqqueue);    //初始化uvc视频队列irqqueue链表  
  7.     queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0;  
  8.     queue->type = type;  
  9. }  

14.uvc V4L2设备
14.1 V4L2操作函数集
[cpp] view plain copy
  1. const struct v4l2_file_operations uvc_fops = {  
  2.     .owner      = THIS_MODULE,  
  3.     .open       = uvc_v4l2_open,    //打开方法  
  4.     .release             = uvc_v4l2_release,    //释放方法  
  5.     .unlocked_ioctl = uvc_v4l2_ioctl,   //控制方法  
  6.     .read       = uvc_v4l2_read,    //读方法  
  7.     .mmap       = uvc_v4l2_mmap,    //映射方法  
  8.     .poll       = uvc_v4l2_poll,    //轮询方法  
  9. };  
14.2 打开方法
14.2.1 相关结构体
[cpp] view plain copy
  1. struct uvc_fh {//uvc句柄  
  2.     struct uvc_video_chain *chain;  //uvc视频链  
  3.     struct uvc_streaming *stream;   //uvc视频流  
  4.     enum uvc_handle_state state;  
  5. };  
14.2.2 open
[cpp] view plain copy
  1. static int uvc_v4l2_open(struct file *file)  
  2. {  
  3.     struct uvc_streaming *stream;  
  4.     struct uvc_fh *handle;  
  5.     int ret = 0;  
  6.   
  7.     uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n");  
  8.     stream = video_drvdata(file);   //获取uvc视频流  
  9.     if (stream->dev->state & UVC_DEV_DISCONNECTED)    //设备没连接  
  10.         return -ENODEV;  
  11.     ret = usb_autopm_get_interface(stream->dev->intf);    //唤醒设备  
  12.     if (ret < 0)  
  13.         return ret;  
  14.     /* Create the device handle. */  
  15.     handle = kzalloc(sizeof *handle, GFP_KERNEL);   //创建uvc句柄  
  16.     if (handle == NULL) {  
  17.         usb_autopm_put_interface(stream->dev->intf);  
  18.         return -ENOMEM;  
  19.     }  
  20.     if (atomic_inc_return(&stream->dev->users) == 1) {  
  21.         ret = uvc_status_start(stream->dev); //uvc状态开始  
  22.         if (ret < 0) {  
  23.             usb_autopm_put_interface(stream->dev->intf);  
  24.             atomic_dec(&stream->dev->users);  
  25.             kfree(handle);  
  26.             return ret;  
  27.         }  
  28.     }  
  29.     handle->chain = stream->chain;    //捆绑uvc句柄和uvc视频链  
  30.     handle->stream = stream; //捆绑uvc句柄和uvc视频流  
  31.     handle->state = UVC_HANDLE_PASSIVE;  //设置uvc状态为未激活  
  32.     file->private_data = handle; //将uvc句柄作为文件的私有数据  
  33.     return 0;  
  34. }  
14.2.2.1 uvc_status_start启动状态
[cpp] view plain copy
  1. int uvc_status_start(struct uvc_device *dev)  
  2. {  
  3.     if (dev->int_urb == NULL)  
  4.         return 0;  
  5.     return usb_submit_urb(dev->int_urb, GFP_KERNEL); //提交urb  
  6. }  
参看 12.uvc状态初始化
14.3 控制方法
14.3.1 V4L2的控制方式可以参考下面的资料
linux媒体接口API
http://linuxtv.org/downloads/v4l-dvb-apis/
常用的命令
[cpp] view plain copy
  1. VIDIOC_REQBUFS:分配内存   
  2. VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址   
  3. VIDIOC_QUERYCAP:查询驱动功能   
  4. VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式   
  5. VIDIOC_S_FMT:设置当前驱动的频捕获格式   
  6. VIDIOC_G_FMT:读取当前驱动的频捕获格式   
  7. VIDIOC_TRY_FMT:验证当前驱动的显示格式   
  8. VIDIOC_CROPCAP:查询驱动的修剪能力   
  9. VIDIOC_S_CROP:设置视频信号的边框   
  10. VIDIOC_G_CROP:读取视频信号的边框   
  11. VIDIOC_QBUF:把数据从缓存中读取出来   
  12. VIDIOC_DQBUF:把数据放回缓存队列   
  13. VIDIOC_STREAMON:开始视频显示函数   
  14. VIDIOC_STREAMOFF:结束视频显示函数   
  15. VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC。   
14.3.2 uvc设备V4L2控制方法uvc_v4l2_do_ioctl
[cpp] view plain copy
  1. static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)  
  2. {  
  3.     struct video_device *vdev = video_devdata(file);//获取V4L2设备  
  4.     struct uvc_fh *handle = file->private_data;//获取uvc句柄  
  5.     struct uvc_video_chain *chain = handle->chain;//获取uvc视频链  
  6.     struct uvc_streaming *stream = handle->stream;//获取uvc视频流  
  7.     long ret = 0;  
  8.   
  9.     switch (cmd) {  
  10.     ...  
  11.     case ...:  
  12.     {  
  13.         ...  
  14.         break;  
  15.     }  
  16.     return ret;  
  17. }  
a.VIDIOC_STREAMON 开始视频显示函数
[cpp] view plain copy
  1. case VIDIOC_STREAMON:  
  2. {  
  3.     int *type = arg;  
  4.     if (*type != stream->type)  
  5.         return -EINVAL;  
  6.     if (!uvc_has_privileges(handle))  
  7.         return -EBUSY;  
  8.     mutex_lock(&stream->mutex);  
  9.     ret = uvc_video_enable(stream, 1);  //uvc视频流使能  
  10.     mutex_unlock(&stream->mutex);  
  11.     if (ret < 0)  
  12.         return ret;  
  13.     break;  
  14. }  
a.1 uvc视频流使能
[cpp] view plain copy
  1. int uvc_video_enable(struct uvc_streaming *stream, int enable)  
  2. {  
  3.     int ret;  
  4.     if (!enable) {  
  5.         uvc_uninit_video(stream, 1);//逆初始化视频  
  6.         usb_set_interface(stream->dev->udev, stream->intfnum, 0);  
  7.         uvc_queue_enable(&stream->queue, 0);//uvc禁用队列  
  8.         return 0;  
  9.     }  
  10.     ret = uvc_queue_enable(&stream->queue, 1);   //uvc使能队列  
  11.     if (ret < 0)  
  12.         return ret;  
  13.     /* Commit the streaming parameters. */  
  14.     ret = uvc_commit_video(stream, &stream->ctrl);   //uvc提交视频参数  
  15.     if (ret < 0)  
  16.         return ret;  
  17.     return uvc_init_video(stream, GFP_KERNEL);  //uvc初始化视频  
  18. }  
a.1.1 uvc使能队列
[cpp] view plain copy
  1. static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)  
  2. {  
  3.     unsigned int i;  
  4.     int ret = 0;  
  5.     mutex_lock(&queue->mutex);  
  6.     if (enable) {   //使能uvc队列  
  7.         if (uvc_queue_streaming(queue)) {   //判断队列标志是否为UVC_QUEUE_STREAMING  
  8.             ret = -EBUSY;  
  9.             goto done;  
  10.         }  
  11.         queue->sequence = 0;  
  12.         queue->flags |= UVC_QUEUE_STREAMING; //设置队列标志  
  13.         queue->buf_used = 0; //设置缓冲区使用标志  
  14.     }   
  15.     else {  
  16.         uvc_queue_cancel(queue, 0); //取消uvc队列  
  17.         INIT_LIST_HEAD(&queue->mainqueue);   //重新初始化uvc队列mainqueue队列头  
  18.         for (i = 0; i < queue->count; ++i)  
  19.             queue->buffer[i].state = UVC_BUF_STATE_IDLE; //设置缓冲区状态为闲置态  
  20.         queue->flags &= ~UVC_QUEUE_STREAMING;    //设置队列标志  
  21.     }  
  22. done:  
  23.     mutex_unlock(&queue->mutex);  
  24.     return ret;  
  25. }  
a.1.2 uvc提交视频参数
[cpp] view plain copy
  1. int uvc_commit_video(struct uvc_streaming *stream,struct uvc_streaming_control *probe)  
  2. {  
  3.     return uvc_set_video_ctrl(stream, probe, 0);    //uvc设置视频控制  
  4. }  
a.1.3 uvc初始化视频
[cpp] view plain copy
  1. static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)  
  2. {  
  3.     struct usb_interface *intf = stream->intf;  
  4.     struct usb_host_endpoint *ep;  
  5.     unsigned int i;  
  6.     int ret;  
  7.     stream->sequence = -1;  
  8.     stream->last_fid = -1;  
  9.     stream->bulk.header_size = 0;  
  10.     stream->bulk.skip_payload = 0;  
  11.     stream->bulk.payload_size = 0;  
  12.     if (intf->num_altsetting > 1) {   //同步方式  
  13.         struct usb_host_endpoint *best_ep = NULL;  
  14.         unsigned int best_psize = 3 * 1024;  
  15.         unsigned int bandwidth;  
  16.         unsigned int uninitialized_var(altsetting);  
  17.         int intfnum = stream->intfnum;  
  18.         /* Isochronous endpoint, select the alternate setting. */  
  19.         bandwidth = stream->ctrl.dwMaxPayloadTransferSize;  
  20.         if (bandwidth == 0) {  
  21.             uvc_trace(UVC_TRACE_VIDEO, "Device requested null bandwidth, defaulting to lowest.\n");  
  22.             bandwidth = 1;  
  23.         }   
  24.         else {  
  25.             uvc_trace(UVC_TRACE_VIDEO, "Device requested %u B/frame bandwidth.\n", bandwidth);  
  26.         }  
  27.         for (i = 0; i < intf->num_altsetting; ++i) {  
  28.             struct usb_host_interface *alts;  
  29.             unsigned int psize;  
  30.             alts = &intf->altsetting[i];  
  31.             ep = uvc_find_endpoint(alts,stream->header.bEndpointAddress);  
  32.             if (ep == NULL)  
  33.                 continue;  
  34.             /* Check if the bandwidth is high enough. */  
  35.             psize = le16_to_cpu(ep->desc.wMaxPacketSize);  
  36.             psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));  
  37.             if (psize >= bandwidth && psize <= best_psize) {  
  38.                 altsetting = i;  
  39.                 best_psize = psize;  
  40.                 best_ep = ep;  
  41.             }  
  42.         }  
  43.         if (best_ep == NULL) {  
  44.             uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting for requested bandwidth.\n");  
  45.             return -EIO;  
  46.         }  
  47.         uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u (%u B/frame bandwidth).\n", altsetting, best_psize);  
  48.         ret = usb_set_interface(stream->dev->udev, intfnum, altsetting);  
  49.         if (ret < 0)  
  50.             return ret;  
  51.         ret = uvc_init_video_isoc(stream, best_ep, gfp_flags);  //uvc初始化视频(同步方法)  
  52.     }   
  53.     else {  //Bulk方式  
  54.         /* Bulk endpoint, proceed to URB initialization. */  
  55.         ep = uvc_find_endpoint(&intf->altsetting[0],stream->header.bEndpointAddress);  
  56.         if (ep == NULL)  
  57.             return -EIO;  
  58.         ret = uvc_init_video_bulk(stream, ep, gfp_flags);   //uvc初始化视频(bulk方法)  
  59.     }  
  60.     if (ret < 0)  
  61.         return ret;  
  62.     /* Submit the URBs. */  
  63.     for (i = 0; i < UVC_URBS; ++i) {  
  64.         ret = usb_submit_urb(stream->urb[i], gfp_flags); //提交urb  
  65.         if (ret < 0) {  
  66.             uvc_printk(KERN_ERR, "Failed to submit URB %u (%d).\n", i, ret);  
  67.             uvc_uninit_video(stream, 1);  
  68.             return ret;  
  69.         }  
  70.     }  
  71.   
  72.     return 0;  
  73. }  
a.1.3.1 同步方式
[cpp] view plain copy
  1. static int uvc_init_video_isoc(struct uvc_streaming *stream,struct usb_host_endpoint *ep, gfp_t gfp_flags)  
  2. {  
  3.     struct urb *urb;  
  4.     unsigned int npackets, i, j;  
  5.     u16 psize;  
  6.     u32 size;  
  7.     psize = le16_to_cpu(ep->desc.wMaxPacketSize);  
  8.     psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));  
  9.     size = stream->ctrl.dwMaxVideoFrameSize;  
  10.     npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags);   //分配urb缓冲区  
  11.     if (npackets == 0)  
  12.         return -ENOMEM;  
  13.     size = npackets * psize;  
  14.     for (i = 0; i < UVC_URBS; ++i) {  
  15.         urb = usb_alloc_urb(npackets, gfp_flags);   //分配urb  
  16.         if (urb == NULL) {  
  17.             uvc_uninit_video(stream, 1);  
  18.             return -ENOMEM;  
  19.         }  
  20.         urb->dev = stream->dev->udev;  //设置urb  
  21.         urb->context = stream;  
  22.         urb->pipe = usb_rcvisocpipe(stream->dev->udev,ep->desc.bEndpointAddress);  
  23.         urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;  
  24.         urb->interval = ep->desc.bInterval;  
  25.         urb->transfer_buffer = stream->urb_buffer[i];  
  26.         urb->transfer_dma = stream->urb_dma[i];  
  27.         urb->complete = uvc_video_complete;  
  28.         urb->number_of_packets = npackets;  
  29.         urb->transfer_buffer_length = size;  
  30.         for (j = 0; j < npackets; ++j) {  
  31.             urb->iso_frame_desc[j].offset = j * psize;  
  32.             urb->iso_frame_desc[j].length = psize;  
  33.         }  
  34.         stream->urb[i] = urb;  
  35.     }  
  36.     return 0;  
  37. }  
a.1.3.2 Bluk方式
[cpp] view plain copy
  1. static int uvc_init_video_bulk(struct uvc_streaming *stream,struct usb_host_endpoint *ep, gfp_t gfp_flags)  
  2. {  
  3.     struct urb *urb;  
  4.     unsigned int npackets, pipe, i;  
  5.     u16 psize;  
  6.     u32 size;  
  7.     psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff;  
  8.     size = stream->ctrl.dwMaxPayloadTransferSize;  
  9.     stream->bulk.max_payload_size = size;  
  10.     npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags);   //分配urb缓冲区  
  11.     if (npackets == 0)  
  12.         return -ENOMEM;  
  13.     size = npackets * psize;  
  14.     if (usb_endpoint_dir_in(&ep->desc))  
  15.         pipe = usb_rcvbulkpipe(stream->dev->udev,ep->desc.bEndpointAddress);  
  16.     else  
  17.         pipe = usb_sndbulkpipe(stream->dev->udev,ep->desc.bEndpointAddress);  
  18.   
  19.     if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)  
  20.         size = 0;  
  21.     for (i = 0; i < UVC_URBS; ++i) {  
  22.         urb = usb_alloc_urb(0, gfp_flags);  //分配urb  
  23.         if (urb == NULL) {  
  24.             uvc_uninit_video(stream, 1);  
  25.             return -ENOMEM;  
  26.         }  
  27.         usb_fill_bulk_urb(urb, stream->dev->udev, pipe,stream->urb_buffer[i], size, uvc_video_complete,stream);    //设置urb  
  28.         urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;  
  29.         urb->transfer_dma = stream->urb_dma[i];  
  30.         stream->urb[i] = urb;  
  31.     }  
  32.     return 0;  
  33. }  
a.1.3.1 同步方式和a.1.3.2 Bluk方式 两种方式初始化uvc视频主要是分配设置urb,然后在uvc_init_video函数中又通过usb_submit_urb提交了urb,两种方法的urb回调函数都是uvc_video_completea.2 urb回调函数uvc_video_complete
[cpp] view plain copy
  1. static void uvc_video_complete(struct urb *urb)  
  2. {  
  3.     struct uvc_streaming *stream = urb->context;  
  4.     struct uvc_video_queue *queue = &stream->queue;  
  5.     struct uvc_buffer *buf = NULL;  
  6.     unsigned long flags;  
  7.     int ret;  
  8.     switch (urb->status) {  
  9.     case 0:  
  10.         break;  
  11.     default:  
  12.         uvc_printk(KERN_WARNING, "Non-zero status (%d) in video completion handler.\n", urb->status);  
  13.     case -ENOENT:       /* usb_kill_urb() called. */  
  14.         if (stream->frozen)  
  15.             return;  
  16.     case -ECONNRESET:   /* usb_unlink_urb() called. */  
  17.     case -ESHUTDOWN:    /* The endpoint is being disabled. */  
  18.         uvc_queue_cancel(queue, urb->status == -ESHUTDOWN);  
  19.         return;  
  20.     }  
  21.     spin_lock_irqsave(&queue->irqlock, flags);  
  22.     if (!list_empty(&queue->irqqueue))  
  23.         buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,queue);  
  24.     spin_unlock_irqrestore(&queue->irqlock, flags);  
  25.     stream->decode(urb, stream, buf);    //调用uvc视频流的decode方法  
  26.     if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {   //再次提交urb  
  27.         uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n",ret);  
  28.     }  
  29. }  

 

对于同步和bilk方式的decode方法分别是  
 stream->decode = uvc_video_decode_isoc;
 stream->decode = uvc_video_encode_bulk;  
这个在前面uvc_video_init函数中设置了
ok后面就开始解码了


阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 食品商务网手机版 批发冷冻食品 食品烘干机什么牌子好 冷冻食品厂家 海鲜食品批发 食品批发代理 什么是食品原料 干货食品批发 食品注册商标需要什么条件 代办qs食品生产许可证 食品中亚硝酸盐的测定 冷冻食品公司 食品营销策划 5888 副食品代理 万国码头 零食批发市场进货货源 时尚购物网站 网上办手机卡 淘常州网上超市 酒网购 优品购 皇冠蛋糕网上订蛋糕 广西乐思购 聪明购 英国购物网站 广州友谊商店网购 水果交易平台 宜芝多蛋糕网上预订 持家有道网上超市 网上卖水果 网上卖菜 英德net网上超市 网上买手机号 什么食物 农副食品批发 吃什么食物降血压 迪士尼可自带食品 食困症 食困 不伦食堂