• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "media/video/capture/win/capability_list_win.h"
6 
7 #include <algorithm>
8 
9 #include "base/logging.h"
10 
11 namespace media {
12 namespace {
13 
14 // Help structure used for comparing video capture capabilities.
15 struct ResolutionDiff {
16   const VideoCaptureCapabilityWin* capability;
17   int diff_height;
18   int diff_width;
19   int diff_frame_rate;
20 };
21 
CompareHeight(const ResolutionDiff & item1,const ResolutionDiff & item2)22 bool CompareHeight(const ResolutionDiff& item1, const ResolutionDiff& item2) {
23   return abs(item1.diff_height) < abs(item2.diff_height);
24 }
25 
CompareWidth(const ResolutionDiff & item1,const ResolutionDiff & item2)26 bool CompareWidth(const ResolutionDiff& item1, const ResolutionDiff& item2) {
27   return abs(item1.diff_width) < abs(item2.diff_width);
28 }
29 
CompareFrameRate(const ResolutionDiff & item1,const ResolutionDiff & item2)30 bool CompareFrameRate(const ResolutionDiff& item1,
31                       const ResolutionDiff& item2) {
32   return abs(item1.diff_frame_rate) < abs(item2.diff_frame_rate);
33 }
34 
CompareColor(const ResolutionDiff & item1,const ResolutionDiff & item2)35 bool CompareColor(const ResolutionDiff& item1, const ResolutionDiff& item2) {
36   return item1.capability->supported_format.pixel_format <
37          item2.capability->supported_format.pixel_format;
38 }
39 
40 }  // namespace.
41 
CapabilityList()42 CapabilityList::CapabilityList() {
43   DetachFromThread();
44 }
45 
~CapabilityList()46 CapabilityList::~CapabilityList() {}
47 
48 // Appends an entry to the list.
Add(const VideoCaptureCapabilityWin & capability)49 void CapabilityList::Add(const VideoCaptureCapabilityWin& capability) {
50   DCHECK(CalledOnValidThread());
51   capabilities_.push_back(capability);
52 }
53 
GetBestMatchedFormat(int requested_width,int requested_height,float requested_frame_rate) const54 const VideoCaptureCapabilityWin& CapabilityList::GetBestMatchedFormat(
55     int requested_width,
56     int requested_height,
57     float requested_frame_rate) const {
58   DCHECK(CalledOnValidThread());
59   DCHECK(!capabilities_.empty());
60 
61   std::list<ResolutionDiff> diff_list;
62 
63   // Loop through the candidates to create a list of differentials between the
64   // requested resolution and the camera capability.
65   for (Capabilities::const_iterator it = capabilities_.begin();
66        it != capabilities_.end(); ++it) {
67     ResolutionDiff diff;
68     diff.capability = &(*it);
69     diff.diff_width = it->supported_format.frame_size.width() - requested_width;
70     diff.diff_height =
71         it->supported_format.frame_size.height() - requested_height;
72     // The 1000 allows using integer arithmetic for f.i. 29.971 fps.
73     diff.diff_frame_rate =
74         1000 * ((static_cast<float>(it->frame_rate_numerator) /
75                  it->frame_rate_denominator) -
76                 requested_frame_rate);
77     diff_list.push_back(diff);
78   }
79 
80   // Sort the best height candidates.
81   diff_list.sort(&CompareHeight);
82   int best_diff = diff_list.front().diff_height;
83   for (std::list<ResolutionDiff>::iterator it = diff_list.begin();
84        it != diff_list.end(); ++it) {
85     if (it->diff_height != best_diff) {
86       // Remove all candidates but the best.
87       diff_list.erase(it, diff_list.end());
88       break;
89     }
90   }
91 
92   // Sort the best width candidates.
93   diff_list.sort(&CompareWidth);
94   best_diff = diff_list.front().diff_width;
95   for (std::list<ResolutionDiff>::iterator it = diff_list.begin();
96        it != diff_list.end(); ++it) {
97     if (it->diff_width != best_diff) {
98       // Remove all candidates but the best.
99       diff_list.erase(it, diff_list.end());
100       break;
101     }
102   }
103 
104   // Sort the best frame rate candidates.
105   diff_list.sort(&CompareFrameRate);
106   best_diff = diff_list.front().diff_frame_rate;
107   for (std::list<ResolutionDiff>::iterator it = diff_list.begin();
108        it != diff_list.end(); ++it) {
109     if (it->diff_frame_rate != best_diff) {
110       diff_list.erase(it, diff_list.end());
111       break;
112     }
113   }
114 
115   // Decide the best color format.
116   diff_list.sort(&CompareColor);
117   return *diff_list.front().capability;
118 }
119 
120 }  // namespace media
121