1

我正在使用 AudioTrack、MediaCodec 和 MediaExtractor 的组合来解码和播放音乐。

根据文件

为了开始解码与先前提交的数据不相邻的数据(即在搜索之后),必须刷新()解码器。客户端在刷新时可能拥有的任何输入或输出缓冲区都会立即被撤销,即在调用 flush() 之后,客户端不再拥有任何缓冲区。

我在寻找后调用flush,所以我也应该调用mAudioTrack.flush();

尽管调用了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() is no-op if not paused or stopped.

No-op if not stopped or paused, or if the track's creation mode is not MODE_STREAM.

One solution would be to lower the buffer of the AudioTrack, so the playing of the previously submitted bytes is not perceptible. In my app, I use a rather large size of 32K and it isn't bothersome.

于 2014-07-22T17:56:05.140 回答