2014-02-18 3 views
0

아래 주어진 코드는 에뮬레이터에서는 정상적으로 작동하지만 장치에서는 정상적으로 작동하지 않습니다.Android MediaCodec API - 장치가 아닌 에뮬레이터에서 음악 재생

V/MediaExtractor (5030) : 자신감 '오디오/MPEG'등의 자동 감지의 미디어 콘텐츠 0.20 V/ChromiumHTTPDataSource (5030) : mContentSize이 정의되지 또는 네트워크 연결이 끊어 수 있습니다 나는 나에게 의심스러운 보았다 다음 줄을 발견 V/ChromiumHTTPDataSource (5030) : mContentSize은 정의되지 않습니다 또는 네트워크 D/(5030) com.example.mediacodectest 분리 될 수 있습니다 MIME 종류 : 오디오/MPEG 내가 힌트/제안을 찾고

. 미리 감사드립니다 ...

private class PlayerThread extends Thread { 

    @Override 
    public void run() { 
     MediaExtractor extractor; 
     MediaCodec codec; 
     ByteBuffer[] codecInputBuffers; 
     ByteBuffer[] codecOutputBuffers; 

     AudioTrack mAudioTrack; 

     mAudioTrack = new AudioTrack(
       AudioManager.STREAM_MUSIC, 
       44100, 
       AudioFormat.CHANNEL_OUT_STEREO, 
       AudioFormat.ENCODING_PCM_16BIT, 
       8192 * 2, 
       AudioTrack.MODE_STREAM); 

     extractor = new MediaExtractor(); 
     try 
     { 
      extractor.setDataSource("http://anmp3streamingsource.com/stream"); 
      MediaFormat format = extractor.getTrackFormat(0); 
      String mime = format.getString(MediaFormat.KEY_MIME); 
      Log.d(TAG, String.format("MIME TYPE: %s", mime)); 

      codec = MediaCodec.createDecoderByType(mime); 
      codec.configure(
        format, 
        null /* surface */, 
        null /* crypto */, 
        0 /* flags */); 
      codec.start(); 
      codecInputBuffers = codec.getInputBuffers(); 
      codecOutputBuffers = codec.getOutputBuffers(); 

      extractor.selectTrack(0); // <= You must select a track. You will read samples from the media from this track! 

      boolean sawInputEOS = false; 
      boolean sawOutputEOS = false;    

      for (;;) { 
       int inputBufIndex = codec.dequeueInputBuffer(-1); 
       if (inputBufIndex >= 0) { 
        ByteBuffer dstBuf = codecInputBuffers[inputBufIndex]; 

        int sampleSize = extractor.readSampleData(dstBuf, 0); 
        long presentationTimeUs = 0; 
        if (sampleSize < 0) { 
         sawInputEOS = true; 
         sampleSize = 0; 
        } else { 
         presentationTimeUs = extractor.getSampleTime(); 
        } 

        codec.queueInputBuffer(inputBufIndex, 
              0, //offset 
              sampleSize, 
              presentationTimeUs, 
              sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0); 
        if (!sawInputEOS) { 
         extractor.advance(); 
        } 

        MediaCodec.BufferInfo info = new BufferInfo(); 
        final int res = codec.dequeueOutputBuffer(info, -1); 
        if (res >= 0) { 
         int outputBufIndex = res; 
         ByteBuffer buf = codecOutputBuffers[outputBufIndex]; 

         final byte[] chunk = new byte[info.size]; 
         buf.get(chunk); // Read the buffer all at once 
         buf.clear(); // ** MUST DO!!! OTHERWISE THE NEXT TIME YOU GET THIS SAME BUFFER BAD THINGS WILL HAPPEN 

         mAudioTrack.play(); 

         if (chunk.length > 0) { 
          mAudioTrack.write(chunk, 0, chunk.length); 
         } 
         codec.releaseOutputBuffer(outputBufIndex, false /* render */); 

         if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { 
          sawOutputEOS = true; 
         } 
        } 
        else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) 
        { 
         codecOutputBuffers = codec.getOutputBuffers(); 
        } 
        else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) 
        { 
         final MediaFormat oformat = codec.getOutputFormat(); 
         Log.d(TAG, "Output format has changed to " + oformat); 
         mAudioTrack.setPlaybackRate(oformat.getInteger(MediaFormat.KEY_SAMPLE_RATE)); 
        } 
       } 
      } 

     }     
     catch (IOException e) 
     { 
      Log.e(TAG, e.getMessage()); 
     } 
    } 
} 
+0

출력 처리가 올바르지 않습니다. http://bigflake.com/mediacodec/#q11에서 FAQ 항목 # 11을 추가했습니다. 표시되는 로그 라인이 너무 의심스럽지 않습니다. 코드가 장치에서 작동하지 않는 방법을보다 명확하게 정의 할 수 있습니까? – fadden

+0

답장을 보내 주셔서 감사합니다. 이 코드는 API 레벨 17 에뮬레이터에서는 제대로 작동하지만 API 레벨 18로 실제 장치에서는 작동하지 않습니다. 다음 줄까지 디버그 할 수 있습니다. final int res = codec.dequeueOutputBuffer (info, -1); 하지만 더 이상 ... – burakk

답변

1

오디오로 작업하지는 않았지만 문제가 발생할 수 있습니다. 코덱이 더 많은 입력을 기다리고 있기 때문에 dequeueOutputBuffer()에 매달려 있습니다.

일부 비디오 코덱은 초기화를 완료하기 전에 ~ 4 개의 버퍼를 원합니다 (for example). 일부 오디오 코덱은 같은 방식으로 작동 할 수 있습니다. 코덱 구현은 장치마다 다르므로 에뮬레이터에서 실행되는 내용이 훨씬 다르게 작동합니다.

타임 아웃을 -1 (영원히 기다림)에서 약한 것 (예 : 1000 마이크로 초)으로 변경하십시오.

+0

감사합니다. 언제 타임 아웃 -1을 설정 하시겠습니까? – burakk

+0

나는 그것을 상수 값으로 사용하지 않을 것이다. 첫 번째 입력 버퍼를 기다리는 중이거나 입력 EOS를 보내고 출력이 소진 될 때까지 기다리는 중일 때는 루핑 포인트가 없습니다. 변수를 -1로 설정할 수 있습니다. 첫 번째 입력을 기다린 다음 변수를 1000으로 설정하고 입력이 부족할 때까지이 변수를 사용하면 다시 -1로 설정됩니다. (시작 대기 시간에 대한 질문이 생겨서 Grafika에서 이런 일을하는 것을 의미했지만, 아직 그것에 대해 아직 알지 못합니다.) – fadden