سؤال

أنا أستخدم libavcodec (أحدث git اعتبارا من 3/3/10) لتشفير PCM الخام إلى AAC (تمكين دعم LIBFAAC). أقوم بذلك عن طريق الاتصال AVCODEC_Encode_Audio مرارا وتكرارا مع Codec_Context-> Frame_Size العينات في كل مرة. تتم عودة الدعوات الأربعة الأولى بنجاح، لكن الدعوة الخامسة لا تعود أبدا. عندما أستخدم GDB لكسر، فإن المكدس تالف.

إذا كنت تستخدم الجرأة لتصدير بيانات PCM إلى ملف .wav، فيمكنني استخدام سطر الأوامر FFMPEG لتحويل إلى AAC دون أي مشاكل، لذلك أنا متأكد من أنه شيء أفعله خطأ.

لقد كتبت برنامج اختبار صغير يكرر مشكلتي. يقرأ بيانات الاختبار من ملف، وهو متاح هنا:http://birdie.protoven.com/Audio.pcm. (~ 2 ثانية من موقعة 16 بت لو PCM)

يمكنني أن أجعل كل شيء يعمل إذا كنت تستخدم FAAC مباشرة، ولكن الكود سيكون منظف قليلا إذا كان بإمكاني استخدام libavcodec، كما أنا أيضا ترميز الفيديو، والكتابة على حد سواء إلى MP4.

معلومات الإصدار ffmpeg:

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

هل هناك شيء ما لا أستخدمه، أو الإعداد بشكل غير صحيح في سياق الترميز الخاص بي، ربما؟ أي مساعدة يحظى بتقدير كبير!

هنا رمز الاختبار الخاص بي:

#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);
}
هل كانت مفيدة؟

المحلول

يبدو أن المشكلة تذهب بعيدا إذا كانت البت أقل من 386000. لست متأكدا من السبب في ذلك، حيث يمكنني أن زودت في البت أعلى من ذلك باستخدام FAAC مباشرة. لكن 128000 جيدة بما يكفي لأغراضي، لذلك أنا قادر على المضي قدما.

نصائح أخرى

أحاول الضغط بتنسيق AAC أيضا بعض المشكلات الأخرى في الترميز. هناك بعض الميزات في المراجعة الأخيرة من FFMPEG (2.8.0). في البداية، هل تحقق ما إذا كان تنسيق العينة مدعوم؟ في الإصدار الخاص بي، التنسيق الوحيد المدعوم هو AV_Sample_FMT_FLTP. فحص التنسيق هو على سبيل المثال:

.

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

}

إذا لاحظت تنسيقات مدعومة، يتم دعم AV_Sample_FMT_FLTP فقط بواسطة برنامج ترميز AAC. يجب عليك استخدام SWRESAMPLE (كما هو مقترح) لتحويل بتنسيق Floater، أو يمكنك القيام بذلك باليد. يجب عليك استخدام AVCODEC_OPEN2 مع خيارات متماثل صارمة من أجل فتح برنامج الترميز. مع تحياتي

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top