Home | History | Annotate | Download | only in win
      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 
     22 bool CompareHeight(const ResolutionDiff& item1, const ResolutionDiff& item2) {
     23   return abs(item1.diff_height) < abs(item2.diff_height);
     24 }
     25 
     26 bool CompareWidth(const ResolutionDiff& item1, const ResolutionDiff& item2) {
     27   return abs(item1.diff_width) < abs(item2.diff_width);
     28 }
     29 
     30 bool CompareFrameRate(const ResolutionDiff& item1,
     31                       const ResolutionDiff& item2) {
     32   return abs(item1.diff_frame_rate) < abs(item2.diff_frame_rate);
     33 }
     34 
     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 
     42 CapabilityList::CapabilityList() {
     43   DetachFromThread();
     44 }
     45 
     46 CapabilityList::~CapabilityList() {}
     47 
     48 // Appends an entry to the list.
     49 void CapabilityList::Add(const VideoCaptureCapabilityWin& capability) {
     50   DCHECK(CalledOnValidThread());
     51   capabilities_.push_back(capability);
     52 }
     53 
     54 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