[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