static int WriteAudioFrame(AVFormatContext *oc, OutputStream *ost, AVI6 *avi) { AVCodecContext *c = NULL; AVPacket pkt = { 0 }; AVFrame *frame = NULL; int ret = 0; int got_packet = 0; int dst_nb_samples = 0; av_init_packet(&pkt); c = ost->st->codec; frame = GetAudioFrame(ost, avi); if (frame) { // フォーマット変換後のサンプル数を決定 dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, frame->sample_rate) + frame->nb_samples, c->sample_rate, c->sample_rate, AV_ROUND_UP); //av_assert0(dst_nb_samples == frame->nb_samples); // フレームを書き込み可能にする ret = av_frame_make_writable(ost->frame); if (ret < 0) exit(1); // 音声フォーマットを変換 ret = swr_convert(ost->swr_ctx, ost->frame->data, dst_nb_samples, (const uint8_t **)frame->data, frame->nb_samples); if (ret < 0) { fprintf(stderr, "Error while converting\n"); return 0; } frame = ost->frame; frame->pts = av_rescale_q(ost->samples_count, (AVRational){1, c->sample_rate}, c->time_base); ost->samples_count += dst_nb_samples; ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet); if (ret < 0) { fprintf(stderr, "Error encoding audio frame: %s\n", MakeErrorString(ret)); return 0; } if (got_packet) { ret = WriteFrame(oc, &c->time_base, ost->st, &pkt); if (ret < 0) { fprintf(stderr, "Error while writing audio frame: %s\n", MakeErrorString(ret)); return 0; } } } return (frame || got_packet) ? 0 : 1; }
void User::AddToPlaybackBuffer(MumbleVoip::PCMAudioFrame* frame) { received_voice_packet_count_++; // Buffer overflow handling: We drop the oldest packet in the buffer if (PlaybackBufferLengthMs() > playback_buffer_max_length_ms ) { MumbleVoip::PCMAudioFrame* frame = GetAudioFrame(); SAFE_DELETE(frame); } playback_queue_.push_back(frame); last_audio_frame_time_.restart(); if (!speaking_) { speaking_ = true; emit StartReceivingAudio(); } }
int main(int argc, char **argv) { int ret = -1; uint8_t *data = NULL; unsigned long size = 0; int times = 0; int width = 0; int height = 0; char *dest = NULL; unsigned long dest_size = 0; long long pts = 0; long long dts = 0; AUDIOPACKET ap[30] = {0}; int ap_len = 0; int i = 0; CAPTURECONFIG captureConfig; PCAPTURECONFIG pCaptureConfig = &captureConfig; ENCODECONFIG encodeConfig; PENCODECONFIG pEncodeConfig = &encodeConfig; PENCODER pEncoder; PCAPTURE pCapture; DWORD start_time, end_time; pCaptureConfig->fps = 5; pCaptureConfig->channels = 2; pCaptureConfig->bits_per_sample = 16; pCaptureConfig->samples_per_sec = 48000; pCaptureConfig->avg_bytes_per_sec = 48000; pEncodeConfig->fps = 5; pEncodeConfig->width = 1366; pEncodeConfig->height = 768; pEncodeConfig->bit_rate = 400000; pEncodeConfig->channels = 2; pEncodeConfig->bits_per_sample = 16; pEncodeConfig->sample_rate = 48000; pEncodeConfig->avg_bytes_per_sec = 48000; pEncodeConfig->record = 1; memcpy(pEncodeConfig->record_file, "D:\\desktop_live.mp4", 20); InitLog(LOG_DEBUG, OUT_FILE); pCapture = InitCapture(pCaptureConfig); if (NULL == pCapture) { printf("init capture failed\n"); return -1; } pEncoder = InitEncoder(pEncodeConfig); if (NULL == pEncoder) { printf("init encoder failed\n"); return -1; } ret = StartCapture(pCapture); if (SECCESS != ret) { printf("start capture failed\n"); return -1; } start_time = end_time = timeGetTime(); while(10*1000 > (end_time - start_time)) { if (SECCESS == GetVideoFrame(pCapture, &data, &size, &width, &height)) { ret = EncodeVideo(pEncoder, data, width, height, &dest, &dest_size, &pts, &dts); if (ret == SECCESS) { free(dest); } times++; printf("video data size = %d\n", size); free(data); } if (SECCESS == GetAudioFrame(pCapture, &data, &size)) { ap_len = 0; ret = EncodeAudio(pEncoder, data, size, ap, &ap_len); if (ret == SECCESS) { for (i=0; i<ap_len; i++) { free(ap[i].data); } } printf("audio data size = %d\n", size); free(data); } end_time = timeGetTime(); } StopCapture(pCapture); FreeCapture(pCapture); FflushEncoder(pEncoder); FreeEncoder(pEncoder); FreeLog(); _CrtDumpMemoryLeaks(); return 0; }
bool AudioMixerImpl::GetMixerAudio( webrtc::AudioFrame* audioFrame ) { if (m_participants.empty()) { return false; } // 分类 bool bMix = false; for ( auto& v : m_participants ) { auto participant = v.participant; auto audioFrame = PopAudioFrame(); bool ret = participant->GetAudioFrame( audioFrame ); if ( !ret ) { v.needMixCount = 0; v.weightFactor = 0.0f; v.audioFrame = nullptr; v.energy = 0; v.isMixed = false; PushAudioFrame( audioFrame ); continue; } bMix = true; v.energy = CalculateEnergy( audioFrame ); v.isSilent = audioFrame->vad_activity_ != webrtc::AudioFrame::kVadActive; v.audioFrame = audioFrame; } if (!bMix) { return false; } if (m_participants.size() > (uint32_t)m_limitCount) { m_participants.sort( [] ( MixerParticipantInfo& lhs, MixerParticipantInfo& rhs ) { return (lhs.energy > rhs.energy); } ); } MixerParticipantList mixerlist; int nMixframeCounter = 0; for ( auto it = m_participants.begin(); it != m_participants.end(); ++it ) { if ( m_limitCount >= nMixframeCounter ) { if (it->energy > 0) { nMixframeCounter++; it->needMixCount = 5; it->isMixed = true; // 这里系数的调整至关重要,目前先简单的处理下 if (it->isSilent) { it->weightFactor = 0.7f; } else { it->weightFactor = 1.0f; } mixerlist.push_back(*it); } } else { if (it->isMixed) { if ( it->needMixCount-- > 0 ) it->weightFactor /= 2; // 渐渐淡出 mixerlist.push_back( *it ); } } } MixFrameList( mixerlist, audioFrame ); for ( auto&v : m_participants ) { if ( v.audioFrame ) PushAudioFrame( v.audioFrame ); } return true; }