gpt4 book ai didi

c - 在 RTP 数据包中使用 FFmpeg 解码 AAC

转载 作者:太空宇宙 更新时间:2023-11-04 04:34:49 27 4
gpt4 key购买 nike

我正在尝试使用 FFmpeg 解码 RTP 数据包中的 AAC。根据rfc document RTP 负载是 audioMuxElement 直接映射的。我尝试删除 RTP header 并将剩余字节读取到 AVPacket 结构,但 avcodec_decode_audio4() 返回错误 -1094995529。这是代码:

#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);
}

我从this question中学到了我应该使用 av_read_frame() 而不是 fread 但我只有 RTP 负载而不是整个文件。直接将 rtp payload 映射到 AVPacket struct 是否正确?如果不是,那么我应该如何解码 RTP 负载?

最佳答案

我最终使用编解码器 AV_CODEC_ID_AAC 而不是 AV_CODEC_ID_AAC_LATM。在深入研究 rfc 和 ISO 文档后,我发现数据包是 LATM 格式的,但 AAC 解码器的输入数据包必须在 ADTS 中格式化,因此必须在此处编写一些解析器。我无法发布代码,但编写代码并不难。

关于c - 在 RTP 数据包中使用 FFmpeg 解码 AAC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31936622/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com