2012-06-27 39 views
9

Tôi đã tích hợp ffmpeg lib trong dự án của mình và tôi cũng có thể lấy thông tin về tệp phương tiện. Nhưng bây giờ tôi phải chơi các tập tin mp3 bằng cách sử dụng lớp AudioTrack trong android bằng cách sử dụng ffmpeg lib.Android: Phát các tệp MP3 bằng AudioTrack bằng ffmpeg

Đối với điều này tôi phải vượt qua bộ đệm byte để AudioTrack nhưng tôi không biết làm thế nào để có được bộ đệm byte từ ffmpeg và sử dụng nó với AudioTrack. Tôi cũng muốn phát tệp ngay lập tức mà không bị chậm trễ.

Đây là mã theo dõi âm thanh của tôi trong java:

AudioTrack track; 
bufferSize = AudioTrack.getMinBufferSize(44100,AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT) 
track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, mode); 

//Play audio clip 
track.play(); 

while(stream_is_over){ 
//Copy the decoded raw buffer from native code to "buffer" ..... 
............ 
track.write(buffer, 0, readBytes); 
} 

bất cứ ai có thể vui lòng cho tôi đoạn code làm việc để chơi các file mp3 với track âm thanh. Tôi đã tìm kiếm rất nhiều nhưng không tìm thấy câu trả lời đúng.

+0

Tại sao bạn không sử dụng được xây dựng trong api để chơi các file mp3? –

+0

xem phần giải thích này http://stackoverflow.com/questions/6228008/decoding-audio-via-android-using-ffmpeg –

+1

@ChrisStratton: bởi vì tôi cũng phải thay đổi tốc độ phát lại mà không thay đổi độ cao của âm thanh. Và không có hỗ trợ cho điều này trong xây dựng trong apis, –

Trả lời

3

tôi quản lý này bằng cách tạo bộ đệm của các tệp âm thanh và sau đó phát nó với lớp AudioTrack khi đang di chuyển. Bây giờ tôi đang cố gắng tạm dừng/dừng tệp âm thanh khiến dừng hoặc tạm dừng AudioTrack không hoạt động.

Đây là mã của tôi để vượt qua bộ đệm byte đến lớp java của tôi:

#include <assert.h> 
#include <jni.h> 
#include <string.h> 
#include <android/log.h> 

#include "libavcodec/avcodec.h" 
#include "libavformat/avformat.h" 

#define LOG_TAG "mylib" 
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 

#define AUDIO_INBUF_SIZE 20480 
#define AUDIO_REFILL_THRESH 4096 

void Java_ru_dzakhov_ffmpeg_test_MainActivity_createEngine(JNIEnv* env, 
     jclass clazz) { 
    avcodec_init(); 

    av_register_all(); 

} 

jstring Java_ru_dzakhov_ffmpeg_test_MainActivity_loadFile(JNIEnv* env, 
     jobject obj, jstring file, jbyteArray array) { 
    { 
     jboolean isfilenameCopy; 
     const char * filename = (*env)->GetStringUTFChars(env, file, 
       &isfilenameCopy); 
     int audioStreamIndex; 
     AVCodec *codec; 
     AVCodecContext *c = NULL; 
     AVFormatContext * pFormatCtx; 
     AVCodecContext * aCodecCtx; 
     int out_size, len, audioStream = -1, i, err; 
     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 

     LOGE("source file name is %s", filename); 

     avcodec_init(); 

     av_register_all(); 

     LOGE("Stage 1"); 
     /* get format somthing of source file to AVFormatContext */ 
     int lError; 
     if ((lError = av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL)) 
       != 0) { 
      LOGE("Error open source file: %d", lError); 
      exit(1); 
     } 
     if ((lError = av_find_stream_info(pFormatCtx)) < 0) { 
      LOGE("Error find stream information: %d", lError); 
      exit(1); 
     } 
     LOGE("Stage 1.5"); 
     LOGE("audio format: %s", pFormatCtx->iformat->name); 
     LOGE("audio bitrate: %d", pFormatCtx->bit_rate); 

     audioStreamIndex = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO, 
       -1, -1, &codec, 0); 

     LOGE("audio codec: %s", codec->name); 

     /* get codec somthing of audio stream to AVCodecContext */ 
     aCodecCtx = pFormatCtx->streams[audioStreamIndex]->codec; 
     if (avcodec_open(aCodecCtx, codec) < 0) { 
      LOGE("cannot open the audio codec!"); 
      exit(1); 
     } 

     printf("Audio decoding\n"); 
     LOGE("Stage 1.7"); 
     LOGE("S"); 
     codec = avcodec_find_decoder(aCodecCtx->codec_id); 
     LOGE("Stage 1.8"); 
     if (!codec) { 
      LOGE("codec not found\n"); 
      exit(1); 
     } 
     LOGE("Stage 2"); 
//    c= avcodec_alloc_context(); 
     LOGE("Stage 3"); 
     /* open it */ 
     if (avcodec_open(aCodecCtx, codec) < 0) { 
      LOGE("could upper"); 
      fprintf(stderr, "could not open codec\n"); 
      LOGE("could not open codec"); 

     } 
     LOGE("Stage 4"); 
     outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); 

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

     /* decode until eof */ 
     avpkt.data = inbuf; 
     avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f); 
     LOGE("Stage 5"); 

     while (avpkt.size > 0) { 
//     LOGE("Stage 6"); 
      out_size = (AVCODEC_MAX_AUDIO_FRAME_SIZE/3) * 2; 
      len = avcodec_decode_audio3(aCodecCtx, (int16_t *) outbuf, 
        &out_size, &avpkt); 
      LOGE("data_size %d len %d", out_size, len); 
      if (len < 0) { 
       fprintf(stderr, "Error while decoding\n"); 
       LOGE("DECODING ERROR"); 
       LOGE("DECODING ERROR %d", len); 
       exit(1); 
      } 
//     LOGE("Stage 7"); 
      if (out_size > 0) { 
       /* if a frame has been decoded, output it */ 
//      LOGE("Stage 8"); 
       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); 
//      LOGE("DECODING ERROR5"); 
      } 
      LOGE("Stage 9"); 
      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; 
      } 
     } 
     LOGE("Stage 12"); 
     fclose(f); 
     free(outbuf); 

     avcodec_close(c); 
     av_free(c); 

    } 
} 
0

tôi không có đầu mối về lập trình trong android, nhưng google vừa giới thiệu một mức độ thấp truyền thông api mới tại I/O 2012

Dưới đây là các liên kết đến các yt video: http://www.youtube.com/watch?v=YmCqJlzIUXs

Các vấn đề liên quan