1

AudioTrack、MediaCodec、および MediaExtractor の組み合わせを使用して、音楽をデコードおよび再生しています。

ドキュメントによると、

以前に送信されたデータに隣接していないデータのデコードを開始するには (つまり、シーク後)、デコーダーを flush() する必要があります。フラッシュの時点でクライアントが所有している可能性のある入力または出力バッファーは、すぐに取り消されます。つまり、flush() の呼び出し後、クライアントはバッファーを所有しなくなります。

mAudioTrack.flush(); も呼び出す必要があるように、シーク後にフラッシュを呼び出しています。

フラッシュが呼び出されますが、audioTrack は以前に書き込まれたデータの一部を再生し、新しく書き込まれたデータから続行します。

Decoder.flush を呼び出さないと、オーディオ再生で顕著な不具合が発生する可能性があります。では、この瞬間的なフラッシュを実現し、新しく書き込まれたデータの再生を継続するにはどうすればよいでしょうか?

コードスニペット:

更新されたコード

do {
                int codedbufferIndex = decoder.dequeueInputBuffer(1000);
                if (codedbufferIndex >= 0) {
                    ByteBuffer codecInput = inputBuffers[codedbufferIndex];
                    synchronized (playerState) {
                        if (seek) {
                            extractor.seekTo(seekTo,
                                    MediaExtractor.SEEK_TO_CLOSEST_SYNC);
                        //  audioTrack.pause();
                        //  audioTrack.stop();
                        //  audioTrack.flush();
                            decoder.flush();
                            seek = false;
                        //  audioTrack.play();
                            continue;
                        }
                    }
                    read = extractor.readSampleData(codecInput, offset);
                    if (read < 0) {
                        if (extractor.hasCacheReachedEndOfStream())
                            Log.e(TAG, "extractor.hasCacheReachedEndOfStream()");
                        break;
                    }
                    presentationTimeUs = extractor.getSampleTime();
                    decoder.queueInputBuffer(codedbufferIndex, offset, read,
                            presentationTimeUs, (read > 0) ? 0
                                    : MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                    int decodedDataBufIndex = decoder.dequeueOutputBuffer(info,
                            2000);
                    if (decodedDataBufIndex >= 0) {
                        ByteBuffer codecOutput = outputBuffers[decodedDataBufIndex];
                        byte[] atInput = new byte[info.size];
                        codecOutput.get(atInput);
                        codecOutput.clear();
                        decoder.releaseOutputBuffer(decodedDataBufIndex, false);
                        if(info.offset != 0){
                            Log.e(TAG,"info.offset = "+String.valueOf(info.offset));
                        }
                        audioTrack.write(atInput, /*0*/info.offset, info.size);
                        extractor.advance();
                    } else if (decodedDataBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                        MediaFormat newFormat = decoder.getOutputFormat();
                        Log.e(TAG,
                                "newFormat: "
                                        + newFormat
                                                .getString(MediaFormat.KEY_MIME));
                        Log.e(TAG,
                                "newFormat: "
                                        + String.valueOf(newFormat
                                                .getInteger(MediaFormat.KEY_SAMPLE_RATE)));

                        Log.e(TAG, "Inside INFO_OUTPUT_FORMAT_CHANGED");
                        audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                                sampleRate, AudioFormat.CHANNEL_OUT_STEREO,
                                AudioFormat.ENCODING_PCM_16BIT, 32768,
                                AudioTrack.MODE_STREAM);
                        audioTrack.play();
                    }
                } else {
                    Log.e(TAG,"codedbufferIndex is  "+String.valueOf(codedbufferIndex));
                }
            } while (read >= 0);
4

1 に答える 1

0

一時停止または停止されていない場合、AudioTrack.flush() はノーオペレーションです。

停止または一時停止していない場合、またはトラックの作成モードが MODE_STREAM でない場合は何もしません。

解決策の 1 つは、AudioTrack のバッファを下げることです。これにより、以前に送信されたバイトの再生が認識されなくなります。私のアプリでは、32K のかなり大きなサイズを使用していますが、それは面倒ではありません。

于 2014-07-22T17:56:05.140 に答える