Codificare l'audio in AAC con libavcodec
-
18-09-2019 - |
Domanda
sto usando libavcodec (ultima git come del 3/3/10) per codificare PCM prima al aac (Supporto libfaac abilitato). Faccio questo chiamando avcodec_encode_audio ripetutamente con codec_context-> campioni frame_size ogni volta. I primi quattro chiamate restituiscono correttamente, ma il quinto invito non ritorna mai. Quando uso gdb per rompere, lo stack è danneggiato.
Se uso audacia di esportare i dati PCM in un file .wav, quindi posso usare Della riga di comando ffmpeg per convertire in AAC senza problemi, quindi sono sicuro che è qualcosa che sto facendo male.
Ho scritto un piccolo programma di test che duplica il mio problema. E 'legge il dati di test da un file, che è disponibile qui: http://birdie.protoven.com/audio.pcm (~ 2 secondi di segno a 16 bit LE pcm)
Posso far funzionare il tutto se uso direttamente FAAC, ma il codice sarebbe un po 'più pulito se solo potessi usare libavcodec, come sto anche la codifica video, e la scrittura sia per un mp4.
informazioni sulla versione di 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
C'è qualcosa che io non sono l'impostazione, o impostare in modo non corretto nel mio codec contesto, forse? Ogni aiuto è molto apprezzato!
Ecco il mio codice di prova:
#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);
}
Soluzione
Il problema sembra andare via se il bitrate è inferiore a 386000. Non capisco perché questo è, come posso codificare a bitrate superiore a quella con FAAC direttamente. Ma 128000 è abbastanza buono per i miei scopi, quindi sono in grado di andare avanti.
Altri suggerimenti
Sto tentando di comprimere in formato AAC anche un presentano alcuni altri problemi di codifica. Ci sono alcune caratteristiche in ultima revisione di ffmpeg (2.8.0). In un primo momento, avete controllato se il formato del campione è supportato? Nella mia versione l'unico formato supportato è AV_SAMPLE_FMT_FLTP. controllo Format è nell'esempio:
/ * verificare che un determinato formato di campionamento è supportato dal codificatore * / 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;
}
Se si osservano i formati supportati, solo AV_SAMPLE_FMT_FLTP è supportato da codec AAC. Si dovrebbe usare swresample (come suggerito) per convertire in formato float planare, oppure è possibile farlo a mano. Si dovrebbe usare avcodec_open2 con opzioni rigorosa sperimentale al fine di aprire codec. saluti