我一直试图使用ffmpeg API将MP3文件解码为pcm,但我一直收到错误
[mp3 @ 0x8553020]标题遗失
这是我使用的代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_AV_CONFIG_H
#undef HAVE_AV_CONFIG_H
#endif
#include "libavcodec/avcodec.h"
#include "libavutil/mathematics.h"
#define INBUF_SIZE 4096
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096
static void audio_decode_example(const char *outfilename, const char *filename)
{
AVCodec *codec;
AVCodecContext *c= NULL;
int out_size, len;
FILE *f, *outfile;
uint8_t *outbuf;
uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
AVPacket avpkt;
av_init_packet(&avpkt);
printf("Audio decoding\n");
/* find the mpeg audio decoder */
codec = avcodec_find_decoder(CODEC_ID_MP3ON4);
if (!codec) {
fprintf(stderr, "codec not found\n");
exit(1);
}
c= avcodec_alloc_context();
/* open it */
if (avcodec_open(c, codec) < 0) {
fprintf(stderr, "could not open codec\n");
exit(1);
}
outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "could not open %s\n", filename);
exit(1);
}
outfile = fopen(outfilename, "wb");
if (!outfile) {
av_free(c);
exit(1);
}
/* decode until eof */
avpkt.data = inbuf;
avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
while (avpkt.size > 0) {
out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
len = avcodec_decode_audio3(c, (short *)outbuf, &out_size, &avpkt);
if (len < 0) {
fprintf(stderr, "Error while decoding\n");
exit(1);
}
if (out_size > 0) {
/* if a frame has been decoded, output it */
fwrite(outbuf, 1, out_size, outfile);
}
avpkt.size -= len;
avpkt.data += len;
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);
free(outbuf);
avcodec_close(c);
av_free(c);
}
int main(int argc, char **argv)
{
const char *filename;
/* must be called before using avcodec lib */
avcodec_init();
/* register all the codecs */
avcodec_register_all();
audio_decode_example("test.wav", argv[1]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我使用相同的代码直接播放声音时,如下所示:
if (out_size > 0) {
/* if a frame has been decoded, output it *
play_sound(outbuf, out_size);
}
Run Code Online (Sandbox Code Playgroud)
我对一些文件没有任何问题,其他mp3文件只是在没有启动的情况下给出错误...有什么想法吗?
PS:此代码来自libavcodec/api-example.c,根据需要进行修改
我想我找到了答案,avpkt.data 前面必须有一个标头,没有任何垃圾或先前的帧字节,或者可能是初始 mp3 文件数据(名称、性别、年份...等)。
所以必须编写一个小解析器,这是 mp3 标头的有用链接(只需在文件中搜索正确的字节,并增加 avpkt.data 指针以匹配):
http://www.mp3-tech.org/programmer/frame_header.html
| 归档时间: |
|
| 查看次数: |
14689 次 |
| 最近记录: |