2012-03-01 20 views
6

(ヘッダーが欠落している)、しかし、私はエラーにmp3デコード使用のffmpegのAPI私はffmpegのAPIを使用して、PCMにMP3ファイルをデコードしようとしている

得続ける[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; 
} 

私は直接音を再生するために同じコードを使用する場合、次のように:

if (out_size > 0) { 
    /* if a frame has been decoded, output it * 
    play_sound(outbuf, out_size); 
} 

私はいくつかのファイルに全く問題はなく、他のmp3ファイルは起動しなくてもエラーが出ます...アイデアはありますか?

PS:このコードは、私は私は私の答えを見つけたと思う

答えて

2

を必要に応じて変更、libavcodecの/ API-はexample.cからで、avpkt.dataは、任意のごみまたは前のフレームバイトせずに、前にヘッダを持っている必要があります、または最初のmp3ファイルのデータ(名前、性別、年...など)かもしれません。

ので、少しパーサが、これはmp3ヘッダーの便利なリンク(単にファイル内に正しいバイトを検索し、一致するavpkt.dataポインタを増やす)で、書いている必要があります。

http://www.mp3-tech.org/programmer/frame_header.html

+4

このエラーの解決方法を教えてください。私はID3タグ付きのmp3ファイルがffmpegを使って再生されていないので、この段階にも没頭しています。 –

+1

@WINエラーの修正方法の詳細を教えてください。 – w2lame

1

fread()の代わりにavformatを読み込みます。例えば、(バッファリングのために)カスタマイズすることができ、開放時にフォーマットを自動的に検出しチェックすることができ、プローブ機能および他のフォーマット関連のものを分離することができる。そしてそれはヘッダーで適切に動作します。私は、使用(警告、コードがエラーを含むことができます)その後

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

あなたは基本的にTCの例からdecoded_frameを準備し、(代わりにavpktの)avcodec_decode_audio4に読み取るために使用パケットを渡す必要があり、以下に来ました。

関連する問題