2010-03-09 39 views
13

Tôi đang sử dụng libavcodec (git mới nhất kể từ 3/3/10) để mã hóa pcm thô thành aac (bật hỗ trợ libfaac). Tôi làm điều này bằng cách gọi avcodec_encode_audio nhiều lần với codec_context-> frame_size mẫu mỗi lần. Bốn cuộc gọi đầu tiên trả về thành công, nhưng cuộc gọi thứ năm không bao giờ trả về. Khi tôi sử dụng gdb để ngắt, ngăn xếp bị hỏng.Mã hóa âm thanh thành aac bằng libavcodec

Nếu tôi sử dụng audacity để xuất dữ liệu pcm sang tệp .wav, thì tôi có thể sử dụng dòng lệnh ffmpeg để chuyển sang aac mà không gặp bất kỳ vấn đề nào, vì vậy tôi chắc chắn đó là .

Tôi đã viết một chương trình thử nghiệm nhỏ sao chép vấn đề của tôi. Nó đọc dữ liệu thử nghiệm từ một tệp, có sẵn tại đây: http://birdie.protoven.com/audio.pcm (~ 2 giây đã ký 16 bit LE pcm)

Tôi có thể làm cho tất cả hoạt động nếu tôi sử dụng FAAC trực tiếp, nhưng mã sẽ là ít sạch hơn nếu tôi chỉ có thể sử dụng libavcodec, như tôi cũng mã hóa video, và viết cả hai vào một mp4.

ffmpeg phiên bản thông tin:

FFmpeg version git-c280040, Copyright (c) 2000-2010 the FFmpeg developers 
    built on Mar 3 2010 15:40:46 with gcc 4.4.1 
    configuration: --enable-libfaac --enable-gpl --enable-nonfree --enable-version3 --enable-postproc --enable-pthreads --enable-debug=3 --enable-shared 
    libavutil  50.10. 0/50.10. 0 
    libavcodec 52.55. 0/52.55. 0 
    libavformat 52.54. 0/52.54. 0 
    libavdevice 52. 2. 0/52. 2. 0 
    libswscale  0.10. 0/0.10. 0 
    libpostproc 51. 2. 0/51. 2. 0 

Có một cái gì đó tôi không thiết lập hoặc thiết lập sai codec bối cảnh của tôi, có lẽ? Bất kỳ trợ giúp nào cũng được đánh giá rất cao!

Đây là mã thử nghiệm của tôi:

#include <stdio.h> 
#include <libavcodec/avcodec.h> 

void EncodeTest(int sampleRate, int channels, int audioBitrate, 
    uint8_t *audioData, size_t audioSize) 
{ 
    AVCodecContext *audioCodec; 
    AVCodec *codec; 
    uint8_t *buf; 
    int bufSize, frameBytes; 

    avcodec_register_all(); 

    //Set up audio encoder 
    codec = avcodec_find_encoder(CODEC_ID_AAC); 
    if (codec == NULL) return; 
    audioCodec = avcodec_alloc_context(); 
    audioCodec->bit_rate = audioBitrate; 
    audioCodec->sample_fmt = SAMPLE_FMT_S16; 
    audioCodec->sample_rate = sampleRate; 
    audioCodec->channels = channels; 
    audioCodec->profile = FF_PROFILE_AAC_MAIN; 
    audioCodec->time_base = (AVRational){1, sampleRate}; 
    audioCodec->codec_type = CODEC_TYPE_AUDIO; 
    if (avcodec_open(audioCodec, codec) < 0) return; 

    bufSize = FF_MIN_BUFFER_SIZE * 10; 
    buf = (uint8_t *)malloc(bufSize); 
    if (buf == NULL) return; 

    frameBytes = audioCodec->frame_size * audioCodec->channels * 2; 
    while (audioSize >= frameBytes) 
    { 
     int packetSize; 

     packetSize = avcodec_encode_audio(audioCodec, buf, bufSize, (short *)audioData); 
     printf("encoder returned %d bytes of data\n", packetSize); 
     audioData += frameBytes; 
     audioSize -= frameBytes; 
    } 
} 

int main() 
{ 
    FILE *stream = fopen("audio.pcm", "rb"); 
    size_t size; 
    uint8_t *buf; 

    if (stream == NULL) 
    { 
     printf("Unable to open file\n"); 
     return 1; 
    } 

    fseek(stream, 0, SEEK_END); 
    size = ftell(stream); 
    fseek(stream, 0, SEEK_SET); 
    buf = (uint8_t *)malloc(size); 
    fread(buf, sizeof(uint8_t), size, stream); 
    fclose(stream); 

    EncodeTest(32000, 2, 448000, buf, size); 
} 
+0

Bạn có thể chia sẻ toàn bộ dự án với tôi không? Tôi đang làm việc trên libav để mã hóa video/âm thanh quá. – suitianshi

Trả lời

4

vấn đề này dường như biến mất nếu tốc độ bit thấp hơn 386000. Không chắc tại sao điều này là, như tôi có thể mã hóa ở bitrate cao hơn so với sử dụng FAAC trực tiếp. Nhưng 128000 là đủ tốt cho mục đích của tôi, vì vậy tôi có thể tiến lên phía trước.

0

Tôi đang cố gắng nén ở định dạng aac cũng có một số vấn đề khác trong mã hóa. Có một số tính năng trong bản sửa đổi cuối cùng của ffmpeg (2.8.0). Đầu tiên, bạn có kiểm tra xem định dạng mẫu có được hỗ trợ không? Trong phiên bản của tôi, định dạng được hỗ trợ duy nhất là AV_SAMPLE_FMT_FLTP. kiểm tra định dạng là trong ví dụ:

/* kiểm tra xem một định dạng mẫu cho trước được hỗ trợ bởi bộ mã hóa */int check_sample_fmt (AVCodec * codec, enum AVSampleFormat sample_fmt) { const enum AVSampleFormat * p = codec-> sample_fmts ;

while (*p != AV_SAMPLE_FMT_NONE) { 
    if (*p == sample_fmt) 
     return 1; 
    p++; 
} 
return 0; 

}

Nếu bạn quan sát các định dạng được hỗ trợ, chỉ AV_SAMPLE_FMT_FLTP được hỗ trợ bởi bộ giải mã AAC. Bạn nên sử dụng swresample (như gợi ý) để chuyển đổi trong định dạng float planare, hoặc bạn có thể làm điều đó bằng tay. Bạn nên sử dụng avcodec_open2 với các tùy chọn sperimental nghiêm ngặt để mở codec. liên quan

Các vấn đề liên quan