2013-02-27 4 views
0

Я пытаюсь декодировать аудиофайл в PCM для использования с AudioTrack. Звук сжимается, шустрый и просто беспорядочный, и для случайного второго звучит так, как должно, но в основном полностью запутано. Я не уверен, где моя ошибка, так это то, как массив передается обратно в playSound?Получение jibberish при использовании ffmpeg в android

Благодарим вас за это, я был бы очень благодарен за помощь в этом вопросе, так как это уже давно ударило о задницу.

Это мой Java-код:

public void init() { 
int bufSize = AudioTrack.getMinBufferSize(44100, 
       AudioFormat.CHANNEL_OUT_STEREO, 
       AudioFormat.ENCODING_PCM_16BIT); 


     track = new AudioTrack(AudioManager.STREAM_MUSIC, 
     44100, 
     AudioFormat.CHANNEL_OUT_STEREO, 
     AudioFormat.ENCODING_PCM_16BIT, 
     bufSize, 
     AudioTrack.MODE_STREAM); 
     log("STARTING!!! _________________________ <--"); 

     byte[] array = new byte[bufSize]; 

     try { 

      fos = new FileOutputStream("/sdcard/acdc.bin"); 

     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     decoder("/sdcard/acdc.ogg", array); 
} 

void playSound(byte[] buf, int size) { 

    try { 
     fos.write(buf, 0, size); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    if(track.getPlayState()!=AudioTrack.PLAYSTATE_PLAYING) { 
     track.play();      
    } 
    int wrote = track.write(buf, 0, size); 
    if (wrote != size) 
     log("WRITING: " + wrote + " but size was: " + size); 
} 

Это моя с функцией:

void Java_com_example_ffmpegsample_MainActivity_decoder(JNIEnv* env, jobject obj,jstring file,jbyteArray array) 
    { 
     jboolean   isfilenameCopy; 
     const char *  filename = (*env)->GetStringUTFChars(env, file, &isfilenameCopy); 
     AVCodec *codec; 
     AVCodecContext *c= NULL; 
     AVFormatContext *pFormatCtx; 
     AVCodecContext *pCodecCtx; 

     int out_size, len; 
     FILE *f, *outfile; 
     uint8_t *outbuf; 
     uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; 
     AVPacket avpkt; 
     LOGI("HERE"); 
     jclass    cls = (*env)->GetObjectClass(env, obj); 
     LOGI(cls); 
     jmethodID   play = (*env)->GetMethodID(env, cls, "playSound", "([BI)V");//At the begining of your main function 

     av_init_packet(&avpkt); 



     av_register_all(); 
     LOGI("AUDIO DECODER"); 
     printf("Audio decoding\n"); 
     int err; 
     err = av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL); 
     if (err!=0) { 
      LOGI("COULD NOT AV_OPEN file"); 
      return; 
     } 
     if(av_find_stream_info(pFormatCtx)<0) { 
       LOGE("Unable to get stream info"); 
       return; 
     } 
     int audioStream = -1; 
     int i; 

     for (i=0; i<pFormatCtx->nb_streams; i++) { 
       if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO) { 
        audioStream = i; 
        break; 
       } 
      } 
      if(audioStream==-1) { 
       LOGE("Unable to find audio stream"); 
       return; 
      } 
     LOGI("Audio stream is [%d]", audioStream); 

     pCodecCtx=pFormatCtx->streams[audioStream]->codec; 
     codec = avcodec_find_decoder(pCodecCtx->codec_id); 
     /* find the mpeg audio decoder */ 
     // codec = avcodec_find_decoder(CODEC_ID_AAC); 
     if (!codec) { 
      LOGI("NO CODEC"); 
      fprintf(stderr, "codec not found\n"); 
      return; 
     } 

     //c= avcodec_alloc_context(); 
     c = pCodecCtx; 

     /* open it */ 
     if (avcodec_open(c, codec) < 0) { 
      fprintf(stderr, "could not open codec\n"); 
      LOGI("NOT LOADING CODEC"); 
      return; 
     } 

     outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); 

     f = fopen(filename, "rb"); 
     if (!f) { 
      fprintf(stderr, "could not open %s\n", filename); 
      LOGI("COULD NOT OPEN FILE"); 
      return; 
     } 

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

     while (avpkt.size > 0) { 
      LOGI("............................." + avpkt.size); 
      out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; 
      len = avcodec_decode_audio3(c, (short *)outbuf, &out_size, &avpkt); 
      if (len < 0) { 
       fprintf(stderr, "Error while decoding\n"); 
       LOGI("ERROR DECODING, error: %d", len); 
       return; 
      } 
      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); 
    } 

ответ

1

Вы создаете аудиодорожки в потоковом режиме с буфером мин размера. Может случиться так, что если он преобразует некоторые данные, а затем записывает некоторые данные, которые имеют место в воспроизведении звука. Это было бы особенно верно, если преобразование должно было продолжать чтение с SD-карты. Вы можете увеличить размер буфера AudioTrack, чтобы убедиться, что это фактор.

Кроме того, я не уверен, но я думаю, что avcodec_decode_audio3 может установить & out_size как размер в шортах, но затем он отправляется в AudioTrack как размер в байтах. (Не проверял API и его байты).

+0

это комментарий, а не ответ :) – bofredo

+0

Спасибо да, я переписал его :) –

+0

Спасибо, однако я попробовал с bufSize * 20, чтобы действительно поместить его, но безрезультатно. – StackOverflowed

1

у вас пробовал использовать простой интерфейс CLI в андроиде, как этот project? Вы можете использовать простой интерфейс fileProcesssor: IN = OUT OGG = сырец ИКМ

смотрите ниже на CLI для преобразования .ogg в формат PCM. Тогда делать все, что с выходом

[email protected] Downloads$ ffmpeg -i Example.ogg -f s16le -acodec pcm_s16le output.raw 

ffmpeg version N-35901-g27a3415 Copyright (c) 2000-2012 the FFmpeg developers 
    built on Oct 7 2012 12:06:43 with gcc 4.6 (Ubuntu/Linaro 4.6.3-1ubuntu5) 
    configuration: --enable-gpl --enable-libfaac --enable-libfdk-aac --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-librtmp --enable-libtheora --enable-libvorbis --enable-libvpx --enable-x11grab --enable-libx264 --enable-nonfree --enable-version3 
    libavutil  51. 73.102/51. 73.102 
    libavcodec  54. 64.100/54. 64.100 
    libavformat 54. 29.105/54. 29.105 
    libavdevice 54. 3.100/54. 3.100 
    libavfilter  3. 19.102/3. 19.102 
    libswscale  2. 1.101/2. 1.101 
    libswresample 0. 16.100/0. 16.100 
    libpostproc 52. 1.100/52. 1.100 
[NULL @ 0x186b840] Invalid packet 
Input #0, ogg, from 'Example.ogg': 
    Duration: 00:00:06.10, start: 0.000000, bitrate: 137 kb/s 
    Stream #0:0: Audio: vorbis, 44100 Hz, stereo, s16, 160 kb/s 
Output #0, s16le, to 'output.raw': 
    Metadata: 
    encoder   : Lavf54.29.105 
    Stream #0:0: Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s 
Stream mapping: 
    Stream #0:0 -> #0:0 (vorbis -> pcm_s16le) 
Press [q] to stop, [?] for help 
size= 1054kB time=00:00:06.11 bitrate=1411.2kbits/s  
video:0kB audio:1054kB subtitle:0 global headers:0kB muxing overhead 0.000000% 

Это предполагает, что вы можете конфиг/сделать FFmpeg для андроида с OGG LIB зависимостей, который может быть сложным процессом ...

+0

Как мне вернуть данные pcm в java? Кроме того, можно ли распространить двоичный код с apk на рынок? – StackOverflowed

+0

java - это то, где вы создаете выражение CLF ffmpeg, как это делается в «guardian» на git ... Итак, у java есть доступ к файлам. JNI/Java обертка вызов является ffmpeg.main() ... CLI называют основной() в ffmpeg.c –

+0

функции JNI, как от опекуна Proj на мерзавца ... # включить // своп RecorderActivity 4 FfmpegService недействительным Java_com_borneo_speech_FfmpegService_runNative (JNIEnv * env, jobject obj, jstring libffmpeg_path, jobjectArray ffmpeg_args) {...} –