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->color < item2.capability->color;
     37 }
     38 
     39 }  // namespace.
     40 
     41 CapabilityList::CapabilityList() {
     42   DetachFromThread();
     43 }
     44 
     45 CapabilityList::~CapabilityList() {}
     46 
     47 // Appends an entry to the list.
     48 void CapabilityList::Add(const VideoCaptureCapabilityWin& capability) {
     49   DCHECK(CalledOnValidThread());
     50   capabilities_.push_back(capability);
     51 }
     52 
     53 const VideoCaptureCapabilityWin& CapabilityList::GetBestMatchedCapability(
     54     int requested_width,
     55     int requested_height,
     56     int requested_frame_rate) const {
     57   DCHECK(CalledOnValidThread());
     58   DCHECK(!capabilities_.empty());
     59 
     60   std::list<ResolutionDiff> diff_list;
     61 
     62   // Loop through the candidates to create a list of differentials between the
     63   // requested resolution and the camera capability.
     64   for (Capabilities::const_iterator it = capabilities_.begin();
     65        it != capabilities_.end(); ++it) {
     66     ResolutionDiff diff;
     67     diff.capability = &(*it);
     68     diff.diff_width = it->width - requested_width;
     69     diff.diff_height = it->height - requested_height;
     70     // The 1000 allows using integer arithmetic for f.i. 29.971 fps.
     71     diff.diff_frame_rate =
     72         1000 * ((static_cast<float>(it->frame_rate_numerator) /
     73                  it->frame_rate_denominator) -
     74                 requested_frame_rate);
     75     diff_list.push_back(diff);
     76   }
     77 
     78   // Sort the best height candidates.
     79   diff_list.sort(&CompareHeight);
     80   int best_diff = diff_list.front().diff_height;
     81   for (std::list<ResolutionDiff>::iterator it = diff_list.begin();
     82        it != diff_list.end(); ++it) {
     83     if (it->diff_height != best_diff) {
     84       // Remove all candidates but the best.
     85       diff_list.erase(it, diff_list.end());
     86       break;
     87     }
     88   }
     89 
     90   // Sort the best width candidates.
     91   diff_list.sort(&CompareWidth);
     92   best_diff = diff_list.front().diff_width;
     93   for (std::list<ResolutionDiff>::iterator it = diff_list.begin();
     94        it != diff_list.end(); ++it) {
     95     if (it->diff_width != best_diff) {
     96       // Remove all candidates but the best.
     97       diff_list.erase(it, diff_list.end());
     98       break;
     99     }
    100   }
    101 
    102   // Sort the best frame rate candidates.
    103   diff_list.sort(&CompareFrameRate);
    104   best_diff = diff_list.front().diff_frame_rate;
    105   for (std::list<ResolutionDiff>::iterator it = diff_list.begin();
    106        it != diff_list.end(); ++it) {
    107     if (it->diff_frame_rate != best_diff) {
    108       diff_list.erase(it, diff_list.end());
    109       break;
    110     }
    111   }
    112 
    113   // Decide the best color format.
    114   diff_list.sort(&CompareColor);
    115   return *diff_list.front().capability;
    116 }
    117 
    118 }  // namespace media
    119