PJ_DEF(pj_status_t) pjmedia_bidirectional_port_create( pj_pool_t *pool, pjmedia_port *get_port, pjmedia_port *put_port, pjmedia_port **p_port ) { struct bidir_port *port; port = PJ_POOL_ZALLOC_T(pool, struct bidir_port); pjmedia_port_info_init(&port->base.info, &get_port->info.name, SIGNATURE, get_port->info.clock_rate, get_port->info.channel_count, get_port->info.bits_per_sample, get_port->info.samples_per_frame); port->get_port = get_port; port->put_port = put_port; port->base.get_frame = &get_frame; port->base.put_frame = &put_frame; *p_port = &port->base; return PJ_SUCCESS; }
pjs_port::pjs_port(const char * name,unsigned signature, unsigned sampling_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, unsigned options):m_options(options) { m_rx_mute = m_tx_mute = false; if(name) { m_name = (char *)malloc(strlen(name)+1); strcpy(m_name,name); } else m_name = NULL; pj_str_t name_str = pj_str(m_name); memset(&m_port,0,sizeof(m_port)); pjmedia_port_info_init(&m_port.info, &name_str, signature, sampling_rate, channel_count, bits_per_sample, samples_per_frame); m_port.get_frame = &get_frame_s; m_port.put_frame = &put_frame_s; m_port.on_destroy = &port_destroy_s; m_port.port_data.pdata = this; }
PJ_DEF(pj_status_t) pjmedia_null_port_create( pj_pool_t *pool, unsigned sampling_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, pjmedia_port **p_port ) { pjmedia_port *port; const pj_str_t name = pj_str("null-port"); PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); port = pj_pool_zalloc(pool, sizeof(pjmedia_port)); PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); pjmedia_port_info_init(&port->info, &name, SIGNATURE, sampling_rate, channel_count, bits_per_sample, samples_per_frame); port->get_frame = &null_get_frame; port->put_frame = &null_put_frame; port->on_destroy = &null_on_destroy; *p_port = port; return PJ_SUCCESS; }
PJ_DEF(pj_status_t) pjmedia_bidirectional_port_create( pj_pool_t *pool, pjmedia_port *get_port, pjmedia_port *put_port, pjmedia_port **p_port ) { struct bidir_port *port; const pjmedia_audio_format_detail *gafd; port = PJ_POOL_ZALLOC_T(pool, struct bidir_port); gafd = pjmedia_format_get_audio_format_detail(&get_port->info.fmt, 1); pjmedia_port_info_init(&port->base.info, &get_port->info.name, SIGNATURE, gafd->clock_rate, gafd->channel_count, gafd->bits_per_sample, PJMEDIA_AFD_SPF(gafd)); port->get_port = get_port; port->put_port = put_port; port->base.get_frame = &get_frame; port->base.put_frame = &put_frame; *p_port = &port->base; return PJ_SUCCESS; }
PJ_DEF(pj_status_t) pjmedia_stereo_port_create( pj_pool_t *pool, pjmedia_port *dn_port, unsigned channel_count, unsigned options, pjmedia_port **p_port ) { const pj_str_t name = pj_str("stereo"); struct stereo_port *sport; unsigned samples_per_frame; /* Validate arguments. */ PJ_ASSERT_RETURN(pool && dn_port && channel_count && p_port, PJ_EINVAL); /* Only supports 16bit samples per frame */ PJ_ASSERT_RETURN(dn_port->info.bits_per_sample == 16, PJMEDIA_ENCBITS); /* Validate channel counts */ PJ_ASSERT_RETURN(((dn_port->info.channel_count>1 && channel_count==1) || (dn_port->info.channel_count==1 && channel_count>1)), PJ_EINVAL); /* Create and initialize port. */ sport = PJ_POOL_ZALLOC_T(pool, struct stereo_port); PJ_ASSERT_RETURN(sport != NULL, PJ_ENOMEM); samples_per_frame = dn_port->info.samples_per_frame * channel_count / dn_port->info.channel_count; pjmedia_port_info_init(&sport->base.info, &name, SIGNATURE, dn_port->info.clock_rate, channel_count, dn_port->info.bits_per_sample, samples_per_frame); sport->dn_port = dn_port; sport->options = options; /* We always need buffer for put_frame */ sport->put_buf = (pj_int16_t*) pj_pool_alloc(pool, dn_port->info.bytes_per_frame); /* See if we need buffer for get_frame */ if (dn_port->info.channel_count > channel_count) { sport->get_buf = (pj_int16_t*) pj_pool_alloc(pool, dn_port->info.bytes_per_frame); } /* Media port interface */ sport->base.get_frame = &stereo_get_frame; sport->base.put_frame = &stereo_put_frame; sport->base.on_destroy = &stereo_destroy; /* Done */ *p_port = &sport->base; return PJ_SUCCESS; }
/* * Create the splitter/combiner. */ PJ_DEF(pj_status_t) pjmedia_splitcomb_create( pj_pool_t *pool, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, unsigned options, pjmedia_port **p_splitcomb) { const pj_str_t name = pj_str("splitcomb"); struct splitcomb *sc; /* Sanity check */ PJ_ASSERT_RETURN(pool && clock_rate && channel_count && samples_per_frame && bits_per_sample && p_splitcomb, PJ_EINVAL); /* Only supports 16 bits per sample */ PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL); *p_splitcomb = NULL; /* Create the splitter/combiner structure */ sc = pj_pool_zalloc(pool, sizeof(struct splitcomb)); PJ_ASSERT_RETURN(sc != NULL, PJ_ENOMEM); /* Create temporary buffers */ sc->get_buf = pj_pool_alloc(pool, samples_per_frame * sizeof(TMP_SAMP_TYPE) / channel_count); PJ_ASSERT_RETURN(sc->get_buf, PJ_ENOMEM); sc->put_buf = pj_pool_alloc(pool, samples_per_frame * sizeof(TMP_SAMP_TYPE) / channel_count); PJ_ASSERT_RETURN(sc->put_buf, PJ_ENOMEM); /* Save options */ sc->options = options; /* Initialize port */ pjmedia_port_info_init(&sc->base.info, &name, SIGNATURE, clock_rate, channel_count, bits_per_sample, samples_per_frame); sc->base.put_frame = &put_frame; sc->base.get_frame = &get_frame; sc->base.on_destroy = &on_destroy; /* Init ports array */ sc->port_desc = pj_pool_zalloc(pool, channel_count*sizeof(*sc->port_desc)); /* Done for now */ *p_splitcomb = &sc->base; return PJ_SUCCESS; }
PJ_DEF(pj_status_t) pjmedia_leaky_bucket_port_create( pj_pool_factory *pool_factory, pjmedia_port *dn_port, pj_size_t bucket_size, unsigned sent_delay, unsigned bits_per_second, unsigned packets_per_second, pjmedia_port **p_port) { const pj_str_t leaky_bucket = { "leaky", 5 }; struct leaky_bucket_port *lb; pj_pool_t *pool; pj_status_t status; PJ_ASSERT_RETURN(pool_factory && dn_port && p_port, PJ_EINVAL); /* Create own memory pool */ pool = pj_pool_create(pool_factory, "leaky", 4000, 4000, NULL); /* Create the port itself */ lb = PJ_POOL_ZALLOC_T(pool, struct leaky_bucket_port); pjmedia_port_info_init(&lb->base.info, &leaky_bucket, SIGNATURE, dn_port->info.clock_rate, dn_port->info.channel_count, dn_port->info.bits_per_sample, dn_port->info.samples_per_frame); /* we have an empty list */ lb->first_item = lb->last_item = NULL; lb->items = 0; /* More init */ lb->dn_port = dn_port; lb->base.get_frame = &lb_get_frame; lb->base.put_frame = &lb_put_frame; lb->base.on_destroy = &lb_on_destroy; lb->bucket_size = bucket_size; lb->pool = pool; lb->last_ts.u64 = 0; lb->frames = 0; /* get a sent rate */ if (sent_delay > 0){ lb->sent_delay = sent_delay; } else if (packets_per_second > 0) { lb->sent_delay = (unsigned) ((double)lb->base.info.clock_rate / \ packets_per_second); } else if (bits_per_second > 0) { lb->bits_per_second = bits_per_second; } PJ_LOG(5, (THIS_FILE, "Leaky bucket port created: bps=%u pps=%u " "sent_delay=%u bucket_size=%u", bits_per_second, packets_per_second, lb->sent_delay, bucket_size)); /* Done */ *p_port = &lb->base; return PJ_SUCCESS; }
PJ_DEF(pj_status_t) pjmedia_mem_capture_create( pj_pool_t *pool, void *buffer, pj_size_t size, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, unsigned options, pjmedia_port **p_port) { struct mem_rec *rec; const pj_str_t name = { "memrec", 6 }; /* Sanity check */ PJ_ASSERT_RETURN(pool && buffer && size && clock_rate && channel_count && samples_per_frame && bits_per_sample && p_port, PJ_EINVAL); /* Can only support 16bit PCM */ PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL); rec = PJ_POOL_ZALLOC_T(pool, struct mem_rec); PJ_ASSERT_RETURN(rec != NULL, PJ_ENOMEM); /* Create the rec */ pjmedia_port_info_init(&rec->base.info, &name, SIGNATURE, clock_rate, channel_count, bits_per_sample, samples_per_frame); rec->base.put_frame = &rec_put_frame; rec->base.get_frame = &rec_get_frame; rec->base.on_destroy = &rec_on_destroy; /* Save the buffer */ rec->buffer = rec->write_pos = (char*)buffer; rec->buf_size = size; /* Options */ rec->options = options; *p_port = &rec->base; return PJ_SUCCESS; }
/* * Create a media port to generate sine wave samples. */ static pj_status_t create_sine_port(pj_pool_t *pool, unsigned sampling_rate, unsigned channel_count, pjmedia_port **p_port) { pjmedia_port *port; unsigned i; unsigned count; pj_str_t name; port_data *sine; PJ_ASSERT_RETURN(pool && channel_count > 0 && channel_count <= 2, PJ_EINVAL); port = pj_pool_zalloc(pool, sizeof(pjmedia_port)); PJ_ASSERT_RETURN(port != NULL, PJ_ENOMEM); /* Fill in port info. */ name = pj_str("sine generator"); pjmedia_port_info_init(&port->info, &name, PJMEDIA_SIG_CLASS_PORT_AUD('s', 'i'), sampling_rate, channel_count, 16, sampling_rate * 20 / 1000 * channel_count); /* Set the function to feed frame */ port->get_frame = &sine_get_frame; /* Create sine port data */ port->port_data.pdata = sine = pj_pool_zalloc(pool, sizeof(port_data)); /* Create samples */ count = PJMEDIA_PIA_SPF(&port->info) / channel_count; sine->samples = pj_pool_alloc(pool, count * sizeof(pj_int16_t)); PJ_ASSERT_RETURN(sine->samples != NULL, PJ_ENOMEM); /* initialise sinusoidal wavetable */ for( i=0; i<count; i++ ) { sine->samples[i] = (pj_int16_t) (10000.0 * sin(((double)i/(double)count) * M_PI * 8.) ); } *p_port = port; return PJ_SUCCESS; }
PJ_DEF(pj_status_t) pjmedia_echo_port_create(pj_pool_t *pool, pjmedia_port *dn_port, unsigned tail_ms, unsigned latency_ms, unsigned options, pjmedia_port **p_port ) { const pj_str_t AEC = { "EC", 2 }; pjmedia_audio_format_detail *afd; struct ec *ec; pj_status_t status; PJ_ASSERT_RETURN(pool && dn_port && p_port, PJ_EINVAL); afd = pjmedia_format_get_audio_format_detail(&dn_port->info.fmt, PJ_TRUE); PJ_ASSERT_RETURN(afd->bits_per_sample==16 && tail_ms, PJ_EINVAL); /* Create the port and the AEC itself */ ec = PJ_POOL_ZALLOC_T(pool, struct ec); pjmedia_port_info_init(&ec->base.info, &AEC, SIGNATURE, afd->clock_rate, afd->channel_count, afd->bits_per_sample, PJMEDIA_AFD_SPF(afd)); status = pjmedia_echo_create2(pool, afd->clock_rate, afd->channel_count, PJMEDIA_AFD_SPF(afd), tail_ms, latency_ms, options, &ec->ec); if (status != PJ_SUCCESS) return status; /* More init */ ec->dn_port = dn_port; ec->base.get_frame = &ec_get_frame; ec->base.put_frame = &ec_put_frame; ec->base.on_destroy = &ec_on_destroy; /* Done */ *p_port = &ec->base; return PJ_SUCCESS; }
PJ_DEF(pj_status_t) pjmedia_mem_player_create( pj_pool_t *pool, const void *buffer, pj_size_t size, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, unsigned options, pjmedia_port **p_port ) { struct mem_player *port; pj_str_t name = pj_str("memplayer"); /* Sanity check */ PJ_ASSERT_RETURN(pool && buffer && size && clock_rate && channel_count && samples_per_frame && bits_per_sample && p_port, PJ_EINVAL); /* Can only support 16bit PCM */ PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL); port = pj_pool_zalloc(pool, sizeof(struct mem_player)); PJ_ASSERT_RETURN(port != NULL, PJ_ENOMEM); /* Create the port */ pjmedia_port_info_init(&port->base.info, &name, SIGNATURE, clock_rate, channel_count, bits_per_sample, samples_per_frame); port->base.put_frame = &mem_put_frame; port->base.get_frame = &mem_get_frame; port->base.on_destroy = &mem_on_destroy; /* Save the buffer */ port->buffer = port->read_pos = (char*)buffer; port->buf_size = size; /* Options */ port->options = options; *p_port = &port->base; return PJ_SUCCESS; }
static struct playlist_port *create_file_list_port(pj_pool_t *pool, const pj_str_t *name) { struct playlist_port *port; port = pj_pool_zalloc(pool, sizeof(struct playlist_port)); if (!port) return NULL; /* Put in default values. * These will be overriden once the file is read. */ pjmedia_port_info_init(&port->base.info, name, SIGNATURE, 8000, 1, 16, 80); port->base.get_frame = &file_list_get_frame; port->base.on_destroy = &file_list_on_destroy; return port; }
PJ_DEF(pj_status_t) pjmedia_echo_port_create(pj_pool_t *pool, pjmedia_port *dn_port, unsigned tail_ms, unsigned latency_ms, unsigned options, pjmedia_port **p_port ) { const pj_str_t AEC = { "EC", 2 }; struct ec *ec; pj_status_t status; PJ_ASSERT_RETURN(pool && dn_port && p_port, PJ_EINVAL); PJ_ASSERT_RETURN(dn_port->info.bits_per_sample==16 && tail_ms, PJ_EINVAL); /* Create the port and the AEC itself */ ec = pj_pool_zalloc(pool, sizeof(struct ec)); pjmedia_port_info_init(&ec->base.info, &AEC, SIGNATURE, dn_port->info.clock_rate, dn_port->info.channel_count, dn_port->info.bits_per_sample, dn_port->info.samples_per_frame); status = pjmedia_echo_create(pool, dn_port->info.clock_rate, dn_port->info.samples_per_frame, tail_ms, latency_ms, options, &ec->ec); if (status != PJ_SUCCESS) return status; /* More init */ ec->dn_port = dn_port; ec->base.get_frame = &ec_get_frame; ec->base.put_frame = &ec_put_frame; ec->base.on_destroy = &ec_on_destroy; /* Done */ *p_port = &ec->base; return PJ_SUCCESS; }
PJ_DECL(pj_status_t) pjmedia_plc_port_create(pj_pool_t *pool, pjmedia_port *dn_port, pjmedia_codec *codec, unsigned fpp, em_plc_mode plc_mode, pjmedia_port **p_port) { const pj_str_t plc = { "plc", 3 }; struct plc_port *plcp; pj_status_t status; PJ_ASSERT_RETURN(pool && dn_port && p_port, PJ_EINVAL); /* Create the port itself */ plcp = PJ_POOL_ZALLOC_T(pool, struct plc_port); plcp->frame_buf = pj_pool_zalloc(pool, BUF_SIZE); pjmedia_port_info_init(&plcp->base.info, &plc, SIGNATURE, dn_port->info.clock_rate, dn_port->info.channel_count, dn_port->info.bits_per_sample, dn_port->info.samples_per_frame*fpp); /* More init */ plcp->dn_port = dn_port; plcp->codec = codec; plcp->fpp = fpp; plcp->plc_mode = plc_mode; plcp->base.get_frame = &plc_get_frame; plcp->base.put_frame = &plc_put_frame; plcp->base.on_destroy = &plc_on_destroy; plcp->frame.type = PJMEDIA_FRAME_TYPE_NONE; plcp->frame.buf = plcp->frame_buf; plcp->stats.received = 0; plcp->stats.lost = 0; plcp->stats.total = 0; /* Done */ *p_port = &plcp->base; return PJ_SUCCESS; }
PJ_DEF(pj_status_t) pjmedia_silence_port_create(pj_pool_t *pool, pjmedia_port *dn_port, unsigned buffer_size, pjmedia_port **p_port) { const pj_str_t silence = { "silence", 7 }; struct silence_port *sp; pj_status_t status; PJ_ASSERT_RETURN(pool && dn_port && p_port, PJ_EINVAL); /* Create the port itself */ sp = PJ_POOL_ZALLOC_T(pool, struct silence_port); pjmedia_port_info_init(&sp->base.info, &silence, SIGNATURE, dn_port->info.clock_rate, dn_port->info.channel_count, dn_port->info.bits_per_sample, dn_port->info.samples_per_frame); /* More init */ sp->dn_port = dn_port; sp->base.get_frame = &sp_get_frame; sp->base.put_frame = &sp_put_frame; sp->base.on_destroy = &sp_on_destroy; sp->frames = 0; sp->last_ts.u64 = 0; /* create circular buffer */ if (!buffer_size) buffer_size = dn_port->info.bits_per_sample * \ dn_port->info.samples_per_frame * 16; pjmedia_circ_buf_create (pool, buffer_size, &sp->buf); /* Done */ *p_port = &sp->base; return PJ_SUCCESS; }
pjmedia_mp3_writer_port_create( pj_pool_t *pool, const char *filename, unsigned sampling_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, const pjmedia_mp3_encoder_option *param_option, pjmedia_port **p_port ) { struct mp3_file_port *fport; pj_status_t status; status = init_blade_dll(); if (status != PJ_SUCCESS) return status; /* Check arguments. */ PJ_ASSERT_RETURN(pool && filename && p_port, PJ_EINVAL); /* Only supports 16bits per sample for now. */ PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL); /* Create file port instance. */ fport = pj_pool_zalloc(pool, sizeof(struct mp3_file_port)); PJ_ASSERT_RETURN(fport != NULL, PJ_ENOMEM); /* Initialize port info. */ pj_strdup2_with_null(pool, &fport->mp3_filename, filename); pjmedia_port_info_init(&fport->base.info, &fport->mp3_filename, SIGNATURE, sampling_rate, channel_count, bits_per_sample, samples_per_frame); fport->base.get_frame = &file_get_frame; fport->base.put_frame = &file_put_frame; fport->base.on_destroy = &file_on_destroy; /* Open file in write and read mode. * We need the read mode because we'll modify the WAVE header once * the recording has completed. */ status = pj_file_open(pool, filename, PJ_O_WRONLY, &fport->fd); if (status != PJ_SUCCESS) { deinit_blade_dll(); return status; } /* Copy and initialize option with default settings */ if (param_option) { pj_memcpy(&fport->mp3_option, param_option, sizeof(pjmedia_mp3_encoder_option)); } else { pj_bzero(&fport->mp3_option, sizeof(pjmedia_mp3_encoder_option)); fport->mp3_option.vbr = PJ_TRUE; } /* Calculate bitrate if it's not specified, only if it's not VBR. */ if (fport->mp3_option.bit_rate == 0 && !fport->mp3_option.vbr) fport->mp3_option.bit_rate = sampling_rate * channel_count; /* Set default quality if it's not specified */ if (fport->mp3_option.quality == 0) fport->mp3_option.quality = 2; /* Init mp3 encoder */ status = init_mp3_encoder(fport, pool); if (status != PJ_SUCCESS) { pj_file_close(fport->fd); deinit_blade_dll(); return status; } /* Done. */ *p_port = &fport->base; PJ_LOG(4,(THIS_FILE, "MP3 file writer '%.*s' created: samp.rate=%dKHz, " "bitrate=%dkbps%s, quality=%d", (int)fport->base.info.name.slen, fport->base.info.name.ptr, fport->base.info.clock_rate/1000, fport->mp3_option.bit_rate/1000, (fport->mp3_option.vbr ? " (VBR)" : ""), fport->mp3_option.quality)); return PJ_SUCCESS; }
pjmedia_splitcomb_create_rev_channel( pj_pool_t *pool, pjmedia_port *splitcomb, unsigned ch_num, unsigned options, pjmedia_port **p_chport) { const pj_str_t name = pj_str("splitcomb-ch"); struct splitcomb *sc = (struct splitcomb*) splitcomb; struct reverse_port *rport; unsigned i; pjmedia_port *port; /* Sanity check */ PJ_ASSERT_RETURN(pool && splitcomb, PJ_EINVAL); /* Make sure this is really a splitcomb port */ PJ_ASSERT_RETURN(sc->base.info.signature == SIGNATURE, PJ_EINVAL); /* Check the channel number */ PJ_ASSERT_RETURN(ch_num < sc->base.info.channel_count, PJ_EINVAL); /* options is unused for now */ PJ_UNUSED_ARG(options); /* Create the port */ rport = pj_pool_zalloc(pool, sizeof(struct reverse_port)); rport->parent = sc; rport->ch_num = ch_num; /* Initialize port info... */ port = &rport->base; pjmedia_port_info_init(&port->info, &name, SIGNATURE_PORT, splitcomb->info.clock_rate, 1, splitcomb->info.bits_per_sample, splitcomb->info.samples_per_frame / splitcomb->info.channel_count); /* ... and the callbacks */ port->put_frame = &rport_put_frame; port->get_frame = &rport_get_frame; port->on_destroy = &rport_on_destroy; rport->buf_cnt = options & 0xFF; if (rport->buf_cnt == 0) rport->buf_cnt = MAX_BUF_CNT; /* Create put buffers */ for (i=0; i<rport->buf_cnt; ++i) { rport->dnstream_buf[i] = pj_pool_zalloc(pool, port->info.bytes_per_frame); PJ_ASSERT_RETURN(rport->dnstream_buf[i], PJ_ENOMEM); } rport->dn_write_pos = rport->buf_cnt/2; /* Create get buffers */ for (i=0; i<rport->buf_cnt; ++i) { rport->upstream_buf[i] = pj_pool_zalloc(pool, port->info.bytes_per_frame); PJ_ASSERT_RETURN(rport->upstream_buf[i], PJ_ENOMEM); } rport->up_write_pos = rport->buf_cnt/2; /* Save port in the splitcomb */ sc->port_desc[ch_num].port = &rport->base; sc->port_desc[ch_num].reversed = PJ_TRUE; /* Done */ *p_chport = port; return PJ_SUCCESS; }
/* * Create file writer port. */ PJ_DEF(pj_status_t) pjmedia_wav_writer_port_create( pj_pool_t *pool, const char *filename, unsigned sampling_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, unsigned flags, pj_ssize_t buff_size, pjmedia_port **p_port ) { struct file_port *fport; pjmedia_wave_hdr wave_hdr; pj_ssize_t size; pj_str_t name; pj_status_t status; /* Check arguments. */ PJ_ASSERT_RETURN(pool && filename && p_port, PJ_EINVAL); /* Only supports 16bits per sample for now. * See flush_buffer(). */ PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL); /* Create file port instance. */ fport = PJ_POOL_ZALLOC_T(pool, struct file_port); PJ_ASSERT_RETURN(fport != NULL, PJ_ENOMEM); /* Initialize port info. */ pj_strdup2(pool, &name, filename); pjmedia_port_info_init(&fport->base.info, &name, SIGNATURE, sampling_rate, channel_count, bits_per_sample, samples_per_frame); fport->base.get_frame = &file_get_frame; fport->base.put_frame = &file_put_frame; fport->base.on_destroy = &file_on_destroy; if (flags == PJMEDIA_FILE_WRITE_ALAW) { fport->fmt_tag = PJMEDIA_WAVE_FMT_TAG_ALAW; fport->bytes_per_sample = 1; } else if (flags == PJMEDIA_FILE_WRITE_ULAW) { fport->fmt_tag = PJMEDIA_WAVE_FMT_TAG_ULAW; fport->bytes_per_sample = 1; } else { fport->fmt_tag = PJMEDIA_WAVE_FMT_TAG_PCM; fport->bytes_per_sample = 2; } /* Open file in write and read mode. * We need the read mode because we'll modify the WAVE header once * the recording has completed. */ status = pj_file_open(pool, filename, PJ_O_WRONLY, &fport->fd); if (status != PJ_SUCCESS) return status; /* Initialize WAVE header */ pj_bzero(&wave_hdr, sizeof(pjmedia_wave_hdr)); wave_hdr.riff_hdr.riff = PJMEDIA_RIFF_TAG; wave_hdr.riff_hdr.file_len = 0; /* will be filled later */ wave_hdr.riff_hdr.wave = PJMEDIA_WAVE_TAG; wave_hdr.fmt_hdr.fmt = PJMEDIA_FMT_TAG; wave_hdr.fmt_hdr.len = 16; wave_hdr.fmt_hdr.fmt_tag = (pj_uint16_t)fport->fmt_tag; wave_hdr.fmt_hdr.nchan = (pj_int16_t)channel_count; wave_hdr.fmt_hdr.sample_rate = sampling_rate; wave_hdr.fmt_hdr.bytes_per_sec = sampling_rate * channel_count * fport->bytes_per_sample; wave_hdr.fmt_hdr.block_align = (pj_uint16_t) (fport->bytes_per_sample * channel_count); wave_hdr.fmt_hdr.bits_per_sample = (pj_uint16_t) (fport->bytes_per_sample * 8); wave_hdr.data_hdr.data = PJMEDIA_DATA_TAG; wave_hdr.data_hdr.len = 0; /* will be filled later */ /* Convert WAVE header from host byte order to little endian * before writing the header. */ pjmedia_wave_hdr_host_to_file(&wave_hdr); /* Write WAVE header */ if (fport->fmt_tag != PJMEDIA_WAVE_FMT_TAG_PCM) { pjmedia_wave_subchunk fact_chunk; pj_uint32_t tmp = 0; fact_chunk.id = PJMEDIA_FACT_TAG; fact_chunk.len = 4; PJMEDIA_WAVE_NORMALIZE_SUBCHUNK(&fact_chunk); /* Write WAVE header without DATA chunk header */ size = sizeof(pjmedia_wave_hdr) - sizeof(wave_hdr.data_hdr); status = pj_file_write(fport->fd, &wave_hdr, &size); if (status != PJ_SUCCESS) { pj_file_close(fport->fd); return status; } /* Write FACT chunk if it stores compressed data */ size = sizeof(fact_chunk); status = pj_file_write(fport->fd, &fact_chunk, &size); if (status != PJ_SUCCESS) { pj_file_close(fport->fd); return status; } size = 4; status = pj_file_write(fport->fd, &tmp, &size); if (status != PJ_SUCCESS) { pj_file_close(fport->fd); return status; } /* Write DATA chunk header */ size = sizeof(wave_hdr.data_hdr); status = pj_file_write(fport->fd, &wave_hdr.data_hdr, &size); if (status != PJ_SUCCESS) { pj_file_close(fport->fd); return status; } } else { size = sizeof(pjmedia_wave_hdr); status = pj_file_write(fport->fd, &wave_hdr, &size); if (status != PJ_SUCCESS) { pj_file_close(fport->fd); return status; } } /* Set buffer size. */ if (buff_size < 1) buff_size = PJMEDIA_FILE_PORT_BUFSIZE; fport->bufsize = buff_size; /* Check that buffer size is greater than bytes per frame */ pj_assert(fport->bufsize >= PJMEDIA_PIA_AVG_FSZ(&fport->base.info)); /* Allocate buffer and set initial write position */ fport->buf = (char*) pj_pool_alloc(pool, fport->bufsize); if (fport->buf == NULL) { pj_file_close(fport->fd); return PJ_ENOMEM; } fport->writepos = fport->buf; /* Done. */ *p_port = &fport->base; PJ_LOG(4,(THIS_FILE, "File writer '%.*s' created: samp.rate=%d, bufsize=%uKB", (int)fport->base.info.name.slen, fport->base.info.name.ptr, PJMEDIA_PIA_SRATE(&fport->base.info), fport->bufsize / 1000)); return PJ_SUCCESS; }
PJ_DEF(pj_status_t) pjmedia_resample_port_create( pj_pool_t *pool, pjmedia_port *dn_port, unsigned clock_rate, unsigned opt, pjmedia_port **p_port ) { const pj_str_t name = pj_str("resample"); struct resample_port *rport; unsigned ptime; pj_status_t status; /* Validate arguments. */ PJ_ASSERT_RETURN(pool && dn_port && clock_rate && p_port, PJ_EINVAL); /* Only supports 16bit samples per frame */ PJ_ASSERT_RETURN(dn_port->info.bits_per_sample == 16, PJMEDIA_ENCBITS); ptime = dn_port->info.samples_per_frame * 1000 / dn_port->info.clock_rate; /* Create and initialize port. */ rport = PJ_POOL_ZALLOC_T(pool, struct resample_port); PJ_ASSERT_RETURN(rport != NULL, PJ_ENOMEM); pjmedia_port_info_init(&rport->base.info, &name, SIGNATURE, clock_rate, dn_port->info.channel_count, BYTES_PER_SAMPLE * 8, clock_rate * ptime / 1000); rport->dn_port = dn_port; rport->options = opt; /* Create buffers. * We need separate buffer for get_frame() and put_frame() since * both functions may run simultaneously. */ rport->get_buf = (pj_int16_t*) pj_pool_alloc(pool, dn_port->info.bytes_per_frame); PJ_ASSERT_RETURN(rport->get_buf != NULL, PJ_ENOMEM); rport->put_buf = (pj_int16_t*) pj_pool_alloc(pool, dn_port->info.bytes_per_frame); PJ_ASSERT_RETURN(rport->put_buf != NULL, PJ_ENOMEM); /* Create "get_frame" resample */ status = pjmedia_resample_create(pool, (opt&PJMEDIA_RESAMPLE_USE_LINEAR)==0, (opt&PJMEDIA_RESAMPLE_USE_SMALL_FILTER)==0, dn_port->info.channel_count, dn_port->info.clock_rate, rport->base.info.clock_rate, dn_port->info.samples_per_frame, &rport->resample_get); if (status != PJ_SUCCESS) return status; /* Create "put_frame" resample */ status = pjmedia_resample_create(pool, (opt&PJMEDIA_RESAMPLE_USE_LINEAR)==0, (opt&PJMEDIA_RESAMPLE_USE_SMALL_FILTER)==0, dn_port->info.channel_count, rport->base.info.clock_rate, dn_port->info.clock_rate, rport->base.info.samples_per_frame, &rport->resample_put); /* Media port interface */ rport->base.get_frame = &resample_get_frame; rport->base.put_frame = &resample_put_frame; rport->base.on_destroy = &resample_destroy; /* Done */ *p_port = &rport->base; return PJ_SUCCESS; }
/* * Create opus writer port. */ PJ_DEF(pj_status_t) pjmedia_opus_writer_port_create( pj_pool_t *pool, const char *filename, unsigned sampling_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, unsigned flags, pj_ssize_t buff_size, pjmedia_port **p_port ) { struct opus_port *oport; struct opus_tool_param *otp; pj_str_t name; pj_status_t status; pjmedia_frame tempframe; int i,ret; /* Check arguments. */ PJ_ASSERT_RETURN(pool && filename && p_port, PJ_EINVAL); /* Only supports 16bits per sample for now. */ PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL); /* Create file port instance. */ oport = PJ_POOL_ZALLOC_T(pool, struct opus_port); PJ_ASSERT_RETURN(oport != NULL, PJ_ENOMEM); /* Initialize port info. */ pj_strdup2(pool, &name, filename); pjmedia_port_info_init(&oport->base.info, &name, SIGNATURE, sampling_rate, channel_count, bits_per_sample, samples_per_frame); oport->base.get_frame = &opus_get_frame; oport->base.put_frame = &opus_put_frame; oport->base.on_destroy = &opus_on_destroy; oport->bytes_per_sample = 2; /********************** * opus-tool Start *********************/ otp = PJ_POOL_ZALLOC_T(pool, struct opus_tool_param); PJ_ASSERT_RETURN(otp != NULL, PJ_ENOMEM); /* Initialize some default parameters. */ otp->opt_ctls_ctlval=NULL; otp->frange=NULL; otp->range_file=NULL; otp->inopt.channels=channel_count; otp->inopt.rate=otp->coding_rate=otp->rate=sampling_rate; /* Some default value */ otp->frame_size=960; otp->bitrate=-1; otp->with_hard_cbr=0; otp->with_cvbr=0; otp->complexity=10; otp->expect_loss=0; otp->lookahead=0; otp->bytes_written=0; otp->pages_out=0; otp->comment_padding=512; otp->eos=0; otp->nb_samples=-1; otp->id=-1; otp->nb_encoded=0; otp->enc_granulepos=0; otp->total_bytes=0; otp->peak_bytes=0; otp->max_ogg_delay=48000; /* 0 dB gain is recommended unless you know what you're doing */ otp->inopt.gain=0; otp->inopt.samplesize=(oport->bytes_per_sample)*8; otp->inopt.endianness=0; otp->inopt.rawmode=0; otp->inopt.ignorelength=0; otp->inopt.copy_comments=1; otp->inopt.skip=0; otp->start_time = time(NULL); srand(((_getpid()&65535)<<15)^(otp->start_time)); otp->serialno=rand(); otp->opus_version="libopus 1.0.3"; /* Vendor string should just be the encoder library, the ENCODER comment specifies the tool used. */ comment_init(&otp->inopt.comments, &otp->inopt.comments_length, otp->opus_version); snprintf(otp->ENCODER_string, sizeof(otp->ENCODER_string), "opusenc from %s %s", PACKAGE_NAME, PACKAGE_VERSION); comment_add(&otp->inopt.comments, &otp->inopt.comments_length, "ENCODER", otp->ENCODER_string); otp->outFile=(char *)filename; otp->rate=otp->inopt.rate; otp->chan=otp->inopt.channels; otp->inopt.skip=0; if(otp->rate>24000)otp->coding_rate=48000; else if(otp->rate>16000)otp->coding_rate=24000; else if(otp->rate>12000)otp->coding_rate=16000; else if(otp->rate>8000)otp->coding_rate=12000; else otp->coding_rate=8000; otp->frame_size=otp->frame_size/(48000/otp->coding_rate); /*OggOpus headers*/ /*FIXME: broke forcemono*/ otp->header.channels=otp->chan; otp->header.channel_mapping=otp->header.channels>8?255:otp->chan>2; otp->header.input_sample_rate=otp->rate; otp->header.gain=otp->inopt.gain; /* Initialize OPUS encoder */ /* Framesizes <10ms can only use the MDCT modes, so we switch on RESTRICTED_LOWDELAY to save the extra 2.5ms of codec lookahead when we'll be using only small frames. */ otp->st=opus_multistream_surround_encoder_create(otp->coding_rate, otp->chan, otp->header.channel_mapping, &otp->header.nb_streams, &otp->header.nb_coupled, otp->header.stream_map, otp->frame_size<480/(48000/otp->coding_rate)?OPUS_APPLICATION_RESTRICTED_LOWDELAY:OPUS_APPLICATION_AUDIO, &ret); if(ret!=OPUS_OK) { fprintf(stderr, "Error cannot create encoder: %s\n", opus_strerror(ret)); exit(1); } otp->min_bytes=otp->max_frame_bytes=(1275*3+7)*otp->header.nb_streams; otp->packet=(unsigned char*)malloc(sizeof(unsigned char)*otp->max_frame_bytes); if(otp->packet==NULL) { fprintf(stderr, "Error allocating packet buffer.\n"); exit(1); } if(otp->bitrate<0) { /* Lower default rate for sampling rates [8000-44100) by a factor of (rate+16k)/(64k) */ otp->bitrate=((64000*otp->header.nb_streams+32000*otp->header.nb_coupled)* (IMIN(48,IMAX(8,((otp->rate<44100?otp->rate:48000)+1000)/1000))+16)+32)>>6; }
pj_status_t pjmedia_sxs_port_server_create(// pj_pool_t *pool, // const char *filename, unsigned sampling_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, unsigned flags, pj_ssize_t buff_size, pjmedia_port **p_port) { sxs_port *fport; pjmedia_wave_hdr wave_hdr; pj_ssize_t size; pj_str_t name; pj_status_t status; char f_type; /* Check arguments. */ // PJ_ASSERT_RETURN(pool && filename && p_port, PJ_EINVAL); /* Only supports 16bits per sample for now. * See flush_buffer(). */ PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL); fport = (sxs_port_t *)calloc(1, sizeof(sxs_port_t)); memset(fport, 0, sizeof(sxs_port_t)); fport->eph = g_param->epfd; // fport->in_vocie_frame_rb = ringbuffer_create(1024*1024*2); fport->use_frame_buff = true; // fport->use_frame_buff = false; memset(fport->lock_free_rbuf_ptr, 0, sizeof(fport->lock_free_rbuf_ptr)); fport->lock_free_rbuf_head_pos = fport->lock_free_rbuf_tail_pos = 0; name = pj_str("hahahahahaha"); pjmedia_port_info_init(&fport->base.info, &name, SIGNATURE, sampling_rate, channel_count, bits_per_sample, samples_per_frame); // fport->base.get_frame = &file_get_frame; // fport->base.put_frame = &file_put_frame; fport->base.get_frame = NULL; fport->base.put_frame = NULL; // fport->base.on_destroy = &file_on_destroy; if (flags == PJMEDIA_FILE_WRITE_ALAW) { fport->fmt_tag = PJMEDIA_WAVE_FMT_TAG_ALAW; fport->bytes_per_sample = 1; } else if (flags == PJMEDIA_FILE_WRITE_ULAW) { fport->fmt_tag = PJMEDIA_WAVE_FMT_TAG_ULAW; fport->bytes_per_sample = 1; } else { fport->fmt_tag = PJMEDIA_WAVE_FMT_TAG_PCM; fport->bytes_per_sample = 2; } /* Set buffer size. */ if (buff_size < 1) buff_size = PJMEDIA_FILE_PORT_BUFSIZE; fport->bufsize = buff_size; /* Check that buffer size is greater than bytes per frame */ // pj_assert(fport->bufsize >= fport->base.info.bytes_per_frame); // socket, bind, listen, accept g_param->mpo_serv_sock = fport->out_serv_fd = create_tcp_server(); g_param->mpi_serv_sock = fport->in_serv_fd = create_tcp_server(); /* Done. */ *p_port = &fport->base; PJ_LOG(4,(THIS_FILE, "File writer '%.*s' created: samp.rate=%d, bufsize=%uKB, bytes per frame=%d", (int)fport->base.info.name.slen, fport->base.info.name.ptr, fport->base.info.clock_rate, fport->bufsize / 1000, fport->base.info.bytes_per_frame)); return PJ_SUCCESS; return 0; }
/* * Create reverse phase port for the specified channel. */ PJ_DEF(pj_status_t) pjmedia_splitcomb_create_rev_channel( pj_pool_t *pool, pjmedia_port *splitcomb, unsigned ch_num, unsigned options, pjmedia_port **p_chport) { const pj_str_t name = pj_str("scomb-rev"); struct splitcomb *sc = (struct splitcomb*) splitcomb; struct reverse_port *rport; unsigned buf_cnt; const pjmedia_audio_format_detail *sc_afd, *p_afd; pjmedia_port *port; pj_status_t status; /* Sanity check */ PJ_ASSERT_RETURN(pool && splitcomb, PJ_EINVAL); /* Make sure this is really a splitcomb port */ PJ_ASSERT_RETURN(sc->base.info.signature == SIGNATURE, PJ_EINVAL); /* Check the channel number */ PJ_ASSERT_RETURN(ch_num < PJMEDIA_PIA_CCNT(&sc->base.info), PJ_EINVAL); /* options is unused for now */ PJ_UNUSED_ARG(options); sc_afd = pjmedia_format_get_audio_format_detail(&splitcomb->info.fmt, 1); /* Create the port */ rport = PJ_POOL_ZALLOC_T(pool, struct reverse_port); rport->parent = sc; rport->ch_num = ch_num; /* Initialize port info... */ port = &rport->base; pjmedia_port_info_init(&port->info, &name, SIGNATURE_PORT, sc_afd->clock_rate, 1, sc_afd->bits_per_sample, PJMEDIA_PIA_SPF(&splitcomb->info) / sc_afd->channel_count); p_afd = pjmedia_format_get_audio_format_detail(&port->info.fmt, 1); /* ... and the callbacks */ port->put_frame = &rport_put_frame; port->get_frame = &rport_get_frame; port->on_destroy = &rport_on_destroy; /* Buffer settings */ buf_cnt = options & 0xFF; if (buf_cnt == 0) buf_cnt = MAX_BUF_CNT; rport->max_burst = MAX_BURST; rport->max_null_frames = MAX_NULL_FRAMES; /* Create downstream/put buffers */ status = pjmedia_delay_buf_create(pool, "scombdb-dn", p_afd->clock_rate, PJMEDIA_PIA_SPF(&port->info), p_afd->channel_count, buf_cnt * p_afd->frame_time_usec / 1000, 0, &rport->buf[DIR_DOWNSTREAM].dbuf); if (status != PJ_SUCCESS) { return status; } /* Create upstream/get buffers */ status = pjmedia_delay_buf_create(pool, "scombdb-up", p_afd->clock_rate, PJMEDIA_PIA_SPF(&port->info), p_afd->channel_count, buf_cnt * p_afd->frame_time_usec / 1000, 0, &rport->buf[DIR_UPSTREAM].dbuf); if (status != PJ_SUCCESS) { pjmedia_delay_buf_destroy(rport->buf[DIR_DOWNSTREAM].dbuf); return status; } /* And temporary upstream/get buffer */ rport->tmp_up_buf = (pj_int16_t*) pj_pool_alloc(pool, PJMEDIA_PIA_AVG_FSZ(&port->info)); /* Save port in the splitcomb */ sc->port_desc[ch_num].port = &rport->base; sc->port_desc[ch_num].reversed = PJ_TRUE; /* Done */ *p_chport = port; return status; }