mp3 decoding using ffmpeg API (Header missing)

前端 未结 2 1365
深忆病人
深忆病人 2020-12-09 22:34

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 :

相关标签:
2条回答
  • 2020-12-09 22:53

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

    0 讨论(0)
  • 2020-12-09 23:03

    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

    0 讨论(0)
提交回复
热议问题