[Live-devel] memory sink
abra kadabra
sivrumit at yahoo.com
Mon Feb 1 01:26:48 PST 2010
Hi,
I want to be able to access every frame that arrived from rtp just as the packets arrive from rtp. Frames include i-p(-b) frames; sequence parameter set, picture parameter set frames for h264.
I looked for a way to do this using existing classes (especially sink classes) but could not find a direct way. Existing implementations handle frames on a high level and do not give access to raw data in any way, I guess.
For that purpose, I made a memory sink class (inspired from filesink) that inherits mediasink class and calls an abstract class memorysinkcallable's onPacket method. when I want a class to be notified on packet arrive, I just make that class inherit memorysinkcallable and implement onPacket method.
Even though that works for me, with this approach I need to have one more thread to receive frames from rtp which loops in env->taskScheduler().doEventLoop().
I was wondering if that was the right approach. Since sink classes do what I've implemented internally, I have doubts about my design. Could someone evaluate this approach please?
Thanks in advance,
Umit
Since I can't upload attachments right now, I am writing classes down here. Sorry for the inconvenience.
HEADER FILE:
#ifndef MEMORYSINK_H_
#define MEMORYSINK_H_
#include "MediaSink.hh"
typedef void (callBackFunc)(unsigned char *frameData, uint32_t frameSize);
// classes which chould be notified when new packet arrives should inherit this abstract class
class MemorySinkCallable {
friend class MemorySink;
private:
virtual callBackFunc onPacket = 0;
};
class MemorySink: public MediaSink {
public:
// c++: this calls callable's onpacket method on packet arrive.
static MemorySink* createNew(UsageEnvironment& env, MemorySinkCallable* callable, uint32_t bufferSize = 20000);
// c: this calls function pcallback on packet arrive
//static MemorySink* createNew(UsageEnvironment& env, callBackFunc pCallBack, uint32_t bufferSize = 20000);
// "bufferSize" should be at least as large as the largest expected
// input frame.
void addData(unsigned char* data, uint32_t dataSize);
protected:
//MemorySink(UsageEnvironment& env, callBackFunc pCallBack, uint32_t bufferSize);
MemorySink(UsageEnvironment& env, MemorySinkCallable* callable, uint32_t bufferSize);
virtual ~MemorySink();
protected:
static void afterGettingFrame(void* clientData, unsigned frameSize,
unsigned /*numTruncatedBytes*/,
struct timeval /*presentationTime*/,
unsigned /*durationInMicroseconds*/);
virtual void afterGettingFrame1(uint32_t frameSize);
unsigned char* fBuffer;
unsigned fBufferSize;
//callBackFunc* pCallBackOnFrame;
MemorySinkCallable* pCallable;
private:
virtual Boolean continuePlaying();
};
#endif /* MEMORYSINK_H_ */
SOURCE FILE:
#include "MemorySink.h"
#include "GroupsockHelper.hh"
#include "OutputFile.hh"
void MemorySink::afterGettingFrame1(uint32_t frameSize) {
addData(fBuffer, frameSize);
// Then try getting the next frame:
continuePlaying();
}
MemorySink::~MemorySink() {
delete[] fBuffer;
}
/*MemorySink *MemorySink::createNew(UsageEnvironment & env,
callBackFunc pCallBack, uint32_t bufferSize) {
return new MemorySink(env, pCallBack, bufferSize);
}*/
MemorySink *MemorySink::createNew(UsageEnvironment & env, MemorySinkCallable* callable, uint32_t bufferSize) {
return new MemorySink(env, callable, bufferSize);
}
/*MemorySink::MemorySink(UsageEnvironment & env, callBackFunc* pCallBack,
uint32_t bufferSize) :
MediaSink(env), fBufferSize(bufferSize), pCallBackOnFrame(pCallBack) {
fBuffer = new unsigned char[bufferSize];
}*/
MemorySink::MemorySink(UsageEnvironment & env, MemorySinkCallable* callable, uint32_t bufferSize) :
MediaSink(env), fBufferSize(bufferSize), pCallable(callable) {
fBuffer = new unsigned char[bufferSize];
}
void MemorySink::addData(unsigned char *data, uint32_t dataSize) {
// call callbackfunc to notify about new frame
/*if ((pCallBackOnFrame != NULL) && (data != NULL)) {
(*pCallBackOnFrame)(data, dataSize);*/
if(pCallable != NULL && (data != NULL)) {
pCallable->onPacket(data, dataSize);
data = NULL;
dataSize = 0;
}
}
void MemorySink::afterGettingFrame(void* clientData, unsigned frameSize, unsigned /*numTruncatedBytes*/,
struct timeval /*presentationTime*/, unsigned /*durationInMicroseconds*/) {
MemorySink* sink = (MemorySink*) clientData;
sink->afterGettingFrame1(frameSize);
}
Boolean MemorySink::continuePlaying() {
if (fSource == NULL) {
return False;
}
fSource->getNextFrame(fBuffer, fBufferSize, afterGettingFrame, this, onSourceClosure, this);
return True;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.live555.com/pipermail/live-devel/attachments/20100201/e6d9cec6/attachment.html>
More information about the live-devel
mailing list