FFmpeg程式設計學習筆記二:音訊重取樣
阿新 • • 發佈:2019-01-28
ffmpeg實現音訊重取樣的核心函式swr_convert功能非常強大,可是ffmpeg文件對它的註釋太過簡單,在應用中往往會出這樣那樣的問題,其實在讀取資料->重取樣->編碼資料的迴圈中在第一次執行swr_convert後還應用swr_convert再作個快取檢測看看是否還有資料,如果有就要把它寫到FIFO中去,留在下次再使用,這點在轉碼和由低向高轉換取樣率時特別重要。
下面一段簡單的程式碼,摘自我自已寫的測試程式.
const int frame_size = FFMIN(fifo_size, m_Opt->encode_pCodecCtx->frame_size); if ((ret = av_audio_fifo_read(m_fifo, (void **)m_fifo_samples_array, frame_size)) < frame_size) { fprintf(stderr, "Could not read data from FIFO\n"); return AVERROR_EXIT; } int out_samples = av_rescale_rnd(swr_get_delay(m_Opt->out_resample_context, 48000) + 1536, 44100, 48000, AV_ROUND_UP); int conver_samples= swr_convert(m_Opt->out_resample_context, m_fifo_conver_samples_array, frame_size, (const uint8_t **)m_fifo_samples_array, frame_size); ret = av_audio_fifo_size(m_conver_fifo); if ((ret = av_audio_fifo_realloc(m_conver_fifo, av_audio_fifo_size(m_conver_fifo) + frame_size)) < 0) { fprintf(stderr, "Could not reallocate FIFO\n"); return ret; } ret = av_audio_fifo_write(m_conver_fifo, (void **)m_fifo_conver_samples_array, conver_samples); fifo_size = av_audio_fifo_size(m_conver_fifo); if ((ret = av_audio_fifo_read(m_conver_fifo, (void **)m_Opt->out_samples_array, frame_size)) < frame_size) { fprintf(stderr, "Could not read data from FIFO\n"); return AVERROR_EXIT; } ret = Encode_audio(ret); int ret1 = 0; while ((ret1 = swr_convert(m_Opt->out_resample_context, m_fifo_conver_samples_array, frame_size, NULL, 0)) > 0) { if ((ret = av_audio_fifo_realloc(m_conver_fifo, av_audio_fifo_size(m_conver_fifo) + ret1)) < 0) { fprintf(stderr, "Could not reallocate FIFO\n"); return ret; } ret = av_audio_fifo_write(m_conver_fifo, (void **)m_fifo_conver_samples_array, ret1); fifo_size = av_audio_fifo_size(m_conver_fifo); if (fifo_size > m_Opt->encode_pFrame->nb_samples) { if ((ret = av_audio_fifo_read(m_conver_fifo, (void **)m_Opt->out_samples_array, frame_size)) < frame_size) { fprintf(stderr, "Could not read data from FIFO\n"); return AVERROR_EXIT; } ret = Encode_audio(ret); }
因為是測試程式碼,有點亂中間也有一些不必要的步驟,主要是為了除錯好用。
重點在:
if ((r = swr_convert(swr_ctx, output, output_nb_samples,(const uint8_t**)input, nb_samples)) < 0)
return -1;
while ((r = swr_convert(swr_ctx, output, output_nb_samples, NULL, 0)) > 0) {
}