Hi
I have modified simpleua.c sample in order to record audio data from 2 different audio streams. In call_on_media_update() callback I can see that the media count is 2, however I am able to record only the first stream. Below is the code I am using. With 2 audio streams the application always crashes in pjmedia_stream_create(). I have also tried to record separately stream 0 or stream 1, but even in this case stream 1 recording generates the same crash. Can you tell me what I am doing wrong ?
thanks
Bogdan
static void call_on_media_update( pjsip_inv_session *inv,
pj_status_t status)
{
pjmedia_stream_info stream_info[MAX_MEDIA_CNT];
const pjmedia_sdp_session *local_sdp;
const pjmedia_sdp_session *remote_sdp;
pjmedia_port *media_port[MAX_MEDIA_CNT];
PJ_LOG(3, (THIS_FILE, "call_on_media_update"));
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "SDP negotiation has failed", status);
/* Here we should disconnect call if we're not in the middle
* of initializing an UAS dialog and if this is not a re-INVITE.
*/
return;
}
/* Get local and remote SDP.
* We need both SDPs to create a media session.
*/
status = pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp);
const unsigned int local_media_count = local_sdp->media_count;
status = pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp);
const unsigned int remote_media_count = remote_sdp->media_count;
PJ_LOG(3, (THIS_FILE, "Media count: local %d, remote %d", local_media_count, remote_media_count));
if ((MAX_MEDIA_CNT < local_media_count) || (MAX_MEDIA_CNT < remote_media_count)) {
app_perror(THIS_FILE, "Either local or remote media count exceed the maximum media count", status);
return;
}
for (unsigned int stream_index = 0; stream_index < local_media_count; ++stream_index) {
PJ_LOG(3, (THIS_FILE, "Audio stream #%d", stream_index));
/* Create stream info based on the media audio SDP. */
PJ_LOG(3, (THIS_FILE, "pjmedia_stream_info_from_sdp"));
status = pjmedia_stream_info_from_sdp(&(stream_info[stream_index]), inv->dlg->pool,
g_med_endpt,
local_sdp, remote_sdp, stream_index);
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Unable to create audio stream info", status);
return;
}
/* If required, we can also change some settings in the stream info,
* (such as jitter buffer settings, codec settings, etc) before we
* create the stream.
*/
/* Create new audio media stream, passing the stream info, and also the
* media socket that we created earlier.
*/
PJ_LOG(3, (THIS_FILE, "pjmedia_stream_create"));
status = pjmedia_stream_create(g_med_endpt, inv->dlg->pool, &(stream_info[stream_index]),
g_med_transport[stream_index], NULL, &(g_med_stream[stream_index]));
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Unable to create audio stream", status);
return;
}
/* Start the audio stream */
PJ_LOG(3, (THIS_FILE, "pjmedia_stream_start"));
status = pjmedia_stream_start(g_med_stream[stream_index]);
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Unable to start audio stream", status);
return;
}
/* Get the media port interface of the audio stream.
* Media port interface is basicly a struct containing get_frame() and
* put_frame() function. With this media port interface, we can attach
* the port interface to conference bridge, or directly to a sound
* player/recorder device.
*/
PJ_LOG(3, (THIS_FILE, "pjmedia_stream_get_port"));
status = pjmedia_stream_get_port(g_med_stream[stream_index], &(media_port[stream_index]));
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Unable to get stream port", status);
return;
}
/* Get clock rate of the media port */
pjmedia_audio_format_detail *u_afd = pjmedia_format_get_audio_format_detail(&(media_port[stream_index]->info.fmt), PJ_TRUE);
const unsigned int clock_rate = u_afd->clock_rate;
/* Get samples/frame */
const unsigned int spf = PJMEDIA_PIA_SPF(&(media_port[stream_index]->info));
/* Get channel count */
const unsigned int channel_count = u_afd->channel_count;
/* Get bits /sample */
const unsigned int bps = u_afd->bits_per_sample;
PJ_LOG(3, (THIS_FILE, "media params: clock rate %d, samp/frame %d, channel count %d, bits/samp %d", clock_rate, spf, channel_count, bps));
/* Create WAVE file writer port. */
PJ_LOG(3, (THIS_FILE, "pjmedia_wav_writer_port_create"));
char filename[1024];
sprintf_s(filename, sizeof(filename), "simple_ua%d.wav", stream_index);
status = pjmedia_wav_writer_port_create(inv->pool, filename,
clock_rate,
channel_count,
spf,
bps,
0, 0,
&(g_file_port[stream_index]));
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Unable to open WAV file for writing", status);
return;
}
/* record stream to wave file */
PJ_LOG(3, (THIS_FILE, "pjmedia_master_port_create"));
status = pjmedia_master_port_create(g_pool, media_port[stream_index], g_file_port[stream_index],
0, &(g_master_port[stream_index]));
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Unable to create master port", status);
return;
}
PJ_LOG(3, (THIS_FILE, "pjmedia_master_port_start"));
status = pjmedia_master_port_start(g_master_port[stream_index]);
if (status != PJ_SUCCESS) {
app_perror(THIS_FILE, "Error starting master port", status);
return;
}
}
/* Done with media. */
PJ_LOG(3, (THIS_FILE, "Done with media"));
}
Bogdan Cristea
tél. portable: +40 (751) 705 754
tél. fixe: +40 (371) 783 139
ID skype: bogdan.cristea77