真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Android音視頻深入十一FFmpeg和AudioTrack播放聲音(附源碼下載)

項(xiàng)目地址,求star
https://github.com/979451341/AudioVideoStudyCodeTwo/tree/master/FFmpeg%E6%92%AD%E6%94%BE%E9%9F%B3%E4%B9%90%EF%BC%88%E4%BF%9D%E7%A8%8B%E5%BA%8F%E4%B8%8D%E6%AD%BB%EF%BC%89

創(chuàng)新互聯(lián)建站是網(wǎng)站建設(shè)技術(shù)企業(yè),為成都企業(yè)提供專(zhuān)業(yè)的做網(wǎng)站、網(wǎng)站制作,網(wǎng)站設(shè)計(jì),網(wǎng)站制作,網(wǎng)站改版等技術(shù)服務(wù)。擁有十余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制適合企業(yè)的網(wǎng)站。十余年品質(zhì),值得信賴(lài)!

這個(gè)是FFmpeg解碼出音頻,給AudioTrack播放,這回才算是java與c語(yǔ)言之間合作

這回我們將會(huì)從c++里調(diào)用java函數(shù),下面就是關(guān)于c++使用AudioTrack的代碼

private AudioTrack audioTrack;
//    這個(gè)方法  是C進(jìn)行調(diào)用  通道數(shù)
public void createTrack(int sampleRateInHz,int nb_channals) {

    int channaleConfig;//通道數(shù)
    if (nb_channals == 1) {
        channaleConfig = AudioFormat.CHANNEL_OUT_MONO;
    } else if (nb_channals == 2) {
        channaleConfig = AudioFormat.CHANNEL_OUT_STEREO;
    }else {
        channaleConfig = AudioFormat.CHANNEL_OUT_MONO;
    }
    int buffersize=AudioTrack.getMinBufferSize(sampleRateInHz,
            channaleConfig, AudioFormat.ENCODING_PCM_16BIT);
    audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,sampleRateInHz,channaleConfig,
            AudioFormat.ENCODING_PCM_16BIT,buffersize,AudioTrack.MODE_STREAM);
    audioTrack.play();
}

//C傳入音頻數(shù)據(jù)
public void playTrack(byte[] buffer, int lenth) {
    if (audioTrack != null && audioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) {
        audioTrack.write(buffer, 0, lenth);
    }
}

我們?cè)賮?lái)看看c++的代碼

首先注冊(cè)組件,然后得到音頻流

 av_register_all();
AVFormatContext *pFormatCtx = avformat_alloc_context();
//open
if (avformat_open_input(&pFormatCtx, input, NULL, NULL) != 0) {
    LOGE("%s","打開(kāi)輸入視頻文件失敗");
    return;
}
//獲取視頻信息
if(avformat_find_stream_info(pFormatCtx,NULL) < 0){
    LOGE("%s","獲取視頻信息失敗");
    return;
}
int audio_stream_idx=-1;
int i=0;
for (int i = 0; i < pFormatCtx->nb_streams; ++i) {
    if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
        LOGE("  找到音頻id %d", pFormatCtx->streams[i]->codec->codec_type);
        audio_stream_idx=i;
        break;
    }
}

獲取×××

//獲取×××上下文
AVCodecContext *pCodecCtx=pFormatCtx->streams[audio_stream_idx]->codec;
//獲取×××
AVCodec *pCodex = avcodec_find_decoder(pCodecCtx->codec_id);
//打開(kāi)×××
if (avcodec_open2(pCodecCtx, pCodex, NULL)<0) {
}

設(shè)置緩存區(qū),保存解碼前后的數(shù)據(jù)

//申請(qǐng)avpakcet,裝解碼前的數(shù)據(jù)
AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
//申請(qǐng)avframe,裝解碼后的數(shù)據(jù)
AVFrame *frame = av_frame_alloc();

設(shè)置解碼出的聲音一系列的屬性,比如:?jiǎn)温暤馈㈦p聲道、采集點(diǎn)大小、采集率,還可以在這里對(duì)聲音添加特效,

//得到SwrContext ,進(jìn)行重采樣,具體參考http://blog.csdn.net/jammg/article/details/52688506
SwrContext *swrContext = swr_alloc();
//緩存區(qū)
uint8_t *out_buffer = (uint8_t *) av_malloc(44100 * 2);

//輸出的聲道布局(立體聲)
uint64_t out_ch_layout=AV_CH_LAYOUT_STEREO;
//輸出采樣位數(shù) 16位
enum AVSampleFormat out_formart=AV_SAMPLE_FMT_S16;
//輸出的采樣率必須與輸入相同
int out_sample_rate = pCodecCtx->sample_rate;

//swr_alloc_set_opts將PCM源文件的采樣格式轉(zhuǎn)換為自己希望的采樣格式
swr_alloc_set_opts(swrContext, out_ch_layout, out_formart, out_sample_rate,
pCodecCtx->channel_layout, pCodecCtx->sample_fmt, pCodecCtx->sample_rate, 0,
NULL);

swr_init(swrContext);

// 獲取通道數(shù) 2
int out_channer_nb = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO);

通過(guò)反射能夠運(yùn)行java函數(shù)

// 反射得到Class類(lèi)型
jclass david_player = env->GetObjectClass(instance);
// 反射得到createAudio方法
jmethodID createAudio = env->GetMethodID(david_player, "createTrack", "(II)V");
// 反射調(diào)用createAudio
env->CallVoidMethod(instance, createAudio, 44100, out_channer_nb);
jmethodID audio_write = env->GetMethodID(david_player, "playTrack", "([BI)V");

在一邊解碼的時(shí)候一邊給數(shù)據(jù)給AudioTrack播放

while (av_read_frame(pFormatCtx, packet) >= 0) {
    if (packet->stream_index == audio_stream_idx) {

// 解碼 mp3 編碼格式frame----pcm frame
avcodec_decode_audio4(pCodecCtx, frame, &got_frame, packet);
if (got_frame) {
LOGE("解碼");
swr_convert(swrContext, &out_buffer, 44100 * 2, (const uint8_t *) frame->data, frame->nb_samples);
// 緩沖區(qū)的大小
int size = av_samples_get_buffer_size(NULL, out_channer_nb, frame->nb_samples,
AV_SAMPLE_FMT_S16, 1);
jbyteArray audio_sample_array = env->NewByteArray(size);
env->SetByteArrayRegion(audio_sample_array, 0, size, (const jbyte
) out_buffer);
env->CallVoidMethod(instance, audio_write, audio_sample_array, size);
env->DeleteLocalRef(audio_sample_array);
}
}
}

釋放資源

av_frame_free(&frame);
swr_free(&swrContext);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
env->ReleaseStringUTFChars(input_, input);

FFmpeg只是音視頻處理的工具,他沒(méi)有播放視頻和音頻的能力,所以我們需要SurfaceView顯示視頻,AudioTrack播放聲音,而且OpenGLES也能播放聲音,這個(gè)后面說(shuō)

下一次就是說(shuō)如何將視頻的聲音給聽(tīng)換掉,也就是將音視頻的解碼和編碼都來(lái)搞一次


網(wǎng)頁(yè)標(biāo)題:Android音視頻深入十一FFmpeg和AudioTrack播放聲音(附源碼下載)
當(dāng)前路徑:http://weahome.cn/article/pdsisp.html

其他資訊

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部