在RTP包中用FFmpeg解码AAC
我正在尝试用FFmpeg解码RTP包中的AAC。根据RTP,有效载荷直接映射为音频像素。我尝试删除RTP头并将剩余字节读取到AVPacket struct,但avcodec_decode_audio4()返回错误-1094995529。代码如下:在RTP包中用FFmpeg解码AAC,c,ffmpeg,rtp,aac,C,Ffmpeg,Rtp,Aac,我正在尝试用FFmpeg解码RTP包中的AAC。根据RTP,有效载荷直接映射为音频像素。我尝试删除RTP头并将剩余字节读取到AVPacket struct,但avcodec_decode_audio4()返回错误-1094995529。代码如下: #include "stdafx.h" #include "stdio.h" #include "conio.h" extern "C" { #ifndef __STDC_CONSTANT_MACROS #define __STDC_CONSTA
#include "stdafx.h"
#include "stdio.h"
#include "conio.h"
extern "C"
{
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif
#include <libavcodec\avcodec.h>
#include <libavformat\avformat.h>
}
// compatibility with newer API
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)
#define av_frame_alloc avcodec_alloc_frame
#define av_frame_free avcodec_free_frame
#endif
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096
#define SAMPLE_RATE 44100
#define CHANNEL_NUM 2
static void decode_packet();
int main(int argc, char *argv[]) {
decode_packet();
getch();
return 0;
}
static void decode_packet()
{
const char *filename = "D:\\NoRTP_AACPacket.dat";
const char *outfilename = "D:\\test2.pcm";
AVCodec *codec;
AVFormatContext *pFormatCtx = NULL;
AVCodecContext * pCodecCtx= NULL;
int len;
FILE *f, *outfile;
uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
AVPacket avpkt;
AVFrame *decoded_frame = NULL;
av_register_all();
av_init_packet(&avpkt);
printf("Decode audio file %s to %s\n", filename, outfilename);
// Find the decoder for the audio stream
codec=avcodec_find_decoder(AV_CODEC_ID_AAC_LATM);
if(codec==NULL) {
fprintf(stderr, "Codec not found\n");
return; // Codec not found
}
pCodecCtx = avcodec_alloc_context3(codec);
if (!pCodecCtx) {
fprintf(stderr, "Could not allocate audio codec context\n");
return;
}
pCodecCtx->sample_rate = SAMPLE_RATE;
pCodecCtx->channels = CHANNEL_NUM;
/* open it */
if (avcodec_open2(pCodecCtx, codec, NULL) < 0) {
fprintf(stderr, "Could not open codec\n");
return;
}
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "Could not open %s\n", filename);
return;
}
outfile = fopen(outfilename, "wb");
if (!outfile) {
av_free(pCodecCtx);
return;
}
avpkt.data = inbuf;
avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
// supposed to do this but don't have AVFormatContext
// int frReadStt = av_read_frame(pFormatCtx, &avpkt);
/* decode until eof */
while (avpkt.size > 0) {
int i, ch;
int got_frame = 0;
if (!decoded_frame) {
if (!(decoded_frame = av_frame_alloc())) {
fprintf(stderr, "Could not allocate audio frame\n");
return;
}
}
len = avcodec_decode_audio4(pCodecCtx, decoded_frame, &got_frame, &avpkt);
if (len < 0) {
fprintf(stderr, "Error while decoding. len = %d \n",len);
return;
}
if (got_frame) {
/* if a frame has been decoded, output it */
int data_size = av_get_bytes_per_sample(pCodecCtx->sample_fmt);
if (data_size < 0) {
/* This should not occur, checking just for paranoia */
fprintf(stderr, "Failed to calculate data size\n");
return;
}
for (i=0; i < decoded_frame->nb_samples; i++)
for (ch=0; ch < pCodecCtx->channels; ch++)
fwrite(decoded_frame->data[ch] + data_size*i, 1, data_size, outfile);
}
avpkt.size -= len;
avpkt.data += len;
avpkt.dts =
avpkt.pts = AV_NOPTS_VALUE;
// frReadStt = av_read_frame(pFormatCtx, &avpkt);
if (avpkt.size < AUDIO_REFILL_THRESH) {
/* Refill the input buffer, to avoid trying to decode
* incomplete frames. Instead of this, one could also use
* a parser, or use a proper container format through
* libavformat. */
memmove(inbuf, avpkt.data, avpkt.size);
avpkt.data = inbuf;
len = fread(avpkt.data + avpkt.size, 1,
AUDIO_INBUF_SIZE - avpkt.size, f);
if (len > 0)
avpkt.size += len;
}
}
fclose(outfile);
fclose(f);
avcodec_close(pCodecCtx);
av_free(pCodecCtx);
av_frame_free(&decoded_frame);
printf("Finish decode audio file %s to %s\n", filename, outfilename);
}
#包括“stdafx.h”
#包括“stdio.h”
#包括“conio.h”
外部“C”
{
#ifndef uu STDC u常量u宏
#定义\uu STDC\u常量\u宏
#恩迪夫
#包括
#包括
}
//与较新API的兼容性
#如果LIBAVCODEC_VERSION_INT采样率=采样率;
pCodecCtx->channels=CHANNEL\u NUM;
/*打开它*/
if(avcodec_open2(pCodecCtx,codec,NULL)<0){
fprintf(stderr,“无法打开编解码器”\n);
返回;
}
f=fopen(文件名,“rb”);
如果(!f){
fprintf(stderr,“无法打开%s\n”,文件名);
返回;
}
outfile=fopen(outfilename,“wb”);
如果(!outfile){
无av_(PCODECTX);
返回;
}
avpkt.data=inbuf;
avpkt.size=fread(inbuf,1,AUDIO_inbuf_size,f);
//应该这样做,但没有上下文
//int frReadStt=av_读取_帧(pFormatCtx和avpkt);
/*解码到eof*/
而(avpkt.size>0){
int i,ch;
int got_frame=0;
如果(!解码帧){
如果(!(解码帧=av帧匹配()){
fprintf(stderr,“无法分配音频帧”\n);
返回;
}
}
len=avcodec\U decode\U audio4(PCODECTX、解码的\U帧、获取的\U帧和avpkt);
if(len<0){
fprintf(stderr,“解码时出错。len=%d\n”,len);
返回;
}
如果(得到了框架){
/*如果一帧已解码,则将其输出*/
int data_size=av_get_bytes_/样本(pCodecCtx->sample_fmt);
如果(数据大小<0){
/*这不应该发生,只检查偏执狂*/
fprintf(stderr,“无法计算数据大小\n”);
返回;
}
对于(i=0;inb_samples;i++)
对于(ch=0;chchannels;ch++)
fwrite(解码帧->数据[ch]+数据大小*i,1,数据大小,输出文件);
}
avpkt.size-=len;
avpkt.data+=len;
avpkt.dts=
avpkt.pts=AV_NOPTS_值;
//frReadStt=av_读取_帧(pFormatCtx和avpkt);
if(avpkt.size<音频\重新填充\阈值){
/*重新填充输入缓冲区,以避免尝试解码
*不完整的框架。除此之外,还可以使用
*解析器,或通过
*libav格式*/
memmove(inbuf,avpkt.data,avpkt.size);
avpkt.data=inbuf;
len=fread(avpkt.data+avpkt.size,1,
音频尺寸-avpkt.SIZE,f);
如果(len>0)
avpkt.size+=len;
}
}
fclose(输出文件);
fclose(f);
avcodec_关闭(PCODECTX);
无av_(PCODECTX);
无av_帧(&解码_帧);
printf(“完成将音频文件%s解码为%s\n”,文件名,输出文件名);
}
我从中学到我应该使用av_read_frame()而不是fread,但我只有RTP有效负载,而不是整个文件。直接将rtp有效负载映射到AVPacket结构是否正确?如果没有,那么我应该如何解码RTP有效负载 我最终使用了编解码器AV_codec_ID_AAC而不是AV_codec_ID_AAC_LATM。在深入研究rfc和ISO文档后,我发现数据包是LATM格式的,但AAC解码器的输入数据包必须在ADTS中格式化,因此这里必须编写一些解析器。我不能发布代码,但写一个也不难 我最终使用了编解码器AV_codec_ID_AAC而不是AV_codec_ID_AAC_LATM。在深入研究rfc和ISO文档后,我发现数据包是LATM格式的,但AAC解码器的输入数据包必须在ADTS中格式化,因此这里必须编写一些解析器。我不能发布代码,但写一个也不难