core/vidl/vidl_dshow_istream_params.cxx
Go to the documentation of this file.
00001 // This is core/vidl/vidl_dshow_istream_params.cxx
00002 //=========================================================================
00003 #include "vidl_dshow_istream_params.h"
00004 //:
00005 // \file
00006 // \brief  DirectShow input stream parameter block.
00007 //
00008 // See vidl_dshow_istream_params.h for details.
00009 //
00010 //=========================================================================
00011 
00012 #include <vidl/vidl_dshow.h>
00013 
00014 #include <vcl_iostream.h>
00015 #include <vcl_iomanip.h>
00016 #include <vcl_sstream.h>
00017 #include <vcl_utility.h>
00018 #if 0
00019 #include <vcl_cassert.h>
00020 #endif
00021 
00022 //-------------------------------------------------------------------------
00023 // Private helpers.
00024 //-------------------------------------------------------------------------
00025 namespace
00026 {
00027   // widths for formatting help (iomanip setw)
00028   const int w1 = 25;
00029   const int w2 = 8;
00030 
00031   vcl_map<vcl_string,vpa_property_wrap> vpa_properties(void)
00032   {
00033     typedef vcl_pair<vcl_string,vpa_property_wrap> pair;
00034 
00035     vcl_map<vcl_string,vpa_property_wrap> properties;
00036 
00037     // IAMVideoProcAmp interface
00038     properties.insert(pair("brightness",             vpa_property_wrap(VideoProcAmp_Brightness)           ));
00039     properties.insert(pair("contrast",               vpa_property_wrap(VideoProcAmp_Contrast)             ));
00040     properties.insert(pair("hue",                    vpa_property_wrap(VideoProcAmp_Hue)                  ));
00041     properties.insert(pair("saturation",             vpa_property_wrap(VideoProcAmp_Saturation)           ));
00042     properties.insert(pair("sharpness",              vpa_property_wrap(VideoProcAmp_Sharpness)            ));
00043     properties.insert(pair("gamma",                  vpa_property_wrap(VideoProcAmp_Gamma)                ));
00044     properties.insert(pair("color_enable",           vpa_property_wrap(VideoProcAmp_ColorEnable)          ));
00045     properties.insert(pair("white_balance",          vpa_property_wrap(VideoProcAmp_WhiteBalance)         ));
00046     properties.insert(pair("backlight_compensation", vpa_property_wrap(VideoProcAmp_BacklightCompensation)));
00047     properties.insert(pair("gain",                   vpa_property_wrap(VideoProcAmp_Gain)                 ));
00048 
00049     return properties;
00050   }
00051 
00052   void print_help(const CComPtr<IAMVideoProcAmp>& am_video_proc_amp,
00053                   const vcl_string& prop_tag)
00054   {
00055     vcl_map<vcl_string,vpa_property_wrap> prop = vpa_properties();
00056     long val, min, max, step, def, flag;
00057 
00058     vcl_cout << vcl_setw(w1) << prop_tag;
00059     if (SUCCEEDED(am_video_proc_amp->GetRange(prop[prop_tag].key,
00060                                               &min,
00061                                               &max,
00062                                               &step,
00063                                               &def,
00064                                               &flag)))
00065     {
00066       am_video_proc_amp->Get(prop[prop_tag].key, &val, &flag);
00067       vcl_cout << vcl_setw(w2) << val
00068                << vcl_setw(w2) << min
00069                << vcl_setw(w2) << max
00070                << vcl_setw(w2) << step
00071                << vcl_setw(w2) << def
00072                << vcl_setw(w2)
00073                << (flag == 0x0001
00074                    ? "auto"
00075                    : flag == 0x0002
00076                      ? "manual"
00077                      : "error")
00078                << '\n';
00079     }
00080     else
00081     {
00082       vcl_cout << " ...Not Supported...\n";
00083     }
00084   }
00085 
00086   void print_output_format_help(const CComPtr<IAMStreamConfig>& asc)
00087   //void print_output_format_help(IAMStreamConfig* asc)
00088   {
00089     AM_MEDIA_TYPE* amt = 0;
00090     VIDEO_STREAM_CONFIG_CAPS* vscc = reinterpret_cast<VIDEO_STREAM_CONFIG_CAPS*>(new BYTE[128]);
00091 
00092     int count = 0, size = 0;
00093     DSHOW_ERROR_IF_FAILED(asc->GetNumberOfCapabilities(&count, &size));
00094 #if 0
00095     assert(sizeof(VIDEO_STREAM_CONFIG_CAPS) == size);
00096 #endif
00097 
00098     DSHOW_ERROR_IF_FAILED(asc->GetFormat(&amt));
00099     vcl_cout << vcl_setw(w1) << "output_format"
00100              << ' ' << vidl_dshow::get_guid_name(amt->subtype) << '\n';
00101     vidl_dshow::delete_media_type(*amt);
00102     amt = 0;
00103 
00104     vcl_cout << vcl_string(w1, ' ') << " Supported output formats\n"
00105              << vcl_string(w1, ' ') << " ------------------------\n";
00106     for (int i = 0; i < count; i++)
00107     {
00108       DSHOW_ERROR_IF_FAILED(
00109         asc->GetStreamCaps(i, &amt, reinterpret_cast<BYTE*>(vscc)));
00110 
00111       double max_frame_interval = static_cast<double>(vscc->MaxFrameInterval);
00112       double min_frame_interval = static_cast<double>(vscc->MinFrameInterval);
00113       vcl_cout << vcl_setw(w1) << i
00114                << vcl_setw(3*w2)
00115                << vidl_dshow::get_guid_name(amt->subtype)
00116                << " ("
00117                << vcl_setw(4) << vscc->InputSize.cx << 'x'
00118                << vcl_setw(4) << vscc->InputSize.cy
00119                << ") "
00120                << vcl_setprecision(2) << 1.0 / (max_frame_interval * 100.0e-9) << '-'
00121                << vcl_setprecision(2) << 1.0 / (min_frame_interval * 100.0e-9) << " fps\n";
00122 
00123       vidl_dshow::delete_media_type(*amt);
00124       amt = 0;
00125     }
00126 
00127     delete vscc;
00128   }
00129 
00130   template <typename T> struct from_string_to
00131   {
00132     T operator()(const vcl_string& str) const
00133     {
00134       T val;
00135 
00136       vcl_istringstream iss(str);
00137       iss >> val;
00138 
00139       return val;
00140     }
00141   };
00142 
00143   template <> struct from_string_to<bool>
00144   {
00145     bool operator()(const vcl_string& str) const
00146     {
00147       if      (str == "t" || str == "true"  || str == "1")
00148       {
00149         return true;
00150       }
00151       else if (str == "f" || str == "false" || str == "0")
00152       {
00153         return false;
00154       }
00155       else
00156       {
00157         vidl_exception_error(vidl_dshow_exception(
00158           "can't convert boolean param string to bool."
00159           + DSHOW_GET_ERROR_TEXT(E_FAIL)));
00160 
00161         return false; // all paths must return...
00162       }
00163     }
00164   };
00165 } // unnamed namespace
00166 
00167 //-------------------------------------------------------------------------
00168 // Implementation.
00169 //-------------------------------------------------------------------------
00170 //: Constructor - default
00171 vidl_dshow_istream_params::vidl_dshow_istream_params(void)
00172   : vpa_properties_(vpa_properties())
00173   , register_in_rot_(false)
00174   , run_when_ready_(true)
00175   , target_output_format_(GUID_NULL)
00176   , load_filter_defaults_(false)
00177 {}
00178 
00179 //: Configure the source filter based on the parameters.
00180 void vidl_dshow_istream_params::configure_filter(
00181   const CComPtr<IBaseFilter>& source)
00182 {
00183   // IAMVideoProcAmp interface.
00184   CComPtr<IAMVideoProcAmp> am_video_proc_amp;
00185   if (SUCCEEDED(source->QueryInterface(
00186     IID_IAMVideoProcAmp, reinterpret_cast<void**>(&am_video_proc_amp))))
00187   {
00188     vcl_map<vcl_string,vpa_property_wrap>::const_iterator iter
00189       = vpa_properties_.begin();
00190     for (; iter != vpa_properties_.end(); iter++)
00191     {
00192       if (iter->second.is_changed)
00193       {
00194         DSHOW_ERROR_IF_FAILED(am_video_proc_amp->Set(
00195           iter->second.key, iter->second.value, VideoProcAmp_Flags_Manual));
00196       }
00197       else if (load_filter_defaults_)
00198       {
00199         long min, max, step, def, flag;
00200         if (SUCCEEDED(am_video_proc_amp->GetRange(iter->second.key,
00201           &min, &max, &step, &def, &flag)))
00202         {
00203           DSHOW_ERROR_IF_FAILED(
00204             am_video_proc_amp->Set(iter->second.key, def, flag));
00205         }
00206       }
00207     }
00208   }
00209 
00210   // IAMStreamConfig interface.
00211   if (output_format_.is_changed || load_filter_defaults_)
00212   {
00213     CComPtr<ICaptureGraphBuilder2> graph_builder;
00214     DSHOW_ERROR_IF_FAILED(
00215       graph_builder.CoCreateInstance(CLSID_CaptureGraphBuilder2));
00216     CComPtr<IAMStreamConfig> am_stream_config;
00217 
00218     DSHOW_ERROR_IF_FAILED(graph_builder->FindInterface(
00219       &PIN_CATEGORY_CAPTURE,
00220       &MEDIATYPE_Video,
00221       source,
00222       IID_IAMStreamConfig,
00223       reinterpret_cast<void**>(&am_stream_config)));
00224 
00225     AM_MEDIA_TYPE* amt = 0;
00226     //VIDEO_STREAM_CONFIG_CAPS vscc;
00227     VIDEO_STREAM_CONFIG_CAPS* vscc
00228       = reinterpret_cast<VIDEO_STREAM_CONFIG_CAPS*>(new BYTE[128]);
00229 
00230     int count = 0, size = 0;
00231     DSHOW_ERROR_IF_FAILED(
00232       am_stream_config->GetNumberOfCapabilities(&count, &size));
00233     // ***** alignment problem... hack to work around bug in DShow
00234 #if 0
00235     assert(sizeof(vscc) == size);
00236 #endif
00237 
00238     DSHOW_ERROR_IF_FAILED(am_stream_config->GetStreamCaps(
00239       output_format_.is_changed ? output_format_.value : 0,
00240       &amt, reinterpret_cast<BYTE*>(vscc)));
00241 
00242     DSHOW_ERROR_IF_FAILED(am_stream_config->SetFormat(amt));
00243 
00244     vidl_dshow::delete_media_type(*amt);
00245 
00246     delete [] vscc;
00247   }
00248 }
00249 
00250 void vidl_dshow_istream_params::print_parameter_help(const vcl_string& name)
00251 {
00252   vidl_dshow::initialize_com();
00253 
00254   CComPtr<IMoniker> moniker = vidl_dshow::get_capture_device_moniker(name);
00255 
00256   CComPtr<IBaseFilter> filter;
00257   DSHOW_ERROR_IF_FAILED(moniker->BindToObject(
00258     0, 0, IID_IBaseFilter, reinterpret_cast<void**>(&filter)));
00259 
00260   print_parameter_help(filter);
00261 }
00262 
00263 void vidl_dshow_istream_params::print_parameter_help(const CComPtr<IBaseFilter>& filter)
00264 {
00265   vcl_cout << "\n\nDirectShow Parameters\n"
00266            << "---------------------\n"
00267            << "1. IAMVideoProcAmp interface:\n\n";
00268 
00269   // IAMVideoProcAmp interface.
00270   CComPtr<IAMVideoProcAmp> am_video_proc_amp;
00271   if (SUCCEEDED(filter->QueryInterface(
00272     IID_IAMVideoProcAmp, reinterpret_cast<void**>(&am_video_proc_amp))))
00273   {
00274     vcl_cout << vcl_string(w1, ' ')
00275              << vcl_setw(w2) << "curr"
00276              << vcl_setw(w2) << "min"
00277              << vcl_setw(w2) << "max"
00278              << vcl_setw(w2) << "step"
00279              << vcl_setw(w2) << "default"
00280              << vcl_setw(w2) << "flags"
00281              << '\n'
00282              << vcl_string(w1, ' ')
00283              << vcl_string(6*w2, '-') << '\n';
00284 
00285     print_help(am_video_proc_amp, "brightness"            );
00286     print_help(am_video_proc_amp, "contrast"              );
00287     print_help(am_video_proc_amp, "hue"                   );
00288     print_help(am_video_proc_amp, "saturation"            );
00289     print_help(am_video_proc_amp, "sharpness"             );
00290     print_help(am_video_proc_amp, "gamma"                 );
00291     print_help(am_video_proc_amp, "color_enable"          );
00292     print_help(am_video_proc_amp, "white_balance"         );
00293     print_help(am_video_proc_amp, "backlight_compensation");
00294     print_help(am_video_proc_amp, "gain"                  );
00295     vcl_cout << '\n';
00296   }
00297   else { vcl_cout << "...Not Supported...\n"; }
00298 
00299   // IAMStreamConfig interface.
00300   CComPtr<ICaptureGraphBuilder2> graph_builder;
00301   DSHOW_ERROR_IF_FAILED(
00302     graph_builder.CoCreateInstance(CLSID_CaptureGraphBuilder2));
00303   CComPtr<IAMStreamConfig> am_stream_config;
00304 
00305   vcl_cout << "\n2.1 IAMStreamConfig interface (Capture Pin):\n\n";
00306 
00307   if (SUCCEEDED(graph_builder->FindInterface(
00308     &PIN_CATEGORY_CAPTURE,
00309     &MEDIATYPE_Video,
00310     filter,
00311     IID_IAMStreamConfig,
00312     reinterpret_cast<void**>(&am_stream_config))))
00313   {
00314     print_output_format_help(am_stream_config);
00315   }
00316   else { vcl_cout << "...Not Supported...\n"; }
00317 
00318   vcl_cout << "\n2.2 IAMStreamConfig interface (Preview Pin):\n\n";
00319 
00320   am_stream_config.Release();
00321   if (SUCCEEDED(graph_builder->FindInterface(
00322     &PIN_CATEGORY_PREVIEW,
00323     &MEDIATYPE_Video,
00324     filter,
00325     IID_IAMStreamConfig,
00326     reinterpret_cast<void**>(&am_stream_config))))
00327   {
00328     print_output_format_help(am_stream_config);
00329   }
00330   else { vcl_cout << "...Not Supported...\n"; }
00331 
00332   vcl_cout << '\n' << vcl_endl;
00333 }
00334 
00335 //: Set properties from a map(string,value).
00336 // \sa mul/mbl/mbl_read_props.h
00337 vidl_dshow_istream_params&
00338 vidl_dshow_istream_params
00339 ::set_properties(const vcl_map<vcl_string,vcl_string>& props)
00340 {
00341   vcl_map<vcl_string,vcl_string>::const_iterator iter;
00342   for (iter = props.begin(); iter != props.end(); iter++)
00343   {
00344     vcl_map<vcl_string,vpa_property_wrap>::iterator property
00345       = vpa_properties_.find(iter->first);
00346     if (property != vpa_properties_.end())
00347     {
00348       property->second.value = from_string_to<long>()(iter->second);
00349       property->second.is_changed = true;
00350     }
00351     else
00352     {
00353       if (iter->first == "output_format")
00354       {
00355         set_output_format(from_string_to<int>()(iter->second));
00356       }
00357       else if (iter->first == "register_in_rot")
00358       {
00359         set_register_in_rot(from_string_to<bool>()(iter->second));
00360       }
00361       else if (iter->first == "run_when_ready")
00362       {
00363         set_run_when_ready(from_string_to<bool>()(iter->second));
00364       }
00365       else if (iter->first == "save_graph_to")
00366       {
00367         set_save_graph_to(iter->second);
00368       }
00369       else if (iter->first == "device_name")
00370       {
00371         set_device_name(iter->second);
00372       }
00373       else if (iter->first == "output_filename")
00374       {
00375         set_output_filename(iter->second);
00376       }
00377       else if (iter->first == "target_output_format")
00378       {
00379         vidl_exception_error(
00380           vidl_exception("Target output format not supported yet!"));
00381         //set_target_output_format(from_string_to<GUID>()(iter->second));
00382       }
00383       else if (iter->first == "load_filter_defaults")
00384       {
00385         set_load_filter_defaults(from_string_to<bool>()(iter->second));
00386       }
00387       else
00388       {
00389         vcl_cerr << "DSHOW: vidl_dshow_istream_params param not valid: "
00390                  << iter->first << vcl_endl;
00391       }
00392     }
00393   }
00394 
00395   return *this;
00396 }
00397 
00398 //-------------------------------------------------------------------------
00399 // Read accessor functions.
00400 //-------------------------------------------------------------------------
00401 
00402 //-------------------------------------------------------------------------
00403 // Write accessor functions.
00404 //-------------------------------------------------------------------------
00405 /* inline */ vidl_dshow_istream_params&
00406 vidl_dshow_istream_params::set_register_in_rot(bool val)
00407 {
00408   register_in_rot_ = val;
00409   return *this;
00410 }
00411 
00412 /* inline */ vidl_dshow_istream_params&
00413 vidl_dshow_istream_params::set_run_when_ready(bool val)
00414 {
00415   run_when_ready_ = val;
00416   return *this;
00417 }
00418 
00419 /* inline */ vidl_dshow_istream_params&
00420 vidl_dshow_istream_params::set_save_graph_to(const vcl_string& name)
00421 {
00422   save_graph_to_ = name;
00423   return *this;
00424 }
00425 
00426 /* inline */ vidl_dshow_istream_params&
00427 vidl_dshow_istream_params::set_device_name(const vcl_string& name)
00428 {
00429   device_name_ = name;
00430   return *this;
00431 }
00432 
00433 /* inline */ vidl_dshow_istream_params&
00434 vidl_dshow_istream_params::set_output_filename(const vcl_string& name)
00435 {
00436   output_filename_ = name;
00437   return *this;
00438 }
00439 
00440 /* inline */ vidl_dshow_istream_params&
00441 vidl_dshow_istream_params::set_target_output_format(GUID val)
00442 {
00443   target_output_format_ = val;
00444   return *this;
00445 }
00446 
00447 /* inline */ vidl_dshow_istream_params&
00448 vidl_dshow_istream_params::set_load_filter_defaults(bool val)
00449 {
00450   load_filter_defaults_ = val;
00451   return *this;
00452 }
00453 
00454 /* inline */ vidl_dshow_istream_params&
00455 vidl_dshow_istream_params::set_output_format(int val)
00456 {
00457   output_format_.value = val;
00458   output_format_.is_changed = true;
00459   return *this;
00460 }