录音机:录制为PCM文件
代码语言:javascript复制//broadcast_record.c
/*
录制wav,之后编码,再通过组播发送出去
组播接收wav, 解码?播放wav
*/
#include <pjmedia-audiodev/audiodev.h>
#include <pjmedia.h>
#include <pjlib.h>
#include <pjlib-util.h>
#include "broadcast_app.h"
#define THIS_FILE "broadcast_record.c"
static volatile pj_pool_t *pool = NULL;
static pjmedia_aud_param param;
static volatile pjmedia_aud_stream *strm = NULL;
static unsigned playback_lat = 20;//PJMEDIA_SND_DEFAULT_PLAY_LATENCY;
static unsigned capture_lat = 20;
static volatile RecordCallback recordCallback = NULL;
int stop_record(void)
{
recordCallback = NULL;
if (strm) {
pjmedia_aud_stream_stop(strm);
pjmedia_aud_stream_destroy(strm);
}
if (pool){
pj_pool_release(pool);
}
strm = NULL;
pool = NULL;
return 0;
}
static pj_status_t wav_rec_cb(void *user_data, pjmedia_frame *frame)
{
//回调函数
//return pjmedia_port_put_frame((pjmedia_port*)user_data, frame);
pj_int16_t *pcm_in = (pj_int16_t*)frame->buf;
//编码?
//发送?
if (recordCallback != NULL){
recordCallback(user_data, pcm_in, (int)frame->size, frame->timestamp.u32.lo);
}
return 0;
}
/*
sample_rate:16000
channel:1
*/
int start_record(int sample_rate, int channel, void *user_data, RecordCallback callback)
{
pj_status_t status;
//first stop
stop_record();
pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(), "wav",
1000, 1000, NULL);
status = pjmedia_aud_dev_default_param(0, ¶m);
if (status != PJ_SUCCESS) {
printf("pjmedia_aud_dev_default_param()", status);
goto on_return;
}
param.dir = PJMEDIA_DIR_CAPTURE;
param.clock_rate = sample_rate;
param.samples_per_frame = (sample_rate/1000)*10*channel;//*2
param.channel_count = channel;
param.bits_per_sample = 16;
/* Latency settings */
param.flags |= (PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY |
PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY);
param.input_latency_ms = capture_lat;
param.output_latency_ms = playback_lat;
if (strm) {
pjmedia_aud_stream_stop(strm);
pjmedia_aud_stream_destroy(strm);
}
status = pjmedia_aud_stream_create(¶m, &wav_rec_cb, NULL, user_data,
&strm);
if (status != PJ_SUCCESS) {
printf("Error opening the sound device", status);
goto on_failed;
}
status = pjmedia_aud_stream_start(strm);
if (status != PJ_SUCCESS) {
printf("Error starting the sound device", status);
goto on_failed;
}
//增加回调函数
recordCallback = callback;
PJ_LOG(3,(THIS_FILE, "Recording started"));
goto on_return;
on_failed:
if (strm) {
pjmedia_aud_stream_stop(strm);
pjmedia_aud_stream_destroy(strm);
}
if (pool){
pj_pool_release(pool);
}
on_return:
return 0;
}
播放器:播放PCM音频;
代码语言:javascript复制//broadcast_play.c
#include <pjmedia-audiodev/audiodev.h>
#include <pjmedia.h>
#include <pjlib.h>
#include <pjlib-util.h>
#include "broadcast_app.h"
#define THIS_FILE "broadcast_play.c"
static volatile pj_pool_t *pool = NULL;
static pjmedia_aud_param param;
static volatile pjmedia_aud_stream *strm = NULL;
static unsigned playback_lat = 20;//PJMEDIA_SND_DEFAULT_PLAY_LATENCY;
static unsigned capture_lat = 20;//PJMEDIA_SND_DEFAULT_REC_LATENCY;
static volatile RecordCallback playCallback = NULL;
static pj_status_t wav_play_cb(void *user_data, pjmedia_frame *frame)
{
//return pjmedia_port_get_frame((pjmedia_port*)user_data, frame);
if (playCallback != NULL){
playCallback(user_data, frame->buf, (int)frame->size, frame->timestamp.u32.lo);
}
return 0;
}
int stop_play(void){
playCallback = NULL;
if (strm) {
pjmedia_aud_stream_stop(strm);
pjmedia_aud_stream_destroy(strm);
}
if (pool){
pj_pool_release(pool);
}
strm = NULL;
pool = NULL;
printf("stop_play() endrn");
return 0;
}
/*
sample_rate:16000
channel:1
user_data:回调的用户对象
callback:回调函数
*/
int start_play(int sample_rate, int channel, void *user_data, PlayCallback callback)
{
pj_status_t status;
//first stop
stop_record();
pool = pj_pool_create(pjmedia_aud_subsys_get_pool_factory(), "play",
1000, 1000, NULL);
status = pjmedia_aud_dev_default_param(0, ¶m);
if (status != PJ_SUCCESS) {
printf("pjmedia_aud_dev_default_param()", status);
goto on_return;
}
param.dir = PJMEDIA_DIR_PLAYBACK;
param.clock_rate = sample_rate;
param.samples_per_frame = (sample_rate/1000)*10*channel;//320;*2
param.channel_count = channel;
param.bits_per_sample = 16;
/* Latency settings */
param.flags |= (PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY |
PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY);
param.input_latency_ms = capture_lat;
param.output_latency_ms = playback_lat;
status = pjmedia_aud_stream_create(¶m, NULL, &wav_play_cb, user_data,
&strm);
if (status != PJ_SUCCESS) {
printf("Error opening the sound device", status);
goto on_failed;
}
status = pjmedia_aud_stream_start(strm);
if (status != PJ_SUCCESS) {
printf("Error starting the sound device", status);
goto on_failed;
}
playCallback = callback;
PJ_LOG(3,(THIS_FILE, "play started,strm:x",strm));
goto on_return;
on_failed:
if (strm) {
pjmedia_aud_stream_stop(strm);
pjmedia_aud_stream_destroy(strm);
}
if (pool){
pj_pool_release(pool);
}
on_return:
return 0;
}
broadcast_app.h
代码语言:javascript复制//broadcast_app.h
#ifndef __BROADCAST_APP__
#define __BROADCAST_APP__
#include <unistd.h>
#ifdef __cplusplus
extern "C"{
#endif
typedef int (*PlayCallback)(void *user_data,uint8_t *rawData, int len, uint32_t timestamp);
typedef int (*RecordCallback)(void *user_data,uint16_t *rawData, int len, uint32_t timestamp);
int start_play(int sample_rate, int channel,void *user_data, PlayCallback callback);
int stop_play(void);
int start_record(int sample_rate, int channel,void *user_data, RecordCallback callback);
int stop_record(void);
#ifdef __cplusplus
}
#endif
#endif//__BROADCAST_APP__
调用:
代码语言:javascript复制
#define RECORD_SAMPLE_RATE 16000
#define RECORD_SAMPLE_CHANNEL 2
static int RecordCallbackFunc(void *user_data,uint16_t *rawData, int len, uint32_t timestamp){
//写wav文件
}
//set mic callback
start_record(RECORD_SAMPLE_RATE, RECORD_SAMPLE_CHANNEL, NULL, RecordCallbackFunc);
static int PlayCallbackFunc(void *user_data,uint8_t *rawData, int len, uint32_t timestamp){
//从缓冲区中读PCM数据,然后写到rawData中
struct ringbuf ringitem ;
int itemlen = ringget(&ringitem);
if (itemlen > 0 && rawData != NULL){
int copy_len = itemlen;
if (itemlen > len){
copy_len = len;
}
memcpy(rawData, ringitem.buffer, copy_len);
}
return 0;
}
start_play(RECORD_SAMPLE_RATE, RECORD_SAMPLE_CHANNEL, NULL, PlayCallbackFunc);