[Live-devel] Buffered MPEG2-TS to RTP how-to
Russell Brennan
rjbrennn at gmail.com
Mon Jun 25 12:28:04 PDT 2007
I have figured out how to do this, so here is the basis of my code, and some
hanging unanswered questions... the code is mostly
testMPEG2TransportStreamer.cpp.
#include <fstream>
#include <math.h>
#include <vector>
#include "liveMedia.hh"
#include "BasicUsageEnvironment.hh"
#include "GroupsockHelper.hh"
// To stream using "source-specific multicast" (SSM), uncomment the
following:
//#define USE_SSM 1
#ifdef USE_SSM
Boolean const isSSM = True;
#else
Boolean const isSSM = False;
#endif
// To set up an internal RTSP server, uncomment the following:
//#define IMPLEMENT_RTSP_SERVER 1
// (Note that this RTSP server works for multicast only)
#define TRANSPORT_PACKET_SIZE 188
#define TRANSPORT_PACKETS_PER_NETWORK_PACKET 7
class pipeToRTP {
public:
// Constructor and destructor
pipeToRTP();
// Primitive execution method
void execute();
protected:
//-----------------------------------------------------------------------
// Variable Declarations
//-----------------------------------------------------------------------
char rtpFileName_[L_tmpnam];
string destAddressStr_;
unsigned short rtpPortNum_;
//-----------------------------------------------------------------------
// Method Declarations
//-----------------------------------------------------------------------
void preamble();
void setupRTP();
void compute();
void play();
void postamble();
// Buffers
char cBuffer_[MAX_GRAB]; // Ouput of FEC is a type 1000 SB
// RTP objects
UsageEnvironment* env;
FramedSource* videoSource;
RTPSink* videoSink;
BasicTaskScheduler* scheduler;
ByteStreamFileSource* Source;
ofstream outPipe_;
};
/**
* pipeToRTP Constructor
*/
pipeToRTP::pipeToRTP() {
tmpnam(rtpFileName_); // make a random filename
}
/**
* Class Execution
*/
void pipeToRTP::execute() {
preamble();
m_sync();
setupRTP();
//compute(); // Called via setupRTP()
postamble();
}
/**
* Preamble
* Initializes file headers, variables, and buffers
*/
void pipeToRTP::preamble() {}
/**
* Main loop
* This is where the data packets are pushed to a file stream
*/
void pipeToRTP::compute() {
while (m_do(lper_, hin_.xfer_len)) {
// Grab to our unix pipe
m_grabx(hin_, cBuffer_, ngot_);
if (ngot_ > 0) {
// Send out the packet to Unix pipe
outPipe_.write(cBuffer_, ngot_); // write a block of data
scheduler->SingleStep(0); // Made this guy public
}
}
}
/**
* Postamble
* Performs post-processing tasks such as closing file headers and freeing
* memory.
*/
void pipeToRTP::postamble() {
#ifdef DEBUG
*env << "...done reading from file\n";
#endif
Medium::close(videoSource);
// Note that this also closes the input file that this source read from.
outPipe_.close();
exit(1);
}
/**
* Main Routine
* Instantiates an instance of the class and calls the execution method
*/
void mainroutine() {
pipeToRTP p;
try {
p.execute();
}
catch (...) {
m_error("Primitive execution failed (pipeToRTP)");
}
}
/**
* setupRTP
* Initializes RTP environment.
*/
void pipeToRTP::setupRTP() {
// Begin by setting up our usage environment:
scheduler = BasicTaskScheduler::createNew();
env = BasicUsageEnvironment::createNew(*scheduler);
...
#ifdef DEBUG
*env << "Beginning streaming...\n";
#endif
outPipe_.open(rtpFileName_); // Open the file
if (!outPipe_) {
cerr << "Could not open fifo for output" << endl;
exit(1);
}
play();
compute();
}
void afterPlaying(void* /*clientData*/) {
// Just for the compiler
}
void pipeToRTP::play() {
unsigned const inputDataChunkSize
= TRANSPORT_PACKETS_PER_NETWORK_PACKET*TRANSPORT_PACKET_SIZE;
// Open the input as a 'byte-stream file source':
Source = ByteStreamFileSource::createNew(*env, rtpFileName_,
inputDataChunkSize);
if (Source == NULL) {
*env << "Unable to open file \"" << rtpFileName_
<< "\" as a byte-stream file source\n";
exit(1);
}
// Create a 'framer' for the input source (to give us proper inter-packet
gaps):
videoSource = MPEG2TransportStreamFramer::createNew(*env, Source);
// Finally, start playing:
#ifdef DEBUG
*env << "Beginning to read from file...\n";
#endif
videoSink->startPlaying(*videoSource, afterPlaying, videoSink);
}
Right, so the only way I could manage to get this working was to use an
ofstream object to write my data to, using a random filename which was
passed to ByteStreamFileSource::createNew. Also, teh above functions play()
and compute() HAD to be withing setupRTP() or else I would get a bad file
descriptor error from select()... this probably has something to do with
scope, but I will not investigate this further. Performace seems to be
good, this uses minimal cpu cycles on my machine.
If anyone has a better alternative to ofstream, I would be happy to hear it!
Russell
On 6/19/07, Russell Brennan <rjbrennn at gmail.com> wrote:
>
> Hello,
>
> I am trying to take a buffer of MPEG2-TS data which is constantly written
> to, and hook it up to live555 for output via RTP. I am currently basing my
> work on the testMEPG2TransportStreamer code, but obviously this was designed
> to stream a file.
> My current idea is not really panning out, due to the fact that I am
> apparently confused... ByteStreamFileSource is used in the test program,
> but it seems that I will need to use a different type of source. Is there
> an existing MediaSource that will work, or will I need to create my own?
>
> Also, MPEG2TransportStreamFramer is used as the videosource to
> videoSink->startPlaying . This would seem to still be valid for what I am
> doing, correct?
>
> Lastly, doEventLoop seems to continuously call SingleStep(), and from what
> I can make of this function, it seems that in some way this is where the
> data to be sent out is packaged and sent. Assuming that I get
> acknowledgement each time my buffer is ready to be sent out, can I simply
> call SingleStep() each time I have data to send?
>
> I hope I was clear enough... Thanks in advance!
>
> --
> Russell Brennan
>
>
--
Russell Brennan
RJBrennn at gmail.com
(708) 699-7314
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.live555.com/pipermail/live-devel/attachments/20070625/e6ea7dbf/attachment.html
More information about the live-devel
mailing list