VideoVis  0.9
Generates a volume visualisation of a video
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
VideoFrameLoader.cpp
Go to the documentation of this file.
1 #include "VideoFrameLoader.h"
2 
3 #include <Shlwapi.h>
4 #include <strsafe.h>
5 #include <Propvarutil.h>
6 #include <QDebug>
7 
8 
10 {
11  initializeFrameLoader();
12 }
13 
15 {
16  initializeFrameLoader();
17  setVideoPath(filePath, false);
18 }
19 
20 void CVideoFrameLoader::initializeFrameLoader()
21 {
22  p_videoURL = NULL;
23  p_videoArray = NULL;
24  p_videoList = NULL;
25 
26  p_videoReader = NULL;
27 
28  m_frameCount = 0;
29  m_totalFrameCount = 0;
30  m_videoWidth = 0;
31  m_videoHeight = 0;
32  m_videoBufferTransfered = false;
33 
34  // Initialize the COM runtime.
35  if (SUCCEEDED(CoInitializeEx(0, COINIT_MULTITHREADED)))
36  m_comInitialisationSuccessful = true;
37 
38  // Initialize the Media Foundation platform.
39  if (SUCCEEDED(MFStartup(MF_VERSION)))
40  m_mediaFoundationInitalisationSuccessful = true;
41 }
42 
43 
45 {
46  if (p_videoURL)
47  delete p_videoURL;
48 
49  if (p_videoArray && !m_videoBufferTransfered)
50  delete p_videoArray;
51 
52  if (p_videoList)
53  {
54  while (!p_videoList->empty())
55  {
56  PBYTE frame = p_videoList->front();
57  p_videoList->pop_front();
58  delete frame;
59  }
60 
61  delete p_videoList;
62  p_videoList = NULL;
63  }
64 
65  SafeRelease((IUnknown**) &p_videoReader);
66 
67  if (m_mediaFoundationInitalisationSuccessful)
68  MFShutdown();
69 
70  if (m_comInitialisationSuccessful)
71  CoUninitialize();
72 }
73 
75 {
76  reset();
77 
78  if (p_videoURL)
79  delete p_videoURL;
80 
81  SafeRelease((IUnknown**) &p_videoReader);
82 
83  p_videoURL = NULL;
84  m_videoWidth = 0;
85  m_videoHeight = 0;
86 
87  return VFL_OK;
88 }
89 
91 {
92  return setVideoPath(filePath, true);
93 }
94 
95 VFLResult CVideoFrameLoader::setVideoPath(PWSTR filePath, bool reset)
96 {
97  if (reset)
99 
100  p_videoURL = new WCHAR[MAXVideoURLLenght];
101 
102  DWORD videoURLLength = MAXVideoURLLenght;
103 
104  if(FAILED(UrlCreateFromPath(filePath, p_videoURL, &videoURLLength, NULL)))
106 
107  return openFileInSourceReader();
108 }
109 
111 {
112  return setVideoURL(fileURL, true);
113 }
114 
115 VFLResult CVideoFrameLoader::setVideoURL(PWSTR fileURL, bool reset)
116 {
117  if (reset)
118  resetProperties();
119 
120  p_videoURL = new WCHAR[MAXVideoURLLenght];
121 
122  if (StringCbCopy(p_videoURL, MAXVideoURLLenght, fileURL) == STRSAFE_E_INSUFFICIENT_BUFFER)
123  return VFL_URL_TO_LONG;
124 
125  return openFileInSourceReader();
126 }
127 
128 VFLResult CVideoFrameLoader::openFileInSourceReader()
129 {
130  IMFAttributes *pSourceReaderAttributes = NULL;
131 
132  MFCreateAttributes(&pSourceReaderAttributes, 1);
133 
134  pSourceReaderAttributes->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, TRUE);
135 
136  //Create the source reader.
137  if(FAILED(MFCreateSourceReaderFromURL(p_videoURL, pSourceReaderAttributes, &p_videoReader)))
138  {
139  SafeRelease((IUnknown **) &pSourceReaderAttributes);
141  }
142 
143  SafeRelease((IUnknown **) &pSourceReaderAttributes);
144 
145  if(FAILED(configureDecoder(p_videoReader)))
147 
148  IMFMediaType *pType;
149 
150  if (FAILED(p_videoReader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, &pType)))
152 
153  if (FAILED(MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, &m_videoWidth, &m_videoHeight)))
154  {
155  pType->Release();
157  }
158 
159  pType->Release();
160 
161  return VFL_OK;
162 }
163 
165 {
166  return loadAllFramesIntoBuffer(0, 0);
167 }
168 
170 {
171  return loadAllFramesIntoBuffer(offset, distanceBetween, 0);
172 }
173 
174 VFLResult CVideoFrameLoader::loadAllFramesIntoBuffer(int offset, int distanceBetween, int lastFrame)
175 {
176  if (!p_videoReader)
177  return VFL_NO_VIDEO_SOURCE;
178 
179  reset();
180 
181  VFLResult vr = addNextFrameToBuffer(offset);
182 
183  if (vr != VFL_OK)
184  return vr;
185 
186  if (lastFrame != 0)
187  while (vr == VFL_OK && m_totalFrameCount + distanceBetween < lastFrame)
188  vr = addNextFrameToBuffer(distanceBetween);
189  else
190  while (vr == VFL_OK)
191  vr = addNextFrameToBuffer(distanceBetween);
192 
193  return vr;
194 }
195 
197 {
198  return addNextFrameToBuffer(0);
199 }
200 
202 {
203  if (!p_videoReader)
204  return VFL_NO_VIDEO_SOURCE;
205 
206  if (p_videoList == NULL)
207  p_videoList = new list<PBYTE>;
208 
209  IMFSample *pSample = NULL;
210  DWORD streamIndex,flags;
211  LONGLONG llTimeStamp;
212 
213  for (int frameCount = 0; frameCount < distanceFromLast + 1; frameCount++)
214  {
215  SafeRelease((IUnknown**) &pSample);
216 
217  p_videoReader->ReadSample(
218  MF_SOURCE_READER_FIRST_VIDEO_STREAM, // Stream index.
219  0, // Flags.
220  &streamIndex, // Receives the actual stream index.
221  &flags, // Receives status flags.
222  &llTimeStamp, // Receives the time stamp.
223  &pSample // Receives the sample or NULL.
224  );
225 
226  if (!pSample)
227  {
228  //SafeRelease((IUnknown**) &p_videoReader);
229  return VFL_NO_MORE_FRAMES;
230  }
231  m_totalFrameCount++;
232  }
233 
234  copyFrameToBuffer(pSample);
235  SafeRelease((IUnknown**) &pSample);
236  m_frameCount++;
237 
238  return VFL_OK;
239 }
240 
242 {
243  if (m_videoWidth == 0 || m_videoHeight == 0)
245 
246  *width = m_videoWidth;
247  *height = m_videoHeight;
248 
249  return VFL_OK;
250 }
251 
253 {
254  if (!p_videoArray)
256 
257  if (p_videoArray == NULL)
259 
260  *videoArray = p_videoArray;
261  m_videoBufferTransfered = true;
262 
263  return VFL_OK;
264 }
265 
267 {
268  if (m_frameCount == 0)
270 
271  *frameCount = m_frameCount;
272 
273  return VFL_OK;
274 }
275 
277 {
278  if (p_videoReader != NULL)
279  setPosition(0);
280 
281  if (p_videoList)
282  {
283  while (!p_videoList->empty())
284  {
285  PBYTE frame = p_videoList->front();
286  p_videoList->pop_front();
287  delete frame;
288  }
289 
290  delete p_videoList;
291  p_videoList = NULL;
292  }
293 
294  if (p_videoArray && !m_videoBufferTransfered)
295  delete p_videoArray;
296 
297  p_videoArray = NULL;
298  m_frameCount = 0;
299  m_totalFrameCount = 0;
300  m_videoBufferTransfered = false;
301 }
302 
303 HRESULT CVideoFrameLoader::configureDecoder(IMFSourceReader *pReader)
304 {
305  IMFMediaType *pType = NULL;
306 
307  // Define the output type.
308  HRESULT hr = MFCreateMediaType(&pType);
309  if (FAILED(hr))
310  {
311  SafeRelease((IUnknown**) &pType);
312  return hr;
313  }
314 
315  hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
316  if (FAILED(hr))
317  {
318  SafeRelease((IUnknown**) &pType);
319  return hr;
320  }
321 
322  hr = pType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32);
323  if (FAILED(hr))
324  {
325  SafeRelease((IUnknown**) &pType);
326  return hr;
327  }
328 
329  // Set the uncompressed format.
330  hr = pReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, pType);
331  if (FAILED(hr))
332  {
333  SafeRelease((IUnknown**) &pType);
334  return hr;
335  }
336 
337  return hr;
338 }
339 
340 HRESULT CVideoFrameLoader::setPosition(const LONGLONG& hnsPosition)
341 {
342  PROPVARIANT var;
343  HRESULT hr = InitPropVariantFromInt64(hnsPosition, &var);
344  if (SUCCEEDED(hr))
345  {
346  hr = p_videoReader->SetCurrentPosition(GUID_NULL, var);
347  PropVariantClear(&var);
348  }
349  return hr;
350 }
351 
352 
354 {
355  int byteCount = m_videoWidth * m_videoHeight * 4;
356 
357  p_videoArray = new BYTE[(long) byteCount * (long) m_frameCount];
358 
359  for (int frameCounter = 0; frameCounter < m_frameCount; frameCounter++)
360  {
361  PBYTE frame = p_videoList->front();
362  p_videoList->pop_front();
363 
364  for (int byteCounter = 0; byteCounter < byteCount; byteCounter++)
365  {
366  p_videoArray[(long) frameCounter * (long) byteCount + byteCounter] = frame[byteCounter];
367  }
368 
369  delete frame;
370  }
371 
372  //delete p_videoList;
373  //p_videoList = NULL;
374 }
375 
376 VFLResult CVideoFrameLoader::copyFrameToBuffer(IMFSample *pSample)
377 {
378  IMFMediaBuffer * pSampleBuffer = NULL;
379 
380  pSample->ConvertToContiguousBuffer(&pSampleBuffer);
381 
382  PBYTE singleFrameByteBuffer;
383 
384  int byteCount = m_videoWidth * m_videoHeight * 4;
385  PBYTE singleFrameByteBufferCopy = new BYTE[byteCount];
386 
387  pSampleBuffer->Lock(&singleFrameByteBuffer, NULL, NULL);
388 
389 
390  for (int byteCounter = 0; byteCounter < byteCount; byteCounter++)
391  singleFrameByteBufferCopy[byteCounter] = singleFrameByteBuffer[byteCounter];
392 
393  //p_videoArray->append((char *)singleFrameByteBuffer, m_videoWidth * m_videoHeight * 4);
394 
395  pSampleBuffer->Unlock();
396  pSampleBuffer->Release();
397 
398  p_videoList->push_back(singleFrameByteBufferCopy);
399 
400  return VFL_OK;
401 }
402 
403 void CVideoFrameLoader::SafeRelease(IUnknown **ppT)
404 {
405  if (*ppT)
406  {
407  (*ppT)->Release();
408  *ppT = NULL;
409  }
410 }