点击android屏幕解决媒体跳过,如何解决?

时间:2015-02-16 08:45:11

标签: java android

我写了一个播放多轨音频文件的Android应用程序,它完全在模拟器中运行。在设备上,它会播放几秒钟,然后开始每隔几秒跳过并弹出一次。如果我在应用程序的死空间中连续点击屏幕,则不会发生跳过,然后在屏幕点击停止后大约5秒再次跳过。我认为这与线程优先级有关,但是我在播放循环中记录线程优先级并且它永远不会改变。

我希望有人可以告诉我:

  1. 一个hack,我可以每秒模拟一次屏幕点击,这样我就可以在不跳过应用程序的情况下进行beta测试
  2. 解释一种调试活动/线程/ etc优先级的方法,当看起来我的线程优先级似乎没有改变时。
  3. 以下是播放器代码的执行方式:

    private class DecodeOperation extends AsyncTask<Void, Void, Void> {
    
        @Override
        protected Void doInBackground(Void... values) { 
            AudioTrackPlayer.this.decodeLoop();
            return null;
        }
    
        @Override
        protected void onPreExecute() {
        }
    
        @Override
        protected void onProgressUpdate(Void... values) {
        }
    }
    

    以下是相关的播放器代码:

    private void decodeLoop()
        {
    
            ByteBuffer[] codecInputBuffers;
            ByteBuffer[] codecOutputBuffers;
    
            // extractor gets information about the stream
            extractor = new MediaExtractor();
            try {
                extractor.setDataSource(this.mUrlString);
            } catch (Exception e) {
                mDelegateHandler.onRadioPlayerError(AudioTrackPlayer.this);
                return;
            }
    
            MediaFormat format = extractor.getTrackFormat(0);
            String mime = format.getString(MediaFormat.KEY_MIME);
    
            // the actual decoder
            codec = MediaCodec.createDecoderByType(mime);
            codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
            codec.start();
            codecInputBuffers = codec.getInputBuffers();
    
            codecOutputBuffers = codec.getOutputBuffers();
    
            // get the sample rate to configure AudioTrack
            int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
    
            Log.i(LOG_TAG,"mime "+mime);
            Log.i(LOG_TAG,"sampleRate "+sampleRate);
    
            // create our AudioTrack instance
            audioTrack = new AudioTrack(
                    AudioManager.STREAM_MUSIC, 
                    sampleRate, 
                    AudioFormat.CHANNEL_OUT_5POINT1, 
                    AudioFormat.ENCODING_PCM_16BIT, 
                    AudioTrack.getMinBufferSize (
                            sampleRate, 
                            AudioFormat.CHANNEL_OUT_5POINT1, 
                            AudioFormat.ENCODING_PCM_16BIT
                            ), 
                    AudioTrack.MODE_STREAM
                    );
    
            // start playing, we will feed you later
            audioTrack.play();
            extractor.selectTrack(0);
    
            // start decoding
            final long kTimeOutUs = 10000;
            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
            boolean sawInputEOS = false;
            boolean sawOutputEOS = false;
            int noOutputCounter = 0;
            int noOutputCounterLimit = 50;
    
    
            while (!sawOutputEOS && noOutputCounter < noOutputCounterLimit && !doStop) {
                //Log.i(LOG_TAG, "loop ");
                noOutputCounter++;
                if (!sawInputEOS) {
    
                    inputBufIndex = codec.dequeueInputBuffer(kTimeOutUs);
                    bufIndexCheck++;
                   // Log.d(LOG_TAG, " bufIndexCheck " + bufIndexCheck);
                    if (inputBufIndex >= 0) {
                        ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
    
                        int sampleSize =
                            extractor.readSampleData(dstBuf, 0 /* offset */);
                        //Log.d(LOG_TAG, "SampleLength = " + String.valueOf(sampleSize));
                        long presentationTimeUs = 0;
    
                        if (sampleSize < 0) {
                            Log.d(LOG_TAG, "saw input EOS.");
                            sawInputEOS = true;
                            sampleSize = 0;
                        } else {
                            presentationTimeUs = extractor.getSampleTime();
                        }
                        // can throw illegal state exception (???)
    
                            codec.queueInputBuffer(
                                    inputBufIndex,
                                    0 /* offset */,
                                    sampleSize,
                                    presentationTimeUs,
                                    sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
    
    
    
                        if (!sawInputEOS) {
                            extractor.advance();
                        }
                    }
                    else
                    {
                        Log.e(LOG_TAG, "inputBufIndex " +inputBufIndex);
                    }
                }
    
                int res = codec.dequeueOutputBuffer(info, kTimeOutUs);
    
                if (res >= 0) {
                    //Log.d(LOG_TAG, "got frame, size " + info.size + "/" + info.presentationTimeUs);
                    if (info.size > 0) {
                        noOutputCounter = 0;
                    }
    
                    int outputBufIndex = res;
                    ByteBuffer buf = codecOutputBuffers[outputBufIndex];
    
                    final byte[] chunk = new byte[info.size];
                    buf.get(chunk);
                    buf.clear();
    
                        audioTrack.write(chunk,0,chunk.length);
                        if(this.mState != State.Playing)
                        {
                            mDelegateHandler.onRadioPlayerPlaybackStarted(AudioTrackPlayer.this);
                        }
                        this.mState = State.Playing;
                    }
                    codec.releaseOutputBuffer(outputBufIndex, false /* render */);
                    if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                        Log.d(LOG_TAG, "saw output EOS.");
                        sawOutputEOS = true;
                    }
                } else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                    codecOutputBuffers = codec.getOutputBuffers();
    
                    Log.d(LOG_TAG, "output buffers have changed.");
                } else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                    MediaFormat oformat = codec.getOutputFormat();
    
                    Log.d(LOG_TAG, "output format has changed to " + oformat);
                } else {
                    Log.d(LOG_TAG, "dequeueOutputBuffer returned " + res);
                }
            }
    
            Log.d(LOG_TAG, "stopping...");
    
            relaxResources(true);
    
            this.mState = State.Stopped;
            doStop = true;
    
            // attempt reconnect
            if(sawOutputEOS)
            {
                try {
                    AudioTrackPlayer.this.play();
                    return;
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }  
    
            if(noOutputCounter >= noOutputCounterLimit)
            {
                mDelegateHandler.onRadioPlayerError(AudioTrackPlayer.this);
            }
            else
            {
                mDelegateHandler.onRadioPlayerStopped(AudioTrackPlayer.this);
            }
        }
    

1 个答案:

答案 0 :(得分:0)

您是否在应用程序运行时监控CPU频率? CPU调控器可能在触摸时缩放CPU并在计时器上缩小。将后台主题的优先级提高到THREAD_PRIORITY_DEFAULT可能会解决问题,AsyncTask的默认优先级非常低,不适合音频。

您还可以将AudioTrack缓冲区的大小增加到getMinBufferSize返回的值的某个倍数,该方法仅返回Class运行的最小缓冲区,但不保证流畅播放。