2016-01-25 27 views
10

W systemie Android 4.4.2 używam MediaCodec do dekodowania plików mp3. Używam queueInputBuffer() do kolejkowania wejściowych ramek MP3 i dequeueOutputBuffer(), aby uzyskać dekodowane ramki. Ale dekoder daje dekodowane wyjście od 8 klatki dalej (w oparciu o bufferInfo.presentationTimeUs) i pomija początkowe 7 klatek. Ten scenariusz występuje tylko dla kilku strumieni, ale nie dla wszystkich strumieni. Ponadto takie zachowanie jest spójne w wielu seriach.Android MediaCodec nie dekoduje wszystkich buforów wejściowych

Chcę dekodowane wyjście wszystkich klatek i nie chcę pominąć żadnych klatek. Czy ktoś może mi pomóc zrozumieć, dlaczego ramki są pomijane? Zapewniam, że strumień nie jest uszkodzony. Ponieważ dostaję INFO_TRY_AGAIN do 7 klatki, gdy poprawny indeks bufora jest zwracany przez `dequeueOutputBuffer ', jego czas prezentacji jest zawsze w 8 klatce.

Poniżej znajduje się kod kolejkowanie:

Log.e(TAG, "audptOffset = "+audptOffset+"input PT = "+audpt); 
       audcodec.queueInputBuffer(audInbufIndex, 0, audchunkSize, audpt, 0); 

obserwuję to w jaki sposób mogę zadzwonić rozkolejkowania i pisać do AudioTrack:

if(!audoutputDone){ 
       if(!waitForAudioRelease){ 
        auoutBufIndex = audcodec.dequeueOutputBuffer(auinfo, 100); 
        Log.e(TAG, "Output PT = " + auinfo.presentationTimeUs+"auoutBufIndex = "+auoutBufIndex); 
       } 
       if (auoutBufIndex >= 0) { 
        waitForAudioRelease = true; 
       } else if (auoutBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { 
        auddecOutBufArray = audcodec.getOutputBuffers(); 
       } else if (auoutBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { 
        MediaFormat newFormat = audcodec.getOutputFormat(); 
        int sampleRate1 = newFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE); 
        int channelCount1 =newFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT); 
        Log.e(TAG, "INFO_OUTPUT_FORMAT_CHANGED"); 
        int minBufSize1 = AudioTrack.getMinBufferSize(sampleRate1, (channelCount1==2)? 
          AudioFormat.CHANNEL_OUT_STEREO:AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); 
        audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 
          sampleRate1, (channelCount1==2)?AudioFormat.CHANNEL_OUT_STEREO:AudioFormat.CHANNEL_OUT_MONO, 
          AudioFormat.ENCODING_PCM_16BIT, minBufSize1, 
          AudioTrack.MODE_STREAM); 
        audioTrack.play(); 
        waitForAudioRelease = false; 
       } 
       audionowUs = System.currentTimeMillis(); 
       if (auoutBufIndex >= 0) {    
        auwhenRealUs = (auinfo.presentationTimeUs/1000) + mStartTimeRealMs - (audptOffset/1000); 
        aulateByUs = audionowUs - auwhenRealUs; 


        if(!audioWaitTillStartTime){ 
         while((mStartTimeRealMs+((auinfo.presentationTimeUs/1000) - (audptOffset/1000))) >= audionowUs){ 
          try { 
           Thread.sleep(10); 
          } catch (InterruptedException e) { 
           // TODO Auto-generated catch block 
           e.printStackTrace(); 
          } 
          audionowUs = System.currentTimeMillis(); 
         } 
         Log.e(TAG,"Play is going to start PT Difference = "+((auinfo.presentationTimeUs/1000) - (audptOffset/1000))); 
        } 

Dodanie kilku dzienników:

02-22 17:46:03.164: E/CL(28650): received play command from server 
02-22 17:46:03.209: E/RealTimeClient(28650): created decoder for audio/mpeg 
02-22 17:46:03.234: E/Music(28650): Output PT = 0 
02-22 17:46:03.234: E/Music(28650): pt of first frame received 1215000 
02-22 17:46:03.234: E/Music(28650): Input PT = 1215000 
02-22 17:46:03.234: E/Music(28650): Output PT = 0 
02-22 17:46:03.234: E/Music(28650): Input PT = 1241122 
02-22 17:46:03.239: E/Music(28650): Output PT = 0 
02-22 17:46:03.239: E/Music(28650): Input PT = 1267244 
02-22 17:46:03.239: E/Music(28650): Output PT = 0 
02-22 17:46:03.239: E/Music(28650): Input PT = 1293367 
02-22 17:46:03.239: E/Music(28650): Output PT = 0 
02-22 17:46:03.239: E/Music(28650): Input PT = 1319489 
02-22 17:46:03.239: E/Music(28650): Output PT = 0 
02-22 17:46:03.244: E/Music(28650): INFO_OUTPUT_FORMAT_CHANGED 
02-22 17:46:03.249: I/Reverb(28650): getpid() 28650, IPCThreadState::self()->getCallingPid() 28650 
02-22 17:46:03.249: E/Reverb(28650): Reverb::StartElementHandler, wrong element or attributes: boolean 
02-22 17:46:03.249: E/Music(28650): Input PT = 1345612 
02-22 17:46:03.254: E/Music(28650): Output PT = 1293367 
02-22 17:46:03.259: E/Music(28650): Input PT = 1371734 
02-22 17:46:03.259: E/Music(28650): Input PT = 1397857 
02-22 17:46:03.259: E/Music(28650): Input PT = 1423979 
02-22 17:46:03.259: E/Music(28650): Input PT = 1450102 
02-22 17:46:03.264: E/Music(28650): Input PT = 1476224 
02-22 17:46:03.269: E/Music(28650): Input PT = 1502346 
02-22 17:46:03.269: E/Music(28650): Input PT = 1528469 
02-22 17:46:03.269: E/Music(28650): Input PT = 1554591 
02-22 17:46:03.269: E/Music(28650): Input PT = 1580714 
02-22 17:46:03.269: E/Music(28650): Input PT = 1606836 
02-22 17:46:03.269: E/Music(28650): Input PT = 1632959 
02-22 17:46:03.269: E/Music(28650): Input PT = 1659081 
02-22 17:46:04.124: W/AudioTrack(28650): releaseBuffer() track 0x5e2faf28 name=0x3 disabled, restarting 
02-22 17:46:04.129: E/Music(28650): Output PT = 1319489 
02-22 17:46:04.129: E/Music(28650): Input PT = 1685204 
02-22 17:46:04.159: E/Music(28650): Output PT = 1345612 
+0

czy masz wyjście dziennika? czasami dekoder zwraca komunikaty w wynikach dziennika. –

+0

@GabrielBursztyn Dekoder specjalnie nie rzucił w tym zakresie żadnych problemów, w każdym razie będę symulował i opublikuję logi tak szybko, jak to możliwe – nmxprime

+0

@GabrielBursztyn, Dodano więcej logów, może to pomóc – nmxprime

Odpowiedz

1

MPEG-1 Layer III (MP3) ma ramki zależne, nie możesz po prostu zacząć od jakiejkolwiek ramki takiej jak Layer I lub Layer II. Cytując z podanego link, "W najgorszym przypadku może być potrzebnych 9 ramek wejściowych, zanim będzie można dekodować pojedynczą ramkę." Najprawdopodobniej to widzisz. Chociaż każda z pierwszych 7 klatek ma powiązany z nią PTS, dopiero po osiągnięciu 8-tej klatki dekoder jest w stanie w pełni zdekodować ramkę i rozpocząć odtwarzanie. Odtwarzanie rozpoczyna się od PTS z 8 klatek. Musiałbyś ręcznie przeanalizować bajty strumienia, o którym mowa, ręcznie, aby w pełni sprawdzić, co się dzieje, ale podejrzewam, że faktycznie grasz wszystkie klatki.

+0

'Odtwarzanie rozpoczyna się od PTS-a 8-tej ramki - czy to oznacza, PTS z dane wyjściowe pierwszej klatki są aktualizowane za pomocą PTS ósmej ramki? – nmxprime

+0

Dodano więcej logów, może to pomóc lepiej zrozumieć. – nmxprime

+0

W najgorszym przypadku nie można odtwarzać pierwszych 8 klatek, ponieważ nie ma wystarczających informacji, aby utworzyć całkowicie zdekodowaną ramkę. Te PTS zostaną zignorowane, a pierwszy PTS do wyprowadzenia będzie powiązany z pierwszą w pełni zdekodowaną ramką (może to być dowolna z pierwszych 9 ramek), która może być przekazana do odtwarzacza audio. Jeśli wprowadzisz do odtwarzacza częściowo zdekodowaną ramkę z PTS, usłyszysz śmieci. Po uzyskaniu pierwszej w pełni zdekodowanej ramki zobaczysz każdy PTS wprowadzony jako wyjście. Wygląda to dokładnie tak, jak dzieje się w dzienniku. – Kaleb