Как декодировать аудио через FFmpeg в Android

Я пишу плеер для Android с FFmpeg, скомпилированный для Android NDK.

Я мог бы открыть файл через 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: INFO / DEBUG (31): * * * * * * * * * * * * ** * * * * 03-22 07:54: 00.988: INFO / DEBUG (31): Создание отпечатка пальца: '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): сигнал 11 (SIGSEGV), адрес ошибки 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 шт. 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 шт. 00018714 / system / lib / libdvm.so 03-22 07:54:01.459: INFO / DEBUG (31): # 16 шт. 0001e8c4 / system / lib / libdvm.so 03-22 07:54:01.469: INFO / DEBUG (31): # 17 шт. 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 пк 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, но когда я веду: int data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE * 2; тогда выскакиевает DEBUG в твои функции, так по моему! Как это можно решить?

EDIT2: мой новый код:


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

2 ответа

Решение

Используйте аудиотрек класс, чтобы сделать работу за вас. Вы можете сделать что-то вроде этого.

JAVA сторона.

            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

                    ....................
                    ....................
                    }

На родной стороне: вам нужно сначала прочитать кадры и преобразовать их в формат необработанного pcm, а затем начать непрерывно заполнять аудио-буфер. Когда буфер заполнен, он будет автоматически воспроизводиться.

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

}

Я не мог оставить комментарий, поэтому я публикую это как ответ.

Я также пытаюсь воспроизвести звук aac с помощью ffmpeg, но у меня много вопросов о том, как заставить его работать.

Я пытался использовать http://code.google.com/p/aacplayer-android/ в качестве ссылки, но автор кода не использует avcodec_decode_audio3 для декодирования. Воспроизведение через AudioTrack сильно запинается, и я предполагаю, что декодер не заполняет буфер достаточно быстро для воспроизведения аудиотрека.

Есть ли другой способ сделать это?

Еще раз прошу прощения за размещение этого в качестве ответа.

Другие вопросы по тегам