libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
AVIStuff.hpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2002 by J.M.McGuiness, coder@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 // Scabbed from the "writeavi" MSDN example.
20 
22 #include"SystemTime.hpp"
23 #include<vfw.h>
24 
25 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE { namespace NTUtils {
26 
27  const unsigned long bazoom=0x00000010L; // this frame is a key frame.
28 
29  class AVIFile {
30  public:
31  inline __stdcall AVIFile(const tchar *file_name);
32  inline __stdcall ~AVIFile(void);
33 
34  inline bool __fastcall Initialise(const HWND parent,const UINT uiflags,const unsigned int fps,BitMapInfoWrapper &bminfo,const std::string &copyright,const std::string &creation_date=TStringToString(SystemTimeAsStr()));
35 
36  inline bool __fastcall WriteFrame(const unsigned int duration,const HBITMAP &frame,const unsigned short colour_depth);
37  inline bool __fastcall WriteFrame(const unsigned int duration,BitMapInfoWrapper &frame);
38 
39  static inline BitMapInfoWrapper __fastcall MakeDIB(const HBITMAP hbitmap,const unsigned short colour_depth);
40 
41  private:
42  PAVIFILE pfile;
43  PAVISTREAM ps,psCompressed,psText;
44  unsigned int frame_number;
45  bool initialised;
46 
47  // I don't allow copying or assignment.
48  inline __stdcall AVIFile(const AVIFile &) noexcept(true);
49  inline AVIFile & __fastcall operator=(const AVIFile &) noexcept(true);
50  };
51 
52  inline __stdcall
53  AVIFile::AVIFile(const tchar *file_name)
54  : pfile(),ps(),psCompressed(),psText(),frame_number(),initialised(false) {
55  AVIFileInit();
56  const HRESULT hr = AVIFileOpen(&pfile, // returned file pointer
57  file_name, // file name
58  OF_WRITE | OF_CREATE, // mode to open file with
59  NULL); // use handler determined
60  assert(hr==AVIERR_OK);
61  }
62 
63  inline __stdcall
64  AVIFile::~AVIFile(void) {
65  if (ps) {
66  AVIStreamClose(ps);
67  }
68  if (psCompressed) {
69  AVIStreamClose(psCompressed);
70  }
71  if (psText) {
72  AVIStreamClose(psText);
73  }
74  if (pfile){
75  AVIFileClose(pfile);
76  }
77  AVIFileExit();
78  }
79 
80  inline bool __fastcall
81  AVIFile::Initialise(const HWND parent,const UINT uiflags,const unsigned int fps,BitMapInfoWrapper &bminfo,const std::string &copyright,const std::string &creation_date) {
82  AVISTREAMINFO strhdr;
83  memset(&strhdr, 0, sizeof(strhdr));
84  strhdr.fccType = streamtypeVIDEO;// stream type
85  strhdr.fccHandler = 0;
86  strhdr.dwScale = 1;
87  strhdr.dwRate = fps;
88  strhdr.dwSuggestedBufferSize = bminfo.Header()->biSizeImage;
89  // And create the stream;
90  if (AVIFileCreateStream(pfile, // file pointer
91  &ps, // returned stream pointer
92  &strhdr)!=AVIERR_OK) { // stream header
93  return true;
94  }
95  AVICOMPRESSOPTIONS opts;
96  AVICOMPRESSOPTIONS *aopts[1] = {&opts};
97  memset(&opts, 0, sizeof(opts));
98  if (!AVISaveOptions(parent, uiflags, 1, &ps, reinterpret_cast<LPAVICOMPRESSOPTIONS *>(&aopts))) {
99  return true;
100  }
101  if (AVIMakeCompressedStream(&psCompressed, ps, &opts, NULL) != AVIERR_OK) {
102  return true;
103  }
104  if (AVIStreamSetFormat(psCompressed, 0,
105  bminfo.Info(), // stream format
106  bminfo.Header()->biSize // format size
107  +bminfo.Header()->biClrUsed * sizeof(RGBQUAD)) != AVIERR_OK) {
108  return true;
109  }
110  if (AVIFileWriteData(pfile,mmioFOURCC('I','C','O','P'),const_cast<char *>(copyright.c_str()),copyright.length()) != AVIERR_OK) {
111  return true;
112  }
113  if (AVIFileWriteData(pfile,mmioFOURCC('I','C','R','D'),const_cast<char *>(creation_date.c_str()),creation_date.length()) != AVIERR_OK) {
114  return true;
115  }
116  // We need this as the "AVISaveOptions(...)" call is asynchronous, so calls to "WriteFrame(...)" could occur before the initialisation is finished...
117  initialised=true;
118  return false;
119  }
120 
121  inline bool __fastcall
122  AVIFile::WriteFrame(const unsigned int duration,const HBITMAP &frame,const unsigned short colour_depth) {
123  if (initialised) {
124  BitMapInfoWrapper bm(frame,colour_depth);
125  const bool ret=WriteFrame(duration,bm);
126  return ret;
127  }
128  return true;
129  }
130 
131  inline bool __fastcall
132  AVIFile::WriteFrame(const unsigned int duration,BitMapInfoWrapper &frame) {
133  if (initialised) {
134  if (AVIStreamWrite(psCompressed, // stream pointer
135  frame_number * duration, // time of this frame
136  1, // number to write
137  reinterpret_cast<BYTE *>(frame.Info()->bmiColors) // pointer to data
138  +frame.Header()->biClrUsed * sizeof(RGBQUAD),
139  frame.Header()->biSizeImage, // size of this frame
140  AVIIF_KEYFRAME, // flags....
141  NULL,
142  NULL) != AVIERR_OK) {
143  return true;
144  }
145  ++frame_number;
146  return false;
147  }
148  return true;
149  }
150 
151 } }