Exemplo n.º 1
0
/* API: create stream */
static pj_status_t bb10_factory_create_stream(pjmedia_aud_dev_factory *f,
                                              const pjmedia_aud_param *param,
                                              pjmedia_aud_rec_cb rec_cb,
                                              pjmedia_aud_play_cb play_cb,
                                              void *user_data,
                                              pjmedia_aud_stream **p_strm)
{
    struct bb10_factory *af = (struct bb10_factory*)f;
    pj_status_t status;
    pj_pool_t* pool;
    struct bb10_stream* stream;

    pool = pj_pool_create (af->pf, "bb10%p", 1024, 1024, NULL);
    if (!pool)
        return PJ_ENOMEM;

    /* Allocate and initialize comon stream data */
    stream = PJ_POOL_ZALLOC_T (pool, struct bb10_stream);
    stream->base.op   = &bb10_stream_op;
    stream->pool      = pool;
    stream->af 	      = af;
    stream->user_data = user_data;
    stream->pb_cb     = play_cb;
    stream->ca_cb     = rec_cb;
    stream->quit      = 0;
    pj_memcpy(&stream->param, param, sizeof(*param));

    /* Init playback */
    if (param->dir & PJMEDIA_DIR_PLAYBACK) {
        status = bb10_open_playback (stream, param);
        if (status != PJ_SUCCESS) {
            pj_pool_release (pool);
            return status;
        }
    }

    /* Init capture */
    if (param->dir & PJMEDIA_DIR_CAPTURE) {
        status = bb10_open_capture (stream, param);
        if (status != PJ_SUCCESS) {
            if (param->dir & PJMEDIA_DIR_PLAYBACK) {
                close_play_pcm(stream);
            }
            pj_pool_release (pool);
            return status;
        }
    }

    *p_strm = &stream->base;
    return PJ_SUCCESS;
}
Exemplo n.º 2
0
static pj_status_t bb10_stream_destroy (pjmedia_aud_stream *s)
{
    struct bb10_stream *stream = (struct bb10_stream*)s;

    TRACE_((THIS_FILE,"bb10_stream_destroy()"));

    bb10_stream_stop (s);

    close_play_pcm(stream);
    close_capture_pcm(stream);

    pj_pool_release (stream->pool);

    return PJ_SUCCESS;
}
Exemplo n.º 3
0
/* API: create stream */
static pj_status_t bb10_factory_create_stream(pjmedia_aud_dev_factory *f,
                                              const pjmedia_aud_param *param,
                                              pjmedia_aud_rec_cb rec_cb,
                                              pjmedia_aud_play_cb play_cb,
                                              void *user_data,
                                              pjmedia_aud_stream **p_strm)
{
    struct bb10_factory *af = (struct bb10_factory*)f;
    pj_status_t status;
    pj_pool_t* pool;
    struct bb10_stream* stream;

    pool = pj_pool_create (af->pf, "bb10%p", 1024, 1024, NULL);
    if (!pool)
        return PJ_ENOMEM;

    /* Allocate and initialize comon stream data */
    stream = PJ_POOL_ZALLOC_T (pool, struct bb10_stream);
    stream->base.op   = &bb10_stream_op;
    stream->pool      = pool;
    stream->af 	      = af;
    stream->user_data = user_data;
    stream->pb_cb     = play_cb;
    stream->ca_cb     = rec_cb;
    stream->quit      = 0;
    pj_memcpy(&stream->param, param, sizeof(*param));

    /* Init playback */
    if (param->dir & PJMEDIA_DIR_PLAYBACK) {
        status = bb10_open_playback (stream, param);
        if (status != PJ_SUCCESS) {
            pj_pool_release (pool);
            return status;
        }
    }

    /* Init capture */
    if (param->dir & PJMEDIA_DIR_CAPTURE) {
        status = bb10_open_capture (stream, param);
        if (status != PJ_SUCCESS) {
            if (param->dir & PJMEDIA_DIR_PLAYBACK) {
                close_play_pcm(stream);
            }
            pj_pool_release (pool);
            return status;
        }
    }

    /* Set the audio routing ONLY if app explicitly asks one */
    if ((param->dir & PJMEDIA_DIR_PLAYBACK) &&
	(param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE))
    {
	status = bb10_stream_set_cap(&stream->base,
				     PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE,
                                     &param->output_route);
	if (status != PJ_SUCCESS) {
	    TRACE_((THIS_FILE, "Error setting output route"));
	    bb10_stream_destroy(&stream->base);
	    return status;
	}
    } else {
	/* Legacy behavior: if none specified, set to speaker */
	status = bb10_initialize_playback_ctrl(stream, false);
    }

    *p_strm = &stream->base;
    return PJ_SUCCESS;
}
Exemplo n.º 4
0
/**
 * Play audio received from PJMEDIA
 */
static int pb_thread_func (void *arg)
{
    struct bb10_stream* stream = (struct bb10_stream *) arg;
    int size                   	= stream->pb_buf_size;
    unsigned long nframes	= stream->pb_frames;
    void *user_data            	= stream->user_data;
    char *buf 		       	= stream->pb_buf;
    pj_timestamp tstamp;
    int result = 0;
    int policy;
    struct sched_param param;

    TRACE_((THIS_FILE, "pb_thread_func: size = %d ", size));

    if (pthread_getschedparam(pthread_self(), &policy, &param) == 0) {
	param.sched_priority = 18;
	pthread_setschedparam (pthread_self(), policy, &param);
    }

    pj_bzero (buf, size);
    tstamp.u64 = 0;

    /* Do the final initialization now the thread has started. */
    if ((result = snd_pcm_plugin_prepare(stream->pb_pcm,
                                         SND_PCM_CHANNEL_PLAYBACK)) < 0)
    {
        close_play_pcm(stream);
        TRACE_((THIS_FILE, "pb_thread_func failed prepare = %d", result));
        return PJ_SUCCESS;
    }

    while (!stream->quit) {
        pjmedia_frame frame;

        frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
        /* pointer to buffer filled by PJMEDIA */
        frame.buf = buf;
        frame.size = size;
        frame.timestamp.u64 = tstamp.u64;
        frame.bit_info = 0;

        /* Read the audio from pjmedia */
        result = stream->pb_cb (user_data, &frame);
        if (result != PJ_SUCCESS || stream->quit)
            break;

        if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
            pj_bzero (buf, size);

        /* Write 640 to play unit */
        result = snd_pcm_plugin_write(stream->pb_pcm,buf,size);
        if (result != size || result < 0) {
	    /* either the write to output device has failed or not the
	     * full amount of bytes have been written. This usually happens
	     * when audio routing is being changed by another thread
	     * Use a status variable for reading the error
	     */
	    snd_pcm_channel_status_t status;
            status.channel = SND_PCM_CHANNEL_PLAYBACK;
            if (snd_pcm_plugin_status (stream->pb_pcm, &status) < 0) {
                /* Call has failed nothing we can do except log and
                 * continue */
            	PJ_LOG(4,(THIS_FILE,
                	  "underrun: playback channel status error"));
            } else {
            	/* The status of the error has been read
            	 * RIM say these are expected so we can "re-prepare" the stream
            	 */
            	PJ_LOG(4,(THIS_FILE,"PLAY thread ERROR status = %d",
            		  status.status));
		if (status.status == SND_PCM_STATUS_READY ||
		    status.status == SND_PCM_STATUS_UNDERRUN ||
		    status.status == SND_PCM_STATUS_ERROR ) 
		{
		    if (snd_pcm_plugin_prepare (stream->pb_pcm,
						SND_PCM_CHANNEL_PLAYBACK) < 0)
		    {
			PJ_LOG(4,(THIS_FILE,
				  "underrun: playback channel prepare error"));
		    }
		}
	    }
        }
	tstamp.u64 += nframes;
    }

    flush_play(stream);
    close_play_pcm(stream);
    TRACE_((THIS_FILE, "pb_thread_func: Stopped"));

    return PJ_SUCCESS;
}
Exemplo n.º 5
0
/**
 * Play audio received from PJMEDIA
 */
static int pb_thread_func (void *arg)
{
    struct bb10_stream* stream = (struct bb10_stream *) arg;
    /* Handle from bb10_open_playback */
    /* Will be 640 */
    int size                   	= stream->pb_buf_size;
    /* 160 frames for 20ms */
    unsigned long nframes	= stream->pb_frames;
    void *user_data            	= stream->user_data;
    char *buf 		       	= stream->pb_buf;
    pj_timestamp tstamp;
    int result = 0;

    pj_bzero (buf, size);
    tstamp.u64 = 0;

    TRACE_((THIS_FILE, "pb_thread_func: size = %d ", size));

    /* Do the final initialization now the thread has started. */
    if ((result = snd_pcm_plugin_prepare(stream->pb_pcm,
                                         SND_PCM_CHANNEL_PLAYBACK)) < 0)
    {
        close_play_pcm(stream);
        TRACE_((THIS_FILE, "pb_thread_func failed prepare = %d", result));
	return PJ_SUCCESS;
    }

    while (!stream->quit) {
        pjmedia_frame frame;

        frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
        /* pointer to buffer filled by PJMEDIA */
        frame.buf = buf;
        frame.size = size;
        frame.timestamp.u64 = tstamp.u64;
        frame.bit_info = 0;

        result = stream->pb_cb (user_data, &frame);
        if (result != PJ_SUCCESS || stream->quit)
            break;

        if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
            pj_bzero (buf, size);

        /* Write 640 to play unit */
        result = snd_pcm_plugin_write(stream->pb_pcm,buf,size);
        if (result != size || result < 0) {
            snd_pcm_channel_status_t status;
            if (snd_pcm_plugin_status (stream->pb_pcm, &status) < 0) {
                PJ_LOG(4,(THIS_FILE,
                	  "underrun: playback channel status error"));
                continue;
            }

            if (status.status == SND_PCM_STATUS_READY ||
        	status.status == SND_PCM_STATUS_UNDERRUN)
            {
                if (snd_pcm_plugin_prepare (stream->pb_pcm,
                                            SND_PCM_CHANNEL_PLAYBACK) < 0)
                {
                    PJ_LOG(4,(THIS_FILE,
                    	      "underrun: playback channel prepare error"));
                    continue;
                }
            }

            TRACE_((THIS_FILE, "pb_thread_func failed write = %d", result));
        }

	tstamp.u64 += nframes;
    }

    flush_play(stream);
    close_play_pcm(stream);
    TRACE_((THIS_FILE, "pb_thread_func: Stopped"));

    return PJ_SUCCESS;
}