// File: p-ranav[P]video_device_discovery/src/video_device_info.cpp
// Function: find_video_devices(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>> const&)
std::vector<VideoDeviceInfo>
find_video_devices(const std::vector<std::string>& filter_pixel_formats) {
  std::vector<VideoDeviceInfo> video_devices;
  
  for (auto& device: get_video_device_files()) {

    VideoDeviceInfo new_device;
    new_device.file = device;

    // Save sensor_id
    std::string split_on = "/dev/video";
    std::stringstream os(device.string().substr(split_on.length()));
    os >> new_device.sensor_id;

    int fd;
    fd = open(device.string().c_str(), O_RDWR);
    if (fd == -1) {
      // couldn't find capture device
      perror("Failed to open video device");
      return {};
    }

    struct v4l2_capability capability;
    if(ioctl(fd, VIDIOC_QUERYCAP, &capability) < 0){
      perror("Failed to get device capabilities, VIDIOC_QUERYCAP");
      return {};
    }

    new_device.driver = std::string{reinterpret_cast<const char*>(capability.driver)};
    new_device.bus_info = std::string{reinterpret_cast<const char*>(capability.bus_info)};
    new_device.card = std::string{reinterpret_cast<const char*>(capability.card)};
    
    // Get supported resolutions
    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    struct v4l2_fmtdesc fmt;
    struct v4l2_frmsizeenum frmsize;

    fmt.index = 0;
    fmt.type = type;
    while (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) >= 0) {
      frmsize.pixel_format = fmt.pixelformat;
      new_device.pixel_formats.push_back(pixfmt_to_string(fmt.pixelformat));
      frmsize.index = 0;
      while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0) {
	if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
	  new_device.resolutions.push_back(std::make_pair(frmsize.discrete.width, frmsize.discrete.height));
	} else if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
	  new_device.resolutions.push_back(std::make_pair(frmsize.stepwise.max_width, frmsize.stepwise.max_height));
	}
	frmsize.index++;
      }
      fmt.index++;
    }
    
    if (filter_pixel_formats.empty()) {
      // no filter
      video_devices.push_back(new_device);
    } else {
      // filter by pixel format
      for (auto& pxlfmt: filter_pixel_formats) {
	for (auto& supported_formats: new_device.pixel_formats) {
	  if (supported_formats.find(pxlfmt) != std::string::npos) {
	    video_devices.push_back(new_device);
	    break;
	  }
	}
      }
    }
  }

  // sort by file, e.g., /dev/video0, /dev/video1, /dev/video2, ...
  std::sort(video_devices.begin(), video_devices.end(), video_device_info_less_than());

  return video_devices;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x5f0, %rsp            # imm = 0x5F0
movq %rdi, -0x570(%rbp)
movq %rdi, %rax
movq %rax, -0x568(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x28(%rbp), %rdi
callq 0xa420
leaq -0x48(%rbp), %rdi
callq 0x14ba0
jmp 0x9b78
leaq -0x48(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rdi
callq 0xa440
movq %rax, -0x60(%rbp)
movq -0x30(%rbp), %rdi
callq 0xa470
movq %rax, -0x68(%rbp)
leaq -0x60(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0xa4a0
testb $0x1, %al
jne 0x9bc8
movl $0x2, -0x6c(%rbp)
jmp 0xa389
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0xa40b
leaq -0x60(%rbp), %rdi
callq 0xa4e0
movq %rax, -0x78(%rbp)
leaq -0x150(%rbp), %rdi
callq 0xa500
movq -0x78(%rbp), %rsi
leaq -0x148(%rbp), %rdi
callq 0xa570
jmp 0x9bf3
leaq -0x171(%rbp), %rdi
movq %rdi, -0x578(%rbp)
callq 0x57a0
movq -0x578(%rbp), %rdx
leaq 0x1f480(%rip), %rsi     # 0x29094
leaq -0x170(%rbp), %rdi
callq 0x81c0
jmp 0x9c22
leaq -0x171(%rbp), %rdi
callq 0x54e0
movq -0x78(%rbp), %rsi
leaq -0x340(%rbp), %rdi
callq 0x7cd0
jmp 0x9c40
leaq -0x170(%rbp), %rdi
callq 0x5690
movq %rax, %rdx
leaq -0x320(%rbp), %rdi
leaq -0x340(%rbp), %rsi
movq $-0x1, %rcx
callq 0x54b0
jmp 0x9c6b
movl $0x10, %edi
movl $0x8, %esi
callq 0xa5c0
movl %eax, -0x57c(%rbp)
jmp 0x9c82
movl -0x57c(%rbp), %edx
leaq -0x300(%rbp), %rdi
leaq -0x320(%rbp), %rsi
callq 0x5710
jmp 0x9c9d
leaq -0x320(%rbp), %rdi
callq 0x52f0
leaq -0x340(%rbp), %rdi
callq 0x52f0
leaq -0x300(%rbp), %rdi
leaq -0x150(%rbp), %rsi
callq 0x5640
jmp 0x9cca
movq -0x78(%rbp), %rsi
leaq -0x368(%rbp), %rdi
callq 0x7cd0
jmp 0x9cdc
leaq -0x368(%rbp), %rdi
callq 0x51b0
movq %rax, %rdi
xorl %eax, %eax
movl $0x2, %esi
callq 0x5380
movl %eax, -0x580(%rbp)
jmp 0x9cff
movl -0x580(%rbp), %eax
movl %eax, -0x344(%rbp)
leaq -0x368(%rbp), %rdi
callq 0x52f0
cmpl $-0x1, -0x344(%rbp)
jne 0x9e01
leaq 0x1f374(%rip), %rdi     # 0x2909f
callq 0x53e0
jmp 0x9d32
movq -0x570(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x5270
movq -0x570(%rbp), %rdi
callq 0xa420
movl $0x1, -0x6c(%rbp)
jmp 0xa31a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0xa36f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x171(%rbp), %rdi
callq 0x54e0
jmp 0xa36f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0xa363
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x9dc2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x320(%rbp), %rdi
callq 0x52f0
leaq -0x340(%rbp), %rdi
callq 0x52f0
jmp 0xa363
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0xa357
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x368(%rbp), %rdi
callq 0x52f0
jmp 0xa357
movl -0x344(%rbp), %edi
movl $0x80685600, %esi       # imm = 0x80685600
leaq -0x3d0(%rbp), %rdx
movb $0x0, %al
callq 0x5610
cmpl $0x0, %eax
jge 0x9e58
leaq 0x1f295(%rip), %rdi     # 0x290bb
callq 0x53e0
jmp 0x9e2d
movq -0x570(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x5270
movq -0x570(%rbp), %rdi
callq 0xa420
movl $0x1, -0x6c(%rbp)
jmp 0xa31a
leaq -0x3f1(%rbp), %rdi
movq %rdi, -0x588(%rbp)
callq 0x57a0
movq -0x588(%rbp), %rdx
leaq -0x3f0(%rbp), %rdi
leaq -0x3d0(%rbp), %rsi
callq 0x81c0
jmp 0x9e87
leaq -0xd8(%rbp), %rdi
leaq -0x3f0(%rbp), %rsi
movq %rsi, -0x5a0(%rbp)
callq 0x5540
movq -0x5a0(%rbp), %rdi
callq 0x52f0
leaq -0x3f1(%rbp), %rdi
callq 0x54e0
leaq -0x3a0(%rbp), %rax
movq %rax, -0x598(%rbp)
leaq -0x419(%rbp), %rdi
movq %rdi, -0x590(%rbp)
callq 0x57a0
movq -0x598(%rbp), %rsi
movq -0x590(%rbp), %rdx
leaq -0x418(%rbp), %rdi
callq 0x81c0
jmp 0x9ef6
leaq -0x98(%rbp), %rdi
leaq -0x418(%rbp), %rsi
movq %rsi, -0x5b8(%rbp)
callq 0x5540
movq -0x5b8(%rbp), %rdi
callq 0x52f0
leaq -0x419(%rbp), %rdi
callq 0x54e0
leaq -0x3c0(%rbp), %rax
movq %rax, -0x5b0(%rbp)
leaq -0x441(%rbp), %rdi
movq %rdi, -0x5a8(%rbp)
callq 0x57a0
movq -0x5b0(%rbp), %rsi
movq -0x5a8(%rbp), %rdx
leaq -0x440(%rbp), %rdi
callq 0x81c0
jmp 0x9f65
leaq -0x150(%rbp), %rdi
addq $0x98, %rdi
leaq -0x440(%rbp), %rsi
callq 0x5540
leaq -0x440(%rbp), %rdi
callq 0x52f0
leaq -0x441(%rbp), %rdi
callq 0x54e0
movl $0x1, -0x448(%rbp)
movl $0x0, -0x488(%rbp)
movl -0x448(%rbp), %eax
movl %eax, -0x484(%rbp)
movl -0x344(%rbp), %edi
movl $0xc0405602, %esi       # imm = 0xC0405602
leaq -0x488(%rbp), %rdx
movb $0x0, %al
callq 0x5610
cmpl $0x0, %eax
jl 0xa1d3
movl -0x45c(%rbp), %eax
movl %eax, -0x4b0(%rbp)
leaq -0x108(%rbp), %rax
movq %rax, -0x5c0(%rbp)
movl -0x45c(%rbp), %esi
leaq -0x4d8(%rbp), %rdi
callq 0x10560
jmp 0xa007
movq -0x5c0(%rbp), %rdi
leaq -0x4d8(%rbp), %rsi
callq 0xa5e0
jmp 0xa01c
leaq -0x4d8(%rbp), %rdi
callq 0x52f0
movl $0x0, -0x4b4(%rbp)
movl -0x344(%rbp), %edi
movl $0xc02c564a, %esi       # imm = 0xC02C564A
leaq -0x4b4(%rbp), %rdx
movb $0x0, %al
callq 0x5610
cmpl $0x0, %eax
jl 0xa1bf
cmpl $0x1, -0x4ac(%rbp)
jne 0xa13c
leaq -0xf0(%rbp), %rax
movq %rax, -0x5d0(%rbp)
leaq -0x4a8(%rbp), %rdi
leaq -0x4a4(%rbp), %rsi
callq 0xa640
movq %rax, -0x5c8(%rbp)
jmp 0xa08b
movq -0x5c8(%rbp), %rax
movq %rax, -0x4f0(%rbp)
leaq -0x4e8(%rbp), %rdi
leaq -0x4f0(%rbp), %rsi
callq 0xa670
jmp 0xa0ae
movq -0x5d0(%rbp), %rdi
leaq -0x4e8(%rbp), %rsi
callq 0xa610
jmp 0xa0c3
jmp 0xa1ab
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x3f1(%rbp), %rdi
callq 0x54e0
jmp 0xa357
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x419(%rbp), %rdi
callq 0x54e0
jmp 0xa357
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x441(%rbp), %rdi
callq 0x54e0
jmp 0xa357
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x4d8(%rbp), %rdi
callq 0x52f0
jmp 0xa357
cmpl $0x3, -0x4ac(%rbp)
jne 0xa1a9
leaq -0xf0(%rbp), %rax
movq %rax, -0x5e0(%rbp)
leaq -0x4a4(%rbp), %rdi
leaq -0x498(%rbp), %rsi
callq 0xa640
movq %rax, -0x5d8(%rbp)
jmp 0xa16f
movq -0x5d8(%rbp), %rax
movq %rax, -0x508(%rbp)
leaq -0x500(%rbp), %rdi
leaq -0x508(%rbp), %rsi
callq 0xa670
jmp 0xa192
movq -0x5e0(%rbp), %rdi
leaq -0x500(%rbp), %rsi
callq 0xa610
jmp 0xa1a7
jmp 0xa1a9
jmp 0xa1ab
movl -0x4b4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4b4(%rbp)
jmp 0xa032
movl -0x488(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x488(%rbp)
jmp 0x9fb7
movq -0x10(%rbp), %rdi
callq 0xa6a0
testb $0x1, %al
jne 0xa1e2
jmp 0xa1f9
leaq -0x28(%rbp), %rdi
leaq -0x150(%rbp), %rsi
callq 0xa6e0
jmp 0xa1f4
jmp 0xa313
movq -0x10(%rbp), %rax
movq %rax, -0x510(%rbp)
movq -0x510(%rbp), %rdi
callq 0xa750
movq %rax, -0x518(%rbp)
movq -0x510(%rbp), %rdi
callq 0xa780
movq %rax, -0x520(%rbp)
leaq -0x518(%rbp), %rdi
leaq -0x520(%rbp), %rsi
callq 0xa7b0
testb $0x1, %al
jne 0xa246
jmp 0xa311
leaq -0x518(%rbp), %rdi
callq 0xa7f0
movq %rax, -0x528(%rbp)
leaq -0x150(%rbp), %rax
addq $0x48, %rax
movq %rax, -0x530(%rbp)
movq -0x530(%rbp), %rdi
callq 0x7d50
movq %rax, -0x538(%rbp)
movq -0x530(%rbp), %rdi
callq 0x7d80
movq %rax, -0x540(%rbp)
leaq -0x538(%rbp), %rdi
leaq -0x540(%rbp), %rsi
callq 0x7db0
testb $0x1, %al
jne 0xa2aa
jmp 0xa2fe
leaq -0x538(%rbp), %rdi
callq 0x7df0
movq %rax, -0x548(%rbp)
movq -0x548(%rbp), %rdi
movq -0x528(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x5880
cmpq $-0x1, %rax
je 0xa2ee
leaq -0x28(%rbp), %rdi
leaq -0x150(%rbp), %rsi
callq 0xa6e0
jmp 0xa2ec
jmp 0xa2fe
jmp 0xa2f0
leaq -0x538(%rbp), %rdi
callq 0x7e10
jmp 0xa291
jmp 0xa300
leaq -0x518(%rbp), %rdi
callq 0xa810
jmp 0xa22a
jmp 0xa313
movl $0x0, -0x6c(%rbp)
leaq -0x300(%rbp), %rdi
callq 0x5390
leaq -0x170(%rbp), %rdi
callq 0x52f0
leaq -0x150(%rbp), %rdi
callq 0x9740
movl -0x6c(%rbp), %eax
testl %eax, %eax
jne 0xa389
jmp 0xa347
jmp 0xa349
leaq -0x60(%rbp), %rdi
callq 0xa830
jmp 0x9b9a
leaq -0x300(%rbp), %rdi
callq 0x5390
leaq -0x170(%rbp), %rdi
callq 0x52f0
leaq -0x150(%rbp), %rdi
callq 0x9740
leaq -0x48(%rbp), %rdi
callq 0xa850
jmp 0xa40b
leaq -0x48(%rbp), %rdi
callq 0xa850
movl -0x6c(%rbp), %eax
subl $0x2, %eax
jne 0xa3f2
jmp 0xa39c
leaq -0x28(%rbp), %rdi
movq %rdi, -0x5e8(%rbp)
callq 0x7c10
movq -0x5e8(%rbp), %rdi
movq %rax, -0x550(%rbp)
callq 0x7c40
movq %rax, -0x558(%rbp)
movq -0x550(%rbp), %rdi
movq -0x558(%rbp), %rsi
callq 0xa8b0
jmp 0xa3db
movq -0x570(%rbp), %rdi
leaq -0x28(%rbp), %rsi
callq 0xa8f0
movl $0x1, -0x6c(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x7f30
movq -0x568(%rbp), %rax
addq $0x5f0, %rsp            # imm = 0x5F0
popq %rbp
retq
leaq -0x28(%rbp), %rdi
callq 0x7f30
movq -0x50(%rbp), %rdi
callq 0x5790
nopl (%rax)