Я создал медиаплеер, используя MediaCodec и MediaSync, но звук воспроизводится дважды - PullRequest
0 голосов
/ 11 февраля 2019

MainActivity имеет кнопки SurfaceView и Воспроизведение, Пауза и Стоп.Он создает и запускает потоки во время воспроизведения.Я изучал столько, сколько смог, и я сделал это из-за ссылки на код, но проблема в том, что когда я играю, я получаю:

'Нормальный вывод видео, аудио +очень быстрый звук '

Это наложенное состояние воспроизведения.Я не думаю, что есть причина для двойного воспроизведения звука, потому что аудио буфер равен releasedOutput, рендерит его false, и только скопированный буфер равен queuedAudio.Пожалуйста, помогите мне с проблемой.

И я не знаю, почему я должен пройти процесс копирования.Если я не пройду процесс копирования, он не будет работать.

И в конце воспроизведения, когда повторение закончится,

Log.i ("mintest", "first end");
Log.i ("mintest", "second end");
Log.i ("mintest", "third end");

Этот журнал должен бытьвключен, но только первый.Это не вызывает никаких других проблем, но, пожалуйста, дайте мне знать, если у вас есть еще причины!

Мой код

public class VideoDecoderThread extends Thread {
    private static final String VIDEO = "video/";
    private static final String AUDIO = "audio/";
    private static final String TAG = "VideoDecoder";
    private MediaExtractor mExtractor, mAudioExtractor;
    private MediaCodec mDecoder, mAudioDecoder;

    private boolean eosReceived;
    private boolean isPaused;

    private BufferInfo info, audioInfo;
    private ByteBuffer[] inputBuffers, audioInputBuffers;
    private boolean isInput, isAudioInput;

    private int mSampleRate;

    private MediaSync mMediaSync;

    @RequiresApi(api = Build.VERSION_CODES.N)
    public boolean init(Surface surface, AssetFileDescriptor filePath) {

        eosReceived = false;
        isPaused = false;
        try {

            mExtractor = new MediaExtractor();
            mExtractor.setDataSource(filePath);

            mAudioExtractor = new MediaExtractor();
            mAudioExtractor.setDataSource(filePath);

            mMediaSync = new MediaSync();
            mMediaSync.setSurface(surface);

            Surface surface1 = mMediaSync.createInputSurface();

            for (int i = 0; i < mExtractor.getTrackCount(); i++) {

                MediaFormat format = mExtractor.getTrackFormat(i);
                String mime = format.getString(MediaFormat.KEY_MIME);

                if (mime.startsWith(VIDEO)) {

                    mExtractor.selectTrack(i);
                    mDecoder = MediaCodec.createDecoderByType(mime);

                    mDecoder.configure(format, surface1, null, 0);
                    mDecoder.start();
                    break;
                }
            }

            for (int i = 0; i < mAudioExtractor.getTrackCount(); i++) {

                MediaFormat format = mAudioExtractor.getTrackFormat(i);
                String mime = format.getString(MediaFormat.KEY_MIME);

                if (mime.startsWith(AUDIO)) {

                    mAudioExtractor.selectTrack(i);
                    mAudioDecoder = MediaCodec.createDecoderByType(mime);

                    mSampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);

                    mAudioDecoder.configure(format, null, null, 0);
                    mAudioDecoder.start();

                    int buffsize = AudioTrack.getMinBufferSize(mSampleRate, AudioFormat.CHANNEL_OUT_STEREO,
                            AudioFormat.ENCODING_PCM_16BIT);

                    AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, mSampleRate,
                            AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, buffsize,
                            AudioTrack.MODE_STREAM);

                    mMediaSync.setAudioTrack(audioTrack);

                    break;
                }
            }

            info = new BufferInfo();
            audioInfo = new BufferInfo();
            inputBuffers = mDecoder.getInputBuffers();
            audioInputBuffers = mAudioDecoder.getInputBuffers();

            isInput = true;
            isAudioInput = true;

        } catch (IOException e) {
            e.printStackTrace();
        }

        return true;
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    public void run() {

        while (!eosReceived) {

            if (!isPaused) {

                if (isInput) {

                    int inputIndex = mDecoder.dequeueInputBuffer(10000);
                    if (inputIndex >= 0) {

                        ByteBuffer inputBuffer = inputBuffers[inputIndex];
                        int sampleSize = mExtractor.readSampleData(inputBuffer, 0);

                        if (mExtractor.advance() && sampleSize > 0) {
                            mDecoder.queueInputBuffer(inputIndex, 0, sampleSize, mExtractor.getSampleTime(), 0);

                        } else {
                            Log.d(TAG, "InputBuffer BUFFER_FLAG_END_OF_STREAM");
                            mDecoder.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                            isInput = false;
                        }
                    }
                }

                int outIndex = mDecoder.dequeueOutputBuffer(info, 10000);
                switch (outIndex) {
                case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
                    Log.d(TAG, "INFO_OUTPUT_BUFFERS_CHANGED");
                    break;

                case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
                    Log.d(TAG, "INFO_OUTPUT_FORMAT_CHANGED format : " + mDecoder.getOutputFormat());
                    break;

                case MediaCodec.INFO_TRY_AGAIN_LATER:
                    Log.d(TAG, "INFO_TRY_AGAIN_LATER");
                    break;

                default:

                    mDecoder.releaseOutputBuffer(outIndex, true);
                    Log.d(TAG, "INFO_OUTPUT_RELEASED");
                    break;
                }

                if (isAudioInput) {

                    int audioInputIndex = mAudioDecoder.dequeueInputBuffer(10000);
                    if (audioInputIndex >= 0) {

                        ByteBuffer audioInputBuffer = audioInputBuffers[audioInputIndex];

                        int audioSampleSize = mAudioExtractor.readSampleData(audioInputBuffer, 0);

                        if (mAudioExtractor.advance() && audioSampleSize > 0) {
                            mAudioDecoder.queueInputBuffer(audioInputIndex, 0, audioSampleSize,
                                    mAudioExtractor.getSampleTime(), 0);
                        } else {
                            mAudioDecoder.queueInputBuffer(audioInputIndex, 0, 0, 0,
                                    MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                            isAudioInput = false;
                        }
                    }
                }

                int audioOutIndex = mAudioDecoder.dequeueOutputBuffer(audioInfo, 10000);
                switch (audioOutIndex) {
                case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
                    mAudioDecoder.getOutputBuffers();
                    break;

                case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
                    break;

                case MediaCodec.INFO_TRY_AGAIN_LATER:

                    break;

                default:

                    ByteBuffer decoderBuffer = mAudioDecoder.getOutputBuffer(audioOutIndex);
                    ByteBuffer copyBuffer = ByteBuffer.allocate(decoderBuffer.remaining());
                    copyBuffer.put(decoderBuffer);
                    copyBuffer.flip();
                    mAudioDecoder.releaseOutputBuffer(audioOutIndex, false);
                    mMediaSync.queueAudio(copyBuffer, audioOutIndex, audioInfo.presentationTimeUs);

                    break;

                }

                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                    Log.d(TAG, "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
                    break;
                }

                mMediaSync.setPlaybackParams(new PlaybackParams().setSpeed(0.5f));
            } else {

                mMediaSync.setPlaybackParams(new PlaybackParams().setSpeed(0.f));
            }

        }

        Log.i("mintest", "first end");

        mMediaSync.setPlaybackParams(new PlaybackParams().setSpeed(0.f));
        mMediaSync.release();

        mDecoder.stop();
        mDecoder.release();
        mExtractor.release();

        Log.i("mintest", "second end");

        mAudioDecoder.stop();
        mAudioDecoder.release();
        mAudioExtractor.release();

        mMediaSync = null;
        mDecoder = null;
        mExtractor = null;
        mAudioDecoder = null;
        mAudioExtractor = null;
        MainActivity.isfirstPlay = true;

        Log.i("mintest", "third end");

    }

    public void close() {
        eosReceived = true;
    }

    public void pause() {
        isPaused = true;
    }

    public void play() {
        isPaused = false;
    }
}
...