summaryrefslogtreecommitdiff
path: root/chromium/media/video/capture/win/capability_list_win.cc
blob: bfa58edcc4bec89b88451e6359e59521cbe8525e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/video/capture/win/capability_list_win.h"

#include <algorithm>

#include "base/logging.h"

namespace media {
namespace {

// Help structure used for comparing video capture capabilities.
struct ResolutionDiff {
  const VideoCaptureCapabilityWin* capability;
  int diff_height;
  int diff_width;
  int diff_frame_rate;
};

bool CompareHeight(const ResolutionDiff& item1, const ResolutionDiff& item2) {
  return abs(item1.diff_height) < abs(item2.diff_height);
}

bool CompareWidth(const ResolutionDiff& item1, const ResolutionDiff& item2) {
  return abs(item1.diff_width) < abs(item2.diff_width);
}

bool CompareFrameRate(const ResolutionDiff& item1,
                      const ResolutionDiff& item2) {
  return abs(item1.diff_frame_rate) < abs(item2.diff_frame_rate);
}

bool CompareColor(const ResolutionDiff& item1, const ResolutionDiff& item2) {
  return item1.capability->supported_format.pixel_format <
         item2.capability->supported_format.pixel_format;
}

}  // namespace.

CapabilityList::CapabilityList() {
  DetachFromThread();
}

CapabilityList::~CapabilityList() {}

// Appends an entry to the list.
void CapabilityList::Add(const VideoCaptureCapabilityWin& capability) {
  DCHECK(CalledOnValidThread());
  capabilities_.push_back(capability);
}

const VideoCaptureCapabilityWin& CapabilityList::GetBestMatchedFormat(
    int requested_width,
    int requested_height,
    int requested_frame_rate) const {
  DCHECK(CalledOnValidThread());
  DCHECK(!capabilities_.empty());

  std::list<ResolutionDiff> diff_list;

  // Loop through the candidates to create a list of differentials between the
  // requested resolution and the camera capability.
  for (Capabilities::const_iterator it = capabilities_.begin();
       it != capabilities_.end(); ++it) {
    ResolutionDiff diff;
    diff.capability = &(*it);
    diff.diff_width = it->supported_format.frame_size.width() - requested_width;
    diff.diff_height =
        it->supported_format.frame_size.height() - requested_height;
    // The 1000 allows using integer arithmetic for f.i. 29.971 fps.
    diff.diff_frame_rate =
        1000 * ((static_cast<float>(it->frame_rate_numerator) /
                 it->frame_rate_denominator) -
                requested_frame_rate);
    diff_list.push_back(diff);
  }

  // Sort the best height candidates.
  diff_list.sort(&CompareHeight);
  int best_diff = diff_list.front().diff_height;
  for (std::list<ResolutionDiff>::iterator it = diff_list.begin();
       it != diff_list.end(); ++it) {
    if (it->diff_height != best_diff) {
      // Remove all candidates but the best.
      diff_list.erase(it, diff_list.end());
      break;
    }
  }

  // Sort the best width candidates.
  diff_list.sort(&CompareWidth);
  best_diff = diff_list.front().diff_width;
  for (std::list<ResolutionDiff>::iterator it = diff_list.begin();
       it != diff_list.end(); ++it) {
    if (it->diff_width != best_diff) {
      // Remove all candidates but the best.
      diff_list.erase(it, diff_list.end());
      break;
    }
  }

  // Sort the best frame rate candidates.
  diff_list.sort(&CompareFrameRate);
  best_diff = diff_list.front().diff_frame_rate;
  for (std::list<ResolutionDiff>::iterator it = diff_list.begin();
       it != diff_list.end(); ++it) {
    if (it->diff_frame_rate != best_diff) {
      diff_list.erase(it, diff_list.end());
      break;
    }
  }

  // Decide the best color format.
  diff_list.sort(&CompareColor);
  return *diff_list.front().capability;
}

}  // namespace media