[Live-devel] How to assign sinks to subsessions

Shaheed Abdol Shaheed at scansoft.co.za
Tue Feb 14 05:13:40 PST 2012


Good afternoon,
 
As a second post to this list, I have to thank you for your first
advice, I was definitely using the wrong testProg to start with. I have
since reworked the testRTSPClient code to function in the fashion that I
wish, but still cannot get both subsessions to provide data to me. Allow
me to explain my use-case:
 
I am trying to obtain the audio/video stream from a Vivotek IP camera
(FD8161), so far I can obtain either the video stream (by supplying a
flag stating that I only want to create the video or audio sink) or the
audio stream perfectly. The moment I try to create two sinks to handle
the data from each subsession, then I fail to get data passed to me in
the afterGettingFrame function of my custom sinks. I know the sinks
should be working fine since it works individually, I will provide the
snippet of code which assigns the sinks to their respective subsessions,
this snippet is what I've modified to create seperate sinks for audio
and video data:
 
...
void SetupStreams()
{
static MediaSubsessionIterator* setupIter = NULL;

if (g_session == NULL)

{

Shutdown();

return;

}

if (setupIter == NULL)

setupIter = new MediaSubsessionIterator(*g_session);

while ((g_setupSubsession = setupIter->next()) != NULL) 

{

// We have another subsession left to set up:

if (g_setupSubsession->clientPortNum() == 0) 

continue; // port # was not set

SetupSubsession(g_setupSubsession, false,
&CStreamReceiver::ContinueAfterSETUP);

g_madeSetupProgress = true;

return;

}

// We're done setting up subsessions.

delete setupIter;

setupIter = NULL;

//if (!g_madeSetupProgress)

// Shutdown();

g_madeSetupProgress = false;

MediaSubsessionIterator iter(*g_session);

while ((g_setupSubsession = iter.next()) != NULL) 

{

if (g_setupSubsession->readSource() == NULL) 

continue; // was not initiated

PAYLOAD_FORMAT destFormat = PAYLOAD_NONE; //-1

//params.type - The type of input device

//payloadType - the input format

//params.format - the desired output format

//Find a sink that converts from payload type to output type (params).
Use recursive function. Chain together.

if (g_audioHandler && stricmp(g_setupSubsession->mediumName(), "audio")
== 0)

{

//Need to figure out what the required destination format is.
PCM/RGB24/etc. (params.type)

map<string, string> params =
TokenizeParameters(g_audioHandler->GetOutputFormatParams());

map<string, string>::iterator itr;

itr = params.find("DestinationFormatAudio");

if (itr != params.end())

destFormat = (PAYLOAD_FORMAT)(strtol((*itr).second.c_str(), NULL, 10));

//create a payload details struct specifically for each sink, cannot use
one global struct for two subsession streams.

sPayloadInfo info;

info.payloadType =
(PAYLOAD_FORMAT)g_setupSubsession->rtpPayloadFormat(); //hopefully this
populates with constant invalid values (that can be checked against)

info.channels = g_setupSubsession->numChannels();

info.frequency = g_setupSubsession->rtpTimestampFrequency();

if (info.payloadType == PAYLOAD_PCMU || info.payloadType ==
PAYLOAD_PCMA)

info.bits = 16; //hopefully this is the correct value. (based on u-law
documen tation)

g_audioMediaSink = g_setupSubsession->sink = static_cast<MediaSink
*>(CFFMPEGAudioMediaSink::createNew(*g_env, g_audioHandler, info,
destFormat));

}

else if (g_videoHandler && stricmp(g_setupSubsession->mediumName(),
"video") == 0) //make sure this subsession is a video stream

{

//Need to figure out what the required destination format is.
PCM/RGB24/etc. (params.type)

map<string, string> params =
TokenizeParameters(g_videoHandler->GetOutputFormatParams());

map<string, string>::iterator itr;

itr = params.find("DestinationFormatVideo");

if (itr != params.end())

destFormat = (PAYLOAD_FORMAT)(strtol((*itr).second.c_str(), NULL, 10));

sPayloadInfo info;

info.payloadType =
(PAYLOAD_FORMAT)g_setupSubsession->rtpPayloadFormat(); //hopefully this
populates with constant invalid values (that can be checked against)

info.channels = g_setupSubsession->numChannels();

info.frequency = g_setupSubsession->rtpTimestampFrequency();

//I'm sure there must be a way to get bpp, etc out of the subsession.

g_videoMediaSink = g_setupSubsession->sink = static_cast<MediaSink
*>(CFFMPEGVideoMediaSink::createNew(*g_env, g_videoHandler, info,
destFormat));

}

else

{

g_setupSubsession->sink = NULL;

LOG((*g_logger), "Failed to create sink for - " <<
g_setupSubsession->mediumName());

}

if (g_setupSubsession->sink)

{

LOG((*g_logger), "Playing sink - " << g_setupSubsession->mediumName());

g_setupSubsession->sink->startPlaying(*(g_setupSubsession->readSource())
, SubsessionAfterPlaying, g_setupSubsession);

// Also set a handler to be called if a RTCP "BYE" arrives for this
subsession:

if (g_setupSubsession->rtcpInstance() != NULL) 

g_setupSubsession->rtcpInstance()->setByeHandler(&CStreamReceiver::Subse
ssionByeHandler, g_setupSubsession);

g_madeSetupProgress = true;

}

}

if (!g_madeSetupProgress) 

Shutdown();

// Finally, start playing each subsession, to start the data flow:

if (g_duration == 0) 

{

if (g_scale > 0) 

g_duration = g_session->playEndTime() - g_initialSeekTime; // use SDP
end time

else if (g_scale < 0) 

g_duration = g_initialSeekTime;

}

if (g_duration < 0) 

g_duration = 0.0;

g_endTime = g_initialSeekTime;

if (g_scale > 0) 

{

if (g_duration <= 0) 

g_endTime = -1.0f;

else 

g_endTime = g_initialSeekTime + g_duration;

} 

else

{

g_endTime = g_initialSeekTime - g_duration;

if (g_endTime < 0)

g_endTime = 0.0f;

}

StartPlayingSession(g_session, g_initialSeekTime, g_endTime, g_scale,
&CStreamReceiver::ContinueAfterPLAY);

 
I can confirm that the parameters are correct to each subsession and to
each sink, which I have logs for which indicate that everything
succeeds, but the data simply does not stream, possibly it's a deadlock,
or a function I should be calling... I have written a filter for the
MPEG4 (using FFMPEG), and a simple audio filter to conver the
u-law/a-law data (camera supports both) to 16-bit signed linear pcm data
- which plays perfectly. I just need a tiny nudge in the right
direction. I have included my SDP response from the camera, just in case
I have misread something and the camera requires another step.
 
v=0
 
o=RTSP 959993539 572 IN IP4 0.0.0.0
 
s=RTSP server
 
c=IN IP4 0.0.0.0
 
t=0 0
 
a=charset:Shift_JIS
 
a=range:npt=0-
 
a=control:*
 
a=etag:1234567890
 
m=video 0 RTP/AVP 96
 
b=AS:0
 
a=rtpmap:96 MP4V-ES/30000
 
a=control:trackID=1
 
a=fmtp:96
profile-level-id=3;config=000001B003000001B509000001010000012000845D4C28
C82258A200;decode_buf=76800
 
m=audio 0 RTP/AVP 0
 
a=control:trackID=6
 
a=rtpmap:0 pcmu/8000
 
Thank you
Regards
___________________________________

Shaheed Abdol

 

Web: www.scansoft.co.za <http://www.scansoft.co.za/> 
Tel:  +27 21 913 8664
Cell: +27 79 835 8771
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.live555.com/pipermail/live-devel/attachments/20120214/64a32242/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: image/png
Size: 32497 bytes
Desc: SST Email.png
URL: <http://lists.live555.com/pipermail/live-devel/attachments/20120214/64a32242/attachment-0001.png>


More information about the live-devel mailing list