如何在Android中通过FFmpeg解码音频
我正在使用为 Android NDK 编译的 FFmpeg 编写一个 Android 播放器。
我可以通过 FFmpeg 打开该文件并写道:
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);
我现在如何解码音频并将其返回到 Java 程序?也许有人可以给我一个例子
编辑: 使用avcodec_decode_audio3时 获取以下信息: 03-22 07:54:00.988:信息/调试 (31):* ** * > ** * ** * * * ** * ** * 03-22 07:54:00.988:信息/调试(31):构建指纹:'generic / sdk / generic /:2.2 / FRF91/43546:eng / test-keys' 03-22 07:54:00.988:信息/调试(31):pid:435,tid:435>>>> org.libsdl.app <<< 03-22 07:54:00.998:信息/调试 (1931):信号 11 (SIGSEGV),故障地址 00000000 03-22 07:54:00.998:信息/调试(1931):r0 00000000 r1 00000000 r2 81893210 r3 00000000 03-22 07:54:01.008:信息/调试(1931):r4 8189324c r5 818931d0 r6 00000000 r7 00000000 03-22 07:54:01.008:信息/调试(1931):r8 00000200 r9 00000600 10 00000300 00000500 fp 03-22 07:54:01.019:信息/调试(1931):ip 81350868 sp bef4c438 lr 8112cb3b pc 8112cb6c cpsr 80000030 03-22 07:54:01.369:信息/调试(31):#00 pc 0012cb6c/数据/数据/org.libsdl.app/lib/libtest.so 03-22 07:54:01.369: 信息/调试(31): # 01 pc 0012db46/数据/数据/org.libsdl.app/lib/libtest.so 03-22 07:54:01.379:信息/调试(31):#02 pc 0013052e/数据/数据/org.libsdl.app/lib/libtest.so 03-22 07:54:01.379: 信息/调试(31): # 03 pc 00132142/数据/数据/org.libsdl.app/lib/libtest.so 03-22 07:54:01.389:信息/调试(31):#04 pc 001a2836/数据/数据/org.libsdl.app/lib/libtest.so 03-22 07:54:01.399:信息/调试(31):#05 pc 00024ee6/数据/数据/org.libsdl.app/lib/libtest.so 03-22 07:54:01.399: 信息/调试(31):#06 pc 00013974/system/lib/libdvm.so 03-22 07:54:01.409: 信息/调试 (31): # 07 pc 0003de3c/system/lib/libdvm.so 03-22 07:54:01.409: 信息/调试(31):#08 pc 00037216/system/lib/libdvm.so 03-22 07:54:01.419: 信息/调试 (31): # 09 pc 000432ec/system/lib/libdvm.so 03-22 07:54:01.419: 信息/调试(31): #10 pc 00018714/system/lib/libdvm.so 03-22 07:54:01.439: 信息/调试(31): #11 pc 0001e8c4/system/lib/libdvm.so 03-22 07:54:01.439: 信息/调试 (31): # 12 pc 0001d790/system/lib/libdvm.so 03-22 07:54:01.439: 信息/调试(31): #13 pc 0005408e/system/lib/libdvm.so 03-22 07:54:01.449: 信息/调试 (31): # 14 pc 0005bde2 /system/lib/libdvm.so 03-22 07:54:01.449: 信息/调试(31): #15 pc 00018714/system/lib/libdvm.so 03-22 07:54:01.459: 信息/调试(31): #16 pc 0001e8c4/system/lib/libdvm.so 03-22 07:54:01.469: 信息/调试 (31): #17 pc 0001d790/system/lib/libdvm.so 03-22 07:54:01.469: 信息/调试 (31): #18 pc 00053eec/system/lib/libdvm.so 03-22 07:54:01.479: 信息/调试 (31): #19 pc 0004072c/system/lib/libdvm.so 03-22 07:54:01.479: 信息/调试(31): #20 pc 00034454/system/lib/libdvm.so 03-22 07:54:01.489: 信息/调试 (31): # 21 pc 0002c930/system/lib/libandroid_runtime.so 03-22 07:54:01.489: 信息/调试 (31): # 22 pc 0002d85c/system/lib/libandroid_runtime.so 03-22 07:54:01.499: 信息/调试 (31): # 23 pc 00008c86/system/bin/app_process 03-22 07:54:01.519: 信息/调试(31): #24 pc 0000d362/system/lib/libc.so
我可以使用avcodec_decode_audio2吗? 我最近几天已经达到了以下代码:
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;
在这种情况下,当 avcodec_decode_audio2 时我得到-1。我做错了什么?
笔记: 当我开车时 int data_size = 417;然后DEBUG不会出现并且函数返回-1,但是当我驱动a时:int data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE * 2;然后 vyskakievaet DEBUG 在你的函数中,所以在我自己的函数中!如何解决这个问题?
编辑2: 我的新代码:
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;
}
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用音轨类来为您完成这项工作。你可以做这样的事情。
JAVA端。
在本机端:您需要首先读取帧并将其转换为原始 pcm 格式,然后开始连续填充音频缓冲区。当缓冲区满时,会自动播放。
}
Use audiotrack class to do the work for you. You can do something like this.
JAVA side.
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.
}
我无法发表评论,所以我将其作为答案发布。
我还尝试使用 ffmpeg 播放 aac 音频,但对于如何使其工作有很多问题。
我尝试使用 http://code.google.com/p/aacplayer-android/ 作为参考,但代码的作者没有使用avcodec_decode_audio3进行解码。通过 AudioTrack 的播放非常断断续续,我认为解码器填充缓冲区的速度不够快,无法让音轨播放。
我还有其他方法可以做到这一点吗?
再次抱歉将其发布为答案。
I could not post a comment, so am posting this as an answer.
I'm also trying to do play aac audio using ffmpeg but have a lot of questions on how to get it working.
I tried using http://code.google.com/p/aacplayer-android/ as a reference, but the author of the code is not using avcodec_decode_audio3 for decoding. The playback through AudioTrack stutters a lot and I assume that the buffer is not getting filled by the decoder fast enough for the audiotrack to play.
Is there any other way I can do this?
Once again, sorry for posting this as a answer.