ffmpeg+audiounit

void audioSpec_init(VideoState *is, Float64 sample_rate){

// is audio input available?

AudioComponentDescription outputcd = {0}; // 10.6 version

outputcd.componentType = kAudioUnitType_Output;

outputcd.componentSubType = kAudioUnitSubType_DefaultOutput;

outputcd.componentManufacturer = kAudioUnitManufacturer_Apple;

AudioComponent comp = AudioComponentFindNext (NULL, &outputcd);

if (comp == NULL) {

printf ("can't get output unit");

exit (-1);

}

CheckError (AudioComponentInstanceNew(comp, &is->audio_wanted_spec.rioUnit),

"Couldn't open component for outputUnit");

AURenderCallbackStruct input;

input.inputProc = audio_unit_callback;

input.inputProcRefCon = is;

CheckError(AudioUnitSetProperty(is->audio_wanted_spec.rioUnit,

kAudioUnitProperty_SetRenderCallback,

kAudioUnitScope_Input,

0,

&input,

sizeof(input)),

"AudioUnitSetProperty failed");

CheckError (AudioUnitInitialize(is->audio_wanted_spec.rioUnit),

"Couldn't initialize output unit");

}

is->audio_frame.data[0]:左声道 拷贝到 audio_buf

is->audio_frame.data[1]:右声道 拷贝到 audio_buf1 

int audio_decode_frame(VideoState *is, uint8_t *audio_buf,uint8_t *audio_buf1, int buf_size, double *pts_ptr) {

int len1, data_size = 0;

AVPacket *pkt = &is->audio_pkt;

double pts;

int n;

for(;;) {

while(is->audio_pkt_size > 0) {

int got_frame = 0;

len1 = avcodec_decode_audio4(is->audio_ctx, &is->audio_frame, &got_frame, pkt);

if(len1 < 0) {

/* if error, skip frame */

is->audio_pkt_size = 0;

break;

}

data_size = 0;

if(got_frame) {

data_size = is->audio_frame.nb_samples * av_get_bytes_per_sample(is->audio_frame.format);

assert(data_size <= buf_size);

memcpy(audio_buf, is->audio_frame.data[0], data_size);

memcpy(audio_buf1, is->audio_frame.data[1], data_size);

}

is->audio_pkt_data += len1;

is->audio_pkt_size -= len1;

if(data_size <= 0) {

/* No data yet, get more frames */

continue;

}

pts = is->audio_clock;

*pts_ptr = pts;

n = 2 * is->audio_ctx->channels;

is->audio_clock += (double)data_size /

(double)(n * is->audio_ctx->sample_rate);

/* We have data, return it and come back for more later */

return data_size;

}

if(pkt->data)

av_free_packet(pkt);

if(is->quit) {

return -1;

}

/* next packet */

if(packet_queue_get(&is->audioq, pkt, 1) < 0) {

return -1;

}

if(pkt->data == flush_pkt.data) {

avcodec_flush_buffers(is->audio_ctx);

continue;

}

is->audio_pkt_data = pkt->data;

is->audio_pkt_size = pkt->size;

/* if update, update the audio clock w/pts */

if(pkt->pts != AV_NOPTS_VALUE) {

is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;

}

}

}

声音回调函数

OSStatus audio_unit_callback(void *inRefCon,

AudioUnitRenderActionFlags *ioActionFlags,

const AudioTimeStamp *inTimeStamp,

UInt32 inBusNumber,

UInt32 inNumberFrames,

AudioBufferList * ioData)

{

for (int iBuffer=0; iBuffer < ioData->mNumberBuffers; ++iBuffer) {

memset(ioData->mBuffers[iBuffer].mData, 0, ioData->mBuffers[iBuffer].mDataByteSize);

}

VideoState *is = (VideoState *)inRefCon;

int len = ioData->mBuffers[0].mDataByteSize;

int len1, audio_size = 0;

double pts;

if(is->audio_buf_index >= is->audio_buf_size){

audio_size = audio_decode_frame(is, is->audio_buf,is->audio_buf1, sizeof(is->audio_buf), &pts);

if(audio_size < 0) {

/* If error, output silence */

is->audio_buf_size = 1024;

memset(is->audio_buf, 0, is->audio_buf_size);

memset(is->audio_buf1, 0, is->audio_buf_size);

} else {

audio_size = synchronize_audio(is, (int16_t *)is->audio_buf,

audio_size, pts);

is->audio_buf_size = audio_size;

audio_size = synchronize_audio(is, (int16_t *)is->audio_buf1,

audio_size, pts);

is->audio_buf_size1  = audio_size;

}

is->audio_buf_index = 0;

}

len1 = is->audio_buf_size - is->audio_buf_index;

if(len1 > len)

len1 = len;

memcpy((float *)ioData->mBuffers[0].mData, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);

memcpy((float *)ioData->mBuffers[1].mData, (uint8_t *)is->audio_buf1 + is->audio_buf_index, len1);

ioData->mBuffers[0].mDataByteSize = len1;

ioData->mBuffers[1].mDataByteSize = len1;

len -= len1;

is->audio_buf_index += len1;

return noErr;

}

具体demo:https://github.com/765450034/ffplay-examples/blob/master/tutorial07%2Baudiounit.c

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容