This is the README FILE of DIMP version 0.9: a multithreaded MPEG player for OS/2 Warp 3.0 using DIVE (Direct Interface to Video Extensions) written by: Peter Van Geit Student at the University of Ghent, Belgium (the small country between France & Germany) vg@iris.elis.rug.ac.be Please send your comments/suggestions/questions to the above adress. 0] CONTENTS 1] Product description 2] Copyright notice 3] Contents 3.1] Executables 3.2] Source code 4] Writing your own MPEG player 5] How the player works 6] VIDEO.DLL description 7] DITHER.DLL description 8] DIVE.DLL description 9] Player performance 1] PRODUCT DESCRIPTION This player is a port of the Berkeley Plateau Research Group MPEG-1 player version 2.0. It implements the standard described in the Committee Draft ISO/IEC CD 11172. This UNIX-player uses X-Windows to display the video sequence. The player doesn't implement real-time synchronisation nor does it supports audio streams. It is shipped with various dithering algorythms. Until now the player has been ported to several platforms including DOS and Windows. The source can be freely obtained via anonymous ftp from "toe.cs.berkeley.edu" in "/pub/multimedia/mpeg/mpeg-2.0.tar.Z" Below I include the copyright notice of the original player: /* * Copyright (c) 1992 The Regents of the University of California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ I ported the player to IBM OS/2 Warp 3.0 and named it DIVE (DIve MPeg). It consists of three parts: video.dll : a dynamic link library which contains the MPEG decoding routines dither.dll: a dynamic link library which includes many dithering algorythms dimp.exe : the player. It implements the interface and manages the above dll's The two above dll's are completely independent and REUSABLE (definition files & headers needed to use them are included) in other applications, the player dimp.exe is nothing more than a demonstration of how to use these libraries. Furthermore I think this player is a very good example showing you how to use DIVE. The player runs under Presentation Manager and has a very functional interface. It uses two threads: one to respond to user actions and one thread that handles the decoding. The player uses the dive.dll dynamic link library for fast screen access. DIVE functionality includes: Direct video frame buffer access Video hardware interrogation Color space conversion (=dithering) Palette conversion Auto-resizing The player comes in two versions: dimp.exe : optimize for speed dimp2.exe : generates extensive statistical information You can start the players at the command line or use drape-and-drop 2] COPYRIGHT NOTICE The changes I made to the original source (which is freely distributable) as well as the new source files I wrote are FREELY distributable/modifiable/ usable, EXCEPT for commercial goals. Also the dynamic link libraries "video.dll","video2.dll" and "dither.dll" may be used FREELY, EXCEPT for commercial goals. The author of this player shall not be held responsible in any way for any damage caused by this player. 3] CONTENTS 3.1] PLAYER EXECUTABLES: (dimpexe.zip) dimp.exe : needs dither.dll and video.dll (This one is optimized for speed) dimp2.exe : needs dither.dll and video2.dll (This one generates extensive statistical output) 3.1] PLAYER SOURCE FILES: (dimpsrc.zip) dimp.h : player header dimp.c : player main file dimp.def : player definition file dimp.rc : player resource file *.ico : various icons used by the player *.dlg : various dialogs used by the player dither.dll: dynamic link library containing dithering routines (included in dimpexe.zip) dither.def: corresponding definition file (used to produce the import library which is linked with the player) pvgdith.h : corresponding header file containing the declarations of the functions implemented in dither.dll used by the player (this file must be #included by the player) video.dll : dynamic link library containg MPEG decoding routines (included in dimpexe.zip) video2.dll: idem but this one generates statistical info (included in dimpexe.zip) video.def : corresponding definition file (used to produce the import library which is linked with the player) video2.def: idem but for video2.dll pvgvideo.h: corresponding header file containing the declarations of the functions implemented in video(2).dll used by the player (this file must be #included by the player) dimp.mak : player make file 3.3] Tools used I wrote this player under IBM OS/2 Warp 3.0 with the IBM C/Set++ 2.1 compiler (latest CSD's) and the IBM Warp 3.0 Toolkit. Therefore if you use the same configuration everything should compile without problems. You can generate an executable running "makeall.cmd" after customizing the makefile "dimp.mak" 4] WRITING YOUR OWN MPEG PLAYER You can write your own MPEG player in just a few hours by using the routines provided in the dither.dll and video(2).dll dynamic link libraries (see below for a description of the routines). All you need to do is to: 1) include "pvgdith.h" and "pvgvideo.h" in your player source file 2) generate the import libraries "dither.lib" and "video.lib" via: implib dither.lib dither.def implib video.lib video.def (use video2.def to generate stat. info) 3) link the import libraries with the object code of your own player See "dimp.c" and "dimp.mak" for more information on the usage You don't need it for the usage of the libraries but if you would be interested in the source code of the video(2) and dither dynamic link libraries, send me a mail at my adress mentionned above. 5] HOW THE PLAYER WORKS EXECUTABLE ACTIONS DYN. LNK. LIBRARIES +----------+ initialize +------------+ | DIMP.EXE | ----------------> | VIDEO.DLL | | ( MPEG | decode next frame | ( MPEG | | player) | ----------------> | decoding) | | | 24-bit decoded frame | | | | <---------------- +------------+ | | | | initialize +------------+ | | ----------------> | DITHER.DLL | | | 24-bit decoded frame | ( 8-bit | | | ----------------> | dithering) | | | 8-bit dithered frame | | | | <---------------- +------------+ | | | | initialize +------------+ | | ----------------> | DIVE.DLL | DISPLAY | | 8-bit dithered frame | | -------> HARDWARE +----------+ ----------------> +------------+ 6] VIDEO.DLL DESCRIPTION The video.dll (video2.dll for the statistical version) dynamic link library implements the folowing datatypes and functions which are declared in "pvgvideo.h". See "dimp.c" to know in which order the routines functions should be called. void init_tables(); Function called first to initialize the Huffman tables used for decoding VidStream Datatype that represents a MPEG-video sequence VidStream * NewVidStream (char * fname, int bufLength, int loop, int quiet, int noDisplay, int ditherType); Function called at the beginning to create a new video sequence structure which contains info/datastructures needed during decoding: fname : the filename of the MPG-file bufLength : 80000 should do fine loop : 0 : stop at the end of the video sequence 1 : restart from the beginning at the end of the sequence noDisplay : ignore this parameter ditherType : the dithering method used (MPEG-decoding needs to know this) see 7] for a description of possible values for this parameter return value: pointer to the video sequence structure. This pointer should be passed to the function below after decoding is done: void DestroyVidStream (VidStream *astream ); Destroys the allocated datastructures needed during decoding typedef int TimeStamp; Datatype used for generating timing info int mpegVidRsrc (TimeStamp time_stamp , VidStream *vid_stream, char ** pditherFlags); Decodes the next (whichever comes first): MPEG slice MPEG frame MB_QUANTUM macro-blocks (declared in pvgvideo.h) time_stamp : always 0 should do fine vid_stream : the pointer returned by NewVidStream pditherFlags: will be initialized with the correct values. This parameter should afterwards be passed through DoDitherImage (see below) You only need to declare it. return value: (1) When mpegVidRsrc is called the FIRST time: MPEG_INFO mpeg stream was valid + info about mpeg-video is available (cfr. dimp.c where you can find the info) MPEG_INVALID mpeg stream was not valid MPEG_NULL 2 NewVidStream was NOT called first (2) When mpegVidRsrc is called after the first time: MPEG_MB_QUANTUM MB_QUANTUM of macroblocks decoded MPEG_SLICE a slice was decoded MPEG_FRAME_SKIP a frame encountered that was labeled as to be skipped MPEG_FRAME_NODISP a frame decoded that must not be displayed yet MPEG_FRAME_DISP a frame decoded that must be displayed MPEG_ERROR an error was encountered, but processing can continue MPEG_DONE_DISP end of mpeg-video encountered, display last frame MPEG_DONE_NODISP end of mpeg-video encountered, no frame left to display void ResetVidStream(void); Called after decoding the last frame when looping void VidStreamFlags(int type, int loop, int noDisplay); Called whenever the method of dithering is changed type : the new dithering method to be used (see below for possible values) loop : ignore this one noDisplay : ignore this one void TogglePFlag(void); Toggles decoding of P-frames on/off. Initially it will be on. void ToggleBFlag(void); Toggles decoding of B-frames on/off. Initially it will be on. With these two functions you can accelerate the video sequence by decoding: I/P/B frames (all frames) -> normal decoding I/P frames only (call ToggleBFlag()) -> faster decoding I frames only (call TogglePFlag() and ToggleBFlag()) -> fastest decoding PS: P-frames are needed to decode B-frames correctly typedef void FNSTAT(); Used in the statistical version of the player (which generates extensive stat. info about the MPEG video stream currently being decoded) typedef FNSTAT * PFNSTAT; Pointer to the previous function type void PassStats(int showEachFlg, PFNSTAT ShowOneStat, PFNSTAT ShowAllStats); Used to pass the functions: *ShowOneStat : will be called by decode2.dll when stat. information is available about the current frame *ShowAllStats : will be called by decode2.dll when stat. information is available about the current video sequence showEachFlag : 1 : *ShowOneStat is called after decoding each frame 0 : ShowOneStat is never called Statval; Structure used to pass statistical info (see pvgvideo.h for details) void GetStats(Statval ** stat); Call this function to get statistical info about the current frame/whole sequence after it is ready (when ShoneOne(All)Stat(s) is called) 7] DITHER.DLL DESCRIPTION The dither.dll dynamic link library implements functions/data types declared in "pvgdith.h". Look at "dimp.c" to know in which order you should call these functions: void InitDither(int type, int lum_range, int cr_range, int cb_range, PBYTE * pPalette, PBYTE *pPal2); Initializes the necessary data structures needed during dithering type : the used dither method. Here follows a list of possible dither types: (1) 8-bit color dithering methods HYBRID_DITHER HYBRID2_DITHER FS4_DITHER FS2_DITHER FS2FAST_DITHER ORDERED_DITHER ORDERED2_DITHER MBORDERED_DITHER Twox2_DITHER (2) 7-bit gray dithering GRAY_DITHER (3) Full color dithering FULL_COLOR_DITHER (4) No dithering is performed NO_DITHER (5) Black/White dithering MONO_DITHER MONO_THRESHOLD lum_range : 8 will do fine cr_range : 4 will do fine cb_range : 4 will do fine pPalette : OS/2 256 color palette (256 4-byte entries, first three bytes correspond with the R,G and B values. pPal2 : exact copy of the previous parameter void TerminateDither (PBYTE pPalette, PBYTE pPal2); Must be called at the end to free all allocated resources used during dithering void DoDitherImage(unsigned char *l, unsigned char *Cr, unsigned char *Cb, unsigned char *disp, int w, int h, char * f); Dithers a 24-bit image (2x2 color subsampled) using the current dithering method l : pointer to the luminance pane (use "current->luminance" field of your VidStream structure) Cr : pointer to the Cr color pane (use "current->Cr" field of your VidStream structure) Cb : pointer to the Cb color pane (use "current->Cb" field of your VidStream structure) disp : pointer to the buffer where the image should be dithered to w : width of the image in pixels (use "mb_width" field of your VidStream structure multiplied by 16) h : height of the image in pixels (use "mb_height" field of your VidStream structure multiplied by 16) f : dither-flags returned by mpegVidRsrc (use the ditherFlag parameter returned by mpegVidRsrc) 8] DIVE.DLL DESCRIPTION Information about the routines of this dynamic link library can be found in the documentation provided with the IBM Warp 3.0 Toolkit. For info on using the routines cfr. "dimp.c". 9] PLAYER PERFORMANCE I tested the player with many MPEG sequences. Most of them, except for a few, seemed to work well. Via EXTRA (Execution Trace Analyzer, included in the Warp Toolkit) I was able to determine the percentage processor usage (PPU) of the three components of the player: (25sec video, dither method = ORDERED_DITHER) mpg-file -> bobo mjackson whacking iicm waterski son dimp.exe 11 13 12 10 13 12 video.dll 68 64 66 68 64 62 dither.dll 20 23 22 22 23 25 It seams that the PPU is relatively constant for different MPEG sequences. The decoding (video.dll) takes the biggest part, but also the dithering ocupies the CPU 20 to 25% of the time. The overhead of the player dimp.exe which includes DIVE (palette conversion + resizing + blitting) is minimal. Secondly I analyzed the PPU when using different dithering techniques: dither method -> ordered ordered2 gray fs2 fs4 fs2fast hybrid hybrid2 mbordered dimp.exe 11 13 15 7 6 9 12 10 10 video.dll 70 64 83 40 33 50 74 60 65 dither.dll 19 23 2 52 61 41 14 30 24 Here we see big variations in the PPU of the dither.dll module. Fastest is gray- dithering which translates luminance values directly to gray shades. fs4- dithering delivers good quality but is the slowest. Fastest 8-bit color dithering is hybrid while maintaining reasonable quality. Any comments/bug reports/suggestions are appreciated. Please send them to the mail-adress mentionned before. Peter Van Geit 11 juli 1995