Как заполнить аудио AVFrame (ffmpeg) данными, полученными из CMSampleBufferRef (AVFoundation)?
Я пишу программу для потокового вещания аудио и видео с веб-камеры на rtmp-сервер. Я работаю в MacOS X 10.8, поэтому я использую фреймворк AVFoundation для получения аудио и видео кадров с устройств ввода. Эти кадры входят в делегат:
-(void) captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer: (CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection
,
где sampleBuffer
содержит аудио или видео данные.
Когда я получаю аудиоданные в sampleBuffer
Я пытаюсь преобразовать эти данные в AVFrame
и кодировать AVFrame
с помощью libavcodec:
aframe = avcodec_alloc_frame(); //AVFrame *aframe; int got_packet, ret; CMItemCount numSamples = CMSampleBufferGetNumSamples(sampleBuffer); //CMSampleBufferRef NSUInteger channelIndex = 0; CMBlockBufferRef audioBlockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer); size_t audioBlockBufferOffset = (channelIndex * numSamples * sizeof(SInt16)); size_t lengthAtOffset = 0; size_t totalLength = 0; SInt16 *samples = NULL; CMBlockBufferGetDataPointer(audioBlockBuffer, audioBlockBufferOffset, &lengthAtOffset, &totalLength, (char **)(&samples)); const AudioStreamBasicDescription *audioDescription = CMAudioFormatDescriptionGetStreamBasicDescription(CMSampleBufferGetFormatDescription(sampleBuffer)); aframe->nb_samples =(int) numSamples; aframe->channels=audioDescription->mChannelsPerFrame; aframe->sample_rate=(int)audioDescription->mSampleRate; //my webCamera configured to produce 16bit 16kHz LPCM mono, so sample format hardcoded here, and seems to be correct avcodec_fill_audio_frame(aframe, aframe->channels, AV_SAMPLE_FMT_S16, (uint8_t *)samples, aframe->nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * aframe->channels, 0); //encoding audio ret = avcodec_encode_audio2(c, &pkt, aframe, &got_packet); if (ret < 0) { fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret)); exit(1); }
Проблема в том, что когда я получаю сформированные кадры, я слышу нужный звук, но он замедляется и прерывистый (как будто после каждого кадра данных появляется один и тот же кадр молчания). Кажется, что-то не так в преобразовании из
CMSampleBuffer
вAVFrame
потому что предварительный просмотр с микрофона, созданного с помощью AVFoundation из тех же буферов сэмплов, воспроизводится нормально.Буду благодарен за вашу помощь.
UPD: создание и инициализация структуры AVCodceContext
audio_codec= avcodec_find_encoder(AV_CODEC_ID_AAC); if (!(audio_codec)) { fprintf(stderr, "Could not find encoder for '%s'\n", avcodec_get_name(AV_CODEC_ID_AAC)); exit(1); } audio_st = avformat_new_stream(oc, audio_codec); //AVFormatContext *oc; if (!audio_st) { fprintf(stderr, "Could not allocate stream\n"); exit(1); } audio_st->id=1; audio_st->codec->sample_fmt= AV_SAMPLE_FMT_S16; audio_st->codec->bit_rate = 64000; audio_st->codec->sample_rate= 16000; audio_st->codec->channels=1; audio_st->codec->codec_type= AVMEDIA_TYPE_AUDIO;