00001
00002
00003 #include "vidl_dshow_file_istream.h"
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <vidl/vidl_dshow.h>
00013 #include <vidl/vidl_frame.h>
00014
00015
00016
00017
00018
00019 vidl_dshow_file_istream
00020 ::vidl_dshow_file_istream(const vcl_string& filename)
00021 : frame_index_(-1)
00022 , end_position_(0)
00023 , is_time_format_frame_(false)
00024 , is_valid_(false)
00025 , buffer_pixel_format_(VIDL_PIXEL_FORMAT_UNKNOWN)
00026 , buffer_width_(0)
00027 , buffer_height_(0)
00028 , register_(0)
00029 {
00030 vidl_dshow::initialize_com();
00031 open(filename);
00032 }
00033
00034
00035 vidl_dshow_file_istream::~vidl_dshow_file_istream(void)
00036 {
00037 close();
00038 }
00039
00040
00041 void vidl_dshow_file_istream::open(const vcl_string& filename)
00042 {
00043
00044 DSHOW_ERROR_IF_FAILED(filter_graph_.CoCreateInstance(CLSID_FilterGraph));
00045
00046
00047 CComPtr<ICaptureGraphBuilder2> graph_builder;
00048 DSHOW_ERROR_IF_FAILED(
00049 graph_builder.CoCreateInstance(CLSID_CaptureGraphBuilder2));
00050
00051
00052 graph_builder->SetFiltergraph(filter_graph_);
00053
00054
00055 CComPtr<IBaseFilter> source_filter;
00056 DSHOW_ERROR_IF_FAILED(filter_graph_->AddSourceFilter(
00057 CA2W(filename.c_str()), L"Source", &source_filter));
00058
00059
00060
00061 DSHOW_ERROR_IF_FAILED(
00062 sample_grabber_.CoCreateInstance(CLSID_SampleGrabber));
00063 sample_grabber_->SetBufferSamples(true);
00064 sample_grabber_->SetOneShot(false);
00065
00066
00067
00068
00069 AM_MEDIA_TYPE media_type;
00070 ZeroMemory(&media_type, sizeof(AM_MEDIA_TYPE));
00071 media_type.majortype = MEDIATYPE_Video;
00072 media_type.subtype = MEDIASUBTYPE_RGB24;
00073 sample_grabber_->SetMediaType(&media_type);
00074
00075
00076 CComQIPtr<IBaseFilter> sample_grabber_filter(sample_grabber_);
00077 DSHOW_ERROR_IF_FAILED(
00078 filter_graph_->AddFilter(sample_grabber_filter, L"Sample Grabber"));
00079
00080
00081 CComPtr<IBaseFilter> null_renderer;
00082 DSHOW_ERROR_IF_FAILED(
00083 null_renderer.CoCreateInstance(CLSID_NullRenderer));
00084 DSHOW_ERROR_IF_FAILED(
00085 filter_graph_->AddFilter(null_renderer, L"Null Renderer"));
00086
00087
00088
00089
00090
00091
00092
00093
00094 CComPtr<IPin> pin;
00095 if (FAILED(graph_builder->FindPin(
00096 source_filter,
00097 PINDIR_OUTPUT,
00098 0,
00099 &MEDIATYPE_Video,
00100 TRUE,
00101 0,
00102 &pin)))
00103 {
00104 DSHOW_ERROR_IF_FAILED(graph_builder->RenderStream(
00105 0, 0,
00106 source_filter,
00107 sample_grabber_filter,
00108
00109 null_renderer));
00110 }
00111 else
00112 {
00113 DSHOW_ERROR_IF_FAILED(graph_builder->RenderStream(
00114 0, &MEDIATYPE_Video,
00115 source_filter,
00116 sample_grabber_filter,
00117 null_renderer));
00118 }
00119
00120
00121
00122
00123
00124
00125 DSHOW_ERROR_IF_FAILED(
00126 sample_grabber_->GetConnectedMediaType(&media_type));
00127 vidl_dshow::get_media_info(media_type,
00128 buffer_width_,
00129 buffer_height_,
00130 buffer_pixel_format_);
00131 vidl_dshow::delete_media_type(media_type);
00132
00133
00134
00135
00136
00137
00138
00139 filter_graph_->QueryInterface(
00140 IID_IMediaControl, reinterpret_cast<void**>(&media_control_));
00141 if (media_control_->Pause() == S_FALSE)
00142 {
00143 OAFilterState state;
00144 DSHOW_ERROR_IF_FAILED(media_control_->GetState(INFINITE, &state));
00145 }
00146
00147
00148 filter_graph_->QueryInterface(
00149 IID_IMediaSeeking, reinterpret_cast<void**>(&media_seeking_));
00150 if (SUCCEEDED(media_seeking_->SetTimeFormat(&TIME_FORMAT_FRAME)))
00151 {
00152 is_time_format_frame_ = true;
00153 }
00154
00155
00156 DSHOW_ERROR_IF_FAILED(media_seeking_->GetStopPosition(&end_position_));
00157
00158
00159 if (false)
00160 {
00161 vidl_dshow::register_in_rot(filter_graph_, register_);
00162 }
00163 }
00164
00165 void vidl_dshow_file_istream::close(void)
00166 {
00167
00168
00169
00170
00171 if (register_ != 0)
00172 {
00173 vidl_dshow::remove_from_rot(register_);
00174 }
00175
00176 sample_grabber_.Release();
00177 media_event_.Release();
00178 media_seeking_.Release();
00179 media_control_.Release();
00180 filter_graph_.Release();
00181 }
00182
00183
00184
00185
00186
00187 inline bool vidl_dshow_file_istream::advance_wait(void)
00188 {
00189 if (!advance_start()) { return false; }
00190
00191
00192 while (!is_frame_available());
00193
00194 return true;
00195 }
00196
00197
00198 inline bool vidl_dshow_file_istream::advance_start(void)
00199 {
00200 if (!is_valid_ && frame_index_ != -1) { return false; }
00201
00202 REFERENCE_TIME next;
00203 if (is_time_format_frame_)
00204 {
00205 next = frame_index_ + 1;
00206 }
00207 else
00208 {
00209 REFERENCE_TIME next_time;
00210 next_time
00211 = static_cast<REFERENCE_TIME>((frame_index_+1) * 10000000.0 / 30.0);
00212
00213 DSHOW_ERROR_IF_FAILED(media_seeking_->ConvertTimeFormat(
00214 &next, 0, next_time, &TIME_FORMAT_MEDIA_TIME));
00215 }
00216
00217 if (next >= end_position_) { return false; }
00218
00219 DSHOW_ERROR_IF_FAILED(media_seeking_->SetPositions(
00220 &next, AM_SEEKING_AbsolutePositioning | AM_SEEKING_ReturnTime,
00221 0, AM_SEEKING_NoPositioning));
00222
00223 buffer_time_[++buffer_index_ % 2] = next / 10000000.0;
00224
00225 ++frame_index_;
00226 is_valid_ = true;
00227
00228 return true;
00229 }
00230
00231
00232
00233 inline bool vidl_dshow_file_istream::is_frame_available(void) const
00234 {
00235 if (media_control_->Pause() == S_FALSE) { return false; }
00236
00237 return is_valid();
00238 }
00239
00240
00241 inline vidl_frame_sptr vidl_dshow_file_istream::read_frame(void)
00242 {
00243 if (!advance_wait()) { return 0; }
00244 return current_frame();
00245 }
00246
00247
00248 inline vidl_frame_sptr vidl_dshow_file_istream::current_frame(void)
00249 {
00250 if (!is_valid_) { return 0; }
00251
00252
00253 long buffer_size = 0;
00254 DSHOW_ERROR_IF_FAILED(sample_grabber_->GetCurrentBuffer(&buffer_size, 0));
00255
00256
00257 unsigned int i = buffer_index_ % 2;
00258 buffer_[i].resize(buffer_size);
00259
00260
00261 DSHOW_ERROR_IF_FAILED(sample_grabber_->GetCurrentBuffer(
00262 &buffer_size, reinterpret_cast<long*>(&buffer_[i][0])));
00263
00264
00265
00266
00267 if (buffer_pixel_format_ == VIDL_PIXEL_FORMAT_UNKNOWN)
00268 {
00269 return new vidl_shared_frame(
00270 &buffer_[i][0], buffer_size, 1, VIDL_PIXEL_FORMAT_UNKNOWN);
00271 }
00272 else
00273 {
00274 return new vidl_shared_frame(
00275 &buffer_[i][0], buffer_width_, buffer_height_, buffer_pixel_format_);
00276 }
00277 }
00278
00279
00280
00281 inline bool vidl_dshow_file_istream::seek_frame(unsigned int frame_number)
00282 {
00283 REFERENCE_TIME next;
00284 if (is_time_format_frame_)
00285 {
00286 next = frame_number;
00287 }
00288 else
00289 {
00290 REFERENCE_TIME next_time;
00291 next_time
00292 = static_cast<REFERENCE_TIME>(frame_number * 10000000.0 / 30.0);
00293 DSHOW_ERROR_IF_FAILED(media_seeking_->ConvertTimeFormat(
00294 &next, 0, next_time, &TIME_FORMAT_MEDIA_TIME));
00295 }
00296
00297
00298 if (next >= end_position_)
00299 {
00300
00301 vcl_cout << "Failed: " << frame_number << vcl_endl;
00302 return false;
00303 }
00304
00305
00306 if (frame_number < frame_index_ && frame_index_ != -1)
00307 {
00308
00309 vcl_cout << "Rewinding: " << frame_number << vcl_endl;
00310
00311
00312
00313
00314
00315
00316 media_control_->Stop();
00317 OAFilterState state;
00318 DSHOW_ERROR_IF_FAILED(media_control_->GetState(INFINITE, &state));
00319 if (media_control_->Pause() == S_FALSE)
00320 {
00321 OAFilterState state;
00322 DSHOW_ERROR_IF_FAILED(media_control_->GetState(INFINITE, &state));
00323 }
00324
00325 frame_index_ = -1;
00326 is_valid_ = false;
00327 }
00328
00329
00330
00331
00332 unsigned int seek_count = frame_number - frame_index_ + 1;
00333 while (--seek_count)
00334 {
00335 if (!advance_wait())
00336 {
00337 vcl_cout << "Failed Loop: " << frame_number << vcl_endl;
00338 is_valid_ = false;
00339 return false;
00340 }
00341 }
00342
00343 frame_index_ = frame_number;
00344 is_valid_ = true;
00345
00346 return true;
00347
00348 #if 0 // commented out
00349
00350 if (frame_number < frame_index_ && frame_index_ != -1)
00351 {
00352 vcl_cout << "Failed: " << frame_number << vcl_endl;
00353 #if 0
00354 DWORD caps = AM_SEEKING_CanSeekBackwards;
00355 if (media_seeking_->CheckCapabilities(&caps) != S_OK)
00356 {
00357 vcl_cout << "Failed: " << frame_number << vcl_endl;
00358 return false;
00359 }
00360 #endif // 0
00361 return false;
00362 }
00363
00364
00365 DSHOW_ERROR_IF_FAILED(media_seeking_->SetPositions(
00366 &next, AM_SEEKING_AbsolutePositioning | AM_SEEKING_ReturnTime,
00367 0, AM_SEEKING_NoPositioning));
00368
00369
00370 buffer_time_[++buffer_index_ % 2] = next / 10000000.0;
00371
00372 frame_index_ = frame_number;
00373
00374 vcl_cout << "Succeeded: " << frame_number << vcl_endl;
00375 return true;
00376 #endif // 0
00377 }