How to decode audio via FFmpeg in Android
Use audiotrack class to do the work for you. You can do something like this.
JAVA side.
AudioTrack track;
int bufSize = 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, bufSize, AudioTrack.MODE_STREAM);
track.play();
while(true){
readBufferFromNative(); //update buffer from native code
....................
....................
}
On native Side : You need to read the frames and convert them into raw pcm format first and then start filling the audio buffer continuously. When the buffer is full, it will automatically play.
JNIEXPORT int JNICALL Java_com_ffmpeg_Main_jniMainEntry(JNIEnv* env, jobject obj, jstring input) {
const char * pszFileName = (*env)->GetStringUTFChars(env, input, 0);
AVFormatContext * m_fc;
int err;
AVPacket pkt;
char * pAudioBuffer = (char *) av_malloc (AVCODEC_MAX_AUDIO_FRAME_SIZE * 2);
int i;
avcodec_register_all ();
avdevice_register_all ();
av_register_all ();
err = av_open_input_file(&m_fc, pszFileName, 0, 0, 0);
err = av_find_stream_info(m_fc);
for(i = 0; i<m_fc->nb_streams; i++) {
if((m_fc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) || (m_fc->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)) {
AVCodec *codec = avcodec_find_decoder(m_fc->streams[i]->codec->codec_id);
if (codec == 0)
continue;
err = avcodec_open(m_fc->streams[i]->codec, codec);
if (err <0)
continue;
}
}
while (av_read_frame(m_fc, &pkt)>= 0) {
if (m_fc-> streams[pkt.stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
int data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE * 2;
int size=pkt->size;
while(size > 0) {
int len = avcodec_decode_audio3(m_fc->streams[pkt.stream_index]->codec, (int16_t *) pAudioBuffer, &data_size, &pkt);
LOGD("data_size %d len %d", data_size, len);
size = pkt->size-len;
}
}
}
}
Comments
-
Kyborg2011 almost 2 years
I am writing a player for Android with FFmpeg compiled for Android NDK.
I could open the file through FFmpeg and wrote this:
av_register_all(); char* str = (*env) -> GetStringUTFChars(env, argv, 0); __android_log_print(ANDROID_LOG_INFO, "HelloNDK!", str, str); if (av_open_input_file (&pFormatCtx, str, NULL, 0, NULL) != 0) return -2; // Couldn't open file // Retrieve stream information if (av_find_stream_info(pFormatCtx) < 0) return -3; // Couldn't find stream information // Dump information about file onto standard error dump_format(pFormatCtx, 0, argv, 0); // Find the first video stream videoStream =- 1; audioStream =- 1; for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO && audioStream <0) { audioStream = i; } } if (audioStream == -1) return -5; aCodecCtx = pFormatCtx->streams[audioStream]->codec; // Set audio settings from codec info aCodec = avcodec_find_decoder(aCodecCtx->codec_id); if (!aCodec) { fprintf (stderr, "Unsupported codec! \n"); return -1; } avcodec_open (aCodecCtx, aCodec);
How can I now decode the audio and return it to the Java program? Maybe somebody could give me an example
EDIT: When using avcodec_decode_audio3 Get the following: 03-22 07:54:00.988: INFO / DEBUG (31): * ** * ** * ** * * * ** * ** * 03-22 07:54:00.988: INFO / DEBUG (31): Build fingerprint: 'generic / sdk / generic /: 2.2/FRF91/43546: eng / test-keys' 03-22 07:54:00.988: INFO / DEBUG (31): pid: 435, tid: 435>>> org.libsdl.app <<< 03-22 07:54:00.998: INFO / DEBUG (1931): signal 11 (SIGSEGV), fault addr 00000000 03-22 07:54:00.998: INFO / DEBUG (1931): r0 00000000 r1 00000000 r2 81893210 r3 00000000 03-22 07:54:01.008: INFO / DEBUG (1931): r4 8189324c r5 818931d0 r6 00000000 r7 00000000 03-22 07:54:01.008: INFO / DEBUG (1931): r8 00000200 r9 00000600 10 00000300 00000500 fp 03-22 07:54:01.019: INFO / DEBUG (1931): ip 81350868 sp bef4c438 lr 8112cb3b pc 8112cb6c cpsr 80000030 03-22 07:54:01.369: INFO / DEBUG (31): # 00 pc 0012cb6c / data / data / org.libsdl.app / lib / libtest.so 03-22 07:54:01.369: INFO / DEBUG (31): # 01 pc 0012db46 / data / data / org.libsdl.app / lib / libtest.so 03-22 07:54:01.379: INFO / DEBUG (31): # 02 pc 0013052e / data / data / org.libsdl.app / lib / libtest.so 03-22 07:54:01.379: INFO / DEBUG (31): # 03 pc 00132142 / data / data / org.libsdl.app / lib / libtest.so 03-22 07:54:01.389: INFO / DEBUG (31): # 04 pc 001a2836 / data / data / org.libsdl.app / lib / libtest.so 03-22 07:54:01.399: INFO / DEBUG (31): # 05 pc 00024ee6 / data / data / org.libsdl.app / lib / libtest.so 03-22 07:54:01.399: INFO / DEBUG (31): # 06 pc 00013974 / system / lib / libdvm.so 03-22 07:54:01.409: INFO / DEBUG (31): # 07 pc 0003de3c / system / lib / libdvm.so 03-22 07:54:01.409: INFO / DEBUG (31): # 08 pc 00037216 / system / lib / libdvm.so 03-22 07:54:01.419: INFO / DEBUG (31): # 09 pc 000432ec / system / lib / libdvm.so 03-22 07:54:01.419: INFO / DEBUG (31): # 10 pc 00018714 / system / lib / libdvm.so 03-22 07:54:01.439: INFO / DEBUG (31): # 11 pc 0001e8c4 / system / lib / libdvm.so 03-22 07:54:01.439: INFO / DEBUG (31): # 12 pc 0001d790 / system / lib / libdvm.so 03-22 07:54:01.439: INFO / DEBUG (31): # 13 pc 0005408e / system / lib / libdvm.so 03-22 07:54:01.449: INFO / DEBUG (31): # 14 pc 0005bde2 / system / lib / libdvm.so 03-22 07:54:01.449: INFO / DEBUG (31): # 15 pc 00018714 / system / lib / libdvm.so 03-22 07:54:01.459: INFO / DEBUG (31): # 16 pc 0001e8c4 / system / lib / libdvm.so 03-22 07:54:01.469: INFO / DEBUG (31): # 17 pc 0001d790 / system / lib / libdvm.so 03-22 07:54:01.469: INFO / DEBUG (31): # 18 pc 00053eec / system / lib / libdvm.so 03-22 07:54:01.479: INFO / DEBUG (31): # 19 pc 0004072c / system / lib / libdvm.so 03-22 07:54:01.479: INFO / DEBUG (31): # 20 pc 00034454 / system / lib / libdvm.so 03-22 07:54:01.489: INFO / DEBUG (31): # 21 pc 0002c930 / system / lib / libandroid_runtime.so 03-22 07:54:01.489: INFO / DEBUG (31): # 22 pc 0002d85c / system / lib / libandroid_runtime.so 03-22 07:54:01.499: INFO / DEBUG (31): # 23 pc 00008c86 / system / bin / app_process 03-22 07:54:01.519: INFO / DEBUG (31): # 24 pc 0000d362 / system / lib / libc.so
Can I use avcodec_decode_audio2? I have in recent days has reached the following code:
AVFormatContext * pFormatCtx; int i, videoStream, audioStream; AVCodecContext * pCodecCtx; AVCodec * pCodec; AVFrame * pFrame; AVPacket packet; int frameFinished; float aspect_ratio; AVCodecContext * aCodecCtx; AVCodec * aCodec; AVCodecContext * c = NULL; int out_size, len; int16_t * audio_buf; uint8_t * outbuf; uint8_t inbuf [AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; av_register_all (); char * str = (* env) -> GetStringUTFChars (env, argv, 0); if (av_open_input_file (& pFormatCtx, str, NULL, 0, NULL)! = 0) return -150; if (av_find_stream_info (pFormatCtx) nb_streams; i + +) { if (pFormatCtx-> streams [i] -> codec-> codec_type == CODEC_TYPE_VIDEO & & videoStream streams [i] -> codec-> codec_type == CODEC_TYPE_AUDIO & & audioStream streams [audioStream] -> codec; aCodec = avcodec_find_decoder (aCodecCtx-> codec_id); if (! aCodec) { fprintf (stderr, "Unsupported codec! \ n"); return -45; } avcodec_open (aCodecCtx, aCodec); c = avcodec_alloc_context (); packet_queue_init (& audioq); while (av_read_frame (pFormatCtx, & packet)> = 0) { if (packet.stream_index == videoStream) { } Else if (packet.stream_index == audioStream) { packet_queue_put (& audioq, & packet); int len1, data_size; data_size = 417; len1 = avcodec_decode_audio2 (aCodecCtx, (int16_t *) audio_buf, & data_size, packet.data, packet.size); return packet.size; } Else { av_free_packet (& packet); } } return 0;
In this case, when the avcodec_decode_audio2 I got -1. What I did wrong?
Note: When I drove int data_size = 417; then DEBUG does not appear and the function returns -1, but when I drive a: int data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE * 2; then vyskakievaet DEBUG in your function so in my own! How can this be solved?
EDIT2: My new code:
JNIEXPORT jint JNICALL Java_org_libsdl_app_SDLActivity_main( JNIEnv* env, jobject obj, int argc, jstring argv, jbyteArray array) { AVFormatContext *pFormatCtx; int i, videoStream, audioStream; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame; AVPacket packet; int frameFinished; float aspect_ratio; AVCodecContext *aCodecCtx; AVCodec *aCodec; SDL_Overlay *bmp; SDL_Surface *screen; SDL_Rect rect; SDL_Event event; SDL_AudioSpec wanted_spec, spec; AVCodecContext *c= NULL; int out_size, len; int16_t *audio_buf; uint8_t *outbuf; uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; char *pAudioBuffer = (char *) av_malloc (AVCODEC_MAX_AUDIO_FRAME_SIZE * 2); av_register_all(); char *str = (*env)->GetStringUTFChars(env, argv, 0); if(av_open_input_file(&pFormatCtx, str, NULL, 0, NULL)!=0) return -150; // Couldn't open file if(av_find_stream_info(pFormatCtx)nb_streams; i++) { if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO && videoStream streams[i]->codec->codec_type==CODEC_TYPE_AUDIO && audioStream streams[audioStream]->codec; aCodec = avcodec_find_decoder(aCodecCtx->codec_id); if(!aCodec) { fprintf(stderr, "Unsupported codec!\n"); return -45; } avcodec_open(aCodecCtx, aCodec); c=avcodec_alloc_context(); packet_queue_init(&audioq); while (av_read_frame(pFormatCtx, &packet)>= 0) { if (aCodecCtx->codec_type == AVMEDIA_TYPE_AUDIO) { int data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE * 2; int size=packet.size; while(size > 0) { int len = avcodec_decode_audio3(aCodecCtx, (int16_t *) pAudioBuffer, &data_size, &packet); jbyte *bytes = (*env)->GetByteArrayElements(env, array, NULL); memcpy(bytes, (int16_t *) pAudioBuffer, size); (*env)->ReleaseByteArrayElements(env, array, bytes, 0); size = packet.size-len; } } } return 5; }