Ari
Ari

Reputation: 1316

how to play mp3 using ffmpeg

I'm trying to play audio mp3 file using ffmpeg in android but I'm facing a problem in the below mentioned code

how to play mp3 using ffmpeg

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

i am getting the len = - 1 in

len = avcodec_decode_audio3(c, (short *)outbuf, &out_size, &avpkt);

what am i doing wrong??

please help

Upvotes: 2

Views: 4690

Answers (2)

user2361120
user2361120

Reputation: 43

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

        }

try this code i done couple of change now its working fine

Upvotes: 4

pogorskiy
pogorskiy

Reputation: 4815

To correctly read the packet from MP3 file, you have to use the AVFormatContext structure.

The code should look something like this (This code without the correct completion, error checking, etc.)

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

Upvotes: 1

Related Questions