Sending my own audio frames

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 
It is finaly working. Thanks alot Norman for your help.
 
 
To anyone who is interested in sending PCM audio frames colected outside of pjsip:
 
// Create a pjmedia_port
pjmedia_port port;
 
// init it's info
pjmedia_port_info_init(&port.info, &name, signature, samplingRate, channelCount, bitsPerSample, samplesPerFrame);
 
// Set it's callback functions
port.get_frame = &get_frame;
port.put_frame = &put_frame;
port.on_destroy = &on_destroy;
 
// Add port to conference bridge
pjmedia_conf_add_port(conference_bridge, pool_vars, &port, NULL, &slot);
 
// Connect the port to the call's conference slot
pjmedia_conf_connect_port(SIPEngine::instance->conference_bridge, slot, call_port, 0);
 
 
// Implement the get_frame...the method called by pjsip to get new audio frames to send
pj_status_t get_frame(struct pjmedia_port* this_port, pjmedia_frame* frame) {
 
     .... code to get an audio frame to be sent
 
     return PJ_SUCCESS;
}
 
// The put_frame method is a simple one...because we only send frames
pj_status_t put_frame(struct pjmedia_port* this_port, const pjmedia_frame* frame) { 
    return PJ_EINVALIDOP;
}
// The on_destroy has to have the following lines of code
pj_status_t on_destroy(struct pjmedia_port* this_port) {
 
     ....
 
     pjmedia_conf_remove_port(conference_bridge, slot);
 
     ...
 
     pjmedia_port_destroy(port);
 
     ...
 
     return PJ_SUCCESS;
}
 
I hope this helps anyone who add the same problems has i did...
 
Rafael Maia
 
 
From: norman@myasd.comTo: pjsip at lists.pjsip.orgDate: Mon, 12 Jan 2009 16:09:50 -0500Subject: Re: Sending my own audio framesYou need to connect it to the port associated with the active call as well. PJ is very flexible with audio routing, so you need to explicitly connect up everything that should "hear" your source. Your player should connect to the user's speakers and the call or calls in progress.




Norman Franke
Answering Service for Directors, Inc.
www.myasd.com

On Jan 12, 2009, at 2:15 PM, Rafael Maia wrote:

 Thanks alot for your source code Norman, it has been a big boost to my code development...  I am having a diferent problem now.I can ear the sound frames i added on my sound speakers, but i am not sending them in the RTP session.I did the following: pjmedia_conf_add_port(conference_bridge, pool_vars, &port, NULL, &slot);pjmedia_conf_connect_port(conference_bridge, slot, inSlot, 0);  I have tested putting frames on the master_port directly, and the saound frames are sent throw RTP: pjmedia_port* master = pjmedia_conf_get_master_port(conference_bridge);pjmedia_port_put_frame(master, &frame);  ...but i don't think this is the proper way to do it Can anyone help?How should i send the audio frames? Thanks in advance for any help....  Rafael Maia  

From: norman@myasd.comTo: pjsip at lists.pjsip.orgDate: Fri, 9 Jan 2009 18:48:10 -0500Subject: Re: Sending my own audio framesYou can use pjmedia_splitcomb_create_rev_channel to reverse the put/get semantics. I do that elsewhere and it works. 

I did then add it to the conference bridge.


Sadly, my code isn't easy to extract and is very C++ using boost and a custom string library.


typedef bool (*GetSamplesPtr)(void * inBuf, uint32_t * ioByteSize, pj_timestamp * inTime);


PlayPort::PlayPort(
unsigned sampling_rate,
unsigned channel_count,
unsigned samples_per_frame,
unsigned bits_per_sample
)
: pool(NULL), mCallIndex(INVALID_CALL_INDEX)
{
    const pj_str_t name = pj_str("file");

    pool = pjsua_pool_create("asd_player", 4000, 4000);
    assert(pool);

    pj_strdup2(pool, &base.info.name, "asd_player");

    base.get_frame = &file_get_frame_get;
    base.put_frame = &file_put_frame_get;
    base.on_destroy = &file_on_destroy_get;

    pjmedia_port_info_init(&base.info, &name, SIGNATURE, sampling_rate, channel_count, bits_per_sample, samples_per_frame);

    port_is_open = true;
    options = 0;
}

PlayPort::~PlayPort()
{
    Close();

    if (pool) {
        pj_pool_release(pool);
        pool = NULL;
    }
}

pj_status_t PlayPort::Open(SInt32 inCallIndex, float inVolume, GetSamplesPtr inFunc)
{
    pj_status_t status;

    status = pjsua_conf_add_port(pool, &base, &slot);
    if (status != PJ_SUCCESS) {
        pjmedia_port_destroy(&base);
        return status;
    }

    mCallIndex = inCallIndex;

    status = pjsua_conf_adjust_rx_level(slot, inVolume);

    port_func = inFunc;

    return status;
}

void PlayPort::Close(void)
{
    file_on_destroy_get(&base);
}

bool PlayPort::IsOpen(void)
{
    return port_is_open && slot >= 0;
}

pj_status_t PlayPort::ConnectTo(int inSlot)
{
    return pjsua_conf_connect(slot, inSlot);
}

pj_status_t PlayPort::DisconnectFrom(int inSlot)
{
    return pjsua_conf_disconnect(slot, inSlot);
}

// Class static
pj_status_t PlayPort::file_on_destroy_get(pjmedia_port *this_port)
{
    // As the first element in a non-virtual class...
    PlayPort *fport = (PlayPort *) this_port;
    boost::recursive_mutex::scoped_lock l(fport->m);

    pj_assert(this_port->info.signature == SIGNATURE);

    if (fport->port_is_open) {
     fport->port_is_open = false; // Prevents a recursive callback

        fport->port_func = NULL;
        pjsua_conf_remove_port(fport->slot); // If it's already removed, e.g. audio device changed, this crashes. 
        fport->slot = 0;
        pjmedia_port_destroy(&fport->base);
    }

    return PJ_SUCCESS;
}

// Class static
pj_status_t PlayPort::file_get_frame_get(pjmedia_port *this_port, pjmedia_frame *frame)
{
    // As the first element in a non-virtual class...
    PlayPort *fport = (PlayPort *) this_port;

    pj_assert(this_port->info.signature == SIGNATURE);

    if (frame->size == 0) return PJ_SUCCESS;
    if (! fport->port_func) return PJ_EEOF;

    pj_size_t frame_size = frame->size;
    if ((*fport->port_func)(frame->buf, &frame_size, (PJSUA_Timestamp *) &frame->timestamp)) {
        if (frame_size < frame->size) {
            bzero((UInt8*)frame->buf + frame_size, frame->size - frame_size);
        }
        frame->timestamp.u64 = 0;
        frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
        return PJ_SUCCESS;
    }
    file_on_destroy_get(this_port);
    return PJ_EEOF;
}

// Class static
pj_status_t PlayPort::file_put_frame_get(pjmedia_port *this_port, const pjmedia_frame *frame)
{
    return PJ_EINVALIDOP;
}






Norman Franke
Answering Service for Directors, Inc.
www.myasd.com

On Jan 9, 2009, at 1:27 PM, Rafael Maia wrote:

 Thanks for your anwser Norman. You are using a very diferent approach from mine. Could you provide some more information ( or some source code ) ? My DirectShow sound reading routines are pushing audio frames that i need to send throw PJSIP. So i need to call put_frame on a media port.How did you created this "Passive" port ? You also add it to the conference bridge, right ? Thanks in advance... Rafael Maia 

From: norman@myasd.comTo: pjsip at lists.pjsip.orgDate: Fri, 9 Jan 2009 12:17:19 -0500Subject: Re: Sending my own audio framesI use pjmedia_port_info_init to create a player port. Something like this:


    pool = pjsua_pool_create("MyPlayerPool", 4000, 4000);
    pj_strdup2(pool, &base.info.name, "MyPlayer");

    base.get_frame = &file_get_frame_get;
    base.put_frame = &file_put_frame_get;
    base.on_destroy = &file_on_destroy_get;

    pjmedia_port_info_init(&base.info, &name, SIGNATURE, sampling_rate, channel_count, bits_per_sample, samples_per_frame);


This works well for playing files in a non-standard format that I need to support. You put your sample generation code in file_get_frame_get.




Norman Franke
Answering Service for Directors, Inc.
www.myasd.com

On Jan 9, 2009, at 9:24 AM, Rafael Maia wrote:

 Hi, i made a media player in DirectShow that captures PCM audio frames from mp3 audio files. I need to send this audio frames to PJSIP. Can anyone help me? I have tried adding a passive_port to the conference bridge and it did not worked. Now i am trying to use splitcomb. And i can send some noise. Here's a code sample: // 1? pjmedia_splitcom_createpj_status_t status = pjmedia_splitcomb_create(pool_vars, nSamplesPerSec, nChannels, samplesPerFrame, wBitsPerSample, 0, &p_splitcomb);// for each channelfor(unsigned int i = 0; i < nChannels; i++)  {     unsigned int p_slot;     pjmedia_port* p_port;      // 2? pjmedia_splitcom_create_rev_channel     status = pjmedia_splitcomb_create_rev_channel(pool_vars, p_splitcomb, i, 0, &p_port);      // 3? pjmedia_conf_add_port     status = pjmedia_conf_add_port(conference_bridge, pool_vars, p_port, NULL, &p_slot);}  And then, when i want to send an audio frame i do the following: pjmedia_port_put_frame(p_splitcomb, &frame);   What is wrong with my code?Am i using splitcom correctly? Any help would be appreciated... Rafael Maia 

O jeito mais f?cil de manter a sua lista de amigos sempre em ordem! Organize seus contatos!_______________________________________________Visit our blog: http://blog.pjsip.orgpjsip mailing listpjsip at lists.pjsip.orghttp://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org

Not?cias direto do New York Times, gols do Lance, videocassetadas e muitos outros v?deos no MSN Videos! Confira j?! _______________________________________________Visit our blog: http://blog.pjsip.orgpjsip mailing listpjsip at lists.pjsip.orghttp://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org

O jeito mais f?cil de manter a sua lista de amigos sempre em ordem! Organize seus contatos!_______________________________________________Visit our blog: http://blog.pjsip.orgpjsip mailing listpjsip at lists.pjsip.orghttp://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org
_________________________________________________________________
Mais do que emails! Confira tudo o que Windows Live? pode oferecer.
http://www.microsoft.com/windows/windowslive/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.pjsip.org/pipermail/pjsip_lists.pjsip.org/attachments/20090113/af9ffe09/attachment-0001.html>


[Index of Archives]     [Asterisk Users]     [Asterisk App Development]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [Linux API]
  Powered by Linux