00001
00002
00003 #include "vidl_dshow_istream_params.h"
00004
00005
00006
00007
00008
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
00024
00025 namespace
00026 {
00027
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
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
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;
00162 }
00163 }
00164 };
00165 }
00166
00167
00168
00169
00170
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
00180 void vidl_dshow_istream_params::configure_filter(
00181 const CComPtr<IBaseFilter>& source)
00182 {
00183
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
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
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
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
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
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
00336
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
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
00400
00401
00402
00403
00404
00405 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 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 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 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 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 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 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 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 }