Android 如何使用ffmpeg播放mp3

Android 如何使用ffmpeg播放mp3,android,audio,android-ndk,ffmpeg,Android,Audio,Android Ndk,Ffmpeg,我正在尝试在android中使用ffmpeg播放音频mp3文件 但是我在下面提到的代码中遇到了一个问题 如何使用ffmpeg播放mp3 void JNICALL Java_com_music_MainActivity_loadFile(JNIEnv* env, jobject obj,jstring file,jbyteArray array) { jboolean isfilenameCopy; const char * filename

我正在尝试在android中使用ffmpeg播放音频mp3文件 但是我在下面提到的代码中遇到了一个问题

如何使用ffmpeg播放mp3

 void JNICALL  Java_com_music_MainActivity_loadFile(JNIEnv* env, jobject obj,jstring file,jbyteArray array)
{
    jboolean            isfilenameCopy;
    const char *        filename = (*env)->GetStringUTFChars(env, file, &isfilenameCopy);
    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;
    jclass              cls = (*env)->GetObjectClass(env, obj);
    jmethodID           play = (*env)->GetMethodID(env, cls, "playSound", "([BI)V");//At the begining of your main function

    av_init_packet(&avpkt);

    printf("Audio decoding\n");


    __android_log_print(ANDROID_LOG_INFO, DEBUG_TAG, "inside load file");
    /* find the mpeg audio decoder */
    codec = avcodec_find_decoder(CODEC_ID_MP3);
    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);
    }

    __android_log_print(ANDROID_LOG_INFO, DEBUG_TAG, "open avcode");
    outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
   __android_log_print(ANDROID_LOG_INFO, DEBUG_TAG, "open %s",outbuf);

    f = fopen(filename, "rb");
    if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }

    /* decode until eof */
    avpkt.data = inbuf;
    avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
    __android_log_print(ANDROID_LOG_INFO, DEBUG_TAG, "data =%s and size %d",avpkt.data,avpkt.size);
    while (avpkt.size > 0) {
        out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
        len = avcodec_decode_audio3(c, (short *)outbuf, &out_size, &avpkt);
        __android_log_print(ANDROID_LOG_INFO, DEBUG_TAG, "length =%d",len);
        if (len < 0) {
            fprintf(stderr, "Error while decoding\n");
            __android_log_print(ANDROID_LOG_INFO, DEBUG_TAG, " failed length =%d",errno);

            exit(1);
        }
        if (out_size > 0) {
            /* if a frame has been decoded, output it */
            jbyte *bytes = (*env)->GetByteArrayElements(env, array, NULL);
            memcpy(bytes, outbuf, out_size); //
            (*env)->ReleaseByteArrayElements(env, array, bytes, 0);
            (*env)->CallVoidMethod(env, obj, play, array, out_size);

        }
        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(f);
    free(outbuf);

    avcodec_close(c);
    av_free(c);
}
我做错了什么


请帮助

要正确读取MP3文件中的数据包,必须使用
AVFormatContext
结构

代码应该是这样的(此代码没有正确的完成、错误检查等)

AVFormatContext*fCtx=NULL;
if(avformat\u open\u输入(&fCtx,filename,NULL,NULL)<0)
出口(1);
avformat_find_stream_info(fCtx,NULL);
AVCodec*codec=nullptr;
int strm=av_find_best_stream(fCtx,AVMEDIA_TYPE_AUDIO,-1,-1和编解码器,0);
AVCodecContext codecCtx=ctx->streams[strm]->codec;
if(avcodec_open2(codecCtx、codec、nullptr)<0)
出口(1);
对于(;;)
{
AVPacket-pkt;
err=av读取帧(fCtx和pkt);
如果(平均误差=err)
打破
如果(pkt.stream_index!=strm)
继续;
AVFrame框架;
int-gotFrame=0;
int len=avcodec\u decode\u audio4(codecCtx、&frame、&gotFrame、&pkt)
//或者在先前版本的ffmpeg中使用avcodec_decode_audio3,正如它写给您的一样。
///检查结果并使用帧(如果是avcodec\U decode\U audio3,则使用缓冲区)
}
void JNICALL Java_com_music_main activity_loadFile(JNIEnv*env、jobject obj、jstring文件、jbyteArray数组)
{
jboolean-isCopy;
int i;
INTERR;
文件*f,*outfile;
int audioStream=-1;
国际关系;
int解码=0;
画出你的尺寸;
AVFrame*frame=av_frame_alloc();
int-got_框架;
uint8\u t inbuf[音频inbuf\u大小+FF\u输入缓冲区\u填充大小];
jclass cls=(*env)->GetObjectClass(env,obj);
jmethodideplay=(*env)->GetMethodID(env,cls,“playSound”,“([BI)V”);//在主函数的开头
const char*szfile=(*env)->GetStringUTFChars(env、file和isCopy);
LOGI(“加载文件中”);
如果((ret=avformat\u open\u输入(&fmt\u ctx,szfile,NULL,NULL))<0)
{
LOGE(“无法打开输入文件\n”);
}
日志(“文件加载%s\n”,szfile);
if((ret=avformat\u find\u stream\u info(fmt\u ctx,NULL))<0)
{
LOGE(“找不到流信息\n”);
}
/*选择音频流*/
ret=av查找最佳流(fmt ctx,AVMEDIA类型音频,-1,-1,&dec,0);
如果(ret<0)
{
LOGE(“在输入文件中找不到音频流\n”);
}
//时基=(int64_t(aCodecCtx->time_base.num)*AV_time_base)/int64_t(aCodecCtx->time_base.den);
音频流索引=ret;
dec_ctx=fmt_ctx->流[音频流索引]->编解码器;
av_opt_set_int(12月ctx,“参考计数帧”,1,0);
if((ret=avcodec_open2(dec_ctx,dec,NULL))<0)
{
LOGE(“无法打开音频解码器\n”);
}
dec_ctx->sample_fmt=AV_sample_fmt_S16
dec_ctx->codec_id=AV_codec_id_AAC;
f=fopen(szfile,“rb”);
如果(!f)
{
LOGE(“无法打开”);
出口(1);
}
//LOGE(“帧%d的时间”,aCodecCtx->time\u base.num);
//av_seek_frame();
//时基=(aCodecCtx->time\u base.num*AV\u time\u base)/(aCodecCtx->time\u base.den);
//LOGE(“帧%d的时间”,aCodecCtx->time\u base.den);
LOGE(“帧%d的时间”,时基);
packet.data=inbuf;
packet.size=fread(inbuf,1,音频大小,f);
LOGE(“第5阶段”);
而(1)
{
如果((ret=av_读取_帧(fmt_ctx和数据包))<0)
打破
if(packet.stream\u index==音频\u流\u索引)
{
avcodec_获取_帧_默认值(帧);
got_frame=0;
ret=avcodec\U decode\U audio4(数字视频编码、帧、帧和数据包);
LOGE(“len=%d”,ret);
如果(ret<0)
{
LOGE(“音频解码错误”);
继续;
}
如果(得到了框架)
{
LOGE(“开始帧解码\n”);
int data\u size=av\u samples\u get\u buffer\u size(NULL,dec\u ctx->channels,frame->nb\u samples,dec\u ctx->sample\u fmt,1);
LOGE(“帧解码后\n”);
jbyte*bytes=(*env)->GetByteArrayElements(env,array,NULL);
memcpy(字节,帧->数据[0],数据大小)//
(*env)->ReleaseByteArrayElements(env,数组,字节,0);
(*env)->CallVoidMethod(env、obj、play、数组、数据大小);
}
packet.size-=ret;
packet.data+=ret;
packet.pts=AV_NOPTS_值;
if(数据包大小<音频\u重新填充\u阈值)
{
memmove(inbuf,packet.data,packet.size);
packet.data=inbuf;
ret=fread(packet.data+packet.size,1,AUDIO\u INBUF\u size-packet.size,f);
如果(ret>0)
packet.size+=ret;
}
}
}
av_免费_数据包(&数据包);
}
试试这段代码,我现在做了一些修改,效果很好

len = avcodec_decode_audio3(c, (short *)outbuf, &out_size, &avpkt);
AVFormatContext * fCtx = NULL;
if(avformat_open_input(&fCtx, filename, NULL, NULL) < 0)
    exit(1);

avformat_find_stream_info(fCtx, NULL);
AVCodec * codec = nullptr;
int strm = av_find_best_stream(fCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
AVCodecContext codecCtx = ctx->streams[strm]->codec;

if (avcodec_open2(codecCtx, codec, nullptr) < 0) 
    exit(1);

for (;;)
{
   AVPacket pkt;
   err = av_read_frame(fCtx , &pkt);
   if (AVERROR_EOF == err)
       break;

   if (pkt.stream_index != strm)
       continue;   

   AVFrame frame;
   int gotFrame = 0;
   int len = avcodec_decode_audio4(codecCtx, &frame, &gotFrame, &pkt)
   // or avcodec_decode_audio3 in previous version of ffmpeg, as it is written you.
   /// check result and use frame (or buffer in case of avcodec_decode_audio3)
}
void JNICALL  Java_com_music_MainActivity_loadFile(JNIEnv* env, jobject obj,jstring       file,jbyteArray array)
{
    jboolean            isCopy;
    int                 i;
    int                  err;
    FILE *f, *outfile;
    int                 audioStream=-1;
    int                 res;
    int                 decoded = 0;
    int                 out_size;

    AVFrame *frame = av_frame_alloc();
              int got_frame;
    uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
    jclass              cls = (*env)->GetObjectClass(env, obj);
    jmethodID           play = (*env)->GetMethodID(env, cls, "playSound", "([BI)V");//At the begining of your main function
    const char *        szfile = (*env)->GetStringUTFChars(env, file, &isCopy);
    LOGI("in load file");

        if ((ret = avformat_open_input(&fmt_ctx, szfile, NULL, NULL)) < 0)
        {
            LOGE("Cannot open input file\n");
        }

        LOGE("file load %s\n",szfile);

        if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0)
        {
            LOGE("Cannot find stream information\n");
        }

        /* select the audio stream */
        ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0);
        if (ret < 0)
        {
            LOGE("Cannot find a audio stream in the input file\n");
        }



       // timeBase = (int64_t(aCodecCtx->time_base.num) * AV_TIME_BASE) / int64_t(aCodecCtx->time_base.den);

        audio_stream_index = ret;
        dec_ctx = fmt_ctx->streams[audio_stream_index]->codec;
        av_opt_set_int(dec_ctx, "refcounted_frames", 1, 0);

        if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0)
        {
            LOGE("Cannot open audio decoder\n");
        }


        dec_ctx->sample_fmt =AV_SAMPLE_FMT_S16
        dec_ctx->codec_id = AV_CODEC_ID_AAC;

        f = fopen(szfile, "rb");

       if (!f)
       {
           LOGE("could not open");
           exit(1);
       }

    //   LOGE("time of frame %d",aCodecCtx->time_base.num);

      // av_seek_frame();

      // timeBase =(aCodecCtx->time_base.num *AV_TIME_BASE)/(aCodecCtx->time_base.den);

     //  LOGE("time of frame %d",aCodecCtx->time_base.den);

       LOGE("time of frame %d",timeBase);
        packet.data = inbuf;
        packet.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
        LOGE("Stage 5");

        while (1)
        {
               if ((ret = av_read_frame(fmt_ctx, &packet)) < 0)
                   break;
               if (packet.stream_index == audio_stream_index)
               {
                       avcodec_get_frame_defaults(frame);
                       got_frame = 0;
                       ret = avcodec_decode_audio4(dec_ctx, frame, &got_frame, &packet);
                       LOGE("len=%d",ret);
                       if (ret < 0)
                       {
                           LOGE("Error decoding audio\n");
                           continue;
                       }

                       if (got_frame)
                       {
                            LOGE("begin frame decode\n");
                            int data_size = av_samples_get_buffer_size(NULL, dec_ctx->channels,frame->nb_samples,dec_ctx->sample_fmt, 1);
                            LOGE("after frame decode\n");

                            jbyte *bytes = (*env)->GetByteArrayElements(env, array, NULL);
                            memcpy(bytes, frame->data[0], data_size); //
                            (*env)->ReleaseByteArrayElements(env, array, bytes, 0);
                            (*env)->CallVoidMethod(env, obj, play, array, data_size);

                       }

                       packet.size -= ret;
                       packet.data += ret;
                       packet.pts = AV_NOPTS_VALUE;
                      if (packet.size < AUDIO_REFILL_THRESH)
                      {
                          memmove(inbuf, packet.data, packet.size);
                          packet.data = inbuf;
                          ret = fread(packet.data + packet.size, 1, AUDIO_INBUF_SIZE - packet.size, f);
                          if (ret > 0)
                              packet.size += ret;
                      }

                 }
          }
               av_free_packet(&packet);

        }