From 698a189619d15ba5df8333501a083923e614365a Mon Sep 17 00:00:00 2001 From: Mark Calderbank Date: Sat, 24 Jun 2006 12:23:20 +0000 Subject: [PATCH] MVP/Windows convergence: Stream; DrainTarget --- afeed.cc | 2 +- audio.h | 4 - audiomvp.cc | 21 ++--- audiomvp.h | 12 +-- audiowin.cc | 19 +++- audiowin.h | 7 +- defines.h | 4 - demuxer.cc | 4 +- demuxer.h | 4 +- draintarget.h | 67 ++++++++------ player.cc | 2 + stream.cc | 242 ++++++++++++-------------------------------------- stream.h | 15 ++-- vfeed.cc | 2 +- video.h | 4 - videomvp.cc | 40 +++++---- videomvp.h | 18 ++-- videowin.cc | 19 +++- videowin.h | 7 +- 19 files changed, 205 insertions(+), 288 deletions(-) diff --git a/afeed.cc b/afeed.cc index 7bc8fbf..5f86445 100644 --- a/afeed.cc +++ b/afeed.cc @@ -60,7 +60,7 @@ void AFeed::stop() void AFeed::threadMethod() { - int alen; + bool alen; while(1) { diff --git a/audio.h b/audio.h index a240121..0baaeb2 100644 --- a/audio.h +++ b/audio.h @@ -58,10 +58,6 @@ class Audio : public DrainTarget virtual int mute()=0; virtual int unMute()=0; -#ifndef NEW_DEMUXER - virtual int write(UCHAR* buffer, ULONG length)=0; -#endif - int volumeUp(); int volumeDown(); int getVolume(); diff --git a/audiomvp.cc b/audiomvp.cc index f7a4ab4..3ef84e1 100644 --- a/audiomvp.cc +++ b/audiomvp.cc @@ -228,23 +228,20 @@ int AudioMVP::test() } #endif - -#ifdef NEW_DEMUXER - -UINT AudioMVP::DeliverMediaSample(MediaPacket packet, UCHAR* buffer, UINT *samplepos) +void AudioMVP::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos) { - return 0; + packet = mplist.front(); } -void AudioMVP::ResetTimeOffsets() +UINT AudioMVP::DeliverMediaSample(const UCHAR* buffer, UINT* samplepos) { + int written = ::write(fdAudio, buffer + packet.pos_buffer + *samplepos, + packet.length - *samplepos); + if (written == (int)(packet.length - *samplepos)) {*samplepos = 0; return 1;} + if (written > 0) *samplepos += written; + return 0; } -#else - -int AudioMVP::write(UCHAR* buffer, ULONG length) +void AudioMVP::ResetTimeOffsets() { - return ::write(fdAudio, buffer, length); } - -#endif diff --git a/audiomvp.h b/audiomvp.h index 0178514..52c3b53 100644 --- a/audiomvp.h +++ b/audiomvp.h @@ -55,14 +55,11 @@ class AudioMVP : public Audio int mute(); int unMute(); -#ifdef NEW_DEMUXER - //Writing Data to Audiodevice -- unused in MVP code so far - virtual UINT DeliverMediaSample(MediaPacket packet, UCHAR* buffer, UINT *samplepos); + //Writing Data to Audiodevice + virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos); + virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos); virtual long long SetStartOffset(long long curreftime, bool *rsync) { return 0; }; virtual void ResetTimeOffsets(); -#else - int write(UCHAR* buffer, ULONG length); -#endif #ifdef DEV int test(); @@ -72,6 +69,9 @@ class AudioMVP : public Audio int initAllParams(); UCHAR streamType; int fdAudio; + + MediaPacket packet; + UINT packetpos; }; #endif diff --git a/audiowin.cc b/audiowin.cc index 189731b..097247f 100644 --- a/audiowin.cc +++ b/audiowin.cc @@ -145,8 +145,23 @@ int AudioWin::unMute() return 1; } -UINT AudioWin::DeliverMediaSample(MediaPacket packet, - UCHAR* buffer, +void AudioWin::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos) +{ + mediapacket = mplist.front(); +} + +UINT AudioWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos) +{ + DeliverMediaPacket(mediapacket, buffer, samplepos); + if (*samplepos == mediapacket.length) { + *samplepos = 0; + return 1; + } + else return 0; +} + +UINT AudioWin::DeliverMediaPacket(MediaPacket packet, + const UCHAR* buffer, UINT *samplepos) { /*First Check, if we have an audio sample*/ diff --git a/audiowin.h b/audiowin.h index 52690b5..b297519 100644 --- a/audiowin.h +++ b/audiowin.h @@ -49,7 +49,12 @@ class AudioWin : public Audio int write(char *buf, int len); // Writing Data to Audiodevice - virtual UINT DeliverMediaSample(MediaPacket packet, UCHAR* buffer, UINT *samplepos); + virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos); + virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos); + UINT DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos); + private: + MediaPacket mediapacket; + public: virtual long long SetStartOffset(long long curreftime, bool *rsync); virtual void ResetTimeOffsets(); diff --git a/defines.h b/defines.h index d3c1f0d..a1a7d7d 100644 --- a/defines.h +++ b/defines.h @@ -21,10 +21,6 @@ #ifndef DEFINES_H #define DEFINES_H -//#define NEW_DEMUXER //Switch for the new demuxer code -//At the beginning the changed code will be switchable -//in order to apply the changes also to the mvp code - typedef unsigned char UCHAR; typedef unsigned short USHORT; typedef unsigned int UINT; diff --git a/demuxer.cc b/demuxer.cc index 8e97ec6..90db814 100644 --- a/demuxer.cc +++ b/demuxer.cc @@ -145,12 +145,12 @@ void Demuxer::setAspectRatio(enum AspectRatio ar) arcnt = 0; } -int Demuxer::writeAudio() +bool Demuxer::writeAudio() { return audiostream.drain(); } -int Demuxer::writeVideo() +bool Demuxer::writeVideo() { return videostream.drain(); } diff --git a/demuxer.h b/demuxer.h index 7e0f88d..c4c9392 100644 --- a/demuxer.h +++ b/demuxer.h @@ -73,8 +73,8 @@ protected: void seek(); void setVideoStream(int id); void setAudioStream(int id); - int writeAudio(); - int writeVideo(); + bool writeAudio(); + bool writeVideo(); virtual int scan(UCHAR* buf, int len) = 0; virtual int findVideoPTS(UCHAR* buf, int len, ULLONG* dest) = 0; diff --git a/draintarget.h b/draintarget.h index 380979b..74d5862 100644 --- a/draintarget.h +++ b/draintarget.h @@ -24,55 +24,66 @@ #include "defines.h" #include - -#ifdef NEW_DEMUXER - struct MediaPacket { - ULLONG recording_byte_pos; //position in recording - ULLONG pts; ULONG pos_buffer; //position in stream buffer ULONG length; //length of the packet - //The last to are only needed on windows, for memory reasons they can be excluded in mvp + // The fields below are not needed by the MVP +#ifdef WIN32 + ULLONG recording_byte_pos; //position in recording + ULLONG pts; long long presentation_time;/* in 100 ns units*/ bool synched; bool disconti; +#endif }; using namespace std; - typedef list MediaPacketList; -#endif - class DrainTarget { public: DrainTarget(); virtual ~DrainTarget(); -#ifdef NEW_DEMUXER - - virtual UINT DeliverMediaSample(MediaPacket packet, UCHAR* buffer, UINT *samplepos)=0; - - /* This function behaviour should be: - Try to deliver the Data from packet.pos_buffer+samplepos to packet.pos_buffer+packet.length, - with considering the bufferwraparound according to buffersize. - Then increasing samplepos, so that on the next call delivering can proceed. So if writebytes are - writen samplepos=samplepos+writebytes! - If samplepos>=packet.length is returned, the next packet can be used for the next call.*/ - virtual long long SetStartOffset(long long curreftime, bool *rsync)=0; virtual void ResetTimeOffsets()=0; -#else - virtual int write(UCHAR* buffer, ULONG length)=0; -#endif - +// The following two functions are used by the Stream +// to deliver media packets to the front end (DrainTarget). +// +// First, the Stream calls PrepareMediaSample, which gives the front end +// read-only access to the Stream's MediaPacketList. PrepareMediaSample should +// examine the list to determine how much it wishes to consume, and +// should copy any data it requires from the MediaPacket objects into +// local storage. +// This function call takes place under a mutex lock to ensure integrity +// of the list structure. It should be fast and must not contain any +// cancellation points, such as I/O calls for logging. +// +// Second, the Stream releases the mutex and calls DeliverMediaSample. +// This function delivers data from the Stream buffer to the presentation +// device and returns information to the Stream regarding how many MediaPackets +// were consumed. Any data copied from the MediaPackets objects during +// PrepareMediaSample is guaranteed by the Stream still to be valid +// during the following DeliverMediaSample call. + + // samplepos is equal to the number of bytes from the first MediaPacket + // in the list that have already been consumed in a previous call. + virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos)=0; + + // The Stream guarantees that the value of *samplepos passed to + // DeliverMediaSample will be equal to the value of samplepos passed to + // PrepareMediaSample in the previous call. + // This function should consume data from the buffer according to the + // decisions made in PrepareMediaSample. Its return value and *samplepos + // tell the Stream how much data it consumed. + // If DeliverMediaSample returns X, the Stream will remove packets 0 to X-1 + // (inclusive) from the list before the next call. + // DeliverMediaSample must also set *samplepos equal to the number of bytes + // processed from packet X (usually zero). + virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)=0; }; - - - #endif - diff --git a/player.cc b/player.cc index bdacba5..7477586 100644 --- a/player.cc +++ b/player.cc @@ -293,6 +293,8 @@ int Player::playInt(bool* doUnlock) else // do prebuffering { logger->log("Player", Log::DEBUG, "Prebuffering..."); +// afeed.start(); +// vfeed.start(); preBuffering = true; } diff --git a/stream.cc b/stream.cc index 6a4531e..21b847a 100644 --- a/stream.cc +++ b/stream.cc @@ -1,5 +1,5 @@ /* - Copyright 2005 Mark Calderbank + Copyright 2005-2006 Mark Calderbank This file is part of VOMP. @@ -19,14 +19,13 @@ */ #include "stream.h" +#include "log.h" Stream::Stream() { initted = 0; - draintarget=NULL; -#ifdef NEW_DEMUXER - cur_packet_pos=0; -#endif + draintarget = NULL; + cur_packet_pos = 0; } Stream::~Stream() @@ -36,16 +35,14 @@ Stream::~Stream() void Stream::shutdown() { - if (initted) { - free(outbuf); -#ifdef NEW_DEMUXER + if (initted) + { + free(outbuf); #ifdef WIN32 - CloseHandle(mutex); -#endif + CloseHandle(mutex); #endif } initted = 0; - } int Stream::init(DrainTarget* tdt, int bufsize) @@ -54,82 +51,31 @@ int Stream::init(DrainTarget* tdt, int bufsize) if (!outbuf) return 0; draintarget = tdt; bufferSize = bufsize; - bufferHead = 0; - bufferTail = 0; - bufferMark = -1; initted = 1; -#ifdef NEW_DEMUXER #ifndef WIN32 pthread_mutex_init(&mutex, NULL); #else mutex=CreateMutex(NULL,FALSE,NULL); -#endif #endif return 1; } void Stream::flush() { -#ifdef NEW_DEMUXER lock(); mediapackets.clear(); unLock(); if (draintarget) draintarget->ResetTimeOffsets(); -#endif - bufferHead = 0; - bufferTail = 0; - bufferMark = -1; } -#ifndef NEW_DEMUXER -int Stream::put(UCHAR* inbuf, int len) +int Stream::put(const UCHAR* inbuf, int len) { int ret = 0; - int tail = bufferTail; - int head = bufferHead; - if (tail == 0) tail = bufferSize; - - if (head < tail) - { - // The free space is in one continuous chunk. - if (len < tail - head) - { - memcpy(outbuf + head, inbuf, len); - bufferHead += len; - ret = len; - } - } - else if (len <= bufferSize - head) - { - // There is enough space above the Head. - memcpy(outbuf + head, inbuf, len); - if (head + len == bufferSize) - bufferHead = 0; - else - bufferHead += len; - ret = len; - } - else if (len < tail) - { - bufferMark = head; - memcpy(outbuf, inbuf, len); - bufferHead = len; - ret = len; - } - return ret; -} -#else -int Stream::put(UCHAR* inbuf, int len) -{ - int ret = 0; - int tail = bufferTail; - int head = bufferHead; - if (tail == 0) tail = bufferSize; - if (!draintarget) return 0; MediaPacket newPacket; - newPacket.length=len; - newPacket.pos_buffer=0; + newPacket.length = len; + newPacket.pos_buffer = 0; +#ifdef WIN32 newPacket.synched=false; newPacket.disconti=false; newPacket.pts=0; @@ -146,142 +92,66 @@ int Stream::put(UCHAR* inbuf, int len) newPacket.presentation_time=(ULLONG)(newPacket.pts*10000LL/90LL); newPacket.presentation_time-=draintarget->SetStartOffset(newPacket.presentation_time,&newPacket.disconti); } +#endif - if (head < tail) + lock(); + int front, back; + if (mediapackets.empty()) { - // The free space is in one continuous chunk. - if (len < tail - head) - { - memcpy(outbuf + head, inbuf, len); - bufferHead += len; - ret = len; - newPacket.pos_buffer=head; - lock(); - mediapackets.push_front(newPacket); - unLock(); - } + back = 0; front = bufferSize; } - else if (len <= bufferSize - head) + else { - // There is enough space above the Head. - memcpy(outbuf + head, inbuf, len); - if (head + len == bufferSize) - bufferHead = 0; - else - bufferHead += len; - - newPacket.pos_buffer=head; - lock(); - mediapackets.push_front(newPacket); - unLock(); + front = mediapackets.front().pos_buffer; + back = mediapackets.back().pos_buffer + mediapackets.back().length; + if (back == bufferSize) back = 0; + } + unLock(); + if (back <= front) + { + // The free space (if any) is in one continuous chunk. + if (len <= front - back) ret = len; // Is there enough of it? + } + else if (len <= bufferSize - back) + { + // There is enough space at the end of the buffer ret = len; } - else if (len < tail) + else if (len <= front) { - bufferMark = head; - memcpy(outbuf, inbuf, len); - bufferHead = len; + // There is enough space at the start of the buffer + back = 0; ret = len; - newPacket.pos_buffer=0; - lock(); - mediapackets.push_front(newPacket); - unLock(); } - return ret; -} -#endif - -#ifndef NEW_DEMUXER - -int Stream::drain() -{ - int ret = 0; - int head = bufferHead; - int tail = bufferTail; - int mark = bufferMark; - int written; - if (mark == -1 && tail > head) mark = bufferSize; - - if (mark >= 0) + if (ret) // Nonzero if we managed to find room for the packet { - // Drain up to the marker. -#ifndef WIN32 - written = draintarget->write(outbuf + tail, (mark - tail)); -#else - written=mark-tail; - MILLISLEEP(1); -#endif - if (written < 0) return ret; - ret += written; - if (written == (mark - tail)) - { - bufferMark = -1; - bufferTail = tail = 0; - } - else - { - bufferTail += written; - return ret; - } + memcpy(outbuf + back, inbuf, len); + newPacket.pos_buffer = back; + lock(); + mediapackets.push_back(newPacket); + unLock(); } - - if (tail == head) return ret; // Empty -#ifndef WIN32 - written = draintarget->write(outbuf + tail, (head - tail)); -#else - written=(head - tail); - MILLISLEEP(1); -#endif - if (written < 0) return ret; - ret += written; - bufferTail = tail + written; return ret; } -#else - -int Stream::drain() +bool Stream::drain() { - int ret = 0; - int written=1; -// draintarget=dt; // this is now set in init, is this ok? - - - - if (mediapackets.empty()) { - return 0; - } - // using mediapackets, may be this is slower but it is more flexible - // while (!mediapackets.empty() && written) { - - int head = bufferHead; - int tail = bufferTail; - int mark = bufferMark; - if (mark == -1 && tail > head) mark = bufferSize; + bool ret = false; lock(); - MediaPacket cur_mp=mediapackets.back(); - unLock(); - written=0; - written=draintarget->DeliverMediaSample(cur_mp,outbuf,&cur_packet_pos); - - ret+=written; - - if (cur_packet_pos==cur_mp.length) { - cur_packet_pos=0; - lock(); - mediapackets.pop_back(); - unLock(); - if ((((ULONG)tail)+cur_mp.length) < ((ULONG)mark)) { - bufferTail=tail+cur_mp.length; - } else { - bufferTail=0; - bufferMark=-1; - } - + UINT listlength = mediapackets.size(); + if (listlength != 0) + { + draintarget->PrepareMediaSample(mediapackets, cur_packet_pos); + unLock(); + UINT consumed = draintarget->DeliverMediaSample(outbuf, &cur_packet_pos); + lock(); + if (consumed != 0) ret = true; + if (consumed > listlength) consumed = listlength; + while (consumed--) mediapackets.pop_front(); } - + unLock(); return ret; } @@ -289,7 +159,7 @@ void Stream::lock() { #ifndef WIN32 pthread_mutex_lock(&mutex); - logger->log("Player", Log::DEBUG, "LOCKED"); + //logger->log("Player", Log::DEBUG, "LOCKED"); #else WaitForSingleObject(mutex, INFINITE ); @@ -299,11 +169,9 @@ void Stream::lock() void Stream::unLock() { #ifndef WIN32 - logger->log("Player", Log::DEBUG, "UNLOCKING"); + //logger->log("Player", Log::DEBUG, "UNLOCKING"); pthread_mutex_unlock(&mutex); #else ReleaseMutex(mutex); #endif } - -#endif diff --git a/stream.h b/stream.h index 507855b..d963330 100644 --- a/stream.h +++ b/stream.h @@ -21,6 +21,10 @@ #ifndef STREAM_H #define STREAM_H +#ifndef WIN32 +#include +#endif + #include #ifndef WIN32 #include @@ -32,8 +36,6 @@ #include "defines.h" #include "draintarget.h" - - class Stream { public: @@ -42,11 +44,10 @@ class Stream int init(DrainTarget* tdt, int bufsize); void shutdown(); void flush(); - int put(UCHAR* inbuf, int len); - int drain(); + int put(const UCHAR* inbuf, int len); + bool drain(); private: -#ifdef NEW_DEMUXER MediaPacketList mediapackets; UINT cur_packet_pos; #ifndef WIN32 @@ -56,15 +57,11 @@ class Stream #endif void lock(); void unLock(); -#endif DrainTarget* draintarget; int initted; UCHAR* outbuf; int bufferSize; - volatile int bufferHead; - volatile int bufferTail; - volatile int bufferMark; }; #endif diff --git a/vfeed.cc b/vfeed.cc index 4fd4657..0255b98 100644 --- a/vfeed.cc +++ b/vfeed.cc @@ -53,7 +53,7 @@ void VFeed::release() void VFeed::threadMethod() { - int vlen; + bool vlen; threadWaitForSignal(); // Don't feed video until audio has started diff --git a/video.h b/video.h index 660e3e9..026aee2 100644 --- a/video.h +++ b/video.h @@ -65,10 +65,6 @@ class Video: public DrainTarget virtual ULONG timecodeToFrameNumber(ULLONG timecode)=0; virtual ULLONG getCurrentTimestamp()=0; -#ifndef NEW_DEMUXER - virtual int write(UCHAR* buffer, ULONG length)=0; -#endif - virtual void turnVideoOn(){}; virtual void turnVideoOff(){}; virtual ULLONG frameNumberToTimecode(ULONG timecode) { return 0; }; diff --git a/videomvp.cc b/videomvp.cc index 43e84a7..279a134 100644 --- a/videomvp.cc +++ b/videomvp.cc @@ -366,25 +366,35 @@ int VideoMVP::test2() } #endif - - -#ifdef NEW_DEMUXER - -UINT VideoMVP::DeliverMediaSample(MediaPacket packet, UCHAR* buffer, UINT *samplepos) -{ - return 0; +void VideoMVP::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos) +{ + MediaPacketList::const_iterator iter = mplist.begin(); + deliver_start = iter->pos_buffer + samplepos; + mediapacket_len[0] = deliver_length = iter->length; + deliver_count = 1; + while (++iter != mplist.end() && + iter->pos_buffer == deliver_start + deliver_length) + { + deliver_length += iter->length; + mediapacket_len[deliver_count] = iter->length; + ++deliver_count; + if (deliver_length >= WRITE_LENGTH || + deliver_count == WRITE_PACKETS) break; + } } -void VideoMVP::ResetTimeOffsets() +UINT VideoMVP::DeliverMediaSample(const UCHAR* buffer, UINT* samplepos) { + int written = ::write(fdVideo, buffer + deliver_start, deliver_length); + if (written == (int)deliver_length) { *samplepos = 0; return deliver_count;} + if (written <= 0) return 0; + // Handle a partial write. Is this possible? Should we bother? + UINT i = 0; + while ((written -= mediapacket_len[i]) >= 0) i++; + *samplepos = mediapacket_len[i] + written; + return i; } -#else - -int VideoMVP::write(UCHAR* buffer, ULONG length) +void VideoMVP::ResetTimeOffsets() { - return ::write(fdVideo, buffer, length); } - -#endif - diff --git a/videomvp.h b/videomvp.h index 3f626d2..b8db9c6 100644 --- a/videomvp.h +++ b/videomvp.h @@ -36,6 +36,9 @@ #include "video.h" #include "stb.h" +#define WRITE_LENGTH (32*1024) // Consume up to 32K at a time from Stream +#define WRITE_PACKETS 16 // But no more than 16 packets + class VideoMVP : public Video { public: @@ -68,14 +71,12 @@ class VideoMVP : public Video ULONG timecodeToFrameNumber(ULLONG timecode); ULLONG getCurrentTimestamp(); -#ifdef NEW_DEMUXER - //Writing Data to Videodevice - virtual UINT DeliverMediaSample(MediaPacket packet, UCHAR* buffer, UINT *samplepos); - virtual long long SetStartOffset(long long curreftime, bool *rsync) { return 0; }; + // Writing Data to Videodevice + virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos); + virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT* samplepos); + virtual long long SetStartOffset(long long curreftime, bool *rsync) + { return 0; }; virtual void ResetTimeOffsets(); -#else - int write(UCHAR* buffer, ULONG length); -#endif #ifdef DEV int test(); @@ -85,6 +86,9 @@ class VideoMVP : public Video private: int checkSCART(); void setLetterboxBorder(char* border); + + UINT deliver_start, deliver_length, deliver_count; + UINT mediapacket_len[WRITE_PACKETS]; }; #endif diff --git a/videowin.cc b/videowin.cc index d029886..35ddff6 100644 --- a/videowin.cc +++ b/videowin.cc @@ -453,9 +453,24 @@ void VideoWin::CleanupDS() } +void VideoWin::PrepareMediaSample(const MediaPacketList& mplist, + UINT samplepos) +{ + mediapacket = mplist.front(); +} + +UINT VideoWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos) +{ + DeliverMediaPacket(mediapacket, buffer, samplepos); + if (*samplepos == mediapacket.length) { + *samplepos = 0; + return 1; + } + else return 0; +} -UINT VideoWin::DeliverMediaSample(MediaPacket packet, - UCHAR* buffer, +UINT VideoWin::DeliverMediaPacket(MediaPacket packet, + const UCHAR* buffer, UINT *samplepos) { /*First Check, if we have an audio sample*/ diff --git a/videowin.h b/videowin.h index 5176d6a..23f558f 100644 --- a/videowin.h +++ b/videowin.h @@ -73,7 +73,12 @@ class VideoWin : public Video ULLONG getCurrentTimestamp(); //Writing Data to Videodevice - virtual UINT DeliverMediaSample(MediaPacket packet, UCHAR* buffer, UINT *samplepos); + virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos); + virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos); + UINT DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos); + private: + MediaPacket mediapacket; + public: int getCurrentAudioMediaSample(IMediaSample** ms); int DeliverAudioMediaSample(); -- 2.39.5