i have been trying to decode an MP3 file to pcm, using ffmpeg API, but i keep getting an error
[mp3 @ 0x8553020]Header missing
this is the code i use :
Use avformat for reading instead of fread(). For example, it can be customized (e.g. for buffering), it can detect and check formats automatically on opening and also has separated probe functions and other format-related stuff. And it works properly with headers. I came to following usage (warning, code can contain errors)
struct FormatCtx {
inline FormatCtx(const char* filename)
: ctx_(avformat_alloc_context()) {
av_init_packet(&p);
if (avformat_open_input(&ctx_, filename, 0, 0) < 0)
abort();
if (avformat_find_stream_info(ctx_, 0) < 0)
abort();
}
inline ~FormatCtx() {
av_free_packet(&p);
}
inline bool read() {
return av_read_frame(ctx_, &p) >= 0;
}
AVFormatContext* ctx_;
AVPacket p;
} formatCtx_;
AVCodec* findCodec(const char* filename) {
AVCodec* codec = formatCtx_.ctx_->audio_codec;
if (codec)
return codec;
codec = avcodec_find_decoder(formatCtx_.ctx_->audio_codec_id);
if (codec)
return codec;
AVOutputFormat* fmt = av_guess_format(0, //const char *short_name,
filename, 0); // const char *mime_type);;
codec = fmt ? avcodec_find_decoder(fmt->audio_codec) : 0;
if (codec)
return codec;
return 0;
}
//*** initialize all stuff ***
AVCodec* codec = findCodec(filename);
if (!codec)
exit(1);
AVCodecContext* c; // class member for me, needed for following reading
int stream_index_; // class member for me, needed for extra stuff
for (size_t i = 0; i < formatCtx_.ctx_->nb_streams; ++i) {
AVCodecContext* tc = formatCtx_.ctx_->streams[i]->codec;
if (tc->codec_type == AVMEDIA_TYPE_AUDIO) {
c = tc;
stream_index_ = i;
break;
}
}
// for example, here we're know track length
l->onDurationDetected(double(formatCtx_.ctx_->streams[stream_index_]->duration)
* av_q2d(formatCtx_.ctx_->streams[stream_index_]->time_base));
if (avcodec_open2(c, codec, &d.d_) < 0)
exit(1);
c->channels = 2;
c->sample_rate = 48000;
c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
c->channel_layout = av_get_default_channel_layout(2);
After that you should basically prepare decoded_frame
from TC's example and pass packet used for reading to avcodec_decode_audio4
(instead of avpkt
).
I think i found my answer, the avpkt.data must have a header in front, without any garbage or previous frame bytes, or may be initial mp3 file data (name, gender, year ... etc).
so a little parser must be wrote, this is a useful link for mp3 headers (just search for the correct bytes in within the file, and increase avpkt.data pointer to match):
http://www.mp3-tech.org/programmer/frame_header.html