2013-08-24 78 views
1

從例子中我得到了這段代碼的基本思想。 但是我不確定我缺少什麼,因爲muxing.c demuxing.c和decode_encoding.c 都使用不同的方法。使用ffmpeg api轉換音頻文件。 avcodec_encode_audio2崩潰

的音頻文件轉換爲其他文件應該大致是這樣的過程: inputfile中-demux->語音串流-read-> inPackets -decode2frames-> 幀 -encode2packets-> outPackets -write->語音串流 - mux-> outputfile

但是,我在demuxing.c中發現了以下注釋: /*寫入第一個平面的原始音頻數據樣本。這對於打包格式(例如AV_SAMPLE_FMT_S16)適用
*。然而,大多數音頻解碼器輸出平面音頻,其使用每個聲道(例如,AV_SAMPLE_FMT_S16P)的音頻採樣的單獨平面。
*換句話說,在這些情況下,此代碼將只寫入第一個音頻通道
*。
*您應該使用libswresample或libavfilter將幀
*轉換爲打包數據。 */

我的這個問題是:

  1. 我能想到的是被調用的解碼器功能的一個檢索到的幀,F.E. avcodec_decode_audio4保存合適的值直接將其放入編碼器中或者是 註釋中提到的重採樣步驟是強制性的?

  2. 我正在採取正確的做法嗎? ffmpeg非常不對稱,即如果有一個函數 open_file_for_input,那麼可能沒有函數open_file_for_output。還有許多不同版本的許多功能(avcodec_decode_audio [1-4])和不同的命名方案,所以很難說,如果一般方法是正確的,或者實際上是在不同版本中使用的醜陋混合技術ffmpeg的顛簸。

  3. ffmpeg使用了很多特定的術語,如'平面採樣'或'打包格式',而且我很難找到這些術語的定義。在沒有深入的音頻知識的情況下,是否可以編寫工作代碼?

這裏是我到目前爲止的代碼,自己目前在avcodec_encode_audio2 崩潰,我不知道爲什麼。

int Java_com_fscz_ffmpeg_Audio_convert(JNIEnv * env, jobject this, jstring jformat, jstring jcodec, jstring jsource, jstring jdest) { 
    jboolean isCopy; 
    jclass configClass = (*env)->FindClass(env, "com.fscz.ffmpeg.Config"); 
    jfieldID fid = (*env)->GetStaticFieldID(env, configClass, "ffmpeg_logging", "I"); 
    logging = (*env)->GetStaticIntField(env, configClass, fid); 

    /// open input 
    const char* sourceFile = (*env)->GetStringUTFChars(env, jsource, &isCopy); 
    AVFormatContext* pInputCtx; 
    AVStream* pInputStream; 
    open_input(sourceFile, &pInputCtx, &pInputStream); 

    // open output 
    const char* destFile = (*env)->GetStringUTFChars(env, jdest, &isCopy); 
    const char* cformat = (*env)->GetStringUTFChars(env, jformat, &isCopy); 
    const char* ccodec = (*env)->GetStringUTFChars(env, jcodec, &isCopy); 
    AVFormatContext* pOutputCtx; 
    AVOutputFormat* pOutputFmt; 
    AVStream* pOutputStream; 
    open_output(cformat, ccodec, destFile, &pOutputCtx, &pOutputFmt, &pOutputStream); 

    /// decode/encode 
    error = avformat_write_header(pOutputCtx, NULL); 
    DIE_IF_LESS_ZERO(error, "error writing output stream header to file: %s, error: %s", destFile, e2s(error)); 

    AVFrame* frame = avcodec_alloc_frame(); 
    DIE_IF_UNDEFINED(frame, "Could not allocate audio frame"); 
    frame->pts = 0; 

    LOGI("allocate packet"); 
    AVPacket pktIn; 
    AVPacket pktOut; 
    LOGI("done"); 
    int got_frame, got_packet, len, frame_count = 0; 
    int64_t processed_time = 0, duration = pInputStream->duration; 
    while (av_read_frame(pInputCtx, &pktIn) >= 0) { 
     do { 
      len = avcodec_decode_audio4(pInputStream->codec, frame, &got_frame, &pktIn); 
      DIE_IF_LESS_ZERO(len, "Error decoding frame: %s", e2s(len)); 
      if (len < 0) break; 
      len = FFMIN(len, pktIn.size); 
      size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample(frame->format); 
      LOGI("audio_frame n:%d nb_samples:%d pts:%s\n", frame_count++, frame->nb_samples, av_ts2timestr(frame->pts, &(pInputStream->codec->time_base))); 
      if (got_frame) { 
       do { 
        av_init_packet(&pktOut); 
        pktOut.data = NULL; 
        pktOut.size = 0; 
        LOGI("encode frame"); 
        DIE_IF_UNDEFINED(pOutputStream->codec, "no output codec"); 
        DIE_IF_UNDEFINED(frame->nb_samples, "no nb samples"); 
        DIE_IF_UNDEFINED(pOutputStream->codec->internal, "no internal"); 
        LOGI("tests done"); 
        len = avcodec_encode_audio2(pOutputStream->codec, &pktOut, frame, &got_packet); 
        LOGI("encode done"); 
        DIE_IF_LESS_ZERO(len, "Error (re)encoding frame: %s", e2s(len)); 
       } while (!got_packet); 
       // write packet; 
       LOGI("write packet"); 
       /* Write the compressed frame to the media file. */ 
       error = av_interleaved_write_frame(pOutputCtx, &pktOut); 
       DIE_IF_LESS_ZERO(error, "Error while writing audio frame: %s", e2s(error)); 
       av_free_packet(&pktOut); 
      } 
      pktIn.data += len; 
      pktIn.size -= len; 
     } while (pktIn.size > 0); 
     av_free_packet(&pktIn); 
    } 

    LOGI("write trailer"); 
    av_write_trailer(pOutputCtx); 
    LOGI("end"); 

    /// close resources 
    avcodec_free_frame(&frame); 
    avcodec_close(pInputStream->codec); 
    av_free(pInputStream->codec); 
    avcodec_close(pOutputStream->codec); 
    av_free(pOutputStream->codec); 
    avformat_close_input(&pInputCtx); 
    avformat_free_context(pOutputCtx); 

    return 0; 
} 
+0

是這個壓縮inputfile中-demux->語音串流-read-> inPackets -decode2frames->幀視頻-encode2packets-> outPackets -write-過程> audiostream -mux-> outputfile –

回答