Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
9.0 KiB

  1. AVIFile: it's not just an API set, it's a way of life.
  2. So, people are confused about how to approach the AVIFile APIs.
  3. Let's try to help by making some things clear.
  4. 1. AVIFile isn't just for AVI files.
  5. Perhaps this would be clearer if these functions had some different
  6. name, but let's live with AVIFile for now. The important thing to
  7. keep in mind is that we aren't talking about .AVI files, but about
  8. some ideal time-based file format which supports the operations we'd
  9. like it to support, like reading and writing from multiple
  10. time-stamped streams. If the APIs conform closely to what's actually
  11. in .AVI files, it's just because I made up both the .AVI format and
  12. the AVIFile APIs.
  13. The guiding principle is that any other type of file containing this
  14. time-stamped sort of data, be it a QuickTime file, an MPEG file, a
  15. .WAV file, or whatever, should be accessible in one simple way.
  16. 2. AVIFile isn't just for files.
  17. Having a uniform API to read these different sorts of files is
  18. convenient, but we can go beyond that. Once you have the abstract
  19. concept of a "file" which is a bundle of "streams" (each of which has
  20. a particular data type and format, along with a start time and
  21. duration, and can be read from or written to at various points in
  22. time), it is clear that not every "file" needs to correspond to an
  23. actual disk file, and not every "stream" has to come from a "file" at
  24. all.
  25. Useful kinds of streams to think about:
  26. Entirely synthetic streams, like the bouncing ball example; in this
  27. case, a "stream" reduces to a function GiveMeVideoFrame(x).
  28. Streams which are essentially filters applied to other streams; for
  29. example, given a stream of video (that is, some abstract object that
  30. can hand you frame 4 if you want it), you can build from that a
  31. "compressed" stream, which is simply a stream that when asked for
  32. frame 4 goes and asks the original stream for its frame 4, then
  33. compresses it and hands it back to you, saying "here's frame 4, all
  34. compressed like you wanted it."
  35. 3. AVIFile tries to conform to the Component Object model.
  36. Since AVIFile is intended to be extensible to support additional file
  37. formats, it has to have some way of transparently linking to DLLs
  38. containing routines that understand those file formats. In the past,
  39. we in MMSys have done this sort of thing using installable drivers
  40. and a message-based scheme. (See MCI, ICM, and more....) With the
  41. release of OLE 2.0, we have a new standard for this sort of thing.
  42. It's a little scary at first, requires either C++ or some C++-like
  43. thinking, and involves header files you haven't seen before. In any
  44. case, we're all going to have to live with it.
  45. 4. Don't be intimidated by talk of C++ and "objects".
  46. From a C point of view, all an "object pointer" like a PAVISTREAM is
  47. is a pointer to a structure whose first member happens to be another
  48. pointer to a table of functions. This means that in addition to
  49. carrying around data like "how long is this video sequence", the
  50. structure also contains pointers to code that knows how to actually
  51. get things done. All C++ does for you is provide a nicer syntax for
  52. doing this sort of thing.
  53. You can make yourself a PAVISTREAM by hand. All you have to do
  54. is allocate room for a structure big enough to contain the pointer
  55. to the function table and any other data you need to keep around.
  56. Then, you make a function table with the Read, Write, and other
  57. functions to operate on your type of stream, and make sure your
  58. structure points to your table. Just like that, you have a bona fide
  59. PAVISTREAM which you can pass to AVISave, AVIStreamRead, and so on.
  60. 5. Luckily, you can usually ignore all of the "Component Object model"
  61. stuff.
  62. Unless you're doing something complicated, you should be able to just
  63. call the various AVIFileXXXX and AVIStreamXXXX APIs and pretty much
  64. ignore all of the talk of ISomethingOrOther and CLSID_Confusing.
  65. If you are trying to make a DLL that will add support for reading and
  66. writing a new file format, you will in fact have to learn something
  67. about what a "class factory" is, but cross that bridge when you come
  68. to it.
  69. 6. AVISave() is just a helper function.
  70. All the AVISave function does is copy some streams into a new file.
  71. It doesn't do anything that you couldn't do yourself by calling the
  72. AVIFileXXXX and AVIStreamXXXX APIs. It does, however, make your life
  73. easier by: calling AVIMakeCompressedStream for you according to the
  74. options you pass in; calling AVIFileOpen and AVIFileCreateStream
  75. appropriately to make the new streams in the new file you're making;
  76. and finally, looping through all of the streams from start to end
  77. copying the data from the old streams into the new file, and doing it
  78. in the right order so that things come out nicely interleaved.
  79. 7. AVIStreamReadData, AVIStreamWriteData, AVIFileReadData, and
  80. AVIFileWriteData are not actually for reading and writing real data.
  81. I know, these routines have bad names and they're just confusing
  82. everybody.
  83. What they're not for: These routines are not what you use to read and
  84. write audio samples and video frames and that sort of thing. For
  85. that, you must use AVIStreamRead and AVIStreamWrite. (If you have a
  86. PAVIFile, call AVIFileGetStream and then call AVIStreamRead.)
  87. What they're for: Reading and writing copyright information, the
  88. author's name, and other stuff like that that's kept in INFO chunks
  89. in RIFF files.
  90. 8. AVIStreamGetFrame is just another helper function.
  91. AVIStreamGetFrame (and AVIStreamGetFrameOpen/Close) are just
  92. functions which handle the relatively simple task of getting a
  93. decompressed video frame out of a stream. This involves finding the
  94. right ICM decompressor for the task at hand, figuring out where the
  95. last key frame was, and decompressing frames as necessary.
  96. Perhaps this should all be done automatically for you; perhaps you
  97. should do this instead by opening a "decompressed" stream based on
  98. the compressed stream you want to read. It's not either of those
  99. ways now, so use AVIStreamGetFrame.
  100. 8a. What in heck is AVIMakeCompressedStream() for?
  101. AVIMakeCompressedStream makes a new stream pointer for you that acts
  102. just like the old stream you already had, but is compressed or
  103. decompressed. That isn't very clear, so I'll try again: If you have
  104. a PAVISTREAM which, when you read it, gives you back 8-bit RGB frames
  105. of "Gone With the Wind", you can use AVIMakeCompressedStream to make
  106. a stream that will return the same pictures, but compressed in, say,
  107. CRAM format. The reverse is also true: given a compressed stream,
  108. AVIMakeCompressedStream can make you an uncompressed version of that
  109. stream.
  110. To use it, just fill out an AVICOMPRESSOPTIONS structure. (Or pass
  111. NULL, which will decompress.)
  112. In theory, you can either read from the compressed stream or write to
  113. it. (Right now, this still doesn't work for audio compression....)
  114. However, you can only do one at a time.
  115. 9. What in the world is an HRESULT?
  116. For some reason, all OLE 2.0 functions return HRESULTs which could
  117. potentially contain extra information about an error that occurred.
  118. For now, they are essentially just the same as a plain error code.
  119. To convert one of the AVIERR_XXXX codes to an HRESULT, call
  120. ResultFromScode() on it. To convert back, use GetScode()....
  121. 10. In its current state, AVIFile is not finished.
  122. Some things which are bad about the current AVIFile APIs:
  123. AVISaveOptions() puts up a nasty big nested dialog which isn't
  124. user-friendly.
  125. AVISave() doesn't handle palette changes correctly.
  126. Almost nothing handles the concept of, say, a wave format changing
  127. halfway through a stream.
  128. T here is no way to find when the next palette change happens, short
  129. of asking for the video format on every frame until you find a place
  130. it changes.
  131. Dealing with compressed and uncompressed streams is kind of screwy.
  132. If you know exactly what you have and what you want, you can call
  133. AVIMakeCompressedStream() to do what you need.
  134. Right now, the handler for compressing streams only supports reading,
  135. not writing. There is no reason this should be true, and maybe I'll
  136. fix it.
  137. There are no status callbacks for anything. If something takes a
  138. really long time, you wait.
  139. Error returns are generally bad, if they're there at all.
  140. There is no way to find what a specific handler can do short of
  141. trying to do it and seeing what works.
  142. The documentation is still primitive.
  143. 11. Miscellaneous hints:
  144. Be sure to call AVIStreamInit() and AVIStreamExit(). If you don't,
  145. the component object DLL won't get initialized and nothing will work.
  146. Be sure the right information is in your registration database. It
  147. should all get put there automatically, but isn't too resistant to
  148. tampering.
  149. Some functions take pointers to long variables which need to be initialized
  150. to the size of your buffer before you call them. You need to use code like:
  151. cbSize = cbBuffer; AVIStreamReadFormat(pstream, 0, lpBuffer, &cbSize);
  152. After this, cbSize will contain the actual correct size of the format, which
  153. you can then compare to the size you passed in to see if your buffer
  154. was large enough.