Author: afterain I have recently just get it done. Given that many people have developed in this regard, they decided to write some of the experiences during this period. Let the later comrades will take some detours. My example is rewritten through the example of DirectShow. If you are playing in the network, there will be some delay. The details will be explained later. I have made it a DLL (actually the need for work :)), you can download at www.feelby.net. The source code including the presentation example. As for other codes in the DLL, you can refer to my original article, you can find in the 9CBS development document (keyword "Direct"), indicating some of the basic knowledge of DirectShow and his operation.
Let me talk about the overall framework of the Memfile example. In fact, DirectShow has already packaged a few classes, CasyncReader and CasyncStream are our most concerned, CasyncReader is already a source filter, and we only need to control data through the CasyncStream class. The CasyncStream class is simple, all of which are some pure virtual functions. We inherited it and perfected its functions.
Now put the focus of the work in the CasyncStream class. Memfile is inheriting it to get your own class CMemstream. Because this class has some of the overall framework of some functions, I use it as a parent class (of course, it can be inherited directly from CasyncStream). There are three important functions: SetPointer (Longlong LLPOS), Read (Pbyte Pbbuffer, DWORD DWBYTESTOREAD, BOOL BALIGN, LPDWORD PDWBYTESREAD), and SIZE (longlong * psizeavailable). Among them, the weight is the READ function, (in fact I have already discarded the setpointer function). So the data operation is done here. The following is explained by the specific code.
Description of the parameters: M_PBDATA read and writes memory data pointer M_LLLENGTH data Total length m_llposition actually read-written memory data position pointer M_DWKBPERSEC Playback Rate is always error, so the operating memory data pointer M_PBDATA is always wrong, so this pointer is changed. Originally, I plan to use m_llposition to virtual memory space (actually a loop 0 --- max, read the front data, refresh the back, then read, refresh, refresh, to achieve this effect), but to be cumbersome Some critical conditions are difficult to judge. So actually I only use its parameter M_LLLLENGTH. You can learn the use of M_llPosition M_PBData through the source code of Memfile. M_llength is a very important parameter. If you have to do a real-time monitoring of the network, you don't want to play for a few hours. By modifying it can reach the length you need. It is a longlong type, that is, 2 of 64 times. It is enough to play N years:). Note: If you change it, you can't continue playing no matter how you add memory data. DirectShow is automatically stopped after playing this length. First, initialization parameters: m_playbuf = new byte [32768 * 10]; // I defined the data buffer m_buf size = 0; // The data size of the buffer is not played, and there is no data, of course 0m_llens = 4000000000000; // This size is played enough, 4T data hmutex = createmutex (NULL, TRUE, "Protect BUF"); // This is a Handle type, when used to play and add data, the integrity of the protection data is then the read function, It is automatically called, and it is a Work Thread. The parameter pbuffer is the output variable. It is the data to play. PDWbytesRead is also an output variable, indicating the data length read, and the rest is the input variable: HResult Read (Pbyte Pbbuffer, DWORD DWBYTESTOREAD, BOOL Balign, LPDWORD PDWBYTESREAD) {Cautolock LCK; DWORD DWREADLENGTH;
DwreadLength = dwbytestoread; // Only in the last packet change this parameter (because it does not meet the size of 32768, I am not modified by default) /// Handle Buf While (32768> m_buf size); // Wait For Add New Data
WaitForsingleObject (hmutex, 1L); file: // This small section is a key copyMemory (pvoid) pbuffer, (pvoid) m_playbuf, dwreadLength); // From our buffer to play data ReleaseMuteMutex (hmutex); m_buf size - = dwreadLength; // Unplayed data size minus the amount of data just played DWReadley (pvoid) M_PlayBuf, (pvoid) (M_PlayBuf dwreadLength), m_buf size); // Move unplayed data to M_PlayBuf Opening so, we do not need a position pointer M_LLPosition. This is good, that is, M_LLPosition actually plays a time from 229376 from 229376, so the judgment of playback is very troublesome, this is why I discard this parameter. m_llposition = dwreadLength; // This is the Memfile code, I didn't go out * pdwbytesread = dwreadlength; returnif;
The end is how we can update our data? It is reasonable to establish a thread here. The following function is I added to the CMemStream class. Then set a thread in the main program to call the function. LONGLONG ADBUF (PBYTE BUF) {IF (M_BUF Size 32768)> 32768 * 10) {// When the added data exceeds our buffer size, return -1 tells the calling program, the specific processing is determined by the calling program, Is it discarded or reuse retURN-1;} WaitforsingleObject (hmutex, 1L); CopyMemory (M_PlayBuf M_BUF size), (PVOID) BUF, 32768); // Add new data to our own buffer ReleaseMutex (HMUTEX);
m_buf size = 32768; // Unplayed data increased by 32768 bytes return m_buf size;}
Note: There are 32768 this number above. This is its default data size, which is not easy, it is better to write a new source filter. This is the key to the "delay problem" of my most beginning to mention. Because it is necessary to play 32768 bytes of data to play, 32768 is the size of our delay, you must wait until the data is increased to 32768 to give play. If 32768 is a second data for your compressed data, then delay for one second, if it is the amount of data of 3 seconds, then delay 3 seconds. This is the limitations of this class. Want to really write Source Filter yourself. I have seen a real-time product, it seems to have my own Compress and Uncompress Filter. When playing in real-time playback of the network, the most important thing is the synchronization of the data (getting new data and playback), which is the synchronization between the READ () function and the addbuf () function. Synchronization. If addbuf is too fast, the data will be lost, slow, resulting in slow playback speed. I am not very studying for multi-threads, so my playing case is just simple reissue. Of course, you can also lose packets, but you can see the effect of playback. I also have code synchronization, just simple SLEEP () for a while. It is actually tested (local file play, just demonstration. Actual local file play, just retransmit package, do not cause loss of packets). Also use with the network, the measured test is 1-2 seconds. In addition, the loss of the packet does not cause the interruption of the play, just the pause on the screen. The description of the presentation example is just a simple example. A lot of code is not organized. The most important one is to create a thread addbufthreadproc. Constantly add data. DWord AddBufthreadProc (LPVOID P) {cfile f; pbyte buf = new byte [32768]; int EOF = 0; F.Open ("E: //r-161936-0600.mpg", cfile :: moderad); while ( 1) // add buf {eof = f.read (buf, 32768); // get new data, you can change it, example buy set if (eof! = 32768) // if data finish break; // SLEEP ( 175); // this Way, IF add Too Quick, Maybe Can Lost Data While (stream_sendbuf (buf) == - 1); // this Way, Not Lost Data} f.close (); return 0;}
Note: It should be noted that this class is originally reading file, subject to the born limit, is not suitable for real-time playback (especially when your data is relatively 32768, if it is 5 seconds, it is I can't accept it. My project is to adjust the amount of data. When the maximum, the delay is small, only 1 second, the amount of data is more than 5 seconds). If used in real time, it is only suitable for a local area network or a broadband network. Of course, if it is just as a web play file or it is better. If the network speed is low, it is also good to transmit MPEG-4. The default is MPEG-1 format, and you can see how to modify play format, supported by Memfile :). What is good idea or suggestions can be connected: afterain@263.net