[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